anubis-ui 1.1.0 → 1.2.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.
- package/README.md +131 -62
- package/index.js +1 -1
- package/package.json +1 -1
- package/src/config/config.tool.ts +8 -29
- package/src/config/presets.config.json +47 -33
- package/src/config/qol.config.json +42 -0
- package/src/config/states.config.json +4 -0
- package/src/interfaces/config.interface.ts +16 -0
- package/src/interfaces/preset.interface.ts +18 -0
- package/src/tools/{extract/classes/index.ts → extraction/extractClasses.ts} +15 -15
- package/src/tools/mapping/mapClassIntoRule.ts +108 -84
- package/src/config/selectors.config.json +0 -13
- package/src/interfaces/config.presets.interface.ts +0 -19
- package/src/tools/declaration/color.ts +0 -3
- /package/src/tools/{fileHandling → fileStuff}/configFile.ts +0 -0
- /package/src/tools/{fileHandling → fileStuff}/cssFile.ts +0 -0
- /package/src/tools/{fileHandling → fileStuff}/file.tools.ts +0 -0
package/README.md
CHANGED
|
@@ -146,18 +146,28 @@ For every config you want to change, add the corresponding section in your confi
|
|
|
146
146
|
// colors.config.json
|
|
147
147
|
"colors": ["primary", "secondary"],
|
|
148
148
|
|
|
149
|
-
//
|
|
150
|
-
"
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
149
|
+
// states.config.json
|
|
150
|
+
"states": ["hover"],
|
|
151
|
+
|
|
152
|
+
// qol.config.json
|
|
153
|
+
"qol": [
|
|
154
|
+
{
|
|
155
|
+
"prefix": "bg",
|
|
156
|
+
"declaration": "background: ${color}"
|
|
157
|
+
}
|
|
158
|
+
],
|
|
154
159
|
|
|
155
160
|
// presets.config.json
|
|
156
|
-
"presets":
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
+
"presets": [
|
|
162
|
+
{
|
|
163
|
+
"prefix": "border",
|
|
164
|
+
"declaration": "border-width: ${value} !important; border-color: ${color} !important; border-style: solid;",
|
|
165
|
+
"variations": {
|
|
166
|
+
"default": "4px",
|
|
167
|
+
"thin": "2px"
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
]
|
|
161
171
|
}
|
|
162
172
|
```
|
|
163
173
|
<sup>anubis.config.json (example)</sup>
|
|
@@ -212,65 +222,125 @@ Configure common style presets
|
|
|
212
222
|
<summary>Default config</summary>
|
|
213
223
|
|
|
214
224
|
```json
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
225
|
+
[
|
|
226
|
+
{
|
|
227
|
+
"prefix": "bg",
|
|
228
|
+
"declaration": "background: ${color}"
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
"prefix": "border",
|
|
232
|
+
"declaration": "border-width: ${value} !important; border-color: ${color} !important; border-style: solid;",
|
|
233
|
+
"variations": {
|
|
234
|
+
"default": "4px",
|
|
235
|
+
"thinest": "1px",
|
|
236
|
+
"thiner": "2px",
|
|
237
|
+
"thin": "3px",
|
|
238
|
+
"thick": "6px",
|
|
239
|
+
"thicker": "8px",
|
|
240
|
+
"thickest": "10px",
|
|
241
|
+
"node": "0.2rem"
|
|
242
|
+
}
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
"prefix": "inner-border",
|
|
246
|
+
"declaration": "box-shadow: inset 0px 0px 0px ${value} ${color}",
|
|
247
|
+
"variations": {
|
|
248
|
+
"default": "4px",
|
|
249
|
+
"thinest": "1px",
|
|
250
|
+
"thiner": "2px",
|
|
251
|
+
"thin": "3px",
|
|
252
|
+
"thick": "6px",
|
|
253
|
+
"thicker": "8px",
|
|
254
|
+
"thickest": "10px",
|
|
255
|
+
"node": "0.2rem"
|
|
256
|
+
}
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
"prefix": "shadow",
|
|
260
|
+
"declaration": "box-shadow: ${value} ${color}",
|
|
261
|
+
"variations": {
|
|
262
|
+
"default": "0px 0px 7px 1px",
|
|
263
|
+
"densest": "0px 0px 3px 1px",
|
|
264
|
+
"denser": "0px 0px 5px 1px",
|
|
265
|
+
"dense": "0px 0px 5px 1px",
|
|
266
|
+
"wide": "0px 0px 10px 1px",
|
|
267
|
+
"wider": "0px 0px 15px 1px",
|
|
268
|
+
"widest": "0px 0px 20px 1px"
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
]
|
|
246
272
|
```
|
|
247
273
|
</details>
|
|
248
274
|
|
|
249
|
-
|
|
250
275
|
---
|
|
251
|
-
###
|
|
252
|
-
Define
|
|
253
|
-
|
|
276
|
+
### Quality of Life (`qol.config.json`)
|
|
277
|
+
Define simple style rules that can have variations but don't require color values. These are CSS declarations that work independently.
|
|
254
278
|
<details>
|
|
255
279
|
<summary>Default config</summary>
|
|
256
280
|
|
|
257
281
|
```json
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
"
|
|
265
|
-
"
|
|
266
|
-
"
|
|
267
|
-
"
|
|
268
|
-
"
|
|
269
|
-
|
|
270
|
-
|
|
282
|
+
[
|
|
283
|
+
{
|
|
284
|
+
"prefix": "smooth",
|
|
285
|
+
"standalone": true,
|
|
286
|
+
"declaration": "transition-duration: ${value}",
|
|
287
|
+
"variations": {
|
|
288
|
+
"default": "0.1s",
|
|
289
|
+
"slowest": "0.5s",
|
|
290
|
+
"slower": "0.3s",
|
|
291
|
+
"slow": "0.2s",
|
|
292
|
+
"quick": "0.07s",
|
|
293
|
+
"quicker": "0.05s",
|
|
294
|
+
"quickest": "0.03s"
|
|
295
|
+
}
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
"prefix": "rounded",
|
|
299
|
+
"standalone": true,
|
|
300
|
+
"declaration": "border-radius: ${value}",
|
|
301
|
+
"variations": {
|
|
302
|
+
"default": "8px",
|
|
303
|
+
"square": "0px",
|
|
304
|
+
"xs": "2px",
|
|
305
|
+
"sm": "4px",
|
|
306
|
+
"md": "8px",
|
|
307
|
+
"lg": "12px",
|
|
308
|
+
"xl": "16px",
|
|
309
|
+
"very": "9999px",
|
|
310
|
+
"full": "50%",
|
|
311
|
+
"half": "100%"
|
|
312
|
+
}
|
|
313
|
+
},
|
|
314
|
+
{
|
|
315
|
+
"prefix": "border",
|
|
316
|
+
"declaration": "border-style: ${value}",
|
|
317
|
+
"variations": {
|
|
318
|
+
"solid": "solid",
|
|
319
|
+
"dashed": "dashed",
|
|
320
|
+
"dotted": "dotted"
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
]
|
|
271
324
|
```
|
|
272
325
|
</details>
|
|
273
326
|
|
|
327
|
+
QoL rules can have:
|
|
328
|
+
1. A prefix
|
|
329
|
+
2. A declaration that uses ${value} for variations
|
|
330
|
+
3. Optional variations with default values
|
|
331
|
+
4. Optional `standalone` flag to allow usage without variations
|
|
332
|
+
|
|
333
|
+
The `standalone` flag allows a QoL rule to be used without any variation. When set to `true`, the rule can be used:
|
|
334
|
+
- With a variation: `rounded-lg`, `smooth-slow`
|
|
335
|
+
- Without a variation: `rounded`, `smooth` (will use the default value)
|
|
336
|
+
|
|
337
|
+
When `standalone` is `false` or not specified, the rule must always include a variation (e.g., `border-dashed`).
|
|
338
|
+
|
|
339
|
+
Example usage:
|
|
340
|
+
```html
|
|
341
|
+
<div class="rounded-lg smooth-slow border-dashed" />
|
|
342
|
+
<div class="rounded smooth" /> <!-- Works because these are standalone -->
|
|
343
|
+
```
|
|
274
344
|
|
|
275
345
|
## Available Utility Classes
|
|
276
346
|
#### Colors
|
|
@@ -312,11 +382,10 @@ Define available states and style prefixes
|
|
|
312
382
|
├── src/
|
|
313
383
|
│ ├── config/ # Configuration files
|
|
314
384
|
│ ├── interfaces/ # TypeScript interfaces
|
|
315
|
-
│ ├── manual/ # Manually trigger anubis actions
|
|
316
385
|
│ └── tools/
|
|
317
|
-
│
|
|
318
|
-
│
|
|
319
|
-
│
|
|
386
|
+
│ ├── extraction/ # Class extraction logic
|
|
387
|
+
│ ├── fileStuff/ # File handling utilities
|
|
388
|
+
│ └── mapping/ # Class to CSS rule mapping
|
|
320
389
|
└── index.js # Plugin entry point
|
|
321
390
|
```
|
|
322
391
|
|
package/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const { init: initConfig } = require('./dist/config/config.tool');
|
|
4
4
|
const { log, logPrefix, logo } = require('./dist/tools/logger');
|
|
5
|
-
const { init: initClassExtraction } = require('./dist/tools/
|
|
5
|
+
const { init: initClassExtraction } = require('./dist/tools/extraction/extractClasses');
|
|
6
6
|
|
|
7
7
|
/** List every imported colors across the projet */
|
|
8
8
|
const colors = [];
|
package/package.json
CHANGED
|
@@ -1,47 +1,26 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { IEnvConfig } from "../interfaces/config.interface";
|
|
2
|
+
import { readUserConfigFile, userConfig } from "../tools/fileStuff/configFile"
|
|
2
3
|
import { log } from "../tools/logger"
|
|
3
4
|
|
|
4
5
|
const fs = require('fs')
|
|
5
6
|
const path = require('path')
|
|
6
7
|
|
|
7
|
-
interface IPreset {
|
|
8
|
-
[key: string]: string
|
|
9
|
-
}
|
|
10
|
-
interface IEnvConfig {
|
|
11
|
-
files: {
|
|
12
|
-
targets: string|string[],
|
|
13
|
-
ignore: string[]
|
|
14
|
-
},
|
|
15
|
-
colors: string[],
|
|
16
|
-
selectors: {
|
|
17
|
-
states: string[],
|
|
18
|
-
prefixes: string[]
|
|
19
|
-
},
|
|
20
|
-
presets: {
|
|
21
|
-
'border': IPreset[],
|
|
22
|
-
'inner-border': IPreset[],
|
|
23
|
-
'shadow': IPreset[],
|
|
24
|
-
},
|
|
25
|
-
[key: string]: any
|
|
26
|
-
}
|
|
27
|
-
|
|
28
8
|
const anubisConfigFolder = path.join(__dirname, '..', '..', 'src', 'config');
|
|
29
9
|
const anubisConfigFiles = [
|
|
10
|
+
'qol',
|
|
30
11
|
'files',
|
|
31
12
|
'colors',
|
|
13
|
+
'states',
|
|
32
14
|
'presets',
|
|
33
|
-
'selectors'
|
|
34
15
|
]
|
|
35
16
|
|
|
36
17
|
const config = {
|
|
18
|
+
qol: [],
|
|
19
|
+
presets: [],
|
|
20
|
+
|
|
37
21
|
files: { targets: [], ignore: [] },
|
|
38
22
|
colors: [],
|
|
39
|
-
|
|
40
|
-
presets: {
|
|
41
|
-
border: [],
|
|
42
|
-
"inner-border": [],
|
|
43
|
-
shadow: [],
|
|
44
|
-
},
|
|
23
|
+
states: [],
|
|
45
24
|
} as IEnvConfig
|
|
46
25
|
|
|
47
26
|
const init = () => {
|
|
@@ -1,33 +1,47 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"prefix": "bg",
|
|
4
|
+
"declaration": "background: ${color}"
|
|
5
|
+
},
|
|
6
|
+
{
|
|
7
|
+
"prefix": "border",
|
|
8
|
+
"declaration": "border-width: ${value} !important; border-color: ${color} !important; border-style: solid;",
|
|
9
|
+
"variations": {
|
|
10
|
+
"default": "4px",
|
|
11
|
+
"thinest": "1px",
|
|
12
|
+
"thiner": "2px",
|
|
13
|
+
"thin": "3px",
|
|
14
|
+
"thick": "6px",
|
|
15
|
+
"thicker": "8px",
|
|
16
|
+
"thickest": "10px",
|
|
17
|
+
"node": "0.2rem"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"prefix": "inner-border",
|
|
22
|
+
"declaration": "box-shadow: inset 0px 0px 0px ${value} ${color}",
|
|
23
|
+
"variations": {
|
|
24
|
+
"default": "4px" ,
|
|
25
|
+
"thinest": "1px" ,
|
|
26
|
+
"thiner": "2px" ,
|
|
27
|
+
"thin": "3px" ,
|
|
28
|
+
"thick": "6px" ,
|
|
29
|
+
"thicker": "8px" ,
|
|
30
|
+
"thickest": "10px" ,
|
|
31
|
+
"node": "0.2rem"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"prefix": "shadow",
|
|
36
|
+
"declaration": "box-shadow: ${value} ${color}",
|
|
37
|
+
"variations": {
|
|
38
|
+
"default": "0px 0px 7px 1px" ,
|
|
39
|
+
"densest": "0px 0px 3px 1px" ,
|
|
40
|
+
"denser": "0px 0px 5px 1px" ,
|
|
41
|
+
"dense": "0px 0px 5px 1px" ,
|
|
42
|
+
"wide": "0px 0px 10px 1px" ,
|
|
43
|
+
"wider": "0px 0px 15px 1px" ,
|
|
44
|
+
"widest": "0px 0px 20px 1px"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
]
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"prefix": "smooth",
|
|
4
|
+
"standalone": true,
|
|
5
|
+
"declaration": "transition-duration: ${value}",
|
|
6
|
+
"variations": {
|
|
7
|
+
"default": "0.1s",
|
|
8
|
+
"slowest": "0.5s",
|
|
9
|
+
"slower": "0.3s",
|
|
10
|
+
"slow": "0.2s",
|
|
11
|
+
"quick": "0.07s",
|
|
12
|
+
"quicker": "0.05s",
|
|
13
|
+
"quickest": "0.03s"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"prefix": "rounded",
|
|
18
|
+
"standalone": true,
|
|
19
|
+
"declaration": "border-radius: ${value}",
|
|
20
|
+
"variations": {
|
|
21
|
+
"default": "8px",
|
|
22
|
+
"square": "0px",
|
|
23
|
+
"xs": "2px",
|
|
24
|
+
"sm": "4px",
|
|
25
|
+
"md": "8px",
|
|
26
|
+
"lg": "12px",
|
|
27
|
+
"xl": "16s",
|
|
28
|
+
"very": "9999px",
|
|
29
|
+
"full": "50%",
|
|
30
|
+
"half": "100%"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"prefix": "border",
|
|
35
|
+
"declaration": "border-style: ${value}",
|
|
36
|
+
"variations": {
|
|
37
|
+
"solid": "solid",
|
|
38
|
+
"dashed": "dashed",
|
|
39
|
+
"dotted": "dotted"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
]
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { IPreset } from "./preset.interface"
|
|
2
|
+
|
|
3
|
+
export interface IFilePatterns {
|
|
4
|
+
targets: string|string[],
|
|
5
|
+
ignore: string[]
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface IEnvConfig {
|
|
9
|
+
qol: IPreset[]
|
|
10
|
+
presets: IPreset[],
|
|
11
|
+
files: IFilePatterns,
|
|
12
|
+
|
|
13
|
+
colors: string[],
|
|
14
|
+
states: string[],
|
|
15
|
+
[key: string]: any
|
|
16
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface IVariation {
|
|
2
|
+
[key: string]: string
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export interface IPreset {
|
|
6
|
+
// [key: string]: string
|
|
7
|
+
prefix: string,
|
|
8
|
+
declaration: string,
|
|
9
|
+
|
|
10
|
+
/** When true, class can be called without variation, creating a rule with default variation */
|
|
11
|
+
standalone?: boolean,
|
|
12
|
+
|
|
13
|
+
/**In a quasar project (quasar.variabls.scss), will set as !default the precised key with the default variations */
|
|
14
|
+
globalVariableOverride?: string,
|
|
15
|
+
|
|
16
|
+
/** List of every possible variations */
|
|
17
|
+
variations: IVariation
|
|
18
|
+
}
|
|
@@ -1,21 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { getFiles } from "../fileStuff/file.tools"
|
|
2
|
+
import { mapClassesIntoRules } from "../mapping/mapClassIntoRule"
|
|
3
|
+
import { buildCssRuleFile } from "../fileStuff/cssFile"
|
|
4
|
+
import { config } from "../../config/config.tool"
|
|
5
5
|
|
|
6
6
|
const fs = require('fs')
|
|
7
7
|
|
|
8
8
|
/** Fetch vue file based on config target patterns */
|
|
9
9
|
const init = async () => {
|
|
10
10
|
const files = await getFiles(config.files)
|
|
11
|
-
// console.log({ files })
|
|
12
11
|
|
|
13
12
|
const uniqueClasses = await getUniqueClasses(files)
|
|
14
13
|
const mappedRules = mapClassesIntoRules(uniqueClasses)
|
|
15
|
-
// console.log({ uniqueClasses, mappedRules })
|
|
16
14
|
|
|
17
15
|
const file = buildCssRuleFile(mappedRules)
|
|
18
|
-
|
|
16
|
+
return file
|
|
19
17
|
}
|
|
20
18
|
|
|
21
19
|
/** Extract detected class and map into a flat set */
|
|
@@ -27,8 +25,6 @@ const getUniqueClasses = async (files: string[]): Promise<string[]> => {
|
|
|
27
25
|
?.sort()
|
|
28
26
|
|
|
29
27
|
const uniqueClasses = Array.from(new Set(extractedClasses))
|
|
30
|
-
// log(`${uniqueClasses?.length} classes found`)
|
|
31
|
-
|
|
32
28
|
return uniqueClasses
|
|
33
29
|
}
|
|
34
30
|
|
|
@@ -37,16 +33,20 @@ const extractClasses = async (filePath: string): Promise<string[]> => {
|
|
|
37
33
|
const file = await fs.promises.readFile(filePath, 'utf-8')
|
|
38
34
|
if (!file) { return [] }
|
|
39
35
|
|
|
40
|
-
const { states,
|
|
36
|
+
const { states, qol, presets } = config
|
|
41
37
|
|
|
42
|
-
const
|
|
43
|
-
const
|
|
38
|
+
const partialPrefixes = presets?.map(p => `${p.prefix}-`)
|
|
39
|
+
const partialQol = qol?.map(q => `${q.prefix}`)
|
|
44
40
|
|
|
45
|
-
const
|
|
41
|
+
const mappedPrefixes = [
|
|
42
|
+
...partialPrefixes,
|
|
43
|
+
...partialQol
|
|
44
|
+
]?.join('|')
|
|
45
|
+
const mappedStates = `(${states?.map(s => `${s}:`)?.join('|')})`
|
|
46
46
|
|
|
47
|
-
const
|
|
48
|
-
if (!matches?.length) { return [] }
|
|
47
|
+
const classDetectionRegex = new RegExp(`${mappedStates}?(${mappedPrefixes})(-?(\\w+(-+)?)+)?`, 'gi')
|
|
49
48
|
|
|
49
|
+
const matches = file.match(classDetectionRegex) || []
|
|
50
50
|
return matches
|
|
51
51
|
}
|
|
52
52
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { config } from "../../config/config.tool"
|
|
2
|
+
import { IPreset } from "../../interfaces/preset.interface"
|
|
2
3
|
import { log } from "../logger"
|
|
3
4
|
|
|
4
5
|
const mapClassesIntoRules = (classes: string[]) => {
|
|
@@ -13,31 +14,52 @@ const mapClassesIntoRules = (classes: string[]) => {
|
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
const mapClassIntoRule = (stringClass: string) => {
|
|
16
|
-
const colorExists = config.colors?.some(color => stringClass.includes(color))
|
|
17
|
-
if (!colorExists) { return }
|
|
18
|
-
|
|
19
17
|
const params = getClassInfos(stringClass)
|
|
20
|
-
// console.log({ params })
|
|
21
18
|
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
/**
|
|
20
|
+
* _ If no variations are found, maybe it's just a color like bg-primary
|
|
21
|
+
* _ So we need to check if the color exists to avoid useless computing
|
|
22
|
+
* */
|
|
23
|
+
if (!params.preset) {
|
|
24
|
+
const { colorExists } = checkOpacity(params.color)
|
|
25
|
+
|
|
26
|
+
if (!colorExists) {
|
|
27
|
+
return
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* _ If the current QoL isn't standalone (can be called without variation)
|
|
33
|
+
* _ no
|
|
34
|
+
*/
|
|
35
|
+
if (!params.color && !params.preset?.standalone) {
|
|
36
|
+
return
|
|
37
|
+
}
|
|
24
38
|
|
|
39
|
+
const rule = mapIntoRule(params)
|
|
25
40
|
return rule
|
|
26
41
|
}
|
|
27
42
|
|
|
28
|
-
const getClassInfos = (stringClass: string)
|
|
43
|
+
const getClassInfos = (stringClass: string) => {
|
|
29
44
|
const { cleanedClass, state } = getStateInfos(stringClass)
|
|
30
45
|
const { cleanedColor, prefix } = getPrefixInfos(cleanedClass)
|
|
31
|
-
const {
|
|
46
|
+
const { preset, variation } = getPresetInfos({ cleanedColor, prefix })
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
state,
|
|
32
50
|
|
|
33
|
-
|
|
34
|
-
|
|
51
|
+
color: cleanedColor,
|
|
52
|
+
prefix,
|
|
53
|
+
|
|
54
|
+
preset,
|
|
55
|
+
variation
|
|
56
|
+
}
|
|
35
57
|
}
|
|
36
58
|
|
|
37
59
|
const getStateInfos = (stringClass: string) => {
|
|
38
60
|
let state = undefined
|
|
39
61
|
|
|
40
|
-
for (const configState of config.
|
|
62
|
+
for (const configState of config.states) {
|
|
41
63
|
if (!stringClass.startsWith(configState)) { continue }
|
|
42
64
|
|
|
43
65
|
state = configState
|
|
@@ -51,62 +73,67 @@ const getStateInfos = (stringClass: string) => {
|
|
|
51
73
|
}
|
|
52
74
|
|
|
53
75
|
const getPrefixInfos = (stringClass: string): { cleanedColor: string, prefix: string } => {
|
|
54
|
-
|
|
76
|
+
const prefixes = [
|
|
77
|
+
...config.presets?.map(q => q.prefix),
|
|
78
|
+
...config.qol?.map(q => q.prefix)
|
|
79
|
+
]
|
|
55
80
|
|
|
56
|
-
for (const
|
|
57
|
-
if (!stringClass.startsWith(
|
|
81
|
+
for (const prefix of prefixes) {
|
|
82
|
+
if (!stringClass.startsWith(prefix)) { continue }
|
|
58
83
|
|
|
59
|
-
|
|
84
|
+
return {
|
|
85
|
+
cleanedColor: stringClass?.slice(prefix.length + 1),
|
|
86
|
+
prefix
|
|
87
|
+
}
|
|
60
88
|
}
|
|
61
89
|
|
|
62
|
-
return
|
|
63
|
-
cleanedColor: stringClass?.slice(prefix.length + 1),
|
|
64
|
-
prefix,
|
|
65
|
-
}
|
|
90
|
+
return null
|
|
66
91
|
}
|
|
67
92
|
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
93
|
+
const getPresetInfos = ({ cleanedColor, prefix }: { cleanedColor: string, prefix?: string }) => {
|
|
94
|
+
/**
|
|
95
|
+
* _ Find preset variants matching the prefix from the config
|
|
96
|
+
* _ Since a prefix can be in multiple presets and qol, filter every matching prefixes then flatten everything
|
|
97
|
+
* TODO fix first default occurence getting picked when duplicate
|
|
98
|
+
* */
|
|
99
|
+
const possiblePresets = [...config.presets, ...config.qol]
|
|
100
|
+
?.filter(p => p.prefix === prefix)
|
|
101
|
+
?.flat()
|
|
102
|
+
if (!possiblePresets?.length) { return { matchingPreset: null, variation: null } }
|
|
103
|
+
|
|
104
|
+
const { colorExists } = checkOpacity(cleanedColor)
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Find the preset where the variations exists
|
|
108
|
+
* If the color exists, it is a preset, so use the preset
|
|
109
|
+
* */
|
|
110
|
+
const matchingPreset = colorExists || !cleanedColor
|
|
111
|
+
? possiblePresets[0]
|
|
112
|
+
: possiblePresets?.find(({ variations }) => !variations || Object.keys(variations)?.find(v => cleanedColor.endsWith(v)))
|
|
113
|
+
|
|
114
|
+
if (!matchingPreset) {
|
|
115
|
+
log(`No preset found for ${cleanedColor || prefix}`)
|
|
116
|
+
|
|
73
117
|
return {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
// variation: {
|
|
77
|
-
// key: 'opacity',
|
|
78
|
-
// value: cleanedColor?.slice(-2),
|
|
79
|
-
// }
|
|
118
|
+
matchingPreset,
|
|
119
|
+
variation: null
|
|
80
120
|
}
|
|
81
121
|
}
|
|
82
122
|
|
|
83
|
-
|
|
84
|
-
const variants = config.presets[prefix as keyof typeof config.presets]
|
|
85
|
-
if (!variants) { return { color: cleanedColor } }
|
|
86
|
-
|
|
87
|
-
// _ Map found variants into a key/value object
|
|
88
|
-
const matchingVariants = variants
|
|
89
|
-
?.map(v => Object.entries(v))
|
|
90
|
-
?.flat()
|
|
91
|
-
?.map(([key, value]) => ({ key, value }))
|
|
92
|
-
// ?.filter(({ key }) => key !== 'default')
|
|
123
|
+
const possibleVariations = (matchingPreset.variations || { default: '' })
|
|
93
124
|
|
|
94
|
-
const
|
|
95
|
-
|
|
125
|
+
const matchingVariation = Object.keys(possibleVariations)
|
|
126
|
+
?.find(v => cleanedColor.endsWith(v)) || 'default'
|
|
96
127
|
|
|
97
|
-
const
|
|
98
|
-
? cleanedColor?.slice(0, variation.key.length + 1)
|
|
99
|
-
: cleanedColor
|
|
128
|
+
const variation = possibleVariations[matchingVariation]
|
|
100
129
|
|
|
101
130
|
return {
|
|
102
|
-
|
|
103
|
-
variation
|
|
131
|
+
preset: matchingPreset,
|
|
132
|
+
variation,
|
|
104
133
|
}
|
|
105
134
|
}
|
|
106
135
|
|
|
107
|
-
|
|
108
|
-
const colorVar = `var(--${color})`
|
|
109
|
-
|
|
136
|
+
const mapIntoRule = ({ state, prefix, color, preset, variation }) => {
|
|
110
137
|
// _ Set state selector
|
|
111
138
|
let stateSelector = ''
|
|
112
139
|
switch (state) {
|
|
@@ -119,50 +146,47 @@ function mapIntoRule({ state, prefix, color, variation }: { state?: string, pref
|
|
|
119
146
|
break
|
|
120
147
|
}
|
|
121
148
|
|
|
122
|
-
let
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
switch (prefix) {
|
|
127
|
-
case 'bg':
|
|
128
|
-
declaration = `background: ${colorVar} !important`
|
|
129
|
-
break
|
|
130
|
-
|
|
131
|
-
case 'text':
|
|
132
|
-
declaration = `color: ${colorVar} !important`
|
|
133
|
-
break
|
|
134
|
-
|
|
135
|
-
case 'border':
|
|
136
|
-
declaration = `border-width: ${variation?.value} !important; border-color: ${colorVar} !important; border-style: solid`
|
|
137
|
-
break
|
|
138
|
-
|
|
139
|
-
case 'inner-border':
|
|
140
|
-
declaration = `box-shadow: inset ${variation?.value} ${colorVar} !important`
|
|
141
|
-
break
|
|
142
|
-
|
|
143
|
-
case 'shadow':
|
|
144
|
-
declaration = `box-shadow: ${variation?.value} ${colorVar} !important`
|
|
145
|
-
break
|
|
149
|
+
let selector = `${prefix}${color ? `-${color}` : ''}`
|
|
150
|
+
if (state) {
|
|
151
|
+
selector = `${state}\\:${selector}${stateSelector}`
|
|
152
|
+
}
|
|
146
153
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
154
|
+
const colorVar = `var(--${color})`
|
|
155
|
+
let declaration = preset.declaration
|
|
156
|
+
?.replace('${value}', variation)
|
|
157
|
+
?.replace('${color}', colorVar)
|
|
151
158
|
|
|
152
|
-
|
|
153
|
-
|
|
159
|
+
if (!declaration.endsWith(';')) {
|
|
160
|
+
declaration += ';'
|
|
154
161
|
}
|
|
155
162
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
163
|
+
if (!declaration.includes('!important')) {
|
|
164
|
+
declaration = declaration
|
|
165
|
+
?.replace(';', ' !important;')
|
|
159
166
|
}
|
|
160
167
|
|
|
161
168
|
const rule = `.${selector} { ${declaration} }`
|
|
162
|
-
|
|
163
169
|
return rule
|
|
164
170
|
}
|
|
165
171
|
|
|
172
|
+
/**
|
|
173
|
+
* _ Check if a color includes opacity (ends with 2 digits)
|
|
174
|
+
* * Opacity is included in the color name during mixin declaration
|
|
175
|
+
* */
|
|
176
|
+
const checkOpacity = (color: string) => {
|
|
177
|
+
const opacityDetectionRegex = new RegExp(/(?:(\w-?)+)-\d{2}$/, 'gm') // Strings that end with two digits
|
|
178
|
+
const isOpacity = opacityDetectionRegex.test(color)
|
|
179
|
+
|
|
180
|
+
const baseColor = isOpacity ? color?.slice(0, -3) : color
|
|
181
|
+
const colorExists = config.colors?.some(configColor => configColor === baseColor)
|
|
182
|
+
|
|
183
|
+
return {
|
|
184
|
+
colorExists,
|
|
185
|
+
isOpacity,
|
|
186
|
+
baseColor
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
166
190
|
export {
|
|
167
191
|
mapClassesIntoRules,
|
|
168
192
|
mapClassIntoRule
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
interface IConfigDeclaration {
|
|
2
|
-
[key: string]: string,
|
|
3
|
-
}
|
|
4
|
-
|
|
5
|
-
export interface IConfigPresets {
|
|
6
|
-
defaultInnerBorderWidth?: string
|
|
7
|
-
innerBorderWidths?: IConfigDeclaration[]
|
|
8
|
-
|
|
9
|
-
defaultBorderWidth?: string
|
|
10
|
-
borderWidths?: IConfigDeclaration[]
|
|
11
|
-
|
|
12
|
-
defaultShadow?: string,
|
|
13
|
-
shadowWidths?: IConfigDeclaration[]
|
|
14
|
-
|
|
15
|
-
defaultBorderRadius?: string
|
|
16
|
-
borderRadiuses?: IConfigDeclaration[]
|
|
17
|
-
|
|
18
|
-
fontWeights?: IConfigDeclaration[]
|
|
19
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|