klenod-build 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.
- checksums.yaml +7 -0
- data/README.md +29 -0
- data/lib/klenod/build/asset.rb +235 -0
- data/lib/klenod/build/asset_compression.rb +58 -0
- data/lib/klenod/build/asset_generation_queue.rb +50 -0
- data/lib/klenod/build/cli/application.rb +108 -0
- data/lib/klenod/build/cli.rb +3 -0
- data/lib/klenod/build/config.rb +142 -0
- data/lib/klenod/build/context.rb +370 -0
- data/lib/klenod/build/dependency.rb +21 -0
- data/lib/klenod/build/errors.rb +175 -0
- data/lib/klenod/build/filesystem_resolver.rb +147 -0
- data/lib/klenod/build/graph/invalidator.rb +246 -0
- data/lib/klenod/build/graph.rb +864 -0
- data/lib/klenod/build/graphviz.rb +282 -0
- data/lib/klenod/build/hashing.rb +21 -0
- data/lib/klenod/build/invalidation_result.rb +55 -0
- data/lib/klenod/build/load_result.rb +7 -0
- data/lib/klenod/build/loaded_module.rb +38 -0
- data/lib/klenod/build/module_id.rb +100 -0
- data/lib/klenod/build/module_record.rb +22 -0
- data/lib/klenod/build/plugin.rb +35 -0
- data/lib/klenod/build/plugins/class_names_runtime.rb +125 -0
- data/lib/klenod/build/plugins/component_defaults.rb +12 -0
- data/lib/klenod/build/plugins/data_plugin.rb +117 -0
- data/lib/klenod/build/plugins/gem_import_plugin.rb +125 -0
- data/lib/klenod/build/plugins/google_fonts_plugin/font_metrics.json +17687 -0
- data/lib/klenod/build/plugins/google_fonts_plugin/font_metrics.rb +105 -0
- data/lib/klenod/build/plugins/google_fonts_plugin/font_metrics.txt +31 -0
- data/lib/klenod/build/plugins/google_fonts_plugin.rb +387 -0
- data/lib/klenod/build/plugins/haml_plugin/companions.rb +40 -0
- data/lib/klenod/build/plugins/haml_plugin/errors.rb +114 -0
- data/lib/klenod/build/plugins/haml_plugin/helper_source.rb +123 -0
- data/lib/klenod/build/plugins/haml_plugin/parser.rb +85 -0
- data/lib/klenod/build/plugins/haml_plugin/transformer/ruby_builder.rb +1039 -0
- data/lib/klenod/build/plugins/haml_plugin/transformer.rb +766 -0
- data/lib/klenod/build/plugins/haml_plugin.rb +369 -0
- data/lib/klenod/build/plugins/image_plugin.rb +401 -0
- data/lib/klenod/build/plugins/intl_plugin.rb +34 -0
- data/lib/klenod/build/plugins/markdown_compiler.rb +180 -0
- data/lib/klenod/build/plugins/markdown_plugin.rb +161 -0
- data/lib/klenod/build/plugins/router_plugin.rb +942 -0
- data/lib/klenod/build/plugins/ruby_plugin.rb +34 -0
- data/lib/klenod/build/plugins/svg_plugin.rb +197 -0
- data/lib/klenod/build/plugins.rb +22 -0
- data/lib/klenod/build/profiler.rb +79 -0
- data/lib/klenod/build/resolution_error_formatter.rb +42 -0
- data/lib/klenod/build/resolver.rb +95 -0
- data/lib/klenod/build/ruby_import_rewriter.rb +436 -0
- data/lib/klenod/build/source_map/editor.rb +110 -0
- data/lib/klenod/build/source_map/map.rb +168 -0
- data/lib/klenod/build/source_map/vlq.rb +68 -0
- data/lib/klenod/build/source_map.rb +12 -0
- data/lib/klenod/build/transform_result.rb +12 -0
- data/lib/klenod/build/version.rb +7 -0
- data/lib/klenod/build/watched_pattern.rb +11 -0
- data/lib/klenod/build/watcher.rb +141 -0
- data/lib/klenod/build.rb +15 -0
- metadata +310 -0
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
require "toml-rb"
|
|
5
|
+
require "yaml"
|
|
6
|
+
|
|
7
|
+
require_relative "../plugin"
|
|
8
|
+
require_relative "../transform_result"
|
|
9
|
+
|
|
10
|
+
module Klenod
|
|
11
|
+
module Build
|
|
12
|
+
module Plugins
|
|
13
|
+
module DataPlugin
|
|
14
|
+
def self.new(...)
|
|
15
|
+
Plugin.new(...)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
class Plugin < Klenod::Build::Plugin
|
|
19
|
+
def self.extensions(*values)
|
|
20
|
+
const_set(:EXTENSIONS, values.freeze)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def transform(module_id, code, _context)
|
|
24
|
+
return super unless self.class::EXTENSIONS.include?(module_id.extname)
|
|
25
|
+
|
|
26
|
+
data = parse(code)
|
|
27
|
+
TransformResult.new(module_source(data), [], nil, [], [], {data: data})
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def import_value(_resolved_dependency, record, context)
|
|
31
|
+
return nil unless self.class::EXTENSIONS.include?(record.id.extname)
|
|
32
|
+
|
|
33
|
+
context.mods.fetch(record.id).const_get(:Exports)::Default
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def runtime_import_value(_resolved_dependency, record, _context)
|
|
37
|
+
return nil unless self.class::EXTENSIONS.include?(record.id.extname)
|
|
38
|
+
|
|
39
|
+
record.metadata.fetch(:data)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
|
|
44
|
+
def module_source(data)
|
|
45
|
+
<<~RUBY
|
|
46
|
+
Default = #{data.inspect}
|
|
47
|
+
RUBY
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
module JsonPlugin
|
|
53
|
+
def self.new(...)
|
|
54
|
+
Plugin.new(...)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
class Plugin < DataPlugin::Plugin
|
|
58
|
+
extensions ".json"
|
|
59
|
+
|
|
60
|
+
private
|
|
61
|
+
|
|
62
|
+
def parse(code)
|
|
63
|
+
JSON.parse(code)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
module YamlPlugin
|
|
69
|
+
def self.new(...)
|
|
70
|
+
Plugin.new(...)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
class Plugin < DataPlugin::Plugin
|
|
74
|
+
extensions ".yaml", ".yml"
|
|
75
|
+
|
|
76
|
+
private
|
|
77
|
+
|
|
78
|
+
def parse(code)
|
|
79
|
+
YAML.safe_load(code, permitted_classes: [Date, Time, Symbol], aliases: true)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
module TomlPlugin
|
|
85
|
+
def self.new(...)
|
|
86
|
+
Plugin.new(...)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
class Plugin < DataPlugin::Plugin
|
|
90
|
+
extensions ".toml"
|
|
91
|
+
|
|
92
|
+
private
|
|
93
|
+
|
|
94
|
+
def parse(code)
|
|
95
|
+
TomlRB.parse(code)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
module TextPlugin
|
|
101
|
+
def self.new(...)
|
|
102
|
+
Plugin.new(...)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
class Plugin < DataPlugin::Plugin
|
|
106
|
+
extensions ".txt", ".text"
|
|
107
|
+
|
|
108
|
+
private
|
|
109
|
+
|
|
110
|
+
def parse(code)
|
|
111
|
+
code
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../dependency"
|
|
4
|
+
require_relative "../errors"
|
|
5
|
+
require_relative "../filesystem_resolver"
|
|
6
|
+
require_relative "../hashing"
|
|
7
|
+
require_relative "../load_result"
|
|
8
|
+
require_relative "../module_id"
|
|
9
|
+
require_relative "../plugin"
|
|
10
|
+
|
|
11
|
+
module Klenod
|
|
12
|
+
module Build
|
|
13
|
+
module Plugins
|
|
14
|
+
module GemImportPlugin
|
|
15
|
+
def self.new(...)
|
|
16
|
+
Plugin.new(...)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
class Plugin < Klenod::Build::Plugin
|
|
20
|
+
DEFAULT_IMPORT_ROOT = "klenod"
|
|
21
|
+
DEFAULT_EXTENSIONS = [".rb", ".haml"].freeze
|
|
22
|
+
|
|
23
|
+
def initialize(import_root: DEFAULT_IMPORT_ROOT, extensions: DEFAULT_EXTENSIONS)
|
|
24
|
+
@import_root = import_root.to_s.delete_prefix("/")
|
|
25
|
+
@extensions = extensions
|
|
26
|
+
@resolved_paths = {}
|
|
27
|
+
@gem_import_roots = {}
|
|
28
|
+
@filesystem_resolvers = {}
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def resolve(dependency, _context)
|
|
32
|
+
module_id = module_id_for(dependency)
|
|
33
|
+
return nil unless module_id&.scheme == :gem
|
|
34
|
+
|
|
35
|
+
resolved_path = resolve_existing_path(module_id)
|
|
36
|
+
resolved_id = module_id_for_path(module_id, resolved_path)
|
|
37
|
+
ResolvedDependency.new(dependency, resolved_id, {scheme: :gem, path: resolved_path.to_s})
|
|
38
|
+
rescue ResolveError => error
|
|
39
|
+
raise error.with_resolution_context(dependency: dependency, importer_id: dependency.importer_id)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def load(module_id, _context)
|
|
43
|
+
return nil unless module_id.scheme == :gem
|
|
44
|
+
|
|
45
|
+
path = path_for(module_id)
|
|
46
|
+
LoadResult.new(path.binread, Hashing.file_hexdigest(path), nil)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
private
|
|
50
|
+
|
|
51
|
+
def module_id_for(dependency)
|
|
52
|
+
specifier = dependency.specifier.to_s
|
|
53
|
+
if specifier.match?(ModuleId::SCHEME_PATTERN)
|
|
54
|
+
module_id = ModuleId.parse(specifier)
|
|
55
|
+
return nil unless module_id.scheme == :gem
|
|
56
|
+
|
|
57
|
+
module_id
|
|
58
|
+
elsif dependency.importer_id&.scheme == :gem
|
|
59
|
+
dependency.importer_id.merge(specifier)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def resolve_existing_path(module_id)
|
|
64
|
+
@resolved_paths.fetch([module_id.to_s, module_id.query]) do |key|
|
|
65
|
+
path_for(module_id)
|
|
66
|
+
resolved = filesystem_resolver_for(module_id).resolve(module_id.relative_path)
|
|
67
|
+
@resolved_paths[key] = resolved
|
|
68
|
+
end
|
|
69
|
+
rescue ResolveError => error
|
|
70
|
+
raise ResolveError.new(
|
|
71
|
+
error.resolution_failure? ? nil : error.message,
|
|
72
|
+
unresolved_path: module_id.to_s,
|
|
73
|
+
reason: error.reason,
|
|
74
|
+
requested_specifier: error.requested_specifier,
|
|
75
|
+
suggestions: error.suggestions
|
|
76
|
+
)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def path_for(module_id)
|
|
80
|
+
raise ResolveError, "Gem import requires a gem name in #{module_id}" if module_id.host.to_s.empty?
|
|
81
|
+
|
|
82
|
+
import_root = import_root_for(module_id.host)
|
|
83
|
+
path = Pathname.new(File.expand_path(module_id.relative_path, import_root))
|
|
84
|
+
assert_inside_import_root!(module_id, import_root, path)
|
|
85
|
+
path
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def import_root_for(gem_name)
|
|
89
|
+
@gem_import_roots.fetch(gem_name) do
|
|
90
|
+
spec = Gem::Specification.find_by_name(gem_name)
|
|
91
|
+
@gem_import_roots[gem_name] = Pathname.new(File.expand_path(@import_root, spec.full_gem_path))
|
|
92
|
+
end
|
|
93
|
+
rescue Gem::LoadError => error
|
|
94
|
+
raise ResolveError, "Could not find gem #{gem_name.inspect}: #{error.message}"
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def filesystem_resolver_for(module_id)
|
|
98
|
+
@filesystem_resolvers.fetch(module_id.host) do |gem_name|
|
|
99
|
+
@filesystem_resolvers[gem_name] =
|
|
100
|
+
FilesystemResolver.new(
|
|
101
|
+
root: import_root_for(gem_name),
|
|
102
|
+
extensions: @extensions,
|
|
103
|
+
path_prefix: "gem://#{gem_name}/"
|
|
104
|
+
)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def assert_inside_import_root!(module_id, import_root, path)
|
|
109
|
+
import_root_path = import_root.to_s
|
|
110
|
+
expanded = path.to_s
|
|
111
|
+
return if expanded == import_root_path || expanded.start_with?("#{import_root_path}/")
|
|
112
|
+
|
|
113
|
+
raise ResolveError, "Gem import escapes import root: #{module_id}"
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def module_id_for_path(module_id, path)
|
|
117
|
+
import_root = import_root_for(module_id.host)
|
|
118
|
+
relative = path.relative_path_from(import_root).to_s
|
|
119
|
+
ModuleId.new("gem://#{module_id.host}/#{relative}", module_id.query)
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|