diff --git a/src/core/compile.ts b/src/core/compile.ts index 28db16b..a2fd77d 100644 --- a/src/core/compile.ts +++ b/src/core/compile.ts @@ -87,7 +87,7 @@ export const collectAndInitDirectives = ( nodeDeps.push(...uniqueCompiledDeps); const directiveData = { - compute: compute(value, el, returnable, refs), + compute: compute(value, el, returnable, refs, uniqueCompiledDeps), deps: uniqueCompiledDeps, value, }; diff --git a/src/core/directives/bind.ts b/src/core/directives/bind.ts index 902dad7..95273fb 100644 --- a/src/core/directives/bind.ts +++ b/src/core/directives/bind.ts @@ -1,7 +1,8 @@ import { DirectiveProps } from '../../models/structs'; export const formatAcceptableWhitespace = (expression: string): string => { - return expression.replace(/\s+/gim, ' ').trim(); + const whitespaceRE = /\s+/gim; + return expression.replace(whitespaceRE, ' ').trim(); }; export const bindDirective = ({ el, parts, data, state }: DirectiveProps): void => { diff --git a/src/core/directives/for.ts b/src/core/directives/for.ts index e19c206..a5e99b5 100644 --- a/src/core/directives/for.ts +++ b/src/core/directives/for.ts @@ -19,7 +19,8 @@ export const forDirective = ({ el, data, state, node }: DirectiveProps): void => setElementCustomProp(el, 'component', true); - const [expression, target] = data.value.split(/\s+(?:in|of)\s+/gim); + const forLoopRE = /\s+(?:in|of)\s+/gim; + const [expression, target] = data.value.split(forLoopRE); const [item, index] = expression?.trim().replace(parenthesisWrapReplaceRE(), '').split(','); // Try to grab by property, else compute it if it's a custom array diff --git a/src/core/directives/model.ts b/src/core/directives/model.ts index 76e71f7..f1e9da9 100644 --- a/src/core/directives/model.ts +++ b/src/core/directives/model.ts @@ -39,7 +39,7 @@ export const inputCallback = ( state[data.value] = payload; } else { payload = typeof payload === 'string' ? `'${payload}'` : payload; - computeExpression(`${data.value} = ${payload}`, el, true)(state); + computeExpression(`$state.${data.value} = ${payload}`, el, true)(state); } return payload; diff --git a/src/core/render.ts b/src/core/render.ts index e20f1d2..c8f5543 100644 --- a/src/core/render.ts +++ b/src/core/render.ts @@ -24,7 +24,7 @@ const render = ( for (const [directiveName, directiveData] of Object.entries(node.directives)) { yield; - const rawDirectiveName = directiveName.split(/:|\./)[0]; + const rawDirectiveName = directiveName.split(rawDirectiveSplitRE())[0]; // Validate if it is a legal directive if (!legalDirectiveNames.includes(rawDirectiveName.toUpperCase())) continue; // Iterate through affected and check if directive value has prop diff --git a/src/core/utils/computeExpression.ts b/src/core/utils/computeExpression.ts index d49c7b2..7d2c07b 100644 --- a/src/core/utils/computeExpression.ts +++ b/src/core/utils/computeExpression.ts @@ -1,14 +1,21 @@ import { UnknownKV } from '../../models/generics'; import { Refs } from '../../models/structs'; +import { expressionPropRE } from './patterns'; export const computeExpression = ( expression: string, el?: HTMLElement, returnable = true, - refs: Refs = {} + refs: Refs = {}, + deps: string[] = [] // eslint-disable-next-line @typescript-eslint/no-explicit-any ): ((state: UnknownKV, event?: Event) => any) => { - const formattedExpression = `with($state){${returnable ? `return ${expression}` : expression}}`; + // This dynamically appends `$state.` to the front of standalone props, allowing the + // user to write less and us to compile and run faster without with() {} + let formattedExpression = `${returnable ? `return ${expression}` : expression}`; + deps.forEach((dep) => { + formattedExpression = formattedExpression.replace(expressionPropRE(dep), `$state.${dep}`); + }); return (state: UnknownKV, event?: Event) => { try { const value = state[expression];