nanoc 4.7.6 → 4.7.7

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 (32) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +2 -2
  3. data/NEWS.md +7 -0
  4. data/lib/nanoc/base/entities/identifiable_collection.rb +8 -8
  5. data/lib/nanoc/base/entities/outdatedness_reasons.rb +0 -5
  6. data/lib/nanoc/base/repos/dependency_store.rb +23 -9
  7. data/lib/nanoc/base/services/compiler/stages/preprocess.rb +2 -1
  8. data/lib/nanoc/base/services/compiler_loader.rb +1 -1
  9. data/lib/nanoc/base/services/outdatedness_checker.rb +0 -1
  10. data/lib/nanoc/base/services/outdatedness_rules.rb +0 -1
  11. data/lib/nanoc/cli/commands/compile.rb +1 -0
  12. data/lib/nanoc/cli/commands/compile_listeners/diff_generator.rb +1 -1
  13. data/lib/nanoc/filters/colorize_syntax.rb +54 -316
  14. data/lib/nanoc/filters/colorize_syntax/colorizers.rb +177 -0
  15. data/lib/nanoc/version.rb +1 -1
  16. data/spec/nanoc/base/compiler_spec.rb +5 -2
  17. data/spec/nanoc/base/entities/identifiable_collection_spec.rb +29 -0
  18. data/spec/nanoc/base/repos/dependency_store_spec.rb +79 -79
  19. data/spec/nanoc/base/services/compiler/stages/compile_reps_spec.rb +5 -2
  20. data/spec/nanoc/base/services/dependency_tracker_spec.rb +7 -1
  21. data/spec/nanoc/base/services/outdatedness_checker_spec.rb +6 -7
  22. data/spec/nanoc/base/services/outdatedness_rules_spec.rb +3 -56
  23. data/spec/nanoc/base/views/document_view_spec.rb +7 -1
  24. data/spec/nanoc/base/views/item_rep_view_spec.rb +7 -1
  25. data/spec/nanoc/base/views/item_view_spec.rb +7 -1
  26. data/spec/nanoc/cli/commands/compile/diff_generator_spec.rb +44 -0
  27. data/spec/nanoc/cli/commands/show_data_spec.rb +1 -5
  28. data/spec/nanoc/integration/compile_command_spec.rb +31 -0
  29. data/test/base/test_dependency_tracker.rb +106 -86
  30. data/test/filters/test_xsl.rb +5 -1
  31. metadata +5 -3
  32. data/lib/nanoc/base/services/outdatedness_rules/paths_modified.rb +0 -20
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a40c3389c6ef42f0924566370507dfc3a2e361f8
4
- data.tar.gz: '09906841a6aa6ba7dc5d4bdc06e5914a4678d274'
3
+ metadata.gz: d25ba882d1c709e130d1da34de63b5bee85ffaa2
4
+ data.tar.gz: 6e3c673ec2c5b30a25edb775f42197813899cabf
5
5
  SHA512:
6
- metadata.gz: 91221955a35dfd5786f068f6fca88f6c3d2ee06cc9ece04e85aedd769c5d66147aec8d37c663c1dcc2e208ce32c38d0939a78d1539dd963f3380fe427d76d854
7
- data.tar.gz: 4ef5eac2bd6d99bbeb5c1276fa13dd498f7cf8e70cce12132945ff682cf90a02a8d11c459bb88300934fd1686f61c6c069a371c196ca51f605516c7454017c89
6
+ metadata.gz: 914fde5a0e842055cabfa804950d3b355f3b03b33b3a72cddbd1654aa4e9233163848386b728e2ce08238de98311d2af31305e874bc421549ac858acb310b73b
7
+ data.tar.gz: 2727ef6a9f49eedec58419971d324ce73a50dad71776ff1e303d7a50567b7a47881e4acb8be100cb095bbea68a4a6540da768aedfaaa29f7c05e63fd8732347f
@@ -1,6 +1,6 @@
1
1
  GIT
2
2
  remote: https://github.com/bbatsov/rubocop.git
3
- revision: cf07b9a493feed28577032c307ddab3cb7b8c2fc
3
+ revision: dcb3f160a2e23218a7826aadd0e64baefd6d7521
4
4
  specs:
