Files
headroom/frontend/node_modules/@ark/util/out/scanner.js
Santhosh Janardhanan de2d83092e 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
2026-02-17 16:19:59 -05:00

88 lines
2.5 KiB
JavaScript

import { Backslash, whitespaceChars } from "./strings.js";
export class Scanner {
chars;
i;
def;
constructor(def) {
this.def = def;
this.chars = [...def];
this.i = 0;
}
/** Get lookahead and advance scanner by one */
shift() {
return (this.chars[this.i++] ?? "");
}
get lookahead() {
return (this.chars[this.i] ?? "");
}
get nextLookahead() {
return this.chars[this.i + 1] ?? "";
}
get length() {
return this.chars.length;
}
shiftUntil(condition) {
let shifted = "";
while (this.lookahead) {
if (condition(this, shifted))
break;
else
shifted += this.shift();
}
return shifted;
}
shiftUntilEscapable(condition) {
let shifted = "";
while (this.lookahead) {
if (this.lookahead === Backslash) {
this.shift();
if (condition(this, shifted))
shifted += this.shift();
else if (this.lookahead === Backslash)
shifted += this.shift();
else
shifted += `${Backslash}${this.shift()}`;
}
else if (condition(this, shifted))
break;
else
shifted += this.shift();
}
return shifted;
}
shiftUntilLookahead(charOrSet) {
return typeof charOrSet === "string" ?
this.shiftUntil(s => s.lookahead === charOrSet)
: this.shiftUntil(s => s.lookahead in charOrSet);
}
shiftUntilNonWhitespace() {
return this.shiftUntil(() => !(this.lookahead in whitespaceChars));
}
jumpToIndex(i) {
this.i = i < 0 ? this.length + i : i;
}
jumpForward(count) {
this.i += count;
}
get location() {
return this.i;
}
get unscanned() {
return this.chars.slice(this.i, this.length).join("");
}
get scanned() {
return this.chars.slice(0, this.i).join("");
}
sliceChars(start, end) {
return this.chars.slice(start, end).join("");
}
lookaheadIs(char) {
return this.lookahead === char;
}
lookaheadIsIn(tokens) {
return this.lookahead in tokens;
}
}
export const writeUnmatchedGroupCloseMessage = (char, unscanned) => `Unmatched ${char}${(unscanned === "" ? "" : ` before ${unscanned}`)}`;
export const writeUnclosedGroupMessage = (missingChar) => `Missing ${missingChar}`;