Fix detached action redirect loops, abstract Spa_Action detection, jqhtml update

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
root
2025-12-10 23:46:50 +00:00
parent 2f2cf41139
commit 3c25b2ff80
87 changed files with 419 additions and 72 deletions

View File

@@ -1001,11 +1001,14 @@ class Spa {
const $detached = $('<div>');
// Instantiate the action on the detached element
// This triggers the full component lifecycle: on_create -> render -> on_render -> on_load -> on_ready
$detached.component(action_name, args);
// Skip render and on_ready phases - detached actions are for data extraction only
// (e.g., getting title/breadcrumbs). Running on_ready() could trigger side effects
// like Spa.dispatch() which would cause redirect loops.
const options = { skip_render_and_ready: true };
$detached.component(action_name, args, options);
const action = $detached.component();
// Wait for the action to be fully ready (including on_load completion)
// Wait for on_load to complete (data fetching)
await action.ready();
console_debug('Spa', `load_detached_action: ${action_name} ready`);

View File

@@ -78,4 +78,71 @@ class Spa_Action extends Component {
const url = this.url(params);
Spa.dispatch(url);
}
// =========================================================================
// Page Title & Breadcrumb System
// =========================================================================
/**
* Page title displayed in the header/title area
*
* Override this in every action to provide a meaningful page title.
* For entity pages, include entity details (e.g., "Contact: John Smith C001")
*
* @returns {Promise<string>} The page title
*/
async page_title() {
return '(title not set)';
}
/**
* Breadcrumb label for this action
*
* Used when this action appears as a parent in another action's breadcrumb chain.
* For entity pages (viewing a specific user, contact, etc.), return the entity name.
* For list/index pages, return the section name.
*
* Default: Returns page_title()
*
* @returns {Promise<string>} The breadcrumb label
*/
async breadcrumb_label() {
return await this.page_title();
}
/**
* Breadcrumb label when this action is the active/last crumb
*
* Use this to show a descriptive action name instead of the entity name
* when the entity name is already visible in the page title above.
*
* Example: For a user profile view page:
* - page_title() = "User Profile: John Smith U001"
* - breadcrumb_label() = "John Smith" (for when it's a parent)
* - breadcrumb_label_active() = "View User Profile" (avoids redundancy with title)
*
* Default: Returns breadcrumb_label()
*
* @returns {Promise<string>} The active breadcrumb label
*/
async breadcrumb_label_active() {
return await this.breadcrumb_label();
}
/**
* Parent action URL for breadcrumb chain
*
* Return the URL of the parent action using Rsx.Route().
* Return null if this action is a root (no parent breadcrumb).
*
* Example:
* async breadcrumb_parent() {
* return Rsx.Route('Settings_Users_Action');
* }
*
* @returns {Promise<string|null>} Parent URL or null if root
*/
async breadcrumb_parent() {
return null;
}
}

View File

@@ -350,6 +350,38 @@ PERFORMANCE CONSIDERATIONS
Excessive decorator usage can increase bundle size.
Consider if simple function calls would be more appropriate.
DECORATOR PARAMETER RESTRICTIONS
Class Name Identifiers Prohibited (JS-DECORATOR-IDENT-01):
Decorator parameters MUST NOT use class name identifiers (bare class
references). The framework cannot guarantee class definition order in
compiled bundle output, so referencing a class in a decorator parameter
may fail if that class hasn't been defined yet.
// WRONG - class identifier as parameter
@some_decorator(User_Model)
class My_Action extends Spa_Action { }
// CORRECT - use string literal instead
@some_decorator('User_Model')
class My_Action extends Spa_Action { }
Why This Matters:
Bundle compilation orders classes based on inheritance hierarchies
(extends chains) and other factors, but NOT based on decorator
parameter dependencies. If Class A's decorator references Class B,
there's no guarantee Class B will be defined before Class A's
decorator is evaluated.
Resolution:
Pass class names as strings and resolve at runtime if needed:
// In decorator implementation or consuming code
const cls = Manifest.get_class_by_name('User_Model');
Enforcement:
This restriction is enforced by the JS-DECORATOR-IDENT-01 code quality
rule, which runs at manifest build time for immediate feedback.
SEE ALSO
bundle_api - Bundle loading and compilation
manifest_api - Build-time validation system

View File

@@ -779,6 +779,54 @@ COMMON PATTERNS
@layout('Frontend_Layout')
class Frontend_Contacts_Action extends Spa_Action { }
DETACHED ACTION LOADING
Spa.load_detached_action() loads an action without affecting the live SPA state.
The action is instantiated on a detached DOM element, runs its full lifecycle
(including on_load), and returns the component instance for inspection.
Use cases:
- Extracting action metadata (titles, breadcrumbs) for navigation UI
- Pre-fetching action data before navigation
- Inspecting action state without rendering it visibly
Basic Usage:
const action = await Spa.load_detached_action('/contacts/123');
if (action) {
const title = action.get_title?.() ?? action.constructor.name;
const breadcrumbs = action.get_breadcrumbs?.();
console.log('Page title:', title);
// IMPORTANT: Clean up when done to prevent memory leaks
action.stop();
}
With Cached Data:
// Skip network request if cached data available
const action = await Spa.load_detached_action('/contacts/123', {
use_cached_data: true
});
Extra Arguments:
// Pass additional args merged with URL-extracted params
const action = await Spa.load_detached_action('/contacts/123', {
some_option: true,
use_cached_data: true
});
What It Does NOT Affect:
- Spa.action (current live action remains unchanged)
- Spa.layout (current live layout remains unchanged)
- Spa.route / Spa.params (current route state unchanged)
- Browser history
- The visible DOM
Returns:
- Fully-initialized Spa_Action instance if route matches
- null if no route matches the URL
IMPORTANT: The caller MUST call action.stop() when done with the detached
action to clean up event listeners and prevent memory leaks.
SEE ALSO
controller(3) - Controller patterns and Ajax endpoints
jqhtml(3) - Component lifecycle and templates

