jekyll-spaceship 0.4.2 → 0.5.2

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.
@@ -24,21 +24,17 @@ module Jekyll::Spaceship
24
24
  filename = File.basename(path, '.rb')
25
25
  next if filename.gsub(/-/, '').downcase != name
26
26
 
27
- Logger.log "use #{filename}"
28
-
27
+ Logger.log "🗂 use #{filename}"
29
28
  require path
30
-
31
29
  constants = Jekyll::Spaceship.constants.select do |c|
32
30
  c.downcase.to_s == name
33
31
  end
34
32
 
35
33
  next if constants.first.nil?
36
-
37
34
  _class = Jekyll::Spaceship.const_get(constants.first)
38
-
39
35
  next unless _class.is_a? Class
40
36
 
41
- _class.new
37
+ Manager.add _class.new
42
38
  end
43
39
  end
44
40
  end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll::Spaceship
4
+ class Type
5
+ HTML_EXTENSIONS = %w(
6
+ .html
7
+ .xhtml
8
+ .htm
9
+ ).freeze
10
+
11
+ CSS_EXTENSIONS = %w(
12
+ .css
13
+ .scss
14
+ ).freeze
15
+
16
+ MD_EXTENSIONS = %w(
17
+ .md
18
+ .markdown
19
+ ).freeze
20
+
21
+ HTML_BLOCK_TYPE_MAP = {
22
+ 'text/markdown' => 'markdown',
23
+ }.freeze
24
+
25
+ def self.html?(_ext)
26
+ HTML_EXTENSIONS.include?(_ext)
27
+ end
28
+
29
+ def self.css?(_ext)
30
+ CSS_EXTENSIONS.include?(_ext)
31
+ end
32
+
33
+ def self.markdown?(_ext)
34
+ MD_EXTENSIONS.include?(_ext)
35
+ end
36
+
37
+ def self.html_block_type(type)
38
+ HTML_BLOCK_TYPE_MAP[type]
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'net/http'
4
+ require 'uri'
5
+ require 'json'
6
+
7
+ module Jekyll::Spaceship
8
+ class EmojiProcessor < Processor
9
+ EMOJI_MARKUP_HOST = 'https://api.github.com/emojis'
10
+ EMOJI_MARKUP_DATA = {}
11
+
12
+ def initialize
13
+ super()
14
+ self.initialize_emoji_data
15
+ end
16
+
17
+ def initialize_emoji_data
18
+ EMOJI_MARKUP_DATA.update get_emoji_markup_data
19
+ end
20
+
21
+ def on_handle_html(content)
22
+ return content if EMOJI_MARKUP_DATA.size.zero?
23
+ # handle emoji markup
24
+ content.scan(/:([\w+-]+):/) do |match_data|
25
+ emoji_markup = match_data[0]
26
+ emoji_image = EMOJI_MARKUP_DATA[emoji_markup]
27
+ next if emoji_image.nil?
28
+ self.handled = true
29
+
30
+ # convert hex string to unicode
31
+ unicode = emoji_image.match(/unicode\/([\d\w]+)/)
32
+ if unicode[1]
33
+ unicode = "0x#{unicode[1]}".to_i(16)
34
+ alt = [unicode].pack('U*')
35
+ end
36
+ alt = emoji_markup if alt.nil?
37
+
38
+ content = content.gsub(
39
+ ":#{emoji_markup}:",
40
+ "<image class=\"emoji\" \
41
+ title=\"#{emoji_markup}\" \
42
+ alt=\"#{alt}\" \
43
+ src=\"#{emoji_image}\" \
44
+ style=\"vertical-align: middle; \
45
+ max-width: 1em; visibility: hidden;\" \
46
+ onload=\"this.style.visibility='visible'\" \
47
+ onerror=\"this.replaceWith(this.alt)\"> \
48
+ </image>"
49
+ )
50
+ end
51
+ content
52
+ end
53
+
54
+ def get_emoji_markup_data
55
+ data = {}
56
+ begin
57
+ source = Net::HTTP.get URI(EMOJI_MARKUP_HOST)
58
+ data = JSON.parse(source)
59
+ rescue StandardError => msg
60
+ logger.log msg
61
+ end
62
+ data
63
+ end
64
+ end
65
+ end
@@ -5,7 +5,7 @@ require "nokogiri"
5
5
  module Jekyll::Spaceship
