npm.io
3.8.9 • Published 5 months ago

@domql/utils

Licence
CC-BY-NC-4.0
Version
3.8.9
Deps
0
Size
495 kB
Vulns
0
Weekly
0

@domql/utils

Core utility functions for the DOMQL element system.

Propertization (props.js)

The propertization system normalizes element definitions by sorting keys between the element root (child elements, framework keys) and props (CSS properties, design tokens, custom data).

Two-phase process

  1. pickupPropsFromElement — Scans element root keys and moves non-element, non-builtin keys into props
  2. pickupElementFromProps — Scans props keys and moves element-like or builtin keys back to the element root
Key classification rules
Pattern Classification Example
Starts with uppercase Child element Header, Button, Nav
Numeric key Child element 0, 1, 2
In DOMQ_PROPERTIES Framework builtin tag, extends, on
In CSS_SELECTOR_PREFIXES CSS-in-props :hover, @mobileS, $isActive
Has define handler Define key (stays at root) $router, deprecated: $propsCollection
childProps Always in props childProps
onXxx + function Event handler onClick, onSubmit
Everything else Prop padding, theme, color
CSS_SELECTOR_PREFIXES
const CSS_SELECTOR_PREFIXES = new Set([
  ':', '@', '[', '*', '+', '~', '&', '>', '

These single-character prefixes identify keys that should be processed by css-in-props via transformersByPrefix. When a key starts with one of these characters, it gets moved into props.

Define-awareness

The $ prefix is shared between css-in-props conditionals ($isActive) and define handlers (built-in $router, plus deprecated v2 handlers like $propsCollection, $collection that some older projects still use). The propertization must check for define handlers before applying prefix rules:

// Check define handlers first — these stay at root
const defineValue = this.define?.[key]
const globalDefineValue = this.context?.define?.[key]
if (isFunction(defineValue) || isFunction(globalDefineValue)) continue

// Only then apply prefix-based classification
if (CSS_SELECTOR_PREFIXES.has(firstChar)) {
  obj.props[key] = value
}

Without this check, define keys like $router (or deprecated $propsCollection in older projects) get moved into props and become invisible to throughInitialDefine, breaking routing and collection-based rendering.

childProps handling

childProps is a framework property that configures child element props. It must always stay in props (consumed by inheritParentProps) even though its value may contain uppercase keys that look like child elements:

// childProps: { Icon: { name: 'star' }, Hgroup: { ... } }
// The uppercase keys inside are NOT child elements
if (key === 'childProps') {
  obj.props[key] = value
  delete obj[key]
  continue
}
ignoreChildProps

When set on element.props, prevents the element from inheriting childProps from its parent via inheritParentProps. Used by fragment elements to avoid double-application of childProps (since fragments explicitly forward childProps to their children).

Scope (scope.js)

createScope(element, parent)

Creates the scope for an element with prototype-chain inheritance:

el.scope → parent.scope → grandparent.scope → ... → root.scope → context.globalScope

Behavior:

  • No own scope — element inherits parent.scope directly (same reference)
  • Own scope defined (scope: { myVar: 1 }) — prototype is set to parent's scope, chaining up to globalScope
  • No parent/root scope — new scope created with Object.create(context.globalScope)
  • No context — plain {}
globalScope

Automatically initialized as context.globalScope = {} if context exists. Sits at the bottom of every scope prototype chain, making its properties accessible from any element via el.scope.X.

// In context or set by the serialization pipeline:
context.globalScope = {
  API_URL: 'https://api.example.com',
  helpers: { capitalize: (s) => s[0].toUpperCase() + s.slice(1) }
}

// Accessible from any element — no import needed:
onClick: (e, el) => fetch(el.scope.API_URL)

// Also directly accessible:
el.context.globalScope.API_URL

When a component defines its own scope, properties shadow parent/global values but the chain remains walkable:

// Parent: scope = { theme: 'dark' }
// Child:  scope = { count: 0 }
// el.scope.count → 0      (own)
// el.scope.theme → 'dark'  (parent, via prototype)
// el.scope.API_URL → '...' (globalScope, via prototype chain)

Key Sets (keys.js)

  • DOMQ_PROPERTIES — Framework-level keys that stay at element root
  • PROPS_METHODS — Keys on the props prototype (update, __element)
  • STATE_METHODS — State management methods (update, parse, set, toggle, etc.)
, '-', '.', '!' ])

These single-character prefixes identify keys that should be processed by __INLINE_CODE_30__ via __INLINE_CODE_31__. When a key starts with one of these characters, it gets moved into __INLINE_CODE_32__.

Define-awareness

The __INLINE_CODE_33__ prefix is shared between css-in-props conditionals (__INLINE_CODE_34__) and define handlers (built-in __INLINE_CODE_35__, plus deprecated v2 handlers like __INLINE_CODE_36__, __INLINE_CODE_37__ that some older projects still use). The propertization must check for define handlers before applying prefix rules:

__CODE_BLOCK_1__

Without this check, define keys like __INLINE_CODE_38__ (or deprecated __INLINE_CODE_39__ in older projects) get moved into __INLINE_CODE_40__ and become invisible to __INLINE_CODE_41__, breaking routing and collection-based rendering.

childProps handling

__INLINE_CODE_42__ is a framework property that configures child element props. It must always stay in __INLINE_CODE_43__ (consumed by __INLINE_CODE_44__) even though its value may contain uppercase keys that look like child elements:

__CODE_BLOCK_2__
ignoreChildProps

When set on __INLINE_CODE_45__, prevents the element from inheriting __INLINE_CODE_46__ from its parent via __INLINE_CODE_47__. Used by fragment elements to avoid double-application of childProps (since fragments explicitly forward childProps to their children).

Scope (__INLINE_CODE_48__)

__INLINE_CODE_49__

Creates the scope for an element with prototype-chain inheritance:

__CODE_BLOCK_3__

Behavior:

  • No own scope — element inherits __INLINE_CODE_50__ directly (same reference)
  • Own scope defined (__INLINE_CODE_51__) — prototype is set to parent's scope, chaining up to __INLINE_CODE_52__
  • No parent/root scope — new scope created with __INLINE_CODE_53__
  • No context — plain __INLINE_CODE_54__
__INLINE_CODE_55__

Automatically initialized as __INLINE_CODE_56__ if context exists. Sits at the bottom of every scope prototype chain, making its properties accessible from any element via __INLINE_CODE_57__.

__CODE_BLOCK_4__

When a component defines its own scope, properties shadow parent/global values but the chain remains walkable:

__CODE_BLOCK_5__

Key Sets (__INLINE_CODE_58__)

  • __INLINE_CODE_59__ — Framework-level keys that stay at element root
  • __INLINE_CODE_60__ — Keys on the props prototype (update, __element)
  • __INLINE_CODE_61__ — State management methods (update, parse, set, toggle, etc.)