11defmodule ExDoc.Formatter.HTML.SearchData do
22 @ moduledoc false
3- alias ExDoc.Utils
43
54 def create ( nodes , extras , proglang ) do
65 items = Enum . flat_map ( nodes , & module / 1 ) ++ Enum . flat_map ( extras , & extra / 1 )
@@ -24,147 +23,92 @@ defmodule ExDoc.Formatter.HTML.SearchData do
2423 Enum . map ( search_data , fn item ->
2524 link =
2625 if item . anchor === "" do
27- "#{ map . id } .html"
26+ "#{ URI . encode ( map . id ) } .html"
2827 else
29- "#{ map . id } .html##{ item . anchor } "
28+ "#{ URI . encode ( map . id ) } .html##{ URI . encode ( item . anchor ) } "
3029 end
3130
3231 encode ( link , item . title <> " - #{ map . id } " , item . type , clean_markdown ( item . body ) )
3332 end )
3433 end
3534
3635 defp extra ( map ) do
37- { intro , sections } = extract_sections_from_markdown ( map . source )
38-
39- intro_json_item =
40- encode (
41- "#{ map . id } .html" ,
42- map . title ,
43- :extras ,
44- intro
45- )
46-
47- section_json_items =
48- for { header , body } <- sections do
49- encode (
50- "#{ map . id } .html##{ Utils . text_to_id ( header ) } " ,
51- header <> " - #{ map . title } " ,
52- :extras ,
53- body
54- )
55- end
56-
57- [ intro_json_item | section_json_items ]
36+ page = URI . encode ( map . id ) <> ".html"
37+ { intro , sections } = extract_sections_from_markdown ( map . source , "" )
38+
39+ intro = encode ( page , map . title , :extras , intro )
40+ [ intro | render_sections ( sections , page , map . title , :extras ) ]
5841 end
5942
6043 defp module ( % ExDoc.ModuleNode { } = node ) do
61- # TODO: This should work on DocAST
62- { intro , sections } = extract_sections ( node . doc_format , node )
63-
64- module =
65- encode (
66- "#{ node . id } .html" ,
67- node . title ,
68- node . type ,
69- intro
70- )
71-
72- module_sections =
73- for { header , body } <- sections do
74- encode (
75- "#{ node . id } .html#module-#{ Utils . text_to_id ( header ) } " ,
76- header <> " - #{ node . title } " ,
77- node . type ,
78- body
79- )
80- end
81-
82- docs = Enum . flat_map ( node . docs , & node_child ( & 1 , node ) )
83- [ module ] ++ module_sections ++ docs
44+ page = URI . encode ( node . id ) <> ".html"
45+ { intro , sections } = extract_sections ( node . source_format , node , "module-" )
46+ module = encode ( page , node . title , node . type , intro )
47+ docs = Enum . flat_map ( node . docs , & node_child ( & 1 , node , page ) )
48+ [ module ] ++ render_sections ( sections , page , node . title , node . type ) ++ docs
8449 end
8550
86- defp node_child ( node , module_node ) do
87- { intro , sections } = extract_sections ( module_node . doc_format , node )
88-
89- child =
90- encode (
91- "#{ module_node . id } .html##{ node . id } " ,
92- "#{ module_node . id } .#{ node . name } /#{ node . arity } " ,
93- node . type ,
94- intro
95- )
96-
97- child_sections =
98- for { header , body } <- sections do
99- encode (
100- "#{ module_node . id } .html##{ node . id } -#{ Utils . text_to_id ( header ) } " ,
101- header <> " - #{ module_node . id } .#{ node . name } /#{ node . arity } " ,
102- node . type ,
103- body
104- )
105- end
106-
107- [ child ] ++ child_sections
51+ defp node_child ( node , module_node , page ) do
52+ title = "#{ module_node . id } .#{ node . name } /#{ node . arity } "
53+ { intro , sections } = extract_sections ( module_node . source_format , node , node . id <> "-" )
54+
55+ child = encode ( "#{ page } ##{ URI . encode ( node . id ) } " , title , node . type , intro )
56+ [ child | render_sections ( sections , page , title , node . type ) ]
10857 end
10958
11059 defp encode ( ref , title , type , doc ) do
111- % {
112- ref: URI . encode ( ref ) ,
113- title: title ,
114- type: type ,
115- doc: doc
116- }
60+ % { ref: ref , title: title , type: type , doc: doc }
11761 end
11862
119- # TODO: Perform this via DocAST and remove doc_format (and perhaps source_doc)
120- defp extract_sections ( "text/markdown" , % { source_doc: % { "en" => doc } } ) do
121- extract_sections_from_markdown ( doc )
63+ # TODO: Perform this via DocAST and remove source_format (and perhaps source_doc)
64+ defp extract_sections ( "text/markdown" , % { source_doc: % { "en" => doc } } , prefix ) do
65+ extract_sections_from_markdown ( doc , prefix )
12266 end
12367
124- defp extract_sections ( "application/erlang+html" , % { rendered_doc : nil } ) do
125- { nil , [ ] }
68+ defp extract_sections ( _format , % { doc : nil } , _prefix ) do
69+ { "" , [ ] }
12670 end
12771
128- defp extract_sections ( "application/erlang+html" , % { rendered_doc : doc } ) do
129- { clean_html ( doc ) , [ ] }
72+ defp extract_sections ( _format , % { doc : doc } , _prefix ) do
73+ { ExDoc.DocAST . text ( doc , " " ) , [ ] }
13074 end
13175
132- defp extract_sections ( _format , _doc ) do
133- { "" , [ ] }
134- end
135-
136- # TODO: This should work on DocAST when we prebuild extra.
137- defp extract_sections_from_markdown ( string ) do
138- [ intro | sections ] =
76+ defp extract_sections_from_markdown ( string , prefix ) do
77+ [ intro | headers_sections ] =
13978 Regex . split ( ~r/ (?<!#)###? (?<header>\b .+)/ , string , include_captures: true )
14079
141- sections =
142- for [ header , section ] <- Enum . chunk_every ( sections , 2 ) do
143- header = String . trim_leading ( header , "#" )
80+ { headers , sections } =
81+ headers_sections
82+ |> Enum . chunk_every ( 2 )
83+ |> Enum . map ( fn [ header , section ] -> { header , section } end )
84+ |> Enum . unzip ( )
14485
145- section =
146- section
147- |> ExDoc.Utils . strip_tags ( " " )
148- |> drop_ignorable_codeblocks ( )
149- |> String . trim ( )
86+ # Now convert the headers into a single markdown document
87+ header_tags =
88+ headers
89+ |> Enum . join ( "\n \n " )
90+ |> ExDoc.Markdown . to_ast ( )
91+ |> ExDoc.DocAST . add_ids_to_headers ( [ :h2 , :h3 ] , prefix )
15092
151- { clean_markdown ( header ) , section }
152- end
93+ sections =
94+ Enum . zip_with ( header_tags , sections , fn { _ , attrs , inner , _ } , section ->
95+ { ExDoc.DocAST . text ( inner ) , Keyword . fetch! ( attrs , :id ) , clean_markdown ( section ) }
96+ end )
15397
15498 { clean_markdown ( intro ) , sections }
15599 end
156100
157- defp clean_markdown ( doc ) do
158- doc
101+ defp clean_markdown ( text ) do
102+ text
159103 |> ExDoc.Utils . strip_tags ( " " )
104+ |> drop_ignorable_codeblocks ( )
160105 |> String . trim ( )
161106 end
162107
163- defp clean_html ( doc ) do
164- doc
165- |> ExDoc.Utils . strip_tags ( " " )
166- |> String . replace ( ~r/ \s +/ , " " )
167- |> String . trim ( )
108+ defp render_sections ( sections , page , title , type ) do
109+ for { header , anchor , body } <- sections do
110+ encode ( "#{ page } ##{ anchor } " , header <> " - " <> title , type , body )
111+ end
168112 end
169113
170114 @ ignored_codeblocks ~w[ vega-lite]
0 commit comments