5
5
  rubocop (0.48.1)
6
6
  parallel (~> 1.10)
@@ -13,7 +13,7 @@ GIT
13
13
  PATH
14
14
  remote: .
15
15
  specs:
16
- nanoc (4.7.6)
16
+ nanoc (4.7.7)
17
17
  cri (~> 2.8)
18
18
  ddplugin (~> 1.0)
19
19
  hamster (~> 3.0)
data/NEWS.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Nanoc news
2
2
 
3
+ ## 4.7.7 (2017-04-16)
4
+
5
+ Enhancements:
6
+
7
+ * Added `--diff` option to `compile` command as a one-time alternative to `enable_output_diff` (#1155)
8
+ * Sped up incremental compilation (#1156, #1157)
9
+
3
10
  ## 4.7.6 (2017-04-15)
4
11
 
5
12
  Enhancements:
@@ -64,6 +64,14 @@ module Nanoc::Int
64
64
  self.class.new(@config, @objects.reject(&block))
65
65
  end
66
66
 
67
+ def object_with_identifier(identifier)
68
+ if frozen?
69
+ @mapping[identifier.to_s]
70
+ else
71
+ @objects.find { |i| i.identifier == identifier }
72
+ end
73
+ end
74
+
67
75
  protected
68
76
 
69
77
  contract C::Any => C::Maybe[C::RespondTo[:identifier]]
@@ -96,14 +104,6 @@ module Nanoc::Int
96
104
  find_all_unmemoized(arg)
97
105
  end
98
106
 
99
- def object_with_identifier(identifier)
100
- if frozen?
101
- @mapping[identifier.to_s]
102
- else
103
- @objects.find { |i| i.identifier == identifier }
104
- end
105
- end
106
-
107
107
  def object_matching_glob(glob)
108
108
  if use_globs?
109
109
  pat = Nanoc::Int::Pattern.from(glob)
@@ -62,11 +62,6 @@ module Nanoc::Int
62
62
  end
63
63
  end
64
64
 
65
- PathsModified = Generic.new(
66
- 'One or more output paths of this item have been modified since the last time the site was compiled.',
67
- Props.new(path: true),
68
- )
69
-
70
65
  UsesAlwaysOutdatedFilter = Generic.new(
71
66
  'This item rep uses one or more filters that cannot track dependencies, and will thus always be considered as outdated.',
72
67
  Props.new(raw_content: true, attributes: true, compiled_content: true),
@@ -3,16 +3,17 @@ module Nanoc::Int
3
3
  class DependencyStore < ::Nanoc::Int::Store
4
4
  include Nanoc::Int::ContractsSupport
5
5
 
6
- # @return [Array<Nanoc::Int::Item, Nanoc::Int::Layout>]
7
- attr_accessor :objects
6
+ attr_accessor :items
7
+ attr_accessor :layouts
8
8
 
9
- # @param [Array<Nanoc::Int::Item, Nanoc::Int::Layout>] objects
10
- def initialize(objects, site: nil)
9
+ def initialize(items, layouts, site: nil)
11
10
  super(Nanoc::Int::Store.tmp_path_for(site: site, store_name: 'dependencies'), 4)
12
11
 
13
- @objects = objects
12
+ @items = items
13
+ @layouts = layouts
14
+
14
15
  @new_objects = []
15
- @graph = Nanoc::Int::DirectedGraph.new([nil] + @objects)
16
+ @graph = Nanoc::Int::DirectedGraph.new([nil] + @items.to_a + @layouts.to_a)
16
17
  end
17
18
 
18
19
  contract C::Or[Nanoc::Int::Item, Nanoc::Int::ItemRep, Nanoc::Int::Layout] => C::ArrayOf[Nanoc::Int::Dependency]
@@ -113,12 +114,25 @@ module Nanoc::Int
113
114
  end
114
115
 
115
116
  def data=(new_data)
117
+ objects = @items.to_a + @layouts.to_a
118
+
116
119
  # Create new graph
117
- @graph = Nanoc::Int::DirectedGraph.new([nil] + @objects)
120
+ @graph = Nanoc::Int::DirectedGraph.new([nil] + objects)
118
121
 
119
122
  # Load vertices
120
123
  previous_objects = new_data[:vertices].map do |reference|
121
- @objects.find { |obj| reference == obj.reference }
124
+ if reference
125
+ case reference[0]
126
+ when :item
127
+ @items.object_with_identifier(reference[1])
128
+ when :layout
129
+ @layouts.object_with_identifier(reference[1])
130
+ else
131
+ raise Nanoc::Int::Errors::InternalInconsistency, "unrecognised reference #{reference[0].inspect}"
132
+ end
133
+ else
134
+ nil
135
+ end
122
136
  end
123
137
 
124
138
  # Load edges
@@ -130,7 +144,7 @@ module Nanoc::Int
130
144
  end
131
145
 
132
146
  # Record dependency from all items on new items
133
- @new_objects = @objects - previous_objects
147
+ @new_objects = objects - previous_objects
134
148
  end
135
149
  end
136
150
  end
@@ -12,7 +12,8 @@ module Nanoc::Int::Compiler::Stages
12
12
  @site.data_source = Nanoc::Int::InMemDataSource.new(@site.items, @site.layouts)
13
13
  @action_provider.preprocess(@site)
14
14
 
15
- @dependency_store.objects = @site.items.to_a + @site.layouts.to_a
15
+ @dependency_store.items = @site.items
16
+ @dependency_store.layouts = @site.layouts
16
17
  @checksum_store.objects = @site.items.to_a + @site.layouts.to_a + @site.code_snippets + [@site.config]
17
18
  end
18
19
 
@@ -5,7 +5,7 @@ module Nanoc::Int
5
5
  action_sequence_store = Nanoc::Int::ActionSequenceStore.new(site: site)
6
6
 
7
7
  dependency_store =
8
- Nanoc::Int::DependencyStore.new(site.items.to_a + site.layouts.to_a, site: site)
8
+ Nanoc::Int::DependencyStore.new(site.items, site.layouts, site: site)
9
9
 
10
10
  objects = site.items.to_a + site.layouts.to_a + site.code_snippets + [site.config]
11
11
 
@@ -13,7 +13,6 @@ module Nanoc::Int
13
13
  RULES_FOR_ITEM_REP =
14
14
  [
15
15
  Rules::RulesModified,
16
- Rules::PathsModified,
17
16
  Rules::ContentModified,
18
17
  Rules::AttributesModified,
19
18
  Rules::NotWritten,
@@ -9,6 +9,5 @@ require_relative 'outdatedness_rules/code_snippets_modified'
9
9
  require_relative 'outdatedness_rules/configuration_modified'
10
10
  require_relative 'outdatedness_rules/content_modified'
11
11
  require_relative 'outdatedness_rules/not_written'
12
- require_relative 'outdatedness_rules/paths_modified'
13
12
  require_relative 'outdatedness_rules/rules_modified'
14
13
  require_relative 'outdatedness_rules/uses_always_outdated_filter'
@@ -4,6 +4,7 @@ description <<-EOS
4
4
  Compile all items of the current site.
5
5
  EOS
6
6
  flag nil, :profile, 'profile compilation' if Nanoc::Feature.enabled?(Nanoc::Feature::PROFILER)
7
+ flag nil, :diff, 'generate diff'
7
8
 
8
9
  require_relative 'compile_listeners/abstract'
9
10
  require_relative 'compile_listeners/debug_printer'
@@ -2,7 +2,7 @@ module Nanoc::CLI::Commands::CompileListeners
2
2
  class DiffGenerator < Abstract
3
3
  # @see Listener#enable_for?
4
4
  def self.enable_for?(command_runner)
5
- command_runner.site.config[:enable_output_diff]
5
+ command_runner.site.config[:enable_output_diff] || command_runner.options[:diff]
6
6
  end
7
7
 
8
8
  # @see Listener#start
@@ -5,92 +5,14 @@ module Nanoc::Filters
5
5
 
6
6
  requires 'nokogiri', 'stringio', 'open3'
7
7
 
8
- # The default colorizer to use for a language if the colorizer for that
9
- # language is not overridden.
10
8
  DEFAULT_COLORIZER = :coderay
11
9
 
12
- # Syntax-highlights code blocks in the given content. Code blocks should
13
- # be enclosed in `pre` elements that contain a `code` element. The code
14
- # element should have an indication of the language the code is in. There
15
- # are two possible ways of adding such an indication:
16
- #
17
- # 1. A HTML class starting with `language-` and followed by the
18
- # code language, as specified by HTML5. For example, `<code class="language-ruby">`.
19
- #
20
- # 2. A comment on the very first line of the code block in the format
21
- # `#!language` where `language` is the language the code is in. For
22
- # example, `#!ruby`.
23
- #
24
- # Options for individual colorizers will be taken from the {#run}
25
- # options’ value for the given colorizer. For example, if the filter is
26
- # invoked with a `:coderay => coderay_options_hash` option, the
27
- # `coderay_options_hash` hash will be passed to the CodeRay colorizer.
28
- #
29
- # Currently, the following colorizers are supported:
30
- #
31
- # * `:coderay` for [Coderay](http://coderay.rubychan.de/)
32
- # * `:pygmentize` for [pygmentize](http://pygments.org/docs/cmdline/), the
33
- # command-line frontend for [Pygments](http://pygments.org/)
34
- # * `:pygmentsrb` for [pygments.rb](https://github.com/tmm1/pygments.rb),
35
- # a Ruby interface for [Pygments](http://pygments.org/)
36
- # * `:simon_highlight` for [Highlight](http://www.andre-simon.de/doku/highlight/en/highlight.html)
37
- # * `:rouge` for [Rouge](https://github.com/jayferd/rouge/)
38
- #
39
- # Additional colorizer implementations are welcome!
40
- #
41
- # @example Using a class to indicate type of code be highlighted
42
- #
43
- # <pre><code class="language-ruby">
44
- # def foo
45
- # "asdf"
46
- # end
47
- # </code></pre>
48
- #
49
- # @example Using a comment to indicate type of code be highlighted
50
- #
51
- # <pre><code>
52
- # #!ruby
53
- # def foo
54
- # "asdf"
55
- # end
56
- # </code></pre>
57
- #
58
- # @example Invoking the filter with custom parameters
59
- #
60
- # filter :colorize_syntax,
61
- # :colorizers => { :ruby => :coderay },
62
- # :coderay => { :line_numbers => :list }
63
- #
64
- # @param [String] content The content to filter
65
- #
66
- # @option params [Symbol] :default_colorizer (DEFAULT_COLORIZER) The
67
- # default colorizer, i.e. the colorizer that will be used when the
68
- # colorizer is not overriden for a specific language.
69
- #
70
- # @option params [Symbol] :syntax (:html) The syntax to use, which can be
71
- # `:html`, `:xml` or `:xhtml`, the latter two being the same.
72
- #
73
- # @option params [Hash] :colorizers ({}) A hash containing
74
- # a mapping of programming languages (symbols, not strings) onto
75
- # colorizers (symbols).
76
- #
77
- # @option params [Boolean] :outside_pre (false) `true` if the colorizer
78
- # should be applied on `code` elements outside `pre` elements, false
79
- # if only `code` elements inside` pre` elements should be colorized.
80
- #
81
- # @option params [Symbol] :is_fullpage (false) Whether to treat the input
82
- # as a full HTML page or a page fragment. When true, HTML boilerplate
83
- # such as the doctype, `html`, `head` and `body` elements will be added.
84
- #
85
- # @return [String] The filtered content
10
+ ExtractedLanguage = Struct.new(:language, :from_class)
11
+
86
12
  def run(content, params = {})
87
13
  Nanoc::Extra::JRubyNokogiriWarner.check_and_warn
88
14
 
89
- # Take colorizers from parameters
90
- @colorizers = Hash.new(params[:default_colorizer] || DEFAULT_COLORIZER)
91
- (params[:colorizers] || {}).each_pair do |language, colorizer|
92
- @colorizers[language] = colorizer
93
- end
15
+ @colorizers = colorizers_from_params(params)
94
16
 
95
17
  syntax = params.fetch(:syntax, :html)
96
18
  parser = parser_for(syntax)
@@ -100,42 +22,56 @@ module Nanoc::Filters
100
22
  selector = params[:outside_pre] ? 'code' : 'pre > code'
101
23
  doc.css(selector).each do |element|
102
24
  # Get language
103
- has_class = false
104
- language = nil
105
- if element['class']
106
- # Get language from class
107
- match = element['class'].match(/(^| )language-([^ ]+)/)
108
- language = match[2] if match
109
- has_class = true if language
110
- else
111
- # Get language from comment line
112
- match = element.inner_text.strip.split[0].match(/^#!([^\/][^\n]*)$/)
113
- language = match[1] if match
114
- element.content = element.content.sub(/^#!([^\/][^\n]*)$\n/, '') if language
115
- end
25
+ extracted_language = extract_language(element)
116
26
 
117
27
  # Give up if there is no hope left
118
- next if language.nil?
28
+ next unless extracted_language
119
29
 
120
30
  # Highlight
121
31
  raw = strip(element.inner_text)
122
- highlighted_code = highlight(raw, language, params)
32
+ highlighted_code = highlight(raw, extracted_language.language, params)
123
33
  element.children = parse_fragment(parser, strip(highlighted_code))
124
34
 
125
35
  # Add language-something class
126
- unless has_class
36
+ unless extracted_language.from_class
127
37
  klass = element['class'] || ''
128
38
  klass << ' ' unless [' ', nil].include?(klass[-1, 1])
129
- klass << "language-#{language}"
39
+ klass << "language-#{extracted_language.language}"
130
40
  element['class'] = klass
131
41
  end
132
42
 
133
- highlight_postprocess(language, element.parent)
43
+ highlight_postprocess(extracted_language.language, element.parent)
134
44
  end
135
45
 
136
46
  serialize(doc, syntax)
137
47
  end
138
48
 
49
+ def extract_language(element)
50
+ has_class = false
51
+ language = nil
52
+ if element['class']
53
+ # Get language from class
54
+ match = element['class'].match(/(^| )language-([^ ]+)/)
55
+ language = match[2] if match
56
+ has_class = true if language
57
+ else
58
+ # Get language from comment line
59
+ match = element.inner_text.strip.split[0].match(/^#!([^\/][^\n]*)$/)
60
+ language = match[1] if match
61
+ element.content = element.content.sub(/^#!([^\/][^\n]*)$\n/, '') if language
62
+ end
63
+
64
+ language ? ExtractedLanguage.new(language, has_class) : nil
65
+ end
66
+
67
+ def colorizers_from_params(params)
68
+ colorizers = Hash.new(params[:default_colorizer] || DEFAULT_COLORIZER)
69
+ (params[:colorizers] || {}).each_pair do |language, colorizer|
70
+ colorizers[language] = colorizer
71
+ end
72
+ colorizers
73
+ end
74
+
139
75
  def parser_for(syntax)
140
76
  case syntax
141
77
  when :html
@@ -173,16 +109,6 @@ module Nanoc::Filters
173
109
  parser_class.fragment(content)
174
110
  end
175
111
 
176
- # Parses the given content using the given class. This method also handles
177
- # an issue with Nokogiri on JRuby causing “cannot modify frozen string”
178
- # errors.
179
- #
180
- # @param [String] content The content to parse
181
- #
182
- # @param [Class] klass The Nokogiri parser class
183
- #
184
- # @param [Boolean] is_fullpage true if the given content is a full page,
185
- # false if it is a fragment
186
112
  def parse(content, klass, is_fullpage)
187
113
  if is_fullpage
188
114
  parse_full(klass, content)
@@ -197,225 +123,37 @@ module Nanoc::Filters
197
123
  end
198
124
  end
199
125
 
200
- # Runs the code through [CodeRay](http://coderay.rubychan.de/).
201
- #
202
- # @param [String] code The code to colorize
203
- #
204
- # @param [String] language The language the code is written in
205
- #
206
- # @param [Hash] params Parameters to pass on to CodeRay
207
- #
208
- # @return [String] The colorized output
209
- def coderay(code, language, params = {})
210
- require 'coderay'
211
-
212
- ::CodeRay.scan(code, language).html(params)
213
- end
214
-
215
- # Returns the input itself, not performing any code highlighting.
216
- #
217
- # @param [String] code The code to colorize
218
- #
219
- # @param [String] language The language the code is written in (unused)
220
- #
221
- # @return [String] The colorized output, which is identical to the input
222
- # in this case
223
- def dummy(code, language, params = {}) # rubocop:disable Lint/UnusedMethodArgument
224
- code
225
- end
226
-
227
- # Runs the content through [pygmentize](http://pygments.org/docs/cmdline/),
228
- # the command-line frontend for [Pygments](http://pygments.org/).
229
- #
230
- # @param [String] code The code to colorize
231
- #
232
- # @param [String] language The language the code is written in
233
- #
234
- # @option params [String, Symbol] :encoding The encoding of the code block
235
- #
236
- # @return [String] The colorized output
237
- def pygmentize(code, language, params = {})
238
- check_availability('pygmentize', '-V')
239
-
240
- params[:encoding] ||= 'utf-8'
241
- params[:nowrap] ||= 'True'
242
-
243
- cmd = ['pygmentize', '-l', language, '-f', 'html']
244
- cmd << '-O' << params.map { |k, v| "#{k}=#{v}" }.join(',') unless params.empty?
245
-
246
- stdout = StringIO.new
247
- stderr = $stderr
248
- piper = Nanoc::Extra::Piper.new(stdout: stdout, stderr: stderr)
249
- piper.run(cmd, code)
250
-
251
- stdout.string
252
- end
253
-
254
- # Runs the content through [Pygments](http://pygments.org/) via
255
- # [pygments.rb](https://github.com/tmm1/pygments.rb).
256
- #
257
- # @param [String] code The code to colorize
258
- #
259
- # @param [String] language The language the code is written in
260
- #
261
- # @return [String] The colorized output
262
- def pygmentsrb(code, language, params = {})
263
- require 'pygments'
264
-
265
- args = params.dup
266
- args[:lexer] ||= language
267
- args[:options] ||= {}
268
- args[:options][:encoding] ||= 'utf-8'
269
- args[:options][:nowrap] ||= 'True'
270
-
271
- Pygments.highlight(code, args)
272
- end
273
-
274
- SIMON_HIGHLIGHT_OPT_MAP = {
275
- wrap: '-W',
276
- include_style: '-I',
277
- line_numbers: '-l',
278
- }.freeze
279
-
280
- # Runs the content through [Highlight](http://www.andre-simon.de/doku/highlight/en/highlight.html).
281
- #
282
- # @param [String] code The code to colorize
283
- #
284
- # @param [String] language The language the code is written in
285
- #
286
- # @option params [String] :style The style to use
287
- #
288
- # @return [String] The colorized output
289
- def simon_highlight(code, language, params = {})
290
- check_availability('highlight', '--version')
291
-
292
- cmd = ['highlight', '--syntax', language, '--fragment']
293
- params.each do |key, _value|
294
- if SIMON_HIGHLIGHT_OPT_MAP[key]
295
- cmd << SIMON_HIGHLIGHT_OPT_MAP[key]
296
- else
297
- # TODO: allow passing other options
298
- case key
299
- when :style
300
- cmd << '--style' << params[:style]
301
- end
302
- end
303
- end
304
-
305
- stdout = StringIO.new
306
- stderr = $stderr
307
- piper = Nanoc::Extra::Piper.new(stdout: stdout, stderr: stderr)
308
- piper.run(cmd, code)
309
-
310
- stdout.string
311
- end
312
-
313
- # Wraps the element in <div class="CodeRay"><div class="code">
314
- def coderay_postprocess(_language, element)
315
- # Skip if we're a free <code>
316
- return if element.parent.nil?
317
-
318
- # <div class="code">
319
- div_inner = Nokogiri::XML::Node.new('div', element.document)
320
- div_inner['class'] = 'code'
321
- div_inner.children = element.dup
322
-
323
- # <div class="CodeRay">
324
- div_outer = Nokogiri::XML::Node.new('div', element.document)
325
- div_outer['class'] = 'CodeRay'
326
- div_outer.children = div_inner
327
-
328
- # orig element
329
- element.swap div_outer
330
- end
331
-
332
- # Runs the content through [Rouge](https://github.com/jayferd/rouge/.
333
- #
334
- # @param [String] code The code to colorize
335
- #
336
- # @param [String] language The language the code is written in
337
- #
338
- # @return [String] The colorized output
339
- def rouge(code, language, params = {})
340
- require 'rouge'
341
-
342
- if Rouge.version < '2' || params.fetch(:legacy, false)
343
- # Rouge 1.x or Rouge 2.x legacy options
344
- formatter_options = {
345
- css_class: params.fetch(:css_class, 'highlight'),
346
- inline_theme: params.fetch(:inline_theme, nil),
347
- line_numbers: params.fetch(:line_numbers, false),
348
- start_line: params.fetch(:start_line, 1),
349
- wrap: params.fetch(:wrap, false),
350
- }
351
- formatter_cls = Rouge::Formatters.const_get(Rouge.version < '2' ? 'HTML' : 'HTMLLegacy')
352
- formatter = formatter_cls.new(formatter_options)
353
- else
354
- formatter = params.fetch(:formatter, Rouge::Formatters::HTML.new)
355
- end
356
-
357
- lexer = Rouge::Lexer.find_fancy(language, code) || Rouge::Lexers::PlainText
358
- formatter.format(lexer.lex(code))
359
- end
360
-
361
- # Removes the double wrapping.
362
- #
363
- # Before:
364
- #
365
- # <pre><code class="language-ruby"><pre class="highlight"><code>
366
- #
367
- # After:
368
- #
369
- # <pre><code class="language-ruby highlight">
370
- def rouge_postprocess(_language, element)
371
- return if element.name != 'pre'
372
-
373
- code1 = element.xpath('code').first
374
- return if code1.nil?
375
-
376
- pre = code1.xpath('pre').first
377
- return if pre.nil?
378
-
379
- code2 = pre.xpath('code').first
380
- return if code2.nil?
381
-
382
- code1.inner_html = code2.inner_html
383
- code1['class'] = [code1['class'], pre['class']].compact.join(' ')
384
- end
385
-
386
126
  protected
387
127
 
388
- KNOWN_COLORIZERS = %i[coderay dummy pygmentize pygmentsrb simon_highlight rouge].freeze
389
-
390
128
  # Removes the first blank lines and any whitespace at the end.
391
129
  def strip(s)
392
130
  s.lines.drop_while { |line| line.strip.empty? }.join.rstrip
393
131
  end
394
132
 
395
- def highlight(code, language, params = {})
396
- colorizer = @colorizers[language.to_sym]
397
- if KNOWN_COLORIZERS.include?(colorizer)
398
- send(colorizer, code, language, params[colorizer] || {})
399
- else
400
- raise "I don’t know how to highlight code using the “#{colorizer}” colorizer"
401
- end
133
+ def colorizer_name_for(language)
134
+ @colorizers[language.to_sym]
402
135
  end
403
136
 
404
- def highlight_postprocess(language, element)
405
- colorizer = @colorizers[language.to_sym]
406
- if KNOWN_COLORIZERS.include?(colorizer)
407
- sym = (colorizer.to_s + '_postprocess').to_sym
408
- if respond_to?(sym)
409
- send(sym, language, element)
410
- end
411
- else
412
- raise "I don’t know how to highlight code using the “#{colorizer}” colorizer"
137
+ def colorizer_named(name)
138
+ colorizer = Colorizers::Abstract.named(name.to_sym)
139
+ unless colorizer
140
+ raise "I don’t know how to highlight code using the “#{name}” colorizer"
413
141
  end
142
+ colorizer
143
+ end
144
+
145
+ def highlight(code, language, params = {})
146
+ colorizer_name = colorizer_name_for(language)
147
+ colorizer = colorizer_named(colorizer_name)
148
+ colorizer.new.process(code, language, params[colorizer_name] || {})
414
149
  end
415
150
 
416
- def check_availability(*cmd)
417
- piper = Nanoc::Extra::Piper.new(stdout: StringIO.new, stderr: StringIO.new)
418
- piper.run(cmd, nil)
151
+ def highlight_postprocess(language, element)
152
+ colorizer_name = colorizer_name_for(language)
153
+ colorizer = colorizer_named(colorizer_name)
154
+ colorizer.new.postprocess(language, element)
419
155
  end
420
156
  end
421
157
  end
158
+
159
+ require_relative 'colorize_syntax/colorizers'