jekyll-kw-sri 0.0.1

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 2973377b85291043610eda6a787a2e0b90cd8a5bacc1e97307e12141d506922c
4
+ data.tar.gz: 0ce8ffe029793579111eb924cd2da6ae01542b597a8a8a1203275eefa2cb4302
5
+ SHA512:
6
+ metadata.gz: 562282c803da6ee51304bc436d2186b5f06e9ca66dca84453207570b9db17881be5d73ffbc5fc0bffaeaf3be77e2d56d2cd99f415a0295536e98640554850c0c
7
+ data.tar.gz: e6c3f3650a781d0391729bac08fc3ebe812c46fee4fe81b2a836d3810da207000b08a51bd3cdfec7eb5a54a45bd70d5d3494cef6c271cdda165fa9256b390ba5
@@ -0,0 +1,115 @@
1
+ # jekyll-kw-sri
2
+
3
+ A plugin for jekyll to calculate [Subresource Integrity][Wikipedia SRI] (SRI) hashes for CSS (even SCSS and SASS) and JS files during build time.
4
+
5
+ > **Subresource Integrity** (SRI) is a security feature that enables browsers to verify that resources they fetch (for example, from a CDN) are delivered without unexpected manipulation. It works by allowing you to provide a cryptographic hash that a fetched resource must match.
6
+
7
+ from [Mozilla docs][Mozilla Subresource Integrity]
8
+
9
+ ## Configuration
10
+
11
+ Add `kw-sri` section to `_config.yml` configure the plugin globally.
12
+
13
+ ```yaml
14
+ kw-sri:
15
+ createTmpfile: false
16
+ hash_type: 'sha384'
17
+ write_source_mapping_url: true
18
+ ```
19
+
20
+ Configuration values
21
+
22
+ | Key | Description | Values (**default**) |
23
+ |--------------------------|---------------------------------------------------|----------------------------|
24
+ | createTmpfile | Debug-Only, save the rendered sass or scss as css | **false**, true |
25
+ | hash_type | Which kind of integrity hash | sha256, **sha384**, sha512 |
26
+ | write_source_mapping_url | Add the map-file like to the css | false, **true** |
27
+
28
+ Add `sri: true` to **Front Matter** of `<page>` or `<post>` to activate the sri plugin.
29
+
30
+ ## Build gem
31
+
32
+ ## Publish gem
33
+
34
+ ## Run tests
35
+
36
+ ```sh
37
+ bundle exec rake test
38
+ ```
39
+
40
+ ### Appraisal - Gemfile Generator
41
+
42
+ [GitHub](https://github.com/thoughtbot/appraisal)
43
+
44
+ 1. Create a `Appraisals` file
45
+ 2. Generate `Gemfiles`
46
+
47
+ ```sh
48
+ bundle exec appraisal generate
49
+ ```
50
+
51
+ ## Notes / Hints
52
+
53
+ ### Site context is empty
54
+
55
+ Inside the `render(context)` function of a `Liquid::Tag` there is a context object. With that context you can get the `site` object, anyhow when you want to cretae your temporry **site** and **context** you need a workaround.
56
+
57
+ Normal way to get the site object from the render function of a custom tag
58
+
59
+ ```ruby
60
+ site = context.registers[:site]
61
+ ```
62
+
63
+ Create a temporary site and context of a **jekyll** environment
64
+
65
+ ```ruby
66
+ site = Jekyll::Site.new(Jekyll::Configuration::DEFAULTS)
67
+ context = Liquid::Context.new({}, {}, { site: site })
68
+ ```
69
+
70
+ ### Base class for custom tag
71
+ Use `Jekyll::Tags::IncludeRelativeTag` instead of `Liquid::Tag` as base class of the custom jekyll tag `SriScssHashTag` will help to read the content of the scss or sass files.
72
+
73
+ ### Find Scss converter
74
+
75
+ Sometimes, especially during testing, the site object is not perfectly setup. So the function `find_converter_instance` will throw an error.
76
+
77
+ **Default** implementation to find the converter.
78
+
79
+ ```ruby
80
+ converter = site.find_converter_instance(Jekyll::Converters::Scss)
81
+ ```
82
+
83
+ **Workaround** implementation to find the converter.
84
+
85
+ ```ruby
86
+ converter = if defined? site.find_converter_instance
87
+ site.find_converter_instance(Jekyll::Converters::Scss)
88
+ else
89
+ site.getConverterImpl(::Jekyll::Converters::Scss)
90
+ end
91
+ ```
92
+
93
+ ## SRI Integrity
94
+
95
+ ```shell
96
+ openssl dgst -sha256 -binary ./style.css | openssl base64 -A
97
+ ```
98
+
99
+ ## Setup Steps
100
+
101
+ ```sh
102
+ bundle init
103
+ bundle add rake
104
+ bundle add simplecov
105
+ bundle add minitest
106
+ bundle add minitest-reporters
107
+ bundle add minitest-profile
108
+ bundle add rspec-mocks
109
+ bundle add rdiscount
110
+ bundle add redcarpet
111
+ bundle add shoulda
112
+ ```
113
+
114
+ [Wikipedia SRI]: https://en.wikipedia.org/wiki/Subresource_Integrity
115
+ [Mozilla Subresource Integrity]: https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'jekyll-kw-sri/configuration'
4
+ require 'jekyll-kw-sri/parser'
5
+
6
+ require 'jekyll'
7
+
8
+ module Jekyll
9
+ module KargWare
10
+ # jekyll-kw-sri custom tag
11
+ class SriScssHashTag < Jekyll::Tags::IncludeRelativeTag
12
+ # class SriScssHashTag < Liquid::Tag
13
+ def initialize(tag_name, input, tokens)
14
+ super
15
+
16
+ raise 'Please enter a file path' if input.length <= 0
17
+
18
+ @scss_file = strip_or_self(input)
19
+ # File.exists? is file?
20
+
21
+ @tag_name = tag_name
22
+ end
23
+
24
+ # def syntax_example
25
+ # "{% #{@tag_name} css/main.scss %}"
26
+ # end
27
+
28
+ def render(context)
29
+ # return '' unless context.registers[:page]['sri']
30
+
31
+ # # Read the global configuration
32
+ # @sri_config = context.registers[:site].config['kw-sri'] || {}
33
+
34
+ cache_compiled_scss(@file, context, lambda {
35
+ if context.nil? || context.registers[:site].nil?
36
+ puts 'WARNING: There was no context, generate default site and context'
37
+ site = Jekyll::Site.new(Jekyll::Configuration::DEFAULTS)
38
+ context = Liquid::Context.new({}, {}, { site: site })
39
+ else
40
+ site = context.registers[:site]
41
+ end
42
+
43
+ converter = site.find_converter_instance(Jekyll::Converters::Scss)
44
+
45
+ result = super(context)
46
+ scss = result.gsub(/^---.*---/m, '')
47
+ data = converter.convert(scss)
48
+
49
+ Integrity::Parser.new(@sri_config).calc_integrity(@scss_file, data)
50
+ })
51
+ end
52
+
53
+ def cache_compiled_scss(path, _context, compute)
54
+ # @@cached_scss ||= {}
55
+ # if @@cached_scss.key?(path)
56
+ # @@cached_scss[path]
57
+ # else
58
+ # @@cached_scss[path] = compute.call
59
+ # end
60
+
61
+ @cached_scss ||= {}
62
+ if @cached_scss.key?(path)
63
+ @cached_scss[path]
64
+ else
65
+ @cached_scss[path] = compute.call
66
+ end
67
+ end
68
+
69
+ # https://stackoverflow.com/a/1000975
70
+ def strip_or_self(str)
71
+ str.strip! || str
72
+ end
73
+
74
+ def tag_includes_dirs(context)
75
+ [context.registers[:site].source].freeze
76
+ end
77
+ end
78
+ end
79
+ end
80
+
81
+ Liquid::Template.register_tag('sri_scss_hash', Jekyll::KargWare::SriScssHashTag)
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ module KargWare
5
+ module Integrity
6
+ # jekyll-kw-sri configuration class
7
+ class Configuration
8
+ attr_accessor :hash_type, :write_source_mapping_url, :create_tmpfile
9
+
10
+ DEFAULT_CONFIG = {
11
+ 'hashType' => 'sha384',
12
+ 'writeSourceMappingURL' => true,
13
+ 'createTmpfile' => false
14
+ }.freeze
15
+
16
+ def initialize(options)
17
+ options = generate_option_hash(options)
18
+
19
+ @hash_type = options['hashType']
20
+ @write_source_mapping_url = options['writeSourceMappingURL']
21
+ @create_tmpfile = options['createTmpfile']
22
+ end
23
+
24
+ private
25
+
26
+ def generate_option_hash(options)
27
+ DEFAULT_CONFIG.merge(options)
28
+ rescue TypeError
29
+ DEFAULT_CONFIG
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'digest'
4
+
5
+ module Jekyll
6
+ module KargWare
7
+ module Integrity
8
+ # jekyll-kw-sri parser class
9
+ class Parser
10
+ attr_reader :configuration
11
+
12
+ def initialize(options = {})
13
+ @configuration = Configuration.new(options)
14
+ end
15
+
16
+ def calc_integrity(filename, data)
17
+ hash_type = @configuration.hash_type
18
+
19
+ data_modified = add_source_mapping_url(filename, data)
20
+
21
+ # Debuging, save rendered css file as tmp file
22
+ File.open(".#{filename}.tmp", 'w') { |file| file.write(data_modified) } if @configuration.create_tmpfile
23
+
24
+ case hash_type
25
+ when 'sha256'
26
+ "sha256-#{Digest::SHA256.base64digest data_modified}"
27
+ when 'sha384'
28
+ "sha384-#{Digest::SHA384.base64digest data_modified}"
29
+ when 'sha512'
30
+ "sha512-#{Digest::SHA512.base64digest data_modified}"
31
+ else
32
+ raise Jekyll::KargWare::Integrity::InvalidHashTypeException, "The type of the hash '#{hash_type}' is invalid!'"
33
+ end
34
+ end
35
+
36
+ def add_source_mapping_url(filename, data)
37
+ if @configuration.write_source_mapping_url
38
+ base = File.basename(filename)
39
+ base = base.sub! 'scss', 'css'
40
+
41
+ data + "\n/*# sourceMappingURL=#{base}.map */"
42
+ else
43
+ data
44
+ end
45
+ end
46
+ end
47
+
48
+ class InvalidHashTypeException < Gem::Exception; end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JekyllKwSri
4
+ VERSION = '0.0.1'
5
+ end
metadata ADDED
@@ -0,0 +1,63 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jekyll-kw-sri
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Nicolas Karg
8
+ - n13.org - Open-Source by KargWare
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2020-11-12 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: jekyll
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '4.0'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '4.0'
28
+ description: Jekyll plugin which calculate the integrity hash of CSS (SCSS, SASS)
29
+ and JS.
30
+ email: rubygems.org@n13.org
31
+ executables: []
32
+ extensions: []
33
+ extra_rdoc_files: []
34
+ files:
35
+ - README.md
36
+ - lib/jekyll-kw-sri.rb
37
+ - lib/jekyll-kw-sri/configuration.rb
38
+ - lib/jekyll-kw-sri/parser.rb
39
+ - lib/version.rb
40
+ homepage: https://github.com/n13org/jekyll-kw-sri
41
+ licenses:
42
+ - MIT
43
+ metadata: {}
44
+ post_install_message:
45
+ rdoc_options: []
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: '2.7'
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: '0'
58
+ requirements: []
59
+ rubygems_version: 3.1.2
60
+ signing_key:
61
+ specification_version: 4
62
+ summary: Jekyll CSS/JS integrity hash plugin
63
+ test_files: []