Module: Coradoc::AsciiDoc::Parser::Inline

Defined in:
lib/coradoc/asciidoc/parser/inline.rb

Constant Summary collapse

TYPOGRAPHIC_QUOTE_PATTERNS =

AsciiDoc typographic quote syntax: a 2-char pattern that Asciidoctor substitutes with the corresponding Unicode curly quote. Single source of truth for the pattern → Unicode char mapping; the transformer reads this table.

The patterns MUST be recognised before monospace_constrained in the inline alternation, otherwise the lone backtick in <code>&quot;</code> or `"`` fires monospace and the surrounding quote collapses to straight ASCII quotes wrapped around a spurious code span.

{
  '"`' => "",  # U+201C left double
  '`"' => "",  # U+201D right double
  "'`" => "",  # U+2018 left single
  "`'" => ""   # U+2019 right single
}.freeze

Instance Method Summary collapse

Instance Method Details

#attribute_referenceObject



28
29
30
31
32
# File 'lib/coradoc/asciidoc/parser/inline.rb', line 28

def attribute_reference
  str('{').present? >> str('{') >>
    match('[a-zA-Z0-9_-]').repeat(1).as(:attribute_reference) >>
    str('}')
end

#bold_constrainedObject



34
35
36
37
38
39
40
# File 'lib/coradoc/asciidoc/parser/inline.rb', line 34

def bold_constrained
  (str('*').present? >> str('*') >>
    match('[^*\n]').repeat(1).as(:text).repeat(1, 1) >>
     str('*') >> str('*').absent? >>
     str("\n\n").absent?
  ).as(:bold_constrained)
end

#bold_unconstrainedObject



42
43
44
45
46
47
# File 'lib/coradoc/asciidoc/parser/inline.rb', line 42

def bold_unconstrained
  (str('**').present? >> str('**') >>
    match('[^*]').repeat(1).as(:text).repeat(1, 1) >>
     str('**')
  ).as(:bold_unconstrained)
end

#constrained_span_content(marker) ⇒ Object

