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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cbba69bcf95b309c36da702cce9670212f7a32985e2522f13b06fdc0058e0b60
4
- data.tar.gz: 679ee30cad6abfe6c6fb271e3816bff2e16f931b94492d0e0223f4dba11263f4
3
+ metadata.gz: 51f0576137305906368ec086aba6c9c11d45799d10dc8a22abd5598a4026251a
4
+ data.tar.gz: 1a52f85350f6d2b3e128b637ec040108d993534ec554296cdd2b998e26551aec
5
5
  SHA512:
6
- metadata.gz: 207137e6fedec9521c2cde3a3215cf7f1ccbc81f6ce0385c385a1c48d31a1ba7d03b3c532e0cbde80ce2f8d33e79a770d299d64cc436acddfc03ed651a2e9fc4
7
- data.tar.gz: 1c78e2e73e99f7c3e007e3cbcea683b1d4a4db5771737530865be9262d42adf5617e6d7b9cb9931b4947937fdc64d927bf38967121b2dc98d1107d5bec01cace
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 foring cell alignment.
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.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
@@ -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
- # handle emoji markup
20
- content.scan(/:([\w\d+-]+):/) do |match|
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
- css_class = self.config['css']['class']
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
- "<img class=\"#{css_class}\""\
32
- " title=\":#{emoji.name}:\""\
33
- " alt=\":#{emoji.name}:\""\
34
- " raw=\"#{emoji.raw}\""\
35
- " src=\"#{config['src']}#{emoji.image_filename}\""\
36
- " style=\"vertical-align: middle; display: inline;"\
37
- " max-width: 1em; visibility: hidden;\""\
38
- " onload=\"this.style.visibility='visible'\""\
39
- " onerror=\"this.replaceWith(this.getAttribute('raw'))\">"\
40
- "</img>"
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
- content
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' => { '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
+ 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
- doc.css('*').each do |node|
49
- if node.content.match(/(?<!\\)\$.+(?<!\\)\$/)
50
- return true
51
- end
52
- if node.content.match(/(?<!\\)\\\(.+(?<!\\)\\\)/)
53
- return true
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
- doc.css('script').each do |node|
58
- type = node['type']
59
- if type and type.match(/math\/tex/)
60
- return true
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
  # ![video](//techslides.com/demos/sample-videos/small.mp4?width=400)
54
54
  def handle_normal_video(element)
55
55
  handle_media(element, {
56
- media_type: 'iframe',
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?:)?\\/\\/.*dai.?ly.*',
94
- id: '(?<=video\\/|\\/)([a-zA-Z0-9\\_\\-]+)',
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.match(/#{host}#{id}\S*/)
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
- "<p> Your browser doesn't support HTML5 audio."\
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. </p>"\
188
+ " instead."\
185
189
  "</audio>"
186
- doc = Nokogiri::XML(html)
187
- element.replace(doc.children.first)
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::XML(html)
205
- element.replace(doc.children.first)
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)
@@ -60,6 +60,9 @@ module Jekyll::Spaceship
60
60
  end
61
61
 
62
62
  def handle_mermaid(code)
63
+ # Handle extra empty lines, otherwise it would cause error
64
+ code = code.gsub(/\n\s*\n/, "\n%%-\n")
65
+
63
66
  # encode to UTF-8
64
67
  code = code.encode('UTF-8')
65
68
  url = get_url(code)
@@ -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 = result.gsub(
23
- /\[([^\n\]]*?)\]\s*\[#{key}\]/,
24
- "[\1](#{val})")
25
- next if result == replace
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.content.match(/(\|)+$/)
154
+ result = cell.inner_html.match(/(\|)+$/)
147
155
  return if result.nil?
148
156
 
149
- cell.content = cell.content.gsub(/(\|)+$/, '')
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.content.match(/^\s*\^{2}/)
207
- cell.content = cell.content.gsub(/^\s*\^{2}/, '')
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
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Jekyll
4
4
  module Spaceship
5
- VERSION = "0.9.4"
5
+ VERSION = "0.9.9"
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.4
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: 2020-10-12 00:00:00.000000000 Z
11
+ date: 2021-04-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: jekyll