Skip to content

Commit

Permalink
Complete rewrite to the plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
AhmedBaset committed Aug 4, 2024
1 parent c18392f commit b0aeeaf
Show file tree
Hide file tree
Showing 8 changed files with 243 additions and 220 deletions.
5 changes: 5 additions & 0 deletions .changeset/sweet-gifts-behave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"eslint-plugin-rtl-friendly": patch
---

Cache result and read from cache for better performance
85 changes: 0 additions & 85 deletions src/configs/tw-logical-properties.ts

This file was deleted.

2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { ESLint, Linter } from "eslint";
import noPhysicalProperties from "./rules/no-physical-properties.js";
import pkg from "../package.json";
import { noPhysicalProperties } from "./rules/no-phyisical-properties/rule";

const rtlFriendly = {
meta: {
Expand Down
99 changes: 99 additions & 0 deletions src/rules/no-phyisical-properties/rule.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { Rule } from "eslint";

import * as ESTree from "estree";
import type { JSXAttribute } from "estree-jsx";
import { extractFromNode } from "../../utils/ast.js";
import { parseForPhysicalClasses } from "../../utils/tailwind.js";

const cache = new Map</** invalid */ string, /** valid */ string>();

export const NO_PHYSICAL_CLASSESS = "NO_PHYSICAL_CLASSESS";

export const noPhysicalProperties: Rule.RuleModule = {
meta: {
type: "suggestion",
docs: {
description: "Encourage the use of RTL-friendly styles",
recommended: true,
},
fixable: "code",
messages: {
[NO_PHYSICAL_CLASSESS]: `Avoid using physical properties such as "{{ invalid }}". Instead, use logical properties like "{{ valid }}" for better RTL support.`,
},
schema: [],
},
create(ctx) {
return {
JSXAttribute: (estreeNode: ESTree.Node) => {
const node = estreeNode as JSXAttribute;

if (node.name.type !== "JSXIdentifier") return;
const attr = node.name.name;

const isClassAttribute = ["className", "class"].includes(attr);
if (!isClassAttribute) return;

let result = extractFromNode(node);
if (!result) return;

result = result.filter((c) => typeof c === "string");
if (!result.length) return;

const classesAsString = result.join(" ");
const cachedValid = cache.get(classesAsString);
if (cachedValid) {
report({ ctx, node, invalid: classesAsString, valid: cachedValid });
return;
}

const classes = classesAsString.split(" ");

const parsed = parseForPhysicalClasses(classes);

const isInvalid = parsed.some((p) => p.isInvalid);
if (!isInvalid) return;

const invalid = parsed.map((p) => p.original).join(" ");
const valid = parsed.map((p) => p.valid).join(" ");

cache.set(classesAsString, valid);
report({ ctx, node, invalid, valid });
},
};
},
};

function report({
ctx,
invalid,
valid,
node,
}: {
ctx: Rule.RuleContext;
node: JSXAttribute;
invalid: string;
valid: string;
}) {
return ctx.report({
node,
messageId: "NO_PHYSICAL_CLASSESS",
data: {
invalid,
valid,
},
loc: {
start: node.loc!.start,
end: node.loc!.end,
},
fix: (fixer) => {
if (node.value?.type === "Literal") {
return fixer.replaceText(
node.value,
node.value.raw?.replace(invalid, valid) ?? ""
);
}

return null;
},
});
}
4 changes: 1 addition & 3 deletions src/rules/no-phyisical-properties/test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { RuleTester } from "eslint";
import noPhysicalProperties, {
NO_PHYSICAL_CLASSESS,
} from "./../no-physical-properties";
import { noPhysicalProperties, NO_PHYSICAL_CLASSESS } from "./rule";

const tester = new RuleTester({
languageOptions: {
Expand Down
131 changes: 0 additions & 131 deletions src/rules/no-physical-properties.ts

This file was deleted.

Loading

0 comments on commit b0aeeaf

Please sign in to comment.