File: element.rb

package info (click to toggle)
ruby-kramdown 2.5.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, trixie
  • size: 2,896 kB
  • sloc: ruby: 6,462; makefile: 10
file content (551 lines) | stat: -rw-r--r-- 16,814 bytes parent folder | download
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
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
# -*- coding: utf-8; frozen_string_literal: true -*-
#
#--
# Copyright (C) 2009-2019 Thomas Leitner <t_leitner@gmx.at>
#
# This file is part of kramdown which is licensed under the MIT.
#++
#

module Kramdown

  # Represents all elements in the element tree.
  #
  # kramdown only uses this one class for representing all available elements in an element tree
  # (paragraphs, headers, emphasis, ...). The type of element can be set via the #type accessor.
  #
  # The root of a kramdown element tree has to be an element of type :root. It needs to have certain
  # option keys set so that conversions work correctly. If only a part of a tree should be
  # converted, duplicate the root node and assign the #children appropriately, e.g:
  #
  #   root = doc.root
  #   new_root = root.dup
  #   new_root.children = [root.children[0]]  # assign new array with elements to convert
  #
  # Following is a description of all supported element types.
  #
  # Note that the option :location may contain the start line number of an element in the source
  # document.
  #
  # == Structural Elements
  #
  # === :root
  #
  # [Category] None
  # [Usage context] As the root element of a document
  # [Content model] Block-level elements
  #
  # Represents the root of a kramdown document.
  #
  # The root element contains the following option keys:
  #
  # :encoding:: When running on Ruby 1.9 this key has to be set to the encoding used for the text
  #             parts of the kramdown document.
  #
  # :abbrev_defs:: This key may be used to store the mapping of abbreviation to abbreviation
  #                definition.
  #
  # :abbrev_attr:: This key may be used to store the mapping of abbreviation to abbreviation
  #                attributes.
  #
  # :options:: This key may be used to store options that were set during parsing of the document.
  #
  # :footnote_count:: This key stores the number of actually referenced footnotes of the document.
  #
  # === :blank
  #
  # [Category] Block-level element
  # [Usage context] Where block-level elements are expected
  # [Content model] Empty
  #
  # Represents one or more blank lines. It is not allowed to have two or more consecutive blank
  # elements.
  #
  # The +value+ field may contain the original content of the blank lines.
  #
  #
  # === :p
  #
  # [Category] Block-level element
  # [Usage context] Where block-level elements are expected
  # [Content model] Span-level elements
  #
  # Represents a paragraph.
  #
  # If the option :transparent is +true+, this element just represents a block of text. I.e. this
  # element just functions as a container for span-level elements.
  #
  #
  # === :header
  #
  # [Category] Block-level element
  # [Usage context] Where block-level elements are expected
  # [Content model] Span-level elements
  #
  # Represents a header.
  #
  # The option :level specifies the header level and has to contain a number between 1 and \6. The
  # option :raw_text has to contain the raw header text.
  #
  #
  # === :blockquote
  #
  # [Category] Block-level element
  # [Usage context] Where block-level elements are expected
  # [Content model] Block-level elements
  #
  # Represents a blockquote.
  #
  #
  # === :codeblock
  #
  # [Category] Block-level element
  # [Usage context] Where block-level elements are expected
  # [Content model] Empty
  #
  # Represents a code block, i.e. a block of text that should be used as-is.
  #
  # The +value+ field has to contain the content of the code block.
  #
  # The option :lang specifies a highlighting language with possible HTML style options (e.g.
  # php?start_inline=1) and should be used instead of a possibly also available language embedded in
  # a class name of the form 'language-LANG'.
  #
  #
  # === :ul
  #
  # [Category] Block-level element
  # [Usage context] Where block-level elements are expected
  # [Content model] One or more :li elements
  #
  # Represents an unordered list.
  #
  #
  # === :ol
  #
  # [Category] Block-level element
  # [Usage context] Where block-level elements are expected
  # [Content model] One or more :li elements
  #
  # Represents an ordered list.
  #
  #
  # === :li
  #
  # [Category] Block-level element
  # [Usage context] Inside :ol and :ul elements
  # [Content model] Block-level elements
  #
  # Represents a list item of an ordered or unordered list.
  #
  # Note that the first child of a list item must not be a :blank element!
  #
  #
  # === :dl
  #
  # [Category] Block-level element
  # [Usage context] Where block-level elements are expected
  # [Content model] One or more groups each consisting of one or more :dt elements followed by one
  #                 or more :dd elements.
  #
  # Represents a definition list which contains groups consisting of terms and definitions for them.
  #
  #
  # === :dt
  #
  # [Category] Block-level element
  # [Usage context] Before :dt or :dd elements inside a :dl elment
  # [Content model] Span-level elements
  #
  # Represents the term part of a term-definition group in a definition list.
  #
  #
  # === :dd
  #
  # [Category] Block-level element
  # [Usage context] After :dt or :dd elements inside a :dl elment
  # [Content model] Block-level elements
  #
  # Represents the definition part of a term-definition group in a definition list.
  #
  #
  # === :hr
  #
  # [Category] Block-level element
  # [Usage context] Where block-level elements are expected
  # [Content model] None
  #
  # Represents a horizontal line.
  #
  #
  # === :table
  #
  # [Category] Block-level element
  # [Usage context] Where block-level elements are expected
  # [Content model] Zero or one :thead elements, one or more :tbody elements, zero or one :tfoot
  #                 elements
  #
  # Represents a table. Each table row (i.e. :tr element) of the table has to contain the same
  # number of :td elements.
  #
  # The option :alignment has to be an array containing the alignment values, exactly one for each
  # column of the table. The possible alignment values are :left, :center, :right and :default.
  #
  #
  # === :thead
  #
  # [Category] None
  # [Usage context] As first element inside a :table element
  # [Content model] One or more :tr elements
  #
  # Represents the table header.
  #
  #
  # === :tbody
  #
  # [Category] None
  # [Usage context] After a :thead element but before a :tfoot element inside a :table element
  # [Content model] One or more :tr elements
  #
  # Represents a table body.
  #
  #
  # === :tfoot
  #
  # [Category] None
  # [Usage context] As last element inside a :table element
  # [Content model] One or more :tr elements
  #
  # Represents the table footer.
  #
  #
  # === :tr
  #
  # [Category] None
  # [Usage context] Inside :thead, :tbody and :tfoot elements
  # [Content model] One or more :td elements
  #
  # Represents a table row.
  #
  #
  # === :td
  #
  # [Category] Block-level element
  # [Usage context] Inside :tr elements
  # [Content model] As child of :thead/:tr span-level elements, as child of :tbody/:tr and
  #                 :tfoot/:tr block-level elements
  #
  # Represents a table cell.
  #
  #
  # === :math
  #
  # [Category] Block/span-level element
  # [Usage context] Where block/span-level elements are expected
  # [Content model] None
  #
  # Represents mathematical text that is written in LaTeX.
  #
  # The +value+ field has to contain the actual mathematical text.
  #
  # The option :category has to be set to either :span or :block depending on the context where the
  # element is used.
  #
  #
  # == Text Markup Elements
  #
  # === :text
  #
  # [Category] Span-level element
  # [Usage context] Where span-level elements are expected
  # [Content model] None
  #
  # Represents text.
  #
  # The +value+ field has to contain the text itself.
  #
  #
  # === :br
  #
  # [Category] Span-level element
  # [Usage context] Where span-level elements are expected
  # [Content model] None
  #
  # Represents a hard line break.
  #
  #
  # === :a
  #
  # [Category] Span-level element
  # [Usage context] Where span-level elements are expected
  # [Content model] Span-level elements
  #
  # Represents a link to an URL.
  #
  # The attribute +href+ has to be set to the URL to which the link points. The attribute +title+
  # optionally contains the title of the link.
  #
  #
  # === :img
  #
  # [Category] Span-level element
  # [Usage context] Where span-level elements are expected
  # [Content model] None
  #
  # Represents an image.
  #
  # The attribute +src+ has to be set to the URL of the image. The attribute +alt+ has to contain a
  # text description of the image. The attribute +title+ optionally contains the title of the image.
  #
  #
  # === :codespan
  #
  # [Category] Span-level element
  # [Usage context] Where span-level elements are expected
  # [Content model] None
  #
  # Represents verbatim text.
  #
  # The +value+ field has to contain the content of the code span.
  #
  #
  # === :footnote
  #
  # [Category] Span-level element
  # [Usage context] Where span-level elements are expected
  # [Content model] None
  #
  # Represents a footnote marker.
  #
  # The +value+ field has to contain an element whose children are the content of the footnote. The
  # option :name has to contain a valid and unique footnote name. A valid footnote name consists of
  # a word character or a digit and then optionally followed by other word characters, digits or
  # dashes.
  #
  #
  # === :em
  #
  # [Category] Span-level element
  # [Usage context] Where span-level elements are expected
  # [Content model] Span-level elements
  #
  # Represents emphasis of its contents.
  #
  #
  # === :strong
  #
  # [Category] Span-level element
  # [Usage context] Where span-level elements are expected
  # [Content model] Span-level elements
  #
  # Represents strong importance for its contents.
  #
  #
  # === :entity
  #
  # [Category] Span-level element
  # [Usage context] Where span-level elements are expected
  # [Content model] None
  #
  # Represents an HTML entity.
  #
  # The +value+ field has to contain an instance of Kramdown::Utils::Entities::Entity. The option
  # :original can be used to store the original representation of the entity.
  #
  #
  # === :typographic_sym
  #
  # [Category] Span-level element
  # [Usage context] Where span-level elements are expected
  # [Content model] None
  #
  # Represents a typographic symbol.
  #
  # The +value+ field needs to contain a Symbol representing the specific typographic symbol from
  # the following list:
  #
  # :mdash:: An mdash character (---)
  # :ndash:: An ndash character (--)
  # :hellip:: An ellipsis (...)
  # :laquo:: A left guillemet (<<)
  # :raquo:: A right guillemet (>>)
  # :laquo_space:: A left guillemet with a space (<< )
  # :raquo_space:: A right guillemet with a space ( >>)
  #
  #
  # === :smart_quote
  #
  # [Category] Span-level element
  # [Usage context] Where span-level elements are expected
  # [Content model] None
  #
  # Represents a quotation character.
  #
  # The +value+ field needs to contain a Symbol representing the specific quotation character:
  #
  # :lsquo:: Left single quote
  # :rsquo:: Right single quote
  # :ldquo:: Left double quote
  # :rdquo:: Right double quote
  #
  #
  # === :abbreviation
  #
  # [Category] Span-level element
  # [Usage context] Where span-level elements are expected
  # [Content model] None
  #
  # Represents a text part that is an abbreviation.
  #
  # The +value+ field has to contain the text part that is the abbreviation. The definition of the
  # abbreviation is stored in the :root element of the document.
  #
  #
  # == Other Elements
  #
  # === :html_element
  #
  # [Category] Block/span-level element
  # [Usage context] Where block/span-level elements or raw HTML elements are expected
  # [Content model] Depends on the element
  #
  # Represents an HTML element.
  #
  # The +value+ field has to contain the name of the HTML element the element is representing.
  #
  # The option :category has to be set to either :span or :block depending on the whether the
  # element is a block-level or a span-level element. The option :content_model has to be set to the
  # content model for the element (either :block if it contains block-level elements, :span if it
  # contains span-level elements or :raw if it contains raw content).
  #
  #
  # === :xml_comment
  #
  # [Category] Block/span-level element
  # [Usage context] Where block/span-level elements are expected or in raw HTML elements
  # [Content model] None
  #
  # Represents an XML/HTML comment.
  #
  # The +value+ field has to contain the whole XML/HTML comment including the delimiters.
  #
  # The option :category has to be set to either :span or :block depending on the context where the
  # element is used.
  #
  #
  # === :xml_pi
  #
  # [Category] Block/span-level element
  # [Usage context] Where block/span-level elements are expected or in raw HTML elements
  # [Content model] None
  #
  # Represents an XML/HTML processing instruction.
  #
  # The +value+ field has to contain the whole XML/HTML processing instruction including the
  # delimiters.
  #
  # The option :category has to be set to either :span or :block depending on the context where the
  # element is used.
  #
  #
  # === :comment
  #
  # [Category] Block/span-level element
  # [Usage context] Where block/span-level elements are expected
  # [Content model] None
  #
  # Represents a comment.
  #
  # The +value+ field has to contain the comment.
  #
  # The option :category has to be set to either :span or :block depending on the context where the
  # element is used. If it is set to :span, then no blank lines are allowed in the comment.
  #
  #
  # === :raw
  #
  # [Category] Block/span-level element
  # [Usage context] Where block/span-level elements are expected
  # [Content model] None
  #
  # Represents a raw string that should not be modified. For example, the element could contain some
  # HTML code that should be output as-is without modification and escaping.
  #
  # The +value+ field has to contain the actual raw text.
  #
  # The option :category has to be set to either :span or :block depending on the context where the
  # element is used. If it is set to :span, then no blank lines are allowed in the raw text.
  #
  # The option :type can be set to an array of strings to define for which converters the raw string
  # is valid.
  #
  class Element

    # A symbol representing the element type. For example, :p or :blockquote.
    attr_accessor :type

    # The value of the element. The interpretation of this field depends on the type of the element.
    # Many elements don't use this field.
    attr_accessor :value

    # The child elements of this element.
    attr_accessor :children

    # Create a new Element object of type +type+. The optional parameters +value+, +attr+ and
    # +options+ can also be set in this constructor for convenience.
    def initialize(type, value = nil, attr = nil, options = nil)
      @type, @value, @attr, @options = type, value, attr, options
      @children = []
    end

    # The attributes of the element.
    def attr
      @attr ||= {}
    end

    # The options hash for the element. It is used for storing arbitray options.
    def options
      @options ||= {}
    end

    def inspect # :nodoc:
      "<kd:#{@type}" \
        "#{value.nil? ? '' : ' value=' + value.inspect}" \
        "#{attr.empty? ? '' : ' attr=' + attr.inspect}" \
        "#{options.empty? ? '' : ' options=' + options.inspect}" \
        "#{children.empty? ? '' : ' children=' + children.inspect}>"
    end

    CATEGORY = {} # :nodoc:
    [:blank, :p, :header, :blockquote, :codeblock, :ul, :ol, :li, :dl, :dt, :dd,
     :table, :td, :hr].each {|b| CATEGORY[b] = :block }
    [:text, :a, :br, :img, :codespan, :footnote, :em, :strong, :entity, :typographic_sym,
     :smart_quote, :abbreviation].each {|b| CATEGORY[b] = :span }

    # Return the category of +el+ which can be :block, :span or +nil+.
    #
    # Most elements have a fixed category, however, some elements can either appear in a block-level
    # or a span-level context. These elements need to have the option :category correctly set.
    def self.category(el)
      CATEGORY[el.type] || el.options[:category]
    end

    # syntactic sugar to simplify calls such as +Kramdown::Element.category(el) == :block+ with
    # +el.block?+.
    #
    # Returns boolean true or false.
    def block?
      (CATEGORY[type] || options[:category]) == :block
    end

    # syntactic sugar to simplify calls such as +Kramdown::Element.category(el) == :span+ with
    # +el.span?+.
    #
    # Returns boolean true or false.
    def span?
      (CATEGORY[type] || options[:category]) == :span
    end

  end

end