Skip to content

Commit

Permalink
Refs: #171; readded not yet correct typespecs
Browse files Browse the repository at this point in the history
  • Loading branch information
RobertDober committed Apr 3, 2018
1 parent 69367f5 commit 7dd5219
Show file tree
Hide file tree
Showing 10 changed files with 45 additions and 0 deletions.
6 changes: 6 additions & 0 deletions lib/earmark.ex
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ defmodule Earmark do
"""

alias Earmark.Options
alias Earmark.Context
import Earmark.Message, only: [emit_messages: 1, sort_messages: 1]

@doc """
Expand Down Expand Up @@ -306,6 +307,7 @@ defmodule Earmark do
Earmark.as_html(original, %Options{smartypants: false})
"""
@spec as_html(String.t | list(String.t), %Options{}) :: {:ok, String.t, list()} | {:error, String.t, list(String.t)}
def as_html(lines, options \\ %Options{}) do
{context, html} = _as_html(lines, options)
case sort_messages(context) do
Expand All @@ -320,13 +322,15 @@ defmodule Earmark do
Otherwise it behaves exactly as `as_html`.
"""
@spec as_html!(String.t | list(String.t), %Options{}) :: String.t
def as_html!(lines, options \\ %Options{})
def as_html!(lines, options = %Options{}) do
{context, html} = _as_html(lines, options)
emit_messages(context)
html
end

@spec _as_html(String.t | list(String.t), %Options{}) :: {%Context{}, String.t}
defp _as_html(lines, options) do
{blocks, context} = parse(lines, options)
case blocks do
Expand All @@ -344,6 +348,7 @@ defmodule Earmark do
for more details.
"""

@spec parse(String.t | list(String.t), %Options{}) :: { Earmark.Block.ts, %Context{} }
def parse(lines, options \\ %Earmark.Options{})
def parse(lines, options = %Options{mapper: mapper}) when is_list(lines) do
{ blocks, links, options1 } = Earmark.Parser.parse(lines, options, false)
Expand Down Expand Up @@ -377,6 +382,7 @@ defmodule Earmark do
end

@doc false
@spec pmap( list(A), (A -> Earmark.Line.t) ) :: Earmark.Line.ts
def pmap(collection, func) do
collection
|> Enum.map(fn item -> Task.async(fn -> func.(item) end) end)
Expand Down
10 changes: 10 additions & 0 deletions lib/earmark/block.ex
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ defmodule Earmark.Block do
# Then extract any id definitions, and build a map from them. Not
# for external consumption.

@spec parse( Line.ts, Options.t ) :: {ts, %{}, Options.t}
def parse(lines, options) do
{blocks, options} = lines |> remove_trailing_blank_lines() |> lines_to_blocks(options)
links = links_from_blocks(blocks)
Expand All @@ -66,6 +67,7 @@ defmodule Earmark.Block do
end


@spec _parse(Line.ts, ts, Options.t) :: {ts, Earmark.Message.ts}
defp _parse([], result, options), do: {result, options}

###################
Expand Down Expand Up @@ -331,6 +333,7 @@ defmodule Earmark.Block do
# Assign attributes that follow a block to that block #
#######################################################

@spec assign_attributes_to_blocks( ts, ts ) :: ts
def assign_attributes_to_blocks([], result), do: Enum.reverse(result)

def assign_attributes_to_blocks([ %Ial{attrs: attrs}, block | rest], result) do
Expand All @@ -349,6 +352,7 @@ defmodule Earmark.Block do
# @spec consolidate_para( ts ) :: { ts, ts, {nil | String.t, number} }
defp consolidate_para( lines ), do: _consolidate_para( lines, [], @not_pending )

@spec _consolidate_para( ts, ts, inline_code_continuation ) :: { ts, ts, inline_code_continuation }
defp _consolidate_para( [], result, pending ) do
{result, [], pending}
end
Expand All @@ -365,6 +369,7 @@ defmodule Earmark.Block do
# Consolidate one or more list items into a list #
##################################################

@spec consolidate_list_items( ts, ts ) :: ts
defp consolidate_list_items([], result) do
result |> Enum.map(&compute_list_spacing/1) # no need to reverse
end
Expand Down Expand Up @@ -405,6 +410,7 @@ defmodule Earmark.Block do
# Read in a table (consecutive TableLines with
# the same number of columns)

@spec read_table( ts, number, %Table{} ) :: { %Table{}, ts }
defp read_table([ %Line.TableLine{columns: cols} | rest ],
col_count,
table = %Table{})
Expand All @@ -426,6 +432,7 @@ defmodule Earmark.Block do
end


@spec look_for_alignments( [String.t] ) :: atom
defp look_for_alignments([ _first, second | _rest ]) do
if Enum.all?(second, fn row -> row =~ ~r{^:?-+:?$} end) do
second
Expand All @@ -451,6 +458,7 @@ defmodule Earmark.Block do
visit(blocks, Map.new, &link_extractor/2)
end

@spec link_extractor(t, %{}) :: %{}
defp link_extractor(item = %IdDef{id: id}, result) do
Map.put(result, String.downcase(id), item)
end
Expand All @@ -462,6 +470,7 @@ defmodule Earmark.Block do
# Visitor pattern for each block #
##################################

@spec visit(ts, %{}, (t, %{} -> %{})) :: %{}
defp visit([], result, _func), do: result

# Structural node BlockQuote -> descend
Expand Down Expand Up @@ -534,6 +543,7 @@ defmodule Earmark.Block do


# (_,{'nil' | binary(),number()}) -> #{}jj
@spec inline_or_text?( Line.t, inline_code_continuation ) :: %{pending: String.t, continue: boolean}
defp inline_or_text?(line, pending)
defp inline_or_text?(line = %Line.Text{}, @not_pending) do
pending = opens_inline_code(line)
Expand Down
3 changes: 3 additions & 0 deletions lib/earmark/helpers/attr_parser.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ defmodule Earmark.Helpers.AttrParser do
import Earmark.Helpers.StringHelpers, only: [ behead: 2 ]
import Earmark.Message, only: [add_message: 2]

alias Earmark.Context

@type errorlist :: list(String.t)

@spec parse_attrs(Context.t, String.t, number()) :: {map, errorlist}
def parse_attrs(context, attrs, lnb) do
{ attrs, errors } = _parse_attrs(%{}, attrs, [], lnb)
{ add_errors(context, errors, lnb), attrs }
Expand Down
1 change: 1 addition & 0 deletions lib/earmark/helpers/line_helpers.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ defmodule Earmark.Helpers.LineHelpers do

alias Earmark.Line

@spec blank?(Line.t) :: boolean
def blank?(%Line.Blank{}), do: true
def blank?(_), do: false

Expand Down
4 changes: 4 additions & 0 deletions lib/earmark/helpers/lookahead_helpers.ex
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ defmodule Earmark.Helpers.LookaheadHelpers do
Otherwise `{nil, 0}` is returned
"""
@spec opens_inline_code(numbered_line) :: inline_code_continuation
def opens_inline_code( %{line: line, lnb: lnb} ) do
case tokenize(line, with: :string_lexer) |> has_still_opening_backtix(nil) do
nil -> {nil, 0}
Expand All @@ -29,6 +30,7 @@ defmodule Earmark.Helpers.LookaheadHelpers do
opening backtix
"""
# (#{},{_,_}) -> {_,_}
@spec still_inline_code(numbered_line, inline_code_continuation) :: inline_code_continuation
def still_inline_code( %{line: line, lnb: lnb}, old = {pending, _pending_lnb} ) do
case tokenize(line, with: :string_lexer) |> has_still_opening_backtix({:old, pending}) do
nil -> {nil, 0}
Expand Down Expand Up @@ -56,6 +58,7 @@ defmodule Earmark.Helpers.LookaheadHelpers do
#######################################################################################
# read_list_lines
#######################################################################################
@spec read_list_lines( Line.ts, inline_code_continuation, number ) :: {boolean, Line.ts, Line.ts, number, number}
@doc """
Called to slurp in the lines for a list item.
basically, we allow indents and blank lines, and
Expand All @@ -69,6 +72,7 @@ defmodule Earmark.Helpers.LookaheadHelpers do

