Page MenuHomePhorge

No OneTemporary

Size
4 KB
Referenced Files
None
Subscribers
None
diff --git a/lib/bbcode/parser.ex b/lib/bbcode/parser.ex
index 6383f0e..17f34c3 100644
--- a/lib/bbcode/parser.ex
+++ b/lib/bbcode/parser.ex
@@ -1,57 +1,80 @@
defmodule BBCode.Parser do
import NimbleParsec
@moduledoc """
Parse BBCode into an abstract tree.
"""
tag = utf8_string([?a..?z, ?A..?Z, ?0..?9], min: 1)
text = utf8_string([not: ?[], min: 1)
+ text_without_newline = utf8_string([not: ?[, not: ?\n], min: 1)
start_tag = ignore(string("[")) |> concat(tag) |> ignore(string("]"))
end_tag = ignore(string("[/")) |> concat(tag) |> ignore(string("]"))
+ star_tag = ignore(string("[*]"))
+
defcombinatorp(
:basic_stanza,
start_tag
- |> repeat(lookahead_not(string("[/")) |> choice([parsec(:basic_stanza), text]))
+ |> repeat(lookahead_not(string("[/")) |> choice([parsec(:child_stanza), text]))
|> wrap()
|> concat(end_tag)
|> post_traverse(:emit_tree_node)
)
defcombinatorp(
:text_stanza,
text
|> wrap()
|> post_traverse(:emit_tree_node)
)
+ defcombinatorp(
+ :star_stanza,
+ star_tag
+ |> repeat(
+ lookahead_not(string("\n"))
+ |> choice([parsec(:child_stanza), text_without_newline])
+ )
+ |> wrap()
+ |> concat(ignore(string("\n")))
+ |> post_traverse(:emit_tree_node_star)
+ )
+
+ defcombinatorp(
+ :child_stanza,
+ choice([parsec(:star_stanza), parsec(:basic_stanza)])
+ )
+
defcombinatorp(
:root_stanza,
- choice([parsec(:basic_stanza), parsec(:text_stanza)])
+ choice([parsec(:child_stanza), parsec(:text_stanza)])
)
defparsecp(
:parse_tree,
repeat(lookahead_not(string("[/")) |> parsec(:root_stanza)) |> eos()
)
+ defp emit_tree_node_star(_rest, [[text]], context, _line, _offset),
+ do: {[{:li, text}], context}
+
defp emit_tree_node(_rest, [tag, [tag, inside]], context, _line, _offset),
do: {[{String.to_atom(tag), inside}], context}
defp emit_tree_node(_rest, [tag, [tag | nodes]], context, _line, _offset),
do: {[{String.to_atom(tag), nodes}], context}
defp emit_tree_node(_rest, [[text]], context, _line, _offset),
do: {[text], context}
def parse(text) do
with {:ok, nodes, _, _, _, _} <- parse_tree(text) do
{:ok, nodes}
else
{:error, e, _, _, _, _} ->
{:error, e}
end
end
end
diff --git a/test/bbcode/parser_test.exs b/test/bbcode/parser_test.exs
index 554f944..c16f3a9 100644
--- a/test/bbcode/parser_test.exs
+++ b/test/bbcode/parser_test.exs
@@ -1,59 +1,70 @@
defmodule BBCode.Parser.Test do
use ExUnit.Case
alias BBCode.Parser
describe "simple tags" do
test "it parses [b] tags correctly" do
assert {:ok, [b: "testing"]} = Parser.parse("[b]testing[/b]")
end
test "it parses [i] tags correctly" do
assert {:ok, [i: "testing"]} = Parser.parse("[i]testing[/i]")
end
test "it parses [u] tags correctly" do
assert {:ok, [u: "testing"]} = Parser.parse("[u]testing[/u]")
end
test "it parses [s] tags correctly" do
assert {:ok, [s: "testing"]} = Parser.parse("[s]testing[/s]")
end
test "it parses [code] tags correctly" do
assert {:ok, [code: "testing"]} = Parser.parse("[code]testing[/code]")
end
test "it parses [quote] tags correctly" do
assert {:ok, [quote: "testing"]} = Parser.parse("[quote]testing[/quote]")
end
end
describe "nested tags" do
test "it parses [ul] lists correctly" do
assert {:ok, [ul: [li: "a", li: "b"]]} = Parser.parse("[ul][li]a[/li][li]b[/li][/ul]")
end
test "it parses [ol] lists correctly" do
assert {:ok, [ol: [li: "a", li: "b"]]} = Parser.parse("[ol][li]a[/li][li]b[/li][/ol]")
end
end
describe "multiline" do
- test "it describes a multiline [li] list" do
+ test "it parses a multiline [li] list" do
data = """
[ul]
[li]a[/li]
[li]b[/li]
[/ul]
"""
assert {:ok, [{:ul, ["\n", {:li, "a"}, "\n", {:li, "b"}, "\n"]}, "\n"]} = Parser.parse(data)
end
+
+ test "it parses a multiline [*] list" do
+ data = """
+ [ul]
+ [*]a
+ [*]b
+ [/ul]
+ """
+
+ assert {:ok, [{:ul, ["\n", {:li, "a"}, {:li, "b"}]}, "\n"]} = Parser.parse(data)
+ end
end
describe "invalid input" do
test "it fails to parse unterminated input" do
{:error, "expected end of string"} = Parser.parse("hello [b]world")
end
end
end

File Metadata

Mime Type
text/x-diff
Expires
Tue, Nov 26, 6:09 PM (1 d, 10 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
40455
Default Alt Text
(4 KB)

Event Timeline