jekyll-spaceship 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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