@duro-app/eslint-plugin 1.0.0 → 1.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.
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/rules/index.d.ts +7 -0
- package/dist/rules/index.d.ts.map +1 -1
- package/dist/rules/index.js +4 -0
- package/dist/rules/index.js.map +1 -1
- package/dist/rules/no-flex-grow-web.d.ts +22 -0
- package/dist/rules/no-flex-grow-web.d.ts.map +1 -0
- package/dist/rules/no-flex-grow-web.js +80 -0
- package/dist/rules/no-flex-grow-web.js.map +1 -0
- package/dist/rules/prefer-ds-form-components.d.ts +11 -0
- package/dist/rules/prefer-ds-form-components.d.ts.map +1 -0
- package/dist/rules/prefer-ds-form-components.js +61 -0
- package/dist/rules/prefer-ds-form-components.js.map +1 -0
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -21,6 +21,13 @@ declare const plugin: {
|
|
|
21
21
|
spacingProperties?: string[];
|
|
22
22
|
radiiProperties?: string[];
|
|
23
23
|
} | undefined)?], unknown, TSESLint.RuleListener>;
|
|
24
|
+
'no-flex-grow-web': TSESLint.RuleModule<"flexGrowForced", [({
|
|
25
|
+
factories?: string[];
|
|
26
|
+
} | undefined)?], unknown, TSESLint.RuleListener>;
|
|
27
|
+
'prefer-ds-form-components': TSESLint.RuleModule<"useFormKit", [({
|
|
28
|
+
allow?: string[];
|
|
29
|
+
htmlObjects?: string[];
|
|
30
|
+
} | undefined)?], unknown, TSESLint.RuleListener>;
|
|
24
31
|
};
|
|
25
32
|
configs: Record<string, TSESLint.FlatConfig.Config>;
|
|
26
33
|
};
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,0BAA0B,CAAA;AACtD,OAAO,EAAC,KAAK,EAAC,MAAM,kBAAkB,CAAA;AAEtC,QAAA,MAAM,MAAM
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,0BAA0B,CAAA;AACtD,OAAO,EAAC,KAAK,EAAC,MAAM,kBAAkB,CAAA;AAEtC,QAAA,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAGK,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC;CAC1D,CAAA;AAmBD,eAAe,MAAM,CAAA;AACrB,OAAO,EAAC,KAAK,EAAC,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -15,6 +15,8 @@ Object.assign(plugin.configs, {
|
|
|
15
15
|
'duro/no-tokens-barrel-import': 'error',
|
|
16
16
|
'duro/no-deprecated-table-parts': 'error',
|
|
17
17
|
'duro/no-raw-design-values': 'warn',
|
|
18
|
+
'duro/no-flex-grow-web': 'warn',
|
|
19
|
+
'duro/prefer-ds-form-components': 'error',
|
|
18
20
|
},
|
|
19
21
|
},
|
|
20
22
|
});
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,KAAK,EAAC,MAAM,kBAAkB,CAAA;AAEtC,MAAM,MAAM,GAAG;IACb,IAAI,EAAE,EAAC,IAAI,EAAE,MAAM,EAAC;IACpB,KAAK;IACL,OAAO,EAAE,EAAgD;CAC1D,CAAA;AAED,2EAA2E;AAC3E,0EAA0E;AAC1E,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE;IAC5B,WAAW,EAAE;QACX,IAAI,EAAE,kBAAkB;QACxB,OAAO,EAAE,EAAC,IAAI,EAAE,MAAM,EAAC;QACvB,KAAK,EAAE;YACL,0BAA0B,EAAE,OAAO;YACnC,8BAA8B,EAAE,OAAO;YACvC,gCAAgC,EAAE,OAAO;YACzC,2BAA2B,EAAE,MAAM;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,KAAK,EAAC,MAAM,kBAAkB,CAAA;AAEtC,MAAM,MAAM,GAAG;IACb,IAAI,EAAE,EAAC,IAAI,EAAE,MAAM,EAAC;IACpB,KAAK;IACL,OAAO,EAAE,EAAgD;CAC1D,CAAA;AAED,2EAA2E;AAC3E,0EAA0E;AAC1E,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE;IAC5B,WAAW,EAAE;QACX,IAAI,EAAE,kBAAkB;QACxB,OAAO,EAAE,EAAC,IAAI,EAAE,MAAM,EAAC;QACvB,KAAK,EAAE;YACL,0BAA0B,EAAE,OAAO;YACnC,8BAA8B,EAAE,OAAO;YACvC,gCAAgC,EAAE,OAAO;YACzC,2BAA2B,EAAE,MAAM;YACnC,uBAAuB,EAAE,MAAM;YAC/B,gCAAgC,EAAE,OAAO;SAC1C;KACmC;CACvC,CAAC,CAAA;AAEF,eAAe,MAAM,CAAA;AACrB,OAAO,EAAC,KAAK,EAAC,CAAA"}
|
package/dist/rules/index.d.ts
CHANGED
|
@@ -15,5 +15,12 @@ export declare const rules: {
|
|
|
15
15
|
spacingProperties?: string[];
|
|
16
16
|
radiiProperties?: string[];
|
|
17
17
|
} | undefined)?], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
18
|
+
'no-flex-grow-web': import("@typescript-eslint/utils/ts-eslint").RuleModule<"flexGrowForced", [({
|
|
19
|
+
factories?: string[];
|
|
20
|
+
} | undefined)?], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
21
|
+
'prefer-ds-form-components': import("@typescript-eslint/utils/ts-eslint").RuleModule<"useFormKit", [({
|
|
22
|
+
allow?: string[];
|
|
23
|
+
htmlObjects?: string[];
|
|
24
|
+
} | undefined)?], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
18
25
|
};
|
|
19
26
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/rules/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/rules/index.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,KAAK;;;;;;;;;;;;;;;;;;;;;;;;CAOjB,CAAA"}
|
package/dist/rules/index.js
CHANGED
|
@@ -2,10 +2,14 @@ import { noRawHtmlElement } from './no-raw-html-element.js';
|
|
|
2
2
|
import { noTokensBarrelImport } from './no-tokens-barrel-import.js';
|
|
3
3
|
import { noDeprecatedTableParts } from './no-deprecated-table-parts.js';
|
|
4
4
|
import { noRawDesignValues } from './no-raw-design-values.js';
|
|
5
|
+
import { noFlexGrowWeb } from './no-flex-grow-web.js';
|
|
6
|
+
import { preferDsFormComponents } from './prefer-ds-form-components.js';
|
|
5
7
|
export const rules = {
|
|
6
8
|
'no-raw-html-element': noRawHtmlElement,
|
|
7
9
|
'no-tokens-barrel-import': noTokensBarrelImport,
|
|
8
10
|
'no-deprecated-table-parts': noDeprecatedTableParts,
|
|
9
11
|
'no-raw-design-values': noRawDesignValues,
|
|
12
|
+
'no-flex-grow-web': noFlexGrowWeb,
|
|
13
|
+
'prefer-ds-form-components': preferDsFormComponents,
|
|
10
14
|
};
|
|
11
15
|
//# sourceMappingURL=index.js.map
|
package/dist/rules/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/rules/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,gBAAgB,EAAC,MAAM,0BAA0B,CAAA;AACzD,OAAO,EAAC,oBAAoB,EAAC,MAAM,8BAA8B,CAAA;AACjE,OAAO,EAAC,sBAAsB,EAAC,MAAM,gCAAgC,CAAA;AACrE,OAAO,EAAC,iBAAiB,EAAC,MAAM,2BAA2B,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/rules/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,gBAAgB,EAAC,MAAM,0BAA0B,CAAA;AACzD,OAAO,EAAC,oBAAoB,EAAC,MAAM,8BAA8B,CAAA;AACjE,OAAO,EAAC,sBAAsB,EAAC,MAAM,gCAAgC,CAAA;AACrE,OAAO,EAAC,iBAAiB,EAAC,MAAM,2BAA2B,CAAA;AAC3D,OAAO,EAAC,aAAa,EAAC,MAAM,uBAAuB,CAAA;AACnD,OAAO,EAAC,sBAAsB,EAAC,MAAM,gCAAgC,CAAA;AAErE,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB,qBAAqB,EAAE,gBAAgB;IACvC,yBAAyB,EAAE,oBAAoB;IAC/C,2BAA2B,EAAE,sBAAsB;IACnD,sBAAsB,EAAE,iBAAiB;IACzC,kBAAkB,EAAE,aAAa;IACjC,2BAA2B,EAAE,sBAAsB;CACpD,CAAA"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { TSESLint } from '@typescript-eslint/utils';
|
|
2
|
+
type MessageIds = 'flexGrowForced';
|
|
3
|
+
type Options = [
|
|
4
|
+
{
|
|
5
|
+
factories?: string[];
|
|
6
|
+
}?
|
|
7
|
+
];
|
|
8
|
+
/**
|
|
9
|
+
* Inside css.create() style objects, flag non-zero `flexGrow`: on the web
|
|
10
|
+
* target react-strict-dom's runtime base style forces computed
|
|
11
|
+
* `flex-grow: 0`, so the declaration silently does nothing and grow-to-fill
|
|
12
|
+
* layouts collapse (verified empirically — a flexGrow:1/flexBasis:0 column
|
|
13
|
+
* grid shrank to its content width).
|
|
14
|
+
*
|
|
15
|
+
* There is no mechanical fix: the working alternatives are a plain React DOM
|
|
16
|
+
* layout scaffold or absolute positioning against a measured container, both
|
|
17
|
+
* structural rewrites. The rule informs; it does not gate — it ships as
|
|
18
|
+
* `warn` in the recommended preset.
|
|
19
|
+
*/
|
|
20
|
+
export declare const noFlexGrowWeb: TSESLint.RuleModule<MessageIds, Options>;
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=no-flex-grow-web.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-flex-grow-web.d.ts","sourceRoot":"","sources":["../../src/rules/no-flex-grow-web.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,QAAQ,EAAW,MAAM,0BAA0B,CAAA;AAEhE,KAAK,UAAU,GAAG,gBAAgB,CAAA;AAClC,KAAK,OAAO,GAAG;IACb;QACE,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;KACrB,CAAC;CACH,CAAA;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,aAAa,EAAE,QAAQ,CAAC,UAAU,CAAC,UAAU,EAAE,OAAO,CAmElE,CAAA"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inside css.create() style objects, flag non-zero `flexGrow`: on the web
|
|
3
|
+
* target react-strict-dom's runtime base style forces computed
|
|
4
|
+
* `flex-grow: 0`, so the declaration silently does nothing and grow-to-fill
|
|
5
|
+
* layouts collapse (verified empirically — a flexGrow:1/flexBasis:0 column
|
|
6
|
+
* grid shrank to its content width).
|
|
7
|
+
*
|
|
8
|
+
* There is no mechanical fix: the working alternatives are a plain React DOM
|
|
9
|
+
* layout scaffold or absolute positioning against a measured container, both
|
|
10
|
+
* structural rewrites. The rule informs; it does not gate — it ships as
|
|
11
|
+
* `warn` in the recommended preset.
|
|
12
|
+
*/
|
|
13
|
+
export const noFlexGrowWeb = {
|
|
14
|
+
defaultOptions: [{}],
|
|
15
|
+
meta: {
|
|
16
|
+
type: 'problem',
|
|
17
|
+
docs: {
|
|
18
|
+
description: 'Disallow non-zero flexGrow in css.create styles (react-strict-dom forces flex-grow: 0 on web)',
|
|
19
|
+
},
|
|
20
|
+
schema: [
|
|
21
|
+
{
|
|
22
|
+
type: 'object',
|
|
23
|
+
properties: {
|
|
24
|
+
factories: { type: 'array', items: { type: 'string' }, uniqueItems: true },
|
|
25
|
+
},
|
|
26
|
+
additionalProperties: false,
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
messages: {
|
|
30
|
+
flexGrowForced: 'flexGrow has no effect under react-strict-dom on web — the runtime forces computed flex-grow: 0, so this layout silently collapses. Lay out with a plain DOM scaffold, or absolute-position against a measured container.',
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
create(context) {
|
|
34
|
+
const options = context.options[0] ?? {};
|
|
35
|
+
const factories = options.factories ?? ['css.create'];
|
|
36
|
+
const sourceCode = context.sourceCode;
|
|
37
|
+
function isZero(value) {
|
|
38
|
+
if (value.type === 'Literal')
|
|
39
|
+
return value.value === 0 || value.value === '0';
|
|
40
|
+
if (value.type === 'UnaryExpression' && value.operator === '-') {
|
|
41
|
+
return value.argument.type === 'Literal' && value.argument.value === 0;
|
|
42
|
+
}
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
function walk(node) {
|
|
46
|
+
for (const prop of node.properties) {
|
|
47
|
+
if (prop.type !== 'Property')
|
|
48
|
+
continue;
|
|
49
|
+
const value = prop.value;
|
|
50
|
+
const name = prop.key.type === 'Identifier' && !prop.computed
|
|
51
|
+
? prop.key.name
|
|
52
|
+
: prop.key.type === 'Literal'
|
|
53
|
+
? String(prop.key.value)
|
|
54
|
+
: null;
|
|
55
|
+
if (name === 'flexGrow' && value.type !== 'ObjectExpression') {
|
|
56
|
+
// Dynamic values (variables, conditionals) are just as forced-to-0
|
|
57
|
+
// as literals — only a literal 0 is knowably redundant-but-harmless.
|
|
58
|
+
if (!isZero(value)) {
|
|
59
|
+
context.report({ node: prop, messageId: 'flexGrowForced' });
|
|
60
|
+
}
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
// Nested objects: named styles at the top level, and media-query /
|
|
64
|
+
// pseudo maps below them ({'@media …': {flexGrow: 1}}).
|
|
65
|
+
if (value.type === 'ObjectExpression')
|
|
66
|
+
walk(value);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
CallExpression(node) {
|
|
71
|
+
if (!factories.includes(sourceCode.getText(node.callee)))
|
|
72
|
+
return;
|
|
73
|
+
const [arg] = node.arguments;
|
|
74
|
+
if (arg && arg.type === 'ObjectExpression')
|
|
75
|
+
walk(arg);
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
//# sourceMappingURL=no-flex-grow-web.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-flex-grow-web.js","sourceRoot":"","sources":["../../src/rules/no-flex-grow-web.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { TSESLint } from '@typescript-eslint/utils';
|
|
2
|
+
type MessageIds = 'useFormKit';
|
|
3
|
+
type Options = [
|
|
4
|
+
{
|
|
5
|
+
allow?: string[];
|
|
6
|
+
htmlObjects?: string[];
|
|
7
|
+
}?
|
|
8
|
+
];
|
|
9
|
+
export declare const preferDsFormComponents: TSESLint.RuleModule<MessageIds, Options>;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=prefer-ds-form-components.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prefer-ds-form-components.d.ts","sourceRoot":"","sources":["../../src/rules/prefer-ds-form-components.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,QAAQ,EAAW,MAAM,0BAA0B,CAAA;AAEhE,KAAK,UAAU,GAAG,YAAY,CAAA;AAC9B,KAAK,OAAO,GAAG;IACb;QACE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;QAChB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;KACvB,CAAC;CACH,CAAA;AAoBD,eAAO,MAAM,sBAAsB,EAAE,QAAQ,CAAC,UAAU,CAAC,UAAU,EAAE,OAAO,CAyC3E,CAAA"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Form fields go through the design system's form kit, not bare html.*
|
|
3
|
+
* primitives: `html.input` → Field.Root + Field.Label + Input, `html.select`
|
|
4
|
+
* → the Select compound, `html.textarea` → Textarea. The kit carries theming
|
|
5
|
+
* (the app-owned duro theme drives the tokens) and a11y wiring that a bare
|
|
6
|
+
* primitive silently drops.
|
|
7
|
+
*
|
|
8
|
+
* no-raw-html-element can't express this: html.input IS the correct
|
|
9
|
+
* react-strict-dom spelling — the problem is the altitude, not the element.
|
|
10
|
+
* The design system's own component sources allow these primitives by
|
|
11
|
+
* disabling the rule for that tree; consumers get it from the react preset.
|
|
12
|
+
*/
|
|
13
|
+
const FORM_KIT = {
|
|
14
|
+
input: 'Field.Root + Field.Label + Input (or Checkbox for checkables)',
|
|
15
|
+
select: 'the Select compound (Select.Root/Trigger/Value/Item)',
|
|
16
|
+
textarea: 'Textarea',
|
|
17
|
+
};
|
|
18
|
+
export const preferDsFormComponents = {
|
|
19
|
+
defaultOptions: [{}],
|
|
20
|
+
meta: {
|
|
21
|
+
type: 'problem',
|
|
22
|
+
docs: {
|
|
23
|
+
description: 'Require @duro-app/ui form components (Field/Input/Select/Textarea) instead of bare html.input/select/textarea',
|
|
24
|
+
},
|
|
25
|
+
schema: [
|
|
26
|
+
{
|
|
27
|
+
type: 'object',
|
|
28
|
+
properties: {
|
|
29
|
+
allow: { type: 'array', items: { type: 'string' }, uniqueItems: true },
|
|
30
|
+
htmlObjects: { type: 'array', items: { type: 'string' }, uniqueItems: true },
|
|
31
|
+
},
|
|
32
|
+
additionalProperties: false,
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
messages: {
|
|
36
|
+
useFormKit: 'Use {{replacement}} from @duro-app/ui instead of html.{{tag}} — the form kit carries the theme and a11y wiring. If the field you need is missing, add it to duro-design-system (`npx duro list`).',
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
create(context) {
|
|
40
|
+
const options = context.options[0] ?? {};
|
|
41
|
+
const allow = new Set(options.allow ?? []);
|
|
42
|
+
const htmlObjects = new Set(options.htmlObjects ?? ['html']);
|
|
43
|
+
return {
|
|
44
|
+
JSXOpeningElement(node) {
|
|
45
|
+
const name = node.name;
|
|
46
|
+
if (name.type !== 'JSXMemberExpression')
|
|
47
|
+
return;
|
|
48
|
+
if (name.object.type !== 'JSXIdentifier' || !htmlObjects.has(name.object.name))
|
|
49
|
+
return;
|
|
50
|
+
const tag = name.property.name;
|
|
51
|
+
if (allow.has(tag))
|
|
52
|
+
return;
|
|
53
|
+
const replacement = FORM_KIT[tag];
|
|
54
|
+
if (!replacement)
|
|
55
|
+
return;
|
|
56
|
+
context.report({ node: name, messageId: 'useFormKit', data: { tag, replacement } });
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
//# sourceMappingURL=prefer-ds-form-components.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prefer-ds-form-components.js","sourceRoot":"","sources":["../../src/rules/prefer-ds-form-components.ts"],"names":[],"mappings":"AAUA;;;;;;;;;;;GAWG;AACH,MAAM,QAAQ,GAA2B;IACvC,KAAK,EAAE,+DAA+D;IACtE,MAAM,EAAE,sDAAsD;IAC9D,QAAQ,EAAE,UAAU;CACrB,CAAA;AAED,MAAM,CAAC,MAAM,sBAAsB,GAA6C;IAC9E,cAAc,EAAE,CAAC,EAAE,CAAC;IACpB,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACJ,WAAW,EACT,+GAA+G;SAClH;QACD,MAAM,EAAE;YACN;gBACE,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE;oBACV,KAAK,EAAE,EAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAC,IAAI,EAAE,QAAQ,EAAC,EAAE,WAAW,EAAE,IAAI,EAAC;oBAClE,WAAW,EAAE,EAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAC,IAAI,EAAE,QAAQ,EAAC,EAAE,WAAW,EAAE,IAAI,EAAC;iBACzE;gBACD,oBAAoB,EAAE,KAAK;aAC5B;SACF;QACD,QAAQ,EAAE;YACR,UAAU,EACR,mMAAmM;SACtM;KACF;IACD,MAAM,CAAC,OAAO;QACZ,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;QACxC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC,CAAA;QAC1C,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,WAAW,IAAI,CAAC,MAAM,CAAC,CAAC,CAAA;QAE5D,OAAO;YACL,iBAAiB,CAAC,IAAgC;gBAChD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAA;gBACtB,IAAI,IAAI,CAAC,IAAI,KAAK,qBAAqB;oBAAE,OAAM;gBAC/C,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,eAAe,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;oBAAE,OAAM;gBACtF,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAA;gBAC9B,IAAI,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC;oBAAE,OAAM;gBAC1B,MAAM,WAAW,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAA;gBACjC,IAAI,CAAC,WAAW;oBAAE,OAAM;gBACxB,OAAO,CAAC,MAAM,CAAC,EAAC,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,YAAY,EAAE,IAAI,EAAE,EAAC,GAAG,EAAE,WAAW,EAAC,EAAC,CAAC,CAAA;YACjF,CAAC;SACF,CAAA;IACH,CAAC;CACF,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@duro-app/eslint-plugin",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "ESLint rules enforcing the Duro design system conventions: react-strict-dom html.* elements, deep token imports, token values over raw px/hex, and no deprecated Table parts.",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
|
41
41
|
},
|
|
42
42
|
"peerDependencies": {
|
|
43
|
-
"eslint": "^9.0.0"
|
|
43
|
+
"eslint": "^9.0.0 || ^10.0.0"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@typescript-eslint/parser": "^8.0.0",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"@typescript-eslint/utils": "^8.0.0",
|
|
49
49
|
"eslint": "^9.20.0",
|
|
50
50
|
"typescript": "^5.7.0",
|
|
51
|
-
"@duro-app/tokens": "^1.
|
|
51
|
+
"@duro-app/tokens": "^1.1.0"
|
|
52
52
|
},
|
|
53
53
|
"scripts": {
|
|
54
54
|
"build": "tsc -p tsconfig.build.json",
|