Packages
mdex
0.10.0
0.13.3
0.13.2
0.13.1
0.13.0
0.12.5
retired
0.12.4
0.12.3
0.12.2
0.12.1
0.12.0
0.11.7
0.11.6
0.11.5
0.11.4
0.11.3
0.11.2
0.11.1
0.11.0
0.10.0
0.9.4
0.9.3
0.9.2
0.9.1
0.9.0
0.8.6
0.8.5
0.8.4
0.8.3
0.8.2
0.8.1
0.8.0
0.7.5
0.7.4
0.7.3
0.7.2
0.7.1
0.7.0
0.6.2
0.6.1
0.6.0
0.5.0
0.4.3
0.4.2
0.4.1
0.4.0
0.3.3
0.3.2
0.3.1
0.3.0
0.2.0
0.1.18
0.1.17
0.1.16
0.1.15
0.1.14
0.1.13
0.1.12
0.1.11
0.1.10
0.1.9
0.1.8
0.1.7
0.1.6
0.1.5
0.1.4
0.1.3
0.1.2
0.1.1
0.1.0
Fast and extensible Markdown for Elixir
Security advisory:
This version has known vulnerabilities.
View advisories
Current section
Files
Jump to
Current section
Files
examples/nimble_publisher.livemd
<!-- livebook:{"persist_outputs":true} --># NimblePublisher```elixirMix.install([ {:mdex, "~> 0.8"}, {:phoenix_live_view, "~> 1.0"}, {:phoenix_playground, "~> 0.1"}, {:nimble_publisher, "~> 1.1"}, {:phoenix_html, "~> 4.2"}])```## Example```elixirdefmodule MDEx.Posts.Post do @enforce_keys [:id, :title, :date, :body] defstruct [:id, :title, :date, :body] def build(filepath, attrs, body) do [year, month, day, id] = filepath |> Path.rootname() |> Path.split() |> List.last() |> String.split("-", parts: 4) id = id |> String.trim_trailing(".md") |> String.downcase() date = Date.from_iso8601!("#{year}-#{month}-#{day}") struct!(__MODULE__, Map.merge(attrs, %{id: id, date: date, body: body})) endend```<!-- livebook:{"output":true} -->```{:module, MDEx.Posts.Post, <<70, 79, 82, 49, 0, 0, 18, ...>>, {:build, 3}}``````elixirdefmodule MDEx.Posts.Parser do def parse(_path, contents) do [header, markdown_body] = String.split(contents, "---\n", trim: true, parts: 2) {%{} = attrs, _} = Code.eval_string(header, []) html_body = markdown_to_html!(markdown_body) {attrs, html_body} end defp markdown_to_html!(markdown_body) do MDEx.to_html!(markdown_body, syntax_highlight: [formatter: {:html_inline, theme: "github_dark"}], extension: [ strikethrough: true, underline: true, tagfilter: true, table: true, autolink: true, tasklist: true, footnotes: true, shortcodes: true ], parse: [ smart: true, relaxed_tasklist_matching: true, relaxed_autolinks: true ], render: [ github_pre_lang: true, escape: true, hardbreaks: true ] ) endend```<!-- livebook:{"output":true} -->```{:module, MDEx.Posts.Parser, <<70, 79, 82, 49, 0, 0, 11, ...>>, {:markdown_to_html!, 1}}``````elixirdefmodule MDEx.Posts.HTMLConverter do # ⚠️ Important ⚠️ # You need to provide a custom converter, because otherwise NimblePublisher # will apply their default markdown -> HTML conversion which will # interfere with MDEx's conversion. def convert(_extname, body, _attrs, _opts), do: bodyend```<!-- livebook:{"output":true} -->```{:module, MDEx.Posts.HTMLConverter, <<70, 79, 82, 49, 0, 0, 7, ...>>, {:convert, 4}}``````elixirdefmodule MDEx.Posts do use NimblePublisher, # Update this filepath to your application # and move the `posts` folder inside your `priv` folder. # # from: Application.app_dir(:my_app, "priv/posts/*.md"), from: Path.join([Path.absname(__DIR__), "posts", "*.md"]), build: MDEx.Posts.Post, parser: MDEx.Posts.Parser, html_converter: MDEx.Posts.HTMLConverter, as: :posts, highlighters: [] @posts Enum.sort_by(@posts, & &1.date, {:desc, Date}) def all_posts, do: @posts defmodule NotFoundError do defexception [:message, plug_status: 404] end def get_post_by_id!(id) do Enum.find(all_posts(), &(&1.id == id)) || raise NotFoundError, "post with id=#{id} not found" endend```<!-- livebook:{"output":true} -->```{:module, MDEx.Posts, <<70, 79, 82, 49, 0, 0, 21, ...>>, {:get_post_by_id!, 1}}``````elixirdefmodule MDEx.DemoLive do use Phoenix.LiveView import Phoenix.HTML def mount(%{"id" => post_id}, _session, socket) do post = MDEx.Posts.get_post_by_id!(post_id) {:ok, assign(socket, :post, post)} end # Show the first blog post by default. # In your app, you'd show an overview of the blog posts instead. def mount(_params, session, socket) do mount(%{"id" => "example-post"}, session, socket) end def render(assigns) do ~H""" <h1>{@post.title}</h1> <h2>{@post.date}</h2> <article> {raw(@post.body)} </article> """ endend```<!-- livebook:{"output":true} -->```{:module, MDEx.DemoLive, <<70, 79, 82, 49, 0, 0, 24, ...>>, {:render, 1}}``````elixirPhoenixPlayground.start(live: MDEx.DemoLive)```<!-- livebook:{"output":true} -->```19:29:52.699 [info] Running PhoenixPlayground.Endpoint with Bandit 1.7.0 at 127.0.0.1:4000 (http)19:29:52.704 [info] Access PhoenixPlayground.Endpoint at http://localhost:400019:29:52.731 [info] CONNECTED TO Phoenix.LiveView.Socket in 16µs Transport: :websocket Serializer: Phoenix.Socket.V2.JSONSerializer Parameters: %{"vsn" => "2.0.0"}```<!-- livebook:{"output":true} -->```{:ok, #PID<0.343.0>}```<!-- livebook:{"output":true} -->```19:29:52.781 [debug] MOUNT PhoenixPlayground.Router.DelegateLive Parameters: %{} Session: %{}19:29:52.781 [debug] Replied in 115µs19:29:52.783 [debug] HANDLE PARAMS in PhoenixPlayground.Router.DelegateLive Parameters: %{}19:29:52.783 [debug] Replied in 61µs19:29:52.801 [info] GET /19:29:52.805 [debug] Processing with PhoenixPlayground.Router.DelegateLive.index/2 Parameters: %{} Pipelines: [:browser]19:29:52.816 [info] Sent 200 in 15ms19:29:52.843 [info] CONNECTED TO Phoenix.LiveView.Socket in 18µs Transport: :websocket Serializer: Phoenix.Socket.V2.JSONSerializer Parameters: %{"vsn" => "2.0.0"}19:29:52.844 [debug] MOUNT PhoenixPlayground.Router.DelegateLive Parameters: %{} Session: %{}19:29:52.844 [debug] Replied in 101µs19:29:52.844 [debug] HANDLE PARAMS in PhoenixPlayground.Router.DelegateLive Parameters: %{}19:29:52.844 [debug] Replied in 21µs```