Skip to content

Commit c47e9e5

Browse files
authoredOct 28, 2023
feat(posts): global permalink and layout (#30)
1 parent d7961c2 commit c47e9e5

File tree

2 files changed

+61
-13
lines changed

2 files changed

+61
-13
lines changed
 

‎lib/tableau/extensions/post_extension.ex

+61-12
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,18 @@
11
defmodule Tableau.PostExtension.Config do
2+
@moduledoc """
3+
Configuration for PostExtension.
4+
5+
## Options
6+
- `:enabled` - boolean - Extension is active or not.
7+
- `:dir` - string - Directory to scan for markdown files. Defaults to `_posts`
8+
- `:future` - boolean - Show posts that have dates later than the current timestamp, or time at which the site is generated.
9+
- `: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_.
10+
- `layout` - string - Elixir module providing page layout for posts. Default is nil
11+
"""
12+
213
import Schematic
314

4-
defstruct enabled: true, dir: "_posts", future: false
15+
defstruct enabled: true, dir: "_posts", future: false, permalink: nil, layout: nil
516

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

@@ -11,7 +22,9 @@ defmodule Tableau.PostExtension.Config do
1122
%{
1223
optional(:enabled) => bool(),
1324
optional(:dir) => str(),
14-
optional(:future) => bool()
25+
optional(:future) => bool(),
26+
optional(:permalink) => str(),
27+
optional(:layout) => str()
1528
},
1629
convert: false
1730
)
@@ -22,30 +35,56 @@ defmodule Tableau.PostExtension.Posts.Post do
2235
def build(filename, attrs, body) do
2336
{:ok, config} = Tableau.Config.new(Map.new(Application.get_env(:tableau, :config, %{})))
2437

38+
{:ok, post_config} =
39+
Tableau.PostExtension.Config.new(
40+
Map.new(Application.get_env(:tableau, Tableau.PostExtension, %{}))
41+
)
42+
2543
attrs
2644
|> Map.put(:body, body)
2745
|> Map.put(:file, filename)
28-
|> Map.put(:layout, Module.concat([attrs.layout]))
46+
|> Map.put(:layout, Module.concat([attrs.layout || post_config.layout]))
2947
|> Map.put(
3048
:date,
3149
DateTime.from_naive!(
3250
Code.eval_string(attrs.date) |> elem(0),
3351
config.timezone
3452
)
3553
)
36-
|> Map.put(
37-
:permalink,
38-
attrs.permalink
39-
|> String.replace(":title", attrs.title)
40-
|> String.replace(" ", "-")
41-
|> String.replace(~r/[^[:alnum:]\/\-]/, "")
42-
|> String.downcase()
43-
)
54+
|> build_permalink(post_config)
4455
end
4556

4657
def parse(_file_path, content) do
4758
Tableau.YamlFrontMatter.parse!(content, atoms: true)
4859
end
60+
61+
defp build_permalink(%{permalink: permalink} = attrs, _config) do
62+
permalink
63+
|> transform_permalink(attrs)
64+
|> then(&Map.put(attrs, :permalink, &1))
65+
end
66+
67+
defp build_permalink(%{title: _title} = attrs, %{permalink: permalink})
68+
when not is_nil(permalink) do
69+
permalink
70+
|> transform_permalink(attrs)
71+
|> then(&Map.put(attrs, :permalink, &1))
72+
end
73+
74+
defp build_permalink(%{file: filename} = attrs, _) do
75+
filename
76+
|> Path.rootname()
77+
|> transform_permalink(attrs)
78+
|> then(&Map.put(attrs, :permalink, &1))
79+
end
80+
81+
defp transform_permalink(path, attrs) do
82+
path
83+
|> String.replace(":title", attrs.title)
84+
|> String.replace(" ", "-")
85+
|> String.replace(~r/[^[:alnum:]\/\-]/, "")
86+
|> String.downcase()
87+
end
4988
end
5089

5190
defmodule Tableau.PostExtension do
@@ -60,7 +99,7 @@ defmodule Tableau.PostExtension do
6099
61100
* `:id` - An Elixir module to be used when compiling the backing `Tableau.Page`
62101
* `:title` - The title of the post
63-
* `:permalink` - The permalink of the post. `:title` will be replaced with the posts title and non alphanumeric characters removed
102+
* `:permalink` - The permalink of the post. `:title` will be replaced with the posts title and non alphanumeric characters removed. Optional.
64103
* `:date` - An Elixir `NaiveDateTime`, often presented as a `sigil_N`
65104
* `:layout` - A Tableau layout module.
66105
@@ -75,6 +114,16 @@ defmodule Tableau.PostExtension do
75114
layout: "ElixirTools.PostLayout"
76115
---
77116
```
117+
118+
## URL generation
119+
120+
If a `:permalink` is specified in the front matter, whatever is there _will_ be the post's permalink.
121+
122+
If a global `:permalink` is set, it's rules will be used. See `Tableau.PostExtension.Config` for details.
123+
124+
If permalink is set in either location, the file's name and path will be used
125+
126+
In all cases, permalinks are stripped of non-alphanumeric characters.
78127
"""
79128

80129
{:ok, config} =

‎mix.exs

-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ defmodule Tableau.MixProject do
4444
{:makeup_elixir, ">= 0.0.0"},
4545
{:tz, "~> 0.26.2"},
4646

47-
4847
# {:yaml_front_matter, "~> 1.0"},
4948
# {:jason, "~> 1.4"},
5049
# {:req, "~> 0.3", only: :test},

0 commit comments

Comments
 (0)
Please sign in to comment.