jekyll-minify-js 0.1.1 → 0.2.11
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/README.md +130 -0
- data/assets/index.js +30131 -0
- data/lib/jekyll-minify-js.rb +116 -91
- data/lib/version.rb +11 -0
- metadata +18 -54
data/lib/jekyll-minify-js.rb
CHANGED
|
@@ -1,109 +1,134 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
4
|
-
require
|
|
5
|
-
require
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
# terser gem not available; plugin will fallback to external CLI or copy
|
|
10
|
-
end
|
|
11
|
-
require 'pathname'
|
|
3
|
+
require "jekyll"
|
|
4
|
+
require "json"
|
|
5
|
+
require "open3"
|
|
6
|
+
require "pathname"
|
|
7
|
+
|
|
8
|
+
require_relative "version"
|
|
12
9
|
|
|
13
|
-
# module Jekyll
|
|
14
10
|
module Jekyll
|
|
15
|
-
#
|
|
16
|
-
#
|
|
17
|
-
#
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
11
|
+
# Minifies JavaScript assets after Jekyll finishes writing the site.
|
|
12
|
+
#
|
|
13
|
+
# The plugin reads files from a configured entry directory, invokes the
|
|
14
|
+
# bundled Node-based terser wrapper, and writes the compiled assets into the
|
|
15
|
+
# destination site output.
|
|
16
|
+
module MinifyJs
|
|
17
|
+
# Runs JavaScript minification from Jekyll's post-write lifecycle.
|
|
18
|
+
#
|
|
19
|
+
# The generator itself does not perform work during the normal generation
|
|
20
|
+
# phase. Instead, {run} is invoked from a `:post_write` hook so Jekyll does
|
|
21
|
+
# not overwrite the generated minified files.
|
|
22
|
+
class TerserGenerator < Jekyll::Generator
|
|
23
|
+
safe true
|
|
24
|
+
priority :low
|
|
21
25
|
|
|
22
|
-
|
|
23
|
-
#
|
|
24
|
-
|
|
26
|
+
# Declares the generator without doing work during the normal build phase.
|
|
27
|
+
#
|
|
28
|
+
# @param _site [Jekyll::Site] the site being generated
|
|
29
|
+
# @return [void]
|
|
30
|
+
def generate(_site)
|
|
31
|
+
# Work is done in the :post_write hook to avoid Jekyll overwriting outputs.
|
|
32
|
+
end
|
|
25
33
|
|
|
26
|
-
|
|
27
|
-
#
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
+
# Merges the plugin configuration with defaults.
|
|
35
|
+
#
|
|
36
|
+
# @param site [Jekyll::Site] the current site instance
|
|
37
|
+
# @return [Hash] the merged `minify_js` configuration
|
|
38
|
+
def self.minify_js_config(site)
|
|
39
|
+
default_config = {
|
|
40
|
+
"enabled" => true,
|
|
41
|
+
"entry_dir" => "js",
|
|
42
|
+
"output_dir" => "js",
|
|
43
|
+
"terser_opts" => {
|
|
44
|
+
"source_map" => true,
|
|
45
|
+
"compress" => true
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
site.config["minify_js"] = default_config.merge(site.config["minify_js"] || {})
|
|
49
|
+
end
|
|
34
50
|
|
|
35
|
-
#
|
|
36
|
-
|
|
37
|
-
|
|
51
|
+
# Runs the Node-based terser wrapper for one JavaScript source string.
|
|
52
|
+
#
|
|
53
|
+
# @param code [String] the JavaScript source to minify
|
|
54
|
+
# @param ts_opts [Hash, nil] terser options passed to the wrapper
|
|
55
|
+
# @return [Hash] the parsed JSON response from the wrapper
|
|
56
|
+
# @raise [RuntimeError] if the wrapper process exits unsuccessfully
|
|
57
|
+
def self.run_terser(code, ts_opts)
|
|
58
|
+
script_path = File.expand_path("../assets/index.js", __dir__)
|
|
59
|
+
input = JSON.generate({
|
|
60
|
+
code: code,
|
|
61
|
+
opts: ts_opts
|
|
62
|
+
}.compact)
|
|
63
|
+
stdout, stderr, status = Open3.capture3("node", script_path, stdin_data: input)
|
|
64
|
+
raise "Minify JS failed: #{stderr}" unless status.success?
|
|
38
65
|
|
|
39
|
-
|
|
40
|
-
|
|
66
|
+
JSON.parse(stdout)
|
|
67
|
+
end
|
|
41
68
|
|
|
42
|
-
|
|
69
|
+
# Finds JavaScript files in the configured entry directory.
|
|
70
|
+
#
|
|
71
|
+
# @param site [Jekyll::Site] the current site instance
|
|
72
|
+
# @param entry [String, nil] the source directory relative to `site.source`
|
|
73
|
+
# @return [Array<String>, nil] matching absolute file paths, or `nil` when
|
|
74
|
+
# no entry directory is configured or no files are found
|
|
75
|
+
def self.entry_js_files(site, entry)
|
|
76
|
+
entry_full = File.join(site.source, entry)
|
|
77
|
+
js_files = Dir.glob(File.join(entry_full, "**", "*.js"))
|
|
78
|
+
if Dir.exist?(entry_full) && js_files.empty?
|
|
79
|
+
Jekyll.logger.warn "MinifyJs:",
|
|
80
|
+
"No JavaScript files found in #{entry_full}."
|
|
81
|
+
end
|
|
82
|
+
return if entry.nil? || js_files.empty?
|
|
43
83
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
mangle_opt = cfg.fetch('mangle', true)
|
|
47
|
-
source_map_enabled = cfg.fetch('source_map', true)
|
|
48
|
-
exclude_patterns = cfg.fetch('exclude', ['**/*.min.js'])
|
|
84
|
+
js_files
|
|
85
|
+
end
|
|
49
86
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
87
|
+
# Resolves the output directory for minified assets.
|
|
88
|
+
#
|
|
89
|
+
# @param site [Jekyll::Site] the current site instance
|
|
90
|
+
# @param out [String, nil] the configured output directory
|
|
91
|
+
# @param entry [String] the configured entry directory
|
|
92
|
+
# @return [String] the absolute destination directory inside `site.dest`
|
|
93
|
+
def self.output_dir(site, out, entry)
|
|
94
|
+
out ? File.join(site.dest, out) : File.join(site.dest, entry)
|
|
95
|
+
end
|
|
56
96
|
|
|
57
|
-
|
|
58
|
-
|
|
97
|
+
# Minifies every JavaScript file configured for the site.
|
|
98
|
+
#
|
|
99
|
+
# Files are written into the resolved output directory. If minification of
|
|
100
|
+
# an individual file fails, the original file is copied instead.
|
|
101
|
+
#
|
|
102
|
+
# @param site [Jekyll::Site] the current site instance
|
|
103
|
+
# @return [void]
|
|
104
|
+
def self.run(site) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
|
|
105
|
+
Jekyll.logger.info "Running jekyll-minify-js v#{Jekyll::MinifyJs::VERSION}"
|
|
106
|
+
mini_js_config = minify_js_config(site)
|
|
107
|
+
entry_dir = mini_js_config["entry_dir"]
|
|
108
|
+
nil if (mini_js_config["enable"] && mini_js_config["enable"] == false) || entry_dir.nil?
|
|
109
|
+
out_dir = output_dir(site, mini_js_config["output_dir"], entry_dir)
|
|
110
|
+
ts_opts = mini_js_config["terser_opts"]
|
|
111
|
+
entry_dir_full = File.join(site.source, entry_dir)
|
|
112
|
+
js_files = entry_js_files(site, entry_dir)
|
|
59
113
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
else
|
|
73
|
-
compiled = Terser.compile(src_content, options)
|
|
74
|
-
map = nil
|
|
75
|
-
end
|
|
76
|
-
compiled += "\n//# sourceMappingURL=#{map_name}\n" unless compiled.include?('sourceMappingURL')
|
|
77
|
-
File.write(out, compiled)
|
|
78
|
-
File.write("#{out}.map", map) if map
|
|
79
|
-
rescue StandardError => e
|
|
80
|
-
Jekyll.logger.warn 'Terser:', "ruby terser failed for #{rel}: #{e.message}; copying original"
|
|
81
|
-
FileUtils.cp(src, out)
|
|
82
|
-
end
|
|
83
|
-
else
|
|
84
|
-
terser_cmd = new.detect_terser_cmd
|
|
85
|
-
if terser_cmd
|
|
86
|
-
cmd = %(#{terser_cmd} #{Shellwords.escape(src)} --compress --mangle -o #{Shellwords.escape(out)} --source-map "url='#{map_name}',includeSources") # rubocop:disable Layout/LineLength
|
|
87
|
-
Jekyll.logger.info 'Terser:', "minifying #{rel} via external terser"
|
|
88
|
-
success = system(cmd)
|
|
89
|
-
unless success && File.exist?(out)
|
|
90
|
-
Jekyll.logger.warn 'Terser:', "minify failed for #{rel}; copying original"
|
|
91
|
-
FileUtils.cp(src, out)
|
|
92
|
-
end
|
|
93
|
-
else
|
|
94
|
-
Jekyll.logger.warn 'Terser:', 'no terser available — copying original JS'
|
|
95
|
-
FileUtils.cp(src, out)
|
|
96
|
-
end
|
|
114
|
+
js_files.each do |src|
|
|
115
|
+
rel = src.sub(/\A#{Regexp.escape(entry_dir_full + File::SEPARATOR)}/, "")
|
|
116
|
+
out = File.join(out_dir, rel)
|
|
117
|
+
src_content = File.read(src)
|
|
118
|
+
result = run_terser(src_content, ts_opts)
|
|
119
|
+
compiled = result["compiled"]
|
|
120
|
+
source_map = result["source_map"]
|
|
121
|
+
File.write(out, compiled)
|
|
122
|
+
File.write("#{out}.map", source_map) if source_map
|
|
123
|
+
rescue StandardError => e
|
|
124
|
+
Jekyll.logger.warn "jekyll-minify-js:", "failed to minify for #{rel}: #{e.message}; copying original"
|
|
125
|
+
FileUtils.cp(src, out)
|
|
97
126
|
end
|
|
98
127
|
end
|
|
99
128
|
end
|
|
100
|
-
|
|
101
|
-
def detect_terser_cmd
|
|
102
|
-
# Prefer the bundler-installed terser (from the `terser` gem) via `bundle exec terser`.
|
|
103
|
-
return 'bundle exec terser' if system('bundle exec terser --version > /dev/null 2>&1')
|
|
104
|
-
return 'terser' if system('terser --version > /dev/null 2>&1')
|
|
105
|
-
|
|
106
|
-
nil
|
|
107
|
-
end
|
|
108
129
|
end
|
|
109
130
|
end
|
|
131
|
+
|
|
132
|
+
Jekyll::Hooks.register :site, :post_write do |site|
|
|
133
|
+
Jekyll::MinifyJs::TerserGenerator.run(site)
|
|
134
|
+
end
|
data/lib/version.rb
ADDED
metadata
CHANGED
|
@@ -1,28 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: jekyll-minify-js
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.11
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
|
-
-
|
|
7
|
+
- phothinmg
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
|
-
- !ruby/object:Gem::Dependency
|
|
13
|
-
name: fileutils
|
|
14
|
-
requirement: !ruby/object:Gem::Requirement
|
|
15
|
-
requirements:
|
|
16
|
-
- - "~>"
|
|
17
|
-
- !ruby/object:Gem::Version
|
|
18
|
-
version: '1.8'
|
|
19
|
-
type: :runtime
|
|
20
|
-
prerelease: false
|
|
21
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
-
requirements:
|
|
23
|
-
- - "~>"
|
|
24
|
-
- !ruby/object:Gem::Version
|
|
25
|
-
version: '1.8'
|
|
26
12
|
- !ruby/object:Gem::Dependency
|
|
27
13
|
name: jekyll
|
|
28
14
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -38,58 +24,36 @@ dependencies:
|
|
|
38
24
|
- !ruby/object:Gem::Version
|
|
39
25
|
version: '4.4'
|
|
40
26
|
- !ruby/object:Gem::Dependency
|
|
41
|
-
name:
|
|
27
|
+
name: open3
|
|
42
28
|
requirement: !ruby/object:Gem::Requirement
|
|
43
29
|
requirements:
|
|
44
|
-
- - "
|
|
30
|
+
- - ">="
|
|
45
31
|
- !ruby/object:Gem::Version
|
|
46
|
-
version: 0.
|
|
32
|
+
version: 0.2.1
|
|
47
33
|
type: :runtime
|
|
48
34
|
prerelease: false
|
|
49
35
|
version_requirements: !ruby/object:Gem::Requirement
|
|
50
36
|
requirements:
|
|
51
|
-
- - "
|
|
52
|
-
- !ruby/object:Gem::Version
|
|
53
|
-
version: 0.4.0
|
|
54
|
-
- !ruby/object:Gem::Dependency
|
|
55
|
-
name: shellwords
|
|
56
|
-
requirement: !ruby/object:Gem::Requirement
|
|
57
|
-
requirements:
|
|
58
|
-
- - "~>"
|
|
59
|
-
- !ruby/object:Gem::Version
|
|
60
|
-
version: 0.2.2
|
|
61
|
-
type: :runtime
|
|
62
|
-
prerelease: false
|
|
63
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
-
requirements:
|
|
65
|
-
- - "~>"
|
|
66
|
-
- !ruby/object:Gem::Version
|
|
67
|
-
version: 0.2.2
|
|
68
|
-
- !ruby/object:Gem::Dependency
|
|
69
|
-
name: terser
|
|
70
|
-
requirement: !ruby/object:Gem::Requirement
|
|
71
|
-
requirements:
|
|
72
|
-
- - "~>"
|
|
73
|
-
- !ruby/object:Gem::Version
|
|
74
|
-
version: '1.2'
|
|
75
|
-
type: :runtime
|
|
76
|
-
prerelease: false
|
|
77
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
-
requirements:
|
|
79
|
-
- - "~>"
|
|
37
|
+
- - ">="
|
|
80
38
|
- !ruby/object:Gem::Version
|
|
81
|
-
version:
|
|
82
|
-
email:
|
|
39
|
+
version: 0.2.1
|
|
40
|
+
email:
|
|
41
|
+
- phothinmg@disroot.org
|
|
83
42
|
executables: []
|
|
84
43
|
extensions: []
|
|
85
44
|
extra_rdoc_files: []
|
|
86
45
|
files:
|
|
87
46
|
- LICENSE.txt
|
|
47
|
+
- README.md
|
|
48
|
+
- assets/index.js
|
|
88
49
|
- lib/jekyll-minify-js.rb
|
|
89
|
-
|
|
50
|
+
- lib/version.rb
|
|
51
|
+
homepage: https://github.com/phothinmg/jekyll-minify-js
|
|
90
52
|
licenses:
|
|
91
53
|
- MIT
|
|
92
54
|
metadata:
|
|
55
|
+
homepage_uri: https://github.com/phothinmg/jekyll-minify-js
|
|
56
|
+
changelog_uri: https://github.com/phothinmg/jekyll-minify-js/blob/main/CHANGELOG.md
|
|
93
57
|
rubygems_mfa_required: 'true'
|
|
94
58
|
rdoc_options: []
|
|
95
59
|
require_paths:
|
|
@@ -98,14 +62,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
98
62
|
requirements:
|
|
99
63
|
- - ">="
|
|
100
64
|
- !ruby/object:Gem::Version
|
|
101
|
-
version:
|
|
65
|
+
version: 3.2.0
|
|
102
66
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
103
67
|
requirements:
|
|
104
68
|
- - ">="
|
|
105
69
|
- !ruby/object:Gem::Version
|
|
106
70
|
version: '0'
|
|
107
71
|
requirements: []
|
|
108
|
-
rubygems_version: 4.0.
|
|
72
|
+
rubygems_version: 4.0.15
|
|
109
73
|
specification_version: 4
|
|
110
|
-
summary: Jekyll plugin for Minify Js
|
|
74
|
+
summary: Jekyll plugin for Minify Js
|
|
111
75
|
test_files: []
|