rubocop-tailwindcss 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/LICENSE +21 -0
- data/README.md +100 -9
- data/config/default.yml +17 -0
- data/lib/rubocop/cop/tailwindcss/class_order.rb +118 -0
- data/lib/rubocop/tailwindcss/plugin.rb +30 -0
- data/lib/rubocop/tailwindcss/sorter.rb +142 -0
- data/lib/rubocop/tailwindcss/version.rb +7 -0
- data/lib/rubocop-tailwindcss.rb +6 -7
- data/vendor/tw-bundle.js +5675 -0
- metadata +57 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 79100a6f1cd6574dbd77a45b7534cf59a0b5f0402b472530f30f5a2d0c288727
|
|
4
|
+
data.tar.gz: db1a933d7774841e731dfb7824926356cdd9bd6f4790131c445dd47a917675b3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5b240e6a2cf95a112e8f5d43f3e675e565dc19f2222f75bc688f56ea53c0abf6ef334cef0d4d06bb0001617c0fa66912cb999d5b8066f8cb3eb8bb992568c620
|
|
7
|
+
data.tar.gz: d100558922d06fe2bf88419b3e3a5605c374f7e01202b2d61403999b85b1d87ca33a472964c2f90105ce6de7f01fdb56e871e7f1a821643af07d8003338b0798
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 am1006
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
CHANGED
|
@@ -1,13 +1,104 @@
|
|
|
1
1
|
# rubocop-tailwindcss
|
|
2
2
|
|
|
3
|
-
RuboCop
|
|
4
|
-
|
|
3
|
+
A RuboCop cop that keeps Tailwind CSS classes in the official sort order -
|
|
4
|
+
the same order [prettier-plugin-tailwindcss](https://github.com/tailwindlabs/prettier-plugin-tailwindcss)
|
|
5
|
+
produces - wherever Ruby carries them: Phlex components, tag helpers, any
|
|
6
|
+
`class:` string keyword.
|
|
5
7
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
```ruby
|
|
9
|
+
# bad
|
|
10
|
+
div(class: "px-4 bg-blue-500 text-white rounded py-2")
|
|
11
|
+
cn("px-4 flex", active && "bg-blue-500 rounded")
|
|
9
12
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
# good (rubocop -a fixes it)
|
|
14
|
+
div(class: "rounded bg-blue-500 px-4 py-2 text-white")
|
|
15
|
+
cn("flex px-4", active && "rounded bg-blue-500")
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
**No node. No subprocesses. No npx.** The official order is computed by
|
|
19
|
+
Tailwind's own design system - a JavaScript library - which this gem ships as
|
|
20
|
+
a single vendored bundle and evaluates inside an embedded JS engine
|
|
21
|
+
([quickjs](https://rubygems.org/gems/quickjs)), warm for the life of the
|
|
22
|
+
process. Cold start is ~30 ms; each sort is sub-millisecond. Your Rails app
|
|
23
|
+
needs no package.json, no node_modules, no JavaScript toolchain.
|
|
24
|
+
|
|
25
|
+
## Installation
|
|
26
|
+
|
|
27
|
+
```ruby
|
|
28
|
+
# Gemfile
|
|
29
|
+
group :development do
|
|
30
|
+
gem "rubocop-tailwindcss", require: false
|
|
31
|
+
end
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
```yaml
|
|
35
|
+
# .rubocop.yml
|
|
36
|
+
plugins:
|
|
37
|
+
- rubocop-tailwindcss
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Usage
|
|
41
|
+
|
|
42
|
+
- **Fix on command:** `rubocop -a --only Tailwindcss/ClassOrder`
|
|
43
|
+
- **CI:** the cop runs inside your normal `rubocop` invocation
|
|
44
|
+
- **Editors:** ruby-lsp surfaces the offense as a diagnostic with a quick fix,
|
|
45
|
+
and applies it on format-on-save where safe autocorrection is enabled
|
|
46
|
+
|
|
47
|
+
## Configuration
|
|
48
|
+
|
|
49
|
+
```yaml
|
|
50
|
+
Tailwindcss/ClassOrder:
|
|
51
|
+
# Your Tailwind entry CSS - theme-aware sorting reads @custom-variant,
|
|
52
|
+
# @theme and friends from here. The default matches tailwindcss-rails.
|
|
53
|
+
# Set to ~ to sort against Tailwind's default theme instead.
|
|
54
|
+
# A configured path that does not exist raises rather than sorting wrong.
|
|
55
|
+
Stylesheet: app/assets/tailwind/application.css
|
|
56
|
+
|
|
57
|
+
# Keyword arguments treated as class carriers.
|
|
58
|
+
Attributes:
|
|
59
|
+
- class
|
|
60
|
+
- classes
|
|
61
|
+
|
|
62
|
+
# Class-merging functions: every plain string literal inside these calls is
|
|
63
|
+
# sorted - positional arguments, hash values at any depth (cva variants),
|
|
64
|
+
# array elements, and the branches of && / || / ternaries.
|
|
65
|
+
Functions:
|
|
66
|
+
- cn
|
|
67
|
+
- cva
|
|
68
|
+
|
|
69
|
+
# The embedded JS engine: quickjs (default, ~2 MB, compiles anywhere) or
|
|
70
|
+
# mini_racer (V8 - add the gem to your Gemfile yourself).
|
|
71
|
+
Engine: quickjs
|
|
72
|
+
|
|
73
|
+
Include:
|
|
74
|
+
- app/views/**/*.rb
|
|
75
|
+
- app/components/**/*.rb
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## What it deliberately leaves alone
|
|
79
|
+
|
|
80
|
+
- **Interpolated strings** (`"px-4 #{state}"`) - the sorter cannot know what
|
|
81
|
+
interpolation produces.
|
|
82
|
+
- **Strings with escape sequences** - source and value diverge; correcting
|
|
83
|
+
them safely is not worth the machinery for class strings.
|
|
84
|
+
- **`%w[]` arrays** - not covered yet.
|
|
85
|
+
|
|
86
|
+
One edge to know, inherited deliberately from prettier-plugin-tailwindcss: a
|
|
87
|
+
single literal carrying *conflicting* utilities inside a merge function -
|
|
88
|
+
`cn("p-4 p-2")` - can change its tailwind-merge result when reordered,
|
|
89
|
+
because tailwind-merge is last-wins within a string. The official plugin
|
|
90
|
+
sorts these anyway, and so does this cop: a literal with an internal conflict
|
|
91
|
+
is already a bug, and sorting merely stops it hiding.
|
|
92
|
+
|
|
93
|
+
## How the order stays honest
|
|
94
|
+
|
|
95
|
+
The vendored bundle is rebuilt per Tailwind release in
|
|
96
|
+
[the parent repo's factory](https://github.com/am1006/tailwindcss-sorter) and
|
|
97
|
+
proven against the official prettier plugin over a real-world corpus before it
|
|
98
|
+
ships. On boot the sorter runs a self-check (sort a known string, raise loudly
|
|
99
|
+
if it comes back unsorted) - a design system that loads but does not sort
|
|
100
|
+
would otherwise pass every file as clean.
|
|
101
|
+
|
|
102
|
+
## License
|
|
103
|
+
|
|
104
|
+
MIT
|
data/config/default.yml
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Tailwindcss/ClassOrder:
|
|
2
|
+
Description: "Sort Tailwind CSS classes in the official order."
|
|
3
|
+
Enabled: true
|
|
4
|
+
Safe: true
|
|
5
|
+
SafeAutoCorrect: true
|
|
6
|
+
VersionAdded: "0.1"
|
|
7
|
+
Stylesheet: app/assets/tailwind/application.css
|
|
8
|
+
Engine: quickjs
|
|
9
|
+
Attributes:
|
|
10
|
+
- class
|
|
11
|
+
- classes
|
|
12
|
+
Functions:
|
|
13
|
+
- cn
|
|
14
|
+
- cva
|
|
15
|
+
Include:
|
|
16
|
+
- app/views/**/*.rb
|
|
17
|
+
- app/components/**/*.rb
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module Tailwindcss
|
|
6
|
+
# Keeps Tailwind CSS classes in the official sort order - the same order
|
|
7
|
+
# prettier-plugin-tailwindcss produces - wherever Ruby carries them:
|
|
8
|
+
# `class:` / `classes:` string keywords (Phlex components, tag helpers)
|
|
9
|
+
# and the string literals inside class-merging functions like `cn` and
|
|
10
|
+
# `cva`.
|
|
11
|
+
#
|
|
12
|
+
# @example
|
|
13
|
+
# # bad
|
|
14
|
+
# div(class: "px-4 bg-blue-500 flex")
|
|
15
|
+
# cn("px-4 flex", active && "bg-muted rounded")
|
|
16
|
+
#
|
|
17
|
+
# # good
|
|
18
|
+
# div(class: "flex bg-blue-500 px-4")
|
|
19
|
+
# cn("flex px-4", active && "rounded bg-muted")
|
|
20
|
+
class ClassOrder < Base
|
|
21
|
+
extend AutoCorrector
|
|
22
|
+
|
|
23
|
+
MSG = "Sort Tailwind CSS classes in the official order"
|
|
24
|
+
|
|
25
|
+
def on_pair(node)
|
|
26
|
+
if target_attribute?(node) && sortable?(node.value)
|
|
27
|
+
check node.value
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def on_send(node)
|
|
32
|
+
if class_function?(node)
|
|
33
|
+
node.arguments.each { |argument| sort_within argument }
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
def target_attribute?(node)
|
|
39
|
+
node.key.sym_type? && attributes.include?(node.key.value.to_s)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def class_function?(node)
|
|
43
|
+
functions.include?(node.method_name.to_s)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Inside a class function, every plain string literal is a class
|
|
47
|
+
# string - prettier's contract, followed here: positional arguments,
|
|
48
|
+
# hash values at any depth, array elements, and the branches of
|
|
49
|
+
# conditionals. Dynamic nodes (variables, calls, interpolation) stay
|
|
50
|
+
# untouched, and `class:` pairs stay with on_pair so nothing is
|
|
51
|
+
# flagged twice.
|
|
52
|
+
def sort_within(node)
|
|
53
|
+
case node.type
|
|
54
|
+
when :str
|
|
55
|
+
check node if sortable?(node)
|
|
56
|
+
when :hash, :kwargs, :array, :and, :or, :begin
|
|
57
|
+
node.children.each { |child| sort_within child if child.is_a?(Parser::AST::Node) }
|
|
58
|
+
when :pair
|
|
59
|
+
sort_within node.value unless target_attribute?(node)
|
|
60
|
+
when :if
|
|
61
|
+
node.branches.compact.each { |branch| sort_within branch }
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Plain quoted string literals carrying at least two classes.
|
|
66
|
+
# Interpolation is invisible to the sorter, and escape sequences make
|
|
67
|
+
# source and value diverge - both are left alone rather than
|
|
68
|
+
# corrected unsafely.
|
|
69
|
+
def sortable?(node)
|
|
70
|
+
node.str_type? && node.value.match?(/\S\s+\S/) && plain_literal?(node)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def plain_literal?(node)
|
|
74
|
+
node.source == %("#{node.value}") || node.source == %('#{node.value}')
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def check(node)
|
|
78
|
+
sorted = sorter.sort(node.value)
|
|
79
|
+
if sorted != node.value
|
|
80
|
+
add_offense(node) do |corrector|
|
|
81
|
+
corrector.replace content_range(node), sorted
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def content_range(node)
|
|
87
|
+
node.source_range.adjust(begin_pos: 1, end_pos: -1)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def attributes
|
|
91
|
+
cop_config.fetch("Attributes", %w[ class classes ])
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def functions
|
|
95
|
+
cop_config.fetch("Functions", %w[ cn cva ])
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def sorter
|
|
99
|
+
RuboCop::Tailwindcss::Sorter.for stylesheet: stylesheet, engine: cop_config.fetch("Engine", "quickjs")
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# A configured stylesheet that does not exist would silently sort
|
|
103
|
+
# with the default theme - wrong for custom variants - so it raises
|
|
104
|
+
# instead. Set Stylesheet to ~ to sort against the default theme.
|
|
105
|
+
def stylesheet
|
|
106
|
+
if path = cop_config["Stylesheet"]
|
|
107
|
+
unless File.exist?(path)
|
|
108
|
+
raise RuboCop::Tailwindcss::Sorter::Error,
|
|
109
|
+
"stylesheet not found at #{path.inspect} - point Tailwindcss/ClassOrder's " \
|
|
110
|
+
"Stylesheet at your Tailwind entry CSS, or set it to ~ for the default theme"
|
|
111
|
+
end
|
|
112
|
+
path
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "lint_roller"
|
|
4
|
+
|
|
5
|
+
module RuboCop
|
|
6
|
+
module Tailwindcss
|
|
7
|
+
class Plugin < LintRoller::Plugin
|
|
8
|
+
def about
|
|
9
|
+
LintRoller::About.new(
|
|
10
|
+
name: "rubocop-tailwindcss",
|
|
11
|
+
version: VERSION,
|
|
12
|
+
homepage: "https://github.com/am1006/tailwindcss-sorter",
|
|
13
|
+
description: "Sort Tailwind CSS classes in Ruby code in the official order."
|
|
14
|
+
)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def supported?(context)
|
|
18
|
+
context.engine == :rubocop
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def rules(_context)
|
|
22
|
+
LintRoller::Rules.new(
|
|
23
|
+
type: :path,
|
|
24
|
+
config_format: :rubocop,
|
|
25
|
+
value: Pathname.new(__dir__).join("../../../config/default.yml")
|
|
26
|
+
)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Tailwindcss
|
|
5
|
+
# The order oracle: Tailwind's design system, bundled into a single JS file
|
|
6
|
+
# and evaluated inside an embedded engine - warm for the life of the
|
|
7
|
+
# process, no node, no subprocesses. Sorting asks the same
|
|
8
|
+
# design.getClassOrder that prettier-plugin-tailwindcss asks; the vendored
|
|
9
|
+
# bundle is proven against the official plugin by this repo's factory.
|
|
10
|
+
#
|
|
11
|
+
# Note: the engines' eval APIs only ever receive this gem's own vendored
|
|
12
|
+
# bundle and JSON-encoded class strings - no untrusted code is evaluated.
|
|
13
|
+
class Sorter
|
|
14
|
+
class Error < StandardError; end
|
|
15
|
+
|
|
16
|
+
# The Tailwind version the vendored bundle must carry - the one number
|
|
17
|
+
# this gem's entire behavior derives from. The factory stamps the bundle
|
|
18
|
+
# at build time and the suite asserts agreement, so bumping either side
|
|
19
|
+
# alone turns the tests red.
|
|
20
|
+
TAILWIND_VERSION = "4.3.1"
|
|
21
|
+
|
|
22
|
+
BUNDLE_PATH = File.expand_path("../../../vendor/tw-bundle.js", __dir__)
|
|
23
|
+
DEFAULT_CSS = %(@import "tailwindcss";)
|
|
24
|
+
|
|
25
|
+
class << self
|
|
26
|
+
# One warm oracle per (process, stylesheet, engine). The PID in the key
|
|
27
|
+
# makes forked rubocop workers each boot their own engine lazily - an
|
|
28
|
+
# embedded VM must never be shared across a fork.
|
|
29
|
+
def for(stylesheet:, engine:)
|
|
30
|
+
key = [ Process.pid, stylesheet, engine ]
|
|
31
|
+
if @key != key
|
|
32
|
+
@key = key
|
|
33
|
+
@instance = new(stylesheet: stylesheet, engine: engine)
|
|
34
|
+
end
|
|
35
|
+
@instance
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def initialize(stylesheet: nil, engine: "quickjs")
|
|
40
|
+
@stylesheet = stylesheet
|
|
41
|
+
@engine = build_engine(engine)
|
|
42
|
+
boot
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def sort(class_string)
|
|
46
|
+
@engine.run("__twSort(#{class_string.to_json})")
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def tailwind_version
|
|
50
|
+
@engine.run("__twMeta.tailwind")
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def entry_sha
|
|
54
|
+
@engine.run("__twMeta.entrySha")
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
private
|
|
58
|
+
def build_engine(name)
|
|
59
|
+
case name.to_s
|
|
60
|
+
when "quickjs" then QuickjsEngine.new
|
|
61
|
+
when "mini_racer" then MiniRacerEngine.new
|
|
62
|
+
else raise Error, %(unknown engine #{name.inspect} - use "quickjs" or "mini_racer")
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def boot
|
|
67
|
+
@engine.run(File.read(BUNDLE_PATH))
|
|
68
|
+
@engine.run("__twInit(#{user_css.to_json})")
|
|
69
|
+
@engine.drain
|
|
70
|
+
assert_loaded
|
|
71
|
+
assert_sorting
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def user_css
|
|
75
|
+
if @stylesheet
|
|
76
|
+
inline_relative_imports File.read(@stylesheet), File.dirname(@stylesheet)
|
|
77
|
+
else
|
|
78
|
+
DEFAULT_CSS
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# The design system receives one flat CSS string: Ruby owns the
|
|
83
|
+
# filesystem, so relative imports are inlined here and only
|
|
84
|
+
# `@import "tailwindcss"` remains for the bundle's embedded files.
|
|
85
|
+
def inline_relative_imports(css, dir)
|
|
86
|
+
css.gsub(%r{@import\s+"(\./[^"]+)"\s*;}) do
|
|
87
|
+
path = File.expand_path(Regexp.last_match(1), dir)
|
|
88
|
+
inline_relative_imports File.read(path), File.dirname(path)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def assert_loaded
|
|
93
|
+
if error = @engine.run("__tw.error")
|
|
94
|
+
raise Error, "Tailwind design system failed to load: #{error}"
|
|
95
|
+
end
|
|
96
|
+
unless @engine.run("__tw.ready")
|
|
97
|
+
raise Error, "Tailwind design system never became ready - promise jobs stalled in the JS engine"
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# A design system that loads but does not sort would pass every file as
|
|
102
|
+
# clean - prove the order before trusting anything it says.
|
|
103
|
+
def assert_sorting
|
|
104
|
+
unless sort("px-4 flex") == "flex px-4"
|
|
105
|
+
raise Error, "sorter self-check failed - the design system is not ordering classes"
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Engine adapters: same bundle, same calls. QuickJS leaves promise jobs
|
|
110
|
+
# to the embedder (drain pumps them); V8 drains its microtask queue
|
|
111
|
+
# itself at the end of every evaluation.
|
|
112
|
+
class QuickjsEngine
|
|
113
|
+
def initialize
|
|
114
|
+
require "quickjs"
|
|
115
|
+
@vm = Quickjs::VM.new(memory_limit: 256 * 1024 * 1024, timeout_msec: 30_000)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def run(code)
|
|
119
|
+
@vm.eval_code(code)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def drain
|
|
123
|
+
@vm.drain_jobs!
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
class MiniRacerEngine
|
|
128
|
+
def initialize
|
|
129
|
+
require "mini_racer"
|
|
130
|
+
@context = MiniRacer::Context.new
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def run(code)
|
|
134
|
+
@context.eval(code)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def drain
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
data/lib/rubocop-tailwindcss.rb
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
end
|
|
3
|
+
require "rubocop"
|
|
4
|
+
|
|
5
|
+
require_relative "rubocop/tailwindcss/version"
|
|
6
|
+
require_relative "rubocop/tailwindcss/plugin"
|
|
7
|
+
require_relative "rubocop/tailwindcss/sorter"
|
|
8
|
+
require_relative "rubocop/cop/tailwindcss/class_order"
|