1
1
defmodule ExDoc.Formatter.HTML.SearchData do
2
2
@ moduledoc false
3
- alias ExDoc.Utils
4
3
5
4
def create ( nodes , extras , proglang ) do
6
5
items = Enum . flat_map ( nodes , & module / 1 ) ++ Enum . flat_map ( extras , & extra / 1 )
@@ -24,147 +23,92 @@ defmodule ExDoc.Formatter.HTML.SearchData do
24
23
Enum . map ( search_data , fn item ->
25
24
link =
26
25
if item . anchor === "" do
27
- "#{ map . id } .html"
26
+ "#{ URI . encode ( map . id ) } .html"
28
27
else
29
- "#{ map . id } .html##{ item . anchor } "
28
+ "#{ URI . encode ( map . id ) } .html##{ URI . encode ( item . anchor ) } "
30
29
end
31
30
32
31
encode ( link , item . title <> " - #{ map . id } " , item . type , clean_markdown ( item . body ) )
33
32
end )
34
33
end
35
34
36
35
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 ) ]
58
41
end
59
42
60
43
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
84
49
end
85
50
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 ) ]
108
57
end
109
58
110
59
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 }
117
61
end
118
62
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 )
122
66
end
123
67
124
- defp extract_sections ( "application/erlang+html" , % { rendered_doc : nil } ) do
125
- { nil , [ ] }
68
+ defp extract_sections ( _format , % { doc : nil } , _prefix ) do
69
+ { "" , [ ] }
126
70
end
127
71
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 , " " ) , [ ] }
130
74
end
131
75
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 ] =
139
78
Regex . split ( ~r/ (?<!#)###? (?<header>\b .+)/ , string , include_captures: true )
140
79
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 ( )
144
85
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 )
150
92
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 )
153
97
154
98
{ clean_markdown ( intro ) , sections }
155
99
end
156
100
157
- defp clean_markdown ( doc ) do
158
- doc
101
+ defp clean_markdown ( text ) do
102
+ text
159
103
|> ExDoc.Utils . strip_tags ( " " )
104
+ |> drop_ignorable_codeblocks ( )
160
105
|> String . trim ( )
161
106
end
162
107
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
168
112
end
169
113
170
114
@ ignored_codeblocks ~w[ vega-lite]
0 commit comments