jekyll-simple-assets 0.2.0 → 0.3.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bbe1fbd068c7784ca4ed4d4ea3777ef10c45a6ed3b960d9fcfdcb843bdff8a1d
4
- data.tar.gz: 44b828531c73f697e539740ee38389626d8aa7560316c2fdff63c663b3a26592
3
+ metadata.gz: 066a9158d842b14dd87beb951baa1012dc97eb74e68009b97ebce1fc75d114dd
4
+ data.tar.gz: a78b84504fdff45054e89b9b3f017692460d9c74c3ed0017df0c45d4605f6950
5
5
  SHA512:
6
- metadata.gz: 7749e0e9835f7891e154438f8dddff62be167d2d1ac1102a6c1c999485f653a1b4b7ef057b7983bd630605306d75245c66e9f0b7667b19be178d09079c353c29
7
- data.tar.gz: 447cfa3bb7e120ae5c9626e25124202932c6e7c66e8fbeb948d2ab749225850391a346aeb25919e69fd702fbc250f1c06548fc2292e2937f28d3170bd6aadcac
6
+ metadata.gz: 556175bc3e9f81311e942242ac3b00574fdb6ac1fd979fe37cb74bd392b170ac14e49c893e917a870ed9714951e65a53e560bb1a76855bb647c2c945a8513528
7
+ data.tar.gz: 2e081620199cdf8ec5330678311d260da6b9405c25b7121324955be887018180c643a5e87cb80d2c1abb8b23fe3d28ae39233d20b00e07e0a9fc78d6549e213a
data/Gemfile.lock ADDED
@@ -0,0 +1,77 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ jekyll-simple-assets (0.2.0)
5
+ css_parser
6
+ jekyll
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ addressable (2.7.0)
12
+ public_suffix (>= 2.0.2, < 5.0)
13
+ colorator (1.1.0)
14
+ concurrent-ruby (1.1.6)
15
+ css_parser (1.7.1)
16
+ addressable
17
+ em-websocket (0.5.1)
18
+ eventmachine (>= 0.12.9)
19
+ http_parser.rb (~> 0.6.0)
20
+ eventmachine (1.2.7)
21
+ ffi (1.13.1)
22
+ forwardable-extended (2.6.0)
23
+ http_parser.rb (0.6.0)
24
+ i18n (1.8.3)
25
+ concurrent-ruby (~> 1.0)
26
+ jekyll (4.1.0)
27
+ addressable (~> 2.4)
28
+ colorator (~> 1.0)
29
+ em-websocket (~> 0.5)
30
+ i18n (~> 1.0)
31
+ jekyll-sass-converter (~> 2.0)
32
+ jekyll-watch (~> 2.0)
33
+ kramdown (~> 2.1)
34
+ kramdown-parser-gfm (~> 1.0)
35
+ liquid (~> 4.0)
36
+ mercenary (~> 0.4.0)
37
+ pathutil (~> 0.9)
38
+ rouge (~> 3.0)
39
+ safe_yaml (~> 1.0)
40
+ terminal-table (~> 1.8)
41
+ jekyll-sass-converter (2.1.0)
42
+ sassc (> 2.0.1, < 3.0)
43
+ jekyll-watch (2.2.1)
44
+ listen (~> 3.0)
45
+ kramdown (2.2.1)
46
+ rexml
47
+ kramdown-parser-gfm (1.1.0)
48
+ kramdown (~> 2.0)
49
+ liquid (4.0.3)
50
+ listen (3.2.1)
51
+ rb-fsevent (~> 0.10, >= 0.10.3)
52
+ rb-inotify (~> 0.9, >= 0.9.10)
53
+ mercenary (0.4.0)
54
+ pathutil (0.16.2)
55
+ forwardable-extended (~> 2.6)
56
+ public_suffix (4.0.5)
57
+ rb-fsevent (0.10.4)
58
+ rb-inotify (0.10.1)
59
+ ffi (~> 1.0)
60
+ rexml (3.2.4)
61
+ rouge (3.20.0)
62
+ safe_yaml (1.0.5)
63
+ sassc (2.4.0)
64
+ ffi (~> 1.9)
65
+ terminal-table (1.8.0)
66
+ unicode-display_width (~> 1.1, >= 1.1.1)
67
+ unicode-display_width (1.7.0)
68
+
69
+ PLATFORMS
70
+ ruby
71
+
72
+ DEPENDENCIES
73
+ bundler
74
+ jekyll-simple-assets!
75
+
76
+ BUNDLED WITH
77
+ 2.1.4
data/README.md CHANGED
@@ -71,6 +71,12 @@ to manipulate the output of the contenthash or asset tags.
71
71
  By default the generation of content hashes is only enabled for production
