From f556c96f1a224dbf93c1d03784661ce281d16d35 Mon Sep 17 00:00:00 2001 From: Filip Gregor Date: Sun, 22 Jun 2025 21:02:31 +0200 Subject: [PATCH 1/5] feat: prepare for regex --- website/package.json | 1 + website/pnpm-lock.yaml | 8 ++++++++ website/src/routes/+layout.svelte | 4 ++-- website/src/routes/algorithms/+page.svelte | 1 + website/src/routes/algorithms/regexes/+page.svelte | 8 ++++++++ 5 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 website/src/routes/algorithms/+page.svelte create mode 100644 website/src/routes/algorithms/regexes/+page.svelte diff --git a/website/package.json b/website/package.json index 37feeb0..d732961 100644 --- a/website/package.json +++ b/website/package.json @@ -30,6 +30,7 @@ "eslint-config-prettier": "^8.10.0", "eslint-plugin-svelte": "^2.43.0", "monaco-editor": "0.40.0", + "@gregofi1/regex-tooling": "^0.0.4", "postcss": "^8.4.39", "prettier": "^2.8.8", "prettier-plugin-svelte": "^2.10.1", diff --git a/website/pnpm-lock.yaml b/website/pnpm-lock.yaml index 155cde4..4e0b497 100644 --- a/website/pnpm-lock.yaml +++ b/website/pnpm-lock.yaml @@ -12,6 +12,9 @@ importers: specifier: ^0.4.1 version: 0.4.1(monaco-editor@0.40.0) devDependencies: + '@gregofi1/regex-tooling': + specifier: ^0.0.4 + version: 0.0.4 '@playwright/test': specifier: ^1.45.2 version: 1.45.2 @@ -251,6 +254,9 @@ packages: resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@gregofi1/regex-tooling@0.0.4': + resolution: {integrity: sha512-nrbAY6kvXjQVoXKxKKyg822k4NWKVDhD896HhaHEzocmT5j/Lofhd5aURRXdPLS1BPfTj+EXMik6CG9h6o4RJw==} + '@humanwhocodes/config-array@0.11.14': resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} engines: {node: '>=10.10.0'} @@ -1927,6 +1933,8 @@ snapshots: '@eslint/js@8.57.0': {} + '@gregofi1/regex-tooling@0.0.4': {} + '@humanwhocodes/config-array@0.11.14': dependencies: '@humanwhocodes/object-schema': 2.0.3 diff --git a/website/src/routes/+layout.svelte b/website/src/routes/+layout.svelte index 6bfc726..3523c8a 100644 --- a/website/src/routes/+layout.svelte +++ b/website/src/routes/+layout.svelte @@ -14,8 +14,8 @@

Run code in browser

