diff --git a/lib/generators/tailwindcss/scaffold/templates/show.html.erb.tt b/lib/generators/tailwindcss/scaffold/templates/show.html.erb.tt
index ed11d9b4..2b6687d2 100644
--- a/lib/generators/tailwindcss/scaffold/templates/show.html.erb.tt
+++ b/lib/generators/tailwindcss/scaffold/templates/show.html.erb.tt
@@ -1,15 +1,15 @@
-
-
- <%% if notice.present? %>
-
<%%= notice %>
- <%% end %>
-
- <%%= render @<%= singular_table_name %> %>
-
- <%%= link_to 'Edit this <%= singular_table_name %>', edit_<%= singular_table_name %>_path(@<%= singular_table_name %>), class: "mt-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>
-
- <%%= button_to 'Destroy this <%= singular_table_name %>', <%= singular_table_name %>_path(@<%= singular_table_name %>), method: :delete, data: { confirm: "Are you sure you want to delete this <%= singular_table_name %>?" }, class: "mt-2 rounded-lg py-3 px-5 bg-gray-100 font-medium" %>
-
- <%%= link_to 'Back to <%= plural_table_name %>', <%= index_helper %>_path, class: "ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>
-
+<%% content_for :title, "Showing <%= human_name.downcase %>" %>
+
+
+ <%% if notice.present? %>
+
<%%= notice %>
+ <%% end %>
+
+
Showing <%= human_name.downcase %>
+
+ <%%= render @<%= singular_table_name %> %>
+
+ <%%= link_to "Edit this <%= human_name.downcase %>", <%= edit_helper(type: :path) %>, class: "w-full sm:w-auto text-center rounded-md px-3.5 py-2.5 bg-gray-100 hover:bg-gray-50 inline-block font-medium" %>
+ <%%= link_to "Back to <%= human_name.pluralize.downcase %>", <%= index_helper %>_path, class: "w-full sm:w-auto text-center mt-2 sm:mt-0 sm:ml-2 rounded-md px-3.5 py-2.5 bg-gray-100 hover:bg-gray-50 inline-block font-medium" %>
+ <%%= button_to "Destroy this <%= human_name.downcase %>", <%= model_resource_name(prefix: "@") %>, method: :delete, form_class: "sm:inline-block mt-2 sm:mt-0 sm:ml-2", class: "w-full rounded-md px-3.5 py-2.5 text-white bg-red-600 hover:bg-red-500 font-medium cursor-pointer", data: { turbo_confirm: "Are you sure?" } %>
diff --git a/lib/generators/test_unit/scaffold/scaffold_generator.rb b/lib/generators/test_unit/scaffold/scaffold_generator.rb
new file mode 100644
index 00000000..511ca7d1
--- /dev/null
+++ b/lib/generators/test_unit/scaffold/scaffold_generator.rb
@@ -0,0 +1,20 @@
+require "rails/generators/test_unit/scaffold/scaffold_generator"
+
+module TestUnit # :nodoc:
+ module Generators # :nodoc:
+ class ScaffoldGenerator < Base # :nodoc:
+ def fix_system_test
+ system_test_file = File.join("test/system", class_path, "#{file_name.pluralize}_test.rb")
+ if turbo_defined? && options[:system_tests] && File.exist?(system_test_file)
+ gsub_file(system_test_file, /(click_on.*Destroy this.*)$/, "accept_confirm { \\1 }")
+ end
+ end
+
+ private
+
+ def turbo_defined?
+ defined?(Turbo)
+ end
+ end
+ end
+end
diff --git a/lib/install/Procfile.dev b/lib/install/Procfile.dev
new file mode 100644
index 00000000..da151fee
--- /dev/null
+++ b/lib/install/Procfile.dev
@@ -0,0 +1,2 @@
+web: bin/rails server
+css: bin/rails tailwindcss:watch
diff --git a/lib/install/application.css b/lib/install/application.css
new file mode 100644
index 00000000..f1d8c73c
--- /dev/null
+++ b/lib/install/application.css
@@ -0,0 +1 @@
+@import "tailwindcss";
diff --git a/lib/install/dev b/lib/install/dev
new file mode 100755
index 00000000..ad72c7d5
--- /dev/null
+++ b/lib/install/dev
@@ -0,0 +1,16 @@
+#!/usr/bin/env sh
+
+if ! gem list foreman -i --silent; then
+ echo "Installing foreman..."
+ gem install foreman
+fi
+
+# Default to port 3000 if not specified
+export PORT="${PORT:-3000}"
+
+# Let the debug gem allow remote connections,
+# but avoid loading until `debugger` is called
+export RUBY_DEBUG_OPEN="true"
+export RUBY_DEBUG_LAZY="true"
+
+exec foreman start -f Procfile.dev "$@"
diff --git a/lib/install/install_tailwindcss.rb b/lib/install/install_tailwindcss.rb
new file mode 100644
index 00000000..3d471d07
--- /dev/null
+++ b/lib/install/install_tailwindcss.rb
@@ -0,0 +1,55 @@
+APPLICATION_LAYOUT_PATH = Rails.root.join("app/views/layouts/application.html.erb")
+CENTERING_CONTAINER_INSERTION_POINT = /^\s*<%= yield %>/.freeze
+TAILWIND_ASSET_PATH = Rails.root.join("app/assets/tailwind/application.css")
+
+if APPLICATION_LAYOUT_PATH.exist?
+ unless File.read(APPLICATION_LAYOUT_PATH).match?(/stylesheet_link_tag :app/)
+ say "Add Tailwindcss include tags in application layout"
+ insert_into_file APPLICATION_LAYOUT_PATH.to_s, <<~ERB.indent(4), before: /^\s*<%= stylesheet_link_tag/
+ <%= stylesheet_link_tag "tailwind", "data-turbo-track": "reload" %>
+ ERB
+ end
+
+ say "Add Tailwindcss container element in application layout"
+ if File.open(APPLICATION_LAYOUT_PATH).read =~ /\n\s*<%= yield %>\n\s*<\/body>/
+ insert_into_file APPLICATION_LAYOUT_PATH.to_s, %(
\n ), before: CENTERING_CONTAINER_INSERTION_POINT
+ insert_into_file APPLICATION_LAYOUT_PATH.to_s, %(\n ), after: CENTERING_CONTAINER_INSERTION_POINT
+ end
+else
+ say "Default application.html.erb is missing!", :red
+ say %( Add <%= stylesheet_link_tag "tailwind", "data-turbo-track": "reload" %> within the tag in your custom layout.)
+end
+
+say "Build into app/assets/builds"
+empty_directory "app/assets/builds"
+keep_file "app/assets/builds"
+
+if (sprockets_manifest_path = Rails.root.join("app/assets/config/manifest.js")).exist?
+ append_to_file sprockets_manifest_path, %(//= link_tree ../builds\n)
+end
+
+if Rails.root.join(".gitignore").exist?
+ append_to_file(".gitignore", %(\n/app/assets/builds/*\n!/app/assets/builds/.keep\n))
+end
+
+unless TAILWIND_ASSET_PATH.exist?
+ say "Add default #{TAILWIND_ASSET_PATH}"
+ copy_file "#{__dir__}/application.css", TAILWIND_ASSET_PATH
+end
+
+if Rails.root.join("Procfile.dev").exist?
+ append_to_file "Procfile.dev", "css: bin/rails tailwindcss:watch\n"
+else
+ say "Add default Procfile.dev"
+ copy_file "#{__dir__}/Procfile.dev", "Procfile.dev"
+
+ say "Ensure foreman is installed"
+ run "gem install foreman"
+end
+
+say "Add bin/dev to start foreman"
+copy_file "#{__dir__}/dev", "bin/dev", force: true
+chmod "bin/dev", 0755, verbose: false
+
+say "Compile initial Tailwind build"
+run "rails tailwindcss:build"
diff --git a/lib/install/tailwindcss.rb b/lib/install/tailwindcss.rb
deleted file mode 100644
index 97666284..00000000
--- a/lib/install/tailwindcss.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-APPLICATION_LAYOUT_PATH = Rails.root.join("app/views/layouts/application.html.erb")
-
-if APPLICATION_LAYOUT_PATH.exist?
- say "Add Tailwindcss include tags and container element in application layout"
- insert_into_file APPLICATION_LAYOUT_PATH.to_s, <<~ERB.indent(4), before: /^\s*<%= stylesheet_link_tag/
- <%= stylesheet_link_tag "inter-font", "data-turbo-track": "reload" %>
- <%= stylesheet_link_tag "tailwind", "data-turbo-track": "reload" %>
- ERB
- insert_into_file APPLICATION_LAYOUT_PATH.to_s, %(
\n ), before: /^\s*<%= yield/
- insert_into_file APPLICATION_LAYOUT_PATH.to_s, %(\n ), after: /^\s*<%= yield %>/
-else
- say "Default application.html.erb is missing!", :red
- say %( Add <%= stylesheet_link_tag "inter-font", "data-turbo-track": "reload" %> and <%= stylesheet_link_tag "tailwind", "data-turbo-track": "reload" %> within the tag in your custom layout.)
-end
-
-# No longer included by default in Rails 7, but for earlier versions of Rails
-if (scaffolds_css_path = Rails.root.join("app/assets/stylesheets/scaffolds.scss")).exist?
- remove_file scaffolds_css_path
-end
-
-say "Turn on purging of unused css classes in production"
-gsub_file Rails.root.join("config/environments/production.rb"), /^\s+#?\s+config.assets.css_compressor =.*$/, %( config.assets.css_compressor = :purger)
diff --git a/lib/install/upgrade_tailwindcss.rb b/lib/install/upgrade_tailwindcss.rb
new file mode 100644
index 00000000..d6ecadab
--- /dev/null
+++ b/lib/install/upgrade_tailwindcss.rb
@@ -0,0 +1,69 @@
+TAILWIND_CONFIG_PATH = Rails.root.join("config/tailwind.config.js")
+APPLICATION_LAYOUT_PATH = Rails.root.join("app/views/layouts/application.html.erb")
+POSTCSS_CONFIG_PATH = Rails.root.join("config/postcss.config.js")
+OLD_TAILWIND_ASSET_PATH = Rails.root.join("app/assets/stylesheets/application.tailwind.css")
+TAILWIND_ASSET_PATH = Rails.root.join("app/assets/tailwind/application.css")
+
+unless TAILWIND_CONFIG_PATH.exist?
+ say "Default tailwind.config.js is missing!", :red
+ abort
+end
+
+if File.read(TAILWIND_CONFIG_PATH).match?(/defaultTheme/)
+ say "Removing references to 'defaultTheme' from #{TAILWIND_CONFIG_PATH}"
+ gsub_file TAILWIND_CONFIG_PATH.to_s, /^(.*defaultTheme)/, "// \\1"
+end
+
+if POSTCSS_CONFIG_PATH.exist?
+ say "Moving PostCSS configuration to application root directory"
+ copy_file POSTCSS_CONFIG_PATH, Rails.root.join("postcss.config.js")
+ remove_file POSTCSS_CONFIG_PATH
+end
+
+if APPLICATION_LAYOUT_PATH.exist?
+ if File.read(APPLICATION_LAYOUT_PATH).match?(/"inter-font"/)
+ say "Strip Inter font CSS from application layout"
+ gsub_file APPLICATION_LAYOUT_PATH.to_s, %r{, "inter-font"}, ""
+ else
+ say "Inter font CSS not detected.", :green
+ end
+
+ if File.read(APPLICATION_LAYOUT_PATH).match?(/stylesheet_link_tag :app/) &&
+ File.read(APPLICATION_LAYOUT_PATH).match?(/stylesheet_link_tag "tailwind"/)
+ say "Remove unnecessary stylesheet_link_tag from application layout"
+ gsub_file APPLICATION_LAYOUT_PATH.to_s, %r{^\s*<%= stylesheet_link_tag "tailwind".*%>$}, ""
+ end
+else
+ say "Default application.html.erb is missing!", :red
+ say %( Please check your layouts and remove any "inter-font" stylesheet links.)
+end
+
+if OLD_TAILWIND_ASSET_PATH.exist?
+ say "Moving #{OLD_TAILWIND_ASSET_PATH} to #{TAILWIND_ASSET_PATH}"
+ copy_file OLD_TAILWIND_ASSET_PATH, TAILWIND_ASSET_PATH
+ remove_file OLD_TAILWIND_ASSET_PATH
+end
+
+if system("npx --version")
+ # We're pinning to v4.1.4 because v4.1.5 of the upgrade tool introduces a dependency version check
+ # on tailwind and I haven't been able to figure out how to get that to work reliably and I am
+ # extremely frustrated with the whole thing. See #544
+ #
+ # At some point we will probably need to unpin this at which point I am sincerely hoping that
+ # someone else will do it.
+ say "Running the upstream Tailwind CSS upgrader"
+ command = Shellwords.join(["npx", "@tailwindcss/upgrade@4.1.4", "--force", "--config", TAILWIND_CONFIG_PATH.to_s])
+ success = run(command, abort_on_failure: false)
+ unless success
+ say "The upgrade tool failed!", :red
+ say %( You probably need to update your configuration. Please read the error messages,)
+ say %( and check the Tailwind CSS upgrade guide at https://tailwindcss.com/docs/upgrade-guide.)
+ abort
+ end
+else
+ say "Could not run the Tailwind upgrade tool. Please see https://tailwindcss.com/docs/upgrade-guide for manual instructions.", :red
+ abort
+end
+
+say "Compile initial Tailwind build"
+run "rails tailwindcss:build"
diff --git a/lib/puma/plugin/tailwindcss.rb b/lib/puma/plugin/tailwindcss.rb
new file mode 100644
index 00000000..29b5b621
--- /dev/null
+++ b/lib/puma/plugin/tailwindcss.rb
@@ -0,0 +1,76 @@
+require "puma/plugin"
+require "tailwindcss/commands"
+
+Puma::Plugin.create do
+ attr_reader :puma_pid, :tailwind_pid, :log_writer
+
+ def start(launcher)
+ @log_writer = launcher.log_writer
+ @puma_pid = $$
+ @tailwind_pid = fork do
+ Thread.new { monitor_puma }
+ # Using IO.popen(command, 'r+') will avoid watch_command read from $stdin.
+ # If we use system(*command) instead, IRB and Debug can't read from $stdin
+ # correctly bacause some keystrokes will be taken by watch_command.
+ begin
+ IO.popen(['bin/rails', 'tailwindcss:watch'], 'r+') do |io|
+ IO.copy_stream(io, $stdout)
+ end
+ rescue Interrupt
+ end
+ end
+
+ if Gem::Version.new(Puma::Const::PUMA_VERSION) >= Gem::Version.new("7")
+ launcher.events.after_stopped { stop_tailwind }
+ else
+ launcher.events.on_stopped { stop_tailwind }
+ end
+
+ in_background do
+ monitor_tailwind
+ end
+ end
+
+ private
+ def stop_tailwind
+ Process.waitpid(tailwind_pid, Process::WNOHANG)
+ log "Stopping tailwind..."
+ Process.kill(:INT, tailwind_pid) if tailwind_pid
+ Process.wait(tailwind_pid)
+ rescue Errno::ECHILD, Errno::ESRCH
+ end
+
+ def monitor_puma
+ monitor(:puma_dead?, "Detected Puma has gone away, stopping tailwind...")
+ end
+
+ def monitor_tailwind
+ monitor(:tailwind_dead?, "Detected tailwind has gone away, stopping Puma...")
+ end
+
+ def monitor(process_dead, message)
+ loop do
+ if send(process_dead)
+ log message
+ Process.kill(:INT, $$)
+ break
+ end
+ sleep 2
+ end
+ end
+
+ def tailwind_dead?
+ Process.waitpid(tailwind_pid, Process::WNOHANG)
+ false
+ rescue Errno::ECHILD, Errno::ESRCH
+ true
+ end
+
+ def puma_dead?
+ Process.ppid != puma_pid
+ end
+
+ def log(...)
+ log_writer.log(...)
+ end
+end
diff --git a/lib/tailwindcss-rails.rb b/lib/tailwindcss-rails.rb
index 4a1b4570..bdfb592d 100644
--- a/lib/tailwindcss-rails.rb
+++ b/lib/tailwindcss-rails.rb
@@ -1,5 +1,7 @@
module Tailwindcss
end
-require "tailwindcss/version"
-require "tailwindcss/engine"
+require_relative "tailwindcss/version"
+require_relative "tailwindcss/engines"
+require_relative "tailwindcss/engine"
+require_relative "tailwindcss/commands"
diff --git a/lib/tailwindcss/commands.rb b/lib/tailwindcss/commands.rb
new file mode 100644
index 00000000..9c910de8
--- /dev/null
+++ b/lib/tailwindcss/commands.rb
@@ -0,0 +1,42 @@
+require "tailwindcss/ruby"
+
+module Tailwindcss
+ module Commands
+ class << self
+ def compile_command(debug: false, **kwargs)
+ debug = ENV["TAILWINDCSS_DEBUG"].present? if ENV.key?("TAILWINDCSS_DEBUG")
+ rails_root = defined?(Rails) ? Rails.root : Pathname.new(Dir.pwd)
+
+ command = [
+ Tailwindcss::Ruby.executable(**kwargs),
+ "-i", rails_root.join("app/assets/tailwind/application.css").to_s,
+ "-o", rails_root.join("app/assets/builds/tailwind.css").to_s,
+ ]
+
+ command << "--minify" unless (debug || rails_css_compressor?)
+
+ postcss_path = rails_root.join("postcss.config.js")
+ command += ["--postcss", postcss_path.to_s] if File.exist?(postcss_path)
+
+ command
+ end
+
+ def watch_command(always: false, **kwargs)
+ compile_command(**kwargs).tap do |command|
+ command << "-w"
+ command << "always" if always
+ end
+ end
+
+ def command_env(verbose:)
+ {}.tap do |env|
+ env["DEBUG"] = "1" if verbose
+ end
+ end
+
+ def rails_css_compressor?
+ defined?(Rails) && Rails&.application&.config&.assets&.css_compressor.present?
+ end
+ end
+ end
+end
diff --git a/lib/tailwindcss/compressor.rb b/lib/tailwindcss/compressor.rb
deleted file mode 100644
index f8c3889f..00000000
--- a/lib/tailwindcss/compressor.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-require "tailwindcss/purger"
-
-class Tailwindcss::Compressor
- def self.instance
- @instance ||= new
- end
-
- def self.call(input)
- instance.call(input)
- end
-
- def initialize(options = {})
- @options = {
- files_with_class_names: files_with_class_names,
- only_purge: %w[ tailwind ]
- }.merge(options).freeze
- end
-
- def call(input)
- if input[:name].in?(@options[:only_purge])
- { data: Tailwindcss::Purger.purge(input[:data], keeping_class_names_from_files: @options[:files_with_class_names]) }
- else
- input[:data]
- end
- end
-
- private
- def files_with_class_names
- Rails.root.glob("app/views/**/*.*") +
- Rails.root.glob("app/helpers/**/*.rb") +
- Rails.root.glob("app/javascript/**/*.js")
- end
-end
diff --git a/lib/tailwindcss/engine.rb b/lib/tailwindcss/engine.rb
index 82986a98..7b88c5f1 100644
--- a/lib/tailwindcss/engine.rb
+++ b/lib/tailwindcss/engine.rb
@@ -1,28 +1,19 @@
require "rails"
-require "tailwindcss/compressor"
module Tailwindcss
class Engine < ::Rails::Engine
- initializer "tailwindcss.compressor" do
- Sprockets.register_compressor "text/css", :purger, Tailwindcss::Compressor
- end
-
- initializer "tailwindcss.assets" do
- Rails.application.config.assets.precompile += %w( tailwind.css inter-font.css )
- end
-
initializer "tailwindcss.disable_generator_stylesheets" do
Rails.application.config.generators.stylesheets = false
end
- initializer "tailwindcss.disable_assets_cache" do
- Rails.application.config.assets.configure do |env|
- env.cache = ActiveSupport::Cache.lookup_store(:null_store)
- end if Rails.env.production?
+ initializer "tailwindcss.exclude_asset_path", before: "propshaft.append_assets_path" do
+ if Rails.application.config.assets.excluded_paths # the app may not be using Propshaft
+ Rails.application.config.assets.excluded_paths << Rails.root.join("app/assets/tailwind")
+ end
end
- config.app_generators do |g|
- g.template_engine :tailwindcss
- end
+ config.app_generators do |g|
+ g.template_engine :tailwindcss
+ end
end
end
diff --git a/lib/tailwindcss/engines.rb b/lib/tailwindcss/engines.rb
new file mode 100644
index 00000000..90bd6d59
--- /dev/null
+++ b/lib/tailwindcss/engines.rb
@@ -0,0 +1,23 @@
+module Tailwindcss
+ module Engines
+ class << self
+ def bundle
+ FileUtils.mkdir_p(Rails.root.join("app/assets/builds/tailwind"))
+ Rails::Engine.subclasses.select do |engine|
+ engine.root.join("app/assets/tailwind/#{engine.engine_name}/engine.css").exist?
+ end.each do |engine|
+ file_path = Rails.root.join("app/assets/builds/tailwind/#{engine.engine_name}.css")
+ FileUtils.rm(file_path) if File.exist?(file_path)
+ template = <<~TEMPLATE
+ /* DO NOT MODIFY THIS FILE, it was auto-generated by tailwindcss-rails */
+
+ @import "#{engine.root.join("app/assets/tailwind/#{engine.engine_name}/engine.css")}";
+ TEMPLATE
+ File.open(file_path, 'w') do |file|
+ file.puts template
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/tailwindcss/purger.rb b/lib/tailwindcss/purger.rb
deleted file mode 100644
index 1c535e41..00000000
--- a/lib/tailwindcss/purger.rb
+++ /dev/null
@@ -1,124 +0,0 @@
-# frozen_string_literal: true
-
-class Tailwindcss::Purger
- CLASS_NAME_PATTERN = /((?:[:A-Za-z0-9_-]+[\\\/:A-Za-z0-9_-]*[0-3][\\.]*5)|(?:[A-Za-z0-9_-]+[\\\/:A-Za-z0-9_-]*))/
-
- CLASS_BREAK = /(?![-_a-z0-9\\])/i # `\b` for class selectors
-
- COMMENT = /#{Regexp.escape "/*"}.*?#{Regexp.escape "*/"}/m
- COMMENTS_AND_BLANK_LINES = /\A(?:^#{COMMENT}?[ \t]*(?:\n|\z)|[ \t]*#{COMMENT})+/
-
- AT_RULE = /@[^{]+/
- CLASSLESS_SELECTOR_GROUP = /[^.{]+/
- CLASSLESS_BEGINNING_OF_BLOCK = /\A\s*(?:#{AT_RULE}|#{CLASSLESS_SELECTOR_GROUP})\{\n?/
-
- SELECTOR_GROUP = /[^{]+/
- BEGINNING_OF_BLOCK = /\A#{SELECTOR_GROUP}\{\n?/
-
- PROPERTY_NAME = /[-_a-z0-9]+/i
- PROPERTY_VALUE = /(?:[^;]|;\S)+/
- PROPERTIES = /\A(?:\s*#{PROPERTY_NAME}:#{PROPERTY_VALUE};\n?)+/
-
- END_OF_BLOCK = /\A\s*\}\n?/
-
- attr_reader :keep_these_class_names
-
- class << self
- def purge(input, keeping_class_names_from_files:)
- new(extract_class_names_from(keeping_class_names_from_files)).purge(input)
- end
-
- def extract_class_names(string)
- string.scan(CLASS_NAME_PATTERN).flatten.uniq.sort!
- end
-
- def extract_class_names_from(files)
- Array(files).flat_map { |file| extract_class_names(file.read) }.uniq.sort!
- end
-
- def escape_class_selector(class_name)
- class_name.gsub(/\A\d|[^-_a-z0-9]/, '\\\\\0')
- end
- end
-
- def initialize(keep_these_class_names)
- @keep_these_class_names = keep_these_class_names
- end
-
- def purge(input)
- conveyor = Conveyor.new(input)
-
- until conveyor.done?
- conveyor.discard(COMMENTS_AND_BLANK_LINES) \
- or conveyor.conditionally_keep(PROPERTIES) { conveyor.staged_output.last != "" } \
- or conveyor.conditionally_keep(END_OF_BLOCK) { not conveyor.staged_output.pop } \
- or conveyor.stage_output(CLASSLESS_BEGINNING_OF_BLOCK) \
- or conveyor.stage_output(BEGINNING_OF_BLOCK) { |match| purge_beginning_of_block(match.to_s) } \
- or raise "infinite loop"
- end
-
- conveyor.output
- end
-
- private
- def keep_these_selectors_pattern
- @keep_these_selectors_pattern ||= begin
- escaped_classes = @keep_these_class_names.map { |name| Regexp.escape self.class.escape_class_selector(name) }
- /(?:\A|,)[^.,{]*(?:[.](?:#{escaped_classes.join("|")})#{CLASS_BREAK}[^.,{]*)*(?=[,{])/
- end
- end
-
- def purge_beginning_of_block(string)
- purged = string.scan(keep_these_selectors_pattern).join
- unless purged.empty?
- purged.sub!(/\A,\s*/, "")
- purged.rstrip!
- purged << " {\n"
- end
- purged
- end
-
- class Conveyor
- attr_reader :output, :staged_output
-
- def initialize(input, output = +"")
- @input = input
- @output = output
- @staged_output = []
- end
-
- def consume(pattern)
- match = pattern.match(@input)
- @input = match.post_match if match
- match
- end
- alias :discard :consume
-
- def stage_output(pattern)
- if match = consume(pattern)
- string = block_given? ? (yield match) : match.to_s
- @staged_output << string
- string
- end
- end
-
- def keep(pattern)
- if match = consume(pattern)
- string = block_given? ? (yield match) : match.to_s
- @output << @staged_output.shift until @staged_output.empty?
- @output << string
- string
- end
- end
-
- def conditionally_keep(pattern)
- keep(pattern) do |match|
- (yield match) ? match.to_s : (break "")
- end
- end
-
- def done?
- @input.empty?
- end
- end
-end
diff --git a/lib/tailwindcss/upstream.rb b/lib/tailwindcss/upstream.rb
new file mode 100644
index 00000000..358db1c0
--- /dev/null
+++ b/lib/tailwindcss/upstream.rb
@@ -0,0 +1,6 @@
+module Tailwindcss
+ module Upstream
+ VERSION = Tailwindcss::Ruby::Upstream::VERSION
+ deprecate_constant :VERSION
+ end
+end
diff --git a/lib/tailwindcss/version.rb b/lib/tailwindcss/version.rb
index 0da3943b..81738c04 100644
--- a/lib/tailwindcss/version.rb
+++ b/lib/tailwindcss/version.rb
@@ -1,3 +1,3 @@
module Tailwindcss
- VERSION = "0.5.4"
+ VERSION = "4.4.0"
end
diff --git a/lib/tasks/build.rake b/lib/tasks/build.rake
new file mode 100644
index 00000000..539a8df9
--- /dev/null
+++ b/lib/tasks/build.rake
@@ -0,0 +1,43 @@
+namespace :tailwindcss do
+ desc "Build your Tailwind CSS"
+ task build: [:environment, :engines] do |_, args|
+ debug = args.extras.include?("debug")
+ verbose = args.extras.include?("verbose")
+
+ command = Tailwindcss::Commands.compile_command(debug: debug)
+ env = Tailwindcss::Commands.command_env(verbose: verbose)
+ puts "Running: #{Shellwords.join(command)}" if verbose
+
+ system(env, *command, exception: true)
+ end
+
+ desc "Watch and build your Tailwind CSS on file changes"
+ task watch: [:environment, :engines] do |_, args|
+ debug = args.extras.include?("debug")
+ always = args.extras.include?("always")
+ verbose = args.extras.include?("verbose")
+
+ command = Tailwindcss::Commands.watch_command(always: always, debug: debug)
+ env = Tailwindcss::Commands.command_env(verbose: verbose)
+ puts "Running: #{Shellwords.join(command)}" if verbose
+
+ system(env, *command)
+ rescue Interrupt
+ puts "Received interrupt, exiting tailwindcss:watch" if args.extras.include?("verbose")
+ end
+
+ desc "Create Tailwind CSS entry point files for Rails Engines"
+ task engines: :environment do
+ Tailwindcss::Engines.bundle
+ end
+end
+
+Rake::Task["assets:precompile"].enhance(["tailwindcss:build"])
+
+if Rake::Task.task_defined?("test:prepare")
+ Rake::Task["test:prepare"].enhance(["tailwindcss:build"])
+elsif Rake::Task.task_defined?("spec:prepare")
+ Rake::Task["spec:prepare"].enhance(["tailwindcss:build"])
+elsif Rake::Task.task_defined?("db:test:prepare")
+ Rake::Task["db:test:prepare"].enhance(["tailwindcss:build"])
+end
diff --git a/lib/tasks/clobber.rake b/lib/tasks/clobber.rake
new file mode 100644
index 00000000..ef9aaf15
--- /dev/null
+++ b/lib/tasks/clobber.rake
@@ -0,0 +1,8 @@
+namespace :tailwindcss do
+ desc "Remove CSS builds"
+ task :clobber do
+ rm_rf Dir["app/assets/builds/[^.]*.css"], verbose: false
+ end
+end
+
+Rake::Task["assets:clobber"].enhance(["tailwindcss:clobber"])
diff --git a/lib/tasks/install.rake b/lib/tasks/install.rake
new file mode 100644
index 00000000..f94ec2a1
--- /dev/null
+++ b/lib/tasks/install.rake
@@ -0,0 +1,6 @@
+namespace :tailwindcss do
+ desc "Install Tailwind CSS into the app"
+ task :install do
+ system "#{RbConfig.ruby} ./bin/rails app:template LOCATION=#{File.expand_path("../install/install_tailwindcss.rb", __dir__)}"
+ end
+end
diff --git a/lib/tasks/tailwindcss_tasks.rake b/lib/tasks/tailwindcss_tasks.rake
deleted file mode 100644
index f568e76f..00000000
--- a/lib/tasks/tailwindcss_tasks.rake
+++ /dev/null
@@ -1,25 +0,0 @@
-namespace :tailwindcss do
- desc "Install Tailwind CSS into the app"
- task :install do
- system "#{RbConfig.ruby} ./bin/rails app:template LOCATION=#{File.expand_path("../install/tailwindcss.rb", __dir__)}"
- end
-
- desc "Show the list of class names being kept in Tailwind CSS"
- task :keeping_class_names do
- puts Tailwindcss::Purger.extract_class_names_from(default_files_with_class_names)
- end
-
- desc "Show Tailwind CSS styles that are left after purging unused class names"
- task :preview_purge do
- puts Tailwindcss::Purger.purge tailwind_css, keeping_class_names_from_files: default_files_with_class_names
- end
-end
-
-def default_files_with_class_names
- Rails.root.glob("app/views/**/*.*") + Rails.root.glob("app/helpers/**/*.rb")
-end
-
-def tailwind_css
- Pathname.new(__FILE__).join("../../../app/assets/stylesheets/tailwind.css").read
-end
-
diff --git a/lib/tasks/upgrade.rake b/lib/tasks/upgrade.rake
new file mode 100644
index 00000000..05047523
--- /dev/null
+++ b/lib/tasks/upgrade.rake
@@ -0,0 +1,6 @@
+namespace :tailwindcss do
+ desc "Upgrade app from Tailwind CSS v3 to v4"
+ task :upgrade do
+ system "#{RbConfig.ruby} ./bin/rails app:template LOCATION=#{File.expand_path("../install/upgrade_tailwindcss.rb", __dir__)}"
+ end
+end
diff --git a/package.json b/package.json
deleted file mode 100644
index 67edea95..00000000
--- a/package.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "dependencies": {
- "@tailwindcss/aspect-ratio": "^0.2.1",
- "@tailwindcss/forms": "^0.3.3",
- "@tailwindcss/typography": "^0.4.1",
- "autoprefixer": "^10.3.1",
- "tailwindcss": "^2.2.7"
- },
- "scripts": {
- "build": "npx tailwind build > ./app/assets/stylesheets/tailwind.css"
- }
-}
diff --git a/tailwind.config.js b/tailwind.config.js
deleted file mode 100644
index c9d8b42c..00000000
--- a/tailwind.config.js
+++ /dev/null
@@ -1,17 +0,0 @@
-const defaultTheme = require('tailwindcss/defaultTheme')
-
-module.exports = {
- darkMode: 'media',
- theme: {
- extend: {
- fontFamily: {
- sans: ['Inter var', ...defaultTheme.fontFamily.sans],
- },
- },
- },
- plugins: [
- require('@tailwindcss/forms'),
- require('@tailwindcss/aspect-ratio'),
- require('@tailwindcss/typography'),
- ]
-}
diff --git a/tailwindcss-rails.gemspec b/tailwindcss-rails.gemspec
index ccedc7b5..45c19c28 100644
--- a/tailwindcss-rails.gemspec
+++ b/tailwindcss-rails.gemspec
@@ -14,7 +14,24 @@ Gem::Specification.new do |spec|
"rubygems_mfa_required" => "true"
}
+ spec.required_rubygems_version = ">= 3.2.0" # for Gem::Platform#match_gem?
+
spec.files = Dir["{app,lib}/**/*", "MIT-LICENSE", "Rakefile", "README.md"]
- spec.add_dependency "railties", ">= 6.0.0"
+ spec.add_dependency "railties", ">= 7.0.0"
+ spec.add_dependency "tailwindcss-ruby", "~> 4.0"
+
+ # TODO: remove this after a suitable period of time after the v4.0.0 release.
+ spec.post_install_message = <<~TEXT
+ == Upgrading to Tailwind CSS v4 ==
+
+ If you are upgrading to tailwindcss-rails 4.x, please read the upgrade guide at:
+
+ https://github.com/rails/tailwindcss-rails/blob/main/README.md#upgrading-your-application-from-tailwind-v3-to-v4
+
+ If you're not ready to upgrade yet, please pin to version 3 in your Gemfile:
+
+ gem "tailwindcss-rails", "~> 3.3.1"
+
+ TEXT
end
diff --git a/test/fixtures/files/placeholders.html.erb b/test/fixtures/files/placeholders.html.erb
deleted file mode 100644
index aa4055ec..00000000
--- a/test/fixtures/files/placeholders.html.erb
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/test/fixtures/files/placeholders.html.haml b/test/fixtures/files/placeholders.html.haml
deleted file mode 100644
index 2f1d542a..00000000
--- a/test/fixtures/files/placeholders.html.haml
+++ /dev/null
@@ -1 +0,0 @@
-%input.placeholder-transparent.focus-within:outline-black/
\ No newline at end of file
diff --git a/test/fixtures/files/placeholders.html.slim b/test/fixtures/files/placeholders.html.slim
deleted file mode 100644
index b25f7659..00000000
--- a/test/fixtures/files/placeholders.html.slim
+++ /dev/null
@@ -1 +0,0 @@
-input.placeholder-transparent.focus-within:outline-black
\ No newline at end of file
diff --git a/test/fixtures/files/show.html.erb b/test/fixtures/files/show.html.erb
deleted file mode 100644
index f8e1118e..00000000
--- a/test/fixtures/files/show.html.erb
+++ /dev/null
@@ -1,209 +0,0 @@
-
-
-
-
Transactions
-
-
- Lorem ipsum dolor sit amet consect adipisicing elit. Possimus magnam voluptatum cupiditate veritatis in accusamus quisquam.
-
-
-
-
-
-
-
-
-
-
- Competitive exchange rates
-
- -
- Lorem ipsum, dolor sit amet consectetur adipisicing elit. Maiores impedit perferendis suscipit eaque, iste dolor cupiditate blanditiis ratione.
-
-
-
-
-
-
-
-
-
- No hidden fees
-
- -
- Lorem ipsum, dolor sit amet consectetur adipisicing elit. Maiores impedit perferendis suscipit eaque, iste dolor cupiditate blanditiis ratione.
-
-
-
-
-
-
-
-
-
- Transfers are instant
-
- -
- Lorem ipsum, dolor sit amet consectetur adipisicing elit. Maiores impedit perferendis suscipit eaque, iste dolor cupiditate blanditiis ratione.
-
-
-
-
-
-
-
-
-
- Mobile notifications
-
- -
- Lorem ipsum, dolor sit amet consectetur adipisicing elit. Maiores impedit perferendis suscipit eaque, iste dolor cupiditate blanditiis ratione.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Anim aute id magna aliqua ad ad non deserunt sunt. Qui irure qui lorem cupidatat commodo. Elit sunt amet fugiat veniam occaecat fugiat aliqua.
-
-
-
-
-
-
-
-

-
-
-
diff --git a/test/fixtures/files/show.html.haml b/test/fixtures/files/show.html.haml
deleted file mode 100644
index 010abfd3..00000000
--- a/test/fixtures/files/show.html.haml
+++ /dev/null
@@ -1,124 +0,0 @@
-.max-w-7xl.mx-auto.px-4.sm:px-6.lg:px-8{:class => "my-1.5 sm:py-0.5 translate-x-1/2"}
- .py-12.bg-white
- .max-w-7xl.mx-auto.px-4.sm:px-6.lg:px-8
- .lg:text-center
- %h2.text-base.text-indigo-600.font-semibold.tracking-wide.uppercase Transactions
- %p.mt-2.text-3xl.leading-8.font-extrabold.tracking-tight.text-gray-900.sm:text-4xl
- A better way to send money
- %p.mt-4.max-w-2xl.text-xl.text-gray-500.lg:mx-auto
- Lorem ipsum dolor sit amet consect adipisicing elit. Possimus magnam voluptatum cupiditate veritatis in accusamus quisquam.
- .mt-10
- %dl.space-y-10.md:space-y-0.md:grid.md:grid-cols-2.md:gap-x-8.md:gap-y-10
- .flex
- .flex-shrink-0
- .flex.items-center.justify-center.h-12.w-12.rounded-md.bg-blue-500.text-white
- / Heroicon name: globe-alt
- %svg.h-6.w-6{"aria-hidden" => "true", :fill => "none", :stroke => "currentColor", :viewbox => "0 0 24 24", :xmlns => "http://www.w3.org/2000/svg"}
- %path{:d => "M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9", "stroke-linecap" => "round", "stroke-linejoin" => "round", "stroke-width" => "2"}
- .ml-4
- %dt.text-lg.leading-6.font-medium.text-gray-900
- Competitive exchange rates
- %dd.mt-2.text-base.text-gray-500
- Lorem ipsum, dolor sit amet consectetur adipisicing elit. Maiores impedit perferendis suscipit eaque, iste dolor cupiditate blanditiis ratione.
- .flex
- .flex-shrink-0
- .flex.items-center.justify-center.h-12.w-12.rounded-md.bg-indigo-500.text-white
- / Heroicon name: scale
- %svg.h-6.w-6{"aria-hidden" => "true", :fill => "none", :stroke => "currentColor", :viewbox => "0 0 24 24", :xmlns => "http://www.w3.org/2000/svg"}
- %path{:d => "M3 6l3 1m0 0l-3 9a5.002 5.002 0 006.001 0M6 7l3 9M6 7l6-2m6 2l3-1m-3 1l-3 9a5.002 5.002 0 006.001 0M18 7l3 9m-3-9l-6-2m0-2v2m0 16V5m0 16H9m3 0h3", "stroke-linecap" => "round", "stroke-linejoin" => "round", "stroke-width" => "2"}
- .ml-4
- %dt.text-lg.leading-6.font-medium.text-gray-900
- No hidden fees
- %dd.mt-2.text-base.text-gray-500
- Lorem ipsum, dolor sit amet consectetur adipisicing elit. Maiores impedit perferendis suscipit eaque, iste dolor cupiditate blanditiis ratione.
- .flex
- .flex-shrink-0
- .flex.items-center.justify-center.h-12.w-12.rounded-md.bg-indigo-500.text-white
- / Heroicon name: lightning-bolt
- %svg.h-6.w-6{"aria-hidden" => "true", :fill => "none", :stroke => "currentColor", :viewbox => "0 0 24 24", :xmlns => "http://www.w3.org/2000/svg"}
- %path{:d => "M13 10V3L4 14h7v7l9-11h-7z", "stroke-linecap" => "round", "stroke-linejoin" => "round", "stroke-width" => "2"}
- .ml-4
- %dt.text-lg.leading-6.font-medium.text-gray-900
- Transfers are instant
- %dd.mt-2.text-base.text-gray-500
- Lorem ipsum, dolor sit amet consectetur adipisicing elit. Maiores impedit perferendis suscipit eaque, iste dolor cupiditate blanditiis ratione.
- .flex
- .flex-shrink-0
- .flex.items-center.justify-center.h-12.w-12.rounded-md.bg-indigo-500.text-white
- / Heroicon name: annotation
- %svg.h-6.w-6{"aria-hidden" => "true", :fill => "none", :stroke => "currentColor", :viewbox => "0 0 24 24", :xmlns => "http://www.w3.org/2000/svg"}
- %path{:d => "M7 8h10M7 12h4m1 8l-4-4H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-3l-4 4z", "stroke-linecap" => "round", "stroke-linejoin" => "round", "stroke-width" => "2"}
- .ml-4
- %dt.text-lg.leading-6.font-medium.text-gray-900
- Mobile notifications
- %dd.mt-2.text-base.text-gray-500
- Lorem ipsum, dolor sit amet consectetur adipisicing elit. Maiores impedit perferendis suscipit eaque, iste dolor cupiditate blanditiis ratione.
- .relative.bg-white.overflow-hidden
- .max-w-7xl.mx-auto
- .relative.z-10.pb-8.bg-white.sm:pb-16.md:pb-20.lg:max-w-2xl.lg:w-full.lg:pb-28.xl:pb-32
- %svg.hidden.lg:block.absolute.right-0.inset-y-0.h-full.w-48.text-white.transform{"aria-hidden" => "true", :class => "translate-x-1/2", :fill => "currentColor", :preserveaspectratio => "none", :viewbox => "0 0 100 100"}
- %polygon{:points => "50,0 100,0 50,100 0,100"}
- .relative.pt-6.px-4.sm:px-6.lg:px-8
- %nav.relative.flex.items-center.justify-between.sm:h-10.lg:justify-start{"aria-label" => "Global"}
- .flex.items-center.flex-grow.flex-shrink-0.lg:flex-grow-0
- .flex.items-center.justify-between.w-full.md:w-auto
- %a{:href => "#"}
- %span.sr-only Workflow
- %img.h-8.w-auto.sm:h-10{:src => "https://tailwindui.com/img/logos/workflow-mark-indigo-600.svg"}/
- .-mr-2.flex.items-center.md:hidden
- %button#main-menu.bg-white.rounded-md.p-2.inline-flex.items-center.justify-center.text-gray-400.hover:text-gray-500.hover:bg-gray-100.focus:outline-none.focus:ring-2.focus:ring-inset.focus:ring-indigo-500{"aria-haspopup" => "true", :type => "button"}
- %span.sr-only Open main menu
- / Heroicon name: menu
- %svg.h-6.w-6{"aria-hidden" => "true", :fill => "none", :stroke => "currentColor", :viewbox => "0 0 24 24", :xmlns => "http://www.w3.org/2000/svg"}
- %path{:d => "M4 6h16M4 12h16M4 18h16", "stroke-linecap" => "round", "stroke-linejoin" => "round", "stroke-width" => "2"}
- .hidden.md:block.md:ml-10.md:pr-4.md:space-x-8
- %a.font-medium.text-gray-500.hover:text-gray-900{:href => "#"} Product
- %a.font-medium.text-gray-500.hover:text-gray-900{:href => "#"} Features
- %a.font-medium.text-gray-500.hover:text-gray-900{:href => "#"} Marketplace
- %a.font-medium.text-gray-500.hover:text-gray-900{:href => "#"} Company
- %a.font-medium.text-indigo-600.hover:text-indigo-500{:href => "#"} Log in
- /
- Mobile menu, show/hide based on menu open state.
-
- Entering: "duration-150 ease-out"
- From: "opacity-0 scale-95"
- To: "opacity-100 scale-100"
- Leaving: "duration-100 ease-in"
- From: "opacity-100 scale-100"
- To: "opacity-0 scale-95"
- .absolute.top-0.inset-x-0.p-2.transition.transform.origin-top-right.md:hidden
- .rounded-lg.shadow-md.bg-white.ring-1.ring-black.ring-opacity-5.overflow-hidden
- .px-5.pt-4.flex.items-center.justify-between
- %div
- %img.h-8.w-auto{:alt => "", :src => "https://tailwindui.com/img/logos/workflow-mark-indigo-600.svg"}/
- .-mr-2
- %button.bg-white.rounded-md.p-2.inline-flex.items-center.justify-center.text-gray-400.hover:text-gray-500.hover:bg-gray-100.focus:outline-none.focus:ring-2.focus:ring-inset.focus:ring-indigo-500{:type => "button"}
- %span.sr-only Close main menu
- / Heroicon name: x
- %svg.h-6.w-6{"aria-hidden" => "true", :fill => "none", :stroke => "currentColor", :viewbox => "0 0 24 24", :xmlns => "http://www.w3.org/2000/svg"}
- %path{:d => "M6 18L18 6M6 6l12 12", "stroke-linecap" => "round", "stroke-linejoin" => "round", "stroke-width" => "2"}
- %div{"aria-labelledby" => "main-menu", "aria-orientation" => "vertical", :role => "menu"}
- .px-2.pt-2.pb-3.space-y-1{:role => "none"}
- %a.block.px-3.py-2.rounded-md.text-base.font-medium.text-gray-700.hover:text-gray-900.hover:bg-gray-50{:href => "#", :role => "menuitem"} Product
- %a.block.px-3.py-2.rounded-md.text-base.font-medium.text-gray-700.hover:text-gray-900.hover:bg-gray-50{:href => "#", :role => "menuitem"} Features
- %a.block.px-3.py-2.rounded-md.text-base.font-medium.text-gray-700.hover:text-gray-900.hover:bg-gray-50{:href => "#", :role => "menuitem"} Marketplace
- %a.block.px-3.py-2.rounded-md.text-base.font-medium.text-gray-700.hover:text-gray-900.hover:bg-gray-50{:href => "#", :role => "menuitem"} Company
- %div{:role => "none"}
- %a.block.w-full.px-5.py-3.text-center.font-medium.text-indigo-600.bg-gray-50.hover:bg-gray-100{:href => "#", :role => "menuitem"}
- Log in
- %main.mt-10.mx-auto.max-w-7xl.px-4.sm:mt-12.sm:px-6.md:mt-16.lg:mt-20.lg:px-8.xl:mt-28
- .sm:text-center.lg:text-left
- %h1.text-4xl.tracking-tight.font-extrabold.text-gray-900.sm:text-5xl.md:text-6xl
- %span.block.xl:inline Data to enrich your
- %span.block.text-indigo-600.xl:inline online business
- %p.mt-3.text-base.text-gray-500.sm:mt-5.sm:text-lg.sm:max-w-xl.sm:mx-auto.md:mt-5.md:text-xl.lg:mx-0
- Anim aute id magna aliqua ad ad non deserunt sunt. Qui irure qui lorem cupidatat commodo. Elit sunt amet fugiat veniam occaecat fugiat aliqua.
- .mt-5.sm:mt-8.sm:flex.sm:justify-center.lg:justify-start
- .rounded-md.shadow
- %a.w-full.flex.items-center.justify-center.px-8.py-3.border.border-transparent.text-base.font-medium.rounded-md.text-white.bg-indigo-600.hover:bg-indigo-700.md:py-4.md:text-lg.md:px-10{:href => "#"}
- Get started
- .mt-3.sm:mt-0.sm:ml-3
- %a.w-full.flex.items-center.justify-center.px-8.py-3.border.border-transparent.text-base.font-medium.rounded-md.text-indigo-700.bg-indigo-100.hover:bg-indigo-200.md:py-4.md:text-lg.md:px-10{:href => "#"}
- Live demo
- .lg:absolute.lg:inset-y-0.lg:right-0{:class => "lg:w-1/2"}
- %img.h-56.w-full.object-cover.sm:h-72.md:h-96.lg:w-full.lg:h-full{:alt => "", :src => "https://images.unsplash.com/photo-1551434678-e076c223a692?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2850&q=80"}/
\ No newline at end of file
diff --git a/test/fixtures/files/show.html.slim b/test/fixtures/files/show.html.slim
deleted file mode 100644
index 04b2eb9e..00000000
--- a/test/fixtures/files/show.html.slim
+++ /dev/null
@@ -1,124 +0,0 @@
-.py-12.bg-white.translate-x-1/2 class="my-1.5 sm:py-0.5"
- .max-w-7xl.mx-auto.px-4.sm:px-6.lg:px-8
- .lg:text-center
- h2.text-base.text-indigo-600.font-semibold.tracking-wide.uppercase
- | Transactions
- p.mt-2.text-3xl.leading-8.font-extrabold.tracking-tight.text-gray-900.sm:text-4xl
- | A better way to send money
- p.mt-4.max-w-2xl.text-xl.text-gray-500.lg:mx-auto
- | Lorem ipsum dolor sit amet consect adipisicing elit. Possimus magnam voluptatum cupiditate veritatis in accusamus quisquam.
- .mt-10
- dl.space-y-10.md:space-y-0.md:grid.md:grid-cols-2.md:gap-x-8.md:gap-y-10
-
- .flex
- .flex-shrink-0
- .flex.items-center.justify-center.h-12.w-12.rounded-md.bg-blue-500.text-white
- svg.h-6.w-6[xmlns="http://www.w3.org/2000/svg" fill="none" viewbox="0 0 24 24" stroke="currentColor" aria-hidden="true"]
- path[stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9"]
- .ml-4
- dt.text-lg.leading-6.font-medium.text-gray-900
- | Competitive exchange rates
- dd.mt-2.text-base.text-gray-500
- | Lorem ipsum, dolor sit amet consectetur adipisicing elit. Maiores impedit perferendis suscipit eaque, iste dolor cupiditate blanditiis ratione.
- .flex
- .flex-shrink-0
- .flex.items-center.justify-center.h-12.w-12.rounded-md.bg-indigo-500.text-white
- svg.h-6.w-6[xmlns="http://www.w3.org/2000/svg" fill="none" viewbox="0 0 24 24" stroke="currentColor" aria-hidden="true"]
- path[stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 6l3 1m0 0l-3 9a5.002 5.002 0 006.001 0M6 7l3 9M6 7l6-2m6 2l3-1m-3 1l-3 9a5.002 5.002 0 006.001 0M18 7l3 9m-3-9l-6-2m0-2v2m0 16V5m0 16H9m3 0h3"]
- .ml-4
- dt.text-lg.leading-6.font-medium.text-gray-900
- | No hidden fees
- dd.mt-2.text-base.text-gray-500
- | Lorem ipsum, dolor sit amet consectetur adipisicing elit. Maiores impedit perferendis suscipit eaque, iste dolor cupiditate blanditiis ratione.
- .flex
- .flex-shrink-0
- .flex.items-center.justify-center.h-12.w-12.rounded-md.bg-indigo-500.text-white
- svg.h-6.w-6[xmlns="http://www.w3.org/2000/svg" fill="none" viewbox="0 0 24 24" stroke="currentColor" aria-hidden="true"]
- path[stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"]
- .ml-4
- dt.text-lg.leading-6.font-medium.text-gray-900
- | Transfers are instant
- dd.mt-2.text-base.text-gray-500
- | Lorem ipsum, dolor sit amet consectetur adipisicing elit. Maiores impedit perferendis suscipit eaque, iste dolor cupiditate blanditiis ratione.
- .flex
- .flex-shrink-0
- .flex.items-center.justify-center.h-12.w-12.rounded-md.bg-indigo-500.text-white
- svg.h-6.w-6[xmlns="http://www.w3.org/2000/svg" fill="none" viewbox="0 0 24 24" stroke="currentColor" aria-hidden="true"]
- path[stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 8h10M7 12h4m1 8l-4-4H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-3l-4 4z"]
- .ml-4
- dt.text-lg.leading-6.font-medium.text-gray-900
- | Mobile notifications
- dd.mt-2.text-base.text-gray-500
- | Lorem ipsum, dolor sit amet consectetur adipisicing elit. Maiores impedit perferendis suscipit eaque, iste dolor cupiditate blanditiis ratione.
-.relative.bg-white.overflow-hidden
- .max-w-7xl.mx-auto
- .relative.z-10.pb-8.bg-white.sm:pb-16.md:pb-20.lg:max-w-2xl.lg:w-full.lg:pb-28.xl:pb-32
- svg.hidden.lg:block.absolute.right-0.inset-y-0.h-full.w-48.text-white.transform.translate-x-1/2[fill="currentColor" viewbox="0 0 100 100" preserveaspectratio="none" aria-hidden="true"]
- polygon[points="50,0 100,0 50,100 0,100"]
- .relative.pt-6.px-4.sm:px-6.lg:px-8
- nav.relative.flex.items-center.justify-between.sm:h-10.lg:justify-start[aria-label="Global"]
- .flex.items-center.flex-grow.flex-shrink-0.lg:flex-grow-0
- .flex.items-center.justify-between.w-full.md:w-auto
- a[href="#"]
- span.sr-only
- | Workflow
- img.h-8.w-auto.sm:h-10[src="https://tailwindui.com/img/logos/workflow-mark-indigo-600.svg"]
- .-mr-2.flex.items-center.md:hidden
- button#main-menu.bg-white.rounded-md.p-2.inline-flex.items-center.justify-center.text-gray-400.hover:text-gray-500.hover:bg-gray-100.focus:outline-none.focus:ring-2.focus:ring-inset.focus:ring-indigo-500[type="button" aria-haspopup="true"]
- span.sr-only
- | Open main menu
- svg.h-6.w-6[xmlns="http://www.w3.org/2000/svg" fill="none" viewbox="0 0 24 24" stroke="currentColor" aria-hidden="true"]
- path[stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"]
- .hidden.md:block.md:ml-10.md:pr-4.md:space-x-8
- a.font-medium.text-gray-500.hover:text-gray-900[href="#"]
- | Product
- a.font-medium.text-gray-500.hover:text-gray-900[href="#"]
- | Features
- a.font-medium.text-gray-500.hover:text-gray-900[href="#"]
- | Marketplace
- a.font-medium.text-gray-500.hover:text-gray-900[href="#"]
- | Company
- a.font-medium.text-indigo-600.hover:text-indigo-500[href="#"]
- | Log in
- .absolute.top-0.inset-x-0.p-2.transition.transform.origin-top-right.md:hidden
- .rounded-lg.shadow-md.bg-white.ring-1.ring-black.ring-opacity-5.overflow-hidden
- .px-5.pt-4.flex.items-center.justify-between
- div
- img.h-8.w-auto[src="https://tailwindui.com/img/logos/workflow-mark-indigo-600.svg" alt=""]
- .-mr-2
- button.bg-white.rounded-md.p-2.inline-flex.items-center.justify-center.text-gray-400.hover:text-gray-500.hover:bg-gray-100.focus:outline-none.focus:ring-2.focus:ring-inset.focus:ring-indigo-500[type="button"]
- span.sr-only
- | Close main menu
- svg.h-6.w-6[xmlns="http://www.w3.org/2000/svg" fill="none" viewbox="0 0 24 24" stroke="currentColor" aria-hidden="true"]
- path[stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"]
- div[role="menu" aria-orientation="vertical" aria-labelledby="main-menu"]
- .px-2.pt-2.pb-3.space-y-1[role="none"]
- a.block.px-3.py-2.rounded-md.text-base.font-medium.text-gray-700.hover:text-gray-900.hover:bg-gray-50[href="#" role="menuitem"]
- | Product
- a.block.px-3.py-2.rounded-md.text-base.font-medium.text-gray-700.hover:text-gray-900.hover:bg-gray-50[href="#" role="menuitem"]
- | Features
- a.block.px-3.py-2.rounded-md.text-base.font-medium.text-gray-700.hover:text-gray-900.hover:bg-gray-50[href="#" role="menuitem"]
- | Marketplace
- a.block.px-3.py-2.rounded-md.text-base.font-medium.text-gray-700.hover:text-gray-900.hover:bg-gray-50[href="#" role="menuitem"]
- | Company
- div[role="none"]
- a.block.w-full.px-5.py-3.text-center.font-medium.text-indigo-600.bg-gray-50.hover:bg-gray-100[href="#" role="menuitem"]
- | Log in
- main.mt-10.mx-auto.max-w-7xl.px-4.sm:mt-12.sm:px-6.md:mt-16.lg:mt-20.lg:px-8.xl:mt-28
- .sm:text-center.lg:text-left
- h1.text-4xl.tracking-tight.font-extrabold.text-gray-900.sm:text-5xl.md:text-6xl
- span.block.xl:inline
- | Data to enrich your
- span.block.text-indigo-600.xl:inline
- | online business
- p.mt-3.text-base.text-gray-500.sm:mt-5.sm:text-lg.sm:max-w-xl.sm:mx-auto.md:mt-5.md:text-xl.lg:mx-0
- | Anim aute id magna aliqua ad ad non deserunt sunt. Qui irure qui lorem cupidatat commodo. Elit sunt amet fugiat veniam occaecat fugiat aliqua.
- .mt-5.sm:mt-8.sm:flex.sm:justify-center.lg:justify-start
- .rounded-md.shadow
- a.w-full.flex.items-center.justify-center.px-8.py-3.border.border-transparent.text-base.font-medium.rounded-md.text-white.bg-indigo-600.hover:bg-indigo-700.md:py-4.md:text-lg.md:px-10[href="#"]
- | Get started
- .mt-3.sm:mt-0.sm:ml-3
- a.w-full.flex.items-center.justify-center.px-8.py-3.border.border-transparent.text-base.font-medium.rounded-md.text-indigo-700.bg-indigo-100.hover:bg-indigo-200.md:py-4.md:text-lg.md:px-10[href="#"]
- | Live demo
- .lg:absolute.lg:inset-y-0.lg:right-0.lg:w-1/2
- img.h-56.w-full.object-cover.sm:h-72.md:h-96.lg:w-full.lg:h-full[src="https://images.unsplash.com/photo-1551434678-e076c223a692?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2850&q=80" alt=""]
\ No newline at end of file
diff --git a/test/fixtures/files/simple.html.erb b/test/fixtures/files/simple.html.erb
deleted file mode 100644
index db7e5696..00000000
--- a/test/fixtures/files/simple.html.erb
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
diff --git a/test/fixtures/files/simple.html.haml b/test/fixtures/files/simple.html.haml
deleted file mode 100644
index 748c17dd..00000000
--- a/test/fixtures/files/simple.html.haml
+++ /dev/null
@@ -1 +0,0 @@
-.max-w-7xl.mx-auto.px-4.sm:px-6.lg:px-8{:class => "my-1.5 sm:py-0.5 translate-x-1/2"}
\ No newline at end of file
diff --git a/test/fixtures/files/simple.html.slim b/test/fixtures/files/simple.html.slim
deleted file mode 100644
index f3549155..00000000
--- a/test/fixtures/files/simple.html.slim
+++ /dev/null
@@ -1 +0,0 @@
-.max-w-7xl.mx-auto.px-4.sm:px-6.lg:px-8.translate-x-1/2 class="my-1.5 sm:py-0.5"
\ No newline at end of file
diff --git a/test/integration/user_install_test.sh b/test/integration/user_install_test.sh
new file mode 100755
index 00000000..46b50560
--- /dev/null
+++ b/test/integration/user_install_test.sh
@@ -0,0 +1,103 @@
+#! /usr/bin/env bash
+# reproduce the documented user journey for installing and running tailwindcss-rails
+# this is run in the CI pipeline, non-zero exit code indicates a failure
+
+set -o pipefail
+set -eux
+
+# set up dependencies
+gem install bcrypt # it's complicated, see Rails 7549ba77. can probably be removed once Rails 8.0 is EOL.
+rm -f Gemfile.lock
+bundle remove actionmailer || true
+bundle remove rails || true
+rm -f Gemfile.lock
+bundle add rails --skip-install ${RAILSOPTS:-}
+bundle install --prefer-local
+bundle exec rails -v
+
+# do our work a directory with spaces in the name (#176, #184)
+rm -rf "My Workspace"
+mkdir "My Workspace"
+pushd "My Workspace"
+
+function prepare_deps {
+ # make sure to use the same version of rails (e.g., install from git source if necessary)
+ bundle remove rails --skip-install
+ rm -f Gemfile.lock
+ bundle add rails --skip-install ${RAILSOPTS:-}
+
+ # use the tailwindcss-rails under test
+ bundle add tailwindcss-rails --skip-install --path="../.."
+ bundle add tailwindcss-ruby --skip-install ${TAILWINDCSSOPTS:-}
+ bundle install --prefer-local
+ bundle show --paths | fgrep tailwind
+ bundle binstubs --all
+}
+
+function install_tailwindcss {
+ # install tailwindcss
+ bin/rails tailwindcss:install
+
+ # TEST: tailwind was installed correctly
+ grep -q "
> Rakefile
+task :still_here do
+ puts "Rake process did not exit early"
+end
+EOF
+
+cat >> app/assets/tailwind/application.css < "Rails 8.0.0.beta" ]] ; then
+ # TEST: presence of the generated file
+ bin/rails generate authentication
+ grep -q PasswordsController app/controllers/passwords_controller.rb
+fi
+
+# TEST: doesn't fail when not generating system tests
+bin/rails generate scaffold memo title:string body:text published:boolean --system-tests=false
+grep -q "Show" app/views/memos/index.html.erb
+
+# TEST: presence of the generated file
+bin/rails generate scaffold post title:string body:text published:boolean --system-tests=true
+grep -q "Show" app/views/posts/index.html.erb
+
+# TEST: the "accept_confirm" system test change was applied cleanly
+grep -q "accept_confirm { click_on \"Destroy this post\"" test/system/posts_test.rb
+
+# TEST: contents of the css file
+bin/rails tailwindcss:build[verbose]
+grep -q "py-2" app/assets/builds/tailwind.css
+
+# TEST: contents include application.css directives
+grep -q "#abc12399" app/assets/builds/tailwind.css
+
+# Application variation #2 ----------------------------------------
+popd
+bundle exec rails new test-install2 --skip-bundle --skip-system-test
+pushd test-install2
+
+prepare_deps
+install_tailwindcss
+
+# TEST: presence of the generated file
+# TEST: nothing blew up without system tests, https://github.com/rails/tailwindcss-rails/issues/559
+bin/rails generate scaffold post title:string body:text published:boolean
+grep -q "Show" app/views/posts/index.html.erb
+
+echo "OK"
diff --git a/test/integration/user_upgrade_test.sh b/test/integration/user_upgrade_test.sh
new file mode 100755
index 00000000..ae4c6852
--- /dev/null
+++ b/test/integration/user_upgrade_test.sh
@@ -0,0 +1,93 @@
+#! /usr/bin/env bash
+# reproduce the documented user journey for installing and running tailwindcss-rails
+# this is run in the CI pipeline, non-zero exit code indicates a failure
+
+set -o pipefail
+set -eux
+
+# set up dependencies
+gem install bcrypt # it's complicated, see Rails 7549ba77. can probably be removed once Rails 8.0 is EOL.
+rm -f Gemfile.lock
+bundle remove actionmailer || true
+bundle remove rails || true
+rm -f Gemfile.lock
+bundle add rails --skip-install ${RAILSOPTS:-}
+bundle install --prefer-local
+
+# do our work a directory with spaces in the name (#176, #184)
+rm -rf "My Workspace"
+mkdir "My Workspace"
+pushd "My Workspace"
+
+# create a rails app
+bundle exec rails -v
+bundle exec rails new test-upgrade --skip-bundle
+pushd test-upgrade
+
+# make sure to use the same version of rails (e.g., install from git source if necessary)
+bundle remove rails --skip-install
+rm -f Gemfile.lock
+bundle add rails --skip-install ${RAILSOPTS:-}
+
+# set up app with tailwindcss-rails v3 and tailwindcss-ruby v3
+bundle add tailwindcss-rails --skip-install --version 3.3.0
+bundle add tailwindcss-ruby --skip-install --version 3.4.17
+bundle install --prefer-local
+bundle show --paths | fgrep tailwind
+bundle binstubs --all
+
+# install tailwindcss
+bin/rails tailwindcss:install
+grep -q inter-font app/views/layouts/application.html.erb
+
+if [[ $(rails -v) > "Rails 8.0.0.beta" ]] ; then
+ # install auth templates
+ bin/rails generate authentication
+ grep -q PasswordsController app/controllers/passwords_controller.rb
+fi
+
+# install scaffold templates
+bin/rails generate scaffold post title:string body:text published:boolean
+grep -q "Show this post" app/views/posts/index.html.erb
+
+# upgrade time!
+bundle remove tailwindcss-rails --skip-install
+bundle remove tailwindcss-ruby --skip-install
+
+bundle add tailwindcss-rails --skip-install --path="../.."
+bundle add tailwindcss-ruby --skip-install ${TAILWINDCSSOPTS:---version 4.0.0}
+
+bundle install --prefer-local
+bundle show --paths | fgrep tailwind
+bundle binstubs --all
+
+# create a postcss file
+cat < config/postcss.config.js
+module.exports = {
+ plugins: {
+ autoprefixer: {},
+ },
+}
+EOF
+
+bin/rails tailwindcss:upgrade
+
+# TEST: removal of inter-font CSS
+if grep -q inter-font app/views/layouts/application.html.erb ; then
+ echo "FAIL: inter-font CSS not removed"
+ exit 1
+fi
+
+# TEST: moving the postcss file
+test ! -a config/postcss.config.js
+test -a postcss.config.js
+
+# TEST: moving application.tailwind.css
+test ! -a app/assets/stylesheets/application.tailwind.css
+test -a app/assets/tailwind/application.css
+
+# generate CSS
+bin/rails tailwindcss:build[verbose]
+grep -q "py-2" app/assets/builds/tailwind.css
+
+echo "OK"
diff --git a/test/lib/generators/tailwindcss/authentication_generator_test.rb b/test/lib/generators/tailwindcss/authentication_generator_test.rb
new file mode 100644
index 00000000..bdf712b0
--- /dev/null
+++ b/test/lib/generators/tailwindcss/authentication_generator_test.rb
@@ -0,0 +1,16 @@
+require "test_helper"
+
+if Rails::VERSION::MAJOR >= 8
+ require "generators/tailwindcss/authentication/authentication_generator"
+
+ class Tailwindcss::Generators::AuthenticationGeneratorTest < Rails::Generators::TestCase
+ tests Tailwindcss::Generators::AuthenticationGenerator
+ destination TAILWINDCSS_TEST_APP_ROOT
+
+ test "generates the new session template" do
+ run_generator
+
+ assert_file "app/views/sessions/new.html.erb"
+ end
+ end
+end
diff --git a/test/lib/generators/tailwindcss/controller_generator_test.rb b/test/lib/generators/tailwindcss/controller_generator_test.rb
index 42b67ec6..62f3b1ee 100644
--- a/test/lib/generators/tailwindcss/controller_generator_test.rb
+++ b/test/lib/generators/tailwindcss/controller_generator_test.rb
@@ -3,14 +3,45 @@
class Tailwindcss::Generators::ControllerGeneratorTest < Rails::Generators::TestCase
tests Tailwindcss::Generators::ControllerGenerator
- destination Dir.mktmpdir
+ destination TAILWINDCSS_TEST_APP_ROOT
arguments %w(Messages index show)
test "generates correct view templates" do
run_generator
- assert_file "app/views/messages/index.html.erb"
- assert_file "app/views/messages/show.html.erb"
+
+ ["index", "show"].each do |view|
+ assert_file "app/views/messages/#{view}.html.erb"
+ end
+ end
+
+ test "generates correct view templates when namespaced" do
+ run_generator ["admin/messages", "index", "show"]
+
+ ["index", "show"].each do |view|
+ assert_file "app/views/admin/messages/#{view}.html.erb"
+ end
end
-end
+ [
+ "lib/templates/erb/controller",
+ "lib/templates/tailwindcss/controller",
+ ].each do |templates_path|
+ test "overriding generator templates in #{templates_path}" do
+ override_dir = File.join(destination_root, templates_path)
+ FileUtils.mkdir_p override_dir
+ File.open(File.join(override_dir, "view.html.erb"), "w") { |f| f.puts "This is a custom template" }
+
+ # change directory because the generator adds a relative path to source_paths
+ Dir.chdir(destination_root) do
+ run_generator
+ end
+
+ ["index", "show"].each do |view|
+ assert_file "app/views/messages/#{view}.html.erb" do |body|
+ assert_match("This is a custom template", body, "index custom template should be used")
+ end
+ end
+ end
+ end
+end
diff --git a/test/lib/generators/tailwindcss/mailer_generator_test.rb b/test/lib/generators/tailwindcss/mailer_generator_test.rb
index db604bd3..e6fa61cc 100644
--- a/test/lib/generators/tailwindcss/mailer_generator_test.rb
+++ b/test/lib/generators/tailwindcss/mailer_generator_test.rb
@@ -3,8 +3,8 @@
require "generators/tailwindcss/mailer/mailer_generator"
class Tailwindcss::Generators::MailerGeneratorTest < Rails::Generators::TestCase
- tests Rails::Generators::MailerGenerator
- destination Dir.mktmpdir
+ tests Tailwindcss::Generators::MailerGenerator
+ destination TAILWINDCSS_TEST_APP_ROOT
arguments %w(Notifications invoice)
@@ -20,6 +20,60 @@ class Tailwindcss::Generators::MailerGeneratorTest < Rails::Generators::TestCase
assert_match %r(app/views/notifications_mailer/invoice\.text\.erb), view
assert_match(/\= @greeting/, view)
end
+
+ assert_file "app/views/layouts/mailer.text.erb" do |view|
+ assert_match("<%= yield %>", view)
+ end
+
+ assert_file "app/views/layouts/mailer.html.erb" do |view|
+ assert_match("<%= yield %>", view)
+ end
end
-end
+ test "generates correct mailer view templates with namespace" do
+ run_generator ["admin/notifications", "invoice"]
+
+ assert_file "app/views/admin/notifications_mailer/invoice.html.erb" do |view|
+ assert_match %r(app/views/admin/notifications_mailer/invoice\.html\.erb), view
+ assert_match(/\= @greeting/, view)
+ end
+
+ assert_file "app/views/admin/notifications_mailer/invoice.text.erb" do |view|
+ assert_match %r(app/views/admin/notifications_mailer/invoice\.text\.erb), view
+ assert_match(/\= @greeting/, view)
+ end
+
+ assert_file "app/views/layouts/admin/mailer.text.erb" do |view|
+ assert_match("<%= yield %>", view)
+ end
+
+ assert_file "app/views/layouts/admin/mailer.html.erb" do |view|
+ assert_match("<%= yield %>", view)
+ end
+ end
+
+ [
+ "lib/templates/erb/mailer",
+ "lib/templates/tailwindcss/mailer",
+ ].each do |templates_path|
+ test "overriding generator templates in #{templates_path}" do
+ override_dir = File.join(destination_root, templates_path)
+ FileUtils.mkdir_p override_dir
+ File.open(File.join(override_dir, "view.html.erb"), "w") { |f| f.puts "This is a custom template" }
+ File.open(File.join(override_dir, "layout.html.erb"), "w") { |f| f.puts "This is a custom layout" }
+
+ # change directory because the generator adds a relative path to source_paths
+ Dir.chdir(destination_root) do
+ run_generator
+ end
+
+ assert_file "app/views/notifications_mailer/invoice.html.erb" do |view|
+ assert_match("This is a custom template", view)
+ end
+
+ assert_file "app/views/layouts/mailer.html.erb" do |view|
+ assert_match("This is a custom layout", view)
+ end
+ end
+ end
+end
diff --git a/test/lib/generators/tailwindcss/scaffold_generator_test.rb b/test/lib/generators/tailwindcss/scaffold_generator_test.rb
index 2973a7a4..fb7db462 100644
--- a/test/lib/generators/tailwindcss/scaffold_generator_test.rb
+++ b/test/lib/generators/tailwindcss/scaffold_generator_test.rb
@@ -3,13 +3,47 @@
class Tailwindcss::Generators::ScaffoldGeneratorTest < Rails::Generators::TestCase
tests Tailwindcss::Generators::ScaffoldGenerator
- destination Dir.mktmpdir
+ destination TAILWINDCSS_TEST_APP_ROOT
arguments %w(message title:string content:text)
- test "generates correct view templates" do
+ test "generates view templates" do
run_generator
- %w(index edit new show _form _message).each { |view| assert_file "app/views/messages/#{view}.html.erb" }
+ %w(index edit new show _form _message).each do |view|
+ assert_file "app/views/messages/#{view}.html.erb"
+ end
+ end
+
+ test "generates view templates with namespace" do
+ run_generator [ "admin/role", "name:string", "description:string" ]
+
+ %w(index edit new show _form _role).each do |view|
+ assert_file "app/views/admin/roles/#{view}.html.erb"
+ end
+ end
+
+ [
+ "lib/templates/tailwindcss/scaffold",
+ "lib/templates/erb/scaffold",
+ ].each do |templates_path|
+ test "overriding generator templates in #{templates_path}" do
+ override_dir = File.join(destination_root, templates_path)
+ FileUtils.mkdir_p override_dir
+ File.open(File.join(override_dir, "index.html.erb"), "w") { |f| f.puts "This is a custom template" }
+
+ # change directory because the generator adds a relative path to source_paths
+ Dir.chdir(destination_root) do
+ run_generator
+ end
+
+ %w(edit new show _form _message).each do |view|
+ assert_file "app/views/messages/#{view}.html.erb"
+ end
+
+ assert_file "app/views/messages/index.html.erb" do |body|
+ assert_match("This is a custom template", body, "index custom template should be used")
+ end
+ end
end
end
diff --git a/test/lib/tailwindcss/commands_test.rb b/test/lib/tailwindcss/commands_test.rb
new file mode 100644
index 00000000..62d1e684
--- /dev/null
+++ b/test/lib/tailwindcss/commands_test.rb
@@ -0,0 +1,121 @@
+require "test_helper"
+require "minitest/mock"
+
+class Tailwindcss::CommandsTest < ActiveSupport::TestCase
+ attr_accessor :executable
+
+ def setup
+ super
+ @executable = Tailwindcss::Ruby.executable
+ end
+
+ test ".compile_command" do
+ Rails.stub(:root, File) do # Rails.root won't work in this test suite
+ actual = Tailwindcss::Commands.compile_command
+ assert_kind_of(Array, actual)
+ assert_equal(executable, actual.first)
+ assert_includes(actual, "-i")
+ assert_includes(actual, "-o")
+ end
+ end
+
+ test ".compile_command debug flag" do
+ Rails.stub(:root, File) do # Rails.root won't work in this test suite
+ actual = Tailwindcss::Commands.compile_command
+ assert_kind_of(Array, actual)
+ assert_equal(executable, actual.first)
+ assert_includes(actual, "--minify")
+
+ actual = Tailwindcss::Commands.compile_command(debug: true)
+ assert_kind_of(Array, actual)
+ assert_equal(executable, actual.first)
+ refute_includes(actual, "--minify")
+ end
+ end
+
+ test ".compile_command debug environment variable" do
+ begin
+ Rails.stub(:root, File) do # Rails.root won't work in this test suite
+ ENV["TAILWINDCSS_DEBUG"] = ""
+ actual = Tailwindcss::Commands.compile_command
+ assert_kind_of(Array, actual)
+ assert_includes(actual, "--minify")
+
+ actual = Tailwindcss::Commands.compile_command(debug: true)
+ assert_kind_of(Array, actual)
+ assert_includes(actual, "--minify")
+
+ ENV["TAILWINDCSS_DEBUG"] = "any non-blank value"
+ actual = Tailwindcss::Commands.compile_command
+ assert_kind_of(Array, actual)
+ refute_includes(actual, "--minify")
+
+ actual = Tailwindcss::Commands.compile_command(debug: true)
+ assert_kind_of(Array, actual)
+ refute_includes(actual, "--minify")
+ end
+ ensure
+ ENV.delete('TAILWINDCSS_DEBUG')
+ end
+ end
+
+ test ".compile_command when Rails compression is on" do
+ Rails.stub(:root, File) do # Rails.root won't work in this test suite
+ Tailwindcss::Commands.stub(:rails_css_compressor?, true) do
+ actual = Tailwindcss::Commands.compile_command
+ assert_kind_of(Array, actual)
+ refute_includes(actual, "--minify")
+ end
+
+ Tailwindcss::Commands.stub(:rails_css_compressor?, false) do
+ actual = Tailwindcss::Commands.compile_command
+ assert_kind_of(Array, actual)
+ assert_includes(actual, "--minify")
+ end
+ end
+ end
+
+ test ".compile_command when postcss.config.js exists" do
+ Dir.mktmpdir do |tmpdir|
+ Rails.stub(:root, Pathname.new(tmpdir)) do # Rails.root won't work in this test suite
+ actual = Tailwindcss::Commands.compile_command
+ assert_kind_of(Array, actual)
+ assert_equal(executable, actual.first)
+ refute_includes(actual, "--postcss")
+
+ config_file = Rails.root.join("postcss.config.js")
+ FileUtils.touch(config_file)
+ actual = Tailwindcss::Commands.compile_command
+ assert_kind_of(Array, actual)
+ assert_equal(executable, actual.first)
+ assert_includes(actual, "--postcss")
+ postcss_index = actual.index("--postcss")
+ assert_equal(actual[postcss_index + 1], config_file.to_s)
+ end
+ end
+ end
+
+ test ".watch_command" do
+ Rails.stub(:root, File) do # Rails.root won't work in this test suite
+ actual = Tailwindcss::Commands.watch_command
+ assert_kind_of(Array, actual)
+ assert_equal(executable, actual.first)
+ assert_includes(actual, "-w")
+ refute_includes(actual, "-p")
+ assert_includes(actual, "--minify")
+
+ actual = Tailwindcss::Commands.watch_command(debug: true)
+ assert_kind_of(Array, actual)
+ assert_equal(executable, actual.first)
+ assert_includes(actual, "-w")
+ refute_includes(actual, "-p")
+ refute_includes(actual, "--minify")
+
+ actual = Tailwindcss::Commands.watch_command(always: true)
+ assert_kind_of(Array, actual)
+ assert_equal(executable, actual.first)
+ assert_includes(actual, "-w")
+ assert_includes(actual, "always")
+ end
+ end
+end
diff --git a/test/lib/tailwindcss/engines_test.rb b/test/lib/tailwindcss/engines_test.rb
new file mode 100644
index 00000000..f4c1b0d2
--- /dev/null
+++ b/test/lib/tailwindcss/engines_test.rb
@@ -0,0 +1,89 @@
+require "test_helper"
+require "minitest/mock"
+
+class Tailwindcss::EnginesTest < ActiveSupport::TestCase
+ def setup
+ super
+ @tmpdir_path = Pathname.new(TAILWINDCSS_TEST_APP_ROOT)
+ @builds_dir = @tmpdir_path.join("app/assets/builds/tailwind")
+ end
+
+ test "bundle creates the builds directory" do
+ Rails.stub(:root, @tmpdir_path) do
+ Tailwindcss::Engines.bundle
+ assert Dir.exist?(@builds_dir), "Expected directory #{@builds_dir} to be created"
+ end
+ end
+
+ test "bundle generates CSS files for engine's tailwind assets" do
+ Rails.stub(:root, @tmpdir_path) do
+ setup_mock_engine("mock_engine", @tmpdir_path)
+
+ Tailwindcss::Engines.bundle
+
+ css_file_path = @builds_dir.join("mock_engine.css")
+ assert File.exist?(css_file_path), "Expected file #{css_file_path} to be created"
+
+ content = File.read(css_file_path)
+ assert_match(/DO NOT MODIFY THIS FILE/, content)
+ assert_match(/@import ".*\/app\/assets\/tailwind\/mock_engine\/engine.css"/, content)
+ end
+ end
+
+ test "bundle removes existing files before generating new ones" do
+ Rails.stub(:root, @tmpdir_path) do
+ setup_mock_engine("mock_engine", @tmpdir_path)
+
+ FileUtils.mkdir_p(@builds_dir)
+ css_file_path = @builds_dir.join("mock_engine.css")
+ File.write(css_file_path, "OLD CONTENT")
+
+ Tailwindcss::Engines.bundle
+
+ content = File.read(css_file_path)
+ assert_no_match(/OLD CONTENT/, content)
+ assert_match(/DO NOT MODIFY THIS FILE/, content)
+ end
+ end
+
+ test "bundle only processes engines with tailwind assets" do
+ Rails.stub(:root, @tmpdir_path) do
+ setup_mock_engine("engine_with_assets", @tmpdir_path)
+
+ Class.new(Rails::Engine) do
+ define_singleton_method(:engine_name) { "engine_without_assets" }
+ define_singleton_method(:root) { Pathname.new(Dir.mktmpdir) }
+ end
+
+ Tailwindcss::Engines.bundle
+
+ assert File.exist?(@builds_dir.join("engine_with_assets.css")), "Expected CSS file for engine with assets"
+ refute File.exist?(@builds_dir.join("engine_without_assets.css")), "Expected no CSS file for engine without assets"
+ end
+ end
+
+ test "bundle handles multiple engines" do
+ Rails.stub(:root, @tmpdir_path) do
+ setup_mock_engine("engine1", @tmpdir_path)
+ setup_mock_engine("engine2", @tmpdir_path)
+
+ Tailwindcss::Engines.bundle
+
+ assert File.exist?(@builds_dir.join("engine1.css")), "Expected CSS file for engine1"
+ assert File.exist?(@builds_dir.join("engine2.css")), "Expected CSS file for engine2"
+ end
+ end
+
+ private
+
+ def setup_mock_engine(name, root_path)
+ tailwind_dir = root_path.join("app/assets/tailwind/#{name}")
+ FileUtils.mkdir_p(tailwind_dir)
+ File.write(tailwind_dir.join("engine.css"), "/* Test CSS */")
+
+ Class.new(Rails::Engine) do
+ define_singleton_method(:engine_name) { name }
+ define_singleton_method(:root) { root_path }
+ end
+ end
+end
diff --git a/test/purger_test.rb b/test/purger_test.rb
deleted file mode 100644
index edc75341..00000000
--- a/test/purger_test.rb
+++ /dev/null
@@ -1,206 +0,0 @@
-require "test_helper"
-
-class Tailwindcss::PurgerTest < ActiveSupport::TestCase
- test "extract class names from erb string" do
- assert_equal %w[ div class max-w-7xl mx-auto my-1.5 px-4 sm:px-6 lg:px-8 sm:py-0.5 translate-x-1/2 ].sort,
- Tailwindcss::Purger.extract_class_names(%())
- end
-
- test "extract class names from erb file" do
- assert_equal %w[ div class max-w-7xl mx-auto my-1.5 px-4 sm:px-6 lg:px-8 sm:py-0.5 translate-x-1/2 ].sort,
- Tailwindcss::Purger.extract_class_names_from(file_fixture("simple.html.erb"))
- end
-
- test "extract class names from haml string" do
- assert_equal %w[ class max-w-7xl mx-auto my-1.5 px-4 sm:px-6 lg:px-8 sm:py-0.5 translate-x-1/2 ].sort,
- Tailwindcss::Purger.extract_class_names(%(.max-w-7xl.mx-auto.px-4.sm:px-6.lg:px-8{:class => "my-1.5 sm:py-0.5 translate-x-1/2"}))
- end
-
- test "extract class names from haml file" do
- assert_equal %w[ class max-w-7xl mx-auto my-1.5 px-4 sm:px-6 lg:px-8 sm:py-0.5 translate-x-1/2 ].sort,
- Tailwindcss::Purger.extract_class_names_from(file_fixture("simple.html.haml"))
- end
-
- test "extract class names from slim string" do
- assert_equal %w[ class max-w-7xl mx-auto my-1.5 px-4 sm:px-6 lg:px-8 sm:py-0.5 translate-x-1/2 ].sort,
- Tailwindcss::Purger.extract_class_names(%(.max-w-7xl.mx-auto.px-4.sm:px-6.lg:px-8.translate-x-1/2 class="my-1.5 sm:py-0.5"))
- end
-
- test "extract class names from slim file" do
- assert_equal %w[ class max-w-7xl mx-auto my-1.5 px-4 sm:px-6 lg:px-8 sm:py-0.5 translate-x-1/2 ].sort,
- Tailwindcss::Purger.extract_class_names_from(file_fixture("simple.html.slim"))
- end
-
- test "basic purge" do
- purged = purged_tailwind_from_erb_fixtures
-
- assert purged !~ /.mt-6 \{/
-
- assert purged =~ /.mt-5 \{/
- assert purged =~ /.sm\\:px-6 \{/
- assert purged =~ /.translate-x-1\\\/2 \{/
- assert purged =~ /.mt-10 \{/
- assert purged =~ /.my-1\\.5 \{/
- assert purged =~ /.sm\\:py-0\\.5 \{/
- end
-
- test "basic haml purge" do
- purged = purged_tailwind_from_haml_fixtures
-
- assert purged !~ /.mt-6 \{/
-
- assert purged =~ /.mt-5 \{/
- assert purged =~ /.sm\\:px-6 \{/
- assert purged =~ /.translate-x-1\\\/2 \{/
- assert purged =~ /.mt-10 \{/
- assert purged =~ /.my-1\\.5 \{/
- assert purged =~ /.sm\\:py-0\\.5 \{/
- end
-
- test "basic slim purge" do
- purged = purged_tailwind_from_slim_fixtures
-
- assert purged !~ /.mt-6 \{/
-
- assert purged =~ /.mt-5 \{/
- assert purged =~ /.sm\\:px-6 \{/
- assert purged =~ /.translate-x-1\\\/2 \{/
- assert purged =~ /.mt-10 \{/
- assert purged =~ /.my-1\\.5 \{/
- assert purged =~ /.sm\\:py-0\\.5 \{/
- end
-
- test "purge handles class names that begin with a number" do
- purged = purged_tailwind(keep_these_class_names: %w[32xl:container])
-
- assert_class_selector "32xl:container", purged
- end
-
- test "purge removes selectors that aren't on the same line as their block brace" do
- purged = purged_tailwind(keep_these_class_names: %w[aspect-w-9])
-
- assert_class_selector "aspect-w-9", purged
- assert_no_class_selector "aspect-w-1", purged
- assert purged !~ /,\s*@media/
- end
-
- test "purge removes empty blocks" do
- purged = purged_tailwind_from_erb_fixtures
-
- assert purged !~ /\{\s*\}/
- end
-
- test "purge removes top-level comments" do
- purged = purged_tailwind_from_erb_fixtures
-
- assert purged !~ /^#{Regexp.escape "/*"}/
- end
-
- test "purge shouldn't remove hover or focus classes" do
- purged = purged_tailwind_from_erb_fixtures
- assert purged =~ /.hover\\\:text-gray-500\:hover \{/
- assert purged =~ /.focus\\\:outline-none\:focus \{/
- assert purged =~ /.focus-within\\\:outline-black\:focus-within \{/
- end
-
- test "purge shouldn't remove placeholder selectors" do
- purged = purged_tailwind_from file_fixture("placeholders.html.erb")
-
- assert purged =~ /.placeholder-transparent\:\:-moz-placeholder \{/
- assert purged =~ /.placeholder-transparent\:-ms-input-placeholder \{/
- assert purged =~ /.placeholder-transparent\:\:placeholder \{/
- end
-
- test "purge handles compound selectors" do
- purged = purged_tailwind(keep_these_class_names: %w[group group-hover:text-gray-500])
-
- assert_class_selector "group", purged
- assert_class_selector "group-hover:text-gray-500", purged
- assert_no_class_selector "group-hover:text-gray-100", purged
- end
-
- test "purge handles complex selector groups" do
- css = <<~CSS
- element.keep, element .keep, .red-herring.discard, .red-herring .discard {
- foo: bar;
- }
- element.discard, element .discard, .red-herring.discard, .red-herring .discard {
- baz: qux;
- }
- CSS
-
- expected = <<~CSS
- element.keep, element .keep {
- foo: bar;
- }
- CSS
-
- assert_equal expected, purged_css(css, keep_these_class_names: %w[keep red-herring])
- end
-
- test "purge handles nested blocks" do
- css = <<~CSS
- .keep {
- foo: bar;
- .discard {
- baz: qux;
- }
- .keep-nested {
- bar: foo;
- }
- }
- CSS
-
- expected = <<~CSS
- .keep {
- foo: bar;
- .keep-nested {
- bar: foo;
- }
- }
- CSS
-
- assert_equal expected, purged_css(css, keep_these_class_names: %w[keep keep-nested])
- end
-
- private
- def class_selector_pattern(class_name)
- /\.#{Regexp.escape Tailwindcss::Purger.escape_class_selector(class_name)}(?![-_a-z0-9\\])/
- end
-
- def assert_class_selector(class_name, css)
- assert css =~ class_selector_pattern(class_name)
- end
-
- def assert_no_class_selector(class_name, css)
- assert css !~ class_selector_pattern(class_name)
- end
-
- def purged_css(css, keep_these_class_names:)
- Tailwindcss::Purger.new(keep_these_class_names).purge(css)
- end
-
- def tailwind
- $tailwind ||= Pathname.new(__FILE__).join("../../app/assets/stylesheets/tailwind.css").read.freeze
- end
-
- def purged_tailwind(keep_these_class_names:)
- purged_css(tailwind, keep_these_class_names: keep_these_class_names)
- end
-
- def purged_tailwind_from_erb_fixtures
- $purged_tailwind_from_erb_fixtures ||= purged_tailwind_from Pathname(__dir__).glob("fixtures/files/*.html.erb")
- end
-
- def purged_tailwind_from_haml_fixtures
- $purged_tailwind_from_haml_fixtures ||= purged_tailwind_from Pathname(__dir__).glob("fixtures/files/*.html.haml")
- end
-
- def purged_tailwind_from_slim_fixtures
- $purged_tailwind_from_haml_fixtures ||= purged_tailwind_from Pathname(__dir__).glob("fixtures/files/*.html.slim")
- end
-
- def purged_tailwind_from files
- Tailwindcss::Purger.purge tailwind, keeping_class_names_from_files: files
- end
-end
diff --git a/test/test_helper.rb b/test/test_helper.rb
index 787ccb8f..68614219 100644
--- a/test/test_helper.rb
+++ b/test/test_helper.rb
@@ -4,11 +4,22 @@
require "rails"
require "rails/test_help"
require "debug"
-require_relative "../lib/tailwindcss-rails"
require "rails/test_unit/reporter"
Rails::TestUnitReporter.executable = "bin/test"
+TAILWINDCSS_TEST_APP_ROOT = Dir.mktmpdir
+Rails::Generators.templates_path << File.join(TAILWINDCSS_TEST_APP_ROOT, "lib/templates")
+
class ActiveSupport::TestCase
- self.file_fixture_path = File.expand_path("fixtures/files", __dir__)
+ def setup
+ FileUtils.rm_rf(TAILWINDCSS_TEST_APP_ROOT)
+ FileUtils.mkdir_p(TAILWINDCSS_TEST_APP_ROOT)
+ end
+
+ def teardown
+ FileUtils.rm_rf(TAILWINDCSS_TEST_APP_ROOT)
+ end
end
+
+require_relative "../lib/tailwindcss-rails"
diff --git a/yarn.lock b/yarn.lock
deleted file mode 100644
index 67ab893a..00000000
--- a/yarn.lock
+++ /dev/null
@@ -1,971 +0,0 @@
-# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
-# yarn lockfile v1
-
-
-"@babel/code-frame@^7.0.0":
- version "7.16.0"
- resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.0.tgz#0dfc80309beec8411e65e706461c408b0bb9b431"
- integrity sha512-IF4EOMEV+bfYwOmNxGzSnjR2EmQod7f1UXOpZM3l4i4o4QNwzjtJAu/HxdjHq0aYBvdqMuQEY1eg0nqW9ZPORA==
- dependencies:
- "@babel/highlight" "^7.16.0"
-
-"@babel/helper-validator-identifier@^7.15.7":
- version "7.15.7"
- resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz#220df993bfe904a4a6b02ab4f3385a5ebf6e2389"
- integrity sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==
-
-"@babel/highlight@^7.16.0":
- version "7.16.0"
- resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.0.tgz#6ceb32b2ca4b8f5f361fb7fd821e3fddf4a1725a"
- integrity sha512-t8MH41kUQylBtu2+4IQA3atqevA2lRgqA2wyVB/YiWmsDSuylZZuXOUy9ric30hfzauEFfdsuk/eXTRrGrfd0g==
- dependencies:
- "@babel/helper-validator-identifier" "^7.15.7"
- chalk "^2.0.0"
- js-tokens "^4.0.0"
-
-"@nodelib/fs.scandir@2.1.5":
- version "2.1.5"
- resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
- integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==
- dependencies:
- "@nodelib/fs.stat" "2.0.5"
- run-parallel "^1.1.9"
-
-"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2":
- version "2.0.5"
- resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b"
- integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==
-
-"@nodelib/fs.walk@^1.2.3":
- version "1.2.8"
- resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a"
- integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==
- dependencies:
- "@nodelib/fs.scandir" "2.1.5"
- fastq "^1.6.0"
-
-"@tailwindcss/aspect-ratio@^0.2.1":
- version "0.2.1"
- resolved "https://registry.yarnpkg.com/@tailwindcss/aspect-ratio/-/aspect-ratio-0.2.1.tgz#a7ce776688b8218d9559a6918f0bccc58f0f16dd"
- integrity sha512-aDFi80aHQ3JM3symJ5iKU70lm151ugIGFCI0yRZGpyjgQSDS+Fbe93QwypC1tCEllQE8p0S7TUu20ih1b9IKLA==
-
-"@tailwindcss/forms@^0.3.3":
- version "0.3.3"
- resolved "https://registry.yarnpkg.com/@tailwindcss/forms/-/forms-0.3.3.tgz#a29d22668804f3dae293dcadbef1aa6315c45b64"
- integrity sha512-U8Fi/gq4mSuaLyLtFISwuDYzPB73YzgozjxOIHsK6NXgg/IWD1FLaHbFlWmurAMyy98O+ao74ksdQefsquBV1Q==
- dependencies:
- mini-svg-data-uri "^1.2.3"
-
-"@tailwindcss/typography@^0.4.1":
- version "0.4.1"
- resolved "https://registry.yarnpkg.com/@tailwindcss/typography/-/typography-0.4.1.tgz#51ddbceea6a0ee9902c649dbe58871c81a831212"
- integrity sha512-ovPPLUhs7zAIJfr0y1dbGlyCuPhpuv/jpBoFgqAc658DWGGrOBWBMpAWLw2KlzbNeVk4YBJMzue1ekvIbdw6XA==
- dependencies:
- lodash.castarray "^4.4.0"
- lodash.isplainobject "^4.0.6"
- lodash.merge "^4.6.2"
- lodash.uniq "^4.5.0"
-
-"@types/parse-json@^4.0.0":
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"
- integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==
-
-acorn-node@^1.6.1:
- version "1.8.2"
- resolved "https://registry.yarnpkg.com/acorn-node/-/acorn-node-1.8.2.tgz#114c95d64539e53dede23de8b9d96df7c7ae2af8"
- integrity sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==
- dependencies:
- acorn "^7.0.0"
- acorn-walk "^7.0.0"
- xtend "^4.0.2"
-
-acorn-walk@^7.0.0:
- version "7.2.0"
- resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc"
- integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==
-
-acorn@^7.0.0:
- version "7.4.1"
- resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
- integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
-
-ansi-styles@^3.2.1:
- version "3.2.1"
- resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
- integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
- dependencies:
- color-convert "^1.9.0"
-
-ansi-styles@^4.1.0:
- version "4.3.0"
- resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
- integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
- dependencies:
- color-convert "^2.0.1"
-
-anymatch@~3.1.2:
- version "3.1.2"
- resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716"
- integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==
- dependencies:
- normalize-path "^3.0.0"
- picomatch "^2.0.4"
-
-arg@^5.0.1:
- version "5.0.1"
- resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.1.tgz#eb0c9a8f77786cad2af8ff2b862899842d7b6adb"
- integrity sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==
-
-autoprefixer@^10.3.1:
- version "10.3.1"
- resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.3.1.tgz#954214821d3aa06692406c6a0a9e9d401eafbed2"
- integrity sha512-L8AmtKzdiRyYg7BUXJTzigmhbQRCXFKz6SA1Lqo0+AR2FBbQ4aTAPFSDlOutnFkjhiz8my4agGXog1xlMjPJ6A==
- dependencies:
- browserslist "^4.16.6"
- caniuse-lite "^1.0.30001243"
- colorette "^1.2.2"
- fraction.js "^4.1.1"
- normalize-range "^0.1.2"
- postcss-value-parser "^4.1.0"
-
-balanced-match@^1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
- integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
-
-binary-extensions@^2.0.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
- integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
-
-brace-expansion@^1.1.7:
- version "1.1.11"
- resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
- integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
- dependencies:
- balanced-match "^1.0.0"
- concat-map "0.0.1"
-
-braces@^3.0.1, braces@~3.0.2:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
- integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
- dependencies:
- fill-range "^7.0.1"
-
-browserslist@^4.16.6:
- version "4.16.7"
- resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.7.tgz#108b0d1ef33c4af1b587c54f390e7041178e4335"
- integrity sha512-7I4qVwqZltJ7j37wObBe3SoTz+nS8APaNcrBOlgoirb6/HbEU2XxW/LpUDTCngM6iauwFqmRTuOMfyKnFGY5JA==
- dependencies:
- caniuse-lite "^1.0.30001248"
- colorette "^1.2.2"
- electron-to-chromium "^1.3.793"
- escalade "^3.1.1"
- node-releases "^1.1.73"
-
-bytes@^3.0.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6"
- integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==
-
-callsites@^3.0.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
- integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
-
-camelcase-css@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5"
- integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==
-
-caniuse-lite@^1.0.30001243, caniuse-lite@^1.0.30001248:
- version "1.0.30001251"
- resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001251.tgz#6853a606ec50893115db660f82c094d18f096d85"
- integrity sha512-HOe1r+9VkU4TFmnU70z+r7OLmtR+/chB1rdcJUeQlAinjEeb0cKL20tlAtOagNZhbrtLnCvV19B4FmF1rgzl6A==
-
-chalk@^2.0.0:
- version "2.4.2"
- resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
- integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
- dependencies:
- ansi-styles "^3.2.1"
- escape-string-regexp "^1.0.5"
- supports-color "^5.3.0"
-
-chalk@^4.1.2:
- version "4.1.2"
- resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
- integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
- dependencies:
- ansi-styles "^4.1.0"
- supports-color "^7.1.0"
-
-chokidar@^3.5.2:
- version "3.5.2"
- resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.2.tgz#dba3976fcadb016f66fd365021d91600d01c1e75"
- integrity sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==
- dependencies:
- anymatch "~3.1.2"
- braces "~3.0.2"
- glob-parent "~5.1.2"
- is-binary-path "~2.1.0"
- is-glob "~4.0.1"
- normalize-path "~3.0.0"
- readdirp "~3.6.0"
- optionalDependencies:
- fsevents "~2.3.2"
-
-color-convert@^1.9.0:
- version "1.9.3"
- resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
- integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
- dependencies:
- color-name "1.1.3"
-
-color-convert@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
- integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
- dependencies:
- color-name "~1.1.4"
-
-color-name@1.1.3:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
- integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
-
-color-name@^1.0.0, color-name@~1.1.4:
- version "1.1.4"
- resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
- integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
-
-color-string@^1.6.0:
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.6.0.tgz#c3915f61fe267672cb7e1e064c9d692219f6c312"
- integrity sha512-c/hGS+kRWJutUBEngKKmk4iH3sD59MBkoxVapS/0wgpCz2u7XsNloxknyvBhzwEs1IbV36D9PwqLPJ2DTu3vMA==
- dependencies:
- color-name "^1.0.0"
- simple-swizzle "^0.2.2"
-
-color@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/color/-/color-4.0.1.tgz#21df44cd10245a91b1ccf5ba031609b0e10e7d67"
- integrity sha512-rpZjOKN5O7naJxkH2Rx1sZzzBgaiWECc6BYXjeCE6kF0kcASJYbUq02u7JqIHwCb/j3NhV+QhRL2683aICeGZA==
- dependencies:
- color-convert "^2.0.1"
- color-string "^1.6.0"
-
-colorette@^1.2.2:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.4.0.tgz#5190fbb87276259a86ad700bff2c6d6faa3fca40"
- integrity sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==
-
-commander@^6.0.0:
- version "6.2.1"
- resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c"
- integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==
-
-concat-map@0.0.1:
- version "0.0.1"
- resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
- integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
-
-cosmiconfig@^7.0.1:
- version "7.0.1"
- resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.1.tgz#714d756522cace867867ccb4474c5d01bbae5d6d"
- integrity sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==
- dependencies:
- "@types/parse-json" "^4.0.0"
- import-fresh "^3.2.1"
- parse-json "^5.0.0"
- path-type "^4.0.0"
- yaml "^1.10.0"
-
-css-color-names@^0.0.4:
- version "0.0.4"
- resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0"
- integrity sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=
-
-css-unit-converter@^1.1.1:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/css-unit-converter/-/css-unit-converter-1.1.2.tgz#4c77f5a1954e6dbff60695ecb214e3270436ab21"
- integrity sha512-IiJwMC8rdZE0+xiEZHeru6YoONC4rfPMqGm2W85jMIbkFvv5nFTwJVFHam2eFrN6txmoUYFAFXiv8ICVeTO0MA==
-
-cssesc@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
- integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==
-
-defined@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693"
- integrity sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=
-
-detective@^5.2.0:
- version "5.2.0"
- resolved "https://registry.yarnpkg.com/detective/-/detective-5.2.0.tgz#feb2a77e85b904ecdea459ad897cc90a99bd2a7b"
- integrity sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==
- dependencies:
- acorn-node "^1.6.1"
- defined "^1.0.0"
- minimist "^1.1.1"
-
-didyoumean@^1.2.2:
- version "1.2.2"
- resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037"
- integrity sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==
-
-dlv@^1.1.3:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.3.tgz#5c198a8a11453596e751494d49874bc7732f2e79"
- integrity sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==
-
-electron-to-chromium@^1.3.793:
- version "1.3.810"
- resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.810.tgz#23e340507e13e48debdb7445d2f8fbfab681c4df"
- integrity sha512-NteznMlGtkIZCJNM2X6AVm3oMqWAdq7TjqagZhmVLPwd9mtrIq+rRxGHerjFAOFIqQJYQUMT72ncd/lVcH1cOw==
-
-error-ex@^1.3.1:
- version "1.3.2"
- resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
- integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==
- dependencies:
- is-arrayish "^0.2.1"
-
-escalade@^3.1.1:
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
- integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==
-
-escape-string-regexp@^1.0.5:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
- integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
-
-fast-glob@^3.2.7:
- version "3.2.7"
- resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.7.tgz#fd6cb7a2d7e9aa7a7846111e85a196d6b2f766a1"
- integrity sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==
- dependencies:
- "@nodelib/fs.stat" "^2.0.2"
- "@nodelib/fs.walk" "^1.2.3"
- glob-parent "^5.1.2"
- merge2 "^1.3.0"
- micromatch "^4.0.4"
-
-fastq@^1.6.0:
- version "1.13.0"
- resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c"
- integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==
- dependencies:
- reusify "^1.0.4"
-
-fill-range@^7.0.1:
- version "7.0.1"
- resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
- integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
- dependencies:
- to-regex-range "^5.0.1"
-
-fraction.js@^4.1.1:
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.1.1.tgz#ac4e520473dae67012d618aab91eda09bcb400ff"
- integrity sha512-MHOhvvxHTfRFpF1geTK9czMIZ6xclsEor2wkIGYYq+PxcQqT7vStJqjhe6S1TenZrMZzo+wlqOufBDVepUEgPg==
-
-fs-extra@^10.0.0:
- version "10.0.0"
- resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.0.0.tgz#9ff61b655dde53fb34a82df84bb214ce802e17c1"
- integrity sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==
- dependencies:
- graceful-fs "^4.2.0"
- jsonfile "^6.0.1"
- universalify "^2.0.0"
-
-fs.realpath@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
- integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
-
-fsevents@~2.3.2:
- version "2.3.2"
- resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
- integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
-
-function-bind@^1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
- integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
-
-glob-parent@^5.1.2, glob-parent@~5.1.2:
- version "5.1.2"
- resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
- integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
- dependencies:
- is-glob "^4.0.1"
-
-glob-parent@^6.0.1:
- version "6.0.2"
- resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3"
- integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==
- dependencies:
- is-glob "^4.0.3"
-
-glob@^7.0.0, glob@^7.1.3:
- version "7.2.0"
- resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023"
- integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==
- dependencies:
- fs.realpath "^1.0.0"
- inflight "^1.0.4"
- inherits "2"
- minimatch "^3.0.4"
- once "^1.3.0"
- path-is-absolute "^1.0.0"
-
-graceful-fs@^4.1.6, graceful-fs@^4.2.0:
- version "4.2.8"
- resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a"
- integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==
-
-has-flag@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
- integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
-
-has-flag@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
- integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
-
-has@^1.0.3:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
- integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
- dependencies:
- function-bind "^1.1.1"
-
-hex-color-regex@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e"
- integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==
-
-hsl-regex@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/hsl-regex/-/hsl-regex-1.0.0.tgz#d49330c789ed819e276a4c0d272dffa30b18fe6e"
- integrity sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4=
-
-hsla-regex@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/hsla-regex/-/hsla-regex-1.0.0.tgz#c1ce7a3168c8c6614033a4b5f7877f3b225f9c38"
- integrity sha1-wc56MWjIxmFAM6S194d/OyJfnDg=
-
-html-tags@^3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.1.0.tgz#7b5e6f7e665e9fb41f30007ed9e0d41e97fb2140"
- integrity sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg==
-
-import-cwd@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/import-cwd/-/import-cwd-3.0.0.tgz#20845547718015126ea9b3676b7592fb8bd4cf92"
- integrity sha512-4pnzH16plW+hgvRECbDWpQl3cqtvSofHWh44met7ESfZ8UZOWWddm8hEyDTqREJ9RbYHY8gi8DqmaelApoOGMg==
- dependencies:
- import-from "^3.0.0"
-
-import-fresh@^3.2.1:
- version "3.3.0"
- resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b"
- integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==
- dependencies:
- parent-module "^1.0.0"
- resolve-from "^4.0.0"
-
-import-from@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/import-from/-/import-from-3.0.0.tgz#055cfec38cd5a27d8057ca51376d7d3bf0891966"
- integrity sha512-CiuXOFFSzkU5x/CR0+z7T91Iht4CXgfCxVOFRhh2Zyhg5wOpWvvDLQUsWl+gcN+QscYBjez8hDCt85O7RLDttQ==
- dependencies:
- resolve-from "^5.0.0"
-
-inflight@^1.0.4:
- version "1.0.6"
- resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
- integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=
- dependencies:
- once "^1.3.0"
- wrappy "1"
-
-inherits@2:
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
- integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
-
-is-arrayish@^0.2.1:
- version "0.2.1"
- resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
- integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=
-
-is-arrayish@^0.3.1:
- version "0.3.2"
- resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03"
- integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==
-
-is-binary-path@~2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09"
- integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==
- dependencies:
- binary-extensions "^2.0.0"
-
-is-color-stop@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/is-color-stop/-/is-color-stop-1.1.0.tgz#cfff471aee4dd5c9e158598fbe12967b5cdad345"
- integrity sha1-z/9HGu5N1cnhWFmPvhKWe1za00U=
- dependencies:
- css-color-names "^0.0.4"
- hex-color-regex "^1.1.0"
- hsl-regex "^1.0.0"
- hsla-regex "^1.0.0"
- rgb-regex "^1.0.1"
- rgba-regex "^1.0.0"
-
-is-core-module@^2.2.0:
- version "2.8.0"
- resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.0.tgz#0321336c3d0925e497fd97f5d95cb114a5ccd548"
- integrity sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==
- dependencies:
- has "^1.0.3"
-
-is-extglob@^2.1.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
- integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=
-
-is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1:
- version "4.0.3"
- resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
- integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
- dependencies:
- is-extglob "^2.1.1"
-
-is-number@^7.0.0:
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
- integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
-
-js-tokens@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
- integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
-
-json-parse-even-better-errors@^2.3.0:
- version "2.3.1"
- resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d"
- integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==
-
-jsonfile@^6.0.1:
- version "6.1.0"
- resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae"
- integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==
- dependencies:
- universalify "^2.0.0"
- optionalDependencies:
- graceful-fs "^4.1.6"
-
-lilconfig@^2.0.3:
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.3.tgz#68f3005e921dafbd2a2afb48379986aa6d2579fd"
- integrity sha512-EHKqr/+ZvdKCifpNrJCKxBTgk5XupZA3y/aCPY9mxfgBzmgh93Mt/WqjjQ38oMxXuvDokaKiM3lAgvSH2sjtHg==
-
-lines-and-columns@^1.1.6:
- version "1.1.6"
- resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00"
- integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=
-
-lodash.castarray@^4.4.0:
- version "4.4.0"
- resolved "https://registry.yarnpkg.com/lodash.castarray/-/lodash.castarray-4.4.0.tgz#c02513515e309daddd4c24c60cfddcf5976d9115"
- integrity sha1-wCUTUV4wna3dTCTGDP3c9ZdtkRU=
-
-lodash.isplainobject@^4.0.6:
- version "4.0.6"
- resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
- integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=
-
-lodash.merge@^4.6.2:
- version "4.6.2"
- resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
- integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
-
-lodash.topath@^4.5.2:
- version "4.5.2"
- resolved "https://registry.yarnpkg.com/lodash.topath/-/lodash.topath-4.5.2.tgz#3616351f3bba61994a0931989660bd03254fd009"
- integrity sha1-NhY1Hzu6YZlKCTGYlmC9AyVP0Ak=
-
-lodash.uniq@^4.5.0:
- version "4.5.0"
- resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
- integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=
-
-lodash@^4.17.21:
- version "4.17.21"
- resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
- integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
-
-merge2@^1.3.0:
- version "1.4.1"
- resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
- integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
-
-micromatch@^4.0.4:
- version "4.0.4"
- resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9"
- integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==
- dependencies:
- braces "^3.0.1"
- picomatch "^2.2.3"
-
-mini-svg-data-uri@^1.2.3:
- version "1.2.3"
- resolved "https://registry.yarnpkg.com/mini-svg-data-uri/-/mini-svg-data-uri-1.2.3.tgz#e16baa92ad55ddaa1c2c135759129f41910bc39f"
- integrity sha512-zd6KCAyXgmq6FV1mR10oKXYtvmA9vRoB6xPSTUJTbFApCtkefDnYueVR1gkof3KcdLZo1Y8mjF2DFmQMIxsHNQ==
-
-minimatch@^3.0.4:
- version "3.0.4"
- resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
- integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
- dependencies:
- brace-expansion "^1.1.7"
-
-minimist@^1.1.1:
- version "1.2.5"
- resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
- integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
-
-modern-normalize@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/modern-normalize/-/modern-normalize-1.1.0.tgz#da8e80140d9221426bd4f725c6e11283d34f90b7"
- integrity sha512-2lMlY1Yc1+CUy0gw4H95uNN7vjbpoED7NNRSBHE25nWfLBdmMzFCsPshlzbxHz+gYMcBEUN8V4pU16prcdPSgA==
-
-nanoid@^3.1.30:
- version "3.1.30"
- resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.30.tgz#63f93cc548d2a113dc5dfbc63bfa09e2b9b64362"
- integrity sha512-zJpuPDwOv8D2zq2WRoMe1HsfZthVewpel9CAvTfc/2mBD1uUT/agc5f7GHGWXlYkFvi1mVxe4IjvP2HNrop7nQ==
-
-node-emoji@^1.11.0:
- version "1.11.0"
- resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-1.11.0.tgz#69a0150e6946e2f115e9d7ea4df7971e2628301c"
- integrity sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==
- dependencies:
- lodash "^4.17.21"
-
-node-releases@^1.1.73:
- version "1.1.74"
- resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.74.tgz#e5866488080ebaa70a93b91144ccde06f3c3463e"
- integrity sha512-caJBVempXZPepZoZAPCWRTNxYQ+xtG/KAi4ozTA5A+nJ7IU+kLQCbqaUjb5Rwy14M9upBWiQ4NutcmW04LJSRw==
-
-normalize-path@^3.0.0, normalize-path@~3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
- integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
-
-normalize-range@^0.1.2:
- version "0.1.2"
- resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942"
- integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=
-
-object-hash@^2.2.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-2.2.0.tgz#5ad518581eefc443bd763472b8ff2e9c2c0d54a5"
- integrity sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==
-
-once@^1.3.0:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
- integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
- dependencies:
- wrappy "1"
-
-parent-module@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2"
- integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==
- dependencies:
- callsites "^3.0.0"
-
-parse-json@^5.0.0:
- version "5.2.0"
- resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd"
- integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==
- dependencies:
- "@babel/code-frame" "^7.0.0"
- error-ex "^1.3.1"
- json-parse-even-better-errors "^2.3.0"
- lines-and-columns "^1.1.6"
-
-path-is-absolute@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
- integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
-
-path-parse@^1.0.6:
- version "1.0.7"
- resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
- integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
-
-path-type@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
- integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
-
-picocolors@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
- integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
-
-picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3:
- version "2.3.0"
- resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972"
- integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==
-
-postcss-js@^3.0.3:
- version "3.0.3"
- resolved "https://registry.yarnpkg.com/postcss-js/-/postcss-js-3.0.3.tgz#2f0bd370a2e8599d45439f6970403b5873abda33"
- integrity sha512-gWnoWQXKFw65Hk/mi2+WTQTHdPD5UJdDXZmX073EY/B3BWnYjO4F4t0VneTCnCGQ5E5GsCdMkzPaTXwl3r5dJw==
- dependencies:
- camelcase-css "^2.0.1"
- postcss "^8.1.6"
-
-postcss-load-config@^3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-3.1.0.tgz#d39c47091c4aec37f50272373a6a648ef5e97829"
- integrity sha512-ipM8Ds01ZUophjDTQYSVP70slFSYg3T0/zyfII5vzhN6V57YSxMgG5syXuwi5VtS8wSf3iL30v0uBdoIVx4Q0g==
- dependencies:
- import-cwd "^3.0.0"
- lilconfig "^2.0.3"
- yaml "^1.10.2"
-
-postcss-nested@5.0.6:
- version "5.0.6"
- resolved "https://registry.yarnpkg.com/postcss-nested/-/postcss-nested-5.0.6.tgz#466343f7fc8d3d46af3e7dba3fcd47d052a945bc"
- integrity sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA==
- dependencies:
- postcss-selector-parser "^6.0.6"
-
-postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.6:
- version "6.0.6"
- resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.6.tgz#2c5bba8174ac2f6981ab631a42ab0ee54af332ea"
- integrity sha512-9LXrvaaX3+mcv5xkg5kFwqSzSH1JIObIx51PrndZwlmznwXRfxMddDvo9gve3gVR8ZTKgoFDdWkbRFmEhT4PMg==
- dependencies:
- cssesc "^3.0.0"
- util-deprecate "^1.0.2"
-
-postcss-value-parser@^3.3.0:
- version "3.3.1"
- resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281"
- integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==
-
-postcss-value-parser@^4.1.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb"
- integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==
-
-postcss@^8.1.6, postcss@^8.2.1:
- version "8.3.11"
- resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.3.11.tgz#c3beca7ea811cd5e1c4a3ec6d2e7599ef1f8f858"
- integrity sha512-hCmlUAIlUiav8Xdqw3Io4LcpA1DOt7h3LSTAC4G6JGHFFaWzI6qvFt9oilvl8BmkbBRX1IhM90ZAmpk68zccQA==
- dependencies:
- nanoid "^3.1.30"
- picocolors "^1.0.0"
- source-map-js "^0.6.2"
-
-pretty-hrtime@^1.0.3:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1"
- integrity sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=
-
-purgecss@^4.0.3:
- version "4.0.3"
- resolved "https://registry.yarnpkg.com/purgecss/-/purgecss-4.0.3.tgz#8147b429f9c09db719e05d64908ea8b672913742"
- integrity sha512-PYOIn5ibRIP34PBU9zohUcCI09c7drPJJtTDAc0Q6QlRz2/CHQ8ywGLdE7ZhxU2VTqB7p5wkvj5Qcm05Rz3Jmw==
- dependencies:
- commander "^6.0.0"
- glob "^7.0.0"
- postcss "^8.2.1"
- postcss-selector-parser "^6.0.2"
-
-queue-microtask@^1.2.2:
- version "1.2.3"
- resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
- integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
-
-quick-lru@^5.1.1:
- version "5.1.1"
- resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932"
- integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==
-
-readdirp@~3.6.0:
- version "3.6.0"
- resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
- integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==
- dependencies:
- picomatch "^2.2.1"
-
-reduce-css-calc@^2.1.8:
- version "2.1.8"
- resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-2.1.8.tgz#7ef8761a28d614980dc0c982f772c93f7a99de03"
- integrity sha512-8liAVezDmUcH+tdzoEGrhfbGcP7nOV4NkGE3a74+qqvE7nt9i4sKLGBuZNOnpI4WiGksiNPklZxva80061QiPg==
- dependencies:
- css-unit-converter "^1.1.1"
- postcss-value-parser "^3.3.0"
-
-resolve-from@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
- integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
-
-resolve-from@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69"
- integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==
-
-resolve@^1.20.0:
- version "1.20.0"
- resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975"
- integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==
- dependencies:
- is-core-module "^2.2.0"
- path-parse "^1.0.6"
-
-reusify@^1.0.4:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
- integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
-
-rgb-regex@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/rgb-regex/-/rgb-regex-1.0.1.tgz#c0e0d6882df0e23be254a475e8edd41915feaeb1"
- integrity sha1-wODWiC3w4jviVKR16O3UGRX+rrE=
-
-rgba-regex@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3"
- integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=
-
-rimraf@^3.0.0:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
- integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
- dependencies:
- glob "^7.1.3"
-
-run-parallel@^1.1.9:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee"
- integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==
- dependencies:
- queue-microtask "^1.2.2"
-
-simple-swizzle@^0.2.2:
- version "0.2.2"
- resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a"
- integrity sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=
- dependencies:
- is-arrayish "^0.3.1"
-
-source-map-js@^0.6.2:
- version "0.6.2"
- resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-0.6.2.tgz#0bb5de631b41cfbda6cfba8bd05a80efdfd2385e"
- integrity sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==
-
-supports-color@^5.3.0:
- version "5.5.0"
- resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
- integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
- dependencies:
- has-flag "^3.0.0"
-
-supports-color@^7.1.0:
- version "7.2.0"
- resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
- integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
- dependencies:
- has-flag "^4.0.0"
-
-tailwindcss@^2.2.7:
- version "2.2.19"
- resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-2.2.19.tgz#540e464832cd462bb9649c1484b0a38315c2653c"
- integrity sha512-6Ui7JSVtXadtTUo2NtkBBacobzWiQYVjYW0ZnKaP9S1ZCKQ0w7KVNz+YSDI/j7O7KCMHbOkz94ZMQhbT9pOqjw==
- dependencies:
- arg "^5.0.1"
- bytes "^3.0.0"
- chalk "^4.1.2"
- chokidar "^3.5.2"
- color "^4.0.1"
- cosmiconfig "^7.0.1"
- detective "^5.2.0"
- didyoumean "^1.2.2"
- dlv "^1.1.3"
- fast-glob "^3.2.7"
- fs-extra "^10.0.0"
- glob-parent "^6.0.1"
- html-tags "^3.1.0"
- is-color-stop "^1.1.0"
- is-glob "^4.0.1"
- lodash "^4.17.21"
- lodash.topath "^4.5.2"
- modern-normalize "^1.1.0"
- node-emoji "^1.11.0"
- normalize-path "^3.0.0"
- object-hash "^2.2.0"
- postcss-js "^3.0.3"
- postcss-load-config "^3.1.0"
- postcss-nested "5.0.6"
- postcss-selector-parser "^6.0.6"
- postcss-value-parser "^4.1.0"
- pretty-hrtime "^1.0.3"
- purgecss "^4.0.3"
- quick-lru "^5.1.1"
- reduce-css-calc "^2.1.8"
- resolve "^1.20.0"
- tmp "^0.2.1"
-
-tmp@^0.2.1:
- version "0.2.1"
- resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14"
- integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==
- dependencies:
- rimraf "^3.0.0"
-
-to-regex-range@^5.0.1:
- version "5.0.1"
- resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
- integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
- dependencies:
- is-number "^7.0.0"
-
-universalify@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717"
- integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==
-
-util-deprecate@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
- integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
-
-wrappy@1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
- integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
-
-xtend@^4.0.2:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
- integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
-
-yaml@^1.10.0, yaml@^1.10.2:
- version "1.10.2"
- resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
- integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==