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.
- checksums.yaml +4 -4
- data/Gemfile.lock +2 -2
- data/NEWS.md +7 -0
- data/lib/nanoc/base/entities/identifiable_collection.rb +8 -8
- data/lib/nanoc/base/entities/outdatedness_reasons.rb +0 -5
- data/lib/nanoc/base/repos/dependency_store.rb +23 -9
- data/lib/nanoc/base/services/compiler/stages/preprocess.rb +2 -1
- data/lib/nanoc/base/services/compiler_loader.rb +1 -1
- data/lib/nanoc/base/services/outdatedness_checker.rb +0 -1
- data/lib/nanoc/base/services/outdatedness_rules.rb +0 -1
- data/lib/nanoc/cli/commands/compile.rb +1 -0
- data/lib/nanoc/cli/commands/compile_listeners/diff_generator.rb +1 -1
- data/lib/nanoc/filters/colorize_syntax.rb +54 -316
- data/lib/nanoc/filters/colorize_syntax/colorizers.rb +177 -0
- data/lib/nanoc/version.rb +1 -1
- data/spec/nanoc/base/compiler_spec.rb +5 -2
- data/spec/nanoc/base/entities/identifiable_collection_spec.rb +29 -0
- data/spec/nanoc/base/repos/dependency_store_spec.rb +79 -79
- data/spec/nanoc/base/services/compiler/stages/compile_reps_spec.rb +5 -2
- data/spec/nanoc/base/services/dependency_tracker_spec.rb +7 -1
- data/spec/nanoc/base/services/outdatedness_checker_spec.rb +6 -7
- data/spec/nanoc/base/services/outdatedness_rules_spec.rb +3 -56
- data/spec/nanoc/base/views/document_view_spec.rb +7 -1
- data/spec/nanoc/base/views/item_rep_view_spec.rb +7 -1
- data/spec/nanoc/base/views/item_view_spec.rb +7 -1
- data/spec/nanoc/cli/commands/compile/diff_generator_spec.rb +44 -0
- data/spec/nanoc/cli/commands/show_data_spec.rb +1 -5
- data/spec/nanoc/integration/compile_command_spec.rb +31 -0
- data/test/base/test_dependency_tracker.rb +106 -86
- data/test/filters/test_xsl.rb +5 -1
- metadata +5 -3
- 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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d25ba882d1c709e130d1da34de63b5bee85ffaa2
|
4
|
+
data.tar.gz: 6e3c673ec2c5b30a25edb775f42197813899cabf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 914fde5a0e842055cabfa804950d3b355f3b03b33b3a72cddbd1654aa4e9233163848386b728e2ce08238de98311d2af31305e874bc421549ac858acb310b73b
|
7
|
+
data.tar.gz: 2727ef6a9f49eedec58419971d324ce73a50dad71776ff1e303d7a50567b7a47881e4acb8be100cb095bbea68a4a6540da768aedfaaa29f7c05e63fd8732347f
|
data/Gemfile.lock
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
GIT
|
2
2
|
remote: https://github.com/bbatsov/rubocop.git
|
3
|
-
revision:
|
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.
|
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
|
-
|
7
|
-
attr_accessor :
|
6
|
+
attr_accessor :items
|
7
|
+
attr_accessor :layouts
|
8
8
|
|
9
|
-
|
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
|
-
@
|
12
|
+
@items = items
|
13
|
+
@layouts = layouts
|
14
|
+
|
14
15
|
@new_objects = []
|
15
|
-
@graph = Nanoc::Int::DirectedGraph.new([nil] + @
|
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] +
|
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
|
-
|
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 =
|
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.
|
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
|
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
|
|
@@ -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
|
-
|
13
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
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
|
396
|
-
|
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
|
405
|
-
colorizer =
|
406
|
-
|
407
|
-
|
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
|
417
|
-
|
418
|
-
|
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'
|