coradoc 0.3.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -0
  3. data/exe/reverse_adoc +24 -3
  4. data/lib/coradoc/document.rb +1 -0
  5. data/lib/coradoc/element/admonition.rb +2 -2
  6. data/lib/coradoc/element/attribute.rb +2 -2
  7. data/lib/coradoc/element/attribute_list.rb +94 -15
  8. data/lib/coradoc/element/audio.rb +13 -2
  9. data/lib/coradoc/element/author.rb +4 -2
  10. data/lib/coradoc/element/base.rb +70 -7
  11. data/lib/coradoc/element/block/core.rb +8 -4
  12. data/lib/coradoc/element/block/quote.rb +1 -1
  13. data/lib/coradoc/element/break.rb +1 -1
  14. data/lib/coradoc/element/document_attributes.rb +6 -6
  15. data/lib/coradoc/element/header.rb +4 -2
  16. data/lib/coradoc/element/image/block_image.rb +13 -2
  17. data/lib/coradoc/element/image/core.rb +34 -5
  18. data/lib/coradoc/element/image/inline_image.rb +2 -2
  19. data/lib/coradoc/element/inline/anchor.rb +4 -2
  20. data/lib/coradoc/element/inline/bold.rb +9 -4
  21. data/lib/coradoc/element/inline/cross_reference.rb +4 -2
  22. data/lib/coradoc/element/inline/hard_line_break.rb +1 -1
  23. data/lib/coradoc/element/inline/highlight.rb +11 -6
  24. data/lib/coradoc/element/inline/italic.rb +9 -4
  25. data/lib/coradoc/element/inline/link.rb +22 -6
  26. data/lib/coradoc/element/inline/monospace.rb +9 -4
  27. data/lib/coradoc/element/inline/quotation.rb +3 -1
  28. data/lib/coradoc/element/inline/subscript.rb +4 -2
  29. data/lib/coradoc/element/inline/superscript.rb +4 -2
  30. data/lib/coradoc/element/list/core.rb +9 -6
  31. data/lib/coradoc/element/list/definition.rb +19 -0
  32. data/lib/coradoc/element/list/ordered.rb +1 -1
  33. data/lib/coradoc/element/list/unordered.rb +1 -1
  34. data/lib/coradoc/element/list.rb +1 -0
  35. data/lib/coradoc/element/list_item.rb +8 -3
  36. data/lib/coradoc/element/list_item_definition.rb +32 -0
  37. data/lib/coradoc/element/paragraph.rb +4 -2
  38. data/lib/coradoc/element/revision.rb +4 -2
  39. data/lib/coradoc/element/section.rb +21 -4
  40. data/lib/coradoc/element/table.rb +27 -10
  41. data/lib/coradoc/element/text_element.rb +48 -8
  42. data/lib/coradoc/element/title.rb +26 -6
  43. data/lib/coradoc/element/video.rb +32 -5
  44. data/lib/coradoc/reverse_adoc/README.adoc +14 -8
  45. data/lib/coradoc/reverse_adoc/cleaner.rb +20 -8
  46. data/lib/coradoc/reverse_adoc/config.rb +35 -16
  47. data/lib/coradoc/reverse_adoc/converters/a.rb +17 -12
  48. data/lib/coradoc/reverse_adoc/converters/aside.rb +0 -4
  49. data/lib/coradoc/reverse_adoc/converters/audio.rb +0 -4
  50. data/lib/coradoc/reverse_adoc/converters/base.rb +48 -44
  51. data/lib/coradoc/reverse_adoc/converters/blockquote.rb +2 -11
  52. data/lib/coradoc/reverse_adoc/converters/br.rb +0 -4
  53. data/lib/coradoc/reverse_adoc/converters/bypass.rb +0 -4
  54. data/lib/coradoc/reverse_adoc/converters/code.rb +5 -42
  55. data/lib/coradoc/reverse_adoc/converters/div.rb +0 -4
  56. data/lib/coradoc/reverse_adoc/converters/dl.rb +55 -0
  57. data/lib/coradoc/reverse_adoc/converters/em.rb +5 -43
  58. data/lib/coradoc/reverse_adoc/converters/figure.rb +0 -4
  59. data/lib/coradoc/reverse_adoc/converters/h.rb +0 -4
  60. data/lib/coradoc/reverse_adoc/converters/head.rb +0 -4
  61. data/lib/coradoc/reverse_adoc/converters/hr.rb +0 -4
  62. data/lib/coradoc/reverse_adoc/converters/img.rb +21 -16
  63. data/lib/coradoc/reverse_adoc/converters/li.rb +0 -4
  64. data/lib/coradoc/reverse_adoc/converters/mark.rb +5 -11
  65. data/lib/coradoc/reverse_adoc/converters/markup.rb +27 -0
  66. data/lib/coradoc/reverse_adoc/converters/ol.rb +0 -4
  67. data/lib/coradoc/reverse_adoc/converters/p.rb +0 -4
  68. data/lib/coradoc/reverse_adoc/converters/pre.rb +0 -4
  69. data/lib/coradoc/reverse_adoc/converters/q.rb +0 -4
  70. data/lib/coradoc/reverse_adoc/converters/strong.rb +5 -41
  71. data/lib/coradoc/reverse_adoc/converters/sub.rb +6 -4
  72. data/lib/coradoc/reverse_adoc/converters/sup.rb +7 -5
  73. data/lib/coradoc/reverse_adoc/converters/table.rb +215 -4
  74. data/lib/coradoc/reverse_adoc/converters/td.rb +1 -7
  75. data/lib/coradoc/reverse_adoc/converters/text.rb +1 -38
  76. data/lib/coradoc/reverse_adoc/converters/tr.rb +0 -4
  77. data/lib/coradoc/reverse_adoc/converters/video.rb +0 -4
  78. data/lib/coradoc/reverse_adoc/converters.rb +21 -0
  79. data/lib/coradoc/reverse_adoc/html_converter.rb +109 -20
  80. data/lib/coradoc/reverse_adoc/plugin.rb +131 -0
  81. data/lib/coradoc/reverse_adoc/plugins/plateau.rb +174 -0
  82. data/lib/coradoc/reverse_adoc/postprocessor.rb +148 -0
  83. data/lib/coradoc/reverse_adoc.rb +3 -0
  84. data/lib/coradoc/version.rb +1 -1
  85. data/lib/reverse_adoc.rb +1 -1
  86. metadata +8 -3
  87. data/lib/coradoc/element/inline/image.rb +0 -26
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c721a05ddb985a8bde74747c3c39e47818beca7525b13115794673394d46b2ab
4
- data.tar.gz: f45600c3b4b85877a97904f38a03d5161b0ff83e7259ad6f54da5e1711ac9e46
3
+ metadata.gz: 71bfd2ac723d58ca75b591bceabcdf834abd9cbbf32e54b96352da21b8f15095
4
+ data.tar.gz: 1a7ea6bf80d64ab4c1349c948aa2aee9ed704dc36ddd07fb7cce78293dca86cd
5
5
  SHA512:
