jekyll-spaceship 0.9.1 → 0.9.6
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/.rspec +3 -0
- data/.travis.yml +6 -6
- data/README.md +13 -6
- data/lib/jekyll-spaceship/cores/config.rb +14 -0
- data/lib/jekyll-spaceship/cores/manager.rb +5 -0
- data/lib/jekyll-spaceship/cores/processor.rb +95 -6
- data/lib/jekyll-spaceship/processors/mathjax-processor.rb +79 -13
- data/lib/jekyll-spaceship/processors/media-processor.rb +72 -81
- data/lib/jekyll-spaceship/processors/mermaid-processor.rb +6 -20
- data/lib/jekyll-spaceship/processors/plantuml-processor.rb +8 -22
- data/lib/jekyll-spaceship/processors/table-processor.rb +3 -1
- data/lib/jekyll-spaceship/version.rb +1 -1
- metadata +7 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 917f5191110c86af367498a90d9ad362185254fdfc30f54eeb48705159b72db7
|
4
|
+
data.tar.gz: 23e627f48d83363b2b473d2c080c98d327ddc51d982290209e218ff755a8920e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: daf20ba10a46e6f8538a02b84153bb19f3371e4ea58b689f4c520a04eb7041e76f172ac5886fca2e8a6e9140515fc7afdb30afec97bdda38d99ed43df6ecb3e7
|
7
|
+
data.tar.gz: '089e665d0359d9c0bfe0e37c1e91dfb63c6bc1dacc2c7f928e617c9d3cd1d8af959005a9cc70fca63f05a3ab5c662a24ac2ebaed113073483bc71676146bb12f'
|
data/.rspec
ADDED
data/.travis.yml
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
language: ruby
|
2
2
|
cache: bundler
|
3
3
|
rvm:
|
4
|
-
- 2.7
|
5
|
-
- 2.3
|
4
|
+
- 2.7
|
5
|
+
- 2.3
|
6
6
|
env:
|
7
7
|
global:
|
8
|
-
|
8
|
+
- NOKOGIRI_USE_SYSTEM_LIBRARIES=true
|
9
9
|
matrix:
|
10
|
-
|
10
|
+
- JEKYLL_VERSION="~> 3.8"
|
11
11
|
matrix:
|
12
12
|
include:
|
13
13
|
- rvm: 2.7
|
@@ -15,8 +15,8 @@ matrix:
|
|
15
15
|
- rvm: 2.7
|
16
16
|
env: JEKYLL_VERSION=">= 4.0.0"
|
17
17
|
before_install:
|
18
|
-
- gem update --system
|
19
|
-
- gem install bundler
|
18
|
+
- gem update --system
|
19
|
+
- gem install bundler
|
20
20
|
before_script: bundle update
|
21
21
|
script: script/cibuild
|
22
22
|
notifications:
|
data/README.md
CHANGED
@@ -146,7 +146,7 @@ plugins:
|
|
146
146
|
|
147
147
|
**💡 Tip:** Note that GitHub Pages runs in `safe` mode and only allows [a set of whitelisted plugins](https://pages.github.com/versions/). To use the gem in GitHub Pages, you need to build locally or use CI (e.g. [travis](https://travis-ci.org/), [github workflow](https://help.github.com/en/actions/configuring-and-managing-workflows/configuring-a-workflow)) and deploy to your `gh-pages` branch.
|
148
148
|
|
149
|
-
### Additions
|
149
|
+
### Additions for Unlimited GitHub Pages
|
150
150
|
|
151
151
|
* Here is a GitHub Action named [jekyll-deploy-action](https://github.com/jeffreytse/jekyll-deploy-action) for Jekyll site deployment conveniently. 👍
|
152
152
|
* Here is a [Jekyll site](https://github.com/jeffreytse/jekyll-jeffreytse-blog) using Travis to build and deploy to GitHub Pages for your references.
|
@@ -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:
|
@@ -186,7 +193,7 @@ jekyll-spaceship:
|
|
186
193
|
syntax:
|
187
194
|
code: 'plantuml!'
|
188
195
|
custom: ['@startuml', '@enduml']
|
189
|
-
src: http://www.plantuml.com/plantuml/
|
196
|
+
src: http://www.plantuml.com/plantuml/svg/
|
190
197
|
mermaid-processor:
|
191
198
|
mode: default # mode value 'pre-fetch' for fetching image at building stage
|
192
199
|
css:
|
@@ -637,7 +644,7 @@ Code above would be parsed as:
|
|
637
644
|
|
638
645
|
### 3. PlantUML Usage
|
639
646
|
|
640
|
-
[PlantUML](
|
647
|
+
[PlantUML](https://plantuml.com) is a component that allows to quickly write:
|
641
648
|
|
642
649
|
- sequence diagram,
|
643
650
|
- use case diagram,
|
@@ -966,7 +973,7 @@ Automatically adds a `target="_blank" rel="noopener noreferrer"` attribute to al
|
|
966
973
|
jekyll-spaceship:
|
967
974
|
element-processor:
|
968
975
|
css:
|
969
|
-
- a: #
|
976
|
+
- a: # Replace all `a` tags
|
970
977
|
props:
|
971
978
|
class: ['(^.*$)', '\0 ext-link'] # Add `ext-link` to class by regex pattern
|
972
979
|
target: _blank # Replace `target` value to `_blank`
|
@@ -982,7 +989,7 @@ Automatically adds `loading="lazy"` to `img` and `iframe` tags to natively load
|
|
982
989
|
jekyll-spaceship:
|
983
990
|
element-processor:
|
984
991
|
css:
|
985
|
-
- a: #
|
992
|
+
- a: # Replace all `a` tags
|
986
993
|
props: #
|
987
994
|
loading: lazy # Replace `loading` value to `lazy`
|
988
995
|
```
|
@@ -997,7 +1004,7 @@ See the following examples to prevent lazy loading.
|
|
997
1004
|
jekyll-spaceship:
|
998
1005
|
element-processor:
|
999
1006
|
css:
|
1000
|
-
- a: #
|
1007
|
+
- a: # Replace all `a` tags
|
1001
1008
|
props: #
|
1002
1009
|
loading: eager # Replace `loading` value to `eager`
|
1003
1010
|
```
|
@@ -5,6 +5,7 @@ module Jekyll::Spaceship
|
|
5
5
|
CONFIG_NAME = 'jekyll-spaceship'
|
6
6
|
DEFAULT_CONFIG = {
|
7
7
|
'processors' => [
|
8
|
+
'cache-processor',
|
8
9
|
'table-processor',
|
9
10
|
'mathjax-processor',
|
10
11
|
'plantuml-processor',
|
@@ -31,6 +32,16 @@ module Jekyll::Spaceship
|
|
31
32
|
first.merge(second.to_h, &merger)
|
32
33
|
end
|
33
34
|
|
35
|
+
def self.deep_dig(obj, key)
|
36
|
+
if obj.respond_to?(:key?) && obj.key?(key)
|
37
|
+
obj[key]
|
38
|
+
elsif obj.respond_to?(:each)
|
39
|
+
result = nil
|
40
|
+
obj.find { |*a| result = self.deep_dig(a.last, key) }
|
41
|
+
result
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
34
45
|
def self.store(section, default)
|
35
46
|
return @@store[section] if default.nil?
|
36
47
|
@@store[section] = deep_merge(default, @@store[section])
|
@@ -54,7 +65,10 @@ module Jekyll::Spaceship
|
|
54
65
|
def self.load_config
|
55
66
|
# post load site config for `group :jekyll_plugin`
|
56
67
|
Jekyll::Hooks.register :site, :after_init do |site|
|
68
|
+
# load config
|
57
69
|
self.load(site.config)
|
70
|
+
# dispatch site after_init event
|
71
|
+
Manager.dispatch(site, :site, :after_init)
|
58
72
|
end
|
59
73
|
end
|
60
74
|
end
|
@@ -14,6 +14,7 @@ module Jekyll::Spaceship
|
|
14
14
|
container = _register.first
|
15
15
|
events = _register.last.uniq
|
16
16
|
events = events.select do |event|
|
17
|
+
next true if event.match(/^after/)
|
17
18
|
next true if event.match(/^post/)
|
18
19
|
next events.index(event.to_s.gsub(/^pre/, 'post').to_sym).nil?
|
19
20
|
end
|
@@ -59,21 +60,25 @@ module Jekyll::Spaceship
|
|
59
60
|
def self.dispatch(page, container, event)
|
60
61
|
@@_processors.each do |processor|
|
61
62
|
processor.dispatch page, container, event
|
63
|
+
break unless processor.next?
|
62
64
|
end
|
63
65
|
if event.to_s.start_with?('post') and Type.html? output_ext(page)
|
64
66
|
self.dispatch_html_block(page)
|
65
67
|
end
|
66
68
|
@@_processors.each do |processor|
|
67
69
|
processor.on_handled if processor.handled
|
70
|
+
break unless processor.next?
|
68
71
|
end
|
69
72
|
end
|
70
73
|
|
71
74
|
def self.ext(page)
|
75
|
+
return unless page.respond_to? :path
|
72
76
|
ext = page.path.match(/\.[^.]+$/)
|
73
77
|
ext.to_s.rstrip
|
74
78
|
end
|
75
79
|
|
76
80
|
def self.output_ext(page)
|
81
|
+
return unless page.respond_to? :url_placeholders
|
77
82
|
page.url_placeholders[:output_ext]
|
78
83
|
end
|
79
84
|
|
@@ -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
|
@@ -86,6 +90,10 @@ module Jekyll::Spaceship
|
|
86
90
|
def self.config
|
87
91
|
end
|
88
92
|
|
93
|
+
def next?
|
94
|
+
true
|
95
|
+
end
|
96
|
+
|
89
97
|
def process?
|
90
98
|
Type.html?(output_ext) or Type.markdown?(ext)
|
91
99
|
end
|
@@ -116,7 +124,7 @@ module Jekyll::Spaceship
|
|
116
124
|
if self.respond_to? method
|
117
125
|
@page.content = self.pre_exclude @page.content
|
118
126
|
@page.content = self.send method, @page.content
|
119
|
-
@page.content = self.
|
127
|
+
@page.content = self.post_exclude @page.content
|
120
128
|
end
|
121
129
|
else
|
122
130
|
if Type.html? output_ext
|
@@ -151,8 +159,8 @@ module Jekyll::Spaceship
|
|
151
159
|
logger.log file
|
152
160
|
end
|
153
161
|
|
154
|
-
def
|
155
|
-
|
162
|
+
def exclusion_regexs()
|
163
|
+
regexs = []
|
156
164
|
@exclusions.each do |type|
|
157
165
|
regex = nil
|
158
166
|
if type == :code
|
@@ -162,7 +170,14 @@ module Jekyll::Spaceship
|
|
162
170
|
elsif type == :liquid_filter
|
163
171
|
regex = /((?<!\\)((\{\{[^\n]*?\}\})|(\{%[^\n]*?%\})))/
|
164
172
|
end
|
165
|
-
|
173
|
+
regexs.push regex unless regex.nil?
|
174
|
+
end
|
175
|
+
regexs
|
176
|
+
end
|
177
|
+
|
178
|
+
def pre_exclude(content, regexs = self.exclusion_regexs())
|
179
|
+
@exclusion_store = []
|
180
|
+
regexs.each do |regex|
|
166
181
|
content.scan(regex) do |match_data|
|
167
182
|
match = match_data[0]
|
168
183
|
id = @exclusion_store.size
|
@@ -173,7 +188,7 @@ module Jekyll::Spaceship
|
|
173
188
|
content
|
174
189
|
end
|
175
190
|
|
176
|
-
def
|
191
|
+
def post_exclude(content)
|
177
192
|
while @exclusion_store.size > 0
|
178
193
|
match = @exclusion_store.pop
|
179
194
|
id = @exclusion_store.size
|
@@ -183,6 +198,20 @@ module Jekyll::Spaceship
|
|
183
198
|
content
|
184
199
|
end
|
185
200
|
|
201
|
+
def get_exclusion(id)
|
202
|
+
result = nil
|
203
|
+
match_data = id.match /<!JEKYLL@(.+)@(.+)>/
|
204
|
+
unless match_data.nil?
|
205
|
+
id = match_data[2].to_i
|
206
|
+
result = {
|
207
|
+
:id => id,
|
208
|
+
:marker => match_data[0],
|
209
|
+
:content => @exclusion_store[id]
|
210
|
+
}
|
211
|
+
end
|
212
|
+
result
|
213
|
+
end
|
214
|
+
|
186
215
|
def self.escape_html(content)
|
187
216
|
# escape link
|
188
217
|
content.scan(/((https?:)?\/\/\S+\?[a-zA-Z0-9%\-_=\.&;]+)/) do |result|
|
@@ -192,5 +221,65 @@ module Jekyll::Spaceship
|
|
192
221
|
end
|
193
222
|
content
|
194
223
|
end
|
224
|
+
|
225
|
+
def self.fetch_img_data(url)
|
226
|
+
begin
|
227
|
+
res = Net::HTTP.get_response URI(url)
|
228
|
+
raise res.body unless res.is_a?(Net::HTTPSuccess)
|
229
|
+
content_type = res.header['Content-Type']
|
230
|
+
raise 'Unknown content type!' if content_type.nil?
|
231
|
+
content_body = res.body.force_encoding('UTF-8')
|
232
|
+
return {
|
233
|
+
'type' => content_type,
|
234
|
+
'body' => content_body
|
235
|
+
}
|
236
|
+
rescue StandardError => msg
|
237
|
+
logger = Logger.new(self.class_name)
|
238
|
+
logger.log msg
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
def self.make_img_tag(data)
|
243
|
+
css_class = data['class']
|
244
|
+
type = data['type']
|
245
|
+
body = data['body']
|
246
|
+
if type == 'url'
|
247
|
+
"<img class=\"#{css_class}\" src=\"#{body}\">"
|
248
|
+
elsif type.include?('svg')
|
249
|
+
body.gsub(/\<\?xml.*?\?>/, '')
|
250
|
+
.gsub(/<!--[^\0]*?-->/, '')
|
251
|
+
.sub(/<svg /, "<svg class=\"#{css_class}\" ")
|
252
|
+
else
|
253
|
+
body = Base64.encode64(body)
|
254
|
+
body = "data:#{type};base64, #{body}"
|
255
|
+
"<img class=\"#{css_class}\" src=\"#{body}\">"
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
def self.handle_bang_link(
|
260
|
+
content,
|
261
|
+
url = '(https?:)?\\/\\/.*',
|
262
|
+
title = '("(.*)".*){0,1}',
|
263
|
+
&block
|
264
|
+
)
|
265
|
+
# pre-handle reference-style links
|
266
|
+
regex = /(\[(.*)\]:\s*(#{url}\s*#{title}))/
|
267
|
+
content.scan regex do |match_data|
|
268
|
+
match = match_data[0]
|
269
|
+
ref_name = match_data[1]
|
270
|
+
ref_value = match_data[2]
|
271
|
+
content = content.gsub(match, '')
|
272
|
+
.gsub(/\!\[(.*)\]\s*\[#{ref_name}\]/,
|
273
|
+
"")
|
274
|
+
end
|
275
|
+
|
276
|
+
# handle inline-style links
|
277
|
+
regex = /(\!\[(.*)\]\(.*#{url}\s*#{title}\))/
|
278
|
+
content.scan regex do |match_data|
|
279
|
+
url = match_data[2]
|
280
|
+
title = match_data[6]
|
281
|
+
block.call(url, title)
|
282
|
+
end
|
283
|
+
end
|
195
284
|
end
|
196
285
|
end
|
@@ -11,14 +11,42 @@ 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
|
+
is_excluded = false
|
39
|
+
patterns['exclude'].each do |pe|
|
40
|
+
break is_excluded = true if expr.match(/#{pe}/)
|
41
|
+
end
|
42
|
+
next if is_excluded
|
43
|
+
escaped_expr = expr
|
44
|
+
.gsub(/(?<!^)\\(?!\S$)/, '\\\\\\\\')
|
45
|
+
.gsub(/\\ /, '\\\\\\ ')
|
46
|
+
content = content.gsub(expr, escaped_expr)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
content
|
22
50
|
end
|
23
51
|
|
24
52
|
def on_handle_html(content)
|
@@ -45,22 +73,60 @@ module Jekyll::Spaceship
|
|
45
73
|
end
|
46
74
|
|
47
75
|
def has_mathjax_expression?(doc)
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
76
|
+
return true unless config['optimize']['enabled'] == true
|
77
|
+
scan_mathjax_expression(doc) do
|
78
|
+
return true
|
79
|
+
end
|
80
|
+
false
|
81
|
+
end
|
82
|
+
|
83
|
+
def get_math_patterns()
|
84
|
+
patterns = []
|
85
|
+
math_patterns = []
|
86
|
+
['tex', 'tex2jax'].each do |t|
|
87
|
+
['inlineMath', 'displayMath'].each do |m|
|
88
|
+
r = config.dig('config', t, m)
|
89
|
+
r&.each do |i|
|
90
|
+
btag = Regexp.escape(i[0])
|
91
|
+
etag = Regexp.escape(i[1])
|
92
|
+
patterns <<= /((?<!\\\\)#{btag}.+?(?<!\\\\)#{etag})/
|
93
|
+
end
|
54
94
|
end
|
55
95
|
end
|
96
|
+
config['optimize']['include'].each do |pattern|
|
97
|
+
patterns <<= /(#{pattern})/
|
98
|
+
end
|
99
|
+
{
|
100
|
+
'include' => patterns,
|
101
|
+
'exclude' => config['optimize']['exclude']
|
102
|
+
}
|
103
|
+
end
|
56
104
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
105
|
+
def scan_mathjax_expression(doc, &block)
|
106
|
+
patterns = get_math_patterns()
|
107
|
+
doc.css('*').each do |node|
|
108
|
+
next if ['code', 'pre', 'figure'].include? node.name
|
109
|
+
next if node.ancestors('code, pre, figure').size > 0
|
110
|
+
next if node.children.size > 1
|
111
|
+
patterns['include'].each do |pattern|
|
112
|
+
# check scripting mathjax expression
|
113
|
+
if node.name == 'script'
|
114
|
+
type = node['type']
|
115
|
+
next unless type
|
116
|
+
next unless type.match(/math\/tex/)
|
117
|
+
end
|
118
|
+
# check normal mathjax expression
|
119
|
+
node.content.scan(pattern) do |result|
|
120
|
+
expr = result[0]
|
121
|
+
is_excluded = false
|
122
|
+
patterns['exclude'].each do |pe|
|
123
|
+
break is_excluded = true if expr.match(/#{pe}/)
|
124
|
+
end
|
125
|
+
next if is_excluded
|
126
|
+
block.call(node, expr)
|
127
|
+
end
|
61
128
|
end
|
62
129
|
end
|
63
|
-
false
|
64
130
|
end
|
65
131
|
end
|
66
132
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'uri'
|
4
|
+
require "nokogiri"
|
4
5
|
|
5
6
|
module Jekyll::Spaceship
|
6
7
|
class MediaProcessor < Processor
|
@@ -18,23 +19,29 @@ module Jekyll::Spaceship
|
|
18
19
|
}
|
19
20
|
end
|
20
21
|
|
21
|
-
def
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
22
|
+
def on_handle_html(content)
|
23
|
+
# use nokogiri to parse html content
|
24
|
+
doc = Nokogiri::HTML(content)
|
25
|
+
# handle each img tag
|
26
|
+
doc.css('img').each do |element|
|
27
|
+
handle_normal_audio(element)
|
28
|
+
handle_normal_video(element)
|
29
|
+
handle_youtube(element)
|
30
|
+
handle_vimeo(element)
|
31
|
+
handle_dailymotion(element)
|
32
|
+
handle_spotify(element)
|
33
|
+
handle_soundcloud(element)
|
34
|
+
end
|
35
|
+
doc.to_html
|
29
36
|
end
|
30
37
|
|
31
38
|
# Examples:
|
32
39
|
# 
|
33
40
|
# 
|
34
|
-
def handle_normal_audio(
|
35
|
-
handle_media(
|
41
|
+
def handle_normal_audio(element)
|
42
|
+
handle_media(element, {
|
36
43
|
media_type: 'audio',
|
37
|
-
host: '(https
|
44
|
+
host: '(https?:\\/\\/)?.*\\/',
|
38
45
|
id: '(.+?\\.(mp3|wav|ogg|mid|midi|aac|wma))',
|
39
46
|
})
|
40
47
|
end
|
@@ -44,10 +51,10 @@ module Jekyll::Spaceship
|
|
44
51
|
# 
|
45
52
|
# 
|
46
53
|
# 
|
47
|
-
def handle_normal_video(
|
48
|
-
handle_media(
|
54
|
+
def handle_normal_video(element)
|
55
|
+
handle_media(element, {
|
49
56
|
media_type: 'iframe',
|
50
|
-
host: '(https
|
57
|
+
host: '(https?:\\/\\/)?.*\\/',
|
51
58
|
id: '(.+?\\.(avi|mp4|webm|ogg|ogv|flv|mkv|mov|wmv|3gp|rmvb|asf))'
|
52
59
|
})
|
53
60
|
end
|
@@ -56,8 +63,8 @@ module Jekyll::Spaceship
|
|
56
63
|
# 
|
57
64
|
# 
|
58
65
|
# 
|
59
|
-
def handle_youtube(
|
60
|
-
handle_media(
|
66
|
+
def handle_youtube(element)
|
67
|
+
handle_media(element, {
|
61
68
|
media_type: 'iframe',
|
62
69
|
host: '(https?:)?\\/\\/.*youtu.*',
|
63
70
|
id: '(?<=\\?v\\=|embed\\/|\\.be\\/)([a-zA-Z0-9\\_\\-]+)',
|
@@ -68,8 +75,8 @@ module Jekyll::Spaceship
|
|
68
75
|
# Examples:
|
69
76
|
# 
|
70
77
|
# 
|
71
|
-
def handle_vimeo(
|
72
|
-
handle_media(
|
78
|
+
def handle_vimeo(element)
|
79
|
+
handle_media(element, {
|
73
80
|
media_type: 'iframe',
|
74
81
|
host: '(https?:)?\\/\\/vimeo\\.com\\/',
|
75
82
|
id: '([0-9]+)',
|
@@ -80,8 +87,8 @@ module Jekyll::Spaceship
|
|
80
87
|
# Examples:
|
81
88
|
# 
|
82
89
|
# 
|
83
|
-
def handle_dailymotion(
|
84
|
-
handle_media(
|
90
|
+
def handle_dailymotion(element)
|
91
|
+
handle_media(element, {
|
85
92
|
media_type: 'iframe',
|
86
93
|
host: '(https?:)?\\/\\/.*dai.?ly.*',
|
87
94
|
id: '(?<=video\\/|\\/)([a-zA-Z0-9\\_\\-]+)',
|
@@ -92,8 +99,8 @@ module Jekyll::Spaceship
|
|
92
99
|
# Examples:
|
93
100
|
# 
|
94
101
|
# 
|
95
|
-
def handle_spotify(
|
96
|
-
handle_media(
|
102
|
+
def handle_spotify(element)
|
103
|
+
handle_media(element, {
|
97
104
|
media_type: 'iframe',
|
98
105
|
host: '(https?:)?\\/\\/open\\.spotify\\.com\\/track\\/',
|
99
106
|
id: '(?<=track\\/)([a-zA-Z0-9\\_\\-]+)',
|
@@ -104,8 +111,8 @@ module Jekyll::Spaceship
|
|
104
111
|
|
105
112
|
# Examples:
|
106
113
|
# 
|
107
|
-
def handle_soundcloud(
|
108
|
-
handle_media(
|
114
|
+
def handle_soundcloud(element)
|
115
|
+
handle_media(element, {
|
109
116
|
media_type: 'iframe',
|
110
117
|
id_from: 'html',
|
111
118
|
host: '(https?:)?\\/\\/soundcloud\\.com\\/.+\\/[^\\?]+',
|
@@ -116,71 +123,53 @@ module Jekyll::Spaceship
|
|
116
123
|
})
|
117
124
|
end
|
118
125
|
|
119
|
-
def handle_media(
|
126
|
+
def handle_media(element, data)
|
120
127
|
host = data[:host]
|
121
|
-
|
128
|
+
src = element.get_attribute('src')
|
129
|
+
title = element.get_attribute('title')
|
130
|
+
id = data[:id_from] === 'html' ? '()' : data[:id]
|
131
|
+
match_data = src.match(/#{host}#{id}\S*/)
|
132
|
+
return if match_data.nil?
|
122
133
|
|
123
134
|
media_type = data[:media_type]
|
124
135
|
base_url = data[:base_url]
|
125
|
-
id = data[:id_from] === 'html'
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
content.scan regex do |match_data|
|
132
|
-
match = match_data[0]
|
133
|
-
ref_name = match_data[1]
|
134
|
-
ref_value = match_data[2]
|
135
|
-
content = content.gsub(match, '')
|
136
|
-
.gsub(/\!\[(.*)\]\s*\[#{ref_name}\]/,
|
137
|
-
"")
|
136
|
+
id = data[:id_from] === 'html' \
|
137
|
+
? get_id_from_html(src, data[:id]) \
|
138
|
+
: match_data[2]
|
139
|
+
qs = src.match(/(?<=\?)(\S*?)$/)
|
140
|
+
qs = Hash[URI.decode_www_form(qs.to_s)].reject do |k, v|
|
141
|
+
next true if v == id or v == ''
|
138
142
|
end
|
139
143
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
: match_data[4]
|
147
|
-
title = match_data[6]
|
148
|
-
qs = url.match(/(?<=\?)(\S*?)$/)
|
149
|
-
qs = Hash[URI.decode_www_form(qs.to_s)].reject do |k, v|
|
150
|
-
next true if v == id or v == ''
|
151
|
-
end
|
152
|
-
|
153
|
-
cfg = self.config['default'].clone
|
154
|
-
cfg['id'] = qs['id'] || cfg['id']
|
155
|
-
cfg['class'] = qs['class'] || cfg['class']
|
156
|
-
cfg['style'] = qs['style'] || cfg['style']
|
157
|
-
cfg['id'] = cfg['id'].gsub('{id}', id)
|
158
|
-
cfg['class'] = cfg['class'].gsub('{id}', id)
|
144
|
+
cfg = self.config['default'].clone
|
145
|
+
cfg['id'] = qs['id'] || cfg['id']
|
146
|
+
cfg['class'] = qs['class'] || cfg['class']
|
147
|
+
cfg['style'] = qs['style'] || cfg['style']
|
148
|
+
cfg['id'] = cfg['id'].gsub('{id}', id)
|
149
|
+
cfg['class'] = cfg['class'].gsub('{id}', id)
|
159
150
|
|
160
|
-
|
161
|
-
|
162
|
-
|
151
|
+
cfg['src'] = URI(base_url ? "#{base_url}#{id}" : src).tap do |v|
|
152
|
+
v.query = URI.encode_www_form(qs) if qs.size > 0
|
153
|
+
end
|
163
154
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
end
|
178
|
-
self.handled = true
|
155
|
+
case media_type
|
156
|
+
when 'audio'
|
157
|
+
cfg['autoplay'] = qs['autoplay'] || data[:autoplay] || cfg['autoplay']
|
158
|
+
cfg['loop'] = qs['loop'] || data[:loop] || cfg['loop']
|
159
|
+
cfg['style'] += ';display: none;' if qs['hidden']
|
160
|
+
handle_audio(element, { cfg: cfg })
|
161
|
+
when 'iframe'
|
162
|
+
cfg['title'] = title
|
163
|
+
cfg['width'] = qs['width'] || data[:width] || cfg['width']
|
164
|
+
cfg['height'] = qs['height'] || data[:height] || cfg['height']
|
165
|
+
cfg['frameborder'] = qs['frameborder'] || cfg['frameborder']
|
166
|
+
cfg['allow'] ||= cfg['allow']
|
167
|
+
handle_iframe(element, { cfg: cfg })
|
179
168
|
end
|
180
|
-
|
169
|
+
self.handled = true
|
181
170
|
end
|
182
171
|
|
183
|
-
def handle_audio(
|
172
|
+
def handle_audio(element, data)
|
184
173
|
cfg = data[:cfg]
|
185
174
|
html = "<audio"\
|
186
175
|
" id=\"#{cfg['id']}\""\
|
@@ -194,10 +183,11 @@ module Jekyll::Spaceship
|
|
194
183
|
" Here is a <a href=\"#{cfg['src']}\">link to download the audio</a>"\
|
195
184
|
"instead. </p>"\
|
196
185
|
"</audio>"
|
197
|
-
|
186
|
+
doc = Nokogiri::XML(html)
|
187
|
+
element.replace(doc.children.first)
|
198
188
|
end
|
199
189
|
|
200
|
-
def handle_iframe(
|
190
|
+
def handle_iframe(element, data)
|
201
191
|
cfg = data[:cfg]
|
202
192
|
html = "<iframe"\
|
203
193
|
" id=\"#{cfg['id']}\""\
|
@@ -211,7 +201,8 @@ module Jekyll::Spaceship
|
|
211
201
|
" frameborder=\"#{cfg['frameborder']}\""\
|
212
202
|
" allowfullscreen>"\
|
213
203
|
"</iframe>"
|
214
|
-
|
204
|
+
doc = Nokogiri::XML(html)
|
205
|
+
element.replace(doc.children.first)
|
215
206
|
end
|
216
207
|
|
217
208
|
def get_id_from_html(url, pattern)
|
@@ -62,18 +62,20 @@ module Jekyll::Spaceship
|
|
62
62
|
def handle_mermaid(code)
|
63
63
|
# encode to UTF-8
|
64
64
|
code = code.encode('UTF-8')
|
65
|
-
|
66
65
|
url = get_url(code)
|
67
66
|
|
68
67
|
# render mode
|
69
68
|
case self.config['mode']
|
70
69
|
when 'pre-fetch'
|
71
|
-
|
70
|
+
data = self.class.fetch_img_data(url)
|
71
|
+
end
|
72
|
+
if data.nil?
|
73
|
+
data = { 'type' => 'url', 'body' => url }
|
72
74
|
end
|
73
75
|
|
74
76
|
# return img tag
|
75
|
-
|
76
|
-
|
77
|
+
data['class'] = self.config['css']['class']
|
78
|
+
self.class.make_img_tag(data)
|
77
79
|
end
|
78
80
|
|
79
81
|
def get_url(code)
|
@@ -96,21 +98,5 @@ module Jekyll::Spaceship
|
|
96
98
|
raise "No supported src ! #{src}"
|
97
99
|
end
|
98
100
|
end
|
99
|
-
|
100
|
-
def get_mermaid_img_data(url)
|
101
|
-
data = ''
|
102
|
-
begin
|
103
|
-
res = Net::HTTP.get_response URI(url)
|
104
|
-
raise res.body unless res.is_a?(Net::HTTPSuccess)
|
105
|
-
data = Base64.encode64(res.body)
|
106
|
-
content_type = res.header['Content-Type']
|
107
|
-
raise 'Unknown content type!' if content_type.nil?
|
108
|
-
data = "data:#{content_type};base64, #{data}"
|
109
|
-
rescue StandardError => msg
|
110
|
-
data = url
|
111
|
-
logger.log msg
|
112
|
-
end
|
113
|
-
data
|
114
|
-
end
|
115
101
|
end
|
116
102
|
end
|
@@ -17,7 +17,7 @@ module Jekyll::Spaceship
|
|
17
17
|
'css' => {
|
18
18
|
'class' => 'plantuml'
|
19
19
|
},
|
20
|
-
'src' => 'http://www.plantuml.com/plantuml/
|
20
|
+
'src' => 'http://www.plantuml.com/plantuml/svg/'
|
21
21
|
}
|
22
22
|
end
|
23
23
|
|
@@ -59,18 +59,20 @@ module Jekyll::Spaceship
|
|
59
59
|
def handle_plantuml(code)
|
60
60
|
# wrap plantuml code
|
61
61
|
code = "@startuml#{code}@enduml".encode('UTF-8')
|
62
|
-
|
63
|
-
url = get_url(code)
|
62
|
+
url = self.get_url(code)
|
64
63
|
|
65
64
|
# render mode
|
66
65
|
case self.config['mode']
|
67
66
|
when 'pre-fetch'
|
68
|
-
|
67
|
+
data = self.class.fetch_img_data(url)
|
68
|
+
end
|
69
|
+
if data.nil?
|
70
|
+
data = { 'type' => 'url', 'body' => url }
|
69
71
|
end
|
70
72
|
|
71
73
|
# return img tag
|
72
|
-
|
73
|
-
|
74
|
+
data['class'] = self.config['css']['class']
|
75
|
+
self.class.make_img_tag(data)
|
74
76
|
end
|
75
77
|
|
76
78
|
def get_url(code)
|
@@ -87,21 +89,5 @@ module Jekyll::Spaceship
|
|
87
89
|
raise "No supported src ! #{src}"
|
88
90
|
end
|
89
91
|
end
|
90
|
-
|
91
|
-
def get_plantuml_img_data(url)
|
92
|
-
data = ''
|
93
|
-
begin
|
94
|
-
res = Net::HTTP.get_response URI(url)
|
95
|
-
raise res.body unless res.is_a?(Net::HTTPSuccess)
|
96
|
-
data = Base64.encode64(res.body)
|
97
|
-
content_type = res.header['Content-Type']
|
98
|
-
raise 'Unknown content type!' if content_type.nil?
|
99
|
-
data = "data:#{content_type};base64, #{data}"
|
100
|
-
rescue StandardError => msg
|
101
|
-
data = url
|
102
|
-
logger.log msg
|
103
|
-
end
|
104
|
-
data
|
105
|
-
end
|
106
92
|
end
|
107
93
|
end
|
@@ -43,7 +43,7 @@ module Jekyll::Spaceship
|
|
43
43
|
.gsub(/((?<!\\)\${1,2})[^\n]*?\1/, '')
|
44
44
|
.match(/(?<!\\)\|/)
|
45
45
|
replace = result.gsub(
|
46
|
-
/(?<!(?<!\\)\\)(\*|\$|\[|\(|\"|_)/, '\\\\\\\\\1')
|
46
|
+
/(?<!(?<!\\)\\)(\*|\$|\[(?!\^)|\(|\"|_)/, '\\\\\\\\\1')
|
47
47
|
next if result == replace
|
48
48
|
content = content.gsub(result, replace)
|
49
49
|
end
|
@@ -305,10 +305,12 @@ module Jekyll::Spaceship
|
|
305
305
|
cvter = self.converter('markdown')
|
306
306
|
return if cvter.nil?
|
307
307
|
content = cell.inner_html
|
308
|
+
content = self.pre_exclude(content, [/(\<code.*\>.*\<\/code\>)/])
|
308
309
|
.gsub(/(?<!\\)\|/, '\\|')
|
309
310
|
.gsub(/^\s+|\s+$/, '')
|
310
311
|
.gsub(/</, '<')
|
311
312
|
.gsub(/>/, '>')
|
313
|
+
content = self.post_exclude(content)
|
312
314
|
content = cvter.convert(content)
|
313
315
|
content = Nokogiri::HTML.fragment(content)
|
314
316
|
if content.children.first&.name == 'p'
|
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.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- jeffreytse
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-12-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: jekyll
|
@@ -114,7 +114,7 @@ dependencies:
|
|
114
114
|
- - "~>"
|
115
115
|
- !ruby/object:Gem::Version
|
116
116
|
version: '3.0'
|
117
|
-
description:
|
117
|
+
description:
|
118
118
|
email:
|
119
119
|
- jeffreytse.mail@gmail.com
|
120
120
|
executables: []
|
@@ -124,6 +124,7 @@ files:
|
|
124
124
|
- ".codeclimate.yml"
|
125
125
|
- ".github/FUNDING.yml"
|
126
126
|
- ".gitignore"
|
127
|
+
- ".rspec"
|
127
128
|
- ".travis.yml"
|
128
129
|
- Gemfile
|
129
130
|
- LICENSE.txt
|
@@ -154,7 +155,7 @@ homepage: https://github.com/jeffreytse/jekyll-spaceship
|
|
154
155
|
licenses:
|
155
156
|
- MIT
|
156
157
|
metadata: {}
|
157
|
-
post_install_message:
|
158
|
+
post_install_message:
|
158
159
|
rdoc_options: []
|
159
160
|
require_paths:
|
160
161
|
- lib
|
@@ -170,7 +171,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
170
171
|
version: '0'
|
171
172
|
requirements: []
|
172
173
|
rubygems_version: 3.0.8
|
173
|
-
signing_key:
|
174
|
+
signing_key:
|
174
175
|
specification_version: 4
|
175
176
|
summary: A Jekyll plugin to provide powerful supports for table, mathjax, plantuml,
|
176
177
|
mermaid, emoji, video, audio, youtube, vimeo, dailymotion, spotify, soundcloud,
|