jekyll-kw-sri 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []