aboutsummaryrefslogtreecommitdiffstats
path: root/src/routes
diff options
context:
space:
mode:
authorLibravatarLarge Libravatar memdmp <memdmpestrogenzone>2025-02-24 01:09:00 +0100
committerLibravatarLarge Libravatar memdmp <memdmpestrogenzone>2025-02-24 01:09:00 +0100
commit54a41f2431c3d60f5845a15447f13413299e41f2 (patch)
treef9395bb35ae4223a8ee944299ce430168de4d657 /src/routes
downloadhttptool-54a41f2431c3d60f5845a15447f13413299e41f2.tar.gz
httptool-54a41f2431c3d60f5845a15447f13413299e41f2.tar.bz2
httptool-54a41f2431c3d60f5845a15447f13413299e41f2.tar.lz
httptool-54a41f2431c3d60f5845a15447f13413299e41f2.zip

feat: da extension

Diffstat (limited to 'src/routes')
-rw-r--r--src/routes/+layout.svelte20
-rw-r--r--src/routes/+layout.ts2
-rw-r--r--src/routes/+page.svelte42
-rw-r--r--src/routes/Monaco.svelte144
-rw-r--r--src/routes/browser.d.ts4
-rw-r--r--src/routes/userland.d.ts4
6 files changed, 216 insertions, 0 deletions
diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte
new file mode 100644
index 0000000..b0e82a6
--- /dev/null
+++ b/src/routes/+layout.svelte
@@ -0,0 +1,20 @@
+<script lang="ts">
+ import { onDestroy, onMount } from 'svelte';
+ import '../app.css';
+ let { children } = $props();
+
+ let mounted = $state(false);
+ onMount(async () => {
+ (globalThis as any).browser = (
+ await import('webextension-polyfill')
+ ).default;
+ mounted = true;
+ });
+ onDestroy(() => (mounted = false));
+</script>
+
+{#if mounted}
+ {@render children()}
+{:else}
+ <p>Waiting on Mount</p>
+{/if}
diff --git a/src/routes/+layout.ts b/src/routes/+layout.ts
new file mode 100644
index 0000000..748cfd9
--- /dev/null
+++ b/src/routes/+layout.ts
@@ -0,0 +1,2 @@
+export const prerender = true;
+export const csr = true;
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte
new file mode 100644
index 0000000..7320c2a
--- /dev/null
+++ b/src/routes/+page.svelte
@@ -0,0 +1,42 @@
+<script lang="ts">
+ import { onMount } from 'svelte';
+ import Monaco from './Monaco.svelte';
+ let content_script = $state('');
+ let default_value = $state(`// Do not put untrusted content here!
+// See https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Intercept_HTTP_requests and https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webRequest for a tutorial on how to handle things.
+// Content saves on every keystroke due to laziness.
+// Reload (disable & re-enable) extension or restart browser to apply changes.
+`);
+ let mounted = $state(false);
+ onMount(async () => {
+ const s = (await browser.storage.local.get('sc')).sc;
+ default_value = s && `${s}`.length ? `${s}` : default_value;
+ content_script = default_value ?? '';
+ setTimeout(() => {
+ mounted = true;
+ setTimeout(() => {
+ content_script = default_value;
+ }, 0);
+ }, 0);
+ });
+ $effect(() => {
+ (async (cs: string) => {
+ if (mounted) {
+ await browser.storage.local.set({ sc: cs });
+ if (browser.runtime.lastError) {
+ console.warn('Last Error is ', browser.runtime.lastError.message);
+ browser.runtime.lastError = undefined;
+ }
+ }
+ })(content_script);
+ });
+</script>
+
+{#if mounted}
+ <Monaco
+ defaultValue={default_value}
+ bind:value={content_script}
+ />
+{:else}
+ Getting Storage
+{/if}
diff --git a/src/routes/Monaco.svelte b/src/routes/Monaco.svelte
new file mode 100644
index 0000000..efdd67a
--- /dev/null
+++ b/src/routes/Monaco.svelte
@@ -0,0 +1,144 @@
+<script lang="ts">
+ import type monaco from 'monaco-editor';
+ import { onDestroy, onMount } from 'svelte';
+ import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker';
+ import jsonWorker from 'monaco-editor/esm/vs/language/json/json.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 tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker';
+ // @ts-ignore
+ import wrqTypes from '@types/webextension-polyfill/namespaces/webRequest.d.ts?raw';
+ // @ts-ignore
+ import evTypes from '@types/webextension-polyfill/namespaces/events.d.ts?raw';
+ import userland from './userland.d.ts?raw';
+
+ let divEl: HTMLDivElement | null = $state(null);
+ let editor: monaco.editor.IStandaloneCodeEditor = $state(null as any);
+ let Monaco: typeof monaco;
+ let {
+ defaultValue = `processRequest = (rq) => rq;
+processResponse = (rs) => rs;
+`,
+ typeDefs = `import type { UserlandBrowser } from './userland';
+declare global {
+ /**
+ * The subset of the host extension's browser type available to the extension
+ * Note: We don't properly sandbox anything. You can likely easily get access to shit outside of here from the browser global.
+ */
+ declare const browser: UserlandBrowser;
+}
+`,
+ value = $bindable(''),
+ }: {
+ value?: string;
+ defaultValue?: string;
+ typeDefs?: string;
+ } = $props();
+ let writeDebounce = false;
+
+ onMount(async () => {
+ // @ts-ignore
+ globalThis.MonacoEnvironment = {
+ getWorker: function (_moduleId: any, label: string) {
+ if (label === 'json') {
+ return new jsonWorker();
+ }
+ if (label === 'css' || label === 'scss' || label === 'less') {
+ return new cssWorker();
+ }
+ if (label === 'html' || label === 'handlebars' || label === 'razor') {
+ return new htmlWorker();
+ }
+ if (label === 'typescript' || label === 'javascript') {
+ return new tsWorker();
+ }
+ return new editorWorker();
+ },
+ };
+
+ Monaco = await import('monaco-editor');
+ Monaco.languages.typescript.typescriptDefaults.setCompilerOptions({
+ allowNonTsExtensions: true,
+ moduleResolution: Monaco.languages.typescript.ModuleResolutionKind.NodeJs,
+ module: Monaco.languages.typescript.ModuleKind.ESNext,
+ noEmit: true,
+ typeRoots: ['node_modules/@types'],
+ });
+ Monaco.editor.defineTheme('redirext', {
+ base: 'vs-dark',
+ inherit: true,
+ rules: [],
+ colors: {
+ 'editor.foreground': '#dedede',
+ 'editor.background': '#23222b',
+ 'editor.selectionBackground': '#4c2889',
+ 'editor.inactiveSelectionBackground': '#444d56',
+ 'editor.lineHighlightBackground': '#444d56',
+ 'editorCursor.foreground': '#ffffff',
+ 'editorWhitespace.foreground': '#6a737d',
+ 'editorIndentGuide.background': '#6a737d',
+ 'editorIndentGuide.activeBackground': '#f6f8fa',
+ 'editor.selectionHighlightBorder': '#444d56',
+ },
+ });
+ if (!divEl) while (!divEl) await new Promise((rs) => setTimeout(rs, 100));
+ Monaco.languages.typescript.typescriptDefaults.addExtraLib(
+ evTypes,
+ 'node_modules/@types/webextension-polyfill/namespaces/events.d.ts'
+ );
+ Monaco.languages.typescript.typescriptDefaults.addExtraLib(
+ wrqTypes,
+ 'node_modules/@types/webextension-polyfill/namespaces/webRequest.d.ts'
+ );
+ Monaco.languages.typescript.typescriptDefaults.addExtraLib(
+ `export * from './namespaces/webRequest';`,
+ 'node_modules/@types/webextension-polyfill/index.d.ts'
+ );
+ Monaco.languages.typescript.typescriptDefaults.addExtraLib(
+ userland,
+ 'node_modules/@types/redirext/userland.d.ts'
+ );
+ Monaco.languages.typescript.typescriptDefaults.addExtraLib(
+ typeDefs,
+ 'node_modules/@types/redirext/index.d.ts'
+ );
+ editor = Monaco.editor.create(divEl, {
+ value: defaultValue,
+ language: 'typescript',
+ theme: 'redirext',
+ autoDetectHighContrast: false,
+ });
+ editor.getModel()?.onDidChangeContent((e) => {
+ writeDebounce = true;
+ const upd = () => {
+ try {
+ value =
+ editor.getValue({ lineEnding: '\n', preserveBOM: false }).trim() +
+ '\n';
+ // console.debug('Updated value from editor to:', value);
+ } catch (error) {
+ writeDebounce = false;
+ throw error;
+ }
+ setTimeout(() => {
+ writeDebounce = false;
+ }, 0);
+ };
+ setTimeout(upd, 0);
+ });
+ });
+ $effect(() => {
+ if (editor && !writeDebounce) {
+ // console.debug('Updating editor with value', value);
+ editor.setValue(value.trim() + '\n');
+ }
+ });
+ onDestroy(() => {
+ if (editor) editor.dispose();
+ });
+</script>
+
+<div
+ bind:this={divEl}
+ class="h-screen overflow-hidden bg-card box-border max-h-full"
+></div>
diff --git a/src/routes/browser.d.ts b/src/routes/browser.d.ts
new file mode 100644
index 0000000..ed54792
--- /dev/null
+++ b/src/routes/browser.d.ts
@@ -0,0 +1,4 @@
+import Browser from 'webextension-polyfill';
+declare global {
+ declare const browser: typeof Browser;
+}
diff --git a/src/routes/userland.d.ts b/src/routes/userland.d.ts
new file mode 100644
index 0000000..7b659b8
--- /dev/null
+++ b/src/routes/userland.d.ts
@@ -0,0 +1,4 @@
+import type { WebRequest } from 'webextension-polyfill';
+export type UserlandBrowser = {
+ get webRequest(): WebRequest.Static;
+};