html-pipeline 2.14.3 → 3.0.2
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/.github/FUNDING.yml +11 -3
- data/.github/dependabot.yml +27 -0
- data/.github/workflows/automerge.yml +13 -0
- data/.github/workflows/ci.yml +22 -0
- data/.github/workflows/lint.yml +23 -0
- data/.github/workflows/publish.yml +19 -0
- data/.rubocop.yml +17 -0
- data/.ruby-version +1 -0
- data/.vscode/settings.json +8 -0
- data/CHANGELOG.md +119 -2
- data/Gemfile +31 -15
- data/{LICENSE → LICENSE.txt} +2 -2
- data/README.md +241 -224
- data/Rakefile +14 -7
- data/UPGRADING.md +34 -0
- data/html-pipeline.gemspec +31 -21
- data/lib/html-pipeline.rb +3 -0
- data/lib/html_pipeline/convert_filter/markdown_filter.rb +26 -0
- data/lib/html_pipeline/convert_filter.rb +17 -0
- data/lib/html_pipeline/filter.rb +89 -0
- data/lib/html_pipeline/node_filter/absolute_source_filter.rb +54 -0
- data/lib/html_pipeline/node_filter/asset_proxy_filter.rb +86 -0
- data/lib/{html/pipeline → html_pipeline/node_filter}/emoji_filter.rb +58 -54
- data/lib/html_pipeline/node_filter/https_filter.rb +22 -0
- data/lib/html_pipeline/node_filter/image_max_width_filter.rb +40 -0
- data/lib/{html/pipeline/@mention_filter.rb → html_pipeline/node_filter/mention_filter.rb} +54 -68
- data/lib/html_pipeline/node_filter/syntax_highlight_filter.rb +62 -0
- data/lib/html_pipeline/node_filter/table_of_contents_filter.rb +70 -0
- data/lib/html_pipeline/node_filter/team_mention_filter.rb +105 -0
- data/lib/html_pipeline/node_filter.rb +31 -0
- data/lib/html_pipeline/sanitization_filter.rb +188 -0
- data/lib/{html/pipeline → html_pipeline/text_filter}/image_filter.rb +3 -3
- data/lib/{html/pipeline → html_pipeline/text_filter}/plain_text_input_filter.rb +3 -5
- data/lib/html_pipeline/text_filter.rb +21 -0
- data/lib/html_pipeline/version.rb +5 -0
- data/lib/html_pipeline.rb +281 -0
- metadata +58 -54
- data/.travis.yml +0 -43
- data/Appraisals +0 -19
- data/CONTRIBUTING.md +0 -60
- data/bin/html-pipeline +0 -78
- data/lib/html/pipeline/@team_mention_filter.rb +0 -99
- data/lib/html/pipeline/absolute_source_filter.rb +0 -52
- data/lib/html/pipeline/autolink_filter.rb +0 -34
- data/lib/html/pipeline/body_content.rb +0 -44
- data/lib/html/pipeline/camo_filter.rb +0 -105
- data/lib/html/pipeline/email_reply_filter.rb +0 -69
- data/lib/html/pipeline/filter.rb +0 -165
- data/lib/html/pipeline/https_filter.rb +0 -29
- data/lib/html/pipeline/image_max_width_filter.rb +0 -37
- data/lib/html/pipeline/markdown_filter.rb +0 -56
- data/lib/html/pipeline/sanitization_filter.rb +0 -144
- data/lib/html/pipeline/syntax_highlight_filter.rb +0 -50
- data/lib/html/pipeline/text_filter.rb +0 -16
- data/lib/html/pipeline/textile_filter.rb +0 -25
- data/lib/html/pipeline/toc_filter.rb +0 -69
- data/lib/html/pipeline/version.rb +0 -7
- data/lib/html/pipeline.rb +0 -210
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class HTMLPipeline
|
4
|
+
class TextFilter < Filter
|
5
|
+
attr_reader :text
|
6
|
+
|
7
|
+
def initialize(text, context: {}, result: {})
|
8
|
+
raise TypeError, "text must be a String" unless text.is_a?(String)
|
9
|
+
|
10
|
+
# Ensure that this is always a string
|
11
|
+
@text = text.respond_to?(:to_str) ? text.to_str : text.to_s
|
12
|
+
super(context: context, result: result)
|
13
|
+
end
|
14
|
+
|
15
|
+
class << self
|
16
|
+
def call(input, context: {}, result: {})
|
17
|
+
new(input, context: context, result: result).call
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,281 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "zeitwerk"
|
4
|
+
lib_dir = File.join(File.dirname(__dir__), "lib")
|
5
|
+
lib_html_pipeline_dir = File.join(File.dirname(__dir__), "lib", "html_pipeline")
|
6
|
+
gem_loader = Zeitwerk::Loader.for_gem
|
7
|
+
gem_loader.inflector.inflect(
|
8
|
+
"html_pipeline" => "HTMLPipeline",
|
9
|
+
)
|
10
|
+
|
11
|
+
gem_loader.ignore(File.join(lib_html_pipeline_dir, "convert_filter"))
|
12
|
+
gem_loader.ignore(File.join(lib_html_pipeline_dir, "node_filter"))
|
13
|
+
gem_loader.ignore(File.join(lib_html_pipeline_dir, "text_filter"))
|
14
|
+
gem_loader.ignore(File.join(lib_dir, "html-pipeline.rb"))
|
15
|
+
gem_loader.setup
|
16
|
+
|
17
|
+
if ENV.fetch("DEBUG", false)
|
18
|
+
require "amazing_print"
|
19
|
+
require "debug"
|
20
|
+
end
|
21
|
+
|
22
|
+
class HTMLPipeline
|
23
|
+
# HTML processing filters and utilities. This module includes a small
|
24
|
+
# framework for defining DOM based content filters and applying them to user
|
25
|
+
# provided content.
|
26
|
+
#
|
27
|
+
# See HTMLPipeline::Filter for information on building filters.
|
28
|
+
#
|
29
|
+
# Construct a Pipeline for running multiple HTML filters. A pipeline is created once
|
30
|
+
# with one to many filters, and it then can be `call`ed many times over the course
|
31
|
+
# of its lifetime with input.
|
32
|
+
#
|
33
|
+
# filters - Array of Filter objects. Each must respond to call(doc,
|
34
|
+
# context). Filters are performed in the order provided.
|
35
|
+
# default_context - The default context hash. Values specified here will be merged
|
36
|
+
# into values from the each individual pipeline run. Can NOT be
|
37
|
+
# nil. Default: empty Hash.
|
38
|
+
# result_class - The default Class of the result object for individual
|
39
|
+
# calls. Default: Hash. Protip: Pass in a Struct to get
|
40
|
+
# some semblance of type safety.
|
41
|
+
class MissingDependencyError < RuntimeError; end
|
42
|
+
class InvalidFilterError < ArgumentError; end
|
43
|
+
|
44
|
+
class << self
|
45
|
+
def optional_dependency(name, requirer)
|
46
|
+
require name
|
47
|
+
rescue LoadError # rubocop:disable Lint/SuppressedException:
|
48
|
+
end
|
49
|
+
|
50
|
+
def require_dependency(name, requirer)
|
51
|
+
require name
|
52
|
+
rescue LoadError => e
|
53
|
+
raise MissingDependencyError,
|
54
|
+
"Missing dependency '#{name}' for #{requirer}. See README.md for details.\n#{e.class.name}: #{e}"
|
55
|
+
end
|
56
|
+
|
57
|
+
def require_dependencies(names, requirer)
|
58
|
+
dependency_list = names.dup
|
59
|
+
loaded = false
|
60
|
+
|
61
|
+
while !loaded && names.length > 1
|
62
|
+
name = names.shift
|
63
|
+
|
64
|
+
begin
|
65
|
+
require_dependency(name, requirer)
|
66
|
+
loaded = true # we got a dependency
|
67
|
+
define_dependency_loaded_method(name, true)
|
68
|
+
# try the next dependency
|
69
|
+
rescue MissingDependencyError
|
70
|
+
define_dependency_loaded_method(name, false)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
return if loaded
|
75
|
+
|
76
|
+
begin
|
77
|
+
name = names.shift
|
78
|
+
require name
|
79
|
+
define_dependency_loaded_method(name, true)
|
80
|
+
rescue LoadError => e
|
81
|
+
raise MissingDependencyError,
|
82
|
+
"Missing all dependencies '#{dependency_list.join(", ")}' for #{requirer}. See README.md for details.\n#{e.class.name}: #{e}"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def define_dependency_loaded_method(name, value)
|
87
|
+
self.class.define_method(:"#{name}_loaded?", -> { value })
|
88
|
+
end
|
89
|
+
end
|
90
|
+
# Public: Returns an Array of Filter objects for this Pipeline.
|
91
|
+
attr_reader :text_filters, :node_filters
|
92
|
+
|
93
|
+
# Public: A hash representing the sanitization configuration settings
|
94
|
+
attr_reader :sanitization_config
|
95
|
+
|
96
|
+
# Public: Instrumentation service for the pipeline.
|
97
|
+
# Set an ActiveSupport::Notifications compatible object to enable.
|
98
|
+
attr_accessor :instrumentation_service
|
99
|
+
|
100
|
+
# Public: String name for this Pipeline. Defaults to Class name.
|
101
|
+
attr_writer :instrumentation_name
|
102
|
+
|
103
|
+
def instrumentation_name
|
104
|
+
return @instrumentation_name if defined?(@instrumentation_name)
|
105
|
+
|
106
|
+
@instrumentation_name = self.class.name
|
107
|
+
end
|
108
|
+
|
109
|
+
class << self
|
110
|
+
# Public: Default instrumentation service for new pipeline objects.
|
111
|
+
attr_accessor :default_instrumentation_service
|
112
|
+
end
|
113
|
+
|
114
|
+
def initialize(text_filters: [], convert_filter: nil, sanitization_config: SanitizationFilter::DEFAULT_CONFIG, node_filters: [], default_context: {}, result_class: Hash)
|
115
|
+
raise ArgumentError, "default_context cannot be nil" if default_context.nil?
|
116
|
+
|
117
|
+
@text_filters = text_filters.flatten.freeze || []
|
118
|
+
validate_filters(@text_filters, HTMLPipeline::TextFilter)
|
119
|
+
|
120
|
+
@node_filters = node_filters.flatten.freeze || []
|
121
|
+
validate_filters(@node_filters, HTMLPipeline::NodeFilter)
|
122
|
+
|
123
|
+
@convert_filter = convert_filter
|
124
|
+
|
125
|
+
if @convert_filter.nil? && (!@text_filters.empty? && !@node_filters.empty?)
|
126
|
+
raise InvalidFilterError, "Must provide `convert_filter` if `text_filters` and `node_filters` are also provided"
|
127
|
+
elsif !@convert_filter.nil?
|
128
|
+
validate_filter(@convert_filter, HTMLPipeline::ConvertFilter)
|
129
|
+
end
|
130
|
+
|
131
|
+
@sanitization_config = sanitization_config.nil? ? nil : Selma::Sanitizer.new(sanitization_config)
|
132
|
+
|
133
|
+
@default_context = default_context.freeze
|
134
|
+
@instrumentation_service = self.class.default_instrumentation_service
|
135
|
+
end
|
136
|
+
|
137
|
+
# Apply all filters in the pipeline to the given HTML.
|
138
|
+
#
|
139
|
+
# html - A UTF-8 String comprised of HTML.
|
140
|
+
# context - The context hash passed to each filter. See the Filter docs
|
141
|
+
# for more info on possible values. This object MUST NOT be modified
|
142
|
+
# in place by filters. Use the Result for passing state back.
|
143
|
+
# result - The result Hash passed to each filter for modification. This
|
144
|
+
# is where Filters store extracted information from the content.
|
145
|
+
#
|
146
|
+
# Returns the result Hash after being filtered by this Pipeline. Contains an
|
147
|
+
# :output key with the String HTML markup based on the
|
148
|
+
# output of the last filter in the pipeline.
|
149
|
+
def call(text, context: {}, result: {})
|
150
|
+
context = @default_context.merge(context)
|
151
|
+
context = context.freeze
|
152
|
+
result ||= {}
|
153
|
+
|
154
|
+
if @text_filters.any?
|
155
|
+
payload = default_payload({
|
156
|
+
text_filters: @text_filters.map(&:name),
|
157
|
+
context: context,
|
158
|
+
result: result,
|
159
|
+
})
|
160
|
+
instrument("call_text_filters.html_pipeline", payload) do
|
161
|
+
result[:output] =
|
162
|
+
@text_filters.inject(text) do |doc, filter|
|
163
|
+
perform_filter(filter, doc, context: context, result: result)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
text = result[:output] || text
|
169
|
+
|
170
|
+
html = if @convert_filter.nil?
|
171
|
+
text
|
172
|
+
else
|
173
|
+
instrument("call_convert_filter.html_pipeline", payload) do
|
174
|
+
html = @convert_filter.call(text)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
unless @node_filters.empty?
|
179
|
+
instrument("call_node_filters.html_pipeline", payload) do
|
180
|
+
result[:output] = Selma::Rewriter.new(sanitizer: @sanitization_config, handlers: @node_filters).rewrite(html)
|
181
|
+
html = result[:output]
|
182
|
+
payload = default_payload({
|
183
|
+
node_filters: @node_filters.map { |f| f.class.name },
|
184
|
+
context: context,
|
185
|
+
result: result,
|
186
|
+
})
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
instrument("html_pipeline.sanitization", payload) do
|
191
|
+
result[:output] = Selma::Rewriter.new(sanitizer: @sanitization_config, handlers: @node_filters).rewrite(html)
|
192
|
+
end
|
193
|
+
|
194
|
+
result = result.merge(@node_filters.collect(&:result).reduce({}, :merge))
|
195
|
+
@node_filters.each(&:reset!)
|
196
|
+
|
197
|
+
result
|
198
|
+
end
|
199
|
+
|
200
|
+
# Internal: Applies a specific filter to the supplied doc.
|
201
|
+
#
|
202
|
+
# The filter is instrumented.
|
203
|
+
#
|
204
|
+
# Returns the result of the filter.
|
205
|
+
def perform_filter(filter, doc, context: {}, result: {})
|
206
|
+
payload = default_payload({
|
207
|
+
filter: filter.name,
|
208
|
+
context: context,
|
209
|
+
result: result,
|
210
|
+
})
|
211
|
+
|
212
|
+
instrument("call_filter.html_pipeline", payload) do
|
213
|
+
filter.call(doc, context: context, result: result)
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
# Like call but guarantee the value returned is a string of HTML markup.
|
218
|
+
def to_html(input, context: {}, result: {})
|
219
|
+
result = call(input, context: context, result: result)
|
220
|
+
output = result[:output]
|
221
|
+
if output.respond_to?(:to_html)
|
222
|
+
output.to_html
|
223
|
+
else
|
224
|
+
output.to_s
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
# Public: setup instrumentation for this pipeline.
|
229
|
+
#
|
230
|
+
# Returns nothing.
|
231
|
+
def setup_instrumentation(name, service: nil)
|
232
|
+
self.instrumentation_name = name
|
233
|
+
self.instrumentation_service =
|
234
|
+
service || self.class.default_instrumentation_service
|
235
|
+
end
|
236
|
+
|
237
|
+
# Internal: if the `instrumentation_service` object is set, instruments the
|
238
|
+
# block, otherwise the block is ran without instrumentation.
|
239
|
+
#
|
240
|
+
# Returns the result of the provided block.
|
241
|
+
def instrument(event, payload = {}, &block)
|
242
|
+
payload ||= default_payload
|
243
|
+
return yield(payload) unless instrumentation_service
|
244
|
+
|
245
|
+
instrumentation_service.instrument(event, payload, &block)
|
246
|
+
end
|
247
|
+
|
248
|
+
# Internal: Default payload for instrumentation.
|
249
|
+
#
|
250
|
+
# Accepts a Hash of additional payload data to be merged.
|
251
|
+
#
|
252
|
+
# Returns a Hash.
|
253
|
+
def default_payload(payload = {})
|
254
|
+
{ pipeline: instrumentation_name }.merge(payload)
|
255
|
+
end
|
256
|
+
|
257
|
+
private def validate_filter(filter, klass)
|
258
|
+
unless correctly_ancestored?(filter, klass)
|
259
|
+
raise InvalidFilterError, "Filter must inherit from `#{klass}`; #{filter} does not"
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
private def validate_filters(filters, klass)
|
264
|
+
return if filters.nil? || filters.empty?
|
265
|
+
|
266
|
+
invalid_filters = filters.reject { |f| correctly_ancestored?(f, klass) }
|
267
|
+
|
268
|
+
unless invalid_filters.empty?
|
269
|
+
verb = invalid_filters.count == 1 ? "does" : "do"
|
270
|
+
raise InvalidFilterError, "All filters must inherit from `#{klass}`; #{invalid_filters.join(", ")} #{verb} not"
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
private def correctly_ancestored?(filter, klass)
|
275
|
+
if filter.respond_to?(:ancestors)
|
276
|
+
filter.ancestors.include?(klass)
|
277
|
+
else
|
278
|
+
filter.class.ancestors.include?(klass)
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|
metadata
CHANGED
@@ -1,114 +1,118 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: html-pipeline
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
- Ryan Tomayko
|
8
|
-
- Jerry Cheung
|
9
7
|
- Garen J. Torikian
|
10
|
-
autorequire:
|
8
|
+
autorequire:
|
11
9
|
bindir: bin
|
12
10
|
cert_chain: []
|
13
|
-
date:
|
11
|
+
date: 2024-01-08 00:00:00.000000000 Z
|
14
12
|
dependencies:
|
15
13
|
- !ruby/object:Gem::Dependency
|
16
|
-
name:
|
14
|
+
name: selma
|
17
15
|
requirement: !ruby/object:Gem::Requirement
|
18
16
|
requirements:
|
19
|
-
- - "
|
17
|
+
- - "~>"
|
20
18
|
- !ruby/object:Gem::Version
|
21
|
-
version: '
|
19
|
+
version: '0.1'
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
23
|
requirements:
|
26
|
-
- - "
|
24
|
+
- - "~>"
|
27
25
|
- !ruby/object:Gem::Version
|
28
|
-
version: '
|
26
|
+
version: '0.1'
|
27
|
+
force_ruby_platform: false
|
29
28
|
- !ruby/object:Gem::Dependency
|
30
|
-
name:
|
29
|
+
name: zeitwerk
|
31
30
|
requirement: !ruby/object:Gem::Requirement
|
32
31
|
requirements:
|
33
|
-
- - "
|
32
|
+
- - "~>"
|
34
33
|
- !ruby/object:Gem::Version
|
35
|
-
version: '
|
34
|
+
version: '2.5'
|
36
35
|
type: :runtime
|
37
36
|
prerelease: false
|
38
37
|
version_requirements: !ruby/object:Gem::Requirement
|
39
38
|
requirements:
|
40
|
-
- - "
|
39
|
+
- - "~>"
|
41
40
|
- !ruby/object:Gem::Version
|
42
|
-
version: '
|
43
|
-
|
41
|
+
version: '2.5'
|
42
|
+
force_ruby_platform: false
|
43
|
+
description: HTML processing filters and utilities
|
44
44
|
email:
|
45
|
-
- ryan@github.com
|
46
|
-
- jerry@github.com
|
47
45
|
- gjtorikian@gmail.com
|
48
46
|
executables: []
|
49
47
|
extensions: []
|
50
48
|
extra_rdoc_files: []
|
51
49
|
files:
|
52
50
|
- ".github/FUNDING.yml"
|
51
|
+
- ".github/dependabot.yml"
|
52
|
+
- ".github/workflows/automerge.yml"
|
53
|
+
- ".github/workflows/ci.yml"
|
54
|
+
- ".github/workflows/lint.yml"
|
55
|
+
- ".github/workflows/publish.yml"
|
53
56
|
- ".gitignore"
|
54
|
-
- ".
|
55
|
-
-
|
57
|
+
- ".rubocop.yml"
|
58
|
+
- ".ruby-version"
|
59
|
+
- ".vscode/settings.json"
|
56
60
|
- CHANGELOG.md
|
57
|
-
- CONTRIBUTING.md
|
58
61
|
- Gemfile
|
59
|
-
- LICENSE
|
62
|
+
- LICENSE.txt
|
60
63
|
- README.md
|
61
64
|
- Rakefile
|
62
|
-
-
|
65
|
+
- UPGRADING.md
|
63
66
|
- html-pipeline.gemspec
|
64
|
-
- lib/html
|
65
|
-
- lib/
|
66
|
-
- lib/
|
67
|
-
- lib/
|
68
|
-
- lib/
|
69
|
-
- lib/
|
70
|
-
- lib/
|
71
|
-
- lib/
|
72
|
-
- lib/
|
73
|
-
- lib/
|
74
|
-
- lib/
|
75
|
-
- lib/
|
76
|
-
- lib/
|
77
|
-
- lib/
|
78
|
-
- lib/
|
79
|
-
- lib/
|
80
|
-
- lib/
|
81
|
-
- lib/
|
82
|
-
- lib/
|
83
|
-
- lib/
|
84
|
-
|
85
|
-
homepage: https://github.com/jch/html-pipeline
|
67
|
+
- lib/html-pipeline.rb
|
68
|
+
- lib/html_pipeline.rb
|
69
|
+
- lib/html_pipeline/convert_filter.rb
|
70
|
+
- lib/html_pipeline/convert_filter/markdown_filter.rb
|
71
|
+
- lib/html_pipeline/filter.rb
|
72
|
+
- lib/html_pipeline/node_filter.rb
|
73
|
+
- lib/html_pipeline/node_filter/absolute_source_filter.rb
|
74
|
+
- lib/html_pipeline/node_filter/asset_proxy_filter.rb
|
75
|
+
- lib/html_pipeline/node_filter/emoji_filter.rb
|
76
|
+
- lib/html_pipeline/node_filter/https_filter.rb
|
77
|
+
- lib/html_pipeline/node_filter/image_max_width_filter.rb
|
78
|
+
- lib/html_pipeline/node_filter/mention_filter.rb
|
79
|
+
- lib/html_pipeline/node_filter/syntax_highlight_filter.rb
|
80
|
+
- lib/html_pipeline/node_filter/table_of_contents_filter.rb
|
81
|
+
- lib/html_pipeline/node_filter/team_mention_filter.rb
|
82
|
+
- lib/html_pipeline/sanitization_filter.rb
|
83
|
+
- lib/html_pipeline/text_filter.rb
|
84
|
+
- lib/html_pipeline/text_filter/image_filter.rb
|
85
|
+
- lib/html_pipeline/text_filter/plain_text_input_filter.rb
|
86
|
+
- lib/html_pipeline/version.rb
|
87
|
+
homepage: https://github.com/gjtorikian/html-pipeline
|
86
88
|
licenses:
|
87
89
|
- MIT
|
88
|
-
metadata:
|
90
|
+
metadata:
|
91
|
+
funding_uri: https://github.com/sponsors/gjtorikian/
|
92
|
+
rubygems_mfa_required: 'true'
|
89
93
|
post_install_message: |
|
90
94
|
-------------------------------------------------
|
91
95
|
Thank you for installing html-pipeline!
|
92
|
-
You must bundle
|
93
|
-
See html-pipeline README.md for more details
|
94
|
-
https://github.com/
|
96
|
+
You must bundle filter gem dependencies.
|
97
|
+
See the html-pipeline README.md for more details:
|
98
|
+
https://github.com/gjtorikian/html-pipeline#dependencies
|
95
99
|
-------------------------------------------------
|
96
100
|
rdoc_options: []
|
97
101
|
require_paths:
|
98
102
|
- lib
|
99
103
|
required_ruby_version: !ruby/object:Gem::Requirement
|
100
104
|
requirements:
|
101
|
-
- - "
|
105
|
+
- - "~>"
|
102
106
|
- !ruby/object:Gem::Version
|
103
|
-
version: '
|
107
|
+
version: '3.1'
|
104
108
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
105
109
|
requirements:
|
106
110
|
- - ">="
|
107
111
|
- !ruby/object:Gem::Version
|
108
|
-
version:
|
112
|
+
version: 3.3.22
|
109
113
|
requirements: []
|
110
|
-
rubygems_version: 3.
|
111
|
-
signing_key:
|
114
|
+
rubygems_version: 3.5.4
|
115
|
+
signing_key:
|
112
116
|
specification_version: 4
|
113
117
|
summary: Helpers for processing content through a chain of filters
|
114
118
|
test_files: []
|
data/.travis.yml
DELETED
@@ -1,43 +0,0 @@
|
|
1
|
-
language: ruby
|
2
|
-
cache: bundler
|
3
|
-
bundler_args: --path ../../vendor/bundle
|
4
|
-
|
5
|
-
addons:
|
6
|
-
apt:
|
7
|
-
sources:
|
8
|
-
- libicu-dev
|
9
|
-
- kalakris-cmake
|
10
|
-
packages:
|
11
|
-
- cmake
|
12
|
-
|
13
|
-
script: bundle exec rake
|
14
|
-
|
15
|
-
gemfile:
|
16
|
-
- gemfiles/rails_6.gemfile
|
17
|
-
- gemfiles/rails_5.gemfile
|
18
|
-
- gemfiles/rails_4.gemfile
|
19
|
-
- gemfiles/rails_3.gemfile
|
20
|
-
|
21
|
-
rvm:
|
22
|
-
- 2.4.6
|
23
|
-
- 2.3.8
|
24
|
-
- 2.5.7
|
25
|
-
- ruby-head
|
26
|
-
|
27
|
-
matrix:
|
28
|
-
fast_finish: true
|
29
|
-
allow_failures:
|
30
|
-
- rvm: ruby-head
|
31
|
-
exclude:
|
32
|
-
- gemfile: gemfiles/rails_6.gemfile
|
33
|
-
rvm: 2.4.6
|
34
|
-
- gemfile: gemfiles/rails_6.gemfile
|
35
|
-
rvm: 2.3.8
|
36
|
-
- gemfile: gemfiles/rails_4.gemfile
|
37
|
-
rvm: 2.5.7
|
38
|
-
- gemfile: gemfiles/rails_4.gemfile
|
39
|
-
rvm: 2.4.6
|
40
|
-
- gemfile: gemfiles/rails_3.gemfile
|
41
|
-
rvm: 2.5.7
|
42
|
-
- gemfile: gemfiles/rails_3.gemfile
|
43
|
-
rvm: 2.4.6
|
data/Appraisals
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
appraise 'rails-3' do
|
4
|
-
gem 'rack', '< 2'
|
5
|
-
gem 'rails', '3.2.22.2'
|
6
|
-
end
|
7
|
-
|
8
|
-
appraise 'rails-4' do
|
9
|
-
gem 'rack', '< 2'
|
10
|
-
gem 'rails', '~> 4.2.6'
|
11
|
-
end
|
12
|
-
|
13
|
-
appraise 'rails-5' do
|
14
|
-
gem 'rails', '~> 5.0.0'
|
15
|
-
end
|
16
|
-
|
17
|
-
appraise 'rails-6' do
|
18
|
-
gem 'rails', '~> 6.0.0'
|
19
|
-
end
|
data/CONTRIBUTING.md
DELETED
@@ -1,60 +0,0 @@
|
|
1
|
-
# Contributing
|
2
|
-
|
3
|
-
Thanks for using and improving `HTML::Pipeline`!
|
4
|
-
|
5
|
-
- [Submitting a New Issue](#submitting-a-new-issue)
|
6
|
-
- [Sending a Pull Request](#sending-a-pull-request)
|
7
|
-
|
8
|
-
## Submitting a New Issue
|
9
|
-
|
10
|
-
If there's an idea you'd like to propose, or a design change, feel free to file a new issue.
|
11
|
-
|
12
|
-
If you have an implementation question or believe you've found a bug, please provide as many details as possible:
|
13
|
-
|
14
|
-
- Input document
|
15
|
-
- Output HTML document
|
16
|
-
- the exact `HTML::Pipeline` code you are using
|
17
|
-
- output of the following from your project
|
18
|
-
|
19
|
-
```
|
20
|
-
ruby -v
|
21
|
-
bundle exec nokogiri -v
|
22
|
-
```
|
23
|
-
|
24
|
-
## Sending a Pull Request
|
25
|
-
|
26
|
-
[Pull requests][pr] are always welcome!
|
27
|
-
|
28
|
-
Check out [the project's issues list][issues] for ideas on what could be improved.
|
29
|
-
|
30
|
-
Before sending, please add tests and ensure the test suite passes.
|
31
|
-
|
32
|
-
### Running the Tests
|
33
|
-
|
34
|
-
To run the full suite:
|
35
|
-
|
36
|
-
`bundle exec rake`
|
37
|
-
|
38
|
-
To run a specific test file:
|
39
|
-
|
40
|
-
`bundle exec ruby -Itest test/html/pipeline_test.rb`
|
41
|
-
|
42
|
-
To run a specific test:
|
43
|
-
|
44
|
-
`bundle exec ruby -Itest test/html/pipeline/markdown_filter_test.rb -n test_disabling_gfm`
|
45
|
-
|
46
|
-
To run the full suite with all [supported rubies][travisyaml] in bash:
|
47
|
-
|
48
|
-
```bash
|
49
|
-
rubies=(ree-1.8.7-2011.03 1.9.2-p290 1.9.3-p429 2.0.0-p247)
|
50
|
-
for r in ${rubies[*]}
|
51
|
-
do
|
52
|
-
rbenv local $r # switch to your version manager of choice
|
53
|
-
bundle install
|
54
|
-
bundle exec rake
|
55
|
-
done
|
56
|
-
```
|
57
|
-
|
58
|
-
[issues]: https://github.com/jch/html-pipeline/issues
|
59
|
-
[pr]: https://help.github.com/articles/using-pull-requests
|
60
|
-
[travisyaml]: https://github.com/jch/html-pipeline/blob/master/.travis.yml
|
data/bin/html-pipeline
DELETED
@@ -1,78 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
require 'html/pipeline'
|
3
|
-
|
4
|
-
require 'optparse'
|
5
|
-
|
6
|
-
# Accept "help", too
|
7
|
-
.map! { |a| a == 'help' ? '--help' : a }
|
8
|
-
|
9
|
-
onParser.new do |opts|
|
10
|
-
opts.banner = <<-HELP.gsub(/^ /, '')
|
11
|
-
Usage: html-pipeline [-h] [-f]
|
12
|
-
html-pipeline [FILTER [FILTER [...]]] < file.md
|
13
|
-
cat file.md | html-pipeline [FILTER [FILTER [...]]]
|
14
|
-
HELP
|
15
|
-
|
16
|
-
opts.separator 'Options:'
|
17
|
-
|
18
|
-
opts.on('-f', '--filters', 'List the available filters') do
|
19
|
-
filters = HTML::Pipeline.constants.grep(/\w+Filter$/)
|
20
|
-
.map { |f| f.to_s.gsub(/Filter$/, '') }
|
21
|
-
|
22
|
-
# Text filter doesn't work, no call method
|
23
|
-
filters -= ['Text']
|
24
|
-
|
25
|
-
abort <<-HELP.gsub(/^ /, '')
|
26
|
-
Available filters:
|
27
|
-
#{filters.join("\n ")}
|
28
|
-
HELP
|
29
|
-
end
|
30
|
-
end.parse!
|
31
|
-
|
32
|
-
# Default to a GitHub-ish pipeline
|
33
|
-
if ARGV.empty?
|
34
|
-
|
35
|
-
filters = [
|
36
|
-
HTML::Pipeline::MarkdownFilter,
|
37
|
-
HTML::Pipeline::SanitizationFilter,
|
38
|
-
HTML::Pipeline::ImageMaxWidthFilter,
|
39
|
-
HTML::Pipeline::EmojiFilter,
|
40
|
-
HTML::Pipeline::AutolinkFilter,
|
41
|
-
HTML::Pipeline::TableOfContentsFilter
|
42
|
-
]
|
43
|
-
|
44
|
-
# Add syntax highlighting if rouge is present
|
45
|
-
begin
|
46
|
-
require 'rouge'
|
47
|
-
filters << HTML::Pipeline::SyntaxHighlightFilter
|
48
|
-
rescue LoadError
|
49
|
-
end
|
50
|
-
|
51
|
-
else
|
52
|
-
|
53
|
-
def filter_named(name)
|
54
|
-
case name
|
55
|
-
when 'Text'
|
56
|
-
raise NameError # Text filter doesn't work, no call method
|
57
|
-
end
|
58
|
-
|
59
|
-
HTML::Pipeline.const_get("#{name}Filter")
|
60
|
-
rescue NameError => e
|
61
|
-
abort "Unknown filter '#{name}'. List filters with the -f option."
|
62
|
-
end
|
63
|
-
|
64
|
-
filters = []
|
65
|
-
until ARGV.empty?
|
66
|
-
name = ARGV.shift
|
67
|
-
filters << filter_named(name)
|
68
|
-
end
|
69
|
-
|
70
|
-
end
|
71
|
-
|
72
|
-
context = {
|
73
|
-
asset_root: '/assets',
|
74
|
-
base_url: '/',
|
75
|
-
gfm: true
|
76
|
-
}
|
77
|
-
|
78
|
-
puts HTML::Pipeline.new(filters, context).call(ARGF.read)[:output]
|