Skip to content

Improve posts extension with slugs, filename as default slug, and config-based default for layout #30

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Oct 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 61 additions & 12 deletions lib/tableau/extensions/post_extension.ex
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
defmodule Tableau.PostExtension.Config do
@moduledoc """
Configuration for PostExtension.

## Options
- `:enabled` - boolean - Extension is active or not.
- `:dir` - string - Directory to scan for markdown files. Defaults to `_posts`
- `:future` - boolean - Show posts that have dates later than the current timestamp, or time at which the site is generated.
- `:permalink` - string - Default output path for posts. Accepts `:title` as a replacement keyword, replaced with the post's provided title. If a post has a `:permalink` provided, that will override this value _for that post_.
- `layout` - string - Elixir module providing page layout for posts. Default is nil
"""

import Schematic

defstruct enabled: true, dir: "_posts", future: false
defstruct enabled: true, dir: "_posts", future: false, permalink: nil, layout: nil

def new(input), do: unify(schematic(), input)

Expand All @@ -11,7 +22,9 @@ defmodule Tableau.PostExtension.Config do
%{
optional(:enabled) => bool(),
optional(:dir) => str(),
optional(:future) => bool()
optional(:future) => bool(),
optional(:permalink) => str(),
optional(:layout) => str()
},
convert: false
)
Expand All @@ -22,30 +35,56 @@ defmodule Tableau.PostExtension.Posts.Post do
def build(filename, attrs, body) do
{:ok, config} = Tableau.Config.new(Map.new(Application.get_env(:tableau, :config, %{})))

{:ok, post_config} =
Tableau.PostExtension.Config.new(
Map.new(Application.get_env(:tableau, Tableau.PostExtension, %{}))
)

attrs
|> Map.put(:body, body)
|> Map.put(:file, filename)
|> Map.put(:layout, Module.concat([attrs.layout]))
|> Map.put(:layout, Module.concat([attrs.layout || post_config.layout]))
|> Map.put(
:date,
DateTime.from_naive!(
Code.eval_string(attrs.date) |> elem(0),
config.timezone
)
)
|> Map.put(
:permalink,
attrs.permalink
|> String.replace(":title", attrs.title)
|> String.replace(" ", "-")
|> String.replace(~r/[^[:alnum:]\/\-]/, "")
|> String.downcase()
)
|> build_permalink(post_config)
end

def parse(_file_path, content) do
Tableau.YamlFrontMatter.parse!(content, atoms: true)
end

defp build_permalink(%{permalink: permalink} = attrs, _config) do
permalink
|> transform_permalink(attrs)
|> then(&Map.put(attrs, :permalink, &1))
end

defp build_permalink(%{title: _title} = attrs, %{permalink: permalink})
when not is_nil(permalink) do
permalink
|> transform_permalink(attrs)
|> then(&Map.put(attrs, :permalink, &1))
end

defp build_permalink(%{file: filename} = attrs, _) do
filename
|> Path.rootname()
|> transform_permalink(attrs)
|> then(&Map.put(attrs, :permalink, &1))
end

defp transform_permalink(path, attrs) do
path
|> String.replace(":title", attrs.title)
|> String.replace(" ", "-")
|> String.replace(~r/[^[:alnum:]\/\-]/, "")
|> String.downcase()
end
end

defmodule Tableau.PostExtension do
Expand All @@ -60,7 +99,7 @@ defmodule Tableau.PostExtension do

* `:id` - An Elixir module to be used when compiling the backing `Tableau.Page`
* `:title` - The title of the post
* `:permalink` - The permalink of the post. `:title` will be replaced with the posts title and non alphanumeric characters removed
* `:permalink` - The permalink of the post. `:title` will be replaced with the posts title and non alphanumeric characters removed. Optional.
* `:date` - An Elixir `NaiveDateTime`, often presented as a `sigil_N`
* `:layout` - A Tableau layout module.

Expand All @@ -75,6 +114,16 @@ defmodule Tableau.PostExtension do
layout: "ElixirTools.PostLayout"
---
```

## URL generation

If a `:permalink` is specified in the front matter, whatever is there _will_ be the post's permalink.

If a global `:permalink` is set, it's rules will be used. See `Tableau.PostExtension.Config` for details.

If permalink is set in either location, the file's name and path will be used

In all cases, permalinks are stripped of non-alphanumeric characters.
"""

{:ok, config} =
Expand Down
1 change: 0 additions & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ defmodule Tableau.MixProject do
{:makeup_elixir, ">= 0.0.0"},
{:tz, "~> 0.26.2"},


# {:yaml_front_matter, "~> 1.0"},
# {:jason, "~> 1.4"},
# {:req, "~> 0.3", only: :test},
Expand Down