html-pipeline 3.0.0.pre3 → 3.0.0.pre5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 613a099c0290d87932d2bbaf78052d8c472518bb911d82fe651ad78a3cc32ee9
4
- data.tar.gz: d03826dc83afb689e87395d3a365a24fd5b3608e3a29b632a79a5928acb84a2b
3
+ metadata.gz: 76b152d297b41b59af64604d1e0b034734c3ce6f3de999b1e614de96f500ecab
4
+ data.tar.gz: 5d06fbfb10d4390bec9b0c7efffadea4c0e7cf1aaf8ff4e57b23c4b2599bd928
5
5
  SHA512:
6
- metadata.gz: 35ce289f0ca10929fba016a5dd0d7c0a6bf0d8f8d4390385590c0937190df67605b96b474a477a54feb5192a54fc5b299940d264483700a9c5deac04cff1b9e1
7
- data.tar.gz: dbddce89afcb5f0291d28c9b24b4a2e4f25ea847d8960dc06a11f0c6cfd6cf2feb169f406fd69ca5f25a3eabc4338ce0cf7f2b94fa2147c682135bb6dee70728
6
+ metadata.gz: b4e943345b5febc342cd26417419982be10d2bc1e393e5783c280e06333db6d0e74a92b7d3fc173e84139fa9bc34f534f8823518b2a54ce7911e2e3e94d8dd86
7
+ data.tar.gz: 7f0fcf7e8821f86acd723a402b5911a3d667a09dd1013ae452a5494395f7535cc30a3bf1b5dca5aaac2c6bb54c103ad62d5ffdaf7f52c4ece182f553ddc810fd
@@ -15,6 +15,3 @@ updates:
15
15
  time: "09:00"
16
16
  timezone: "Etc/UTC"
17
17
  open-pull-requests-limit: 10
18
- allow:
19
- - dependency-name: "*"
20
- dependency-type: "production"
@@ -9,26 +9,5 @@ permissions:
9
9
 
10
10
  jobs:
11
11
  dependabot:
12
- name: Dependabot
13
- runs-on: ubuntu-latest
14
-
15
- if: ${{ github.actor == 'dependabot[bot]' }}
16
- steps:
17
- - name: Fetch Dependabot metadata
18
- id: dependabot-metadata
19
- uses: dependabot/fetch-metadata@v1
20
- with:
21
- github-token: "${{ secrets.GITHUB_TOKEN }}"
22
-
23
- - name: Approve Dependabot PR
24
- if: ${{steps.dependabot-metadata.outputs.update-type != 'version-update:semver-major'}}
25
- run: gh pr review --approve "$PR_URL"
26
- env:
27
- PR_URL: ${{github.event.pull_request.html_url}}
28
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
29
-
30
- - name: Merge Dependabot PR
31
- run: gh pr merge --auto --squash "$PR_URL"
32
- env:
33
- PR_URL: ${{ github.event.pull_request.html_url }}
34
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
12
+ uses: yettoapp/actions/.github/workflows/automerge_dependabot.yml@main
13
+ secrets: inherit
@@ -0,0 +1,22 @@
1
+ name: CI
2
+
3
+ on:
4
+ pull_request:
5
+
6
+ permissions:
7
+ contents: read
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+
13
+ steps:
14
+ - uses: actions/checkout@v3
15
+
16
+ - name: Set up Ruby
17
+ uses: yettoapp/actions/setup-languages@main
18
+ with:
19
+ ruby: true
20
+
21
+ - name: Run tests
22
+ run: bundle exec rake test
@@ -13,11 +13,11 @@ jobs:
13
13
  runs-on: ubuntu-latest
14
14
  steps:
15
15
  - uses: actions/checkout@v3
16
- - uses: ruby/setup-ruby@v1
16
+
17
+ - name: Set up Ruby
18
+ uses: yettoapp/actions/setup-languages@main
17
19
  with:
18
- ruby-version: 3.1.0
19
- rubygems: latest
20
- bundler-cache: true
21
- - run: bundle install
20
+ ruby: true
21
+
22
22
  - name: Rubocop
23
23
  run: bundle exec rake rubocop
