feat: Reinitialize frontend with SvelteKit and TypeScript

- Delete old Vite+Svelte frontend
- Initialize new SvelteKit project with TypeScript
- Configure Tailwind CSS v4 + DaisyUI
- Implement JWT authentication with auto-refresh
- Create login page with form validation (Zod)
- Add protected route guards
- Update Docker configuration for single-stage build
- Add E2E tests with Playwright (6/11 passing)
- Fix Svelte 5 reactivity with $state() runes

Known issues:
- 5 E2E tests failing (timing/async issues)
- Token refresh implementation needs debugging
- Validation error display timing
This commit is contained in:
2026-02-17 16:19:59 -05:00
parent 54df6018f5
commit de2d83092e
28274 changed files with 3816354 additions and 90 deletions

15
frontend/node_modules/arkregex/out/charset.d.ts generated vendored Normal file
View File

@@ -0,0 +1,15 @@
import type { Backslash, ErrorMessage, noSuggest, Scanner, writeUnclosedGroupMessage } from "@ark/util";
import type { parseEscapedChar, StringDigit } from "./escape.ts";
import type { s, State } from "./state.ts";
export type parseCharset<s extends State, unscanned extends string> = Scanner.shiftUntilEscapable<unscanned, "]", Backslash> extends (Scanner.shiftResult<infer scanned, infer nextUnscanned>) ? nextUnscanned extends `]${infer remaining}` ? scanned extends Scanner.shift<"^", string> ? s.shiftQuantifiable<s, string, remaining> : parseNonNegatedCharset<scanned, never, null> extends (infer result extends string) ? [
result
] extends [never] ? s.error<emptyCharacterSetMessage> : s.shiftQuantifiable<s, result, remaining> : never : s.error<writeUnclosedGroupMessage<"]">> : never;
type parseNonNegatedCharset<chars extends string, set extends string, lastChar extends string | null> = parseChar<chars> extends Scanner.shiftResult<infer result, infer unscanned> ? result extends UnescapedDashMarker ? parseDash<unscanned, set, lastChar> : result extends ErrorMessage ? result : parseNonNegatedCharset<unscanned, set | result, result> : set;
type parseDash<unscanned extends string, set extends string, lastChar extends string | null> = lastChar extends string ? parseChar<unscanned> extends (Scanner.shiftResult<infer rangeEnd, infer next>) ? parseNonNegatedCharset<next, set | inferRange<lastChar, rangeEnd>, null> : // trailing -, treat as literal
set | "-" : parseNonNegatedCharset<unscanned, set | "-", "-">;
type inferRange<start extends string, end extends string> = start | end extends StringDigit ? `${number}` : string;
type UnescapedDashMarker = noSuggest<"dash">;
type parseChar<unscanned extends string> = unscanned extends Scanner.shift<infer lookahead, infer next> ? lookahead extends Backslash ? next extends Scanner.shift<infer escaped, infer postEscaped> ? Scanner.shiftResult<parseEscapedChar<escaped>, postEscaped> : never : Scanner.shiftResult<lookahead extends "-" ? UnescapedDashMarker : lookahead, next> : null;
export declare const emptyCharacterSetMessage = "Empty character set [] is unsatisfiable";
export type emptyCharacterSetMessage = typeof emptyCharacterSetMessage;
export {};

1
frontend/node_modules/arkregex/out/charset.js generated vendored Normal file
View File

@@ -0,0 +1 @@
export const emptyCharacterSetMessage = "Empty character set [] is unsatisfiable";

29
frontend/node_modules/arkregex/out/escape.d.ts generated vendored Normal file
View File

@@ -0,0 +1,29 @@
import type { ErrorMessage, Scanner, WhitespaceChar } from "@ark/util";
import type { Control, ReferenceNode, s, State } from "./state.ts";
export type parseEscape<s extends State, unscanned extends string> = unscanned extends Scanner.shift<infer char, infer nextUnscanned> ? char extends NonZeroDigit ? parseNumericBackreference<s, unscanned> : char extends "k" ? parseNamedBackreference<s, nextUnscanned> : char extends UnicodePropertyChar ? parseUnicodeProperty<s, char, nextUnscanned> : parseSingleEscapedCharacter<s, char, nextUnscanned> : s.error<trailingBackslashMessage>;
type parseNumericBackreference<s extends State, fullUnscanned extends string> = Scanner.shiftUntilNot<fullUnscanned, StringDigit> extends (Scanner.shiftResult<infer ref, infer remaining>) ? s.shiftQuantifiable<s, ReferenceNode<ref>, remaining> : never;
type parseNamedBackreference<s extends State, unscanned extends string> = unscanned extends `<${infer ref}>${infer following}` ? s.shiftQuantifiable<s, ReferenceNode<ref>, following> : s.error<missingBackreferenceNameMessage>;
type parseUnicodeProperty<s extends State, char extends UnicodePropertyChar, unscanned extends string> = unscanned extends `{${string}}${infer following}` ? s.shiftQuantifiable<s, string, following> : s.error<writeInvalidUnicodePropertyMessage<char>>;
type parseSingleEscapedCharacter<s extends State, char extends string, remaining extends string> = parseEscapedChar<char> extends infer result extends string ? result extends ErrorMessage ? s.error<result> : s.shiftQuantifiable<s, result, remaining> : never;
export type parseEscapedChar<char extends string> = char extends RegexClassChar ? string : char extends "d" ? `${number}` : char extends "s" ? WhitespaceChar : char extends BoundaryChar ? "" : char extends Control ? char : char extends "c" ? ErrorMessage<caretNotationMessage> : char extends StringEscapableChar ? ErrorMessage<writeStringEscapableMessage<char>> : ErrorMessage<writeUnnecessaryEscapeMessage<char>>;
export declare const trailingBackslashMessage = "A regex cannot end with \\";
export type trailingBackslashMessage = typeof trailingBackslashMessage;
export declare const writeUnresolvableBackreferenceMessage: <ref extends string | number>(ref: ref) => writeUnresolvableBackreferenceMessage<ref>;
export type writeUnresolvableBackreferenceMessage<ref extends string | number> = `Group ${ref} does not exist`;
export declare const missingBackreferenceNameMessage = "\\k must be followed by a named reference like <name>";
export type missingBackreferenceNameMessage = typeof missingBackreferenceNameMessage;
export declare const writeInvalidUnicodePropertyMessage: <char extends UnicodePropertyChar>(char: char) => writeInvalidUnicodePropertyMessage<char>;
export type writeInvalidUnicodePropertyMessage<char extends UnicodePropertyChar> = `\\${char} must be followed by a property like \\${char}{Emoji_Presentation}`;
export declare const writeUnnecessaryEscapeMessage: <char extends string>(char: char) => writeUnnecessaryEscapeMessage<char>;
export type writeUnnecessaryEscapeMessage<char extends string> = `Escape preceding ${char} is unnecessary and should be removed.`;
export declare const writeStringEscapableMessage: (char: StringEscapableChar) => "\\v should be specified with a single backslash like regex('\\n')" | "\\u should be specified with a single backslash like regex('\\n')" | "\\0 should be specified with a single backslash like regex('\\n')" | "\\t should be specified with a single backslash like regex('\\n')" | "\\n should be specified with a single backslash like regex('\\n')" | "\\r should be specified with a single backslash like regex('\\n')" | "\\f should be specified with a single backslash like regex('\\n')" | "\\x should be specified with a single backslash like regex('\\n')";
export type writeStringEscapableMessage<char extends StringEscapableChar> = `\\${char} should be specified with a single backslash like regex('\n')`;
export declare const caretNotationMessage = "\\\\cX notation is not supported. Use hex (\\\\x) or unicode (\\\\u) instead.";
export type caretNotationMessage = "\\cX notation is not supported. Use hex (\\x) or unicode (\\u) instead.";
export type StringEscapableChar = "t" | "n" | "r" | "f" | "v" | "0" | "x" | "u";
export type RegexClassChar = "w" | "W" | "D" | "S";
export type BoundaryChar = "b" | "B";
export type UnicodePropertyChar = "p" | "P";
export type NonZeroDigit = "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9";
export type StringDigit = "0" | NonZeroDigit;
export {};

