generated from unjs/template
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
196 additions
and
159 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { isArray, isObject, isString, unique } from "./shared"; | ||
|
||
/** | ||
* | ||
*/ | ||
export function classnames(...literals: ClassName[]) { | ||
return unique(literals | ||
.reduce<string[]>((prev, cur) => { | ||
if (isArray(cur)) { | ||
prev.push(...classnames(...cur)); | ||
} else if (isString(cur)) { | ||
prev.push(...cur.trim().split(/\s+/)); | ||
} else if (isObject(cur)) { | ||
prev.push(...Object.keys(cur).filter((key) => !!cur[key])); | ||
} | ||
return prev; | ||
}, [])).filter((item) => !!item); | ||
} | ||
|
||
/** | ||
* @alias classnames | ||
*/ | ||
export const cls = classnames; | ||
|
||
export type ClassName = | ||
| Record<string, boolean | undefined | null> | ||
| string | ||
| undefined | ||
| null | ||
| ClassName[]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { range } from "./range"; | ||
import { isArray, isIterable, isNumber, isObject } from "./shared"; | ||
|
||
export function renderList<U>(source: string, render: (item: string, index: number) => U): U[]; | ||
|
||
export function renderList<T, U>(source: T[], render: (item: T, index: number) => U): U[]; | ||
|
||
export function renderList<T, U>(source: Iterable<T>, render: (item: T, index: number) => U): U[]; | ||
|
||
export function renderList<U>(source: number, render: (item: number, index: number) => U): U[]; | ||
|
||
export function renderList<T, U>(source: T, render: <K extends keyof T>(item: T[K], key: T[K], index: number) => U): U[]; | ||
|
||
export function renderList(source: any, render: (...args: any[]) => any) { | ||
if (isArray(source)) { | ||
return source.map(render); | ||
} else if (isNumber(source)) { | ||
return range(1, source + 1).map(render); | ||
} else if (isIterable(source)) { | ||
return Array.from(source).map(render); | ||
} | ||
if (isObject(source)) { | ||
return Object.keys(source).map((key, index) => render(source[key], key, index)); | ||
} | ||
return []; | ||
} | ||
|
||
/** | ||
* @alias renderList | ||
*/ | ||
export const each = renderList; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,106 +1,7 @@ | ||
import type * as CSS from "csstype"; | ||
export * from "./each"; | ||
|
||
function trimClassName(className: string) { | ||
return className.trim().split(/\s+/); | ||
} | ||
export * from "./range"; | ||
|
||
function unique<S>(arr: Iterable<S>) { | ||
return Array.from(new Set(arr)); | ||
} | ||
export * from "./cls"; | ||
|
||
function toSnakeCase(str: string, separator = "_") { | ||
return str.replace(/[A-Z]/g, (match) => `${separator}${match.toLowerCase()}`); | ||
} | ||
|
||
export function classnames(...literals: ClassName[]) { | ||
return unique(literals | ||
.reduce<string[]>((prev, cur) => { | ||
if (Array.isArray(cur)) { | ||
prev.push(...classnames(...cur)); | ||
} else if (typeof cur === "string") { | ||
prev.push(...trimClassName(cur)); | ||
} else if (typeof cur === "object" && cur !== null) { | ||
prev.push(...Object.keys(cur).filter((key) => !!cur[key])); | ||
} | ||
return prev; | ||
}, [])).filter((item) => !!item); | ||
} | ||
|
||
export function unit_f<U extends string = StyleUnit>(value: string | number, unit: U = "px" as U) { | ||
if (/^[0-9]+(\.[0-9]+)?$/.test(String(value))) { | ||
return `${value}${unit}`; | ||
} | ||
return value; | ||
} | ||
|
||
export const cls = classnames; | ||
|
||
export function style(stylesheet: CSSProperties) { | ||
return Object.keys(stylesheet).reduce<string[]>((prev, cur) => { | ||
const value = stylesheet[cur as keyof CSSProperties]; | ||
if (typeof value === "string" || typeof value === "number") { | ||
prev.push(`${toSnakeCase(cur, "-")}: ${value};`); | ||
} | ||
return prev; | ||
}, []).join(" "); | ||
} | ||
|
||
export interface CSSProperties extends CSS.Properties<string | number>, CSS.PropertiesHyphen<string | number> { | ||
} | ||
|
||
export type ClassName = | ||
| Record<string, boolean | undefined | null> | ||
| string | ||
| undefined | ||
| null | ||
| ClassName[]; | ||
|
||
export type StyleUnit = "px" | "rem" | "em" | "vw" | "vh" | "vmin" | "vmax" | "%" | "cm" | "mm" | "in" | "pt" | "pc"; | ||
|
||
function isIterable<T>(obj: any): obj is Iterable<T> { | ||
return obj && typeof obj[Symbol.iterator] === "function"; | ||
} | ||
|
||
export function range(source: string): string[]; | ||
|
||
export function range<T>(iterable: Iterable<T>): T[]; | ||
|
||
export function range(min: number, max: number): number[]; | ||
|
||
export function range(max: number): number[]; | ||
|
||
export function range<T>(min: number | Iterable<T>, max?: number): T[] | number[] | string[] { | ||
if (typeof min === "number") { | ||
if (typeof max === "number") { | ||
return Array.from({ length: max - min }, (_, index) => index + min); | ||
} | ||
return Array.from({ length: min }, (_, index) => index); | ||
} | ||
return Array.from(min); | ||
} | ||
|
||
export function renderList<U>(source: string, render: (item: string, index: number) => U): U[]; | ||
|
||
export function renderList<T, U>(source: T[], render: (item: T, index: number) => U): U[]; | ||
|
||
export function renderList<T, U>(source: Iterable<T>, render: (item: T, index: number) => U): U[]; | ||
|
||
export function renderList<U>(source: number, render: (item: number, index: number) => U): U[]; | ||
|
||
export function renderList<T, U>(source: T, render: <K extends keyof T>(item: T[K], key: T[K], index: number) => U): U[]; | ||
|
||
export function renderList(source: any, render: (...args: any[]) => any) { | ||
if (Array.isArray(source)) { | ||
return source.map(render); | ||
} else if (typeof source === "number") { | ||
return range(1, source + 1).map(render); | ||
} else if (isIterable(source)) { | ||
return Array.from(source).map(render); | ||
} | ||
if (typeof source === "object" && source !== null) { | ||
return Object.keys(source).map((key, index) => render(source[key], key, index)); | ||
} | ||
return []; | ||
} | ||
|
||
export const each = renderList; | ||
export * from "./style"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { isNumber } from "./shared"; | ||
|
||
export function range(source: string): string[]; | ||
|
||
export function range<T>(iterable: Iterable<T>): T[]; | ||
|
||
export function range(min: number, max: number): number[]; | ||
|
||
export function range(max: number): number[]; | ||
|
||
export function range<T>(min: number | Iterable<T>, max?: number): T[] | number[] | string[] { | ||
if (isNumber(min)) { | ||
if (isNumber(max)) { | ||
return Array.from({ length: max - min }, (_, index) => index + min); | ||
} | ||
return Array.from({ length: min }, (_, index) => index); | ||
} | ||
return Array.from(min); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
export function isIterable<T>(obj: any): obj is Iterable<T> { | ||
return obj && typeof obj[Symbol.iterator] === "function"; | ||
} | ||
|
||
export function isObject(obj: any): obj is Record<string, any> { | ||
return typeof obj === "object" && obj !== null; | ||
} | ||
|
||
export function isString(obj: any): obj is string { | ||
return typeof obj === "string"; | ||
} | ||
|
||
export function isNumber(obj: any): obj is number { | ||
return typeof obj === "number"; | ||
} | ||
|
||
export function isArray<T>(obj: any): obj is T[] { | ||
return Array.isArray(obj); | ||
} | ||
|
||
export function unique<S>(arr: Iterable<S>) { | ||
return Array.from(new Set(arr)); | ||
} | ||
|
||
export function camelToSnakeCase(str: string, separator = "_") { | ||
return str.replace(/[A-Z]/g, (match) => `${separator}${match.toLowerCase()}`); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import type * as CSS from "csstype"; | ||
import { camelToSnakeCase, isNumber, isString } from "./shared"; | ||
|
||
export function unit_f<U extends string = StyleUnit>(value: string | number, unit: U = "px" as U) { | ||
if (/^[0-9]+(\.[0-9]+)?$/.test(String(value))) { | ||
return `${value}${unit}`; | ||
} | ||
return value; | ||
} | ||
|
||
export function style(stylesheet: CSSProperties) { | ||
return Object.keys(stylesheet).reduce<string[]>((prev, cur) => { | ||
const value = stylesheet[cur as keyof CSSProperties]; | ||
if (isNumber(value) || isString(value)) { | ||
prev.push(`${camelToSnakeCase(cur, "-")}: ${value};`); | ||
} | ||
return prev; | ||
}, []).join(" "); | ||
} | ||
|
||
export interface CSSProperties extends CSS.Properties<string | number>, CSS.PropertiesHyphen<string | number> { | ||
} | ||
|
||
export type StyleUnit = "px" | "rem" | "em" | "vw" | "vh" | "vmin" | "vmax" | "%" | "cm" | "mm" | "in" | "pt" | "pc"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { expect, test } from "vitest"; | ||
import { cls } from "../src/cls"; | ||
|
||
test("test classnames", () => { | ||
expect(cls({ | ||
foo: true, | ||
bar: false | ||
}, "baz", ["p-4 foo m-3", { | ||
absolute: true, | ||
relative: false | ||
}]).join(" ")).toBe("foo baz p-4 m-3 absolute"); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import { expect, test } from "vitest"; | ||
import { each } from "../src/each"; | ||
|
||
test("test each", () => { | ||
expect(each(5, (item) => item)).toEqual([1, 2, 3, 4, 5]); | ||
expect(each([0, 1, 2, 3], (_, index) => index)).toEqual([0, 1, 2, 3]); | ||
expect(each("abc", (s) => s)).toEqual(["a", "b", "c"]); | ||
expect(each({ a: 1, b: 2, c: 3 }, (item, key) => `${item}-${key}`)).toEqual(["1-a", "2-b", "3-c"]); | ||
|
||
// invalid value | ||
expect(each(null, (item) => item)).toEqual([]); | ||
expect(each(undefined, (item) => item)).toEqual([]); | ||
expect(each(0, (item) => item)).toEqual([]); | ||
expect(each("", (item) => item)).toEqual([]); | ||
expect(each(false, (item) => item)).toEqual([]); | ||
expect(each(true, (item) => item)).toEqual([]); | ||
expect(each(NaN, (item) => item)).toEqual([]); | ||
expect(each(String, (item) => item)).toEqual([]); | ||
expect(each(Symbol, (item) => item)).toEqual([]); | ||
expect(each(() => [1, 2, 3, 4], (item) => item)).toEqual([]); | ||
}); |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { expect, test } from "vitest"; | ||
import { range } from "../src/range"; | ||
|
||
test("test range", () => { | ||
expect(range(5)).toEqual([0, 1, 2, 3, 4]); | ||
expect(range(1, 5)).toEqual([1, 2, 3, 4]); | ||
expect(range("abc")).toEqual(["a", "b", "c"]); | ||
}); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { expect, test } from "vitest"; | ||
import { style, unit_f } from "../src/style"; | ||
|
||
test("test unit_f", () => { | ||
expect(unit_f(1)).toBe("1px"); | ||
expect(unit_f("1")).toBe("1px"); | ||
expect(unit_f("1rem")).toBe("1rem"); | ||
expect(unit_f("1px", "rem")).toBe("1px"); | ||
expect(unit_f("1rem", "%")).toBe("1rem"); | ||
}); | ||
|
||
test("test style", () => { | ||
expect(style({ | ||
color: "red", | ||
fontSize: "1rem", | ||
margin: 0, | ||
padding: "1rem" | ||
})).toBe("color: red; font-size: 1rem; margin: 0; padding: 1rem;"); | ||
}); |