6
6
  class MathjaxProcessor < Processor
7
7
  def process?
8
- return true if html?(output_ext)
8
+ return true if Type.html?(output_ext)
9
9
  end
10
10
 
11
11
  def on_handle_html(content)
@@ -20,7 +20,10 @@ module Jekyll::Spaceship
20
20
 
21
21
  params = "config=TeX-AMS-MML_HTMLorMML"
22
22
  src = "//cdn.mathjax.org/mathjax/latest/MathJax.js?#{params}"
23
- config = "MathJax.Hub.Config({tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']]}});"
23
+ config = "MathJax.Hub.Config({ \
24
+ tex2jax: { inlineMath: [['$','$'], ['\\\\(','\\\\)']] } \
25
+ });"
26
+
24
27
  head.add_child("<script src=\"#{src}\">#{config}</script>")
25
28
 
26
29
  doc.to_html
@@ -28,7 +31,10 @@ module Jekyll::Spaceship
28
31
 
29
32
  def has_mathjax_expression?(doc)
30
33
  doc.css('*').each do |node|
31
- if node.content.match(/\$.+\$/)
34
+ if node.content.match(/(?<!\\)\$.+(?<!\\)\$/)
35
+ return true
36
+ end
37
+ if node.content.match(/(?<!\\)\\\(.+(?<!\\)\\\)/)
32
38
  return true
33
39
  end
34
40
  end
@@ -1,9 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "base64"
4
+
3
5
  module Jekyll::Spaceship
4
6
  class PlantUMLProcessor < Processor
5
7
  exclude :none
6
8
 
9
+ PLANT_UML_HOST = 'http://www.plantuml.com/plantuml/png/'
10
+
7
11
  def on_handle_markdown(content)
8
12
  # match default plantuml block and code block
