jekyll-spaceship 0.4.0 → 0.5.0

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.
@@ -1,54 +1,46 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'nokogiri'
4
-
5
3
  module Jekyll::Spaceship
6
4
  class Processor
7
- @@_hooks = {}
8
- @@_registers = []
9
- @@_processers = []
10
- @@_priority = nil
11
-
12
- attr_accessor :priority
13
- attr_accessor :page
14
- attr_accessor :handled
15
-
16
5
  DEFAULT_PRIORITY = 20
17
6
 
18
7
  PRIORITY_MAP = {
19
- :low => 10,
20
- :normal => 20,
21
- :high => 30,
8
+ :lowest => 0,
9
+ :low => 10,
10
+ :normal => 20,
11
+ :high => 30,
12
+ :highest => 40,
22
13
  }.freeze
23
14
 
24
- HTML_EXTENSIONS = %w(
25
- .html
26
- .xhtml
27
- .htm
28
- ).freeze
15
+ @@_registers = []
16
+ @@_exclusions = []
17
+ @@_priority = nil
29
18
 
30
- CSS_EXTENSIONS = %w(
31
- .css
32
- .scss
33
- ).freeze
19
+ attr_reader :page
20
+ attr_reader :logger
21
+ attr_reader :priority
22
+ attr_reader :registers
23
+ attr_reader :exclusions
24
+ attr_accessor :handled
34
25
 
35
- MD_EXTENSIONS = %w(
36
- .md
37
- .markdown
38
- ).freeze
26
+ def name
27
+ self.class.name.split('::').last
28
+ end
39
29
 
40
30
  def initialize()
41
31
  self.initialize_priority
42
32
  self.initialize_register
33
+ self.initialize_exclusions
34
+ @logger = Logger.new(self.name)
43
35
  end
44
36
 
45
37
  def initialize_priority
46
- @@_priority = DEFAULT_PRIORITY if @@_priority.nil?
47
38
  @priority = @@_priority
39
+ unless @priority.nil? or @priority.is_a? Numeric
40
+ @priority = PRIORITY_MAP[@priority.to_sym]
41
+ end
42
+ @priority = DEFAULT_PRIORITY if @priority.nil?
48
43
  @@_priority = nil
49
-
50
- @@_processers.push(self)
51
- @@_processers = @@_processers.sort { |a, b| b.priority <=> a.priority }
52
44
  end
53
45
 
54
46
  def initialize_register
@@ -56,224 +48,115 @@ module Jekyll::Spaceship
56
48
  self.class.register :pages, :pre_render, :post_render
57
49
  self.class.register :posts, :pre_render, :post_render
58
50
  end
51
+ @registers = Array.new @@_registers
52
+ @@_registers.clear
53
+ end
59
54
 
60
- @@_registers.each do |_register|
61
- container = _register.first
62
- events = _register.last.uniq
63
- events = events.select do |event|
64
- next true if event.match(/^post/)
65
- next !events.any?(event.to_s.gsub(/^pre/, 'post').to_sym)
66
- end
67
- events.each do |event|
68
- self.class.hook container, event
69
- end
55
+ def initialize_exclusions
56
+ if @@_exclusions.size.zero?
57
+ self.class.exclude :code, :block_quotes
70
58
  end
71
- @@_registers.clear
59
+ @exclusions = @@_exclusions.uniq
60
+ @@_exclusions.clear
72
61
  end
73
62
 
74
63
  def self.priority(value)
75
- value = value.to_sym
76
- if PRIORITY_MAP.has_key? value
77
- @@_priority = PRIORITY_MAP[value]
78
- elsif value.nil?
79
- @@_priority = DEFAULT_PRIORITY
80
- else
81
- @@_priority = value
82
- end
64
+ @@_priority = value.to_sym
83
65
  end
84
66
 
85
67
  def self.register(container, *events)
86
68
  @@_registers << [container, events]
87
69
  end
88
70
 
89
- def self.hook_register(container, event)
90
- hook_name = "#{container}_#{event}".to_sym
91
- return false if @@_hooks.has_key? hook_name
92
- @@_hooks[hook_name] = true
71
+ def self.exclude(*types)
72
+ @@_exclusions = types
93
73
  end
94
74
 
95
- def self.hook(container, event, &block)
96
- return if not hook_register container, event
75
+ def process?
76
+ Type.html?(output_ext) or Type.markdown?(ext)
77
+ end
97
78
 
98
- # define dispatch proc
99
- dispatch = ->(instance) {
100
- @@_processers.each do |processor|
101
- processor.page = instance
102
- processor.handled = false
103
- next if not processor.process?
104
- processor.dispatch container, event
105
- end
106
- if event.to_s.start_with?('post') and self.html? output_ext(instance)
107
- self.handle_html_block(instance)
108
- end
109
- @@_processers.each do |processor|
110
- processor.page = instance
111
- if processor.handled
112
- processor.on_handled
113
- end
114
- end
115
- block.call if block
116
- }
79
+ def ext
80
+ Manager.ext @page
81
+ end
117
82
 
118
- if event.to_s.start_with?('after')
119
- Jekyll::Hooks.register container, event do |instance|
120
- dispatch.call instance
121
- end
122
- elsif event.to_s.start_with?('post')
123
- Jekyll::Hooks.register container, event do |instance|
124
- dispatch.call instance
125
- end
83
+ def output_ext
84
+ Manager.output_ext @page
85
+ end
126
86
 
127
- # auto add pre-event
128
- register container, event.to_s.sub('post', 'pre').to_sym
129
- elsif event.to_s.start_with?('pre')
130
- Jekyll::Hooks.register container, event do |instance|
131
- dispatch.call instance
132
- end
133
- end
87
+ def converter(name)
88
+ Manager.converter @page, name
134
89
  end
