coradoc 0.3.0 → 1.0.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.
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