booklab-sml 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|