|
1 | 1 | defmodule Tableau.Extension.Common do
|
2 | 2 | @moduledoc false
|
3 | 3 |
|
| 4 | + @doc """ |
| 5 | + Expand content paths from a wildcard. |
| 6 | + """ |
4 | 7 | def paths(wildcard) do
|
5 | 8 | wildcard |> Path.wildcard() |> Enum.sort()
|
6 | 9 | end
|
7 | 10 |
|
| 11 | + @doc """ |
| 12 | + Build content entries from a list of paths. |
| 13 | +
|
| 14 | + Content should contain YAML frontmatter, with the body from the file passed to the callback. |
| 15 | + """ |
8 | 16 | def entries(paths, callback) do
|
9 | 17 | for path <- paths do
|
10 | 18 | {front_matter, body} = Tableau.YamlFrontMatter.parse!(File.read!(path), atoms: true)
|
11 | 19 | "." <> ext = Path.extname(path)
|
12 | 20 | callback.(%{path: path, ext: String.to_atom(ext), front_matter: front_matter, pre_convert_body: body})
|
13 | 21 | end
|
14 | 22 | end
|
| 23 | + |
| 24 | + @doc """ |
| 25 | + Builds a permalink from a template and frontmatter and/or config. |
| 26 | +
|
| 27 | + Frontmatter keys are substituted for colon prefixed template keys of the same name. |
| 28 | +
|
| 29 | + If no permalink template is provided, the permalink will be derived from the file path. |
| 30 | +
|
| 31 | + If the frontamtter contains a `:date` key, it is broken down into `:day`, `:month`, and `:year` |
| 32 | + components and those can be used in the permalink template. |
| 33 | + """ |
| 34 | + def build_permalink(%{permalink: permalink} = front_matter, _config) do |
| 35 | + permalink |
| 36 | + |> transform_permalink(front_matter) |
| 37 | + |> then(&Map.put(front_matter, :permalink, &1)) |
| 38 | + end |
| 39 | + |
| 40 | + def build_permalink(front_matter, %{permalink: permalink}) when not is_nil(permalink) do |
| 41 | + permalink |
| 42 | + |> transform_permalink(front_matter) |
| 43 | + |> then(&Map.put(front_matter, :permalink, &1)) |
| 44 | + end |
| 45 | + |
| 46 | + def build_permalink(%{file: filename} = front_matter, config) do |
| 47 | + filename |
| 48 | + |> Path.rootname() |
| 49 | + |> String.replace_prefix(config.dir, "") |
| 50 | + |> transform_permalink(front_matter) |
| 51 | + |> then(&Map.put(front_matter, :permalink, &1)) |
| 52 | + end |
| 53 | + |
| 54 | + defp transform_permalink(path, front_matter) do |
| 55 | + vars = |
| 56 | + front_matter |
| 57 | + |> Map.new(fn {k, v} -> {":#{k}", v} end) |
| 58 | + |> then(fn vars -> |
| 59 | + if is_struct(front_matter[:date], DateTime) do |
| 60 | + Map.merge(vars, %{ |
| 61 | + ":day" => front_matter.date.day |> to_string() |> String.pad_leading(2, "0"), |
| 62 | + ":month" => front_matter.date.month |> to_string() |> String.pad_leading(2, "0"), |
| 63 | + ":year" => front_matter.date.year |
| 64 | + }) |
| 65 | + else |
| 66 | + vars |
| 67 | + end |
| 68 | + end) |
| 69 | + |
| 70 | + path |
| 71 | + |> String.replace(Map.keys(vars), &to_string(Map.fetch!(vars, &1))) |
| 72 | + |> String.replace(" ", "-") |
| 73 | + |> String.replace("_", "-") |
| 74 | + |> String.replace(~r/[^[:alnum:]\/\-.]/, "") |
| 75 | + |> String.downcase() |
| 76 | + |> URI.encode() |
| 77 | + end |
15 | 78 | end
|
0 commit comments