//#region node_modules/sugar-high/lib/index.js
var JSXBrackets = new Set([
	"<",
	">",
	"{",
	"}",
	"[",
	"]"
]);
var Keywords_Js = new Set([
	"for",
	"do",
	"while",
	"if",
	"else",
	"return",
	"function",
	"var",
	"let",
	"const",
	"true",
	"false",
	"undefined",
	"this",
	"new",
	"delete",
	"typeof",
	"in",
	"instanceof",
	"void",
	"break",
	"continue",
	"switch",
	"case",
	"default",
	"throw",
	"try",
	"catch",
	"finally",
	"debugger",
	"with",
	"yield",
	"async",
	"await",
	"class",
	"extends",
	"super",
	"import",
	"export",
	"from",
	"static"
]);
var Keywords_Ts = new Set([
	...Keywords_Js,
	"type",
	"interface",
	"enum",
	"implements",
	"readonly",
	"abstract",
	"declare",
	"namespace",
	"module",
	"private",
	"protected",
	"public",
	"override",
	"keyof",
	"infer",
	"is",
	"asserts",
	"satisfies",
	"as",
	"unknown",
	"never",
	"any",
	"number",
	"string",
	"boolean",
	"bigint",
	"symbol",
	"object"
]);
var Signs = new Set([
	"+",
	"-",
	"*",
	"/",
	"%",
	"=",
	"!",
	"&",
	"|",
	"^",
	"~",
	"!",
	"?",
	":",
	".",
	",",
	";",
	`'`,
	"\"",
	".",
	"(",
	")",
	"[",
	"]",
	"#",
	"@",
	"\\",
	...JSXBrackets
]);
var DefaultOptions = {
	keywords: Keywords_Js,
	onCommentStart: isCommentStart_Js,
	onCommentEnd: isCommentEnd_Js
};
/**
* Fast, heuristic TS detection. It intentionally prefers speed over full parsing.
* @param {string} code
* @returns {boolean}
*/
function isLikelyTypeScript(code) {
	let tsScore = 0;
	if (/\binterface\s+[A-Za-z_$][\w$]*/.test(code)) tsScore += 2;
	if (/\btype\s+[A-Za-z_$][\w$]*\s*=/.test(code)) tsScore += 2;
	if (/\benum\s+[A-Za-z_$][\w$]*/.test(code)) tsScore += 2;
	if (/\b(?:implements|readonly|declare|namespace|satisfies|infer|keyof|asserts)\b/.test(code)) tsScore += 2;
	if (/:\s*[A-Za-z_$][\w$]*(?:<[^>\n]+>)?(?:\[\])?(?=\s*[,)=;{])/m.test(code)) tsScore += 1;
	if (/\b(?:const|let|var)\s+[A-Za-z_$][\w$]*\s*:\s*/.test(code)) tsScore += 1;
	if (/\)\s*:\s*[A-Za-z_$][\w$]*(?:<[^>\n]+>)?(?:\[\])?\s*(?:=>|\{)/.test(code)) tsScore += 1;
	return tsScore >= 2;
}
/**
* Detects `<T, U = ...>(` style generic parameter lists so they are not
* treated as JSX tags.
* @param {string} code
* @param {number} startIndex
* @returns {boolean}
*/
function isTypeParameterListStart(code, startIndex) {
	if (code[startIndex] !== "<") return false;
	let depth = 0;
	let sawIdentifierStart = false;
	for (let i = startIndex; i < code.length; i++) {
		const ch = code[i];
		if (ch === "<") {
			depth++;
			continue;
		}
		if (ch === ">") {
			depth--;
			if (depth === 0) {
				let next = i + 1;
				while (next < code.length && /\s/.test(code[next])) next++;
				if (!(sawIdentifierStart && code[next] === "(")) return false;
				const tail = code.slice(next, next + 320);
				return /\)\s*(?::[\s\S]{0,120}?)?=>/.test(tail);
			}
			continue;
		}
		if (depth === 0) continue;
		if (/[$A-Za-z_]/.test(ch)) {
			sawIdentifierStart = true;
			continue;
		}
		if (/[\s,\.\=\?\:\|\&\[\]]/.test(ch)) continue;
		return false;
	}
	return false;
}
/**
*
* 0  - identifier
* 1  - keyword
* 2  - string
* 3  - Class, number and null
* 4  - property
* 5  - entity
* 6  - jsx literals
* 7  - sign
* 8  - comment
* 9  - break
* 10 - space
*
*/
var TokenTypes = [
	"identifier",
	"keyword",
	"string",
	"class",
	"property",
	"entity",
	"jsxliterals",
	"sign",
	"comment",
	"break",
	"space"
];
var [T_IDENTIFIER, T_KEYWORD, T_STRING, T_CLS_NUMBER, T_PROPERTY, T_ENTITY, T_JSX_LITERALS, T_SIGN, T_COMMENT, T_BREAK, T_SPACE] = TokenTypes.map((_, i) => i);
function isSpaces(str) {
	return /^[^\S\r\n]+$/g.test(str);
}
function isSign(ch) {
	return Signs.has(ch);
}
function encode(str) {
	return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
}
function isWord(chr) {
	return /^[\w_]+$/.test(chr) || hasUnicode(chr);
}
function isCls(str) {
	const chr0 = str[0];
	return isWord(chr0) && chr0 === chr0.toUpperCase() || str === "null";
}
function hasUnicode(s) {
	return /[^\u0000-\u007f]/.test(s);
}
function isAlpha(chr) {
	return /^[a-zA-Z]$/.test(chr);
}
function isIdentifierChar(chr) {
	return isAlpha(chr) || hasUnicode(chr);
}
function isIdentifier(str) {
	return isIdentifierChar(str[0]) && (str.length === 1 || isWord(str.slice(1)));
}
function isStrTemplateChr(chr) {
	return chr === "`";
}
function isSingleQuotes(chr) {
	return chr === "\"" || chr === "'";
}
function isStringQuotation(chr) {
	return isSingleQuotes(chr) || isStrTemplateChr(chr);
}
/** @returns {0|1|2}  */
function isCommentStart_Js(curr, next) {
	const str = curr + next;
	if (str === "/*") return 2;
	return str === "//" ? 1 : 0;
}
/** @returns {0|1|2}  */
function isCommentEnd_Js(prev, curr) {
	return prev + curr === "*/" ? 2 : curr === "\n" ? 1 : 0;
}
function isRegexStart(str) {
	return str[0] === "/" && !isCommentStart_Js(str[0], str[1]);
}
/**
* @param {string} code
* @param {{
*   keywords?: Set<string>
*   typeKeywords?: Set<string>
*   onCommentStart?: (curr: string, next: string) => number | boolean
*   onCommentEnd?: (prev: string, curr: string) => number | boolean
*   onQuote?: (curr: string, i: number, code: string) => number | null | undefined
* } | undefined} options
* Optional `onQuote(curr, i, code)` at `code[i] === "'"`: return length to consume from `i` (>= 1),
* or null/undefined/below 1 for default JS single-quoted strings. No substring allocation.
* @return {Array<[number, string]>}
*/
function tokenize(code, options) {
	const mergedOptions = {
		...DefaultOptions,
		...options
	};
	const hasCustomKeywords = !!(options && options.keywords instanceof Set);
	const isTs = isLikelyTypeScript(code);
	const resolvedKeywords = hasCustomKeywords ? mergedOptions.keywords : isTs ? Keywords_Ts : Keywords_Js;
	const { onCommentStart, onCommentEnd } = mergedOptions;
	const resolvedTypeKeywords = mergedOptions.typeKeywords instanceof Set ? mergedOptions.typeKeywords : null;
	let current = "";
	let type = -1;
	/** @type {[number, string]} */
	let last = [-1, ""];
	/** @type {[number, string]} */
	let beforeLast = [-2, ""];
	/** @type {Array<[number, string]>} */
	const tokens = [];
	/**
	* TS generics (`Map<string>`) and JSX (`<div>`) share the same `<Name …>` lexical shape. We use
	* one tag-lexer mode (__jsxTag + __jsxStack) for both when we enter it; isTsTypeArgStart and
	* isTypeParameterListStart only decide when *not* to enter (e.g. `foo<T>`, `<T>(x)=>`).
	* __jsxEnter gates that mode so a latched __jsxTag (from `<` in `"a<b"`) does not run the tag
	* lexer until we are in real JSX/TSX surface (not inside strings).
	* @type {boolean}
	*/
	let __jsxEnter = false;
	/** @type {0 | 1 | 2} 0 = none; 1 = inside `<open`; 2 = inside `</close` */
	let __jsxTag = 0;
	let __jsxExpr = false;
	/** Nested `<open>…</open>` depth (content between tags, including nested elements). */
	let __jsxStack = 0;
	const __jsxChild = () => __jsxEnter && !__jsxExpr && !__jsxTag;
	const inJsxTag = () => __jsxTag && !__jsxChild();
	const inJsxLiterals = () => !__jsxTag && __jsxChild() && !__jsxExpr && __jsxStack > 0;
	/** @type {string | null} */
	let __strQuote = null;
	let __regexQuoteStart = false;
	let __strTemplateExprStack = 0;
	let __strTemplateQuoteStack = 0;
	const inStringQuotes = () => __strQuote !== null;
	const inRegexQuotes = () => __regexQuoteStart;
	const inStrTemplateLiterals = () => __strTemplateQuoteStack > __strTemplateExprStack;
	const inStrTemplateExpr = () => __strTemplateQuoteStack > 0 && __strTemplateQuoteStack === __strTemplateExprStack;
	const inStringContent = () => inStringQuotes() || inStrTemplateLiterals();
	/**
	*
	* @param {string} token
	* @returns {number}
	*/
	function classify(token) {
		const isLineBreak = token === "\n";
		if (inJsxTag()) {
			if (inStringQuotes()) return T_STRING;
			const [, lastToken] = last;
			if (isIdentifier(token)) {
				if (lastToken === "<" || lastToken === "</") return T_ENTITY;
			}
		}
		if (inJsxLiterals()) return T_JSX_LITERALS;
		if (inStringQuotes() || inStrTemplateLiterals()) return T_STRING;
		else if (resolvedTypeKeywords && resolvedTypeKeywords.has(token)) return last[1] === "." ? T_IDENTIFIER : T_CLS_NUMBER;
		else if (resolvedKeywords.has(token)) return last[1] === "." ? T_IDENTIFIER : T_KEYWORD;
		else if (isLineBreak) return T_BREAK;
		else if (isSpaces(token)) return T_SPACE;
		else if (token.split("").every(isSign)) return T_SIGN;
		else if (isCls(token)) return inJsxTag() ? T_IDENTIFIER : T_CLS_NUMBER;
		else {
			if (isIdentifier(token)) {
				const isLastPropDot = last[1] === "." && isIdentifier(beforeLast[1]);
				if (!inStringContent() && !isLastPropDot) return T_IDENTIFIER;
				if (isLastPropDot) return T_PROPERTY;
			}
			return T_STRING;
		}
	}
	/**
	*
	* @param {number | undefined} [type_]
	* @param {string | undefined} [token_]
	*/
	const append = (type_, token_) => {
		if (token_) current = token_;
		if (current) {
			type = typeof type_ === "number" ? type_ : classify(current);
			/** @type [number, string]  */
			const pair = [type, current];
			if (type !== T_SPACE && type !== T_BREAK) {
				beforeLast = last;
				last = pair;
			}
			tokens.push(pair);
		}
		current = "";
	};
	for (let i = 0; i < code.length; i++) {
		const curr = code[i];
		const prev = code[i - 1];
		const next = code[i + 1];
		const p_c = prev + curr;
		const c_n = curr + next;
		if (typeof mergedOptions.onQuote === "function" && curr === "'" && !inStringQuotes() && !inJsxLiterals() && !inStrTemplateLiterals()) {
			const rawLen = mergedOptions.onQuote(curr, i, code);
			if (typeof rawLen === "number" && rawLen >= 1 && !Number.isNaN(rawLen)) {
				const len = Math.min(rawLen, code.length - i);
				const end = i + len;
				append();
				current = code.slice(i, end);
				append(T_IDENTIFIER);
				i = end - 1;
				continue;
			}
		}
		if (isSingleQuotes(curr) && !inJsxLiterals() && !inStrTemplateLiterals()) {
			append();
			if (prev !== `\\`) {
				if (__strQuote && curr === __strQuote) __strQuote = null;
				else if (!__strQuote) __strQuote = curr;
			}
			append(T_STRING, curr);
			continue;
		}
		if (!inStrTemplateLiterals()) {
			if (prev !== "\\n" && isStrTemplateChr(curr)) {
				append();
				append(T_STRING, curr);
				__strTemplateQuoteStack++;
				continue;
			}
		}
		if (inStrTemplateLiterals()) {
			if (prev !== "\\n" && isStrTemplateChr(curr)) {
				if (__strTemplateQuoteStack > 0) {
					append();
					__strTemplateQuoteStack--;
					append(T_STRING, curr);
					continue;
				}
			}
			if (c_n === "${") {
				__strTemplateExprStack++;
				append(T_STRING);
				append(T_SIGN, c_n);
				i++;
				continue;
			}
		}
		if (inStrTemplateExpr() && curr === "}") {
			append();
			__strTemplateExprStack--;
			append(T_SIGN, curr);
			continue;
		}
		if (__jsxChild()) {
			if (curr === "{") {
				append();
				append(T_SIGN, curr);
				__jsxExpr = true;
				continue;
			}
		}
		if (__jsxEnter) {
			if (!__jsxTag && curr === "<") {
				append();
				if (next === "/") {
					__jsxTag = 2;
					current = c_n;
					i++;
				} else {
					__jsxTag = 1;
					current = curr;
				}
				append(T_SIGN);
				continue;
			}
			if (__jsxTag) {
				if (curr === ">" && !"/=".includes(prev)) {
					append();
					if (__jsxTag === 1) {
						__jsxTag = 0;
						__jsxStack++;
					} else {
						__jsxTag = 0;
						__jsxEnter = false;
					}
					append(T_SIGN, curr);
					continue;
				}
				if (c_n === "/>" || c_n === "</") {
					if (current !== "<" && current !== "/") append();
					if (c_n === "/>") __jsxTag = 0;
					else __jsxStack--;
					if (!__jsxStack) __jsxEnter = false;
					current = c_n;
					i++;
					append(T_SIGN);
					continue;
				}
				if (curr === "<") {
					append();
					current = curr;
					append(T_SIGN);
					continue;
				}
				if (next === "-" && !inStringContent() && !inJsxLiterals()) {
					if (current) {
						append(T_PROPERTY, current + curr + next);
						i++;
						continue;
					}
				}
				if (next === "=" && !inStringContent()) {
					if (!isSpaces(curr)) {
						if (isSpaces(current)) append();
						const prop = current + curr;
						if (isIdentifier(prop)) {
							append(T_PROPERTY, prop);
							continue;
						}
					}
				}
			}
		}
		if (!__jsxTag && (curr === "<" && isIdentifierChar(next) || c_n === "</")) {
			let prevNonSpace = i - 1;
			while (prevNonSpace >= 0 && /\s/.test(code[prevNonSpace])) prevNonSpace--;
			const prevChar = prevNonSpace >= 0 ? code[prevNonSpace] : "";
			const [lastType, lastTok] = last;
			let typeArgFromPending = false;
			let jsxFromPending = false;
			if (current && !isSpaces(current)) {
				const w = current;
				if (isCls(w) || w === "true" || w === "false") typeArgFromPending = true;
				else if (resolvedKeywords.has(w) && isIdentifier(w)) jsxFromPending = true;
				else if (isIdentifier(w)) typeArgFromPending = true;
			}
			const isTsTypeArgStart = curr === "<" && /[$\w\]\)]/.test(prevChar) && (typeArgFromPending || !jsxFromPending && (lastType === T_IDENTIFIER || lastType === T_CLS_NUMBER || lastType === T_SIGN && (lastTok === ")" || lastTok === "]")));
			const isTsGenericStart = curr === "<" && isTypeParameterListStart(code, i);
			if (!isTsTypeArgStart && !isTsGenericStart) __jsxTag = next === "/" ? 2 : 1;
			if (curr === "<" && (next === "/" || isAlpha(next))) {
				if (!isTsTypeArgStart && !isTsGenericStart && !inStringContent() && !inJsxLiterals() && !inRegexQuotes()) __jsxEnter = true;
			}
		}
		const isQuotationChar = isStringQuotation(curr);
		const isStringTemplateLiterals = inStrTemplateLiterals();
		const isRegexChar = !__jsxEnter && isRegexStart(c_n);
		const isJsxLiterals = inJsxLiterals();
		if (isQuotationChar || isStringTemplateLiterals || isSingleQuotes(__strQuote)) current += curr;
		else if (isRegexChar) {
			append();
			const [lastType, lastToken] = last;
			if (isRegexChar && lastType !== -1 && !(lastType === T_SIGN && ")" !== lastToken || lastType === T_COMMENT)) {
				current = curr;
				append();
				continue;
			}
			__regexQuoteStart = true;
			const start = i++;
			const isEof = () => i >= code.length;
			const isEol = () => isEof() || code[i] === "\n";
			let foundClose = false;
			for (; !isEol(); i++) if (code[i] === "/" && code[i - 1] !== "\\") {
				foundClose = true;
				while (start !== i && /^[a-z]$/.test(code[i + 1]) && !isEol()) i++;
				break;
			}
			__regexQuoteStart = false;
			if (start !== i && foundClose) {
				current = code.slice(start, i + 1);
				append(T_STRING);
			} else {
				current = curr;
				append();
				i = start;
			}
		} else if (onCommentStart(curr, next)) {
			append();
			const start = i;
			const startCommentType = onCommentStart(curr, next);
			if (startCommentType) {
				for (; i < code.length; i++) if (onCommentEnd(code[i - 1], code[i]) == startCommentType) break;
			}
			current = code.slice(start, i + 1);
			append(T_COMMENT);
		} else if (curr === " " || curr === "\n") if (curr === " " && (isSpaces(current) || !current || isJsxLiterals)) {
			current += curr;
			if (next === "<") append();
		} else {
			append();
			current = curr;
			append();
		}
		else if (__jsxExpr && curr === "}") {
			append();
			current = curr;
			append();
			__jsxExpr = false;
		} else if (isJsxLiterals && !JSXBrackets.has(curr) || inStrTemplateLiterals() || (isWord(curr) === isWord(current[current.length - 1]) || __jsxChild()) && !Signs.has(curr)) current += curr;
		else {
			if (p_c === "</") current = p_c;
			append();
			if (p_c !== "</") current = curr;
			if (c_n === "</" || c_n === "/>") {
				current = c_n;
				append();
				i++;
			} else if (JSXBrackets.has(curr)) append();
		}
	}
	append();
	return tokens;
}
/**
* @param {Array<[number, string]>} tokens
* @return {Array<{type: string, tagName: string, children: any[], properties: Record<string, string>}>}
*/
function generate(tokens) {
	const lines = [];
	/**
	* @param {any} children
	* @return {{type: string, tagName: string, children: any[], properties: Record<string, string>}}
	*/
	const createLine = (children) => ({
		type: "element",
		tagName: "span",
		children,
		properties: { className: "sh__line" }
	});
	/**
	* @param {Array<[number, string]>} tokens
	* @returns {void}
	*/
	function flushLine(tokens) {
		/** @type {Array<any>} */
		const lineTokens = tokens.map(([type, value]) => {
			const tokenType = TokenTypes[type];
			return {
				type: "element",
				tagName: "span",
				children: [{
					type: "text",
					value
				}],
				properties: {
					className: `sh__token--${tokenType}`,
					style: { color: `var(--sh-${tokenType})` }
				}
			};
		});
		lines.push(createLine(lineTokens));
	}
	/** @type {Array<[number, string]>} */
	const lineTokens = [];
	let lastWasBreak = false;
	for (let i = 0; i < tokens.length; i++) {
		const token = tokens[i];
		const [type, value] = token;
		const isLastToken = i === tokens.length - 1;
		if (type !== T_BREAK) {
			if (value.includes("\n")) {
				const lines = value.split("\n");
				for (let j = 0; j < lines.length; j++) {
					lineTokens.push([type, lines[j]]);
					if (j < lines.length - 1) {
						flushLine(lineTokens);
						lineTokens.length = 0;
					}
				}
			} else lineTokens.push(token);
			lastWasBreak = false;
		} else {
			if (lastWasBreak) flushLine([]);
			else {
				flushLine(lineTokens);
				lineTokens.length = 0;
			}
			if (isLastToken) flushLine([]);
			lastWasBreak = true;
		}
	}
	if (lineTokens.length) flushLine(lineTokens);
	return lines;
}
/** @param {{ className: string, style?: Record<string, string> }} props */
var propsToString = (props) => {
	let str = `class="${props.className}"`;
	if (props.style) {
		const style = Object.entries(props.style).map(([key, value]) => `${key}:${value}`).join(";");
		str += ` style="${style}"`;
	}
	return str;
};
function toHtml(lines) {
	return lines.map((line) => {
		const { tagName: lineTag } = line;
		const tokens = line.children.map((child) => {
			const { tagName, children, properties } = child;
			return `<${tagName} ${propsToString(properties)}>${encode(children[0].value)}</${tagName}>`;
		}).join("");
		return `<${lineTag} class="${line.properties.className}">${tokens}</${lineTag}>`;
	}).join("\n");
}
/**
*
* @param {string} code
* @param {{
*   keywords?: Set<string>
*   typeKeywords?: Set<string>
*   onCommentStart?: (curr: string, next: string) => number | boolean
*   onCommentEnd?: (curr: string, prev: string) => number | boolean
*   onQuote?: (curr: string, i: number, code: string) => number | null | undefined
* } | undefined} options
* `onQuote` same as `tokenize`.
* @returns {string}
*/
function highlight(code, options) {
	return toHtml(generate(tokenize(code, options)));
}
/** @type {const} */ new Map(TokenTypes.map((type, i) => [type, i]));
//#endregion
export { highlight };

//# sourceMappingURL=index77.js.map