Packages
ex_doc
0.30.8
0.40.3
0.40.2
0.40.1
0.40.0
0.39.3
0.39.2
0.39.1
0.39.0
0.38.4
0.38.3
0.38.2
0.38.1
0.38.0
0.37.3
0.37.2
0.37.1
0.37.0
0.37.0-rc.2
0.37.0-rc.1
0.37.0-rc.0
0.36.1
0.36.0
0.35.1
0.35.0
0.34.2
0.34.1
0.34.0
0.33.0
0.32.2
0.32.1
0.32.0
0.31.2
0.31.1
0.31.0
0.30.9
0.30.8
0.30.7
0.30.6
0.30.5
0.30.4
0.30.3
0.30.2
0.30.1
0.30.0
0.29.4
0.29.3
0.29.2
0.29.1
0.29.0
0.28.6
0.28.5
0.28.4
0.28.3
0.28.2
0.28.1
0.28.0
0.27.3
0.27.2
0.27.1
0.27.0
0.26.0
0.25.5
0.25.4
0.25.3
0.25.2
0.25.1
0.25.0
0.24.2
0.24.1
0.24.0
0.23.0
0.22.6
0.22.5
0.22.4
0.22.2
0.22.1
0.22.0
0.21.3
0.21.2
0.21.1
0.21.0
0.20.2
0.20.1
0.20.0
0.19.3
0.19.2
0.19.1
0.19.0
0.19.0-rc
0.18.4
0.18.3
0.18.2
0.18.1
0.18.0
retired
0.17.1
0.17.0
retired
0.16.4
0.16.3
0.16.2
0.16.1
0.16.0
0.15.1
0.15.0
0.14.5
0.14.4
0.14.3
0.14.2
0.14.1
0.14.0
0.13.2
0.13.1
0.13.0
0.12.0
0.11.5
0.11.4
0.11.3
0.11.2
0.11.1
0.11.0
0.10.0
0.9.0
0.8.4
0.8.3
0.8.2
0.8.1
0.8.0
0.7.3
0.7.2
0.7.1
0.7.0
0.6.2
0.6.1
0.6.0
0.5.2
0.5.1
ExDoc is a documentation generation tool for Elixir
Current section
Files
Jump to
Current section
Files
lib/ex_doc/formatter/html/search_data.ex
defmodule ExDoc.Formatter.HTML.SearchData do
@moduledoc false
# TODO: It should not depend on the parent module
alias ExDoc.Formatter.HTML
def create(nodes, extras, proglang) do
content_type =
case proglang do
:elixir -> "text/markdown"
:erlang -> "text/plain"
end
items = Enum.flat_map(nodes, &module/1) ++ Enum.flat_map(extras, &extra/1)
data = %{
items: items,
content_type: content_type
}
["searchData=" | ExDoc.Utils.to_json(data)]
end
defp extra(map) do
{intro, sections} = extract_sections_from_markdown(map.source)
intro_json_item =
encode(
"#{map.id}.html",
map.title,
:extras,
intro
)
section_json_items =
for {header, body} <- sections do
encode(
"#{map.id}.html##{HTML.text_to_id(header)}",
header <> " - #{map.title}",
:extras,
body
)
end
[intro_json_item | section_json_items]
end
defp module(%ExDoc.ModuleNode{} = node) do
{intro, sections} = extract_sections(node.doc_format, node)
module =
encode(
"#{node.id}.html",
node.title,
node.type,
intro
)
module_sections =
for {header, body} <- sections do
encode(
"#{node.id}.html#module-#{HTML.text_to_id(header)}",
header <> " - #{node.title}",
node.type,
body
)
end
functions = Enum.flat_map(node.docs, &node_child(&1, node))
types = Enum.flat_map(node.typespecs, &node_child(&1, node))
[module] ++ module_sections ++ functions ++ types
end
defp node_child(node, module_node) do
{intro, sections} = extract_sections(module_node.doc_format, node)
child =
encode(
"#{module_node.id}.html##{node.id}",
"#{module_node.id}.#{node.name}/#{node.arity}",
node.type,
intro
)
child_sections =
for {header, body} <- sections do
encode(
"#{module_node.id}.html##{node.id}-#{HTML.text_to_id(header)}",
header <> " - #{module_node.id}.#{node.name}/#{node.arity}",
node.type,
body
)
end
[child] ++ child_sections
end
defp encode(ref, title, type, doc) do
%{
ref: URI.encode(ref),
title: title,
type: type,
doc: doc
}
end
defp extract_sections("text/markdown", %{source_doc: %{"en" => doc}}) do
extract_sections_from_markdown(doc)
end
defp extract_sections("application/erlang+html", %{rendered_doc: nil}) do
{nil, []}
end
defp extract_sections("application/erlang+html", %{rendered_doc: doc}) do
{clean_html(doc), []}
end
defp extract_sections(_format, _doc) do
{"", []}
end
defp extract_sections_from_markdown(string) do
[intro | sections] = Regex.split(~r/## (?<header>\b.+)/, string, include_captures: true)
sections =
for [header, section] <- Enum.chunk_every(sections, 2) do
"## " <> header = header
section =
section
|> HTML.strip_tags(" ")
|> drop_ignorable_codeblocks()
|> String.trim()
{clean_markdown(header), section}
end
{clean_markdown(intro), sections}
end
defp clean_markdown(doc) do
doc
|> HTML.strip_tags(" ")
|> String.trim()
end
defp clean_html(doc) do
doc
|> HTML.strip_tags(" ")
|> String.replace(~r/\s+/, " ")
|> String.trim()
end
@ignored_codeblocks ~w[vega-lite]
defp drop_ignorable_codeblocks(section) do
block_names = Enum.join(@ignored_codeblocks, "|")
String.replace(section, ~r/^```(?:#{block_names})\n(?:[\s\S]*?)```$/m, "")
end
end