animalize | 6261ae9 | 2018-10-08 16:20:54 -0500 | [diff] [blame] | 1 | """ |
| 2 | Escape the `body` part of .chm source file to 7-bit ASCII, to fix visual |
| 3 | effect on some MBCS Windows systems. |
| 4 | |
| 5 | https://bugs.python.org/issue32174 |
| 6 | """ |
| 7 | |
| 8 | import re |
| 9 | from html.entities import codepoint2name |
| 10 | |
Steve Dower | afe17a7 | 2018-12-19 18:20:06 -0800 | [diff] [blame] | 11 | from sphinx.util.logging import getLogger |
| 12 | |
animalize | 6261ae9 | 2018-10-08 16:20:54 -0500 | [diff] [blame] | 13 | # escape the characters which codepoint > 0x7F |
| 14 | def _process(string): |
| 15 | def escape(matchobj): |
| 16 | codepoint = ord(matchobj.group(0)) |
| 17 | |
| 18 | name = codepoint2name.get(codepoint) |
| 19 | if name is None: |
| 20 | return '&#%d;' % codepoint |
| 21 | else: |
| 22 | return '&%s;' % name |
| 23 | |
| 24 | return re.sub(r'[^\x00-\x7F]', escape, string) |
| 25 | |
| 26 | def escape_for_chm(app, pagename, templatename, context, doctree): |
| 27 | # only works for .chm output |
Steve Dower | afe17a7 | 2018-12-19 18:20:06 -0800 | [diff] [blame] | 28 | if getattr(app.builder, 'name', '') != 'htmlhelp': |
animalize | 6261ae9 | 2018-10-08 16:20:54 -0500 | [diff] [blame] | 29 | return |
| 30 | |
| 31 | # escape the `body` part to 7-bit ASCII |
| 32 | body = context.get('body') |
| 33 | if body is not None: |
| 34 | context['body'] = _process(body) |
| 35 | |
Steve Dower | afe17a7 | 2018-12-19 18:20:06 -0800 | [diff] [blame] | 36 | def fixup_keywords(app, exception): |
| 37 | # only works for .chm output |
| 38 | if getattr(app.builder, 'name', '') != 'htmlhelp' or exception: |
| 39 | return |
| 40 | |
| 41 | getLogger(__name__).info('fixing HTML escapes in keywords file...') |
| 42 | outdir = app.builder.outdir |
| 43 | outname = app.builder.config.htmlhelp_basename |
| 44 | with app.builder.open_file(outdir, outname + '.hhk', 'r') as f: |
| 45 | index = f.read() |
| 46 | with app.builder.open_file(outdir, outname + '.hhk', 'w') as f: |
| 47 | f.write(index.replace(''', ''')) |
| 48 | |
animalize | 6261ae9 | 2018-10-08 16:20:54 -0500 | [diff] [blame] | 49 | def setup(app): |
| 50 | # `html-page-context` event emitted when the HTML builder has |
| 51 | # created a context dictionary to render a template with. |
| 52 | app.connect('html-page-context', escape_for_chm) |
Steve Dower | afe17a7 | 2018-12-19 18:20:06 -0800 | [diff] [blame] | 53 | # `build-finished` event emitted when all the files have been |
| 54 | # output. |
| 55 | app.connect('build-finished', fixup_keywords) |
animalize | 6261ae9 | 2018-10-08 16:20:54 -0500 | [diff] [blame] | 56 | |
| 57 | return {'version': '1.0', 'parallel_read_safe': True} |