@@ -0,0 +1,19 @@
1
+ name: Release
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ push:
6
+ branches:
7
+ - main
8
+ paths:
9
+ - "lib/html_pipeline/version.rb"
10
+
11
+ jobs:
12
+ ruby:
13
+ uses: yettoapp/actions/.github/workflows/ruby_gem_release.yml@main
14
+ secrets:
15
+ rubygems_api_key: ${{ secrets.RUBYGEMS_API_BOT_KEY }}
16
+ gh_token: ${{ secrets.GITHUB_TOKEN }}
17
+ with:
18
+ gem_name: html-pipeline
19
+ version_filepath: lib/html_pipeline/version.rb
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.2.1
@@ -0,0 +1,8 @@
1
+ {
2
+ "[markdown]": {
3
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
4
+ },
5
+ "[ruby]": {
6
+ "editor.defaultFormatter": "Shopify.ruby-lsp"
7
+ }
8
+ }
data/Gemfile CHANGED
@@ -28,7 +28,7 @@ end
28
28
 
29
29
  group :test do
30
30
  gem "commonmarker", "~> 1.0.0.pre7", require: false
31
- gem "gemoji", "~> 3.0", require: false
31
+ gem "gemoji", "~> 4.1", require: false
32
32
  gem "gemojione", "~> 4.3", require: false
33
33
 
34
34
  gem "minitest"
@@ -38,5 +38,5 @@ group :test do
38
38
  gem "nokogiri", "~> 1.13"
39
39
 
40
40
  gem "minitest-focus", "~> 1.1"
41
- gem "rouge", "~> 3.1", require: false
41
+ gem "rouge", "~> 4.1", require: false
42
42
  end
data/README.md CHANGED
@@ -1,23 +1,31 @@
1
- # HTMLPipeline
1
+ # HTML-Pipeline
2
2
 
3
3
  > **Note**
4
- > This README refers to the behavior in the new 3.0.0.pre1 gem.
4
+ > This README refers to the behavior in the new 3.0.0.pre gem.
5
5
 
6
6
  HTML processing filters and utilities. This module is a small
7
7
  framework for defining CSS-based content filters and applying them to user
8
8
  provided content.
9
9
 
