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 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,