Skip to content

Commit

Permalink
Fix: Transform - Literal property refence cases #46
Browse files Browse the repository at this point in the history
  • Loading branch information
black7375 committed Jul 24, 2024
1 parent 0fb7541 commit 8da12f0
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 20 deletions.
78 changes: 71 additions & 7 deletions packages/transform-to-vanilla/src/transform-object/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ import type {
AtRulesKeywords
} from "@/types/style-rule";
import type { Properties } from "csstype";
import { replacePropertyReference } from "@/transform-values/proerty-reference";
import { replacePropertyReference } from "@/transform-values/property-reference";

const mergeObject = deepmerge();

Expand All @@ -50,7 +50,7 @@ export type StyleResult = {
// vars: StyleRuleValue; }': accentColor, alignContent, alignItems, alignSelf, and 905 more.ts(2740)
[key in string]: VanillaStyleRuleValue;
};
type CSSRuleExistValue = Exclude<CSSRuleValue, undefined>;
export type CSSRuleExistValue = Exclude<CSSRuleValue, undefined>;

export type AtRulesPrefix = `@${AtRulesKeywords}`;
export interface TransformContext {
Expand Down Expand Up @@ -386,9 +386,13 @@ function transformAnonymous(key: string, value: CSSRuleValue) {
}

function transformCommonValue(value: CSSRuleValue, context: TransformContext) {
return typeof value === "string"
? simplyImportant(replaceCSSVar(replacePropertyReference(value, context)))
: value;
if (typeof value === "string") {
const result = replacePropertyReference(value, context);
return typeof result === "string"
? simplyImportant(replaceCSSVar(result))
: result;
}
return value;
}

function isPropertyNested(context: TransformContext) {
Expand Down Expand Up @@ -1149,6 +1153,20 @@ if (import.meta.vitest) {
} satisfies StyleRule);
});

it("Property Reference & Fallback style", () => {
expect(
transformStyle({
fontSize: "1rem",
padding: ["16px", "@fontSize"],
margin: "@padding"
})
).toStrictEqual({
fontSize: "1rem",
padding: ["16px", "1rem"],
margin: ["16px", "1rem"]
} satisfies StyleRule);
});

it("Property Reference & Nested", () => {
expect(
transformStyle({
Expand Down Expand Up @@ -1183,6 +1201,38 @@ if (import.meta.vitest) {
}
}
} satisfies StyleRule);

expect(
transformStyle({
"nav li > &": {
background: "red",
"@media (prefers-color-scheme: dark)": {
background: "blue",
_hover: {
color: "@background"
}
}
}
})
).toStrictEqual({
selectors: {
"nav li > &": {
background: "red"
}
},
"@media": {
"(prefers-color-scheme: dark)": {
selectors: {
"nav li > &": {
background: "blue"
},
"nav li > &:hover": {
color: "blue"
}
}
}
}
} satisfies StyleRule);
});
});

