deadfire 0.4.0 → 0.6.0
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/.github/workflows/ci.yml +4 -1
- data/.gitignore +1 -0
- data/Gemfile.lock +96 -4
- data/README.md +18 -48
- data/changelog.md +12 -1
- data/deadfire.gemspec +6 -1
- data/lib/.keep +0 -0
- data/lib/deadfire/asset_loader.rb +67 -0
- data/lib/deadfire/asset_registry.rb +88 -0
- data/lib/deadfire/ast_printer.rb +6 -1
- data/lib/deadfire/configuration.rb +11 -1
- data/lib/deadfire/css_generator.rb +1 -1
- data/lib/deadfire/front_end/apply_node.rb +1 -1
- data/lib/deadfire/front_end/parser.rb +0 -4
- data/lib/deadfire/front_end/stylesheet_node.rb +1 -1
- data/lib/deadfire/interpreter.rb +6 -10
- data/lib/deadfire/mixin_parser.rb +51 -0
- data/lib/deadfire/parser_engine.rb +11 -1
- data/lib/deadfire/railtie.rb +35 -0
- data/lib/deadfire/spec.rb +2 -0
- data/lib/deadfire/version.rb +1 -1
- data/lib/deadfire.rb +6 -2
- metadata +70 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bf5ff2b972555ed94df49077860d3a5097400ada7b48aa753cfea0297eef953d
|
4
|
+
data.tar.gz: ae2b3e72441a00b32658cb8998b92f71ae33f5197cefa973cff7d4a688bb2b12
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 998ae91967f0cea560a426d521bd1882e764e4168aab5c12af464a8b9d40d3d7849320c88a636f4755df98c009c55a7cabc7e79c04f615b1a8fe37ec71a5e45b
|
7
|
+
data.tar.gz: 53e6a195fa84207d70e0cf4d23d258cae2c82c52d5e614f48c925b75b398d3d9630a0e90e19290efe0dcc7952ec56495ff35efec5d2ea7d51f2cd2dcabb9baef
|
data/.github/workflows/ci.yml
CHANGED
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,14 +1,61 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
deadfire (0.
|
4
|
+
deadfire (0.5.0)
|
5
|
+
actionpack (>= 7.0.0)
|
6
|
+
activesupport (>= 7.0.0)
|
7
|
+
propshaft (>= 0.9.0)
|
8
|
+
railties (>= 7.0.0)
|
5
9
|
|
6
10
|
GEM
|
7
11
|
remote: https://rubygems.org/
|
8
12
|
specs:
|
13
|
+
actionpack (7.1.3.4)
|
14
|
+
actionview (= 7.1.3.4)
|
15
|
+
activesupport (= 7.1.3.4)
|
16
|
+
nokogiri (>= 1.8.5)
|
17
|
+
racc
|
18
|
+
rack (>= 2.2.4)
|
19
|
+
rack-session (>= 1.0.1)
|
20
|
+
rack-test (>= 0.6.3)
|
21
|
+
rails-dom-testing (~> 2.2)
|
22
|
+
rails-html-sanitizer (~> 1.6)
|
23
|
+
actionview (7.1.3.4)
|
24
|
+
activesupport (= 7.1.3.4)
|
25
|
+
builder (~> 3.1)
|
26
|
+
erubi (~> 1.11)
|
27
|
+
rails-dom-testing (~> 2.2)
|
28
|
+
rails-html-sanitizer (~> 1.6)
|
29
|
+
activesupport (7.1.3.4)
|
30
|
+
base64
|
31
|
+
bigdecimal
|
32
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
33
|
+
connection_pool (>= 2.2.5)
|
34
|
+
drb
|
35
|
+
i18n (>= 1.6, < 2)
|
36
|
+
minitest (>= 5.1)
|
37
|
+
mutex_m
|
38
|
+
tzinfo (~> 2.0)
|
9
39
|
ansi (1.5.0)
|
10
|
-
|
11
|
-
|
40
|
+
base64 (0.2.0)
|
41
|
+
bigdecimal (3.1.8)
|
42
|
+
builder (3.3.0)
|
43
|
+
concurrent-ruby (1.3.4)
|
44
|
+
connection_pool (2.4.1)
|
45
|
+
crass (1.0.6)
|
46
|
+
drb (2.2.1)
|
47
|
+
erubi (1.13.0)
|
48
|
+
i18n (1.14.6)
|
49
|
+
concurrent-ruby (~> 1.0)
|
50
|
+
io-console (0.7.2)
|
51
|
+
irb (1.14.0)
|
52
|
+
rdoc (>= 4.0.0)
|
53
|
+
reline (>= 0.4.2)
|
54
|
+
loofah (2.23.1)
|
55
|
+
crass (~> 1.0.2)
|
56
|
+
nokogiri (>= 1.12.0)
|
57
|
+
mini_portile2 (2.8.7)
|
58
|
+
minitest (5.25.1)
|
12
59
|
minitest-focus (1.3.1)
|
13
60
|
minitest (>= 4, < 6)
|
14
61
|
minitest-reporters (1.5.0)
|
@@ -16,8 +63,53 @@ GEM
|
|
16
63
|
builder
|
17
64
|
minitest (>= 5.0)
|
18
65
|
ruby-progressbar
|
66
|
+
mutex_m (0.2.0)
|
67
|
+
nokogiri (1.16.7)
|
68
|
+
mini_portile2 (~> 2.8.2)
|
69
|
+
racc (~> 1.4)
|
70
|
+
propshaft (0.9.0)
|
71
|
+
actionpack (>= 7.0.0)
|
72
|
+
activesupport (>= 7.0.0)
|
73
|
+
rack
|
74
|
+
railties (>= 7.0.0)
|
75
|
+
psych (5.1.2)
|
76
|
+
stringio
|
77
|
+
racc (1.8.1)
|
78
|
+
rack (3.1.8)
|
79
|
+
rack-session (2.0.0)
|
80
|
+
rack (>= 3.0.0)
|
81
|
+
rack-test (2.1.0)
|
82
|
+
rack (>= 1.3)
|
83
|
+
rackup (2.1.0)
|
84
|
+
rack (>= 3)
|
85
|
+
webrick (~> 1.8)
|
86
|
+
rails-dom-testing (2.2.0)
|
87
|
+
activesupport (>= 5.0.0)
|
88
|
+
minitest
|
89
|
+
nokogiri (>= 1.6)
|
90
|
+
rails-html-sanitizer (1.6.0)
|
91
|
+
loofah (~> 2.21)
|
92
|
+
nokogiri (~> 1.14)
|
93
|
+
railties (7.1.3.4)
|
94
|
+
actionpack (= 7.1.3.4)
|
95
|
+
activesupport (= 7.1.3.4)
|
96
|
+
irb
|
97
|
+
rackup (>= 1.0.0)
|
98
|
+
rake (>= 12.2)
|
99
|
+
thor (~> 1.0, >= 1.2.2)
|
100
|
+
zeitwerk (~> 2.6)
|
19
101
|
rake (12.3.3)
|
102
|
+
rdoc (6.7.0)
|
103
|
+
psych (>= 4.0.0)
|
104
|
+
reline (0.5.9)
|
105
|
+
io-console (~> 0.5)
|
20
106
|
ruby-progressbar (1.11.0)
|
107
|
+
stringio (3.1.1)
|
108
|
+
thor (1.3.1)
|
109
|
+
tzinfo (2.0.6)
|
110
|
+
concurrent-ruby (~> 1.0)
|
111
|
+
webrick (1.9.0)
|
112
|
+
zeitwerk (2.6.16)
|
21
113
|
|
22
114
|
PLATFORMS
|
23
115
|
ruby
|
@@ -30,4 +122,4 @@ DEPENDENCIES
|
|
30
122
|
rake
|
31
123
|
|
32
124
|
BUNDLED WITH
|
33
|
-
2.
|
125
|
+
2.6.1
|
data/README.md
CHANGED
@@ -79,34 +79,9 @@ Re-use the styles using @apply:
|
|
79
79
|
}
|
80
80
|
```
|
81
81
|
|
82
|
-
### Nesting
|
83
|
-
|
84
|
-
The CSS nesting feature, as described in the CSS Nesting specification (https://drafts.csswg.org/css-nesting/), allows for more intuitive and concise styling by enabling the nesting of CSS rules within one another. This feature simplifies the structure of stylesheets and improves readability.
|
85
|
-
|
86
|
-
Now that nesting has been upstreamed to CSS, meaning it is now a part of the official CSS specification. As a result, Deafire will leverage the native CSS nesting feature instead of implementing this feature (which was the original goal of this project).
|
87
|
-
|
88
|
-
Example:
|
89
|
-
|
90
|
-
```css
|
91
|
-
.foo {
|
92
|
-
color: green;
|
93
|
-
}
|
94
|
-
.foo .bar {
|
95
|
-
font-size: 1.4rem;
|
96
|
-
}
|
97
|
-
|
98
|
-
/* can be simplified to */
|
99
|
-
.foo {
|
100
|
-
color: green;
|
101
|
-
.bar {
|
102
|
-
font-size: 1.4rem;
|
103
|
-
}
|
104
|
-
}
|
105
|
-
```
|
106
|
-
|
107
82
|
### Fault tolerant
|
108
83
|
|
109
|
-
When Deadfire encounters an error, such as a missing mixin or other issues, it does not
|
84
|
+
When Deadfire encounters an error, such as a missing mixin or other issues, it does not raise an error that would halt the execution. Instead, it continues processing the CSS code and collects the encountered errors. These errors are then reported through the ErrorReporter class, allowing you to handle or display them as needed.
|
110
85
|
|
111
86
|
By adopting this fault-tolerant approach, Deadfire aims to provide more flexibility and resilience when dealing with CSS code that may contain errors or inconsistencies. It allows you to gather information about the encountered issues and take appropriate actions based on the reported errors.
|
112
87
|
|
@@ -126,41 +101,36 @@ Or install it yourself as:
|
|
126
101
|
|
127
102
|
`> gem install deadfire`
|
128
103
|
|
129
|
-
##
|
104
|
+
## Ruby on Rails
|
130
105
|
|
131
|
-
|
106
|
+
Deadfire aims to work alongside the new asset pipeline, Propshaft.
|
132
107
|
|
133
|
-
|
108
|
+
With the gem included in your app's Gemfile, by default all your css files will be pre-processed.
|
134
109
|
|
135
|
-
|
110
|
+
For more control over the files you want to pre-process;
|
111
|
+
|
112
|
+
`Deadfire.configuration.root_path` - change the root path where files are processed e.g. tailwind is bundled into `app/assets/builds/tailwind.css`
|
113
|
+
which means the root_path will need updating, whereas the default deadfire root_path is `app/assetss/stylesheets`.
|
136
114
|
|
137
115
|
```ruby
|
138
116
|
# config/initializers/assets.rb
|
139
|
-
|
140
|
-
def compile(logical_path, input)
|
141
|
-
Deadfire.parse(input, root_path: Rails.root.join("app", "assets", "stylesheets"))
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
Rails.application.config.assets.compilers << ["text/css", DeadfireCompiler]
|
117
|
+
Deadfire.configuration.root_path = Rails.root.join("app/assets").to_s
|
146
118
|
```
|
147
|
-
### Sprockets
|
148
119
|
|
149
|
-
|
120
|
+
`Deadfire.configuration.preprocess` - configure exactly which files you want to pre-process, which caches all the utility classes declared
|
121
|
+
so they are available using `@apply` in your stylesheets.
|
150
122
|
|
151
123
|
```ruby
|
152
124
|
# config/initializers/assets.rb
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
Deadfire.configuration.
|
160
|
-
Sprockets.register_preprocessor('text/css', DeadfireProcessor.new)
|
125
|
+
Deadfire.configuration.preprocess("builds/tailwind.css")
|
126
|
+
```
|
127
|
+
|
128
|
+
To preprocess a file for a specific path like admin e.g. /admin/users, use the path keyword;
|
129
|
+
|
130
|
+
```ruby
|
131
|
+
Deadfire.configuration.preprocess("builds/tailwind.css", path: "admin")
|
161
132
|
```
|
162
133
|
|
163
|
-
Your css file should now be run through Deadfire.
|
164
134
|
## Development
|
165
135
|
|
166
136
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/changelog.md
CHANGED
@@ -1,5 +1,15 @@
|
|
1
1
|
## Changelog
|
2
|
-
### 0.
|
2
|
+
### 0.7.0 (current)
|
3
|
+
|
4
|
+
### 0.6.0 (15 Jan 2025)
|
5
|
+
- Drop config.deadfire.* instead the Deadfire.configuration is preferred for configuring deadfire.
|
6
|
+
|
7
|
+
### 0.5.0 (12 Dec 2024)
|
8
|
+
- Drop ruby 2.7
|
9
|
+
- Add a railties to make it real simple to pre-process every file for a simple setup
|
10
|
+
- Added the asset registry to make it easier to control how or which file is used as a mixin
|
11
|
+
- Excluded files are no longer pro-processed
|
12
|
+
- Make rails + propshaft dependencies
|
3
13
|
|
4
14
|
### 0.4.0 (18 May 2024)
|
5
15
|
- Fix parsing comments that have 2 stars e.g. /**
|
@@ -15,6 +25,7 @@
|
|
15
25
|
Deadfire will look for the file nav.css, then nav.scss in the `config.root_path` in the case when a file extension is not included.
|
16
26
|
|
17
27
|
- Simplify the configuration by having one option called compressed instead of keep_newlines and keep_comments.
|
28
|
+
- Add the ability to exclude files from being pre-processed via the `config.deadfire.excluded_files` option.
|
18
29
|
|
19
30
|
### 0.3.0 (15 November 2023)
|
20
31
|
|
data/deadfire.gemspec
CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.summary = "Deadfire - lightweight css preprocessor"
|
10
10
|
spec.homepage = "https://github.com/hahmed/deadfire"
|
11
11
|
spec.license = "MIT"
|
12
|
-
spec.required_ruby_version = Gem::Requirement.new(">=
|
12
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 3.0")
|
13
13
|
|
14
14
|
spec.metadata["homepage_uri"] = spec.homepage
|
15
15
|
spec.metadata["source_code_uri"] = "https://github.com/hahmed/deadfire"
|
@@ -23,4 +23,9 @@ Gem::Specification.new do |spec|
|
|
23
23
|
spec.bindir = "exe"
|
24
24
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
25
25
|
spec.require_paths = ["lib"]
|
26
|
+
|
27
|
+
spec.add_dependency "actionpack", ">= 7.0.0"
|
28
|
+
spec.add_dependency "activesupport", ">= 7.0.0"
|
29
|
+
spec.add_dependency "railties", ">= 7.0.0"
|
30
|
+
spec.add_dependency "propshaft", ">= 0.9.0"
|
26
31
|
end
|
data/lib/.keep
ADDED
File without changes
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Deadfire
|
4
|
+
# AssetLoader is responsible for loading mixin templates from the file system which can be used to mixin css into
|
5
|
+
# your stylesheet.
|
6
|
+
class AssetLoader
|
7
|
+
attr_reader :settings
|
8
|
+
|
9
|
+
def initialize(path)
|
10
|
+
@path = path
|
11
|
+
@cache = ActiveSupport::Cache::FileStore.new("tmp/deadfire_cache")
|
12
|
+
end
|
13
|
+
|
14
|
+
def cache_css(name, value)
|
15
|
+
cached_mixins[name] = value
|
16
|
+
end
|
17
|
+
|
18
|
+
def cached_css(name)
|
19
|
+
cached_mixins[name]
|
20
|
+
end
|
21
|
+
|
22
|
+
def preload(force_reload=false)
|
23
|
+
if force_reload
|
24
|
+
@_cached_mixins = nil
|
25
|
+
end
|
26
|
+
|
27
|
+
cached_mixins
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def cached_mixins
|
33
|
+
@_cached_mixins ||= load_mixins
|
34
|
+
end
|
35
|
+
|
36
|
+
def load_mixins
|
37
|
+
Array.wrap(Deadfire.configuration.asset_registry.mixins_for(@path)).each.with_object({}) do |filename, data|
|
38
|
+
unless File.exist?(filename)
|
39
|
+
Deadfire.config.logger.error("Mixin not found: #{filename}")
|
40
|
+
next
|
41
|
+
end
|
42
|
+
|
43
|
+
stat = File.stat(filename)
|
44
|
+
key = "#{filename}-#{stat.mtime.hash}"
|
45
|
+
|
46
|
+
content = @cache.fetch(key)
|
47
|
+
|
48
|
+
if content.nil?
|
49
|
+
content = load_and_parse_mixin(filename, key)
|
50
|
+
end
|
51
|
+
|
52
|
+
content.each do |key, value|
|
53
|
+
Deadfire.config.logger.warn("Mixin '#{key}' will be overrided with a new value.") if data.key?(key)
|
54
|
+
|
55
|
+
data[key] = value
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def load_and_parse_mixin(filename, key)
|
61
|
+
content = File.read(filename)
|
62
|
+
mixins = ParserEngine.new(content).load_mixins
|
63
|
+
@cache.write(key, mixins)
|
64
|
+
mixins
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Deadfire
|
4
|
+
class AssetRegistry
|
5
|
+
attr_reader :settings
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@settings = Hash.new { |h, k| h[k] = [] }
|
9
|
+
end
|
10
|
+
|
11
|
+
# for a given path, load all the mixins that are registered
|
12
|
+
# this makes it possible to load admin or other scoped mixins for a
|
13
|
+
# specific path
|
14
|
+
def register_path(path, *mixins)
|
15
|
+
normalized_mixins = Array.wrap(mixins).map { |p| full_path(p) }
|
16
|
+
normalize_path = strip_path(path).to_s
|
17
|
+
@settings[normalize_path].concat(normalized_mixins)
|
18
|
+
end
|
19
|
+
|
20
|
+
# for a given path, load all the mixins that are registered
|
21
|
+
# e.g. admin/ or admin will load all mixins for admin, if admin is a scope
|
22
|
+
# all mixins for admin/* will be loaded
|
23
|
+
def mixins_for(path)
|
24
|
+
return [] unless path.present?
|
25
|
+
|
26
|
+
mixins = []
|
27
|
+
|
28
|
+
mixins.concat Array.wrap(@settings[path])
|
29
|
+
|
30
|
+
if settings["*"].present?
|
31
|
+
mixins.concat Array.wrap(settings["*"])
|
32
|
+
end
|
33
|
+
|
34
|
+
scope = scope_from_path(path)
|
35
|
+
|
36
|
+
if scope.present? && settings[scope].present?
|
37
|
+
mixins.concat Array.wrap(settings[scope])
|
38
|
+
end
|
39
|
+
|
40
|
+
mixins.compact.uniq
|
41
|
+
end
|
42
|
+
|
43
|
+
def clear
|
44
|
+
@settings.clear
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def full_path(filename)
|
50
|
+
if File.exist?(filename)
|
51
|
+
filename
|
52
|
+
else
|
53
|
+
normalize_path(filename)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def normalize_path(filename)
|
58
|
+
path = File.join(Deadfire.config.root_path, filename)
|
59
|
+
path = css_extension(path)
|
60
|
+
|
61
|
+
unless File.exist?(path)
|
62
|
+
raise "Error finding asset path #{path}"
|
63
|
+
end
|
64
|
+
|
65
|
+
path
|
66
|
+
end
|
67
|
+
|
68
|
+
def css_extension(filename)
|
69
|
+
filename.end_with?(".css") ? filename : "#{filename}.css"
|
70
|
+
end
|
71
|
+
|
72
|
+
def scope?(path)
|
73
|
+
path.include?("/")
|
74
|
+
end
|
75
|
+
|
76
|
+
def scope_from_path(path)
|
77
|
+
if scope?(path)
|
78
|
+
path.split("/")[0...-1].join("/")
|
79
|
+
else
|
80
|
+
nil
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def strip_path(path)
|
85
|
+
path.split("/").last
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
data/lib/deadfire/ast_printer.rb
CHANGED
@@ -13,7 +13,7 @@ module Deadfire
|
|
13
13
|
def visit_stylesheet_node(node)
|
14
14
|
puts "StylesheetNode"
|
15
15
|
node.statements.each do |statement|
|
16
|
-
#
|
16
|
+
# todo
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
@@ -54,5 +54,10 @@ module Deadfire
|
|
54
54
|
puts "CommentNode"
|
55
55
|
puts " Comment: #{node.comment.lexeme}"
|
56
56
|
end
|
57
|
+
|
58
|
+
def visit_newline_node(node)
|
59
|
+
puts "NewlineNode"
|
60
|
+
puts " Newline: #{node.text}"
|
61
|
+
end
|
57
62
|
end
|
58
63
|
end
|
@@ -3,7 +3,7 @@ require "logger"
|
|
3
3
|
|
4
4
|
module Deadfire
|
5
5
|
class Configuration
|
6
|
-
attr_reader :directories, :root_path, :compressed, :logger, :supressed
|
6
|
+
attr_reader :directories, :root_path, :compressed, :logger, :supressed, :excluded_files, :asset_registry
|
7
7
|
|
8
8
|
def initialize
|
9
9
|
@directories = []
|
@@ -11,6 +11,8 @@ module Deadfire
|
|
11
11
|
@compressed = false
|
12
12
|
@logger = Logger.new(STDOUT, level: :warn)
|
13
13
|
@supressed = true
|
14
|
+
@excluded_files = []
|
15
|
+
@asset_registry = AssetRegistry.new
|
14
16
|
end
|
15
17
|
|
16
18
|
def root_path=(value)
|
@@ -33,5 +35,13 @@ module Deadfire
|
|
33
35
|
def supressed=(value)
|
34
36
|
@supressed = value
|
35
37
|
end
|
38
|
+
|
39
|
+
def excluded_files=(value)
|
40
|
+
@excluded_files = value
|
41
|
+
end
|
42
|
+
|
43
|
+
def preprocess(*mixins, path: "*")
|
44
|
+
@asset_registry.register_path(path, *mixins)
|
45
|
+
end
|
36
46
|
end
|
37
47
|
end
|
data/lib/deadfire/interpreter.rb
CHANGED
@@ -1,12 +1,10 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Deadfire
|
4
4
|
class Interpreter # :nodoc:
|
5
|
-
|
6
|
-
self.cached_apply_rules = Hash.new { |h, k| h[k] = nil }
|
7
|
-
|
8
|
-
def initialize(error_reporter)
|
5
|
+
def initialize(error_reporter, asset_loader)
|
9
6
|
@error_reporter = error_reporter
|
7
|
+
@asset_loader = asset_loader
|
10
8
|
end
|
11
9
|
|
12
10
|
def interpret(node)
|
@@ -27,8 +25,8 @@ module Deadfire
|
|
27
25
|
if node.block
|
28
26
|
visit_block_node(node.block, node)
|
29
27
|
|
30
|
-
unless
|
31
|
-
|
28
|
+
unless @asset_loader.cached_css(node.selector.selector)
|
29
|
+
@asset_loader.cache_css(node.selector.selector, node.block) if node.selector.cacheable?
|
32
30
|
end
|
33
31
|
end
|
34
32
|
end
|
@@ -60,9 +58,7 @@ module Deadfire
|
|
60
58
|
def apply_mixin(mixin, node)
|
61
59
|
updated_declarations = []
|
62
60
|
mixin.mixin_names.each do |mixin_name|
|
63
|
-
if
|
64
|
-
cached_block = Interpreter.cached_apply_rules[mixin_name]
|
65
|
-
|
61
|
+
if cached_block = @asset_loader.cached_css(mixin_name)
|
66
62
|
# NOTE: remove the left and right brace but we probably don't need to do this, how can this be simplified?
|
67
63
|
cached_block.declarations[1...-1].each do |cached_declaration|
|
68
64
|
updated_declarations << cached_declaration
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Deadfire
|
4
|
+
class MixinParser # :nodoc:
|
5
|
+
attr_reader :mixins
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@mixins = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def interpret(node)
|
12
|
+
node.accept(self)
|
13
|
+
end
|
14
|
+
|
15
|
+
def visit_stylesheet_node(node)
|
16
|
+
node.statements.each { |child| child.accept(self) }
|
17
|
+
end
|
18
|
+
|
19
|
+
def visit_at_rule_node(node)
|
20
|
+
if node.block
|
21
|
+
visit_block_node(node.block, node)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def visit_ruleset_node(node)
|
26
|
+
if node.block
|
27
|
+
visit_block_node(node.block, node)
|
28
|
+
|
29
|
+
if node.selector.cacheable?
|
30
|
+
if @mixins.key?(node.selector.selector)
|
31
|
+
Deadfire.config.logger.warn("Mixin '#{node.selector.selector}' will be overrided with a new value.")
|
32
|
+
end
|
33
|
+
|
34
|
+
@mixins[node.selector.selector] = node.block
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def visit_block_node(node, parent)
|
40
|
+
end
|
41
|
+
|
42
|
+
def visit_comment_node(node)
|
43
|
+
end
|
44
|
+
|
45
|
+
def visit_apply_node(node)
|
46
|
+
end
|
47
|
+
|
48
|
+
def visit_newline_node(node)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -7,12 +7,13 @@ module Deadfire
|
|
7
7
|
def initialize(content, options = {})
|
8
8
|
@error_reporter = ErrorReporter.new
|
9
9
|
@options = {}
|
10
|
+
@asset_loader = AssetLoader.new(options[:filename])
|
10
11
|
@scanner = FrontEnd::Scanner.new(content, error_reporter)
|
11
12
|
end
|
12
13
|
|
13
14
|
def parse
|
14
15
|
ast = _parse
|
15
|
-
interpreter = Interpreter.new(error_reporter)
|
16
|
+
interpreter = Interpreter.new(error_reporter, @asset_loader)
|
16
17
|
ast.statements.each do |node|
|
17
18
|
interpreter.interpret(node)
|
18
19
|
end
|
@@ -31,6 +32,15 @@ module Deadfire
|
|
31
32
|
@error_reporter.errors?
|
32
33
|
end
|
33
34
|
|
35
|
+
def load_mixins
|
36
|
+
ast = _parse
|
37
|
+
parser = MixinParser.new
|
38
|
+
ast.statements.each do |node|
|
39
|
+
parser.interpret(node)
|
40
|
+
end
|
41
|
+
parser.mixins
|
42
|
+
end
|
43
|
+
|
34
44
|
private
|
35
45
|
|
36
46
|
def _parse
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "rails"
|
3
|
+
require "propshaft"
|
4
|
+
|
5
|
+
module Deadfire
|
6
|
+
class Railties < ::Rails::Railtie
|
7
|
+
initializer :deadfire do |app|
|
8
|
+
Deadfire.configure do |deadfire_config|
|
9
|
+
deadfire_config.root_path = Rails.root.join("app/assets/stylesheets").to_s unless deadfire_config.root_path.present?
|
10
|
+
|
11
|
+
deadfire_config.excluded_files = []
|
12
|
+
deadfire_config.compressed = config.assets.compressed
|
13
|
+
deadfire_config.logger = config.assets.logger || Rails.logger
|
14
|
+
end
|
15
|
+
|
16
|
+
class DeadfireCompiler < ::Propshaft::Compiler
|
17
|
+
def compile(logical_path, input)
|
18
|
+
path = logical_path.path.to_s
|
19
|
+
|
20
|
+
return input if Deadfire.config.excluded_files.include?(path)
|
21
|
+
|
22
|
+
# by default, all files in the will be preprocessed
|
23
|
+
if Deadfire.config.asset_registry.settings.empty?
|
24
|
+
all_files = Dir.glob("#{Deadfire.config.root_path}/**/*.css")
|
25
|
+
Deadfire.config.preprocess(*all_files)
|
26
|
+
end
|
27
|
+
|
28
|
+
Deadfire.parse(input, filename: logical_path.logical_path.to_s)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
config.assets.compilers << ["text/css", DeadfireCompiler]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/deadfire/spec.rb
CHANGED
@@ -23,6 +23,7 @@ module Deadfire
|
|
23
23
|
PAGE = "@page"
|
24
24
|
FONT_FACE = "@font-face"
|
25
25
|
KEYFRAMES = "@keyframes"
|
26
|
+
WEBKIT_KEYFRAMES = "@-webkit-keyframes"
|
26
27
|
SUPPORTS = "@supports"
|
27
28
|
NAMESPACE = "@namespace"
|
28
29
|
COUNTER_STYLE = "@counter-style"
|
@@ -38,6 +39,7 @@ module Deadfire
|
|
38
39
|
PAGE,
|
39
40
|
FONT_FACE,
|
40
41
|
KEYFRAMES,
|
42
|
+
WEBKIT_KEYFRAMES,
|
41
43
|
SUPPORTS,
|
42
44
|
NAMESPACE,
|
43
45
|
COUNTER_STYLE,
|
data/lib/deadfire/version.rb
CHANGED
data/lib/deadfire.rb
CHANGED
@@ -1,11 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative "deadfire/ast_printer"
|
4
|
+
require_relative "deadfire/asset_loader"
|
5
|
+
require_relative "deadfire/asset_registry"
|
4
6
|
require_relative "deadfire/css_generator"
|
5
7
|
require_relative "deadfire/configuration"
|
6
8
|
require_relative "deadfire/errors"
|
7
9
|
require_relative "deadfire/error_reporter"
|
8
10
|
require_relative "deadfire/interpreter"
|
11
|
+
require_relative "deadfire/mixin_parser"
|
9
12
|
require_relative "deadfire/parser_engine"
|
10
13
|
require_relative "deadfire/spec"
|
11
14
|
require_relative "deadfire/filename_helper"
|
@@ -47,9 +50,10 @@ module Deadfire
|
|
47
50
|
config.compressed = options[:compressed]
|
48
51
|
end
|
49
52
|
|
50
|
-
parser = ParserEngine.new(content)
|
51
|
-
# TODO: hook into a logger and report the errors
|
53
|
+
parser = ParserEngine.new(content, filename: options[:filename])
|
52
54
|
parser.parse
|
53
55
|
end
|
54
56
|
end
|
55
57
|
end
|
58
|
+
|
59
|
+
require_relative "deadfire/railtie"
|
metadata
CHANGED
@@ -1,16 +1,72 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: deadfire
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Haroon Ahmed
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
12
|
-
dependencies:
|
13
|
-
|
11
|
+
date: 2025-01-15 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: actionpack
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 7.0.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 7.0.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activesupport
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 7.0.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 7.0.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: railties
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 7.0.0
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 7.0.0
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: propshaft
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.9.0
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.9.0
|
69
|
+
description:
|
14
70
|
email:
|
15
71
|
- haroon.ahmed25@gmail.com
|
16
72
|
executables: []
|
@@ -37,7 +93,10 @@ files:
|
|
37
93
|
- bin/test
|
38
94
|
- changelog.md
|
39
95
|
- deadfire.gemspec
|
96
|
+
- lib/.keep
|
40
97
|
- lib/deadfire.rb
|
98
|
+
- lib/deadfire/asset_loader.rb
|
99
|
+
- lib/deadfire/asset_registry.rb
|
41
100
|
- lib/deadfire/ast_printer.rb
|
42
101
|
- lib/deadfire/configuration.rb
|
43
102
|
- lib/deadfire/css_generator.rb
|
@@ -57,7 +116,9 @@ files:
|
|
57
116
|
- lib/deadfire/front_end/stylesheet_node.rb
|
58
117
|
- lib/deadfire/front_end/token.rb
|
59
118
|
- lib/deadfire/interpreter.rb
|
119
|
+
- lib/deadfire/mixin_parser.rb
|
60
120
|
- lib/deadfire/parser_engine.rb
|
121
|
+
- lib/deadfire/railtie.rb
|
61
122
|
- lib/deadfire/spec.rb
|
62
123
|
- lib/deadfire/version.rb
|
63
124
|
homepage: https://github.com/hahmed/deadfire
|
@@ -67,7 +128,7 @@ metadata:
|
|
67
128
|
homepage_uri: https://github.com/hahmed/deadfire
|
68
129
|
source_code_uri: https://github.com/hahmed/deadfire
|
69
130
|
changelog_uri: https://github.com/hahmed/deadfire/changelog.md
|
70
|
-
post_install_message:
|
131
|
+
post_install_message:
|
71
132
|
rdoc_options: []
|
72
133
|
require_paths:
|
73
134
|
- lib
|
@@ -75,15 +136,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
75
136
|
requirements:
|
76
137
|
- - ">="
|
77
138
|
- !ruby/object:Gem::Version
|
78
|
-
version: '
|
139
|
+
version: '3.0'
|
79
140
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
80
141
|
requirements:
|
81
142
|
- - ">="
|
82
143
|
- !ruby/object:Gem::Version
|
83
144
|
version: '0'
|
84
145
|
requirements: []
|
85
|
-
rubygems_version: 3.
|
86
|
-
signing_key:
|
146
|
+
rubygems_version: 3.0.3.1
|
147
|
+
signing_key:
|
87
148
|
specification_version: 4
|
88
149
|
summary: Deadfire - lightweight css preprocessor
|
89
150
|
test_files: []
|