From 2a4c960ba4acadbc0fafadb6c7024d63871cbc2b Mon Sep 17 00:00:00 2001 From: Astrian Zheng Date: Thu, 22 May 2025 11:48:27 +1000 Subject: [PATCH] refactor: improve code readability by adding braces for conditional statements --- src/main.ts | 28 ++++++--- src/utils/initState.ts | 23 ++++--- src/utils/parseTemplate.ts | 5 +- src/utils/processTemplateMarcos.ts | 84 +++++++++++++++++--------- src/utils/setupArrowFunctionHandler.ts | 4 +- src/utils/triggerDomUpdates.ts | 15 +++-- 6 files changed, 109 insertions(+), 50 deletions(-) diff --git a/src/main.ts b/src/main.ts index 57a5408..3ed8917 100644 --- a/src/main.ts +++ b/src/main.ts @@ -158,7 +158,9 @@ export default (options: ComponentOptions) => { private _evaluateIfCondition(element: Element, condition: string) { const info = this._conditionalElements.get(element) - if (!info) { return } + if (!info) { + return + } // Evaluate the condition const result = this._evaluateExpression(condition) @@ -172,7 +174,9 @@ export default (options: ComponentOptions) => { info.placeholder.nextSibling, ) // Remove the element from the DOM - } else { element.parentNode?.removeChild(element) } + } else { + element.parentNode?.removeChild(element) + } // Update the state info.isPresent = shouldShow @@ -366,7 +370,9 @@ export default (options: ComponentOptions) => { let result = this._states for (const part of parts) { - if (result === undefined || result === null) { return undefined } + if (result === undefined || result === null) { + return undefined + } result = (result as { [key: string]: Record })[part] } @@ -374,11 +380,15 @@ export default (options: ComponentOptions) => { } connectedCallback() { - if (onMount) { onMount.call(this) } + if (onMount) { + onMount.call(this) + } } disconnectedCallback() { - if (onUnmount) { onUnmount.call(this) } + if (onUnmount) { + onUnmount.call(this) + } } static get observedAttributes() { @@ -390,7 +400,9 @@ export default (options: ComponentOptions) => { oldValue: string, newValue: string, ) { - if (onAttributeChanged) { onAttributeChanged(attrName, oldValue, newValue) } + if (onAttributeChanged) { + onAttributeChanged(attrName, oldValue, newValue) + } } // state manager @@ -402,7 +414,9 @@ export default (options: ComponentOptions) => { const parts = keyPath.split('.') let result = this._states for (const part of parts) { - if (result === undefined || result === null) { return undefined } + if (result === undefined || result === null) { + return undefined + } result = (result as { [key: string]: Record })[part] } return result diff --git a/src/utils/initState.ts b/src/utils/initState.ts index 59e9f65..9f6eff0 100644 --- a/src/utils/initState.ts +++ b/src/utils/initState.ts @@ -49,7 +49,9 @@ export default function initState( if (Number.parseInt(i) === valueRoute.length - 1) { currentTarget[key] = value } else { - if (!currentTarget[key]) currentTarget[key] = {} + if (!currentTarget[key]) { + currentTarget[key] = {} + } currentTarget = currentTarget[key] as Record } } @@ -62,15 +64,18 @@ export default function initState( getNestedState: ops.getNestedState, scheduleUpdate: ops.scheduleUpdate, }) - if (ops.statesListenersSelf[keyPath]) + if (ops.statesListenersSelf[keyPath]) { ops.statesListenersSelf[keyPath](value) + } // trigger %if macros - if (ops.conditionalElements.size > 0) + if (ops.conditionalElements.size > 0) { ops.conditionalElements.forEach((info, element) => { - if (info.expr.includes(keyPath)) + if (info.expr.includes(keyPath)) { ops.evaluateIfCondition(element, info.expr) + } }) + } // trigger state update events statesListeners?.[keyPath]?.(value) @@ -80,8 +85,9 @@ export default function initState( get: (target: Record, keyPath: string) => { // collect state dependencies if (ops.currentRenderingElement) { - if (!ops.stateToElementsMap[keyPath]) + if (!ops.stateToElementsMap[keyPath]) { ops.stateToElementsMap[keyPath] = new Set() + } ops.stateToElementsMap[keyPath].add(ops.currentRenderingElement) } @@ -89,10 +95,13 @@ export default function initState( let currentTarget = target for (const i in valueRoute) { const key = valueRoute[i] - if (Number.parseInt(i) === valueRoute.length - 1) + if (Number.parseInt(i) === valueRoute.length - 1) { return currentTarget[key] + } - if (!currentTarget[key]) currentTarget[key] = {} + if (!currentTarget[key]) { + currentTarget[key] = {} + } currentTarget = currentTarget[key] as Record } return undefined diff --git a/src/utils/parseTemplate.ts b/src/utils/parseTemplate.ts index b946b57..aa07e09 100644 --- a/src/utils/parseTemplate.ts +++ b/src/utils/parseTemplate.ts @@ -5,8 +5,9 @@ export default function parseTemplate(template: string): Element { const mainContent = doc.body.firstElementChild let rootElement: Element - if (mainContent) rootElement = document.importNode(mainContent, true) - else { + if (mainContent) { + rootElement = document.importNode(mainContent, true) + } else { const container = document.createElement('div') container.innerHTML = template rootElement = container diff --git a/src/utils/processTemplateMarcos.ts b/src/utils/processTemplateMarcos.ts index 653cd9d..97d2d29 100644 --- a/src/utils/processTemplateMarcos.ts +++ b/src/utils/processTemplateMarcos.ts @@ -109,8 +109,9 @@ export default function processTemplateMacros( options.updateTextNode(textNode, expr, originalContent) // Add dependency relationship for this state path - if (!options.stateToElementsMap[expr]) + if (!options.stateToElementsMap[expr]) { options.stateToElementsMap[expr] = new Set() + } options.stateToElementsMap[expr].add( textNode as unknown as HTMLElement, @@ -219,14 +220,14 @@ export default function processTemplateMacros( currentElementNode.removeAttribute(attr.name) // Handle different types of macros - if (macroName === 'connect') + if (macroName === 'connect') { // Handle state connection: %connect="stateName" setupTwoWayBinding(currentElementNode, expr, { getNestedState: context.getState.bind(context), setState: context.setState.bind(context), statesListeners: options.stateListeners, }) - else if (macroName === 'if') { + } else if (macroName === 'if') { ifDirectivesToProcess.push({ element: currentElementNode, expr }) } else if (macroName === 'for') { const listContext: ListRenderingContext = { @@ -238,8 +239,7 @@ export default function processTemplateMacros( triggerFunc: options.triggerFunc.bind(context), } setupListRendering(currentElementNode, expr, listContext) - } else if (macroName === 'key') continue - else console.warn(`Unknown macro: %${macroName}`) + } } } } @@ -272,12 +272,13 @@ function setupTwoWayBinding( const value = ops.getNestedState(expr) // Set the initial value - if (value !== undefined) + if (value !== undefined) { element.setAttribute('data-laterano-connect', String(value)) - else + } else { console.error( `State \`${expr}\` not found in the component state. Although Laterano will try to work with it, it may has potentially unexpected behavior.`, ) + } // Add event listener for input events element.addEventListener('input', (event: Event) => { @@ -290,8 +291,11 @@ function setupTwoWayBinding( // Add event listener for state changes ops.statesListeners[expr] = (newValue: unknown) => { - if (element instanceof HTMLInputElement) element.value = newValue as string - else element.setAttribute('data-laterano-connect', String(newValue)) + if (element instanceof HTMLInputElement) { + element.value = newValue as string + } else { + element.setAttribute('data-laterano-connect', String(newValue)) + } } } @@ -322,7 +326,9 @@ function setupConditionRendering( const statePaths = ops.extractStatePathsFromExpression(expr) for (const path of statePaths) { - if (!ops.stateToElementsMap[path]) ops.stateToElementsMap[path] = new Set() + if (!ops.stateToElementsMap[path]) { + ops.stateToElementsMap[path] = new Set() + } ops.stateToElementsMap[path].add(element as HTMLElement) } } @@ -349,7 +355,9 @@ function evaluateExpressionWithItemContext( let value = itemContext[itemVar] for (const part of parts) { - if (value === undefined || value === null) return undefined + if (value === undefined || value === null) { + return undefined + } value = (value as { [key: string]: unknown })[part] } @@ -461,7 +469,7 @@ function processElementWithItemContext( const textNode = node as Text const updatedContent = textContent.replace( /\{\{\s*([^}]+)\s*\}\}/g, - (match, expr) => { + (_match, expr) => { const value = evaluateExpressionWithItemContext( expr.trim(), itemContext, @@ -476,8 +484,11 @@ function processElementWithItemContext( } // Process the text nodes of the element itself - for (const node of Array.from(element.childNodes)) - if (node.nodeType === Node.TEXT_NODE) processTextNodes(node) + for (const node of Array.from(element.childNodes)) { + if (node.nodeType === Node.TEXT_NODE) { + processTextNodes(node) + } + } // Process attribute bindings (:attr) for (const attr of Array.from(element.attributes)) { @@ -490,7 +501,9 @@ function processElementWithItemContext( context, ) - if (value !== undefined) element.setAttribute(attrName, String(value)) + if (value !== undefined) { + element.setAttribute(attrName, String(value)) + } // Remove the original binding attribute element.removeAttribute(attr.name) @@ -555,7 +568,9 @@ function processElementWithItemContext( shouldDisplay = Boolean(result) // Apply the condition - if (!shouldDisplay) (element as HTMLElement).style.display = 'none' + if (!shouldDisplay) { + ;(element as HTMLElement).style.display = 'none' + } } } @@ -581,11 +596,14 @@ function processElementWithItemContext( } // If this element is a list element, skip child element processing - if (hasForDirective) return + if (hasForDirective) { + return + } // Recursively process all child elements - for (const child of Array.from(element.children)) + for (const child of Array.from(element.children)) { processElementWithItemContext(child, itemContext, context) + } } // Handle list rendering (%for macro) @@ -643,22 +661,27 @@ function setupListRendering( } // Detach all currently rendered DOM items - for (const item of renderedItems) - if (item.element.parentNode === parentNode) + for (const item of renderedItems) { + if (item.element.parentNode === parentNode) { parentNode.removeChild(item.element) + } + } // Get key attribute if available const keyAttr = template.getAttribute('%key') - if (!keyAttr) + if (!keyAttr) { console.warn( '%key attribute not found in the template, which is not a recommended practice.', ) + } // Store a map of existing items by key for reuse const existingElementsByKey = new Map() - for (const item of renderedItems) - if (item.key !== undefined) existingElementsByKey.set(item.key, item) - + for (const item of renderedItems) { + if (item.key !== undefined) { + existingElementsByKey.set(item.key, item) + } + } // Clear rendered items renderedItems.length = 0 @@ -704,7 +727,9 @@ function setupListRendering( const itemContext = { [itemVar]: item, } - if (indexVar) itemContext[indexVar] = index + if (indexVar) { + itemContext[indexVar] = index + } // insert %key attribute if (keyAttr) { @@ -730,17 +755,20 @@ function setupListRendering( placeholder.parentNode?.insertBefore(fragment, placeholder.nextSibling) // Remove any remaining unused items - for (const item of existingElementsByKey.values()) - if (item.element.parentNode) + for (const item of existingElementsByKey.values()) { + if (item.element.parentNode) { item.element.parentNode.removeChild(item.element) + } + } } // Initial render updateList() // Set up state dependency for collection changes - if (!context.stateToElementsMap[collectionExpr]) + if (!context.stateToElementsMap[collectionExpr]) { context.stateToElementsMap[collectionExpr] = new Set() + } // Using a unique identifier for this list rendering instance const listVirtualElement = document.createElement('div') diff --git a/src/utils/setupArrowFunctionHandler.ts b/src/utils/setupArrowFunctionHandler.ts index a7eb8e1..97d7a15 100644 --- a/src/utils/setupArrowFunctionHandler.ts +++ b/src/utils/setupArrowFunctionHandler.ts @@ -24,7 +24,9 @@ export default function setupArrowFunctionHandler( throw new Error(`Invalid arrow function syntax: ${handlerValue}`) } const paramsStr = (() => { - if (splitted[0].includes('(')) return splitted[0].trim() + if (splitted[0].includes('(')) { + return splitted[0].trim() + } return `(${splitted[0].trim()})` })() const bodyStr = splitted[1].trim() diff --git a/src/utils/triggerDomUpdates.ts b/src/utils/triggerDomUpdates.ts index 5b923cb..99ac106 100644 --- a/src/utils/triggerDomUpdates.ts +++ b/src/utils/triggerDomUpdates.ts @@ -25,8 +25,9 @@ export default function triggerDomUpdates( if (ops.stateToElementsMap[keyPath]) { const updateQueue = new Set() - for (const element of ops.stateToElementsMap[keyPath]) + for (const element of ops.stateToElementsMap[keyPath]) { updateQueue.add(element) + } ops.scheduleUpdate(updateQueue) } @@ -34,18 +35,22 @@ export default function triggerDomUpdates( // Update text bindings that depend on this state if (ops.textBindings) { // this._textBindings.forEach((binding) => { - for (const binding of ops.textBindings) - if (binding.expr === keyPath || binding.expr.startsWith(`${keyPath}.`)) + for (const binding of ops.textBindings) { + if (binding.expr === keyPath || binding.expr.startsWith(`${keyPath}.`)) { ops.updateTextNode(binding.node, binding.expr, binding.originalContent) + } + } } // Update attribute bindings that depend on this state if (ops.attributeBindings) { - for (const binding of ops.attributeBindings) + for (const binding of ops.attributeBindings) { if (binding.expr === keyPath || binding.expr.startsWith(`${keyPath}.`)) { const value = ops.getNestedState(binding.expr) - if (value !== undefined) + if (value !== undefined) { binding.element.setAttribute(binding.attrName, String(value)) + } } + } } }