Skip to content

Commit

Permalink
feat(core): change cssObject types to accept declaration block defini…
Browse files Browse the repository at this point in the history
…tion
  • Loading branch information
TomokiMiyauci committed Mar 28, 2022
1 parent 92e553c commit 74f3281
Show file tree
Hide file tree
Showing 11 changed files with 117 additions and 52 deletions.
24 changes: 17 additions & 7 deletions core/resolve.ts
Expand Up @@ -16,13 +16,14 @@ import {
wrap,
} from "./deps.ts";
import {
isBlockDefinition,
isCSSDefinition,
isCSSObject,
isDeclBlockDefinition,
} from "./utils/assert.ts";
import type {
CSS,
CSSMap,
CSSObject,
IdentifierDefinition,
MatchInfo,
ModifierDefinition,
Expand Down Expand Up @@ -98,13 +99,10 @@ export function resolveCSSMap(
const rest = tail(path);

if (isLength0(rest)) {
if (isCSSDefinition(value)) {
return value.value;
} else if (isBlockDefinition(value)) {
return {
[context.className]: value,
};
if (isCSSObject(value)) {
return constructCSS(value, context.className);
}

return _resolve("", value);
} else {
if (!isCSSObject(value)) {
Expand Down Expand Up @@ -311,3 +309,15 @@ export function resolveModifierMap(
};
return _resolve(fullPath, modifierMap);
}

export function constructCSS(cssObject: CSSObject, className: string): CSS {
if (isCSSDefinition(cssObject)) {
return cssObject.value;
} else if (isDeclBlockDefinition(cssObject)) {
return { [className]: cssObject.value };
} else {
return {
[className]: cssObject,
};
}
}
42 changes: 40 additions & 2 deletions core/resolve_test.ts
@@ -1,5 +1,5 @@
import { expect } from "../dev_deps.ts";
import { resolveCSSMap } from "./resolve.ts";
import { expect, ParamReturn } from "../dev_deps.ts";
import { constructCSS, resolveCSSMap } from "./resolve.ts";
import { createContext } from "../utils/context.ts";
import type { CSS, CSSMap, RuntimeContext, StaticContext } from "./types.ts";

Expand Down Expand Up @@ -168,3 +168,41 @@ Deno.test("resolveCSSMap", () => {
expect(maybeRoot).toEqual(result);
});
});

Deno.test("constructCSS", () => {
const table: ParamReturn<typeof constructCSS>[] = [
[{}, "", { "": {} }],
[{}, ".test", { ".test": {} }],
[{ display: "block" }, ".block", { ".block": { display: "block" } }],
[{ paddingLeft: 1 }, ".pl-1", { ".pl-1": { paddingLeft: 1 } }],
[{ "padding-left": 1 }, ".pl-1", { ".pl-1": { "padding-left": 1 } }],
[{ paddingLeft: 1, paddingRight: 1 }, ".px-1", {
".px-1": { paddingLeft: 1, paddingRight: 1 },
}],
[{ type: "css", value: {} }, ".test", {}],
[
{ type: "css", value: { "@keyframe spin": { "100%": { rotate: 360 } } } },
".test",
{ "@keyframe spin": { "100%": { rotate: 360 } } },
],
[
{ type: "css", value: { display: "block" } },
".test",
{ display: "block" },
],
[
{ type: "css", value: { display: "block" } },
".test",
{ display: "block" },
],
[{ type: "decl", value: {} }, ".block", {
".block": {},
}],
[{ type: "decl", value: { display: "block" } }, ".block", {
".block": { display: "block" },
}],
];
table.forEach(([cssObject, className, result]) =>
expect(constructCSS(cssObject, className)).toEqual(result)
);
});
13 changes: 9 additions & 4 deletions core/types.ts
Expand Up @@ -6,17 +6,22 @@ export type Tree<Leaf, P extends PropertyKey = string | number> = {

export type CSS = Tree<string | number>;

/** CSS Block Declaration */
export type DeclBlock = Record<string, string | number>;

export type CSSDefinition = {
type: "css";
value: CSS;
};

/** User definition of CSS Block Declaration */
export type BlockDefinition = Record<string, string | number>;
export type DeclBlockDefinition = {
type: "decl";
value: DeclBlock;
};

export type CSSObject =
| CSSDefinition
| BlockDefinition;
| DeclBlockDefinition
| DeclBlock;

export type Preset = Labeled & {
fn: (
Expand Down
18 changes: 15 additions & 3 deletions core/utils/assert.ts
@@ -1,4 +1,9 @@
import type { BlockDefinition, CSSDefinition, CSSObject } from "./../types.ts";
import type {
CSSDefinition,
CSSObject,
DeclBlock,
DeclBlockDefinition,
} from "./../types.ts";
import {
AtRule,
Declaration,
Expand All @@ -16,14 +21,15 @@ export function isValidSelector(selector: string): selector is string {
return reValidSelector.test(selector);
}

export function isBlockDefinition(value: unknown): value is BlockDefinition {
export function isDeclBlock(value: unknown): value is DeclBlock {
if (!isObject(value)) return false;

return Object.values(value).every((v) => isString(v) || isNumber(v));
}

export function isCSSObject(value: unknown): value is CSSObject {
return isCSSDefinition(value) || isBlockDefinition(value);
return isCSSDefinition(value) || isDeclBlockDefinition(value) ||
isDeclBlock(value);
}

export function isCSSDefinition(
Expand All @@ -32,6 +38,12 @@ export function isCSSDefinition(
return isObject(value) && prop("type", value) === "css" &&
isObject(prop("value", value));
}
export function isDeclBlockDefinition(
value: unknown,
): value is DeclBlockDefinition {
return isObject(value) && prop("type", value) === "decl" &&
isObject(prop("value", value));
}

export function isDeclaration(node: Node): node is Declaration {
return node.type === "decl";
Expand Down
44 changes: 22 additions & 22 deletions preset_tw/identifier/$single.ts
Expand Up @@ -13,7 +13,7 @@ import {
shortDecimal,
unit,
} from "../../core/utils/format.ts";
import type { BlockDefinition, CSSMap } from "../../core/types.ts";
import type { CSSMap, DeclBlock } from "../../core/types.ts";
import {
customPropertySet,
handleTransform,
Expand Down Expand Up @@ -77,7 +77,7 @@ export const basis: CSSMap = {
], [reBracket_$, ([, arbitrary]) => ({ "flex-basis": arbitrary })]]),
};

export const block: BlockDefinition = { display: "block" };
export const block: DeclBlock = { display: "block" };

export const bottom: CSSMap = {
0: { bottom: "0px" },
Expand Down Expand Up @@ -226,7 +226,7 @@ export const inline: CSSMap = {
table: { display: "inline-table" },
grid: { display: "inline-grid" },
};
export const isolate: BlockDefinition = { isolation: "isolate" };
export const isolate: DeclBlock = { isolation: "isolate" };
export const isolation: CSSMap = {
auto: { isolation: "auto" },
};
Expand Down Expand Up @@ -718,14 +718,14 @@ export const z: CSSMap = {
[reBracket_$, ([, arbitrary]) => ({ zIndex: arbitrary })],
]),
};
export const $static: BlockDefinition = { position: "static" };
export const fixed: BlockDefinition = { position: "fixed" };
export const absolute: BlockDefinition = { position: "absolute" };
export const relative: BlockDefinition = { position: "relative" };
export const sticky: BlockDefinition = { position: "sticky" };
export const visible: BlockDefinition = { visibility: "visible" };
export const invisible: BlockDefinition = { visibility: "hidden" };
export const antialiased: BlockDefinition = {
export const $static: DeclBlock = { position: "static" };
export const fixed: DeclBlock = { position: "fixed" };
export const absolute: DeclBlock = { position: "absolute" };
export const relative: DeclBlock = { position: "relative" };
export const sticky: DeclBlock = { position: "sticky" };
export const visible: DeclBlock = { visibility: "visible" };
export const invisible: DeclBlock = { visibility: "hidden" };
export const antialiased: DeclBlock = {
WebkitFontSmoothing: "antialiased",
MozOsxFontSmoothing: "grayscale",
};
Expand All @@ -735,10 +735,10 @@ export const subpixel: CSSMap = {
MozOsxFontSmoothing: "auto",
},
};
export const italic: BlockDefinition = { fontStyle: "italic" };
export const contents: BlockDefinition = { display: "contents" };
export const hidden: BlockDefinition = { display: "none" };
export const overline: BlockDefinition = { textDecorationLine: "overline" };
export const italic: DeclBlock = { fontStyle: "italic" };
export const contents: DeclBlock = { display: "contents" };
export const hidden: DeclBlock = { display: "none" };
export const overline: DeclBlock = { textDecorationLine: "overline" };
export const line: CSSMap = {
through: { textDecorationLine: "line-through" },
};
Expand All @@ -758,7 +758,7 @@ export const sr: CSSMap = {
borderWidth: 0,
},
};
export const ordinal: BlockDefinition = { fontVariantNumeric: "ordinal" };
export const ordinal: DeclBlock = { fontVariantNumeric: "ordinal" };
export const slashed: CSSMap = {
zero: { fontVariantNumeric: "slashed-zero" },
};
Expand All @@ -780,10 +780,10 @@ export const diagonal: CSSMap = {
export const stacked: CSSMap = {
fractions: { fontVariantNumeric: "stacked-fractions" },
};
export const uppercase: BlockDefinition = { textTransform: "uppercase" };
export const lowercase: BlockDefinition = { textTransform: "lowercase" };
export const capitalize: BlockDefinition = { textTransform: "capitalize" };
export const truncate: BlockDefinition = {
export const uppercase: DeclBlock = { textTransform: "uppercase" };
export const lowercase: DeclBlock = { textTransform: "lowercase" };
export const capitalize: DeclBlock = { textTransform: "capitalize" };
export const truncate: DeclBlock = {
overflow: "hidden",
textOverflow: "ellipsis",
whiteSpace: "nowrap",
Expand Down Expand Up @@ -814,7 +814,7 @@ export const contrast: CSSMap = {
]),
};

function handleDrop(value: string, varPrefix: string): BlockDefinition {
function handleDrop(value: string, varPrefix: string): DeclBlock {
return {
[customProperty("drop-shadow", varPrefix)]: value,
filter: filterValue(varPrefix),
Expand Down Expand Up @@ -872,7 +872,7 @@ function handleSingleFilter(
propertyName: string,
value: string | number,
varPrefix: string,
): BlockDefinition {
): DeclBlock {
return {
[customProperty(propertyName, varPrefix)]: `${propertyName}(${value})`,
filter: filterValue(varPrefix),
Expand Down
4 changes: 2 additions & 2 deletions preset_tw/identifier/_filter_utils.ts
@@ -1,7 +1,7 @@
import { customPropertySet } from "./_utils.ts";
import { shortDecimal } from "../../core/utils/format.ts";
import { parseNumeric, per } from "../../core/utils/monad.ts";
import type { BlockDefinition } from "../../core/types.ts";
import type { DeclBlock } from "../../core/types.ts";
export function filterValue(variablePrefix: string): string {
const [, varFnBlur] = customPropertySet("blur", variablePrefix);
const [, varFnBrightness] = customPropertySet("brightness", variablePrefix);
Expand All @@ -23,7 +23,7 @@ export function handleFilter(
propertyName: string,
value: string,
variablePrefix: string,
): BlockDefinition | undefined {
): DeclBlock | undefined {
return parseNumeric(value).andThen(per(100)).map(shortDecimal).match({
some: (number) => {
const [varName] = customPropertySet(propertyName, variablePrefix);
Expand Down
4 changes: 2 additions & 2 deletions preset_tw/identifier/_utils.ts
Expand Up @@ -10,7 +10,7 @@ import {
} from "../../core/utils/format.ts";
import { RGBA } from "../../core/utils/parse.ts";
import { per } from "../../core/utils/monad.ts";
import type { BlockDefinition } from "../../core/types.ts";
import type { DeclBlock } from "../../core/types.ts";

export function fillRGBA(
{ a, ...rest }: RGBA,
Expand Down Expand Up @@ -73,7 +73,7 @@ export function handleTransform(
properties: string[],
value: string,
varPrefix: string,
): BlockDefinition {
): DeclBlock {
return {
...associateWith(
properties.map((property) => customProperty(property, varPrefix)),
Expand Down
4 changes: 2 additions & 2 deletions preset_tw/identifier/backdrop.ts
Expand Up @@ -3,7 +3,7 @@ import { parseNumeric } from "../../core/utils/monad.ts";
import { ratio, shortDecimal, unit } from "../../core/utils/format.ts";
import { execMatch, re$PositiveNumber } from "../../core/utils/regexp.ts";
import { customProperty } from "../../core/utils/format.ts";
import type { BlockDefinition, CSSMap } from "../../core/types.ts";
import type { CSSMap, DeclBlock } from "../../core/types.ts";

const BACKDROP_BLUR = "backdrop-blur";

Expand Down Expand Up @@ -46,7 +46,7 @@ function handleFilter(
property: string,
value: string | number,
varPrefix: string,
): BlockDefinition {
): DeclBlock {
return {
[customProperty(property, varPrefix)]: value,
"backdrop-filter": backdropFilterValue(varPrefix),
Expand Down
4 changes: 2 additions & 2 deletions preset_tw/identifier/blur.ts
@@ -1,7 +1,7 @@
import { customPropertySet } from "./_utils.ts";
import type { BlockDefinition, CSSMap } from "../../core/types.ts";
import type { CSSMap, DeclBlock } from "../../core/types.ts";

function handleBlur(value: string, variablePrefix: string): BlockDefinition {
function handleBlur(value: string, variablePrefix: string): DeclBlock {
const [varBlur, varFnBlur] = customPropertySet("blur", variablePrefix);
const [, varFnBrightness] = customPropertySet("brightness", variablePrefix);
const [, varFnContract] = customPropertySet("contrast", variablePrefix);
Expand Down
8 changes: 4 additions & 4 deletions preset_tw/identifier/ring.ts
Expand Up @@ -15,23 +15,23 @@ import {
ratio,
rgbFn,
} from "../../core/utils/format.ts";
import type { BlockDefinition, CSSMap } from "../../core/types.ts";
import type { CSSMap, DeclBlock } from "../../core/types.ts";

function toRingColor(varPrefix: string) {
return (value: string): BlockDefinition => ({
return (value: string): DeclBlock => ({
[customProperty("ring-color", varPrefix)]: value,
});
}
function toRingOffsetColor(varPrefix: string) {
return (value: string): BlockDefinition => ({
return (value: string): DeclBlock => ({
[customProperty("ring-offset-color", varPrefix)]: value,
});
}

function handleRingWidth(
value: string,
variablePrefix: string,
): BlockDefinition {
): DeclBlock {
const [varRingOffsetShadow, varFnRingOffsetShadow] = customPropertySet(
"ring-offset-shadow",
variablePrefix,
Expand Down
4 changes: 2 additions & 2 deletions preset_tw/identifier/scale.ts
Expand Up @@ -7,13 +7,13 @@ import {
shortDecimal,
} from "../../core/utils/format.ts";
import { associateWith } from "../deps.ts";
import type { BlockDefinition, CSSMap } from "../../core/types.ts";
import type { CSSMap, DeclBlock } from "../../core/types.ts";

function handleScale(
properties: string[],
value: string,
varPrefix: string,
): BlockDefinition | undefined {
): DeclBlock | undefined {
return parseNumeric(value).map(ratio).map(shortDecimal).match({
some: (v) => ({
...associateWith(
Expand Down

0 comments on commit 74f3281

Please sign in to comment.