Current section
Files
Jump to
Current section
Files
lib/lofi_parse.ex
defmodule Lofi.Parse do
@moduledoc """
Parses Lofi content into a structure of text, tags, and mentions.
"""
@tags_regex ~r/\B#[A-Za-z0-9_-]+(:\s*[^#]*)?/
@tag_key_value_regex ~r/\B#([a-zA-Z0-9-_]+)(:\s*([^#]*))?/
@mentions_regex ~r/@([a-zA-Z0-9_-]+(?:\.[a-zA-Z0-9-_]+)*)/
defp clean_text(input) do
Regex.replace(@tags_regex, input, "")
end
defp parse_tag_key_value(input) do
case Regex.run(@tag_key_value_regex, input) do
[_whole, key] ->
{key, {:flag, true}}
[_whole, key, _left, value] ->
{key, {:value, String.trim(value)}}
end
end
defp parse_tags(input) do
Regex.scan(@tags_regex, input)
|> Enum.map( fn l ->
l
|> List.first
|> parse_tag_key_value
end)
|> Map.new
end
defp parse_mention(input) do
String.slice(input, 1..-1) # Remove leading @
|> String.split(".")
end
defp parse_texts_and_mentions(input) do
texts_and_mentions = Regex.split(@mentions_regex, input, include_captures: true)
process_texts_and_mentions(texts_and_mentions, [], [])
end
defp process_texts_and_mentions([ "" ], texts, mentions) do
process_texts_and_mentions([], texts, mentions)
end
defp process_texts_and_mentions([ text ], texts, mentions) do
process_texts_and_mentions([], [ text | texts ], mentions)
end
defp process_texts_and_mentions([ text | [ mention | rest ] ], texts, mentions) do
process_texts_and_mentions(rest, [ text | texts ], [ parse_mention(mention) | mentions ])
end
defp process_texts_and_mentions([], texts, mentions) do
{Enum.reverse(texts), Enum.reverse(mentions)}
end
@doc """
Parses Lofi content into a structure of text, tags, and mentions.
## Examples
iex> Lofi.Parse.parse_element("hello")
%Lofi.Element{ texts: ["hello"], tags: %{} }
iex> Lofi.Parse.parse_element("Click me #button")
%Lofi.Element{ texts: ["Click me"], tags: %{ "button" => {:flag, true} } }
iex> Lofi.Parse.parse_element("hello @first-name @last-name")
%Lofi.Element{ texts: ["hello ", " "], mentions: [["first-name"], ["last-name"]] }
"""
def parse_element(raw_string) when is_bitstring(raw_string) do
{texts, mentions} = raw_string
|> clean_text
|> String.trim
|> parse_texts_and_mentions
tags = parse_tags(raw_string)
%Lofi.Element{ texts: texts, mentions: mentions, tags: tags }
end
end