tailwindcss-rb 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.
@@ -0,0 +1,93 @@
1
+ require 'active_support/core_ext/object/blank'
2
+ require 'tailwindcss/helpers'
3
+
4
+ module Tailwindcss
5
+ module Compiler
6
+ class HashArgsExtractor
7
+ def call(ast:)
8
+ extract_hash_arguments_from_ast_nodes(ast)
9
+ end
10
+
11
+ private
12
+
13
+ def extract_hash_arguments_from_ast_nodes(node)
14
+ hash_args = []
15
+ return unless node.is_a?(Parser::AST::Node)
16
+
17
+ if node.type == :send
18
+ hash_args += extract_hashes(node).flatten(10)
19
+ end
20
+
21
+ node.children.each do |child|
22
+ next unless child.is_a?(Parser::AST::Node)
23
+
24
+ hash_args += extract_hash_arguments_from_ast_nodes(child)
25
+ end
26
+
27
+ hash_args.flatten.compact
28
+ end
29
+
30
+ def extract_hashes(node)
31
+ scan_for_hash_children(node).each_with_object([]) { |hash_node, acc| extract_value(hash_node, acc) }.compact
32
+ end
33
+
34
+ def scan_for_hash_children(node)
35
+ node.children[2..].select { |child| child.type == :hash }
36
+ end
37
+
38
+ def extract_value(node, acc)
39
+ node.children.select { |n| n.type == :pair }.each do |key_value_node|
40
+ key_node = key_value_node.children.first
41
+ value_node = key_value_node.children.last
42
+ value = pair_node_value(key_node, value_node)
43
+
44
+ acc << value if value.present?
45
+ end
46
+ end
47
+
48
+ def pair_node_value(key_node, value_node)
49
+ key = source_code(key_node)
50
+ case value_node.type
51
+ when :hash
52
+ hashes = []
53
+ extract_value(value_node, hashes)
54
+ hashes.flatten.map { |h| { key.to_sym => h } }
55
+ when :int, :str, :sym, :float
56
+ { key.to_sym => node_text(value_node) }
57
+ when :true
58
+ { key.to_sym => true }
59
+ when :false
60
+ { key.to_sym => false }
61
+ else
62
+ extract_color_scheme_calls(key_node, value_node)
63
+ end
64
+ end
65
+
66
+ def extract_color_scheme_calls(key_node, value_node)
67
+ value = source_code(value_node)
68
+ return unless value.include?('color_scheme_token') || value.include?('color_token')
69
+
70
+ weight_node = value_node.children[3]
71
+ weight = weight_node ? eval(source_code(weight_node)) : 500
72
+
73
+ if value.include?('color_scheme_token')
74
+ color_scheme_token = eval(source_code(value_node.children[2]))
75
+ color = Tailwindcss::Helpers.color_scheme_token(color_scheme_token, weight)
76
+ elsif value.include?('color_token')
77
+ color_token = eval(source_code(value_node.children[2]))
78
+ color = Tailwindcss::Helpers.color_token(color_token, weight)
79
+ end
80
+
81
+ { source_code(key_node).to_sym => color }
82
+ end
83
+
84
+ def node_text(node)
85
+ source_code(node).delete(':').delete('\'').to_s
86
+ end
87
+
88
+ def source_code(node)
89
+ node.location.expression.source
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,48 @@
1
+ require "fileutils"
2
+
3
+ module Tailwindcss
4
+ module Compiler
5
+ class Output
6
+ def add_entry(file_path:, classes:)
7
+ file_path = absolute_path(file_path)
8
+ return if classes.blank?
9
+
10
+ path = output_file_path(file_path:)
11
+ folder = create_output_folder(file_path: path)
12
+
13
+ path += ".classes"
14
+ File.open(path, "wb") do |file|
15
+ file << classes.join("\n")
16
+ end
17
+ File.delete(path) if File.empty?(path)
18
+ end
19
+
20
+ def compile_classes_dir
21
+ absolute_path(Tailwindcss.config.compiler.compile_classes_dir.call)
22
+ end
23
+
24
+ def create_output_folder(file_path:)
25
+ dir_name = File.dirname(file_path)
26
+ FileUtils.mkdir_p(dir_name)
27
+ end
28
+
29
+ def output_file_path(file_path:)
30
+ content.each do |folder|
31
+ if file_path.start_with?(folder)
32
+ return File.join(compile_classes_dir, file_path.delete_prefix(folder.to_s))
33
+ end
34
+ end
35
+
36
+ return nil
37
+ end
38
+
39
+ def content
40
+ Tailwindcss.config.content.call.map { |path| absolute_path(path) }
41
+ end
42
+
43
+ def absolute_path(path)
44
+ File.expand_path(path)
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,64 @@
1
+
2
+ require "listen"
3
+ require "tailwindcss"
4
+ require "tailwindcss/compiler/file_classes_extractor"
5
+ require "tailwindcss/compiler/output"
6
+ require "tailwindcss/compiler/connection" if defined?(ActionCable)
7
+ require "tailwindcss/compiler/channel" if defined?(ActionCable)
8
+
9
+ module Tailwindcss
10
+ module Compiler
11
+ class Runner
12
+ def initialize(watch: nil)
13
+ @watch = watch
14
+ end
15
+
16
+ def call # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
17
+ output = Output.new
18
+ file_classes_extractor = FileClassesExtractor.new
19
+
20
+ content.each do |location|
21
+ if watch || (watch.nil? && Tailwindcss.config.watch_content)
22
+ listener = Listen.to(File.dirname(location.to_s), only: /\.(rb|erb)$/) do |modified, added, removed|
23
+ Tailwindcss.logger.info "Recompiling Tailwindcss..."
24
+ Tailwindcss.logger.info "Modified: #{modified}"
25
+ Tailwindcss.logger.info "Added: #{added}"
26
+ Tailwindcss.logger.info "Removed: #{removed}"
27
+ (modified + added + removed).compact.each do |file_path|
28
+ next unless File.file?(file_path)
29
+
30
+ classes = file_classes_extractor.call(file_path:)
31
+ next unless classes.present?
32
+
33
+ output.add_entry(file_path:, classes:)
34
+ end
35
+
36
+ Tailwindcss.compile_css!
37
+ end
38
+
39
+ listener.start
40
+ end
41
+
42
+ Dir.glob("#{location}/**/*").each do |file_path|
43
+ next unless File.file?(file_path)
44
+
45
+ classes = file_classes_extractor.call(file_path:)
46
+ next unless classes.present?
47
+
48
+ output.add_entry(file_path:, classes:)
49
+ end
50
+ end
51
+
52
+ Tailwindcss.compile_css!
53
+ end
54
+
55
+ private
56
+
57
+ attr_reader :watch
58
+
59
+ def content
60
+ Tailwindcss.config.content.respond_to?(:call) ? Tailwindcss.config.content.call : Tailwindcss.config.content
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,322 @@
1
+ module Tailwindcss
2
+ module Constants
3
+ COLOR_WEIGHTS = ([nil] + %i[50 100 200 300 400 500 600 700 800 900]).freeze
4
+ BREAKPOINTS = %i[xs sm md lg xl 2xl].freeze
5
+ PSEUDO_SELECTORS = %i[hover focus active visited disabled first last first_of_type last_of_type odd even group_hover].freeze
6
+ PSEUDO_ELEMENTS = %i[before after file first_letter first_line selection backdrop marker].freeze
7
+
8
+ ALIGN_CONTENT = %i[normal center start end between around evenly baseline stretch].freeze
9
+ ALIGN_ITEMS = %i[start end center baseline stretch].freeze
10
+ BACKFACE_VISIBILITY = %i[visible hidden].freeze
11
+ BACKGROUND_ATTACHMENT = %i[fixed local scroll].freeze
12
+ BACKGROUND_BLEND_MODE = %i[normal multiply screen overlay darken lighten color-dodge color-burn hard-light
13
+ soft-light difference exclusion hue saturation color luminosity].freeze
14
+ BACKGROUND_CLIP = %i[border padding content].freeze
15
+ BACKGROUND_IMAGE = %i[none gradient-to-t gradient-to-tr gradient-to-r gradient-to-br gradient-to-b gradient-to-bl
16
+ gradient-to-l gradient-to-tl].freeze
17
+ BACKGROUND_ORIGIN = %i[border padding content].freeze
18
+ BACKGROUND_POSITION = %i[bottom center left left-bottom left-top right right-bottom right-top
19
+ top].freeze
20
+ BACKGROUND_REPEAT = %i[repeat repeat-x repeat-y no-repeat round space].freeze
21
+ BORDER_RADIUSES = %i[none sm md lg full].freeze
22
+ BACKGROUND_SIZE = %i[auto cover contain].freeze
23
+ BORDER_COLLAPSE = %i[collapse separate].freeze
24
+ BORDER_RADIUS = %i[none sm true md lg xl 2xl 3xl full] + [true].freeze
25
+ CONTENT = %i[none].freeze
26
+ SPACING = %i[0 px 0.5 1 1.5 2 2.5 3 3.5 4 5 6 7 8 9 10 11 12 14 16 20 24 28 32 36 40 44 48 52 56 60 64 72
27
+ 80 96 auto].freeze
28
+ BORDER_STYLE = %i[solid dashed dotted double none].freeze
29
+ BORDER = [true, false].freeze
30
+ BORDER_WIDTH = %i[0 1 2 4 8].freeze
31
+ BOX_DECORATION_BREAK = %i[slice clone].freeze
32
+ BOX_SHADOW = (%i[sm md lg xl 2xl inner none] + [true]).freeze
33
+ BOX_SIZING = %i[border content].freeze
34
+ CAPTION_SIDE = %i[top bottom].freeze
35
+ CLEAR = %i[left right both none].freeze
36
+ COLORS = %i[transparent current inherit black white neutral zync stone gray red amber yellow lime green blue indigo
37
+ violet purple pink slate emerald fuchsia rose cyan teal sky].freeze
38
+ COLOR_SCHEME = {
39
+ primary: :purple,
40
+ secondary: :indigo,
41
+ success: :emerald,
42
+ danger: :rose,
43
+ warning: :yellow,
44
+ info: :teal,
45
+ neutral: :gray,
46
+ dark: :black,
47
+ light: :white
48
+ }.freeze
49
+ COLUMNS = %i[auto 1 2 3 4 5 6 7 8 9 10 11 12 3xs 2xs xs sm md lg xl 2xl 3xl 4xl 5xl 6xl 7xl].freeze
50
+ COLUMN_SPAN = %i[auto 1 2 3 4 5 6 7 8 9 10 11 12 all].freeze
51
+ COLUMN_START = %i[auto 1 2 3 4 5 6 7 8 9 10 11 12 13].freeze
52
+ COLUMN_END = %i[auto 1 2 3 4 5 6 7 8 9 10 11 12 13].freeze
53
+ CURSOR = %i[auto default pointer wait text move help not-allowed].freeze
54
+ DISPLAY = %i[block inline-block inline inline-table table table-caption table-cell table-column table-column-group
55
+ table-footer-group table-header-group table-row table-row-group flow-root grid inline-grid contents
56
+ list-item hidden flex inline-flex].freeze
57
+ EMPTY_CELLS = %i[show hide].freeze
58
+ FLEX_BASIS = %i[auto 0].freeze
59
+ FLEX_DIRECTION = %i[row row-reverse col col-reverse].freeze
60
+ FLEX_GROW = [0, true].freeze
61
+ FLEX_SHRINK = [0, true].freeze
62
+ FLEX_WRAP = %i[wrap nowrap wrap-reverse].freeze
63
+ FLEX = %i[1 auto initial none].freeze
64
+ FONT_FAMILY = %i[sans serif mono].freeze
65
+ FONT_SIZE = %i[xs sm base lg xl 2xl 3xl 4xl 5xl 6xl 7xl 8xl 9xl].freeze
66
+ FONT_STYLE = %i[italic non-italic].freeze
67
+ FONT_VARIANT_NUMERIC = %i[normal-nums ordinal slashed-zero lining-nums oldstyle-nums proportional-nums
68
+ tabular-nums diagonal-fractions stacked-fractions].freeze
69
+ FONT_WEIGHT = %i[hairline thin light normal medium semibold bold extrabold black].freeze
70
+ GRID_AUTO_COLUMNS = %i[auto min max fr].freeze
71
+ GRID_AUTO_FLOW = %i[row column dense row-dense column-dense].freeze
72
+ GRID_AUTO_ROWS = %i[auto min max fr].freeze
73
+ GRID_TEMPLATE_COLUMNS = %i[none 1 2 3 4 5 6 7 8 9 10 11 12].freeze
74
+ GRID_TEMPLATE_ROWS = %i[none 1 2 3 4 5 6].freeze
75
+ GROUP = [true, false].freeze
76
+ SIZES = %i[0 px 0.5 1 1.5 2 2.5 3 3.5 4 5 6 7 8 9 10 11 12 14 16 20 24 28 32 36 40 44 48 52 56 60 64 72
77
+ 80 96 auto 1/2 1/3 2/3 1/4 2/4 3/4 1/5 2/5 3/5 4/5 1/6 2/6 3/6 4/6 5/6 full screen min max fit].freeze
78
+ HYPHENS = %i[none manual auto].freeze
79
+ ISOLATION = %i[isolate auto].freeze
80
+ JUSTIFY_CONTENT = %i[start end center between around evenly].freeze
81
+ JUSTIFY_ITEMS = %i[start end center baseline stretch].freeze
82
+ JUSTIFY_SELF = %i[start end center auto stretch].freeze
83
+ LETTER_SPACING = %i[tighter tight normal wide wider widest].freeze
84
+ LINE_HEIGHT = %i[none tight snug normal relaxed loose 3 4 5 6 7 8 9 10].freeze
85
+ LIST_STYLE_IMAGE = %i[none].freeze
86
+ LIST_STYLE_POSITION = %i[inside outside].freeze
87
+ LIST_STYLE_TYPE = %i[none disc decimal].freeze
88
+ MAX_SIZE = %i[0 xs sm md lg xl 2xl 3xl 4xl 5xl 6xl 7xl full screen min max fit prose screen-sm screen-md
89
+ screen-lg screen-xl screen-2xl].freeze
90
+ MIN_SIZE = [0, :full, :min, :max, :fit].freeze
91
+ MIX_BLEND_MODE = %i[normal multiply screen overlay darken lighten color-dodge color-burn hard-light soft-light
92
+ difference exclusion hue saturation color luminosity].freeze
93
+ OBJECT_FIT = %i[contain cover fill none scale-down].freeze
94
+ OBJECT_POSITION = %i[top right bottom left center].freeze
95
+ OPACITY = %i[0 5 10 20 25 30 40 50 60 70 75 80 90 95 100].freeze
96
+ ORDER = %i[first last none 1 2 3 4 5 6 7 8 9 10 11 12].freeze
97
+ OUTLINE_STYLE = %i[dotted dashed solid double none].freeze
98
+ OUTLINE_WIDTH = %i[0 1 2 4 8].freeze
99
+ OVERFLOW = %i[auto hidden visible scroll x-hidden y-hidden x-scroll y-scroll x-auto y-auto].freeze
100
+ PLACE_ITEMS = %i[start end center stretch].freeze
101
+ PLACE_SELF = %i[start end center stretch].freeze
102
+ POINTER_EVENTS = %i[none auto].freeze
103
+ POSITION = %i[static fixed absolute relative sticky].freeze
104
+ RESIZE = %i[true false none x y].freeze
105
+ ROTATE = %i[0 1 2 3 6 12 45 90 180].map { [_1, :"-#{_1}"] }.flatten.freeze
106
+ ROW_SPAN = %i[auto 1 2 3 4 5 6 full].freeze
107
+ ROW_START = %i[auto 1 2 3 4 5 6 7].freeze
108
+ ROW_END = %i[auto 1 2 3 4 5 6 7].freeze
109
+ SCALE = %i[0 50 75 90 95 100 105 110 125 150 200].freeze
110
+ SCROLL_BEHAVIOR = %i[auto smooth].freeze
111
+ SCROLL_SNAP_ALIGN = %i[start end center none].freeze
112
+ SCROLL_SNAP_STOP = %i[always normal].freeze
113
+ SCROLL_SNAP_TYPE = %i[none mandatory proximity].freeze
114
+ TABLE_LAYOUT = %i[auto fixed].freeze
115
+ TEXT_ALIGN = %i[left center right justify start end].freeze
116
+ TEXT_DECORATION = %i[underline line-through no-underline].freeze
117
+ TEXT_DECORATION_STYLE = %i[solid double dotted dashed wavy].freeze
118
+ TEXT_DECORATION_THICKNESS = %i[auto from-font 0 1 2 4 8].freeze
119
+ TEXT_OVERFLOW = %i[ellipsis truncate].freeze
120
+ TEXT_TRANSFORM = %i[uppercase lowercase capitalize normal].freeze
121
+ TEXT_UNDERLINE_OFFSET = %i[auto 0 1 2 4 8].freeze
122
+ TRANSFORM_ORIGIN = %i[center top-right top top-left right bottom-right bottom bottom-left left].freeze
123
+ TRANSITION = %i[none all colors opacity shadow transform].freeze
124
+ TRANSLATE = %i[0 0.5 px 1 1.5 2 2.5 3 3.5 4 5 6 7 8 9 10 11 12 14 16 20 24 28 32 36 40 44 48 52 56 60 64 72 80 96 1/2 1/3 2/3 1/4 2/3 2/4 3/4 full].map { [_1, :"-#{_1}"] }.flatten.freeze
125
+ USER_SELECT = %i[none text all auto].freeze
126
+ VERTICAL_ALIGN = %i[top middle bottom baseline text-top text-bottom sub super].freeze
127
+ VISIBILITY = %i[visible invisible collapse].freeze
128
+ WHITESPACE = %i[normal nowrap pre pre-line pre-wrap break-words].freeze
129
+ WILL_CHANGE = %i[auto scroll contents opacity transform].freeze
130
+ WORD_BREAK = %i[normal words all keep].freeze
131
+ Z_INDEX = %i[0 10 20 30 40 50 auto].freeze
132
+
133
+ COLOR_WITH_WEIGHTS = proc {
134
+ COLORS.map do |color|
135
+ COLOR_WEIGHTS.map { |weight| [color, weight].compact.join("-") }
136
+ end.flatten.freeze
137
+ }
138
+
139
+ THEME = {
140
+ align_content: {values: ALIGN_CONTENT, token: "content"},
141
+ align_items: {values: ALIGN_ITEMS, token: "items", alias: :items},
142
+ backface_visibility: {values: BACKFACE_VISIBILITY, token: "backface"},
143
+ background: {values: COLOR_WITH_WEIGHTS, token: "bg", alias: :bg},
144
+ background_attachment: {values: BACKGROUND_ATTACHMENT, token: "bg"},
145
+ background_blend_mode: {values: BACKGROUND_BLEND_MODE, token: "bg"},
146
+ background_clip: {values: BACKGROUND_CLIP, token: "bg"},
147
+ background_color: {values: COLOR_WITH_WEIGHTS, token: "bg"},
148
+ background_image: {values: BACKGROUND_IMAGE, token: "bg"},
149
+ background_origin: {values: BACKGROUND_ORIGIN, token: "bg"},
150
+ background_position: {values: BACKGROUND_POSITION, token: "bg"},
151
+ background_repeat: {values: BACKGROUND_REPEAT, token: "bg"},
152
+ background_size: {values: BACKGROUND_SIZE, token: "bg"},
153
+ border_bottom_left_radius: {values: BORDER_RADIUS, token: "rounded-bl"},
154
+ border_bottom_right_radius: {values: BORDER_RADIUS, token: "rounded-br"},
155
+ border_top_left_radius: {values: BORDER_RADIUS, token: "rounded-tl"},
156
+ border_top_right_radius: {values: BORDER_RADIUS, token: "rounded-tr"},
157
+ border_top_radius: {values: BORDER_RADIUS, token: "rounded-t"},
158
+ border_bottom_radius: {values: BORDER_RADIUS, token: "rounded-b"},
159
+ border_left_radius: {values: BORDER_RADIUS, token: "rounded-l"},
160
+ border_right_radius: {values: BORDER_RADIUS, token: "rounded-r"},
161
+ border_collapse: {values: BORDER_COLLAPSE, token: "border"},
162
+ border_color: {values: COLOR_WITH_WEIGHTS, token: "border"},
163
+ border_radius: {values: BORDER_RADIUS, token: "rounded", alias: :rounded},
164
+ border_spacing: {values: SPACING, token: "border-spacing"},
165
+ border_spacing_x: {values: SPACING, token: "border-spacing-x"},
166
+ border_spacing_y: {values: SPACING, token: "border-spacing-y"},
167
+ border_style: {values: BORDER_STYLE, token: "border"},
168
+ border: {values: BORDER, token: "border"},
169
+ border_top: {values: BORDER + BORDER_WIDTH, token: "border-t"},
170
+ border_bottom: {values: BORDER + BORDER_WIDTH, token: "border-b"},
171
+ border_left: {values: BORDER + BORDER_WIDTH, token: "border-l"},
172
+ border_right: {values: BORDER + BORDER_WIDTH, token: "border-r"},
173
+ border_width: {values: BORDER_WIDTH, token: "border"},
174
+ border_y: {values: BORDER_WIDTH, token: "border-y"},
175
+ border_x: {values: BORDER_WIDTH, token: "border-x"},
176
+ border_start: {values: BORDER_WIDTH, token: "border-s"},
177
+ border_end: {values: BORDER_WIDTH, token: "border-e"},
178
+ bottom: {values: SIZES, token: "bottom"},
179
+ box_decoration_break: {values: BOX_DECORATION_BREAK, token: "box-decoration-break"},
180
+ box_shadow: {values: BOX_SHADOW, token: "shadow", alias: :shadow},
181
+ box_sizing: {values: BOX_SIZING, token: "box"},
182
+ caption_side: {values: CAPTION_SIDE, token: "caption"},
183
+ clear: {values: CLEAR, token: "clear"},
184
+ color: {values: COLOR_WITH_WEIGHTS, token: "text"},
185
+ column_gap: {values: SPACING, token: "gap"},
186
+ column_span: {values: COLUMN_SPAN, token: "col-span", alias: :col_span},
187
+ column_start: {values: COLUMN_START, token: "col-start", alias: :col_start},
188
+ column_end: {values: COLUMN_END, token: "col-end", alias: :col_end},
189
+ columns: {values: COLUMNS, token: "columns"},
190
+ content: {values: CONTENT, token: "content"},
191
+ cursor: {values: CURSOR, token: "cursor"},
192
+ display: {values: DISPLAY, token: nil, alias: :d},
193
+ empty_cells: {values: EMPTY_CELLS, token: "empty"},
194
+ end: {values: SIZES, token: "end"},
195
+ fill: {values: COLOR_WITH_WEIGHTS, token: "fill"},
196
+ flex_basis: {values: FLEX_BASIS, token: "flex"},
197
+ flex_direction: {values: FLEX_DIRECTION, token: "flex", alias: :direction},
198
+ flex_grow: {values: FLEX_GROW, token: "flex", alias: :grow},
199
+ flex_shrink: {values: FLEX_SHRINK, token: "flex", alias: :shrink},
200
+ flex_wrap: {values: FLEX_WRAP, token: "flex"},
201
+ flex: {values: FLEX, token: "flex"},
202
+ font_family: {values: FONT_FAMILY, token: "font"},
203
+ font_size: {values: FONT_SIZE, token: "text"},
204
+ font_style: {values: FONT_STYLE, token: nil},
205
+ font_variant_numeric: {values: FONT_VARIANT_NUMERIC, token: nil},
206
+ font_weight: {values: FONT_WEIGHT, token: "font"},
207
+ grid_auto_columns: {values: GRID_AUTO_COLUMNS, token: "auto-cols"},
208
+ grid_auto_flow: {values: GRID_AUTO_FLOW, token: "grid-flow"},
209
+ grid_auto_rows: {values: GRID_AUTO_ROWS, token: "auto-rows"},
210
+ group: {values: GROUP, token: "group"},
211
+ gap: {values: SPACING, token: "gap"},
212
+ gap_x: {values: SPACING, token: "gap-x"},
213
+ gap_y: {values: SPACING, token: "gap-y"},
214
+ grid_template_columns: {values: GRID_TEMPLATE_COLUMNS, token: "grid-cols", alias: :grid_cols},
215
+ grid_template_rows: {values: GRID_TEMPLATE_ROWS, token: "grid-rows"},
216
+ height: {values: SIZES, token: "h", alias: :h},
217
+ hyphens: {values: HYPHENS, token: "hyphens"},
218
+ inset: {values: SIZES, token: "inset"},
219
+ inset_x: {values: SIZES, token: "inset-x"},
220
+ inset_y: {values: SIZES, token: "inset-y"},
221
+ isolation: {values: ISOLATION, token: "isolation"},
222
+ justify_content: {values: JUSTIFY_CONTENT, token: "justify", alias: :justify},
223
+ justify_items: {values: JUSTIFY_ITEMS, token: "justify"},
224
+ justify_self: {values: JUSTIFY_SELF, token: "justify"},
225
+ left: {values: SIZES, token: "left"},
226
+ letter_spacing: {values: LETTER_SPACING, token: "tracking"},
227
+ line_height: {values: LINE_HEIGHT, token: "leading"},
228
+ list_style_image: {values: LIST_STYLE_IMAGE, token: "list-image"},
229
+ list_style_position: {values: LIST_STYLE_POSITION, token: "list"},
230
+ list_style_type: {values: LIST_STYLE_TYPE, token: "list"},
231
+ margin_bottom: {values: SPACING, token: "mb", alias: :mb},
232
+ margin_end: {values: SPACING, token: "me", alias: :me},
233
+ margin_left: {values: SPACING, token: "ml", alias: :ml},
234
+ margin_right: {values: SPACING, token: "mr", alias: :mr},
235
+ margin_start: {values: SPACING, token: "ms", alias: :ms},
236
+ margin_top: {values: SPACING, token: "mt", alias: :mt},
237
+ margin_x: {values: SPACING, token: "mx", alias: :mx},
238
+ margin_y: {values: SPACING, token: "my", alias: :my},
239
+ margin: {values: SPACING, token: "m", alias: :m},
240
+ max_height: {values: SIZES, token: "max-h", alias: :max_h},
241
+ max_width: {values: SIZES, token: "max-w", alias: :max_w},
242
+ min_height: {values: SIZES, token: "min-h", alias: :min_h},
243
+ min_width: {values: SIZES, token: "min-w", alias: :min_w},
244
+ mix_blend_mode: {values: MIX_BLEND_MODE, token: "mix-blend"},
245
+ object_fit: {values: OBJECT_FIT, token: "object"},
246
+ object_position: {values: OBJECT_POSITION, token: "object"},
247
+ opacity: {values: OPACITY, token: "opacity"},
248
+ order: {values: ORDER, token: "order"},
249
+ outline_color: {values: COLOR_WITH_WEIGHTS, token: "outline"},
250
+ outline_style: {values: OUTLINE_STYLE, token: "outline", alias: :outline},
251
+ outline_width: {values: OUTLINE_WIDTH, token: "outline"},
252
+ overflow: {values: OVERFLOW, token: "overflow"},
253
+ overflow_x: {values: OVERFLOW, token: "overflow-x"},
254
+ overflow_y: {values: OVERFLOW, token: "overflow-y"},
255
+ padding: {values: SPACING, token: "p", alias: :p},
256
+ padding_bottom: {values: SPACING, token: "pb", alias: :pb},
257
+ padding_left: {values: SPACING, token: "pl", alias: :pl},
258
+ padding_right: {values: SPACING, token: "pr", alias: :pr},
259
+ padding_top: {values: SPACING, token: "pt", alias: :pt},
260
+ padding_x: {values: SPACING, token: "px", alias: :px},
261
+ padding_y: {values: SPACING, token: "py", alias: :py},
262
+ place_items: {values: PLACE_ITEMS, token: "place"},
263
+ place_self: {values: PLACE_SELF, token: "place"},
264
+ pointer_events: {values: POINTER_EVENTS, token: "pointer"},
265
+ position: {values: POSITION, token: nil},
266
+ resize: {values: RESIZE, token: "resize"},
267
+ right: {values: SIZES, token: "right"},
268
+ rotate: {values: ROTATE, token: proc { _1.to_s.start_with?("-") ? "-rotate-#{_1.to_s[1..-1]}" : "rotate-#{_1}" }},
269
+ row_gap: {values: SPACING, token: "gap"},
270
+ row_span: {values: ROW_SPAN, token: "row-span"},
271
+ row_start: {values: ROW_START, token: "row-start"},
272
+ row_end: {values: ROW_END, token: "row-end"},
273
+ scale: {values: SCALE, token: "scale"},
274
+ scale_x: {values: SCALE, token: "scale-x"},
275
+ scale_y: {values: SCALE, token: "scale-y"},
276
+ scroll_behavior: {values: SCROLL_BEHAVIOR, token: "scroll"},
277
+ scroll_margin_bottom: {values: SPACING, token: "scroll-mb"},
278
+ scroll_margin_left: {values: SPACING, token: "scroll-ml"},
279
+ scroll_margin_right: {values: SPACING, token: "scroll-mr"},
280
+ scroll_margin_top: {values: SPACING, token: "scroll-mt"},
281
+ scroll_margin_x: {values: SPACING, token: "scroll-mx"},
282
+ scroll_margin_y: {values: SPACING, token: "scroll-my"},
283
+ scroll_margin_start: {values: SPACING, token: "scroll-ms"},
284
+ scroll_margin_end: {values: SPACING, token: "scroll-me"},
285
+ scroll_padding_bottom: {values: SPACING, token: "scroll-pb"},
286
+ scroll_padding_left: {values: SPACING, token: "scroll-pl"},
287
+ scroll_padding_right: {values: SPACING, token: "scroll-pr"},
288
+ scroll_padding_top: {values: SPACING, token: "scroll-pt"},
289
+ scroll_padding_x: {values: SPACING, token: "scroll-px"},
290
+ scroll_padding_y: {values: SPACING, token: "scroll-py"},
291
+ scroll_padding_start: {values: SPACING, token: "scroll-ps"},
292
+ scroll_padding_end: {values: SPACING, token: "scroll-pe"},
293
+ scroll_snap_align: {values: SCROLL_SNAP_ALIGN, token: "snap"},
294
+ scroll_snap_stop: {values: SCROLL_SNAP_STOP, token: "snap"},
295
+ scroll_snap_type: {values: SCROLL_SNAP_TYPE, token: "snap"},
296
+ start: {values: SIZES, token: "start"},
297
+ table_layout: {values: TABLE_LAYOUT, token: "table"},
298
+ text_align: {values: TEXT_ALIGN, token: "text"},
299
+ text_decoration_color: {values: COLOR_WITH_WEIGHTS, token: "decoration"},
300
+ text_decoration_style: {values: TEXT_DECORATION_STYLE, token: "decoration"},
301
+ text_decoration_thickness: {values: TEXT_DECORATION_THICKNESS, token: "decoration"},
302
+ text_decoration: {values: TEXT_DECORATION, token: proc { _1 }},
303
+ text_indent: {values: SPACING, token: "indent"},
304
+ text_overflow: {values: TEXT_OVERFLOW, token: proc { |v| (v == "truncate") ? "truncate" : "text-#{v}" }},
305
+ text_transform: {values: TEXT_TRANSFORM, token: nil},
306
+ text_underline_offset: {values: TEXT_UNDERLINE_OFFSET, token: "underline-offset"},
307
+ top: {values: SIZES, token: "top"},
308
+ transform_origin: {values: TRANSFORM_ORIGIN, token: "origin"},
309
+ transition: {values: TRANSITION + [true], token: "transition"},
310
+ translate_x: {values: TRANSLATE, token: proc { _1.to_s.start_with?("-") ? "-translate-#{_1.to_s[1..-1]}" : "translate-#{_1}" }},
311
+ translate_y: {values: TRANSLATE, token: proc { _1.to_s.start_with?("-") ? "-translate-y-#{_1.to_s[1..-1]}" : "translate-y-#{_1}" }},
312
+ user_select: {values: USER_SELECT, token: "select"},
313
+ vertical_align: {values: VERTICAL_ALIGN, token: "align"},
314
+ visibility: {values: VISIBILITY, token: nil},
315
+ whitespace: {values: WHITESPACE, token: "whitespace", alias: :white_space},
316
+ width: {values: SIZES, token: "w", alias: :w},
317
+ will_change: {values: WILL_CHANGE, token: "will-change"},
318
+ word_break: {values: WORD_BREAK, token: "break"},
319
+ z_index: {values: Z_INDEX, token: "z", alias: :z}
320
+ }.freeze
321
+ end
322
+ end
@@ -0,0 +1,26 @@
1
+ module Tailwindcss
2
+ module Helpers
3
+ extend self
4
+
5
+ def tailwind(**style_attributes)
6
+ Style.new(**style_attributes).to_s
7
+ end
8
+ alias tw tailwind
9
+
10
+ def ab(value)
11
+ ArbitraryValue.new(value)
12
+ end
13
+
14
+ # @param token [String] A value your Tailwindcss.theme.color_scheme keys
15
+ # @param weight [Integer] A value between 100 and 900
16
+ def color_scheme_token(token, weight = 500)
17
+ color_token(Tailwindcss.theme.color_scheme[token.to_sym], weight)
18
+ end
19
+
20
+ # @param color_token [String] A value your of any of tailwinds color tokens
21
+ # @param weight [Integer] A value between 100 and 900
22
+ def color_token(color_token, weight = 500)
23
+ "#{color_token}-#{weight}"
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,17 @@
1
+ require "tailwindcss/installers/config_file_generator"
2
+
3
+ module Tailwindcss
4
+ class Installer
5
+ def call
6
+ Installers::ConfigFileGenerator.new.call
7
+ install_packages
8
+ end
9
+
10
+ private
11
+
12
+ def install_packages
13
+ system("yarn init -y") unless File.exist?('./package.json')
14
+ system("yarn add -D tailwindcss autoprefixer postcss")
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,37 @@
1
+ require "tailwindcss"
2
+ require "json"
3
+
4
+ module Tailwindcss
5
+ module Installers
6
+ class ConfigFileGenerator
7
+ def call
8
+ File.write("./tailwind.config.js", tailwind_config_file_content)
9
+ end
10
+
11
+ private
12
+
13
+ def content
14
+ value = Tailwindcss.config.content
15
+ return value unless value.respond_to?(:call)
16
+
17
+ value.call
18
+ end
19
+
20
+ def tailwind_config_file_content
21
+ content_option = (content + ["./tmp/tailwindcss"]).map { "#{_1}/**/*" }
22
+ <<~TAILWIND_CONFIG
23
+ /** @type {import('tailwindcss').Config} */
24
+
25
+ /** this file was generated automatically, please do not modify it directly!! */
26
+ /** instead change your tailwindcss-rb config and run `bundle exec rake tailwindcss:generate_config_file` */
27
+
28
+ export default {
29
+ content: #{content_option.to_json},
30
+ prefix: '#{Tailwindcss.config.prefix}',
31
+ #{Tailwindcss.config.tailwind_config_overrides.call.map { |k, v| "#{k}: #{v}," }.join("\n")}
32
+ }
33
+ TAILWIND_CONFIG
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,29 @@
1
+ require "ostruct"
2
+ require "tailwindcss/style_attributes_to_list_converter"
3
+
4
+ module Tailwindcss
5
+ class Style < ::OpenStruct
6
+ def initialize(attributes = {})
7
+ super
8
+ @attributes = attributes
9
+ end
10
+
11
+ def to_a
12
+ to_string_converter.call(**@attributes)
13
+ end
14
+
15
+ def to_s
16
+ to_a.join(" ")
17
+ end
18
+
19
+ def to_html_attributes
20
+ {class: to_s}
21
+ end
22
+
23
+ private
24
+
25
+ def to_string_converter
26
+ @to_string_converter ||= StyleAttributesToListConverter.new
27
+ end
28
+ end
29
+ end