diff --git a/lib/simplates/pagination.ex b/lib/simplates/pagination.ex index b963013..61c57d5 100644 --- a/lib/simplates/pagination.ex +++ b/lib/simplates/pagination.ex @@ -10,31 +10,46 @@ defmodule Simplates.Pagination do import Simplates.Simplate, only: [config: 1] - @script_regex ~r/^\(?P.+?)^\<\/script\>/sim - @template_regex ~r/^\(?P.+?)^\<\/template\>/sim + def parse_pages(raw) do + blocks = Simplates.Parser.parse(raw) |> parse_blocks - def parse_pages(raw) do - raw = "" <> raw <> "" - script = parse_scripts(Floki.find(raw, "root > script")) - templates = parse_templates(Floki.find(raw, "root > template")) + script = parse_scripts(blocks[:script_blocks]) + templates = parse_templates(blocks[:template_blocks]) %{code: script, templates: templates} end + defp parse_blocks(blocks) do + Enum.reduce(blocks, %{}, fn(b, acc) -> + {tag, _, _} = Floki.parse(b) + + type = cond do + tag == "script" -> :script_blocks + tag == "template" -> :template_blocks + end + + b = String.trim(b) + + Map.put(acc, type, Map.get(acc, type, []) ++ [b]) + end) + end + defp parse_scripts(raw_script) when length(raw_script) == 1 do # For now you can only have one script - {_, _, children_nodes} = raw_script |> hd() - page_content = Floki.raw_html(children_nodes) + page_content = hd(raw_script) + |> String.split("\n") + |> Enum.drop(1) + |> Enum.drop(-1) + |> Enum.join("\n") %Simplates.Page{ - raw: page_content, - # Is this the right place to compile? + raw: page_content, compiled: Simplates.Renderers.CodeRenderer.compile(page_content), renderer: Simplates.Renderers.CodeRenderer, content_type: nil } end - defp parse_scripts([]) do + defp parse_scripts(nil) do %Simplates.Page{ raw: "", compiled: Simplates.Renderers.CodeRenderer.compile(""), @@ -49,12 +64,20 @@ defmodule Simplates.Pagination do Map.put(acc, template.content_type, template) end) end - defp parse_templates([]) do + defp parse_templates(nil) do {} end - defp parse_template({_, _, children_nodes} = html_tree) do - page_content = Floki.raw_html(children_nodes) |> String.trim_leading() |> String.trim_trailing() + defp parse_template(raw_template) do + header = raw_template |> String.split("\n") |> hd() + + html_tree = Floki.parse(header <> "") + + page_content = raw_template + |> String.split("\n") + |> Enum.drop(1) + |> Enum.drop(-1) + |> Enum.join("\n") {renderer_found, renderer} = attr_or_default(:renderer, Floki.attribute([html_tree], "via"), config(:default_renderer)) # content type will be fixed in simplates, due to bound simplates diff --git a/lib/simplates/parser.ex b/lib/simplates/parser.ex new file mode 100644 index 0000000..83073dd --- /dev/null +++ b/lib/simplates/parser.ex @@ -0,0 +1,42 @@ +defmodule Simplates.Parser do + @moduledoc """ + Handles blocking out a file into blocks of templates/scripts + + Then it's up to specline to the paginator/specline + """ + + @block_regex ~r/(^\|^\)|(^\<\/template\>|^\<\/script\>)/im + + def parse(input) do + input |> String.trim() |> String.split("\n") |> find_block() + end + + def find_block(lines) do + find_block(lines, 0, [], []) + end + + def find_block(remaining, found, in_block, blocks) when found == 2 do + in_block = Enum.join(in_block, "\n") + find_block(remaining, 0, [], blocks ++ [in_block]) + end + + def find_block([], _found, _in_block, blocks) do + blocks + end + + def find_block(remaining, found, in_block, blocks) do + line = hd(remaining) + regex_matches = Regex.match?(@block_regex, line) + + in_block = in_block ++ [line] + + found = + case regex_matches do + true -> found + 1 + false -> found + end + + find_block(Enum.drop(remaining, 1), found, in_block, blocks) + end + +end \ No newline at end of file diff --git a/test.exs b/test.exs deleted file mode 100644 index 53c78e2..0000000 --- a/test.exs +++ /dev/null @@ -1,84 +0,0 @@ -defmodule XmlNode do - require Record - Record.defrecord :xmlAttribute, Record.extract(:xmlAttribute, from_lib: "xmerl/include/xmerl.hrl") - Record.defrecord :xmlText, Record.extract(:xmlText, from_lib: "xmerl/include/xmerl.hrl") - - def from_string(xml_string, options \\ [quiet: true]) do - {doc, []} = - xml_string - |> :binary.bin_to_list - |> :xmerl_scan.string(options) - - doc - end - - def all(node, path) do - for child_element <- xpath(node, path) do - child_element - end - end - - def first(node, path), do: node |> xpath(path) |> take_one - defp take_one([head | _]), do: head - defp take_one(_), do: nil - - def node_name(nil), do: nil - def node_name(node), do: elem(node, 1) - - def attr(node, name), do: node |> xpath('./@#{name}') |> extract_attr - defp extract_attr([xmlAttribute(value: value)]), do: List.to_string(value) - defp extract_attr(_), do: nil - - def text(node), do: node |> xpath('./text()') |> extract_text - defp extract_text([xmlText(value: value)]), do: List.to_string(value) - defp extract_text(_x), do: nil - - defp xpath(nil, _), do: [] - defp xpath(node, path) do - :xmerl_xpath.string(to_char_list(path), node) - end -end - -doc = XmlNode.from_string( - """ - - - -""" -) - -IO.inspect(doc) - -Enum.each(XmlNode.all(doc, "//root/template"), fn(node) -> - IO.inspect(node) - IO.puts "#{XmlNode.node_name(node)} id=#{XmlNode.attr(node, "id")} text=#{XmlNode.text(node)}" -end) - -IO.puts( - doc - |> XmlNode.first("//child[@id='2']") - |> XmlNode.text -) - -IO.puts( - doc - |> XmlNode.first("//child[@id='3']") - |> XmlNode.text -) - -IO.puts( - doc - |> XmlNode.first("//root") - |> XmlNode.first("template") - |> XmlNode.text -) \ No newline at end of file diff --git a/test/simplates/fake-www/index.spt b/test/simplates/fake-www/index.spt index 1e7fbdd..4a9e0fb 100644 --- a/test/simplates/fake-www/index.spt +++ b/test/simplates/fake-www/index.spt @@ -1 +1,3 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/test/simplates/pagination_test.exs b/test/simplates/pagination_test.exs index 4711e44..2b4a23e 100644 --- a/test/simplates/pagination_test.exs +++ b/test/simplates/pagination_test.exs @@ -4,7 +4,7 @@ defmodule Simplates.PaginationTest do alias Simplates.Pagination, as: Pagination test "single page adds one code pages" do - pages = Pagination.parse_pages("") + pages = Pagination.parse_pages("") assert pages.code.raw == "" assert pages.templates[nil].raw == "Hello, world! I have no code!" @@ -12,8 +12,12 @@ defmodule Simplates.PaginationTest do test "two page adds nothing" do pages = Pagination.parse_pages(" - - ") + +") assert String.trim(pages.code.raw) == "some_code = 3" assert String.trim(pages.templates[nil].raw) == "Hello, world! I have SOME code!" @@ -21,17 +25,20 @@ defmodule Simplates.PaginationTest do test "two page adds nothing with specline" do pages = Pagination.parse_pages(" - -