GithubHelp home page GithubHelp logo

thomasin / elm-frontmatter Goto Github PK

View Code? Open in Web Editor NEW
2.0 1.0 0.0 1.04 MB

turn frontmatter into elm!

Home Page: https://package.elm-lang.org/packages/thomasin/elm-frontmatter/latest/

License: BSD 3-Clause "New" or "Revised" License

JavaScript 5.87% Elm 94.13%

elm-frontmatter's Introduction

In a vaguely similar way to Haykll, Jekyll, turns Frontmatter files into Elm code that you can then import and use in your Elm app like any other module. Also handles image copying and processing.

The package works as expected, but worth being aware there is still quite a bit of work to go into making it a nice user experience.

Contents

Installation and setup
├── Install Packages
└── Get Started
Running
└── Options
Directory Structure
├── content.md Files
└── Singleton vs Collection Item Files

Installation and Setup

Install Packages

npm install elm-frontmatter
npm install elm-format (Optionally)
elm install thomasin/elm-frontmatter

Note: elm-format will be used if it is found.
If it is not installed, files will still be written but unformatted.

Get Started

Create a folder /content in the same directory as your elm.json.

To decode your first frontmatter file you can populate:

(1) A file /content/index.md with

---
title: First page
---

woohoo

(2) A file Content.elm (placed in whichever folder your Main.elm is in) with

module Content exposing (decoder)

import Content.Decode as Decode
import Content.Type as Type

-- Required by the Node app and cannot be removed or unexposed.
decoder : Type.Path -> Decode.QueryResult
decoder typePath =
    case typePath of
        Type.Single [ "Content", "Index" ] ->
            Decode.frontmatter Decode.string
                [ Decode.attribute "title" Decode.string
                ]
        _ ->
            Decode.throw

(3) Run npx elm-frontmatter

Running

Run with npx elm-frontmatter

# Will look for frontmatter files in ./content/ and an elm.json file at ./elm.json.
# Will look for a Content.elm file in the first folder listed in your elm.json's `source-directories`,
# and will output the generated `Content` files into that same folder.
elm-frontmatter
# Will look for frontmatter files in ./md/ and an elm.json file at ./elm/elm.json.
# Will look for a Content.elm file in the first folder listed in your elm.json's `source-directories`,
# and will output the generated `Content` files into that same folder.
elm-frontmatter  --elm-json-dir=./elm ./md
# Will look for .md files in ./md/ and an elm.json file at ./elm/elm.json.
# Will look for a Content.elm file in the first folder listed in your elm.json's `source-directories`,
# and will output the generated `Content` files into that same folder.
elm-frontmatter --elm-dir='./src/elm'
# Will look for .md files in ./content/ and an elm.json file at ./elm.json.
# Will look for a Content.elm file at ./src/elm/,
# and will output the generated `Content` files also into ./src/elm.
elm-frontmatter --elm-dir='./src/elm'
# Same as previous except will generate new files without asking for confirmation.
# If `--yes` or `-y` is used, the `--elm-dir` argument must also be provided.
elm-frontmatter --elm-dir='./src/elm' -y

Options

  • --glob
    Will only process frontmatter files in your content directory that match this glob.
    Defaults to **/*.md.
  • --elm-json-dir
    The directory that contains your project's elm.json file. Defaults to . (current directory).
  • --elm-dir
    The directory that contains your project's Main.elm file. Defaults to the first directory in your elm.json source-directories array.
  • --yes/-y
    Set this to generate Elm files without asking for permission.
    --elm-dir needs to be set to use this argument.

Directory Structure

.
└── content
    └── about
    |   └── content.md --> /Content/About.elm
    ├── posts
    |   ├── content.md --> /Content/Posts.elm
    |   ├── [first-post].md --> /Content/Posts.elm
    |   ├── [second-post]  
    |   |   └── content.md --> /Content/Posts.elm
    |   └── happy 
    |      ├── banner.jpg --> /image-gen/happy/banner.jpg
    |      └── ness.md --> /Content/Posts/Happy/Ness.elm
    └── quote
        ├── first.md --> /Content/Quote/First.elm
        └── second.md --> /Content/Quote/Second.elm

Once decoded, a generated /Content folder for this would look like

.
└── Content
    └── About.elm
    |   └── #content : Content
    ├── Posts.elm
    |   ├── #content : Content
    |   ├── #firstPost : CollectionItem
    |   └── #secondPost : CollectionItem
    ├── Posts
    |   └── Happy 
    |       └── Ness.elm
    |           └── #content : Content
    └── Quote
        ├── First.elm
        |   └── #content : Content
        └── Second.elm
            └── #content : Content

content.md Files

content.md files are treated similarly to index.html files in webpages. If there is one in a folder, it will treat its containing folder name as its file name. This is useful if you want to keep images or other information colocated with .md files e.g.

.
└── content
    └── people
        ├── [person1]
        |   ├── content.md
        |   └── thumbnail.jpg
        └── [person2]
            ├── content.md
            └── thumbnail.jpg

will generate

.
└── Content
    └── People.elm
        ├── #person1 : CollectionItem
        └── #person2 : CollectionItem

Notes:

  • If you have two conflicting files, say posts.md and posts/content.md, one will be overwritten.
  • Since content.md files have special behaviour, having a top level content file/folder or a [content] file/folder will throw an error and terminate the content generation.

Singleton vs Collection Item Files

See the Content.Type module

The two types of files you can have are singleton or collection item files. Collection item files are surrounded by brackets [file-name].md.
Collection item files share a type with other bracketed files at the same level, and will be generated into the same module.
Singleton files will be turned into a content function in a module based on their file name. They can share a module with collection item functions, but two singleton functions won't share a module.
When writing your Content.elm#decoder function, singleton files can be matched using Content.Type.Single [ "Content", "Output", "Module", "Dir" ]. Collection item files can be matched using Content.Type.Collection [ "Content", "Output", "Module", "Dir" ].

module Content exposing (decoder)

import Content.Decode as Decode
import Content.Type as Type

decoder : Type.Path -> Decode.QueryResult
decoder typePath =
    case typePath of
        -- Will match `content/posts.md`
        Type.Single [ "Content", "Posts" ] ->
            Decode.frontmatter
                [ Decode.attribute "title" Decode.string
                , Decode.attribute "allPosts" (Decode.list (Decode.reference (Type.Collection [ "Content", "Posts" ])))
                ]

        -- Will match `content/posts/[first-post].md`, `content/posts/[second-post].md`, etc
        Type.Collection [ "Content", "Posts" ] ->
            Decode.frontmatter
                [ Decode.attribute "title" Decode.string
                , Decode.attribute "author" Decode.string
                , Decode.attribute "publishedAt" Decode.datetime
                ]
        _ ->
            Decode.throw

this decoder will generate a Content/Posts.elm module that is like

module Content.Posts exposing (Content, CollectionItem, content, firstPost, secondPost)

import Time


type alias Content =
    { title : String
    , allPosts : List CollectionItem
    }


type alias CollectionItem =
    { title : String
    , author : String
    , publishedAt : Time.Posix
    }


content : Content
content =
    ...


firstPost : CollectionItem
firstPost =
    ...


secondPost : CollectionItem
secondPost =
    ...

elm-frontmatter's People

Contributors

thomasin avatar

Stargazers

Rod avatar Adam McArthur avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.