@jqhtml/core 2.2.222
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +24 -0
- package/dist/component-registry.d.ts +64 -0
- package/dist/component-registry.d.ts.map +1 -0
- package/dist/component.d.ts +336 -0
- package/dist/component.d.ts.map +1 -0
- package/dist/debug-entry.d.ts +36 -0
- package/dist/debug-entry.d.ts.map +1 -0
- package/dist/debug-overlay.d.ts +61 -0
- package/dist/debug-overlay.d.ts.map +1 -0
- package/dist/debug.d.ts +19 -0
- package/dist/debug.d.ts.map +1 -0
- package/dist/index.cjs +4384 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +91 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4347 -0
- package/dist/index.js.map +1 -0
- package/dist/instruction-processor.d.ts +31 -0
- package/dist/instruction-processor.d.ts.map +1 -0
- package/dist/jqhtml-core.esm.js +4352 -0
- package/dist/jqhtml-core.esm.js.map +1 -0
- package/dist/jqhtml-debug.esm.js +575 -0
- package/dist/jqhtml-debug.esm.js.map +1 -0
- package/dist/jquery-plugin.d.ts +30 -0
- package/dist/jquery-plugin.d.ts.map +1 -0
- package/dist/lifecycle-manager.d.ts +34 -0
- package/dist/lifecycle-manager.d.ts.map +1 -0
- package/dist/load-coordinator.d.ts +79 -0
- package/dist/load-coordinator.d.ts.map +1 -0
- package/dist/local-storage.d.ts +147 -0
- package/dist/local-storage.d.ts.map +1 -0
- package/dist/template-renderer.d.ts +17 -0
- package/dist/template-renderer.d.ts.map +1 -0
- package/laravel-bridge/README.md +242 -0
- package/laravel-bridge/autoload.php +51 -0
- package/laravel-bridge/composer.json +34 -0
- package/laravel-bridge/config/jqhtml.php +82 -0
- package/laravel-bridge/examples/node-integration.js +201 -0
- package/laravel-bridge/src/JqhtmlErrorFormatter.php +187 -0
- package/laravel-bridge/src/JqhtmlException.php +173 -0
- package/laravel-bridge/src/JqhtmlExceptionRenderer.php +93 -0
- package/laravel-bridge/src/JqhtmlServiceProvider.php +72 -0
- package/laravel-bridge/src/Middleware/JqhtmlErrorMiddleware.php +90 -0
- package/laravel-bridge/tests/ExceptionFormattingTest.php +219 -0
- package/package.json +74 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Load Coordinator - Request deduplication for component on_load() calls
|
|
3
|
+
*
|
|
4
|
+
* Coordinates parallel component loading to prevent duplicate requests.
|
|
5
|
+
* When multiple components with identical names and args load simultaneously,
|
|
6
|
+
* only the first (leader) executes on_load(). Others (followers) wait for
|
|
7
|
+
* the leader's result.
|
|
8
|
+
*
|
|
9
|
+
* Key Concepts:
|
|
10
|
+
* - **INVOCATION_KEY**: Unique identifier for component name + args combination
|
|
11
|
+
* - **Leader**: First component to reach on_load() for a given INVOCATION_KEY
|
|
12
|
+
* - **Follower**: Subsequent components that wait for leader's result
|
|
13
|
+
*
|
|
14
|
+
* Lifecycle:
|
|
15
|
+
* 1. Leader reaches on_load() → create coordination entry
|
|
16
|
+
* 2. Followers reach on_load() → join waiting queue
|
|
17
|
+
* 3. Leader completes → distribute data to all followers
|
|
18
|
+
* 4. Clear coordination entry (no caching)
|
|
19
|
+
*
|
|
20
|
+
* @internal This class is not exposed in the public API
|
|
21
|
+
*/
|
|
22
|
+
import type { Jqhtml_Component } from './component.js';
|
|
23
|
+
export interface InvocationKeyResult {
|
|
24
|
+
key: string | null;
|
|
25
|
+
uncacheable_property?: string;
|
|
26
|
+
}
|
|
27
|
+
export declare class Load_Coordinator {
|
|
28
|
+
private static _registry;
|
|
29
|
+
/**
|
|
30
|
+
* Generate INVOCATION_KEY from component name and args
|
|
31
|
+
* Uses deterministic JSON serialization (sorted keys)
|
|
32
|
+
* Excludes internal properties (those starting with _)
|
|
33
|
+
*
|
|
34
|
+
* For functions/objects:
|
|
35
|
+
* - Checks for ._jqhtml_cache_id property (assigned by RSpade)
|
|
36
|
+
* - Falls back to .jqhtml_cache_id() method if property doesn't exist
|
|
37
|
+
* - If neither exists, marks property as uncacheable
|
|
38
|
+
*
|
|
39
|
+
* Returns object with:
|
|
40
|
+
* - key: Cache key string, or null if uncacheable
|
|
41
|
+
* - uncacheable_property: Name of first property that prevented caching (for debugging)
|
|
42
|
+
*/
|
|
43
|
+
static generate_invocation_key(component_name: string, args: any): InvocationKeyResult;
|
|
44
|
+
/**
|
|
45
|
+
* Check if a component should execute on_load() or wait for existing request
|
|
46
|
+
* Returns true if component should execute (is leader), false if should wait (is follower)
|
|
47
|
+
*/
|
|
48
|
+
static should_execute_on_load(component: Jqhtml_Component): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Register a leader component that will execute on_load()
|
|
51
|
+
* Creates coordination entry and returns a function to call when on_load() completes
|
|
52
|
+
*/
|
|
53
|
+
static register_leader(component: Jqhtml_Component, on_load_promise: Promise<void>): () => void;
|
|
54
|
+
/**
|
|
55
|
+
* Get the coordination promise for a follower component
|
|
56
|
+
* Returns a promise that resolves when the leader completes
|
|
57
|
+
*/
|
|
58
|
+
static get_coordination_promise(component: Jqhtml_Component): Promise<void> | null;
|
|
59
|
+
/**
|
|
60
|
+
* Complete coordination after leader's on_load() finishes
|
|
61
|
+
* Distributes data to all waiting followers and cleans up entry
|
|
62
|
+
* @private
|
|
63
|
+
*/
|
|
64
|
+
private static _complete_coordination;
|
|
65
|
+
/**
|
|
66
|
+
* Handle leader on_load() error
|
|
67
|
+
* Propagates error to all followers and cleans up entry
|
|
68
|
+
*/
|
|
69
|
+
static handle_leader_error(component: Jqhtml_Component, error: Error): void;
|
|
70
|
+
/**
|
|
71
|
+
* Get current registry state (for debugging)
|
|
72
|
+
*/
|
|
73
|
+
static get_registry_state(): any;
|
|
74
|
+
/**
|
|
75
|
+
* Clear all coordination entries (for testing/debugging)
|
|
76
|
+
*/
|
|
77
|
+
static clear_all(): void;
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=load-coordinator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load-coordinator.d.ts","sourceRoot":"","sources":["../src/load-coordinator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAWvD,MAAM,WAAW,mBAAmB;IAChC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,oBAAoB,CAAC,EAAE,MAAM,CAAC;CACjC;AAED,qBAAa,gBAAgB;IACzB,OAAO,CAAC,MAAM,CAAC,SAAS,CAA6C;IAErE;;;;;;;;;;;;;OAaG;IACH,MAAM,CAAC,uBAAuB,CAAC,cAAc,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG,mBAAmB;IAqEtF;;;OAGG;IACH,MAAM,CAAC,sBAAsB,CAAC,SAAS,EAAE,gBAAgB,GAAG,OAAO;IAoBnE;;;OAGG;IACH,MAAM,CAAC,eAAe,CAClB,SAAS,EAAE,gBAAgB,EAC3B,eAAe,EAAE,OAAO,CAAC,IAAI,CAAC,GAC/B,MAAM,IAAI;IAkBb;;;OAGG;IACH,MAAM,CAAC,wBAAwB,CAAC,SAAS,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAWlF;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAC,sBAAsB;IA8CrC;;;OAGG;IACH,MAAM,CAAC,mBAAmB,CAAC,SAAS,EAAE,gBAAgB,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI;IAuC3E;;OAEG;IACH,MAAM,CAAC,kBAAkB,IAAI,GAAG;IAahC;;OAEG;IACH,MAAM,CAAC,SAAS,IAAI,IAAI;CAG3B"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Jqhtml_Local_Storage - Scoped local storage for JQHTML component caching
|
|
3
|
+
*
|
|
4
|
+
* Provides safe, scoped access to localStorage with automatic handling of
|
|
5
|
+
* unavailable storage, quota exceeded errors, and scope invalidation.
|
|
6
|
+
*
|
|
7
|
+
* Key Features:
|
|
8
|
+
* - **Manual scoping**: Cache key must be set via set_cache_key() before use
|
|
9
|
+
* - **Graceful degradation**: Returns null when storage unavailable or cache key not set
|
|
10
|
+
* - **Quota management**: Auto-clears storage when full and retries operation
|
|
11
|
+
* - **Scope validation**: Clears storage when cache key changes
|
|
12
|
+
* - **Developer-friendly keys**: Scoped suffix allows easy inspection in dev tools
|
|
13
|
+
*
|
|
14
|
+
* Scoping Strategy:
|
|
15
|
+
* Storage is scoped by a user-provided cache key (typically a session identifier,
|
|
16
|
+
* user ID, or combination of relevant scope factors). This scope is stored in
|
|
17
|
+
* `_jqhtml_cache_key`. If the cache key changes between page loads, all JQHTML
|
|
18
|
+
* storage is cleared to prevent stale data from different sessions/users.
|
|
19
|
+
*
|
|
20
|
+
* Key Format:
|
|
21
|
+
* Keys are stored as: `jqhtml::developer_key::cache_key`
|
|
22
|
+
* Example: `jqhtml::User_Profile_data::user_123`
|
|
23
|
+
*
|
|
24
|
+
* The `jqhtml::` prefix identifies JQHTML keys, allowing safe clearing of only our keys
|
|
25
|
+
* without affecting other JavaScript libraries. This enables transparent coexistence
|
|
26
|
+
* with third-party libraries that also use browser storage.
|
|
27
|
+
*
|
|
28
|
+
* Quota Exceeded Handling:
|
|
29
|
+
* When storage quota is exceeded during a set operation, only JQHTML keys (prefixed with
|
|
30
|
+
* `jqhtml::`) are cleared, preserving other libraries' data. The operation is then retried
|
|
31
|
+
* once. This ensures the application continues functioning even when storage is full.
|
|
32
|
+
*
|
|
33
|
+
* Usage:
|
|
34
|
+
* // Must set cache key first (typically done once on page load)
|
|
35
|
+
* Jqhtml_Local_Storage.set_cache_key('user_123');
|
|
36
|
+
*
|
|
37
|
+
* // Then use storage normally
|
|
38
|
+
* Jqhtml_Local_Storage.set('cached_component', {html: '...', timestamp: Date.now()});
|
|
39
|
+
* const cached = Jqhtml_Local_Storage.get('cached_component');
|
|
40
|
+
* Jqhtml_Local_Storage.remove('cached_component');
|
|
41
|
+
*
|
|
42
|
+
* IMPORTANT - Volatile Storage:
|
|
43
|
+
* Storage can be cleared at any time due to:
|
|
44
|
+
* - User clearing browser data
|
|
45
|
+
* - Private browsing mode restrictions
|
|
46
|
+
* - Quota exceeded errors
|
|
47
|
+
* - Cache key changes
|
|
48
|
+
* - Browser storage unavailable
|
|
49
|
+
*
|
|
50
|
+
* Therefore, NEVER store critical data. Only use for:
|
|
51
|
+
* - Cached component HTML (performance optimization)
|
|
52
|
+
* - Transient UI state (convenience, not required)
|
|
53
|
+
*
|
|
54
|
+
* @internal This class is not exposed in the public API
|
|
55
|
+
*/
|
|
56
|
+
export declare class Jqhtml_Local_Storage {
|
|
57
|
+
private static _cache_key;
|
|
58
|
+
private static _storage_available;
|
|
59
|
+
private static _initialized;
|
|
60
|
+
/**
|
|
61
|
+
* Set the cache key and initialize storage
|
|
62
|
+
* Must be called before any get/set operations
|
|
63
|
+
* @param {string} cache_key - Unique identifier for this cache scope
|
|
64
|
+
*/
|
|
65
|
+
static set_cache_key(cache_key: string): void;
|
|
66
|
+
/**
|
|
67
|
+
* Check if cache key has been set
|
|
68
|
+
* @returns {boolean} True if cache key is configured
|
|
69
|
+
*/
|
|
70
|
+
static has_cache_key(): boolean;
|
|
71
|
+
/**
|
|
72
|
+
* Initialize storage system and validate scope
|
|
73
|
+
* Called automatically after cache key is set
|
|
74
|
+
* @private
|
|
75
|
+
*/
|
|
76
|
+
private static _init;
|
|
77
|
+
/**
|
|
78
|
+
* Check if localStorage is available
|
|
79
|
+
* @returns {boolean}
|
|
80
|
+
* @private
|
|
81
|
+
*/
|
|
82
|
+
private static _is_storage_available;
|
|
83
|
+
/**
|
|
84
|
+
* Validate storage scope and clear JQHTML keys if cache key changed
|
|
85
|
+
* Only clears keys prefixed with 'jqhtml::' to preserve other libraries' data
|
|
86
|
+
* @private
|
|
87
|
+
*/
|
|
88
|
+
private static _validate_scope;
|
|
89
|
+
/**
|
|
90
|
+
* Clear only JQHTML keys from storage (keys starting with 'jqhtml::')
|
|
91
|
+
* Preserves keys from other libraries
|
|
92
|
+
* @private
|
|
93
|
+
*/
|
|
94
|
+
private static _clear_jqhtml_keys;
|
|
95
|
+
/**
|
|
96
|
+
* Build scoped key with JQHTML namespace prefix
|
|
97
|
+
* @param {string} key - Developer-provided key
|
|
98
|
+
* @returns {string}
|
|
99
|
+
* @private
|
|
100
|
+
*/
|
|
101
|
+
private static _build_key;
|
|
102
|
+
/**
|
|
103
|
+
* Check if storage is ready for use
|
|
104
|
+
* @returns {boolean}
|
|
105
|
+
* @private
|
|
106
|
+
*/
|
|
107
|
+
private static _is_ready;
|
|
108
|
+
/**
|
|
109
|
+
* Set item in localStorage
|
|
110
|
+
* @param {string} key - Storage key
|
|
111
|
+
* @param {*} value - Value to store (will be JSON serialized)
|
|
112
|
+
*/
|
|
113
|
+
static set(key: string, value: any): void;
|
|
114
|
+
/**
|
|
115
|
+
* Get item from localStorage
|
|
116
|
+
* @param {string} key - Storage key
|
|
117
|
+
* @returns {*|null} Parsed value or null if not found/unavailable
|
|
118
|
+
*/
|
|
119
|
+
static get(key: string): any | null;
|
|
120
|
+
/**
|
|
121
|
+
* Remove item from localStorage
|
|
122
|
+
* @param {string} key - Storage key
|
|
123
|
+
*/
|
|
124
|
+
static remove(key: string): void;
|
|
125
|
+
/**
|
|
126
|
+
* Internal set implementation with scope validation and quota handling
|
|
127
|
+
* @param {string} key
|
|
128
|
+
* @param {*} value - Original value (not used, kept for clarity)
|
|
129
|
+
* @param {string} serialized - Pre-serialized JSON string
|
|
130
|
+
* @private
|
|
131
|
+
*/
|
|
132
|
+
private static _set_item;
|
|
133
|
+
/**
|
|
134
|
+
* Internal get implementation
|
|
135
|
+
* @param {string} key
|
|
136
|
+
* @returns {*|null}
|
|
137
|
+
* @private
|
|
138
|
+
*/
|
|
139
|
+
private static _get_item;
|
|
140
|
+
/**
|
|
141
|
+
* Internal remove implementation
|
|
142
|
+
* @param {string} key
|
|
143
|
+
* @private
|
|
144
|
+
*/
|
|
145
|
+
private static _remove_item;
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=local-storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-storage.d.ts","sourceRoot":"","sources":["../src/local-storage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDG;AACH,qBAAa,oBAAoB;IAC7B,OAAO,CAAC,MAAM,CAAC,UAAU,CAAuB;IAChD,OAAO,CAAC,MAAM,CAAC,kBAAkB,CAAwB;IACzD,OAAO,CAAC,MAAM,CAAC,YAAY,CAAkB;IAE7C;;;;OAIG;IACH,MAAM,CAAC,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAK7C;;;OAGG;IACH,MAAM,CAAC,aAAa,IAAI,OAAO;IAI/B;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAC,KAAK;IAepB;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAC,qBAAqB;IAYpC;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAC,eAAe;IA4B9B;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAC,kBAAkB;IA2BjC;;;;;OAKG;IACH,OAAO,CAAC,MAAM,CAAC,UAAU;IAIzB;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAC,SAAS;IAIxB;;;;OAIG;IACH,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,IAAI;IAqBzC;;;;OAIG;IACH,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,GAAG,IAAI;IAQnC;;;OAGG;IACH,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAQhC;;;;;;OAMG;IACH,OAAO,CAAC,MAAM,CAAC,SAAS;IA4BxB;;;;;OAKG;IACH,OAAO,CAAC,MAAM,CAAC,SAAS;IAexB;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAC,YAAY;CAS9B"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JQHTML v2 Template Renderer
|
|
3
|
+
*
|
|
4
|
+
* Connects compiled templates to components
|
|
5
|
+
* Processes instruction arrays and handles bindings
|
|
6
|
+
*/
|
|
7
|
+
import type { Jqhtml_Component } from './component.js';
|
|
8
|
+
/**
|
|
9
|
+
* Render a template for a component
|
|
10
|
+
* Templates are functions that return [instructions, context] tuples
|
|
11
|
+
*/
|
|
12
|
+
export declare function render_template(component: Jqhtml_Component, template_fn?: Function): Promise<void>;
|
|
13
|
+
/**
|
|
14
|
+
* Helper to escape HTML for safe output
|
|
15
|
+
*/
|
|
16
|
+
export declare function escape_html(str: string): string;
|
|
17
|
+
//# sourceMappingURL=template-renderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template-renderer.d.ts","sourceRoot":"","sources":["../src/template-renderer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AA2EvD;;;GAGG;AACH,wBAAsB,eAAe,CACnC,SAAS,EAAE,gBAAgB,EAC3B,WAAW,CAAC,EAAE,QAAQ,GACrB,OAAO,CAAC,IAAI,CAAC,CAqDf;AA6KD;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAI/C"}
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
# JQHTML Laravel Bridge
|
|
2
|
+
|
|
3
|
+
Laravel integration package for JQHTML template error reporting with source map support.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
composer require jqhtml/laravel-bridge
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Configuration
|
|
12
|
+
|
|
13
|
+
Publish the configuration file:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
php artisan vendor:publish --tag=jqhtml-config
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
### Basic Setup
|
|
22
|
+
|
|
23
|
+
The package automatically registers its service provider and exception handler extensions. No additional setup is required for basic functionality.
|
|
24
|
+
|
|
25
|
+
### Error Handling
|
|
26
|
+
|
|
27
|
+
When a JQHTML template error occurs, the package will:
|
|
28
|
+
|
|
29
|
+
1. Parse the error message to extract template location information
|
|
30
|
+
2. Load source maps if available
|
|
31
|
+
3. Format the error for Laravel's exception handler
|
|
32
|
+
4. Display enhanced error information in debug mode
|
|
33
|
+
|
|
34
|
+
### Middleware
|
|
35
|
+
|
|
36
|
+
To automatically catch and format JQHTML errors, add the middleware to your route groups:
|
|
37
|
+
|
|
38
|
+
```php
|
|
39
|
+
// In app/Http/Kernel.php
|
|
40
|
+
protected $middlewareGroups = [
|
|
41
|
+
'web' => [
|
|
42
|
+
// ...
|
|
43
|
+
\Jqhtml\LaravelBridge\Middleware\JqhtmlErrorMiddleware::class,
|
|
44
|
+
],
|
|
45
|
+
];
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Manual Exception Creation
|
|
49
|
+
|
|
50
|
+
```php
|
|
51
|
+
use Jqhtml\LaravelBridge\JqhtmlException;
|
|
52
|
+
|
|
53
|
+
// Create from JavaScript error data
|
|
54
|
+
$jsError = json_decode($errorJson, true);
|
|
55
|
+
$exception = JqhtmlException::createFromJsError($jsError);
|
|
56
|
+
|
|
57
|
+
// Create manually
|
|
58
|
+
$exception = new JqhtmlException(
|
|
59
|
+
'Unclosed component definition',
|
|
60
|
+
'templates/user-card.jqhtml', // template file
|
|
61
|
+
42, // line number
|
|
62
|
+
15, // column number
|
|
63
|
+
$sourceCode, // template source
|
|
64
|
+
'Did you forget </Define:UserCard>?' // suggestion
|
|
65
|
+
);
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Integration with Node.js Compiler
|
|
69
|
+
|
|
70
|
+
When compiling JQHTML templates with Node.js, catch errors and pass them to Laravel:
|
|
71
|
+
|
|
72
|
+
```javascript
|
|
73
|
+
// Node.js side
|
|
74
|
+
try {
|
|
75
|
+
const compiled = jqhtml.compile(template);
|
|
76
|
+
} catch (error) {
|
|
77
|
+
// Send error details to Laravel
|
|
78
|
+
const errorData = {
|
|
79
|
+
message: error.message,
|
|
80
|
+
filename: error.filename,
|
|
81
|
+
line: error.line,
|
|
82
|
+
column: error.column,
|
|
83
|
+
source: error.source,
|
|
84
|
+
suggestion: error.suggestion
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
// Pass to Laravel via API or process communication
|
|
88
|
+
sendToLaravel(errorData);
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
```php
|
|
93
|
+
// Laravel side - Best Practice
|
|
94
|
+
use Jqhtml\LaravelBridge\JqhtmlException;
|
|
95
|
+
|
|
96
|
+
// Parse compiler JSON output
|
|
97
|
+
$errorData = json_decode($compiler_output, true);
|
|
98
|
+
|
|
99
|
+
if ($errorData && isset($errorData['error'])) {
|
|
100
|
+
// JqhtmlException extends ViewException, so this will show
|
|
101
|
+
// the template file as the error source in Laravel/Ignition
|
|
102
|
+
$exception = JqhtmlException::createFromJsError(
|
|
103
|
+
$errorData['error'],
|
|
104
|
+
$templatePath // Pass the actual template path
|
|
105
|
+
);
|
|
106
|
+
throw $exception;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Alternative: Direct ViewException usage (if not using the bridge)
|
|
110
|
+
if ($errorData && isset($errorData['error'])) {
|
|
111
|
+
$error = $errorData['error'];
|
|
112
|
+
$line = $error['line'] ?? 1;
|
|
113
|
+
|
|
114
|
+
throw new \Illuminate\View\ViewException(
|
|
115
|
+
$error['message'],
|
|
116
|
+
0, // code
|
|
117
|
+
1, // severity
|
|
118
|
+
$templatePath, // file
|
|
119
|
+
$line, // line
|
|
120
|
+
null // previous
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Source Map Support
|
|
126
|
+
|
|
127
|
+
The package supports source maps for mapping compiled JavaScript back to original JQHTML templates:
|
|
128
|
+
|
|
129
|
+
```php
|
|
130
|
+
// Configure source map storage location
|
|
131
|
+
config(['jqhtml.source_maps_path' => storage_path('sourcemaps')]);
|
|
132
|
+
|
|
133
|
+
// The formatter will automatically look for source maps
|
|
134
|
+
// when an error includes a compiled file reference
|
|
135
|
+
$exception->setCompiledFile('/path/to/compiled.js');
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Custom Error Views
|
|
139
|
+
|
|
140
|
+
Create a custom error view at `resources/views/jqhtml/error.blade.php`:
|
|
141
|
+
|
|
142
|
+
```blade
|
|
143
|
+
@extends('errors::layout')
|
|
144
|
+
|
|
145
|
+
@section('title', 'JQHTML Template Error')
|
|
146
|
+
|
|
147
|
+
@section('message')
|
|
148
|
+
<div class="jqhtml-error">
|
|
149
|
+
<h2>{{ $exception->getMessage() }}</h2>
|
|
150
|
+
|
|
151
|
+
@if($exception->getSuggestion())
|
|
152
|
+
<div class="suggestion">
|
|
153
|
+
💡 {{ $exception->getSuggestion() }}
|
|
154
|
+
</div>
|
|
155
|
+
@endif
|
|
156
|
+
|
|
157
|
+
@if($exception->getTemplateFile())
|
|
158
|
+
<div class="location">
|
|
159
|
+
📍 {{ $exception->getTemplateFile() }}:{{ $exception->getTemplateLine() }}:{{ $exception->getTemplateColumn() }}
|
|
160
|
+
</div>
|
|
161
|
+
@endif
|
|
162
|
+
|
|
163
|
+
@if(isset($error_data['source_context']))
|
|
164
|
+
<div class="source-context">
|
|
165
|
+
<pre><code>@foreach($error_data['source_context'] as $line)
|
|
166
|
+
@if($line['is_error_line'])<strong>> {{ $line['line_number'] }} | {{ $line['content'] }}
|
|
167
|
+
@if($line['error_column']){{ str_repeat(' ', $line['error_column'] + 8) }}{{ str_repeat('^', 20) }}@endif</strong>
|
|
168
|
+
@else {{ $line['line_number'] }} | {{ $line['content'] }}
|
|
169
|
+
@endif
|
|
170
|
+
@endforeach</code></pre>
|
|
171
|
+
</div>
|
|
172
|
+
@endif
|
|
173
|
+
</div>
|
|
174
|
+
@endsection
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## Configuration Options
|
|
178
|
+
|
|
179
|
+
```php
|
|
180
|
+
return [
|
|
181
|
+
// Where to store source map files
|
|
182
|
+
'source_maps_path' => storage_path('jqhtml-sourcemaps'),
|
|
183
|
+
|
|
184
|
+
// Show source code context in errors
|
|
185
|
+
'show_source_context' => env('APP_DEBUG', false),
|
|
186
|
+
|
|
187
|
+
// Lines of context to show
|
|
188
|
+
'context_lines' => 5,
|
|
189
|
+
|
|
190
|
+
// Cache compiled templates
|
|
191
|
+
'cache_compiled' => !env('APP_DEBUG', false),
|
|
192
|
+
|
|
193
|
+
// Where to store compiled templates
|
|
194
|
+
'compiled_path' => storage_path('jqhtml-compiled'),
|
|
195
|
+
|
|
196
|
+
// Enable source map generation
|
|
197
|
+
'enable_source_maps' => env('APP_DEBUG', false),
|
|
198
|
+
|
|
199
|
+
// Source map mode: 'inline', 'external', or 'both'
|
|
200
|
+
'source_map_mode' => 'external',
|
|
201
|
+
];
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Laravel Ignition Integration
|
|
205
|
+
|
|
206
|
+
The package automatically integrates with Laravel Ignition (if installed) to provide enhanced error display:
|
|
207
|
+
|
|
208
|
+
- Template file location with line and column numbers
|
|
209
|
+
- Source code context with error highlighting
|
|
210
|
+
- Helpful suggestions for common mistakes
|
|
211
|
+
- Source map resolution for compiled files
|
|
212
|
+
|
|
213
|
+
## API Reference
|
|
214
|
+
|
|
215
|
+
### JqhtmlException
|
|
216
|
+
|
|
217
|
+
Main exception class for JQHTML template errors. **Extends Laravel's `ViewException`** for optimal integration with Laravel's error handling and Ignition error pages.
|
|
218
|
+
|
|
219
|
+
When thrown, this exception ensures:
|
|
220
|
+
- The template file appears as the error source in Laravel/Ignition
|
|
221
|
+
- Line numbers point to the actual template location
|
|
222
|
+
- The error page shows your JQHTML template, not the PHP processor
|
|
223
|
+
|
|
224
|
+
### JqhtmlErrorFormatter
|
|
225
|
+
|
|
226
|
+
Formats exceptions for display with source context and source map support.
|
|
227
|
+
|
|
228
|
+
### JqhtmlExceptionRenderer
|
|
229
|
+
|
|
230
|
+
Renders exceptions for web and JSON responses.
|
|
231
|
+
|
|
232
|
+
### JqhtmlServiceProvider
|
|
233
|
+
|
|
234
|
+
Registers services and extends Laravel's exception handler.
|
|
235
|
+
|
|
236
|
+
### JqhtmlErrorMiddleware
|
|
237
|
+
|
|
238
|
+
Middleware for catching and wrapping JQHTML errors.
|
|
239
|
+
|
|
240
|
+
## License
|
|
241
|
+
|
|
242
|
+
MIT
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* JQHTML Laravel Bridge Autoloader
|
|
5
|
+
*
|
|
6
|
+
* Include this file from your Laravel project to load the JQHTML error handling bridge:
|
|
7
|
+
*
|
|
8
|
+
* require_once base_path('node_modules/@jqhtml/core/laravel-bridge/autoload.php');
|
|
9
|
+
*
|
|
10
|
+
* Or if using in a service provider:
|
|
11
|
+
*
|
|
12
|
+
* require_once dirname(__DIR__, 3) . '/node_modules/@jqhtml/core/laravel-bridge/autoload.php';
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
// This is a Laravel bridge - it REQUIRES Laravel to function
|
|
16
|
+
if (!class_exists('Illuminate\\Support\\ServiceProvider')) {
|
|
17
|
+
throw new \RuntimeException(
|
|
18
|
+
'JQHTML Laravel Bridge requires Laravel. ' .
|
|
19
|
+
'This file should only be included from within a Laravel application.'
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Register the autoloader for JQHTML Laravel Bridge classes
|
|
24
|
+
spl_autoload_register(function ($class) {
|
|
25
|
+
// Check if the class is in the Jqhtml\LaravelBridge namespace
|
|
26
|
+
$prefix = 'Jqhtml\\LaravelBridge\\';
|
|
27
|
+
$len = strlen($prefix);
|
|
28
|
+
|
|
29
|
+
if (strncmp($prefix, $class, $len) !== 0) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Get the relative class name
|
|
34
|
+
$relative_class = substr($class, $len);
|
|
35
|
+
|
|
36
|
+
// Replace namespace separators with directory separators
|
|
37
|
+
$file = __DIR__ . '/src/' . str_replace('\\', '/', $relative_class) . '.php';
|
|
38
|
+
|
|
39
|
+
// If the file exists, require it
|
|
40
|
+
if (file_exists($file)) {
|
|
41
|
+
require $file;
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
// Auto-register the service provider if in Laravel application context
|
|
46
|
+
if (function_exists('app') && app() instanceof \Illuminate\Foundation\Application) {
|
|
47
|
+
app()->register(\Jqhtml\LaravelBridge\JqhtmlServiceProvider::class);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Return the namespace for convenience
|
|
51
|
+
return 'Jqhtml\\LaravelBridge';
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "jqhtml/laravel-bridge",
|
|
3
|
+
"description": "Laravel integration bridge for JQHTML template error reporting and source maps",
|
|
4
|
+
"type": "library",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"authors": [
|
|
7
|
+
{
|
|
8
|
+
"name": "JQHTML Team"
|
|
9
|
+
}
|
|
10
|
+
],
|
|
11
|
+
"require": {
|
|
12
|
+
"php": "^7.4|^8.0",
|
|
13
|
+
"illuminate/support": "^8.0|^9.0|^10.0|^11.0"
|
|
14
|
+
},
|
|
15
|
+
"autoload": {
|
|
16
|
+
"psr-4": {
|
|
17
|
+
"Jqhtml\\LaravelBridge\\": "src/"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"autoload-dev": {
|
|
21
|
+
"psr-4": {
|
|
22
|
+
"Jqhtml\\LaravelBridge\\Tests\\": "tests/"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"extra": {
|
|
26
|
+
"laravel": {
|
|
27
|
+
"providers": [
|
|
28
|
+
"Jqhtml\\LaravelBridge\\JqhtmlServiceProvider"
|
|
29
|
+
]
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"minimum-stability": "stable",
|
|
33
|
+
"prefer-stable": true
|
|
34
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
return [
|
|
4
|
+
/*
|
|
5
|
+
|--------------------------------------------------------------------------
|
|
6
|
+
| JQHTML Source Maps Path
|
|
7
|
+
|--------------------------------------------------------------------------
|
|
8
|
+
|
|
|
9
|
+
| This option defines where JQHTML source map files should be stored.
|
|
10
|
+
| Source maps help map compiled JavaScript back to original JQHTML templates
|
|
11
|
+
| for better error reporting and debugging.
|
|
12
|
+
|
|
|
13
|
+
*/
|
|
14
|
+
'source_maps_path' => storage_path('jqhtml-sourcemaps'),
|
|
15
|
+
|
|
16
|
+
/*
|
|
17
|
+
|--------------------------------------------------------------------------
|
|
18
|
+
| Show Source Context
|
|
19
|
+
|--------------------------------------------------------------------------
|
|
20
|
+
|
|
|
21
|
+
| When enabled, error messages will include the surrounding source code
|
|
22
|
+
| context to help identify the exact location and nature of the error.
|
|
23
|
+
|
|
|
24
|
+
*/
|
|
25
|
+
'show_source_context' => env('APP_DEBUG', false),
|
|
26
|
+
|
|
27
|
+
/*
|
|
28
|
+
|--------------------------------------------------------------------------
|
|
29
|
+
| Error Context Lines
|
|
30
|
+
|--------------------------------------------------------------------------
|
|
31
|
+
|
|
|
32
|
+
| Number of lines to show before and after the error line when displaying
|
|
33
|
+
| source context in error messages.
|
|
34
|
+
|
|
|
35
|
+
*/
|
|
36
|
+
'context_lines' => 5,
|
|
37
|
+
|
|
38
|
+
/*
|
|
39
|
+
|--------------------------------------------------------------------------
|
|
40
|
+
| Cache Compiled Templates
|
|
41
|
+
|--------------------------------------------------------------------------
|
|
42
|
+
|
|
|
43
|
+
| When enabled, compiled JQHTML templates will be cached to improve
|
|
44
|
+
| performance. Disable during development for immediate template updates.
|
|
45
|
+
|
|
|
46
|
+
*/
|
|
47
|
+
'cache_compiled' => env('JQHTML_CACHE', !env('APP_DEBUG', false)),
|
|
48
|
+
|
|
49
|
+
/*
|
|
50
|
+
|--------------------------------------------------------------------------
|
|
51
|
+
| Compiled Templates Path
|
|
52
|
+
|--------------------------------------------------------------------------
|
|
53
|
+
|
|
|
54
|
+
| Directory where compiled JQHTML templates should be stored.
|
|
55
|
+
|
|
|
56
|
+
*/
|
|
57
|
+
'compiled_path' => storage_path('jqhtml-compiled'),
|
|
58
|
+
|
|
59
|
+
/*
|
|
60
|
+
|--------------------------------------------------------------------------
|
|
61
|
+
| Enable Source Maps
|
|
62
|
+
|--------------------------------------------------------------------------
|
|
63
|
+
|
|
|
64
|
+
| Whether to generate source maps for compiled templates. Source maps
|
|
65
|
+
| increase compilation time slightly but provide better debugging.
|
|
66
|
+
|
|
|
67
|
+
*/
|
|
68
|
+
'enable_source_maps' => env('APP_DEBUG', false),
|
|
69
|
+
|
|
70
|
+
/*
|
|
71
|
+
|--------------------------------------------------------------------------
|
|
72
|
+
| Source Map Mode
|
|
73
|
+
|--------------------------------------------------------------------------
|
|
74
|
+
|
|
|
75
|
+
| How source maps should be generated:
|
|
76
|
+
| - 'inline': Embed source map directly in compiled file
|
|
77
|
+
| - 'external': Save source map as separate .map file
|
|
78
|
+
| - 'both': Generate both inline and external source maps
|
|
79
|
+
|
|
|
80
|
+
*/
|
|
81
|
+
'source_map_mode' => 'external',
|
|
82
|
+
];
|