juxscript 1.1.2 → 1.1.4
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/machinery/build3.js +7 -91
- package/machinery/compiler3.js +3 -209
- package/machinery/config.js +93 -6
- package/machinery/serve.js +255 -0
- package/machinery/watcher.js +49 -161
- package/package.json +19 -5
- package/lib/components/alert.ts +0 -200
- package/lib/components/app.ts +0 -247
- package/lib/components/badge.ts +0 -101
- package/lib/components/base/BaseComponent.ts +0 -421
- package/lib/components/base/FormInput.ts +0 -227
- package/lib/components/button.ts +0 -178
- package/lib/components/card.ts +0 -173
- package/lib/components/chart.ts +0 -231
- package/lib/components/checkbox.ts +0 -242
- package/lib/components/code.ts +0 -123
- package/lib/components/container.ts +0 -140
- package/lib/components/data.ts +0 -135
- package/lib/components/datepicker.ts +0 -234
- package/lib/components/dialog.ts +0 -172
- package/lib/components/divider.ts +0 -100
- package/lib/components/dropdown.ts +0 -186
- package/lib/components/element.ts +0 -267
- package/lib/components/fileupload.ts +0 -309
- package/lib/components/grid.ts +0 -291
- package/lib/components/guard.ts +0 -92
- package/lib/components/heading.ts +0 -96
- package/lib/components/helpers.ts +0 -41
- package/lib/components/hero.ts +0 -224
- package/lib/components/icon.ts +0 -178
- package/lib/components/icons.ts +0 -464
- package/lib/components/include.ts +0 -410
- package/lib/components/input.ts +0 -457
- package/lib/components/list.ts +0 -419
- package/lib/components/loading.ts +0 -100
- package/lib/components/menu.ts +0 -275
- package/lib/components/modal.ts +0 -284
- package/lib/components/nav.ts +0 -257
- package/lib/components/paragraph.ts +0 -97
- package/lib/components/progress.ts +0 -159
- package/lib/components/radio.ts +0 -278
- package/lib/components/req.ts +0 -303
- package/lib/components/script.ts +0 -41
- package/lib/components/select.ts +0 -252
- package/lib/components/sidebar.ts +0 -275
- package/lib/components/style.ts +0 -41
- package/lib/components/switch.ts +0 -246
- package/lib/components/table.ts +0 -1249
- package/lib/components/tabs.ts +0 -250
- package/lib/components/theme-toggle.ts +0 -293
- package/lib/components/tooltip.ts +0 -144
- package/lib/components/view.ts +0 -190
- package/lib/components/write.ts +0 -272
- package/lib/layouts/default.css +0 -260
- package/lib/layouts/figma.css +0 -334
- package/lib/reactivity/state.ts +0 -78
- package/lib/utils/fetch.ts +0 -553
- package/machinery/ast.js +0 -347
- package/machinery/build.js +0 -466
- package/machinery/bundleAssets.js +0 -0
- package/machinery/bundleJux.js +0 -0
- package/machinery/bundleVendors.js +0 -0
- package/machinery/doc-generator.js +0 -136
- package/machinery/imports.js +0 -155
- package/machinery/server.js +0 -166
- package/machinery/ts-shim.js +0 -46
- package/machinery/validators/file-validator.js +0 -123
|
@@ -1,410 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
* Include - Include external resources (CSS, JS, images, fonts, etc.)
|
|
4
|
-
* Auto-detects resource type from URL and provides simple, fluent API
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
type IncludeType = 'stylesheet' | 'script' | 'image' | 'font' | 'preload' | 'prefetch' | 'module' | 'json';
|
|
8
|
-
type IncludeLocation = 'head' | 'body-start' | 'body-end';
|
|
9
|
-
|
|
10
|
-
interface IncludeOptions {
|
|
11
|
-
as?: string;
|
|
12
|
-
crossOrigin?: 'anonymous' | 'use-credentials';
|
|
13
|
-
integrity?: string;
|
|
14
|
-
async?: boolean;
|
|
15
|
-
defer?: boolean;
|
|
16
|
-
location?: IncludeLocation;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export class Include {
|
|
20
|
-
private url: string;
|
|
21
|
-
private type: IncludeType;
|
|
22
|
-
private options: IncludeOptions = {};
|
|
23
|
-
private element: HTMLElement | null = null;
|
|
24
|
-
private explicitType: boolean = false; // NEW: Track if type was explicitly set
|
|
25
|
-
|
|
26
|
-
constructor(urlOrFile: string) {
|
|
27
|
-
this.url = urlOrFile;
|
|
28
|
-
this.type = this.detectType(urlOrFile);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/* -------------------------
|
|
32
|
-
* Type Detection
|
|
33
|
-
* ------------------------- */
|
|
34
|
-
|
|
35
|
-
private detectType(url: string): IncludeType {
|
|
36
|
-
// Check for common script patterns in URLs (CDN, etc.)
|
|
37
|
-
if (url.includes('tailwindcss') ||
|
|
38
|
-
url.includes('jsdelivr.net/npm') ||
|
|
39
|
-
url.includes('unpkg.com') ||
|
|
40
|
-
url.includes('cdn.') ||
|
|
41
|
-
url.match(/\.(js|mjs)($|\?)/)) {
|
|
42
|
-
return 'script';
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
if (url.endsWith('.css')) return 'stylesheet';
|
|
46
|
-
if (url.endsWith('.json')) return 'json';
|
|
47
|
-
if (url.match(/\.(png|jpg|jpeg|gif|svg|webp)$/i)) return 'image';
|
|
48
|
-
if (url.match(/\.(woff|woff2|ttf|otf|eot)$/i)) return 'font';
|
|
49
|
-
|
|
50
|
-
// Default to script for extensionless URLs from CDN domains
|
|
51
|
-
if (!url.includes('.') || url.match(/^https?:\/\/cdn/)) {
|
|
52
|
-
return 'script';
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
return 'preload';
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/* -------------------------
|
|
59
|
-
* Fluent Type Setters
|
|
60
|
-
* ------------------------- */
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Force treat as CSS stylesheet
|
|
64
|
-
* Use when URL doesn't have .css extension
|
|
65
|
-
*/
|
|
66
|
-
withCss(): this {
|
|
67
|
-
this.type = 'stylesheet';
|
|
68
|
-
this.explicitType = true; // Mark as explicit
|
|
69
|
-
return this;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Force treat as JavaScript
|
|
74
|
-
* Use when URL doesn't have .js extension (CDN scripts, etc.)
|
|
75
|
-
*
|
|
76
|
-
* @example
|
|
77
|
-
* jux.include('https://cdn.tailwindcss.com').withJs().render();
|
|
78
|
-
* jux.include('https://unpkg.com/alpine').withJs({ defer: true }).render();
|
|
79
|
-
*/
|
|
80
|
-
withJs(options?: { async?: boolean; defer?: boolean }): this {
|
|
81
|
-
this.type = 'script';
|
|
82
|
-
this.explicitType = true; // Mark as explicit
|
|
83
|
-
if (options?.async) this.options.async = true;
|
|
84
|
-
if (options?.defer) this.options.defer = true;
|
|
85
|
-
return this;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Force treat as ES module
|
|
90
|
-
* Use for module scripts
|
|
91
|
-
*/
|
|
92
|
-
withModule(): this {
|
|
93
|
-
this.type = 'module';
|
|
94
|
-
this.explicitType = true; // Mark as explicit
|
|
95
|
-
return this;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
withImage(): this {
|
|
99
|
-
this.type = 'image';
|
|
100
|
-
this.explicitType = true;
|
|
101
|
-
return this;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
withFont(): this {
|
|
105
|
-
this.type = 'font';
|
|
106
|
-
this.explicitType = true;
|
|
107
|
-
return this;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
withPreload(as?: string): this {
|
|
111
|
-
this.type = 'preload';
|
|
112
|
-
this.explicitType = true;
|
|
113
|
-
if (as) this.options.as = as;
|
|
114
|
-
return this;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
withPrefetch(): this {
|
|
118
|
-
this.type = 'prefetch';
|
|
119
|
-
this.explicitType = true;
|
|
120
|
-
return this;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
withJson(): this {
|
|
124
|
-
this.type = 'json';
|
|
125
|
-
this.explicitType = true;
|
|
126
|
-
return this;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/* -------------------------
|
|
130
|
-
* Convenience aliases for common patterns
|
|
131
|
-
* ------------------------- */
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Shorthand for .withJs()
|
|
135
|
-
* @example jux.include(url).asScript()
|
|
136
|
-
*/
|
|
137
|
-
asScript(options?: { async?: boolean; defer?: boolean }): this {
|
|
138
|
-
return this.withJs(options);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* Shorthand for .withCss()
|
|
143
|
-
* @example jux.include(url).asStylesheet()
|
|
144
|
-
*/
|
|
145
|
-
asStylesheet(): this {
|
|
146
|
-
return this.withCss();
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/* -------------------------
|
|
150
|
-
* JSON Fetching
|
|
151
|
-
* ------------------------- */
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* Fetch and parse JSON file
|
|
155
|
-
* Returns a Promise that resolves to the parsed JSON data
|
|
156
|
-
*
|
|
157
|
-
* Usage:
|
|
158
|
-
* const config = await jux.include('config.json').asJson();
|
|
159
|
-
* const data = await jux.include('/api/data').asJson();
|
|
160
|
-
*/
|
|
161
|
-
async asJson<T = any>(): Promise<T> {
|
|
162
|
-
try {
|
|
163
|
-
const response = await fetch(this.url);
|
|
164
|
-
|
|
165
|
-
if (!response.ok) {
|
|
166
|
-
throw new Error(`HTTP error! status: ${response.status}`);
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
const data = await response.json();
|
|
170
|
-
console.log(`✓ JSON loaded: ${this.url}`);
|
|
171
|
-
return data;
|
|
172
|
-
} catch (error: any) {
|
|
173
|
-
throw error;
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* Fetch JSON and execute callback with data
|
|
179
|
-
*
|
|
180
|
-
* Usage:
|
|
181
|
-
* jux.include('config.json').onJson(data => {
|
|
182
|
-
* console.log('Config:', data);
|
|
183
|
-
* });
|
|
184
|
-
*/
|
|
185
|
-
onJson<T = any>(callback: (data: T) => void): this {
|
|
186
|
-
this.asJson<T>().then(callback).catch(error => {
|
|
187
|
-
console.error('Failed to load JSON:', error);
|
|
188
|
-
});
|
|
189
|
-
return this;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
/* -------------------------
|
|
193
|
-
* Options
|
|
194
|
-
* ------------------------- */
|
|
195
|
-
|
|
196
|
-
with(options: IncludeOptions): this {
|
|
197
|
-
this.options = { ...this.options, ...options };
|
|
198
|
-
return this;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
inHead(): this {
|
|
202
|
-
this.options.location = 'head';
|
|
203
|
-
return this;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
inBody(): this {
|
|
207
|
-
this.options.location = 'body-end';
|
|
208
|
-
return this;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
async(): this {
|
|
212
|
-
this.options.async = true;
|
|
213
|
-
return this;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
defer(): this {
|
|
217
|
-
this.options.defer = true;
|
|
218
|
-
return this;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
crossOrigin(value: 'anonymous' | 'use-credentials' = 'anonymous'): this {
|
|
222
|
-
this.options.crossOrigin = value;
|
|
223
|
-
return this;
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
integrity(hash: string): this {
|
|
227
|
-
this.options.integrity = hash;
|
|
228
|
-
return this;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
/* -------------------------
|
|
232
|
-
* Render
|
|
233
|
-
* ------------------------- */
|
|
234
|
-
|
|
235
|
-
render(): this {
|
|
236
|
-
if (typeof document === 'undefined') return this;
|
|
237
|
-
|
|
238
|
-
// Don't render JSON type (it's fetched via asJson() instead)
|
|
239
|
-
if (this.type === 'json') {
|
|
240
|
-
console.warn('Include: JSON files should be loaded with .asJson() instead of .render()');
|
|
241
|
-
return this;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
try {
|
|
245
|
-
this.remove();
|
|
246
|
-
|
|
247
|
-
let element: HTMLElement;
|
|
248
|
-
|
|
249
|
-
switch (this.type) {
|
|
250
|
-
case 'stylesheet':
|
|
251
|
-
element = this.createStylesheet();
|
|
252
|
-
break;
|
|
253
|
-
case 'script':
|
|
254
|
-
case 'module':
|
|
255
|
-
element = this.createScript();
|
|
256
|
-
break;
|
|
257
|
-
case 'image':
|
|
258
|
-
case 'font':
|
|
259
|
-
case 'preload':
|
|
260
|
-
case 'prefetch':
|
|
261
|
-
element = this.createLink();
|
|
262
|
-
break;
|
|
263
|
-
default:
|
|
264
|
-
throw new Error(`Unknown include type: ${this.type}`);
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
const container = this.getContainer();
|
|
268
|
-
const location = this.options.location || 'head';
|
|
269
|
-
|
|
270
|
-
if (location === 'body-end') {
|
|
271
|
-
container.appendChild(element);
|
|
272
|
-
} else {
|
|
273
|
-
container.insertBefore(element, container.firstChild);
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
this.element = element;
|
|
277
|
-
|
|
278
|
-
// Log with type indicator
|
|
279
|
-
const typeIndicator = this.explicitType ? '(explicit)' : '(auto-detected)';
|
|
280
|
-
console.log(`✓ Include loaded as ${this.type} ${typeIndicator}: ${this.url}`);
|
|
281
|
-
} catch (error: any) {
|
|
282
|
-
throw error;
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
return this;
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
/* -------------------------
|
|
289
|
-
* Element Creation
|
|
290
|
-
* ------------------------- */
|
|
291
|
-
|
|
292
|
-
private createStylesheet(): HTMLLinkElement {
|
|
293
|
-
const link = document.createElement('link');
|
|
294
|
-
link.rel = 'stylesheet';
|
|
295
|
-
link.href = this.url;
|
|
296
|
-
|
|
297
|
-
if (this.options.crossOrigin) link.crossOrigin = this.options.crossOrigin;
|
|
298
|
-
if (this.options.integrity) link.integrity = this.options.integrity;
|
|
299
|
-
|
|
300
|
-
link.onload = () => console.log(`✓ Stylesheet loaded: ${this.url}`);
|
|
301
|
-
link.onerror = () => this.handleError('stylesheet');
|
|
302
|
-
|
|
303
|
-
return link;
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
private createScript(): HTMLScriptElement {
|
|
307
|
-
const script = document.createElement('script');
|
|
308
|
-
script.src = this.url;
|
|
309
|
-
|
|
310
|
-
if (this.type === 'module') script.type = 'module';
|
|
311
|
-
if (this.options.async) script.async = true;
|
|
312
|
-
if (this.options.defer) script.defer = true;
|
|
313
|
-
if (this.options.crossOrigin) script.crossOrigin = this.options.crossOrigin;
|
|
314
|
-
if (this.options.integrity) script.integrity = this.options.integrity;
|
|
315
|
-
|
|
316
|
-
script.onload = () => console.log(`✓ Script loaded: ${this.url}`);
|
|
317
|
-
script.onerror = () => this.handleError('script');
|
|
318
|
-
|
|
319
|
-
return script;
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
private createLink(): HTMLLinkElement {
|
|
323
|
-
const link = document.createElement('link');
|
|
324
|
-
|
|
325
|
-
// Set rel based on type
|
|
326
|
-
if (this.type === 'prefetch') {
|
|
327
|
-
link.rel = 'prefetch';
|
|
328
|
-
} else {
|
|
329
|
-
link.rel = 'preload';
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
link.href = this.url;
|
|
333
|
-
|
|
334
|
-
// Set 'as' attribute
|
|
335
|
-
if (this.type === 'image') {
|
|
336
|
-
link.as = 'image';
|
|
337
|
-
} else if (this.type === 'font') {
|
|
338
|
-
link.as = 'font';
|
|
339
|
-
link.crossOrigin = this.options.crossOrigin || 'anonymous';
|
|
340
|
-
} else if (this.options.as) {
|
|
341
|
-
link.as = this.options.as;
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
if (this.options.crossOrigin && this.type !== 'font') {
|
|
345
|
-
link.crossOrigin = this.options.crossOrigin;
|
|
346
|
-
}
|
|
347
|
-
if (this.options.integrity) {
|
|
348
|
-
link.integrity = this.options.integrity;
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
return link;
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
/* -------------------------
|
|
355
|
-
* Helpers
|
|
356
|
-
* ------------------------- */
|
|
357
|
-
|
|
358
|
-
private getContainer(): HTMLElement {
|
|
359
|
-
const location = this.options.location || 'head';
|
|
360
|
-
return location === 'head' ? document.head : document.body;
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
private handleError(type: string): void {
|
|
364
|
-
const error = new Error(`Failed to load ${type}: ${this.url}`);
|
|
365
|
-
throw error;
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
remove(): this {
|
|
370
|
-
if (this.element?.parentNode) {
|
|
371
|
-
this.element.parentNode.removeChild(this.element);
|
|
372
|
-
this.element = null;
|
|
373
|
-
}
|
|
374
|
-
return this;
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
/**
|
|
379
|
-
* Factory function - auto-detects type and renders immediately
|
|
380
|
-
*
|
|
381
|
-
* Usage:
|
|
382
|
-
* // Auto-detect (works for most cases)
|
|
383
|
-
* jux.include('styles.css');
|
|
384
|
-
* jux.include('script.js').async();
|
|
385
|
-
*
|
|
386
|
-
* // Explicit type (for extensionless URLs)
|
|
387
|
-
* jux.include('https://cdn.tailwindcss.com').withJs();
|
|
388
|
-
* jux.include('https://cdn.tailwindcss.com').asScript();
|
|
389
|
-
* jux.include('https://unpkg.com/htmx.org').withJs({ defer: true });
|
|
390
|
-
*
|
|
391
|
-
* // CDN with parameters
|
|
392
|
-
* jux.include('https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4').withJs();
|
|
393
|
-
*
|
|
394
|
-
* // Module
|
|
395
|
-
* jux.include('app.mjs').withModule();
|
|
396
|
-
*
|
|
397
|
-
* // For JSON:
|
|
398
|
-
* const data = await jux.include('config.json').asJson();
|
|
399
|
-
* jux.include('data.json').onJson(data => console.log(data));
|
|
400
|
-
*/
|
|
401
|
-
export function include(urlOrFile: string): Include {
|
|
402
|
-
const imp = new Include(urlOrFile);
|
|
403
|
-
|
|
404
|
-
// Don't auto-render JSON files
|
|
405
|
-
if (imp['type'] !== 'json') {
|
|
406
|
-
imp.render();
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
return imp;
|
|
410
|
-
}
|