ngage 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (109) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +22 -0
  3. data/exe/ngage +55 -0
  4. data/lib/ngage.rb +3 -0
  5. data/lib/ngage/jekyll.rb +204 -0
  6. data/lib/ngage/jekyll/cleaner.rb +111 -0
  7. data/lib/ngage/jekyll/collection.rb +235 -0
  8. data/lib/ngage/jekyll/command.rb +103 -0
  9. data/lib/ngage/jekyll/commands/build.rb +93 -0
  10. data/lib/ngage/jekyll/commands/clean.rb +45 -0
  11. data/lib/ngage/jekyll/commands/doctor.rb +173 -0
  12. data/lib/ngage/jekyll/commands/help.rb +34 -0
  13. data/lib/ngage/jekyll/commands/new.rb +157 -0
  14. data/lib/ngage/jekyll/commands/new_theme.rb +42 -0
  15. data/lib/ngage/jekyll/commands/serve.rb +354 -0
  16. data/lib/ngage/jekyll/commands/serve/live_reload_reactor.rb +122 -0
  17. data/lib/ngage/jekyll/commands/serve/livereload_assets/livereload.js +1183 -0
  18. data/lib/ngage/jekyll/commands/serve/servlet.rb +203 -0
  19. data/lib/ngage/jekyll/commands/serve/websockets.rb +81 -0
  20. data/lib/ngage/jekyll/configuration.rb +391 -0
  21. data/lib/ngage/jekyll/converter.rb +54 -0
  22. data/lib/ngage/jekyll/converters/identity.rb +41 -0
  23. data/lib/ngage/jekyll/converters/markdown.rb +116 -0
  24. data/lib/ngage/jekyll/converters/markdown/kramdown_parser.rb +122 -0
  25. data/lib/ngage/jekyll/converters/smartypants.rb +70 -0
  26. data/lib/ngage/jekyll/convertible.rb +253 -0
  27. data/lib/ngage/jekyll/deprecator.rb +50 -0
  28. data/lib/ngage/jekyll/document.rb +503 -0
  29. data/lib/ngage/jekyll/drops/collection_drop.rb +20 -0
  30. data/lib/ngage/jekyll/drops/document_drop.rb +69 -0
  31. data/lib/ngage/jekyll/drops/drop.rb +209 -0
  32. data/lib/ngage/jekyll/drops/excerpt_drop.rb +15 -0
  33. data/lib/ngage/jekyll/drops/jekyll_drop.rb +32 -0
  34. data/lib/ngage/jekyll/drops/site_drop.rb +56 -0
  35. data/lib/ngage/jekyll/drops/static_file_drop.rb +14 -0
  36. data/lib/ngage/jekyll/drops/unified_payload_drop.rb +26 -0
  37. data/lib/ngage/jekyll/drops/url_drop.rb +89 -0
  38. data/lib/ngage/jekyll/entry_filter.rb +127 -0
  39. data/lib/ngage/jekyll/errors.rb +20 -0
  40. data/lib/ngage/jekyll/excerpt.rb +180 -0
  41. data/lib/ngage/jekyll/external.rb +76 -0
  42. data/lib/ngage/jekyll/filters.rb +390 -0
  43. data/lib/ngage/jekyll/filters/date_filters.rb +110 -0
  44. data/lib/ngage/jekyll/filters/grouping_filters.rb +64 -0
  45. data/lib/ngage/jekyll/filters/url_filters.rb +68 -0
  46. data/lib/ngage/jekyll/frontmatter_defaults.rb +233 -0
  47. data/lib/ngage/jekyll/generator.rb +5 -0
  48. data/lib/ngage/jekyll/hooks.rb +106 -0
  49. data/lib/ngage/jekyll/layout.rb +62 -0
  50. data/lib/ngage/jekyll/liquid_extensions.rb +22 -0
  51. data/lib/ngage/jekyll/liquid_renderer.rb +63 -0
  52. data/lib/ngage/jekyll/liquid_renderer/file.rb +56 -0
  53. data/lib/ngage/jekyll/liquid_renderer/table.rb +98 -0
  54. data/lib/ngage/jekyll/log_adapter.rb +151 -0
  55. data/lib/ngage/jekyll/mime.types +825 -0
  56. data/lib/ngage/jekyll/page.rb +185 -0
  57. data/lib/ngage/jekyll/page_without_a_file.rb +14 -0
  58. data/lib/ngage/jekyll/plugin.rb +92 -0
  59. data/lib/ngage/jekyll/plugin_manager.rb +115 -0
  60. data/lib/ngage/jekyll/publisher.rb +23 -0
  61. data/lib/ngage/jekyll/reader.rb +154 -0
  62. data/lib/ngage/jekyll/readers/collection_reader.rb +22 -0
  63. data/lib/ngage/jekyll/readers/data_reader.rb +75 -0
  64. data/lib/ngage/jekyll/readers/layout_reader.rb +70 -0
  65. data/lib/ngage/jekyll/readers/page_reader.rb +25 -0
  66. data/lib/ngage/jekyll/readers/post_reader.rb +72 -0
  67. data/lib/ngage/jekyll/readers/static_file_reader.rb +25 -0
  68. data/lib/ngage/jekyll/readers/theme_assets_reader.rb +51 -0
  69. data/lib/ngage/jekyll/regenerator.rb +195 -0
  70. data/lib/ngage/jekyll/related_posts.rb +52 -0
  71. data/lib/ngage/jekyll/renderer.rb +266 -0
  72. data/lib/ngage/jekyll/site.rb +476 -0
  73. data/lib/ngage/jekyll/static_file.rb +169 -0
  74. data/lib/ngage/jekyll/stevenson.rb +60 -0
  75. data/lib/ngage/jekyll/tags/highlight.rb +108 -0
  76. data/lib/ngage/jekyll/tags/include.rb +226 -0
  77. data/lib/ngage/jekyll/tags/link.rb +40 -0
  78. data/lib/ngage/jekyll/tags/post_url.rb +104 -0
  79. data/lib/ngage/jekyll/theme.rb +73 -0
  80. data/lib/ngage/jekyll/theme_builder.rb +121 -0
  81. data/lib/ngage/jekyll/url.rb +160 -0
  82. data/lib/ngage/jekyll/utils.rb +370 -0
  83. data/lib/ngage/jekyll/utils/ansi.rb +57 -0
  84. data/lib/ngage/jekyll/utils/exec.rb +26 -0
  85. data/lib/ngage/jekyll/utils/internet.rb +37 -0
  86. data/lib/ngage/jekyll/utils/platforms.rb +82 -0
  87. data/lib/ngage/jekyll/utils/thread_event.rb +31 -0
  88. data/lib/ngage/jekyll/utils/win_tz.rb +75 -0
  89. data/lib/ngage/site_template/.gitignore +5 -0
  90. data/lib/ngage/site_template/404.html +25 -0
  91. data/lib/ngage/site_template/_config.yml +47 -0
  92. data/lib/ngage/site_template/_posts/0000-00-00-welcome-to-jekyll.markdown.erb +29 -0
  93. data/lib/ngage/site_template/about.markdown +18 -0
  94. data/lib/ngage/site_template/index.markdown +6 -0
  95. data/lib/ngage/theme_template/CODE_OF_CONDUCT.md.erb +74 -0
  96. data/lib/ngage/theme_template/Gemfile +4 -0
  97. data/lib/ngage/theme_template/LICENSE.txt.erb +21 -0
  98. data/lib/ngage/theme_template/README.md.erb +52 -0
  99. data/lib/ngage/theme_template/_layouts/default.html +1 -0
  100. data/lib/ngage/theme_template/_layouts/page.html +5 -0
  101. data/lib/ngage/theme_template/_layouts/post.html +5 -0
  102. data/lib/ngage/theme_template/example/_config.yml.erb +1 -0
  103. data/lib/ngage/theme_template/example/_post.md +12 -0
  104. data/lib/ngage/theme_template/example/index.html +14 -0
  105. data/lib/ngage/theme_template/example/style.scss +7 -0
  106. data/lib/ngage/theme_template/gitignore.erb +6 -0
  107. data/lib/ngage/theme_template/theme.gemspec.erb +19 -0
  108. data/lib/ngage/version.rb +5 -0
  109. metadata +328 -0