9
13
  pattern = Regexp.union(
@@ -35,18 +39,28 @@ module Jekyll::Spaceship
35
39
 
36
40
  def handle_plantuml(code)
37
41
  # wrap plantuml code
38
- uml = "@startuml#{code}@enduml"
39
-
40
- dir = File.dirname(__FILE__)
41
- jar = dir + "/../utils/plantuml/plantuml.jar"
42
- echo = "echo -e \"#{uml.gsub('"', '\"')}\""
43
- plantuml = "java -jar \"#{jar}\" -pipe 2>/dev/null"
42
+ code = "@startuml#{code}@enduml".encode('UTF-8')
44
43
 
45
- # exec plantuml.jar and output base64 data
46
- base64 = `#{echo} | #{plantuml} | base64`
44
+ # encode to hex string
45
+ code = '~h' + code.unpack("H*").first
46
+ data = self.get_plantuml_img_data(code)
47
47
 
48
48
  # return img tag
49
- "<img src=\"data:image/png;base64, #{base64}\">"
49
+ "<img src=\"#{data}\">"
50
+ end
51
+
52
+ def get_plantuml_img_data(code)
53
+ data = ''
54
+ url = "#{PLANT_UML_HOST}#{code}"
55
+ begin
56
+ data = Net::HTTP.get URI(url)
57
+ data = Base64.encode64(data)
58
+ data = "data:image/png;base64, #{data}"
59
+ rescue StandardError => msg
60
+ data = url
61
+ logger.log msg
62
+ end
63
+ data
50
64
  end
51
65
  end
52
66
  end
@@ -46,23 +46,7 @@ module Jekyll::Spaceship
46
46
  # use nokogiri to parse html content
47
47
  doc = Nokogiri::HTML(content)
48
48
 
49
- data = OpenStruct.new(_: OpenStruct.new)
50
- data.reset = ->(scope, namespace = nil) {
51
- data._.marshal_dump.each do |key, val|
52
- if namespace == key or namespace.nil?
53
- data._[key][scope] = OpenStruct.new
54
- end
55
- end
56
- }
57
- data.scope = ->(namespace) {
58
- if not data._[namespace]
59
- data._[namespace] = OpenStruct.new(
60
- table: OpenStruct.new,
61
- row: OpenStruct.new
62
- )
63
- end
64
- data._[namespace]
65
- }
49
+ data = self.table_scope_data
66
50
 
67
51
  # handle each table
68
52
  doc.css('table').each do |table|
@@ -96,45 +80,66 @@ module Jekyll::Spaceship
96
80
  doc.to_html
97
81
  end
98
82
 
83
+ def table_scope_data
84
+ data = OpenStruct.new(_: OpenStruct.new)
85
+ data.reset = ->(scope, namespace = nil) {
86
+ data._.marshal_dump.each do |key, val|
87
+ if namespace == key or namespace.nil?
88
+ data._[key][scope] = OpenStruct.new
89
+ end
90
+ end
91
+ }
92
+ data.scope = ->(namespace) {
93
+ if not data._[namespace]
94
+ data._[namespace] = OpenStruct.new(
95
+ table: OpenStruct.new,
96
+ row: OpenStruct.new
97
+ )
98
+ end
99
+ data._[namespace]
100
+ }
101
+ data
102
+ end
103
+
99
104
  def handle_colspan(data)
100
105
  scope = data.scope.call __method__
101
- scope_table = scope.table
102
- scope_row = scope.row
103
106
  cells = data.cells
104
107
  cell = data.cell
105
108
 
106
- if scope_table.row != data.row
107
- scope_table.row = data.row
108
- scope_row.colspan = 0
109
+ if scope.table.row != data.row
110
+ scope.table.row = data.row
111
+ scope.row.colspan = 0
109
112
  end
110
113
 
111
114
  # handle colspan
112
- result = cell.content.match(/(\s*\|)+$/)
113
- if cell == cells.last and scope_row.colspan > 0
114
- range = (cells.count - scope_row.colspan)...cells.count
115
- for i in range do
116
- cells[i].remove
115
+ if cell == cells.last and scope.row.colspan > 0
116
+ cells.count.downto(cells.count - scope.row.colspan + 1) do |i|
117
+ c = cells[i - 1]
118
+ return unless c.get_attribute('colspan').nil?
119
+ c.remove
117
120
  end
118
121
  end
119
- if result
120
- result = result[0]
121
- scope_row.colspan += result.scan(/\|/).count
122
- cell.content = cell.content.gsub(/(\s*\|)+$/, '')
123
- cell.set_attribute('colspan', scope_row.colspan + 1)
124
- end
122
+
123
+ result = cell.content.match(/(\|)+$/)
124
+ return if result.nil?
125
+
126
+ cell.content = cell.content.gsub(/(\|)+$/, '')
127
+ result = result[0]
128
+ colspan = result.scan(/\|/).count
129
+ scope.row.colspan += colspan
130
+ cell.set_attribute('colspan', colspan + 1)
125
131
  end
126
132
 
127
133
  def handle_multi_rows(data)
128
134
  scope = data.scope.call __method__
129
- scope_table = scope.table
130
135
  cells = data.cells
131
136
  row = data.row
132
137
  cell = data.cell
133
138
 
134
- if scope_table.table != data.table
135
- scope_table.table = data.table
136
- scope_table.multi_row_cells = nil
137
- scope_table.multi_row_start = false
139
+ if scope.table.table != data.table
140
+ scope.table.table = data.table
141
+ scope.table.multi_row_cells = nil
142
+ scope.table.multi_row_start = false
138
143
  end
139
144
 
140
145
  # handle multi-rows
@@ -143,41 +148,38 @@ module Jekyll::Spaceship
143
148
  match = cell.content.match(/(?<!\\)\\\s*$/)
144
149
  if match
145
150
  cell.content = cell.content.gsub(/(?<!\\)\\\s*$/, '')
146
- if not scope_table.multi_row_start
147
- scope_table.multi_row_cells = cells
148
- scope_table.multi_row_start = true
151
+ if not scope.table.multi_row_start
152
+ scope.table.multi_row_cells = cells
153
+ scope.table.multi_row_start = true
149
154
  end
150
155
  end
151
156
 
152
- if scope_table.multi_row_cells != cells and scope_table.multi_row_start
153
- for i in 0...scope_table.multi_row_cells.count do
154
- multi_row_cell = scope_table.multi_row_cells[i]
157
+ if scope.table.multi_row_cells != cells and scope.table.multi_row_start
158
+ for i in 0...scope.table.multi_row_cells.count do
159
+ multi_row_cell = scope.table.multi_row_cells[i]
155
160
  multi_row_cell.content += " \n#{cells[i].content}"
156
161
  end
157
162
  row.remove
158
163
  end
159
- scope_table.multi_row_start = false if not match
164
+ scope.table.multi_row_start = false if not match
160
165
  end
161
166
 
162
167
  def handle_rowspan(data)
163
168
  scope = data.scope.call __method__
164
- scope_table = scope.table
165
- scope_row = scope.row
166
169
  cell = data.cell
167
170
  cells = data.cells
168
171
 
169
- if scope_table.table != data.table
170
- scope_table.table = data.table
171
- scope_table.span_row_cells = []
172
+ if scope.table.table != data.table
173
+ scope.table.table = data.table
174
+ scope.table.span_row_cells = []
172
175
  end
173
-
174
- if scope_row.row != data.row
175
- scope_row.row = data.row
176
- scope_row.col_index = 0
176
+ if scope.row.row != data.row
177
+ scope.row.row = data.row
178
+ scope.row.col_index = 0
177
179
  end
178
180
 
179
181
  # handle rowspan
180
- span_cell = scope_table.span_row_cells[scope_row.col_index]
182
+ span_cell = scope.table.span_row_cells[scope.row.col_index]
181
183
  if span_cell and cell.content.match(/^\s*\^{2}/)
182
184
  cell.content = cell.content.gsub(/^\s*\^{2}/, '')
183
185
  span_cell.content += " \n#{cell.content}"
@@ -186,10 +188,9 @@ module Jekyll::Spaceship
186
188
  span_cell.set_attribute('rowspan', "#{rowspan}")
187
189
  cell.remove
188
190
  else
189
- scope_table.span_row_cells[scope_row.col_index] = cell
191
+ scope.table.span_row_cells[scope.row.col_index] = cell
190
192
  end
191
-
192
- scope_row.col_index += 1
193
+ scope.row.col_index += [cell.get_attribute('colspan').to_i, 1].max
193
194
  end
194
195
 
195
196
  def handle_text_align(data)
@@ -211,7 +212,6 @@ module Jekyll::Spaceship
211
212
 
212
213
  # handle text align
213
214
  return if align == 0
214
-
215
215
  style = cell.get_attribute('style')
216
216
  if align == 1
217
217
  align = 'text-align: left'
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'uri'
4
+
3
5
  module Jekyll::Spaceship
4
6
  class VideoProcessor < Processor
5
7
  def on_handle_markdown(content)
@@ -70,22 +72,26 @@ module Jekyll::Spaceship
70
72
  url = match_data[2]
71
73
  id = match_data[4]
72
74
  title = match_data[6]
73
- width = url.match(/(?<=width=)(\S*?)(?=&|$)/)
74
- height = url.match(/(?<=height=)(\S*?)(?=&|$)/)
75
+ qs = url.match(/(?<=\?)(\S*?)$/)
76
+ qs = Hash[URI.decode_www_form(qs.to_s)].reject do |k, v|
77
+ next true if v == id or v == ''
78
+ end
75
79
 
76
- data[:width] = 600 if data[:width].nil?
77
- data[:height] = 400 if data[:height].nil?
80
+ width = qs['width'] || data[:width] || 600
81
+ height = qs['height'] || data[:height] || 400
78
82
  style = "max-width: 100%" if width.nil?
79
- width = data[:width] if width.nil?
80
- height = data[:height] if height.nil?
81
83
 
82
- url = "#{iframe_url}#{id}"
84
+ url = URI("#{iframe_url}#{id}").tap do |v|
85
+ v.query = URI.encode_www_form(qs) if qs.size > 0
86
+ end
87
+
83
88
  html = "<iframe \
84
89
  src=\"#{url}\" \
85
90
  title=\"#{title}\" \
86
91
  width=\"#{width}\" \
87
92
  height=\"#{height}\" \
88
93
  style=\"#{style}\" \
94
+ allow=\"autoplay; encrypted-media\" \
89
95
  frameborder=\"0\" \
90
96
  allowfullscreen=\"\">\
91
97
  </iframe>"
File without changes