mirror of
				https://github.com/jaandrle/deka-dom-el
				synced 2025-11-04 07:09:15 +01:00 
			
		
		
		
	⚡ irelands
This commit is contained in:
		@@ -4,7 +4,7 @@ echo("Building static documentation files…");
 | 
				
			|||||||
echo("Preparing…");
 | 
					echo("Preparing…");
 | 
				
			||||||
import { path_target, pages as pages_registered, styles, dispatchEvent, t } from "../docs/ssr.js";
 | 
					import { path_target, pages as pages_registered, styles, dispatchEvent, t } from "../docs/ssr.js";
 | 
				
			||||||
import { createHTMl } from "./docs/jsdom.js";
 | 
					import { createHTMl } from "./docs/jsdom.js";
 | 
				
			||||||
import { register } from "../jsdom.js";
 | 
					import { register, queue } from "../jsdom.js";
 | 
				
			||||||
const pkg= s.cat("package.json").xargs(JSON.parse);
 | 
					const pkg= s.cat("package.json").xargs(JSON.parse);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if(s.test("-d", path_target.root)){
 | 
					if(s.test("-d", path_target.root)){
 | 
				
			||||||
@@ -31,6 +31,7 @@ for(const { id, info } of pages){
 | 
				
			|||||||
	serverDOM.document.body.append(
 | 
						serverDOM.document.body.append(
 | 
				
			||||||
		el(page, { pkg, info }),
 | 
							el(page, { pkg, info }),
 | 
				
			||||||
	);
 | 
						);
 | 
				
			||||||
 | 
						await queue();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	echo.use("-R", `Writing ${id}.html…`);
 | 
						echo.use("-R", `Writing ${id}.html…`);
 | 
				
			||||||
	dispatchEvent("oneachrender", document);
 | 
						dispatchEvent("oneachrender", document);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -236,12 +236,11 @@ function registerClientPart(page_id){
 | 
				
			|||||||
		`),
 | 
							`),
 | 
				
			||||||
	);
 | 
						);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Register our highlighting script to run after Shiki loads
 | 
					 | 
				
			||||||
	const scriptElement = el("script", { type: "module" });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	registerClientFile(
 | 
						registerClientFile(
 | 
				
			||||||
		new URL("./code.js.js", import.meta.url),
 | 
							new URL("./code.js.js", import.meta.url),
 | 
				
			||||||
		scriptElement
 | 
							{
 | 
				
			||||||
 | 
								head: el("script", { type: "module" }),
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	);
 | 
						);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	is_registered[page_id]= true;
 | 
						is_registered[page_id]= true;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										37
									
								
								docs/components/examples/ireland-test/counter.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								docs/components/examples/ireland-test/counter.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
				
			|||||||
 | 
					import { el } from "deka-dom-el";
 | 
				
			||||||
 | 
					import { S } from "deka-dom-el/signals";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const className = "client-side-counter";
 | 
				
			||||||
 | 
					document.body.append(
 | 
				
			||||||
 | 
						el("style").append(`
 | 
				
			||||||
 | 
					.${className} {
 | 
				
			||||||
 | 
						border: 1px dashed #ccc;
 | 
				
			||||||
 | 
						padding: 1em;
 | 
				
			||||||
 | 
						margin: 1em;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
							`.trim())
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function CounterStandard() {
 | 
				
			||||||
 | 
						// Create reactive state with a signal
 | 
				
			||||||
 | 
						const count = S(0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Create UI components that react to state changes
 | 
				
			||||||
 | 
						return el("div", { className }).append(
 | 
				
			||||||
 | 
							el("h4", "Client-Side Counter"),
 | 
				
			||||||
 | 
							el("div", {
 | 
				
			||||||
 | 
								// The textContent updates automatically when count changes
 | 
				
			||||||
 | 
								textContent: S(() => `Count: ${count.get()}`),
 | 
				
			||||||
 | 
							}),
 | 
				
			||||||
 | 
							el("div", { className: "controls" }).append(
 | 
				
			||||||
 | 
								el("button", {
 | 
				
			||||||
 | 
									onclick: () => count.set(count.get() - 1),
 | 
				
			||||||
 | 
									textContent: "-",
 | 
				
			||||||
 | 
								}),
 | 
				
			||||||
 | 
								el("button", {
 | 
				
			||||||
 | 
									onclick: () => count.set(count.get() + 1),
 | 
				
			||||||
 | 
									textContent: "+",
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
							)
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										88
									
								
								docs/components/ireland.html.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								docs/components/ireland.html.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,88 @@
 | 
				
			|||||||
 | 
					import { el, queue } from "deka-dom-el";
 | 
				
			||||||
 | 
					import { addEventListener, registerClientFile } from "../ssr.js";
 | 
				
			||||||
 | 
					import { relative } from "node:path";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const dir= new URL("./", import.meta.url).pathname;
 | 
				
			||||||
 | 
					const dirFE= "irelands";
 | 
				
			||||||
 | 
					// Track all component instances for client-side rehydration
 | 
				
			||||||
 | 
					const componentsRegistry = new Map();
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Creates a component that shows code and its runtime output
 | 
				
			||||||
 | 
					 * with server-side pre-rendering and client-side rehydration
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param {object} attrs
 | 
				
			||||||
 | 
					 * @param {URL} attrs.src - Path to the file containing the component
 | 
				
			||||||
 | 
					 * @param {string} [attrs.exportName="default"] - Name of the export to use
 | 
				
			||||||
 | 
					 * @param {string} attrs.page_id - ID of the current page
 | 
				
			||||||
 | 
					 * @param {object} [attrs.props={}] - Props to pass to the component
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export function ireland({ src, exportName = "default", props = {} }) {
 | 
				
			||||||
 | 
						// relative src against the current directory
 | 
				
			||||||
 | 
						const path= "./"+relative(dir, src.pathname);
 | 
				
			||||||
 | 
						const id = "ireland-" + generateComponentId(src);
 | 
				
			||||||
 | 
						const element = el.mark({ type: "ireland", name: ireland.name });
 | 
				
			||||||
 | 
						queue(import(path).then(module => {
 | 
				
			||||||
 | 
							const component = module[exportName];
 | 
				
			||||||
 | 
							element.replaceWith(el(component, props, mark(id)));
 | 
				
			||||||
 | 
						}));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(!componentsRegistry.size)
 | 
				
			||||||
 | 
							addEventListener("oneachrender", registerClientPart);
 | 
				
			||||||
 | 
						componentsRegistry.set(id, {
 | 
				
			||||||
 | 
							src,
 | 
				
			||||||
 | 
							path: dirFE+"/"+path.split("/").pop(),
 | 
				
			||||||
 | 
							exportName,
 | 
				
			||||||
 | 
							props,
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return element;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function registerClientPart(){
 | 
				
			||||||
 | 
						const todo= Array.from(componentsRegistry.entries())
 | 
				
			||||||
 | 
							.map(([ id, d ]) => {
 | 
				
			||||||
 | 
								registerClientFile(d.src, {
 | 
				
			||||||
 | 
									folder: dirFE,
 | 
				
			||||||
 | 
									// not all browsers support importmap
 | 
				
			||||||
 | 
									replacer(file){
 | 
				
			||||||
 | 
										return file
 | 
				
			||||||
 | 
											.replaceAll(/ from "deka-dom-el(\/signals)?";/g, ` from "./esm-with-signals.js";`);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
								return [ id, d ];
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
						const store = JSON.stringify(JSON.stringify(todo));
 | 
				
			||||||
 | 
						registerClientFile(new URL("./ireland.js.js", import.meta.url));
 | 
				
			||||||
 | 
						registerClientFile(new URL("../../dist/esm-with-signals.js", import.meta.url), { folder: dirFE });
 | 
				
			||||||
 | 
						document.head.append(
 | 
				
			||||||
 | 
							// not all browsers support importmap
 | 
				
			||||||
 | 
							el("script", { type: "importmap" }).append(`
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						"imports": {
 | 
				
			||||||
 | 
							"deka-dom-el": "./${dirFE}/esm-with-signals.js",
 | 
				
			||||||
 | 
							"deka-dom-el/signals": "./${dirFE}/esm-with-signals.js"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
							`.trim())
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
						document.body.append(
 | 
				
			||||||
 | 
							el("script", { type: "module" }).append(`
 | 
				
			||||||
 | 
					import { loadIrelands } from "./ireland.js.js";
 | 
				
			||||||
 | 
					loadIrelands(new Map(JSON.parse(${store})));
 | 
				
			||||||
 | 
							`.trim())
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					function mark(id) { return el=> el.dataset.ddeMark= id; }
 | 
				
			||||||
 | 
					const store_prev= new Map();
 | 
				
			||||||
 | 
					/** @param {URL} src */
 | 
				
			||||||
 | 
					function generateComponentId(src){
 | 
				
			||||||
 | 
						const candidate= parseInt(relative((new URL("..", import.meta.url)).pathname, src.pathname)
 | 
				
			||||||
 | 
							.split("")
 | 
				
			||||||
 | 
							.map(ch=> ch.charCodeAt(0))
 | 
				
			||||||
 | 
							.join(""), 10)
 | 
				
			||||||
 | 
							.toString(36)
 | 
				
			||||||
 | 
							.replace(/000+/g, "");
 | 
				
			||||||
 | 
						const count= 1 + ( store_prev.get(candidate) || 0 );
 | 
				
			||||||
 | 
						store_prev.set(candidate, count);
 | 
				
			||||||
 | 
						return count.toString()+"-"+candidate;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										13
									
								
								docs/components/ireland.js.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								docs/components/ireland.js.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					// not all browsers support importmaps
 | 
				
			||||||
 | 
					// import { el } from "deka-dom-el";
 | 
				
			||||||
 | 
					import { el } from "./irelands/esm-with-signals.js";
 | 
				
			||||||
 | 
					export function loadIrelands(store) {
 | 
				
			||||||
 | 
						document.body.querySelectorAll("[data-dde-mark]").forEach(ireland => {
 | 
				
			||||||
 | 
							const { ddeMark }= ireland.dataset;
 | 
				
			||||||
 | 
							if(!store.has(ddeMark)) return;
 | 
				
			||||||
 | 
							const { path, exportName, props }= store.get(ddeMark);
 | 
				
			||||||
 | 
							import("./"+path).then(module => {
 | 
				
			||||||
 | 
								ireland.replaceWith(el(module[exportName], props));
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -104,6 +104,7 @@ export function page({ pkg, info }){
 | 
				
			|||||||
			el("li").append(...T`${el("strong", "Custom Elements")} — Building web components`),
 | 
								el("li").append(...T`${el("strong", "Custom Elements")} — Building web components`),
 | 
				
			||||||
			el("li").append(...T`${el("strong", "Debugging")} — Tools to help you build and fix your apps`),
 | 
								el("li").append(...T`${el("strong", "Debugging")} — Tools to help you build and fix your apps`),
 | 
				
			||||||
			el("li").append(...T`${el("strong", "Extensions")} — Integrating third-party functionalities`),
 | 
								el("li").append(...T`${el("strong", "Extensions")} — Integrating third-party functionalities`),
 | 
				
			||||||
 | 
								el("li").append(...T`${el("strong", "Ireland Components")} — Creating interactive demos with server-side pre-rendering`),
 | 
				
			||||||
			el("li").append(...T`${el("strong", "SSR")} — Server-side rendering with DDE`)
 | 
								el("li").append(...T`${el("strong", "SSR")} — Server-side rendering with DDE`)
 | 
				
			||||||
		),
 | 
							),
 | 
				
			||||||
		el("p").append(...T`
 | 
							el("p").append(...T`
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,9 +18,10 @@ export function page({ pkg, info }){
 | 
				
			|||||||
	return el(simplePage, { info, pkg }).append(
 | 
						return el(simplePage, { info, pkg }).append(
 | 
				
			||||||
		el("div", { className: "warning" }).append(
 | 
							el("div", { className: "warning" }).append(
 | 
				
			||||||
			el("p").append(...T`
 | 
								el("p").append(...T`
 | 
				
			||||||
				This part of the documentation is primarily intended for technical enthusiasts and library authors.
 | 
									This part of the documentation is primarily intended for technical enthusiasts and documentation
 | 
				
			||||||
				For regular users, this capability will hopefully be covered by third-party libraries or frameworks
 | 
									authors. It describes an advanced feature, not a core part of the library. Most users will not need to
 | 
				
			||||||
				that provide simpler SSR integration using deka-dom-el.
 | 
									implement this functionality directly in their applications. This capability will hopefully be covered
 | 
				
			||||||
 | 
									by third-party libraries or frameworks that provide simpler SSR integration using deka-dom-el.
 | 
				
			||||||
			`)
 | 
								`)
 | 
				
			||||||
		),
 | 
							),
 | 
				
			||||||
		el("p").append(...T`
 | 
							el("p").append(...T`
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										360
									
								
								docs/p10-ireland.html.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										360
									
								
								docs/p10-ireland.html.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,360 @@
 | 
				
			|||||||
 | 
					import { T, t } from "./utils/index.js";
 | 
				
			||||||
 | 
					export const info= {
 | 
				
			||||||
 | 
						title: t`Ireland Components`,
 | 
				
			||||||
 | 
						fullTitle: t`Interactive Demo Components with Server-Side Pre-Rendering`,
 | 
				
			||||||
 | 
						description: t`Creating live, interactive component examples in documentation with server-side rendering and client-side hydration.`,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { el } from "deka-dom-el";
 | 
				
			||||||
 | 
					import { simplePage } from "./layout/simplePage.html.js";
 | 
				
			||||||
 | 
					import { h3 } from "./components/pageUtils.html.js";
 | 
				
			||||||
 | 
					import { code } from "./components/code.html.js";
 | 
				
			||||||
 | 
					import { ireland } from "./components/ireland.html.js";
 | 
				
			||||||
 | 
					/** @param {string} url */
 | 
				
			||||||
 | 
					const fileURL= url=> new URL(url, import.meta.url);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @param {import("./types.js").PageAttrs} attrs */
 | 
				
			||||||
 | 
					export function page({ pkg, info }){
 | 
				
			||||||
 | 
						const page_id= info.id;
 | 
				
			||||||
 | 
						return el(simplePage, { info, pkg }).append(
 | 
				
			||||||
 | 
							el("div", { className: "warning" }).append(
 | 
				
			||||||
 | 
								el("p").append(...T`
 | 
				
			||||||
 | 
									This part of the documentation is primarily intended for technical enthusiasts and documentation
 | 
				
			||||||
 | 
									authors. It describes an advanced feature, not a core part of the library. Most users will not need to
 | 
				
			||||||
 | 
									implement this functionality directly in their applications. This capability will hopefully be covered
 | 
				
			||||||
 | 
									by third-party libraries or frameworks that provide simpler SSR integration using deka-dom-el.
 | 
				
			||||||
 | 
								`)
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							el(h3, t`What Are Ireland Components?`),
 | 
				
			||||||
 | 
							el("p").append(...T`
 | 
				
			||||||
 | 
								Ireland components are a special type of documentation component that:
 | 
				
			||||||
 | 
							`),
 | 
				
			||||||
 | 
							el("ul").append(
 | 
				
			||||||
 | 
								el("li", t`Display source code with syntax highlighting`),
 | 
				
			||||||
 | 
								el("li", t`Pre-render components on the server during documentation build`),
 | 
				
			||||||
 | 
								el("li", t`Copy component source files to the documentation output`),
 | 
				
			||||||
 | 
								el("li", t`Provide client-side rehydration for interactive demos`),
 | 
				
			||||||
 | 
								el("li", t`Allow users to run and experiment with components in real-time`)
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							el(h3, t`How Ireland Components Work`),
 | 
				
			||||||
 | 
							el("p").append(...T`
 | 
				
			||||||
 | 
								The Ireland component system consists of several parts working together:
 | 
				
			||||||
 | 
							`),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							el("ol").append(
 | 
				
			||||||
 | 
								el("li").append(...T`
 | 
				
			||||||
 | 
									${el("strong", "Server-side rendering:")} Components are pre-rendered during the documentation build process
 | 
				
			||||||
 | 
								`),
 | 
				
			||||||
 | 
								el("li").append(...T`
 | 
				
			||||||
 | 
									${el("strong", "Component registration:")} Source files are copied to the documentation output directory
 | 
				
			||||||
 | 
								`),
 | 
				
			||||||
 | 
								el("li").append(...T`
 | 
				
			||||||
 | 
									${el("strong", "Client-side scripting:")} JavaScript code is generated to load and render components
 | 
				
			||||||
 | 
								`),
 | 
				
			||||||
 | 
								el("li").append(...T`
 | 
				
			||||||
 | 
									${el("strong", "User interaction:")} The "Run Component" button dynamically loads and renders the component
 | 
				
			||||||
 | 
								`)
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							el(h3, t`Implementation Architecture`),
 | 
				
			||||||
 | 
							el("p").append(...T`
 | 
				
			||||||
 | 
								The core of the Ireland system is implemented in ${el("code", "docs/components/ireland.html.js")}.
 | 
				
			||||||
 | 
								It integrates with the SSR build process using the ${el("code", "registerClientFile")} function from ${el("code", "docs/ssr.js")}.
 | 
				
			||||||
 | 
							`),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							el(code, { content: `
 | 
				
			||||||
 | 
					// Basic usage of an ireland component
 | 
				
			||||||
 | 
					el(ireland, {
 | 
				
			||||||
 | 
					  src: fileURL("./components/examples/path/to/component.js"),
 | 
				
			||||||
 | 
					  exportName: "NamedExport", // optional, defaults to "default",
 | 
				
			||||||
 | 
					})`, page_id }),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							el("p").append(...T`
 | 
				
			||||||
 | 
								During the build process (${el("code", "bs/docs.js")}), the following happens:
 | 
				
			||||||
 | 
							`),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							el("ol").append(
 | 
				
			||||||
 | 
								el("li", t`Component source code is loaded and displayed with syntax highlighting`),
 | 
				
			||||||
 | 
								el("li", t`Source files are registered to be copied to the output directory`),
 | 
				
			||||||
 | 
								el("li", t`Client-side scripts are generated for each page with ireland components`),
 | 
				
			||||||
 | 
								el("li", t`The component is wrapped in a UI container with controls`)
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							el(h3, t`Core Implementation Details`),
 | 
				
			||||||
 | 
							el("p").append(...T`
 | 
				
			||||||
 | 
								Let's look at the key parts of the ireland component implementation:
 | 
				
			||||||
 | 
							`),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							el("h4", t`Building SSR`),
 | 
				
			||||||
 | 
							el(code, { content: `
 | 
				
			||||||
 | 
					// From bs/docs.js - Server-side rendering engine
 | 
				
			||||||
 | 
					import { createHTMl } from "./docs/jsdom.js";
 | 
				
			||||||
 | 
					import { register, queue } from "../jsdom.js";
 | 
				
			||||||
 | 
					import { path_target, dispatchEvent } from "../docs/ssr.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// For each page, render it on the server
 | 
				
			||||||
 | 
					for(const { id, info } of pages) {
 | 
				
			||||||
 | 
					  // Create a virtual DOM environment for server-side rendering
 | 
				
			||||||
 | 
					  const serverDOM = createHTMl("");
 | 
				
			||||||
 | 
					  serverDOM.registerGlobally("HTMLScriptElement");
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  // Register deka-dom-el with the virtual DOM
 | 
				
			||||||
 | 
					  const { el } = await register(serverDOM.dom);
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  // Import and render the page component
 | 
				
			||||||
 | 
					  const { page } = await import(\`../docs/\${id}.html.js\`);
 | 
				
			||||||
 | 
					  serverDOM.document.body.append(
 | 
				
			||||||
 | 
					    el(page, { pkg, info }),
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  // Process the queue of asynchronous operations
 | 
				
			||||||
 | 
					  await queue();
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  // Trigger render event handlers
 | 
				
			||||||
 | 
					  dispatchEvent("oneachrender", document);
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  // Write the HTML to the output file
 | 
				
			||||||
 | 
					  s.echo(serverDOM.serialize()).to(path_target.root+id+".html");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Final build step - trigger SSR end event
 | 
				
			||||||
 | 
					dispatchEvent("onssrend");
 | 
				
			||||||
 | 
					`, page_id }),
 | 
				
			||||||
 | 
							el("h4", t`File Registration`),
 | 
				
			||||||
 | 
							el(code, { content: `
 | 
				
			||||||
 | 
					// From docs/ssr.js - File registration system
 | 
				
			||||||
 | 
					export function registerClientFile(url, { head, folder = "", replacer } = {}) {
 | 
				
			||||||
 | 
					  // Ensure folder path ends with a slash
 | 
				
			||||||
 | 
					  if(folder && !folder.endsWith("/")) folder += "/";
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  // Extract filename from URL
 | 
				
			||||||
 | 
					  const file_name = url.pathname.split("/").pop();
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  // Create target directory if needed
 | 
				
			||||||
 | 
					  s.mkdir("-p", path_target.root+folder);
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  // Get file content and apply optional replacer function
 | 
				
			||||||
 | 
					  let content = s.cat(url);
 | 
				
			||||||
 | 
					  if(replacer) content = s.echo(replacer(content.toString()));
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  // Write content to the output directory
 | 
				
			||||||
 | 
					  content.to(path_target.root+folder+file_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // If a head element was provided, add it to the document
 | 
				
			||||||
 | 
					  if(!head) return;
 | 
				
			||||||
 | 
					  head[head instanceof HTMLScriptElement ? "src" : "href"] = file_name;
 | 
				
			||||||
 | 
					  document.head.append(head);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					`, page_id }),
 | 
				
			||||||
 | 
							el("h4", t`Server-Side Rendering`),
 | 
				
			||||||
 | 
							el(code, { content: `
 | 
				
			||||||
 | 
					// From docs/components/ireland.html.js - Server-side component implementation
 | 
				
			||||||
 | 
					export function ireland({ src, exportName = "default", props = {} }) {
 | 
				
			||||||
 | 
					  // Calculate relative path for imports
 | 
				
			||||||
 | 
					  const path = "./"+relative(dir, src.pathname);
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  // Generate unique ID for this component instance
 | 
				
			||||||
 | 
					  const id = "ireland-" + generateComponentId(src);
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  // Create placeholder element
 | 
				
			||||||
 | 
					  const element = el.mark({ type: "ireland", name: ireland.name });
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  // Import and render the component during SSR
 | 
				
			||||||
 | 
					  queue(import(path).then(module => {
 | 
				
			||||||
 | 
					    const component = module[exportName];
 | 
				
			||||||
 | 
					    element.replaceWith(el(component, props, mark(id)));
 | 
				
			||||||
 | 
					  }));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Register client-side hydration on first component
 | 
				
			||||||
 | 
					  if(!componentsRegistry.size)
 | 
				
			||||||
 | 
					    addEventListener("oneachrender", registerClientPart);
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  // Store component info for client-side hydration
 | 
				
			||||||
 | 
					  componentsRegistry.set(id, {
 | 
				
			||||||
 | 
					    src,
 | 
				
			||||||
 | 
					    path: dirFE+"/"+path.split("/").pop(),
 | 
				
			||||||
 | 
					    exportName,
 | 
				
			||||||
 | 
					    props,
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return element;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Register client-side resources
 | 
				
			||||||
 | 
					function registerClientPart() {
 | 
				
			||||||
 | 
					  // Process all component registrations
 | 
				
			||||||
 | 
					  const todo = Array.from(componentsRegistry.entries())
 | 
				
			||||||
 | 
					    .map(([ id, d ]) => {
 | 
				
			||||||
 | 
					      // Copy the component source file to output directory
 | 
				
			||||||
 | 
					      registerClientFile(d.src, {
 | 
				
			||||||
 | 
					        folder: dirFE,
 | 
				
			||||||
 | 
					        // Replace bare imports for browser compatibility
 | 
				
			||||||
 | 
					        replacer(file) {
 | 
				
			||||||
 | 
					          return file.replaceAll(
 | 
				
			||||||
 | 
					            / from "deka-dom-el(\/signals)?";/g, 
 | 
				
			||||||
 | 
					            \` from "./esm-with-signals.js";\`
 | 
				
			||||||
 | 
					          );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					      return [ id, d ];
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  // Serialize the component registry for client-side use
 | 
				
			||||||
 | 
					  const store = JSON.stringify(JSON.stringify(todo));
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  // Copy client-side scripts to output
 | 
				
			||||||
 | 
					  registerClientFile(new URL("./ireland.js.js", import.meta.url));
 | 
				
			||||||
 | 
					  registerClientFile(new URL("../../dist/esm-with-signals.js", import.meta.url), { folder: dirFE });
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  // Add import map for package resolution
 | 
				
			||||||
 | 
					  document.head.append(
 | 
				
			||||||
 | 
					    el("script", { type: "importmap" }).append(\`
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  "imports": {
 | 
				
			||||||
 | 
					    "deka-dom-el": "./\${dirFE}/esm-with-signals.js",
 | 
				
			||||||
 | 
					    "deka-dom-el/signals": "./\${dirFE}/esm-with-signals.js"
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					    \`.trim())
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  // Add bootstrap script to load components
 | 
				
			||||||
 | 
					  document.body.append(
 | 
				
			||||||
 | 
					    el("script", { type: "module" }).append(\`
 | 
				
			||||||
 | 
					import { loadIrelands } from "./ireland.js.js";
 | 
				
			||||||
 | 
					loadIrelands(new Map(JSON.parse(\${store})));
 | 
				
			||||||
 | 
					    \`.trim())
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					`, page_id }),
 | 
				
			||||||
 | 
							el("h4", t`Client-Side Hydration`),
 | 
				
			||||||
 | 
							el(code, { content: `
 | 
				
			||||||
 | 
					// From docs/components/ireland.js.js - Client-side hydration
 | 
				
			||||||
 | 
					import { el } from "./irelands/esm-with-signals.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function loadIrelands(store) {
 | 
				
			||||||
 | 
					  // Find all marked components in the DOM
 | 
				
			||||||
 | 
					  document.body.querySelectorAll("[data-dde-mark]").forEach(ireland => {
 | 
				
			||||||
 | 
					    const { ddeMark } = ireland.dataset;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // Skip if this component isn't in our registry
 | 
				
			||||||
 | 
					    if(!store.has(ddeMark)) return;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // Get component information
 | 
				
			||||||
 | 
					    const { path, exportName, props } = store.get(ddeMark);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // Dynamically import the component module
 | 
				
			||||||
 | 
					    import("./" + path).then(module => {
 | 
				
			||||||
 | 
					      // Replace the server-rendered element with the client-side version
 | 
				
			||||||
 | 
					      ireland.replaceWith(el(module[exportName], props));
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					`, page_id }),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							el(h3, t`Live Example`),
 | 
				
			||||||
 | 
								el("p").append(...T`
 | 
				
			||||||
 | 
									Here's a live example of an Ireland component showing a standard counter.
 | 
				
			||||||
 | 
									The component is defined in ${el("code", "docs/components/examples/ireland-test/counter.js")} and
 | 
				
			||||||
 | 
									rendered with the Ireland component system:
 | 
				
			||||||
 | 
								`),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								el(code, {
 | 
				
			||||||
 | 
									src: fileURL("./components/examples/ireland-test/counter.js"),
 | 
				
			||||||
 | 
									page_id
 | 
				
			||||||
 | 
								}),
 | 
				
			||||||
 | 
								el(ireland, {
 | 
				
			||||||
 | 
									src: fileURL("./components/examples/ireland-test/counter.js"),
 | 
				
			||||||
 | 
									exportName: "CounterStandard",
 | 
				
			||||||
 | 
									page_id
 | 
				
			||||||
 | 
								}),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								el("p").append(...T`
 | 
				
			||||||
 | 
									When the "Run Component" button is clicked, the component is loaded and rendered dynamically.
 | 
				
			||||||
 | 
									The counter state is maintained using signals, allowing for reactive updates as you click
 | 
				
			||||||
 | 
									the buttons to increment and decrement the value.
 | 
				
			||||||
 | 
								`),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							el(h3, t`Creating Your Own Components`),
 | 
				
			||||||
 | 
							el("p").append(...T`
 | 
				
			||||||
 | 
								To create components for use with the Ireland system, follow these guidelines:
 | 
				
			||||||
 | 
							`),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							el("ol").append(
 | 
				
			||||||
 | 
								el("li").append(...T`
 | 
				
			||||||
 | 
									${el("strong", "Export a function:")} Components should be exported as named or default functions
 | 
				
			||||||
 | 
								`),
 | 
				
			||||||
 | 
								el("li").append(...T`
 | 
				
			||||||
 | 
									${el("strong", "Return a DOM element:")} The function should return a valid DOM element created with ${el("code", "el()")}
 | 
				
			||||||
 | 
								`),
 | 
				
			||||||
 | 
								el("li").append(...T`
 | 
				
			||||||
 | 
									${el("strong", "Accept props:")} Components should accept a props object, even if not using it
 | 
				
			||||||
 | 
								`),
 | 
				
			||||||
 | 
								el("li").append(...T`
 | 
				
			||||||
 | 
									${el("strong", "Manage reactivity:")} Use signals for state management where appropriate
 | 
				
			||||||
 | 
								`),
 | 
				
			||||||
 | 
								el("li").append(...T`
 | 
				
			||||||
 | 
									${el("strong", "Handle cleanup:")} Include any necessary cleanup for event listeners or signals
 | 
				
			||||||
 | 
								`)
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							el(h3, t`Practical Considerations and Limitations`),
 | 
				
			||||||
 | 
								el("p").append(...T`
 | 
				
			||||||
 | 
									When implementing Ireland components in real documentation, there are several important
 | 
				
			||||||
 | 
									considerations to keep in mind:
 | 
				
			||||||
 | 
								`),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								el("div", { className: "warning" }).append(
 | 
				
			||||||
 | 
									el("h4", t`Module Resolution and Bundling`),
 | 
				
			||||||
 | 
									el("p").append(...T`
 | 
				
			||||||
 | 
										The examples shown here use bare module specifiers like ${el("code", "import { el } from \"deka-dom-el\"")}
 | 
				
			||||||
 | 
										which aren't supported in all browsers without importmaps. In a production implementation, you would need to:
 | 
				
			||||||
 | 
									`),
 | 
				
			||||||
 | 
									el("ol").append(
 | 
				
			||||||
 | 
										el("li", t`Replace bare import paths with actual paths during the build process`),
 | 
				
			||||||
 | 
										el("li", t`Bundle component dependencies to avoid multiple requests`),
 | 
				
			||||||
 | 
										el("li", t`Ensure all module dependencies are properly resolved and copied to the output directory`)
 | 
				
			||||||
 | 
									),
 | 
				
			||||||
 | 
									el("p").append(...T`
 | 
				
			||||||
 | 
										In this documentation, we replace the paths with ${el("code", "./esm-with-signals.js")} and provide
 | 
				
			||||||
 | 
										a bundled version of the library, but more complex components might require a dedicated bundling step.
 | 
				
			||||||
 | 
									`)
 | 
				
			||||||
 | 
								),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								el("div", { className: "note" }).append(
 | 
				
			||||||
 | 
									el("h4", t`Component Dependencies`),
 | 
				
			||||||
 | 
									el("p").append(...T`
 | 
				
			||||||
 | 
										Real-world components typically depend on multiple modules and assets. The Ireland system would need
 | 
				
			||||||
 | 
										to be extended to:
 | 
				
			||||||
 | 
									`),
 | 
				
			||||||
 | 
									el("ul").append(
 | 
				
			||||||
 | 
										el("li", t`Detect and analyze all dependencies of a component`),
 | 
				
			||||||
 | 
										el("li", t`Bundle these dependencies together or ensure they're properly copied to the output directory`),
 | 
				
			||||||
 | 
										el("li", t`Handle non-JavaScript assets like CSS, images, or data files`)
 | 
				
			||||||
 | 
									)
 | 
				
			||||||
 | 
								),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								el(h3, t`Advanced Usage`),
 | 
				
			||||||
 | 
								el("p").append(...T`
 | 
				
			||||||
 | 
									The Ireland system can be extended in several ways to address these limitations:
 | 
				
			||||||
 | 
								`),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								el("ul").append(
 | 
				
			||||||
 | 
									el("li", t`Integrate with a bundler like esbuild, Rollup, or Webpack`),
 | 
				
			||||||
 | 
									el("li", t`Add props support for configuring components at runtime`),
 | 
				
			||||||
 | 
									el("li", t`Implement module caching to reduce network requests`),
 | 
				
			||||||
 | 
									el("li", t`Add code editing capabilities for interactive experimentation`),
 | 
				
			||||||
 | 
									el("li", t`Support TypeScript and other languages through transpilation`),
 | 
				
			||||||
 | 
									el("li", t`Implement state persistence between runs`)
 | 
				
			||||||
 | 
								),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								el("p").append(...T`
 | 
				
			||||||
 | 
									This documentation site itself is built using the techniques described here,
 | 
				
			||||||
 | 
									showcasing how deka-dom-el can be used to create both the documentation and
 | 
				
			||||||
 | 
									the interactive examples within it. The implementation here is simplified for clarity,
 | 
				
			||||||
 | 
									while a production-ready system would need to address the considerations above.
 | 
				
			||||||
 | 
								`)
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										19
									
								
								docs/ssr.js
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								docs/ssr.js
									
									
									
									
									
								
							@@ -13,16 +13,23 @@ export let pages= [];
 | 
				
			|||||||
 * @typedef registerClientFile
 | 
					 * @typedef registerClientFile
 | 
				
			||||||
 * @type {function}
 | 
					 * @type {function}
 | 
				
			||||||
 * @param {URL} url
 | 
					 * @param {URL} url
 | 
				
			||||||
 * @param {HTMLScriptElement|HTMLLinkElement} [element_head]
 | 
					 * @param {Object} [options]
 | 
				
			||||||
 | 
					 * @param {HTMLScriptElement|HTMLLinkElement} [options.head]
 | 
				
			||||||
 | 
					 * @param {string} [options.folder]
 | 
				
			||||||
 | 
					 * @param {function} [options.replacer]
 | 
				
			||||||
 * */
 | 
					 * */
 | 
				
			||||||
export function registerClientFile(url, element_head){
 | 
					export function registerClientFile(url, { head, folder= "", replacer }= {}){
 | 
				
			||||||
 | 
						if(folder && !folder.endsWith("/")) folder+= "/";
 | 
				
			||||||
	const file_name= url.pathname.split("/").pop();
 | 
						const file_name= url.pathname.split("/").pop();
 | 
				
			||||||
	s.cat(url).to(path_target.root+file_name);
 | 
						s.mkdir("-p", path_target.root+folder);
 | 
				
			||||||
 | 
						let content= s.cat(url)
 | 
				
			||||||
 | 
						if(replacer) content= s.echo(replacer(content.toString()));
 | 
				
			||||||
 | 
						content.to(path_target.root+folder+file_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if(!element_head) return;
 | 
						if(!head) return;
 | 
				
			||||||
	element_head[element_head instanceof HTMLScriptElement ? "src" : "href"]= file_name;
 | 
						head[head instanceof HTMLScriptElement ? "src" : "href"]= file_name;
 | 
				
			||||||
	document.head.append(
 | 
						document.head.append(
 | 
				
			||||||
		element_head
 | 
							head
 | 
				
			||||||
	);
 | 
						);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										32
									
								
								index.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										32
									
								
								index.d.ts
									
									
									
									
										vendored
									
									
								
							@@ -72,6 +72,17 @@ export function assignAttribute<El extends SupportedElement, ATT extends keyof E
 | 
				
			|||||||
): ElementAttributes<El>[ATT]
 | 
					): ElementAttributes<El>[ATT]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type ExtendedHTMLElementTagNameMap= HTMLElementTagNameMap & CustomElementTagNameMap;
 | 
					type ExtendedHTMLElementTagNameMap= HTMLElementTagNameMap & CustomElementTagNameMap;
 | 
				
			||||||
 | 
					export namespace el {
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Creates a marker comment for elements
 | 
				
			||||||
 | 
					   * 
 | 
				
			||||||
 | 
					   * @param {{ type: "component"|"reactive"|"ireland"|"later", name?: string, host?: "this"|"parentElement" }} attrs - Marker attributes
 | 
				
			||||||
 | 
					   * @param {boolean} [is_open=false] - Whether the marker is open-ended
 | 
				
			||||||
 | 
					   * @returns {Comment} Comment node marker
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  export function mark(attrs: { type: "component"|"reactive"|"ireland"|"later", name?: string, host?: "this"|"parentElement" }, is_open?: boolean): Comment;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function el<
 | 
					export function el<
 | 
				
			||||||
	A extends ddeComponentAttributes,
 | 
						A extends ddeComponentAttributes,
 | 
				
			||||||
	EL extends SupportedElement | ddeDocumentFragment
 | 
						EL extends SupportedElement | ddeDocumentFragment
 | 
				
			||||||
@@ -251,6 +262,27 @@ export function customElementWithDDE<EL extends (new ()=> HTMLElement)>(custom_e
 | 
				
			|||||||
export function lifecyclesToEvents<EL extends (new ()=> HTMLElement)>(custom_element: EL): EL
 | 
					export function lifecyclesToEvents<EL extends (new ()=> HTMLElement)>(custom_element: EL): EL
 | 
				
			||||||
export function observedAttributes(custom_element: HTMLElement): Record<string, string>
 | 
					export function observedAttributes(custom_element: HTMLElement): Record<string, string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * This is used primarly for server side rendering. To be sure that all async operations
 | 
				
			||||||
 | 
					 * are finished before the page is sent to the client.
 | 
				
			||||||
 | 
					 * ```
 | 
				
			||||||
 | 
					 *	// on component
 | 
				
			||||||
 | 
					 *	function component(){
 | 
				
			||||||
 | 
					 *		…
 | 
				
			||||||
 | 
					 *		queue(fetch(...).then(...));
 | 
				
			||||||
 | 
					 *	}
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * // building the page
 | 
				
			||||||
 | 
					 * async function build(){
 | 
				
			||||||
 | 
					 *		const { component }= await import("./component.js");
 | 
				
			||||||
 | 
					 *		document.body.append(el(component));
 | 
				
			||||||
 | 
					 *		await queue();
 | 
				
			||||||
 | 
					 *		retutn document.body.innerHTML;
 | 
				
			||||||
 | 
					 *	}
 | 
				
			||||||
 | 
					 * ```
 | 
				
			||||||
 | 
					 * */
 | 
				
			||||||
 | 
					export function queue(promise?: Promise<unknown>): Promise<unknown>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* TypeScript MEH */
 | 
					/* TypeScript MEH */
 | 
				
			||||||
declare global{
 | 
					declare global{
 | 
				
			||||||
	type ddeAppend<el>= (...nodes: (Node | string)[])=> el;
 | 
						type ddeAppend<el>= (...nodes: (Node | string)[])=> el;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2
									
								
								jsdom.js
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								jsdom.js
									
									
									
									
									
								
							@@ -17,7 +17,7 @@ env.setDeleteAttr= function(obj, prop, value){
 | 
				
			|||||||
	if(value) return obj.setAttribute(prop, "");
 | 
						if(value) return obj.setAttribute(prop, "");
 | 
				
			||||||
	obj.removeAttribute(prop);
 | 
						obj.removeAttribute(prop);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
const keys= { H: "HTMLElement", S: "SVGElement", F: "DocumentFragment", M: "MutationObserver", D: "document" };
 | 
					const keys= { H: "HTMLElement", S: "SVGElement", F: "DocumentFragment", D: "document" };
 | 
				
			||||||
let env_bk= {};
 | 
					let env_bk= {};
 | 
				
			||||||
let dom_last;
 | 
					let dom_last;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -100,5 +100,6 @@
 | 
				
			|||||||
		"jshint": "~2.13",
 | 
							"jshint": "~2.13",
 | 
				
			||||||
		"nodejsscript": "^1.0.2",
 | 
							"nodejsscript": "^1.0.2",
 | 
				
			||||||
		"size-limit-node-esbuild": "~0.3"
 | 
							"size-limit-node-esbuild": "~0.3"
 | 
				
			||||||
	}
 | 
						},
 | 
				
			||||||
 | 
						"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user