@@ -0,0 +1,390 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_all "jekyll/filters"
4
+
5
+ module Jekyll
6
+ module Filters
7
+ include URLFilters
8
+ include GroupingFilters
9
+ include DateFilters
10
+
11
+ # Convert a Markdown string into HTML output.
12
+ #
13
+ # input - The Markdown String to convert.
14
+ #
15
+ # Returns the HTML formatted String.
16
+ def markdownify(input)
17
+ @context.registers[:site].find_converter_instance(
18
+ Jekyll::Converters::Markdown
19
+ ).convert(input.to_s)
20
+ end
21
+
22
+ # Convert quotes into smart quotes.
23
+ #
24
+ # input - The String to convert.
25
+ #
26
+ # Returns the smart-quotified String.
27
+ def smartify(input)
28
+ @context.registers[:site].find_converter_instance(
29
+ Jekyll::Converters::SmartyPants
30
+ ).convert(input.to_s)
31
+ end
32
+
33
+ # Convert a Sass string into CSS output.
34
+ #
35
+ # input - The Sass String to convert.
36
+ #
37
+ # Returns the CSS formatted String.
38
+ def sassify(input)
39
+ @context.registers[:site].find_converter_instance(
40
+ Jekyll::Converters::Sass
41
+ ).convert(input)
42
+ end
43
+
44
+ # Convert a Scss string into CSS output.
45
+ #
46
+ # input - The Scss String to convert.
47
+ #
48
+ # Returns the CSS formatted String.
49
+ def scssify(input)
50
+ @context.registers[:site].find_converter_instance(
51
+ Jekyll::Converters::Scss
52
+ ).convert(input)
53
+ end
54
+
55
+ # Slugify a filename or title.
56
+ #
57
+ # input - The filename or title to slugify.
58
+ # mode - how string is slugified
59
+ #
60
+ # Returns the given filename or title as a lowercase URL String.
61
+ # See Utils.slugify for more detail.
62
+ def slugify(input, mode = nil)
63
+ Utils.slugify(input, :mode => mode)
64
+ end
65
+
66
+ # XML escape a string for use. Replaces any special characters with
67
+ # appropriate HTML entity replacements.
68
+ #
69
+ # input - The String to escape.
70
+ #
71
+ # Examples
72
+ #
73
+ # xml_escape('foo "bar" <baz>')
74
+ # # => "foo &quot;bar&quot; &lt;baz&gt;"
75
+ #
76
+ # Returns the escaped String.
77
+ def xml_escape(input)
78
+ input.to_s.encode(:xml => :attr).gsub(%r!\A"|"\Z!, "")
79
+ end
80
+
81
+ # CGI escape a string for use in a URL. Replaces any special characters
82
+ # with appropriate %XX replacements.
83
+ #
84
+ # input - The String to escape.
85
+ #
86
+ # Examples
87
+ #
88
+ # cgi_escape('foo,bar;baz?')
89
+ # # => "foo%2Cbar%3Bbaz%3F"
90
+ #
91
+ # Returns the escaped String.
92
+ def cgi_escape(input)
93
+ CGI.escape(input)
94
+ end
95
+
96
+ # URI escape a string.
97
+ #
98
+ # input - The String to escape.
99
+ #
100
+ # Examples
101
+ #
102
+ # uri_escape('foo, bar \\baz?')
103
+ # # => "foo,%20bar%20%5Cbaz?"
104
+ #
105
+ # Returns the escaped String.
106
+ def uri_escape(input)
107
+ Addressable::URI.normalize_component(input)
108
+ end
109
+
110
+ # Replace any whitespace in the input string with a single space
111
+ #
112
+ # input - The String on which to operate.
113
+ #
114
+ # Returns the formatted String
115
+ def normalize_whitespace(input)
116
+ input.to_s.gsub(%r!\s+!, " ").strip
117
+ end
118
+
119
+ # Count the number of words in the input string.
120
+ #
121
+ # input - The String on which to operate.
122
+ #
123
+ # Returns the Integer word count.
124
+ def number_of_words(input)
125
+ input.split.length
126
+ end
127
+
128
+ # Join an array of things into a string by separating with commas and the
129
+ # word "and" for the last one.
130
+ #
131
+ # array - The Array of Strings to join.
132
+ # connector - Word used to connect the last 2 items in the array
133
+ #
134
+ # Examples
135
+ #
136
+ # array_to_sentence_string(["apples", "oranges", "grapes"])
137
+ # # => "apples, oranges, and grapes"
138
+ #
139
+ # Returns the formatted String.
140
+ def array_to_sentence_string(array, connector = "and")
141
+ case array.length
142
+ when 0
143
+ ""
144
+ when 1
145
+ array[0].to_s
146
+ when 2
147
+ "#{array[0]} #{connector} #{array[1]}"
148
+ else
149
+ "#{array[0...-1].join(", ")}, #{connector} #{array[-1]}"
150
+ end
151
+ end
152
+
153
+ # Convert the input into json string
154
+ #
155
+ # input - The Array or Hash to be converted
156
+ #
157
+ # Returns the converted json string
158
+ def jsonify(input)
159
+ as_liquid(input).to_json
160
+ end
161
+
162
+ # Filter an array of objects
163
+ #
164
+ # input - the object array
165
+ # property - property within each object to filter by
166
+ # value - desired value
167
+ #
168
+ # Returns the filtered array of objects
169
+ def where(input, property, value)
170
+ return input if property.nil? || value.nil?
171
+ return input unless input.respond_to?(:select)
172
+
173
+ input = input.values if input.is_a?(Hash)
174
+ input_id = input.hash
175
+
176
+ # implement a hash based on method parameters to cache the end-result
177
+ # for given parameters.
178
+ @where_filter_cache ||= {}
179
+ @where_filter_cache[input_id] ||= {}
180
+ @where_filter_cache[input_id][property] ||= {}
181
+
182
+ # stash or retrive results to return
183
+ @where_filter_cache[input_id][property][value] ||= begin
184
+ input.select do |object|
185
+ Array(item_property(object, property)).map!(&:to_s).include?(value.to_s)
186
+ end || []
187
+ end
188
+ end
189
+
190
+ # Filters an array of objects against an expression
191
+ #
192
+ # input - the object array
193
+ # variable - the variable to assign each item to in the expression
194
+ # expression - a Liquid comparison expression passed in as a string
195
+ #
196
+ # Returns the filtered array of objects
197
+ def where_exp(input, variable, expression)
198
+ return input unless input.respond_to?(:select)
199
+
200
+ input = input.values if input.is_a?(Hash) # FIXME
201
+
202
+ condition = parse_condition(expression)
203
+ @context.stack do
204
+ input.select do |object|
205
+ @context[variable] = object
206
+ condition.evaluate(@context)
207
+ end
208
+ end || []
209
+ end
210
+
211
+ # Convert the input into integer
212
+ #
213
+ # input - the object string
214
+ #
215
+ # Returns the integer value
216
+ def to_integer(input)
217
+ return 1 if input == true
218
+ return 0 if input == false
219
+
220
+ input.to_i
221
+ end
222
+
223
+ # Sort an array of objects
224
+ #
225
+ # input - the object array
226
+ # property - property within each object to filter by
227
+ # nils ('first' | 'last') - nils appear before or after non-nil values
228
+ #
229
+ # Returns the filtered array of objects
230
+ def sort(input, property = nil, nils = "first")
231
+ raise ArgumentError, "Cannot sort a null object." if input.nil?
232
+
233
+ if property.nil?
234
+ input.sort
235
+ else
236
+ if nils == "first"
237
+ order = - 1
238
+ elsif nils == "last"
239
+ order = + 1
240
+ else
241
+ raise ArgumentError, "Invalid nils order: " \
242
+ "'#{nils}' is not a valid nils order. It must be 'first' or 'last'."
243
+ end
244
+
245
+ sort_input(input, property, order)
246
+ end
247
+ end
248
+
249
+ def pop(array, num = 1)
250
+ return array unless array.is_a?(Array)
251
+
252
+ num = Liquid::Utils.to_integer(num)
253
+ new_ary = array.dup
254
+ new_ary.pop(num)
255
+ new_ary
256
+ end
257
+
258
+ def push(array, input)
259
+ return array unless array.is_a?(Array)
260
+
261
+ new_ary = array.dup
262
+ new_ary.push(input)
263
+ new_ary
264
+ end
265
+
266
+ def shift(array, num = 1)
267
+ return array unless array.is_a?(Array)
268
+
269
+ num = Liquid::Utils.to_integer(num)
270
+ new_ary = array.dup
271
+ new_ary.shift(num)
272
+ new_ary
273
+ end
274
+
275
+ def unshift(array, input)
276
+ return array unless array.is_a?(Array)
277
+
278
+ new_ary = array.dup
279
+ new_ary.unshift(input)
280
+ new_ary
281
+ end
282
+
283
+ def sample(input, num = 1)
284
+ return input unless input.respond_to?(:sample)
285
+
286
+ num = Liquid::Utils.to_integer(num) rescue 1
287
+ if num == 1
288
+ input.sample
289
+ else
290
+ input.sample(num)
291
+ end
292
+ end
293
+
294
+ # Convert an object into its String representation for debugging
295
+ #
296
+ # input - The Object to be converted
297
+ #
298
+ # Returns a String representation of the object.
299
+ def inspect(input)
300
+ xml_escape(input.inspect)
301
+ end
302
+
303
+ private
304
+
305
+ # Sort the input Enumerable by the given property.
306
+ # If the property doesn't exist, return the sort order respective of
307
+ # which item doesn't have the property.
308
+ # We also utilize the Schwartzian transform to make this more efficient.
309
+ def sort_input(input, property, order)
310
+ input.map { |item| [item_property(item, property), item] }
311
+ .sort! do |a_info, b_info|
312
+ a_property = a_info.first
313
+ b_property = b_info.first
314
+
315
+ if !a_property.nil? && b_property.nil?
316
+ - order
317
+ elsif a_property.nil? && !b_property.nil?
318
+ + order
319
+ else
320
+ a_property <=> b_property || a_property.to_s <=> b_property.to_s
321
+ end
322
+ end
323
+ .map!(&:last)
324
+ end
325
+
326
+ def item_property(item, property)
327
+ if item.respond_to?(:to_liquid)
328
+ property.to_s.split(".").reduce(item.to_liquid) do |subvalue, attribute|
329
+ parse_sort_input(subvalue[attribute])
330
+ end
331
+ elsif item.respond_to?(:data)
332
+ parse_sort_input(item.data[property.to_s])
333
+ else
334
+ parse_sort_input(item[property.to_s])
335
+ end
336
+ end
337
+
338
+ # return numeric values as numbers for proper sorting
339
+ def parse_sort_input(property)
340
+ number_like = %r!\A\s*-?(?:\d+\.?\d*|\.\d+)\s*\Z!
341
+ return property.to_f if property =~ number_like
342
+
343
+ property
344
+ end
345
+
346
+ def as_liquid(item)
347
+ case item
348
+ when Hash
349
+ pairs = item.map { |k, v| as_liquid([k, v]) }
350
+ Hash[pairs]
351
+ when Array
352
+ item.map { |i| as_liquid(i) }
353
+ else
354
+ if item.respond_to?(:to_liquid)
355
+ liquidated = item.to_liquid
356
+ # prevent infinite recursion for simple types (which return `self`)
357
+ if liquidated == item
358
+ item
359
+ else
360
+ as_liquid(liquidated)
361
+ end
362
+ else
363
+ item
364
+ end
365
+ end
366
+ end
367
+
368
+ # Parse a string to a Liquid Condition
369
+ def parse_condition(exp)
370
+ parser = Liquid::Parser.new(exp)
371
+ left_expr = parser.expression
372
+ operator = parser.consume?(:comparison)
373
+ condition =
374
+ if operator
375
+ Liquid::Condition.new(Liquid::Expression.parse(left_expr),
376
+ operator,
377
+ Liquid::Expression.parse(parser.expression))
378
+ else
379
+ Liquid::Condition.new(Liquid::Expression.parse(left_expr))
380
+ end
381
+ parser.consume(:end_of_string)
382
+
383
+ condition
384
+ end
385
+ end
386
+ end
387
+
388
+ Liquid::Template.register_filter(
389
+ Jekyll::Filters
390
+ )
@@ -0,0 +1,110 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ module Filters
5
+ module DateFilters
6
+ # Format a date in short format e.g. "27 Jan 2011".
7
+ # Ordinal format is also supported, in both the UK
8
+ # (e.g. "27th Jan 2011") and US ("e.g. Jan 27th, 2011") formats.
9
+ # UK format is the default.
10
+ #
11
+ # date - the Time to format.
12
+ # type - if "ordinal" the returned String will be in ordinal format
13
+ # style - if "US" the returned String will be in US format.
14
+ # Otherwise it will be in UK format.
15
+ #
16
+ # Returns the formatting String.
17
+ def date_to_string(date, type = nil, style = nil)
18
+ stringify_date(date, "%b", type, style)
19
+ end
20
+
21
+ # Format a date in long format e.g. "27 January 2011".
22
+ # Ordinal format is also supported, in both the UK
23
+ # (e.g. "27th January 2011") and US ("e.g. January 27th, 2011") formats.
24
+ # UK format is the default.
25
+ #
26
+ # date - the Time to format.
27
+ # type - if "ordinal" the returned String will be in ordinal format
28
+ # style - if "US" the returned String will be in US format.
29
+ # Otherwise it will be in UK format.
30
+ #
31
+ # Returns the formatted String.
32
+ def date_to_long_string(date, type = nil, style = nil)
33
+ stringify_date(date, "%B", type, style)
34
+ end
35
+
36
+ # Format a date for use in XML.
37
+ #
38
+ # date - The Time to format.
39
+ #
40
+ # Examples
41
+ #
42
+ # date_to_xmlschema(Time.now)
43
+ # # => "2011-04-24T20:34:46+08:00"
44
+ #
45
+ # Returns the formatted String.
46
+ def date_to_xmlschema(date)
47
+ return date if date.to_s.empty?
48
+
49
+ time(date).xmlschema
50
+ end
51
+
52
+ # Format a date according to RFC-822
53
+ #
54
+ # date - The Time to format.
55
+ #
56
+ # Examples
57
+ #
58
+ # date_to_rfc822(Time.now)
59
+ # # => "Sun, 24 Apr 2011 12:34:46 +0000"
60
+ #
61
+ # Returns the formatted String.
62
+ def date_to_rfc822(date)
63
+ return date if date.to_s.empty?
64
+
65
+ time(date).rfc822
66
+ end
67
+
68
+ private
69
+
70
+ # month_type: Notations that evaluate to 'Month' via `Time#strftime` ("%b", "%B")
71
+ # type: nil (default) or "ordinal"
72
+ # style: nil (default) or "US"
73
+ #
74
+ # Returns a stringified date or the empty input.
75
+ def stringify_date(date, month_type, type = nil, style = nil)
76
+ return date if date.to_s.empty?
77
+
78
+ time = time(date)
79
+ if type == "ordinal"
80
+ day = time.day
81
+ ordinal_day = "#{day}#{ordinal(day)}"
82
+ return time.strftime("#{month_type} #{ordinal_day}, %Y") if style == "US"
83
+
84
+ return time.strftime("#{ordinal_day} #{month_type} %Y")
85
+ end
86
+ time.strftime("%d #{month_type} %Y")
87
+ end
88
+
89
+ def ordinal(number)
90
+ return "th" if (11..13).cover?(number)
91
+
92
+ case number % 10
93
+ when 1 then "st"
94
+ when 2 then "nd"
95
+ when 3 then "rd"
96
+ else "th"
97
+ end
98
+ end
99
+
100
+ def time(input)
101
+ date = Liquid::Utils.to_date(input)
102
+ unless date.respond_to?(:to_time)
103
+ raise Errors::InvalidDateError,
104
+ "Invalid Date: '#{input.inspect}' is not a valid datetime."
105
+ end
106
+ date.to_time.dup.localtime
107
+ end
108
+ end
109
+ end
110
+ end