@zukhruf/eslint 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.
- package/LICENSE +21 -0
- package/README.md +138 -0
- package/dist/authoring/ast.d.ts +10 -0
- package/dist/authoring/ast.d.ts.map +1 -0
- package/dist/authoring/ast.js +22 -0
- package/dist/authoring/ast.js.map +1 -0
- package/dist/authoring/import-ban.d.ts +14 -0
- package/dist/authoring/import-ban.d.ts.map +1 -0
- package/dist/authoring/import-ban.js +32 -0
- package/dist/authoring/import-ban.js.map +1 -0
- package/dist/authoring/path-scope.d.ts +12 -0
- package/dist/authoring/path-scope.d.ts.map +1 -0
- package/dist/authoring/path-scope.js +28 -0
- package/dist/authoring/path-scope.js.map +1 -0
- package/dist/authoring/rule-module.d.ts +14 -0
- package/dist/authoring/rule-module.d.ts.map +1 -0
- package/dist/authoring/rule-module.js +23 -0
- package/dist/authoring/rule-module.js.map +1 -0
- package/dist/authoring/scoped-rule.d.ts +8 -0
- package/dist/authoring/scoped-rule.d.ts.map +1 -0
- package/dist/authoring/scoped-rule.js +12 -0
- package/dist/authoring/scoped-rule.js.map +1 -0
- package/dist/authoring/selector-rule.d.ts +17 -0
- package/dist/authoring/selector-rule.d.ts.map +1 -0
- package/dist/authoring/selector-rule.js +23 -0
- package/dist/authoring/selector-rule.js.map +1 -0
- package/dist/base/config.d.ts +8 -0
- package/dist/base/config.d.ts.map +1 -0
- package/dist/base/config.js +122 -0
- package/dist/base/config.js.map +1 -0
- package/dist/base/options.d.ts +23 -0
- package/dist/base/options.d.ts.map +1 -0
- package/dist/base/options.js +22 -0
- package/dist/base/options.js.map +1 -0
- package/dist/concept.d.ts +16 -0
- package/dist/concept.d.ts.map +1 -0
- package/dist/concept.js +5 -0
- package/dist/concept.js.map +1 -0
- package/dist/diagnostics/config.d.ts +4 -0
- package/dist/diagnostics/config.d.ts.map +1 -0
- package/dist/diagnostics/config.js +25 -0
- package/dist/diagnostics/config.js.map +1 -0
- package/dist/diagnostics/consistent-event-name.d.ts +4 -0
- package/dist/diagnostics/consistent-event-name.d.ts.map +1 -0
- package/dist/diagnostics/consistent-event-name.js +72 -0
- package/dist/diagnostics/consistent-event-name.js.map +1 -0
- package/dist/diagnostics/no-fabricated-fallback.d.ts +4 -0
- package/dist/diagnostics/no-fabricated-fallback.d.ts.map +1 -0
- package/dist/diagnostics/no-fabricated-fallback.js +116 -0
- package/dist/diagnostics/no-fabricated-fallback.js.map +1 -0
- package/dist/diagnostics/no-hardcoded-id-shape.d.ts +4 -0
- package/dist/diagnostics/no-hardcoded-id-shape.d.ts.map +1 -0
- package/dist/diagnostics/no-hardcoded-id-shape.js +73 -0
- package/dist/diagnostics/no-hardcoded-id-shape.js.map +1 -0
- package/dist/environment/config.d.ts +7 -0
- package/dist/environment/config.d.ts.map +1 -0
- package/dist/environment/config.js +28 -0
- package/dist/environment/config.js.map +1 -0
- package/dist/environment/no-default-for-path-env.d.ts +10 -0
- package/dist/environment/no-default-for-path-env.d.ts.map +1 -0
- package/dist/environment/no-default-for-path-env.js +124 -0
- package/dist/environment/no-default-for-path-env.js.map +1 -0
- package/dist/environment/no-single-env-read-wrapper.d.ts +10 -0
- package/dist/environment/no-single-env-read-wrapper.d.ts.map +1 -0
- package/dist/environment/no-single-env-read-wrapper.js +76 -0
- package/dist/environment/no-single-env-read-wrapper.js.map +1 -0
- package/dist/environment/no-undeclared-process-env.d.ts +11 -0
- package/dist/environment/no-undeclared-process-env.d.ts.map +1 -0
- package/dist/environment/no-undeclared-process-env.js +195 -0
- package/dist/environment/no-undeclared-process-env.js.map +1 -0
- package/dist/files.d.ts +16 -0
- package/dist/files.d.ts.map +1 -0
- package/dist/files.js +27 -0
- package/dist/files.js.map +1 -0
- package/dist/hono/config.d.ts +3 -0
- package/dist/hono/config.d.ts.map +1 -0
- package/dist/hono/config.js +18 -0
- package/dist/hono/config.js.map +1 -0
- package/dist/hono/no-untyped-empty-json.d.ts +8 -0
- package/dist/hono/no-untyped-empty-json.d.ts.map +1 -0
- package/dist/hono/no-untyped-empty-json.js +14 -0
- package/dist/hono/no-untyped-empty-json.js.map +1 -0
- package/dist/imports/no-deepagents-agent.d.ts +3 -0
- package/dist/imports/no-deepagents-agent.d.ts.map +1 -0
- package/dist/imports/no-deepagents-agent.js +7 -0
- package/dist/imports/no-deepagents-agent.js.map +1 -0
- package/dist/imports/no-playwright-test.d.ts +3 -0
- package/dist/imports/no-playwright-test.d.ts.map +1 -0
- package/dist/imports/no-playwright-test.js +7 -0
- package/dist/imports/no-playwright-test.js.map +1 -0
- package/dist/imports/no-state-managers.d.ts +3 -0
- package/dist/imports/no-state-managers.d.ts.map +1 -0
- package/dist/imports/no-state-managers.js +15 -0
- package/dist/imports/no-state-managers.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/island/island-scope.d.ts +10 -0
- package/dist/island/island-scope.d.ts.map +1 -0
- package/dist/island/island-scope.js +21 -0
- package/dist/island/island-scope.js.map +1 -0
- package/dist/island/no-console.d.ts +9 -0
- package/dist/island/no-console.d.ts.map +1 -0
- package/dist/island/no-console.js +39 -0
- package/dist/island/no-console.js.map +1 -0
- package/dist/island/no-generic-port.d.ts +8 -0
- package/dist/island/no-generic-port.d.ts.map +1 -0
- package/dist/island/no-generic-port.js +14 -0
- package/dist/island/no-generic-port.js.map +1 -0
- package/dist/island/no-process-env.d.ts +3 -0
- package/dist/island/no-process-env.d.ts.map +1 -0
- package/dist/island/no-process-env.js +10 -0
- package/dist/island/no-process-env.js.map +1 -0
- package/dist/island/plugin.d.ts +25 -0
- package/dist/island/plugin.d.ts.map +1 -0
- package/dist/island/plugin.js +67 -0
- package/dist/island/plugin.js.map +1 -0
- package/dist/language/no-enum.d.ts +3 -0
- package/dist/language/no-enum.d.ts.map +1 -0
- package/dist/language/no-enum.js +7 -0
- package/dist/language/no-enum.js.map +1 -0
- package/dist/nx-policy/dependency-policy.d.ts +30 -0
- package/dist/nx-policy/dependency-policy.d.ts.map +1 -0
- package/dist/nx-policy/dependency-policy.js +31 -0
- package/dist/nx-policy/dependency-policy.js.map +1 -0
- package/dist/nx-policy/island-constraint.d.ts +10 -0
- package/dist/nx-policy/island-constraint.d.ts.map +1 -0
- package/dist/nx-policy/island-constraint.js +15 -0
- package/dist/nx-policy/island-constraint.js.map +1 -0
- package/dist/nx-policy/module-boundaries.d.ts +29 -0
- package/dist/nx-policy/module-boundaries.d.ts.map +1 -0
- package/dist/nx-policy/module-boundaries.js +20 -0
- package/dist/nx-policy/module-boundaries.js.map +1 -0
- package/dist/nx-project/config.d.ts +4 -0
- package/dist/nx-project/config.d.ts.map +1 -0
- package/dist/nx-project/config.js +20 -0
- package/dist/nx-project/config.js.map +1 -0
- package/dist/nx-project/no-missing-asset-input.d.ts +9 -0
- package/dist/nx-project/no-missing-asset-input.d.ts.map +1 -0
- package/dist/nx-project/no-missing-asset-input.js +209 -0
- package/dist/nx-project/no-missing-asset-input.js.map +1 -0
- package/dist/nx.d.ts +5 -0
- package/dist/nx.d.ts.map +1 -0
- package/dist/nx.js +5 -0
- package/dist/nx.js.map +1 -0
- package/dist/packaged-app/config.d.ts +4 -0
- package/dist/packaged-app/config.d.ts.map +1 -0
- package/dist/packaged-app/config.js +19 -0
- package/dist/packaged-app/config.js.map +1 -0
- package/dist/packaged-app/no-bare-spawn.d.ts +4 -0
- package/dist/packaged-app/no-bare-spawn.d.ts.map +1 -0
- package/dist/packaged-app/no-bare-spawn.js +175 -0
- package/dist/packaged-app/no-bare-spawn.js.map +1 -0
- package/dist/plugin.d.ts +14 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +48 -0
- package/dist/plugin.js.map +1 -0
- package/dist/pulumi/config.d.ts +3 -0
- package/dist/pulumi/config.d.ts.map +1 -0
- package/dist/pulumi/config.js +17 -0
- package/dist/pulumi/config.js.map +1 -0
- package/dist/pulumi/require-server-replace-guard.d.ts +4 -0
- package/dist/pulumi/require-server-replace-guard.d.ts.map +1 -0
- package/dist/pulumi/require-server-replace-guard.js +120 -0
- package/dist/pulumi/require-server-replace-guard.js.map +1 -0
- package/dist/react/config.d.ts +4 -0
- package/dist/react/config.d.ts.map +1 -0
- package/dist/react/config.js +13 -0
- package/dist/react/config.js.map +1 -0
- package/dist/react/require-combobox-popover-modal.d.ts +10 -0
- package/dist/react/require-combobox-popover-modal.d.ts.map +1 -0
- package/dist/react/require-combobox-popover-modal.js +101 -0
- package/dist/react/require-combobox-popover-modal.js.map +1 -0
- package/dist/react-router/config.d.ts +3 -0
- package/dist/react-router/config.d.ts.map +1 -0
- package/dist/react-router/config.js +34 -0
- package/dist/react-router/config.js.map +1 -0
- package/dist/react-router/no-internal-anchor.d.ts +8 -0
- package/dist/react-router/no-internal-anchor.d.ts.map +1 -0
- package/dist/react-router/no-internal-anchor.js +14 -0
- package/dist/react-router/no-internal-anchor.js.map +1 -0
- package/dist/react-router/no-raw-route-path.d.ts +9 -0
- package/dist/react-router/no-raw-route-path.d.ts.map +1 -0
- package/dist/react-router/no-raw-route-path.js +17 -0
- package/dist/react-router/no-raw-route-path.js.map +1 -0
- package/dist/react-router/require-loader-data-type-argument.d.ts +10 -0
- package/dist/react-router/require-loader-data-type-argument.d.ts.map +1 -0
- package/dist/react-router/require-loader-data-type-argument.js +16 -0
- package/dist/react-router/require-loader-data-type-argument.js.map +1 -0
- package/dist/tailwind/class-name-check.d.ts +12 -0
- package/dist/tailwind/class-name-check.d.ts.map +1 -0
- package/dist/tailwind/class-name-check.js +16 -0
- package/dist/tailwind/class-name-check.js.map +1 -0
- package/dist/tailwind/config.d.ts +3 -0
- package/dist/tailwind/config.d.ts.map +1 -0
- package/dist/tailwind/config.js +18 -0
- package/dist/tailwind/config.js.map +1 -0
- package/dist/tailwind/no-arbitrary-z-index.d.ts +3 -0
- package/dist/tailwind/no-arbitrary-z-index.d.ts.map +1 -0
- package/dist/tailwind/no-arbitrary-z-index.js +7 -0
- package/dist/tailwind/no-arbitrary-z-index.js.map +1 -0
- package/dist/tailwind/no-h-screen.d.ts +3 -0
- package/dist/tailwind/no-h-screen.d.ts.map +1 -0
- package/dist/tailwind/no-h-screen.js +7 -0
- package/dist/tailwind/no-h-screen.js.map +1 -0
- package/dist/tailwind/no-will-change.d.ts +3 -0
- package/dist/tailwind/no-will-change.d.ts.map +1 -0
- package/dist/tailwind/no-will-change.js +7 -0
- package/dist/tailwind/no-will-change.js.map +1 -0
- package/dist/test-files/config.d.ts +3 -0
- package/dist/test-files/config.d.ts.map +1 -0
- package/dist/test-files/config.js +16 -0
- package/dist/test-files/config.js.map +1 -0
- package/dist/test-files/no-test-lifecycle-hooks.d.ts +3 -0
- package/dist/test-files/no-test-lifecycle-hooks.d.ts.map +1 -0
- package/dist/test-files/no-test-lifecycle-hooks.js +9 -0
- package/dist/test-files/no-test-lifecycle-hooks.js.map +1 -0
- package/dist/test-files/require-msw-error-on-unhandled-request.d.ts +10 -0
- package/dist/test-files/require-msw-error-on-unhandled-request.d.ts.map +1 -0
- package/dist/test-files/require-msw-error-on-unhandled-request.js +16 -0
- package/dist/test-files/require-msw-error-on-unhandled-request.js.map +1 -0
- package/dist/workspace/project-manifest.d.ts +14 -0
- package/dist/workspace/project-manifest.d.ts.map +1 -0
- package/dist/workspace/project-manifest.js +45 -0
- package/dist/workspace/project-manifest.js.map +1 -0
- package/dist/workspace/workspace-root.d.ts +12 -0
- package/dist/workspace/workspace-root.d.ts.map +1 -0
- package/dist/workspace/workspace-root.js +46 -0
- package/dist/workspace/workspace-root.js.map +1 -0
- package/package.json +67 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { enable } from "../concept.js";
|
|
2
|
+
import { SOURCE, TESTS } from "../files.js";
|
|
3
|
+
import noInternalAnchor from "./no-internal-anchor.js";
|
|
4
|
+
import noRawRoutePath from "./no-raw-route-path.js";
|
|
5
|
+
import requireLoaderDataTypeArgument from "./require-loader-data-type-argument.js";
|
|
6
|
+
const rules = {
|
|
7
|
+
'require-loader-data-type-argument': requireLoaderDataTypeArgument,
|
|
8
|
+
'no-raw-route-path': noRawRoutePath,
|
|
9
|
+
'no-internal-anchor': noInternalAnchor,
|
|
10
|
+
};
|
|
11
|
+
export const reactRouter = {
|
|
12
|
+
name: 'react-router',
|
|
13
|
+
rules,
|
|
14
|
+
config: (plugins) => [
|
|
15
|
+
{
|
|
16
|
+
name: 'zukhruf/react-router',
|
|
17
|
+
files: SOURCE,
|
|
18
|
+
plugins,
|
|
19
|
+
rules: { 'zukhruf/require-loader-data-type-argument': 'error' },
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
// A test renders links to whatever path it sets up.
|
|
23
|
+
name: 'zukhruf/react-router/links',
|
|
24
|
+
files: SOURCE,
|
|
25
|
+
ignores: TESTS,
|
|
26
|
+
plugins,
|
|
27
|
+
rules: enable({
|
|
28
|
+
'no-raw-route-path': noRawRoutePath,
|
|
29
|
+
'no-internal-anchor': noInternalAnchor,
|
|
30
|
+
}),
|
|
31
|
+
},
|
|
32
|
+
],
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/react-router/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,MAAM,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,gBAAgB,MAAM,yBAAyB,CAAC;AACvD,OAAO,cAAc,MAAM,wBAAwB,CAAC;AACpD,OAAO,6BAA6B,MAAM,wCAAwC,CAAC;AAEnF,MAAM,KAAK,GAAG;IACZ,mCAAmC,EAAE,6BAA6B;IAClE,mBAAmB,EAAE,cAAc;IACnC,oBAAoB,EAAE,gBAAgB;CACvC,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAY;IAClC,IAAI,EAAE,cAAc;IACpB,KAAK;IACL,MAAM,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC;QACnB;YACE,IAAI,EAAE,sBAAsB;YAC5B,KAAK,EAAE,MAAM;YACb,OAAO;YACP,KAAK,EAAE,EAAE,2CAA2C,EAAE,OAAO,EAAE;SAChE;QACD;YACE,oDAAoD;YACpD,IAAI,EAAE,4BAA4B;YAClC,KAAK,EAAE,MAAM;YACb,OAAO,EAAE,KAAK;YACd,OAAO;YACP,KAAK,EAAE,MAAM,CAAC;gBACZ,mBAAmB,EAAE,cAAc;gBACnC,oBAAoB,EAAE,gBAAgB;aACvC,CAAC;SACH;KACF;CACF,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A raw `<a>` to an internal path bypasses the client router and the route
|
|
3
|
+
* table, so a link to a removed page ships green. The `(?!\/)` lookahead lets
|
|
4
|
+
* protocol-relative URLs (`//cdn…`) through.
|
|
5
|
+
*/
|
|
6
|
+
declare const _default: import("eslint").Rule.RuleModule;
|
|
7
|
+
export default _default;
|
|
8
|
+
//# sourceMappingURL=no-internal-anchor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-internal-anchor.d.ts","sourceRoot":"","sources":["../../src/react-router/no-internal-anchor.ts"],"names":[],"mappings":"AAEA;;;;GAIG;;AACH,wBAQG"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { selectorRule } from "../authoring/selector-rule.js";
|
|
2
|
+
/**
|
|
3
|
+
* A raw `<a>` to an internal path bypasses the client router and the route
|
|
4
|
+
* table, so a link to a removed page ships green. The `(?!\/)` lookahead lets
|
|
5
|
+
* protocol-relative URLs (`//cdn…`) through.
|
|
6
|
+
*/
|
|
7
|
+
export default selectorRule({
|
|
8
|
+
description: "Disallow raw <a> elements to internal paths; use react-router's <Link>",
|
|
9
|
+
selectors: [
|
|
10
|
+
'JSXOpeningElement[name.name="a"] > JSXAttribute[name.name="href"][value.value=/^\\/(?!\\/)/]',
|
|
11
|
+
],
|
|
12
|
+
message: "Internal path in a raw <a> — use <Link to={href('/path')}> from react-router so the route table checks it.",
|
|
13
|
+
});
|
|
14
|
+
//# sourceMappingURL=no-internal-anchor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-internal-anchor.js","sourceRoot":"","sources":["../../src/react-router/no-internal-anchor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAE7D;;;;GAIG;AACH,eAAe,YAAY,CAAC;IAC1B,WAAW,EACT,wEAAwE;IAC1E,SAAS,EAAE;QACT,8FAA8F;KAC/F;IACD,OAAO,EACL,4GAA4G;CAC/G,CAAC,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A raw path is a string the route table never sees: removing a route leaves
|
|
3
|
+
* every link to it compiling. `href()` is checked against the registered
|
|
4
|
+
* routes. Only identifier callees match, so `window.location.replace('/')`
|
|
5
|
+
* stays a browser call.
|
|
6
|
+
*/
|
|
7
|
+
declare const _default: import("eslint").Rule.RuleModule;
|
|
8
|
+
export default _default;
|
|
9
|
+
//# sourceMappingURL=no-raw-route-path.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-raw-route-path.d.ts","sourceRoot":"","sources":["../../src/react-router/no-raw-route-path.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;;AACH,wBAUG"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { selectorRule } from "../authoring/selector-rule.js";
|
|
2
|
+
/**
|
|
3
|
+
* A raw path is a string the route table never sees: removing a route leaves
|
|
4
|
+
* every link to it compiling. `href()` is checked against the registered
|
|
5
|
+
* routes. Only identifier callees match, so `window.location.replace('/')`
|
|
6
|
+
* stays a browser call.
|
|
7
|
+
*/
|
|
8
|
+
export default selectorRule({
|
|
9
|
+
description: "Require internal paths in links and navigation to be built with react-router's href()",
|
|
10
|
+
selectors: [
|
|
11
|
+
'JSXAttribute[name.name="to"] > Literal[value=/^\\//]',
|
|
12
|
+
'JSXAttribute[name.name="to"] > JSXExpressionContainer > :matches(Literal[value=/^\\//], TemplateLiteral[quasis.0.value.raw=/^\\//])',
|
|
13
|
+
'CallExpression[callee.name=/^(navigate|redirect|replace)$/] > :matches(Literal[value=/^\\//], TemplateLiteral[quasis.0.value.raw=/^\\//]):first-child',
|
|
14
|
+
],
|
|
15
|
+
message: "Raw internal path — build it with href('/path') from react-router so the route table checks it; append a query as `${href('/path')}?…`.",
|
|
16
|
+
});
|
|
17
|
+
//# sourceMappingURL=no-raw-route-path.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-raw-route-path.js","sourceRoot":"","sources":["../../src/react-router/no-raw-route-path.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAE7D;;;;;GAKG;AACH,eAAe,YAAY,CAAC;IAC1B,WAAW,EACT,uFAAuF;IACzF,SAAS,EAAE;QACT,sDAAsD;QACtD,qIAAqI;QACrI,uJAAuJ;KACxJ;IACD,OAAO,EACL,yIAAyI;CAC5I,CAAC,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* react-router's `useLoaderData<T = any>()` defaults its type argument to
|
|
3
|
+
* `any`, so annotating the receiving variable (`const x: T = useLoaderData()`)
|
|
4
|
+
* compiles whatever the loader returns. Only the type-argument form,
|
|
5
|
+
* `useLoaderData<typeof loader>()`, connects the component to its loader.
|
|
6
|
+
* `useRouteLoaderData` has the same trap.
|
|
7
|
+
*/
|
|
8
|
+
declare const _default: import("eslint").Rule.RuleModule;
|
|
9
|
+
export default _default;
|
|
10
|
+
//# sourceMappingURL=require-loader-data-type-argument.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"require-loader-data-type-argument.d.ts","sourceRoot":"","sources":["../../src/react-router/require-loader-data-type-argument.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;;AACH,wBAQG"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { selectorRule } from "../authoring/selector-rule.js";
|
|
2
|
+
/**
|
|
3
|
+
* react-router's `useLoaderData<T = any>()` defaults its type argument to
|
|
4
|
+
* `any`, so annotating the receiving variable (`const x: T = useLoaderData()`)
|
|
5
|
+
* compiles whatever the loader returns. Only the type-argument form,
|
|
6
|
+
* `useLoaderData<typeof loader>()`, connects the component to its loader.
|
|
7
|
+
* `useRouteLoaderData` has the same trap.
|
|
8
|
+
*/
|
|
9
|
+
export default selectorRule({
|
|
10
|
+
description: 'Require a type argument on useLoaderData() and useRouteLoaderData()',
|
|
11
|
+
selectors: [
|
|
12
|
+
'CallExpression[callee.name=/^use(Route)?LoaderData$/]:not([typeArguments])',
|
|
13
|
+
],
|
|
14
|
+
message: 'Bare useLoaderData()/useRouteLoaderData() returns `any` — pass the generic (e.g. useLoaderData<typeof loader>()) so the return type is compiler-checked.',
|
|
15
|
+
});
|
|
16
|
+
//# sourceMappingURL=require-loader-data-type-argument.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"require-loader-data-type-argument.js","sourceRoot":"","sources":["../../src/react-router/require-loader-data-type-argument.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAE7D;;;;;;GAMG;AACH,eAAe,YAAY,CAAC;IAC1B,WAAW,EACT,qEAAqE;IACvE,SAAS,EAAE;QACT,4EAA4E;KAC7E;IACD,OAAO,EACL,0JAA0J;CAC7J,CAAC,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Rule } from 'eslint';
|
|
2
|
+
/**
|
|
3
|
+
* A Tailwind class written in a string or a template literal. Both selector
|
|
4
|
+
* forms use a regex: esquery's `*=` never matches a Literal's `value`.
|
|
5
|
+
*/
|
|
6
|
+
export declare function classNameCheck({ description, pattern, message, }: {
|
|
7
|
+
description: string;
|
|
8
|
+
/** esquery regex body, e.g. `h-screen` or `z-\\[`. */
|
|
9
|
+
pattern: string;
|
|
10
|
+
message: string;
|
|
11
|
+
}): Rule.RuleModule;
|
|
12
|
+
//# sourceMappingURL=class-name-check.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"class-name-check.d.ts","sourceRoot":"","sources":["../../src/tailwind/class-name-check.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAInC;;;GAGG;AACH,wBAAgB,cAAc,CAAC,EAC7B,WAAW,EACX,OAAO,EACP,OAAO,GACR,EAAE;IACD,WAAW,EAAE,MAAM,CAAC;IACpB,sDAAsD;IACtD,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB,GAAG,IAAI,CAAC,UAAU,CASlB"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { selectorRule } from "../authoring/selector-rule.js";
|
|
2
|
+
/**
|
|
3
|
+
* A Tailwind class written in a string or a template literal. Both selector
|
|
4
|
+
* forms use a regex: esquery's `*=` never matches a Literal's `value`.
|
|
5
|
+
*/
|
|
6
|
+
export function classNameCheck({ description, pattern, message, }) {
|
|
7
|
+
return selectorRule({
|
|
8
|
+
description,
|
|
9
|
+
message,
|
|
10
|
+
selectors: [
|
|
11
|
+
`Literal[value=/${pattern}/]`,
|
|
12
|
+
`TemplateLiteral TemplateElement[value.raw=/${pattern}/]`,
|
|
13
|
+
],
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=class-name-check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"class-name-check.js","sourceRoot":"","sources":["../../src/tailwind/class-name-check.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAE7D;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,EAC7B,WAAW,EACX,OAAO,EACP,OAAO,GAMR;IACC,OAAO,YAAY,CAAC;QAClB,WAAW;QACX,OAAO;QACP,SAAS,EAAE;YACT,kBAAkB,OAAO,IAAI;YAC7B,8CAA8C,OAAO,IAAI;SAC1D;KACF,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/tailwind/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAU,MAAM,eAAe,CAAC;AAYrD,eAAO,MAAM,QAAQ,EAAE,OAMtB,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { enable } from "../concept.js";
|
|
2
|
+
import { SOURCE } from "../files.js";
|
|
3
|
+
import noArbitraryZIndex from "./no-arbitrary-z-index.js";
|
|
4
|
+
import noHScreen from "./no-h-screen.js";
|
|
5
|
+
import noWillChange from "./no-will-change.js";
|
|
6
|
+
const rules = {
|
|
7
|
+
'no-h-screen': noHScreen,
|
|
8
|
+
'no-arbitrary-z-index': noArbitraryZIndex,
|
|
9
|
+
'no-will-change': noWillChange,
|
|
10
|
+
};
|
|
11
|
+
export const tailwind = {
|
|
12
|
+
name: 'tailwind',
|
|
13
|
+
rules,
|
|
14
|
+
config: (plugins) => [
|
|
15
|
+
{ name: 'zukhruf/tailwind', files: SOURCE, plugins, rules: enable(rules) },
|
|
16
|
+
],
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/tailwind/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,MAAM,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,iBAAiB,MAAM,2BAA2B,CAAC;AAC1D,OAAO,SAAS,MAAM,kBAAkB,CAAC;AACzC,OAAO,YAAY,MAAM,qBAAqB,CAAC;AAE/C,MAAM,KAAK,GAAG;IACZ,aAAa,EAAE,SAAS;IACxB,sBAAsB,EAAE,iBAAiB;IACzC,gBAAgB,EAAE,YAAY;CAC/B,CAAC;AAEF,MAAM,CAAC,MAAM,QAAQ,GAAY;IAC/B,IAAI,EAAE,UAAU;IAChB,KAAK;IACL,MAAM,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC;QACnB,EAAE,IAAI,EAAE,kBAAkB,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE;KAC3E;CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-arbitrary-z-index.d.ts","sourceRoot":"","sources":["../../src/tailwind/no-arbitrary-z-index.ts"],"names":[],"mappings":";AAEA,wBAMG"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { classNameCheck } from "./class-name-check.js";
|
|
2
|
+
export default classNameCheck({
|
|
3
|
+
description: 'Disallow arbitrary z-[N] classes; stacking order comes from the theme tokens',
|
|
4
|
+
pattern: 'z-\\[',
|
|
5
|
+
message: 'Use the z-index theme tokens instead of an arbitrary z-[N]. Add a new value to the @theme block when the scale lacks one.',
|
|
6
|
+
});
|
|
7
|
+
//# sourceMappingURL=no-arbitrary-z-index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-arbitrary-z-index.js","sourceRoot":"","sources":["../../src/tailwind/no-arbitrary-z-index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,eAAe,cAAc,CAAC;IAC5B,WAAW,EACT,8EAA8E;IAChF,OAAO,EAAE,OAAO;IAChB,OAAO,EACL,2HAA2H;CAC9H,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-h-screen.d.ts","sourceRoot":"","sources":["../../src/tailwind/no-h-screen.ts"],"names":[],"mappings":";AAEA,wBAMG"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { classNameCheck } from "./class-name-check.js";
|
|
2
|
+
export default classNameCheck({
|
|
3
|
+
description: 'Disallow h-screen classes, which miss the mobile browser chrome; use the dvh units',
|
|
4
|
+
pattern: 'h-screen',
|
|
5
|
+
message: 'Use h-dvh/min-h-dvh/max-h-dvh instead of h-screen variants for correct mobile viewport behavior.',
|
|
6
|
+
});
|
|
7
|
+
//# sourceMappingURL=no-h-screen.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-h-screen.js","sourceRoot":"","sources":["../../src/tailwind/no-h-screen.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,eAAe,cAAc,CAAC;IAC5B,WAAW,EACT,oFAAoF;IACtF,OAAO,EAAE,UAAU;IACnB,OAAO,EACL,kGAAkG;CACrG,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-will-change.d.ts","sourceRoot":"","sources":["../../src/tailwind/no-will-change.ts"],"names":[],"mappings":";AAEA,wBAKG"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { classNameCheck } from "./class-name-check.js";
|
|
2
|
+
export default classNameCheck({
|
|
3
|
+
description: 'Disallow will-change classes',
|
|
4
|
+
pattern: 'will-change',
|
|
5
|
+
message: 'Avoid will-change in Tailwind classes. Only use within active CSS animations if absolutely necessary.',
|
|
6
|
+
});
|
|
7
|
+
//# sourceMappingURL=no-will-change.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-will-change.js","sourceRoot":"","sources":["../../src/tailwind/no-will-change.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,eAAe,cAAc,CAAC;IAC5B,WAAW,EAAE,8BAA8B;IAC3C,OAAO,EAAE,aAAa;IACtB,OAAO,EACL,uGAAuG;CAC1G,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/test-files/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAU,MAAM,eAAe,CAAC;AAUrD,eAAO,MAAM,KAAK,EAAE,OAMnB,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { enable } from "../concept.js";
|
|
2
|
+
import { TESTS } from "../files.js";
|
|
3
|
+
import noTestLifecycleHooks from "./no-test-lifecycle-hooks.js";
|
|
4
|
+
import requireMswErrorOnUnhandledRequest from "./require-msw-error-on-unhandled-request.js";
|
|
5
|
+
const rules = {
|
|
6
|
+
'no-test-lifecycle-hooks': noTestLifecycleHooks,
|
|
7
|
+
'require-msw-error-on-unhandled-request': requireMswErrorOnUnhandledRequest,
|
|
8
|
+
};
|
|
9
|
+
export const tests = {
|
|
10
|
+
name: 'tests',
|
|
11
|
+
rules,
|
|
12
|
+
config: (plugins) => [
|
|
13
|
+
{ name: 'zukhruf/tests', files: TESTS, plugins, rules: enable(rules) },
|
|
14
|
+
],
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/test-files/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,MAAM,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,oBAAoB,MAAM,8BAA8B,CAAC;AAChE,OAAO,iCAAiC,MAAM,6CAA6C,CAAC;AAE5F,MAAM,KAAK,GAAG;IACZ,yBAAyB,EAAE,oBAAoB;IAC/C,wCAAwC,EAAE,iCAAiC;CAC5E,CAAC;AAEF,MAAM,CAAC,MAAM,KAAK,GAAY;IAC5B,IAAI,EAAE,OAAO;IACb,KAAK;IACL,MAAM,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC;QACnB,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE;KACvE;CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-test-lifecycle-hooks.d.ts","sourceRoot":"","sources":["../../src/test-files/no-test-lifecycle-hooks.ts"],"names":[],"mappings":";AAEA,wBAQG"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { selectorRule } from "../authoring/selector-rule.js";
|
|
2
|
+
export default selectorRule({
|
|
3
|
+
description: 'Disallow test lifecycle hooks; each test arranges and tears down its own state',
|
|
4
|
+
selectors: [
|
|
5
|
+
'CallExpression[callee.name=/^(before|after|beforeEach|afterEach|beforeAll|afterAll)$/]',
|
|
6
|
+
],
|
|
7
|
+
message: 'No test lifecycle hooks. Write self-contained AAA tests: inline arrange in each test and run teardown (cleanup, mock restore, resource stop) in a per-test try/finally.',
|
|
8
|
+
});
|
|
9
|
+
//# sourceMappingURL=no-test-lifecycle-hooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-test-lifecycle-hooks.js","sourceRoot":"","sources":["../../src/test-files/no-test-lifecycle-hooks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAE7D,eAAe,YAAY,CAAC;IAC1B,WAAW,EACT,gFAAgF;IAClF,SAAS,EAAE;QACT,wFAAwF;KACzF;IACD,OAAO,EACL,yKAAyK;CAC5K,CAAC,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* msw answers only what a handler lists. Without this option an unstubbed
|
|
3
|
+
* request is warned about and sent to the real network, so the test passes on
|
|
4
|
+
* a live dependency it never meant to touch. Scoped by the `msw/node` import;
|
|
5
|
+
* a `listen()` on something else in the same file, called with no argument or
|
|
6
|
+
* an object, is the one known false positive.
|
|
7
|
+
*/
|
|
8
|
+
declare const _default: import("eslint").Rule.RuleModule;
|
|
9
|
+
export default _default;
|
|
10
|
+
//# sourceMappingURL=require-msw-error-on-unhandled-request.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"require-msw-error-on-unhandled-request.d.ts","sourceRoot":"","sources":["../../src/test-files/require-msw-error-on-unhandled-request.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;;AACH,wBAOG"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { selectorRule } from "../authoring/selector-rule.js";
|
|
2
|
+
/**
|
|
3
|
+
* msw answers only what a handler lists. Without this option an unstubbed
|
|
4
|
+
* request is warned about and sent to the real network, so the test passes on
|
|
5
|
+
* a live dependency it never meant to touch. Scoped by the `msw/node` import;
|
|
6
|
+
* a `listen()` on something else in the same file, called with no argument or
|
|
7
|
+
* an object, is the one known false positive.
|
|
8
|
+
*/
|
|
9
|
+
export default selectorRule({
|
|
10
|
+
description: "Require msw's server.listen() to fail on unhandled requests",
|
|
11
|
+
selectors: [
|
|
12
|
+
'Program:has(ImportDeclaration[source.value="msw/node"]) CallExpression[callee.property.name="listen"]:matches([arguments.length=0], [arguments.0.type="ObjectExpression"]):not(:has(Property[key.name="onUnhandledRequest"] > Literal[value="error"]))',
|
|
13
|
+
],
|
|
14
|
+
message: "msw: server.listen() must pass { onUnhandledRequest: 'error' } so an unstubbed request fails the test instead of reaching the network.",
|
|
15
|
+
});
|
|
16
|
+
//# sourceMappingURL=require-msw-error-on-unhandled-request.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"require-msw-error-on-unhandled-request.js","sourceRoot":"","sources":["../../src/test-files/require-msw-error-on-unhandled-request.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAE7D;;;;;;GAMG;AACH,eAAe,YAAY,CAAC;IAC1B,WAAW,EAAE,6DAA6D;IAC1E,SAAS,EAAE;QACT,wPAAwP;KACzP;IACD,OAAO,EACL,wIAAwI;CAC3I,CAAC,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface Project {
|
|
2
|
+
/** Absolute folder that holds the project's project.json or package.json. */
|
|
3
|
+
readonly root: string;
|
|
4
|
+
/** Tags from project.json `tags` and package.json `nx.tags`. */
|
|
5
|
+
readonly tags: readonly string[];
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* The project that holds `filename`, as Nx defines one: the nearest folder with
|
|
9
|
+
* a project.json or a package.json. Its tags are read from those manifests
|
|
10
|
+
* rather than from Nx's cached project graph, which does not exist on a fresh
|
|
11
|
+
* clone, so tags that an Nx plugin infers are not seen.
|
|
12
|
+
*/
|
|
13
|
+
export declare function projectOf(filename: string): Project | undefined;
|
|
14
|
+
//# sourceMappingURL=project-manifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-manifest.d.ts","sourceRoot":"","sources":["../../src/workspace/project-manifest.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,OAAO;IACtB,6EAA6E;IAC7E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,gEAAgE;IAChE,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;CAClC;AAqCD;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAE/D"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { dirname, join, resolve } from 'node:path';
|
|
3
|
+
import { isRecord, stringsAt } from "../authoring/ast.js";
|
|
4
|
+
const projectByDirectory = new Map();
|
|
5
|
+
function readJson(path) {
|
|
6
|
+
return existsSync(path) ? JSON.parse(readFileSync(path, 'utf8')) : undefined;
|
|
7
|
+
}
|
|
8
|
+
function projectAt(directory) {
|
|
9
|
+
const projectJson = join(directory, 'project.json');
|
|
10
|
+
const packageJson = join(directory, 'package.json');
|
|
11
|
+
if (!existsSync(projectJson) && !existsSync(packageJson))
|
|
12
|
+
return undefined;
|
|
13
|
+
const packageManifest = readJson(packageJson);
|
|
14
|
+
const nx = isRecord(packageManifest) ? packageManifest['nx'] : undefined;
|
|
15
|
+
return {
|
|
16
|
+
root: directory,
|
|
17
|
+
tags: [
|
|
18
|
+
...stringsAt(readJson(projectJson), 'tags'),
|
|
19
|
+
...stringsAt(nx, 'tags'),
|
|
20
|
+
],
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function findProject(directory) {
|
|
24
|
+
const project = projectAt(directory);
|
|
25
|
+
if (project)
|
|
26
|
+
return project;
|
|
27
|
+
const parent = dirname(directory);
|
|
28
|
+
return parent === directory ? undefined : projectOfDirectory(parent);
|
|
29
|
+
}
|
|
30
|
+
function projectOfDirectory(directory) {
|
|
31
|
+
if (!projectByDirectory.has(directory)) {
|
|
32
|
+
projectByDirectory.set(directory, findProject(directory));
|
|
33
|
+
}
|
|
34
|
+
return projectByDirectory.get(directory);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* The project that holds `filename`, as Nx defines one: the nearest folder with
|
|
38
|
+
* a project.json or a package.json. Its tags are read from those manifests
|
|
39
|
+
* rather than from Nx's cached project graph, which does not exist on a fresh
|
|
40
|
+
* clone, so tags that an Nx plugin infers are not seen.
|
|
41
|
+
*/
|
|
42
|
+
export function projectOf(filename) {
|
|
43
|
+
return projectOfDirectory(dirname(resolve(filename)));
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=project-manifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-manifest.js","sourceRoot":"","sources":["../../src/workspace/project-manifest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEnD,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAS1D,MAAM,kBAAkB,GAAG,IAAI,GAAG,EAA+B,CAAC;AAElE,SAAS,QAAQ,CAAC,IAAY;IAC5B,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC/E,CAAC;AAED,SAAS,SAAS,CAAC,SAAiB;IAClC,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;IACpD,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;IACpD,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC;QAAE,OAAO,SAAS,CAAC;IAC3E,MAAM,eAAe,GAAG,QAAQ,CAAC,WAAW,CAAC,CAAC;IAC9C,MAAM,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACzE,OAAO;QACL,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACJ,GAAG,SAAS,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;YAC3C,GAAG,SAAS,CAAC,EAAE,EAAE,MAAM,CAAC;SACzB;KACF,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,SAAiB;IACpC,MAAM,OAAO,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC;IACrC,IAAI,OAAO;QAAE,OAAO,OAAO,CAAC;IAC5B,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAClC,OAAO,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC;AACvE,CAAC;AAED,SAAS,kBAAkB,CAAC,SAAiB;IAC3C,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;QACvC,kBAAkB,CAAC,GAAG,CAAC,SAAS,EAAE,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC;IAC5D,CAAC;IACD,OAAO,kBAAkB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;AAC3C,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,QAAgB;IACxC,OAAO,kBAAkB,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACxD,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The workspace that holds `directory`: the nearest folder at or above it with
|
|
3
|
+
* an nx.json, a pnpm-workspace.yaml, or a package.json that declares
|
|
4
|
+
* workspaces. It is found from the path being linted, never from where this
|
|
5
|
+
* module or the ESLint config sits: installed under node_modules, or loaded by
|
|
6
|
+
* a project's own config under `nx lint`, those say nothing about the
|
|
7
|
+
* workspace.
|
|
8
|
+
*/
|
|
9
|
+
export declare function workspaceRootOf(directory: string): string | undefined;
|
|
10
|
+
/** `filename` relative to its workspace root with `/` separators; the absolute path outside any workspace. */
|
|
11
|
+
export declare function relativeToWorkspace(filename: string): string;
|
|
12
|
+
//# sourceMappingURL=workspace-root.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace-root.d.ts","sourceRoot":"","sources":["../../src/workspace/workspace-root.ts"],"names":[],"mappings":"AAuBA;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAMrE;AAQD,8GAA8G;AAC9G,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAK5D"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { dirname, join, relative, resolve, sep } from 'node:path';
|
|
3
|
+
import { isRecord } from "../authoring/ast.js";
|
|
4
|
+
// Rules run once per linted file; most files of a run share a few folders.
|
|
5
|
+
const rootByDirectory = new Map();
|
|
6
|
+
function declaresWorkspaces(directory) {
|
|
7
|
+
const manifest = join(directory, 'package.json');
|
|
8
|
+
if (!existsSync(manifest))
|
|
9
|
+
return false;
|
|
10
|
+
const parsed = JSON.parse(readFileSync(manifest, 'utf8'));
|
|
11
|
+
return isRecord(parsed) && 'workspaces' in parsed;
|
|
12
|
+
}
|
|
13
|
+
function isWorkspaceRoot(directory) {
|
|
14
|
+
return (existsSync(join(directory, 'nx.json')) ||
|
|
15
|
+
existsSync(join(directory, 'pnpm-workspace.yaml')) ||
|
|
16
|
+
declaresWorkspaces(directory));
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* The workspace that holds `directory`: the nearest folder at or above it with
|
|
20
|
+
* an nx.json, a pnpm-workspace.yaml, or a package.json that declares
|
|
21
|
+
* workspaces. It is found from the path being linted, never from where this
|
|
22
|
+
* module or the ESLint config sits: installed under node_modules, or loaded by
|
|
23
|
+
* a project's own config under `nx lint`, those say nothing about the
|
|
24
|
+
* workspace.
|
|
25
|
+
*/
|
|
26
|
+
export function workspaceRootOf(directory) {
|
|
27
|
+
const start = resolve(directory);
|
|
28
|
+
if (!rootByDirectory.has(start)) {
|
|
29
|
+
rootByDirectory.set(start, findWorkspaceRoot(start));
|
|
30
|
+
}
|
|
31
|
+
return rootByDirectory.get(start);
|
|
32
|
+
}
|
|
33
|
+
function findWorkspaceRoot(directory) {
|
|
34
|
+
if (isWorkspaceRoot(directory))
|
|
35
|
+
return directory;
|
|
36
|
+
const parent = dirname(directory);
|
|
37
|
+
return parent === directory ? undefined : workspaceRootOf(parent);
|
|
38
|
+
}
|
|
39
|
+
/** `filename` relative to its workspace root with `/` separators; the absolute path outside any workspace. */
|
|
40
|
+
export function relativeToWorkspace(filename) {
|
|
41
|
+
const absolute = resolve(filename);
|
|
42
|
+
const root = workspaceRootOf(dirname(absolute));
|
|
43
|
+
const path = root === undefined ? absolute : relative(root, absolute);
|
|
44
|
+
return path.split(sep).join('/');
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=workspace-root.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace-root.js","sourceRoot":"","sources":["../../src/workspace/workspace-root.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAElE,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAE/C,2EAA2E;AAC3E,MAAM,eAAe,GAAG,IAAI,GAAG,EAA8B,CAAC;AAE9D,SAAS,kBAAkB,CAAC,SAAiB;IAC3C,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;IACjD,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,KAAK,CAAC;IACxC,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;IACnE,OAAO,QAAQ,CAAC,MAAM,CAAC,IAAI,YAAY,IAAI,MAAM,CAAC;AACpD,CAAC;AAED,SAAS,eAAe,CAAC,SAAiB;IACxC,OAAO,CACL,UAAU,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QACtC,UAAU,CAAC,IAAI,CAAC,SAAS,EAAE,qBAAqB,CAAC,CAAC;QAClD,kBAAkB,CAAC,SAAS,CAAC,CAC9B,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe,CAAC,SAAiB;IAC/C,MAAM,KAAK,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IACjC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;QAChC,eAAe,CAAC,GAAG,CAAC,KAAK,EAAE,iBAAiB,CAAC,KAAK,CAAC,CAAC,CAAC;IACvD,CAAC;IACD,OAAO,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AACpC,CAAC;AAED,SAAS,iBAAiB,CAAC,SAAiB;IAC1C,IAAI,eAAe,CAAC,SAAS,CAAC;QAAE,OAAO,SAAS,CAAC;IACjD,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAClC,OAAO,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;AACpE,CAAC;AAED,8GAA8G;AAC9G,MAAM,UAAU,mBAAmB,CAAC,QAAgB;IAClD,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnC,MAAM,IAAI,GAAG,eAAe,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;IAChD,MAAM,IAAI,GAAG,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACtE,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACnC,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@zukhruf/eslint",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "ESLint rules and configs shared across workspaces. Every check is its own named rule, so a repo's own config cannot silently erase it.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/JanuaryLabs/zukhruf",
|
|
9
|
+
"directory": "packages/eslint"
|
|
10
|
+
},
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/JanuaryLabs/zukhruf/issues"
|
|
13
|
+
},
|
|
14
|
+
"homepage": "https://github.com/JanuaryLabs/zukhruf/tree/main/packages/eslint#readme",
|
|
15
|
+
"keywords": [
|
|
16
|
+
"eslint",
|
|
17
|
+
"eslintplugin",
|
|
18
|
+
"eslint-plugin",
|
|
19
|
+
"nx"
|
|
20
|
+
],
|
|
21
|
+
"type": "module",
|
|
22
|
+
"engines": {
|
|
23
|
+
"node": ">=24"
|
|
24
|
+
},
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"exports": {
|
|
27
|
+
"./package.json": "./package.json",
|
|
28
|
+
".": {
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"import": "./dist/index.js",
|
|
31
|
+
"default": "./dist/index.js"
|
|
32
|
+
},
|
|
33
|
+
"./nx": {
|
|
34
|
+
"types": "./dist/nx.d.ts",
|
|
35
|
+
"import": "./dist/nx.js",
|
|
36
|
+
"default": "./dist/nx.js"
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"files": [
|
|
40
|
+
"dist",
|
|
41
|
+
"!dist/spec/**",
|
|
42
|
+
"!**/*.tsbuildinfo",
|
|
43
|
+
"!**/*.test.*"
|
|
44
|
+
],
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"access": "public"
|
|
47
|
+
},
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"globals": "^17.13.0",
|
|
50
|
+
"ignore": "^7.0.12"
|
|
51
|
+
},
|
|
52
|
+
"peerDependencies": {
|
|
53
|
+
"@eslint/js": "^9.30.0 || ^10.0.0",
|
|
54
|
+
"@nx/eslint-plugin": ">=21.0.0",
|
|
55
|
+
"eslint": "^9.30.0 || ^10.0.0",
|
|
56
|
+
"eslint-plugin-functional": "^10.0.0",
|
|
57
|
+
"eslint-plugin-import-x": "^4.16.0",
|
|
58
|
+
"jsonc-eslint-parser": "^2.4.0 || ^3.0.0",
|
|
59
|
+
"typescript": ">=5.8.0 <6.1.0",
|
|
60
|
+
"typescript-eslint": "^8.47.0"
|
|
61
|
+
},
|
|
62
|
+
"peerDependenciesMeta": {
|
|
63
|
+
"@nx/eslint-plugin": {
|
|
64
|
+
"optional": true
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|