Пример #1
0
    def translate(self):
        visitor = PDFTranslator(self.document, self.builder)
        self.document.walkabout(visitor)
        lang = self.config.language or 'en'
        langmod = get_language_available(lang)[2]
        self.docutils_languages = {lang: langmod}

        # Generate Contents topic manually
        if self.use_toc:
            contents=nodes.topic(classes=['contents'])
            contents+=nodes.title('')
            contents[0]+=nodes.Text(langmod.labels['contents'])
            contents['ids']=['Contents']
            pending=nodes.topic()
            contents.append(pending)
            pending.details={}
            self.document.insert(0,nodes.raw(text='SetPageCounter 1 arabic', format='pdf'))
            self.document.insert(0,nodes.raw(text='OddPageBreak %s'%self.page_template, format='pdf'))
            self.document.insert(0,contents)
            self.document.insert(0,nodes.raw(text='SetPageCounter 1 lowerroman', format='pdf'))
            contTrans=PDFContents(self.document)
            contTrans.toc_depth = self.toc_depth
            contTrans.startnode=pending
            contTrans.apply()

        if self.use_coverpage:
            # Generate cover page

            # FIXME: duplicate from createpdf, refactor!
            # Add the Sphinx template paths
            def add_template_path(path):
                return os.path.join(self.srcdir, path)

            jinja_env = jinja2.Environment(
                loader=jinja2.FileSystemLoader([
                        self.srcdir, os.path.expanduser('~/.rst2pdf'),
                        os.path.join(self.PATH,'templates')] +
                        list(map(add_template_path, self.config.templates_path))),
                autoescape=jinja2.select_autoescape(['html', 'xml'])
            )

            try:
                template = jinja_env.get_template(self.config.pdf_cover_template)
            except jinja2.TemplateNotFound:
                log.error("Can't find cover template %s, using default"%self.config.pdf_cover_template)
                template = jinja_env.get_template('sphinxcover.tmpl')

            # This is what's used in the python docs because
            # Latex does a manual linebreak. This sucks.
            authors=self.document.settings.author.split('\\')

            # Honour the "today" config setting
            if self.config.today :
                date = self.config.today
            else:
                date=time.strftime(self.config.today_fmt or _('%B %d, %Y'))

            # Feed data to the template, get restructured text.
            cover_text = template.render(
                                title=self.document.settings.title or visitor.elements['title'],
                                subtitle='%s %s'%(_('version'),self.config.version),
                                authors=authors,
                                date=date
                                )

            cover_tree = docutils.core.publish_doctree(cover_text)
            self.document.insert(0, cover_tree)

        sio=BytesIO()

        if self.invariant:
            createpdf.patch_PDFDate()
            createpdf.patch_digester()

        createpdf.RstToPdf(sphinx=True,
                 stylesheets=self.stylesheets,
                 language=self.__language,
                 breaklevel=self.breaklevel,
                 breakside=self.breakside,
                 fit_mode=self.fitmode,
                 font_path=self.fontpath,
                 inline_footnotes=self.inline_footnotes,
                 highlightlang=self.highlightlang,
                 splittables=self.splittables,
                 style_path=self.style_path,
                 repeat_table_rows=self.repeat_table_rows,
                 basedir=self.srcdir,
                 def_dpi=self.default_dpi,
                 real_footnotes=self.real_footnotes,
                 numbered_links=self.use_numbered_links,
                 background_fit_mode=self.fit_background_mode,
                 baseurl=self.baseurl,
                 section_header_depth=self.section_header_depth
                ).createPdf(doctree=self.document,
                    output=sio,
                    compressed=self.compressed)
        self.output=sio.getvalue()
