diff --git a/packages/transform-to-vanilla/src/transform-keys/merge-key.ts b/packages/transform-to-vanilla/src/transform-keys/merge-key.ts index 707417d..03e9d92 100644 --- a/packages/transform-to-vanilla/src/transform-keys/merge-key.ts +++ b/packages/transform-to-vanilla/src/transform-keys/merge-key.ts @@ -1,19 +1,17 @@ -import { NonNullableString } from "../types/string"; - -// == Type ================================================================ -type HasSignInString = `${NonNullableString}$` | `${NonNullableString}_`; -type InputKeyValue = NonNullableString | HasSignInString; - // == Interface ================================================================ -export function removeSignSimbol(keyStr: InputKeyValue) { - return hasSignSimbol(keyStr) - ? keyStr.substring(0, keyStr.length - 1) - : keyStr; +export function removeMergeSymbol(keyStr: string) { + return keyStr.substring(0, keyStr.length - 1); } -// == Utils ==================================================================== -function hasSignSimbol(value: InputKeyValue): value is HasSignInString { - return value.endsWith("$") || value.endsWith("_"); +export function mergeKeyInfo(keyStr: string) { + const isMergeToComma = keyStr.endsWith("$"); + const isMergeToSpace = keyStr.endsWith("_"); + + return { + isMergeToComma, + isMergeToSpace, + isMergeSymbol: isMergeToComma || isMergeToSpace + }; } // == Tests ==================================================================== @@ -21,18 +19,53 @@ if (import.meta.vitest) { const { describe, it, expect } = import.meta.vitest; describe.concurrent("Remove Key Sign Symbol", () => { + it("Has Sign Symbol to the end", () => { + expect(removeMergeSymbol("boxShadow$")).toBe("boxShadow"); + expect(removeMergeSymbol("transform_")).toBe("transform"); + }); + }); + + describe.concurrent("Get key info has merge symbol", () => { it("No Sign Symbol", () => { - expect(removeSignSimbol("boxShadow")).toBe("boxShadow"); + expect(mergeKeyInfo("boxShadow")).toStrictEqual({ + isMergeToComma: false, + isMergeToSpace: false, + isMergeSymbol: false + }); }); it("Has Sign Symbol to the end", () => { - expect(removeSignSimbol("boxShadow$")).toBe("boxShadow"); - expect(removeSignSimbol("transform_")).toBe("transform"); + expect(mergeKeyInfo("boxShadow$")).toStrictEqual({ + isMergeToComma: true, + isMergeToSpace: false, + isMergeSymbol: true + }); + expect(mergeKeyInfo("transform_")).toStrictEqual({ + isMergeToComma: false, + isMergeToSpace: true, + isMergeSymbol: true + }); }); it("Has Sign Symbol in the middle or at the first", () => { - expect(removeSignSimbol("box$Shadow")).toBe("box$Shadow"); - expect(removeSignSimbol("trans_form")).toBe("trans_form"); - expect(removeSignSimbol("$boxShadow")).toBe("$boxShadow"); - expect(removeSignSimbol("_transform")).toBe("_transform"); + expect(mergeKeyInfo("box$Shadow")).toStrictEqual({ + isMergeToComma: false, + isMergeToSpace: false, + isMergeSymbol: false + }); + expect(mergeKeyInfo("trans_form")).toStrictEqual({ + isMergeToComma: false, + isMergeToSpace: false, + isMergeSymbol: false + }); + expect(mergeKeyInfo("$boxShadow")).toStrictEqual({ + isMergeToComma: false, + isMergeToSpace: false, + isMergeSymbol: false + }); + expect(mergeKeyInfo("_transform")).toStrictEqual({ + isMergeToComma: false, + isMergeToSpace: false, + isMergeSymbol: false + }); }); }); } diff --git a/packages/transform-to-vanilla/src/transform-object/index.ts b/packages/transform-to-vanilla/src/transform-object/index.ts index 4ad7418..7f9179e 100644 --- a/packages/transform-to-vanilla/src/transform-object/index.ts +++ b/packages/transform-to-vanilla/src/transform-object/index.ts @@ -1,3 +1,6 @@ +import { replacePseudoSelectors } from "@/transform-keys/simple-pseudo-selectors"; +import { removeMergeSymbol, mergeKeyInfo } from "@/transform-keys/merge-key"; +import { mergeToComma, mergeToSpace } from "@/transform-values/merge-values"; import { simplyImportant } from "@/transform-values/simply-important"; import type { StyleRule } from "@vanilla-extract/css"; import type { @@ -6,7 +9,6 @@ import type { CSSRuleValue, VanillaStyleRuleValue } from "@/types/style-rule"; -import { replacePseudoSelectors } from "@/transform-keys/simple-pseudo-selectors"; // == Interface ================================================================ export function transformStyle(style: CSSRule) { @@ -22,20 +24,45 @@ export function transformStyle(style: CSSRule) { CSSRuleKey, CSSRuleValue ][]) { + const { isMergeToComma, isMergeToSpace, isMergeSymbol } = mergeKeyInfo(key); + const transformedValue = typeof value === "object" ? Array.isArray(value) - ? value - : transformStyle(value as CSSRule) // TODO: Array - : typeof value === "string" - ? simplyImportant(value) - : value; - const transformedKey = replacePseudoSelectors(key); + ? transformArrayValue(value, isMergeToComma, isMergeToSpace) + : transformStyle(value as CSSRule) + : transformCommonValue(value); + const transformedKey = replacePseudoSelectors( + isMergeSymbol ? removeMergeSymbol(key) : key + ); result[transformedKey] = transformedValue as VanillaStyleRuleValue; } return result as StyleRule; } +// == Utils ==================================================================== +function transformArrayValue( + value: CSSRuleValue, + isMergeToComma: boolean, + isMergeToSpace: boolean +): CSSRuleValue { + const transformed = isMergeToComma + ? mergeToComma(value as string[]) + : isMergeToSpace + ? mergeToSpace(value as string[]) + : value; + + return Array.isArray(transformed) + ? // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore: error TS2590: Expression produces a union type that is too complex to represent + (transformed.map(transformCommonValue) as CSSRuleValue) + : transformed; +} + +function transformCommonValue(value: CSSRuleValue) { + return typeof value === "string" ? simplyImportant(value) : value; +} + // == Tests ==================================================================== if (import.meta.vitest) { const { describe, it, expect } = import.meta.vitest; @@ -48,7 +75,33 @@ if (import.meta.vitest) { }) ).toStrictEqual({ overflow: ["auto", "overlay"] - }); + } satisfies StyleRule); + }); + + it("Merge Values", () => { + expect( + transformStyle({ + boxShadow$: ["inset 0 0 10px #555", "0 0 20px black"], + transform_: ["scale(2)", "rotate(15deg)"] + }) + ).toStrictEqual({ + boxShadow: "inset 0 0 10px #555, 0 0 20px black", + transform: "scale(2) rotate(15deg)" + } satisfies StyleRule); + + expect( + transformStyle({ + transform_: [ + // Apply to all + "scale(2)", + + // Fallback style + ["rotate(28.64deg)", "rotate(0.5rad)"] + ] + }) + ).toStrictEqual({ + transform: ["scale(2) rotate(28.64deg)", "scale(2) rotate(0.5rad)"] + } satisfies StyleRule); }); it("Simply Important", () => { @@ -59,6 +112,14 @@ if (import.meta.vitest) { ).toStrictEqual({ color: "red !important" } satisfies StyleRule); + + expect( + transformStyle({ + overflow: ["auto !", "overlay"] + }) + ).toStrictEqual({ + overflow: ["auto !important", "overlay"] + } satisfies StyleRule); }); it("Simple Psudo", () => {