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 +4 -4
- data/Gemfile.lock +77 -0
- data/README.md +26 -0
- data/jekyll-simple-assets.gemspec +1 -0
- data/lib/jekyll-simple-assets.rb +49 -175
- data/lib/jekyll-simple-assets/content-hash.rb +186 -0
- data/lib/jekyll-simple-assets/critical.rb +130 -0
- data/lib/jekyll-simple-assets/version.rb +1 -1
- metadata +20 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 066a9158d842b14dd87beb951baa1012dc97eb74e68009b97ebce1fc75d114dd
|
4
|
+
data.tar.gz: a78b84504fdff45054e89b9b3f017692460d9c74c3ed0017df0c45d4605f6950
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
```
|
data/lib/jekyll-simple-assets.rb
CHANGED
@@ -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
|
-
|
61
|
-
|
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
|
-
|
70
|
+
Liquid::Template.register_filter(Jekyll::SimpleAssets::SimpleAssetsFilters)
|
115
71
|
|
116
|
-
|
72
|
+
Jekyll::Hooks.register :site, :post_render, priority: :low do |site, payload|
|
73
|
+
Jekyll::SimpleAssets::site(site)
|
117
74
|
|
118
|
-
|
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
|
-
|
77
|
+
potential_assets += site.pages
|
78
|
+
potential_assets += site.static_files
|
124
79
|
|
125
|
-
|
126
|
-
SimpleAssets::page_assets_map[page_path][asset_path][@type] << placeholder
|
127
|
-
end
|
80
|
+
potential_pages = potential_assets
|
128
81
|
|
129
|
-
|
130
|
-
|
131
|
-
|
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
|
-
|
141
|
-
|
142
|
-
|
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
|
-
|
148
|
-
|
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
|
-
|
155
|
-
|
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
|
-
|
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
|
-
|
193
|
-
|
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
|
-
|
215
|
-
|
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
|
-
|
223
|
-
|
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
|
-
|
247
|
-
|
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
|
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.
|
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-
|
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
|
-
|
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
|