Пример #2
0
    def assemble_doctree(self, docname, title, author, appendices):

        # FIXME: use the new inline_all_trees from Sphinx.
        # check how the LaTeX builder does it.

        self.docnames = set([docname])
        self.spinx_logger.info(darkgreen(docname) + " ")
        def process_tree(docname, tree):
            tree = tree.deepcopy()
            for toctreenode in tree.traverse(addnodes.toctree):
                newnodes = []
                includefiles = map(str, toctreenode['includefiles'])
                for includefile in includefiles:
                    try:
                        self.spinx_logger.info(darkgreen(includefile) + " ")
                        subtree = process_tree(includefile,
                        self.env.get_doctree(includefile))
                        self.docnames.add(includefile)
                    except Exception:
                        self.warn('%s: toctree contains ref to nonexisting file %r'\
                                                     % (docname, includefile))
                    else:
                        sof = addnodes.start_of_file(docname=includefile)
                        sof.children = subtree.children
                        newnodes.append(sof)
                toctreenode.parent.replace(toctreenode, newnodes)
            return tree

        tree = self.env.get_doctree(docname)
        tree = process_tree(docname, tree)

        self.docutils_languages = {}
        if self.config.language:
            self.docutils_languages[self.config.language] = \
                get_language_available(self.config.language)[2]

        if self.opts.get('pdf_use_index',self.config.pdf_use_index):
            # Add index at the end of the document

            # This is a hack. create_index creates an index from
            # ALL the documents data, not just this one.
            # So, we preserve a copy, use just what we need, then
            # restore it.
            t=copy(self.env.indexentries)
            try:
                self.env.indexentries={docname:self.env.indexentries[docname+'-gen']}
            except KeyError:
                self.env.indexentries={}
                for dname in self.docnames:
                    self.env.indexentries[dname]=t.get(dname,[])
            genindex = IndexEntries(self.env).create_index(self)
            self.env.indexentries=t
            # EOH (End Of Hack)

            if genindex: # No point in creating empty indexes
                index_nodes=genindex_nodes(genindex)
                tree.append(nodes.raw(text='OddPageBreak twoColumn', format='pdf'))
                tree.append(index_nodes)

        # This is stolen from the HTML builder's prepare_writing function
        self.domain_indices = []
        # html_domain_indices can be False/True or a list of index names
        indices_config = self.config.pdf_domain_indices
        if indices_config and hasattr(self.env, 'domains'):
            for domain in self.env.domains.values():
                for indexcls in domain.indices:
                    indexname = '%s-%s' % (domain.name, indexcls.name)
                    if isinstance(indices_config, list):
                        if indexname not in indices_config:
                            continue
                    # deprecated config value
                    if indexname == 'py-modindex' and \
                           not self.config.pdf_use_modindex:
                        continue
                    content, collapse = indexcls(domain).generate()
                    if content:
                        self.domain_indices.append(
                            (indexname, indexcls, content, collapse))

        # self.domain_indices contains a list of indices to generate, like
        # this:
        # [('py-modindex',
        #    <class 'sphinx.domains.python.PythonModuleIndex'>,
        #   [(u'p', [[u'parrot', 0, 'test', u'module-parrot', 'Unix, Windows',
        #   '', 'Analyze and reanimate dead parrots.']])], True)]

        # Now this in the HTML builder is passed onto write_domain_indices.
        # We handle it right here

        for indexname, indexcls, content, collapse in self.domain_indices:
            indexcontext = dict(
                indextitle = indexcls.localname,
                content = content,
                collapse_index = collapse,
            )
            # In HTML this is handled with a Jinja template, domainindex.html
            # We have to generate docutils stuff right here in the same way.
            self.spinx_logger.info(' ' + indexname)
            print

            output=['DUMMY','=====','',
                    '.. _modindex:\n\n']
            t=indexcls.localname
            t+='\n'+'='*len(t)+'\n'
            output.append(t)

            for letter, entries in content:
                output.append('.. cssclass:: heading4\n\n%s\n\n'%letter)
                for (name, grouptype, page, anchor,
                    extra, qualifier, description) in entries:
                    if qualifier:
                        q = '[%s]'%qualifier
                    else:
                        q = ''

                    if extra:
                        e = '(%s)'%extra
                    else:
                        e = ''
                    output.append ('`%s <#%s>`_ %s %s'%(name, anchor, e, q))
                    output.append('    %s'%description)
                output.append('')

            dt = docutils.core.publish_doctree('\n'.join(output))[1:]
            dt.insert(0,nodes.raw(text='OddPageBreak twoColumn', format='pdf'))
            tree.extend(dt)


        if appendices:
            tree.append(nodes.raw(text='OddPageBreak %s'%self.page_template, format='pdf'))
            self.spinx_logger.info()
            self.spinx_logger.info('adding appendixes...')
            for docname in appendices:
                self.spinx_logger.info(darkgreen(docname) + " ")
                appendix = self.env.get_doctree(docname)
                appendix['docname'] = docname
                tree.append(appendix)
            self.spinx_logger.info('done')

        # Replace Sphinx's HighlightLanguageTransform with our own for Spinx version between 1.8.0 & less than 2.0.0 as
        # Sphinx's HighlightLanguageTransform breaks linenothreshold setting in the highlight directive (See issue #721)
        # This code can be removed when we drop support for Python 2
        if sphinx.__version__ > '1.7.9' and sphinx.__version__ < '2.0.0':
            for i in range(len(self.env.app.registry.post_transforms)):
                if self.env.app.registry.post_transforms[i].__name__ == 'HighlightLanguageTransform':
                    self.env.app.registry.post_transforms[i] = HighlightLanguageTransform
                    break

        self.spinx_logger.info("resolving references...")
        self.env.resolve_references(tree, docname, self)

        for pendingnode in tree.traverse(addnodes.pending_xref):
            # This needs work, need to keep track of all targets
            # so I don't replace and create hanging refs, which
            # crash
            if pendingnode.get('reftarget',None) == 'genindex'\
                and self.config.pdf_use_index:
                pendingnode.replace_self(nodes.reference(text=pendingnode.astext(),
                    refuri=pendingnode['reftarget']))
            # FIXME: probably need to handle dangling links to domain-specific indexes
            else:
                # FIXME: This is from the LaTeX builder and I still don't understand it
                # well, and doesn't seem to work

                # resolve :ref:s to distant tex files -- we can't add a cross-reference,
                # but append the document name
                docname = pendingnode['refdocname']
                sectname = pendingnode['refsectname']
                newnodes = [nodes.emphasis(sectname, sectname)]
                for subdir, title in self.titles:
                    if docname.startswith(subdir):
                        newnodes.append(nodes.Text(_(' (in '), _(' (in ')))
                        newnodes.append(nodes.emphasis(title, title))
                        newnodes.append(nodes.Text(')', ')'))
                        break
                else:
                    pass
                pendingnode.replace_self(newnodes)
            #else:
                #pass
        return tree
