darkroom 0.0.3 → 0.0.6

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.
@@ -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 cannot be
6
- # found.
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 < StandardError
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+ - The path of the asset that cannot be found.
15
- # * +referenced_from+ - The path of the asset the not-found asset was referenced from.
16
- # * +referenced_from_line+ - The line number where the not-found asset was referenced.
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 to_s
28
- "Asset not found#{
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 in multiple load paths.
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+ - The path of the asset that has the same path as another asset.
14
- # * +first_load_path+ - The load path where the first asset with the path was found.
15
- # * +second_load_path+ - The load path where the second asset with the path was found.
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+ - The name of the library that's missing.
14
- # * +need+ - The reason the library is needed ('compile' or 'minify').
15
- # * +extension+ - The extenion of the type of asset that needs the library.
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Darkroom
4
- VERSION = '0.0.3'
4
+ VERSION = '0.0.6'
5
5
  end
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/errors/asset_not_found_error')
8
- require('darkroom/errors/duplicate_asset_error')
9
- require('darkroom/errors/missing_library_error')
10
- require('darkroom/errors/processing_error')
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::Asset.add_spec('.css', 'text/css',
14
- dependency_regex: /^ *@import +#{Darkroom::Asset::IMPORT_PATH_REGEX} *; *$/,
15
- minify: -> (content) { SassC::Engine.new(content, style: :compressed).render },
16
- minify_lib: 'sassc',
17
- )
18
-
19
- Darkroom::Asset.add_spec('.js', 'application/javascript',
20
- dependency_regex: /^ *import +#{Darkroom::Asset::IMPORT_PATH_REGEX} *;? *$/,
21
- minify: -> (content) { Uglifier.compile(content, harmony: true) },
22
- minify_lib: 'uglifier',
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.3
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: 2021-03-27 00:00:00.000000000 Z
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/spec_not_defined_error.rb
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.3
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