10
frontend/node_modules/arkregex/out/escape.js generated vendored Normal file
View File

@@ -0,0 +1,10 @@
export const trailingBackslashMessage = "A regex cannot end with \\";
export const writeUnresolvableBackreferenceMessage = (ref) => `Group ${ref} does not exist`;
export const missingBackreferenceNameMessage = "\\k must be followed by a named reference like <name>";
export const writeInvalidUnicodePropertyMessage = (char) => `\\${char} must be followed by a property like \\${char}{Emoji_Presentation}`;
export const writeUnnecessaryEscapeMessage = (char) => `Escape preceding ${char} is unnecessary and should be removed.`;
// we have to add extra backslashes to the runtime variants of these
// so that attest can compare them correctly to their type-level equivalents
// the runtime variants are only used for the tests
export const writeStringEscapableMessage = (char) => `\\${char} should be specified with a single backslash like regex('\\n')`;
export const caretNotationMessage = "\\\\cX notation is not supported. Use hex (\\\\x) or unicode (\\\\u) instead.";

23
frontend/node_modules/arkregex/out/execArray.d.ts generated vendored Normal file
View File

@@ -0,0 +1,23 @@
import type { DynamicBase } from "@ark/util";
import type { Flags, IndexedCaptures, NamedCaptures } from "./regex.ts";
export interface RegexExecArray<patternAndCaptures extends IndexedCaptures, namedCaptures extends NamedCaptures, flags extends Flags> extends DynamicBase<patternAndCaptures> {
/**
* The index of the search at which the result was found.
*/
index: number;
/**
* A copy of the search string.
*/
input: patternAndCaptures[0];
indices: flags extends `${string}d${string}` ? RegexIndicesArray<patternAndCaptures, namedCaptures> : undefined;
groups: keyof namedCaptures extends never ? undefined : namedCaptures;
}
export type RegexIndexRange = [start: number, end: number];
interface RegexIndicesArray<patternAndCaptures extends IndexedCaptures, namedCaptures extends NamedCaptures> extends DynamicBase<{
[i in keyof patternAndCaptures]: RegexIndexRange;
}> {
groups: keyof namedCaptures extends never ? undefined : {
[k in keyof namedCaptures]: RegexIndexRange;
};
}
export {};

1
frontend/node_modules/arkregex/out/execArray.js generated vendored Normal file
View File

@@ -0,0 +1 @@
export {};

33
frontend/node_modules/arkregex/out/group.d.ts generated vendored Normal file
View File

