html-pipeline 2.14.2 → 3.0.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/.github/FUNDING.yml +11 -3
  3. data/.github/dependabot.yml +20 -0
  4. data/.github/workflows/automerge.yml +34 -0
  5. data/.github/workflows/lint.yml +23 -0
  6. data/.github/workflows/tag_and_release.yml +70 -0
  7. data/.github/workflows/test.yml +33 -0
  8. data/.rubocop.yml +17 -0
  9. data/CHANGELOG.md +762 -180
  10. data/Gemfile +29 -15
  11. data/{LICENSE → LICENSE.txt} +2 -2
  12. data/README.md +209 -218
  13. data/Rakefile +14 -7
  14. data/UPGRADING.md +35 -0
  15. data/html-pipeline.gemspec +31 -21
  16. data/lib/html-pipeline.rb +3 -0
  17. data/lib/html_pipeline/convert_filter/markdown_filter.rb +26 -0
  18. data/lib/html_pipeline/convert_filter.rb +17 -0
  19. data/lib/html_pipeline/filter.rb +89 -0
  20. data/lib/{html/pipeline → html_pipeline/node_filter}/absolute_source_filter.rb +23 -21
  21. data/lib/{html/pipeline → html_pipeline/node_filter}/emoji_filter.rb +58 -54
  22. data/lib/html_pipeline/node_filter/https_filter.rb +22 -0
  23. data/lib/html_pipeline/node_filter/image_max_width_filter.rb +40 -0
  24. data/lib/{html/pipeline/@mention_filter.rb → html_pipeline/node_filter/mention_filter.rb} +55 -69
  25. data/lib/html_pipeline/node_filter/table_of_contents_filter.rb +68 -0
  26. data/lib/html_pipeline/node_filter/team_mention_filter.rb +105 -0
  27. data/lib/html_pipeline/node_filter.rb +31 -0
  28. data/lib/html_pipeline/sanitization_filter.rb +65 -0
  29. data/lib/{html/pipeline → html_pipeline/text_filter}/image_filter.rb +3 -3
  30. data/lib/{html/pipeline → html_pipeline/text_filter}/plain_text_input_filter.rb +3 -5
  31. data/lib/html_pipeline/text_filter.rb +21 -0
  32. data/lib/html_pipeline/version.rb +5 -0
  33. data/lib/html_pipeline.rb +252 -0
  34. metadata +52 -54
  35. data/.travis.yml +0 -43
  36. data/Appraisals +0 -19
  37. data/CONTRIBUTING.md +0 -60
  38. data/bin/html-pipeline +0 -78
  39. data/lib/html/pipeline/@team_mention_filter.rb +0 -99
  40. data/lib/html/pipeline/autolink_filter.rb +0 -34
  41. data/lib/html/pipeline/body_content.rb +0 -44
  42. data/lib/html/pipeline/camo_filter.rb +0 -105
  43. data/lib/html/pipeline/email_reply_filter.rb +0 -68
  44. data/lib/html/pipeline/filter.rb +0 -165
  45. data/lib/html/pipeline/https_filter.rb +0 -29
  46. data/lib/html/pipeline/image_max_width_filter.rb +0 -37
  47. data/lib/html/pipeline/markdown_filter.rb +0 -56
  48. data/lib/html/pipeline/sanitization_filter.rb +0 -144
  49. data/lib/html/pipeline/syntax_highlight_filter.rb +0 -50
  50. data/lib/html/pipeline/text_filter.rb +0 -16
  51. data/lib/html/pipeline/textile_filter.rb +0 -25
  52. data/lib/html/pipeline/toc_filter.rb +0 -69
  53. data/lib/html/pipeline/version.rb +0 -7
  54. data/lib/html/pipeline.rb +0 -210
