bluedoc-sml 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 40d3fbabc52157a7a48ee82bea31d367c8f9bc58bdac3306c273ac21ee6d24a8
4
+ data.tar.gz: e2d7b3f1e44cf5b1d574ba1f3d1342d0f618950ab999fc9dbf06f73fd3377289
5
+ SHA512:
6
+ metadata.gz: 7751835475a13fecb9fc8ca6d32163a020cd16a271123941b9a393e2da99cc04b25eab2621ed869f1cc8fe74f6b52bcef87a9e9cdc8b4c366369611552e295ee
7
+ data.tar.gz: c1fbc2dc08ef51738ba72ec656ffdc923c10aad6abea0ce5959c5d9b6357c7081976f62db8d71106641995913d2e5bffd41a588186320a76ae774b5f536f59f6
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2018 Jason Lee
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,28 @@
1
+ # BlueDoc::SML
2
+
3
+ [![CircleCI](https://circleci.com/gh/bluedoc-org/bluedoc-sml/tree/master.svg?style=shield&circle-token=231806e2ce24e58a85190a0cd167b7d2da27c0b9)](https://circleci.com/gh/bluedoc-org/bluedoc-sml/tree/master)
4
+
5
+ SML __(Slate markup language)__ is a rich text format for describe of the BlueDoc rich contents.
6
+
7
+ It base on [JsonML](http://jsonml.org) format, and including custom DSL.
8
+
9
+ ## Usage
10
+
11
+ ```rb
12
+ gem "bluedoc-sml"
13
+ ```
14
+
15
+ and then run `bundle install`
16
+
17
+ ```rb
18
+ $ sml = %(["p", { align: "center", indent: 1 }, "Hello world"])
19
+ $ renderer = BlueDoc::SML.parse(sml)
20
+ $ renderer.to_html
21
+ => <p style="text-align: center; text-indent: 32px;">Hello world</p>
22
+ $ renderer.to_text
23
+ => "Hello world"
24
+ ```
25
+
26
+ ## License
27
+
28
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ require "bundler/setup"
5
+ rescue LoadError
6
+ puts "You must `gem install bundler` and `bundle install` to run rake tasks"
7
+ end
8
+
9
+ require "rdoc/task"
10
+
11
+ RDoc::Task.new(:rdoc) do |rdoc|
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")
17
+ end
18
+
19
+ require "bundler/gem_tasks"
20
+
21
+ require "rake/testtask"
22
+
23
+ Rake::TestTask.new(:test) do |t|
24
+ t.libs << "test"
25
+ t.pattern = "test/**/*_test.rb"
26
+ t.verbose = false
27
+ t.warning = false
28
+ end
29
+
30
+ task default: :test
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/concern"
4
+ require "bluedoc/plantuml"
5
+ require "bluedoc/sml/version"
6
+ require "bluedoc/sml/utils"
7
+ require "bluedoc/sml/rules"
8
+ require "bluedoc/sml/config"
9
+ require "bluedoc/sml/renderer"
10
+ require "bluedoc/sml/base"
11
+
12
+ module BlueDoc
13
+ module SML
14
+ end
15
+ end
@@ -0,0 +1,53 @@
1
+ require "zlib"
2
+
3
+ module BlueDoc
4
+ class Plantuml
5
+ class << self
6
+ def encode(text)
7
+ result = ""
8
+ compressedData = Zlib::Deflate.deflate(text)
9
+ compressedData.chars.each_slice(3) do |bytes|
10
+ #print bytes[0], ' ' , bytes[1] , ' ' , bytes[2]
11
+ b1 = bytes[0].nil? ? 0 : (bytes[0].ord & 0xFF)
12
+ b2 = bytes[1].nil? ? 0 : (bytes[1].ord & 0xFF)
13
+ b3 = bytes[2].nil? ? 0 : (bytes[2].ord & 0xFF)
14
+ result += append3bytes(b1, b2, b3)
15
+ end
16
+ result
17
+ end
18
+
19
+ def append3bytes(b1, b2, b3)
20
+ c1 = b1 >> 2
21
+ c2 = ((b1 & 0x3) << 4) | (b2 >> 4)
22
+ c3 = ((b2 & 0xF) << 2) | (b3 >> 6)
23
+ c4 = b3 & 0x3F
24
+ return encode6bit(c1 & 0x3F).chr +
25
+ encode6bit(c2 & 0x3F).chr +
26
+ encode6bit(c3 & 0x3F).chr +
27
+ encode6bit(c4 & 0x3F).chr
28
+ end
29
+
30
+ def encode6bit(b)
31
+ if b < 10
32
+ return ('0'.ord + b).chr
33
+ end
34
+ b = b - 10
35
+ if b < 26
36
+ return ('A'.ord + b).chr
37
+ end
38
+ b = b - 26
39
+ if b < 26
40
+ return ('a'.ord + b).chr
41
+ end
42
+ b = b - 26
43
+ if b == 0
44
+ return '-'
45
+ end
46
+ if b == 1
47
+ return '_'
48
+ end
49
+ return '?'
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "yaml"
4
+
5
+ module BlueDoc
6
+ module SML
7
+ def self.parse(src, options = {})
8
+ renderer = Renderer.new(src, options)
9
+ renderer
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BlueDoc::SML
4
+ class Config
5
+ attr_accessor :plantuml_service_host
6
+ attr_accessor :mathjax_service_host
7
+ end
8
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext"
4
+
5
+ module BlueDoc::SML
6
+ class Renderer
7
+ include BlueDoc::SML::Utils
8
+
9
+ attr_accessor :sml, :value, :config
10
+
11
+ # For table, list for temp mark in block
12
+ attr_accessor :in_block
13
+
14
+ def initialize(sml, options)
15
+ @sml = sml
16
+ @config = Config.new
17
+ @config.plantuml_service_host = options[:plantuml_service_host]
18
+ @config.mathjax_service_host = options[:mathjax_service_host]
19
+ @value = YAML.load(sml)
20
+ end
21
+
22
+ def to_html
23
+ node_to_html(self.value)
24
+ end
25
+
26
+ def to_s
27
+ to_html
28
+ end
29
+
30
+ def node_to_html(node, opts = {})
31
+ opts[:renderer] = self
32
+
33
+ rule = BlueDoc::SML::Rules::find_by_node(node)
34
+ rule.to_html(node, opts)
35
+ end
36
+
37
+ def children_to_html(node)
38
+ return node if node.is_a?(String)
39
+
40
+ children = self.class.get_children(node)
41
+ children.each_with_index.map do |child, idx|
42
+ prev_node = idx > 0 ? children[idx - 1] : nil
43
+ next_node = idx < children.length ? children[idx + 1] : nil
44
+
45
+ node_to_html(child, prev: prev_node, next: next_node)
46
+ end.join("")
47
+ end
48
+
49
+ def to_text
50
+ node_to_text(self.value)
51
+ end
52
+
53
+ def node_to_text(node, opts = {})
54
+ opts[:renderer] = self
55
+ rule = BlueDoc::SML::Rules::find_by_node(node)
56
+ rule.to_text(node, opts)&.strip
57
+ end
58
+
59
+ def children_to_text(node)
60
+ return node if node.is_a?(String)
61
+ children = self.class.get_children(node)
62
+ children.each_with_index.map do |child, idx|
63
+ text = node_to_text(child, {})
64
+ text.blank? ? nil : text
65
+ end.compact.join(" ")
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bluedoc/sml/rules/base"
4
+
5
+ module BlueDoc::SML
6
+ module Rules
7
+ def self.all
8
+ return @rules if defined? @rules
9
+ rules = []
10
+ Dir.glob(::File.expand_path("rules/*.rb", __dir__)).each do |path|
11
+ rule_name = ::File.basename(path, ".rb")
12
+ require "bluedoc/sml/rules/#{rule_name}"
13
+
14
+ next if rule_name == "base"
15
+ rules << "BlueDoc::SML::Rules::#{rule_name.classify}".constantize
16
+ end
17
+ @rules = rules
18
+ @rules
19
+ end
20
+
21
+ def self.find_by_node(node)
22
+ all.find { |rule| rule.match?(node) } || BlueDoc::SML::Rules::Base
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "escape_utils"
4
+
5
+ module BlueDoc::SML::Rules
6
+ class SyntaxError < Exception; end
7
+
8
+ class Base
9
+ include BlueDoc::SML::Utils
10
+
11
+ INDENT_PX = 8
12
+
13
+ class << self
14
+ include EscapeUtils
15
+ end
16
+
17
+
18
+ def self.match?(node)
19
+ false
20
+ end
21
+
22
+ def self.to_html(node, opts = {})
23
+ children = opts[:renderer].children_to_html(node)
24
+ tag = tag_name(node)
25
+ %(<#{tag}>#{children}</#{tag}>)
26
+ end
27
+
28
+ def self.to_text(node, opts = {})
29
+ opts[:renderer].children_to_text(node)
30
+ end
31
+
32
+ protected
33
+ def self.style_for_attrs(attrs, style = {})
34
+ attrs ||= {}
35
+ if attrs[:align]
36
+ style["text-align"] = attrs[:align]
37
+ end
38
+
39
+ if attrs[:indent]
40
+ if attrs[:indent].is_a?(Hash)
41
+ # text-indent
42
+ text_indent = attrs.dig(:indent, :firstline)
43
+ style["text-indent"] = "#{4 * INDENT_PX}px" if text_indent && text_indent > 0
44
+
45
+ # padding-left
46
+ indent_left = attrs.dig(:indent, :left)
47
+ style["padding-left"] = "#{indent_left * INDENT_PX}px" if indent_left && indent_left > 0
48
+ end
49
+ end
50
+
51
+ props = css_attrs(style)
52
+ return "" if props.strip.blank?
53
+ %( style="#{props}")
54
+ rescue => e
55
+ ""
56
+ end
57
+
58
+ def self.css_attrs(style)
59
+ style.map { |k, v| "#{k}: #{v};" }.join(" ")
60
+ end
61
+
62
+ def self.html_attrs(attrs)
63
+ attrs[:width] = nil if attrs[:width].to_i == 0
64
+ attrs[:height] = nil if attrs[:height].to_i == 0
65
+
66
+ props = attrs.map { |k, v| v.present? ? %(#{k}="#{v}") : nil }.compact.join(" ")
67
+ %( #{props})
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BlueDoc::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,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BlueDoc::SML::Rules
4
+ class Br < Base
5
+ def self.match?(node)
6
+ tag_name(node) == "br"
7
+ end
8
+
9
+ def self.to_html(node, opts = {})
10
+ %(<br>)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rouge"
4
+ require "rouge/plugins/redcarpet"
5
+
6
+ module BlueDoc::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,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BlueDoc::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
+ attrs[:name] ||= ""
16
+
17
+ return attrs[:name] if attrs[:src].blank?
18
+
19
+ humanize_size = number_to_human_size(attrs[:size] || 0)
20
+
21
+ out = <<~HTML
22
+ <a class="attachment-file" title="#{attrs[:name]}" target="_blank" href="#{attrs[:src]}">
23
+ <span class="icon-box"><i class="fas fa-file"></i></span>
24
+ <span class="filename">#{escape_html(attrs[:name])}</span>
25
+ <span class="filesize">#{escape_html(humanize_size)}</span>
26
+ </a>
27
+ HTML
28
+
29
+ out
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "digest/md5"
4
+
5
+ module BlueDoc::SML::Rules
6
+ class Heading < Base
7
+ def self.match?(node)
8
+ %w[h1 h2 h3 h4 h5 h6].include?(tag_name(node))
9
+ end
10
+
11
+ def self.to_html(node, opts = {})
12
+ renderer = opts[:renderer]
13
+ title = renderer.children_to_html(node) || ""
14
+ heading_tag = tag_name(node)
15
+
16
+ title_length = title.length
17
+ min_length = title_length * 0.3
18
+ words_length = /[a-z0-9]/i.match(title)&.length || 0
19
+ header_id = title.gsub(/[^a-z0-9]+/i, "-").downcase.gsub(/^\-|\-$/, "")
20
+ if title_length - header_id.length > min_length
21
+ header_id = Digest::MD5.hexdigest(title.strip)[0..8]
22
+ end
23
+
24
+ %(<#{heading_tag} id="#{header_id}"><a href="##{header_id}" class="heading-anchor">#</a>#{title}</#{heading_tag}>)
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BlueDoc::SML::Rules
4
+ class Hr < Base
5
+ def self.match?(node)
6
+ tag_name(node) == "hr"
7
+ end
8
+
9
+ def self.to_html(node, opts = {})
10
+ %(<hr>)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BlueDoc::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
+ attrs[:name] ||= ""
12
+
13
+ return attrs[:name] if attrs[:src].blank?
14
+
15
+ attr_html = html_attrs(
16
+ src: attrs[:src],
17
+ alt: attrs[:name],
18
+ width: attrs[:width],
19
+ height: attrs[:height]
20
+ )
21
+
22
+ %(<img#{attr_html}>)
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BlueDoc::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]}" target="_blank">#{name}</a>)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BlueDoc::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] || 0) + 1
27
+
28
+ style_attrs = style_for_attrs(attrs,
29
+ "padding-left": "#{indent_left * INDENT_PX}px"
30
+ )
31
+
32
+ wrap_tag = list_type == "bulleted" ? "ul" : "ol"
33
+
34
+
35
+ # <ul>
36
+ # <li>Bold text</li>
37
+ # <li>Important text
38
+ # <ul>
39
+ # <li>Emphasized text</li>
40
+ # <li>
41
+ # Small text
42
+ # <ul>
43
+ # <li>Subscript text</li>
44
+ # </ul>
45
+ # </li>
46
+ # </ul>
47
+ # </li>
48
+ # </ul>
49
+
50
+ # get prev attrs
51
+ prev_name = tag_name(opts[:prev])
52
+ next_name = tag_name(opts[:next])
53
+ prev_level = attributes(opts[:prev])[:level]
54
+ next_level = attributes(opts[:next])[:level]
55
+
56
+ outs = []
57
+
58
+
59
+ if prev_name != "list" || prev_level != level
60
+ outs << %(<#{wrap_tag} data-level="#{level}">)
61
+ end
62
+
63
+ li_item = "<li>#{children}"
64
+
65
+ if next_name == "list"
66
+ if next_level < level
67
+ (level - next_level + 1).times do
68
+ li_item += "</li></#{wrap_tag}>"
69
+ end
70
+ elsif next_level == level
71
+ li_item += "</li>"
72
+ else
73
+ li_item += "\n"
74
+ end
75
+ else
76
+ (level - 1 + 1).times do
77
+ li_item += "</li></#{wrap_tag}>"
78
+ end
79
+ end
80
+
81
+ outs << li_item
82
+
83
+ outs.join("\n")
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BlueDoc::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
+ code = (attrs[:code] || "").strip
14
+ return "" if code.blank?
15
+
16
+ svg_code = URI::encode(code)
17
+ src = "#{renderer.config.mathjax_service_host}/svg?tex=#{svg_code}"
18
+
19
+ %(<img class="tex-image" src="#{src}">)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BlueDoc::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
+ attrs = attributes(node)
13
+
14
+ style_attrs = style_for_attrs(attrs)
15
+
16
+ %(<p#{style_attrs}>#{children}</p>)
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BlueDoc::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
+ code = (attrs[:code] || "").strip
14
+ return "" if code.blank?
15
+
16
+ svg_code = BlueDoc::Plantuml.encode(code)
17
+ %(<img src="#{renderer.config.plantuml_service_host}/svg/#{svg_code}" class="plantuml-image" />)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BlueDoc::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 BlueDoc::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,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BlueDoc::SML::Rules
4
+ class SpanWithMark < Base
5
+ MARKS = {
6
+ cd: ["<code>", "</code>"],
7
+ b: ["<strong>", "</strong>"],
8
+ i: ["<i>", "</i>"],
9
+ s: ["<del>", "</del>"],
10
+ u: ["<u>", "</u>"],
11
+ m: ["<mark>", "</mark>"],
12
+ sup: ["<sup>", "</sup>"],
13
+ sub: ["<sub>", "</sub>"],
14
+ }
15
+
16
+
17
+ def self.match?(node)
18
+ return false unless tag_name(node) == "span"
19
+ attrs = attributes(node)
20
+ attrs[:t] == 0
21
+ end
22
+
23
+ def self.to_html(node, opts = {})
24
+ attrs = attributes(node)
25
+ renderer = opts[:renderer]
26
+ if attrs[:cd] == 1
27
+ children = renderer.children_to_text(node)
28
+ else
29
+ children = renderer.children_to_html(node)
30
+ end
31
+
32
+ case attrs[:va]
33
+ when "superscript" then attrs[:sup] = 1
34
+ when "subscript" then attrs[:sub] = 1
35
+ end
36
+
37
+ MARKS.each_key do |key|
38
+ if attrs[key] == 1
39
+ mark = MARKS[key]
40
+ children = "#{mark.first}#{children}#{mark.last}"
41
+ end
42
+ end
43
+
44
+ children
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BlueDoc::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,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BlueDoc::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
+ style_attrs = style_for_attrs(attrs, style)
16
+ %(<td#{style_attrs}>#{children}</td>)
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BlueDoc::SML::Rules
4
+ class Text < Base
5
+ def self.match?(node)
6
+ node.is_a?(String)
7
+ end
8
+
9
+ def self.to_html(node, opts = {})
10
+ node
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BlueDoc::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
+ children = renderer.children_to_html(node)
12
+
13
+ %(<tr>#{children}</tr>)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BlueDoc::SML::Rules
4
+ class Video < Base
5
+ def self.match?(node)
6
+ tag_name(node) == "video"
7
+ end
8
+
9
+ def self.to_html(node, opts = {})
10
+ attrs = attributes(node)
11
+
12
+ return "" if attrs[:src].blank?
13
+
14
+ width = attrs[:width]
15
+ if width == 0 || width.blank?
16
+ width = "100%"
17
+ end
18
+
19
+ video_attrs = html_attrs(
20
+ width: width
21
+ )
22
+
23
+ out = <<~HTML
24
+ <video controls preload="no"#{video_attrs}>
25
+ <source src="#{attrs[:src]}" type="#{attrs[:type]}">
26
+ </video>
27
+ HTML
28
+
29
+ out
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BlueDoc::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
+ return nil if node.blank?
14
+ node[0] || ""
15
+ end
16
+
17
+ def attributes(node, add_if_mission: false)
18
+ return {} if node.blank?
19
+ return node[1].deep_symbolize_keys if has_attributes?(node)
20
+ return {} unless add_if_mission
21
+
22
+ name = node.shift || ""
23
+ attrs = {}
24
+ node.unshift(attrs)
25
+ node.unshift(name)
26
+
27
+ attrs
28
+ end
29
+
30
+ def has_attributes?(node)
31
+ return false unless element?(node)
32
+ attributes?(node[1])
33
+ end
34
+
35
+ def attributes?(node)
36
+ return false if node.nil?
37
+ node.is_a?(Hash)
38
+ end
39
+
40
+ def element?(node)
41
+ node.is_a?(Array) && node[0].is_a?(String)
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BlueDoc
4
+ module SML
5
+ VERSION = "0.5.2"
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,118 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bluedoc-sml
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.5.2
5
+ platform: ruby
6
+ authors:
7
+ - Jason Lee
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-02-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
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'
55
+ description: SML is a rich text format for describe of the BlueDoc rich contents,
56
+ base on [JsonML](http://jsonml.org).
57
+ email:
58
+ - huacnlee@gmail.com
59
+ executables: []
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - MIT-LICENSE
64
+ - README.md
65
+ - Rakefile
66
+ - lib/bluedoc-sml.rb
67
+ - lib/bluedoc/plantuml.rb
68
+ - lib/bluedoc/sml/base.rb
69
+ - lib/bluedoc/sml/config.rb
70
+ - lib/bluedoc/sml/renderer.rb
71
+ - lib/bluedoc/sml/rules.rb
72
+ - lib/bluedoc/sml/rules/base.rb
73
+ - lib/bluedoc/sml/rules/blockquote.rb
74
+ - lib/bluedoc/sml/rules/br.rb
75
+ - lib/bluedoc/sml/rules/codeblock.rb
76
+ - lib/bluedoc/sml/rules/file.rb
77
+ - lib/bluedoc/sml/rules/heading.rb
78
+ - lib/bluedoc/sml/rules/hr.rb
79
+ - lib/bluedoc/sml/rules/image.rb
80
+ - lib/bluedoc/sml/rules/link.rb
81
+ - lib/bluedoc/sml/rules/list.rb
82
+ - lib/bluedoc/sml/rules/math.rb
83
+ - lib/bluedoc/sml/rules/paragraph.rb
84
+ - lib/bluedoc/sml/rules/plantuml.rb
85
+ - lib/bluedoc/sml/rules/root.rb
86
+ - lib/bluedoc/sml/rules/span.rb
87
+ - lib/bluedoc/sml/rules/span_with_mark.rb
88
+ - lib/bluedoc/sml/rules/table.rb
89
+ - lib/bluedoc/sml/rules/td.rb
90
+ - lib/bluedoc/sml/rules/text.rb
91
+ - lib/bluedoc/sml/rules/tr.rb
92
+ - lib/bluedoc/sml/rules/video.rb
93
+ - lib/bluedoc/sml/utils.rb
94
+ - lib/bluedoc/sml/version.rb
95
+ homepage: https://bluedoc.org
96
+ licenses:
97
+ - MIT
98
+ metadata: {}
99
+ post_install_message:
100
+ rdoc_options: []
101
+ require_paths:
102
+ - lib
103
+ required_ruby_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ required_rubygems_version: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
113
+ requirements: []
114
+ rubygems_version: 3.0.1
115
+ signing_key:
116
+ specification_version: 4
117
+ summary: SML is a rich text format for describe of the BlueDoc rich contents.
118
+ test_files: []