72
72
  builds (if JEKYLL_ENV is set to 'production').
73
73
 
74
+ ## Critical CSS
75
+
76
+ This plugin can also be used to generate critical css stylesheets. See
77
+ configuration for more information on doing this. To generate critical css,
78
+ [critical](https://github.com/addyosmani/critical) must be installed.
79
+
74
80
  ## Configuration
75
81
 
76
82
  ```
@@ -83,4 +89,24 @@ simple_assets:
83
89
  # The length of the content hashes generated.
84
90
  # default: 16
85
91
  hash_length: 8
92
+
93
+ # Options for generating a critical css file using the `critical` npm module
94
+ critical_css:
95
+
96
+ # Array of source css files used to take the critical css from
97
+ css_files:
98
+ - assets/css/style.css
99
+
100
+ # Array of critical css files to generate
101
+ files:
102
+ # The path of the critical css file output
103
+ - output_file: assets/css/critical.css
104
+ # The path of the input page used to generate the critical css
105
+ # either this option or layout can be used
106
+ input_page_path: _drafts/webmentions-static-site.md
107
+ # The layout to use to generate critical css
108
+ # (will use the first page found with this layout)
109
+ layout: post
110
+ # If the rules should be removed from the original source css files
111
+ extract: true
86
112
  ```
@@ -19,6 +19,7 @@ Gem::Specification.new do |spec|
19
19
  spec.required_ruby_version = ">= 2.3.0"
20
20
 
21
21
  spec.add_runtime_dependency "jekyll"
22
+ spec.add_runtime_dependency "css_parser"
22
23
 
23
24
  spec.add_development_dependency "bundler"
24
25
  end
@@ -2,6 +2,11 @@
2
2
 
3
3
  require 'digest'
4
4
  require 'pathname'
5
+ require 'open3'
6
+ require 'shellwords'
7
+
8
+ require 'jekyll-simple-assets/content-hash'
9
+ require 'jekyll-simple-assets/critical'
5
10
 
6
11
  module Jekyll
7
12
  module SimpleAssets
@@ -13,14 +18,14 @@ module Jekyll
13
18
  @@config ||= @@site.config['simple_assets']
14
19
  end
15
20
 
16
- def self.hash_length
17
- config['hash_length'] || 16
18
- end
19
-
20
21
  def self.hashing_enabled?
21
22
  config['hashing_enabled'] || ENV['JEKYLL_ENV'] == 'production'
22
23
  end
23
24
 
25
+ def self.critical_css_enabled?
26
+ config.key?('critical_css')
27
+ end
28
+
24
29
  module SimpleAssetsFilters
25
30
  def md5 (input)
26
31
  Digest::MD5.hexdigest(input)
@@ -56,200 +61,69 @@ module Jekyll
56
61
  content
57
62
  end
58
63
  end
64
+ end
65
+ end
59
66
 
60
- def self.page_assets_map
61
- @@page_assets_map ||= {}
62
- end
63
-
64
- def self.asset_placeholder_map
65
- @@asset_placeholder_map ||= {}
66
- end
67
-
68
- def self.asset_contenthash_map
69
- @@asset_contenthash_map ||= {}
70
- end
71
-
72
- def self.get_placeholder (asset_path)
73
- asset_placeholder_map[asset_path] ||= Digest::MD5.base64digest(asset_path)
74
- end
75
-
76
- def self.relative_url (path)
77
- "#{ @@site.config['baseurl'] || '' }/#{ path }".gsub(%r{/{2,}}, '/')
78
- end
79
-
80
- class AssetTag < Liquid::Tag
81
- def initialize (tag_name, text, tokens)
82
- super
83
- @text = text
84
- end
85
-
86
- def get_value (context, expression)
87
- result = nil
88
-
89
- unless expression.empty?
90
- lookup_path = expression.split('.')
91
- result = context
92
- lookup_path.each do |variable|
93
- result = result[variable] if result
94
- end
95
- end
96
-
97
- case result
98
- when 'true'
99
- result = true
100
- when 'false'
101
- result = false
102
- end
103
-
104
- result || expression
105
- end
106
-
107
- def render (context)
108
- site = SimpleAssets::site(context.registers[:site])
109
-
110
- page = context.environments.first['page']
111
-
112
- args = Shellwords.split(@text)
67
+ Liquid::Template.register_tag('bundle', Jekyll::SimpleAssets::BundleTag)
68
+ Liquid::Template.register_tag('bundle_raw', Jekyll::SimpleAssets::BundleRawTag)
113
69
 
114
- page_path = context['page']['path'].sub(/^\//, '')
70
+ Liquid::Template.register_filter(Jekyll::SimpleAssets::SimpleAssetsFilters)
115
71
 
116
- asset_path = get_value(context, args[0]).sub(/^\//, '')
72
+ Jekyll::Hooks.register :site, :post_render, priority: :low do |site, payload|
73
+ Jekyll::SimpleAssets::site(site)
117
74
 
118
- if SimpleAssets::hashing_enabled?
119
- SimpleAssets::page_assets_map[page_path] ||= {}
120
- SimpleAssets::page_assets_map[page_path][asset_path] ||= {}
121
- SimpleAssets::page_assets_map[page_path][asset_path][@type] ||= []
75
+ potential_assets = []
122
76
 
123
- placeholder = SimpleAssets::get_placeholder(asset_path)
77
+ potential_assets += site.pages
78
+ potential_assets += site.static_files
124
79
 
125
- unless SimpleAssets::page_assets_map[page_path][asset_path][@type].include? placeholder
126
- SimpleAssets::page_assets_map[page_path][asset_path][@type] << placeholder
127
- end
80
+ potential_pages = potential_assets
128
81
 
129
- "#{ @type }::#{ placeholder }"
130
- else
131
- if @type == 'path'
132
- SimpleAssets::relative_url(asset_path)
133
- else
134
- placeholder[0, SimpleAssets::hash_length]
135
- end
136
- end
137
- end
138
- end
82
+ site.collections.each do |collection_name, collection|
83
+ potential_pages = potential_pages + collection.docs
84
+ end
139
85
 
140
- class PathTag < AssetTag
141
- def initialize (tag_name, text, tokens)
142
- super
143
- @type = 'path'
144
- end
86
+ if Jekyll::SimpleAssets::critical_css_enabled?
87
+ potential_assets.each do |asset|
88
+ Jekyll::SimpleAssets::make_temp_css_files_for_critical(asset)
145
89
  end
146
90
 
147
- class ContentHashTag < AssetTag
148
- def initialize (tag_name, text, tokens)
149
- super
150
- @type = 'contenthash'
151
- end
91
+ potential_pages.each do |doc|
92
+ Jekyll::SimpleAssets::get_html_input_for_critical(doc, site)
152
93
  end
153
94
 
154
- def self.resolve_asset_content_hashes (asset, site)
155
- asset_path = asset.path.sub("#{ site.config['source'] }/", '')
156
-
157
- if File.extname(asset_path) == '.scss'
158
- asset_path = Pathname.new(asset_path).sub_ext('.css').to_path()
159
- elsif File.extname(asset_path) == '.ts'
160
- asset_path = Pathname.new(asset_path).sub_ext('.js').to_path()
161
- end
162
-
163
- return unless SimpleAssets::asset_placeholder_map[asset_path]
164
- return if SimpleAssets::asset_contenthash_map[asset_path]
165
-
166
- content = ""
167
-
168
- # Prefer reading from output if available, because in theory should
169
- # be faster than from disk, but fall back to reading from disk for
170
- # static assets.
171
- if asset.respond_to? :output
172
- content = asset.output
173
- elsif File.file? asset_path
174
- content = File.read asset_path
175
- elsif File.file? asset.path
176
- content = File.read asset.path
177
- else
178
- Jekyll.logger.warn "SimpleAssets", "File: #{ asset_path } not found"
179
- end
180
-
181
- if content.nil?
182
- Jekyll.logger.warn "SimpleAssets", "#{ asset_path } has no content"
183
- end
184
-
185
- base64hash = Digest::MD5.base64digest(content)
186
-
187
- hash = base64hash[0, SimpleAssets::hash_length]
95
+ Jekyll::SimpleAssets::generate_critical_css(site)
96
+ end
188
97
 
189
- SimpleAssets::asset_contenthash_map[asset_path] = hash
98
+ if Jekyll::SimpleAssets::hashing_enabled?
99
+ potential_assets.each do |asset|
100
+ Jekyll::SimpleAssets::resolve_asset_content_hashes(asset, site)
190
101
  end
191
102
 
192
- def self.replace_placeholders_for_asset (doc, site)
193
- page_path = doc.path.sub("#{ site.config['source'] }/", '')
194
-
195
- return unless SimpleAssets::page_assets_map[page_path]
196
-
197
- SimpleAssets::page_assets_map[page_path].each do |asset_path, types|
198
- types.each do |type, placeholders|
199
- placeholders.each do |placeholder_hash|
200
- unless SimpleAssets::asset_contenthash_map[asset_path]
201
- Jekyll.logger.warn "SimpleAssets", "No contenthash for: #{ asset_path } not found"
202
- end
203
-
204
- replacement = SimpleAssets::asset_contenthash_map[asset_path]
205
-
206
- if type == 'path'
207
- replacement = "#{ asset_path }?v=#{ replacement }"
208
-
209
- replacement = SimpleAssets::relative_url(replacement)
210
- end
211
-
212
- placeholder = "#{ type }::#{ SimpleAssets::asset_placeholder_map[asset_path] }"
103
+ if Jekyll::SimpleAssets::critical_css_enabled?
104
+ Jekyll::SimpleAssets::resolve_critical_css_content_hashes(site)
105
+ end
213
106
 
214
- doc.output = doc.output.gsub(placeholder, replacement)
215
- end
216
- end
217
- end
107
+ potential_pages.each do |doc|
108
+ Jekyll::SimpleAssets::replace_placeholders_for_asset(doc, site)
218
109
  end
219
110
  end
220
111
  end
221
112
 
222
- Liquid::Template.register_tag('asset', Jekyll::SimpleAssets::PathTag)
223
- Liquid::Template.register_tag('contenthash', Jekyll::SimpleAssets::ContentHashTag)
224
- Liquid::Template.register_tag('bundle', Jekyll::SimpleAssets::BundleTag)
225
- Liquid::Template.register_tag('bundle_raw', Jekyll::SimpleAssets::BundleRawTag)
226
-
227
- Liquid::Template.register_filter(Jekyll::SimpleAssets::SimpleAssetsFilters)
228
-
229
- Jekyll::Hooks.register :site, :post_render do |site, payload|
230
- Jekyll::SimpleAssets::site(site)
231
-
232
- return unless Jekyll::SimpleAssets::hashing_enabled?
233
-
234
- potential_assets = []
235
-
236
- potential_assets += site.pages
237
- potential_assets += site.static_files
238
-
239
- potential_assets.each do |asset|
240
- Jekyll::SimpleAssets::resolve_asset_content_hashes(asset, site)
241
- end
242
-
243
- docs = []
113
+ Jekyll::Hooks.register :site, :post_read do |site|
114
+ css_pages = [];
244
115
 
245
116
  site.pages.each do |doc|
246
- Jekyll::SimpleAssets::replace_placeholders_for_asset(doc, site)
247
- end
248
-
249
- site.collections.each do |collection_name, collection|
250
- collection.docs.each do |doc|
251
- Jekyll::SimpleAssets::replace_placeholders_for_asset(doc, site)
117
+ if doc.extname == '.scss'
118
+ css_pages << doc
119
+ site.pages = site.pages - [ doc ]
252
120
  end
253
121
  end
122
+
123
+ site.pages = css_pages + site.pages
254
124
  end
255
125
 
126
+ # Jekyll::Hooks.register :pages, :post_render do |document|
127
+ # puts 'rendered:' + document.path
128
+ # end
129
+
@@ -0,0 +1,186 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ module SimpleAssets
5
+
6
+
7
+ def self.hash_length
8
+ config['hash_length'] || 16
9
+ end
10
+
11
+ def self.page_assets_map
12
+ @@page_assets_map ||= {}
13
+ end
14
+
15
+ def self.asset_placeholder_map
16
+ @@asset_placeholder_map ||= {}
17
+ end
18
+
19
+ def self.asset_contenthash_map
20
+ @@asset_contenthash_map ||= {}
21
+ end
22
+
23
+ def self.get_placeholder (asset_path)
24
+ asset_placeholder_map[asset_path] ||= Digest::MD5.base64digest(asset_path)
25
+ end
26
+
27
+ def self.relative_url (path)
28
+ "#{ @@site.config['baseurl'] || '' }/#{ path }".gsub(%r{/{2,}}, '/')
29
+ end
30
+
31
+ class AssetTag < Liquid::Tag
32
+ def initialize (tag_name, text, tokens)
33
+ super
34
+ @text = text
35
+ end
36
+
37
+ def get_value (context, expression)
38
+ result = nil
39
+
40
+ unless expression.empty?
41
+ lookup_path = expression.split('.')
42
+ result = context
43
+ lookup_path.each do |variable|
44
+ result = result[variable] if result
45
+ end
46
+ end
47
+
48
+ case result
49
+ when 'true'
50
+ result = true
51
+ when 'false'
52
+ result = false
53
+ end
54
+
55
+ result || expression
56
+ end
57
+
58
+ def render (context)
59
+ site = SimpleAssets::site(context.registers[:site])
60
+
61
+ page = context.environments.first['page']
62
+
63
+ args = Shellwords.split(@text)
64
+
65
+ page_path = context['page']['path'].sub(/^\//, '')
66
+
67
+ asset_path = get_value(context, args[0]).sub(/^\//, '')
68
+
69
+ if SimpleAssets::hashing_enabled?
70
+ SimpleAssets::page_assets_map[page_path] ||= {}
71
+ SimpleAssets::page_assets_map[page_path][asset_path] ||= {}
72
+ SimpleAssets::page_assets_map[page_path][asset_path][@type] ||= []
73
+
74
+ placeholder = SimpleAssets::get_placeholder(asset_path)
75
+
76
+ unless SimpleAssets::page_assets_map[page_path][asset_path][@type].include? placeholder
77
+ SimpleAssets::page_assets_map[page_path][asset_path][@type] << placeholder
78
+ end
79
+
80
+ "#{ @type }::#{ placeholder }"
81
+ else
82
+ if @type == 'path'
83
+ SimpleAssets::relative_url(asset_path)
84
+ else
85
+ placeholder[0, SimpleAssets::hash_length]
86
+ end
87
+ end
88
+ end
89
+ end
90
+
91
+ class PathTag < AssetTag
92
+ def initialize (tag_name, text, tokens)
93
+ super
94
+ @type = 'path'
95
+ end
96
+ end
97
+
98
+ class ContentHashTag < AssetTag
99
+ def initialize (tag_name, text, tokens)
100
+ super
101
+ @type = 'contenthash'
102
+ end
103
+ end
104
+
105
+ def self.resolve_asset_content_hashes (asset, site)
106
+ asset_path = asset.path.sub("#{ site.config['source'] }/", '')
107
+
108
+ if File.extname(asset_path) == '.scss'
109
+ asset_path = Pathname.new(asset_path).sub_ext('.css').to_path()
110
+ elsif File.extname(asset_path) == '.ts'
111
+ asset_path = Pathname.new(asset_path).sub_ext('.js').to_path()
112
+ end
113
+
114
+ return unless SimpleAssets::asset_placeholder_map[asset_path]
115
+ return if SimpleAssets::asset_contenthash_map[asset_path]
116
+
117
+ content = ""
118
+
119
+ # Prefer reading from output if available, because in theory should
120
+ # be faster than from disk, but fall back to reading from disk for
121
+ # static assets.
122
+ if asset.respond_to? :output
123
+ content = asset.output
124
+ elsif File.file? asset_path
125
+ content = File.read asset_path
126
+ elsif File.file? asset.path
127
+ content = File.read asset.path
128
+ else
129
+ Jekyll.logger.warn "SimpleAssets:", "File: #{ asset_path } not found"
130
+ end
131
+
132
+ if content.nil?
133
+ Jekyll.logger.warn "SimpleAssets:", "#{ asset_path } has no content"
134
+ end
135
+
136
+ base64hash = Digest::MD5.base64digest(content)
137
+
138
+ hash = base64hash[0, SimpleAssets::hash_length].gsub(/[+\/]/, '_')
139
+
140
+ SimpleAssets::asset_contenthash_map[asset_path] = hash
141
+ end
142
+
143
+ def self.replace_placeholders_for_path (page_path, input)
144
+ output = input
145
+
146
+ SimpleAssets::page_assets_map[page_path].each do |asset_path, types|
147
+ types.each do |type, placeholders|
148
+ placeholders.each do |placeholder_hash|
149
+ unless SimpleAssets::asset_contenthash_map[asset_path]
150
+ Jekyll.logger.warn "SimpleAssets:", "No contenthash for: #{ asset_path } not found"
151
+
152
+ next
153
+ end
154
+
155
+ replacement = SimpleAssets::asset_contenthash_map[asset_path]
156
+
157
+ if type == 'path'
158
+ replacement = "#{ asset_path }?v=#{ replacement }"
159
+
160
+ replacement = SimpleAssets::relative_url(replacement)
161
+ end
162
+
163
+ placeholder = "#{ type }::#{ SimpleAssets::asset_placeholder_map[asset_path] }"
164
+
165
+ output = output.gsub(placeholder, replacement)
166
+ end
167
+ end
168
+ end
169
+
170
+ output
171
+ end
172
+
173
+ def self.replace_placeholders_for_asset (doc, site)
174
+ page_path = doc.path.sub("#{ site.config['source'] }/", '')
175
+
176
+ return unless SimpleAssets::page_assets_map[page_path]
177
+
178
+ doc.output = SimpleAssets::replace_placeholders_for_path(page_path, doc.output)
179
+ end
180
+
181
+
182
+ end
183
+ end
184
+
185
+ Liquid::Template.register_tag('asset', Jekyll::SimpleAssets::PathTag)
186
+ Liquid::Template.register_tag('contenthash', Jekyll::SimpleAssets::ContentHashTag)
@@ -0,0 +1,130 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'css_parser'
4
+ require 'tempfile'
5
+
6
+ module Jekyll
7
+ module SimpleAssets
8
+
9
+
10
+ def self.critical_css_source_files
11
+ @@critical_css_source_files ||= []
12
+ end
13
+
14
+ def self.make_temp_css_files_for_critical (asset)
15
+ SimpleAssets::config['critical_css']['css_files'].each do |path|
16
+ next unless asset.path == path || asset.path == path.sub(/\.css$/, '.scss')
17
+
18
+ f = Tempfile.new('css-source')
19
+ f.write asset.output
20
+ f.close
21
+
22
+ SimpleAssets::critical_css_source_files << { 'file' => f, 'page' => asset }
23
+ end
24
+ end
25
+
26
+ def self.get_html_input_for_critical (doc, site)
27
+ return unless doc.respond_to? '[]'
28
+
29
+ SimpleAssets::config['critical_css']['files'].each do |file|
30
+ next if file['html']
31
+
32
+ page_path = doc.path.sub("#{ site.config['source'] }/", '')
33
+
34
+ next unless page_path == file['input_page_path'] || file['layout'] == doc['layout']
35
+
36
+ file['html'] = doc.output
37
+ end
38
+ end
39
+
40
+ def self.generate_critical_css (site)
41
+ css_files_str = ''
42
+
43
+ SimpleAssets::critical_css_source_files.each do |f|
44
+ css_files_str += "--css #{ f['file'].path } "
45
+
46
+ f['css'] = CssParser::Parser.new
47
+ f['css'].load_string! f['page'].output
48
+ end
49
+
50
+ SimpleAssets::config['critical_css']['files'].each do |file|
51
+ css_path = File.join(site.config['destination'], file['output_file'])
52
+
53
+ html = file['html']
54
+
55
+ critical_cmd = "npx critical #{ css_files_str }"
56
+
57
+ Jekyll.logger.debug("SimpleAssets:", "Running command: #{ critical_cmd }")
58
+
59
+ Open3.popen3(critical_cmd) do |stdin, stdout, stderr, wait_thr|
60
+ stdin.write(html)
61
+ stdin.close
62
+
63
+ err = stderr.read
64
+ unless wait_thr.value.success?
65
+ Jekyll.logger.error("SimpleAssets:", 'Critical:' + err || stdout.read)
66
+
67
+ next
68
+ else
69
+ Jekyll.logger.warn("SimpleAssets:", 'Critical:' + err) if err
70
+ end
71
+
72
+ critical_css_str = stdout.read
73
+
74
+ asset_path = file['output_file'].sub(/^\//, '')
75
+
76
+ base64hash = Digest::MD5.base64digest(critical_css_str)
77
+
78
+ hash = base64hash[0, SimpleAssets::hash_length].gsub(/[+\/]/, '_')
79
+
80
+ SimpleAssets::asset_contenthash_map[asset_path] = hash
81
+
82
+ IO.write(css_path, critical_css_str)
83
+
84
+ site.keep_files << asset_path
85
+
86
+ if file['extract']
87
+ critical_css = CssParser::Parser.new
88
+
89
+ critical_css.load_string! critical_css_str
90
+
91
+ SimpleAssets::critical_css_source_files.each do |f|
92
+ f['css'].each_rule_set do |source_rule_set, source_media_type|
93
+ critical_css.each_rule_set do |critical_rule_set, critical_media_type|
94
+ if critical_rule_set.selectors.join(',') == source_rule_set.selectors.join(',')
95
+ f['css'].remove_rule_set! source_rule_set, source_media_type
96
+ f['extract'] = true
97
+
98
+ break
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
106
+
107
+ SimpleAssets::critical_css_source_files.each do |f|
108
+ f['page'].output = f['css'].to_s if f['extract']
109
+ end
110
+ end
111
+
112
+ def self.resolve_critical_css_content_hashes (site)
113
+ SimpleAssets::critical_css_source_files.each do |source_file|
114
+ page = source_file['page']
115
+ page_path = page.path.sub("#{ site.config['source'] }/", '')
116
+
117
+ SimpleAssets::config['critical_css']['files'].each do |file|
118
+ css_path = File.join(site.config['destination'], file['output_file'])
119
+ content = IO.read(css_path)
120
+
121
+ critical = SimpleAssets::replace_placeholders_for_path(page_path, content)
122
+
123
+ IO.write(css_path, critical)
124
+ end
125
+ end
126
+ end
127
+
128
+
129
+ end
130
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Jekyll
4
4
  module SimpleAssets
5
- VERSION = "0.2.0"
5
+ VERSION = "0.3.1"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jekyll-simple-assets
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sophie Askew
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-05-20 00:00:00.000000000 Z
11
+ date: 2020-06-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: jekyll
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: css_parser
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: bundler
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -47,10 +61,13 @@ extra_rdoc_files: []
47
61
  files:
48
62
  - ".gitignore"
49
63
  - Gemfile
64
+ - Gemfile.lock
50
65
  - LICENSE
51
66
  - README.md
52
67
  - jekyll-simple-assets.gemspec
53
68
  - lib/jekyll-simple-assets.rb
69
+ - lib/jekyll-simple-assets/content-hash.rb
70
+ - lib/jekyll-simple-assets/critical.rb
54
71
  - lib/jekyll-simple-assets/version.rb
55
72
  homepage: https://github.com/syldexiahime/jekyll-simple-assets
56
73
  licenses:
@@ -71,8 +88,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
71
88
  - !ruby/object:Gem::Version
72
89
  version: '0'
73
90
  requirements: []
74
- rubyforge_project:
75
- rubygems_version: 2.7.6
91
+ rubygems_version: 3.1.3
76
92
  signing_key:
77
93
  specification_version: 4
78
94
  summary: Some simple asset utils for jekyll