Skip to content

Commit 25edb37

Browse files
halostatuemhanberg
andauthored
feat!: update to MDEx 0.10 (#169)
* feat!: update to MDEx 0.10 MDEx 0.10 has a few breaking changes which should have minimal impact on Tableau, but the larger change is that there is explicit support for plugins in MDEx, using the similar patterns as Req does. To simplify the use of plugins in Tableau, I have added a `plugins` key to `config.markdown.mdex` which is extracted and used to attach MDEx plugin modules prior to calling `MDEx.to_html!()`. This _could_ be implemented as a separate key `config.mdex_plugins`, but since it's part of the markdown converter, this felt more natural to me. If MDEx or one of its plugins adds a `plugins` option, this will break that -- but I think it's low probability. * Clarify that `:plugins` is non-standard and Tableau only Co-authored-by: Mitchell Hanberg <mitch@mitchellhanberg.com> * Refactor plugin resolution Refactor `MDExConverter.markdown/2` and `MDExConverter.convert/4` functions to use Keyword.pop for plugins. `MDExConverter.markdown/2` no longer tries to *merge* `:plugins`. * Improve MDEx plugin attach calls Ensure that the code is loaded before trying to call `mod.attach/1`. * Fix argument order in Keyword.pop for mdex config --------- Co-authored-by: Mitchell Hanberg <mitch@mitchellhanberg.com>
1 parent de5e67c commit 25edb37

4 files changed

Lines changed: 45 additions & 14 deletions

File tree

lib/tableau.ex

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ defmodule Tableau do
99
* `:url` - string (required) - The URL of your website.
1010
* `:converters` - mapping of file extensions to converter module. Defaults to `[md: Tableau.MDExConverter]`
1111
* `:markdown` - keyword
12-
* `:mdex` - keyword - Options to pass to `MDEx.to_html/2`
12+
* `:mdex` - keyword - Options to pass to `MDEx.to_html/2`. See `MDEx` documentation for list of options, as options listed here are non-standard and specific to Tableau.
13+
* `:plugins` - module list - MDEx plugin modules to attach to the processing pipeline
1314
* `:slug` - keyword - Options to pass to `Slug.slugify/2`
1415
1516
### Example
@@ -41,7 +42,8 @@ defmodule Tableau do
4142
footnotes: true
4243
],
4344
render: [unsafe: true],
44-
syntax_highlight: [formatter: {:html_inline, theme: "neovim_dark"}]
45+
syntax_highlight: [formatter: {:html_inline, theme: "neovim_dark"}],
46+
plugins: [MDExGFM]
4547
]
4648
]
4749
```
@@ -61,9 +63,5 @@ defmodule Tableau do
6163
6264
Will use the globally configured options, but you can also pass it overrides.
6365
"""
64-
def markdown(content, overrides \\ []) do
65-
{:ok, config} = Tableau.Config.get()
66-
67-
MDEx.to_html!(content, Keyword.merge(config.markdown[:mdex], overrides))
68-
end
66+
defdelegate markdown(content, overrides \\ []), to: Tableau.MDExConverter
6967
end
Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,41 @@
11
defmodule Tableau.MDExConverter do
22
@moduledoc """
3-
Converter to parse markdown content with `MDEx`
3+
Converter to parse markdown content with `MDEx` with support for MDEx plugins.
44
"""
5+
6+
@doc """
7+
Convert markdown content to HTML using `MDEx.to_html!/2`.
8+
9+
Will use the globally configured options, but you can also pass it overrides.
10+
"""
11+
def markdown(content, overrides \\ []) do
12+
{:ok, config} = Tableau.Config.get()
13+
14+
{plugins, mdex_config} =
15+
config.markdown[:mdex]
16+
|> Keyword.merge(overrides)
17+
|> Keyword.pop(:plugins, [])
18+
19+
render!(content, mdex_config, plugins)
20+
end
21+
522
def convert(_filepath, _front_matter, body, %{site: %{config: config}}) do
6-
MDEx.to_html!(body, config.markdown[:mdex])
23+
{plugins, mdex_config} = Keyword.pop(config.markdown[:mdex], :plugins, [])
24+
render!(body, mdex_config, plugins)
25+
end
26+
27+
defp render!(content, mdex_config, plugins) do
28+
mdex_config
29+
|> Keyword.put(:markdown, content)
30+
|> MDEx.new()
31+
|> attach_plugins(plugins)
32+
|> MDEx.to_html!()
33+
end
34+
35+
defp attach_plugins(mdex, plugins) do
36+
Enum.reduce(plugins, mdex, fn mod, mdex ->
37+
Code.ensure_loaded!(mod)
38+
mod.attach(mdex)
39+
end)
740
end
841
end

mix.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ defmodule Tableau.MixProject do
3737
{:date_time_parser, "~> 1.2"},
3838
{:html_entities, "~> 0.5.2"},
3939
{:libgraph, "~> 0.16.0"},
40-
{:mdex, "~> 0.9.0"},
40+
{:mdex, "~> 0.10.0"},
4141
{:schematic, "~> 0.5.1"},
4242
{:slugify, "~> 1.3"},
4343
{:tz, "~> 0.28.1"},

mix.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
%{
2-
"autumn": {:hex, :autumn, "0.5.5", "05cda4e2b79957c8540eb0184f1ac00fba187a6dabd8461e78c40f9fc8417f2d", [:mix], [{:nimble_options, "~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:rustler, "~> 0.29", [hex: :rustler, repo: "hexpm", optional: false]}, {:rustler_precompiled, "~> 0.6", [hex: :rustler_precompiled, repo: "hexpm", optional: false]}], "hexpm", "49e40b50e16fc49dcbf0bd4071b32e5f64755403c8073490aff2a536d442df36"},
2+
"autumn": {:hex, :autumn, "0.5.7", "f6bfdc30d3f8d5e82ba5648489db7a7b6b7479d7be07a8288d4db2437434e26d", [:mix], [{:nimble_options, "~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:rustler, "~> 0.29", [hex: :rustler, repo: "hexpm", optional: true]}, {:rustler_precompiled, "~> 0.6", [hex: :rustler_precompiled, repo: "hexpm", optional: false]}], "hexpm", "d272bfddeeea863420a8eb994d42af219ca5391191dd765bf045fbacf56a28d1"},
33
"bandit": {:hex, :bandit, "1.5.7", "6856b1e1df4f2b0cb3df1377eab7891bec2da6a7fd69dc78594ad3e152363a50", [:mix], [{:hpax, "~> 1.0.0", [hex: :hpax, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:thousand_island, "~> 1.0", [hex: :thousand_island, repo: "hexpm", optional: false]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "f2dd92ae87d2cbea2fa9aa1652db157b6cba6c405cb44d4f6dd87abba41371cd"},
4-
"castore": {:hex, :castore, "1.0.15", "8aa930c890fe18b6fe0a0cff27b27d0d4d231867897bd23ea772dee561f032a3", [:mix], [], "hexpm", "96ce4c69d7d5d7a0761420ef743e2f4096253931a3ba69e5ff8ef1844fe446d3"},
4+
"castore": {:hex, :castore, "1.0.17", "4f9770d2d45fbd91dcf6bd404cf64e7e58fed04fadda0923dc32acca0badffa2", [:mix], [], "hexpm", "12d24b9d80b910dd3953e165636d68f147a31db945d2dcb9365e441f8b5351e5"},
55
"date_time_parser": {:hex, :date_time_parser, "1.2.0", "3d5a816b91967f51e0f94dcb16a34b2cb780f22cd48931779e81d72f7d3eadb1", [:mix], [{:kday, "~> 1.0", [hex: :kday, repo: "hexpm", optional: false]}], "hexpm", "0cf09ada9f42c0b3bfba02dc0ea2e4b4d2f543d9d2bf99b831a29e6b4a4160e5"},
66
"earmark_parser": {:hex, :earmark_parser, "1.4.44", "f20830dd6b5c77afe2b063777ddbbff09f9759396500cdbe7523efd58d7a339c", [:mix], [], "hexpm", "4778ac752b4701a5599215f7030989c989ffdc4f6df457c5f36938cc2d2a2750"},
77
"ex_doc": {:hex, :ex_doc, "0.37.3", "f7816881a443cd77872b7d6118e8a55f547f49903aef8747dbcb345a75b462f9", [:mix], [{:earmark_parser, "~> 1.4.42", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "e6aebca7156e7c29b5da4daa17f6361205b2ae5f26e5c7d8ca0d3f7e18972233"},
@@ -15,14 +15,14 @@
1515
"makeup": {:hex, :makeup, "1.2.1", "e90ac1c65589ef354378def3ba19d401e739ee7ee06fb47f94c687016e3713d1", [:mix], [{:nimble_parsec, "~> 1.4", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "d36484867b0bae0fea568d10131197a4c2e47056a6fbe84922bf6ba71c8d17ce"},
1616
"makeup_elixir": {:hex, :makeup_elixir, "1.0.1", "e928a4f984e795e41e3abd27bfc09f51db16ab8ba1aebdba2b3a575437efafc2", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "7284900d412a3e5cfd97fdaed4f5ed389b8f2b4cb49efc0eb3bd10e2febf9507"},
1717
"makeup_erlang": {:hex, :makeup_erlang, "1.0.2", "03e1804074b3aa64d5fad7aa64601ed0fb395337b982d9bcf04029d68d51b6a7", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "af33ff7ef368d5893e4a267933e7744e46ce3cf1f61e2dccf53a111ed3aa3727"},
18-
"mdex": {:hex, :mdex, "0.9.2", "d70e0a9116105733d7999cbbfcb52823b6e6a4b02174205f0d0815cb1ed68dd4", [:mix], [{:autumn, ">= 0.5.4", [hex: :autumn, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:nimble_options, "~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:rustler, "~> 0.32", [hex: :rustler, repo: "hexpm", optional: false]}, {:rustler_precompiled, "~> 0.7", [hex: :rustler_precompiled, repo: "hexpm", optional: false]}], "hexpm", "d5a3371ec939141d971ed500bdbf3a23a22a91df80753356b256ec13dfadfd13"},
18+
"mdex": {:hex, :mdex, "0.10.0", "eae4d3bd4c0b77d6d959146a2d6faaec045686548ad1468630130095dbd93def", [:mix], [{:autumn, ">= 0.5.4", [hex: :autumn, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:nimble_options, "~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}, {:rustler, "~> 0.32", [hex: :rustler, repo: "hexpm", optional: false]}, {:rustler_precompiled, "~> 0.7", [hex: :rustler_precompiled, repo: "hexpm", optional: false]}], "hexpm", "6ad76e32056c44027fe985da7da506e033b07037896d1f130f7d5c332b0d0ac0"},
1919
"mime": {:hex, :mime, "2.0.6", "8f18486773d9b15f95f4f4f1e39b710045fa1de891fada4516559967276e4dc2", [:mix], [], "hexpm", "c9945363a6b26d747389aac3643f8e0e09d30499a138ad64fe8fd1d13d9b153e"},
2020
"nimble_options": {:hex, :nimble_options, "1.1.1", "e3a492d54d85fc3fd7c5baf411d9d2852922f66e69476317787a7b2bb000a61b", [:mix], [], "hexpm", "821b2470ca9442c4b6984882fe9bb0389371b8ddec4d45a9504f00a66f650b44"},
2121
"nimble_parsec": {:hex, :nimble_parsec, "1.4.2", "8efba0122db06df95bfaa78f791344a89352ba04baedd3849593bfce4d0dc1c6", [:mix], [], "hexpm", "4b21398942dda052b403bbe1da991ccd03a053668d147d53fb8c4e0efe09c973"},
2222
"plug": {:hex, :plug, "1.16.1", "40c74619c12f82736d2214557dedec2e9762029b2438d6d175c5074c933edc9d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a13ff6b9006b03d7e33874945b2755253841b238c34071ed85b0e86057f8cddc"},
2323
"plug_crypto": {:hex, :plug_crypto, "2.1.0", "f44309c2b06d249c27c8d3f65cfe08158ade08418cf540fd4f72d4d6863abb7b", [:mix], [], "hexpm", "131216a4b030b8f8ce0f26038bc4421ae60e4bb95c5cf5395e1421437824c4fa"},
2424
"rustler": {:hex, :rustler, "0.37.1", "721434020c7f6f8e1cdc57f44f75c490435b01de96384f8ccb96043f12e8a7e0", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "24547e9b8640cf00e6a2071acb710f3e12ce0346692e45098d84d45cdb54fd79"},
25-
"rustler_precompiled": {:hex, :rustler_precompiled, "0.8.3", "4e741024b0b097fe783add06e53ae9a6f23ddc78df1010f215df0c02915ef5a8", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:rustler, "~> 0.23", [hex: :rustler, repo: "hexpm", optional: true]}], "hexpm", "c23f5f33cb6608542de4d04faf0f0291458c352a4648e4d28d17ee1098cddcc4"},
25+
"rustler_precompiled": {:hex, :rustler_precompiled, "0.8.4", "700a878312acfac79fb6c572bb8b57f5aae05fe1cf70d34b5974850bbf2c05bf", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:rustler, "~> 0.23", [hex: :rustler, repo: "hexpm", optional: true]}], "hexpm", "3b33d99b540b15f142ba47944f7a163a25069f6d608783c321029bc1ffb09514"},
2626
"schematic": {:hex, :schematic, "0.5.1", "be4b2c03115d5a593459c11a7249a6fbb45855947d9653e9250455dcd7df1d42", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "02f913c97e6e04ccdaa02004679a7a16bb16fe0449583ad647e296d8e8961546"},
2727
"slugify": {:hex, :slugify, "1.3.1", "0d3b8b7e5c1eeaa960e44dce94382bee34a39b3ea239293e457a9c5b47cc6fd3", [:mix], [], "hexpm", "cb090bbeb056b312da3125e681d98933a360a70d327820e4b7f91645c4d8be76"},
2828
"styler": {:hex, :styler, "1.1.1", "ccb55763316915b5de532bf14c587c211ddc86bc749ac676e74dfacd3894cc0d", [:mix], [], "hexpm", "80ce12fb862e13d998589eea7c1932f4e6ce9d6ded2182cb322f8f9b2b8d3632"},

0 commit comments

Comments
 (0)