Пример #3
0
    def translate(self):
        visitor = PDFTranslator(self.document, self.builder)
        self.document.walkabout(visitor)
        lang = self.config.language or 'en'
        langmod = get_language_available(lang)[2]
        self.docutils_languages = {lang: langmod}

        # Generate Contents topic manually
        if self.use_toc:
            contents=nodes.topic(classes=['contents'])
            contents+=nodes.title('')
            contents[0]+=nodes.Text(langmod.labels['contents'])
            contents['ids']=['Contents']
            pending=nodes.topic()
            contents.append(pending)
            pending.details={}
            self.document.insert(0,nodes.raw(text='SetPageCounter 1 arabic', format='pdf'))
            self.document.insert(0,nodes.raw(text='OddPageBreak %s'%self.page_template, format='pdf'))
            self.document.insert(0,contents)
            self.document.insert(0,nodes.raw(text='SetPageCounter 1 lowerroman', format='pdf'))
            contTrans=PDFContents(self.document)
            contTrans.toc_depth = self.toc_depth
            contTrans.startnode=pending
            contTrans.apply()

        if self.use_coverpage:
            # Generate cover page

            # FIXME: duplicate from createpdf, refactor!

            # Find cover template, save it in cover_file
            def find_cover(name):
                cover_path=[self.srcdir, os.path.expanduser('~/.rst2pdf'),
                                            os.path.join(self.PATH,'templates')]

                # Add the Sphinx template paths
                def add_template_path(path):
                    return os.path.join(self.srcdir, path)

                cover_path.extend(map(add_template_path, self.config.templates_path))

                cover_file=None
                for d in cover_path:
                    if os.path.exists(os.path.join(d,name)):
                        cover_file=os.path.join(d,name)
                        break
                return cover_file

            cover_file=find_cover(self.config.pdf_cover_template)
            if cover_file is None:
                log.error("Can't find cover template %s, using default"%self.custom_cover)
                cover_file=find_cover('sphinxcover.tmpl')

            # This is what's used in the python docs because
            # Latex does a manual linebreak. This sucks.
            authors=self.document.settings.author.split('\\')

            # Feed data to the template, get restructured text.
            cover_text = createpdf.renderTemplate(tname=cover_file,
                                title=self.document.settings.title or visitor.elements['title'],
                                subtitle='%s %s'%(_('version'),self.config.version),
                                authors=authors,
                                date=ustrftime(self.config.today_fmt or _('%B %d, %Y'))
                                )

            cover_tree = docutils.core.publish_doctree(cover_text)
            self.document.insert(0, cover_tree)

        sio=StringIO()

        if self.invariant:
            createpdf.patch_PDFDate()
            createpdf.patch_digester()

        createpdf.RstToPdf(sphinx=True,
                 stylesheets=self.stylesheets,
                 language=self.__language,
                 breaklevel=self.breaklevel,
                 breakside=self.breakside,
                 fit_mode=self.fitmode,
                 font_path=self.fontpath,
                 inline_footnotes=self.inline_footnotes,
                 highlightlang=self.highlightlang,
                 splittables=self.splittables,
                 style_path=self.style_path,
                 basedir=self.srcdir,
                 def_dpi=self.default_dpi,
                 real_footnotes=self.real_footnotes,
                 numbered_links=self.use_numbered_links,
                 background_fit_mode=self.fit_background_mode,
                 baseurl=self.baseurl,
                 section_header_depth=self.section_header_depth
                ).createPdf(doctree=self.document,
                    output=sio,
                    compressed=self.compressed)
        self.output=sio.getvalue()
Пример #4
0
    def translate(self):
        visitor = PDFTranslator(self.document, self.builder)
        self.document.walkabout(visitor)
        lang = self.config.language or 'en'
        langmod = get_language_available(lang)[2]
        self.docutils_languages = {lang: langmod}

        # Generate Contents topic manually
        if self.use_toc:
            contents = nodes.topic(classes=['contents'])
            contents += nodes.title('')
            contents[0] += nodes.Text(langmod.labels['contents'])
            contents['ids'] = ['Contents']
            pending = nodes.topic()
            contents.append(pending)
            pending.details = {}
            self.document.insert(
                0, nodes.raw(text='SetPageCounter 1 arabic', format='pdf'))
            self.document.insert(
                0,
                nodes.raw(text='OddPageBreak %s' % self.page_template,
                          format='pdf'))
            self.document.insert(0, contents)
            self.document.insert(
                0, nodes.raw(text='SetPageCounter 1 lowerroman', format='pdf'))
            contTrans = PDFContents(self.document)
            contTrans.toc_depth = self.toc_depth
            contTrans.startnode = pending
            contTrans.apply()

        if self.use_coverpage:
            # Generate cover page

            # FIXME: duplicate from createpdf, refactor!

            # Find cover template, save it in cover_file
            def find_cover(name):
                cover_path = [
                    self.srcdir,
                    os.path.expanduser('~/.rst2pdf'),
                    os.path.join(self.PATH, 'templates')
                ]

                # Add the Sphinx template paths
                def add_template_path(path):
                    return os.path.join(self.srcdir, path)

                cover_path.extend(
                    map(add_template_path, self.config.templates_path))

                cover_file = None
                for d in cover_path:
                    if os.path.exists(os.path.join(d, name)):
                        cover_file = os.path.join(d, name)
                        break
                return cover_file

            cover_file = find_cover(self.config.pdf_cover_template)
            if cover_file is None:
                log.error("Can't find cover template %s, using default" %
                          self.custom_cover)
                cover_file = find_cover('sphinxcover.tmpl')

            # This is what's used in the python docs because
            # Latex does a manual linebreak. This sucks.
            authors = self.document.settings.author.split('\\')

            # Feed data to the template, get restructured text.
            cover_text = createpdf.renderTemplate(
                tname=cover_file,
                title=self.document.settings.title
                or visitor.elements['title'],
                subtitle='%s %s' % (_('version'), self.config.version),
                authors=authors,
                date=ustrftime(self.config.today_fmt or _('%B %d, %Y')))

            cover_tree = docutils.core.publish_doctree(cover_text)
            self.document.insert(0, cover_tree)

        sio = StringIO()

        if self.invariant:
            createpdf.patch_PDFDate()
            createpdf.patch_digester()

        createpdf.RstToPdf(sphinx=True,
                           stylesheets=self.stylesheets,
                           language=self.__language,
                           breaklevel=self.breaklevel,
                           breakside=self.breakside,
                           fit_mode=self.fitmode,
                           font_path=self.fontpath,
                           inline_footnotes=self.inline_footnotes,
                           highlightlang=self.highlightlang,
                           splittables=self.splittables,
                           style_path=self.style_path,
                           basedir=self.srcdir,
                           def_dpi=self.default_dpi,
                           real_footnotes=self.real_footnotes,
                           numbered_links=self.use_numbered_links,
                           background_fit_mode=self.fit_background_mode,
                           baseurl=self.baseurl,
                           section_header_depth=self.section_header_depth,
                           floating_images=self.floating_images).createPdf(
                               doctree=self.document,
                               output=sio,
                               compressed=self.compressed)
        self.output = sio.getvalue()