@@ -0,0 +1,33 @@
import type { ErrorMessage, Scanner, writeUnclosedGroupMessage } from "@ark/util";
import type { State, s } from "./state.ts";
type LookaroundChar = "=" | "!";
export type ModifiableFlag = "i" | "m" | "s";
export type parseGroup<s extends State, unscanned extends string> = unscanned extends Scanner.shift<infer lookahead, infer next> ? lookahead extends "?" ? parseNonCapturingGroup<s, next> : s.pushGroup<s, State.UnnamedCaptureKind.indexed, unscanned, undefined> : s.error<writeUnclosedGroupMessage<")">>;
type parseNonCapturingGroup<s extends State, unscanned extends string> = unscanned extends Scanner.shift<infer lookahead, infer next> ? lookahead extends ":" ? s.pushGroup<s, State.UnnamedCaptureKind.noncapturing, next, undefined> : lookahead extends LookaroundChar ? s.pushGroup<s, State.UnnamedCaptureKind.lookaround, next, undefined> : lookahead extends "<" ? parseNamedGroupOrLookbehind<s, next> : shiftModifiers<unscanned> extends (ShiftedModifiers<infer flags, infer negated, infer following>) ? following extends ErrorMessage<infer message> ? s.error<message> : s.pushGroup<s, State.UnnamedCaptureKind.noncapturing, following, "i" extends flags ? true : "i" extends negated ? false : undefined> : never : s.error<writeUnclosedGroupMessage<")">>;
type ShiftedModifiers<flags extends ModifiableFlag = ModifiableFlag, negated extends ModifiableFlag = ModifiableFlag, unscanned extends string = string> = [ParsedModifiers<flags, negated>, unscanned];
type ParsedModifiers<flags extends ModifiableFlag = ModifiableFlag, negated extends ModifiableFlag = ModifiableFlag> = {
flags: flags;
negated: negated;
};
type shiftModifiers<unscanned extends string> = Scanner.shiftUntil<unscanned, ":" | ")"> extends (Scanner.shiftResult<infer scanned, infer next>) ? next extends Scanner.shift<infer terminator, infer following> ? terminator extends ":" ? parseModifiers<scanned> extends (ParsedModifiers<infer flags, infer negated>) ? ShiftedModifiers<flags, negated, following> : ShiftedModifiers<never, never, ErrorMessage<parseModifiers<scanned> & string>> : ShiftedModifiers<never, never, ErrorMessage<unescapedLiteralQuestionMarkMessage>> : ShiftedModifiers<never, never, ErrorMessage<writeUnclosedGroupMessage<")">>> : never;
type parseModifiers<unscanned extends string> = _parseModifiers<unscanned, never, never>;
type _parseModifiers<unscanned extends string, flags extends ModifiableFlag, negated extends ModifiableFlag> = unscanned extends Scanner.shift<infer lookahead, infer next> ? lookahead extends "-" ? [
negated
] extends [never] ? next extends Scanner.shift<infer modifier, infer next> ? modifier extends ModifiableFlag ? modifier extends flags | negated ? writeDuplicateModifierMessage<modifier> : _parseModifiers<next, flags, negated | modifier> : writeInvalidModifierMessage<modifier> : missingNegatedModifierMessage : multipleModifierDashesMessage : lookahead extends ModifiableFlag ? lookahead extends flags | negated ? writeDuplicateModifierMessage<lookahead> : [
negated
] extends [never] ? _parseModifiers<next, flags | lookahead, negated> : _parseModifiers<next, flags, negated | lookahead> : writeInvalidModifierMessage<lookahead> : ParsedModifiers<flags, negated>;
export declare const writeDuplicateModifierMessage: <modifier extends ModifiableFlag>(modifier: modifier) => writeDuplicateModifierMessage<modifier>;
type writeDuplicateModifierMessage<modifier extends ModifiableFlag> = `Modifier ${modifier} cannot appear multiple times in a single group`;
export declare const multipleModifierDashesMessage = "Modifiers can include at most one '-' to negate subsequent flags";
type multipleModifierDashesMessage = typeof multipleModifierDashesMessage;
export declare const missingNegatedModifierMessage = "- must be followed by the modifier flag to negate ('i', 'm' or 's')";
type missingNegatedModifierMessage = typeof missingNegatedModifierMessage;
export declare const writeInvalidModifierMessage: <char extends string>(char: char) => writeInvalidModifierMessage<char>;
type writeInvalidModifierMessage<char extends string> = `Modifier flag ${char} must be 'i', 'm' or 's'`;
type parseNamedGroupOrLookbehind<s extends State, unscanned extends string> = unscanned extends Scanner.shift<LookaroundChar, infer next> ? s.pushGroup<s, State.UnnamedCaptureKind.lookaround, next, undefined> : shiftNamedGroup<unscanned> extends (Scanner.shiftResult<infer name, infer following>) ? s.pushGroup<s, name, following, undefined> : s.error<writeUnclosedGroupMessage<")">>;
type shiftNamedGroup<unscanned extends string> = unscanned extends `${infer name}>${infer next}` ? name extends "" ? Scanner.shiftResult<"", ErrorMessage<unnamedCaptureGroupMessage>> : Scanner.shiftResult<name, next> : Scanner.shiftResult<"", ErrorMessage<writeUnclosedGroupMessage<">">>>;
export declare const unnamedCaptureGroupMessage = "Capture group <> requires a name";
export type unnamedCaptureGroupMessage = typeof unnamedCaptureGroupMessage;
export declare const unescapedLiteralQuestionMarkMessage = "literal ? must be escaped at the start of a group";
export type unescapedLiteralQuestionMarkMessage = typeof unescapedLiteralQuestionMarkMessage;
export {};

6
frontend/node_modules/arkregex/out/group.js generated vendored Normal file
View File

@@ -0,0 +1,6 @@
export const writeDuplicateModifierMessage = (modifier) => `Modifier ${modifier} cannot appear multiple times in a single group`;
export const multipleModifierDashesMessage = "Modifiers can include at most one '-' to negate subsequent flags";
export const missingNegatedModifierMessage = `- must be followed by the modifier flag to negate ('i', 'm' or 's')`;
export const writeInvalidModifierMessage = (char) => `Modifier flag ${char} must be 'i', 'm' or 's'`;
export const unnamedCaptureGroupMessage = "Capture group <> requires a name";
export const unescapedLiteralQuestionMarkMessage = "literal ? must be escaped at the start of a group";

1
frontend/node_modules/arkregex/out/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1 @@
export { regex, type Regex } from "./regex.ts";

1
frontend/node_modules/arkregex/out/index.js generated vendored Normal file
View File

@@ -0,0 +1 @@
export { regex } from "./regex.js";

10
frontend/node_modules/arkregex/out/parse.d.ts generated vendored Normal file
View File

