nanoc 4.7.6 → 4.7.7
Sign up to get free protection for your applications and to get access to all the features.
- 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'
|