File: Sectioning.py

package info (click to toggle)
plastex 3.1-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 6,132 kB
  • sloc: python: 23,341; xml: 18,076; javascript: 7,755; ansic: 46; makefile: 40; sh: 26
file content (358 lines) | stat: -rw-r--r-- 10,872 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
"""
C.4 Sectioning and Table of Contents (p174)

"""

from plasTeX import Command

#
# C.4.1 Sectioning Commands
#

class cachedproperty(object):
    """ Property whose value is only calculated once and cached """
    def __init__(self, func):
        self._func = func
    def __get__(self, obj, type=None):
        if obj is None:
            return self
        try:
            return getattr(obj, '@%s' % self._func.__name__)
        except AttributeError:
            result = self._func(obj)
            setattr(obj, '@%s' % self._func.__name__, result)
            return result


class TableOfContents(object):
    """
    Table of Contents object

    The table of contents object is a proxy object that limits the
    depth of a table of contents entry.  Each time the `tableofcontents'
    attribute is accessed on the given node, the depth level is
    increased.  Once the depth limit has been reached, no more
    table of contents entries are returned.

    """

    def __init__(self, node, limit, level=1):
        """
        Instantiate a table of contents object

        Arguments:
        node -- the node to retrieve the table of contents from
        limit -- the number of levels to display
        level -- the current level

        """
        self._toc_node = node
        self._toc_limit = limit
        self._toc_level = level

    def __getattribute__(self, name):
        """
        Proxy all attributes to the real object except `tableofcontents'

        Each nested call to the tableofcontents should limit the
        depth of the items displayed.

        """
        # Attributes that belong to the ToC object
        if name.startswith('_toc_'):
            return object.__getattribute__(self, name)

        # Limit the number of ToC levels
        if name in ['tableofcontents','fulltableofcontents']:
            if self._toc_level < self._toc_limit:
                return [type(self)(x._toc_node, self._toc_limit,
                        self._toc_level+1) for x in self._toc_node.fulltableofcontents]
            else:
                return []

        # All other attribute accesses get passed on
        return getattr(self._toc_node, name)

