booklab-sml 0.1.0 → 0.2.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 +4 -4
- data/Rakefile +14 -12
- data/lib/booklab/sml/base.rb +3 -32
- data/lib/booklab/sml/config.rb +8 -0
- data/lib/booklab/sml/renderer.rb +41 -0
- data/lib/booklab/sml/rules/base.rb +32 -0
- data/lib/booklab/sml/rules/blockquote.rb +18 -0
- data/lib/booklab/sml/rules/br.rb +13 -0
- data/lib/booklab/sml/rules/codeblock.rb +25 -0
- data/lib/booklab/sml/rules/file.rb +31 -0
- data/lib/booklab/sml/rules/heading.rb +16 -0
- data/lib/booklab/sml/rules/hr.rb +13 -0
- data/lib/booklab/sml/rules/image.rb +25 -0
- data/lib/booklab/sml/rules/link.rb +18 -0
- data/lib/booklab/sml/rules/list.rb +58 -0
- data/lib/booklab/sml/rules/math.rb +19 -0
- data/lib/booklab/sml/rules/paragraph.rb +15 -0
- data/lib/booklab/sml/rules/plantuml.rb +17 -0
- data/lib/booklab/sml/rules/root.rb +14 -0
- data/lib/booklab/sml/rules/span.rb +16 -0
- data/lib/booklab/sml/rules/span_with_mark.rb +44 -0
- data/lib/booklab/sml/rules/table.rb +16 -0
- data/lib/booklab/sml/rules/td.rb +27 -0
- data/lib/booklab/sml/rules/text.rb +13 -0
- data/lib/booklab/sml/rules/tr.rb +17 -0
- data/lib/booklab/sml/rules.rb +22 -0
- data/lib/booklab/sml/utils.rb +43 -0
- data/lib/booklab/sml/version.rb +3 -1
- data/lib/booklab-sml.rb +9 -1
- metadata +55 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f40ffbae208235a1dfafa968aa9816198027175749c37b846133c4c90d1e0579
|
4
|
+
data.tar.gz: e47ff7a87045859d6d78ad591651e1e0c92f2ca3d9f745c1c71cd47971910962
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2826b2f592c86982df5694b1fb8deaf788d0639facc2bd67a956b7028f1621d73dcc1c686df6b54676afbfa27029c53b0f220a7a224e0e898060e289d9723381
|
7
|
+
data.tar.gz: 50fe6bdd5bbfbb946b3c543f2359f34c82b43f68b9b091c3517b25a50cf54cbab75018087e38dbc0e53c08f37c3d888a74f9ce40e698aac9ce8f1a382170e670
|
data/Rakefile
CHANGED
@@ -1,26 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
begin
|
2
|
-
require
|
4
|
+
require "bundler/setup"
|
3
5
|
rescue LoadError
|
4
|
-
puts
|
6
|
+
puts "You must `gem install bundler` and `bundle install` to run rake tasks"
|
5
7
|
end
|
6
8
|
|
7
|
-
require
|
9
|
+
require "rdoc/task"
|
8
10
|
|
9
11
|
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
-
rdoc.rdoc_dir =
|
11
|
-
rdoc.title =
|
12
|
-
rdoc.options <<
|
13
|
-
rdoc.rdoc_files.include(
|
14
|
-
rdoc.rdoc_files.include(
|
12
|
+
rdoc.rdoc_dir = "rdoc"
|
13
|
+
rdoc.title = "Jsonml"
|
14
|
+
rdoc.options << "--line-numbers"
|
15
|
+
rdoc.rdoc_files.include("README.md")
|
16
|
+
rdoc.rdoc_files.include("lib/**/*.rb")
|
15
17
|
end
|
16
18
|
|
17
|
-
require
|
19
|
+
require "bundler/gem_tasks"
|
18
20
|
|
19
|
-
require
|
21
|
+
require "rake/testtask"
|
20
22
|
|
21
23
|
Rake::TestTask.new(:test) do |t|
|
22
|
-
t.libs <<
|
23
|
-
t.pattern =
|
24
|
+
t.libs << "test"
|
25
|
+
t.pattern = "test/**/*_test.rb"
|
24
26
|
t.verbose = false
|
25
27
|
end
|
26
28
|
|
data/lib/booklab/sml/base.rb
CHANGED
@@ -4,38 +4,9 @@ require "yaml"
|
|
4
4
|
|
5
5
|
module BookLab
|
6
6
|
module SML
|
7
|
-
def self.parse(src,
|
8
|
-
|
9
|
-
|
7
|
+
def self.parse(src, options = {})
|
8
|
+
renderer = Renderer.new(src, options)
|
9
|
+
renderer.to_html
|
10
10
|
end
|
11
|
-
|
12
|
-
private
|
13
|
-
|
14
|
-
# base code from: https://github.com/blambeau/jsonml-rb
|
15
|
-
def self.parse_node(src, out = StringIO.new)
|
16
|
-
has_attrs = src[1].is_a?(Hash)
|
17
|
-
first_child = has_attrs ? 2 : 1
|
18
|
-
|
19
|
-
case src
|
20
|
-
when Array
|
21
|
-
out << "<#{src.first}"
|
22
|
-
out << " " << attrs2html(src[1]) if has_attrs
|
23
|
-
out << ">"
|
24
|
-
src[first_child..-1].each { |child| parse_node(child, out) }
|
25
|
-
out << "</#{src.first}>"
|
26
|
-
when String
|
27
|
-
out << src
|
28
|
-
else
|
29
|
-
raise "Unexpected node `#{src}`"
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def self.attrs2html(attrs)
|
34
|
-
attrs.each_pair.map { |pair| attr2html(*pair) }.join(" ")
|
35
|
-
end
|
36
|
-
|
37
|
-
def self.attr2html(key, value)
|
38
|
-
%(#{key}="#{value}")
|
39
|
-
end
|
40
11
|
end
|
41
12
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext"
|
4
|
+
|
5
|
+
module BookLab::SML
|
6
|
+
class Renderer
|
7
|
+
include BookLab::SML::Utils
|
8
|
+
|
9
|
+
attr_accessor :sml, :config
|
10
|
+
|
11
|
+
def initialize(sml, options)
|
12
|
+
@sml = sml
|
13
|
+
@config = Config.new
|
14
|
+
@config.plantuml_service_host = options[:plantuml_service_host]
|
15
|
+
@config.mathjax_service_host = options[:mathjax_service_host]
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_html
|
19
|
+
node_to_html(YAML.load(sml))
|
20
|
+
end
|
21
|
+
|
22
|
+
def node_to_html(node, opts = {})
|
23
|
+
opts[:renderer] = self
|
24
|
+
|
25
|
+
rule = BookLab::SML::Rules::find_by_node(node)
|
26
|
+
rule.to_html(node, opts)
|
27
|
+
end
|
28
|
+
|
29
|
+
def children_to_html(node)
|
30
|
+
return node if node.is_a?(String)
|
31
|
+
|
32
|
+
children = self.class.get_children(node)
|
33
|
+
children.each_with_index.map do |child, idx|
|
34
|
+
prev_node = idx > 0 ? children[idx - 1] : nil
|
35
|
+
next_node = idx < children.length ? children[idx + 1] : nil
|
36
|
+
|
37
|
+
node_to_html(child)
|
38
|
+
end.join("")
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "escape_utils"
|
4
|
+
|
5
|
+
module BookLab::SML::Rules
|
6
|
+
class SyntaxError < Exception; end
|
7
|
+
|
8
|
+
class Base
|
9
|
+
include BookLab::SML::Utils
|
10
|
+
|
11
|
+
class << self
|
12
|
+
include EscapeUtils
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
def self.match?(node)
|
17
|
+
false
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.to_html(node, opts = {})
|
21
|
+
children = opts[:renderer].children_to_html(node)
|
22
|
+
tag = tag_name(node)
|
23
|
+
%(<#{tag}>#{children}</#{tag}>)
|
24
|
+
end
|
25
|
+
|
26
|
+
protected
|
27
|
+
|
28
|
+
def self.styleize(style)
|
29
|
+
style.map { |k, v| "#{k}: #{v};" }.join(" ")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BookLab::SML::Rules
|
4
|
+
class Blockquote < Base
|
5
|
+
def self.match?(node)
|
6
|
+
tag_name(node) == "blockquote"
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.to_html(node, opts = {})
|
10
|
+
renderer = opts[:renderer]
|
11
|
+
attrs = attributes(node)
|
12
|
+
|
13
|
+
children = renderer.children_to_html(node)
|
14
|
+
|
15
|
+
%(<blockquote>#{children}</blockquote>)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rouge"
|
4
|
+
require "rouge/plugins/redcarpet"
|
5
|
+
|
6
|
+
module BookLab::SML::Rules
|
7
|
+
class Codeblock < Base
|
8
|
+
class << self
|
9
|
+
include Rouge::Plugins::Redcarpet
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.match?(node)
|
13
|
+
tag_name(node) == "codeblock"
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.to_html(node, opts = {})
|
17
|
+
attrs = attributes(node)
|
18
|
+
|
19
|
+
language = attrs[:language]
|
20
|
+
code = attrs[:code]
|
21
|
+
|
22
|
+
block_code(code, language)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BookLab::SML::Rules
|
4
|
+
class File < Base
|
5
|
+
class << self
|
6
|
+
include ActiveSupport::NumberHelper
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.match?(node)
|
10
|
+
tag_name(node) == "file"
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.to_html(node, opts = {})
|
14
|
+
attrs = attributes(node)
|
15
|
+
|
16
|
+
return attrs[:name] if attrs[:src].blank?
|
17
|
+
|
18
|
+
humanize_size = number_to_human_size(attrs[:size] || 0)
|
19
|
+
|
20
|
+
out = <<~HTML
|
21
|
+
<a class="attachment-file" title="#{attrs[:name]}" target="_blank" href="#{attrs[:src]}">
|
22
|
+
<span class="icon-box"><i class="fas fa-file"></i></span>
|
23
|
+
<span class="filename">#{escape_html(attrs[:name])}</span>
|
24
|
+
<span class="filesize">#{escape_html(humanize_size)}</span>
|
25
|
+
</a>
|
26
|
+
HTML
|
27
|
+
|
28
|
+
out
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BookLab::SML::Rules
|
4
|
+
class Heading < Base
|
5
|
+
def self.match?(node)
|
6
|
+
%w[h1 h2 h3 h4 h5 h6].include?(tag_name(node))
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.to_html(node, opts = {})
|
10
|
+
renderer = opts[:renderer]
|
11
|
+
title = renderer.children_to_html(node)
|
12
|
+
heading_tag = tag_name(node)
|
13
|
+
%(<#{heading_tag}>#{title}</#{heading_tag}>)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BookLab::SML::Rules
|
4
|
+
class Image < Base
|
5
|
+
def self.match?(node)
|
6
|
+
tag_name(node) == "image"
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.to_html(node, opts = {})
|
10
|
+
attrs = attributes(node)
|
11
|
+
|
12
|
+
return attrs[:name] if attrs[:src].blank?
|
13
|
+
|
14
|
+
html_attrs = {
|
15
|
+
src: attrs[:src],
|
16
|
+
alt: attrs[:name],
|
17
|
+
width: attrs[:width],
|
18
|
+
height: attrs[:height]
|
19
|
+
}
|
20
|
+
|
21
|
+
attr_html = html_attrs.map { |k, v| v.present? ? %(#{k}="#{v}") : nil }.compact.join(" ")
|
22
|
+
%(<img #{attr_html}>)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BookLab::SML::Rules
|
4
|
+
class Link < Base
|
5
|
+
def self.match?(node)
|
6
|
+
tag_name(node) == "link"
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.to_html(node, opts = {})
|
10
|
+
renderer = opts[:renderer]
|
11
|
+
attrs = attributes(node)
|
12
|
+
name = renderer.children_to_html(node)
|
13
|
+
return name if attrs[:href].blank?
|
14
|
+
|
15
|
+
%(<a href="#{attrs[:href]}" title="#{attrs[:title]}">#{name}</a>)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BookLab::SML::Rules
|
4
|
+
class List < Base
|
5
|
+
def self.match?(node)
|
6
|
+
tag_name(node) == "list"
|
7
|
+
end
|
8
|
+
|
9
|
+
INDENT_PX = 8
|
10
|
+
|
11
|
+
def self.to_html(node, opts = {})
|
12
|
+
renderer = opts[:renderer]
|
13
|
+
attrs = attributes(node)
|
14
|
+
children = renderer.children_to_html(node)
|
15
|
+
|
16
|
+
# Normal paragraph data
|
17
|
+
text_align = attrs[:align] || "left"
|
18
|
+
indent = attrs[:indent]
|
19
|
+
text_indent = indent && indent[:firstline]
|
20
|
+
indent_left = indent ? indent[:left] : 0
|
21
|
+
|
22
|
+
# List style
|
23
|
+
nid = attrs[:nid]
|
24
|
+
list_type = attrs[:type] || "bulleted"
|
25
|
+
level = attrs[:level] || 1
|
26
|
+
num = attrs[:num] || 1
|
27
|
+
pstyle = attrs[:pstyle] || "paragraph"
|
28
|
+
|
29
|
+
wrap_tag = attrs[:type] == "bulleted" ? "ul" : "ol"
|
30
|
+
item_tag = "li"
|
31
|
+
|
32
|
+
case pstyle
|
33
|
+
when "paragraph" then item_tag = "p"
|
34
|
+
when "heading1" then item_tag = "h1"
|
35
|
+
when "heading2" then item_tag = "h2"
|
36
|
+
else item_tag = "p"
|
37
|
+
end
|
38
|
+
|
39
|
+
style = {
|
40
|
+
"text-align": text_align,
|
41
|
+
"text-indent": text_indent ? "#{4 * INDENT_PX}px" : "0px",
|
42
|
+
"padding-left": "#{indent_left * INDENT_PX}px"
|
43
|
+
}.map { |k, v| "#{k}: #{v};" }.join(" ")
|
44
|
+
|
45
|
+
outs = []
|
46
|
+
if opts[:prev] && tag_name(opts[:prev]) != "list"
|
47
|
+
outs << %(<#{wrap_tag} style="#{style}">)
|
48
|
+
end
|
49
|
+
|
50
|
+
outs << %(<li>#{children}</li>)
|
51
|
+
|
52
|
+
if opts[:next] && tag_name(opts[:next]) != "list"
|
53
|
+
outs << "</#{wrap_tag}>"
|
54
|
+
end
|
55
|
+
outs.join("")
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BookLab::SML::Rules
|
4
|
+
class Math < Base
|
5
|
+
def self.match?(node)
|
6
|
+
tag_name(node) == "math"
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.to_html(node, opts = {})
|
10
|
+
renderer = opts[:renderer]
|
11
|
+
attrs = attributes(node)
|
12
|
+
|
13
|
+
svg_code = URI::encode(attrs[:code])
|
14
|
+
src = "#{renderer.config.mathjax_service_host}/svg?tex=#{svg_code}"
|
15
|
+
|
16
|
+
%(<img class="tex-image" src="#{src}">)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BookLab::SML::Rules
|
4
|
+
class Paragraph < Base
|
5
|
+
def self.match?(node)
|
6
|
+
tag_name(node) == "p"
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.to_html(node, opts = {})
|
10
|
+
renderer = opts[:renderer]
|
11
|
+
children = renderer.children_to_html(node)
|
12
|
+
%(<p>#{children}</p>)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BookLab::SML::Rules
|
4
|
+
class Plantuml < Base
|
5
|
+
def self.match?(node)
|
6
|
+
tag_name(node) == "plantuml"
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.to_html(node, opts = {})
|
10
|
+
attrs = attributes(node)
|
11
|
+
renderer = opts[:renderer]
|
12
|
+
|
13
|
+
svg_code = URI::encode((attrs[:code] || "").strip)
|
14
|
+
%(<img src="#{renderer.config.plantuml_service_host}/svg/#{svg_code}" class="plantuml-image" />)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BookLab::SML::Rules
|
4
|
+
class Root < Base
|
5
|
+
def self.match?(node)
|
6
|
+
tag_name(node) == "root"
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.to_html(node, opts = {})
|
10
|
+
renderer = opts[:renderer]
|
11
|
+
renderer.children_to_html(node)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BookLab::SML::Rules
|
4
|
+
class Span < Base
|
5
|
+
def self.match?(node)
|
6
|
+
return false unless tag_name(node) == "span"
|
7
|
+
attrs = attributes(node)
|
8
|
+
attrs[:t] == 1
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.to_html(node, opts = {})
|
12
|
+
renderer = opts[:renderer]
|
13
|
+
renderer.children_to_html(node)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BookLab::SML::Rules
|
4
|
+
class SpanWithMark < Base
|
5
|
+
MARKS = {
|
6
|
+
cd: ["<code>", "</code>"],
|
7
|
+
b: ["<strong>", "</strong>"],
|
8
|
+
i: ["<em>", "</em>"],
|
9
|
+
s: ["<del>", "</del>"],
|
10
|
+
u: ["<u>", "</u>"],
|
11
|
+
mt: ["$", "$"],
|
12
|
+
m: ["==", "=="],
|
13
|
+
sup: ["<sup>", "</sup>"],
|
14
|
+
sub: ["<sub>", "</sub>"],
|
15
|
+
}
|
16
|
+
|
17
|
+
|
18
|
+
def self.match?(node)
|
19
|
+
return false unless tag_name(node) == "span"
|
20
|
+
attrs = attributes(node)
|
21
|
+
attrs[:t] == 0
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.to_html(node, opts = {})
|
25
|
+
attrs = attributes(node)
|
26
|
+
renderer = opts[:renderer]
|
27
|
+
children = renderer.children_to_html(node)
|
28
|
+
|
29
|
+
case attrs[:va]
|
30
|
+
when "superscript" then attrs[:sup] = 1
|
31
|
+
when "subscript" then attrs[:sub] = 1
|
32
|
+
end
|
33
|
+
|
34
|
+
MARKS.each_key do |key|
|
35
|
+
if attrs[key] == 1
|
36
|
+
mark = MARKS[key]
|
37
|
+
children = "#{mark.first}#{children}#{mark.last}"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
children
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BookLab::SML::Rules
|
4
|
+
class Table < Base
|
5
|
+
def self.match?(node)
|
6
|
+
tag_name(node) == "table"
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.to_html(node, opts = {})
|
10
|
+
renderer = opts[:renderer]
|
11
|
+
children = renderer.children_to_html(node)
|
12
|
+
|
13
|
+
%(<table>#{children}</table>)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BookLab::SML::Rules
|
4
|
+
class Td < Base
|
5
|
+
def self.match?(node)
|
6
|
+
tag_name(node) == "tc"
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.to_html(node, opts = {})
|
10
|
+
renderer = opts[:renderer]
|
11
|
+
attrs = attributes(node)
|
12
|
+
children = renderer.children_to_html(node)
|
13
|
+
|
14
|
+
style = {}
|
15
|
+
if attrs[:align]
|
16
|
+
style["text-align"] = attrs[:align]
|
17
|
+
end
|
18
|
+
|
19
|
+
style_attrs = ""
|
20
|
+
if style.any?
|
21
|
+
style_attrs = %( style="#{styleize(style)}")
|
22
|
+
end
|
23
|
+
|
24
|
+
%(<td#{style_attrs}>#{children}</td>)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BookLab::SML::Rules
|
4
|
+
class Tr < Base
|
5
|
+
def self.match?(node)
|
6
|
+
tag_name(node) == "tr"
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.to_html(node, opts = {})
|
10
|
+
renderer = opts[:renderer]
|
11
|
+
attrs = attributes(node)
|
12
|
+
children = renderer.children_to_html(node)
|
13
|
+
|
14
|
+
%(<tr>#{children}</tr>)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BookLab::SML
|
4
|
+
module Rules
|
5
|
+
def self.all
|
6
|
+
return @rules if defined? @rules
|
7
|
+
rules = []
|
8
|
+
Dir.glob(::File.expand_path("rules/*.rb", __dir__)).each do |path|
|
9
|
+
require path
|
10
|
+
rule_name = ::File.basename(path, ".rb")
|
11
|
+
next if rule_name == "base"
|
12
|
+
rules << "BookLab::SML::Rules::#{rule_name.classify}".constantize
|
13
|
+
end
|
14
|
+
@rules = rules
|
15
|
+
@rules
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.find_by_node(node)
|
19
|
+
all.find { |rule| rule.match?(node) } || BookLab::SML::Rules::Base
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BookLab::SML
|
4
|
+
module Utils
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
class_methods do
|
8
|
+
def get_children(node)
|
9
|
+
has_attributes?(node) ? node[2..-1] : node[1..-1]
|
10
|
+
end
|
11
|
+
|
12
|
+
def tag_name(node)
|
13
|
+
node[0] || ""
|
14
|
+
end
|
15
|
+
|
16
|
+
def attributes(node, add_if_mission: false)
|
17
|
+
return node[1].deep_symbolize_keys if has_attributes?(node)
|
18
|
+
return nil unless add_if_mission
|
19
|
+
|
20
|
+
name = node.shift || ""
|
21
|
+
attrs = {}
|
22
|
+
node.unshift(attrs)
|
23
|
+
node.unshift(name)
|
24
|
+
|
25
|
+
attrs
|
26
|
+
end
|
27
|
+
|
28
|
+
def has_attributes?(node)
|
29
|
+
raise "Invalid SML format:\n#{node.inspect}" unless element?(node)
|
30
|
+
attributes?(node[1])
|
31
|
+
end
|
32
|
+
|
33
|
+
def attributes?(node)
|
34
|
+
return false if node.nil?
|
35
|
+
node.is_a?(Hash)
|
36
|
+
end
|
37
|
+
|
38
|
+
def element?(node)
|
39
|
+
node.is_a?(Array) && node[0].is_a?(String)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/booklab/sml/version.rb
CHANGED
data/lib/booklab-sml.rb
CHANGED
@@ -1,7 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/concern"
|
1
4
|
require "booklab/sml/version"
|
5
|
+
require "booklab/sml/rules"
|
6
|
+
require "booklab/sml/config"
|
7
|
+
require "booklab/sml/utils"
|
8
|
+
require "booklab/sml/renderer"
|
2
9
|
require "booklab/sml/base"
|
3
10
|
|
11
|
+
|
4
12
|
module BookLab
|
5
13
|
module SML
|
6
14
|
end
|
7
|
-
end
|
15
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: booklab-sml
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jason Lee
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-01-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -24,6 +24,34 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rouge
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: escape_utils
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
27
55
|
description: "*SML* is a document format base on [JsonML](http://jsonml.org)."
|
28
56
|
email:
|
29
57
|
- huacnlee@gmail.com
|
@@ -36,6 +64,30 @@ files:
|
|
36
64
|
- Rakefile
|
37
65
|
- lib/booklab-sml.rb
|
38
66
|
- lib/booklab/sml/base.rb
|
67
|
+
- lib/booklab/sml/config.rb
|
68
|
+
- lib/booklab/sml/renderer.rb
|
69
|
+
- lib/booklab/sml/rules.rb
|
70
|
+
- lib/booklab/sml/rules/base.rb
|
71
|
+
- lib/booklab/sml/rules/blockquote.rb
|
72
|
+
- lib/booklab/sml/rules/br.rb
|
73
|
+
- lib/booklab/sml/rules/codeblock.rb
|
74
|
+
- lib/booklab/sml/rules/file.rb
|
75
|
+
- lib/booklab/sml/rules/heading.rb
|
76
|
+
- lib/booklab/sml/rules/hr.rb
|
77
|
+
- lib/booklab/sml/rules/image.rb
|
78
|
+
- lib/booklab/sml/rules/link.rb
|
79
|
+
- lib/booklab/sml/rules/list.rb
|
80
|
+
- lib/booklab/sml/rules/math.rb
|
81
|
+
- lib/booklab/sml/rules/paragraph.rb
|
82
|
+
- lib/booklab/sml/rules/plantuml.rb
|
83
|
+
- lib/booklab/sml/rules/root.rb
|
84
|
+
- lib/booklab/sml/rules/span.rb
|
85
|
+
- lib/booklab/sml/rules/span_with_mark.rb
|
86
|
+
- lib/booklab/sml/rules/table.rb
|
87
|
+
- lib/booklab/sml/rules/td.rb
|
88
|
+
- lib/booklab/sml/rules/text.rb
|
89
|
+
- lib/booklab/sml/rules/tr.rb
|
90
|
+
- lib/booklab/sml/utils.rb
|
39
91
|
- lib/booklab/sml/version.rb
|
40
92
|
homepage: https://github.com/huacnlee/booklab-sml
|
41
93
|
licenses:
|
@@ -56,8 +108,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
56
108
|
- !ruby/object:Gem::Version
|
57
109
|
version: '0'
|
58
110
|
requirements: []
|
59
|
-
|
60
|
-
rubygems_version: 2.7.8
|
111
|
+
rubygems_version: 3.0.1
|
61
112
|
signing_key:
|
62
113
|
specification_version: 4
|
63
114
|
summary: SML is a document format base on JsonML
|