finalize textile-md converter

This commit is contained in:
Luna D 2021-09-12 18:59:44 +02:00
parent cab0fb1b18
commit cb0ac0a9f5
No known key found for this signature in database
GPG key ID: 81AF416F2CC36FC8
2 changed files with 104 additions and 18 deletions

View file

@ -1,3 +1,16 @@
# LUNA PRESENTS THEE
#
# DA ULTIMATE, BESTEST, MOST SECURE AND DEFINITELY NOT BUGGY
# TEXTILE TO MARKDOWN CONVERTER PARSER LIBRARY THING!!!!!
#
# IT'S SO AWESOME I HAVE TO DESCRIBE IT IN ALL CAPS
#
# BY LOOKING AT THIS SOURCE CODE YOU AGREE THAT I MAY NOT BE HELD
# RESPONSIBLE FOR YOU DEVELOPING EYE CANCER
#
# YOU'VE BEEN WARNED
#
# COPYRIGHT (C) (R) (TM) LUNA (C) (R) (TM) 2021-206969696969
defmodule Philomena.Textile.ParserMarkdown do defmodule Philomena.Textile.ParserMarkdown do
alias Philomena.Textile.Lexer alias Philomena.Textile.Lexer
alias Philomena.Markdown alias Philomena.Markdown
@ -55,6 +68,17 @@ defmodule Philomena.Textile.ParserMarkdown do
# Helper corresponding to Kleene star (*) operator # Helper corresponding to Kleene star (*) operator
# Match a specificed rule zero or more times # Match a specificed rule zero or more times
defp repeat(rule, parser, tokens, bq) when bq == true do
case rule.(parser, tokens, true) do
{:ok, tree, r_tokens} ->
{:ok, tree2, r2_tokens} = repeat(rule, parser, r_tokens, true)
{:ok, [tree, tree2], r2_tokens}
_ ->
{:ok, [], tokens}
end
end
defp repeat(rule, parser, tokens) do defp repeat(rule, parser, tokens) do
case rule.(parser, tokens) do case rule.(parser, tokens) do
{:ok, tree, r_tokens} -> {:ok, tree, r_tokens} ->
@ -70,6 +94,18 @@ defmodule Philomena.Textile.ParserMarkdown do
# #
# open_token callback* close_token # open_token callback* close_token
# #
defp simple_recursive(:bq_open, :bq_close, open_tag, close_tag, callback, parser, [
{:bq_open, open} | r_tokens
]) do
case repeat(callback, parser, r_tokens, true) do
{:ok, tree, [{:bq_close, _} | r2_tokens]} ->
{:ok, [{:markup, open_tag}, tree, {:markup, close_tag}], r2_tokens}
{:ok, tree, r2_tokens} ->
{:ok, [{:text, escape(open)}, tree], r2_tokens}
end
end
defp simple_recursive(open_token, close_token, open_tag, close_tag, callback, parser, [ defp simple_recursive(open_token, close_token, open_tag, close_tag, callback, parser, [
{open_token, open} | r_tokens {open_token, open} | r_tokens
]) do ]) do
@ -350,7 +386,13 @@ defmodule Philomena.Textile.ParserMarkdown do
defp inline_textile_element_not_opening_markup(_parser, [{:char, lit} | r_tokens]) do defp inline_textile_element_not_opening_markup(_parser, [{:char, lit} | r_tokens]) do
{binary, r2_tokens} = assemble_binary(:char, <<lit::utf8>>, r_tokens) {binary, r2_tokens} = assemble_binary(:char, <<lit::utf8>>, r_tokens)
{:ok, [{:text, escape(binary)}], r2_tokens} # A bit of an ugly hack to force the parser to output >> instead of &gt;&gt;
case binary do
">>" ->
{:ok, [{:text, binary}], r2_tokens}
_ ->
{:ok, [{:text, escape(binary)}], r2_tokens}
end
end end
defp inline_textile_element_not_opening_markup(_parser, [ defp inline_textile_element_not_opening_markup(_parser, [
@ -379,17 +421,15 @@ defmodule Philomena.Textile.ParserMarkdown do
defp inline_textile_element_not_opening_markup(parser, [{:bq_cite_start, start} | r_tokens]) do defp inline_textile_element_not_opening_markup(parser, [{:bq_cite_start, start} | r_tokens]) do
case repeat(&bq_cite_text/2, parser, r_tokens) do case repeat(&bq_cite_text/2, parser, r_tokens) do
{:ok, tree, [{:bq_cite_open, open} | r2_tokens]} -> {:ok, tree, [{:bq_cite_open, open} | r2_tokens]} ->
case repeat(&block_textile_element/2, parser, r2_tokens) do case repeat(&block_textile_element/3, parser, r2_tokens, true) do
{:ok, tree2, [{:bq_close, _} | r3_tokens]} -> {:ok, tree2, [{:bq_close, _} | r3_tokens]} ->
cite = escape(flatten(tree)) cite = escape(flatten(tree))
{:ok, {:ok,
[ [
{:markup, "<blockquote author=\""}, {:markup, "\n> "},
{:markup, cite},
{:markup, "\">"},
tree2, tree2,
{:markup, "</blockquote>"} {:markup, "\n"}
], r3_tokens} ], r3_tokens}
{:ok, tree2, r3_tokens} -> {:ok, tree2, r3_tokens} ->
@ -413,7 +453,7 @@ defmodule Philomena.Textile.ParserMarkdown do
defp inline_textile_element_not_opening_markup(parser, tokens) do defp inline_textile_element_not_opening_markup(parser, tokens) do
[ [
{:bq_open, :bq_close, "<blockquote>", "</blockquote>"}, {:bq_open, :bq_close, "\n> ", "\n"},
{:spoiler_open, :spoiler_close, "||", "||"}, {:spoiler_open, :spoiler_close, "||", "||"},
{:bracketed_b_open, :bracketed_b_close, "**", "**"}, {:bracketed_b_open, :bracketed_b_close, "**", "**"},
{:bracketed_i_open, :bracketed_i_close, "_", "_"}, {:bracketed_i_open, :bracketed_i_close, "_", "_"},
@ -426,15 +466,27 @@ defmodule Philomena.Textile.ParserMarkdown do
{:bracketed_sub_open, :bracketed_sub_close, "%", "%"} {:bracketed_sub_open, :bracketed_sub_close, "%", "%"}
] ]
|> Enum.find_value(fn {open_token, close_token, open_tag, close_tag} -> |> Enum.find_value(fn {open_token, close_token, open_tag, close_tag} ->
simple_recursive( if open_token == :bq_open do
open_token, simple_recursive(
close_token, open_token,
open_tag, close_token,
close_tag, open_tag,
&block_textile_element/2, close_tag,
parser, &block_textile_element/3,
tokens parser,
) tokens
)
else
simple_recursive(
open_token,
close_token,
open_tag,
close_tag,
&block_textile_element/2,
parser,
tokens
)
end
|> case do |> case do
{:ok, tree, r_tokens} -> {:ok, tree, r_tokens} ->
{:ok, tree, r_tokens} {:ok, tree, r_tokens}
@ -451,12 +503,24 @@ defmodule Philomena.Textile.ParserMarkdown do
# double_newline | newline | inline_textile_element; # double_newline | newline | inline_textile_element;
# #
defp block_textile_element(_parser, [{:double_newline, _} | r_tokens], bq) when bq == true do
{:ok, [{:markup, "\n> \n> "}], r_tokens}
end
defp block_textile_element(_parser, [{:newline, _} | r_tokens], bq) when bq == true do
{:ok, [{:markup, "\n> "}], r_tokens}
end
defp block_textile_element(parser, tokens, _bq) do
inline_textile_element(parser, tokens)
end
defp block_textile_element(_parser, [{:double_newline, _} | r_tokens]) do defp block_textile_element(_parser, [{:double_newline, _} | r_tokens]) do
{:ok, [{:markup, "\n"}], r_tokens} {:ok, [{:markup, "\n\n"}], r_tokens}
end end
defp block_textile_element(_parser, [{:newline, _} | r_tokens]) do defp block_textile_element(_parser, [{:newline, _} | r_tokens]) do
{:ok, [{:markup, "\n\n"}], r_tokens} {:ok, [{:markup, "\n"}], r_tokens}
end end
defp block_textile_element(parser, tokens) do defp block_textile_element(parser, tokens) do

View file

@ -0,0 +1,22 @@
defmodule PhilomenaWeb.TextileMarkdownRenderer do
alias Philomena.Textile.ParserMarkdown
def render_one(post, conn) do
hd(render_collection([post], conn))
end
def render_collection(posts, conn) do
opts = %{image_transform: &Camo.Image.image_url/1}
parsed = Enum.map(posts, &ParserMarkdown.parse(opts, &1.body))
parsed
|> Enum.map(fn tree ->
tree
|> Enum.map(fn
{_k, text} ->
text
end)
|> Enum.join()
end)
end
end