class SectionUtils(object):
    """ General utilities for getting information about sections """

    tocdepth = None

    @cachedproperty
    def footnotes(self):
        output = []
        for f in self.ownerDocument.userdata.get('footnotes', []):
            s = f.currentSection
            while s is not None and not s.filename:
                s = s.currentSection
            if s is self:
                output.append(f)
        for i, f in enumerate(output):
            f.mark.attributes['num'] = i+1
        return output

    @cachedproperty
    def subsections(self):
        """ Retrieve a list of all immediate subsections of this section """
        return [x for x in self if x.level < Command.ENDSECTIONS_LEVEL]

    @cachedproperty
    def siblings(self):
        """ Retrieve a list of all sibling sections of this section """
        if not self.parentNode or self.level == Command.DOCUMENT_LEVEL:
            return []
        return [x for x in self.parentNode.subsections if x is not self]

    @cachedproperty
    def tableofcontents(self):
        """ Return a toble of contents object limited to toc-depth """
        if self.tocdepth is not None:
            tocdepth = self.tocdepth
        else:
            tocdepth = self.config['document']['toc-depth']

        # Bail out if they don't want a ToC
        if tocdepth < 1:
            return []

        # Don't create a ToC unless at least one subsection creates a file
        if not [x for x in self.subsections if x.filename]:
            return []

        # Include sections that don't create files in the ToC
        if self.config['document']['toc-non-files']:
            return [TableOfContents(x, tocdepth) for x in self.subsections]

        # Only include sections that create files in the ToC
        return [TableOfContents(x, tocdepth) for x in self.subsections
                                             if x.filename]

    @cachedproperty
    def fulltableofcontents(self):
        """ Return a toble of contents object without limits """
        # Include sections that don't create files in the ToC
        if self.config['document']['toc-non-files']:
            return [TableOfContents(x, 1000) for x in self.subsections]

        # Only include sections that create files in the ToC
        return [TableOfContents(x, 1000) for x in self.subsections
                                             if x.filename]

    @cachedproperty
    def allSections(self):
        """ Retrieve a list of all sections within (and including) this one """
        sections = [self]
        for item in self.subsections:
            sections.extend(item.allSections)
        return sections

    @cachedproperty
    def documentSections(self):
        """ Retrieve a list of all sections in the document """
        document = self
        while document.level is not Command.DOCUMENT_LEVEL:
            document = document.parentNode
            if document is None:
                return []
        return document.allSections

    @cachedproperty
    def links(self):
        """
        Return a dictionary containing a lot of navigation information

        See http://fantasai.tripod.com/qref/Appendix/LinkTypes/ltdef.html

        """
        sections = [x for x in self.documentSections if x.filename]

        breadcrumbs = [self]
        parent = None
        if self.level > Command.DOCUMENT_LEVEL:
            item = parent = self.parentNode
            while item is not None and item.level > Command.DOCUMENT_LEVEL:
                breadcrumbs.append(item)
                item = item.parentNode
            if item is not None:
                breadcrumbs.append(item)
        breadcrumbs.reverse()

        first = top = breadcrumbs[0]
        last = sections[-1]
        prev = next = None
        breaknext = False
        for item in sections:
            if item is self:
                breaknext = True
                continue
            if breaknext:
                next = item
                break
            prev = item

        document = part = chapter = section = subsection = None
        for item in breadcrumbs:
            if item.level == Command.DOCUMENT_LEVEL:
                document = item
            elif item.level == Command.PART_LEVEL:
                part = item
            elif item.level == Command.CHAPTER_LEVEL:
                chapter = item
            elif item.level == Command.SECTION_LEVEL:
                section = item
            elif item.level == Command.SUBSECTION_LEVEL:
                subsection = item

        nav = {}
        nav['home'] = top
        nav['start'] = top
        nav['begin'] = nav['first'] = first
        nav['end'] = nav['last'] = last
        nav['next'] = next
        nav['previous'] = nav['prev'] = prev
        nav['up'] = parent
        nav['top'] = nav['origin'] = top
        nav['parent'] = parent
        nav['child'] = self.subsections
        nav['sibling'] = self.siblings

        # These aren't actually part of the spec, but I added
        # them for consistency.
        nav['document'] = document
        nav['part'] = part

        nav['chapter'] = chapter
        nav['section'] = section
        nav['subsection'] = subsection
        nav['appendix'] = None
        nav['glossary'] = None
        nav['bibliography'] = None
        nav['help'] = None
        nav['navigator'] = top
        nav['toc'] = nav['contents'] = top
        nav['index'] = None
        nav['search'] = None
        nav['bookmark'] = None
        nav['banner'] = None
        nav['copyright'] = None
        nav['trademark'] = None
        nav['disclaimer'] = None
        nav['publisher'] = None
        nav['editor'] = None
        nav['author'] = None
        nav['made'] = None
        nav['meta'] = None
        nav['script'] = None
        nav['stylesheet'] = []
        nav['alternate'] = []
        nav['translation'] = []

        # Additional related entries
        nav['shortcut icon'] = None
        nav['breadcrumbs'] = breadcrumbs

        # Get navigation info from the linkTypes
        navinfo = self.ownerDocument.userdata.get('links', {})
        for key, value in list(navinfo.items()):
            nav[key] = value

        # Get user-defined links
        links = {}
        for key, value in self.config['links']['links'].items():
            newkey, type = key.strip().split('-',1)
            if newkey not in links:
                links[newkey] = {}
            links[newkey][type] = value

        # Set links in nav object
        for key, value in list(links.items()):
            if key not in list(nav.keys()) or nav[key] is None:
                nav[key] = value

        return nav

    def digest(self, tokens):
        # Absorb the tokens that belong to us
#       text = []
        for item in tokens:
#           if item.nodeType == Command.TEXT_NODE:
#               text.append(item)
#               continue
            if item.level <= self.level:
                tokens.push(item)
                break
            if item.nodeType == Command.ELEMENT_NODE:
                item.parentNode = self
                item.digest(tokens)
#           self.appendText(text, self.ownerDocument.charsubs)
            self.appendChild(item)
#       self.appendText(text, self.ownerDocument.charsubs)
        self.paragraphs()


class StartSection(SectionUtils, Command):
    blockType = True
    args = '* [ toc ] title'

class part(StartSection):
    level = Command.PART_LEVEL
    counter = 'part'

class chapter(StartSection):
    level = Command.CHAPTER_LEVEL
    counter = 'chapter'

class section(StartSection):
    level = Command.SECTION_LEVEL
    counter = 'section'

class subsection(StartSection):
    level = Command.SUBSECTION_LEVEL
    counter = 'subsection'

class subsubsection(StartSection):
    level = Command.SUBSUBSECTION_LEVEL
    counter = 'subsubsection'

class paragraph(StartSection):
    level = Command.PARAGRAPH_LEVEL
    counter = 'paragraph'

class subparagraph(StartSection):
    level = Command.SUBPARAGRAPH_LEVEL
    counter = 'subparagraph'

class subsubparagraph(StartSection):
    level = Command.SUBSUBPARAGRAPH_LEVEL
    counter = 'subsubparagraph'

#
# C.4.2 The Appendix
#

class appendix(Command):
    """ This needs to be implemented in the cls file """
    blockType = True

#
# C.4.3 Table of Contents
#

class tableofcontents(Command):
    blockType = True

class listoffigures(Command):
    blockType = True

class listoftables(Command):
    blockType = True

class addcontentsline(Command):
    args = 'file:str level:str text'

class addtocontents(Command):
    args = 'file:str text'

#
# C.4.4 Style Parameters
#