ngage 0.0.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.
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