darkroom 0.0.3 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -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