- + {@render children?.()} diff --git a/website/src/routes/code/+page.svelte b/website/src/routes/code/+page.svelte index 6a9a6da..24206c0 100644 --- a/website/src/routes/code/+page.svelte +++ b/website/src/routes/code/+page.svelte @@ -11,14 +11,14 @@ import { errorToast } from '$lib/toastPresets'; import ShareBox from '$lib/ShareBox.svelte'; - let editor: MonacoEditor; - let shareBox: ShareBox; + let editor: MonacoEditor = $state(); + let shareBox: ShareBox = $state(); - let loading = false; - let lastResult: Result = { + let loading = $state(false); + let lastResult: Result = $state({ stdout: '', stderr: '' - }; + }); /// Only last compilation can overwrite the result, otherwise slower code /// executed earlier could overwrite result from faster code executed later. let lastResultId = 0; @@ -27,10 +27,10 @@ // It would be nice if we could bind these guys together into an object, // but it seems that the bind:value things doesn't really work with it. - let currentLanguage: LangKey = 'lua'; - let currentExecutor: string | undefined; - let currentCompiler: string | undefined; - let compilerOptions: string | undefined; + let currentLanguage: LangKey = $state('lua'); + let currentExecutor: string | undefined = $state(); + let currentCompiler: string | undefined = $state(); + let compilerOptions: string | undefined = $state(); const getSelection = (): Selection => ({ language: currentLanguage, @@ -39,9 +39,9 @@ compilerOptions: compilerOptions }); - $: langObj = languages[currentLanguage]; + let langObj = $derived(languages[currentLanguage]); - let vimChecker: HTMLInputElement; + let vimChecker: HTMLInputElement = $state(); const delay = 2000; @@ -243,10 +243,10 @@
- + - -
-
+
+
+ Your link is ready! + +
+
+ + +
+
diff --git a/website/src/lib/Spinner.svelte b/website/src/lib/Spinner.svelte index 19cbf1b..79935b9 100644 --- a/website/src/lib/Spinner.svelte +++ b/website/src/lib/Spinner.svelte @@ -1,4 +1,4 @@
diff --git a/website/src/lib/constants.ts b/website/src/lib/constants.ts index aa4ac93..f0fb1cb 100644 --- a/website/src/lib/constants.ts +++ b/website/src/lib/constants.ts @@ -1,74 +1,74 @@ -import type { ILanguage, LangKey } from './types'; +import type { ILanguage, LangKey } from "./types"; export const languages: { [key in LangKey]: ILanguage } = { - lua: { - name: 'lua', - server_name: 'lua', - editor_name: 'lua', - text: 'Lua', - executors: ['lua5.4.6', 'lua5.3.6', 'lua5.2.4', 'lua5.1.5'] - }, - js: { - name: 'js', - server_name: 'js', - editor_name: 'javascript', - text: 'Javascript', - executors: ['nodejs-bookworm'] - }, - python3: { - name: 'python3', - server_name: 'python3', - editor_name: 'python', - text: 'Python 3', - executors: ['python3-bookworm'] - }, - racket: { - name: 'racket', - server_name: 'racket', - editor_name: 'scheme', - text: 'Racket', - executors: ['racket-v8.11.1'] - }, - bash: { - name: 'bash', - server_name: 'bash', - editor_name: 'shell', - text: 'Bash', - executors: ['bash-bookworm'] - }, - c: { - name: 'c', - server_name: 'c', - editor_name: 'c', - text: 'C', - compilers: ['gcc-bookworm'] - }, - cpp: { - name: 'cpp', - server_name: 'cpp', - editor_name: 'cpp', - text: 'C++', - compilers: ['gcc-bookworm'] - }, - haskell: { - name: 'haskell', - server_name: 'haskell', - editor_name: 'haskell', - text: 'Haskell', - compilers: ['ghc-bookworm'] - }, - rust: { - name: 'rust', - server_name: 'rust', - editor_name: 'rust', - text: 'Rust', - compilers: ['rustc-bookworm'] - }, - mjolnir: { - name: 'mjolnir', - server_name: 'mjolnir', - editor_name: 'mjolnir', - text: 'Mjolnir', - executors: ['master'] - } + lua: { + name: "lua", + server_name: "lua", + editor_name: "lua", + text: "Lua", + executors: ["lua5.4.6", "lua5.3.6", "lua5.2.4", "lua5.1.5"], + }, + js: { + name: "js", + server_name: "js", + editor_name: "javascript", + text: "Javascript", + executors: ["nodejs-bookworm"], + }, + python3: { + name: "python3", + server_name: "python3", + editor_name: "python", + text: "Python 3", + executors: ["python3-bookworm"], + }, + racket: { + name: "racket", + server_name: "racket", + editor_name: "scheme", + text: "Racket", + executors: ["racket-v8.11.1"], + }, + bash: { + name: "bash", + server_name: "bash", + editor_name: "shell", + text: "Bash", + executors: ["bash-bookworm"], + }, + c: { + name: "c", + server_name: "c", + editor_name: "c", + text: "C", + compilers: ["gcc-bookworm"], + }, + cpp: { + name: "cpp", + server_name: "cpp", + editor_name: "cpp", + text: "C++", + compilers: ["gcc-bookworm"], + }, + haskell: { + name: "haskell", + server_name: "haskell", + editor_name: "haskell", + text: "Haskell", + compilers: ["ghc-bookworm"], + }, + rust: { + name: "rust", + server_name: "rust", + editor_name: "rust", + text: "Rust", + compilers: ["rustc-bookworm"], + }, + mjolnir: { + name: "mjolnir", + server_name: "mjolnir", + editor_name: "mjolnir", + text: "Mjolnir", + executors: ["master"], + }, }; diff --git a/website/src/lib/defaultPrograms.ts b/website/src/lib/defaultPrograms.ts index 5e87f48..959d4c7 100644 --- a/website/src/lib/defaultPrograms.ts +++ b/website/src/lib/defaultPrograms.ts @@ -1,101 +1,104 @@ export interface IPrograms { - [key: string]: string; + [key: string]: string; } export const defaultPrograms: IPrograms = { - lua: [ - 'local function fact(n)', - ' if n == 0 then', - ' return 1', - ' else', - ' return n * fact(n - 1)', - ' end', - 'end', - '', - 'print(fact(5))' - ].join('\n'), - javascript: [ - 'function fact(n) {', - ' if (n === 0) {', - ' return 1;', - ' } else {', - ' return n * fact(n - 1);', - ' }', - '}', - '', - 'console.log(fact(5));' - ].join('\n'), - scheme: [ - '#lang racket', - '', - '(define (fact n)', - ' (if (= n 0)', - ' 1', - ' (* n (fact (- n 1)))))', - '', - '(display (fact 5))' - ].join('\n'), - python: [ - 'def fact(n):', - ' if n == 0:', - ' return 1', - ' else:', - ' return n * fact(n - 1)', - '', - 'print(fact(5))' - ].join('\n'), - shell: ['#!/bin/bash', '', "echo 'Hello, World!'"].join('\n'), - c: [ - '#include ', - '', - 'int fact(int n) {', - ' if (n == 0) {', - ' return 1;', - ' } else {', - ' return n * fact(n - 1);', - ' }', - '}', - '', - 'int main() {', - ' printf("%d\\n", fact(5));', - ' return 0;', - '}' - ].join('\n'), - cpp: [ - '#include ', - '', - 'int fact(int n) {', - ' if (n == 0) {', - ' return 1;', - ' } else {', - ' return n * fact(n - 1);', - ' }', - '}', - '', - 'int main() {', - ' std::cout << fact(5) << "\\n";', - ' return 0;', - '}' - ].join('\n'), - haskell: ['fact 0 = 1', 'fact n = n * fact (n - 1)', '', 'main = putStrLn $ show $ fact 5'].join( - '\n' - ), - rust: [ - 'fn fact(n: u64) -> u64 {', - ' if n == 0 {', - ' 1', - ' } else {', - ' n * fact(n - 1)', - ' }', - '}', - '', - 'fn main() {', - ' println!("{}", fact(5));', - '}' - ].join('\n'), - mjolnir: [ - 'fn fact(n: Int): Int = if n == 0 { 1 } else { n * fact(n - 1) }', - '', - 'fn main() -> Int = fact(5)' - ].join('\n') + lua: [ + "local function fact(n)", + " if n == 0 then", + " return 1", + " else", + " return n * fact(n - 1)", + " end", + "end", + "", + "print(fact(5))", + ].join("\n"), + javascript: [ + "function fact(n) {", + " if (n === 0) {", + " return 1;", + " } else {", + " return n * fact(n - 1);", + " }", + "}", + "", + "console.log(fact(5));", + ].join("\n"), + scheme: [ + "#lang racket", + "", + "(define (fact n)", + " (if (= n 0)", + " 1", + " (* n (fact (- n 1)))))", + "", + "(display (fact 5))", + ].join("\n"), + python: [ + "def fact(n):", + " if n == 0:", + " return 1", + " else:", + " return n * fact(n - 1)", + "", + "print(fact(5))", + ].join("\n"), + shell: ["#!/bin/bash", "", "echo 'Hello, World!'"].join("\n"), + c: [ + "#include ", + "", + "int fact(int n) {", + " if (n == 0) {", + " return 1;", + " } else {", + " return n * fact(n - 1);", + " }", + "}", + "", + "int main() {", + ' printf("%d\\n", fact(5));', + " return 0;", + "}", + ].join("\n"), + cpp: [ + "#include ", + "", + "int fact(int n) {", + " if (n == 0) {", + " return 1;", + " } else {", + " return n * fact(n - 1);", + " }", + "}", + "", + "int main() {", + ' std::cout << fact(5) << "\\n";', + " return 0;", + "}", + ].join("\n"), + haskell: [ + "fact 0 = 1", + "fact n = n * fact (n - 1)", + "", + "main = putStrLn $ show $ fact 5", + ].join("\n"), + rust: [ + "fn fact(n: u64) -> u64 {", + " if n == 0 {", + " 1", + " } else {", + " n * fact(n - 1)", + " }", + "}", + "", + "fn main() {", + ' println!("{}", fact(5));', + "}", + ].join("\n"), + mjolnir: [ + "fn fact(n: Int): Int = if n == 0 { 1 } else { n * fact(n - 1) }", + "", + "fn main() -> Int = fact(5)", + ].join("\n"), }; diff --git a/website/src/lib/monaco/MonacoEditor.svelte b/website/src/lib/monaco/MonacoEditor.svelte index bc709b1..dde0545 100644 --- a/website/src/lib/monaco/MonacoEditor.svelte +++ b/website/src/lib/monaco/MonacoEditor.svelte @@ -1,95 +1,95 @@
-
+
diff --git a/website/src/lib/monaco/monaco.ts b/website/src/lib/monaco/monaco.ts index e13cca7..b4fc4da 100644 --- a/website/src/lib/monaco/monaco.ts +++ b/website/src/lib/monaco/monaco.ts @@ -1,36 +1,36 @@ -import * as monaco from 'monaco-editor'; +import * as monaco from "monaco-editor"; -import './syntax-highlight/haskell'; +import "./syntax-highlight/haskell"; // Import the workers in a production-safe way. // This is different than in Monaco's documentation for Vite, // but avoids a weird error ("Unexpected usage") at runtime -import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker'; -import cssWorker from 'monaco-editor/esm/vs/language/css/css.worker?worker'; -import htmlWorker from 'monaco-editor/esm/vs/language/html/html.worker?worker'; -import jsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker'; -import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker'; +import editorWorker from "monaco-editor/esm/vs/editor/editor.worker?worker"; +import cssWorker from "monaco-editor/esm/vs/language/css/css.worker?worker"; +import htmlWorker from "monaco-editor/esm/vs/language/html/html.worker?worker"; +import jsonWorker from "monaco-editor/esm/vs/language/json/json.worker?worker"; +import tsWorker from "monaco-editor/esm/vs/language/typescript/ts.worker?worker"; self.MonacoEnvironment = { - getWorker: function (_: string, label: string) { - switch (label) { - case 'json': - return new jsonWorker(); - case 'css': - case 'scss': - case 'less': - return new cssWorker(); - case 'html': - case 'handlebars': - case 'razor': - return new htmlWorker(); - case 'typescript': - case 'javascript': - return new tsWorker(); - default: - return new editorWorker(); - } - } + getWorker: function (_: string, label: string) { + switch (label) { + case "json": + return new jsonWorker(); + case "css": + case "scss": + case "less": + return new cssWorker(); + case "html": + case "handlebars": + case "razor": + return new htmlWorker(); + case "typescript": + case "javascript": + return new tsWorker(); + default: + return new editorWorker(); + } + }, }; export default monaco; diff --git a/website/src/lib/monaco/syntax-highlight/haskell.ts b/website/src/lib/monaco/syntax-highlight/haskell.ts index 1e42085..46d3a7c 100644 --- a/website/src/lib/monaco/syntax-highlight/haskell.ts +++ b/website/src/lib/monaco/syntax-highlight/haskell.ts @@ -1,107 +1,114 @@ -import * as monaco from 'monaco-editor'; +import * as monaco from "monaco-editor"; // TODO: This is definitely not a correct version // but it at least provides some colors... const syntax = (): monaco.languages.IMonarchLanguage => ({ - keywords: [ - 'as', - 'case', - 'of', - 'class', - 'data', - 'default', - 'deriving', - 'do', - 'forall', - 'if', - 'then', - 'else', - 'import', - 'let', - 'in', - 'where' - ], + keywords: [ + "as", + "case", + "of", + "class", + "data", + "default", + "deriving", + "do", + "forall", + "if", + "then", + "else", + "import", + "let", + "in", + "where", + ], - typeKeywords: ['Int', 'Real', 'String'], + typeKeywords: ["Int", "Real", "String"], - operators: [ - '!', - "'", - '"', - '-', - '--', - '-<', - '-<<', - '->', - '::', - ';', - '<-', - ',', - '=', - '=>', - '>', - '?', - '#', - '*', - '@', - '\\', - '_', - '`', - '|', - '~', - '$' - ], + operators: [ + "!", + "'", + '"', + "-", + "--", + "-<", + "-<<", + "->", + "::", + ";", + "<-", + ",", + "=", + "=>", + ">", + "?", + "#", + "*", + "@", + "\\", + "_", + "`", + "|", + "~", + "$", + ], - // we include these common regular expressions - symbols: /[=>](?!@symbols)/, '@brackets'], - [/@symbols/, { cases: { '@operators': 'operator', '@default': '' } }], + // delimiters and operators + [/[{}()[\]]/, "@brackets"], + [/[<>](?!@symbols)/, "@brackets"], + [/@symbols/, { cases: { "@operators": "operator", "@default": "" } }], - // numbers - [/[0-9]+/, 'number'], + // numbers + [/[0-9]+/, "number"], - // strings - [/"([^"\\]|\\.)*$/, 'string.invalid'], // non-teminated string - [/"/, { token: 'string.quote', bracket: '@open', next: '@string' }], + // strings + [/"([^"\\]|\\.)*$/, "string.invalid"], // non-teminated string + [/"/, { token: "string.quote", bracket: "@open", next: "@string" }], - // characters - [/'[^\\']'/, 'string'], - [/(')(@escapes)(')/, ['string', 'string.escape', 'string']], - [/'/, 'string.invalid'] - ], + // characters + [/'[^\\']'/, "string"], + [/(')(@escapes)(')/, ["string", "string.escape", "string"]], + [/'/, "string.invalid"], + ], - string: [ - [/[^\\"]+/, 'string'], - [/@escapes/, 'string.escape'], - [/\\./, 'string.escape.invalid'], - [/"/, { token: 'string.quote', bracket: '@close', next: '@pop' }] - ], + string: [ + [/[^\\"]+/, "string"], + [/@escapes/, "string.escape"], + [/\\./, "string.escape.invalid"], + [/"/, { token: "string.quote", bracket: "@close", next: "@pop" }], + ], - whitespace: [ - [/[ \t\r\n]+/, 'white'], - [/--.*$/, 'comment'] - ] - } + whitespace: [ + [/[ \t\r\n]+/, "white"], + [/--.*$/, "comment"], + ], + }, }); -monaco.languages.register({ id: 'haskell' }); -monaco.languages.setMonarchTokensProvider('haskell', syntax()); +monaco.languages.register({ id: "haskell" }); +monaco.languages.setMonarchTokensProvider("haskell", syntax()); diff --git a/website/src/lib/remoteUtils.ts b/website/src/lib/remoteUtils.ts index 0cb7202..f064c51 100644 --- a/website/src/lib/remoteUtils.ts +++ b/website/src/lib/remoteUtils.ts @@ -1,73 +1,73 @@ -import type { LangKey, LinkData, Result } from '$lib/types'; +import type { LangKey, LinkData, Result } from "$lib/types"; const TOO_MANY_REQUESTS = 429; export const sendCodeToServer = async ( - code: string, - language: LangKey, - compiler?: string, - executor?: string, - compilerOptions?: string + code: string, + language: LangKey, + compiler?: string, + executor?: string, + compilerOptions?: string, ): Promise => { - const body = JSON.stringify({ - code, - language, - compiler, - compiler_args: compilerOptions?.split(' '), - executor - }); - const response = await fetch('/api/code-eval', { - method: 'POST', - body, - mode: 'cors', - headers: { - 'Content-Type': 'application/json', - Accept: 'application/json' - } - }); - if (response.ok) { - return await response.json(); - } else { - throw new Error('Could not evaluate'); - } + const body = JSON.stringify({ + code, + language, + compiler, + compiler_args: compilerOptions?.split(" "), + executor, + }); + const response = await fetch("/api/code-eval", { + method: "POST", + body, + mode: "cors", + headers: { + "Content-Type": "application/json", + Accept: "application/json", + }, + }); + if (response.ok) { + return await response.json(); + } else { + throw new Error("Could not evaluate"); + } }; export const generateNewLink = async (data: LinkData): Promise => { - const body = JSON.stringify(data); + const body = JSON.stringify(data); - const response = await fetch('/api/link', { - method: 'POST', - body, - mode: 'cors', - headers: { - 'Content-Type': 'application/json', - Accept: 'application/json' - } - }); + const response = await fetch("/api/link", { + method: "POST", + body, + mode: "cors", + headers: { + "Content-Type": "application/json", + Accept: "application/json", + }, + }); - if (response.ok) { - const { key } = await response.json(); - return key; - } else if (response.status === TOO_MANY_REQUESTS) { - throw new Error('Too many requests, please try again later.'); - } else { - throw new Error('Could not generate link'); - } + if (response.ok) { + const { key } = await response.json(); + return key; + } else if (response.status === TOO_MANY_REQUESTS) { + throw new Error("Too many requests, please try again later."); + } else { + throw new Error("Could not generate link"); + } }; export const getLinkData = async (key: string): Promise => { - const response = await fetch(`/api/link/${key}`, { - method: 'GET', - mode: 'cors', - headers: { - Accept: 'application/json' - } - }); + const response = await fetch(`/api/link/${key}`, { + method: "GET", + mode: "cors", + headers: { + Accept: "application/json", + }, + }); - if (response.ok) { - const { value } = await response.json(); - return JSON.parse(value); - } else { - throw new Error('Could not fetch link data'); - } + if (response.ok) { + const { value } = await response.json(); + return JSON.parse(value); + } else { + throw new Error("Could not fetch link data"); + } }; diff --git a/website/src/lib/settings.ts b/website/src/lib/settings.ts index 6e963a9..e444a3b 100644 --- a/website/src/lib/settings.ts +++ b/website/src/lib/settings.ts @@ -1,26 +1,26 @@ export interface Settings { - vimMode: boolean; + vimMode: boolean; } const defaultSettings: Settings = { - vimMode: false + vimMode: false, }; export const getSettings = (): Settings => { - const settings = localStorage.getItem('settings'); - if (settings) { - return JSON.parse(settings); - } else { - return defaultSettings; - } + const settings = localStorage.getItem("settings"); + if (settings) { + return JSON.parse(settings); + } else { + return defaultSettings; + } }; export const setVimMode = (vimMode: boolean) => { - const settings = getSettings(); - settings.vimMode = vimMode; - setSettings(settings); + const settings = getSettings(); + settings.vimMode = vimMode; + setSettings(settings); }; export const setSettings = (settings: Settings) => { - localStorage.setItem('settings', JSON.stringify(settings)); + localStorage.setItem("settings", JSON.stringify(settings)); }; diff --git a/website/src/lib/toastPresets.ts b/website/src/lib/toastPresets.ts index b6222a6..2587746 100644 --- a/website/src/lib/toastPresets.ts +++ b/website/src/lib/toastPresets.ts @@ -1,13 +1,13 @@ -import { toast } from '@zerodevx/svelte-toast'; +import { toast } from "@zerodevx/svelte-toast"; type ToastOpts = Parameters[1]; export const errorToast: ToastOpts = { - theme: { - '--toastBackground': 'rgba(196, 0, 0, 1.0)', - '--toastColor': 'white', - '--toastProgressBackground': 'rgba(255, 255, 255, 0.5)' - }, - duration: 5000, - dismissable: true + theme: { + "--toastBackground": "rgba(196, 0, 0, 1.0)", + "--toastColor": "white", + "--toastProgressBackground": "rgba(255, 255, 255, 0.5)", + }, + duration: 5000, + dismissable: true, }; diff --git a/website/src/lib/types.ts b/website/src/lib/types.ts index 950f3e7..2e696e6 100644 --- a/website/src/lib/types.ts +++ b/website/src/lib/types.ts @@ -1,20 +1,20 @@ export type ILanguage = { - name: string; - // Name of the language as used by the server - server_name: string; - // Name of the language as used by the monaco editor. - // This can be different from the actual language, - // for example for Racket we use Scheme. - editor_name: string; - // The text representation, what is shown in the dropdown. - text: string; - executors?: string[]; - compilers?: string[]; + name: string; + // Name of the language as used by the server + server_name: string; + // Name of the language as used by the monaco editor. + // This can be different from the actual language, + // for example for Racket we use Scheme. + editor_name: string; + // The text representation, what is shown in the dropdown. + text: string; + executors?: string[]; + compilers?: string[]; }; export type Result = { - stdout: string; - stderr: string; + stdout: string; + stderr: string; }; /// What the user has currently selected. @@ -23,26 +23,26 @@ export type Result = { /// you add warants a change of all items /// in the DB, unless you make it optional. export type Selection = { - language: LangKey; - executor?: string; - compiler?: string; - compilerOptions?: string; + language: LangKey; + executor?: string; + compiler?: string; + compilerOptions?: string; }; /// Data that are saved in the DB under links export type LinkData = { - selection: Selection; - code: string; + selection: Selection; + code: string; }; export type LangKey = - | 'lua' - | 'js' - | 'python3' - | 'racket' - | 'bash' - | 'c' - | 'cpp' - | 'rust' - | 'mjolnir' - | 'haskell'; + | "lua" + | "js" + | "python3" + | "racket" + | "bash" + | "c" + | "cpp" + | "rust" + | "mjolnir" + | "haskell"; diff --git a/website/src/routes/+layout.svelte b/website/src/routes/+layout.svelte index 8eea5d1..ae59a42 100644 --- a/website/src/routes/+layout.svelte +++ b/website/src/routes/+layout.svelte @@ -1,33 +1,33 @@
- -
- CodeRunner3000 -