@type read_list_info :: %{pending: maybe(String.t), pending_lnb: number, initial_indent: number, min_indent: maybe(number)}

@spec _read_list_lines(Line.ts, Line.ts, read_list_info) :: {boolean, Line.ts, Line.ts, number}
# List items with initial_indent + 2
defp _read_list_lines([ line = %Line.ListItem{initial_indent: li_indent} | rest ], result,
params=%{pending: nil, initial_indent: initial_indent, min_indent: min_indent})
Expand Down
1 change: 1 addition & 0 deletions lib/earmark/helpers/string_helpers.ex
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ defmodule Earmark.Helpers.StringHelpers do
iex> behead_tuple("prefixpostfix", "prefix")
{"prefix", "postfix"}
"""
@spec behead_tuple( String.t, String.t ) :: {String.t, String.t}
def behead_tuple(str, lead) do
{lead, behead(str, lead)}
end
Expand Down
1 change: 1 addition & 0 deletions lib/earmark/line.ex
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ defmodule Earmark.Line do
# proceeding

# (_,atom() | tuple() | #{},_) -> ['Elixir.B']
@spec scan_lines( list(String.t), %Earmark.Options{}, boolean ) :: ts
def scan_lines lines, options \\ %Earmark.Options{}, recursive \\ false
def scan_lines lines, options, recursive do
lines_with_count( lines, options.line - 1)
Expand Down
6 changes: 6 additions & 0 deletions lib/earmark/message.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ defmodule Earmark.Message do
@type ts:: list(t)
@type container_type :: Options.t | Context.t

@spec add_messages(container_type, ts) :: container_type
def add_messages(container, messages), do:
Enum.reduce(messages, container, &(add_message(&2, &1)))

@spec add_message(container_type, t) :: container_type
def add_message(container, message)
def add_message(options = %Options{}, message) do
%{options | messages: [message | options.messages]}
Expand All @@ -19,14 +21,17 @@ defmodule Earmark.Message do
%{context | options: %{context.options | messages: [message | get_messages(context)]}}
end

@spec add_messages_from(Context.t, Context.t) :: Context.t
def add_messages_from(context, message_container) do
add_messages(context, message_container.options.messages)
end

@spec get_messages( container_type ) :: ts
def get_messages(container)
def get_messages(%Context{options: %{messages: messages}}), do: messages
def get_messages(%Options{messages: messages}), do: messages

@spec set_messages( Context.t, ts ) :: Context.t
def set_messages(container, messages)
def set_messages(c = %Context{}, messages), do: put_in(c.options.messages, messages)

Expand All @@ -49,6 +54,7 @@ defmodule Earmark.Message do
defp emit_message(filename, msg), do:
IO.puts(:stderr, format_message(filename, msg))

@spec format_message( String.t, t ) :: String.t
defp format_message filename, {type, line, text} do
"#{filename}:#{line}: #{type}: #{text}"
end
Expand Down
6 changes: 6 additions & 0 deletions lib/earmark/parser.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ defmodule Earmark.Parser do
import Earmark.Message, only: [add_messages: 2]


@spec parse(list(String.t), %Earmark.Options{}, boolean) :: {Block.ts(), %{}}
def parse(text_lines), do: parse(text_lines, %Earmark.Options{}, false)

def parse(text_lines, options = %Earmark.Options{}, recursive) do
Expand All @@ -30,9 +31,11 @@ defmodule Earmark.Parser do
{ blocks, footnotes, options1 }
end

@spec footnote_def?( Block.t )::boolean
defp footnote_def?(%Block.FnDef{}), do: true
defp footnote_def?(_block), do: false

@spec find_footnote_links(Block.t) :: list(String.t)
defp find_footnote_links(%Block.Para{lines: lines, lnb: lnb}) do
lines
|> Enum.zip(Stream.iterate(lnb, &(&1 + 1)))
Expand All @@ -43,13 +46,15 @@ defmodule Earmark.Parser do
end
defp find_footnote_links(_), do: []

@spec extract_footnote_links({String.t, number()}) :: list({String.t, number()})
defp extract_footnote_links({line, lnb}) do
Regex.scan(~r{\[\^([^\]]+)\]}, line)
|> Enum.map(&tl/1)
|> Enum.zip(Stream.cycle([lnb]))
end


@spec get_footnote_numbers( list({String.t, number()} ), Block.ts, %Earmark.Options{} ) :: Block.ts
def get_footnote_numbers(refs, footnotes, options) do
Enum.reduce(refs, {[], []}, fn({ref, lnb}, {defined, undefined}) ->
r = hd(ref)
Expand All @@ -62,6 +67,7 @@ defmodule Earmark.Parser do
end)
end

@spec create_footnote_blocks(Block.ts, Block.ts) :: Block.ts
defp create_footnote_blocks(blocks, []), do: blocks

defp create_footnote_blocks(blocks, footnotes) do
Expand Down
7 changes: 7 additions & 0 deletions lib/earmark/scanner.ex
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ defmodule Earmark.Scanner do
@type t_continuation :: {token, String.t, boolean()}


@spec scan_line( String.t ) :: tokens
@doc """
Scans a line into a list of tokens
"""
Expand All @@ -44,6 +45,7 @@ defmodule Earmark.Scanner do
|> Enum.reverse
end

@spec scan_line_into_tokens( String.t, tokens, boolean() ) :: tokens
# Empty Line
defp scan_line_into_tokens "", [], _beg do
[]
Expand All @@ -56,6 +58,7 @@ defmodule Earmark.Scanner do
scan_line_into_tokens( rest, [token|tokens], still_at_beg )
end

@spec scan_next_token( String.t, boolean ) :: false | t_continuation
defp scan_next_token line, beg_of_line
defp scan_next_token line, true do
cond do
Expand Down Expand Up @@ -102,6 +105,7 @@ defmodule Earmark.Scanner do
|> Tuple.append( false )
end

@spec scan_token_not_at_beg( String.t ) :: {} | t_continuation
defp scan_token_not_at_beg line do
cond do
matches = Regex.run( @backtix_rgx, line ) ->
Expand All @@ -119,6 +123,7 @@ defmodule Earmark.Scanner do
end
end

@spec make_ruler_from( String.t ) :: token
defp make_ruler_from type do
case type do
"*" -> %RulerFat{}
Expand All @@ -127,6 +132,7 @@ defmodule Earmark.Scanner do
end
end

@spec make_list_item( String.t ) :: %ListItem{}
defp make_list_item bullet do
case bullet do
"*" -> %ListItem{type: :ul, bullet: "*"}
Expand All @@ -135,6 +141,7 @@ defmodule Earmark.Scanner do
end
end

@spec prefixed_with_ws(String.t, String.t) :: false | { %Text{}, String.t, true}
defp prefixed_with_ws line, ws do
if ws == "" do
false
Expand Down

0 comments on commit 7dd5219

Please sign in to comment.