18
node_modules/.package-lock.json generated vendored
View File

@@ -2211,9 +2211,9 @@
}
},
"node_modules/@jqhtml/core": {
"version": "2.3.14",
"resolved": "http://privatenpm.hanson.xyz/@jqhtml/core/-/core-2.3.14.tgz",
"integrity": "sha512-hJkCDrFhE1RnCCu0dG2wl+DqOzOZ92TRz93VlVjkgX+wu6muM0knbM5lsLnK9LD6n6nT13u5pvQEl1DVQVQRLg==",
"version": "2.3.15",
"resolved": "http://privatenpm.hanson.xyz/@jqhtml/core/-/core-2.3.15.tgz",
"integrity": "sha512-Up20LBvvrMro9R6vVM8qUJIZDjzpUdkBbh+etOnJaCMKQ87figdVr9OuqWT4ua2Rd9wM6fp/VLKX0/+wHQ0pEQ==",
"license": "MIT",
"dependencies": {
"@rollup/plugin-node-resolve": "^16.0.1",
@@ -2237,9 +2237,9 @@
}
},
"node_modules/@jqhtml/parser": {
"version": "2.3.14",
"resolved": "http://privatenpm.hanson.xyz/@jqhtml/parser/-/parser-2.3.14.tgz",
"integrity": "sha512-WMpYG1pagvopbLg2dUAc94C62oiyQ2rPhAl4lPcCxL6VDOFeeCBzjdqx/40oie551y/yiCcrd2nr3YeXDh2bnw==",
"version": "2.3.15",
"resolved": "http://privatenpm.hanson.xyz/@jqhtml/parser/-/parser-2.3.15.tgz",
"integrity": "sha512-4Uyhp+5gtg/a73aucCgNCzop7AqS1OsCvuYrWs1ia+lLopyFeJNUUNVX3zcbUARq/49HdZ7Ima8/qdKOjTllAw==",
"license": "MIT",
"dependencies": {
"@types/jest": "^29.5.11",
@@ -2277,9 +2277,9 @@
}
},
"node_modules/@jqhtml/vscode-extension": {
"version": "2.3.14",
"resolved": "http://privatenpm.hanson.xyz/@jqhtml/vscode-extension/-/vscode-extension-2.3.14.tgz",
"integrity": "sha512-I0Z83JBB3b2RQYs/KQ8FNTpuvsvgH15MvByMvEsffGRCnEr3ehX4BCxWizjaIrpqPzakQjIZQSe1KW9mNbmGfw==",
"version": "2.3.15",
"resolved": "http://privatenpm.hanson.xyz/@jqhtml/vscode-extension/-/vscode-extension-2.3.15.tgz",
"integrity": "sha512-YmqKUcevVcHOchQHP5OGcmEaY9wlTdwjnrDXeiWLluMzikkgPllVMgWA7tw0hOWAPSWp/eGMGVr1k549G4ErBA==",
"license": "MIT",
"engines": {
"vscode": "^1.74.0"

0
node_modules/@jqhtml/core/dist/boot.d.ts generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/core/dist/boot.d.ts.map generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/core/dist/component-registry.d.ts generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/core/dist/component-registry.d.ts.map generated vendored Normal file → Executable file
View File

2
node_modules/@jqhtml/core/dist/component.d.ts generated vendored Normal file → Executable file
View File

@@ -51,6 +51,8 @@ export declare class Jqhtml_Component {
private _is_dynamic;
private _on_render_complete;
private _use_cached_data_hit;
private _skip_render_and_ready;
private _skip_ready;
constructor(element?: any, args?: Record<string, any>);
/**
* Protect lifecycle methods from manual invocation

2
node_modules/@jqhtml/core/dist/component.d.ts.map generated vendored Normal file → Executable file
View File

@@ -1 +1 @@
{"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../src/component.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../src/component.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAcH,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,YAAY,CAAC,EAAE;YACb,GAAG,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,KAAK,IAAI,CAAC;YACjF,UAAU,EAAE,MAAM,IAAI,CAAC;SACxB,CAAC;KACH;CACF;AAED,qBAAa,gBAAgB;IAE3B,MAAM,CAAC,kBAAkB,UAAQ;IACjC,MAAM,CAAC,QAAQ,CAAC,EAAE,GAAG,CAAC;IAGtB,CAAC,EAAE,GAAG,CAAC;IACP,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAK;IAGzB,OAAO,CAAC,kBAAkB,CAAmB;IAC7C,OAAO,CAAC,aAAa,CAAiC;IACtD,OAAO,CAAC,WAAW,CAAiC;IACpD,OAAO,CAAC,aAAa,CAAoC;IACzD,OAAO,CAAC,iBAAiB,CAAkB;IAC3C,OAAO,CAAC,QAAQ,CAAkB;IAClC,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,mBAAmB,CAAuB;IAClD,OAAO,CAAC,oBAAoB,CAAwE;IACpG,OAAO,CAAC,iBAAiB,CAA0B;IACnD,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,iBAAiB,CAAkB;IAC3C,OAAO,CAAC,aAAa,CAAa;IAClC,OAAO,CAAC,oBAAoB,CAAoC;IAChE,OAAO,CAAC,oBAAoB,CAAuB;IACnD,OAAO,CAAC,uBAAuB,CAAoC;IACnE,OAAO,CAAC,aAAa,CAAkB;IACvC,OAAO,CAAC,iBAAiB,CAAC,CAAsB;IAChD,OAAO,CAAC,yBAAyB,CAAwB;IACzD,OAAO,CAAC,sBAAsB,CAAkB;IAGhD,OAAO,CAAC,UAAU,CAAuB;IAGzC,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,iBAAiB,CAAkB;IAC3C,OAAO,CAAC,8BAA8B,CAAkB;IACxD,OAAO,CAAC,WAAW,CAAkB;IAGrC,OAAO,CAAC,mBAAmB,CAAkB;IAG7C,OAAO,CAAC,oBAAoB,CAAkB;IAI9C,OAAO,CAAC,sBAAsB,CAAkB;IAIhD,OAAO,CAAC,WAAW,CAAkB;gBAEzB,OAAO,CAAC,EAAE,GAAG,EAAE,IAAI,GAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM;IAsJzD;;;;OAIG;IACH,OAAO,CAAC,0BAA0B;IAmClC;;;;;;OAMG;YACW,eAAe;IAO7B;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IAO5B;;;OAGG;IACH;;;OAGG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAe5B;;;;;;;;OAQG;IACH,OAAO,CAAC,EAAE,GAAE,MAAM,GAAG,IAAW,GAAG,MAAM;IA0UzC;;;;;;;;;;;;OAYG;IACH,MAAM,CAAC,EAAE,GAAE,MAAM,GAAG,IAAW,GAAG,IAAI;IA+CtC;;;OAGG;IACH,MAAM,CAAC,EAAE,GAAE,MAAM,GAAG,IAAW,GAAG,IAAI;IAItC;;;OAGG;IACG,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAsJ7B;;;;;OAKG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA0U5B;;;;OAIG;IACG,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAwD7B;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,KAAK,CAAC,QAAQ,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAgB3C;;;;OAIG;YACW,wBAAwB;IAqCtC;;;;;;;;;;OAUG;YACW,4BAA4B;IAqC1C;;;;;;;;OAQG;IACG,MAAM,CAAC,aAAa,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAsBpD;;;;;;;;OAQG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAI9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAiCG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAmO9B;;;;OAIG;IACH;;;;OAIG;IACH,KAAK,IAAI,IAAI;IA+Cb;;;OAGG;IACH,IAAI,IAAI,IAAI;IAkBZ,SAAS,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IACjC,SAAS,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAC3B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IACxB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAC/B,OAAO,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAE/B;;;;;;;;;OASG;IACH,QAAQ,CAAC,IAAI,MAAM;IAEnB;;;;OAIG;IACH;;;OAGG;IACH,gBAAgB,IAAI,OAAO;IA6B3B;;OAEG;IACH,cAAc,IAAI,MAAM;IAIxB;;;;;;OAMG;IACH,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,SAAS,EAAE,gBAAgB,KAAK,IAAI,GAAG,IAAI;IAsB7E;;;OAGG;IACH,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAiBjC;;;OAGG;IACH,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO;IAK3C;;;;;;;;;;;;;;;OAeG;IACH,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,GAAG;IAgB3B;;;;;;;;;;;;;;;OAeG;IACH,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI;IAgB9C;;;OAGG;IACH,YAAY,IAAI,gBAAgB,GAAG,IAAI;IAIvC;;OAEG;IACH,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,EAAE;IAa1C;;OAEG;IACH,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI;IAoBlD;;OAEG;IACH,MAAM,CAAC,mBAAmB,IAAI,MAAM,EAAE;IA0CtC,OAAO,CAAC,aAAa;IAIrB;;;OAGG;IACH,OAAO,CAAC,qBAAqB;IAkB7B,OAAO,CAAC,kBAAkB;IA4B1B,OAAO,CAAC,yBAAyB;IAuHjC,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,mBAAmB;IAO3B,OAAO,CAAC,gBAAgB;IAcxB;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;IA+BzB,OAAO,CAAC,cAAc;IActB,OAAO,CAAC,UAAU;IAUlB;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,0BAA0B;CAqEnC"}

0
node_modules/@jqhtml/core/dist/debug-entry.d.ts generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/core/dist/debug-entry.d.ts.map generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/core/dist/debug.d.ts generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/core/dist/debug.d.ts.map generated vendored Normal file → Executable file
View File

89
node_modules/@jqhtml/core/dist/index.cjs generated vendored Normal file → Executable file
View File

@@ -32,6 +32,12 @@ class LifecycleManager {
/**
* Boot a component - run its full lifecycle
* Called when component is created
*
* Supports lifecycle skip flags:
* - skip_render_and_ready: Skip first render/on_render and skip on_ready entirely.
* Component reports ready after on_load completes.
* - skip_ready: Skip on_ready only.
* Component reports ready after on_render completes (after potential re-render from on_load).
*/
async boot_component(component) {
this.active_components.add(component);
@@ -43,18 +49,39 @@ class LifecycleManager {
return;
// Trigger create event
component.trigger('create');
// Render phase - creates DOM and child components
// Note: _render() now calls on_render() internally after DOM update
// Capture render ID to detect if another render happens before ready
let render_id = component._render();
// Check if stopped during render
if (component._stopped)
return;
// Check for skip_render_and_ready flag
const skip_render_and_ready = component._skip_render_and_ready;
const skip_ready = component._skip_ready;
let render_id;
if (skip_render_and_ready) {
// Skip the first render/on_render before on_load
// Still need to set render_id to 0 for tracking
render_id = 0;
component._render_count = 0;
}
else {
// Render phase - creates DOM and child components
// Note: _render() now calls on_render() internally after DOM update
// Capture render ID to detect if another render happens before ready
render_id = component._render();
// Check if stopped during render
if (component._stopped)
return;
}
// Load phase - may modify this.data
await component._load();
// Check if stopped during load
if (component._stopped)
return;
// If skip_render_and_ready, mark component as ready now and return
if (skip_render_and_ready) {
// Set ready state and trigger event
component._ready_state = 4;
component._update_debug_attrs();
component._log_lifecycle('ready', 'complete (skip_render_and_ready)');
component.trigger('ready');
return;
}
// If data changed during load, re-render
// Note: _render() now calls on_render() internally after DOM update
if (component._should_rerender()) {
@@ -68,6 +95,15 @@ class LifecycleManager {
if (component._render_count !== render_id) {
return; // Stale render, don't call ready
}
// If skip_ready, mark component as ready now without calling _ready()
if (skip_ready) {
// Set ready state and trigger event
component._ready_state = 4;
component._update_debug_attrs();
component._log_lifecycle('ready', 'complete (skip_ready)');
component.trigger('ready');
return;
}
// Ready phase - waits for children, then calls on_ready()
await component._ready();
// Check if stopped during ready
@@ -568,12 +604,26 @@ function process_tag_to_html(instruction, html, tagElements, components, context
*/
function process_component_to_html(instruction, html, components, context) {
const [componentName, originalProps, contentOrSlots] = instruction.comp;
// Propagate use_cached_data from parent to child if parent has it set
// This allows a parent component with use_cached_data=true to automatically
// Propagate lifecycle flags from parent to child if parent has them set
// This allows a parent component with these flags to automatically
// pass this behavior to all child components rendered in its template
let props = originalProps;
if (context.args?.use_cached_data === true && props.use_cached_data === undefined) {
props = { ...originalProps, use_cached_data: true };
const parentArgs = context.args;
// Check if we need to propagate any flags
const propagate_use_cached_data = parentArgs?.use_cached_data === true && props.use_cached_data === undefined;
const propagate_skip_render_and_ready = parentArgs?.skip_render_and_ready === true && props.skip_render_and_ready === undefined;
const propagate_skip_ready = parentArgs?.skip_ready === true && props.skip_ready === undefined;
if (propagate_use_cached_data || propagate_skip_render_and_ready || propagate_skip_ready) {
props = { ...originalProps };
if (propagate_use_cached_data) {
props.use_cached_data = true;
}
if (propagate_skip_render_and_ready) {
props.skip_render_and_ready = true;
}
if (propagate_skip_ready) {
props.skip_ready = true;
}
}
// Determine if third parameter is a function (default content) or object (named slots)
let contentFn;
@@ -1144,6 +1194,12 @@ class Jqhtml_Component {
this._on_render_complete = false; // True after on_render() has been called post-on_load
// use_cached_data feature - skip on_load() when cache hit occurs
this._use_cached_data_hit = false; // True if use_cached_data=true AND cache was used
// skip_render_and_ready feature - skip first render/on_render and on_ready entirely
// Component reports ready after on_load completes
this._skip_render_and_ready = false;
// skip_ready feature - skip on_ready only
// Component reports ready after on_render completes
this._skip_ready = false;
this._cid = this._generate_cid();
this._lifecycle_manager = LifecycleManager.get_instance();
// Create or wrap element
@@ -1181,6 +1237,13 @@ class Jqhtml_Component {
// Merge in order: defineArgs (defaults from Define tag) < dataAttrs < args (invocation overrides)
const defineArgs = template_for_args?.defineArgs || {};
this.args = { ...defineArgs, ...dataAttrs, ...args };
// Set lifecycle skip flags from args
if (this.args.skip_render_and_ready === true) {
this._skip_render_and_ready = true;
}
if (this.args.skip_ready === true) {
this._skip_ready = true;
}
// Attach component to element
this.$.data('_component', this);
// Apply CSS classes and attributes
@@ -4485,7 +4548,7 @@ class Load_Coordinator {
continue; // Skip internal properties
}
// Skip framework properties that shouldn't affect cache identity
if (key === 'use_cached_data') {
if (key === 'use_cached_data' || key === 'skip_render_and_ready' || key === 'skip_ready') {
continue;
}
const value = args[key];
@@ -4704,7 +4767,7 @@ function init(jQuery) {
}
}
// Version - will be replaced during build with actual version from package.json
const version = '2.3.14';
const version = '2.3.15';
// Default export with all functionality
const jqhtml = {
// Core

2
node_modules/@jqhtml/core/dist/index.cjs.map generated vendored Normal file → Executable file

File diff suppressed because one or more lines are too long

0
node_modules/@jqhtml/core/dist/index.d.ts generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/core/dist/index.d.ts.map generated vendored Normal file → Executable file
View File

89
node_modules/@jqhtml/core/dist/index.js generated vendored Normal file → Executable file
View File

@@ -28,6 +28,12 @@ class LifecycleManager {
/**
* Boot a component - run its full lifecycle
* Called when component is created
*
* Supports lifecycle skip flags:
* - skip_render_and_ready: Skip first render/on_render and skip on_ready entirely.
* Component reports ready after on_load completes.
* - skip_ready: Skip on_ready only.
* Component reports ready after on_render completes (after potential re-render from on_load).
*/
async boot_component(component) {
this.active_components.add(component);
@@ -39,18 +45,39 @@ class LifecycleManager {
return;
// Trigger create event
component.trigger('create');
// Render phase - creates DOM and child components
// Note: _render() now calls on_render() internally after DOM update
// Capture render ID to detect if another render happens before ready
let render_id = component._render();
// Check if stopped during render
if (component._stopped)
return;
// Check for skip_render_and_ready flag
const skip_render_and_ready = component._skip_render_and_ready;
const skip_ready = component._skip_ready;
let render_id;
if (skip_render_and_ready) {
// Skip the first render/on_render before on_load
// Still need to set render_id to 0 for tracking
render_id = 0;
component._render_count = 0;
}
else {
// Render phase - creates DOM and child components
// Note: _render() now calls on_render() internally after DOM update
// Capture render ID to detect if another render happens before ready
render_id = component._render();
// Check if stopped during render
if (component._stopped)
return;
}
// Load phase - may modify this.data
await component._load();
// Check if stopped during load
if (component._stopped)
return;
// If skip_render_and_ready, mark component as ready now and return
if (skip_render_and_ready) {
// Set ready state and trigger event
component._ready_state = 4;
component._update_debug_attrs();
component._log_lifecycle('ready', 'complete (skip_render_and_ready)');
component.trigger('ready');
return;
}
// If data changed during load, re-render
// Note: _render() now calls on_render() internally after DOM update
if (component._should_rerender()) {
@@ -64,6 +91,15 @@ class LifecycleManager {
if (component._render_count !== render_id) {
return; // Stale render, don't call ready
}
// If skip_ready, mark component as ready now without calling _ready()
if (skip_ready) {
// Set ready state and trigger event
component._ready_state = 4;
component._update_debug_attrs();
component._log_lifecycle('ready', 'complete (skip_ready)');
component.trigger('ready');
return;
}
// Ready phase - waits for children, then calls on_ready()
await component._ready();
// Check if stopped during ready
@@ -564,12 +600,26 @@ function process_tag_to_html(instruction, html, tagElements, components, context
*/
function process_component_to_html(instruction, html, components, context) {
const [componentName, originalProps, contentOrSlots] = instruction.comp;
// Propagate use_cached_data from parent to child if parent has it set
// This allows a parent component with use_cached_data=true to automatically
// Propagate lifecycle flags from parent to child if parent has them set
// This allows a parent component with these flags to automatically
// pass this behavior to all child components rendered in its template
let props = originalProps;
if (context.args?.use_cached_data === true && props.use_cached_data === undefined) {
props = { ...originalProps, use_cached_data: true };
const parentArgs = context.args;
// Check if we need to propagate any flags
const propagate_use_cached_data = parentArgs?.use_cached_data === true && props.use_cached_data === undefined;
const propagate_skip_render_and_ready = parentArgs?.skip_render_and_ready === true && props.skip_render_and_ready === undefined;
const propagate_skip_ready = parentArgs?.skip_ready === true && props.skip_ready === undefined;
if (propagate_use_cached_data || propagate_skip_render_and_ready || propagate_skip_ready) {
props = { ...originalProps };
if (propagate_use_cached_data) {
props.use_cached_data = true;
}
if (propagate_skip_render_and_ready) {
props.skip_render_and_ready = true;
}
if (propagate_skip_ready) {
props.skip_ready = true;
}
}
// Determine if third parameter is a function (default content) or object (named slots)
let contentFn;
@@ -1140,6 +1190,12 @@ class Jqhtml_Component {
this._on_render_complete = false; // True after on_render() has been called post-on_load
// use_cached_data feature - skip on_load() when cache hit occurs
this._use_cached_data_hit = false; // True if use_cached_data=true AND cache was used
// skip_render_and_ready feature - skip first render/on_render and on_ready entirely
// Component reports ready after on_load completes
this._skip_render_and_ready = false;
// skip_ready feature - skip on_ready only
// Component reports ready after on_render completes
this._skip_ready = false;
this._cid = this._generate_cid();
this._lifecycle_manager = LifecycleManager.get_instance();
// Create or wrap element
@@ -1177,6 +1233,13 @@ class Jqhtml_Component {
// Merge in order: defineArgs (defaults from Define tag) < dataAttrs < args (invocation overrides)
const defineArgs = template_for_args?.defineArgs || {};
this.args = { ...defineArgs, ...dataAttrs, ...args };
// Set lifecycle skip flags from args
if (this.args.skip_render_and_ready === true) {
this._skip_render_and_ready = true;
}
if (this.args.skip_ready === true) {
this._skip_ready = true;
}
// Attach component to element
this.$.data('_component', this);
// Apply CSS classes and attributes
@@ -4481,7 +4544,7 @@ class Load_Coordinator {
continue; // Skip internal properties
}
// Skip framework properties that shouldn't affect cache identity
if (key === 'use_cached_data') {
if (key === 'use_cached_data' || key === 'skip_render_and_ready' || key === 'skip_ready') {
continue;
}
const value = args[key];
@@ -4700,7 +4763,7 @@ function init(jQuery) {
}
}
// Version - will be replaced during build with actual version from package.json
const version = '2.3.14';
const version = '2.3.15';
// Default export with all functionality
const jqhtml = {
// Core

2
node_modules/@jqhtml/core/dist/index.js.map generated vendored Normal file → Executable file

File diff suppressed because one or more lines are too long

0
node_modules/@jqhtml/core/dist/instruction-processor.d.ts generated vendored Normal file → Executable file
View File

2
node_modules/@jqhtml/core/dist/instruction-processor.d.ts.map generated vendored Normal file → Executable file
View File

@@ -1 +1 @@
{"version":3,"file":"instruction-processor.d.ts","sourceRoot":"","sources":["../src/instruction-processor.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAIlD,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;CAC7C;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC;CAC/C;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,GAAG,KAAK,CAAC,GAAG,EAAE,EAAE,gBAAgB,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,CAAC,GAAG,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAC;CAClL;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,CAAC,GAAG,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC;CAClF;AAED,MAAM,MAAM,WAAW,GAAG,cAAc,GAAG,iBAAiB,GAAG,oBAAoB,GAAG,eAAe,GAAG,MAAM,CAAC;AAqB/G,wBAAgB,GAAG,IAAI,MAAM,CA2C5B;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,YAAY,EAAE,WAAW,EAAE,EAC3B,MAAM,EAAE,GAAG,EACX,OAAO,EAAE,gBAAgB,EACzB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,GACtC,IAAI,CAwCN;AAsdD;;GAEG;AACH,wBAAgB,aAAa,CAAC,YAAY,EAAE,WAAW,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAW1F"}
{"version":3,"file":"instruction-processor.d.ts","sourceRoot":"","sources":["../src/instruction-processor.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAIlD,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;CAC7C;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC;CAC/C;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,GAAG,KAAK,CAAC,GAAG,EAAE,EAAE,gBAAgB,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,CAAC,GAAG,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAC;CAClL;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,CAAC,GAAG,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC;CAClF;AAED,MAAM,MAAM,WAAW,GAAG,cAAc,GAAG,iBAAiB,GAAG,oBAAoB,GAAG,eAAe,GAAG,MAAM,CAAC;AAqB/G,wBAAgB,GAAG,IAAI,MAAM,CA2C5B;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,YAAY,EAAE,WAAW,EAAE,EAC3B,MAAM,EAAE,GAAG,EACX,OAAO,EAAE,gBAAgB,EACzB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,GACtC,IAAI,CAwCN;AAseD;;GAEG;AACH,wBAAgB,aAAa,CAAC,YAAY,EAAE,WAAW,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAW1F"}

91
node_modules/@jqhtml/core/dist/jqhtml-core.esm.js generated vendored Normal file → Executable file
View File

@@ -1,5 +1,5 @@
/**
* JQHTML Core v2.3.14
* JQHTML Core v2.3.15
* (c) 2025 JQHTML Team
* Released under the MIT License
*/
@@ -33,6 +33,12 @@ class LifecycleManager {
/**
* Boot a component - run its full lifecycle
* Called when component is created
*
* Supports lifecycle skip flags:
* - skip_render_and_ready: Skip first render/on_render and skip on_ready entirely.
* Component reports ready after on_load completes.
* - skip_ready: Skip on_ready only.
* Component reports ready after on_render completes (after potential re-render from on_load).
*/
async boot_component(component) {
this.active_components.add(component);
@@ -44,18 +50,39 @@ class LifecycleManager {
return;
// Trigger create event
component.trigger('create');
// Render phase - creates DOM and child components
// Note: _render() now calls on_render() internally after DOM update
// Capture render ID to detect if another render happens before ready
let render_id = component._render();
// Check if stopped during render
if (component._stopped)
return;
// Check for skip_render_and_ready flag
const skip_render_and_ready = component._skip_render_and_ready;
const skip_ready = component._skip_ready;
let render_id;
if (skip_render_and_ready) {
// Skip the first render/on_render before on_load
// Still need to set render_id to 0 for tracking
render_id = 0;
component._render_count = 0;
}
else {
// Render phase - creates DOM and child components
// Note: _render() now calls on_render() internally after DOM update
// Capture render ID to detect if another render happens before ready
render_id = component._render();
// Check if stopped during render
if (component._stopped)
return;
}
// Load phase - may modify this.data
await component._load();
// Check if stopped during load
if (component._stopped)
return;
// If skip_render_and_ready, mark component as ready now and return
if (skip_render_and_ready) {
// Set ready state and trigger event
component._ready_state = 4;
component._update_debug_attrs();
component._log_lifecycle('ready', 'complete (skip_render_and_ready)');
component.trigger('ready');
return;
}
// If data changed during load, re-render
// Note: _render() now calls on_render() internally after DOM update
if (component._should_rerender()) {
@@ -69,6 +96,15 @@ class LifecycleManager {
if (component._render_count !== render_id) {
return; // Stale render, don't call ready
}
// If skip_ready, mark component as ready now without calling _ready()
if (skip_ready) {
// Set ready state and trigger event
component._ready_state = 4;
component._update_debug_attrs();
component._log_lifecycle('ready', 'complete (skip_ready)');
component.trigger('ready');
return;
}
// Ready phase - waits for children, then calls on_ready()
await component._ready();
// Check if stopped during ready
@@ -569,12 +605,26 @@ function process_tag_to_html(instruction, html, tagElements, components, context
*/
function process_component_to_html(instruction, html, components, context) {
const [componentName, originalProps, contentOrSlots] = instruction.comp;
// Propagate use_cached_data from parent to child if parent has it set
// This allows a parent component with use_cached_data=true to automatically
// Propagate lifecycle flags from parent to child if parent has them set
// This allows a parent component with these flags to automatically
// pass this behavior to all child components rendered in its template
let props = originalProps;
if (context.args?.use_cached_data === true && props.use_cached_data === undefined) {
props = { ...originalProps, use_cached_data: true };
const parentArgs = context.args;
// Check if we need to propagate any flags
const propagate_use_cached_data = parentArgs?.use_cached_data === true && props.use_cached_data === undefined;
const propagate_skip_render_and_ready = parentArgs?.skip_render_and_ready === true && props.skip_render_and_ready === undefined;
const propagate_skip_ready = parentArgs?.skip_ready === true && props.skip_ready === undefined;
if (propagate_use_cached_data || propagate_skip_render_and_ready || propagate_skip_ready) {
props = { ...originalProps };
if (propagate_use_cached_data) {
props.use_cached_data = true;
}
if (propagate_skip_render_and_ready) {
props.skip_render_and_ready = true;
}
if (propagate_skip_ready) {
props.skip_ready = true;
}
}
// Determine if third parameter is a function (default content) or object (named slots)
let contentFn;
@@ -1145,6 +1195,12 @@ class Jqhtml_Component {
this._on_render_complete = false; // True after on_render() has been called post-on_load
// use_cached_data feature - skip on_load() when cache hit occurs
this._use_cached_data_hit = false; // True if use_cached_data=true AND cache was used
// skip_render_and_ready feature - skip first render/on_render and on_ready entirely
// Component reports ready after on_load completes
this._skip_render_and_ready = false;
// skip_ready feature - skip on_ready only
// Component reports ready after on_render completes
this._skip_ready = false;
this._cid = this._generate_cid();
this._lifecycle_manager = LifecycleManager.get_instance();
// Create or wrap element
@@ -1182,6 +1238,13 @@ class Jqhtml_Component {
// Merge in order: defineArgs (defaults from Define tag) < dataAttrs < args (invocation overrides)
const defineArgs = template_for_args?.defineArgs || {};
this.args = { ...defineArgs, ...dataAttrs, ...args };
// Set lifecycle skip flags from args
if (this.args.skip_render_and_ready === true) {
this._skip_render_and_ready = true;
}
if (this.args.skip_ready === true) {
this._skip_ready = true;
}
// Attach component to element
this.$.data('_component', this);
// Apply CSS classes and attributes
@@ -4486,7 +4549,7 @@ class Load_Coordinator {
continue; // Skip internal properties
}
// Skip framework properties that shouldn't affect cache identity
if (key === 'use_cached_data') {
if (key === 'use_cached_data' || key === 'skip_render_and_ready' || key === 'skip_ready') {
continue;
}
const value = args[key];
@@ -4705,7 +4768,7 @@ function init(jQuery) {
}
}
// Version - will be replaced during build with actual version from package.json
const version = '2.3.14';
const version = '2.3.15';
// Default export with all functionality
const jqhtml = {
// Core

2
node_modules/@jqhtml/core/dist/jqhtml-core.esm.js.map generated vendored Normal file → Executable file

File diff suppressed because one or more lines are too long

0
node_modules/@jqhtml/core/dist/jqhtml-debug.esm.js generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/core/dist/jqhtml-debug.esm.js.map generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/core/dist/jquery-plugin.d.ts generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/core/dist/jquery-plugin.d.ts.map generated vendored Normal file → Executable file
View File

6
node_modules/@jqhtml/core/dist/lifecycle-manager.d.ts generated vendored Normal file → Executable file
View File

@@ -20,6 +20,12 @@ export declare class LifecycleManager {
/**
* Boot a component - run its full lifecycle
* Called when component is created
*
* Supports lifecycle skip flags:
* - skip_render_and_ready: Skip first render/on_render and skip on_ready entirely.
* Component reports ready after on_load completes.
* - skip_ready: Skip on_ready only.
* Component reports ready after on_render completes (after potential re-render from on_load).
*/
boot_component(component: Jqhtml_Component): Promise<void>;
/**

2
node_modules/@jqhtml/core/dist/lifecycle-manager.d.ts.map generated vendored Normal file → Executable file
View File

@@ -1 +1 @@
{"version":3,"file":"lifecycle-manager.d.ts","sourceRoot":"","sources":["../src/lifecycle-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEvD,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;AAEpE,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAmB;IAC1C,OAAO,CAAC,iBAAiB,CAAoC;IAE7D,MAAM,CAAC,YAAY,IAAI,gBAAgB;;IAevC;;;OAGG;IACG,cAAc,CAAC,SAAS,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAsDhE;;OAEG;IACH,oBAAoB,CAAC,SAAS,EAAE,gBAAgB,GAAG,IAAI;IAIvD;;OAEG;IACG,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;CAetC"}
{"version":3,"file":"lifecycle-manager.d.ts","sourceRoot":"","sources":["../src/lifecycle-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEvD,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;AAEpE,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAmB;IAC1C,OAAO,CAAC,iBAAiB,CAAoC;IAE7D,MAAM,CAAC,YAAY,IAAI,gBAAgB;;IAevC;;;;;;;;;OASG;IACG,cAAc,CAAC,SAAS,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAuFhE;;OAEG;IACH,oBAAoB,CAAC,SAAS,EAAE,gBAAgB,GAAG,IAAI;IAIvD;;OAEG;IACG,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;CAetC"}

0
node_modules/@jqhtml/core/dist/load-coordinator.d.ts generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/core/dist/load-coordinator.d.ts.map generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/core/dist/local-storage.d.ts generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/core/dist/local-storage.d.ts.map generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/core/dist/template-renderer.d.ts generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/core/dist/template-renderer.d.ts.map generated vendored Normal file → Executable file
View File

2
node_modules/@jqhtml/core/package.json generated vendored Normal file → Executable file
View File

@@ -1,6 +1,6 @@
{
"name": "@jqhtml/core",
"version": "2.3.14",
"version": "2.3.15",
"description": "Core runtime library for JQHTML",
"type": "module",
"main": "./dist/index.js",

0
node_modules/@jqhtml/parser/dist/ast.d.ts generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/parser/dist/ast.d.ts.map generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/parser/dist/ast.js generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/parser/dist/ast.js.map generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/parser/dist/codegen.d.ts generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/parser/dist/codegen.d.ts.map generated vendored Normal file → Executable file
View File

2
node_modules/@jqhtml/parser/dist/codegen.js generated vendored Normal file → Executable file
View File

@@ -1377,7 +1377,7 @@ export class CodeGenerator {
for (const [name, component] of this.components) {
code += `// Component: ${name}\n`;
code += `jqhtml_components.set('${name}', {\n`;
code += ` _jqhtml_version: '2.3.14',\n`; // Version will be replaced during build
code += ` _jqhtml_version: '2.3.15',\n`; // Version will be replaced during build
code += ` name: '${name}',\n`;
code += ` tag: '${component.tagName}',\n`;
code += ` defaultAttributes: ${this.serializeAttributeObject(component.defaultAttributes)},\n`;

0
node_modules/@jqhtml/parser/dist/codegen.js.map generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/parser/dist/compiler.d.ts generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/parser/dist/compiler.d.ts.map generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/parser/dist/compiler.js generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/parser/dist/compiler.js.map generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/parser/dist/errors.d.ts generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/parser/dist/errors.d.ts.map generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/parser/dist/errors.js generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/parser/dist/errors.js.map generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/parser/dist/index.d.ts generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/parser/dist/index.d.ts.map generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/parser/dist/index.js generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/parser/dist/index.js.map generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/parser/dist/integration.d.ts generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/parser/dist/integration.d.ts.map generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/parser/dist/integration.js generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/parser/dist/integration.js.map generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/parser/dist/lexer.d.ts generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/parser/dist/lexer.d.ts.map generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/parser/dist/lexer.js generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/parser/dist/lexer.js.map generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/parser/dist/parser.d.ts generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/parser/dist/parser.d.ts.map generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/parser/dist/parser.js generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/parser/dist/parser.js.map generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/parser/dist/runtime.d.ts generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/parser/dist/runtime.d.ts.map generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/parser/dist/runtime.js generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/parser/dist/runtime.js.map generated vendored Normal file → Executable file
View File

2
node_modules/@jqhtml/parser/package.json generated vendored Normal file → Executable file
View File

@@ -1,6 +1,6 @@
{
"name": "@jqhtml/parser",
"version": "2.3.14",
"version": "2.3.15",
"description": "JQHTML template parser - converts templates to JavaScript",
"type": "module",
"main": "dist/index.js",

View File

@@ -1 +1 @@
2.3.14
2.3.15

0
node_modules/@jqhtml/vscode-extension/blade-language-configuration.json generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/vscode-extension/out/blade_component_provider.js generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/vscode-extension/out/blade_component_provider.js.map generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/vscode-extension/out/blade_language_config.js generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/vscode-extension/out/blade_language_config.js.map generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/vscode-extension/out/blade_spacer.js generated vendored Normal file → Executable file
View File

0
node_modules/@jqhtml/vscode-extension/out/blade_spacer.js.map generated vendored Normal file → Executable file
View File

2
node_modules/@jqhtml/vscode-extension/package.json generated vendored Normal file → Executable file
View File

@@ -2,7 +2,7 @@
"name": "@jqhtml/vscode-extension",
"displayName": "JQHTML",
"description": "Syntax highlighting and language support for JQHTML template files",
"version": "2.3.14",
"version": "2.3.15",
"publisher": "jqhtml",
"license": "MIT",
"publishConfig": {

0
node_modules/@jqhtml/vscode-extension/syntaxes/blade-jqhtml.tmLanguage.json generated vendored Normal file → Executable file
View File

18
package-lock.json generated
View File

@@ -2658,9 +2658,9 @@
}
},
"node_modules/@jqhtml/core": {
"version": "2.3.14",
"resolved": "http://privatenpm.hanson.xyz/@jqhtml/core/-/core-2.3.14.tgz",
"integrity": "sha512-hJkCDrFhE1RnCCu0dG2wl+DqOzOZ92TRz93VlVjkgX+wu6muM0knbM5lsLnK9LD6n6nT13u5pvQEl1DVQVQRLg==",
"version": "2.3.15",
"resolved": "http://privatenpm.hanson.xyz/@jqhtml/core/-/core-2.3.15.tgz",
"integrity": "sha512-Up20LBvvrMro9R6vVM8qUJIZDjzpUdkBbh+etOnJaCMKQ87figdVr9OuqWT4ua2Rd9wM6fp/VLKX0/+wHQ0pEQ==",
"license": "MIT",
"dependencies": {
"@rollup/plugin-node-resolve": "^16.0.1",
@@ -2684,9 +2684,9 @@
}
},
"node_modules/@jqhtml/parser": {
"version": "2.3.14",
"resolved": "http://privatenpm.hanson.xyz/@jqhtml/parser/-/parser-2.3.14.tgz",
"integrity": "sha512-WMpYG1pagvopbLg2dUAc94C62oiyQ2rPhAl4lPcCxL6VDOFeeCBzjdqx/40oie551y/yiCcrd2nr3YeXDh2bnw==",
"version": "2.3.15",
"resolved": "http://privatenpm.hanson.xyz/@jqhtml/parser/-/parser-2.3.15.tgz",
"integrity": "sha512-4Uyhp+5gtg/a73aucCgNCzop7AqS1OsCvuYrWs1ia+lLopyFeJNUUNVX3zcbUARq/49HdZ7Ima8/qdKOjTllAw==",
"license": "MIT",
"dependencies": {
"@types/jest": "^29.5.11",
@@ -2724,9 +2724,9 @@
}
},
"node_modules/@jqhtml/vscode-extension": {
"version": "2.3.14",
"resolved": "http://privatenpm.hanson.xyz/@jqhtml/vscode-extension/-/vscode-extension-2.3.14.tgz",
"integrity": "sha512-I0Z83JBB3b2RQYs/KQ8FNTpuvsvgH15MvByMvEsffGRCnEr3ehX4BCxWizjaIrpqPzakQjIZQSe1KW9mNbmGfw==",
"version": "2.3.15",
"resolved": "http://privatenpm.hanson.xyz/@jqhtml/vscode-extension/-/vscode-extension-2.3.15.tgz",
"integrity": "sha512-YmqKUcevVcHOchQHP5OGcmEaY9wlTdwjnrDXeiWLluMzikkgPllVMgWA7tw0hOWAPSWp/eGMGVr1k549G4ErBA==",
"license": "MIT",
"engines": {
"vscode": "^1.74.0"