@@ -0,0 +1,252 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "zeitwerk"
4
+ lib_dir = File.join(File.dirname(__dir__), "lib")
5
+ gem_loader = Zeitwerk::Loader.for_gem
6
+ gem_loader.inflector.inflect(
7
+ "html_pipeline" => "HTMLPipeline",
8
+ )
9
+ gem_loader.ignore(File.join(lib_dir, "html-pipeline.rb"))
10
+ gem_loader.setup
11
+
12
+ if ENV.fetch("DEBUG", false)
13
+ require "amazing_print"
14
+ require "debug"
15
+ end
16
+
17
+ class HTMLPipeline
18
+ # HTML processing filters and utilities. This module includes a small
19
+ # framework for defining DOM based content filters and applying them to user
20
+ # provided content.
21
+ #
22
+ # See HTMLPipeline::Filter for information on building filters.
23
+ #
24
+ # Construct a Pipeline for running multiple HTML filters. A pipeline is created once
25
+ # with one to many filters, and it then can be `call`ed many times over the course
26
+ # of its lifetime with input.
27
+ #
28
+ # filters - Array of Filter objects. Each must respond to call(doc,
29
+ # context). Filters are performed in the order provided.
30
+ # default_context - The default context hash. Values specified here will be merged
31
+ # into values from the each individual pipeline run. Can NOT be
32
+ # nil. Default: empty Hash.
33
+ # result_class - The default Class of the result object for individual
34
+ # calls. Default: Hash. Protip: Pass in a Struct to get
35
+ # some semblance of type safety.
36
+ class MissingDependencyError < RuntimeError; end
37
+ class InvalidFilterError < ArgumentError; end
38
+
39
+ class << self
40
+ def optional_dependency(name, requirer)
41
+ require name
42
+ rescue LoadError # rubocop:disable Lint/SuppressedException:
43
+ end
44
+
45
+ def require_dependency(name, requirer)
46
+ require name
47
+ rescue LoadError => e
48
+ raise MissingDependencyError,
49
+ "Missing dependency '#{name}' for #{requirer}. See README.md for details.\n#{e.class.name}: #{e}"
50
+ end
51
+
52
+ def require_dependencies(names, requirer)
53
+ dependency_list = names.dup
54
+ loaded = false
55
+
56
+ while !loaded && names.length > 1
57
+ name = names.shift
58
+
59
+ begin
60
+ require_dependency(name, requirer)
61
+ loaded = true # we got a dependency
62
+ define_dependency_loaded_method(name, true)
63
+ # try the next dependency
64
+ rescue MissingDependencyError
65
+ define_dependency_loaded_method(name, false)
66
+ end
67
+ end
68
+
69
+ return if loaded
70
+
71
+ begin
72
+ name = names.shift
73
+ require name
74
+ define_dependency_loaded_method(name, true)
75
+ rescue LoadError => e
76
+ raise MissingDependencyError,
77
+ "Missing all dependencies '#{dependency_list.join(", ")}' for #{requirer}. See README.md for details.\n#{e.class.name}: #{e}"
78
+ end
79
+ end
80
+
81
+ def define_dependency_loaded_method(name, value)
82
+ self.class.define_method(:"#{name}_loaded?", -> { value })
83
+ end
84
+ end
85
+ # Public: Returns an Array of Filter objects for this Pipeline.
86
+ attr_reader :text_filters, :node_filters
87
+
88
+ # Public: A hash representing the sanitization configuration settings
89
+ attr_reader :sanitization_config
90
+
91
+ # Public: Instrumentation service for the pipeline.
92
+ # Set an ActiveSupport::Notifications compatible object to enable.
93
+ attr_accessor :instrumentation_service
94
+
95
+ # Public: String name for this Pipeline. Defaults to Class name.
96
+ attr_writer :instrumentation_name
97
+
98
+ def instrumentation_name
99
+ return @instrumentation_name if defined?(@instrumentation_name)
100
+
101
+ @instrumentation_name = self.class.name
102
+ end
103
+
104
+ class << self
105
+ # Public: Default instrumentation service for new pipeline objects.
106
+ attr_accessor :default_instrumentation_service
107
+ end
108
+
109
+ def initialize(text_filters: [], convert_filter: nil, sanitization_config: SanitizationFilter::DEFAULT_CONFIG, node_filters: [], default_context: {}, result_class: Hash)
110
+ raise ArgumentError, "default_context cannot be nil" if default_context.nil?
111
+
112
+ @text_filters = text_filters.flatten.freeze
113
+ validate_filters(@text_filters, HTMLPipeline::TextFilter)
114
+
115
+ @node_filters = node_filters.flatten.freeze
116
+ validate_filters(@node_filters, HTMLPipeline::NodeFilter)
117
+
118
+ @convert_filter = convert_filter
119
+ if @convert_filter.nil? && !@node_filters.empty?
120
+ raise InvalidFilterError, "Must provide `convert_filter` if `node_filter`s is also provided"
121
+ elsif !@convert_filter.nil?
122
+ validate_filter(@convert_filter, HTMLPipeline::ConvertFilter)
123
+ end
124
+
125
+ @sanitization_config = sanitization_config.nil? ? nil : Selma::Sanitizer.new(sanitization_config)
126
+
127
+ @default_context = default_context.freeze
128
+ @instrumentation_service = self.class.default_instrumentation_service
129
+ end
130
+
131
+ # Apply all filters in the pipeline to the given HTML.
132
+ #
133
+ # html - A UTF-8 String comprised of HTML.
134
+ # context - The context hash passed to each filter. See the Filter docs
135
+ # for more info on possible values. This object MUST NOT be modified
136
+ # in place by filters. Use the Result for passing state back.
137
+ # result - The result Hash passed to each filter for modification. This
138
+ # is where Filters store extracted information from the content.
139
+ #
140
+ # Returns the result Hash after being filtered by this Pipeline. Contains an
141
+ # :output key with the String HTML markup based on the
142
+ # output of the last filter in the pipeline.
143
+ def call(text, context: {}, result: {})
144
+ context = @default_context.merge(context)
145
+ context = context.freeze
146
+ result ||= {}
147
+
148
+ payload = default_payload({ text_filters: @text_filters.map(&:name),
149
+ context: context, result: result, })
150
+ instrument("call_text_filters.html_pipeline", payload) do
151
+ result[:output] =
152
+ @text_filters.inject(text) do |doc, filter|
153
+ perform_filter(filter, doc, context: context, result: result)
154
+ end
155
+ end
156
+
157
+ text = result[:output]
158
+
159
+ html = @convert_filter.call(text) unless @convert_filter.nil?
160
+
161
+ unless @node_filters.empty?
162
+ payload = default_payload({ node_filters: @node_filters.map { |f| f.class.name },
163
+ context: context, result: result, })
164
+ instrument("call_node_filters.html_pipeline", payload) do
165
+ result[:output] = Selma::Rewriter.new(sanitizer: @sanitization_config, handlers: @node_filters).rewrite(html)
166
+ end
167
+ end
168
+
169
+ result = result.merge(Hash[*@node_filters.collect(&:result).flatten])
170
+ @node_filters.each(&:reset!)
171
+
172
+ result
173
+ end
174
+
175
+ # Internal: Applies a specific filter to the supplied doc.
176
+ #
177
+ # The filter is instrumented.
178
+ #
179
+ # Returns the result of the filter.
180
+ def perform_filter(filter, doc, context: {}, result: {})
181
+ payload = default_payload({ filter: filter.name,
182
+ context: context, result: result, })
183
+ instrument("call_filter.html_pipeline", payload) do
184
+ filter.call(doc, context: context, result: result)
185
+ end
186
+ end
187
+
188
+ # Like call but guarantee the value returned is a string of HTML markup.
189
+ def to_html(input, context: {}, result: {})
190
+ result = call(input, context: context, result: result)
191
+ output = result[:output]
192
+ if output.respond_to?(:to_html)
193
+ output.to_html
194
+ else
195
+ output.to_s
196
+ end
197
+ end
198
+
199
+ # Public: setup instrumentation for this pipeline.
200
+ #
201
+ # Returns nothing.
202
+ def setup_instrumentation(name, service: nil)
203
+ self.instrumentation_name = name
204
+ self.instrumentation_service =
205
+ service || self.class.default_instrumentation_service
206
+ end
207
+
208
+ # Internal: if the `instrumentation_service` object is set, instruments the
209
+ # block, otherwise the block is ran without instrumentation.
210
+ #
211
+ # Returns the result of the provided block.
212
+ def instrument(event, payload = {}, &block)
213
+ payload ||= default_payload
214
+ return yield(payload) unless instrumentation_service
215
+
216
+ instrumentation_service.instrument(event, payload, &block)
217
+ end
218
+
219
+ # Internal: Default payload for instrumentation.
220
+ #
221
+ # Accepts a Hash of additional payload data to be merged.
222
+ #
223
+ # Returns a Hash.
224
+ def default_payload(payload = {})
225
+ { pipeline: instrumentation_name }.merge(payload)
226
+ end
227
+
228
+ private def validate_filter(filter, klass)
229
+ unless correctly_ancestored?(filter, klass)
230
+ raise InvalidFilterError, "Filter must inherit from `#{klass}`; #{filter} does not"
231
+ end
232
+ end
233
+
234
+ private def validate_filters(filters, klass)
235
+ return if filters.nil? || filters.empty?
236
+
237
+ invalid_filters = filters.reject { |f| correctly_ancestored?(f, klass) }
238
+
239
+ unless invalid_filters.empty?
240
+ verb = invalid_filters.count == 1 ? "does" : "do"
241
+ raise InvalidFilterError, "All filters must inherit from `#{klass}`; #{invalid_filters.join(", ")} #{verb} not"
242
+ end
243
+ end
244
+
245
+ private def correctly_ancestored?(filter, klass)
246
+ if filter.respond_to?(:ancestors)
247
+ filter.ancestors.include?(klass)
248
+ else
249
+ filter.class.ancestors.include?(klass)
250
+ end
251
+ end
252
+ end
metadata CHANGED
@@ -1,114 +1,112 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: html-pipeline
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.14.2
4
+ version: 3.0.0.pre1
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-06-12 00:00:00.000000000 Z
11
+ date: 2022-12-30 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.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.0.1
29
27
  - !ruby/object:Gem::Dependency
