jekyll-spaceship 0.9.4 → 0.9.9
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/.github/FUNDING.yml +1 -1
- data/README.md +8 -1
- data/lib/jekyll-spaceship/cores/config.rb +10 -0
- data/lib/jekyll-spaceship/cores/processor.rb +6 -1
- data/lib/jekyll-spaceship/processors/emoji-processor.rb +56 -15
- data/lib/jekyll-spaceship/processors/mathjax-processor.rb +89 -13
- data/lib/jekyll-spaceship/processors/media-processor.rb +36 -11
- data/lib/jekyll-spaceship/processors/mermaid-processor.rb +3 -0
- data/lib/jekyll-spaceship/processors/table-processor.rb +18 -10
- data/lib/jekyll-spaceship/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 51f0576137305906368ec086aba6c9c11d45799d10dc8a22abd5598a4026251a
|
4
|
+
data.tar.gz: 1a52f85350f6d2b3e128b637ec040108d993534ec554296cdd2b998e26551aec
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1445456d3974c347367ae35c8b8b2ceec320f523931620d3ad4f19f3982ddefff2f9426f9f47318b6e548da9c0b25b0b370733a472250065579c27296785ce49
|
7
|
+
data.tar.gz: f78d6fd69910ea7350b77a6d0c8702214d097e8813032fb4254fa53f4521805c5f2b74c3f1ea8c763cb305b145929d6e12810653952ef57c4c32765048ccaffe
|
data/.github/FUNDING.yml
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# These are supported funding model platforms
|
2
2
|
|
3
|
-
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
3
|
+
github: jeffreytse # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
4
4
|
patreon: jeffreytse
|
5
5
|
open_collective: # Replace with a single Open Collective username
|
6
6
|
ko_fi: jeffreytse
|
data/README.md
CHANGED
@@ -177,8 +177,15 @@ jekyll-spaceship:
|
|
177
177
|
inlineMath:
|
178
178
|
- ['$','$']
|
179
179
|
- ['\(','\)']
|
180
|
+
displayMath:
|
181
|
+
- ['$$','$$']
|
182
|
+
- ['\[','\]']
|
180
183
|
svg:
|
181
184
|
fontCache: 'global'
|
185
|
+
optimize: # optimization on building stage to check and add mathjax scripts
|
186
|
+
enabled: true # value `false` for adding to all pages
|
187
|
+
include: [] # include patterns for math expressions checking (regexp)
|
188
|
+
exclude: [] # exclude patterns for math expressions checking (regexp)
|
182
189
|
plantuml-processor:
|
183
190
|
mode: default # mode value 'pre-fetch' for fetching image at building stage
|
184
191
|
css:
|
@@ -434,7 +441,7 @@ Code above would be parsed as:
|
|
434
441
|
#### Cell Alignment
|
435
442
|
|
436
443
|
Markdown table syntax use colons ":" for forcing column alignment.
|
437
|
-
Therefore, here we also use it for
|
444
|
+
Therefore, here we also use it for forcing cell alignment.
|
438
445
|
|
439
446
|
Table cell can be set alignment separately.
|
440
447
|
|
@@ -31,6 +31,16 @@ module Jekyll::Spaceship
|
|
31
31
|
first.merge(second.to_h, &merger)
|
32
32
|
end
|
33
33
|
|
34
|
+
def self.deep_dig(obj, key)
|
35
|
+
if obj.respond_to?(:key?) && obj.key?(key)
|
36
|
+
obj[key]
|
37
|
+
elsif obj.respond_to?(:each)
|
38
|
+
result = nil
|
39
|
+
obj.find { |*a| result = self.deep_dig(a.last, key) }
|
40
|
+
result
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
34
44
|
def self.store(section, default)
|
35
45
|
return @@store[section] if default.nil?
|
36
46
|
@@store[section] = deep_merge(default, @@store[section])
|
@@ -25,7 +25,11 @@ module Jekyll::Spaceship
|
|
25
25
|
attr_accessor :handled
|
26
26
|
|
27
27
|
def name
|
28
|
-
self.class.
|
28
|
+
self.class.class_name
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.class_name
|
32
|
+
self.name.split('::').last
|
29
33
|
end
|
30
34
|
|
31
35
|
def filename
|
@@ -212,6 +216,7 @@ module Jekyll::Spaceship
|
|
212
216
|
'body' => content_body
|
213
217
|
}
|
214
218
|
rescue StandardError => msg
|
219
|
+
logger = Logger.new(self.class_name)
|
215
220
|
logger.log msg
|
216
221
|
end
|
217
222
|
end
|
@@ -16,31 +16,72 @@ module Jekyll::Spaceship
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def on_handle_html(content)
|
19
|
-
|
20
|
-
|
19
|
+
emoji_filter(content, 'pre code') do |emoji|
|
20
|
+
# mark current file has been handled
|
21
|
+
self.handled = true
|
22
|
+
|
23
|
+
# here is the replacement content
|
24
|
+
"<img class=\"#{config['css']['class']}\""\
|
25
|
+
" title=\":#{emoji.name}:\""\
|
26
|
+
" alt=\":#{emoji.name}:\""\
|
27
|
+
" raw=\"#{emoji.raw}\""\
|
28
|
+
" src=\"#{config['src']}#{emoji.image_filename}\""\
|
29
|
+
" style=\"vertical-align: middle; display: inline;"\
|
30
|
+
" max-width: 1em; visibility: hidden;\""\
|
31
|
+
" onload=\"this.style.visibility='visible'\""\
|
32
|
+
" onerror=\"this.replaceWith(this.getAttribute('raw'))\">"\
|
33
|
+
"</img>"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def emoji_filter(content, selector)
|
38
|
+
# use nokogiri to parse html
|
39
|
+
doc = Nokogiri::HTML(content)
|
40
|
+
|
41
|
+
body = doc.at('body')
|
42
|
+
|
43
|
+
# in case of a page has no the body node, especially when your
|
44
|
+
# page's layout field of front matter is nil or unavailable
|
45
|
+
return content if body.nil?
|
46
|
+
|
47
|
+
# filter nodes (pre, code)
|
48
|
+
nodes = body.css(selector)
|
49
|
+
nodes.each do |node|
|
50
|
+
# handle emoji markup
|
51
|
+
node.inner_html = node.inner_html.gsub(
|
52
|
+
/:([\w\d+-]+?):/, '\:\1\:'
|
53
|
+
)
|
54
|
+
end
|
55
|
+
|
56
|
+
# parse the emoji
|
57
|
+
content = body.inner_html
|
58
|
+
content.scan(/(?<!\\):([\w\d+-]+?)(?<!\\):/) do |match|
|
59
|
+
# Skip invalid emoji name
|
21
60
|
emoji = Emoji.find_by_alias match[0]
|
22
61
|
next if emoji.nil?
|
23
|
-
self.handled = true
|
24
62
|
|
25
63
|
# escape plus sign
|
26
64
|
emoji_name = emoji.name.gsub('+', '\\\+')
|
27
|
-
|
65
|
+
|
66
|
+
result = yield emoji
|
67
|
+
next if result.nil?
|
28
68
|
|
29
69
|
content = content.gsub(
|
30
70
|
/(?<!\=")\s*:#{emoji_name}:\s*(?!"\s)/,
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
71
|
+
result)
|
72
|
+
end
|
73
|
+
|
74
|
+
body.inner_html = content
|
75
|
+
|
76
|
+
# restore nodes (pre, code)
|
77
|
+
nodes.each do |node|
|
78
|
+
# handle emoji markup
|
79
|
+
node.inner_html = node.inner_html.gsub(
|
80
|
+
/\\:([\w\d+-]+?)\\:/, ':\1:'
|
41
81
|
)
|
42
82
|
end
|
43
|
-
|
83
|
+
|
84
|
+
doc.to_html
|
44
85
|
end
|
45
86
|
end
|
46
87
|
end
|
@@ -11,14 +11,45 @@ module Jekyll::Spaceship
|
|
11
11
|
'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js',
|
12
12
|
],
|
13
13
|
'config' => {
|
14
|
-
'tex' => {
|
14
|
+
'tex' => {
|
15
|
+
'inlineMath' => [['$','$'], ['\\(','\\)']],
|
16
|
+
'displayMath' => [['$$','$$'], ['\\[','\\]']]
|
17
|
+
},
|
15
18
|
'svg': { 'fontCache': 'global' }
|
19
|
+
},
|
20
|
+
'optimize' => {
|
21
|
+
'enabled' => true,
|
22
|
+
'include' => [],
|
23
|
+
'exclude' => []
|
16
24
|
}
|
17
25
|
}
|
18
26
|
end
|
19
27
|
|
20
28
|
def process?
|
21
|
-
return true if Type.html?(output_ext)
|
29
|
+
return true if Type.html?(output_ext) or Type.markdown?(output_ext)
|
30
|
+
end
|
31
|
+
|
32
|
+
def on_handle_markdown(content)
|
33
|
+
# pre-handle mathjax expressions in markdown
|
34
|
+
patterns = get_math_patterns()
|
35
|
+
patterns['include'].each do |pattern|
|
36
|
+
content.scan(pattern) do |result|
|
37
|
+
expr = result[0]
|
38
|
+
body = result[1]
|
39
|
+
next if body.size.zero?
|
40
|
+
is_excluded = false
|
41
|
+
patterns['exclude'].each do |pe|
|
42
|
+
break is_excluded = true if expr.match(/#{pe}/)
|
43
|
+
end
|
44
|
+
next if is_excluded
|
45
|
+
escaped_expr = expr
|
46
|
+
.gsub(/(?<!^)\\(?!\S$)/, '\\\\\\\\')
|
47
|
+
.gsub(/(?<!\\)\$\$/, '\\\$\\\$')
|
48
|
+
.gsub(/\\ /, '\\\\\\ ')
|
49
|
+
content = content.gsub(expr, escaped_expr)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
content
|
22
53
|
end
|
23
54
|
|
24
55
|
def on_handle_html(content)
|
@@ -45,22 +76,67 @@ module Jekyll::Spaceship
|
|
45
76
|
end
|
46
77
|
|
47
78
|
def has_mathjax_expression?(doc)
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
79
|
+
return true unless config['optimize']['enabled'] == true
|
80
|
+
scan_mathjax_expression(doc) do
|
81
|
+
return true
|
82
|
+
end
|
83
|
+
false
|
84
|
+
end
|
85
|
+
|
86
|
+
def get_math_patterns()
|
87
|
+
patterns = []
|
88
|
+
math_patterns = []
|
89
|
+
['tex', 'tex2jax'].each do |t|
|
90
|
+
['inlineMath', 'displayMath'].each do |m|
|
91
|
+
r = config.dig('config', t, m)
|
92
|
+
r&.each do |i|
|
93
|
+
btag = Regexp.escape(i[0])
|
94
|
+
etag = Regexp.escape(i[1])
|
95
|
+
patterns <<= /((?<!\\\\)#{btag}(.*?)(?<!\\\\)#{etag})/
|
96
|
+
end
|
54
97
|
end
|
55
98
|
end
|
99
|
+
config['optimize']['include'].each do |pattern|
|
100
|
+
patterns <<= /(#{pattern})/
|
101
|
+
end
|
102
|
+
{
|
103
|
+
'include' => patterns,
|
104
|
+
'exclude' => config['optimize']['exclude']
|
105
|
+
}
|
106
|
+
end
|
56
107
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
108
|
+
def scan_mathjax_expression(doc, &block)
|
109
|
+
patterns = get_math_patterns()
|
110
|
+
doc = doc.clone
|
111
|
+
|
112
|
+
# remove code, pre, figure nodes
|
113
|
+
doc.css('body code, body pre, body figure').each do |node|
|
114
|
+
node.remove
|
115
|
+
end
|
116
|
+
|
117
|
+
# remove scripting mathjax expression
|
118
|
+
doc.css('body script').each do |node|
|
119
|
+
next if node['type']&.match(/math\/tex/)
|
120
|
+
node.remove
|
121
|
+
end
|
122
|
+
|
123
|
+
# scan mathjax expressions
|
124
|
+
doc.css('body *').each do |node|
|
125
|
+
patterns['include'].each do |pattern|
|
126
|
+
# check normal mathjax expression
|
127
|
+
node.content.scan(pattern) do |result|
|
128
|
+
expr = result[0]
|
129
|
+
body = result[1]
|
130
|
+
next if body.size.zero?
|
131
|
+
is_excluded = false
|
132
|
+
patterns['exclude'].each do |pe|
|
133
|
+
break is_excluded = true if expr.match(/#{pe}/)
|
134
|
+
end
|
135
|
+
next if is_excluded
|
136
|
+
block.call(node, expr)
|
137
|
+
end
|
61
138
|
end
|
62
139
|
end
|
63
|
-
false
|
64
140
|
end
|
65
141
|
end
|
66
142
|
end
|
@@ -42,7 +42,7 @@ module Jekyll::Spaceship
|
|
42
42
|
handle_media(element, {
|
43
43
|
media_type: 'audio',
|
44
44
|
host: '(https?:\\/\\/)?.*\\/',
|
45
|
-
id: '(.+?\\.(mp3|wav|ogg|mid|midi|aac|wma))'
|
45
|
+
id: '(.+?\\.(mp3|wav|ogg|mid|midi|aac|wma))'
|
46
46
|
})
|
47
47
|
end
|
48
48
|
|
@@ -53,7 +53,7 @@ module Jekyll::Spaceship
|
|
53
53
|
# 
|
54
54
|
def handle_normal_video(element)
|
55
55
|
handle_media(element, {
|
56
|
-
media_type: '
|
56
|
+
media_type: 'video',
|
57
57
|
host: '(https?:\\/\\/)?.*\\/',
|
58
58
|
id: '(.+?\\.(avi|mp4|webm|ogg|ogv|flv|mkv|mov|wmv|3gp|rmvb|asf))'
|
59
59
|
})
|
@@ -90,8 +90,8 @@ module Jekyll::Spaceship
|
|
90
90
|
def handle_dailymotion(element)
|
91
91
|
handle_media(element, {
|
92
92
|
media_type: 'iframe',
|
93
|
-
host: '(https?:)
|
94
|
-
id: '(
|
93
|
+
host: '(https?:)?\\/\\/(?>www\\.)?dai\\.?ly(?>motion\\.com\\/video)?\\/',
|
94
|
+
id: '([a-zA-Z0-9\\_\\-]+)',
|
95
95
|
base_url: "https://www.dailymotion.com/embed/video/"
|
96
96
|
})
|
97
97
|
end
|
@@ -128,7 +128,7 @@ module Jekyll::Spaceship
|
|
128
128
|
src = element.get_attribute('src')
|
129
129
|
title = element.get_attribute('title')
|
130
130
|
id = data[:id_from] === 'html' ? '()' : data[:id]
|
131
|
-
match_data = src
|
131
|
+
match_data = src&.match(/#{host}#{id}\S*/)
|
132
132
|
return if match_data.nil?
|
133
133
|
|
134
134
|
media_type = data[:media_type]
|
@@ -158,6 +158,10 @@ module Jekyll::Spaceship
|
|
158
158
|
cfg['loop'] = qs['loop'] || data[:loop] || cfg['loop']
|
159
159
|
cfg['style'] += ';display: none;' if qs['hidden']
|
160
160
|
handle_audio(element, { cfg: cfg })
|
161
|
+
when 'video'
|
162
|
+
cfg['autoplay'] = qs['autoplay'] || data[:autoplay] || cfg['autoplay']
|
163
|
+
cfg['loop'] = qs['loop'] || data[:loop] || cfg['loop']
|
164
|
+
handle_video(element, { cfg: cfg })
|
161
165
|
when 'iframe'
|
162
166
|
cfg['title'] = title
|
163
167
|
cfg['width'] = qs['width'] || data[:width] || cfg['width']
|
@@ -179,12 +183,32 @@ module Jekyll::Spaceship
|
|
179
183
|
" src=\"#{cfg['src']}\""\
|
180
184
|
" style=\"#{cfg['style']}\""\
|
181
185
|
" controls>" \
|
182
|
-
"
|
186
|
+
" Your browser doesn't support HTML5 audio."\
|
183
187
|
" Here is a <a href=\"#{cfg['src']}\">link to download the audio</a>"\
|
184
|
-
"instead.
|
188
|
+
" instead."\
|
185
189
|
"</audio>"
|
186
|
-
doc = Nokogiri::
|
187
|
-
element.
|
190
|
+
doc = Nokogiri::HTML(html)
|
191
|
+
return if element.parent.nil?
|
192
|
+
element.replace(doc.at('body').children.first)
|
193
|
+
end
|
194
|
+
|
195
|
+
def handle_video(element, data)
|
196
|
+
cfg = data[:cfg]
|
197
|
+
html = "<video"\
|
198
|
+
" id=\"#{cfg['id']}\""\
|
199
|
+
" class=\"#{cfg['class']}\""\
|
200
|
+
" style=\"#{cfg['style']}\""\
|
201
|
+
" #{cfg['autoplay'] ? 'autoplay' : ''}"\
|
202
|
+
" #{cfg['loop'] ? 'loop' : ''}"\
|
203
|
+
" controls>" \
|
204
|
+
" <source src=\"#{cfg['src']}\">" \
|
205
|
+
" Your browser doesn't support HTML5 video."\
|
206
|
+
" Here is a <a href=\"#{cfg['src']}\">link to download the video</a>"\
|
207
|
+
" instead."\
|
208
|
+
"</video>"
|
209
|
+
doc = Nokogiri::HTML(html)
|
210
|
+
return if element.parent.nil?
|
211
|
+
element.replace(doc.at('body').children.first)
|
188
212
|
end
|
189
213
|
|
190
214
|
def handle_iframe(element, data)
|
@@ -201,8 +225,9 @@ module Jekyll::Spaceship
|
|
201
225
|
" frameborder=\"#{cfg['frameborder']}\""\
|
202
226
|
" allowfullscreen>"\
|
203
227
|
"</iframe>"
|
204
|
-
doc = Nokogiri::
|
205
|
-
element.
|
228
|
+
doc = Nokogiri::HTML(html)
|
229
|
+
return if element.parent.nil?
|
230
|
+
element.replace(doc.at('body').children.first)
|
206
231
|
end
|
207
232
|
|
208
233
|
def get_id_from_html(url, pattern)
|
@@ -18,13 +18,21 @@ module Jekyll::Spaceship
|
|
18
18
|
end
|
19
19
|
if references.size > 0
|
20
20
|
content.scan(/[^\n]*(?<!\\)\|[^\n]*/) do |result|
|
21
|
+
replace = result
|
21
22
|
references.each do |key, val|
|
22
|
-
replace =
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
content = content.gsub(result, replace)
|
23
|
+
replace = replace.gsub(
|
24
|
+
/\[([^\n\]]*?)\]\s*\[#{Regexp.escape(key)}\]/,
|
25
|
+
"[\\1](#{val})"
|
26
|
+
)
|
27
27
|
end
|
28
|
+
references.each do |key, val|
|
29
|
+
replace = replace.gsub(
|
30
|
+
/\[#{Regexp.escape(key)}\](?!\s*\(.*?\))/,
|
31
|
+
"[#{key}](#{val})"
|
32
|
+
)
|
33
|
+
end
|
34
|
+
next if result == replace
|
35
|
+
content = content.gsub(result, replace)
|
28
36
|
end
|
29
37
|
end
|
30
38
|
|
@@ -43,7 +51,7 @@ module Jekyll::Spaceship
|
|
43
51
|
.gsub(/((?<!\\)\${1,2})[^\n]*?\1/, '')
|
44
52
|
.match(/(?<!\\)\|/)
|
45
53
|
replace = result.gsub(
|
46
|
-
/(?<!(?<!\\)\\)(\*|\$|\[|\(|\"|_)/, '\\\\\\\\\1')
|
54
|
+
/(?<!(?<!\\)\\)(\*|\$|\[(?!\^)|\(|\"|_)/, '\\\\\\\\\1')
|
47
55
|
next if result == replace
|
48
56
|
content = content.gsub(result, replace)
|
49
57
|
end
|
@@ -143,10 +151,10 @@ module Jekyll::Spaceship
|
|
143
151
|
end
|
144
152
|
end
|
145
153
|
|
146
|
-
result = cell.
|
154
|
+
result = cell.inner_html.match(/(\|)+$/)
|
147
155
|
return if result.nil?
|
148
156
|
|
149
|
-
cell.
|
157
|
+
cell.inner_html = cell.inner_html.gsub(/(\|)+$/, '')
|
150
158
|
result = result[0]
|
151
159
|
colspan = result.scan(/\|/).count
|
152
160
|
scope.row.colspan += colspan
|
@@ -203,8 +211,8 @@ module Jekyll::Spaceship
|
|
203
211
|
|
204
212
|
# handle rowspan
|
205
213
|
span_cell = scope.table.span_row_cells[scope.row.col_index]
|
206
|
-
if span_cell and cell.
|
207
|
-
cell.
|
214
|
+
if span_cell and cell.inner_html.match(/^\s*\^{2}/)
|
215
|
+
cell.inner_html = cell.inner_html.gsub(/^\s*\^{2}/, '')
|
208
216
|
span_cell.inner_html += "\n<br>\n#{cell.inner_html}"
|
209
217
|
rowspan = span_cell.get_attribute('rowspan') || 1
|
210
218
|
rowspan = rowspan.to_i + 1
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jekyll-spaceship
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- jeffreytse
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-04-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: jekyll
|