def build_navigation_doc(self, outdir=None, outname='nav.xhtml'): # type: (str, str) -> None """Write the metainfo file nav.xhtml.""" if outdir: warnings.warn('The arguments of Epub3Builder.build_navigation_doc() ' 'is deprecated.', RemovedInSphinx40Warning, stacklevel=2) else: outdir = self.outdir logger.info(__('writing %s file...'), outname) if self.config.epub_tocscope == 'default': doctree = self.env.get_and_resolve_doctree( self.config.master_doc, self, prune_toctrees=False, includehidden=False) refnodes = self.get_refnodes(doctree, []) self.toc_add_files(refnodes) else: # 'includehidden' refnodes = self.refnodes navlist = self.build_navlist(refnodes) copy_asset_file(path.join(self.template_dir, 'nav.xhtml_t'), path.join(outdir, outname), self.navigation_doc_metadata(navlist)) # Add nav.xhtml to epub file if outname not in self.files: self.files.append(outname)
def build_toc(self, outdir=None, outname='toc.ncx'): # type: (str, str) -> None """Write the metainfo file toc.ncx.""" if outdir: warnings.warn('The arguments of EpubBuilder.build_toc() is deprecated.', RemovedInSphinx40Warning, stacklevel=2) else: outdir = self.outdir logger.info(__('writing %s file...'), outname) if self.config.epub_tocscope == 'default': doctree = self.env.get_and_resolve_doctree(self.config.master_doc, self, prune_toctrees=False, includehidden=False) refnodes = self.get_refnodes(doctree, []) self.toc_add_files(refnodes) else: # 'includehidden' refnodes = self.refnodes self.check_refnodes(refnodes) navpoints = self.build_navpoints(refnodes) level = max(item['level'] for item in self.refnodes) level = min(level, self.config.epub_tocdepth) copy_asset_file(path.join(self.template_dir, 'toc.ncx_t'), path.join(outdir, outname), self.toc_metadata(level, navpoints))
def copy_static_entry(source, targetdir, builder, context={}, exclude_matchers=(), level=0): """[DEPRECATED] Copy a HTML builder static_path entry from source to targetdir. Handles all possible cases of files, directories and subdirectories. """ if exclude_matchers: relpath = relative_path(path.join(builder.srcdir, 'dummy'), source) for matcher in exclude_matchers: if matcher(relpath): return if path.isfile(source): copy_asset_file(source, targetdir, context, builder.templates) elif path.isdir(source): if not path.isdir(targetdir): os.mkdir(targetdir) for entry in os.listdir(source): if entry.startswith('.'): continue newtarget = targetdir if path.isdir(path.join(source, entry)): newtarget = path.join(targetdir, entry) copy_static_entry(path.join(source, entry), newtarget, builder, context, level=level+1, exclude_matchers=exclude_matchers)
def build_container(self, outdir, outname): # type: (unicode, unicode) -> None """Write the metainfo file META-INF/container.xml.""" logger.info('writing %s file...', outname) filename = path.join(outdir, outname) ensuredir(path.dirname(filename)) copy_asset_file(path.join(self.template_dir, 'container.xml'), filename)
def copy_static_entry(source, targetdir, builder, context={}, exclude_matchers=(), level=0): # type: (unicode, unicode, Any, Dict, Tuple[Callable, ...], int) -> None """[DEPRECATED] Copy a HTML builder static_path entry from source to targetdir. Handles all possible cases of files, directories and subdirectories. """ warnings.warn('sphinx.util.copy_static_entry is deprecated for removal', RemovedInSphinx30Warning, stacklevel=2) if exclude_matchers: relpath = relative_path(path.join(builder.srcdir, 'dummy'), source) for matcher in exclude_matchers: if matcher(relpath): return if path.isfile(source): copy_asset_file(source, targetdir, context, builder.templates) elif path.isdir(source): if not path.isdir(targetdir): os.mkdir(targetdir) for entry in os.listdir(source): if entry.startswith('.'): continue newtarget = targetdir if path.isdir(path.join(source, entry)): newtarget = path.join(targetdir, entry) copy_static_entry(path.join(source, entry), newtarget, builder, context, level=level + 1, exclude_matchers=exclude_matchers)
def build_access_page(self, language_dir: str) -> None: """Build the access page.""" context = { 'toc': self.config.master_doc + self.out_suffix, 'title': self.config.applehelp_title, } copy_asset_file(path.join(template_dir, '_access.html_t'), language_dir, context)
def copy_support_files(self): # type: () -> None try: with progress_message(__('copying Texinfo support files')): logger.info('Makefile ', nonl=True) copy_asset_file(os.path.join(template_dir, 'Makefile'), self.outdir) except OSError as err: logger.warning(__("error writing file Makefile: %s"), err)
def copy_applehelp_icon(self, resources_dir: str) -> None: """Copy the icon, if one is supplied.""" if self.config.applehelp_icon: try: with progress_message(__('copying icon... ')): applehelp_icon = path.join(self.srcdir, self.config.applehelp_icon) copy_asset_file(applehelp_icon, resources_dir) except Exception as err: logger.warning(__('cannot copy icon file %r: %s'), applehelp_icon, err)
def build_mimetype(self, outdir=None, outname='mimetype'): # type: (str, str) -> None """Write the metainfo file mimetype.""" if outdir: warnings.warn('The arguments of EpubBuilder.build_mimetype() is deprecated.', RemovedInSphinx40Warning, stacklevel=2) else: outdir = self.outdir logger.info(__('writing %s file...'), outname) copy_asset_file(path.join(self.template_dir, 'mimetype'), path.join(outdir, outname))
def build_container(self, outdir=None, outname='META-INF/container.xml'): # type: (str, str) -> None """Write the metainfo file META-INF/container.xml.""" if outdir: warnings.warn('The arguments of EpubBuilder.build_container() is deprecated.', RemovedInSphinx40Warning, stacklevel=2) else: outdir = self.outdir logger.info(__('writing %s file...'), outname) filename = path.join(outdir, outname) ensuredir(path.dirname(filename)) copy_asset_file(path.join(self.template_dir, 'container.xml'), filename)
def finish(self): # type: () -> None self.copy_image_files() logger.info(bold(__('copying Texinfo support files... ')), nonl=True) # copy Makefile fn = path.join(self.outdir, 'Makefile') logger.info(fn, nonl=1) try: copy_asset_file(os.path.join(template_dir, 'Makefile'), fn) except (IOError, OSError) as err: logger.warning(__("error writing file %s: %s"), fn, err) logger.info(__(' done'))
def copy_stopword_list(self) -> None: """Copy a stopword list (.stp) to outdir. The stopword list contains a list of words the full text search facility shouldn't index. Note that this list must be pretty small. Different versions of the MS docs claim the file has a maximum size of 256 or 512 bytes (including \r\n at the end of each line). Note that "and", "or", "not" and "near" are operators in the search language, so no point indexing them even if we wanted to. """ template = path.join(template_dir, 'project.stp') filename = path.join(self.outdir, self.config.htmlhelp_basename + '.stp') copy_asset_file(template, filename)
def finish(self): # copy image files if self.images: self.info(bold('copying images...'), nonl=1) for src, dest in iteritems(self.images): self.info(' '+src, nonl=1) copy_asset_file(path.join(self.srcdir, src), path.join(self.outdir, dest)) self.info() # copy TeX support files from texinputs context = {'latex_engine': self.config.latex_engine} self.info(bold('copying TeX support files...')) staticdirname = path.join(package_dir, 'texinputs') for filename in os.listdir(staticdirname): if not filename.startswith('.'): copy_asset_file(path.join(staticdirname, filename), self.outdir, context=context) # copy additional files if self.config.latex_additional_files: self.info(bold('copying additional files...'), nonl=1) for filename in self.config.latex_additional_files: self.info(' '+filename, nonl=1) copy_asset_file(path.join(self.confdir, filename), self.outdir) self.info() # the logo is handled differently if self.config.latex_logo: if not path.isfile(path.join(self.confdir, self.config.latex_logo)): raise SphinxError('logo file %r does not exist' % self.config.latex_logo) else: copy_asset_file(path.join(self.confdir, self.config.latex_logo), self.outdir) self.info('done')
def copy_image_files(self): # type: () -> None if self.images: stringify_func = ImageAdapter(self.app.env).get_original_image_uri for src in status_iterator(self.images, __('copying images... '), "brown", len(self.images), self.app.verbosity, stringify_func=stringify_func): dest = self.images[src] try: copy_asset_file(path.join(self.srcdir, src), path.join(self.outdir, dest)) except Exception as err: logger.warning(__('cannot copy image file %r: %s'), path.join(self.srcdir, src), err)
def finish(self): # type: () -> None self.copy_image_files() # copy TeX support files from texinputs context = {'latex_engine': self.config.latex_engine} logger.info(bold('copying TeX support files...')) staticdirname = path.join(package_dir, 'texinputs') for filename in os.listdir(staticdirname): if not filename.startswith('.'): copy_asset_file(path.join(staticdirname, filename), self.outdir, context=context) # use pre-1.6.x Makefile for make latexpdf on Windows if os.name == 'nt': staticdirname = path.join(package_dir, 'texinputs_win') copy_asset_file(path.join(staticdirname, 'Makefile_t'), self.outdir, context=context) # copy additional files if self.config.latex_additional_files: logger.info(bold('copying additional files...'), nonl=1) for filename in self.config.latex_additional_files: logger.info(' ' + filename, nonl=1) copy_asset_file(path.join(self.confdir, filename), self.outdir) logger.info('') # the logo is handled differently if self.config.latex_logo: if not path.isfile(path.join(self.confdir, self.config.latex_logo)): raise SphinxError('logo file %r does not exist' % self.config.latex_logo) else: copy_asset_file(path.join(self.confdir, self.config.latex_logo), self.outdir) logger.info('done')
def write_message_catalog(self): # type: () -> None formats = self.config.numfig_format context = { 'addtocaptions': r'\@iden', 'figurename': formats.get('figure', '').split('%s', 1), 'tablename': formats.get('table', '').split('%s', 1), 'literalblockname': formats.get('code-block', '').split('%s', 1) } if self.context['babel'] or self.context['polyglossia']: context['addtocaptions'] = r'\addto\captions%s' % self.babel.get_language() filename = path.join(package_dir, 'templates', 'latex', 'sphinxmessages.sty_t') copy_asset_file(filename, self.outdir, context=context, renderer=LaTeXRenderer())
def build_toc(self, outdir, outname): # type: (unicode, unicode) -> None """Write the metainfo file toc.ncx.""" logger.info('writing %s file...', outname) if self.config.epub_tocscope == 'default': doctree = self.env.get_and_resolve_doctree(self.config.master_doc, self, prune_toctrees=False, includehidden=False) refnodes = self.get_refnodes(doctree, []) self.toc_add_files(refnodes) else: # 'includehidden' refnodes = self.refnodes navpoints = self.build_navpoints(refnodes) level = max(item['level'] for item in self.refnodes) level = min(level, self.config.epub_tocdepth) copy_asset_file(path.join(self.template_dir, 'toc.ncx_t'), path.join(outdir, outname), self.toc_metadata(level, navpoints))
def finish(self): # type: () -> None self.copy_image_files() self.write_message_catalog() # copy TeX support files from texinputs # configure usage of xindy (impacts Makefile and latexmkrc) # FIXME: convert this rather to a confval with suitable default # according to language ? but would require extra documentation if self.config.language: xindy_lang_option = \ XINDY_LANG_OPTIONS.get(self.config.language[:2], '-L general -C utf8 ') xindy_cyrillic = self.config.language[:2] in XINDY_CYRILLIC_SCRIPTS else: xindy_lang_option = '-L english -C utf8 ' xindy_cyrillic = False context = { 'latex_engine': self.config.latex_engine, 'xindy_use': self.config.latex_use_xindy, 'xindy_lang_option': xindy_lang_option, 'xindy_cyrillic': xindy_cyrillic, } logger.info(bold(__('copying TeX support files...'))) staticdirname = path.join(package_dir, 'texinputs') for filename in os.listdir(staticdirname): if not filename.startswith('.'): copy_asset_file(path.join(staticdirname, filename), self.outdir, context=context) # use pre-1.6.x Makefile for make latexpdf on Windows if os.name == 'nt': staticdirname = path.join(package_dir, 'texinputs_win') copy_asset_file(path.join(staticdirname, 'Makefile_t'), self.outdir, context=context) # copy additional files if self.config.latex_additional_files: logger.info(bold(__('copying additional files...')), nonl=1) for filename in self.config.latex_additional_files: logger.info(' ' + filename, nonl=1) copy_asset_file(path.join(self.confdir, filename), self.outdir) logger.info('') # the logo is handled differently if self.config.latex_logo: if not path.isfile(path.join(self.confdir, self.config.latex_logo)): raise SphinxError(__('logo file %r does not exist') % self.config.latex_logo) else: copy_asset_file(path.join(self.confdir, self.config.latex_logo), self.outdir) logger.info(__('done'))
def build_navigation_doc(self, outdir, outname): # type: (unicode, unicode) -> None """Write the metainfo file nav.xhtml.""" logger.info(__('writing %s file...'), outname) if self.config.epub_tocscope == 'default': doctree = self.env.get_and_resolve_doctree( self.config.master_doc, self, prune_toctrees=False, includehidden=False) refnodes = self.get_refnodes(doctree, []) self.toc_add_files(refnodes) else: # 'includehidden' refnodes = self.refnodes navlist = self.build_navlist(refnodes) copy_asset_file(path.join(self.template_dir, 'nav.xhtml_t'), path.join(outdir, outname), self.navigation_doc_metadata(navlist)) # Add nav.xhtml to epub file if outname not in self.files: self.files.append(outname)
def test_copy_asset_file(tempdir): renderer = DummyTemplateLoader() # copy normal file src = (tempdir / 'asset.txt') src.write_text('# test data') dest = (tempdir / 'output.txt') copy_asset_file(src, dest) assert dest.exists() assert src.text() == dest.text() # copy template file src = (tempdir / 'asset.txt_t') src.write_text('# {{var1}} data') dest = (tempdir / 'output.txt_t') copy_asset_file(src, dest, {'var1': 'template'}, renderer) assert not dest.exists() assert (tempdir / 'output.txt').exists() assert (tempdir / 'output.txt').text() == '# template data' # copy template file to subdir src = (tempdir / 'asset.txt_t') src.write_text('# {{var1}} data') subdir1 = (tempdir / 'subdir') subdir1.makedirs() copy_asset_file(src, subdir1, {'var1': 'template'}, renderer) assert (subdir1 / 'asset.txt').exists() assert (subdir1 / 'asset.txt').text() == '# template data' # copy template file without context src = (tempdir / 'asset.txt_t') subdir2 = (tempdir / 'subdir2') subdir2.makedirs() copy_asset_file(src, subdir2) assert not (subdir2 / 'asset.txt').exists() assert (subdir2 / 'asset.txt_t').exists() assert (subdir2 / 'asset.txt_t').text() == '# {{var1}} data'
def finish(self): # type: () -> None self.copy_image_files() # copy TeX support files from texinputs context = {'latex_engine': self.config.latex_engine} logger.info(bold('copying TeX support files...')) staticdirname = path.join(package_dir, 'texinputs') for filename in os.listdir(staticdirname): if not filename.startswith('.'): copy_asset_file(path.join(staticdirname, filename), self.outdir, context=context) # use pre-1.6.x Makefile for make latexpdf on Windows if os.name == 'nt': staticdirname = path.join(package_dir, 'texinputs_win') copy_asset_file(path.join(staticdirname, 'Makefile_t'), self.outdir, context=context) # copy additional files if self.config.latex_additional_files: logger.info(bold('copying additional files...'), nonl=1) for filename in self.config.latex_additional_files: logger.info(' ' + filename, nonl=1) copy_asset_file(path.join(self.confdir, filename), self.outdir) logger.info('') # the logo is handled differently if self.config.latex_logo: if not path.isfile(path.join(self.confdir, self.config.latex_logo)): raise SphinxError('logo file %r does not exist' % self.config.latex_logo) else: copy_asset_file( path.join(self.confdir, self.config.latex_logo), self.outdir) logger.info('done')
def finish(self): # copy image files if self.images: self.info(bold('copying images...'), nonl=1) for src, dest in iteritems(self.images): self.info(' ' + src, nonl=1) copy_asset_file(path.join(self.srcdir, src), path.join(self.outdir, dest)) self.info() # copy TeX support files from texinputs context = {'latex_engine': self.config.latex_engine} self.info(bold('copying TeX support files...')) staticdirname = path.join(package_dir, 'texinputs') for filename in os.listdir(staticdirname): if not filename.startswith('.'): copy_asset_file(path.join(staticdirname, filename), self.outdir, context=context) # copy additional files if self.config.latex_additional_files: self.info(bold('copying additional files...'), nonl=1) for filename in self.config.latex_additional_files: self.info(' ' + filename, nonl=1) copy_asset_file(path.join(self.confdir, filename), self.outdir) self.info() # the logo is handled differently if self.config.latex_logo: if not path.isfile(path.join(self.confdir, self.config.latex_logo)): raise SphinxError('logo file %r does not exist' % self.config.latex_logo) else: copy_asset_file( path.join(self.confdir, self.config.latex_logo), self.outdir) self.info('done')
def copy_support_files(self): # type: () -> None """copy TeX support files from texinputs.""" # configure usage of xindy (impacts Makefile and latexmkrc) # FIXME: convert this rather to a confval with suitable default # according to language ? but would require extra documentation if self.config.language: xindy_lang_option = \ XINDY_LANG_OPTIONS.get(self.config.language[:2], '-L general -C utf8 ') xindy_cyrillic = self.config.language[:2] in XINDY_CYRILLIC_SCRIPTS else: xindy_lang_option = '-L english -C utf8 ' xindy_cyrillic = False context = { 'latex_engine': self.config.latex_engine, 'xindy_use': self.config.latex_use_xindy, 'xindy_lang_option': xindy_lang_option, 'xindy_cyrillic': xindy_cyrillic, } logger.info(bold(__('copying TeX support files...'))) staticdirname = path.join(package_dir, 'texinputs') for filename in os.listdir(staticdirname): if not filename.startswith('.'): copy_asset_file(path.join(staticdirname, filename), self.outdir, context=context) # use pre-1.6.x Makefile for make latexpdf on Windows if os.name == 'nt': staticdirname = path.join(package_dir, 'texinputs_win') copy_asset_file(path.join(staticdirname, 'Makefile_t'), self.outdir, context=context) # the logo is handled differently if self.config.latex_logo: if not path.isfile(path.join(self.confdir, self.config.latex_logo)): raise SphinxError( __('logo file %r does not exist') % self.config.latex_logo) else: copy_asset_file( path.join(self.confdir, self.config.latex_logo), self.outdir)
def copy_latex_additional_files(self): # type: () -> None for filename in self.config.latex_additional_files: logger.info(' ' + filename, nonl=True) copy_asset_file(path.join(self.confdir, filename), self.outdir)
def build_mimetype(self, outdir, outname): # type: (unicode, unicode) -> None """Write the metainfo file mimetype.""" logger.info('writing %s file...', outname) copy_asset_file(path.join(self.template_dir, 'mimetype'), path.join(outdir, outname))
def write_message_catalog(self): # type: () -> None filename = path.join(package_dir, 'templates', 'latex', 'sphinxmessages.sty_t') copy_asset_file(filename, self.outdir, context={}, renderer=LaTeXRenderer())
def write(self, *ignored): version = self.config.version libchanges = {} apichanges = [] otherchanges = {} if version not in self.env.versionchanges: self.info(bold('no changes in version %s.' % version)) return self.info(bold('writing summary file...')) for type, docname, lineno, module, descname, content in \ self.env.versionchanges[version]: if isinstance(descname, tuple): descname = descname[0] ttext = self.typemap[type] context = content.replace('\n', ' ') if descname and docname.startswith('c-api'): if not descname: continue if context: entry = '<b>%s</b>: <i>%s:</i> %s' % (descname, ttext, context) else: entry = '<b>%s</b>: <i>%s</i>.' % (descname, ttext) apichanges.append((entry, docname, lineno)) elif descname or module: if not module: module = _('Builtins') if not descname: descname = _('Module level') if context: entry = '<b>%s</b>: <i>%s:</i> %s' % (descname, ttext, context) else: entry = '<b>%s</b>: <i>%s</i>.' % (descname, ttext) libchanges.setdefault(module, []).append( (entry, docname, lineno)) else: if not context: continue entry = '<i>%s:</i> %s' % (ttext.capitalize(), context) title = self.env.titles[docname].astext() otherchanges.setdefault((docname, title), []).append( (entry, docname, lineno)) ctx = { 'project': self.config.project, 'version': version, 'docstitle': self.config.html_title, 'shorttitle': self.config.html_short_title, 'libchanges': sorted(iteritems(libchanges)), 'apichanges': sorted(apichanges), 'otherchanges': sorted(iteritems(otherchanges)), 'show_copyright': self.config.html_show_copyright, 'show_sphinx': self.config.html_show_sphinx, } with codecs.open(path.join(self.outdir, 'index.html'), 'w', 'utf8') as f: f.write(self.templates.render('changes/frameset.html', ctx)) with codecs.open(path.join(self.outdir, 'changes.html'), 'w', 'utf8') as f: f.write(self.templates.render('changes/versionchanges.html', ctx)) hltext = [ '.. versionadded:: %s' % version, '.. versionchanged:: %s' % version, '.. deprecated:: %s' % version ] def hl(no, line): line = '<a name="L%s"> </a>' % no + htmlescape(line) for x in hltext: if x in line: line = '<span class="hl">%s</span>' % line break return line self.info(bold('copying source files...')) for docname in self.env.all_docs: with codecs.open(self.env.doc2path(docname), 'r', self.env.config.source_encoding) as f: try: lines = f.readlines() except UnicodeDecodeError: self.warn('could not read %r for changelog creation' % docname) continue targetfn = path.join(self.outdir, 'rst', os_path(docname)) + '.html' ensuredir(path.dirname(targetfn)) with codecs.open(targetfn, 'w', 'utf-8') as f: text = ''.join( hl(i + 1, line) for (i, line) in enumerate(lines)) ctx = { 'filename': self.env.doc2path(docname, None), 'text': text } f.write(self.templates.render('changes/rstsource.html', ctx)) themectx = dict( ('theme_' + key, val) for (key, val) in iteritems(self.theme.get_options({}))) copy_asset_file(path.join(package_dir, 'themes', 'default', 'static', 'default.css_t'), self.outdir, context=themectx, renderer=self.templates) copy_asset_file( path.join(package_dir, 'themes', 'basic', 'static', 'basic.css'), self.outdir)
def build_mimetype(self) -> None: """Write the metainfo file mimetype.""" logger.info(__('writing mimetype file...')) copy_asset_file(path.join(self.template_dir, 'mimetype'), self.outdir)
def build_content(self, outdir: str = None, outname: str = 'content.opf') -> None: """Write the metainfo file content.opf It contains bibliographic data, a file list and the spine (the reading order). """ if outdir: warnings.warn( 'The arguments of EpubBuilder.build_content() is deprecated.', RemovedInSphinx40Warning, stacklevel=2) else: outdir = self.outdir logger.info(__('writing %s file...'), outname) metadata = self.content_metadata() # files if not outdir.endswith(os.sep): outdir += os.sep olen = len(outdir) self.files = [] # type: List[str] self.ignored_files = ['.buildinfo', 'mimetype', 'content.opf', 'toc.ncx', 'META-INF/container.xml', 'Thumbs.db', 'ehthumbs.db', '.DS_Store', 'nav.xhtml', self.config.epub_basename + '.epub'] + \ self.config.epub_exclude_files if not self.use_index: self.ignored_files.append('genindex' + self.out_suffix) for root, dirs, files in os.walk(outdir): dirs.sort() for fn in sorted(files): filename = path.join(root, fn)[olen:] if filename in self.ignored_files: continue ext = path.splitext(filename)[-1] if ext not in self.media_types: # we always have JS and potentially OpenSearch files, don't # always warn about them if ext not in ('.js', '.xml'): logger.warning(__('unknown mimetype for %s, ignoring'), filename, type='epub', subtype='unknown_project_files') continue filename = filename.replace(os.sep, '/') item = ManifestItem(html.escape(filename), html.escape(self.make_id(filename)), html.escape(self.media_types[ext])) metadata['manifest_items'].append(item) self.files.append(filename) # spine spinefiles = set() for refnode in self.refnodes: if '#' in refnode['refuri']: continue if refnode['refuri'] in self.ignored_files: continue spine = Spine(html.escape(self.make_id(refnode['refuri'])), True) metadata['spines'].append(spine) spinefiles.add(refnode['refuri']) for info in self.domain_indices: spine = Spine(html.escape(self.make_id(info[0] + self.out_suffix)), True) metadata['spines'].append(spine) spinefiles.add(info[0] + self.out_suffix) if self.use_index: spine = Spine( html.escape(self.make_id('genindex' + self.out_suffix)), True) metadata['spines'].append(spine) spinefiles.add('genindex' + self.out_suffix) # add auto generated files for name in self.files: if name not in spinefiles and name.endswith(self.out_suffix): spine = Spine(html.escape(self.make_id(name)), False) metadata['spines'].append(spine) # add the optional cover html_tmpl = None if self.config.epub_cover: image, html_tmpl = self.config.epub_cover image = image.replace(os.sep, '/') metadata['cover'] = html.escape(self.make_id(image)) if html_tmpl: spine = Spine(html.escape(self.make_id(self.coverpage_name)), True) metadata['spines'].insert(0, spine) if self.coverpage_name not in self.files: ext = path.splitext(self.coverpage_name)[-1] self.files.append(self.coverpage_name) item = ManifestItem( html.escape(self.coverpage_name), html.escape(self.make_id(self.coverpage_name)), html.escape(self.media_types[ext])) metadata['manifest_items'].append(item) ctx = { 'image': html.escape(image), 'title': self.config.project } self.handle_page( path.splitext(self.coverpage_name)[0], ctx, html_tmpl) spinefiles.add(self.coverpage_name) auto_add_cover = True auto_add_toc = True if self.config.epub_guide: for type, uri, title in self.config.epub_guide: file = uri.split('#')[0] if file not in self.files: self.files.append(file) if type == 'cover': auto_add_cover = False if type == 'toc': auto_add_toc = False metadata['guides'].append( Guide(html.escape(type), html.escape(title), html.escape(uri))) if auto_add_cover and html_tmpl: metadata['guides'].append( Guide('cover', self.guide_titles['cover'], html.escape(self.coverpage_name))) if auto_add_toc and self.refnodes: metadata['guides'].append( Guide('toc', self.guide_titles['toc'], html.escape(self.refnodes[0]['refuri']))) # write the project file copy_asset_file(path.join(self.template_dir, 'content.opf_t'), path.join(outdir, outname), metadata)
def build_mimetype(self, outdir, outname): # type: (unicode, unicode) -> None """Write the metainfo file mimetype.""" logger.info(__('writing %s file...'), outname) copy_asset_file(path.join(self.template_dir, 'mimetype'), path.join(outdir, outname))
def write(self, *ignored): # type: (Any) -> None version = self.config.version libchanges = {} # type: Dict[unicode, List[Tuple[unicode, unicode, int]]] apichanges = [] # type: List[Tuple[unicode, unicode, int]] otherchanges = {} # type: Dict[Tuple[unicode, unicode], List[Tuple[unicode, unicode, int]]] # NOQA if version not in self.env.versionchanges: logger.info(bold('no changes in version %s.' % version)) return logger.info(bold('writing summary file...')) for type, docname, lineno, module, descname, content in \ self.env.versionchanges[version]: if isinstance(descname, tuple): descname = descname[0] ttext = self.typemap[type] context = content.replace('\n', ' ') if descname and docname.startswith('c-api'): if not descname: continue if context: entry = '<b>%s</b>: <i>%s:</i> %s' % (descname, ttext, context) else: entry = '<b>%s</b>: <i>%s</i>.' % (descname, ttext) apichanges.append((entry, docname, lineno)) elif descname or module: if not module: module = _('Builtins') if not descname: descname = _('Module level') if context: entry = '<b>%s</b>: <i>%s:</i> %s' % (descname, ttext, context) else: entry = '<b>%s</b>: <i>%s</i>.' % (descname, ttext) libchanges.setdefault(module, []).append((entry, docname, lineno)) else: if not context: continue entry = '<i>%s:</i> %s' % (ttext.capitalize(), context) title = self.env.titles[docname].astext() otherchanges.setdefault((docname, title), []).append( (entry, docname, lineno)) ctx = { 'project': self.config.project, 'version': version, 'docstitle': self.config.html_title, 'shorttitle': self.config.html_short_title, 'libchanges': sorted(iteritems(libchanges)), 'apichanges': sorted(apichanges), 'otherchanges': sorted(iteritems(otherchanges)), 'show_copyright': self.config.html_show_copyright, 'show_sphinx': self.config.html_show_sphinx, } with codecs.open(path.join(self.outdir, 'index.html'), 'w', 'utf8') as f: # type: ignore # NOQA f.write(self.templates.render('changes/frameset.html', ctx)) with codecs.open(path.join(self.outdir, 'changes.html'), 'w', 'utf8') as f: # type: ignore # NOQA f.write(self.templates.render('changes/versionchanges.html', ctx)) hltext = ['.. versionadded:: %s' % version, '.. versionchanged:: %s' % version, '.. deprecated:: %s' % version] def hl(no, line): # type: (int, unicode) -> unicode line = '<a name="L%s"> </a>' % no + htmlescape(line) for x in hltext: if x in line: line = '<span class="hl">%s</span>' % line break return line logger.info(bold('copying source files...')) for docname in self.env.all_docs: with codecs.open(self.env.doc2path(docname), 'r', # type: ignore self.env.config.source_encoding) as f: try: lines = f.readlines() except UnicodeDecodeError: logger.warning('could not read %r for changelog creation', docname) continue targetfn = path.join(self.outdir, 'rst', os_path(docname)) + '.html' ensuredir(path.dirname(targetfn)) with codecs.open(targetfn, 'w', 'utf-8') as f: # type: ignore text = ''.join(hl(i + 1, line) for (i, line) in enumerate(lines)) ctx = { 'filename': self.env.doc2path(docname, None), 'text': text } f.write(self.templates.render('changes/rstsource.html', ctx)) themectx = dict(('theme_' + key, val) for (key, val) in iteritems(self.theme.get_options({}))) copy_asset_file(path.join(package_dir, 'themes', 'default', 'static', 'default.css_t'), self.outdir, context=themectx, renderer=self.templates) copy_asset_file(path.join(package_dir, 'themes', 'basic', 'static', 'basic.css'), self.outdir)
def build_container(self, outname: str = 'META-INF/container.xml') -> None: # NOQA """Write the metainfo file META-INF/container.xml.""" logger.info(__('writing META-INF/container.xml file...')) outdir = path.join(self.outdir, 'META-INF') ensuredir(outdir) copy_asset_file(path.join(self.template_dir, 'container.xml'), outdir)
def build_content(self, outdir, outname): # type: (unicode, unicode) -> None """Write the metainfo file content.opf It contains bibliographic data, a file list and the spine (the reading order). """ logger.info('writing %s file...', outname) metadata = self.content_metadata() # files if not outdir.endswith(os.sep): outdir += os.sep olen = len(outdir) self.files = [] # type: List[unicode] self.ignored_files = ['.buildinfo', 'mimetype', 'content.opf', 'toc.ncx', 'META-INF/container.xml', 'Thumbs.db', 'ehthumbs.db', '.DS_Store', 'nav.xhtml', self.config.epub_basename + '.epub'] + \ self.config.epub_exclude_files if not self.use_index: self.ignored_files.append('genindex' + self.out_suffix) for root, dirs, files in os.walk(outdir): dirs.sort() for fn in sorted(files): filename = path.join(root, fn)[olen:] if filename in self.ignored_files: continue ext = path.splitext(filename)[-1] if ext not in self.media_types: # we always have JS and potentially OpenSearch files, don't # always warn about them if ext not in ('.js', '.xml'): logger.warning('unknown mimetype for %s, ignoring', filename, type='epub', subtype='unknown_project_files') continue filename = filename.replace(os.sep, '/') item = ManifestItem(self.esc(filename), self.esc(self.make_id(filename)), self.esc(self.media_types[ext])) metadata['manifest_items'].append(item) self.files.append(filename) # spine spinefiles = set() for refnode in self.refnodes: if '#' in refnode['refuri']: continue if refnode['refuri'] in self.ignored_files: continue spine = Spine(self.esc(self.make_id(refnode['refuri'])), True) metadata['spines'].append(spine) spinefiles.add(refnode['refuri']) for info in self.domain_indices: spine = Spine(self.esc(self.make_id(info[0] + self.out_suffix)), True) metadata['spines'].append(spine) spinefiles.add(info[0] + self.out_suffix) if self.use_index: spine = Spine(self.esc(self.make_id('genindex' + self.out_suffix)), True) metadata['spines'].append(spine) spinefiles.add('genindex' + self.out_suffix) # add auto generated files for name in self.files: if name not in spinefiles and name.endswith(self.out_suffix): spine = Spine(self.esc(self.make_id(name)), False) metadata['spines'].append(spine) # add the optional cover html_tmpl = None if self.config.epub_cover: image, html_tmpl = self.config.epub_cover image = image.replace(os.sep, '/') metadata['cover'] = self.esc(self.make_id(image)) if html_tmpl: spine = Spine(self.esc(self.make_id(self.coverpage_name)), True) metadata['spines'].insert(0, spine) if self.coverpage_name not in self.files: ext = path.splitext(self.coverpage_name)[-1] self.files.append(self.coverpage_name) item = ManifestItem(self.esc(self.coverpage_name), self.esc(self.make_id(self.coverpage_name)), self.esc(self.media_types[ext])) metadata['manifest_items'].append(item) ctx = {'image': self.esc(image), 'title': self.config.project} self.handle_page( path.splitext(self.coverpage_name)[0], ctx, html_tmpl) spinefiles.add(self.coverpage_name) auto_add_cover = True auto_add_toc = True if self.config.epub_guide: for type, uri, title in self.config.epub_guide: file = uri.split('#')[0] if file not in self.files: self.files.append(file) if type == 'cover': auto_add_cover = False if type == 'toc': auto_add_toc = False metadata['guides'].append(Guide(self.esc(type), self.esc(title), self.esc(uri))) if auto_add_cover and html_tmpl: metadata['guides'].append(Guide('cover', self.guide_titles['cover'], self.esc(self.coverpage_name))) if auto_add_toc and self.refnodes: metadata['guides'].append(Guide('toc', self.guide_titles['toc'], self.esc(self.refnodes[0]['refuri']))) # write the project file copy_asset_file(path.join(self.template_dir, 'content.opf_t'), path.join(outdir, outname), metadata)
def copy_static_files(app): themePath = Path(__file__).parent.joinpath("theme") clsFile = themePath.joinpath("jupyterBook.cls") copy_asset_file(str(clsFile), app.outdir)
def write(self, *ignored): # type: (Any) -> None version = self.config.version domain = cast(ChangeSetDomain, self.env.get_domain('changeset')) libchanges = {} # type: Dict[str, List[Tuple[str, str, int]]] apichanges = [] # type: List[Tuple[str, str, int]] otherchanges = {} # type: Dict[Tuple[str, str], List[Tuple[str, str, int]]] changesets = domain.get_changesets_for(version) if not changesets: logger.info(bold(__('no changes in version %s.') % version)) return logger.info(bold(__('writing summary file...'))) for changeset in changesets: if isinstance(changeset.descname, tuple): descname = changeset.descname[0] else: descname = changeset.descname ttext = self.typemap[changeset.type] context = changeset.content.replace('\n', ' ') if descname and changeset.docname.startswith('c-api'): if context: entry = '<b>%s</b>: <i>%s:</i> %s' % (descname, ttext, context) else: entry = '<b>%s</b>: <i>%s</i>.' % (descname, ttext) apichanges.append((entry, changeset.docname, changeset.lineno)) elif descname or changeset.module: module = changeset.module or _('Builtins') if not descname: descname = _('Module level') if context: entry = '<b>%s</b>: <i>%s:</i> %s' % (descname, ttext, context) else: entry = '<b>%s</b>: <i>%s</i>.' % (descname, ttext) libchanges.setdefault(module, []).append((entry, changeset.docname, changeset.lineno)) else: if not context: continue entry = '<i>%s:</i> %s' % (ttext.capitalize(), context) title = self.env.titles[changeset.docname].astext() otherchanges.setdefault((changeset.docname, title), []).append( (entry, changeset.docname, changeset.lineno)) ctx = { 'project': self.config.project, 'version': version, 'docstitle': self.config.html_title, 'shorttitle': self.config.html_short_title, 'libchanges': sorted(libchanges.items()), 'apichanges': sorted(apichanges), 'otherchanges': sorted(otherchanges.items()), 'show_copyright': self.config.html_show_copyright, 'show_sphinx': self.config.html_show_sphinx, } with open(path.join(self.outdir, 'index.html'), 'w', encoding='utf8') as f: f.write(self.templates.render('changes/frameset.html', ctx)) with open(path.join(self.outdir, 'changes.html'), 'w', encoding='utf8') as f: f.write(self.templates.render('changes/versionchanges.html', ctx)) hltext = ['.. versionadded:: %s' % version, '.. versionchanged:: %s' % version, '.. deprecated:: %s' % version] def hl(no, line): # type: (int, str) -> str line = '<a name="L%s"> </a>' % no + html.escape(line) for x in hltext: if x in line: line = '<span class="hl">%s</span>' % line break return line logger.info(bold(__('copying source files...'))) for docname in self.env.all_docs: with open(self.env.doc2path(docname), encoding=self.env.config.source_encoding) as f: try: lines = f.readlines() except UnicodeDecodeError: logger.warning(__('could not read %r for changelog creation'), docname) continue targetfn = path.join(self.outdir, 'rst', os_path(docname)) + '.html' ensuredir(path.dirname(targetfn)) with open(targetfn, 'w', encoding='utf-8') as f: text = ''.join(hl(i + 1, line) for (i, line) in enumerate(lines)) ctx = { 'filename': self.env.doc2path(docname, None), 'text': text } f.write(self.templates.render('changes/rstsource.html', ctx)) themectx = {'theme_' + key: val for (key, val) in self.theme.get_options({}).items()} copy_asset_file(path.join(package_dir, 'themes', 'default', 'static', 'default.css_t'), self.outdir, context=themectx, renderer=self.templates) copy_asset_file(path.join(package_dir, 'themes', 'basic', 'static', 'basic.css'), self.outdir)
def on_build_finished(app, exc): # type: (Sphinx, Exception) -> None if exc is None: src = path.join(sphinx.package_dir, 'templates', 'graphviz', 'graphviz.css') dst = path.join(app.outdir, '_static') copy_asset_file(src, dst)