6
- metadata.gz: 0063e9145b1a8e46046c7397b4278a480535ee119624842fad72a8e9280def9de4af7c8335dc5f64b5a118040a8e178af800b27879d8c335a00d37d574b34bbb
7
- data.tar.gz: 8f02e79025a941ab47c8f359a7638129ce2e7a7aa80352a38bb9004540efdbadff8cd3c0427641004ab834a346f7d39676b9ace64e47f62dcbb9c0b0a357d2ce
6
+ metadata.gz: 555800621a06ffafc07e03a5c2cdca1210de6369d524a606de51df78b1ee9b19aaba30d32d8a448347237e488362a59677781a02502a1d8891fb89aa1cc267f5
7
+ data.tar.gz: 22707b18c6ed99fb4c6127885d871875ed1fed2906d2d10dcdd5f4ed9bdd1b1bfe3f19fd092768ccc4d488bdb7e705aba9ba7ab948ceace9cc679f1ee733eddc
data/README.md CHANGED
@@ -66,4 +66,8 @@ Coradoc::Parser.parse(sample_asciidoc)
66
66
 
67
67
  This interface will return the abstract syntax tree.
68
68
 
69
+ ### Converting from HTML to AsciiDoc (reverse_adoc)
70
+
71
+ See: [reverse_adoc README](https://github.com/metanorma/coradoc/blob/main/lib/coradoc/reverse_adoc/README.adoc)
72
+
69
73
  [sandi-metz]: http://robots.thoughtbot.com/post/50655960596/sandi-metz-rules-for-developers
data/exe/reverse_adoc CHANGED
@@ -28,6 +28,18 @@ OptionParser.new do |opts|
28
28
  Coradoc::ReverseAdoc.config.unknown_tags = v
29
29
  end
30
30
 
31
+ opts.on("-r", "--require RUBYMODULE", "Require additional Ruby file") do |v|
32
+ require v
33
+ end
34
+
35
+ opts.on("--track-time", "Track time spent on each step") do
36
+ Coradoc::ReverseAdoc.config.track_time = true
37
+ end
38
+
39
+ opts.on("--split-sections LEVEL", "Split sections up to LEVEL") do |i|
40
+ Coradoc::ReverseAdoc.config.split_sections = i.to_i
41
+ end
42
+
31
43
  opts.on("-v", "--version", "Version information") do |_v|
32
44
  puts "reverse_adoc: v#{Coradoc::ReverseAdoc::VERSION}"
33
45
  exit
@@ -54,6 +66,10 @@ if Coradoc::ReverseAdoc.config.external_images && Coradoc::ReverseAdoc.config.de
54
66
  raise "The -e | --external-images feature must be used with -o | --output. Exiting."
55
67
  end
56
68
 
69
+ if Coradoc::ReverseAdoc.config.split_sections && Coradoc::ReverseAdoc.config.destination.nil?
70
+ raise "The --split_sections feature must be used with -o | --output. Exiting."
71
+ end
72
+
57
73
  # Read from STDIN
58
74
  adoc_content = Coradoc::ReverseAdoc.convert(input_content)
59
75
 
@@ -64,7 +80,12 @@ unless Coradoc::ReverseAdoc.config.destination
64
80
  end
65
81
 
66
82
  # Write output to Coradoc::ReverseAdoc.config.destination
67
- FileUtils.mkdir_p(File.dirname(Coradoc::ReverseAdoc.config.destination))
68
- File.open(Coradoc::ReverseAdoc.config.destination, "w") do |file|
69
- file.write(adoc_content)
83
+ adoc_content = {nil => adoc_content} unless adoc_content.is_a? Hash
84
+
85
+ adoc_content.each do |file, content|
86
+ destination = Coradoc::ReverseAdoc.config.destination
87
+ destdir = File.dirname(destination)
88
+ filename = file ? "#{destdir}/#{file}" : destination
89
+ FileUtils.mkdir_p(File.dirname(filename))
90
+ File.write(filename, content)
70
91
  end
@@ -1,3 +1,4 @@
1
+ require_relative "element/base"
1
2
  require_relative "element/title"
2
3
  require_relative "element/block"
3
4
  require_relative "element/section"
@@ -1,7 +1,7 @@
1
1
  module Coradoc
2
2
  module Element
3
- class Admonition
4
- attr_reader :type, :content, :line_break
3
+ class Admonition < Base
4
+ attr_accessor :type, :content, :line_break
5
5
 
6
6
  def initialize(content, type, options = {})
7
7
  @content = content
@@ -1,7 +1,7 @@
1
1
  module Coradoc
2
2
  module Element
3
- class Attribute
4
- attr_reader :key, :value
3
+ class Attribute < Base
4
+ attr_accessor :key, :value
5
5
 
6
6
  def initialize(key, value, _options = {})
7
7
  @key = key.to_s
@@ -1,45 +1,124 @@
1
1
  module Coradoc
2
2
  module Element
3
- class AttributeList
4
- attr_reader :positional, :named
3
+ class AttributeList < Base
4
+ attr_accessor :positional, :named, :rejected_positional, :rejected_named
5
+
6
+ declare_children :positional, :named
5
7
 
6
8
  def initialize(*positional, **named)
7
9
  @positional = positional || []
8
10
  @named = named || {}
11
+ @rejected_positional = []
12
+ @rejected_named = []
9
13
  end
10
14
 
11
- def add_positional(attr)
12
- @positional << attr
15
+ def add_positional(*attr)
16
+ @positional += attr
13
17
  end
14
18
 
15
19
  def add_named(name, value)
16
20
  @named[name] = value
17
21
  end
18
22
 
23
+ def any?
24
+ !empty?
25
+ end
26
+
19
27
  def empty?
20
28
  @positional.empty? && @named.empty?
21
29
  end
22
30
 
23
- def to_adoc
31
+ def validate_attr(attr, matcher)
32
+ matcher === attr
33
+ end
34
+
35
+ def validate_positional(validators)
36
+ @positional.each_with_index do |value, i|
37
+ # TODO: Decide what to do with this value
38
+ _positional_name = validators[i][0]
39
+
40
+ validator = validators[i][1]
41
+
42
+ unless validator && validate_attr(value, validator)
43
+ @positional[i] = nil
44
+ @rejected_positional << [i, value]
45
+ end
46
+ end
47
+
48
+ @positional.pop while !@positional.empty? && @positional.last.nil?
49
+ end
50
+
51
+ def validate_named(validators)
52
+ @named.each_with_index do |(name, value), i|
53
+ name = name.to_sym
54
+ validator = validators[name]
55
+
56
+ unless validator && validate_attr(value, validator)
57
+ @named.delete(name)
58
+ @rejected_named << [name, value]
59
+ end
60
+ end
61
+ end
62
+
63
+ def to_adoc(show_empty = true)
24
64
  return "[]" if [@positional, @named].all?(:empty?)
25
65
 
26
- adoc = ""
27
- adoc << @positional.join(",") if @positional.any?
66
+ adoc = +""
67
+ if !@positional.empty?
68
+ adoc << @positional.map { |p| [nil, ""].include?(p) ? '""' : p }.join(",")
69
+ end
28
70
  adoc << "," if @positional.any? && @named.any?
29
71
  adoc << @named.map do |k, v|
30
72
  if v.is_a?(String)
31
- v2 = v.to_s
32
- v2 = v2.include?("\"") ? v2.gsub("\"", "\\\"") : v2
33
- if v2.include?(" ") || v2.include?(",") || v2.include?("\"")
34
- v2 = "\"#{v2}\""
73
+ v = v.gsub("\"", "\\\"")
74
+ if v.include?(" ") || v.include?(",") || v.include?('"')
75
+ v = "\"#{v}\""
35
76
  end
36
77
  elsif v.is_a?(Array)
37
- v2 = "\"#{v.join(',')}\""
78
+ v = "\"#{v.join(',')}\""
38
79
  end
39
- [k.to_s, "=", v2].join
80
+ [k.to_s, "=", v].join
40
81
  end.join(",")
41
- adoc = "[#{adoc}]" if @positional.any? || @named.any?
42
- adoc
82
+
83
+ if !empty? || (empty? && show_empty)
84
+ "[#{adoc}]"
85
+ elsif empty? && !show_empty
86
+ adoc
87
+ end
88
+ end
89
+
90
+ module Matchers
91
+ def one(*args)
92
+ One.new(*args)
93
+ end
94
+
95
+ class One
96
+ def initialize(*possibilities)
97
+ @possibilities = possibilities
98
+ end
99
+
100
+ def ===(other)
101
+ @possibilities.any? { |i| i === other }
102
+ end
103
+ end
104
+
105
+ def many(*args)
106
+ Many.new(*args)
107
+ end
108
+
109
+ # TODO: Find a way to only reject some values but not all?
110
+ class Many
111
+ def initialize(*possibilities)
112
+ @possibilities = possibilities
113
+ end
114
+
115
+ def ===(other)
116
+ other = other.split(",") if other.is_a?(String)
117
+
118
+ other.is_a?(Array) &&
119
+ other.all? { |i| @possibilities.any? { |p| p === i } }
120
+ end
121
+ end
43
122
  end
44
123
  end
45
124
  end
@@ -1,7 +1,9 @@
1
1
  module Coradoc
2
2
  module Element
3
- class Audio
4
- attr_reader :id, :title, :src, :options, :anchor
3
+ class Audio < Base
4
+ attr_accessor :id, :title, :src, :options, :anchor, :attributes
5
+
6
+ declare_children :id, :title, :anchor, :attributes
5
7
 
6
8
  def initialize(title, options = {})
7
9
  @title = title
@@ -17,6 +19,15 @@ module Coradoc
17
19
  attrs = @attributes.empty? ? "\[\]" : @attributes.to_adoc
18
20
  [anchor, title, "audio::", @src, attrs].join("")
19
21
  end
22
+
23
+ extend AttributeList::Matchers
24
+ VALIDATORS_NAMED = {
25
+ title: String,
26
+ start: Integer,
27
+ end: Integer,
28
+ options: many("nofollow", "noopener", "inline", "interactive"),
29
+ opts: many("nofollow", "noopener", "inline", "interactive"),
30
+ }
20
31
  end
21
32
  end
22
33
  end
@@ -1,7 +1,9 @@
1
1
  module Coradoc
2
2
  module Element
3
- class Author
4
- attr_reader :email, :last_name, :first_name
3
+ class Author < Base
4
+ attr_accessor :email, :last_name, :first_name
5
+
6
+ declare_children :email, :last_name, :first_name
5
7
 
6
8
  def initialize(first_name, last_name, email, middle_name = nil)
7
9
  @first_name = first_name
@@ -1,15 +1,78 @@
1
1
  module Coradoc
2
2
  module Element
3
3
  class Base
4
- # attr_reader :document_attributes
4
+ # The idea here, is that HTML content generators may often introduce
5
+ # a lot of unnecessary markup, that only makes sense in the HTML+CSS
6
+ # context. The idea is that certain cases can be simplified, making it
7
+ # so that the result is equivalent, but much simpler, allowing us to
8
+ # generate a nicer AsciiDoc syntax for those cases.
9
+ def simplify_block_content(content)
10
+ content = Array(content)
11
+ collected_content = []
12
+ content.each do |i|
13
+ case i
14
+ when Coradoc::Element::Section
15
+ return content unless i.safe_to_collapse?
5
16
 
6
- # def initialize(asciidoc)
7
- # @document_attributes = extract_document_attributes(asciidoc)
8
- # end
17
+ simplified = simplify_block_content(i.contents)
9
18
 
10
- # def extract_document_attributes(asciidoc)
11
- # @document_attributes ||= DocumentAttributes.new(asciidoc.attributes)
12
- # end
19
+ if simplified && !simplified.empty?
20
+ collected_content << simplified
21
+ end
22
+ else
23
+ collected_content << i
24
+ end
25
+ end
26
+
27
+ collected_content = collected_content.compact
28
+
29
+ # We can safely do this optimization only if there's just one other
30
+ # element inside this structure.
31
+ if collected_content.length <= 1
32
+ collected_content
33
+ else
34
+ content
35
+ end
36
+ end
37
+
38
+ def self.declare_children(*children)
39
+ @children = (@children || []).dup + children
40
+ end
41
+
42
+ def self.visit(element, &block)
43
+ element = yield element, :pre
44
+ element = if element.respond_to? :visit
45
+ element.visit(&block)
46
+ elsif element.is_a? Array
47
+ element.map { |child| visit(child, &block) }.flatten.compact
48
+ elsif element.is_a? Hash
49
+ element.to_h do |k, v|
50
+ [visit(k, &block), visit(v, &block)]
51
+ end
52
+ else
53
+ element
54
+ end
55
+ yield element, :post
56
+ end
57
+
58
+ def self.children_accessors
59
+ @children || []
60
+ end
61
+
62
+ def children_accessors
63
+ self.class.children_accessors
64
+ end
65
+
66
+ def visit(&block)
67
+ children_accessors.each do |accessor|
68
+ child = public_send(accessor)
69
+ result = self.class.visit(child, &block)
70
+ if result != child
71
+ public_send(:"#{accessor}=", result)
72
+ end
73
+ end
74
+ self
75
+ end
13
76
  end
14
77
  end
15
78
  end
@@ -3,15 +3,17 @@ require_relative "../inline/anchor"
3
3
  module Coradoc
4
4
  module Element
5
5
  module Block
6
- class Core
7
- attr_reader :title, :lines, :attributes, :lang, :id
6
+ class Core < Base
7
+ attr_accessor :title, :lines, :attributes, :lang, :id
8
+
9
+ declare_children :title, :lines, :attributes, :lang, :id
8
10
 
9
11
  def initialize(title, options = {})
10
12
  @title = title
11
13
  @lines = options.fetch(:lines, [])
12
14
  @type_str = options.fetch(:type, nil)
13
15
  @delimiter = options.fetch(:delimiter, "")
14
- @attributes = options.fetch(:attributes, {})
16
+ @attributes = options.fetch(:attributes, AttributeList.new)
15
17
  @lang = options.fetch(:lang, nil)
16
18
  @id = options.fetch(:id, nil)
17
19
  @anchor = @id.nil? ? nil : Inline::Anchor.new(@id)
@@ -33,7 +35,9 @@ module Coradoc
33
35
  end
34
36
 
35
37
  def gen_attributes
36
- @attributes.nil? ? "" : "#{@attributes.to_adoc}\n"
38
+ attrs = @attributes.to_adoc(false)
39
+ return "#{attrs}\n" if !attrs.empty?
40
+ ""
37
41
  end
38
42
 
39
43
  def gen_delimiter
@@ -4,7 +4,7 @@ module Coradoc
4
4
  class Quote < Core
5
5
  def initialize(title, options = {})
6
6
  @title = title
7
- @attributes = options.fetch(:attributes, {})
7
+ @attributes = options.fetch(:attributes, AttributeList.new)
8
8
  @lines = options.fetch(:lines, [])
9
9
  @delimiter_char = "_"
10
10
  @delimiter_len = options.fetch(:delimiter_len, 4)
@@ -1,7 +1,7 @@
1
1
  module Coradoc
2
2
  module Element
3
3
  module Break
4
- class ThematicBreak
4
+ class ThematicBreak < Base
5
5
  def to_adoc
6
6
  "\n* * *\n"
7
7
  end
@@ -1,7 +1,9 @@
1
1
  module Coradoc
2
2
  module Element
3
- class DocumentAttributes
4
- attr_reader :data
3
+ class DocumentAttributes < Base
4
+ attr_accessor :data
5
+
6
+ declare_children :data
5
7
 
6
8
  def initialize(data = {}, options = {})
7
9
  @data = data
@@ -9,10 +11,8 @@ module Coradoc
9
11
  end
10
12
 
11
13
  def to_hash
12
- Hash.new.tap do |hash|
13
- data.each do |attribute|
14
- hash[attribute.key.to_s] = attribute.value.to_s.gsub("'", "")
15
- end
14
+ data.to_h do |attribute|
15
+ [attribute.key.to_s, attribute.value.to_s.gsub("'", "")]
16
16
  end
17
17
  end
18
18
  end
@@ -1,7 +1,9 @@
1
1
  module Coradoc
2
2
  module Element
3
- class Header
4
- attr_reader :title, :author, :revision
3
+ class Header < Base
4
+ attr_accessor :title, :author, :revision
5
+
6
+ declare_children :title
5
7
 
6
8
  def initialize(title, options = {})
7
9
  @title = title
@@ -2,10 +2,21 @@ module Coradoc
2
2
  module Element
3
3
  module Image
4
4
  class BlockImage < Core
5
- def initialize(title, id, src, options = ())
6
- super(title, id, src, options)
5
+ def initialize(title, id, src, options = {})
6
+ super
7
7
  @colons = "::"
8
8
  end
9
+
10
+ def validate_named
11
+ @attributes.validate_named(VALIDATORS_NAMED, VALIDATORS_NAMED_BLOCK)
12
+ end
13
+
14
+ extend AttributeList::Matchers
15
+ VALIDATORS_NAMED_BLOCK = {
16
+ caption: String,
17
+ align: one("left", "center", "right"),
18
+ float: one("left", "right"),
19
+ }
9
20
  end
10
21
  end
11
22
  end
@@ -1,24 +1,53 @@
1
1
  module Coradoc
2
2
  module Element
3
3
  module Image
4
- class Core
5
- attr_reader :title, :id, :src, :attributes
4
+ class Core < Base
5
+ attr_accessor :title, :id, :src, :attributes
6
6
 
7
- def initialize(title, id, src, options = ())
7
+ declare_children :id, :src, :title, :attributes
8
+
9
+ def initialize(title, id, src, options = {})
8
10
  @title = title
9
11
  @id = id
10
12
  @anchor = @id.nil? ? nil : Coradoc::Element::Inline::Anchor.new(@id)
11
13
  @src = src
12
- @attributes = options.fetch(:attributes, [])
14
+ @attributes = options.fetch(:attributes, AttributeList.new)
13
15
  @title = options.fetch(:title, nil)
16
+ if @attributes.any?
17
+ @attributes.validate_positional(VALIDATORS_POSITIONAL)
18
+ @attributes.validate_named(VALIDATORS_NAMED)
19
+ end
14
20
  end
15
21
 
16
22
  def to_adoc
17
23
  anchor = @anchor.nil? ? "" : "#{@anchor.to_adoc}\n"
18
24
  title = ".#{@title}\n" unless @title.to_s.empty?
19
- attrs = @attributes.empty? ? "\[\]" : @attributes.to_adoc
25
+ attrs = @attributes.to_adoc
20
26
  [anchor, title, "image", @colons, @src, attrs].join("")
21
27
  end
28
+
29
+ extend AttributeList::Matchers
30
+ VALIDATORS_POSITIONAL = [
31
+ [:alt, String],
32
+ [:width, Integer],
33
+ [:height, Integer],
34
+ ]
35
+
36
+ VALIDATORS_NAMED = {
37
+ id: String,
38
+ alt: String,
39
+ fallback: String,
40
+ title: String,
41
+ width: Integer,
42
+ height: Integer,
43
+ link: String, # change to that URI regexp
44
+ window: String,
45
+ scale: Integer,
46
+ scaledwidth: /\A[0-9]{1,2}%\z/,
47
+ pdfwidth: /\A[0-9]+vw\z/,
48
+ role: many(/.*/, "left", "right", "th", "thumb", "related", "rel"),
49
+ opts: many("nofollow", "noopener", "inline", "interactive"),
50
+ }
22
51
  end
23
52
  end
24
53
  end
@@ -2,8 +2,8 @@ module Coradoc
2
2
  module Element
3
3
  module Image
4
4
  class InlineImage < Core
5
- def initialize(title, id, src, options = ())
6
- super(title, id, src, options)
5
+ def initialize(title, id, src, options = {})
6
+ super
7
7
  @colons = ":"
8
8
  end
9
9
  end
@@ -1,8 +1,10 @@
1
1
  module Coradoc
2
2
  module Element
3
3
  module Inline
4
- class Anchor
5
- attr_reader :id
4
+ class Anchor < Base
5
+ attr_accessor :id
6
+
7
+ declare_children :id
6
8
 
7
9
  def initialize(id)
8
10
  @id = id
@@ -1,18 +1,23 @@
1
1
  module Coradoc
2
2
  module Element
3
3
  module Inline
4
- class Bold
4
+ class Bold < Base
5
5
  attr_accessor :content, :unconstrained
6
6
 
7
- def initialize(content, unconstrained = true)
7
+ declare_children :content
8
+
9
+ def initialize(content, unconstrained: true)
8
10
  @content = content
9
11
  @unconstrained = unconstrained
10
12
  end
11
13
 
12
14
  def to_adoc
13
15
  content = Coradoc::Generator.gen_adoc(@content)
14
- doubled = @unconstrained ? "*" : ""
15
- "#{doubled}*#{content.strip}*#{doubled}#{content[/\s+$/]}"
16
+ if @unconstrained
17
+ "**#{content}**"
18
+ else
19
+ "*#{content}*"
20
+ end
16
21
  end
17
22
  end
18
23
  end
@@ -1,8 +1,10 @@
1
1
  module Coradoc
2
2
  module Element
3
3
  module Inline
4
- class CrossReference
5
- attr_reader :href, :name
4
+ class CrossReference < Base
5
+ attr_accessor :href, :name
6
+
7
+ declare_children :href, :name
6
8
 
7
9
  def initialize(href, name = nil)
8
10
  @href = href
@@ -1,7 +1,7 @@
1
1
  module Coradoc
2
2
  module Element
3
3
  module Inline
4
- class HardLineBreak
4
+ class HardLineBreak < Base
5
5
  def to_adoc
6
6
  " +\n"
7
7
  end
@@ -1,18 +1,23 @@
1
1
  module Coradoc
2
2
  module Element
3
3
  module Inline
4
- class Highlight
5
- attr_accessor :content
4
+ class Highlight < Base
5
+ attr_accessor :content, :unconstrained
6
6
 
7
- def initialize(content, constrained = true)
7
+ declare_children :content
8
+
9
+ def initialize(content, unconstrained: true)
8
10
  @content = content
9
- @constrained = constrained
11
+ @unconstrained = unconstrained
10
12
  end
11
13
 
12
14
  def to_adoc
13
15
  content = Coradoc::Generator.gen_adoc(@content)
14
- doubled = @constrained ? "" : "#"
15
- "#{content[/^\s*/]}#{doubled}##{content.strip}##{doubled}#{content[/\s*$/]}"
16
+ if @unconstrained
17
+ "###{content}##"
18
+ else
19
+ "##{content}#"
20
+ end
16
21
  end
17
22
  end
18
23
  end