aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/eval.ts22
-rw-r--r--src/index.ts43
-rw-r--r--src/parser.ts11
-rw-r--r--src/utils/adt.ts17
-rw-r--r--src/utils/parser-comb.ts171
-rw-r--r--src/utils/result.ts18
6 files changed, 170 insertions, 112 deletions
diff --git a/src/eval.ts b/src/eval.ts
index 191a76b..5e99282 100644
--- a/src/eval.ts
+++ b/src/eval.ts
@@ -12,7 +12,11 @@ export type EvalActions = {
setAttribute(name: string, value: string): Promise<void>
withEvent(fn: (e: any) => void): Promise<void>
getFormData(): Promise<FormData | undefined>
- sendRequest(_: { method: string, url: string, data: FormData | undefined }): Promise<void>
+ sendRequest(_: {
+ method: string
+ url: string
+ data: FormData | undefined
+ }): Promise<void>
// calculate ??
}
@@ -20,19 +24,19 @@ type EvalValue = string | undefined | void
export const evalExpr = async (
expr: Expr,
- actions: EvalActions
+ actions: EvalActions,
): Promise<EvalValue> =>
match<Promise<EvalValue>, Expr>(expr, {
Call: async ({ name, args }) => getFunctions(name, args, actions),
- LiteralString: async (s) => s,
+ LiteralString: async s => s,
LiteralNumber: async ({ value, unit }) =>
matchString<number, CSSUnit>(unit, {
s: () => value * 1000,
_: () => value,
}).toString(),
- Identifier: async (s) => s,
- VarIdentifier: async (s) => s,
- _: async (_) => undefined,
+ Identifier: async s => s,
+ VarIdentifier: async s => s,
+ _: async _ => undefined,
})
const getFunctions = (name: string, args: Expr[], actions: EvalActions) =>
@@ -93,9 +97,11 @@ const getFunctions = (name: string, args: Expr[], actions: EvalActions) =>
},
'prevent-default': async () => actions.withEvent(e => e.preventDefault()),
- 'request': async () => {
+ request: async () => {
const url = await evalExpr(args[0], actions)
- const method = args[1] ? (await evalExpr(args[1], actions) ?? 'post') : 'post'
+ const method = args[1]
+ ? (await evalExpr(args[1], actions)) ?? 'post'
+ : 'post'
if (url) {
const data = await actions.getFormData()
diff --git a/src/index.ts b/src/index.ts
index b48b1d8..2d70c3f 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -12,7 +12,7 @@ const EVENT_HANDLERS = {
const PROPERTIES = [
'--cssx-children',
'--cssx-text',
- '--cssx-disgustingly-set-innerhtml'
+ '--cssx-disgustingly-set-innerhtml',
]
const injectStyles = () => {
@@ -25,7 +25,7 @@ const injectStyles = () => {
const properties = [...PROPERTIES, ...Object.values(EVENT_HANDLERS)]
$style.textContent = `.cssx-layer {
- ${properties.map((p) => `${p}: ${UNSET_PROPERTY_VALUE};`).join(' ')}
+ ${properties.map(p => `${p}: ${UNSET_PROPERTY_VALUE};`).join(' ')}
}`
document.body.appendChild($style)
@@ -45,8 +45,8 @@ const getEvalActions = ($element: Element, event: any): EvalActions => ({
addClass: async (id, cls) => document.getElementById(id)?.classList.add(cls),
removeClass: async (id, cls) =>
document.getElementById(id)?.classList.remove(cls),
- delay: (delay) => new Promise((res) => setTimeout(res, delay)),
- jsEval: async (js) => (0, eval)(js),
+ delay: delay => new Promise(res => setTimeout(res, delay)),
+ jsEval: async js => (0, eval)(js),
loadCssx: async (id, url) =>
new Promise((resolve, reject) => {
const $link = Object.assign(document.createElement('link'), {
@@ -66,7 +66,7 @@ const getEvalActions = ($element: Element, event: any): EvalActions => ({
}
document.body.appendChild($link)
}),
- getVariable: async (varName) => getPropertyValue($element, varName),
+ getVariable: async varName => getPropertyValue($element, varName),
updateVariable: async (targetId, varName, value) => {
const $el = document.getElementById(targetId)
if ($el) {
@@ -76,15 +76,21 @@ const getEvalActions = ($element: Element, event: any): EvalActions => ({
setAttribute: async (name, value) => {
$element.setAttribute(name, value)
},
- withEvent: async (fn) => fn(event),
- getFormData: async () => $element.nodeName === 'FORM' ? new FormData($element as HTMLFormElement) : undefined,
+ withEvent: async fn => fn(event),
+ getFormData: async () =>
+ $element.nodeName === 'FORM'
+ ? new FormData($element as HTMLFormElement)
+ : undefined,
sendRequest: async ({ url, method, data }) => {
await fetch(url, { method, body: data })
// TODO: Handle response?
},
})
-const handleEvents = async ($element: Element, isNewElement: boolean = false) => {
+const handleEvents = async (
+ $element: Element,
+ isNewElement: boolean = false,
+) => {
for (const [eventType, property] of Object.entries(EVENT_HANDLERS)) {
const handlerExpr = getPropertyValue($element, property)
@@ -106,17 +112,17 @@ const handleEvents = async ($element: Element, isNewElement: boolean = false) =>
}
}
-let nodeCount = 0
-const manageElement = async ($element: Element, isNewElement: boolean = false) => {
- if (nodeCount++ > 100) return // NOTE: Temporary. To prevent infinite rec
-
+const manageElement = async (
+ $element: Element,
+ isNewElement: boolean = false,
+) => {
await handleEvents($element, isNewElement)
const text = getPropertyValue($element, '--cssx-text')
if (text) $element.textContent = text
const html = getPropertyValue($element, '--cssx-disgustingly-set-innerhtml')
- if (html) $element.innerHTML = html
+ if (html) $element.innerHTML = html.replace(/(^'|")|('|"$)/g, '')
const childrenIds = getChildrenIds($element)
if (childrenIds.length > 0) {
@@ -127,12 +133,13 @@ const manageElement = async ($element: Element, isNewElement: boolean = false) =
$element.appendChild($childrenRoot)
for (const childId of childrenIds) {
- let isNewElement = false;
const selector = childId.split('#')
const [tag, id] = selector.length >= 2 ? selector : ['div', ...selector]
- const $child =
- $childrenRoot.querySelector(`:scope > #${id}`) ??
- (isNewElement = true, Object.assign(document.createElement(tag || 'div'), { id }))
+ let $child = $childrenRoot.querySelector(`:scope > #${id}`)
+ const isNewElement = !$child
+ if (!$child) {
+ $child = Object.assign(document.createElement(tag || 'div'), { id })
+ }
$childrenRoot.appendChild($child)
await manageElement($child, isNewElement)
}
@@ -147,4 +154,4 @@ const render = async ({ root = document.body }: Options = {}) => {
await manageElement(root)
}
-render()
+render() \ No newline at end of file
diff --git a/src/parser.ts b/src/parser.ts
index 9cb0405..3279f57 100644
--- a/src/parser.ts
+++ b/src/parser.ts
@@ -8,7 +8,7 @@ export type Expr = Enum<{
Identifier: string
VarIdentifier: string
LiteralString: string
- LiteralNumber: { value: number, unit: CSSUnit }
+ LiteralNumber: { value: number; unit: CSSUnit }
}>
export const Expr = constructors<Expr>()
@@ -31,9 +31,9 @@ const callExprParser = (input: string) =>
P.map(
P.zip2(
consumeWhitespace(identifierParser),
- parens(consumeWhitespace(P.sepBy(exprParser, comma)))
+ parens(consumeWhitespace(P.sepBy(exprParser, comma))),
),
- ([name, args]) => Expr.Call({ name, args })
+ ([name, args]) => Expr.Call({ name, args }),
)(input)
const stringLiteralParser: P.Parser<Expr> = P.map(
@@ -41,14 +41,15 @@ const stringLiteralParser: P.Parser<Expr> = P.map(
P.between(singleQuote, P.regex(/^[^']*/), singleQuote),
P.between(doubleQuote, P.regex(/^[^"]*/), doubleQuote),
]),
- Expr.LiteralString
+ Expr.LiteralString,
)
const numberParser = P.regex(/^[-+]?((\d*\.\d+)|\d+)/)
const numberExprParser: P.Parser<Expr> = P.map(
P.zip2(numberParser, P.optional(P.regex(/^(s|ms)/i))),
- ([value, unit]) => Expr.LiteralNumber({ value: Number(value), unit: (unit ?? '') as CSSUnit }),
+ ([value, unit]) =>
+ Expr.LiteralNumber({ value: Number(value), unit: (unit ?? '') as CSSUnit }),
)
const exprParser: P.Parser<Expr> = P.or([
diff --git a/src/utils/adt.ts b/src/utils/adt.ts
index 78ab667..45d9e50 100644
--- a/src/utils/adt.ts
+++ b/src/utils/adt.ts
@@ -1,14 +1,18 @@
type TagValue<T, N> = T extends Tag<N, infer V> ? V : never
-export const match =
- <R, T extends Tag<string, any>>(tag: T, pattern: {
+export const match = <R, T extends Tag<string, any>>(
+ tag: T,
+ pattern: {
[key in T['tag'] | '_']?: (v: TagValue<T, key>) => R
- }): R => ((pattern as any)[tag.tag] || (pattern._ as any))(tag.value)
+ },
+): R => ((pattern as any)[tag.tag] || (pattern._ as any))(tag.value)
-export const matchString =
- <R, T extends string = string>(key: T, pattern: {
+export const matchString = <R, T extends string = string>(
+ key: T,
+ pattern: {
[key in T | '_']?: (key: key) => R
- }): R => ((pattern as any)[key] || (pattern._ as any))(key)
+ },
+): R => ((pattern as any)[key] || (pattern._ as any))(key)
type Tag<N, V> = { tag: N; value: V }
export type Enum<T> = { [N in keyof T]: Tag<N, T[N]> }[keyof T]
@@ -26,4 +30,3 @@ export const constructors = <T extends Tag<string, any>>(): {
},
},
) as any
-
diff --git a/src/utils/parser-comb.ts b/src/utils/parser-comb.ts
index f682068..3f171b8 100644
--- a/src/utils/parser-comb.ts
+++ b/src/utils/parser-comb.ts
@@ -1,83 +1,120 @@
-import { match } from './adt';
-import { Result, mapResult, chainResult } from './result';
+import { match } from './adt'
+import { Result, mapResult, chainResult } from './result'
-export type ParseResult<T> = Result<{ value: T, input: string }, { error: string, input: string }>;
+export type ParseResult<T> = Result<
+ { value: T; input: string },
+ { error: string; input: string }
+>
-export type Parser<T> = (input: string) => ParseResult<T>;
+export type Parser<T> = (input: string) => ParseResult<T>
-export const regex = (re: RegExp): Parser<string> => input => {
- if (input.length === 0) return Result.Err({ error: 'fuckedinput', input })
- const res = input.match(re)
- if (!res) return Result.Err({ error: 'fucked', input });
- return Result.Ok({ value: res[0], input: input.replace(re, '') });
-}
+export const regex =
+ (re: RegExp): Parser<string> =>
+ input => {
+ if (input.length === 0) return Result.Err({ error: 'fuckedinput', input })
+ const res = input.match(re)
+ if (!res) return Result.Err({ error: 'fucked', input })
+ return Result.Ok({ value: res[0], input: input.replace(re, '') })
+ }
-export const string = (str: string): Parser<string> => input => {
- if (input.length === 0) return Result.Err({ error: 'fuckedinput', input })
- if (!input.startsWith(str)) return Result.Err({ error: 'fuckedstring', input })
- return Result.Ok({ value: str, input: input.slice(str.length) });
-}
+export const string =
+ (str: string): Parser<string> =>
+ input => {
+ if (input.length === 0) return Result.Err({ error: 'fuckedinput', input })
+ if (!input.startsWith(str))
+ return Result.Err({ error: 'fuckedstring', input })
+ return Result.Ok({ value: str, input: input.slice(str.length) })
+ }
-export const or = <T>([parser, ...rest]: Array<Parser<T>>): Parser<T> => input => {
- if (rest.length === 0) return parser(input);
- const result = parser(input)
- return match(result, {
- Ok: () => result,
- Err: (_) => or(rest)(input),
- });
-}
+export const or =
+ <T>([parser, ...rest]: Array<Parser<T>>): Parser<T> =>
+ input => {
+ if (rest.length === 0) return parser(input)
+ const result = parser(input)
+ return match(result, {
+ Ok: () => result,
+ Err: _ => or(rest)(input),
+ })
+ }
-export const mapParseResult = <T, R>(parser: Parser<T>, fn: (_: { value: T, input: string }) => { value: R, input: string }): Parser<R> => input =>
- mapResult(parser(input), fn)
+export const mapParseResult =
+ <T, R>(
+ parser: Parser<T>,
+ fn: (_: { value: T; input: string }) => { value: R; input: string },
+ ): Parser<R> =>
+ input =>
+ mapResult(parser(input), fn)
export const map = <T, R>(parser: Parser<T>, fn: (_: T) => R): Parser<R> =>
- mapParseResult(parser, ({ value, ...rest }) => ({ ...rest, value: fn(value) }));
+ mapParseResult(parser, ({ value, ...rest }) => ({
+ ...rest,
+ value: fn(value),
+ }))
-export const zip2 = <A, B>(parserA: Parser<A>, parserB: Parser<B>): Parser<readonly [A, B]> => input => {
- // TODO: refactor please. shit code
- const resa: Result<{ value: A, input: string }, { error: string, input: string }> = parserA(input);
- return chainResult(resa, ({ value: a, input: inputB }) => {
- const res: Result<{ value: readonly [A, B], input: string }, { error: string, input: string }> =
- map(parserB, (b) => [a, b] as const)(inputB)
- return res
- })
-}
+export const zip2 =
+ <A, B>(parserA: Parser<A>, parserB: Parser<B>): Parser<readonly [A, B]> =>
+ input => {
+ // TODO: refactor please. shit code
+ const resa: Result<
+ { value: A; input: string },
+ { error: string; input: string }
+ > = parserA(input)
+ return chainResult(resa, ({ value: a, input: inputB }) => {
+ const res: Result<
+ { value: readonly [A, B]; input: string },
+ { error: string; input: string }
+ > = map(parserB, b => [a, b] as const)(inputB)
+ return res
+ })
+ }
-export const prefixed = <A>(parserPrefix: Parser<any>, parser: Parser<A>): Parser<A> =>
- map(zip2(parserPrefix, parser), ([_, a]) => a);
+export const prefixed = <A>(
+ parserPrefix: Parser<any>,
+ parser: Parser<A>,
+): Parser<A> => map(zip2(parserPrefix, parser), ([_, a]) => a)
-export const suffixed = <A>(parser: Parser<A>, parserSuffix: Parser<any>): Parser<A> =>
- map(zip2(parser, parserSuffix), ([a, _]) => a);
+export const suffixed = <A>(
+ parser: Parser<A>,
+ parserSuffix: Parser<any>,
+): Parser<A> => map(zip2(parser, parserSuffix), ([a, _]) => a)
-export const between = <A>(prefix: Parser<any>, parser: Parser<A>, suffix: Parser<any>): Parser<A> =>
- suffixed(prefixed(prefix, parser), suffix)
+export const between = <A>(
+ prefix: Parser<any>,
+ parser: Parser<A>,
+ suffix: Parser<any>,
+): Parser<A> => suffixed(prefixed(prefix, parser), suffix)
-export const many0 = <A>(parser: Parser<A>): Parser<Array<A>> => originalInput =>
- match(parser(originalInput), {
- Ok: ({ value, input }) => map(many0(parser), ls => [value, ...ls])(input),
- Err: ({ input }) => Result.Ok({ value: [], input }),
- })
+export const many0 =
+ <A>(parser: Parser<A>): Parser<Array<A>> =>
+ originalInput =>
+ match(parser(originalInput), {
+ Ok: ({ value, input }) => map(many0(parser), ls => [value, ...ls])(input),
+ Err: ({ input }) => Result.Ok({ value: [], input }),
+ })
-export const many1 = <A>(parser: Parser<A>): Parser<Array<A>> => originalInput =>
- match(parser(originalInput), {
- Ok: ({ value, input }) => map(many0(parser), ls => [value, ...ls])(input),
- Err: err => Result.Err(err),
- })
+export const many1 =
+ <A>(parser: Parser<A>): Parser<Array<A>> =>
+ originalInput =>
+ match(parser(originalInput), {
+ Ok: ({ value, input }) => map(many0(parser), ls => [value, ...ls])(input),
+ Err: err => Result.Err(err),
+ })
-export const sepBy = <A>(parser: Parser<A>, sepP: Parser<any>): Parser<Array<A>> => originalInput =>
- match(parser(originalInput), {
- Ok: ({ value, input }) => map(
- many0(prefixed(sepP, parser)),
- ls => [value, ...ls]
- )(input),
- Err: _ => Result.Ok({ value: [], input: originalInput }),
- })
-
-export const optional = <A>(parser: Parser<A>): Parser<undefined | A> => input => {
- const result = parser(input)
- return match(result, {
- Ok: _ => result,
- Err: _ => Result.Ok({ value: undefined, input })
- })
-}
+export const sepBy =
+ <A>(parser: Parser<A>, sepP: Parser<any>): Parser<Array<A>> =>
+ originalInput =>
+ match(parser(originalInput), {
+ Ok: ({ value, input }) =>
+ map(many0(prefixed(sepP, parser)), ls => [value, ...ls])(input),
+ Err: _ => Result.Ok({ value: [], input: originalInput }),
+ })
+export const optional =
+ <A>(parser: Parser<A>): Parser<undefined | A> =>
+ input => {
+ const result = parser(input)
+ return match(result, {
+ Ok: _ => result,
+ Err: _ => Result.Ok({ value: undefined, input }),
+ })
+ }
diff --git a/src/utils/result.ts b/src/utils/result.ts
index c0120b8..39a7fe6 100644
--- a/src/utils/result.ts
+++ b/src/utils/result.ts
@@ -1,14 +1,18 @@
-import { Enum, constructors, match } from "./adt";
+import { Enum, constructors, match } from './adt'
-export type Result<V, E> = Enum<{ Ok: V, Err: E }>
+export type Result<V, E> = Enum<{ Ok: V; Err: E }>
export const Result = constructors<Result<any, any>>()
-export const mapResult = <A, B, E>(res: Result<A, E>, fn: (_: A) => B): Result<B, E> =>
- chainResult(res, a => Result.Ok(fn(a)))
+export const mapResult = <A, B, E>(
+ res: Result<A, E>,
+ fn: (_: A) => B,
+): Result<B, E> => chainResult(res, a => Result.Ok(fn(a)))
-export const chainResult = <A, B, E>(res: Result<A, E>, fn: (_: A) => Result<B, E>): Result<B, E> =>
+export const chainResult = <A, B, E>(
+ res: Result<A, E>,
+ fn: (_: A) => Result<B, E>,
+): Result<B, E> =>
match(res, {
Ok: a => fn(a),
Err: e => Result.Err(e),
- });
-
+ })