10
- [Although this project was started at GitHub](https://github.com/blog/1311-html-pipeline-chainable-content-filters), they no longer do. This gem must be considered standalone and independent from GitHub.
11
-
12
- - [Installation](#installation)
13
- - [Usage](#usage)
14
- - [More Examples](#more-examples)
15
- - [Filters](#filters)
16
- - [Dependencies](#dependencies)
17
- - [Documentation](#documentation)
18
- - [Instrumenting](#instrumenting)
19
- - [Third Party Extensions](#third-party-extensions)
20
- - [FAQ](#faq)
10
+ [Although this project was started at GitHub](https://github.com/blog/1311-html-pipeline-chainable-content-filters), they no longer use it. This gem must be considered standalone and independent from GitHub.
11
+
12
+ - [HTML-Pipeline](#html-pipeline)
13
+ - [Installation](#installation)
14
+ - [Usage](#usage)
15
+ - [More Examples](#more-examples)
16
+ - [Filters](#filters)
17
+ - [TextFilters](#textfilters)
18
+ - [ConvertFilter](#convertfilter)
19
+ - [Sanitization](#sanitization)
20
+ - [NodeFilters](#nodefilters)
21
+ - [Dependencies](#dependencies)
22
+ - [Documentation](#documentation)
23
+ - [Instrumenting](#instrumenting)
24
+ - [Third Party Extensions](#third-party-extensions)
25
+ - [FAQ](#faq)
26
+ - [1. Why doesn't my pipeline work when there's no root element in the document?](#1-why-doesnt-my-pipeline-work-when-theres-no-root-element-in-the-document)
27
+ - [2. How do I customize an allowlist for `SanitizationFilter`s?](#2-how-do-i-customize-an-allowlist-for-sanitizationfilters)
28
+ - [Contributors](#contributors)
21
29
 
22
30
  ## Installation
23
31
 
@@ -231,6 +239,7 @@ end
231
239
  For more information on how to write effective `NodeFilter`s, refer to the provided filters, and see the underlying lib, [Selma](https://www.github.com/gjtorikian/selma) for more information.
232
240
 
233
241
  - `AbsoluteSourceFilter`: replace relative image urls with fully qualified versions
242
+ - `AssetProxyFilter`: replace image links with an encoded link to an asset server
234
243
  - `EmojiFilter`: converts `:<emoji>:` to [emoji](http://www.emoji-cheat-sheet.com/)
235
244
  - (Note: the included `MarkdownFilter` will already convert emoji)
236
245
  - `HttpsFilter`: Replacing http urls with https versions
@@ -25,7 +25,7 @@ Gem::Specification.new do |gem|
25
25
  "rubygems_mfa_required" => "true",
26
26
  }
27
27
 
28
- gem.add_dependency("selma", "~> 0.0.1")
28
+ gem.add_dependency("selma", "~> 0.1")
29
29
  gem.add_dependency("zeitwerk", "~> 2.5")
30
30
 
31
31
  gem.post_install_message = <<~MSG
@@ -12,6 +12,6 @@ class HTMLPipeline
12
12
  def call(text, context: {}, result: {})
13
13
  new(context: context, result: result).call(text)
14
14
  end
15
- end
15
+ end
16
16
  end
17
17
  end
@@ -49,7 +49,7 @@ class HTMLPipeline
49
49
  def call(input, context: {})
50
50
  raise NoMethodError
51
51
  end
52
- end
52
+ end
53
53
  # Make sure the context has everything we need. Noop: Subclasses can override.
54
54
  def validate; end
55
55
 
@@ -4,6 +4,19 @@ require "uri"
4
4
 
5
5
  class HTMLPipeline
6
6
  class NodeFilter
7
+ # HTML Filter for replacing relative and root relative image URLs with
8
+ # fully qualified URLs
9
+ #
10
+ # This is useful if an image is root relative but should really be going
11
+ # through a cdn, or if the content for the page assumes the host is known
12
+ # i.e. scraped webpages and some RSS feeds.
13
+ #
14
+ # Context options:
15
+ # :image_base_url - Base URL for image host for root relative src.
16
+ # :image_subpage_url - For relative src.
17
+ #
18
+ # This filter does not write additional information to the context.
19
+ # Note: This filter would need to be run before AssetProxyFilter.
7
20
  class AbsoluteSourceFilter < NodeFilter
8
21
  SELECTOR = Selma::Selector.new(match_element: "img")
9
22
 
@@ -11,19 +24,6 @@ class HTMLPipeline
11
24
  SELECTOR
12
25
  end
13
26
 
14
- # HTML Filter for replacing relative and root relative image URLs with
15
- # fully qualified URLs
16
- #
17
- # This is useful if an image is root relative but should really be going
18
- # through a cdn, or if the content for the page assumes the host is known
19
- # i.e. scraped webpages and some RSS feeds.
20
- #
21
- # Context options:
22
- # :image_base_url - Base URL for image host for root relative src.
23
- # :image_subpage_url - For relative src.
24
- #
25
- # This filter does not write additional information to the context.
26
- # This filter would need to be run before CamoFilter.
27
27
  def handle_element(element)
28
28
  src = element["src"]
29
29
  return if src.nil? || src.empty?
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "openssl"
4
+
5
+ class HTMLPipeline
6
+ class NodeFilter
7
+ # Proxy images/assets to another server, such as
8
+ # [cactus/go-camo](https://github.com/cactus/go-camo#).
9
+ # Reduces mixed content warnings as well as hiding the customer's
10
+ # IP address when requesting images.
11
+ # Copies the original img `src` to `data-canonical-src` then replaces the
12
+ # `src` with a new url to the proxy server.
13
+ #
14
+ # Based on https://github.com/gjtorikian/html-pipeline/blob/v2.14.3/lib/html/pipeline/camo_filter.rb
15
+ class AssetProxyFilter < NodeFilter
16
+ SELECTOR = Selma::Selector.new(match_element: "img")
17
+
18
+ def selector
19
+ SELECTOR
20
+ end
21
+
22
+ def handle_element(element)
23
+ original_src = element["src"]
24
+ return unless original_src
25
+
26
+ begin
27
+ uri = URI.parse(original_src)
28
+ rescue StandardError
29
+ return
30
+ end
31
+
32
+ return if uri.host.nil? && !original_src.start_with?("///")
33
+ return if asset_host_allowed?(uri.host)
34
+
35
+ element["src"] = asset_proxy_url(original_src)
36
+ element["data-canonical-src"] = original_src
37
+ end
38
+
39
+ def validate
40
+ needs(:asset_proxy, :asset_proxy_secret_key)
41
+ end
42
+
43
+ def asset_host_allowed?(host)
44
+ context[:asset_proxy_domain_regexp] ? context[:asset_proxy_domain_regexp].match?(host) : false
45
+ end
46
+
47
+ class << self
48
+ # This helps setup the context. It's not needed if you're always providing
49
+ # all the necessary keys in the context. One example would be to override
50
+ # this and pull the settings from a set of global application settings.
51
+ def transform_context(context, proxy_settings = {})
52
+ context[:asset_proxy] = proxy_settings[:url] if proxy_settings[:url]
53
+ context[:asset_proxy_secret_key] = proxy_settings[:secret_key] if proxy_settings[:secret_key]
54
+
55
+ allowlist = determine_allowlist(proxy_settings)
56
+ context[:asset_proxy_domain_regexp] ||= compile_allowlist(allowlist)
57
+
58
+ context
59
+ end
60
+
61
+ def compile_allowlist(domain_list)
62
+ return if domain_list.empty?
63
+
64
+ escaped = domain_list.map { |domain| Regexp.escape(domain).gsub("\\*", ".*?") }
65
+ Regexp.new("^(#{escaped.join("|")})$", Regexp::IGNORECASE)
66
+ end
67
+
68
+ def determine_allowlist(proxy_settings)
69
+ proxy_settings[:allowlist] || []
70
+ end
71
+ end
72
+
73
+ private def asset_proxy_url(url)
74
+ "#{context[:asset_proxy]}/#{asset_url_hash(url)}/#{hexencode(url)}"
75
+ end
76
+
77
+ private def asset_url_hash(url)
78
+ OpenSSL::HMAC.hexdigest("sha1", context[:asset_proxy_secret_key], url)
79
+ end
80
+
81
+ private def hexencode(str)
82
+ str.unpack1("H*")
83
+ end
84
+ end
85
+ end
86
+ end
@@ -38,7 +38,7 @@ class HTMLPipeline
38
38
  yield match, login
39
39
  end
40
40
  end
41
- end
41
+ end
42
42
  # Hash that contains all of the mention patterns used by the pipeline
43
43
  MENTION_PATTERNS = Hash.new do |hash, key|
44
44
  hash[key] = %r{
@@ -35,7 +35,7 @@ class HTMLPipeline
35
35
  yield match, org, team
36
36
  end
37
37
  end
38
- end
38
+ end
39
39
 
40
40
  # Default pattern used to extract team names from text. The value can be
41
41
  # overridden by providing the team_pattern variable in the context. To
@@ -183,6 +183,6 @@ class HTMLPipeline
183
183
  sanitization_config = Selma::Sanitizer.new(config)
184
184
  Selma::Rewriter.new(sanitizer: sanitization_config).rewrite(html)
185
185
  end
186
- end
186
+ end
187
187
  end
188
188
  end
@@ -16,6 +16,6 @@ class HTMLPipeline
16
16
  def call(input, context: {}, result: {})
17
17
  new(input, context: context, result: result).call
18
18
  end
19
- end
19
+ end
20
20
  end
21
21
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class HTMLPipeline
4
- VERSION = "3.0.0.pre3"
4
+ VERSION = "3.0.0.pre5"
5
5
  end
data/lib/html_pipeline.rb CHANGED
@@ -81,7 +81,7 @@ class HTMLPipeline
81
81
  def define_dependency_loaded_method(name, value)
82
82
  self.class.define_method(:"#{name}_loaded?", -> { value })
83
83
  end
84
- end
84
+ end
85
85
  # Public: Returns an Array of Filter objects for this Pipeline.
86
86
  attr_reader :text_filters, :node_filters
87
87
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: html-pipeline
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0.pre3
4
+ version: 3.0.0.pre5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Garen J. Torikian
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-02-15 00:00:00.000000000 Z
11
+ date: 2023-06-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: selma
@@ -16,14 +16,15 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.0.1
19
+ version: '0.1'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.0.1
26
+ version: '0.1'
27
+ force_ruby_platform: false
27
28
  - !ruby/object:Gem::Dependency
28
29
  name: zeitwerk
29
30
  requirement: !ruby/object:Gem::Requirement
@@ -38,6 +39,7 @@ dependencies:
38
39
  - - "~>"
39
40
  - !ruby/object:Gem::Version
40
41
  version: '2.5'
42
+ force_ruby_platform: false
41
43
  description: HTML processing filters and utilities
42
44
  email:
43
45
  - gjtorikian@gmail.com
@@ -48,11 +50,13 @@ files:
48
50
  - ".github/FUNDING.yml"
49
51
  - ".github/dependabot.yml"
50
52
  - ".github/workflows/automerge.yml"
53
+ - ".github/workflows/ci.yml"
51
54
  - ".github/workflows/lint.yml"
52
- - ".github/workflows/tag_and_release.yml"
53
- - ".github/workflows/test.yml"
55
+ - ".github/workflows/publish.yml"
54
56
  - ".gitignore"
55
57
  - ".rubocop.yml"
58
+ - ".ruby-version"
59
+ - ".vscode/settings.json"
56
60
  - CHANGELOG.md
57
61
  - Gemfile
58
62
  - LICENSE.txt
@@ -67,6 +71,7 @@ files:
67
71
  - lib/html_pipeline/filter.rb
68
72
  - lib/html_pipeline/node_filter.rb
69
73
  - lib/html_pipeline/node_filter/absolute_source_filter.rb
74
+ - lib/html_pipeline/node_filter/asset_proxy_filter.rb
70
75
  - lib/html_pipeline/node_filter/emoji_filter.rb
71
76
  - lib/html_pipeline/node_filter/https_filter.rb
72
77
  - lib/html_pipeline/node_filter/image_max_width_filter.rb
@@ -106,7 +111,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
106
111
  - !ruby/object:Gem::Version
107
112
  version: 3.3.22
108
113
  requirements: []
109
- rubygems_version: 3.3.26
114
+ rubygems_version: 3.4.13
110
115
  signing_key:
111
116
  specification_version: 4
112
117
  summary: Helpers for processing content through a chain of filters
@@ -1,70 +0,0 @@
1
- name: Tag and Release
2
-
3
- on:
4
- workflow_dispatch:
5
- push:
6
- branches:
7
- - main
8
- paths:
9
- - "lib/html_pipeline/version.rb"
10
-
11
- jobs:
12
- release:
13
- env:
14
- GEM_NAME: html-pipeline
15
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
16
- GEM_HOST_API_KEY: ${{ secrets.RUBYGEMS_API_BOT_KEY }}
17
- runs-on: ubuntu-latest
18
- steps:
19
- - uses: actions/checkout@v3
20
-
21
- - name: Set up Ruby 3.1
22
- uses: ruby/setup-ruby@v1
23
- with:
24
- ruby-version: 3.1
25
- bundler-cache: true
26
-
27
- - name: Configure Git
28
- run: |
29
- git config --local user.email "actions@github.com"
30
- git config --local user.name "Actions Auto Build"
31
-
32
- - name: Get current version
33
- id: version-label
34
- run: |
35
- VERSION=$(grep VERSION lib/html_pipeline/version.rb | head -n 1 | cut -d'"' -f2)
36
- echo "version=${VERSION}" >> $GITHUB_OUTPUT
37
-
38
- - name: Create tag
39
- run: |
40
- git tag -a v${{ steps.version-label.outputs.version }} -m "Release v${{ steps.version-label.outputs.version }}"
41
- git push origin --tags
42
-
43
- - name: Generate CHANGELOG.md
44
- id: changelog
45
- run: script/generate_changelog
46
-
47
- - name: Commit & Push Changelog
48
- run: |
49
- git config --local user.email "actions@github.com"
50
- git config --local user.name "Actions Auto Build"
51
- git add -f CHANGELOG.md
52
- git commit -m "docs: update changelog" || true
53
- git push
54
-
55
- - name: Publish release
56
- env:
57
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
58
- run: |
59
- gh release create v${{ steps.version-label.outputs.version }} --generate-notes
60
-
61
- - name: Publish to RubyGems
62
- run: |
63
- mkdir -p $HOME/.gem
64
- touch $HOME/.gem/credentials
65
- chmod 0600 $HOME/.gem/credentials
66
- printf -- "---\n:rubygems_api_key: ${RUBYGEMS_API_BOT_KEY}\n" > $HOME/.gem/credentials
67
- bundle exec rake package
68
- for gem in pkg/html-pipeline-${{ steps.version-label.outputs.version }}*.gem ; do
69
- gem push "$gem" --host https://rubygems.org
70
- done
@@ -1,33 +0,0 @@
1
- name: Tests
2
-
3
- on:
4
- pull_request:
5
-
6
- permissions:
7
- contents: read
8
-
9
- jobs:
10
- test:
11
- runs-on: ubuntu-latest
12
-
13
- strategy:
14
- fail-fast: true
15
- matrix:
16
- ruby-version:
17
- - 3.1.0
18
-
19
- steps:
20
- - uses: actions/checkout@v3
21
-
22
- - name: Set up Ruby ${{ matrix.ruby-version }}
23
- uses: ruby/setup-ruby@v1
24
- with:
25
- ruby-version: ${{ matrix.ruby-version }}
26
- rubygems: latest
27
- bundler-cache: true
28
-
29
- - name: Install dependencies
30
- run: bundle install
31
-
32
- - name: Run tests
33
- run: bundle exec rake test