135
90
 
136
- def dispatch(container, event)
91
+ def dispatch(page, container, event)
92
+ @page = page
93
+ @handled = false
94
+ return unless self.process?
137
95
  method = "on_#{container}_#{event}"
138
96
  self.send method, @page if self.respond_to? method
139
-
97
+ method = ''
140
98
  if event.to_s.start_with?('pre')
141
- if markdown? ext
99
+ if Type.markdown? ext
142
100
  method = 'on_handle_markdown'
143
- else
144
- method = ''
145
101
  end
146
-
147
102
  if self.respond_to? method
103
+ @page.content = self.pre_exclude @page.content
148
104
  @page.content = self.send method, @page.content
105
+ @page.content = self.after_exclude @page.content
149
106
  end
150
107
  else
151
- if html? output_ext
108
+ if Type.html? output_ext
152
109
  method = 'on_handle_html'
153
110
  elsif css? output_ext
154
111
  method = 'on_handle_css'
155
- else
156
- method = ''
157
112
  end
158
-
159
113
  if self.respond_to? method
160
114
  @page.output = self.send method, @page.output
161
115
  end
162
116
  end
163
117
  end
164
118
 
165
- def html?(_ext)
166
- self.class.html? _ext
167
- end
168
-
169
- def css?(_ext)
170
- self.class.css? _ext
171
- end
172
-
173
- def markdown?(_ext)
174
- self.class.markdown? _ext
175
- end
176
-
177
- def self.html?(_ext)
178
- HTML_EXTENSIONS.include?(_ext)
179
- end
180
-
181
- def self.css?(_ext)
182
- CSS_EXTENSIONS.include?(_ext)
183
- end
184
-
185
- def self.markdown?(_ext)
186
- MD_EXTENSIONS.include?(_ext)
187
- end
188
-
189
- def converter(name)
190
- self.class.converter(@page, name)
191
- end
192
-
193
- def self.converter(instance, name)
194
- instance.site.converters.each do |converter|
195
- class_name = converter.class.to_s.downcase
196
- return converter if class_name.end_with?(name.downcase)
197
- end
198
- end
199
-
200
- def ext
201
- self.class.ext @page
119
+ def on_handle_html_block(content, type)
120
+ # default handle method
121
+ content
202
122
  end
203
123
 
204
- def output_ext
205
- self.class.output_ext @page
206
- end
207
-
208
- def self.ext(instance)
209
- instance.data['ext']
210
- end
211
-
212
- def self.output_ext(instance)
213
- instance.url_placeholders[:output_ext]
214
- end
215
-
216
- def process?
217
- html?(output_ext) or markdown?(ext)
124
+ def on_handle_html(content)
125
+ # default handle method
126
+ content
218
127
  end
219
128
 
220
129
  def on_handled
221
- processor = self.class.name.split('::').last
222
130
  file = page.path.gsub(/.*_posts\//, '')
223
- Logger.log "[#{processor}] #{file}"
131
+ logger.log file
224
132
  end
225
133
 
226
- def self.handle_html_block(instance)
227
- doc = Nokogiri::HTML(instance.output)
228
-
229
- doc.css('script').each do |node|
230
- blk_type = node['type']
231
- blk_content = node.content
232
-
233
- cvter = nil
234
- method = ''
235
- block_method = 'on_handle_html_block'
236
-
237
- case blk_type
238
- when 'text/markdown'
239
- method = 'on_handle_markdown'
240
- cvter = self.converter(instance, 'markdown')
134
+ def pre_exclude(content)
135
+ @exclusion_store = []
136
+ @exclusions.each do |type|
137
+ regex = nil
138
+ if type == :code
139
+ regex = /(`{3}\s*(\w*)((?:.|\n)*?)`{3})/
241
140
  end
242
-
243
- @@_processers.each do |processor|
244
- processor.page = instance
245
- next if not processor.process?
246
-
247
- # dispatch to on_handle_html_block
248
- if processor.respond_to? block_method
249
- blk_content = processor.send block_method blk_content, blk_type
250
- end
251
-
252
- # dispatch to other handlers
253
- if processor.respond_to? method
254
- blk_content = processor.send method, blk_content
255
- end
256
- end
257
-
258
- if not cvter.nil?
259
- blk_content = cvter.convert blk_content
141
+ next if regex.nil?
142
+ content.scan(regex) do |match_data|
143
+ match = match_data[0]
144
+ id = @exclusion_store.size
145
+ content = content.gsub(match, "[//]: JEKYLL_EXCLUDE_##{id}")
146
+ @exclusion_store.push match
260
147
  end
261
-
262
- next if method == ''
263
-
264
- method = 'on_handle_html'
265
- @@_processers.each do |processor|
266
- processor.page = instance
267
- next if not processor.process?
268
- if processor.respond_to? method
269
- blk_content = processor.send method, blk_content
270
- end
271
- end
272
-
273
- node.replace Nokogiri::HTML.fragment(blk_content)
274
148
  end
149
+ content
150
+ end
275
151
 
276
- instance.output = doc.to_html
152
+ def after_exclude(content)
153
+ while @exclusion_store.size > 0
154
+ match = @exclusion_store.pop
155
+ id = @exclusion_store.size
156
+ content = content.gsub("[//]: JEKYLL_EXCLUDE_##{id}", match)
157
+ end
158
+ @exclusion_store = []
159
+ content
277
160
  end
278
161
  end
279
162
  end
@@ -25,20 +25,16 @@ module Jekyll::Spaceship
25
25
  next if filename.gsub(/-/, '').downcase != name
26
26
 
27
27
  Logger.log "use #{filename}"
28
-
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