@@ -0,0 +1,10 @@
import type { Backslash, ErrorMessage, Scanner } from "@ark/util";
import type { parseCharset } from "./charset.ts";
import type { parseEscape } from "./escape.ts";
import type { parseGroup } from "./group.ts";
import type { parseBuiltinQuantifier, parsePossibleRange, QuantifyingChar } from "./quantify.ts";
import type { Anchor, AnchorMarker, s, State, UnionTree } from "./state.ts";
export type parseState<s extends State> = s["unscanned"] extends ErrorMessage ? s["unscanned"] : s["unscanned"] extends "" ? s.finalize<s> : parseState<next<s>>;
export type next<s extends State> = s["unscanned"] extends Scanner.shift<infer lookahead, infer unscanned> ? lookahead extends "." ? s.shiftQuantifiable<s, string, unscanned> : lookahead extends Backslash ? parseEscape<s, unscanned> : lookahead extends "|" ? s.finalizeBranch<s, unscanned> : lookahead extends Anchor ? s.anchor<s, AnchorMarker<lookahead>, unscanned> : lookahead extends "(" ? parseGroup<s, unscanned> : lookahead extends ")" ? s.popGroup<s, unscanned> : lookahead extends QuantifyingChar ? parseBuiltinQuantifier<s, lookahead, unscanned> : lookahead extends "{" ? parsePossibleRange<s, unscanned> : lookahead extends "[" ? parseCharset<s, unscanned> : s.shiftQuantifiable<s, maybeSplitCasing<s["caseInsensitive"], lookahead>, unscanned> : never;
type maybeSplitCasing<caseInsensitive extends boolean, char extends string> = caseInsensitive extends false ? char : Lowercase<char> extends Uppercase<char> ? char : UnionTree<[Lowercase<char>, Capitalize<char>]>;
export {};

1
frontend/node_modules/arkregex/out/parse.js generated vendored Normal file
View File

@@ -0,0 +1 @@
export {};

43
frontend/node_modules/arkregex/out/quantify.d.ts generated vendored Normal file
View File

@@ -0,0 +1,43 @@
import type { parseNonNegativeInteger, Scanner } from "@ark/util";
import type { s, State } from "./state.ts";
export type parseBuiltinQuantifier<s extends State, quantifier extends QuantifyingChar, unscanned extends string> = s["root"] extends "" ? s.error<writeUnmatchedQuantifierError<quantifier>> : quantifyBuiltin<s, quantifier, unscanned extends Scanner.shift<"?", infer lazyUnscanned> ? lazyUnscanned : unscanned>;
type quantifyBuiltin<s extends State, quantifier extends QuantifyingChar, unscanned extends string> = quantifier extends "?" ? s.pushQuantifier<s, 0, 1, unscanned> : quantifier extends "+" ? s.pushQuantifier<s, 1, null, unscanned> : quantifier extends "*" ? s.pushQuantifier<s, 0, null, unscanned> : never;
type ParsedRange = {
min: number;
max: number | null;
unscanned: string;
};
declare namespace ParsedRange {
type from<r extends ParsedRange> = r;
}
type skipPossibleQuestionMark<unscanned extends string> = unscanned extends `?${infer next}` ? next : unscanned;
type parsePossibleRangeString<unscanned extends string> = unscanned extends (`${infer l extends `${number}`},${infer r extends `${number}`}}${infer next}`) ? ParsedRange.from<{
min: parseNonNegativeInteger<l>;
max: parseNonNegativeInteger<r>;
unscanned: skipPossibleQuestionMark<next>;
}> : unscanned extends `${infer l extends `${number}`},}${infer next}` ? ParsedRange.from<{
min: parseNonNegativeInteger<l>;
max: null;
unscanned: skipPossibleQuestionMark<next>;
}> : unscanned extends `${infer l extends `${number}`}}${infer next}` ? ParsedRange.from<{
min: parseNonNegativeInteger<l>;
max: parseNonNegativeInteger<l>;
unscanned: skipPossibleQuestionMark<next>;
}> : null;
type parseQuantifier<unscanned extends string, parsed extends ParsedRange> = unscanned extends `${infer range}${parsed["unscanned"]}` ? `{${range}` : never;
export type parsePossibleRange<s extends State, unscanned extends string, parsed extends ParsedRange | null = parsePossibleRangeString<unscanned>> = parsed extends ParsedRange ? s["root"] extends "" ? s.error<writeUnmatchedQuantifierError<parseQuantifier<unscanned, parsed>>> : [parsed["min"], parsed["max"]] extends ([
never,
unknown
] | [unknown, never]) ? s.error<writeUnnaturalNumberQuantifierError<parseQuantifier<unscanned, parsed>>> : s.pushQuantifier<s, parsed["min"], parsed["max"], parsed["unscanned"] extends Scanner.shift<"?", infer lazyUnscanned> ? lazyUnscanned : parsed["unscanned"]> : s.shiftQuantifiable<s, "{", unscanned>;
export type quantify<pattern extends string, min extends number, max extends number | null> = tryFastPath<pattern, min, max>;
type tryFastPath<pattern extends string, min extends number, max extends number | null> = max extends 0 ? "" : string extends pattern ? string : `${number}` extends pattern ? `${number}` : min extends 0 ? max extends 1 ? "" | pattern : max extends number ? loopFromZero<pattern, max, "", []> : // max is null, all we can do is append ${string}
"" | `${pattern}${string}` : loopUntilMin<pattern, min, max, "", []>;
type loopFromZero<base extends string, max extends number, acc extends string, repetitions extends 1[]> = repetitions["length"] extends max ? acc : loopFromZero<base, max, acc | `${acc}${base}`, [...repetitions, 1]>;
type loopUntilMin<base extends string, min extends number, max extends number | null, acc extends string, repetitions extends 1[]> = repetitions["length"] extends min ? max extends number ? loopUntilMax<base, min, max, acc, repetitions> : repetitions["length"] extends 0 ? acc | `${acc}${base}${string}` : `${acc}${string}` : loopUntilMin<base, min, max, `${acc}${base}`, [...repetitions, 1]>;
type loopUntilMax<base extends string, min extends number, max extends number, acc extends string, repetitions extends 1[]> = repetitions["length"] extends max ? acc : loopUntilMax<base, min, max, acc | `${acc}${base}`, [...repetitions, 1]>;
export type QuantifyingChar = "*" | "+" | "?";
export declare const writeUnmatchedQuantifierError: <quantifier extends string>(quantifier: quantifier) => writeUnmatchedQuantifierError<quantifier>;
export type writeUnmatchedQuantifierError<quantifier extends string> = `Quantifier ${quantifier} requires a preceding token`;
export declare const writeUnnaturalNumberQuantifierError: <quantifier extends string>(quantifier: quantifier) => writeUnnaturalNumberQuantifierError<quantifier>;
export type writeUnnaturalNumberQuantifierError<quantifier extends string> = `Quantifier ${quantifier} must use natural numbers`;
export {};

