jekyll-spaceship 0.4.2 → 0.5.2
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/.codeclimate.yml +38 -0
- data/.github/FUNDING.yml +12 -0
- data/README.md +117 -8
- data/jekyll-spaceship.gemspec +2 -1
- data/lib/jekyll-spaceship.rb +2 -0
- data/lib/jekyll-spaceship/cores/logger.rb +19 -4
- data/lib/jekyll-spaceship/cores/manager.rb +118 -0
- data/lib/jekyll-spaceship/cores/processor.rb +62 -225
- data/lib/jekyll-spaceship/cores/register.rb +2 -6
- data/lib/jekyll-spaceship/cores/type.rb +41 -0
- data/lib/jekyll-spaceship/processors/emoji-processor.rb +65 -0
- data/lib/jekyll-spaceship/processors/mathjax-processor.rb +9 -3
- data/lib/jekyll-spaceship/processors/plantuml-processor.rb +23 -9
- data/lib/jekyll-spaceship/processors/table-processor.rb +59 -59
- data/lib/jekyll-spaceship/processors/video-processor.rb +13 -7
- data/lib/jekyll-spaceship/utils/.keep +0 -0
- data/lib/jekyll-spaceship/version.rb +1 -1
- data/logos/jekyll-spaceship-logo.png +0 -0
- metadata +24 -4
- data/lib/jekyll-spaceship/utils/plantuml/plantuml.jar +0 -0
@@ -24,21 +24,17 @@ module Jekyll::Spaceship
|
|
24
24
|
filename = File.basename(path, '.rb')
|
25
25
|
next if filename.gsub(/-/, '').downcase != name
|
26
26
|
|
27
|
-
Logger.log "use #{filename}"
|
28
|
-
|
27
|
+
Logger.log "🗂 use #{filename}"
|
29
28
|
require path
|
30
|
-
|
31
29
|
constants = Jekyll::Spaceship.constants.select do |c|
|
32
30
|
c.downcase.to_s == name
|
33
31
|
end
|
34
32
|
|
35
33
|
next if constants.first.nil?
|
36
|
-
|
37
34
|
_class = Jekyll::Spaceship.const_get(constants.first)
|
38
|
-
|
39
35
|
next unless _class.is_a? Class
|
40
36
|
|
41
|
-
_class.new
|
37
|
+
Manager.add _class.new
|
42
38
|
end
|
43
39
|
end
|
44
40
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Jekyll::Spaceship
|
4
|
+
class Type
|
5
|
+
HTML_EXTENSIONS = %w(
|
6
|
+
.html
|
7
|
+
.xhtml
|
8
|
+
.htm
|
9
|
+
).freeze
|
10
|
+
|
11
|
+
CSS_EXTENSIONS = %w(
|
12
|
+
.css
|
13
|
+
.scss
|
14
|
+
).freeze
|
15
|
+
|
16
|
+
MD_EXTENSIONS = %w(
|
17
|
+
.md
|
18
|
+
.markdown
|
19
|
+
).freeze
|
20
|
+
|
21
|
+
HTML_BLOCK_TYPE_MAP = {
|
22
|
+
'text/markdown' => 'markdown',
|
23
|
+
}.freeze
|
24
|
+
|
25
|
+
def self.html?(_ext)
|
26
|
+
HTML_EXTENSIONS.include?(_ext)
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.css?(_ext)
|
30
|
+
CSS_EXTENSIONS.include?(_ext)
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.markdown?(_ext)
|
34
|
+
MD_EXTENSIONS.include?(_ext)
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.html_block_type(type)
|
38
|
+
HTML_BLOCK_TYPE_MAP[type]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'net/http'
|
4
|
+
require 'uri'
|
5
|
+
require 'json'
|
6
|
+
|
7
|
+
module Jekyll::Spaceship
|
8
|
+
class EmojiProcessor < Processor
|
9
|
+
EMOJI_MARKUP_HOST = 'https://api.github.com/emojis'
|
10
|
+
EMOJI_MARKUP_DATA = {}
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
super()
|
14
|
+
self.initialize_emoji_data
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize_emoji_data
|
18
|
+
EMOJI_MARKUP_DATA.update get_emoji_markup_data
|
19
|
+
end
|
20
|
+
|
21
|
+
def on_handle_html(content)
|
22
|
+
return content if EMOJI_MARKUP_DATA.size.zero?
|
23
|
+
# handle emoji markup
|
24
|
+
content.scan(/:([\w+-]+):/) do |match_data|
|
25
|
+
emoji_markup = match_data[0]
|
26
|
+
emoji_image = EMOJI_MARKUP_DATA[emoji_markup]
|
27
|
+
next if emoji_image.nil?
|
28
|
+
self.handled = true
|
29
|
+
|
30
|
+
# convert hex string to unicode
|
31
|
+
unicode = emoji_image.match(/unicode\/([\d\w]+)/)
|
32
|
+
if unicode[1]
|
33
|
+
unicode = "0x#{unicode[1]}".to_i(16)
|
34
|
+
alt = [unicode].pack('U*')
|
35
|
+
end
|
36
|
+
alt = emoji_markup if alt.nil?
|
37
|
+
|
38
|
+
content = content.gsub(
|
39
|
+
":#{emoji_markup}:",
|
40
|
+
"<image class=\"emoji\" \
|
41
|
+
title=\"#{emoji_markup}\" \
|
42
|
+
alt=\"#{alt}\" \
|
43
|
+
src=\"#{emoji_image}\" \
|
44
|
+
style=\"vertical-align: middle; \
|
45
|
+
max-width: 1em; visibility: hidden;\" \
|
46
|
+
onload=\"this.style.visibility='visible'\" \
|
47
|
+
onerror=\"this.replaceWith(this.alt)\"> \
|
48
|
+
</image>"
|
49
|
+
)
|
50
|
+
end
|
51
|
+
content
|
52
|
+
end
|
53
|
+
|
54
|
+
def get_emoji_markup_data
|
55
|
+
data = {}
|
56
|
+
begin
|
57
|
+
source = Net::HTTP.get URI(EMOJI_MARKUP_HOST)
|
58
|
+
data = JSON.parse(source)
|
59
|
+
rescue StandardError => msg
|
60
|
+
logger.log msg
|
61
|
+
end
|
62
|
+
data
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -5,7 +5,7 @@ require "nokogiri"
|
|
5
5
|
module Jekyll::Spaceship
|
6
6
|
class MathjaxProcessor < Processor
|
7
7
|
def process?
|
8
|
-
return true if html?(output_ext)
|
8
|
+
return true if Type.html?(output_ext)
|
9
9
|
end
|
10
10
|
|
11
11
|
def on_handle_html(content)
|
@@ -20,7 +20,10 @@ module Jekyll::Spaceship
|
|
20
20
|
|
21
21
|
params = "config=TeX-AMS-MML_HTMLorMML"
|
22
22
|
src = "//cdn.mathjax.org/mathjax/latest/MathJax.js?#{params}"
|
23
|
-
config = "MathJax.Hub.Config({
|
23
|
+
config = "MathJax.Hub.Config({ \
|
24
|
+
tex2jax: { inlineMath: [['$','$'], ['\\\\(','\\\\)']] } \
|
25
|
+
});"
|
26
|
+
|
24
27
|
head.add_child("<script src=\"#{src}\">#{config}</script>")
|
25
28
|
|
26
29
|
doc.to_html
|
@@ -28,7 +31,10 @@ module Jekyll::Spaceship
|
|
28
31
|
|
29
32
|
def has_mathjax_expression?(doc)
|
30
33
|
doc.css('*').each do |node|
|
31
|
-
if node.content.match(
|
34
|
+
if node.content.match(/(?<!\\)\$.+(?<!\\)\$/)
|
35
|
+
return true
|
36
|
+
end
|
37
|
+
if node.content.match(/(?<!\\)\\\(.+(?<!\\)\\\)/)
|
32
38
|
return true
|
33
39
|
end
|
34
40
|
end
|
@@ -1,9 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "base64"
|
4
|
+
|
3
5
|
module Jekyll::Spaceship
|
4
6
|
class PlantUMLProcessor < Processor
|
5
7
|
exclude :none
|
6
8
|
|
9
|
+
PLANT_UML_HOST = 'http://www.plantuml.com/plantuml/png/'
|
10
|
+
|
7
11
|
def on_handle_markdown(content)
|
8
12
|
# match default plantuml block and code block
|
9
13
|
pattern = Regexp.union(
|
@@ -35,18 +39,28 @@ module Jekyll::Spaceship
|
|
35
39
|
|
36
40
|
def handle_plantuml(code)
|
37
41
|
# wrap plantuml code
|
38
|
-
|
39
|
-
|
40
|
-
dir = File.dirname(__FILE__)
|
41
|
-
jar = dir + "/../utils/plantuml/plantuml.jar"
|
42
|
-
echo = "echo -e \"#{uml.gsub('"', '\"')}\""
|
43
|
-
plantuml = "java -jar \"#{jar}\" -pipe 2>/dev/null"
|
42
|
+
code = "@startuml#{code}@enduml".encode('UTF-8')
|
44
43
|
|
45
|
-
#
|
46
|
-
|
44
|
+
# encode to hex string
|
45
|
+
code = '~h' + code.unpack("H*").first
|
46
|
+
data = self.get_plantuml_img_data(code)
|
47
47
|
|
48
48
|
# return img tag
|
49
|
-
"<img src=\"
|
49
|
+
"<img src=\"#{data}\">"
|
50
|
+
end
|
51
|
+
|
52
|
+
def get_plantuml_img_data(code)
|
53
|
+
data = ''
|
54
|
+
url = "#{PLANT_UML_HOST}#{code}"
|
55
|
+
begin
|
56
|
+
data = Net::HTTP.get URI(url)
|
57
|
+
data = Base64.encode64(data)
|
58
|
+
data = "data:image/png;base64, #{data}"
|
59
|
+
rescue StandardError => msg
|
60
|
+
data = url
|
61
|
+
logger.log msg
|
62
|
+
end
|
63
|
+
data
|
50
64
|
end
|
51
65
|
end
|
52
66
|
end
|
@@ -46,23 +46,7 @@ module Jekyll::Spaceship
|
|
46
46
|
# use nokogiri to parse html content
|
47
47
|
doc = Nokogiri::HTML(content)
|
48
48
|
|
49
|
-
data =
|
50
|
-
data.reset = ->(scope, namespace = nil) {
|
51
|
-
data._.marshal_dump.each do |key, val|
|
52
|
-
if namespace == key or namespace.nil?
|
53
|
-
data._[key][scope] = OpenStruct.new
|
54
|
-
end
|
55
|
-
end
|
56
|
-
}
|
57
|
-
data.scope = ->(namespace) {
|
58
|
-
if not data._[namespace]
|
59
|
-
data._[namespace] = OpenStruct.new(
|
60
|
-
table: OpenStruct.new,
|
61
|
-
row: OpenStruct.new
|
62
|
-
)
|
63
|
-
end
|
64
|
-
data._[namespace]
|
65
|
-
}
|
49
|
+
data = self.table_scope_data
|
66
50
|
|
67
51
|
# handle each table
|
68
52
|
doc.css('table').each do |table|
|
@@ -96,45 +80,66 @@ module Jekyll::Spaceship
|
|
96
80
|
doc.to_html
|
97
81
|
end
|
98
82
|
|
83
|
+
def table_scope_data
|
84
|
+
data = OpenStruct.new(_: OpenStruct.new)
|
85
|
+
data.reset = ->(scope, namespace = nil) {
|
86
|
+
data._.marshal_dump.each do |key, val|
|
87
|
+
if namespace == key or namespace.nil?
|
88
|
+
data._[key][scope] = OpenStruct.new
|
89
|
+
end
|
90
|
+
end
|
91
|
+
}
|
92
|
+
data.scope = ->(namespace) {
|
93
|
+
if not data._[namespace]
|
94
|
+
data._[namespace] = OpenStruct.new(
|
95
|
+
table: OpenStruct.new,
|
96
|
+
row: OpenStruct.new
|
97
|
+
)
|
98
|
+
end
|
99
|
+
data._[namespace]
|
100
|
+
}
|
101
|
+
data
|
102
|
+
end
|
103
|
+
|
99
104
|
def handle_colspan(data)
|
100
105
|
scope = data.scope.call __method__
|
101
|
-
scope_table = scope.table
|
102
|
-
scope_row = scope.row
|
103
106
|
cells = data.cells
|
104
107
|
cell = data.cell
|
105
108
|
|
106
|
-
if
|
107
|
-
|
108
|
-
|
109
|
+
if scope.table.row != data.row
|
110
|
+
scope.table.row = data.row
|
111
|
+
scope.row.colspan = 0
|
109
112
|
end
|
110
113
|
|
111
114
|
# handle colspan
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
115
|
+
if cell == cells.last and scope.row.colspan > 0
|
116
|
+
cells.count.downto(cells.count - scope.row.colspan + 1) do |i|
|
117
|
+
c = cells[i - 1]
|
118
|
+
return unless c.get_attribute('colspan').nil?
|
119
|
+
c.remove
|
117
120
|
end
|
118
121
|
end
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
122
|
+
|
123
|
+
result = cell.content.match(/(\|)+$/)
|
124
|
+
return if result.nil?
|
125
|
+
|
126
|
+
cell.content = cell.content.gsub(/(\|)+$/, '')
|
127
|
+
result = result[0]
|
128
|
+
colspan = result.scan(/\|/).count
|
129
|
+
scope.row.colspan += colspan
|
130
|
+
cell.set_attribute('colspan', colspan + 1)
|
125
131
|
end
|
126
132
|
|
127
133
|
def handle_multi_rows(data)
|
128
134
|
scope = data.scope.call __method__
|
129
|
-
scope_table = scope.table
|
130
135
|
cells = data.cells
|
131
136
|
row = data.row
|
132
137
|
cell = data.cell
|
133
138
|
|
134
|
-
if
|
135
|
-
|
136
|
-
|
137
|
-
|
139
|
+
if scope.table.table != data.table
|
140
|
+
scope.table.table = data.table
|
141
|
+
scope.table.multi_row_cells = nil
|
142
|
+
scope.table.multi_row_start = false
|
138
143
|
end
|
139
144
|
|
140
145
|
# handle multi-rows
|
@@ -143,41 +148,38 @@ module Jekyll::Spaceship
|
|
143
148
|
match = cell.content.match(/(?<!\\)\\\s*$/)
|
144
149
|
if match
|
145
150
|
cell.content = cell.content.gsub(/(?<!\\)\\\s*$/, '')
|
146
|
-
if not
|
147
|
-
|
148
|
-
|
151
|
+
if not scope.table.multi_row_start
|
152
|
+
scope.table.multi_row_cells = cells
|
153
|
+
scope.table.multi_row_start = true
|
149
154
|
end
|
150
155
|
end
|
151
156
|
|
152
|
-
if
|
153
|
-
for i in 0...
|
154
|
-
multi_row_cell =
|
157
|
+
if scope.table.multi_row_cells != cells and scope.table.multi_row_start
|
158
|
+
for i in 0...scope.table.multi_row_cells.count do
|
159
|
+
multi_row_cell = scope.table.multi_row_cells[i]
|
155
160
|
multi_row_cell.content += " \n#{cells[i].content}"
|
156
161
|
end
|
157
162
|
row.remove
|
158
163
|
end
|
159
|
-
|
164
|
+
scope.table.multi_row_start = false if not match
|
160
165
|
end
|
161
166
|
|
162
167
|
def handle_rowspan(data)
|
163
168
|
scope = data.scope.call __method__
|
164
|
-
scope_table = scope.table
|
165
|
-
scope_row = scope.row
|
166
169
|
cell = data.cell
|
167
170
|
cells = data.cells
|
168
171
|
|
169
|
-
if
|
170
|
-
|
171
|
-
|
172
|
+
if scope.table.table != data.table
|
173
|
+
scope.table.table = data.table
|
174
|
+
scope.table.span_row_cells = []
|
172
175
|
end
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
scope_row.col_index = 0
|
176
|
+
if scope.row.row != data.row
|
177
|
+
scope.row.row = data.row
|
178
|
+
scope.row.col_index = 0
|
177
179
|
end
|
178
180
|
|
179
181
|
# handle rowspan
|
180
|
-
span_cell =
|
182
|
+
span_cell = scope.table.span_row_cells[scope.row.col_index]
|
181
183
|
if span_cell and cell.content.match(/^\s*\^{2}/)
|
182
184
|
cell.content = cell.content.gsub(/^\s*\^{2}/, '')
|
183
185
|
span_cell.content += " \n#{cell.content}"
|
@@ -186,10 +188,9 @@ module Jekyll::Spaceship
|
|
186
188
|
span_cell.set_attribute('rowspan', "#{rowspan}")
|
187
189
|
cell.remove
|
188
190
|
else
|
189
|
-
|
191
|
+
scope.table.span_row_cells[scope.row.col_index] = cell
|
190
192
|
end
|
191
|
-
|
192
|
-
scope_row.col_index += 1
|
193
|
+
scope.row.col_index += [cell.get_attribute('colspan').to_i, 1].max
|
193
194
|
end
|
194
195
|
|
195
196
|
def handle_text_align(data)
|
@@ -211,7 +212,6 @@ module Jekyll::Spaceship
|
|
211
212
|
|
212
213
|
# handle text align
|
213
214
|
return if align == 0
|
214
|
-
|
215
215
|
style = cell.get_attribute('style')
|
216
216
|
if align == 1
|
217
217
|
align = 'text-align: left'
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'uri'
|
4
|
+
|
3
5
|
module Jekyll::Spaceship
|
4
6
|
class VideoProcessor < Processor
|
5
7
|
def on_handle_markdown(content)
|
@@ -70,22 +72,26 @@ module Jekyll::Spaceship
|
|
70
72
|
url = match_data[2]
|
71
73
|
id = match_data[4]
|
72
74
|
title = match_data[6]
|
73
|
-
|
74
|
-
|
75
|
+
qs = url.match(/(?<=\?)(\S*?)$/)
|
76
|
+
qs = Hash[URI.decode_www_form(qs.to_s)].reject do |k, v|
|
77
|
+
next true if v == id or v == ''
|
78
|
+
end
|
75
79
|
|
76
|
-
|
77
|
-
|
80
|
+
width = qs['width'] || data[:width] || 600
|
81
|
+
height = qs['height'] || data[:height] || 400
|
78
82
|
style = "max-width: 100%" if width.nil?
|
79
|
-
width = data[:width] if width.nil?
|
80
|
-
height = data[:height] if height.nil?
|
81
83
|
|
82
|
-
url = "#{iframe_url}#{id}"
|
84
|
+
url = URI("#{iframe_url}#{id}").tap do |v|
|
85
|
+
v.query = URI.encode_www_form(qs) if qs.size > 0
|
86
|
+
end
|
87
|
+
|
83
88
|
html = "<iframe \
|
84
89
|
src=\"#{url}\" \
|
85
90
|
title=\"#{title}\" \
|
86
91
|
width=\"#{width}\" \
|
87
92
|
height=\"#{height}\" \
|
88
93
|
style=\"#{style}\" \
|
94
|
+
allow=\"autoplay; encrypted-media\" \
|
89
95
|
frameborder=\"0\" \
|
90
96
|
allowfullscreen=\"\">\
|
91
97
|
</iframe>"
|
File without changes
|