Run code in browser

- -
+ > + CodeRunner3000 +

Run code in browser

+ + - {@render children?.()} + {@render children?.()}
diff --git a/website/src/routes/+page.svelte b/website/src/routes/+page.svelte index 00ab41e..903d737 100644 --- a/website/src/routes/+page.svelte +++ b/website/src/routes/+page.svelte @@ -1,8 +1,8 @@ diff --git a/website/src/routes/algorithms/regexes/+page.svelte b/website/src/routes/algorithms/regexes/+page.svelte index 523cdff..c3b506f 100644 --- a/website/src/routes/algorithms/regexes/+page.svelte +++ b/website/src/routes/algorithms/regexes/+page.svelte @@ -1,8 +1,91 @@ - +
+

+ Regular Expression Compiler to Finite Automater +

+

+ Enter a regular expression to visualize its NFA and DFA. We only support + limited features of regular expression, namely +

+
    +
  • - Implicit Concatenation
  • +
  • - Union (|)
  • +
  • - Kleene Star and Plus (e.g., a*, a+)
  • +
  • - Optional (using ?)
  • +
  • - Grouping (using parentheses)
  • +
+ +
+

Conversion Algorithm from Regex to NFA/eNFA:

+ +
+ +
+ +
+ +
+

NFA

+
+
+ +
-
- +
+