2
frontend/node_modules/arkregex/out/quantify.js generated vendored Normal file
View File

@@ -0,0 +1,2 @@
export const writeUnmatchedQuantifierError = (quantifier) => `Quantifier ${quantifier} requires a preceding token`;
export const writeUnnaturalNumberQuantifierError = (quantifier) => `Quantifier ${quantifier} must use natural numbers`;

38
frontend/node_modules/arkregex/out/regex.d.ts generated vendored Normal file
View File

@@ -0,0 +1,38 @@
import type { ErrorMessage, inferred } from "@ark/util";
import type { RegexExecArray } from "./execArray.ts";
import type { parseState } from "./parse.ts";
import type { State } from "./state.ts";
export type IndexedCaptures = Array<string | undefined>;
export type NamedCaptures = Record<string, string | undefined>;
export type UnicodeFlag = "v" | "u";
export type Flags = `${"d" | ""}${"g" | ""}${"i" | ""}${"m" | ""}${"s" | ""}${UnicodeFlag | ""}${"y" | ""}`;
export type RegexContext = {
flags?: Flags;
captures?: IndexedCaptures;
names?: NamedCaptures;
};
export interface Regex<out pattern extends string = string, out ctx extends RegexContext = RegexContext> extends RegExp {
[inferred]: pattern;
infer: pattern;
inferCaptures: ctx["captures"] extends IndexedCaptures ? ctx["captures"] : [];
inferNamedCaptures: ctx["names"] extends NamedCaptures ? ctx["names"] : {};
inferExecArray: RegexExecArray<[
pattern,
...this["inferCaptures"]
], this["inferNamedCaptures"], this["flags"]>;
flags: ctx["flags"] extends Flags ? ctx["flags"] : "";
test(s: string): s is pattern;
exec(s: string): this["inferExecArray"] | null;
exec(s: string): never;
}
export interface RegexParser {
<src extends string, flags extends Flags = "">(src: regex.validate<src, flags>, flags?: flags): regex.parse<src, flags>;
as: <pattern extends string = string, ctx extends RegexContext = {}>(src: string, flags?: Flags) => Regex<pattern, ctx>;
}
export declare const regex: RegexParser;
export type regex<pattern extends string = string, ctx extends RegexContext = RegexContext> = Regex<pattern, ctx>;
export declare namespace regex {
type infer<src extends string, flags extends Flags = ""> = parse<src, flags> extends Regex<infer pattern> ? pattern : never;
type validate<src extends string, flags extends Flags = ""> = parse<src, flags> extends infer e extends ErrorMessage ? e : src;
type parse<src extends string, flags extends Flags = ""> = parseState<State.initialize<src, flags>>;
}

2
frontend/node_modules/arkregex/out/regex.js generated vendored Normal file
View File

@@ -0,0 +1,2 @@
export const regex = ((src, flags) => new RegExp(src, flags));
Object.assign(regex, { as: regex });

359
frontend/node_modules/arkregex/out/state.d.ts generated vendored Normal file
View File