30
- name: nokogiri
28
+ name: zeitwerk
31
29
  requirement: !ruby/object:Gem::Requirement
32
30
  requirements:
33
- - - ">="
31
+ - - "~>"
34
32
  - !ruby/object:Gem::Version
35
- version: '1.4'
33
+ version: '2.5'
36
34
  type: :runtime
37
35
  prerelease: false
38
36
  version_requirements: !ruby/object:Gem::Requirement
39
37
  requirements:
40
- - - ">="
38
+ - - "~>"
41
39
  - !ruby/object:Gem::Version
42
- version: '1.4'
43
- description: GitHub HTML processing filters and utilities
40
+ version: '2.5'
41
+ description: HTML processing filters and utilities
44
42
  email:
45
- - ryan@github.com
46
- - jerry@github.com
47
43
  - gjtorikian@gmail.com
48
44
  executables: []
49
45
  extensions: []
50
46
  extra_rdoc_files: []
51
47
  files:
52
48
  - ".github/FUNDING.yml"
49
+ - ".github/dependabot.yml"
50
+ - ".github/workflows/automerge.yml"
51
+ - ".github/workflows/lint.yml"
52
+ - ".github/workflows/tag_and_release.yml"
53
+ - ".github/workflows/test.yml"
53
54
  - ".gitignore"
