html-pipeline 2.14.3 → 3.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/.github/FUNDING.yml +11 -3
  3. data/.github/dependabot.yml +27 -0
  4. data/.github/workflows/automerge.yml +13 -0
  5. data/.github/workflows/ci.yml +22 -0
  6. data/.github/workflows/lint.yml +23 -0
  7. data/.github/workflows/publish.yml +19 -0
  8. data/.rubocop.yml +17 -0
  9. data/.ruby-version +1 -0
  10. data/.vscode/settings.json +8 -0
  11. data/CHANGELOG.md +111 -2
  12. data/Gemfile +31 -15
  13. data/{LICENSE → LICENSE.txt} +2 -2
  14. data/README.md +240 -223
  15. data/Rakefile +14 -7
  16. data/UPGRADING.md +34 -0
  17. data/html-pipeline.gemspec +31 -21
  18. data/lib/html-pipeline.rb +3 -0
  19. data/lib/html_pipeline/convert_filter/markdown_filter.rb +26 -0
  20. data/lib/html_pipeline/convert_filter.rb +17 -0
  21. data/lib/html_pipeline/filter.rb +89 -0
  22. data/lib/html_pipeline/node_filter/absolute_source_filter.rb +54 -0
  23. data/lib/html_pipeline/node_filter/asset_proxy_filter.rb +86 -0
  24. data/lib/{html/pipeline → html_pipeline/node_filter}/emoji_filter.rb +58 -54
  25. data/lib/html_pipeline/node_filter/https_filter.rb +22 -0
  26. data/lib/html_pipeline/node_filter/image_max_width_filter.rb +40 -0
  27. data/lib/{html/pipeline/@mention_filter.rb → html_pipeline/node_filter/mention_filter.rb} +54 -68
  28. data/lib/html_pipeline/node_filter/syntax_highlight_filter.rb +62 -0
  29. data/lib/html_pipeline/node_filter/table_of_contents_filter.rb +70 -0
  30. data/lib/html_pipeline/node_filter/team_mention_filter.rb +105 -0
  31. data/lib/html_pipeline/node_filter.rb +31 -0
  32. data/lib/html_pipeline/sanitization_filter.rb +188 -0
  33. data/lib/{html/pipeline → html_pipeline/text_filter}/image_filter.rb +3 -3
  34. data/lib/{html/pipeline → html_pipeline/text_filter}/plain_text_input_filter.rb +3 -5
  35. data/lib/html_pipeline/text_filter.rb +21 -0
  36. data/lib/html_pipeline/version.rb +5 -0
  37. data/lib/html_pipeline.rb +267 -0
  38. metadata +58 -54
  39. data/.travis.yml +0 -43
  40. data/Appraisals +0 -19
  41. data/CONTRIBUTING.md +0 -60
  42. data/bin/html-pipeline +0 -78
  43. data/lib/html/pipeline/@team_mention_filter.rb +0 -99
  44. data/lib/html/pipeline/absolute_source_filter.rb +0 -52
  45. data/lib/html/pipeline/autolink_filter.rb +0 -34
  46. data/lib/html/pipeline/body_content.rb +0 -44
  47. data/lib/html/pipeline/camo_filter.rb +0 -105
  48. data/lib/html/pipeline/email_reply_filter.rb +0 -69
  49. data/lib/html/pipeline/filter.rb +0 -165
  50. data/lib/html/pipeline/https_filter.rb +0 -29
  51. data/lib/html/pipeline/image_max_width_filter.rb +0 -37
  52. data/lib/html/pipeline/markdown_filter.rb +0 -56
  53. data/lib/html/pipeline/sanitization_filter.rb +0 -144
  54. data/lib/html/pipeline/syntax_highlight_filter.rb +0 -50
  55. data/lib/html/pipeline/text_filter.rb +0 -16
  56. data/lib/html/pipeline/textile_filter.rb +0 -25
  57. data/lib/html/pipeline/toc_filter.rb +0 -69
  58. data/lib/html/pipeline/version.rb +0 -7
  59. 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,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class HTMLPipeline