Content model for a constrained inline span (`…`, *…*, _…_, #…#). Allows the corresponding unconstrained marker pair ( ``, **, __, ##) to appear inside the content rather than terminating the span at the first marker character.

Asciidoctor treats the contents of a constrained span as an inline literal — nested constrained markers do not close the span. Without this allowance, `<<\`\`x\`\`>>` fails to match as a single monospace span: the parser sees the inner `` as a failed single-backtick close attempt, backtracks out of monospace_constrained, and the <<…>> payload then fires the cross_reference rule with the backticks glued onto the target.

Single source of truth for every constrained rule's content model — adding a new constrained marker reuses this helper rather than re-spelling the alternation (DRY).



279
280
281
# File 'lib/coradoc/asciidoc/parser/inline.rb', line 279

def constrained_span_content(marker)
  (match("[^#{marker}\n]") | str(marker * 2)).repeat(1)
end

#hard_line_breakObject



217
218
219
220
# File 'lib/coradoc/asciidoc/parser/inline.rb', line 217

def hard_line_break
  ((str(' +') >> str("\n")) |
     (str('\\') >> str("\n"))).as(:hard_line_break)
end

#hard_line_break_marker?Boolean

AsciiDoc hard line break: a space followed by + at end of line, or a backslash at end of line. Both forms render as <br> inside the enclosing paragraph/verse. Recognised ahead of text_unformatted so the marker isn't swallowed as plain text.

Returns:

  • (Boolean)


212
213
214
215
# File 'lib/coradoc/asciidoc/parser/inline.rb', line 212

def hard_line_break_marker?
  (str(' +') >> str("\n")).present? |
    (str('\\') >> str("\n")).present?
end

#highlight_constrainedObject



79
80
81
82
83
84
# File 'lib/coradoc/asciidoc/parser/inline.rb', line 79

def highlight_constrained
  (str('#') >>
    match('[^#\n]').repeat(1).as(:text).repeat(1, 1) >>
     str('#') >> str('#').absent?
  ).as(:highlight_constrained)
end

#highlight_unconstrainedObject



86
87
88
89
90
91
# File 'lib/coradoc/asciidoc/parser/inline.rb', line 86

def highlight_unconstrained
  (str('##') >>
    match('[^#\n]').repeat(1).as(:text).repeat(1, 1) >>
     str('##')
  ).as(:highlight_unconstrained)
end

#inlineObject



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
# File 'lib/coradoc/asciidoc/parser/inline.rb', line 222

def inline
  typographic_quote |
    bold_unconstrained |
    bold_constrained |
    span_unconstrained |
    span_constrained |
    italic_unconstrained |
    italic_constrained |
    highlight_unconstrained |
    highlight_constrained |
    monospace_unconstrained |
    monospace_constrained |
    superscript |
    subscript |
    attribute_reference |
    escaped_xref |
    cross_reference |
    term_inline |
    term_inline2 |
    footnote |
    stem |
    link |
    inline_image |
    inline_passthrough |
    underline |
    small |
    hard_line_break
end

#inline_chars?Boolean

Returns:

  • (Boolean)


192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
# File 'lib/coradoc/asciidoc/parser/inline.rb', line 192

def inline_chars?
  match('[\[*#_{<^~`]').present? |
    typographic_quote.present? |
    str('http').present? |
    str('https').present? |
    str('link:').present? |
    str('image:').present? |
    str('+++').present? |
    str('pass:').present? |
    term_type.present? |
    str('footnote').present? |
    stem_type.present? |
    str('\\<<').present? |
    hard_line_break_marker?
end

#inline_imageObject



140
141
142
143
144
145
146
# File 'lib/coradoc/asciidoc/parser/inline.rb', line 140

def inline_image
  (str('image:').present? >> str('image:') >>
    str(':').absent? >>
    match('[A-Za-z0-9_.\\-:/&?=+,%#~;]+').repeat(1).as(:path) >>
    attribute_list(:attribute_list).maybe
  ).as(:inline_image)
end

#inline_passthroughObject



172
173
174
# File 'lib/coradoc/asciidoc/parser/inline.rb', line 172

def inline_passthrough
  inline_passthrough_triple_plus | inline_passthrough_macro
end

#inline_passthrough_macroObject

pass:[raw] macro form. Equivalent semantic to triple-plus: the bracket payload survives all substitutions verbatim. Common use is inside monospace spans to keep characters like < from being re-interpreted as xref markers. The optional subs segment (pass:quotes[...]) is consumed but currently ignored — the payload is always passed through raw.



164
165
166
167
168
169
170
# File 'lib/coradoc/asciidoc/parser/inline.rb', line 164

def inline_passthrough_macro
  (str('pass:').present? >> str('pass:') >>
    match('[a-zA-Z,+]').repeat(0) >>
    str('[') >> (str(']]').absent? >> match('[^\]\n]')).repeat(1).as(:raw) >>
    str(']')
  ).as(:inline_passthrough)
end

#inline_passthrough_triple_plusObject

Triple-plus inline passthrough: +++raw content+++. The content passes through all substitutions verbatim. Common use is to embed raw HTML in AsciiDoc documents.



151
152
153
154
155
156
# File 'lib/coradoc/asciidoc/parser/inline.rb', line 151

def inline_passthrough_triple_plus
  (str('+++') >>
    (str('+++').absent? >> match('[^\n]')).repeat(1).as(:raw) >>
    str('+++')
  ).as(:inline_passthrough)
end

#italic_constrainedObject



65
66
67
68
69
70
# File 'lib/coradoc/asciidoc/parser/inline.rb', line 65

def italic_constrained
  (str('_') >> str('_').absent? >>
    match('[^_\n]').repeat(1).as(:text).repeat(1, 1) >>
     str('_') >> str('_').absent?
  ).as(:italic_constrained)
end

#italic_unconstrainedObject



72
73
74
75
76
77
# File 'lib/coradoc/asciidoc/parser/inline.rb', line 72

def italic_unconstrained
  (str('__') >>
    match('[^_]').repeat(1).as(:text).repeat(1, 1) >>
     str('__')
  ).as(:italic_unconstrained)
end


129
130
131
132
133
134
135
136
137
138
# File 'lib/coradoc/asciidoc/parser/inline.rb', line 129

def link
  ((str('http').present? | str('https').present? | str('ftp').present?) >>
    match('[A-Za-z0-9_.\\-:/&?=+,%#~;]+').repeat(1).as(:path) >>
    (str('[') >> match('[^\\]]').repeat(1).as(:text) >> str(']')).maybe
  ).as(:link) |
    (str('link:').present? >> str('link:') >>
      match('[A-Za-z0-9_.\\-:/&?=+,%#~;]+').repeat(1).as(:path) >>
      (str('[') >> match('[^\\]]').repeat(1).as(:text) >> str(']')).maybe
    ).as(:link)
end

#monospace_constrainedObject



93
94
95
96
97
98
# File 'lib/coradoc/asciidoc/parser/inline.rb', line 93

def monospace_constrained
  (str('`') >>
    constrained_span_content('`').as(:text).repeat(1, 1) >>
     str('`') >> str('`').absent?
  ).as(:monospace_constrained)
end

#monospace_unconstrainedObject



100
101
102
103
104
105
# File 'lib/coradoc/asciidoc/parser/inline.rb', line 100

def monospace_unconstrained
  (str('``') >>
    match('[^\`]').repeat(1).as(:text).repeat(1, 1) >>
     str('``')
  ).as(:monospace_unconstrained)
end

#smallObject



184
185
186
187
188
189
190
# File 'lib/coradoc/asciidoc/parser/inline.rb', line 184

def small
  (attribute_list >> match('\\[.small\\]').as(:role) >>
    str('#') >>
    match('[^#\n]').repeat(1).as(:text) >>
    str('#')
  ).as(:small)
end

#spanObject



121
122
123
124
125
126
127
# File 'lib/coradoc/asciidoc/parser/inline.rb', line 121

def span
  attribute_list >>
    (str('#') >>
      match('[^#\n]').repeat(1).as(:text) >>
       str('#') >> str('#').absent?
    ).as(:span)
end

#span_constrainedObject



49
50
51
52
53
54
55
# File 'lib/coradoc/asciidoc/parser/inline.rb', line 49

def span_constrained
  (attribute_list >>
    str('#') >>
    match('[^#\n]').repeat(1).as(:text) >>
     str('#') >> str('#').absent?
  ).as(:span_constrained)
end

#span_unconstrainedObject



57
58
59
60
61
62
63
# File 'lib/coradoc/asciidoc/parser/inline.rb', line 57

def span_unconstrained
  (attribute_list >>
    str('##') >>
    match('[^#\n]').repeat(1).as(:text) >>
     str('##')
  ).as(:span_unconstrained)
end

#subscriptObject



114
115
116
117
118
119
# File 'lib/coradoc/asciidoc/parser/inline.rb', line 114

def subscript
  (str('~') >>
    match('[^~\n]').repeat(1).as(:text).repeat(1, 1) >>
     str('~')
  ).as(:subscript)
end

#superscriptObject



107
108
109
110
111
112
# File 'lib/coradoc/asciidoc/parser/inline.rb', line 107

def superscript
  (str('^') >>
    match('[^^\n]').repeat(1).as(:text).repeat(1, 1) >>
     str('^')
  ).as(:superscript)
end

#text_anyObject



287
288
289
290
291
292
293
# File 'lib/coradoc/asciidoc/parser/inline.rb', line 287

def text_any
  (text_formatted |
          text_unformatted.as(:text)
  ).repeat(2) |
    text_formatted.repeat(1, 1) |
    text_unformatted
end

#text_formattedObject



283
284
285
# File 'lib/coradoc/asciidoc/parser/inline.rb', line 283

def text_formatted
  (inline_chars? >> inline)
end

#text_unformattedObject



251
252
253
254
255
256
257
258
259
260
# File 'lib/coradoc/asciidoc/parser/inline.rb', line 251

def text_unformatted
  # `str('\\<<').absent?` stops text from consuming the backslash of
  # an escaped xref (`\<<`). Without this guard, the `\` is taken as
  # plain text, the `<<` re-enters cross_reference, and the literal
  # escape is destroyed.
  (str('\\<<').absent? >>
    inline.absent? >>
    match("[^\n]")
  ).repeat(1)
end

#typographic_quoteObject



24
25
26
# File 'lib/coradoc/asciidoc/parser/inline.rb', line 24

def typographic_quote
  (str('"`') | str('`"') | str("'`") | str("`'")).as(:typographic_quote)
end

#underlineObject



176
177
178
179
180
181
182
# File 'lib/coradoc/asciidoc/parser/inline.rb', line 176

def underline
  (attribute_list >> match('\\[.underline\\]').as(:role) >>
    str('#') >>
    match('[^#\n]').repeat(1).as(:text) >>
    str('#')
  ).as(:underline)
end