@@ -0,0 +1,359 @@
import type { contains, ErrorMessage, noSuggest, NumberLiteral, setIndex, unionKeyOf, writeUnclosedGroupMessage, writeUnmatchedGroupCloseMessage, ZeroWidthSpace } from "@ark/util";
import type { writeUnresolvableBackreferenceMessage } from "./escape.ts";
import type { quantify, QuantifyingChar } from "./quantify.ts";
import type { Flags, IndexedCaptures, NamedCaptures, Regex, RegexContext } from "./regex.ts";
export interface State extends State.Group {
unscanned: string;
groups: State.Group[];
/** the initial flags passed to the root of the expression */
flags: Flags;
}
export declare namespace State {
type from<s extends State> = s;
type initialize<source extends string, flags extends Flags> = from<{
unscanned: source;
groups: [];
capture: never;
branches: [];
sequence: SequenceTree.Empty;
root: "";
caseInsensitive: contains<flags, "i">;
flags: flags;
}>;
enum UnnamedCaptureKind {
indexed,
lookaround,
noncapturing
}
type CaptureKind = string | UnnamedCaptureKind;
type Group = {
/** the name of the group or its kind */
capture: CaptureKind;
branches: RegexAst[];
sequence: RegexAst;
root: RegexAst;
caseInsensitive: boolean;
};
namespace Group {
type from<g extends Group> = g;
type pop<init extends Group, last extends Group[]> = [...last, init];
type finalize<g extends Group> = g["branches"] extends [] ? pushQuantifiable<g["sequence"], g["root"]> : [...g["branches"], pushQuantifiable<g["sequence"], g["root"]>] extends (infer branches extends RegexAst[]) ? finalizeUnion<branches, []> : never;
type finalizeUnion<remaining extends RegexAst[], flattened extends RegexAst[]> = remaining extends ([
infer head extends RegexAst,
...infer tail extends RegexAst[]
]) ? head extends UnionTree<infer headBranches> ? finalizeUnion<tail, [...flattened, ...headBranches]> : finalizeUnion<tail, [...flattened, head]> : UnionTree<flattened>;
}
}
export type Boundary = Anchor | "(" | ")" | "[" | "]";
export type Anchor = "^" | "$";
export type Control = QuantifyingChar | Boundary | "|" | "." | "{" | "-" | "\\";
export type AnchorMarker<inner extends Anchor = Anchor> = `<${ZeroWidthSpace}${inner}${ZeroWidthSpace}>`;
export type StartAnchorMarker = AnchorMarker<"^">;
export type EndAnchorMarker = AnchorMarker<"$">;
export declare namespace s {
type error<message extends string> = State.from<{
unscanned: ErrorMessage<message>;
groups: [];
capture: never;
branches: [];
sequence: SequenceTree.Empty;
root: "";
caseInsensitive: false;
flags: "";
}>;
type shiftQuantifiable<s extends State, root extends RegexAst, unscanned extends string> = State.from<{
unscanned: unscanned;
groups: s["groups"];
capture: s["capture"];
branches: s["branches"];
sequence: pushQuantifiable<s["sequence"], s["root"]>;
root: root;
caseInsensitive: s["caseInsensitive"];
flags: s["flags"];
}>;
type pushQuantified<s extends State, quantified extends RegexAst, unscanned extends string> = State.from<{
unscanned: unscanned;
groups: s["groups"];
capture: s["capture"];
branches: s["branches"];
sequence: pushQuantifiable<s["sequence"], quantified>;
root: "";
caseInsensitive: s["caseInsensitive"];
flags: s["flags"];
}>;
type pushQuantifier<s extends State, min extends number, max extends number | null, unscanned extends string> = State.from<{
unscanned: unscanned;
groups: s["groups"];
capture: s["capture"];
branches: s["branches"];
sequence: pushQuantifiable<s["sequence"], {
kind: "quantifier";
ast: s["root"];
min: min;
max: max;
}>;
root: "";
caseInsensitive: s["caseInsensitive"];
flags: s["flags"];
}>;
type finalizeBranch<s extends State, unscanned extends string> = State.from<{
unscanned: unscanned;
groups: s["groups"];
capture: s["capture"];
branches: [...s["branches"], pushQuantifiable<s["sequence"], s["root"]>];
sequence: SequenceTree.Empty;
root: "";
caseInsensitive: s["caseInsensitive"];
flags: s["flags"];
}>;
type anchor<s extends State, a extends AnchorMarker, unscanned extends string> = State.from<{
unscanned: unscanned;
groups: s["groups"];
capture: s["capture"];
branches: s["branches"];
sequence: pushQuantifiable<s["sequence"], pushQuantifiable<s["root"], a>>;
root: "";
caseInsensitive: s["caseInsensitive"];
flags: s["flags"];
}>;
type pushGroup<s extends State, capture extends string | State.UnnamedCaptureKind, unscanned extends string, caseInsensitive extends boolean | undefined> = State.from<{
unscanned: unscanned;
groups: [...s["groups"], s];
capture: capture;
branches: [];
sequence: SequenceTree.Empty;
root: "";
caseInsensitive: caseInsensitive extends boolean ? caseInsensitive : s["caseInsensitive"];
flags: s["flags"];
}>;
type popGroup<s extends State, unscanned extends string> = s["groups"] extends State.Group.pop<infer last, infer init> ? State.from<{
unscanned: unscanned;
groups: init;
capture: last["capture"];
branches: last["branches"];
sequence: pushQuantifiable<last["sequence"], last["root"]>;
root: s["capture"] extends CapturedGroupKind ? GroupTree<State.Group.finalize<s>, s["capture"]> : s["capture"] extends State.UnnamedCaptureKind.lookaround ? "" : State.Group.finalize<s>;
caseInsensitive: last["caseInsensitive"];
flags: s["flags"];
}> : s.error<writeUnmatchedGroupCloseMessage<")", unscanned>>;
type finalize<s extends State> = s["groups"] extends [unknown, ...unknown[]] ? ErrorMessage<writeUnclosedGroupMessage<")">> : finalizeRegexOrError<finalizeTree<State.Group.finalize<s>, {
captures: EmptyCaptures;
names: {};
flags: s["flags"];
errors: [];
}>>;
type finalizeRegexOrError<r extends FinalizationResult> = r["ctx"]["errors"] extends [] ? applyAnchors<r["pattern"]> extends infer pattern extends string ? contains<pattern, StartAnchorMarker> extends false ? contains<pattern, EndAnchorMarker> extends false ? Regex<pattern, finalizeContext<r["ctx"]>> : ErrorMessage<writeMidAnchorError<"$">> : ErrorMessage<writeMidAnchorError<"^">> : never : r["ctx"]["errors"][0];
type finalizeContext<ctx extends FinalizationContext> = ctx["captures"] extends EmptyCaptures ? finalizeContextWithoutCaptures<ctx> : finalizeContextWithCaptures<{
captures: ctx["captures"] extends ([
IndexedCaptureOffset,
...infer rest extends IndexedCaptures
]) ? rest : never;
names: ctx["names"];
flags: ctx["flags"];
errors: ctx["errors"];
}>;
type finalizeContextWithoutCaptures<ctx extends FinalizationContext> = ctx["flags"] extends "" ? {} : {
flags: ctx["flags"];
};
type finalizeContextWithCaptures<ctx extends FinalizationContext> = keyof ctx["names"] extends never ? ctx["flags"] extends "" ? {
captures: ctx["captures"];
} : {
captures: ctx["captures"];
flags: ctx["flags"];
} : ctx["flags"] extends "" ? {
captures: ctx["captures"];
names: ctx["names"];
} : {
captures: ctx["captures"];
names: ctx["names"];
flags: ctx["flags"];
};
}
export type RegexAst = string | ReferenceNode | UnionTree | SequenceTree | GroupTree | QuantifierTree;
export interface ReferenceNode<to extends string = string> {
kind: "reference";
to: to;
}
export declare namespace ReferenceNode {
type finalize<self extends ReferenceNode, ctx extends FinalizationContext, to extends string = self["to"]> = to extends NumberLiteral & keyof ctx["captures"] ? ctx["captures"][to] extends IncompleteCaptureGroup ? FinalizationResult.error<ctx, writeIncompleteReferenceError<to>> : FinalizationResult.from<{
pattern: inferReference<ctx["captures"][to]>;
ctx: ctx;
}> : to extends keyof ctx["names"] ? ctx["names"][to] extends IncompleteCaptureGroup ? FinalizationResult.error<ctx, writeIncompleteReferenceError<to>> : FinalizationResult.from<{
pattern: inferReference<ctx["names"][to]>;
ctx: ctx;
}> : FinalizationResult.error<ctx, writeUnresolvableBackreferenceMessage<to>>;
type inferReference<to extends string | undefined> = to extends string ? to : "";
}
export declare const writeIncompleteReferenceError: <ref extends string>(ref: ref) => writeIncompleteReferenceError<ref>;
export type writeIncompleteReferenceError<ref extends string> = `Reference to incomplete group '${ref}' has no effect`;
export interface SequenceTree<ast extends RegexAst[] = RegexAst[]> {
kind: "sequence";
ast: ast;
}
export declare namespace SequenceTree {
type Empty = SequenceTree<[]>;
type finalize<self extends SequenceTree, ctx extends FinalizationContext> = _finalize<self["ast"], "", ctx>;
type _finalize<tree extends unknown[], pattern extends string, ctx extends FinalizationContext> = tree extends [infer head, ...infer tail] ? finalizeTree<head, ctx> extends infer r ? r extends FinalizationResult ? _finalize<tail, appendNonRedundant<pattern, r["pattern"]>, r["ctx"]> : never : never : FinalizationResult.from<{
pattern: pattern;
ctx: ctx;
}>;
}
export interface UnionTree<ast extends RegexAst[] = RegexAst[]> {
kind: "union";
ast: ast;
}
export declare namespace UnionTree {
type finalize<self extends UnionTree, ctx extends FinalizationContext> = _finalize<self["ast"], [], ctx>;
type FinalizedBranch = {
pattern: string;
captures: IndexedCaptures;
names: NamedCaptures;
};
namespace FinalizedBranch {
type from<b extends FinalizedBranch> = b;
}
type _finalize<astBranches extends unknown[], acc extends FinalizedBranch[], ctx extends FinalizationContext> = astBranches extends [infer head, ...infer tail] ? finalizeTree<head, ctx> extends infer r ? r extends FinalizationResult ? _finalize<tail, finalizeBranch<acc, ctx, r>, ctx> : never : never : finalizeBranches<keyof acc, acc, ctx>;
type finalizeBranch<acc extends FinalizedBranch[], ctx extends FinalizationContext, r extends FinalizationResult> = [
...acc,
FinalizedBranch.from<{
pattern: r["pattern"];
captures: finalizeBranchCaptures<acc, ctx, r>;
names: r["ctx"]["names"];
}>
];
type finalizeBranchCaptures<acc extends FinalizedBranch[], ctx extends FinalizationContext, r extends FinalizationResult, branchCaptures extends IndexedCaptures = extractNewCaptures<ctx["captures"], r["ctx"]["captures"]>> = acc extends [] ? branchCaptures : acc[0]["captures"] extends (infer firstCaptureBranch extends IndexedCaptures) ? branchCaptures extends [] ? {
[i in keyof firstCaptureBranch]: undefined;
} : [...{
[i in keyof firstCaptureBranch]: undefined;
}, ...branchCaptures] : never;
type finalizeBranches<i, acc extends FinalizedBranch[], ctx extends FinalizationContext> = i extends keyof acc & NumberLiteral ? FinalizationResult.from<{
pattern: acc[i]["pattern"];
ctx: {
flags: ctx["flags"];
captures: [...ctx["captures"], ...acc[i]["captures"]];
names: {
[k in unionKeyOf<acc[number]["names"]>]: k extends (keyof acc[i]["names"]) ? acc[i]["names"][k] : undefined;
};
errors: ctx["errors"];
};
}> : never;
}
export type CapturedGroupKind = string | State.UnnamedCaptureKind.indexed;
export type IncompleteCaptureGroup = noSuggest<"incompleteCaptureGroup">;
export type IndexedCaptureOffset = noSuggest<"indexedCaptureOffset">;
/**
* Offset captures to match 1-based indexing for references
* (i.e so that \1 would match the first capture group)
*/
export type EmptyCaptures = [IndexedCaptureOffset];
export interface GroupTree<ast extends RegexAst = RegexAst, capture extends CapturedGroupKind = CapturedGroupKind> {
kind: "group";
capture: capture;
ast: ast;
}
export declare namespace GroupTree {
type finalize<self extends GroupTree, ctx extends FinalizationContext> = finalizeGroupAst<self, ctx> extends infer r ? r extends FinalizationResult ? finalizeGroupResult<self, ctx, r> : never : never;
type finalizeGroupAst<self extends GroupTree, ctx extends FinalizationContext> = finalizeTree<self["ast"], self["capture"] extends string ? {
captures: [...ctx["captures"], IncompleteCaptureGroup];
names: ctx["names"] & {
[_ in self["capture"]]: IncompleteCaptureGroup;
};
flags: ctx["flags"];
errors: ctx["errors"];
} : self["capture"] extends State.UnnamedCaptureKind.indexed ? {
captures: [...ctx["captures"], IncompleteCaptureGroup];
names: ctx["names"];
flags: ctx["flags"];
errors: ctx["errors"];
} : ctx>;
type finalizeGroupResult<self extends GroupTree, ctx extends FinalizationContext, r extends FinalizationResult> = FinalizationResult.from<{
pattern: r["pattern"];
ctx: self["capture"] extends string ? finalizeNamedCapture<self["capture"], ctx["captures"]["length"], r["pattern"], r["ctx"]> : self["capture"] extends State.UnnamedCaptureKind.indexed ? finalizeUnnamedCapture<ctx["captures"]["length"], r["pattern"], r["ctx"]> : r["ctx"];
}>;
type finalizeNamedCapture<name extends string, index extends number, pattern extends string, ctx extends FinalizationContext> = FinalizationContext.from<{
captures: setIndex<ctx["captures"], index, anchorsAway<pattern>>;
names: {
[k in keyof ctx["names"]]: k extends name ? anchorsAway<pattern> : ctx["names"][k];
};
flags: ctx["flags"];
errors: ctx["errors"];
}>;
type finalizeUnnamedCapture<index extends number, pattern extends string, ctx extends FinalizationContext> = FinalizationContext.from<{
captures: setIndex<ctx["captures"], index, anchorsAway<pattern>>;
names: ctx["names"];
flags: ctx["flags"];
errors: ctx["errors"];
}>;
}
export interface QuantifierTree<ast extends RegexAst = RegexAst> {
kind: "quantifier";
ast: ast;
min: number;
max: number | null;
}
export declare namespace QuantifierTree {
type finalize<self extends QuantifierTree, ctx extends FinalizationContext> = finalizeTree<self["ast"], ctx> extends infer r extends FinalizationResult ? finalizeQuantifierResult<self, ctx, r> : never;
type finalizeQuantifierResult<self extends QuantifierTree, ctx extends FinalizationContext, r extends FinalizationResult, quantifiedCaptures extends IndexedCaptures = extractNewCaptures<ctx["captures"], r["ctx"]["captures"]>> = self["min"] extends 0 ? quantifiedCaptures extends [] ? finalizeNonZeroMinQuantified<self, r> : finalizeZeroMinQuantifiedWithCaptures<self, ctx, r, quantifiedCaptures> : finalizeNonZeroMinQuantified<self, r>;
type finalizeNonZeroMinQuantified<self extends QuantifierTree, r extends FinalizationResult> = FinalizationResult.from<{
pattern: quantify<r["pattern"], self["min"], self["max"]>;
ctx: r["ctx"];
}>;
type finalizeZeroMinQuantifiedWithCaptures<self extends QuantifierTree, ctx extends FinalizationContext, r extends FinalizationResult, quantifiedCaptures extends IndexedCaptures> = finalizeZeroQuantified<ctx, r, quantifiedCaptures> | finalizeOnePlusQuantified<self["max"], r>;
type finalizeZeroQuantified<ctx extends FinalizationContext, r extends FinalizationResult, quantifiedCaptures extends IndexedCaptures> = FinalizationResult.from<{
pattern: "";
ctx: {
captures: [
...ctx["captures"],
...{
[i in keyof quantifiedCaptures]: undefined;
}
];
flags: r["ctx"]["flags"];
names: zeroQuantifiedNames<ctx["names"], r["ctx"]["names"]>;
errors: r["ctx"]["errors"];
};
}>;
type zeroQuantifiedNames<base extends NamedCaptures, result extends NamedCaptures> = {
[k in keyof result]: k extends keyof base ? result[k] : undefined;
} & unknown;
type finalizeOnePlusQuantified<max extends number | null, r extends FinalizationResult> = max extends 1 ? r : FinalizationResult.from<{
pattern: quantify<r["pattern"], 1, max>;
ctx: r["ctx"];
}>;
}
export type pushQuantifiable<sequence extends RegexAst, root extends RegexAst> = root extends "" ? sequence : sequence extends string ? sequence extends "" ? root : root extends string ? appendNonRedundant<sequence, root> : SequenceTree<[sequence, root]> : sequence extends SequenceTree ? pushToSequence<sequence, root> : SequenceTree<[sequence, root]>;
type pushToSequence<sequence extends SequenceTree, root extends RegexAst> = sequence extends SequenceTree.Empty ? root : root extends SequenceTree ? SequenceTree<[...sequence["ast"], ...root["ast"]]> : SequenceTree<[...sequence["ast"], root]>;
type extractNewCaptures<base extends IndexedCaptures, result extends IndexedCaptures> = result extends readonly [...base, ...infer elements extends IndexedCaptures] ? elements : [];
export interface FinalizationContext extends Required<RegexContext> {
errors: ErrorMessage[];
}
export declare namespace FinalizationContext {
type from<ctx extends FinalizationContext> = ctx;
}
export type FinalizationResult = {
pattern: string;
ctx: FinalizationContext;
};
export declare namespace FinalizationResult {
type from<r extends FinalizationResult> = r;
type error<ctx extends FinalizationContext, message extends string> = from<{
pattern: string;
ctx: {
captures: ctx["captures"];
names: ctx["names"];
flags: ctx["flags"];
errors: [...ctx["errors"], ErrorMessage<message>];
};
}>;
}
export type finalizeTree<tree, ctx extends FinalizationContext> = tree extends string ? FinalizationResult.from<{
pattern: tree;
ctx: ctx;
}> : tree extends SequenceTree ? SequenceTree.finalize<tree, ctx> : tree extends UnionTree ? UnionTree.finalize<tree, ctx> : tree extends GroupTree ? GroupTree.finalize<tree, ctx> : tree extends QuantifierTree ? QuantifierTree.finalize<tree, ctx> : tree extends ReferenceNode ? ReferenceNode.finalize<tree, ctx> : never;
type applyAnchors<pattern extends string> = pattern extends `${StartAnchorMarker}${infer startStripped}` ? startStripped extends `${infer bothStripped}${EndAnchorMarker}` ? bothStripped : appendNonRedundant<startStripped, string> : pattern extends `${infer endStripped}${EndAnchorMarker}` ? prependNonRedundant<endStripped, string> : prependNonRedundant<appendNonRedundant<pattern, string>, string>;
type anchorsAway<pattern extends string> = pattern extends `${StartAnchorMarker}${infer startStripped}` ? startStripped extends `${infer bothStripped}${EndAnchorMarker}` ? bothStripped : startStripped : pattern extends `${infer endStripped}${EndAnchorMarker}` ? endStripped : pattern;
type appendNonRedundant<base extends string, suffix extends string> = string extends base ? string extends suffix ? string : `${base}${suffix}` : `${number}` extends base ? `${number}` extends suffix ? `${number}` : `${base}${suffix}` : `${base}${suffix}`;
type prependNonRedundant<base extends string, prefix extends string> = string extends base ? string extends prefix ? string : `${prefix}${base}` : `${number}` extends base ? `${number}` extends prefix ? `${number}` : `${prefix}${base}` : `${prefix}${base}`;
export declare const writeMidAnchorError: <anchor extends Anchor>(anchor: anchor) => writeMidAnchorError<anchor>;
type writeMidAnchorError<anchor extends Anchor> = `Anchor ${anchor} may not appear mid-pattern`;
export {};

2
frontend/node_modules/arkregex/out/state.js generated vendored Normal file
View File

@@ -0,0 +1,2 @@
export const writeIncompleteReferenceError = (ref) => `Reference to incomplete group '${ref}' has no effect`;
export const writeMidAnchorError = (anchor) => `Anchor ${anchor} may not appear mid-pattern`;