coradoc 0.2.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.docker/Dockerfile +1 -1
- data/.docker/docker-compose.yml +2 -2
- data/.editorconfig +15 -0
- data/CHANGELOG.md +4 -0
- data/README.md +4 -0
- data/Rakefile +10 -0
- data/coradoc.gemspec +11 -2
- data/exe/reverse_adoc +91 -0
- data/exe/w2a +72 -0
- data/lib/coradoc/document.rb +6 -6
- data/lib/coradoc/element/admonition.rb +8 -6
- data/lib/coradoc/element/attribute.rb +2 -2
- data/lib/coradoc/element/attribute_list.rb +94 -15
- data/lib/coradoc/element/audio.rb +14 -3
- data/lib/coradoc/element/author.rb +18 -14
- data/lib/coradoc/element/base.rb +69 -8
- data/lib/coradoc/element/block/core.rb +10 -6
- data/lib/coradoc/element/block/literal.rb +1 -1
- data/lib/coradoc/element/block/quote.rb +1 -1
- data/lib/coradoc/element/block/sourcecode.rb +2 -2
- data/lib/coradoc/element/break.rb +1 -1
- data/lib/coradoc/element/document_attributes.rb +6 -6
- data/lib/coradoc/element/header.rb +4 -2
- data/lib/coradoc/element/image/block_image.rb +13 -2
- data/lib/coradoc/element/image/core.rb +35 -5
- data/lib/coradoc/element/image/inline_image.rb +2 -2
- data/lib/coradoc/element/image.rb +0 -1
- data/lib/coradoc/element/inline/anchor.rb +4 -2
- data/lib/coradoc/element/inline/bold.rb +10 -4
- data/lib/coradoc/element/inline/cross_reference.rb +4 -2
- data/lib/coradoc/element/inline/hard_line_break.rb +1 -1
- data/lib/coradoc/element/inline/highlight.rb +12 -6
- data/lib/coradoc/element/inline/italic.rb +10 -4
- data/lib/coradoc/element/inline/link.rb +26 -10
- data/lib/coradoc/element/inline/monospace.rb +10 -4
- data/lib/coradoc/element/inline/quotation.rb +4 -1
- data/lib/coradoc/element/inline/subscript.rb +5 -2
- data/lib/coradoc/element/inline/superscript.rb +5 -2
- data/lib/coradoc/element/inline.rb +0 -1
- data/lib/coradoc/element/list/core.rb +10 -8
- data/lib/coradoc/element/list/definition.rb +19 -0
- data/lib/coradoc/element/list/ordered.rb +1 -1
- data/lib/coradoc/element/list/unordered.rb +1 -1
- data/lib/coradoc/element/list.rb +1 -1
- data/lib/coradoc/element/list_item.rb +9 -4
- data/lib/coradoc/element/list_item_definition.rb +32 -0
- data/lib/coradoc/element/paragraph.rb +5 -3
- data/lib/coradoc/element/revision.rb +20 -16
- data/lib/coradoc/element/section.rb +21 -4
- data/lib/coradoc/element/table.rb +36 -19
- data/lib/coradoc/element/text_element.rb +63 -17
- data/lib/coradoc/element/title.rb +27 -7
- data/lib/coradoc/element/video.rb +33 -6
- data/lib/coradoc/generator.rb +2 -2
- data/lib/coradoc/legacy_parser.rb +41 -41
- data/lib/coradoc/oscal.rb +2 -4
- data/lib/coradoc/parser/asciidoc/content.rb +15 -15
- data/lib/coradoc/parser/asciidoc/document_attributes.rb +1 -1
- data/lib/coradoc/parser/asciidoc/header.rb +6 -6
- data/lib/coradoc/parser/asciidoc/section.rb +1 -1
- data/lib/coradoc/reverse_adoc/LICENSE.txt +25 -0
- data/lib/coradoc/reverse_adoc/README.adoc +308 -0
- data/lib/coradoc/reverse_adoc/cleaner.rb +125 -0
- data/lib/coradoc/reverse_adoc/config.rb +73 -0
- data/lib/coradoc/reverse_adoc/converters/a.rb +47 -0
- data/lib/coradoc/reverse_adoc/converters/aside.rb +12 -0
- data/lib/coradoc/reverse_adoc/converters/audio.rb +25 -0
- data/lib/coradoc/reverse_adoc/converters/base.rb +104 -0
- data/lib/coradoc/reverse_adoc/converters/blockquote.rb +18 -0
- data/lib/coradoc/reverse_adoc/converters/br.rb +11 -0
- data/lib/coradoc/reverse_adoc/converters/bypass.rb +77 -0
- data/lib/coradoc/reverse_adoc/converters/code.rb +19 -0
- data/lib/coradoc/reverse_adoc/converters/div.rb +14 -0
- data/lib/coradoc/reverse_adoc/converters/dl.rb +55 -0
- data/lib/coradoc/reverse_adoc/converters/drop.rb +22 -0
- data/lib/coradoc/reverse_adoc/converters/em.rb +17 -0
- data/lib/coradoc/reverse_adoc/converters/figure.rb +21 -0
- data/lib/coradoc/reverse_adoc/converters/h.rb +38 -0
- data/lib/coradoc/reverse_adoc/converters/head.rb +19 -0
- data/lib/coradoc/reverse_adoc/converters/hr.rb +11 -0
- data/lib/coradoc/reverse_adoc/converters/ignore.rb +16 -0
- data/lib/coradoc/reverse_adoc/converters/img.rb +98 -0
- data/lib/coradoc/reverse_adoc/converters/li.rb +13 -0
- data/lib/coradoc/reverse_adoc/converters/mark.rb +15 -0
- data/lib/coradoc/reverse_adoc/converters/markup.rb +27 -0
- data/lib/coradoc/reverse_adoc/converters/math.rb +31 -0
- data/lib/coradoc/reverse_adoc/converters/ol.rb +60 -0
- data/lib/coradoc/reverse_adoc/converters/p.rb +19 -0
- data/lib/coradoc/reverse_adoc/converters/pass_through.rb +13 -0
- data/lib/coradoc/reverse_adoc/converters/pre.rb +51 -0
- data/lib/coradoc/reverse_adoc/converters/q.rb +12 -0
- data/lib/coradoc/reverse_adoc/converters/strong.rb +16 -0
- data/lib/coradoc/reverse_adoc/converters/sub.rb +18 -0
- data/lib/coradoc/reverse_adoc/converters/sup.rb +18 -0
- data/lib/coradoc/reverse_adoc/converters/table.rb +280 -0
- data/lib/coradoc/reverse_adoc/converters/td.rb +77 -0
- data/lib/coradoc/reverse_adoc/converters/text.rb +28 -0
- data/lib/coradoc/reverse_adoc/converters/th.rb +14 -0
- data/lib/coradoc/reverse_adoc/converters/tr.rb +18 -0
- data/lib/coradoc/reverse_adoc/converters/video.rb +25 -0
- data/lib/coradoc/reverse_adoc/converters.rb +53 -0
- data/lib/coradoc/reverse_adoc/errors.rb +10 -0
- data/lib/coradoc/reverse_adoc/html_converter.rb +150 -0
- data/lib/coradoc/reverse_adoc/plugin.rb +131 -0
- data/lib/coradoc/reverse_adoc/plugins/plateau.rb +174 -0
- data/lib/coradoc/reverse_adoc/postprocessor.rb +148 -0
- data/lib/coradoc/reverse_adoc.rb +30 -0
- data/lib/coradoc/transformer.rb +24 -14
- data/lib/coradoc/version.rb +1 -1
- data/lib/reverse_adoc.rb +20 -0
- metadata +184 -5
- data/lib/coradoc/element/inline/image.rb +0 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 71bfd2ac723d58ca75b591bceabcdf834abd9cbbf32e54b96352da21b8f15095
|
4
|
+
data.tar.gz: 1a7ea6bf80d64ab4c1349c948aa2aee9ed704dc36ddd07fb7cce78293dca86cd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 555800621a06ffafc07e03a5c2cdca1210de6369d524a606de51df78b1ee9b19aaba30d32d8a448347237e488362a59677781a02502a1d8891fb89aa1cc267f5
|
7
|
+
data.tar.gz: 22707b18c6ed99fb4c6127885d871875ed1fed2906d2d10dcdd5f4ed9bdd1b1bfe3f19fd092768ccc4d488bdb7e705aba9ba7ab948ceace9cc679f1ee733eddc
|
data/.docker/Dockerfile
CHANGED
data/.docker/docker-compose.yml
CHANGED
data/.editorconfig
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# EditorConfig is awesome: http://EditorConfig.org
|
2
|
+
|
3
|
+
# top-most EditorConfig file
|
4
|
+
root = true
|
5
|
+
|
6
|
+
# Unix-style newlines with a newline ending every file
|
7
|
+
[*]
|
8
|
+
charset = utf-8
|
9
|
+
end_of_line = lf
|
10
|
+
|
11
|
+
[{*.adoc,*.html,*.js,*.json,*.rake,*.rb,*.rf,*.yaml,*.yml,Rakefile,rakefile}]
|
12
|
+
indent_style = space
|
13
|
+
indent_size = 2
|
14
|
+
insert_final_newline = true
|
15
|
+
trim_trailing_whitespace = true
|
data/CHANGELOG.md
CHANGED
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/Rakefile
CHANGED
@@ -1,7 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "bundler/gem_tasks"
|
4
|
+
|
5
|
+
if File.exist?(".codeclimate")
|
6
|
+
ENV["CODECLIMATE_REPO_TOKEN"] = File.read(".codeclimate").strip
|
7
|
+
end
|
8
|
+
|
4
9
|
require "rspec/core/rake_task"
|
5
10
|
|
6
11
|
RSpec::Core::RakeTask.new(:spec)
|
7
12
|
task default: :spec
|
13
|
+
|
14
|
+
desc "Open an irb session preloaded with this library"
|
15
|
+
task :console do
|
16
|
+
sh "irb -Ilib -rcoradoc -rcoradoc/reverse_adoc"
|
17
|
+
end
|
data/coradoc.gemspec
CHANGED
@@ -28,11 +28,20 @@ Gem::Specification.new do |spec|
|
|
28
28
|
spec.require_paths = ["lib"]
|
29
29
|
spec.required_ruby_version = ">= 2.7.0"
|
30
30
|
|
31
|
-
spec.add_dependency "
|
31
|
+
spec.add_dependency "marcel", "~> 1.0.0"
|
32
|
+
spec.add_dependency "mathml2asciimath"
|
33
|
+
spec.add_dependency "nokogiri", "~> 1.13"
|
32
34
|
spec.add_dependency "oscal", "~> 0.1.1"
|
33
|
-
|
35
|
+
spec.add_dependency "parslet"
|
36
|
+
spec.add_dependency "premailer", "~> 1.11.0"
|
37
|
+
spec.add_dependency "word-to-markdown"
|
38
|
+
spec.add_development_dependency "codeclimate-test-reporter"
|
34
39
|
spec.add_development_dependency "pry"
|
35
40
|
spec.add_development_dependency "rake"
|
41
|
+
spec.add_development_dependency "redcarpet"
|
36
42
|
spec.add_development_dependency "rspec"
|
37
43
|
spec.add_development_dependency "rubocop"
|
44
|
+
spec.add_development_dependency "rubocop-performance"
|
45
|
+
spec.add_development_dependency "simplecov"
|
46
|
+
# spec.add_runtime_dependency "thor"
|
38
47
|
end
|
data/exe/reverse_adoc
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Usage: reverse_adoc [FILE]...
|
3
|
+
# Usage: cat FILE | reverse_adoc
|
4
|
+
require "rubygems"
|
5
|
+
require "bundler/setup"
|
6
|
+
|
7
|
+
require "coradoc/reverse_adoc"
|
8
|
+
require "optparse"
|
9
|
+
require "fileutils"
|
10
|
+
|
11
|
+
OptionParser.new do |opts|
|
12
|
+
opts.banner = "Usage: reverse_adoc [options] <file>"
|
13
|
+
opts.on("-m", "--mathml2asciimath", "Convert MathML to AsciiMath") do |_v|
|
14
|
+
Coradoc::ReverseAdoc.config.mathml2asciimath = true
|
15
|
+
end
|
16
|
+
|
17
|
+
opts.on("-oFILENAME", "--output=FILENAME", "Output file to write to") do |v|
|
18
|
+
Coradoc::ReverseAdoc.config.destination = File.expand_path(v)
|
19
|
+
# puts "output goes to #{Coradoc::ReverseAdoc.config.destination}"
|
20
|
+
end
|
21
|
+
|
22
|
+
opts.on("-e", "--external-images", "Export images if data URI") do |_v|
|
23
|
+
Coradoc::ReverseAdoc.config.external_images = true
|
24
|
+
end
|
25
|
+
|
26
|
+
opts.on("-u", "--unknown_tags [pass_through, drop, bypass, raise]",
|
27
|
+
"Unknown tag handling (default: pass_through)") do |v|
|
28
|
+
Coradoc::ReverseAdoc.config.unknown_tags = v
|
29
|
+
end
|
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
|
+
|
43
|
+
opts.on("-v", "--version", "Version information") do |_v|
|
44
|
+
puts "reverse_adoc: v#{Coradoc::ReverseAdoc::VERSION}"
|
45
|
+
exit
|
46
|
+
end
|
47
|
+
|
48
|
+
opts.on("-h", "--help", "Prints this help") do
|
49
|
+
puts opts
|
50
|
+
exit
|
51
|
+
end
|
52
|
+
end.parse!
|
53
|
+
|
54
|
+
if filename = ARGV.pop
|
55
|
+
input_content = IO.read(filename)
|
56
|
+
Coradoc::ReverseAdoc.config.sourcedir = File.dirname(File.expand_path(filename))
|
57
|
+
else
|
58
|
+
if Coradoc::ReverseAdoc.config.external_images
|
59
|
+
raise "The -e | --external-images feature cannot be used with STDIN input. Exiting."
|
60
|
+
end
|
61
|
+
|
62
|
+
input_content = ARGF.read
|
63
|
+
end
|
64
|
+
|
65
|
+
if Coradoc::ReverseAdoc.config.external_images && Coradoc::ReverseAdoc.config.destination.nil?
|
66
|
+
raise "The -e | --external-images feature must be used with -o | --output. Exiting."
|
67
|
+
end
|
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
|
+
|
73
|
+
# Read from STDIN
|
74
|
+
adoc_content = Coradoc::ReverseAdoc.convert(input_content)
|
75
|
+
|
76
|
+
# Print to STDOUT
|
77
|
+
unless Coradoc::ReverseAdoc.config.destination
|
78
|
+
puts adoc_content
|
79
|
+
exit
|
80
|
+
end
|
81
|
+
|
82
|
+
# Write output to Coradoc::ReverseAdoc.config.destination
|
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)
|
91
|
+
end
|
data/exe/w2a
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "rubygems"
|
5
|
+
require "bundler/setup"
|
6
|
+
|
7
|
+
require "word-to-markdown"
|
8
|
+
require "optparse"
|
9
|
+
require "coradoc/reverse_adoc"
|
10
|
+
|
11
|
+
ARGV.push("-h") if ARGV.empty?
|
12
|
+
|
13
|
+
OptionParser.new do |opts|
|
14
|
+
opts.banner = "Usage: w2a [options] <file>"
|
15
|
+
opts.on("-m", "--mathml2asciimath", "Convert MathML to AsciiMath") do |_v|
|
16
|
+
Coradoc::ReverseAdoc.config.mathml2asciimath = true
|
17
|
+
end
|
18
|
+
|
19
|
+
opts.on("-oFILENAME", "--output=FILENAME", "Output file to write to") do |v|
|
20
|
+
Coradoc::ReverseAdoc.config.destination = File.expand_path(v)
|
21
|
+
# puts "output goes to #{Coradoc::ReverseAdoc.config.destination}"
|
22
|
+
end
|
23
|
+
|
24
|
+
opts.on("-e", "--external-images", "Export images if data URI") do |_v|
|
25
|
+
Coradoc::ReverseAdoc.config.external_images = true
|
26
|
+
end
|
27
|
+
|
28
|
+
opts.on("-v", "--version", "Version information") do |_v|
|
29
|
+
puts "reverse_adoc: v#{Coradoc::ReverseAdoc::VERSION}"
|
30
|
+
puts "[dependency] WordToMarkdown: v#{WordToMarkdown::VERSION}"
|
31
|
+
if Gem.win_platform?
|
32
|
+
puts "[dependency] LibreOffice: version not available on Windows"
|
33
|
+
else
|
34
|
+
puts "[dependency] LibreOffice: v#{WordToMarkdown.soffice.version}"
|
35
|
+
end
|
36
|
+
exit
|
37
|
+
end
|
38
|
+
|
39
|
+
opts.on("-h", "--help", "Prints this help") do
|
40
|
+
puts opts
|
41
|
+
exit
|
42
|
+
end
|
43
|
+
end.parse!
|
44
|
+
|
45
|
+
filename = ARGV.pop
|
46
|
+
raise "Please provide an input file to process. Exiting." unless filename
|
47
|
+
|
48
|
+
if Coradoc::ReverseAdoc.config.external_images && Coradoc::ReverseAdoc.config.destination.nil?
|
49
|
+
raise "The -e | --external-images feature must be used with -o | --output. Exiting."
|
50
|
+
end
|
51
|
+
|
52
|
+
Coradoc::ReverseAdoc.config.sourcedir = Dir.mktmpdir
|
53
|
+
|
54
|
+
doc = WordToMarkdown.new(filename, Coradoc::ReverseAdoc.config.sourcedir)
|
55
|
+
# File.open("test.html", "w:UTF-8") { |f| f.write doc.document.html }
|
56
|
+
adoc_content = Coradoc::ReverseAdoc.convert(
|
57
|
+
Coradoc::ReverseAdoc.cleaner.preprocess_word_html(doc.document.html),
|
58
|
+
WordToMarkdown::REVERSE_MARKDOWN_OPTIONS,
|
59
|
+
)
|
60
|
+
# puts scrub_whitespace(doc.document.html)
|
61
|
+
|
62
|
+
# Print to STDOUT
|
63
|
+
unless Coradoc::ReverseAdoc.config.destination
|
64
|
+
puts adoc_content
|
65
|
+
exit
|
66
|
+
end
|
67
|
+
|
68
|
+
# Write output to Coradoc::ReverseAdoc.config.destination
|
69
|
+
FileUtils.mkdir_p(File.dirname(Coradoc::ReverseAdoc.config.destination))
|
70
|
+
File.open(Coradoc::ReverseAdoc.config.destination, "w") do |file|
|
71
|
+
file.write(adoc_content)
|
72
|
+
end
|
data/lib/coradoc/document.rb
CHANGED
@@ -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"
|
@@ -20,7 +21,6 @@ require_relative "element/break"
|
|
20
21
|
|
21
22
|
module Coradoc
|
22
23
|
class Document
|
23
|
-
|
24
24
|
class << self
|
25
25
|
def from_adoc(filename)
|
26
26
|
ast = Coradoc::Parser.parse(filename)
|
@@ -43,22 +43,22 @@ module Coradoc
|
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
|
-
|
46
|
+
new(
|
47
47
|
document_attributes: @document_attributes,
|
48
48
|
header: @header,
|
49
|
-
sections: @sections
|
49
|
+
sections: @sections,
|
50
50
|
)
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
54
54
|
attr_accessor :header, :document_attributes, :sections
|
55
55
|
|
56
|
-
def initialize(options={})
|
57
|
-
@document_attributes = options.fetch(:document_attributes,
|
56
|
+
def initialize(options = {})
|
57
|
+
@document_attributes = options.fetch(:document_attributes,
|
58
|
+
Coradoc::Element::DocumentAttributes.new)
|
58
59
|
@header = options.fetch(:header, Coradoc::Element::Header.new(""))
|
59
60
|
@sections = options.fetch(:sections, [])
|
60
61
|
self
|
61
62
|
end
|
62
|
-
|
63
63
|
end
|
64
64
|
end
|
@@ -1,11 +1,13 @@
|
|
1
1
|
module Coradoc
|
2
|
-
|
3
|
-
|
2
|
+
module Element
|
3
|
+
class Admonition < Base
|
4
|
+
attr_accessor :type, :content, :line_break
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
def initialize(content, type, options = {})
|
7
|
+
@content = content
|
8
|
+
@type = type.downcase.to_sym
|
9
|
+
@line_break = options.fetch(:line_break, "")
|
10
|
+
end
|
9
11
|
end
|
10
12
|
end
|
11
13
|
end
|
@@ -1,45 +1,124 @@
|
|
1
1
|
module Coradoc
|
2
2
|
module Element
|
3
|
-
class AttributeList
|
4
|
-
|
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
|
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
|
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
|
-
|
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
|
-
|
32
|
-
|
33
|
-
|
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
|
-
|
78
|
+
v = "\"#{v.join(',')}\""
|
38
79
|
end
|
39
|
-
[k.to_s, "=",
|
80
|
+
[k.to_s, "=", v].join
|
40
81
|
end.join(",")
|
41
|
-
|
42
|
-
|
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,13 +1,15 @@
|
|
1
1
|
module Coradoc
|
2
2
|
module Element
|
3
|
-
class Audio
|
4
|
-
|
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
|
8
10
|
@id = options.fetch(:id, nil)
|
9
11
|
@anchor = Inline::Anchor.new(@id) if @id
|
10
|
-
@src = options.fetch(:src,
|
12
|
+
@src = options.fetch(:src, "")
|
11
13
|
@attributes = options.fetch(:attributes, [])
|
12
14
|
end
|
13
15
|
|
@@ -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,20 +1,24 @@
|
|
1
1
|
module Coradoc
|
2
|
-
|
3
|
-
|
2
|
+
module Element
|
3
|
+
class Author < Base
|
4
|
+
attr_accessor :email, :last_name, :first_name
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
6
|
+
declare_children :email, :last_name, :first_name
|
7
|
+
|
8
|
+
def initialize(first_name, last_name, email, middle_name = nil)
|
9
|
+
@first_name = first_name
|
10
|
+
@last_name = last_name
|
11
|
+
@email = email
|
12
|
+
@middle_name = middle_name
|
13
|
+
end
|
11
14
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
def to_adoc
|
16
|
+
adoc = "#{@first_name} "
|
17
|
+
adoc << "#{@middle_name} " if @middle_name
|
18
|
+
adoc << @last_name.to_s
|
19
|
+
adoc << " <#{@email}>" if @email
|
20
|
+
adoc
|
21
|
+
end
|
18
22
|
end
|
19
23
|
end
|
20
24
|
end
|
data/lib/coradoc/element/base.rb
CHANGED
@@ -1,17 +1,78 @@
|
|
1
1
|
module Coradoc
|
2
2
|
module Element
|
3
3
|
class Base
|
4
|
-
#
|
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
|
-
|
7
|
-
# @document_attributes = extract_document_attributes(asciidoc)
|
8
|
-
# end
|
17
|
+
simplified = simplify_block_content(i.contents)
|
9
18
|
|
10
|
-
|
19
|
+
if simplified && !simplified.empty?
|
20
|
+
collected_content << simplified
|
21
|
+
end
|
22
|
+
else
|
23
|
+
collected_content << i
|
24
|
+
end
|
25
|
+
end
|
11
26
|
|
12
|
-
|
13
|
-
|
14
|
-
|
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
|
15
76
|
end
|
16
77
|
end
|
17
78
|
end
|