15
15
StandaloneHTMLBuilder )
16
16
from sphinx .util .console import bold
17
17
18
+
18
19
from .embed import EmbedDirective
19
20
from .mixins import BuilderMixin
20
21
27
28
log = getLogger (__name__ )
28
29
29
30
DEFAULT_STATIC_URL = 'https://assets.readthedocs.org/static/'
31
+ ONLINE_BUILDERS = [
32
+ 'readthedocs' , 'readthedocsdirhtml' , 'readthedocssinglehtml'
33
+ ]
34
+ # Only run JSON output once during HTML build
35
+ # This saves resources and keeps filepaths correct,
36
+ # because singlehtml filepaths are different
37
+ JSON_BUILDERS = [
38
+ 'html' , 'dirhtml' ,
39
+ 'readthedocs' , 'readthedocsdirhtml'
40
+ ]
30
41
31
42
# Whitelist keys that we want to output
32
43
# to the json artifacts.
33
- KEYS = [
44
+ JSON_KEYS = [
34
45
'body' ,
35
46
'title' ,
36
47
'sourcename' ,
@@ -65,15 +76,12 @@ def update_body(app, pagename, templatename, context, doctree):
65
76
"""
66
77
67
78
STATIC_URL = context .get ('STATIC_URL' , DEFAULT_STATIC_URL )
68
- online_builders = [
69
- 'readthedocs' , 'readthedocsdirhtml' , 'readthedocssinglehtml'
70
- ]
71
79
if app .builder .name == 'readthedocssinglehtmllocalmedia' :
72
80
if 'html_theme' in context and context ['html_theme' ] == 'sphinx_rtd_theme' :
73
81
theme_css = '_static/css/theme.css'
74
82
else :
75
83
theme_css = '_static/css/badge_only.css'
76
- elif app .builder .name in online_builders :
84
+ elif app .builder .name in ONLINE_BUILDERS :
77
85
if 'html_theme' in context and context ['html_theme' ] == 'sphinx_rtd_theme' :
78
86
theme_css = '%scss/sphinx_rtd_theme.css' % STATIC_URL
79
87
else :
@@ -148,6 +156,8 @@ def generate_json_artifacts(app, pagename, templatename, context, doctree):
148
156
149
157
This way we can skip generating this in other build step.
150
158
"""
159
+ if app .builder .name not in JSON_BUILDERS :
160
+ return
151
161
try :
152
162
# We need to get the output directory where the docs are built
153
163
# _build/json.
@@ -161,7 +171,7 @@ def generate_json_artifacts(app, pagename, templatename, context, doctree):
161
171
with open (outjson , 'w+' ) as json_file :
162
172
to_context = {
163
173
key : context .get (key , '' )
164
- for key in KEYS
174
+ for key in JSON_KEYS
165
175
}
166
176
json .dump (to_context , json_file , indent = 4 )
167
177
except TypeError :
@@ -172,12 +182,73 @@ def generate_json_artifacts(app, pagename, templatename, context, doctree):
172
182
log .exception (
173
183
'Fail to save JSON output for page {page}' .format (page = outjson )
174
184
)
175
- except Exception as e :
185
+ except Exception :
176
186
log .exception (
177
187
'Failure in JSON search dump for page {page}' .format (page = outjson )
178
188
)
179
189
180
190
191
+ def dump_sphinx_data (app , exception ):
192
+ """
193
+ Dump data that is only in memory during Sphinx build.
194
+ This is mostly used for search indexing.
195
+
196
+ This includes:
197
+
198
+ * `paths`: A mapping of HTML Filename -> RST file
199
+ * `pages`: A mapping of HTML Filename -> Sphinx Page name
200
+ * `titles`: A mapping of HTML Filename -> Page Title
201
+ * `types`: A mapping of Sphinx Domain type slugs -> human-readable name for that type
202
+
203
+ """
204
+ if app .builder .name not in JSON_BUILDERS or exception :
205
+ return
206
+ try :
207
+ types = {}
208
+ titles = {}
209
+ paths = {}
210
+ pages = {}
211
+
212
+ for domain_name , domain_obj in app .env .domains .items ():
213
+ for type_name , type_obj in domain_obj .object_types .items ():
214
+ key = "{}:{}" .format (domain_name , type_name )
215
+ types [key ] = str (type_obj .lname )
216
+
217
+ for page , title in app .env .titles .items ():
218
+ page_uri = app .builder .get_target_uri (page )
219
+ titles [page_uri ] = title .astext ()
220
+ paths [page_uri ] = app .env .doc2path (page , base = None )
221
+ pages [page_uri ] = page
222
+
223
+ to_dump = {
224
+ 'types' : types ,
225
+ 'titles' : titles ,
226
+ 'paths' : paths ,
227
+ 'pages' : pages ,
228
+ }
229
+
230
+ # We need to get the output directory where the docs are built
231
+ # _build/json.
232
+ build_json = os .path .abspath (
233
+ os .path .join (app .outdir , '..' , 'json' )
234
+ )
235
+ outjson = os .path .join (build_json , 'readthedocs-sphinx-domain-names.json' )
236
+ with open (outjson , 'w+' ) as json_file :
237
+ json .dump (to_dump , json_file , indent = 4 )
238
+ except TypeError :
239
+ log .exception (
240
+ 'Fail to encode JSON for object names'
241
+ )
242
+ except IOError :
243
+ log .exception (
244
+ 'Fail to save JSON for object names'
245
+ )
246
+ except Exception :
247
+ log .exception (
248
+ 'Failure in JSON search dump for object names'
249
+ )
250
+
251
+
181
252
class HtmlBuilderMixin (BuilderMixin ):
182
253
183
254
static_readthedocs_files = [
@@ -271,6 +342,7 @@ def setup(app):
271
342
app .connect ('builder-inited' , finalize_media )
272
343
app .connect ('html-page-context' , update_body )
273
344
app .connect ('html-page-context' , generate_json_artifacts )
345
+ app .connect ('build-finished' , dump_sphinx_data )
274
346
275
347
# Embed
276
348
app .add_directive ('readthedocs-embed' , EmbedDirective )
0 commit comments