DFA

+
+
diff --git a/website/src/routes/api/code-eval/+server.ts b/website/src/routes/api/code-eval/+server.ts index 390c45c..c7fa3f0 100644 --- a/website/src/routes/api/code-eval/+server.ts +++ b/website/src/routes/api/code-eval/+server.ts @@ -1,30 +1,30 @@ -import type { RequestEvent } from '@sveltejs/kit'; -import { error } from '@sveltejs/kit'; +import type { RequestEvent } from "@sveltejs/kit"; +import { error } from "@sveltejs/kit"; export async function POST({ request }: RequestEvent): Promise { - const url = import.meta.env.VITE_CODERUNNER_BACKEND_URL as string; - const api = import.meta.env.VITE_CODERUNNER_BACKEND_API_PATH as string; - if (!url || !api) { - console.log('Coderunner backend API URL is not set'); - error(400, 'Internal server error'); - } - const body = await request.text(); - console.log('Request body', body); - try { - const response = await fetch(`${url}${api}`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - Accept: 'application/json' - }, - body - }); - return response; - } catch (e) { - console.log('Failed to compile code'); - console.log(' - Backend URL', url); - console.log(' - Backend API', api); - console.log(e); - error(500, `Internal server error`); - } + const url = import.meta.env.VITE_CODERUNNER_BACKEND_URL as string; + const api = import.meta.env.VITE_CODERUNNER_BACKEND_API_PATH as string; + if (!url || !api) { + console.log("Coderunner backend API URL is not set"); + error(400, "Internal server error"); + } + const body = await request.text(); + console.log("Request body", body); + try { + const response = await fetch(`${url}${api}`, { + method: "POST", + headers: { + "Content-Type": "application/json", + Accept: "application/json", + }, + body, + }); + return response; + } catch (e) { + console.log("Failed to compile code"); + console.log(" - Backend URL", url); + console.log(" - Backend API", api); + console.log(e); + error(500, `Internal server error`); + } } diff --git a/website/src/routes/api/link/+server.ts b/website/src/routes/api/link/+server.ts index e5b0923..0692bb7 100644 --- a/website/src/routes/api/link/+server.ts +++ b/website/src/routes/api/link/+server.ts @@ -1,38 +1,42 @@ -import type { RequestEvent } from '@sveltejs/kit'; +import type { RequestEvent } from "@sveltejs/kit"; const TOO_MANY_REQUESTS = 429; const backendUrl = import.meta.env.VITE_CODERUNNER_BACKEND_URL as string; -export async function POST({ request, getClientAddress }: RequestEvent): Promise { - if (backendUrl === undefined) { - throw new Error('Backend URL is not set'); - } - const url = `${backendUrl}/api/v1/link/new`; - - const body = await request.text(); - - // This will most likely be behind a proxy. Still, if forwarded is not set - // we have to send some ip address. - const xforwardedfor = request.headers.get('x-forwarded-for') || getClientAddress(); - - const response = await fetch(url, { - method: 'POST', - body, - headers: { - 'content-type': request.headers.get('content-type') ?? 'text/plain', - accept: 'application/json', - 'X-Forwarded-For': xforwardedfor - } - }); - - if (!response.ok) { - if (response.status === TOO_MANY_REQUESTS) { - throw new Error('Too many requests to link generator, try again later'); - } - - throw new Error('Failed to fetch link data'); - } - - return response; +export async function POST({ + request, + getClientAddress, +}: RequestEvent): Promise { + if (backendUrl === undefined) { + throw new Error("Backend URL is not set"); + } + const url = `${backendUrl}/api/v1/link/new`; + + const body = await request.text(); + + // This will most likely be behind a proxy. Still, if forwarded is not set + // we have to send some ip address. + const xforwardedfor = + request.headers.get("x-forwarded-for") || getClientAddress(); + + const response = await fetch(url, { + method: "POST", + body, + headers: { + "content-type": request.headers.get("content-type") ?? "text/plain", + accept: "application/json", + "X-Forwarded-For": xforwardedfor, + }, + }); + + if (!response.ok) { + if (response.status === TOO_MANY_REQUESTS) { + throw new Error("Too many requests to link generator, try again later"); + } + + throw new Error("Failed to fetch link data"); + } + + return response; } diff --git a/website/src/routes/api/link/[key]/+server.ts b/website/src/routes/api/link/[key]/+server.ts index ddad89b..6f88912 100644 --- a/website/src/routes/api/link/[key]/+server.ts +++ b/website/src/routes/api/link/[key]/+server.ts @@ -1,26 +1,31 @@ -import type { RequestEvent } from '@sveltejs/kit'; +import type { RequestEvent } from "@sveltejs/kit"; const backendUrl = import.meta.env.VITE_CODERUNNER_BACKEND_URL as string; -export async function GET({ params, request, getClientAddress }: RequestEvent): Promise { - if (!backendUrl) { - throw new Error('No backend URL provided'); - } +export async function GET({ + params, + request, + getClientAddress, +}: RequestEvent): Promise { + if (!backendUrl) { + throw new Error("No backend URL provided"); + } - const key = params.key; - if (!key) { - throw new Error('No key provided'); - } + const key = params.key; + if (!key) { + throw new Error("No key provided"); + } - const url = `${backendUrl}/api/v1/link/get/${key}`; - // This will most likely be behind a proxy. Still, if forwarded is not set - // we have to send some ip address. - const xforwardedfor = request.headers.get('x-forwarded-for') || getClientAddress(); + const url = `${backendUrl}/api/v1/link/get/${key}`; + // This will most likely be behind a proxy. Still, if forwarded is not set + // we have to send some ip address. + const xforwardedfor = + request.headers.get("x-forwarded-for") || getClientAddress(); - return await fetch(url, { - method: 'GET', - headers: { - 'X-Forwarded-For': xforwardedfor - } - }); + return await fetch(url, { + method: "GET", + headers: { + "X-Forwarded-For": xforwardedfor, + }, + }); } diff --git a/website/src/routes/code/+page.svelte b/website/src/routes/code/+page.svelte index 24206c0..cb14d68 100644 --- a/website/src/routes/code/+page.svelte +++ b/website/src/routes/code/+page.svelte @@ -1,314 +1,329 @@
-
-
- - - {#if langObj.executors?.length ?? 0 > 0} - - {/if} - {#if langObj.compilers?.length ?? 0 > 0} - - {/if} - - Vim - {#if langObj.compilers} - - {/if} - - - - - -
-
- -
-
- +
+
+ + + {#if langObj.executors?.length ?? 0 > 0} + + {/if} + {#if langObj.compilers?.length ?? 0 > 0} + + {/if} + + Vim + {#if langObj.compilers} + + {/if} + + + + + +
+
+ +
+
+
diff --git a/website/svelte.config.js b/website/svelte.config.js index dfdb468..1b58bb9 100644 --- a/website/svelte.config.js +++ b/website/svelte.config.js @@ -1,22 +1,22 @@ -import adapter from '@sveltejs/adapter-node'; -import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'; +import adapter from "@sveltejs/adapter-node"; +import { vitePreprocess } from "@sveltejs/vite-plugin-svelte"; /** @type {import('@sveltejs/kit').Config} */ const config = { - // Consult https://kit.svelte.dev/docs/integrations#preprocessors - // for more information about preprocessors - preprocess: vitePreprocess(), + // Consult https://kit.svelte.dev/docs/integrations#preprocessors + // for more information about preprocessors + preprocess: vitePreprocess(), - kit: { - // adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list. - // If your environment is not supported or you settled on a specific environment, switch out the adapter. - // See https://kit.svelte.dev/docs/adapters for more information about adapters. - adapter: adapter({ - out: 'build', - envPrefix: 'WEBSITE_', - dynamic_origin: true - }) - } + kit: { + // adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list. + // If your environment is not supported or you settled on a specific environment, switch out the adapter. + // See https://kit.svelte.dev/docs/adapters for more information about adapters. + adapter: adapter({ + out: "build", + envPrefix: "WEBSITE_", + dynamic_origin: true, + }), + }, }; export default config; diff --git a/website/tailwind.config.js b/website/tailwind.config.js index bfe0bc2..03114c6 100644 --- a/website/tailwind.config.js +++ b/website/tailwind.config.js @@ -1,8 +1,8 @@ /** @type {import('tailwindcss').Config} */ export default { - content: ['./src/**/*.{html,js,svelte,ts}'], - theme: { - extend: {} - }, - plugins: [] + content: ["./src/**/*.{html,js,svelte,ts}"], + theme: { + extend: {}, + }, + plugins: [], }; diff --git a/website/tests/basic_test.ts b/website/tests/basic_test.ts index 8bf89c8..bded1f9 100644 --- a/website/tests/basic_test.ts +++ b/website/tests/basic_test.ts @@ -1,46 +1,50 @@ -import { test, expect } from '@playwright/test'; +import { test, expect } from "@playwright/test"; declare global { - interface Window { - getMonacoEditorValue: () => string; - setMonacoEditorValue: (value: string) => void; - } + interface Window { + getMonacoEditorValue: () => string; + setMonacoEditorValue: (value: string) => void; + } } -test('test basic lang, compiler and executor.', async ({ page }) => { - await page.goto('/code', { waitUntil: 'networkidle' }); +test("test basic lang, compiler and executor.", async ({ page }) => { + await page.goto("/code", { waitUntil: "networkidle" }); - const monacoValue1 = await page.evaluate(() => window.getMonacoEditorValue()); - expect(monacoValue1).toBeTruthy(); + const monacoValue1 = await page.evaluate(() => window.getMonacoEditorValue()); + expect(monacoValue1).toBeTruthy(); - const language = page.locator('[name="language"]'); - await expect(language).toBeVisible(); - await expect(language.locator('option:checked')).toHaveText('Lua'); + const language = page.locator('[name="language"]'); + await expect(language).toBeVisible(); + await expect(language.locator("option:checked")).toHaveText("Lua"); - const executor = page.locator('[name="executor"]'); - await expect(executor).toBeVisible(); - await executor.selectOption({ value: 'lua5.1.5' }); - await expect(executor).toHaveValue('lua5.1.5'); - const monacoValue2 = await page.evaluate(() => window.getMonacoEditorValue()); - expect(monacoValue2).toBeTruthy(); + const executor = page.locator('[name="executor"]'); + await expect(executor).toBeVisible(); + await executor.selectOption({ value: "lua5.1.5" }); + await expect(executor).toHaveValue("lua5.1.5"); + const monacoValue2 = await page.evaluate(() => window.getMonacoEditorValue()); + expect(monacoValue2).toBeTruthy(); - const compilerSelect = page.locator('[name="compiler"]'); - await expect(compilerSelect).not.toBeVisible(); + const compilerSelect = page.locator('[name="compiler"]'); + await expect(compilerSelect).not.toBeVisible(); }); -test('test changing lang, should change editor', async ({ page }) => { - await page.goto('/code', { waitUntil: 'networkidle' }); +test("test changing lang, should change editor", async ({ page }) => { + await page.goto("/code", { waitUntil: "networkidle" }); - const monacoValueLua = await page.evaluate(() => window.getMonacoEditorValue()); - expect(monacoValueLua).toBeTruthy(); - const language = page.locator('[name="language"]'); - await expect(language).toBeVisible(); - await expect(language.locator('option:checked')).toHaveText('Lua'); + const monacoValueLua = await page.evaluate(() => + window.getMonacoEditorValue(), + ); + expect(monacoValueLua).toBeTruthy(); + const language = page.locator('[name="language"]'); + await expect(language).toBeVisible(); + await expect(language.locator("option:checked")).toHaveText("Lua"); - await language.selectOption({ value: 'python3' }); - await expect(language).toHaveValue('python3'); + await language.selectOption({ value: "python3" }); + await expect(language).toHaveValue("python3"); - const monacoValuePython = await page.evaluate(() => window.getMonacoEditorValue()); + const monacoValuePython = await page.evaluate(() => + window.getMonacoEditorValue(), + ); - expect(monacoValuePython).not.toEqual(monacoValueLua); + expect(monacoValuePython).not.toEqual(monacoValueLua); }); diff --git a/website/tests/share_test.ts b/website/tests/share_test.ts index e942423..f6dd26f 100644 --- a/website/tests/share_test.ts +++ b/website/tests/share_test.ts @@ -1,47 +1,55 @@ -import { test, expect } from '@playwright/test'; - -test('test generating share link and accessing it', async ({ page }) => { - await page.goto('/code', { waitUntil: 'networkidle' }); - - // switch executor - const executor = page.locator('[name="executor"]'); - await expect(executor).toBeVisible(); - await executor.selectOption({ value: 'lua5.1.5' }); - - // edit the code a bit - await page.evaluate(() => window.setMonacoEditorValue('print("hello from lua5.1.5")')); - - const triggerShareBtn = page.locator('[name="share-dialog-btn"]'); - const shareDialog = page.locator('[data-pw="share-dialog"]'); - const closeButton = page.locator('[name="share-dialog-close-btn"]'); - - await expect(shareDialog).not.toBeVisible(); - - await triggerShareBtn.click(); - await expect(shareDialog).toBeVisible(); - - const link = await page.locator('[name="share-dialog-link-input"]').inputValue(); - expect(link).toBeTruthy(); - - await closeButton.click(); - await expect(shareDialog).not.toBeVisible(); - - // change values because the previous code will be in local storage - const language = page.locator('[name="language"]'); - await expect(language).toBeVisible(); - await language.selectOption({ value: 'python3' }); - await page.evaluate(() => window.setMonacoEditorValue('print("hello from python3")')); - - // go to the share link - await page.goto(link, { waitUntil: 'networkidle' }); - const editorValueAfter = await page.evaluate(() => window.getMonacoEditorValue()); - expect(editorValueAfter).toEqual('print("hello from lua5.1.5")'); - - const languageAfter = page.locator('[name="language"]'); - await expect(languageAfter).toBeVisible(); - await expect(languageAfter.locator('option:checked')).toHaveText('Lua'); - - const executorAfter = page.locator('[name="executor"]'); - await expect(executorAfter).toBeVisible(); - await expect(executorAfter).toHaveValue('lua5.1.5'); +import { test, expect } from "@playwright/test"; + +test("test generating share link and accessing it", async ({ page }) => { + await page.goto("/code", { waitUntil: "networkidle" }); + + // switch executor + const executor = page.locator('[name="executor"]'); + await expect(executor).toBeVisible(); + await executor.selectOption({ value: "lua5.1.5" }); + + // edit the code a bit + await page.evaluate(() => + window.setMonacoEditorValue('print("hello from lua5.1.5")'), + ); + + const triggerShareBtn = page.locator('[name="share-dialog-btn"]'); + const shareDialog = page.locator('[data-pw="share-dialog"]'); + const closeButton = page.locator('[name="share-dialog-close-btn"]'); + + await expect(shareDialog).not.toBeVisible(); + + await triggerShareBtn.click(); + await expect(shareDialog).toBeVisible(); + + const link = await page + .locator('[name="share-dialog-link-input"]') + .inputValue(); + expect(link).toBeTruthy(); + + await closeButton.click(); + await expect(shareDialog).not.toBeVisible(); + + // change values because the previous code will be in local storage + const language = page.locator('[name="language"]'); + await expect(language).toBeVisible(); + await language.selectOption({ value: "python3" }); + await page.evaluate(() => + window.setMonacoEditorValue('print("hello from python3")'), + ); + + // go to the share link + await page.goto(link, { waitUntil: "networkidle" }); + const editorValueAfter = await page.evaluate(() => + window.getMonacoEditorValue(), + ); + expect(editorValueAfter).toEqual('print("hello from lua5.1.5")'); + + const languageAfter = page.locator('[name="language"]'); + await expect(languageAfter).toBeVisible(); + await expect(languageAfter.locator("option:checked")).toHaveText("Lua"); + + const executorAfter = page.locator('[name="executor"]'); + await expect(executorAfter).toBeVisible(); + await expect(executorAfter).toHaveValue("lua5.1.5"); }); diff --git a/website/tsconfig.json b/website/tsconfig.json index a3ea88e..0cd1665 100644 --- a/website/tsconfig.json +++ b/website/tsconfig.json @@ -1,18 +1,18 @@ { - "extends": "./.svelte-kit/tsconfig.json", - "compilerOptions": { - "allowJs": true, - "checkJs": true, - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - "resolveJsonModule": true, - "skipLibCheck": true, - "sourceMap": true, - "strict": true, - "strictNullChecks": true - } - // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias - // - // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes - // from the referenced tsconfig.json - TypeScript does not merge them in + "extends": "./.svelte-kit/tsconfig.json", + "compilerOptions": { + "allowJs": true, + "checkJs": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "sourceMap": true, + "strict": true, + "strictNullChecks": true + } + // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias + // + // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes + // from the referenced tsconfig.json - TypeScript does not merge them in } diff --git a/website/vite.config.ts b/website/vite.config.ts index 37b6a84..49c9e7c 100644 --- a/website/vite.config.ts +++ b/website/vite.config.ts @@ -1,9 +1,9 @@ -import { sveltekit } from '@sveltejs/kit/vite'; -import { defineConfig } from 'vitest/config'; +import { sveltekit } from "@sveltejs/kit/vite"; +import { defineConfig } from "vitest/config"; export default defineConfig({ - plugins: [sveltekit()], - test: { - include: ['src/**/*.{test,spec}.{js,ts}'] - } + plugins: [sveltekit()], + test: { + include: ["src/**/*.{test,spec}.{js,ts}"], + }, }); From c41bf807c383020facb2dc4399911fe4341cc2e9 Mon Sep 17 00:00:00 2001 From: Filip Gregor Date: Sun, 22 Jun 2025 22:02:18 +0200 Subject: [PATCH 4/5] ci: install with frozen lockfile --- .github/workflows/tests.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 9b3b058..d30414a 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -65,13 +65,13 @@ jobs: steps: - uses: pnpm/action-setup@v4 with: - version: 8 + version: 9 - name: Checkout uses: actions/checkout@v4 - name: build and test run: | cd website - pnpm install + pnpm install --frozen-lockfile pnpm run lint build-website: @@ -81,13 +81,13 @@ jobs: steps: - uses: pnpm/action-setup@v4 with: - version: 8 + version: 9 - name: Checkout uses: actions/checkout@v4 - name: build and test run: | cd website - pnpm install + pnpm install --frozen-lockfile pnpm run build pnpm run test:unit @@ -98,7 +98,7 @@ jobs: steps: - uses: pnpm/action-setup@v4 with: - version: 8 + version: 9 - uses: actions/checkout@v4 - name: Install deps run: | From 47de22c2d01521f5de99b5eff3827dcd776a544b Mon Sep 17 00:00:00 2001 From: Filip Gregor Date: Sun, 22 Jun 2025 22:11:28 +0200 Subject: [PATCH 5/5] feat: bump regex-tooling --- website/package.json | 2 +- website/pnpm-lock.yaml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/website/package.json b/website/package.json index 77ae54a..c9aee61 100644 --- a/website/package.json +++ b/website/package.json @@ -17,7 +17,7 @@ "test:unit": "vitest" }, "devDependencies": { - "@gregofi1/regex-tooling": "^0.0.4", + "@gregofi1/regex-tooling": "^0.0.6", "@playwright/test": "^1.45.2", "@sveltejs/adapter-auto": "^3.0.0", "@sveltejs/adapter-node": "^2.0.0", diff --git a/website/pnpm-lock.yaml b/website/pnpm-lock.yaml index 7777570..cc3732c 100644 --- a/website/pnpm-lock.yaml +++ b/website/pnpm-lock.yaml @@ -13,8 +13,8 @@ importers: version: 0.4.1(monaco-editor@0.52.2) devDependencies: '@gregofi1/regex-tooling': - specifier: ^0.0.4 - version: 0.0.4 + specifier: ^0.0.6 + version: 0.0.6 '@playwright/test': specifier: ^1.45.2 version: 1.45.2 @@ -257,8 +257,8 @@ packages: resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - '@gregofi1/regex-tooling@0.0.4': - resolution: {integrity: sha512-nrbAY6kvXjQVoXKxKKyg822k4NWKVDhD896HhaHEzocmT5j/Lofhd5aURRXdPLS1BPfTj+EXMik6CG9h6o4RJw==} + '@gregofi1/regex-tooling@0.0.6': + resolution: {integrity: sha512-Yuag7cgbFMxBTMIwWhs2fBxd0kGA8GWz2/I3vbWx1ytgybZIJlznGK3rP5Qo926nrOvdb5czTsncb+eRn0qnAg==} '@humanwhocodes/config-array@0.11.14': resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} @@ -2016,7 +2016,7 @@ snapshots: '@eslint/js@8.57.0': {} - '@gregofi1/regex-tooling@0.0.4': {} + '@gregofi1/regex-tooling@0.0.6': {} '@humanwhocodes/config-array@0.11.14': dependencies: