sphinx-docx 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,59 @@
1
+ """Sphinx extension that builds Word (.docx) documents."""
2
+ from importlib.metadata import PackageNotFoundError, version as _version
3
+
4
+ from sphinx.util.osutil import make_filename
5
+ from sphinx_docx.builder import DocxBuilder
6
+
7
+ try:
8
+ __version__ = _version('sphinx-docx')
9
+ except PackageNotFoundError: # running from a source tree, not installed
10
+ __version__ = '0.0.0.dev0'
11
+
12
+ __all__ = ['DocxBuilder', 'setup', '__version__']
13
+
14
+
15
+ def setup(app):
16
+ """Register the docx builder and its configuration values with Sphinx."""
17
+ app.add_builder(DocxBuilder)
18
+
19
+ def default_docx_documents(conf):
20
+ """Build the default ``docx_documents`` entry: one file from the master doc."""
21
+ start_doc = conf.master_doc
22
+ filename = '%s.docx' % make_filename(conf.project)
23
+ title = conf.project
24
+ # author configuration value is available from Sphinx 1.8
25
+ author = getattr(conf, 'author', 'sphinx_docx')
26
+ properties = {
27
+ 'title': title,
28
+ 'creator': author,
29
+ 'subject': '',
30
+ 'category': '',
31
+ 'description': 'This document generated by sphinx_docx',
32
+ 'keywords': ['python', 'Office Open XML', 'Word'],
33
+ }
34
+ toc_only = False
35
+ return [(start_doc, filename, properties, toc_only)]
36
+
37
+ app.add_config_value('docx_documents', default_docx_documents, 'env')
38
+ app.add_config_value('docx_style', '', 'env')
39
+ app.add_config_value('docx_pagebreak_before_section', 0, 'env')
40
+ app.add_config_value('docx_pagebreak_before_file', 0, 'env')
41
+ app.add_config_value('docx_pagebreak_before_table_of_contents', -1, 'env')
42
+ app.add_config_value('docx_pagebreak_after_table_of_contents', 0, 'env')
43
+ app.add_config_value('docx_coverpage', 1, 'env')
44
+ app.add_config_value('docx_update_fields', False, 'env')
45
+ app.add_config_value('docx_bake_property_fields', True, 'env')
46
+ app.add_config_value('docx_table_options', {
47
+ 'landscape_columns': 0,
48
+ 'in_single_page': False,
49
+ 'row_splittable': True,
50
+ 'header_in_all_page': False,
51
+ }, 'env')
52
+ app.add_config_value('docx_style_names', {}, 'env')
53
+ app.add_config_value('docx_nested_character_style', True, 'env')
54
+
55
+ return {
56
+ 'version': __version__,
57
+ 'parallel_read_safe': True,
58
+ 'parallel_write_safe': True,
59
+ }
sphinx_docx/builder.py ADDED
@@ -0,0 +1,180 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ sphinxcontrib-docxbuilder
4
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
+
6
+ OpenXML Document Sphinx builder.
7
+
8
+ :copyright:
9
+ Copyright 2010 by shimizukawa at gmail dot com (Sphinx-users.jp).
10
+ :license: BSD, see LICENSE for details.
11
+ :modified:
12
+ Modifications for sphinx_docx by Nefti-sama
13
+ https://github.com/Nefti-sama/sphinx_docx
14
+ """
15
+
16
+ import os
17
+
18
+ from docutils import nodes
19
+ from docutils.io import FileOutput
20
+ from sphinx import addnodes
21
+ from sphinx.builders import Builder
22
+ from sphinx.util import logging
23
+ from sphinx.util.docutils import new_document
24
+ from sphinx.util.osutil import ensuredir
25
+
26
+ from sphinx_docx.writer import DocxWriter, DocxTranslator, findall
27
+
28
+
29
+ class DocxBuilder(Builder):
30
+ """Sphinx builder writing the documentation as docx files."""
31
+ # pylint: disable=attribute-defined-outside-init
32
+ name = 'docx'
33
+ format = 'docx'
34
+ out_suffix = '.docx'
35
+ default_translator_class = DocxTranslator
36
+
37
+ def init(self):
38
+ """Set up the image directory, logger and document list."""
39
+ self.imagedir = '_images'
40
+ self._logger = logging.getLogger('sphinx_docx')
41
+ self._docx_documents = []
42
+
43
+ def get_outdated_docs(self):
44
+ """Report outdated documents; every build writes all documents."""
45
+ return 'pass'
46
+
47
+ def get_target_uri(self, docname, typ=None):
48
+ """Return the target URI of a document, which is its name."""
49
+ return docname
50
+
51
+ def prepare_writing(self, docnames):
52
+ """Drop invalid ``docx_documents`` entries and create the writer.
53
+
54
+ Entries naming an unknown document or an empty filename are warned about
55
+ and skipped.
56
+ """
57
+ for entry in self.config.docx_documents:
58
+ if entry[0] not in self.env.all_docs:
59
+ self._logger.warning(
60
+ 'unknown document %s is found '
61
+ 'in docx_documents' % entry[0])
62
+ continue
63
+ if not entry[1]:
64
+ self._logger.warning(
65
+ 'invalid filename %s s found for %s '
66
+ 'in docx_documents' % (entry[1]. entry[0]))
67
+ continue
68
+ self._docx_documents.append(entry)
69
+ if not self._docx_documents:
70
+ self._logger.warning('no valid entry is found in docx_documents')
71
+ self.writer = DocxWriter(self)
72
+
73
+ def assemble_doctree(self, master, toctree_only):
74
+ """Return the doctree of ``master`` with every toctree expanded in place.
75
+
76
+ With ``toctree_only``, only the toctrees of the master document are kept,
77
+ not its own content.
78
+ """
79
+ tree = self.env.get_doctree(master)
80
+ if toctree_only:
81
+ doc = new_document('sphinx_docx/builder.py')
82
+ for toctree in findall(tree, addnodes.toctree):
83
+ # ids is not assigned to toctree, but to the parent
84
+ toctree.get('ids').extend(toctree.parent.get('ids'))
85
+ doc.append(toctree)
86
+ tree = doc
87
+ tree = insert_all_toctrees(tree, master, self.env, [])
88
+ tree['docname'] = master
89
+ self._logger.info('')
90
+ # TODO: Support cross references
91
+ return tree
92
+
93
+ def make_numfig_map(self):
94
+ """Map ``docname/node_id`` to a figure number, per figure type."""
95
+ numfig_map = {}
96
+ for docname, item in self.env.toc_fignumbers.items():
97
+ for figtype, info in item.items():
98
+ prefix = self.config.numfig_format.get(figtype)
99
+ if prefix is None:
100
+ continue
101
+ _, num_map = numfig_map.setdefault(figtype, (prefix, {}))
102
+ for node_id, num in info.items():
103
+ key = '%s/%s' % (docname, node_id)
104
+ num_map[key] = num
105
+ return numfig_map
106
+
107
+ def make_numsec_map(self):
108
+ """Map ``docname/node_id`` to a section number."""
109
+ numsec_map = {}
110
+ for docname, info in self.env.toc_secnumbers.items():
111
+ for node_id, num in info.items():
112
+ key = '%s/%s' % (docname, node_id)
113
+ numsec_map[key] = num
114
+ return numsec_map
115
+
116
+ def write(self, *_ignored): # pylint: disable=arguments-differ
117
+ """Write every valid ``docx_documents`` entry to a docx file."""
118
+ docnames = self.env.all_docs
119
+
120
+ self._logger.info('preparing documents... ', nonl=True)
121
+ self.prepare_writing(docnames)
122
+ self._logger.info('done')
123
+
124
+ for entry in self._docx_documents:
125
+ start_doc, docname, props = entry[:3]
126
+ toctree_only = entry[3] if len(entry) > 3 else False
127
+
128
+ self._logger.info('processing %s... ' % docname, nonl=True)
129
+ doctree = self.assemble_doctree(start_doc, toctree_only)
130
+ self.doc_properties = props
131
+ self._logger.info('writing... ', nonl=True)
132
+ self.write_doc(docname, doctree)
133
+ self._logger.info('done')
134
+
135
+ def write_doc(self, docname, doctree):
136
+ """Write one doctree to ``docname`` under the output directory."""
137
+ outfilename = os.path.join(self.outdir, docname)
138
+ ensuredir(os.path.dirname(outfilename))
139
+ # FileOutput handles bytes; BinaryFileOutput is removed in docutils 0.24
140
+ destination = FileOutput(destination_path=outfilename, mode='wb')
141
+ self.writer.write(doctree, destination)
142
+
143
+ def finish(self):
144
+ """Finish the build; nothing is left to do."""
145
+ pass
146
+
147
+ def insert_all_toctrees(tree, docname, env, traversed):
148
+ """Return a copy of ``tree`` with the documents of each toctree inlined.
149
+
150
+ ``traversed`` collects the documents already inlined, so a document
151
+ included twice is expanded only once.
152
+ """
153
+ tree = tree.deepcopy()
154
+ env.apply_post_transforms(tree, docname)
155
+ for index, toctreenode in enumerate(findall(tree, addnodes.toctree)):
156
+ # Numbered within the document rather than taken from
157
+ # id(toctreenode): that is the object's address, so it differs
158
+ # between runs, and it reaches the file as a bookmark name. Two
159
+ # builds of unchanged sources have to produce the same document.
160
+ nodeid = 'docx_expanded_toctree_%s_%d' % (
161
+ docname.replace('/', '_'), index)
162
+ newnodes = nodes.container(ids=[nodeid])
163
+ toctreenode['docx_expanded_toctree_refid'] = nodeid
164
+ includefiles = toctreenode['includefiles']
165
+ for includefile in includefiles:
166
+ if includefile in traversed:
167
+ continue
168
+ try:
169
+ traversed.append(includefile)
170
+ subtree = insert_all_toctrees(
171
+ env.get_doctree(includefile), includefile, env, traversed)
172
+ except Exception: # pylint: disable=broad-except
173
+ continue
174
+ start_of_file = addnodes.start_of_file(docname=includefile)
175
+ start_of_file.children = subtree.children
176
+ newnodes.append(start_of_file)
177
+ parent = toctreenode.parent
178
+ index = parent.index(toctreenode)
179
+ parent.insert(index + 1, newnodes)
180
+ return tree
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2009-2010 Mike MacCana
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1 @@
1
+ from sphinx_docx.docx.docx import *