asciidoctor_vaped 0.1.0
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 +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +46 -0
- data/exe/asciidoctor_vaped +6 -0
- data/lib/asciidoctor_vaped/ast/document.rb +34 -0
- data/lib/asciidoctor_vaped/ast/element.rb +17 -0
- data/lib/asciidoctor_vaped/ast/node.rb +53 -0
- data/lib/asciidoctor_vaped/ast/text.rb +40 -0
- data/lib/asciidoctor_vaped/cli.rb +59 -0
- data/lib/asciidoctor_vaped/converter/base_converter.rb +68 -0
- data/lib/asciidoctor_vaped/converter/docbook.rb +116 -0
- data/lib/asciidoctor_vaped/converter/html.rb +119 -0
- data/lib/asciidoctor_vaped/converter/node.rb +92 -0
- data/lib/asciidoctor_vaped/converter.rb +6 -0
- data/lib/asciidoctor_vaped/error.rb +5 -0
- data/lib/asciidoctor_vaped/parser/blocks/admonition.rb +18 -0
- data/lib/asciidoctor_vaped/parser/blocks/common/base_node.rb +23 -0
- data/lib/asciidoctor_vaped/parser/blocks/common/blank_line.rb +19 -0
- data/lib/asciidoctor_vaped/parser/blocks/common/comment.rb +19 -0
- data/lib/asciidoctor_vaped/parser/blocks/delimited/delimited_node.rb +62 -0
- data/lib/asciidoctor_vaped/parser/blocks/delimited/example.rb +18 -0
- data/lib/asciidoctor_vaped/parser/blocks/delimited/listing.rb +14 -0
- data/lib/asciidoctor_vaped/parser/blocks/delimited/literal.rb +14 -0
- data/lib/asciidoctor_vaped/parser/blocks/delimited/open.rb +18 -0
- data/lib/asciidoctor_vaped/parser/blocks/delimited/passthrough.rb +14 -0
- data/lib/asciidoctor_vaped/parser/blocks/delimited/quote.rb +18 -0
- data/lib/asciidoctor_vaped/parser/blocks/delimited/sidebar.rb +18 -0
- data/lib/asciidoctor_vaped/parser/blocks/heading.rb +19 -0
- data/lib/asciidoctor_vaped/parser/blocks/lists/list_base.rb +29 -0
- data/lib/asciidoctor_vaped/parser/blocks/lists/list_item.rb +24 -0
- data/lib/asciidoctor_vaped/parser/blocks/lists/ordered_list.rb +16 -0
- data/lib/asciidoctor_vaped/parser/blocks/lists/unordered_list.rb +16 -0
- data/lib/asciidoctor_vaped/parser/blocks/metadata/caption.rb +17 -0
- data/lib/asciidoctor_vaped/parser/blocks/metadata/document_attribute.rb +18 -0
- data/lib/asciidoctor_vaped/parser/blocks/metadata/element_attributes.rb +86 -0
- data/lib/asciidoctor_vaped/parser/blocks/paragraph.rb +20 -0
- data/lib/asciidoctor_vaped/parser/blocks/tables/table.rb +58 -0
- data/lib/asciidoctor_vaped/parser/blocks/tables/table_cell.rb +13 -0
- data/lib/asciidoctor_vaped/parser/blocks/tables/table_row.rb +15 -0
- data/lib/asciidoctor_vaped/parser/blocks.rb +39 -0
- data/lib/asciidoctor_vaped/parser/context.rb +51 -0
- data/lib/asciidoctor_vaped/parser/inline.rb +60 -0
- data/lib/asciidoctor_vaped/parser/inlines/emphasis.rb +19 -0
- data/lib/asciidoctor_vaped/parser/inlines/link.rb +20 -0
- data/lib/asciidoctor_vaped/parser/inlines/monospace.rb +19 -0
- data/lib/asciidoctor_vaped/parser/inlines/strong.rb +19 -0
- data/lib/asciidoctor_vaped/parser/inlines/url.rb +19 -0
- data/lib/asciidoctor_vaped/parser.rb +72 -0
- data/lib/asciidoctor_vaped/reader.rb +47 -0
- data/lib/asciidoctor_vaped/version.rb +5 -0
- data/lib/asciidoctor_vaped.rb +52 -0
- data/sig/asciidoctor_vaped.rbs +53 -0
- metadata +96 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "common/base_node"
|
|
4
|
+
|
|
5
|
+
module AsciidoctorVaped
|
|
6
|
+
module Parser
|
|
7
|
+
module Blocks
|
|
8
|
+
class Admonition < BaseNode
|
|
9
|
+
PATTERN = /\A(NOTE|TIP|IMPORTANT|WARNING|CAUTION):\s+(.+)\z/
|
|
10
|
+
|
|
11
|
+
def parse(context)
|
|
12
|
+
name, text = context.reader.read.match(PATTERN).captures
|
|
13
|
+
context.append AST::Element.new(:admonition, attributes: { name: }, children: Inline.parse(text))
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module AsciidoctorVaped
|
|
4
|
+
module Parser
|
|
5
|
+
module Blocks
|
|
6
|
+
class BaseNode
|
|
7
|
+
def initialize(successor = nil)
|
|
8
|
+
@successor = successor
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def handle(context)
|
|
12
|
+
return parse(context) if match?(context)
|
|
13
|
+
|
|
14
|
+
@successor&.handle(context)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def match?(context)
|
|
18
|
+
context.reader.peek&.match?(self.class::PATTERN)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "base_node"
|
|
4
|
+
|
|
5
|
+
module AsciidoctorVaped
|
|
6
|
+
module Parser
|
|
7
|
+
module Blocks
|
|
8
|
+
class BlankLine < BaseNode
|
|
9
|
+
def match?(context)
|
|
10
|
+
context.reader.peek&.strip == ""
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def parse(context)
|
|
14
|
+
context.reader.skip_blank_lines
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "base_node"
|
|
4
|
+
|
|
5
|
+
module AsciidoctorVaped
|
|
6
|
+
module Parser
|
|
7
|
+
module Blocks
|
|
8
|
+
class Comment < BaseNode
|
|
9
|
+
def match?(context)
|
|
10
|
+
context.reader.peek&.start_with?("//")
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def parse(context)
|
|
14
|
+
context.reader.peek == "////" ? context.reader.read_delimited("////") : context.reader.read
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../common/base_node"
|
|
4
|
+
|
|
5
|
+
module AsciidoctorVaped
|
|
6
|
+
module Parser
|
|
7
|
+
module Blocks
|
|
8
|
+
class DelimitedNode < BaseNode
|
|
9
|
+
def match?(context)
|
|
10
|
+
delimiters.include?(context.reader.peek)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def parse(context)
|
|
14
|
+
lines = context.reader.read_delimited(context.reader.peek)
|
|
15
|
+
node = build_node(context, lines)
|
|
16
|
+
context.append node
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def delimiters
|
|
20
|
+
[delimiter]
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def attributes(context)
|
|
24
|
+
return {} unless admonition?(context)
|
|
25
|
+
|
|
26
|
+
{ name: context.pending_attributes[:style].to_s.upcase }
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def context_name(context)
|
|
30
|
+
admonition?(context) ? :admonition : default_context_name
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def build_node(context, lines)
|
|
36
|
+
text = lines.join("\n")
|
|
37
|
+
return AST::Element.new(context_name(context), attributes: attributes(context), children: parse_children(context, lines)) if compound?(context)
|
|
38
|
+
|
|
39
|
+
AST::Element.new(context_name(context), attributes: attributes(context), children: [Inline.text_node(text)])
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def parse_children(context, lines)
|
|
43
|
+
node = AST::Element.new(context_name(context), attributes: attributes(context))
|
|
44
|
+
Parser.parse_nodes context.nested(node, Reader.new(lines.join("\n")))
|
|
45
|
+
node.children
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def compound?(context)
|
|
49
|
+
admonition?(context)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def admonition?(context)
|
|
53
|
+
context.pending_attributes[:style]&.to_s&.match?(/\A(?:NOTE|TIP|IMPORTANT|WARNING|CAUTION)\z/i)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def default_context_name
|
|
57
|
+
raise NotImplementedError, "#{self.class} must implement #default_context_name"
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "delimited_node"
|
|
4
|
+
|
|
5
|
+
module AsciidoctorVaped
|
|
6
|
+
module Parser
|
|
7
|
+
module Blocks
|
|
8
|
+
class Example < DelimitedNode
|
|
9
|
+
def delimiter = "===="
|
|
10
|
+
def default_context_name = :example
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
def compound?(_context) = true
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "delimited_node"
|
|
4
|
+
|
|
5
|
+
module AsciidoctorVaped
|
|
6
|
+
module Parser
|
|
7
|
+
module Blocks
|
|
8
|
+
class Open < DelimitedNode
|
|
9
|
+
def delimiter = "--"
|
|
10
|
+
def default_context_name = :open
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
def compound?(_context) = true
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "delimited_node"
|
|
4
|
+
|
|
5
|
+
module AsciidoctorVaped
|
|
6
|
+
module Parser
|
|
7
|
+
module Blocks
|
|
8
|
+
class Passthrough < DelimitedNode
|
|
9
|
+
def delimiters = %w[+++ ++++]
|
|
10
|
+
def default_context_name = :pass
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "delimited_node"
|
|
4
|
+
|
|
5
|
+
module AsciidoctorVaped
|
|
6
|
+
module Parser
|
|
7
|
+
module Blocks
|
|
8
|
+
class Quote < DelimitedNode
|
|
9
|
+
def delimiter = "____"
|
|
10
|
+
def default_context_name = :quote
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
def compound?(_context) = true
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "delimited_node"
|
|
4
|
+
|
|
5
|
+
module AsciidoctorVaped
|
|
6
|
+
module Parser
|
|
7
|
+
module Blocks
|
|
8
|
+
class Sidebar < DelimitedNode
|
|
9
|
+
def delimiter = "****"
|
|
10
|
+
def default_context_name = :sidebar
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
def compound?(_context) = true
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "common/base_node"
|
|
4
|
+
|
|
5
|
+
module AsciidoctorVaped
|
|
6
|
+
module Parser
|
|
7
|
+
module Blocks
|
|
8
|
+
class Heading < BaseNode
|
|
9
|
+
PATTERN = /\A(=+)\s+(.+)\z/
|
|
10
|
+
|
|
11
|
+
def parse(context)
|
|
12
|
+
markers, title = context.reader.read.match(PATTERN).captures
|
|
13
|
+
level = [markers.length - 1, 1].max
|
|
14
|
+
context.open_section AST::Element.new(:section, attributes: { level: }, children: Inline.parse(title))
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../common/base_node"
|
|
4
|
+
require_relative "list_item"
|
|
5
|
+
|
|
6
|
+
module AsciidoctorVaped
|
|
7
|
+
module Parser
|
|
8
|
+
module Blocks
|
|
9
|
+
class ListBase < BaseNode
|
|
10
|
+
def match?(context)
|
|
11
|
+
context.reader.peek&.match?(pattern)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def parse(context)
|
|
15
|
+
list = AST::Element.new(list_context)
|
|
16
|
+
item_context = context.nested(list)
|
|
17
|
+
item_chain.handle(item_context) while match?(context)
|
|
18
|
+
context.append(list)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def item_chain
|
|
24
|
+
Blocks.chain([[ListItem, { pattern: }]])
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../common/base_node"
|
|
4
|
+
|
|
5
|
+
module AsciidoctorVaped
|
|
6
|
+
module Parser
|
|
7
|
+
module Blocks
|
|
8
|
+
class ListItem < BaseNode
|
|
9
|
+
def initialize(successor = nil, pattern:)
|
|
10
|
+
super(successor)
|
|
11
|
+
@pattern = pattern
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def match?(context)
|
|
15
|
+
context.reader.peek&.match?(@pattern)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def parse(context)
|
|
19
|
+
context.append AST::Element.new(:list_item, children: Inline.parse(context.reader.read.sub(@pattern, "")))
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "list_base"
|
|
4
|
+
|
|
5
|
+
module AsciidoctorVaped
|
|
6
|
+
module Parser
|
|
7
|
+
module Blocks
|
|
8
|
+
class OrderedList < ListBase
|
|
9
|
+
private
|
|
10
|
+
|
|
11
|
+
def list_context = :olist
|
|
12
|
+
def pattern = /\A\.\s+/
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "list_base"
|
|
4
|
+
|
|
5
|
+
module AsciidoctorVaped
|
|
6
|
+
module Parser
|
|
7
|
+
module Blocks
|
|
8
|
+
class UnorderedList < ListBase
|
|
9
|
+
private
|
|
10
|
+
|
|
11
|
+
def list_context = :ulist
|
|
12
|
+
def pattern = /\A[*-]\s+/
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../common/base_node"
|
|
4
|
+
|
|
5
|
+
module AsciidoctorVaped
|
|
6
|
+
module Parser
|
|
7
|
+
module Blocks
|
|
8
|
+
class Caption < BaseNode
|
|
9
|
+
PATTERN = /\A\.([^.\s].*)\z/
|
|
10
|
+
|
|
11
|
+
def parse(context)
|
|
12
|
+
context.pending_title = context.reader.read.match(PATTERN)[1]
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../common/base_node"
|
|
4
|
+
|
|
5
|
+
module AsciidoctorVaped
|
|
6
|
+
module Parser
|
|
7
|
+
module Blocks
|
|
8
|
+
class DocumentAttribute < BaseNode
|
|
9
|
+
PATTERN = /\A:([^:\s][^:]*):\s*(.*)\z/
|
|
10
|
+
|
|
11
|
+
def parse(context)
|
|
12
|
+
name, value = context.reader.read.match(PATTERN).captures
|
|
13
|
+
context.document.register_attribute(name, value)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../common/base_node"
|
|
4
|
+
require "strscan"
|
|
5
|
+
|
|
6
|
+
module AsciidoctorVaped
|
|
7
|
+
module Parser
|
|
8
|
+
module Blocks
|
|
9
|
+
class ElementAttributes < BaseNode
|
|
10
|
+
PATTERN = /\A\[(.+)\]\z/
|
|
11
|
+
|
|
12
|
+
def parse(context)
|
|
13
|
+
context.add_pending_attributes parse_attributes(context.reader.read.match(PATTERN)[1])
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def parse_attributes(value)
|
|
19
|
+
split_attributes(value).each_with_object({ positional: [] }) do |part, attributes|
|
|
20
|
+
parse_attribute(part, attributes)
|
|
21
|
+
end.then { |attributes| normalize_attributes(attributes) }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def split_attributes(value)
|
|
25
|
+
value.scan(/(?:"[^"]*"|'[^']*'|[^,])+/).map(&:strip).reject(&:empty?)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def parse_attribute(part, attributes)
|
|
29
|
+
name, value = part.split("=", 2)
|
|
30
|
+
return attributes[:positional] << unquote(part) unless value
|
|
31
|
+
|
|
32
|
+
assign_named_attribute(attributes, name.strip, unquote(value.strip))
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def assign_named_attribute(attributes, name, value)
|
|
36
|
+
key = normalize_name(name)
|
|
37
|
+
return parse_options(value, attributes) if key == :opts
|
|
38
|
+
|
|
39
|
+
attributes[key] = value
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def normalize_attributes(attributes)
|
|
43
|
+
positional = attributes.delete(:positional)
|
|
44
|
+
parse_shorthand(positional.shift, attributes)
|
|
45
|
+
attributes[:language] = positional.shift if attributes[:style] == :source && positional.any?
|
|
46
|
+
positional.each { |part| attributes[normalize_name(part)] = true }
|
|
47
|
+
attributes
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def parse_shorthand(value, attributes)
|
|
51
|
+
return unless value
|
|
52
|
+
|
|
53
|
+
scanner = StringScanner.new(value)
|
|
54
|
+
attributes[:style] = scanner.scan(/[^\s#.%]+/)&.to_sym
|
|
55
|
+
parse_shorthand_marks(scanner.rest, attributes)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def parse_shorthand_marks(value, attributes)
|
|
59
|
+
value.scan(/([#.%])([^#.%]+)/).each do |mark, name|
|
|
60
|
+
case mark
|
|
61
|
+
when "#" then attributes[:id] = name
|
|
62
|
+
when "." then append_role(attributes, name)
|
|
63
|
+
when "%" then attributes[normalize_name(name)] = true
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def append_role(attributes, name)
|
|
69
|
+
attributes[:role] = [attributes[:role], name].compact.join(" ")
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def parse_options(value, attributes)
|
|
73
|
+
value.split(",").map(&:strip).each { |option| attributes[normalize_name(option)] = true }
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def normalize_name(value)
|
|
77
|
+
value.tr("-", "_").to_sym
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def unquote(value)
|
|
81
|
+
value.sub(/\A(["'])(.*)\1\z/, "\\2")
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "common/base_node"
|
|
4
|
+
|
|
5
|
+
module AsciidoctorVaped
|
|
6
|
+
module Parser
|
|
7
|
+
module Blocks
|
|
8
|
+
class Paragraph < BaseNode
|
|
9
|
+
def match?(_context)
|
|
10
|
+
true
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def parse(context)
|
|
14
|
+
lines = context.reader.read_until_blank
|
|
15
|
+
context.append AST::Element.new(:paragraph, children: Inline.parse(lines.join("\n")))
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../delimited/delimited_node"
|
|
4
|
+
require_relative "table_row"
|
|
5
|
+
|
|
6
|
+
module AsciidoctorVaped
|
|
7
|
+
module Parser
|
|
8
|
+
module Blocks
|
|
9
|
+
class Table < DelimitedNode
|
|
10
|
+
def delimiter = "|==="
|
|
11
|
+
|
|
12
|
+
def parse(context)
|
|
13
|
+
table = AST::Element.new(:table)
|
|
14
|
+
rows(context.reader.read_delimited(delimiter)).each { |cells| table << TableRow.build(cells) }
|
|
15
|
+
context.append(table)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def rows(lines)
|
|
21
|
+
columns = nil
|
|
22
|
+
pending = []
|
|
23
|
+
rows = []
|
|
24
|
+
|
|
25
|
+
lines.each do |line|
|
|
26
|
+
cells = cells_for(line)
|
|
27
|
+
next if cells.empty?
|
|
28
|
+
|
|
29
|
+
if cells.length > 1
|
|
30
|
+
columns ||= cells.length
|
|
31
|
+
flush_pending(rows, pending, columns)
|
|
32
|
+
cells.each_slice(columns) { |row| rows << row }
|
|
33
|
+
elsif columns
|
|
34
|
+
pending.concat(cells)
|
|
35
|
+
flush_pending(rows, pending, columns)
|
|
36
|
+
else
|
|
37
|
+
rows << cells
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
rows << pending unless pending.empty?
|
|
42
|
+
rows
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def flush_pending(rows, pending, columns)
|
|
46
|
+
rows << pending.shift(columns) while pending.length >= columns
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def cells_for(line)
|
|
50
|
+
return [] if line.strip == ""
|
|
51
|
+
|
|
52
|
+
line.sub(/\A\|/, "").split(/\s+\|/).map(&:strip)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "table_cell"
|
|
4
|
+
|
|
5
|
+
module AsciidoctorVaped
|
|
6
|
+
module Parser
|
|
7
|
+
module Blocks
|
|
8
|
+
class TableRow
|
|
9
|
+
def self.build(cells)
|
|
10
|
+
AST::Element.new(:table_row, children: cells.map { |cell| TableCell.build(cell) })
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "blocks/common/base_node"
|
|
4
|
+
require_relative "blocks/common/blank_line"
|
|
5
|
+
require_relative "blocks/common/comment"
|
|
6
|
+
require_relative "blocks/metadata/document_attribute"
|
|
7
|
+
require_relative "blocks/metadata/caption"
|
|
8
|
+
require_relative "blocks/metadata/element_attributes"
|
|
9
|
+
require_relative "blocks/heading"
|
|
10
|
+
require_relative "blocks/delimited/delimited_node"
|
|
11
|
+
require_relative "blocks/delimited/listing"
|
|
12
|
+
require_relative "blocks/delimited/literal"
|
|
13
|
+
require_relative "blocks/delimited/example"
|
|
14
|
+
require_relative "blocks/delimited/quote"
|
|
15
|
+
require_relative "blocks/delimited/sidebar"
|
|
16
|
+
require_relative "blocks/delimited/open"
|
|
17
|
+
require_relative "blocks/delimited/passthrough"
|
|
18
|
+
require_relative "blocks/tables/table_cell"
|
|
19
|
+
require_relative "blocks/tables/table_row"
|
|
20
|
+
require_relative "blocks/tables/table"
|
|
21
|
+
require_relative "blocks/admonition"
|
|
22
|
+
require_relative "blocks/lists/list_item"
|
|
23
|
+
require_relative "blocks/lists/list_base"
|
|
24
|
+
require_relative "blocks/lists/unordered_list"
|
|
25
|
+
require_relative "blocks/lists/ordered_list"
|
|
26
|
+
require_relative "blocks/paragraph"
|
|
27
|
+
|
|
28
|
+
module AsciidoctorVaped
|
|
29
|
+
module Parser
|
|
30
|
+
module Blocks
|
|
31
|
+
def self.chain(handlers)
|
|
32
|
+
handlers.reverse.inject(nil) do |successor, handler|
|
|
33
|
+
handler, kwargs = handler
|
|
34
|
+
handler.new(successor, **(kwargs || {}))
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|