import { EdgeError } from "edge-error";
import { find, html } from "property-information";
import lodash from "@poppinss/utils/lodash";
import he from "he";
import Macroable from "@poppinss/macroable";
import { EOL } from "node:os";
import stringifyAttributes from "stringify-attributes";
//#region \0rolldown/runtime.js
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
var __exportAll = (all, no_symbols) => {
	let target = {};
	for (var name in all) __defProp(target, name, {
		get: all[name],
		enumerable: true
	});
	if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
	return target;
};
var __copyProps = (to, from, except, desc) => {
	if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
		key = keys[i];
		if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
			get: ((k) => from[k]).bind(null, key),
			enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
		});
	}
	return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
	value: mod,
	enumerable: true
}) : target, mod));
//#endregion
//#region node_modules/classnames/index.js
var require_classnames = /* @__PURE__ */ __commonJSMin(((exports, module) => {
	/*!
	Copyright (c) 2018 Jed Watson.
	Licensed under the MIT License (MIT), see
	http://jedwatson.github.io/classnames
	*/
	(function() {
		"use strict";
		var hasOwn = {}.hasOwnProperty;
		function classNames() {
			var classes = "";
			for (var i = 0; i < arguments.length; i++) {
				var arg = arguments[i];
				if (arg) classes = appendClass(classes, parseValue(arg));
			}
			return classes;
		}
		function parseValue(arg) {
			if (typeof arg === "string" || typeof arg === "number") return arg;
			if (typeof arg !== "object") return "";
			if (Array.isArray(arg)) return classNames.apply(null, arg);
			if (arg.toString !== Object.prototype.toString && !arg.toString.toString().includes("[native code]")) return arg.toString();
			var classes = "";
			for (var key in arg) if (hasOwn.call(arg, key) && arg[key]) classes = appendClass(classes, key);
			return classes;
		}
		function appendClass(value, newClass) {
			if (!newClass) return value;
			if (value) return value + " " + newClass;
			return value + newClass;
		}
		if (typeof module !== "undefined" && module.exports) {
			classNames.default = classNames;
			module.exports = classNames;
		} else if (typeof define === "function" && typeof define.amd === "object" && define.amd) define("classnames", [], function() {
			return classNames;
		});
		else window.classNames = classNames;
	})();
}));
//#endregion
//#region src/utils.ts
var import_classnames = /* @__PURE__ */ __toESM(require_classnames(), 1);
/**
* Function to register custom properties
* with "property-information" package.
*/
function definePropertyInformation(property, value) {
	html.normal[property] = property;
	html.property[property] = {
		attribute: property,
		boolean: true,
		property,
		space: "html",
		booleanish: false,
		commaOrSpaceSeparated: false,
		commaSeparated: false,
		spaceSeparated: false,
		number: false,
		overloadedBoolean: false,
		defined: false,
		mustUseProperty: false,
		...value
	};
}
definePropertyInformation("x-cloak");
definePropertyInformation("x-ignore");
definePropertyInformation("x-transition:enterstart", {
	attribute: "x-transition:enter-start",
	property: "x-transition:enterStart",
	boolean: false,
	spaceSeparated: true,
	commaOrSpaceSeparated: true
});
definePropertyInformation("x-transition:enterend", {
	attribute: "x-transition:enter-end",
	property: "x-transition:enterEnd",
	boolean: false,
	spaceSeparated: true,
	commaOrSpaceSeparated: true
});
definePropertyInformation("x-transition:leavestart", {
	attribute: "x-transition:leave-start",
	property: "x-transition:leaveStart",
	boolean: false,
	spaceSeparated: true,
	commaOrSpaceSeparated: true
});
definePropertyInformation("x-transition:leaveend", {
	attribute: "x-transition:leave-end",
	property: "x-transition:leaveEnd",
	boolean: false,
	spaceSeparated: true,
	commaOrSpaceSeparated: true
});
/**
* Alpine namespaces we handle with special
* rules when stringifying attributes
*/
const alpineNamespaces = {
	x: "x-",
	xOn: "x-on:",
	xBind: "x-bind:",
	xTransition: "x-transition:"
};
/**
* Raise an `E_UNALLOWED_EXPRESSION` exception. Filename and expression is
* required to point the error stack to the correct file
*/
function unallowedExpression(message, filename, loc) {
	throw new EdgeError(message, "E_UNALLOWED_EXPRESSION", {
		line: loc.line,
		col: loc.col,
		filename
	});
}
/**
* Validates the expression type to be part of the allowed
* expressions only.
*
* The filename is required to report errors.
*
* ```js
* isNotSubsetOf(expression, ['Literal', 'Identifier'], () => {})
* ```
*/
function isSubsetOf(expression, expressions, errorCallback) {
	if (!expressions.includes(expression.type)) errorCallback();
}
/**
* Validates the expression type not to be part of the disallowed
* expressions.
*
* The filename is required to report errors.
*
* ```js
* isNotSubsetOf(expression, 'SequenceExpression', () => {})
* ```
*/
function isNotSubsetOf(expression, expressions, errorCallback) {
	if (expressions.includes(expression.type)) errorCallback();
}
/**
* Parses the jsArg by generating and transforming its AST
*/
function parseJsArg(parser, token) {
	return parser.utils.transformAst(parser.utils.generateAST(token.properties.jsArg, token.loc, token.filename), token.filename, parser);
}
/**
* Each loop. A soft replacement for `lodash.each` that we were using earlier
*/
function each(collection, iteratee) {
	if (Array.isArray(collection)) {
		for (let [key, value] of collection.entries()) iteratee(value, key);
		return;
	}
	if (typeof collection === "string") {
		let index = 0;
		for (let value of collection) iteratee(value, index++);
		return;
	}
	if (collection && typeof collection === "object") for (let [key, value] of Object.entries(collection)) iteratee(value, key);
}
/**
* Async each loop. A soft replacement for `lodash.each` that we were
* using earlier with support for async await
*/
async function asyncEach(collection, iteratee) {
	if (Array.isArray(collection)) {
		for (let [key, value] of collection.entries()) await iteratee(value, key);
		return;
	}
	if (typeof collection === "string") {
		let index = 0;
		for (let value of collection) await iteratee(value, index++);
		return;
	}
	if (collection && typeof collection === "object") for (let [key, value] of Object.entries(collection)) await iteratee(value, key);
}
/**
* This class generates a valid object as a string, which is written to the template
* output. The reason we need a string like object, since we don't want it's
* properties to be evaluated during the object creation, instead it must
* be evaluated when the compiled output is invoked.
*/
var StringifiedObject = class {
	#obj = "";
	addSpread(key) {
		this.#obj += this.#obj.length ? `, ${key}` : `${key}`;
	}
	/**
	* Add key/value pair to the object.
	*
	* ```js
	* stringifiedObject.add('username', `'virk'`)
	* ```
	*/
	add(key, value, isComputed = false) {
		key = isComputed ? `[${key}]` : key;
		this.#obj += this.#obj.length ? `, ${key}: ${value}` : `${key}: ${value}`;
	}
	/**
	* Returns the object alike string back.
	*
	* ```js
	* stringifiedObject.flush()
	*
	* // returns
	* `{ username: 'virk' }`
	* ```
	*/
	flush() {
		const obj = `{ ${this.#obj} }`;
		this.#obj = "";
		return obj;
	}
};
/**
* Stringify an object to props to HTML attributes
*/
function stringifyAttributes$1(props, namespace) {
	const attributes = Object.keys(props);
	if (attributes.length === 0) return "";
	return attributes.reduce((result, key) => {
		let value = props[key];
		key = namespace ? `${namespace}${key}` : key;
		/**
		* No value defined, remove attribute
		*/
		if (!value) return result;
		/**
		* Handle alpine properties separately
		*/
		if (alpineNamespaces[key] && typeof value === "object") {
			result = result.concat(stringifyAttributes$1(value, alpineNamespaces[key]));
			return result;
		}
		const propInfo = find(html, key);
		/**
		* Ignore unknown attributes
		*/
		if (!propInfo) return result;
		const attribute = propInfo.attribute;
		/**
		* Boolean properties
		*/
		if (value === true) {
			result.push(attribute);
			return result;
		}
		/**
		* Encoding rules for certain properties.
		*
		* - Class values can be objects with conditionals
		* - Non-booleanish and numeric properties will be html escaped
		* - Arrays will be concatenated into a string list and html escaped
		*/
		if (key === "class") value = `"${(0, import_classnames.default)(value)}"`;
		else if (Array.isArray(value)) value = `"${value.join(propInfo.commaSeparated ? "," : " ")}"`;
		else value = `"${String(value)}"`;
		/**
		* Push attribute value string
		*/
		result.push(`${attribute}=${value}`);
		return result;
	}, []).join(" ");
}
/**
* Copy-pasted from
* https://github.com/ai/nanoid/blob/main/nanoid.js
*/
const seed = "useandom26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";
let nanoid = (length = 15) => {
	let output = "";
	const random = crypto.getRandomValues(new Uint8Array(length));
	for (let n = 0; n < length; n++) output += seed[63 & random[n]];
	return output;
};
//#endregion
//#region src/edge/stacks.ts
var Stacks = class {
	#contentSources = /* @__PURE__ */ new Map();
	/**
	* Pre-seeded content before the placeholder has been
	* defined.
	*/
	#seededPlaceholders = /* @__PURE__ */ new Map();
	/**
	* Placeholders to be flushed
	*/
	#placeholders = /* @__PURE__ */ new Map();
	/**
	* Returns the placeholder name for a given stack
	*/
	#createPlaceholder(name) {
		return `<!-- @edge.stacks.${name} -->`;
	}
	/**
	* Create a new stack placeholder. Multiple calls to this method
	* with the same name results in an exception.
	*/
	create(name) {
		if (this.#placeholders.has(name)) throw new Error(`Cannot declare stack "${name}" for multiple times`);
		/**
		* Copy content from the seeded placeholders and delete it
		*/
		const seededPlaceholder = this.#seededPlaceholders.get(name) || [];
		this.#seededPlaceholders.delete(name);
		this.#placeholders.set(name, [...seededPlaceholder]);
		return this.#createPlaceholder(name);
	}
	/**
	* Push content inside a given stack. Content can be pre-seeded
	* without creating a stack
	*/
	pushTo(name, contents) {
		let placeholder = this.#placeholders.get(name);
		if (!placeholder) {
			if (!this.#seededPlaceholders.has(name)) this.#seededPlaceholders.set(name, []);
			this.#seededPlaceholders.get(name).push(contents);
			return this;
		}
		/**
		* Defined content for the unique key inside a given
		* stack
		*/
		placeholder.push(contents);
		return this;
	}
	/**
	* Push content to the top inside a given stack.
	* Content can be pre-seeded without creating a stack
	*/
	pushToTop(name, contents) {
		let placeholder = this.#placeholders.get(name);
		if (!placeholder) {
			if (!this.#seededPlaceholders.has(name)) this.#seededPlaceholders.set(name, []);
			this.#seededPlaceholders.get(name).unshift(contents);
			return this;
		}
		/**
		* Defined content for the unique key inside a given
		* stack
		*/
		placeholder.unshift(contents);
		return this;
	}
	/**
	* Push contents to a stack with a unique source id. A
	* source can only push once to a given stack.
	*/
	pushOnceTo(name, sourceId, contents) {
		const contentSources = this.#contentSources.get(name);
		if (contentSources && contentSources.has(sourceId)) return;
		this.pushTo(name, contents);
		/**
		* Track source
		*/
		if (contentSources) contentSources.add(sourceId);
		else this.#contentSources.set(name, new Set([sourceId]));
	}
	/**
	* Push contents to the top of a stack with a unique source id.
	* A source can only push once to a given stack.
	*/
	pushOnceToTop(name, sourceId, contents) {
		const contentSources = this.#contentSources.get(name);
		if (contentSources && contentSources.has(sourceId)) return;
		this.pushToTop(name, contents);
		/**
		* Track source
		*/
		if (contentSources) contentSources.add(sourceId);
		else this.#contentSources.set(name, new Set([sourceId]));
	}
	/**
	* Fill placeholders with their actual content
	*/
	fillPlaceholders(contents) {
		for (let [name, sources] of this.#placeholders) contents = contents.replace(this.#createPlaceholder(name), sources.join(EOL));
		this.#placeholders.clear();
		this.#seededPlaceholders.clear();
		return contents;
	}
};
//#endregion
//#region src/component/props.ts
/**
* Representation of component props with ability to serialize
* them into HTML attributes
*/
var ComponentProps = class ComponentProps {
	#values;
	constructor(values) {
		this.#values = values;
		Object.assign(this, values);
	}
	/**
	* Create a typed instance of Component props with properties
	*/
	static create(values) {
		return new ComponentProps(values);
	}
	/**
	* Reference to props raw values
	*/
	all() {
		return this.#values;
	}
	/**
	* Check if a key exists
	*/
	has(key) {
		return lodash.has(this.#values, key);
	}
	/**
	* Get key value
	*/
	get(key, defaultValue) {
		return lodash.get(this.#values, key, defaultValue);
	}
	/**
	* Returns a new props bag with only the mentioned keys
	*/
	only(keys) {
		return new ComponentProps(lodash.pick(this.#values, keys));
	}
	/**
	* Returns a new props bag with except the mentioned keys
	*/
	except(keys) {
		return new ComponentProps(lodash.omit(this.#values, keys));
	}
	/**
	* Merge defaults with the props
	*
	* - All other attributes will be overwritten when defined in props
	* - Classes will be merged together.
	*/
	merge(values) {
		if (values.class && this.#values["class"]) {
			const classesSet = /* @__PURE__ */ new Set();
			(Array.isArray(values.class) ? values.class : [values]).forEach((item) => {
				classesSet.add(item);
			});
			(Array.isArray(this.#values["class"]) ? this.#values["class"] : [this.#values["class"]]).forEach((item) => {
				classesSet.add(item);
			});
			return new ComponentProps({
				...values,
				...this.#values,
				class: Array.from(classesSet)
			});
		}
		return new ComponentProps({
			...values,
			...this.#values
		});
	}
	/**
	* Merge defaults with the props, if the given condition is truthy
	*/
	mergeIf(conditional, values) {
		if (conditional) return this.merge(values);
		return this;
	}
	/**
	* Merge defaults with the props, if the given condition is falsy
	*/
	mergeUnless(conditional, values) {
		if (!conditional) return this.merge(values);
		return this;
	}
	/**
	* Converts props to HTML attributes
	*/
	toAttrs() {
		return htmlSafe(stringifyAttributes$1(this.#values));
	}
};
//#endregion
//#region src/migrate/props.ts
/**
* Class to ease interactions with component props
*/
var Props = class {
	/**
	* Use ".next" property to migrate to newer
	* api
	*/
	next;
	constructor(props) {
		this[Symbol.for("options")] = { props };
		Object.assign(this, props);
		this.next = new ComponentProps(props);
	}
	/**
	* Merges the className attribute with the class attribute
	*/
	#mergeClassAttributes(props) {
		if (props.className) {
			if (!props.class) props.class = [];
			/**
			* Normalize class attribute to be an array
			*/
			if (!Array.isArray(props.class)) props.class = [props.class];
			props.class = props.class.concat(props.className);
			props.className = false;
		}
		return props;
	}
	/**
	* Find if a key exists inside the props
	*/
	has(key) {
		const value = this.get(key);
		return value !== void 0 && value !== null;
	}
	/**
	* Get value for a given key
	*/
	get(key, defaultValue) {
		return lodash.get(this.all(), key, defaultValue);
	}
	/**
	* Returns all the props
	*/
	all() {
		return this[Symbol.for("options")].props;
	}
	/**
	* Validate prop value
	*/
	validate(key, validateFn) {
		validateFn(key, this.get(key));
	}
	/**
	* Return values for only the given keys
	*/
	only(keys) {
		return lodash.pick(this.all(), keys);
	}
	/**
	* Return values except the given keys
	*/
	except(keys) {
		return lodash.omit(this.all(), keys);
	}
	/**
	* Serialize all props to a string of HTML attributes
	*/
	serialize(mergeProps, prioritizeInline = true) {
		/**
		* Prioritize user attributes when prioritizeInline=false
		*/
		const attributes = prioritizeInline ? lodash.merge({}, this.all(), mergeProps) : lodash.merge({}, mergeProps, this.all());
		return htmlSafe(stringifyAttributes(this.#mergeClassAttributes(attributes)));
	}
	/**
	* Serialize only the given keys to a string of HTML attributes
	*/
	serializeOnly(keys, mergeProps, prioritizeInline = true) {
		/**
		* Prioritize user attributes when prioritizeInline=false
		*/
		const attributes = prioritizeInline ? lodash.merge({}, this.only(keys), mergeProps) : lodash.merge({}, mergeProps, this.only(keys));
		return htmlSafe(stringifyAttributes(this.#mergeClassAttributes(attributes)));
	}
	/**
	* Serialize except the given keys to a string of HTML attributes
	*/
	serializeExcept(keys, mergeProps, prioritizeInline = true) {
		/**
		* Prioritize user attributes when prioritizeInline=false
		*/
		const attributes = prioritizeInline ? lodash.merge({}, this.except(keys), mergeProps) : lodash.merge({}, mergeProps, this.except(keys));
		return htmlSafe(stringifyAttributes(this.#mergeClassAttributes(attributes)));
	}
};
//#endregion
//#region src/template.ts
/**
* An instance of this class passed to the escape
* method ensures that underlying value is never
* escaped.
*/
var SafeValue = class {
	value;
	constructor(value) {
		this.value = value;
	}
};
/**
* Escapes a given string
*/
function escape(input) {
	return input instanceof SafeValue ? input.value : he.escape(String(input));
}
/**
* Mark value as safe and not to be escaped
*/
function htmlSafe(value) {
	return new SafeValue(value);
}
/**
* The template is used to compile and run templates. Also the instance
* of template is passed during runtime to render `dynamic partials`
* and `dynamic components`.
*/
var Template = class extends Macroable {
	#compiler;
	#processor;
	/**
	* The shared state is used to hold the globals and locals,
	* since it is shared with components too.
	*/
	#sharedState;
	/**
	* Template stacks holds a collection of placeholders
	* and their content to be filled before returning
	* the output.
	*/
	stacks = new Stacks();
	constructor(compiler, globals, locals, processor) {
		super();
		this.#compiler = compiler;
		this.#processor = processor;
		this.#sharedState = compiler.compat ? lodash.merge({}, globals, locals) : {
			...globals,
			...locals
		};
	}
	/**
	* Trims top and bottom new lines from the content
	*/
	#trimTopBottomNewLines(value) {
		return value.replace(/^\n|^\r\n/, "").replace(/\n$|\r\n$/, "");
	}
	/**
	* Render a compiled template with state
	*/
	#renderCompiled(compiledTemplate, state) {
		const templateState = {
			...this.#sharedState,
			...state
		};
		const $context = {};
		/**
		* Process template as a promise.
		*/
		if (this.#compiler.async) return compiledTemplate(this, templateState, $context).then((output) => {
			output = this.#trimTopBottomNewLines(output);
			output = this.stacks.fillPlaceholders(output);
			return this.#processor.executeOutput({
				output,
				template: this,
				state: templateState
			});
		});
		let output = this.#trimTopBottomNewLines(compiledTemplate(this, templateState, $context));
		output = this.stacks.fillPlaceholders(output);
		return this.#processor.executeOutput({
			output,
			template: this,
			state: templateState
		});
	}
	/**
	* Render a partial
	*
	* ```js
	* const partialFn = template.compilePartial('includes/user')
	*
	* // render and use output
	* partialFn(template, state, ctx)
	* ```
	*/
	compilePartial(templatePath, ...localVariables) {
		return this.#compiler.compile(templatePath, localVariables);
	}
	/**
	* Render a component
	*
	* ```js
	* const componentFn = template.compileComponent('components/button')
	*
	* // render and use output
	* componentFn(template, template.getComponentState(props, slots, caller), ctx)
	* ```
	*/
	compileComponent(templatePath) {
		return this.#compiler.compile(templatePath);
	}
	/**
	* Returns the isolated state for a given component
	*/
	getComponentState(props, slots, caller) {
		return {
			...this.#sharedState,
			...props,
			$slots: slots,
			$caller: caller,
			$props: this.#compiler.compat ? new Props(props) : new ComponentProps(props)
		};
	}
	/**
	* Render a template with it's state.
	*
	* ```js
	* template.render('welcome', { key: 'value' })
	* ```
	*/
	render(template, state) {
		let compiledTemplate = this.#compiler.compile(template);
		return this.#renderCompiled(compiledTemplate, state);
	}
	/**
	* Render template from a raw string
	*
	* ```js
	* template.renderRaw('Hello {{ username }}', { username: 'virk' })
	* ```
	*/
	renderRaw(contents, state, templatePath) {
		let compiledTemplate = this.#compiler.compileRaw(contents, templatePath);
		return this.#renderCompiled(compiledTemplate, state);
	}
	/**
	* Escapes the value to be HTML safe. Only strings are escaped
	* and rest all values will be returned as it is.
	*/
	escape(input) {
		return escape(input);
	}
	/**
	* Creates an instance of the EdgeError
	*/
	createError(errorMessage, filename, lineNumber, column) {
		return new EdgeError(errorMessage, "E_RUNTIME_EXCEPTION", {
			filename,
			line: lineNumber,
			col: column
		});
	}
	/**
	* Throws EdgeError. Use "createError" to create a new
	* error instance
	*/
	newError(errorMessage, filename, lineNumber, column) {
		throw this.createError(errorMessage, filename, lineNumber, column);
	}
	/**
	* Rethrows the runtime exception by re-constructing the error message
	* to point back to the original filename
	*/
	reThrow(error, filename, lineNumber) {
		if (error instanceof EdgeError) throw error;
		throw new EdgeError(error.message.replace(/state\./, ""), "E_RUNTIME_EXCEPTION", {
			filename,
			line: lineNumber,
			col: 0
		});
	}
};
//#endregion
//#region node_modules/js-stringify/index.js
var require_js_stringify = /* @__PURE__ */ __commonJSMin(((exports, module) => {
	module.exports = stringify;
	function stringify(obj) {
		if (obj instanceof Date) return "new Date(" + stringify(obj.toISOString()) + ")";
		if (obj === void 0) return "undefined";
		return JSON.stringify(obj).replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029").replace(/</g, "\\u003C").replace(/>/g, "\\u003E").replace(/\//g, "\\u002F");
	}
}));
//#endregion
export { StringifiedObject as a, isNotSubsetOf as c, parseJsArg as d, stringifyAttributes$1 as f, __toESM as g, __exportAll as h, htmlSafe as i, isSubsetOf as l, require_classnames as m, Template as n, asyncEach as o, unallowedExpression as p, escape as r, each as s, require_js_stringify as t, nanoid as u };
