darkroom 0.0.3 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE +1 -1
- data/README.md +127 -41
- data/VERSION +1 -1
- data/lib/darkroom/asset.rb +253 -100
- data/lib/darkroom/darkroom.rb +60 -13
- data/lib/darkroom/delegates/css.rb +39 -0
- data/lib/darkroom/delegates/html.rb +53 -0
- data/lib/darkroom/delegates/htx.rb +21 -0
- data/lib/darkroom/delegates/javascript.rb +14 -0
- data/lib/darkroom/errors/asset_error.rb +33 -0
- data/lib/darkroom/errors/asset_not_found_error.rb +10 -21
- data/lib/darkroom/errors/circular_reference_error.rb +21 -0
- data/lib/darkroom/errors/duplicate_asset_error.rb +4 -4
- data/lib/darkroom/errors/invalid_path_error.rb +28 -0
- data/lib/darkroom/errors/missing_library_error.rb +3 -3
- data/lib/darkroom/errors/unrecognized_extension_error.rb +21 -0
- data/lib/darkroom/version.rb +1 -1
- data/lib/darkroom.rb +16 -32
- metadata +11 -4
- data/lib/darkroom/errors/spec_not_defined_error.rb +0 -28
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative('../asset')
|
4
|
+
|
5
|
+
class Darkroom
|
6
|
+
class Asset
|
7
|
+
##
|
8
|
+
# Delegate for CSS assets.
|
9
|
+
#
|
10
|
+
CSSDelegate = Delegate.new(
|
11
|
+
content_type: 'text/css',
|
12
|
+
import_regex: /^ *@import +#{QUOTED_PATH.source} *; *(\n|$)/.freeze,
|
13
|
+
reference_regex: /url\(\s*#{REFERENCE_PATH.source}\s*\)/x.freeze,
|
14
|
+
|
15
|
+
validate_reference: ->(asset, match, format) do
|
16
|
+
if format == 'displace'
|
17
|
+
'Cannot displace in CSS files'
|
18
|
+
elsif !asset.image? && !asset.font?
|
19
|
+
'Referenced asset must be an image or font type'
|
20
|
+
end
|
21
|
+
end,
|
22
|
+
|
23
|
+
reference_content: ->(asset, match, format) do
|
24
|
+
if format == 'utf8'
|
25
|
+
content = asset.content.gsub('#', '%23')
|
26
|
+
content.gsub!(/(['"])/, '\\\\\1')
|
27
|
+
content.gsub!("\n", "\\\n")
|
28
|
+
|
29
|
+
content
|
30
|
+
end
|
31
|
+
end,
|
32
|
+
|
33
|
+
minify_lib: 'sassc',
|
34
|
+
minify: ->(content) do
|
35
|
+
SassC::Engine.new(content, style: :compressed).render
|
36
|
+
end,
|
37
|
+
)
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative('../asset')
|
4
|
+
|
5
|
+
class Darkroom
|
6
|
+
class Asset
|
7
|
+
HTMLDelegate = Delegate.new(
|
8
|
+
content_type: 'text/html',
|
9
|
+
reference_regex: %r{
|
10
|
+
<(?<tag>a|area|audio|base|embed|iframe|img|input|link|script|source|track|video)\s+[^>]*
|
11
|
+
(?<attr>href|src)=#{REFERENCE_PATH.source}[^>]*>
|
12
|
+
}x.freeze,
|
13
|
+
|
14
|
+
validate_reference: ->(asset, match, format) do
|
15
|
+
return unless format == 'displace'
|
16
|
+
|
17
|
+
if match[:tag] == 'link'
|
18
|
+
'Asset type must be text/css' unless asset.content_type == 'text/css'
|
19
|
+
elsif match[:tag] == 'script'
|
20
|
+
'Asset type must be text/javascript' unless asset.content_type == 'text/javascript'
|
21
|
+
elsif match[:tag] == 'img'
|
22
|
+
'Asset type must be image/svg+xml' unless asset.content_type == 'image/svg+xml'
|
23
|
+
else
|
24
|
+
"Cannot displace <#{match[:tag]}> tags"
|
25
|
+
end
|
26
|
+
end,
|
27
|
+
|
28
|
+
reference_content: ->(asset, match, format) do
|
29
|
+
case format
|
30
|
+
when 'displace'
|
31
|
+
if match[:tag] == 'link' && asset.content_type == 'text/css'
|
32
|
+
"<style>#{asset.content}</style>"
|
33
|
+
elsif match[:tag] == 'script' && asset.content_type == 'text/javascript'
|
34
|
+
offset = match.begin(0)
|
35
|
+
|
36
|
+
"#{match[0][0..(match.begin(:attr) - 2 - offset)]}"\
|
37
|
+
"#{match[0][(match.end(:quoted) + match[:quote].size - offset)..(match.end(0) - offset)]}"\
|
38
|
+
"#{asset.content}"
|
39
|
+
elsif match[:tag] == 'img' && asset.content_type == 'image/svg+xml'
|
40
|
+
asset.content
|
41
|
+
end
|
42
|
+
when 'utf8'
|
43
|
+
quote = match[:quote] == '' ? Asset::DEFAULT_QUOTE : match[:quote]
|
44
|
+
|
45
|
+
content = asset.content.gsub('#', '%23')
|
46
|
+
content.gsub!(quote, quote == "'" ? '"' : "'")
|
47
|
+
|
48
|
+
content
|
49
|
+
end
|
50
|
+
end,
|
51
|
+
)
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative('../asset')
|
4
|
+
require_relative('html')
|
5
|
+
require_relative('javascript')
|
6
|
+
|
7
|
+
class Darkroom
|
8
|
+
class Asset
|
9
|
+
HTXDelegate = Delegate.new(
|
10
|
+
content_type: JavaScriptDelegate.content_type,
|
11
|
+
import_regex: HTMLDelegate.import_regex,
|
12
|
+
reference_regex: HTMLDelegate.reference_regex,
|
13
|
+
validate_reference: HTMLDelegate.validate_reference,
|
14
|
+
reference_content: HTMLDelegate.reference_content,
|
15
|
+
compile_lib: 'htx',
|
16
|
+
compile: ->(path, content) { HTX.compile(path, content) },
|
17
|
+
minify_lib: JavaScriptDelegate.minify_lib,
|
18
|
+
minify: JavaScriptDelegate.minify,
|
19
|
+
)
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative('../asset')
|
4
|
+
|
5
|
+
class Darkroom
|
6
|
+
class Asset
|
7
|
+
JavaScriptDelegate = Delegate.new(
|
8
|
+
content_type: 'text/javascript',
|
9
|
+
import_regex: /^ *import +#{QUOTED_PATH.source} *;? *(\n|$)/.freeze,
|
10
|
+
minify_lib: 'terser',
|
11
|
+
minify: ->(content) { Terser.compile(content) },
|
12
|
+
)
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Darkroom
|
4
|
+
##
|
5
|
+
# General error class used for errors encountered while processing an asset.
|
6
|
+
#
|
7
|
+
class AssetError < StandardError
|
8
|
+
attr_reader(:detail, :source_path, :source_line_num)
|
9
|
+
|
10
|
+
##
|
11
|
+
# Creates a new instance.
|
12
|
+
#
|
13
|
+
# * +message+ - Description of the error.
|
14
|
+
# * +detail+ - Additional detail about the error.
|
15
|
+
# * +source_path+ - Path of the asset that contains the error (optional).
|
16
|
+
# * +source_line_num+ - Line number in the asset where the error is located (optional).
|
17
|
+
#
|
18
|
+
def initialize(message, detail, source_path = nil, source_line_num = nil)
|
19
|
+
super(message)
|
20
|
+
|
21
|
+
@detail = detail
|
22
|
+
@source_path = source_path
|
23
|
+
@source_line_num = source_line_num
|
24
|
+
end
|
25
|
+
|
26
|
+
##
|
27
|
+
# Returns a string representation of the error.
|
28
|
+
#
|
29
|
+
def to_s
|
30
|
+
"#{"#{@source_path}:#{@source_line_num || '?'}: " if @source_path}#{super}: #{@detail}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -1,33 +1,22 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative('asset_error')
|
4
|
+
|
3
5
|
class Darkroom
|
4
6
|
##
|
5
|
-
# Error class used when an asset requested explicitly or specified as a dependency of another
|
6
|
-
#
|
7
|
+
# Error class used when an asset requested explicitly or specified as a dependency of another doesn't
|
8
|
+
# exist.
|
7
9
|
#
|
8
|
-
class AssetNotFoundError <
|
9
|
-
attr_reader(:path, :referenced_from, :referenced_from_line)
|
10
|
-
|
10
|
+
class AssetNotFoundError < AssetError
|
11
11
|
##
|
12
12
|
# Creates a new instance.
|
13
13
|
#
|
14
|
-
# * +path+ -
|
15
|
-
# * +
|
16
|
-
# * +
|
17
|
-
#
|
18
|
-
def initialize(path, referenced_from = nil, referenced_from_line = nil)
|
19
|
-
@path = path
|
20
|
-
@referenced_from = referenced_from
|
21
|
-
@referenced_from_line = referenced_from_line
|
22
|
-
end
|
23
|
-
|
24
|
-
##
|
25
|
-
# Returns a string representation of the error.
|
14
|
+
# * +path+ - Path of asset that doesn't exist.
|
15
|
+
# * +source_path+ - Path of the asset that contains the error (optional).
|
16
|
+
# * +source_line_num+ - Line number in the asset where the error is located (optional).
|
26
17
|
#
|
27
|
-
def
|
28
|
-
|
29
|
-
" (referenced from #{@referenced_from}:#{@referenced_from_line || '?'})" if @referenced_from
|
30
|
-
}: #{@path}"
|
18
|
+
def initialize(path, source_path = nil, source_line_num = nil)
|
19
|
+
super('Asset not found', path, source_path, source_line_num)
|
31
20
|
end
|
32
21
|
end
|
33
22
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative('asset_error')
|
4
|
+
|
5
|
+
class Darkroom
|
6
|
+
##
|
7
|
+
# Error class used when an asset reference results in a circular reference chain.
|
8
|
+
#
|
9
|
+
class CircularReferenceError < AssetError
|
10
|
+
##
|
11
|
+
# Creates a new instance.
|
12
|
+
#
|
13
|
+
# * +snippet+ - Snippet showing the reference.
|
14
|
+
# * +source_path+ - Path of the asset that contains the error.
|
15
|
+
# * +source_line_num+ - Line number in the asset where the error is located.
|
16
|
+
#
|
17
|
+
def initialize(snippet, source_path, source_line_num)
|
18
|
+
super('Reference would result in a circular reference chain', snippet, source_path, source_line_num)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
class Darkroom
|
4
4
|
##
|
5
|
-
# Error class used when an asset exists
|
5
|
+
# Error class used when an asset exists under multiple load paths.
|
6
6
|
#
|
7
7
|
class DuplicateAssetError < StandardError
|
8
8
|
attr_reader(:path, :first_load_path, :second_load_path)
|
@@ -10,9 +10,9 @@ class Darkroom
|
|
10
10
|
##
|
11
11
|
# Creates a new instance.
|
12
12
|
#
|
13
|
-
# * +path+ -
|
14
|
-
# * +first_load_path+ -
|
15
|
-
# * +second_load_path+ -
|
13
|
+
# * +path+ - Path of the asset that exists under multiple load paths.
|
14
|
+
# * +first_load_path+ - Load path where the asset was first found.
|
15
|
+
# * +second_load_path+ - Load path where the asset was subsequently found.
|
16
16
|
#
|
17
17
|
def initialize(path, first_load_path, second_load_path)
|
18
18
|
@path = path
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Darkroom
|
4
|
+
##
|
5
|
+
# Error class used when an asset's path contains one or more invalid characters.
|
6
|
+
#
|
7
|
+
class InvalidPathError < StandardError
|
8
|
+
attr_reader(:path, :index)
|
9
|
+
|
10
|
+
##
|
11
|
+
# Creates a new instance.
|
12
|
+
#
|
13
|
+
# * +path+ - Path of the asset with the invalid character(s).
|
14
|
+
# * +index+ - Position of the first bad character in the path.
|
15
|
+
#
|
16
|
+
def initialize(path, index)
|
17
|
+
@path = path
|
18
|
+
@index = index
|
19
|
+
end
|
20
|
+
|
21
|
+
##
|
22
|
+
# Returns a string representation of the error.
|
23
|
+
#
|
24
|
+
def to_s
|
25
|
+
"Asset path contains one or more invalid characters (#{DISALLOWED_PATH_CHARS}): #{@path}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -10,9 +10,9 @@ class Darkroom
|
|
10
10
|
##
|
11
11
|
# Creates a new instance.
|
12
12
|
#
|
13
|
-
# * +library+ -
|
14
|
-
# * +need+ -
|
15
|
-
# * +extension+ -
|
13
|
+
# * +library+ - Name of the library that's missing.
|
14
|
+
# * +need+ - Reason the library is needed ('compile' or 'minify').
|
15
|
+
# * +extension+ - Extension of the type of asset that needs the library.
|
16
16
|
#
|
17
17
|
def initialize(library, need, extension)
|
18
18
|
@library = library
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative('asset_error')
|
4
|
+
|
5
|
+
class Darkroom
|
6
|
+
##
|
7
|
+
# Error class used when a reference is made to a file with an unrecognized extension.
|
8
|
+
#
|
9
|
+
class UnrecognizedExtensionError < AssetError
|
10
|
+
##
|
11
|
+
# Creates a new instance.
|
12
|
+
#
|
13
|
+
# * +file+ - File with the unrecognized extension.
|
14
|
+
# * +source_path+ - Path of the asset that contains the error (optional).
|
15
|
+
# * +source_line_num+ - Line number in the asset where the error is located (optional).
|
16
|
+
#
|
17
|
+
def initialize(file, source_path = nil, source_line_num = nil)
|
18
|
+
super('File extension not recognized', file, source_path, source_line_num)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/darkroom/version.rb
CHANGED
data/lib/darkroom.rb
CHANGED
@@ -4,36 +4,20 @@ require('darkroom/asset')
|
|
4
4
|
require('darkroom/darkroom')
|
5
5
|
require('darkroom/version')
|
6
6
|
|
7
|
-
require('darkroom/
|
8
|
-
require('darkroom/
|
9
|
-
require('darkroom/
|
10
|
-
require('darkroom/
|
11
|
-
require('darkroom/errors/spec_not_defined_error')
|
7
|
+
require('darkroom/delegates/css')
|
8
|
+
require('darkroom/delegates/html')
|
9
|
+
require('darkroom/delegates/htx')
|
10
|
+
require('darkroom/delegates/javascript')
|
12
11
|
|
13
|
-
Darkroom
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
)
|
18
|
-
|
19
|
-
Darkroom
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
)
|
24
|
-
|
25
|
-
Darkroom::Asset.add_spec('.htx', 'application/javascript',
|
26
|
-
compile: -> (path, content) { HTX.compile(path, content) },
|
27
|
-
compile_lib: 'htx',
|
28
|
-
minify: Darkroom::Asset.spec('.js').minify,
|
29
|
-
minify_lib: Darkroom::Asset.spec('.js').minify_lib,
|
30
|
-
)
|
31
|
-
|
32
|
-
Darkroom::Asset.add_spec('.htm', '.html', 'text/html')
|
33
|
-
Darkroom::Asset.add_spec('.ico', 'image/x-icon')
|
34
|
-
Darkroom::Asset.add_spec('.jpg', '.jpeg', 'image/jpeg')
|
35
|
-
Darkroom::Asset.add_spec('.png', 'image/png')
|
36
|
-
Darkroom::Asset.add_spec('.svg', 'image/svg+xml')
|
37
|
-
Darkroom::Asset.add_spec('.txt', 'text/plain')
|
38
|
-
Darkroom::Asset.add_spec('.woff', 'font/woff')
|
39
|
-
Darkroom::Asset.add_spec('.woff2', 'font/woff2')
|
12
|
+
Darkroom.register('.css', Darkroom::Asset::CSSDelegate)
|
13
|
+
Darkroom.register('.htm', '.html', Darkroom::Asset::HTMLDelegate)
|
14
|
+
Darkroom.register('.htx', Darkroom::Asset::HTXDelegate)
|
15
|
+
Darkroom.register('.ico', 'image/x-icon')
|
16
|
+
Darkroom.register('.jpg', '.jpeg', 'image/jpeg')
|
17
|
+
Darkroom.register('.js', Darkroom::Asset::JavaScriptDelegate)
|
18
|
+
Darkroom.register('.json', 'application/json')
|
19
|
+
Darkroom.register('.png', 'image/png')
|
20
|
+
Darkroom.register('.svg', 'image/svg+xml')
|
21
|
+
Darkroom.register('.txt', 'text/plain')
|
22
|
+
Darkroom.register('.woff', 'font/woff')
|
23
|
+
Darkroom.register('.woff2', 'font/woff2')
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: darkroom
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nate Pickens
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-05-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -59,11 +59,18 @@ files:
|
|
59
59
|
- lib/darkroom.rb
|
60
60
|
- lib/darkroom/asset.rb
|
61
61
|
- lib/darkroom/darkroom.rb
|
62
|
+
- lib/darkroom/delegates/css.rb
|
63
|
+
- lib/darkroom/delegates/html.rb
|
64
|
+
- lib/darkroom/delegates/htx.rb
|
65
|
+
- lib/darkroom/delegates/javascript.rb
|
66
|
+
- lib/darkroom/errors/asset_error.rb
|
62
67
|
- lib/darkroom/errors/asset_not_found_error.rb
|
68
|
+
- lib/darkroom/errors/circular_reference_error.rb
|
63
69
|
- lib/darkroom/errors/duplicate_asset_error.rb
|
70
|
+
- lib/darkroom/errors/invalid_path_error.rb
|
64
71
|
- lib/darkroom/errors/missing_library_error.rb
|
65
72
|
- lib/darkroom/errors/processing_error.rb
|
66
|
-
- lib/darkroom/errors/
|
73
|
+
- lib/darkroom/errors/unrecognized_extension_error.rb
|
67
74
|
- lib/darkroom/version.rb
|
68
75
|
homepage: https://github.com/npickens/darkroom
|
69
76
|
licenses:
|
@@ -87,7 +94,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
87
94
|
- !ruby/object:Gem::Version
|
88
95
|
version: '0'
|
89
96
|
requirements: []
|
90
|
-
rubygems_version: 3.2.
|
97
|
+
rubygems_version: 3.2.32
|
91
98
|
signing_key:
|
92
99
|
specification_version: 4
|
93
100
|
summary: A fast, lightweight, and straightforward web asset management library.
|
@@ -1,28 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class Darkroom
|
4
|
-
##
|
5
|
-
# Error class used when a spec is not defined for a particular file extension.
|
6
|
-
#
|
7
|
-
class SpecNotDefinedError < StandardError
|
8
|
-
attr_reader(:extension, :file)
|
9
|
-
|
10
|
-
##
|
11
|
-
# Creates a new instance.
|
12
|
-
#
|
13
|
-
# * +extension+ - Extension for which there is no spec defined.
|
14
|
-
# * +file+ - File path of the asset whose loading was attempted.
|
15
|
-
#
|
16
|
-
def initialize(extension, file = nil)
|
17
|
-
@extension = extension
|
18
|
-
@file = file
|
19
|
-
end
|
20
|
-
|
21
|
-
##
|
22
|
-
# Returns a string representation of the error.
|
23
|
-
#
|
24
|
-
def to_s
|
25
|
-
"Spec not defined for #{@extension} files#{" (#{@file})" if @file}"
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|