diff --git a/assets/css/app.css b/assets/css/app.css index dcdd49c3..acaa4508 100644 --- a/assets/css/app.css +++ b/assets/css/app.css @@ -327,6 +327,38 @@ select.select { text-decoration: underline; } +/* API docs page — narrower reading column, since the site font is + monospace and monospace prose is uncomfortable past ~80ch. */ +.markdown-content.api-docs { + max-width: 60rem; + font-size: 0.95rem; +} + +.markdown-content.api-docs code { + word-break: break-word; +} + +.markdown-content.api-docs h1 { + font-size: 1.75rem; +} + +.markdown-content.api-docs h2 { + font-size: 1.3rem; +} + +.markdown-content.api-docs h3 { + font-size: 1.1rem; +} + +.markdown-content.api-docs table { + font-size: 0.85em; +} + +.markdown-content.api-docs th, +.markdown-content.api-docs td { + white-space: normal; +} + /* Allow map interaction through non-content parts of Leaflet popups */ .leaflet-popup { pointer-events: none; } .leaflet-popup-content-wrapper, .leaflet-popup-tip, .leaflet-popup-close-button { pointer-events: auto; } diff --git a/lib/microwaveprop/markdown.ex b/lib/microwaveprop/markdown.ex index bb2d056a..c8e4436e 100644 --- a/lib/microwaveprop/markdown.ex +++ b/lib/microwaveprop/markdown.ex @@ -45,8 +45,9 @@ defmodule Microwaveprop.Markdown do parse_blocks(remaining, [{:table, table_lines} | acc]) end - # Unordered list - defp parse_blocks(["- " <> item | rest], acc) do + # Unordered list — accept any of CommonMark's bullet markers (- * +). + defp parse_blocks([line | rest], acc) when binary_part(line, 0, min(byte_size(line), 2)) in ["- ", "* ", "+ "] do + item = binary_part(line, 2, byte_size(line) - 2) {items, remaining} = take_list(rest, [item]) parse_blocks(remaining, [{:ul, items} | acc]) end @@ -86,9 +87,28 @@ defmodule Microwaveprop.Markdown do defp take_table(["|" <> _ = line | rest], acc), do: take_table(rest, [line | acc]) defp take_table(rest, acc), do: {Enum.reverse(acc), rest} - defp take_list(["- " <> item | rest], acc), do: take_list(rest, [item | acc]) - defp take_list([" " <> cont | rest], [prev | items]), do: take_list(rest, [prev <> " " <> String.trim(cont) | items]) - defp take_list(rest, acc), do: {Enum.reverse(acc), rest} + defp take_list([line | rest] = all, acc) do + cond do + bullet_line?(line) -> + item = binary_part(line, 2, byte_size(line) - 2) + take_list(rest, [item | acc]) + + String.starts_with?(line, " ") and acc != [] -> + [prev | items] = acc + take_list(rest, [prev <> " " <> String.trim(line) | items]) + + true -> + {Enum.reverse(acc), all} + end + end + + defp take_list([], acc), do: {Enum.reverse(acc), []} + + defp bullet_line?(line) when byte_size(line) >= 2 do + binary_part(line, 0, 2) in ["- ", "* ", "+ "] + end + + defp bullet_line?(_), do: false defp take_ordered_list([line | rest], acc) do if Regex.match?(~r/^\d+\.\s/, line) do @@ -105,7 +125,9 @@ defmodule Microwaveprop.Markdown do defp take_paragraph(["" | rest], acc), do: {Enum.reverse(acc), rest} defp take_paragraph(["#" <> _ | _] = rest, acc), do: {Enum.reverse(acc), rest} defp take_paragraph(["|" <> _ | _] = rest, acc), do: {Enum.reverse(acc), rest} - defp take_paragraph(["- " <> _ | _] = rest, acc), do: {Enum.reverse(acc), rest} + defp take_paragraph([line | _] = rest, acc) when binary_part(line, 0, min(byte_size(line), 2)) in ["- ", "* ", "+ "] do + {Enum.reverse(acc), rest} + end defp take_paragraph(["```" <> _ | _] = rest, acc), do: {Enum.reverse(acc), rest} defp take_paragraph(["---" | _] = rest, acc), do: {Enum.reverse(acc), rest} diff --git a/lib/microwaveprop_web/live/api_docs_live.ex b/lib/microwaveprop_web/live/api_docs_live.ex index b8f19043..f0fea24a 100644 --- a/lib/microwaveprop_web/live/api_docs_live.ex +++ b/lib/microwaveprop_web/live/api_docs_live.ex @@ -14,7 +14,7 @@ defmodule MicrowavepropWeb.ApiDocsLive do def render(assigns) do ~H""" -
+
{raw(@content)}
diff --git a/test/microwaveprop/markdown_test.exs b/test/microwaveprop/markdown_test.exs index d072a810..10c38313 100644 --- a/test/microwaveprop/markdown_test.exs +++ b/test/microwaveprop/markdown_test.exs @@ -85,6 +85,24 @@ defmodule Microwaveprop.MarkdownTest do assert result =~ "
  • first
  • " assert result =~ "
  • second
  • " end + + test "renders unordered list with * bullets" do + result = Markdown.to_html!("* one\n* two") + assert result =~ "