Пример #5
0
    def assemble_doctree(self, docname, title, author, appendices):

        # FIXME: use the new inline_all_trees from Sphinx.
        # check how the LaTeX builder does it.

        self.docnames = set([docname])
        self.info(darkgreen(docname) + " ", nonl=1)
        def process_tree(docname, tree):
            tree = tree.deepcopy()
            for toctreenode in tree.traverse(addnodes.toctree):
                newnodes = []
                includefiles = map(str, toctreenode['includefiles'])
                for includefile in includefiles:
                    try:
                        self.info(darkgreen(includefile) + " ", nonl=1)
                        subtree = process_tree(includefile,
                        self.env.get_doctree(includefile))
                        self.docnames.add(includefile)
                    except Exception:
                        self.warn('%s: toctree contains ref to nonexisting file %r'\
                                                     % (docname, includefile))
                    else:
                        sof = addnodes.start_of_file(docname=includefile)
                        sof.children = subtree.children
                        newnodes.append(sof)
                toctreenode.parent.replace(toctreenode, newnodes)
            return tree

        tree = self.env.get_doctree(docname)
        tree = process_tree(docname, tree)

        self.docutils_languages = {}
        if self.config.language:
            self.docutils_languages[self.config.language] = \
                get_language_available(self.config.language)[2]

        if self.opts.get('pdf_use_index',self.config.pdf_use_index):
            # Add index at the end of the document

            # This is a hack. create_index creates an index from
            # ALL the documents data, not just this one.
            # So, we preserve a copy, use just what we need, then
            # restore it.
            #from pudb import set_trace; set_trace()
            t=copy(self.env.indexentries)
            try:
                self.env.indexentries={docname:self.env.indexentries[docname+'-gen']}
            except KeyError:
                self.env.indexentries={}
                for dname in self.docnames:
                    self.env.indexentries[dname]=t.get(dname,[])
            genindex = self.env.create_index(self)
            self.env.indexentries=t
            # EOH (End Of Hack)

            if genindex: # No point in creating empty indexes
                index_nodes=genindex_nodes(genindex)
                tree.append(nodes.raw(text='OddPageBreak twoColumn', format='pdf'))
                tree.append(index_nodes)

        # This is stolen from the HTML builder's prepare_writing function
        self.domain_indices = []
        # html_domain_indices can be False/True or a list of index names
        indices_config = self.config.pdf_domain_indices
        if indices_config and hasattr(self.env, 'domains'):
            for domain in self.env.domains.itervalues():
                for indexcls in domain.indices:
                    indexname = '%s-%s' % (domain.name, indexcls.name)
                    if isinstance(indices_config, list):
                        if indexname not in indices_config:
                            continue
                    # deprecated config value
                    if indexname == 'py-modindex' and \
                           not self.config.pdf_use_modindex:
                        continue
                    content, collapse = indexcls(domain).generate()
                    if content:
                        self.domain_indices.append(
                            (indexname, indexcls, content, collapse))

        # self.domain_indices contains a list of indices to generate, like
        # this:
        # [('py-modindex',
        #    <class 'sphinx.domains.python.PythonModuleIndex'>,
        #   [(u'p', [[u'parrot', 0, 'test', u'module-parrot', 'Unix, Windows',
        #   '', 'Analyze and reanimate dead parrots.']])], True)]

        # Now this in the HTML builder is passed onto write_domain_indices.
        # We handle it right here

        for indexname, indexcls, content, collapse in self.domain_indices:
            indexcontext = dict(
                indextitle = indexcls.localname,
                content = content,
                collapse_index = collapse,
            )
            # In HTML this is handled with a Jinja template, domainindex.html
            # We have to generate docutils stuff right here in the same way.
            self.info(' ' + indexname, nonl=1)
            print

            output=['DUMMY','=====','',
                    '.. _modindex:\n\n']
            t=indexcls.localname
            t+='\n'+'='*len(t)+'\n'
            output.append(t)

            for letter, entries in content:
                output.append('.. cssclass:: heading4\n\n%s\n\n'%letter)
                for (name, grouptype, page, anchor,
                    extra, qualifier, description) in entries:
                    if qualifier:
                        q = '[%s]'%qualifier
                    else:
                        q = ''

                    if extra:
                        e = '(%s)'%extra
                    else:
                        e = ''
                    output.append ('`%s <#%s>`_ %s %s'%(name, anchor, e, q))
                    output.append('    %s'%description)
                output.append('')

            dt = docutils.core.publish_doctree('\n'.join(output))[1:]
            dt.insert(0,nodes.raw(text='OddPageBreak twoColumn', format='pdf'))
            tree.extend(dt)


        if appendices:
            tree.append(nodes.raw(text='OddPageBreak %s'%self.page_template, format='pdf'))
            self.info()
            self.info('adding appendixes...', nonl=1)
            for docname in appendices:
                self.info(darkgreen(docname) + " ", nonl=1)
                appendix = self.env.get_doctree(docname)
                appendix['docname'] = docname
                tree.append(appendix)
            self.info('done')

        self.info()
        self.info("resolving references...")
        #print tree
        #print '--------------'
        self.env.resolve_references(tree, docname, self)
        #print tree

        for pendingnode in tree.traverse(addnodes.pending_xref):
            # This needs work, need to keep track of all targets
            # so I don't replace and create hanging refs, which
            # crash
            if pendingnode.get('reftarget',None) == 'genindex'\
                and self.config.pdf_use_index:
                pendingnode.replace_self(nodes.reference(text=pendingnode.astext(),
                    refuri=pendingnode['reftarget']))
            # FIXME: probably need to handle dangling links to domain-specific indexes
            else:
                # FIXME: This is from the LaTeX builder and I still don't understand it
                # well, and doesn't seem to work

                # resolve :ref:s to distant tex files -- we can't add a cross-reference,
                # but append the document name
                docname = pendingnode['refdocname']
                sectname = pendingnode['refsectname']
                newnodes = [nodes.emphasis(sectname, sectname)]
                for subdir, title in self.titles:
                    if docname.startswith(subdir):
                        newnodes.append(nodes.Text(_(' (in '), _(' (in ')))
                        newnodes.append(nodes.emphasis(title, title))
                        newnodes.append(nodes.Text(')', ')'))
                        break
                else:
                    pass
                pendingnode.replace_self(newnodes)
            #else:
                #pass
        return tree