54
- - ".travis.yml"
55
- - Appraisals
55
+ - ".rubocop.yml"
56
56
  - CHANGELOG.md
57
- - CONTRIBUTING.md
58
57
  - Gemfile
59
- - LICENSE
58
+ - LICENSE.txt
60
59
  - README.md
61
60
  - Rakefile
62
- - bin/html-pipeline
61
+ - UPGRADING.md
63
62
  - 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
63
+ - lib/html-pipeline.rb
64
+ - lib/html_pipeline.rb
65
+ - lib/html_pipeline/convert_filter.rb
66
+ - lib/html_pipeline/convert_filter/markdown_filter.rb
67
+ - lib/html_pipeline/filter.rb
68
+ - lib/html_pipeline/node_filter.rb
69
+ - lib/html_pipeline/node_filter/absolute_source_filter.rb
70
+ - lib/html_pipeline/node_filter/emoji_filter.rb
71
+ - lib/html_pipeline/node_filter/https_filter.rb
72
+ - lib/html_pipeline/node_filter/image_max_width_filter.rb
73
+ - lib/html_pipeline/node_filter/mention_filter.rb
74
+ - lib/html_pipeline/node_filter/table_of_contents_filter.rb
75
+ - lib/html_pipeline/node_filter/team_mention_filter.rb
76
+ - lib/html_pipeline/sanitization_filter.rb
77
+ - lib/html_pipeline/text_filter.rb
78
+ - lib/html_pipeline/text_filter/image_filter.rb
79
+ - lib/html_pipeline/text_filter/plain_text_input_filter.rb
80
+ - lib/html_pipeline/version.rb
81
+ homepage: https://github.com/gjtorikian/html-pipeline
86
82
  licenses:
87
83
  - MIT
88
- metadata: {}
84
+ metadata:
85
+ funding_uri: https://github.com/sponsors/gjtorikian/
86
+ rubygems_mfa_required: 'true'
89
87
  post_install_message: |
90
88
  -------------------------------------------------
91
89
  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
90
+ You must bundle filter gem dependencies.
91
+ See the html-pipeline README.md for more details:
92
+ https://github.com/gjtorikian/html-pipeline#dependencies
95
93
  -------------------------------------------------
96
94
  rdoc_options: []
97
95
  require_paths:
98
96
  - lib
99
97
  required_ruby_version: !ruby/object:Gem::Requirement
100
98
  requirements:
101
- - - ">="
99
+ - - "~>"
102
100
  - !ruby/object:Gem::Version
103
- version: '0'
101
+ version: '3.1'
104
102
  required_rubygems_version: !ruby/object:Gem::Requirement
105
103
  requirements:
106
104
  - - ">="
107
105
  - !ruby/object:Gem::Version
108
- version: '0'
106
+ version: 3.3.22
109
107
  requirements: []
110
- rubygems_version: 3.3.7
111
- signing_key:
108
+ rubygems_version: 3.3.26
109
+ signing_key:
112
110
  specification_version: 4
113
111
  summary: Helpers for processing content through a chain of filters
114
112
  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]