4
+ VERSION = "3.0.1"
5
+ end
@@ -0,0 +1,267 @@
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
+ payload = default_payload({
155
+ text_filters: @text_filters.map(&:name),
156
+ context: context,
157
+ result: result,
158
+ })
159
+ instrument("call_text_filters.html_pipeline", payload) do
160
+ result[:output] =
161
+ @text_filters.inject(text) do |doc, filter|
162
+ perform_filter(filter, doc, context: context, result: result)
163
+ end
164
+ end
165
+
166
+ text = result[:output]
167
+
168
+ html = @convert_filter.call(text) unless @convert_filter.nil?
169
+
170
+ unless @node_filters.empty?
171
+ payload = default_payload({
172
+ node_filters: @node_filters.map { |f| f.class.name },
173
+ context: context,
174
+ result: result,
175
+ })
176
+ instrument("call_node_filters.html_pipeline", payload) do
177
+ result[:output] = Selma::Rewriter.new(sanitizer: @sanitization_config, handlers: @node_filters).rewrite(html)
178
+ end
179
+ end
180
+
181
+ result = result.merge(@node_filters.collect(&:result).reduce({}, :merge))
182
+ @node_filters.each(&:reset!)
183
+
184
+ result
185
+ end
186
+
187
+ # Internal: Applies a specific filter to the supplied doc.
188
+ #
189
+ # The filter is instrumented.
190
+ #
191
+ # Returns the result of the filter.
192
+ def perform_filter(filter, doc, context: {}, result: {})
193
+ payload = default_payload({
194
+ filter: filter.name,
195
+ context: context,
196
+ result: result,
197
+ })
198
+ instrument("call_filter.html_pipeline", payload) do
199
+ filter.call(doc, context: context, result: result)
200
+ end
201
+ end
202
+
203
+ # Like call but guarantee the value returned is a string of HTML markup.
204
+ def to_html(input, context: {}, result: {})
205
+ result = call(input, context: context, result: result)
206
+ output = result[:output]
207
+ if output.respond_to?(:to_html)
208
+ output.to_html
209
+ else
210
+ output.to_s
211
+ end
212
+ end
213
+
214
+ # Public: setup instrumentation for this pipeline.
215
+ #
216
+ # Returns nothing.
217
+ def setup_instrumentation(name, service: nil)
218
+ self.instrumentation_name = name
219
+ self.instrumentation_service =
220
+ service || self.class.default_instrumentation_service
221
+ end
222
+
223
+ # Internal: if the `instrumentation_service` object is set, instruments the
224
+ # block, otherwise the block is ran without instrumentation.
225
+ #
226
+ # Returns the result of the provided block.
227
+ def instrument(event, payload = {}, &block)
228
+ payload ||= default_payload
229
+ return yield(payload) unless instrumentation_service
230
+
231
+ instrumentation_service.instrument(event, payload, &block)
232
+ end
233
+
234
+ # Internal: Default payload for instrumentation.
235
+ #
236
+ # Accepts a Hash of additional payload data to be merged.
237
+ #
238
+ # Returns a Hash.
239
+ def default_payload(payload = {})
240
+ { pipeline: instrumentation_name }.merge(payload)
241
+ end
242
+
243
+ private def validate_filter(filter, klass)
244
+ unless correctly_ancestored?(filter, klass)
245
+ raise InvalidFilterError, "Filter must inherit from `#{klass}`; #{filter} does not"
246
+ end
247
+ end
248
+
249
+ private def validate_filters(filters, klass)
250
+ return if filters.nil? || filters.empty?
251
+
252
+ invalid_filters = filters.reject { |f| correctly_ancestored?(f, klass) }
253
+
254
+ unless invalid_filters.empty?
255
+ verb = invalid_filters.count == 1 ? "does" : "do"
256
+ raise InvalidFilterError, "All filters must inherit from `#{klass}`; #{invalid_filters.join(", ")} #{verb} not"
257
+ end
258
+ end
259
+
260
+ private def correctly_ancestored?(filter, klass)
261
+ if filter.respond_to?(:ancestors)
262
+ filter.ancestors.include?(klass)
263
+ else
264
+ filter.class.ancestors.include?(klass)
265
+ end
266
+ end
267
+ 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: 2.14.3
4
+ version: 3.0.1
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: 2022-10-14 00:00:00.000000000 Z
11
+ date: 2023-12-28 00:00:00.000000000 Z
14
12
  dependencies:
15
13
  - !ruby/object:Gem::Dependency
16
- name: activesupport
14
+ name: selma
17
15
  requirement: !ruby/object:Gem::Requirement
18
16
  requirements:
19
- - - ">="
17
+ - - "~>"
20
18
  - !ruby/object:Gem::Version
21
- version: '2'
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: '2'
26
+ version: '0.1'
27
+ force_ruby_platform: false
29
28
  - !ruby/object:Gem::Dependency
30
- name: nokogiri
29
+ name: zeitwerk
31
30
  requirement: !ruby/object:Gem::Requirement
32
31
  requirements:
33
- - - ">="
32
+ - - "~>"
34
33
  - !ruby/object:Gem::Version
35
- version: '1.4'
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: '1.4'
43
- description: GitHub HTML processing filters and utilities
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
- - ".travis.yml"
55
- - Appraisals
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
- - bin/html-pipeline
65
+ - UPGRADING.md
63
66
  - html-pipeline.gemspec
64
- - lib/html/pipeline.rb
65
- - lib/html/pipeline/@mention_filter.rb
66
- - lib/html/pipeline/@team_mention_filter.rb
67
- - lib/html/pipeline/absolute_source_filter.rb
68
- - lib/html/pipeline/autolink_filter.rb
69
- - lib/html/pipeline/body_content.rb
70
- - lib/html/pipeline/camo_filter.rb
71
- - lib/html/pipeline/email_reply_filter.rb
72
- - lib/html/pipeline/emoji_filter.rb
73
- - lib/html/pipeline/filter.rb
74
- - lib/html/pipeline/https_filter.rb
75
- - lib/html/pipeline/image_filter.rb
76
- - lib/html/pipeline/image_max_width_filter.rb
77
- - lib/html/pipeline/markdown_filter.rb
78
- - lib/html/pipeline/plain_text_input_filter.rb
79
- - lib/html/pipeline/sanitization_filter.rb
80
- - lib/html/pipeline/syntax_highlight_filter.rb
81
- - lib/html/pipeline/text_filter.rb
82
- - lib/html/pipeline/textile_filter.rb
83
- - lib/html/pipeline/toc_filter.rb
84
- - lib/html/pipeline/version.rb
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 Filter gem dependencies.
93
- See html-pipeline README.md for more details.
94
- https://github.com/jch/html-pipeline#dependencies
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: '0'
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: '0'
112
+ version: 3.3.22
109
113
  requirements: []
110
- rubygems_version: 3.3.7
111
- signing_key:
114
+ rubygems_version: 3.5.3
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]