jekyll-spaceship 0.9.1 → 0.9.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 989c96c9ba4f7b3d1ec891d43022360ab1bea0a4de2956e8a94c24c927df6ca1
4
- data.tar.gz: 3aa37c0d529d883e2cef637556d65f65d31e9a5c8ee304ca2a2ee01de11ac527
3
+ metadata.gz: 917f5191110c86af367498a90d9ad362185254fdfc30f54eeb48705159b72db7
4
+ data.tar.gz: 23e627f48d83363b2b473d2c080c98d327ddc51d982290209e218ff755a8920e
5
5
  SHA512:
6
- metadata.gz: a7bbab4048b639e86cf01e88132c4b9de13acf9651667bcefc15eaaae6c57a3663b69498ebf6172037268ecb63a456a8cf53c751036717f471a8e060a7b5a14b
7
- data.tar.gz: 56aab57a999fd3604f1b95475662478c8520ab703a9ae2405f863072c92c012cb1dec094814d17d6e1696ce2d3eea7fb0987e78a77a6c7a8465b95db61826702
6
+ metadata.gz: daf20ba10a46e6f8538a02b84153bb19f3371e4ea58b689f4c520a04eb7041e76f172ac5886fca2e8a6e9140515fc7afdb30afec97bdda38d99ed43df6ecb3e7
7
+ data.tar.gz: '089e665d0359d9c0bfe0e37c1e91dfb63c6bc1dacc2c7f928e617c9d3cd1d8af959005a9cc70fca63f05a3ab5c662a24ac2ebaed113073483bc71676146bb12f'
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --format progress
3
+ --require spec_helper
@@ -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
- - NOKOGIRI_USE_SYSTEM_LIBRARIES=true
8
+ - NOKOGIRI_USE_SYSTEM_LIBRARIES=true
9
9
  matrix:
10
- - JEKYLL_VERSION="~> 3.8"
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/png/
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](http://plantuml.sourceforge.net/) is a component that allows to quickly write:
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: # Replce all `a` tags
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: # Replce all `a` tags
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: # Replce all `a` tags
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.name.split('::').last
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.after_exclude @page.content
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 pre_exclude(content)
155
- @exclusion_store = []
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
- next if regex.nil?
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 after_exclude(content)
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
+ "![\1](#{ref_value})")
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' => { 'inlineMath' => [['$','$'], ['\\(','\\)']] },
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
- doc.css('*').each do |node|
49
- if node.content.match(/(?<!\\)\$.+(?<!\\)\$/)
50
- return true
51
- end
52
- if node.content.match(/(?<!\\)\\\(.+(?<!\\)\\\)/)
53
- return true
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
- doc.css('script').each do |node|
58
- type = node['type']
59
- if type and type.match(/math\/tex/)
60
- return true
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 on_handle_markdown(content)
22
- content = handle_normal_audio(content)
23
- content = handle_normal_video(content)
24
- content = handle_youtube(content)
25
- content = handle_vimeo(content)
26
- content = handle_dailymotion(content)
27
- content = handle_spotify(content)
28
- content = handle_soundcloud(content)
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
  # ![audio](//www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3)
33
40
  # ![audio](//www.expample.com/examples/t-rex-roar.mp3?autoplay=true&loop=true)
