coradoc-adoc 2.0.34 → 2.0.36
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.
- checksums.yaml +4 -4
- data/grammar/coradoc-adoc.artifact.json +1 -0
- data/grammar/coradoc-adoc.parg +396 -0
- data/lib/coradoc/asciidoc/formatter.rb +75 -0
- data/lib/coradoc/asciidoc/lint/document_title.rb +26 -0
- data/lib/coradoc/asciidoc/lint/duplicate_ids.rb +36 -0
- data/lib/coradoc/asciidoc/lint/empty_section.rb +45 -0
- data/lib/coradoc/asciidoc/lint/heading_levels.rb +44 -0
- data/lib/coradoc/asciidoc/lint.rb +27 -0
- data/lib/coradoc/asciidoc/model/text_element.rb +18 -5
- data/lib/coradoc/asciidoc/parser/base.rb +28 -11
- data/lib/coradoc/asciidoc/parser/citation.rb +10 -0
- data/lib/coradoc/asciidoc/parser/document_attributes.rb +6 -1
- data/lib/coradoc/asciidoc/parser/inline.rb +26 -19
- data/lib/coradoc/asciidoc/parser/list.rb +25 -8
- data/lib/coradoc/asciidoc/parser/paragraph.rb +4 -2
- data/lib/coradoc/asciidoc/parser/positioned_string.rb +40 -0
- data/lib/coradoc/asciidoc/parser/rule_dispatcher.rb +3 -2
- data/lib/coradoc/asciidoc/parser/tree_materializer.rb +28 -0
- data/lib/coradoc/asciidoc/parser.rb +2 -0
- data/lib/coradoc/asciidoc/serializer/serializers/block/source_code.rb +3 -1
- data/lib/coradoc/asciidoc/serializer/serializers/list/item.rb +4 -0
- data/lib/coradoc/asciidoc/serializer/serializers/table.rb +8 -2
- data/lib/coradoc/asciidoc/serializer/serializers/text_element.rb +3 -1
- data/lib/coradoc/asciidoc/transform/from_core_model/list_building.rb +86 -0
- data/lib/coradoc/asciidoc/transform/from_core_model.rb +100 -29
- data/lib/coradoc/asciidoc/transform/frontmatter_attribute_map.rb +3 -2
- data/lib/coradoc/asciidoc/transform/text_extract_visitor.rb +5 -2
- data/lib/coradoc/asciidoc/transform/to_core_model.rb +12 -2
- data/lib/coradoc/asciidoc/transform.rb +1 -0
- data/lib/coradoc/asciidoc/transformer/source_line_extractor.rb +1 -1
- data/lib/coradoc/asciidoc/transformer/table_cell_builder.rb +18 -7
- data/lib/coradoc/asciidoc/version.rb +1 -1
- data/lib/coradoc/asciidoc.rb +12 -0
- data/lib/coradoc/util/asciidoc.rb +56 -0
- metadata +16 -5
|
@@ -5,6 +5,8 @@ module Coradoc
|
|
|
5
5
|
module Transform
|
|
6
6
|
# Transforms CoreModel to AsciiDoc models
|
|
7
7
|
class FromCoreModel
|
|
8
|
+
extend Transform::ListBuilding
|
|
9
|
+
|
|
8
10
|
@registered = false
|
|
9
11
|
|
|
10
12
|
class << self
|
|
@@ -216,24 +218,11 @@ module Coradoc
|
|
|
216
218
|
)
|
|
217
219
|
end
|
|
218
220
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
)
|
|
225
|
-
end
|
|
226
|
-
|
|
227
|
-
case list.marker_type
|
|
228
|
-
when 'ordered'
|
|
229
|
-
Coradoc::AsciiDoc::Model::List::Ordered.new(items: items)
|
|
230
|
-
when 'definition'
|
|
231
|
-
Coradoc::AsciiDoc::Model::List::Definition.new(items: items)
|
|
232
|
-
else
|
|
233
|
-
Coradoc::AsciiDoc::Model::List::Unordered.new(items: items)
|
|
234
|
-
end
|
|
235
|
-
end
|
|
236
|
-
|
|
221
|
+
# Lists nested inside list items carry depth markers so
|
|
222
|
+
# AsciiDoc reads them as nested rather than sibling lists —
|
|
223
|
+
# without this, item children other than text were dropped
|
|
224
|
+
# entirely (#68 territory). Nested lists keep their own
|
|
225
|
+
# marker type one level deeper.
|
|
237
226
|
def transform_list_item(item)
|
|
238
227
|
Coradoc::AsciiDoc::Model::List::Item.new(
|
|
239
228
|
content: item.flat_text,
|
|
@@ -256,12 +245,95 @@ module Coradoc
|
|
|
256
245
|
)
|
|
257
246
|
end
|
|
258
247
|
|
|
259
|
-
|
|
248
|
+
# Nested inline structure lives in +children+ (e.g. an
|
|
249
|
+
# ItalicElement whose single child is a BoldElement);
|
|
250
|
+
# +content+ is only the flattened display string. Build the
|
|
251
|
+
# adoc model from children so nesting survives, and default
|
|
252
|
+
# to the constrained marker — the constrained/unstrained
|
|
253
|
+
# distinction is not carried in CoreModel, and constrained
|
|
254
|
+
# is the correct rendering for span-boundary emphasis (#159).
|
|
255
|
+
def inline_model(klass, inline, unconstrained: false)
|
|
256
|
+
content = if inline.children.nil? || inline.children.empty?
|
|
257
|
+
inline.content.to_s
|
|
258
|
+
else
|
|
259
|
+
create_text_elements(inline.children)
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
klass.new(content: content, unconstrained: unconstrained)
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
# `_*text*_` parses to Italic{Bold{text}}; Metanorma renders
|
|
266
|
+
# same-span emphasis correctly only with italic innermost
|
|
267
|
+
# (`*_text_*`, #159). When an italic's entire content is one
|
|
268
|
+
# bold (or a bold's one italic), rebuild as Bold outer /
|
|
269
|
+
# Italic inner, both constrained.
|
|
270
|
+
def swap_emphasis_nesting(inline, unconstrained: false)
|
|
271
|
+
children = Array(inline.children)
|
|
272
|
+
return nil unless children.size == 1
|
|
273
|
+
|
|
274
|
+
only = children.first
|
|
275
|
+
return nil unless only.is_a?(CoreModel::InlineElement)
|
|
276
|
+
|
|
277
|
+
inner_kids = Array(only.children)
|
|
278
|
+
return nil unless inner_kids.empty? || inner_kids.all?(CoreModel::TextContent)
|
|
279
|
+
|
|
280
|
+
outer_type = inline.resolve_format_type
|
|
281
|
+
inner_type = only.resolve_format_type
|
|
282
|
+
return nil unless %w[bold italic].include?(outer_type) && outer_type != inner_type &&
|
|
283
|
+
%w[bold italic].include?(inner_type)
|
|
284
|
+
|
|
285
|
+
classes = {
|
|
286
|
+
'bold' => Coradoc::AsciiDoc::Model::Inline::Bold,
|
|
287
|
+
'italic' => Coradoc::AsciiDoc::Model::Inline::Italic
|
|
288
|
+
}
|
|
289
|
+
inner = classes[outer_type].new(
|
|
290
|
+
content: only.children.nil? || only.children.empty? ? only.content.to_s : create_text_elements(only.children),
|
|
291
|
+
unconstrained: false
|
|
292
|
+
)
|
|
293
|
+
classes[inner_type].new(content: inner, unconstrained: unconstrained)
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
# AsciiDoc constrained markers only reparse as emphasis when
|
|
297
|
+
# the opening delimiter follows a boundary and the closing
|
|
298
|
+
# one precedes one. CoreModel does not carry the constraint,
|
|
299
|
+
# so derive it from the adjacent sibling text: an inline
|
|
300
|
+
# touching a word character on either side must serialize
|
|
301
|
+
# with the unconstrained form or the emphasis is lost on
|
|
302
|
+
# reparse (mid-word bolding is common in Word documents).
|
|
303
|
+
def unconstrained_flanks?(left, right)
|
|
304
|
+
left_ok = left.nil? || left.match?(/\s/)
|
|
305
|
+
right_ok = right.nil? || right.match?(/\s|[[:punct:]]/)
|
|
306
|
+
!(left_ok && right_ok)
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
def sibling_edge(items, index, direction)
|
|
310
|
+
item = items[index]
|
|
311
|
+
text = case item
|
|
312
|
+
when Coradoc::CoreModel::TextContent then item.text.to_s
|
|
313
|
+
when Coradoc::CoreModel::InlineElement then item.content.to_s
|
|
314
|
+
when String then item
|
|
315
|
+
else return nil
|
|
316
|
+
end
|
|
317
|
+
return nil if text.empty?
|
|
318
|
+
|
|
319
|
+
direction == :last ? text[-1] : text[0]
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
def transform_inline(inline, siblings: nil, index: 0)
|
|
323
|
+
left = siblings && index.positive? ? sibling_edge(siblings, index - 1, :last) : nil
|
|
324
|
+
right = siblings ? sibling_edge(siblings, index + 1, :first) : nil
|
|
325
|
+
unconstrained = unconstrained_flanks?(left, right)
|
|
260
326
|
case inline.resolve_format_type
|
|
261
327
|
when 'bold'
|
|
262
|
-
Coradoc::AsciiDoc::Model::Inline::Bold
|
|
328
|
+
inline_model(Coradoc::AsciiDoc::Model::Inline::Bold, inline,
|
|
329
|
+
unconstrained: unconstrained)
|
|
263
330
|
when 'italic'
|
|
264
|
-
|
|
331
|
+
# #159: italic directly wrapping only bold (`_*text*_`)
|
|
332
|
+
# re-serializes as Bold outer / Italic inner (`*_text_*`)
|
|
333
|
+
# for correct Metanorma rendering.
|
|
334
|
+
swap_emphasis_nesting(inline, unconstrained: unconstrained) ||
|
|
335
|
+
inline_model(Coradoc::AsciiDoc::Model::Inline::Italic, inline,
|
|
336
|
+
unconstrained: unconstrained)
|
|
265
337
|
when 'monospace'
|
|
266
338
|
Coradoc::AsciiDoc::Model::Inline::Monospace.new(content: inline.content)
|
|
267
339
|
when 'highlight'
|
|
@@ -546,7 +618,13 @@ module Coradoc
|
|
|
546
618
|
def create_text_elements(content)
|
|
547
619
|
case content
|
|
548
620
|
when Array
|
|
549
|
-
content.map
|
|
621
|
+
content.each_with_index.map do |item, i|
|
|
622
|
+
if item.is_a?(Coradoc::CoreModel::InlineElement)
|
|
623
|
+
transform_inline(item, siblings: content, index: i)
|
|
624
|
+
else
|
|
625
|
+
create_text_elements(item)
|
|
626
|
+
end
|
|
627
|
+
end
|
|
550
628
|
when Coradoc::CoreModel::InlineElement
|
|
551
629
|
transform_inline(content)
|
|
552
630
|
when Coradoc::CoreModel::TextContent
|
|
@@ -577,13 +655,6 @@ module Coradoc
|
|
|
577
655
|
attrs['language'] = block.language if block.language
|
|
578
656
|
attrs
|
|
579
657
|
end
|
|
580
|
-
|
|
581
|
-
def default_marker(marker_type)
|
|
582
|
-
case marker_type
|
|
583
|
-
when 'ordered' then '.'
|
|
584
|
-
else '*'
|
|
585
|
-
end
|
|
586
|
-
end
|
|
587
658
|
end
|
|
588
659
|
|
|
589
660
|
def transform(model) = self.class.transform(model)
|
|
@@ -59,10 +59,11 @@ module Coradoc
|
|
|
59
59
|
# @return [Hash{String=>String}]
|
|
60
60
|
def attributes_from_block(block)
|
|
61
61
|
result = {}
|
|
62
|
-
|
|
62
|
+
data = CoreModel::FrontmatterBlock::Codec.to_hash(block)
|
|
63
|
+
return result if data.empty?
|
|
63
64
|
|
|
64
65
|
MAPPINGS.each do |(_, front_key, _)|
|
|
65
|
-
value =
|
|
66
|
+
value = data[front_key]
|
|
66
67
|
next if value.nil?
|
|
67
68
|
|
|
68
69
|
attr_name = front_key_to_attribute(front_key)
|
|
@@ -109,15 +109,18 @@ module Coradoc
|
|
|
109
109
|
|
|
110
110
|
# Collections
|
|
111
111
|
def visit_array(models)
|
|
112
|
+
# Fragments of one source line concatenate (an escape splits
|
|
113
|
+
# `foo\_bar` into three pieces); a soft line break joins
|
|
114
|
+
# with a space (soft-wrapped paragraph lines).
|
|
112
115
|
result = []
|
|
113
116
|
models.each_with_index do |item, idx|
|
|
114
117
|
text = visit(item)
|
|
115
118
|
next if text.empty?
|
|
116
119
|
|
|
117
120
|
result << text
|
|
118
|
-
next
|
|
121
|
+
next if idx == models.length - 1
|
|
119
122
|
|
|
120
|
-
result << ' ' if item.is_a?(Model::TextElement) && item.line_break
|
|
123
|
+
result << ' ' if item.is_a?(Model::TextElement) && item.line_break == "\n"
|
|
121
124
|
end
|
|
122
125
|
result.join
|
|
123
126
|
end
|
|
@@ -108,12 +108,22 @@ module Coradoc
|
|
|
108
108
|
DelimiterMapping::CHAR_TO_SEMANTIC[char] || :open
|
|
109
109
|
end
|
|
110
110
|
|
|
111
|
+
# Reused parser/transformer for inline re-parsing: Parsanol's
|
|
112
|
+
# VM program cache is keyed by atom identity, so a fresh parser
|
|
113
|
+
# per call recompiled the grammar every time (see also
|
|
114
|
+
# Transformer::TableCellBuilder).
|
|
115
|
+
def inline_reparse
|
|
116
|
+
@inline_reparse ||= [
|
|
117
|
+
Coradoc::AsciiDoc::Parser::Base.new,
|
|
118
|
+
Coradoc::AsciiDoc::Transformer.new
|
|
119
|
+
]
|
|
120
|
+
end
|
|
121
|
+
|
|
111
122
|
def parse_inline_text(raw_text)
|
|
112
123
|
return [] if raw_text.nil? || raw_text.to_s.strip.empty?
|
|
113
124
|
|
|
114
125
|
text = raw_text.to_s
|
|
115
|
-
parser =
|
|
116
|
-
transformer = Coradoc::AsciiDoc::Transformer.new
|
|
126
|
+
parser, transformer = inline_reparse
|
|
117
127
|
|
|
118
128
|
parsed = parser.text_any.parse(text)
|
|
119
129
|
result = transformer.apply({ text: parsed })
|
|
@@ -8,6 +8,7 @@ module Coradoc
|
|
|
8
8
|
autoload :ToCoreModel, "#{__dir__}/transform/to_core_model"
|
|
9
9
|
autoload :ToCoreModelRegistrations, "#{__dir__}/transform/to_core_model_registrations"
|
|
10
10
|
autoload :FromCoreModel, "#{__dir__}/transform/from_core_model"
|
|
11
|
+
autoload :ListBuilding, "#{__dir__}/transform/from_core_model/list_building"
|
|
11
12
|
autoload :FromCoreModelRegistrations, "#{__dir__}/transform/from_core_model_registrations"
|
|
12
13
|
autoload :TextExtractVisitor, "#{__dir__}/transform/text_extract_visitor"
|
|
13
14
|
autoload :InlineTransformVisitor, "#{__dir__}/transform/inline_transform_visitor"
|
|
@@ -33,7 +33,7 @@ module Coradoc
|
|
|
33
33
|
|
|
34
34
|
def extract(node)
|
|
35
35
|
case node
|
|
36
|
-
when Parsanol::Slice then line_of(node)
|
|
36
|
+
when Parsanol::Slice, Coradoc::AsciiDoc::Parser::PositionedString then line_of(node)
|
|
37
37
|
when Coradoc::AsciiDoc::Model::Base then node.source_line
|
|
38
38
|
when Hash then extract_from_hash(node)
|
|
39
39
|
when Array then extract_from_array(node)
|
|
@@ -13,6 +13,16 @@ module Coradoc
|
|
|
13
13
|
module TableCellBuilder
|
|
14
14
|
module_function
|
|
15
15
|
|
|
16
|
+
# Reused parser for cell-content re-parsing. Atoms are memoized
|
|
17
|
+
# per parser instance and Parsanol's VM program cache is keyed by
|
|
18
|
+
# atom identity — a fresh parser per cell recompiled the whole
|
|
19
|
+
# grammar for every cell (tables transformed ~50× slower than
|
|
20
|
+
# they parsed). Sequential reuse only; parse state lives in the
|
|
21
|
+
# per-call context, not the parser.
|
|
22
|
+
def inline_parser
|
|
23
|
+
@inline_parser ||= Coradoc::AsciiDoc::Parser::Base.new
|
|
24
|
+
end
|
|
25
|
+
|
|
16
26
|
# @param format [Hash, String, Object, nil] Cell format from parser
|
|
17
27
|
# @param content [Object] Cell content
|
|
18
28
|
# @return [Model::TableCell]
|
|
@@ -59,14 +69,15 @@ module Coradoc
|
|
|
59
69
|
# @param style [String, nil] 'a' (AsciiDoc), 'l' (literal), or nil
|
|
60
70
|
# @return [Array<Model::TextElement>]
|
|
61
71
|
def parse_inline_content(text, style = nil)
|
|
62
|
-
|
|
72
|
+
text = text.to_s.strip unless style == 'l'
|
|
73
|
+
return [Model::TextElement.new(content: '')] if text.empty?
|
|
63
74
|
|
|
64
75
|
return parse_block_content(text) if style == 'a'
|
|
65
76
|
return [Model::TextElement.new(content: text.to_s)] if style == 'l'
|
|
66
77
|
|
|
67
|
-
parser =
|
|
78
|
+
parser = inline_parser
|
|
68
79
|
begin
|
|
69
|
-
ast = parser.text_any.parse(text.to_s)
|
|
80
|
+
ast = Parser::TreeMaterializer.convert(parser.text_any.parse(text.to_s))
|
|
70
81
|
transformed = Transformer.new.apply(ast)
|
|
71
82
|
content_array = transformed.is_a?(Array) ? transformed : [transformed]
|
|
72
83
|
[Model::TextElement.new(content: content_array)]
|
|
@@ -81,7 +92,7 @@ module Coradoc
|
|
|
81
92
|
def parse_block_content(text)
|
|
82
93
|
return [Model::TextElement.new(content: '')] if text.nil? || text.to_s.strip.empty?
|
|
83
94
|
|
|
84
|
-
parser =
|
|
95
|
+
parser = inline_parser
|
|
85
96
|
text_str = text.to_s
|
|
86
97
|
|
|
87
98
|
if /^(\*+|-+|\d+\.)/m.match?(text_str)
|
|
@@ -89,14 +100,14 @@ module Coradoc
|
|
|
89
100
|
if list_match
|
|
90
101
|
list_text = list_match[1] + list_match[2]
|
|
91
102
|
begin
|
|
92
|
-
ast = parser.list.parse(list_text)
|
|
103
|
+
ast = Parser::TreeMaterializer.convert(parser.list.parse(list_text))
|
|
93
104
|
transformed = Transformer.new.apply(ast)
|
|
94
105
|
|
|
95
106
|
before_list = text_str[0, list_match.begin(1) - 1].strip
|
|
96
107
|
before_elements = []
|
|
97
108
|
unless before_list.empty?
|
|
98
109
|
begin
|
|
99
|
-
before_ast = parser.text_any.parse(before_list)
|
|
110
|
+
before_ast = Parser::TreeMaterializer.convert(parser.text_any.parse(before_list))
|
|
100
111
|
before_transformed = Transformer.new.apply(before_ast)
|
|
101
112
|
before_array = before_transformed.is_a?(Array) ? before_transformed : [before_transformed]
|
|
102
113
|
before_elements = [Model::TextElement.new(content: before_array)]
|
|
@@ -113,7 +124,7 @@ module Coradoc
|
|
|
113
124
|
end
|
|
114
125
|
|
|
115
126
|
begin
|
|
116
|
-
ast = parser.text_any.parse(text_str)
|
|
127
|
+
ast = Parser::TreeMaterializer.convert(parser.text_any.parse(text_str))
|
|
117
128
|
transformed = Transformer.new.apply(ast)
|
|
118
129
|
content_array = transformed.is_a?(Array) ? transformed : [transformed]
|
|
119
130
|
[Model::TextElement.new(content: content_array)]
|
data/lib/coradoc/asciidoc.rb
CHANGED
|
@@ -32,6 +32,9 @@ module Coradoc
|
|
|
32
32
|
autoload :Model, "#{__dir__}/asciidoc/model"
|
|
33
33
|
autoload :Parser, "#{__dir__}/asciidoc/parser"
|
|
34
34
|
autoload :Transformer, "#{__dir__}/asciidoc/transformer"
|
|
35
|
+
# Registration side effect: loading registers rules into Coradoc::Lint.registry.
|
|
36
|
+
autoload :Lint, "#{__dir__}/asciidoc/lint"
|
|
37
|
+
autoload :Formatter, "#{__dir__}/asciidoc/formatter"
|
|
35
38
|
autoload :Serializer, "#{__dir__}/asciidoc/serializer"
|
|
36
39
|
autoload :Transform, "#{__dir__}/asciidoc/transform"
|
|
37
40
|
autoload :Builder, "#{__dir__}/asciidoc/builder"
|
|
@@ -79,6 +82,15 @@ module Coradoc
|
|
|
79
82
|
Transform::ToCoreModel.transform(document)
|
|
80
83
|
end
|
|
81
84
|
|
|
85
|
+
# Canonical-format AsciiDoc text (#110): parse to the model
|
|
86
|
+
# tree, serialize, and normalize inter-block whitespace.
|
|
87
|
+
#
|
|
88
|
+
# @param text [String] AsciiDoc content
|
|
89
|
+
# @return [String] canonically formatted AsciiDoc
|
|
90
|
+
def format(text)
|
|
91
|
+
Formatter.call(text)
|
|
92
|
+
end
|
|
93
|
+
|
|
82
94
|
# Serialize a document model to AsciiDoc string
|
|
83
95
|
#
|
|
84
96
|
# @param document [Coradoc::AsciiDoc::Model::Document, Coradoc::CoreModel::Base]
|
|
@@ -50,6 +50,62 @@ module Coradoc
|
|
|
50
50
|
result
|
|
51
51
|
end
|
|
52
52
|
|
|
53
|
+
# Escape delimiter characters in plain-text content so the text
|
|
54
|
+
# survives a reparse (#92): `__x__`, `**x**`, `x~2~` and `` `x` ``
|
|
55
|
+
# would otherwise re-enter as formatting. Runs of two or more
|
|
56
|
+
# delimiters (`__`, `**`, `~~`) are dangerous anywhere; a single
|
|
57
|
+
# `*`, `_` or `~` only forms a constrained pair at a
|
|
58
|
+
# boundary/word transition; `^` and `` ` `` attach to words.
|
|
59
|
+
def self.escape_text_delimiters(text)
|
|
60
|
+
return '' if text.nil?
|
|
61
|
+
|
|
62
|
+
text.to_s.gsub(/(?<!\\)[`*_~^]+/) do |run|
|
|
63
|
+
match = Regexp.last_match
|
|
64
|
+
dangerous =
|
|
65
|
+
case run[0]
|
|
66
|
+
when '`'
|
|
67
|
+
true
|
|
68
|
+
when '^'
|
|
69
|
+
word_transition?(text, match)
|
|
70
|
+
else
|
|
71
|
+
run.length >= 2 || word_transition?(text, match)
|
|
72
|
+
end
|
|
73
|
+
dangerous ? run.chars.map { |c| "\\#{c}" }.join : run
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
WHITESPACE = /\s/
|
|
78
|
+
WORD_CHAR = /[[:word:]]/
|
|
79
|
+
PUNCT_CHAR = /[[:punct:]]/
|
|
80
|
+
private_constant :WHITESPACE, :WORD_CHAR, :PUNCT_CHAR
|
|
81
|
+
|
|
82
|
+
# A delimiter run at [start, stop) is dangerous when it can open
|
|
83
|
+
# a pair (boundary on its left, word char on its right) or close
|
|
84
|
+
# one (word char on its left, boundary-or-punctuation on its
|
|
85
|
+
# right — AsciiDoc lets a closing delimiter precede punctuation).
|
|
86
|
+
def self.word_transition?(text, match)
|
|
87
|
+
start = match.begin(0)
|
|
88
|
+
stop = match.end(0)
|
|
89
|
+
before = start.zero? ? nil : text[start - 1]
|
|
90
|
+
after = stop >= text.length ? nil : text[stop]
|
|
91
|
+
|
|
92
|
+
opens = boundary?(before) && word?(after)
|
|
93
|
+
closes = word?(before) && (boundary?(after) || punctuation?(after))
|
|
94
|
+
opens || closes
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def self.boundary?(char)
|
|
98
|
+
char.nil? || char.match?(WHITESPACE)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def self.word?(char)
|
|
102
|
+
!char.nil? && char.match?(WORD_CHAR)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def self.punctuation?(char)
|
|
106
|
+
!char.nil? && char.match?(PUNCT_CHAR)
|
|
107
|
+
end
|
|
108
|
+
|
|
53
109
|
# Unescape AsciiDoc characters in content
|
|
54
110
|
#
|
|
55
111
|
# @param content [String] The content to unescape
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: coradoc-adoc
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.0.
|
|
4
|
+
version: 2.0.36
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
@@ -41,16 +41,16 @@ dependencies:
|
|
|
41
41
|
name: parsanol
|
|
42
42
|
requirement: !ruby/object:Gem::Requirement
|
|
43
43
|
requirements:
|
|
44
|
-
- - "
|
|
44
|
+
- - "~>"
|
|
45
45
|
- !ruby/object:Gem::Version
|
|
46
|
-
version:
|
|
46
|
+
version: 1.3.123
|
|
47
47
|
type: :runtime
|
|
48
48
|
prerelease: false
|
|
49
49
|
version_requirements: !ruby/object:Gem::Requirement
|
|
50
50
|
requirements:
|
|
51
|
-
- - "
|
|
51
|
+
- - "~>"
|
|
52
52
|
- !ruby/object:Gem::Version
|
|
53
|
-
version:
|
|
53
|
+
version: 1.3.123
|
|
54
54
|
- !ruby/object:Gem::Dependency
|
|
55
55
|
name: rake
|
|
56
56
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -104,6 +104,8 @@ extra_rdoc_files: []
|
|
|
104
104
|
files:
|
|
105
105
|
- ".rspec"
|
|
106
106
|
- Rakefile
|
|
107
|
+
- grammar/coradoc-adoc.artifact.json
|
|
108
|
+
- grammar/coradoc-adoc.parg
|
|
107
109
|
- lib/coradoc/asciidoc.rb
|
|
108
110
|
- lib/coradoc/asciidoc/builder.rb
|
|
109
111
|
- lib/coradoc/asciidoc/builder/block_builder.rb
|
|
@@ -112,6 +114,12 @@ files:
|
|
|
112
114
|
- lib/coradoc/asciidoc/builder/list_builder.rb
|
|
113
115
|
- lib/coradoc/asciidoc/builder/text_builder.rb
|
|
114
116
|
- lib/coradoc/asciidoc/delimiter_mapping.rb
|
|
117
|
+
- lib/coradoc/asciidoc/formatter.rb
|
|
118
|
+
- lib/coradoc/asciidoc/lint.rb
|
|
119
|
+
- lib/coradoc/asciidoc/lint/document_title.rb
|
|
120
|
+
- lib/coradoc/asciidoc/lint/duplicate_ids.rb
|
|
121
|
+
- lib/coradoc/asciidoc/lint/empty_section.rb
|
|
122
|
+
- lib/coradoc/asciidoc/lint/heading_levels.rb
|
|
115
123
|
- lib/coradoc/asciidoc/model.rb
|
|
116
124
|
- lib/coradoc/asciidoc/model/admonition.rb
|
|
117
125
|
- lib/coradoc/asciidoc/model/anchorable.rb
|
|
@@ -229,12 +237,14 @@ files:
|
|
|
229
237
|
- lib/coradoc/asciidoc/parser/list.rb
|
|
230
238
|
- lib/coradoc/asciidoc/parser/metadata_detector.rb
|
|
231
239
|
- lib/coradoc/asciidoc/parser/paragraph.rb
|
|
240
|
+
- lib/coradoc/asciidoc/parser/positioned_string.rb
|
|
232
241
|
- lib/coradoc/asciidoc/parser/rule_dispatcher.rb
|
|
233
242
|
- lib/coradoc/asciidoc/parser/section.rb
|
|
234
243
|
- lib/coradoc/asciidoc/parser/stem.rb
|
|
235
244
|
- lib/coradoc/asciidoc/parser/table.rb
|
|
236
245
|
- lib/coradoc/asciidoc/parser/term.rb
|
|
237
246
|
- lib/coradoc/asciidoc/parser/text.rb
|
|
247
|
+
- lib/coradoc/asciidoc/parser/tree_materializer.rb
|
|
238
248
|
- lib/coradoc/asciidoc/reference_materializers.rb
|
|
239
249
|
- lib/coradoc/asciidoc/reference_materializers/navigation.rb
|
|
240
250
|
- lib/coradoc/asciidoc/serializer.rb
|
|
@@ -330,6 +340,7 @@ files:
|
|
|
330
340
|
- lib/coradoc/asciidoc/transform/element_transformers/other_transformer.rb
|
|
331
341
|
- lib/coradoc/asciidoc/transform/element_transformers/table_transformer.rb
|
|
332
342
|
- lib/coradoc/asciidoc/transform/from_core_model.rb
|
|
343
|
+
- lib/coradoc/asciidoc/transform/from_core_model/list_building.rb
|
|
333
344
|
- lib/coradoc/asciidoc/transform/from_core_model_registrations.rb
|
|
334
345
|
- lib/coradoc/asciidoc/transform/frontmatter_attribute_map.rb
|
|
335
346
|
- lib/coradoc/asciidoc/transform/inline_transform_visitor.rb
|