tailwindcss-rails 0.3.3 → 0.4.3
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/README.md +18 -13
- data/app/assets/stylesheets/tailwind.css +172198 -158668
- data/lib/install/tailwindcss.rb +17 -0
- data/lib/tailwindcss/purger.rb +94 -34
- data/lib/tailwindcss/version.rb +1 -1
- data/lib/tasks/tailwindcss_tasks.rake +2 -21
- metadata +4 -6
- data/lib/install/stylesheets/application.scss +0 -3
- data/lib/install/tailwindcss_with_asset_pipeline.rb +0 -12
- data/lib/install/tailwindcss_with_webpacker.rb +0 -22
@@ -0,0 +1,17 @@
|
|
1
|
+
APPLICATION_LAYOUT_PATH = Rails.root.join("app/views/layouts/application.html.erb")
|
2
|
+
|
3
|
+
if APPLICATION_LAYOUT_PATH.exist?
|
4
|
+
say "Add Tailwindcss include tags in application layout"
|
5
|
+
insert_into_file Rails.root.join("app/views/layouts/application.html.erb").to_s, %(\n <%= stylesheet_link_tag "inter-font", "data-turbo-track": "reload" %>\n <%= stylesheet_link_tag "tailwind", "data-turbo-track": "reload" %>), before: /^\s*<%= stylesheet_link_tag/
|
6
|
+
else
|
7
|
+
say "Default application.html.erb is missing!", :red
|
8
|
+
say %( Add <%= stylesheet_link_tag "inter-font", "data-turbo-track": "reload" %> and <%= stylesheet_link_tag "tailwind", "data-turbo-track": "reload" %> within the <head> tag in your custom layout.)
|
9
|
+
end
|
10
|
+
|
11
|
+
# No longer included by default in Rails 7, but for earlier versions of Rails
|
12
|
+
if (scaffolds_css_path = Rails.root.join("app/assets/stylesheets/scaffolds.scss")).exist?
|
13
|
+
remove_file scaffolds_css_path
|
14
|
+
end
|
15
|
+
|
16
|
+
say "Turn on purging of unused css classes in production"
|
17
|
+
gsub_file Rails.root.join("config/environments/production.rb"), /^\s+#?\s+config.assets.css_compressor =.*$/, %( config.assets.css_compressor = :purger)
|
data/lib/tailwindcss/purger.rb
CHANGED
@@ -1,8 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Tailwindcss::Purger
|
2
|
-
CLASS_NAME_PATTERN
|
3
|
-
|
4
|
-
|
5
|
-
|
4
|
+
CLASS_NAME_PATTERN = /((?:[:A-Za-z0-9_-]+[\\\/:A-Za-z0-9_-]*[0-3][\\.]*5)|(?:[A-Za-z0-9_-]+[\\\/:A-Za-z0-9_-]*))/
|
5
|
+
|
6
|
+
CLASS_BREAK = /(?![-_a-z0-9\\])/i # `\b` for class selectors
|
7
|
+
|
8
|
+
COMMENT = /#{Regexp.escape "/*"}.*?#{Regexp.escape "*/"}/m
|
9
|
+
COMMENTS_AND_BLANK_LINES = /\A(?:^#{COMMENT}?[ \t]*(?:\n|\z)|[ \t]*#{COMMENT})+/
|
10
|
+
|
11
|
+
AT_RULE = /@[^{]+/
|
12
|
+
CLASSLESS_SELECTOR_GROUP = /[^.{]+/
|
13
|
+
CLASSLESS_BEGINNING_OF_BLOCK = /\A\s*(?:#{AT_RULE}|#{CLASSLESS_SELECTOR_GROUP})\{\n?/
|
14
|
+
|
15
|
+
SELECTOR_GROUP = /[^{]+/
|
16
|
+
BEGINNING_OF_BLOCK = /\A#{SELECTOR_GROUP}\{\n?/
|
17
|
+
|
18
|
+
PROPERTY_NAME = /[-_a-z0-9]+/i
|
19
|
+
PROPERTY_VALUE = /(?:[^;]|;\S)+/
|
20
|
+
PROPERTIES = /\A(?:\s*#{PROPERTY_NAME}:#{PROPERTY_VALUE};\n?)+/
|
21
|
+
|
22
|
+
END_OF_BLOCK = /\A\s*\}\n?/
|
6
23
|
|
7
24
|
attr_reader :keep_these_class_names
|
8
25
|
|
@@ -12,11 +29,15 @@ class Tailwindcss::Purger
|
|
12
29
|
end
|
13
30
|
|
14
31
|
def extract_class_names(string)
|
15
|
-
string.scan(CLASS_NAME_PATTERN).flatten.uniq.sort
|
32
|
+
string.scan(CLASS_NAME_PATTERN).flatten.uniq.sort!
|
16
33
|
end
|
17
34
|
|
18
35
|
def extract_class_names_from(files)
|
19
|
-
Array(files).flat_map { |file| extract_class_names(file.read) }.uniq.sort
|
36
|
+
Array(files).flat_map { |file| extract_class_names(file.read) }.uniq.sort!
|
37
|
+
end
|
38
|
+
|
39
|
+
def escape_class_selector(class_name)
|
40
|
+
class_name.gsub(/\A\d|[^-_a-z0-9]/, '\\\\\0')
|
20
41
|
end
|
21
42
|
end
|
22
43
|
|
@@ -25,40 +46,79 @@ class Tailwindcss::Purger
|
|
25
46
|
end
|
26
47
|
|
27
48
|
def purge(input)
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
inside_ignored_selector = false if line =~ CLOSING_SELECTOR_PATTERN
|
38
|
-
when line =~ OPENING_SELECTOR_PATTERN
|
39
|
-
if keep_these_class_names.include? class_name_in(line)
|
40
|
-
output << line
|
41
|
-
inside_kept_selector = true
|
42
|
-
else
|
43
|
-
inside_ignored_selector = true
|
44
|
-
end
|
45
|
-
else
|
46
|
-
output << line
|
47
|
-
end
|
49
|
+
conveyor = Conveyor.new(input)
|
50
|
+
|
51
|
+
until conveyor.done?
|
52
|
+
conveyor.discard(COMMENTS_AND_BLANK_LINES) \
|
53
|
+
or conveyor.conditionally_keep(PROPERTIES) { conveyor.staged_output.last != "" } \
|
54
|
+
or conveyor.conditionally_keep(END_OF_BLOCK) { not conveyor.staged_output.pop } \
|
55
|
+
or conveyor.stage_output(CLASSLESS_BEGINNING_OF_BLOCK) \
|
56
|
+
or conveyor.stage_output(BEGINNING_OF_BLOCK) { |match| purge_beginning_of_block(match.to_s) } \
|
57
|
+
or raise "infinite loop"
|
48
58
|
end
|
49
59
|
|
50
|
-
|
60
|
+
conveyor.output
|
51
61
|
end
|
52
62
|
|
53
63
|
private
|
54
|
-
def
|
55
|
-
|
56
|
-
.
|
57
|
-
.
|
58
|
-
|
64
|
+
def keep_these_selectors_pattern
|
65
|
+
@keep_these_selectors_pattern ||= begin
|
66
|
+
escaped_classes = @keep_these_class_names.map { |name| Regexp.escape self.class.escape_class_selector(name) }
|
67
|
+
/(?:\A|,)[^.,{]*(?:[.](?:#{escaped_classes.join("|")})#{CLASS_BREAK}[^.,{]*)*(?=[,{])/
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def purge_beginning_of_block(string)
|
72
|
+
purged = string.scan(keep_these_selectors_pattern).join
|
73
|
+
unless purged.empty?
|
74
|
+
purged.sub!(/\A,\s*/, "")
|
75
|
+
purged.rstrip!
|
76
|
+
purged << " {\n"
|
77
|
+
end
|
78
|
+
purged
|
59
79
|
end
|
60
80
|
|
61
|
-
|
62
|
-
output
|
81
|
+
class Conveyor
|
82
|
+
attr_reader :output, :staged_output
|
83
|
+
|
84
|
+
def initialize(input, output = +"")
|
85
|
+
@input = input
|
86
|
+
@output = output
|
87
|
+
@staged_output = []
|
88
|
+
end
|
89
|
+
|
90
|
+
def consume(pattern)
|
91
|
+
match = pattern.match(@input)
|
92
|
+
@input = match.post_match if match
|
93
|
+
match
|
94
|
+
end
|
95
|
+
alias :discard :consume
|
96
|
+
|
97
|
+
def stage_output(pattern)
|
98
|
+
if match = consume(pattern)
|
99
|
+
string = block_given? ? (yield match) : match.to_s
|
100
|
+
@staged_output << string
|
101
|
+
string
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def keep(pattern)
|
106
|
+
if match = consume(pattern)
|
107
|
+
string = block_given? ? (yield match) : match.to_s
|
108
|
+
@output << @staged_output.shift until @staged_output.empty?
|
109
|
+
@output << string
|
110
|
+
string
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def conditionally_keep(pattern)
|
115
|
+
keep(pattern) do |match|
|
116
|
+
(yield match) ? match.to_s : (break "")
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def done?
|
121
|
+
@input.empty?
|
122
|
+
end
|
63
123
|
end
|
64
124
|
end
|
data/lib/tailwindcss/version.rb
CHANGED
@@ -1,23 +1,7 @@
|
|
1
1
|
namespace :tailwindcss do
|
2
2
|
desc "Install Tailwind CSS into the app"
|
3
3
|
task :install do
|
4
|
-
|
5
|
-
Rake::Task["tailwindcss:install:webpacker"].invoke
|
6
|
-
else
|
7
|
-
Rake::Task["tailwindcss:install:asset_pipeline"].invoke
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
namespace :install do
|
12
|
-
desc "Install Tailwind CSS with the asset pipeline"
|
13
|
-
task :asset_pipeline do
|
14
|
-
run_install_template "tailwindcss_with_asset_pipeline"
|
15
|
-
end
|
16
|
-
|
17
|
-
desc "Install Tailwind CSS with webpacker"
|
18
|
-
task :webpacker do
|
19
|
-
run_install_template "tailwindcss_with_webpacker"
|
20
|
-
end
|
4
|
+
system "#{RbConfig.ruby} ./bin/rails app:template LOCATION=#{File.expand_path("../install/tailwindcss.rb", __dir__)}"
|
21
5
|
end
|
22
6
|
|
23
7
|
desc "Show the list of class names being kept in Tailwind CSS"
|
@@ -31,10 +15,6 @@ namespace :tailwindcss do
|
|
31
15
|
end
|
32
16
|
end
|
33
17
|
|
34
|
-
def run_install_template(path)
|
35
|
-
system "#{RbConfig.ruby} ./bin/rails app:template LOCATION=#{File.expand_path("../install/#{path}.rb", __dir__)}"
|
36
|
-
end
|
37
|
-
|
38
18
|
def default_files_with_class_names
|
39
19
|
Rails.root.glob("app/views/**/*.*") + Rails.root.glob("app/helpers/**/*.rb")
|
40
20
|
end
|
@@ -42,3 +22,4 @@ end
|
|
42
22
|
def tailwind_css
|
43
23
|
Pathname.new(__FILE__).join("../../../app/assets/stylesheets/tailwind.css").read
|
44
24
|
end
|
25
|
+
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tailwindcss-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Heinemeier Hansson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-08-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -51,9 +51,7 @@ files:
|
|
51
51
|
- app/assets/fonts/Inter-roman.vietnamese.var.woff2
|
52
52
|
- app/assets/stylesheets/inter-font.css.erb
|
53
53
|
- app/assets/stylesheets/tailwind.css
|
54
|
-
- lib/install/
|
55
|
-
- lib/install/tailwindcss_with_asset_pipeline.rb
|
56
|
-
- lib/install/tailwindcss_with_webpacker.rb
|
54
|
+
- lib/install/tailwindcss.rb
|
57
55
|
- lib/tailwindcss-rails.rb
|
58
56
|
- lib/tailwindcss/compressor.rb
|
59
57
|
- lib/tailwindcss/engine.rb
|
@@ -80,7 +78,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
80
78
|
- !ruby/object:Gem::Version
|
81
79
|
version: '0'
|
82
80
|
requirements: []
|
83
|
-
rubygems_version: 3.1.
|
81
|
+
rubygems_version: 3.1.4
|
84
82
|
signing_key:
|
85
83
|
specification_version: 4
|
86
84
|
summary: Integrate Tailwind CSS with the asset pipeline in Rails.
|
@@ -1,12 +0,0 @@
|
|
1
|
-
APPLICATION_LAYOUT_PATH = Rails.root.join("app/views/layouts/application.html.erb")
|
2
|
-
|
3
|
-
if APPLICATION_LAYOUT_PATH.exist?
|
4
|
-
say "Add Tailwindcss include tags in application layout"
|
5
|
-
insert_into_file Rails.root.join("app/views/layouts/application.html.erb").to_s, %(\n <%= stylesheet_link_tag "inter-font" %>\n <%= stylesheet_link_tag "tailwind" %>), before: /^\s*<%= stylesheet_link_tag/
|
6
|
-
else
|
7
|
-
say "Default application.html.erb is missing!", :red
|
8
|
-
say %( Add <%= stylesheet_link_tag "inter-font" %> and <%= stylesheet_link_tag "tailwind" %> within the <head> tag in your custom layout.)
|
9
|
-
end
|
10
|
-
|
11
|
-
say "Turn on purging of unused css classes in production"
|
12
|
-
gsub_file Rails.root.join("config/environments/production.rb"), /^\s+#?\s+config.assets.css_compressor =.*$/, %( config.assets.css_compressor = :purger)
|
@@ -1,22 +0,0 @@
|
|
1
|
-
WEBPACK_STYLESHEETS_PATH = "#{Webpacker.config.source_path}/stylesheets"
|
2
|
-
APPLICATION_LAYOUT_PATH = Rails.root.join("app/views/layouts/application.html.erb")
|
3
|
-
|
4
|
-
say "Installing Tailwind CSS"
|
5
|
-
run "yarn add tailwindcss@npm:@tailwindcss/postcss7-compat postcss@^7 autoprefixer@^9"
|
6
|
-
insert_into_file "#{Webpacker.config.source_entry_path}/application.js", "\nimport \"stylesheets/application\"\n"
|
7
|
-
|
8
|
-
say "Configuring Tailwind CSS"
|
9
|
-
directory Pathname.new(__dir__).join("stylesheets"), Webpacker.config.source_path.join("stylesheets")
|
10
|
-
Dir.chdir(WEBPACK_STYLESHEETS_PATH) { run "npx tailwindcss init" }
|
11
|
-
|
12
|
-
insert_into_file "postcss.config.js", "require('tailwindcss')(\"./app/javascript/stylesheets/tailwind.config.js\"),\n ",
|
13
|
-
before: "require('postcss-import')"
|
14
|
-
|
15
|
-
|
16
|
-
if APPLICATION_LAYOUT_PATH.exist?
|
17
|
-
say "Add Tailwindcss include tags in application layout"
|
18
|
-
insert_into_file Rails.root.join("app/views/layouts/application.html.erb").to_s, %(\n <%= stylesheet_pack_tag "application", "data-turbo-track": "reload" %>), before: /\s*<\/head>/
|
19
|
-
else
|
20
|
-
say "Default application.html.erb is missing!", :red
|
21
|
-
say %( Add <%= stylesheet_pack_tag "application", "data-turbo-track": "reload" %> within the <head> tag in your custom layout.)
|
22
|
-
end
|