34
- def handle_normal_audio(content)
35
- handle_media(content, {
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
  # ![video](//www.html5rocks.com/en/tutorials/video/basics/devstories.webm)
45
52
  # ![video](//techslides.com/demos/sample-videos/small.ogv?allow=autoplay)
46
53
  # ![video](//techslides.com/demos/sample-videos/small.mp4?width=400)
47
- def handle_normal_video(content)
48
- handle_media(content, {
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
  # ![youtube](https://www.youtube.com/watch?v=XA2WjJbmmoM "title")
57
64
  # ![youtube](http://www.youtube.com/embed/w-m_yZCLF5Q)
58
65
  # ![youtube](//youtu.be/mEP3YXaSww8?height=100%&width=400)
59
- def handle_youtube(content)
60
- handle_media(content, {
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
  # ![vimeo](https://vimeo.com/263856289)
70
77
  # ![vimeo](https://vimeo.com/263856289?height=100%&width=400)
71
- def handle_vimeo(content)
72
- handle_media(content, {
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
  # ![dailymotion](https://www.dailymotion.com/video/x7tgcev)
82
89
  # ![dailymotion](https://dai.ly/x7tgcev?height=100%&width=400)
83
- def handle_dailymotion(content)
84
- handle_media(content, {
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
  # ![spotify](//open.spotify.com/track/4Dg5moVCTqxAb7Wr8Dq2T5)
94
101
  # ![spotify](//open.spotify.com/track/37mEkAaqCE7FXMvnlVA8pp?width=400)
95
- def handle_spotify(content)
96
- handle_media(content, {
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
  # ![soundcloud](//soundcloud.com/aviciiofficial/preview-avicii-vs-lenny)
107
- def handle_soundcloud(content)
108
- handle_media(content, {
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(content, data)
126
+ def handle_media(element, data)
120
127
  host = data[:host]
121
- return content if content.sub(/#{host}/, '').nil?
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' ? '()' : data[:id]
126
- url = "(#{host}#{id}\\S*)"
127
- title = '("(.*)".*){0,1}'
128
-
129
- # pre-handle reference-style links
130
- regex = /(\[(.*)\]:\s*(#{url}\s*#{title}))/
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
- "![\1](#{ref_value})")
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
- # handle inline-style links
141
- regex = /(\!\[(.*)\]\(.*#{url}\s*#{title}\))/
142
- content.scan regex do |match_data|
143
- url = match_data[2]
144
- id = data[:id_from] === 'html' \
145
- ? get_id_from_html(url, data[:id]) \
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
- cfg['src'] = URI(base_url ? "#{base_url}#{id}" : url).tap do |v|
161
- v.query = URI.encode_www_form(qs) if qs.size > 0
162
- end
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
- case media_type
165
- when 'audio'
166
- cfg['autoplay'] = qs['autoplay'] || data[:autoplay] || cfg['autoplay']
167
- cfg['loop'] = qs['loop'] || data[:loop] || cfg['loop']
168
- cfg['style'] += ';display: none;' if qs['hidden']
169
- content = handle_audio(content, { target: match_data[0], cfg: cfg })
170
- when 'iframe'
171
- cfg['title'] = title
172
- cfg['width'] = qs['width'] || data[:width] || cfg['width']
173
- cfg['height'] = qs['height'] || data[:height] || cfg['height']
174
- cfg['frameborder'] = qs['frameborder'] || cfg['frameborder']
175
- cfg['allow'] ||= cfg['allow']
176
- content = handle_iframe(content, { target: match_data[0], cfg: cfg })
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
- content
169
+ self.handled = true
181
170
  end
182
171
 
183
- def handle_audio(content, data)
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
- content.gsub(data[:target], html)
186
+ doc = Nokogiri::XML(html)
187
+ element.replace(doc.children.first)
198
188
  end
199
189
 
200
- def handle_iframe(content, data)
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
- content.gsub(data[:target], html)
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
- url = self.get_mermaid_img_data(url)
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
- css_class = self.config['css']['class']
76
- "<img class=\"#{css_class}\" src=\"#{url}\">"
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/png/'
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
- url = self.get_plantuml_img_data(url)
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
- css_class = self.config['css']['class']
73
- "<img class=\"#{css_class}\" src=\"#{url}\">"
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(/&lt;/, '<')
311
312
  .gsub(/&gt;/, '>')
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'
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Jekyll
4
4
  module Spaceship
5
- VERSION = "0.9.1"
5
+ VERSION = "0.9.6"
6
6
  end
7
7
  end
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.1
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-08-10 00:00:00.000000000 Z
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,