Expand All @@ -1192,18 +1242,22 @@ if (import.meta.vitest) {
transformStyle({
"@media": {
"screen and (min-width: 768px)": {
margin: 10,
_hover: {
padding: {
BlockEnd: 3,
Right: "20px",
Left: "@margin",
InlineStart: ["@Left", "@Right"],
InlineEnd: ["16px", "1rem"]
}
},
"@supports (display: grid)": {
background: {
Color: "red",
Image: "none",
Clip: ["initial", "-moz-initial"]
Clip: ["initial", "-moz-initial"],
Attachment: "@Clip"
}
}
}
Expand All @@ -1212,10 +1266,13 @@ if (import.meta.vitest) {
).toStrictEqual({
"@media": {
"screen and (min-width: 768px)": {
margin: 10,
selectors: {
"&:hover": {
paddingBlockEnd: 3,
paddingRight: "20px",
paddingLeft: 10,
paddingInlineStart: [10, "20px"],
paddingInlineEnd: ["16px", "1rem"]
}
}
Expand All @@ -1227,7 +1284,8 @@ if (import.meta.vitest) {
"screen and (min-width: 768px)": {
backgroundColor: "red",
backgroundImage: "none",
backgroundClip: ["initial", "-moz-initial"]
backgroundClip: ["initial", "-moz-initial"],
backgroundAttachment: ["initial", "-moz-initial"]
}
}
}
Expand All @@ -1242,6 +1300,7 @@ if (import.meta.vitest) {
background: {
base: "red",
_hover: "green",
_active: "@base",
"[disabled]": "blue",
"nav li > &": "black",
"@media (prefers-color-scheme: dark)": "white",
Expand All @@ -1253,6 +1312,7 @@ if (import.meta.vitest) {
Color: {
base: "transparent",
_hover: "Highlight",
_active: "@_hover",
"@media (prefers-reduced-motion)": "MenuText"
},
"@media (prefers-reduced-motion)": {
Expand All @@ -1274,6 +1334,10 @@ if (import.meta.vitest) {
background: "green",
backgroundColor: "Highlight"
},
"&:active": {
background: "red",
backgroundColor: "Highlight"
},
"&[disabled]": {
background: "blue"
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,44 @@
import type { TransformContext } from "@/transform-object";
import type { TransformContext, CSSRuleExistValue } from "@/transform-object";

// == Interface ================================================================
const propertyReferenceRegex = /\B@[\w\-_]+/g;
const LITERAL_PROPERTY_REFERENCE_REGEX = /^@[\w\-_]+$/;
const PROPERTY_REFERENCE_REGEX = /\B@[\w\-_]+/g;

export function replacePropertyReference(
valueStr: string,
context: TransformContext
) {
return valueStr.replaceAll(propertyReferenceRegex, (matched: string) => {
const withoutPrefix = matched.substring(1);
if (isPropertyKeyExist(withoutPrefix, context)) {
const target = context.propertyReference[withoutPrefix];
return typeof target === "string"
? replacePropertyReference(target, context)
: (target as string); // Can be number, undefined
} else {
throw new Error(`Property reference not found: ${matched}`);
}
): string | CSSRuleExistValue | (string | CSSRuleExistValue)[] {
if (LITERAL_PROPERTY_REFERENCE_REGEX.test(valueStr)) {
return getReplacement(valueStr, context);
}

return valueStr.replace(PROPERTY_REFERENCE_REGEX, (matched: string) => {
const result = getReplacement(matched, context);
if (typeof result === "object") return JSON.stringify(result);
return String(result);
});
}

function getReplacement(
reference: string,
context: TransformContext
): string | CSSRuleExistValue | (string | CSSRuleExistValue)[] {
const withoutPrefix = reference.substring(1);
if (isPropertyKeyExist(withoutPrefix, context)) {
const target = context.propertyReference[withoutPrefix];
if (Array.isArray(target)) {
return target.map((v) =>
typeof v === "string" ? replacePropertyReference(v, context) : v
);
}
return typeof target === "string"
? replacePropertyReference(target, context)
: (target as CSSRuleExistValue);
} else {
throw new Error(`Property reference not found: ${reference}`);
}
}

function isPropertyKeyExist(
key: string,
context: TransformContext
Expand Down Expand Up @@ -77,6 +96,28 @@ if (import.meta.vitest) {
).toBe("50px");
});

it("One reference with literal type", () => {
// Number
expect(
replacePropertyReference("@width", {
...initTransformContext,
propertyReference: {
width: 10
}
})
).toBe(10);

// Array
expect(
replacePropertyReference("@width", {
...initTransformContext,
propertyReference: {
width: [1, 2]
}
})
).toStrictEqual([1, 2]);
});

it("With complex string", () => {
expect(
replacePropertyReference("calc(@width / 2)", {
Expand Down Expand Up @@ -130,6 +171,16 @@ if (import.meta.vitest) {
}
})
).toBe("calc(50px + 50px)");

expect(
replacePropertyReference("@height", {
...initTransformContext,
propertyReference: {
width: "50px",
height: ["@width", "@width"]
}
})
).toStrictEqual(["50px", "50px"]);
});
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,9 @@ if (import.meta.vitest) {
it("! to End with space", () => {
expect(simplyImportant("red !")).toBe("red !important");
});

it("!important to End", () => {
expect(simplyImportant("red !important")).toBe("red !important");
});
});
}

0 comments on commit 8da12f0

Please sign in to comment.