From a3579a4ff1de01171dc392a669379aa31b376424 Mon Sep 17 00:00:00 2001 From: sfja Date: Mon, 6 Jan 2025 01:48:11 +0100 Subject: [PATCH] init --- .gitignore | 2 + bundle.ts | 12 + deno.jsonc | 12 + deno.lock | 35 ++ dist/bundle.js | 187 ++++++++++ index.html | 42 +++ package-lock.json | 452 ++++++++++++++++++++++++ package.json | 5 + src/index.ts | 264 ++++++++++++++ src/test_data.ts | 871 ++++++++++++++++++++++++++++++++++++++++++++++ style.css | 15 + 11 files changed, 1897 insertions(+) create mode 100644 .gitignore create mode 100644 bundle.ts create mode 100644 deno.jsonc create mode 100644 deno.lock create mode 100644 dist/bundle.js create mode 100644 index.html create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 src/index.ts create mode 100644 src/test_data.ts create mode 100644 style.css diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d570088 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules/ + diff --git a/bundle.ts b/bundle.ts new file mode 100644 index 0000000..28b3820 --- /dev/null +++ b/bundle.ts @@ -0,0 +1,12 @@ +import * as esbuild from "npm:esbuild"; +import { denoPlugins } from "jsr:@luca/esbuild-deno-loader"; + +await esbuild.build({ + plugins: [...denoPlugins()], + entryPoints: ["./src/index.ts"], + outfile: "./dist/bundle.js", + bundle: true, + format: "esm", +}); + +esbuild.stop(); diff --git a/deno.jsonc b/deno.jsonc new file mode 100644 index 0000000..dc38e78 --- /dev/null +++ b/deno.jsonc @@ -0,0 +1,12 @@ +{ + "tasks": { + "bundle": "deno run --check --allow-read --allow-write --allow-env --allow-run bundle.ts" + }, + "compilerOptions": { + "checkJs": false, + "lib": ["dom", "dom.iterable", "dom.asynciterable", "deno.ns"] + }, + "fmt": { + "indentWidth": 4 + } +} diff --git a/deno.lock b/deno.lock new file mode 100644 index 0000000..8b9101f --- /dev/null +++ b/deno.lock @@ -0,0 +1,35 @@ +{ + "version": "4", + "specifiers": { + "jsr:@luca/esbuild-deno-loader@*": "0.11.1", + "jsr:@std/bytes@^1.0.2": "1.0.4", + "jsr:@std/encoding@^1.0.5": "1.0.5", + "jsr:@std/path@^1.0.6": "1.0.8" + }, + "jsr": { + "@luca/esbuild-deno-loader@0.11.1": { + "integrity": "dc020d16d75b591f679f6b9288b10f38bdb4f24345edb2f5732affa1d9885267", + "dependencies": [ + "jsr:@std/bytes", + "jsr:@std/encoding", + "jsr:@std/path" + ] + }, + "@std/bytes@1.0.4": { + "integrity": "11a0debe522707c95c7b7ef89b478c13fb1583a7cfb9a85674cd2cc2e3a28abc" + }, + "@std/encoding@1.0.5": { + "integrity": "ecf363d4fc25bd85bd915ff6733a7e79b67e0e7806334af15f4645c569fefc04" + }, + "@std/path@1.0.8": { + "integrity": "548fa456bb6a04d3c1a1e7477986b6cffbce95102d0bb447c67c4ee70e0364be" + } + }, + "workspace": { + "packageJson": { + "dependencies": [ + "npm:esbuild@~0.24.2" + ] + } + } +} diff --git a/dist/bundle.js b/dist/bundle.js new file mode 100644 index 0000000..7e0cb8c --- /dev/null +++ b/dist/bundle.js @@ -0,0 +1,187 @@ +// src/index.ts +async function githubTree(name, ref) { + return { + id: 0, + path: "", + filename: name, + kind: { + type: "dir", + children: await githubListRecursive(name, ref) + } + }; +} +async function githubListRecursive(name, ref, path = "", nextId = [1]) { + const fileNodes = await fetch( + `https://api.github.com/repos/${name}/contents${path}?ref=${ref}` + ).then((res) => res.json()); + return Promise.all( + fileNodes.map(async (node) => { + const id = nextId[0]++; + if (node.type === "dir") { + return await githubListRecursive( + name, + ref, + `${path}/${node.name}`, + nextId + ).then((children) => ({ + id, + filename: node.name, + path, + kind: { type: "dir", children } + })); + } else if (node.type === "file") { + return { + id, + filename: node.name, + path, + kind: { type: "file", url: node.download_url } + }; + } + throw new Error(); + }) + ); +} +function generateTreeHtml(node) { + return ``; +} +function generateNodeHtml(node) { + if (node.kind.type === "dir") { + const children = node.kind.children.map((node2) => generateNodeHtml(node2)).join(""); + return `
  • + + ${node.filename}/ + +
  • `; + } else if (node.kind.type === "file") { + return ` +
  • + + ${node.filename} +
  • + `; + } + throw new Error(); +} +function queryHtmlINodes(tree) { + const nodes = /* @__PURE__ */ new Map(); + queryHtmlINodesRecursive(nodes, tree); + return nodes; +} +function queryHtmlINodesRecursive(nodes, node, parentId) { + const checkbox = document.querySelector(`#checkbox-${node.id}`); + if (node.kind.type === "dir") { + nodes.set(node.id, { node, parentId, checkbox }); + for (const child of node.kind.children) { + queryHtmlINodesRecursive(nodes, child, node.id); + } + } else if (node.kind.type === "file") { + nodes.set(node.id, { node, parentId, checkbox }); + } +} +function hydrateHtmlTree(tree) { + for (const node of tree.values()) { + node.checkbox.addEventListener("change", () => { + if (node.node.kind.type === "dir") { + setCheckChildrenRecursively( + tree, + node.node.id, + node.checkbox.checked + ); + } + checkParentDirCheckRecursively(tree, node.parentId); + }); + } +} +function setCheckChildrenRecursively(tree, id, state) { + const node = tree.get(id); + if (node.node.kind.type !== "dir") { + throw new Error(); + } + for (const { id: childId } of node.node.kind.children) { + const child = tree.get(childId); + child.checkbox.checked = state; + if (child.node.kind.type === "dir") { + setCheckChildrenRecursively(tree, childId, state); + } + } +} +function checkParentDirCheckRecursively(tree, parentId) { + if (parentId === void 0) { + return; + } + const parent = tree.get(parentId); + if (parent === void 0) { + throw new Error(); + } + if (parent.node.kind.type !== "dir") { + return; + } + const checked = parent.node.kind.children.some(({ id }) => tree.get(id).checkbox.checked); + parent.checkbox.checked = checked; + checkParentDirCheckRecursively(tree, parent.parentId); +} +async function* searchTree(tree, pattern) { + for (const node of tree.values()) { + if (node.node.kind.type !== "file") { + continue; + } + if (!node.checkbox.checked) { + continue; + } + const text = await fetch(node.node.kind.url).then((res) => res.text()); + const lines = text.split("\n").map((v, i) => [v, i]); + for (const [linetext, i] of lines) { + if (!pattern.test(linetext)) { + continue; + } + const { filename, path } = node.node; + const linenr = i + 1; + yield { filename, path, linetext, linenr }; + } + } +} +var repoNameInput = document.querySelector("#repo-name"); +var repoRefInput = document.querySelector("#repo-ref"); +var gitProviderSelect = document.querySelector("#git-provider"); +var loadRepoButton = document.querySelector("#load-repo"); +var fileTreeDiv = document.querySelector("#file-tree"); +var searchPatternInput = document.querySelector("#search-pattern"); +var searchButton = document.querySelector("#search"); +var searchStatusSpan = document.querySelector("#search-status"); +var searchResultsDiv = document.querySelector("#search-results"); +loadRepoButton.onclick = async () => { + const name = repoNameInput.value; + const ref = repoRefInput.value; + const provider = gitProviderSelect.value; + if (provider === "github") { + const tree = await githubTree(name, ref); + fileTreeDiv.innerHTML = generateTreeHtml(tree); + const htmlTree = queryHtmlINodes(tree); + hydrateHtmlTree(htmlTree); + searchStatusSpan.innerText = ``; + searchButton.onclick = async () => { + const patternText = searchPatternInput.value; + const pattern = new RegExp(patternText); + searchStatusSpan.innerText = "Searching ..."; + searchResultsDiv.innerHTML = ""; + let matches = 0; + for await (const match of searchTree(htmlTree, pattern)) { + matches += 1; + searchResultsDiv.innerHTML += ` +
    +

    ${match.path}/${match.filename} line ${match.linenr}

    + ${match.linetext} +
    + `; + } + if (matches === 0) { + searchStatusSpan.innerText = "** Nothing found **"; + } else { + searchStatusSpan.innerText = `\u22C6\u02D9\u27E1 Done, ${matches} matches \u27E1\u02D9\u22C6`; + } + }; + } +}; +searchButton.onclick = () => { + searchStatusSpan.innerText = `No repository loaded :(`; +}; diff --git a/index.html b/index.html new file mode 100644 index 0000000..f037252 --- /dev/null +++ b/index.html @@ -0,0 +1,42 @@ + + + + + + + + + Git Repo Search + + +

    Git Repo Search

    + +
    +
    + + +
    +
    + + +
    +
    + + +
    + +
    +
    + + +
    +
    + + +
    +
    +
    + + diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..2828207 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,452 @@ +{ + "name": "git-repo-search", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "esbuild": "^0.24.2" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz", + "integrity": "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.2.tgz", + "integrity": "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.2.tgz", + "integrity": "sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.2.tgz", + "integrity": "sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz", + "integrity": "sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.2.tgz", + "integrity": "sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.2.tgz", + "integrity": "sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.2.tgz", + "integrity": "sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz", + "integrity": "sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz", + "integrity": "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.2.tgz", + "integrity": "sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.2.tgz", + "integrity": "sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.2.tgz", + "integrity": "sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.2.tgz", + "integrity": "sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.2.tgz", + "integrity": "sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.2.tgz", + "integrity": "sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.2.tgz", + "integrity": "sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.24.2.tgz", + "integrity": "sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.2.tgz", + "integrity": "sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.2.tgz", + "integrity": "sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.2.tgz", + "integrity": "sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.2.tgz", + "integrity": "sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.2.tgz", + "integrity": "sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.2.tgz", + "integrity": "sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.2.tgz", + "integrity": "sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/esbuild": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.2.tgz", + "integrity": "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.24.2", + "@esbuild/android-arm": "0.24.2", + "@esbuild/android-arm64": "0.24.2", + "@esbuild/android-x64": "0.24.2", + "@esbuild/darwin-arm64": "0.24.2", + "@esbuild/darwin-x64": "0.24.2", + "@esbuild/freebsd-arm64": "0.24.2", + "@esbuild/freebsd-x64": "0.24.2", + "@esbuild/linux-arm": "0.24.2", + "@esbuild/linux-arm64": "0.24.2", + "@esbuild/linux-ia32": "0.24.2", + "@esbuild/linux-loong64": "0.24.2", + "@esbuild/linux-mips64el": "0.24.2", + "@esbuild/linux-ppc64": "0.24.2", + "@esbuild/linux-riscv64": "0.24.2", + "@esbuild/linux-s390x": "0.24.2", + "@esbuild/linux-x64": "0.24.2", + "@esbuild/netbsd-arm64": "0.24.2", + "@esbuild/netbsd-x64": "0.24.2", + "@esbuild/openbsd-arm64": "0.24.2", + "@esbuild/openbsd-x64": "0.24.2", + "@esbuild/sunos-x64": "0.24.2", + "@esbuild/win32-arm64": "0.24.2", + "@esbuild/win32-ia32": "0.24.2", + "@esbuild/win32-x64": "0.24.2" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..57602ed --- /dev/null +++ b/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "esbuild": "^0.24.2" + } +} diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..a60c90a --- /dev/null +++ b/src/index.ts @@ -0,0 +1,264 @@ +import test_data from "./test_data.ts"; + +export type INode = { + kind: INodeKind; + filename: string; + path: string; + id: number; +}; + +type INodeKind = + | { type: "dir"; children: INode[] } + | { type: "file"; url: string }; + +type GithubContentEntry = { + type: string; + name: string; + download_url: string; +}; + +async function githubTree(name: string, ref: string): Promise { + return { + id: 0, + path: "", + filename: name, + kind: { + type: "dir", + children: await githubListRecursive(name, ref), + }, + }; +} + +async function githubListRecursive( + name: string, + ref: string, + path = "", + nextId = [1], +): Promise { + const fileNodes: GithubContentEntry[] = await fetch( + `https://api.github.com/repos/${name}/contents${path}?ref=${ref}`, + ).then((res) => res.json()); + return Promise.all( + fileNodes.map(async (node): Promise => { + const id = nextId[0]++; + if (node.type === "dir") { + return await githubListRecursive( + name, + ref, + `${path}/${node.name}`, + nextId, + ).then((children): INode => ({ + id, + filename: node.name, + path, + kind: { type: "dir", children }, + })); + } else if (node.type === "file") { + return { + id, + filename: node.name, + path, + kind: { type: "file", url: node.download_url }, + }; + } + throw new Error(); + }), + ); +} + +function generateTreeHtml(node: INode): string { + return `
      ${generateNodeHtml(node)}
    `; +} + +function generateNodeHtml(node: INode): string { + if (node.kind.type === "dir") { + const children = node.kind.children + .map((node) => generateNodeHtml(node)) + .join(""); + return `
  • + + ${node.filename}/ +
      ${children}
    +
  • `; + } else if (node.kind.type === "file") { + return ` +
  • + + ${node.filename} +
  • + `; + } + throw new Error(); +} + +type HtmlTree = Map; + +type HtmlINode = { + node: INode; + parentId?: number; + checkbox: HTMLInputElement; +}; + +function queryHtmlINodes(tree: INode): HtmlTree { + const nodes = new Map(); + queryHtmlINodesRecursive(nodes, tree); + return nodes; +} + +function queryHtmlINodesRecursive( + nodes: HtmlTree, + node: INode, + parentId?: number, +) { + const checkbox = document + .querySelector(`#checkbox-${node.id}`)!; + if (node.kind.type === "dir") { + nodes.set(node.id, { node, parentId, checkbox }); + for (const child of node.kind.children) { + queryHtmlINodesRecursive(nodes, child, node.id); + } + } else if (node.kind.type === "file") { + nodes.set(node.id, { node, parentId, checkbox }); + } +} + +function hydrateHtmlTree(tree: HtmlTree) { + for (const node of tree.values()) { + node.checkbox.addEventListener("change", () => { + if (node.node.kind.type === "dir") { + setCheckChildrenRecursively( + tree, + node.node.id, + node.checkbox.checked, + ); + } + checkParentDirCheckRecursively(tree, node.parentId); + }); + } +} + +function setCheckChildrenRecursively( + tree: HtmlTree, + id: number, + state: boolean, +) { + const node = tree.get(id)!; + if (node.node.kind.type !== "dir") { + throw new Error(); + } + for (const { id: childId } of node.node.kind.children) { + const child = tree.get(childId)!; + child.checkbox.checked = state; + if (child.node.kind.type === "dir") { + setCheckChildrenRecursively(tree, childId, state); + } + } +} + +function checkParentDirCheckRecursively(tree: HtmlTree, parentId?: number) { + if (parentId === undefined) { + return; + } + const parent = tree.get(parentId); + if (parent === undefined) { + throw new Error(); + } + if (parent.node.kind.type !== "dir") { + return; + } + const checked = parent.node.kind.children + .some(({ id }) => tree.get(id)!.checkbox.checked); + parent.checkbox.checked = checked; + checkParentDirCheckRecursively(tree, parent.parentId); +} + +type FileMatch = { + filename: string; + path: string; + linetext: string; + linenr: number; +}; + +async function* searchTree( + tree: HtmlTree, + pattern: RegExp, +): AsyncGenerator { + for (const node of tree.values()) { + if (node.node.kind.type !== "file") { + continue; + } + if (!node.checkbox.checked) { + continue; + } + const text = await fetch(node.node.kind.url) + .then((res) => res.text()); + const lines = text.split("\n").map((v, i) => [v, i] as const); + for (const [linetext, i] of lines) { + if (!pattern.test(linetext)) { + continue; + } + const { filename, path } = node.node; + const linenr = i + 1; + yield { filename, path, linetext, linenr }; + } + } +} + +const repoNameInput = document + .querySelector("#repo-name")!; +const repoRefInput = document + .querySelector("#repo-ref")!; +const gitProviderSelect = document + .querySelector("#git-provider")!; +const loadRepoButton = document + .querySelector("#load-repo")!; +const fileTreeDiv = document + .querySelector("#file-tree")!; +const searchPatternInput = document + .querySelector("#search-pattern")!; +const searchButton = document + .querySelector("#search")!; +const searchStatusSpan = document + .querySelector("#search-status")!; +const searchResultsDiv = document + .querySelector("#search-results")!; + +loadRepoButton.onclick = async () => { + const name = repoNameInput.value; + const ref = repoRefInput.value; + const provider = gitProviderSelect.value; + + if (provider === "github") { + const tree = await githubTree(name, ref); + fileTreeDiv.innerHTML = generateTreeHtml(tree); + const htmlTree = queryHtmlINodes(tree); + hydrateHtmlTree(htmlTree); + + searchStatusSpan.innerText = ``; + searchButton.onclick = async () => { + const patternText = searchPatternInput.value; + const pattern = new RegExp(patternText); + searchStatusSpan.innerText = "Searching ..."; + searchResultsDiv.innerHTML = ""; + let matches = 0; + for await (const match of searchTree(htmlTree, pattern)) { + matches += 1; + searchResultsDiv.innerHTML += ` +
    +

    ${match.path}/${match.filename} line ${match.linenr}

    + ${match.linetext} +
    + `; + } + if (matches === 0) { + searchStatusSpan.innerText = "** Nothing found **"; + } else { + searchStatusSpan.innerText = `⋆˙⟡ Done, ${matches} matches ⟡˙⋆`; + } + }; + } +}; + +searchButton.onclick = () => { + searchStatusSpan.innerText = `No repository loaded :(`; +}; diff --git a/src/test_data.ts b/src/test_data.ts new file mode 100644 index 0000000..c2b80fe --- /dev/null +++ b/src/test_data.ts @@ -0,0 +1,871 @@ +import type { INode } from "./index.ts" + +export default { + "id": 0, + "path": "", + "filename": "simonfj20/danskc", + "kind": { + "type": "dir", + "children": [ + { + "id": 1, + "filename": ".gitignore", + "path": "", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/.gitignore" + } + }, + { + "id": 2, + "filename": ".vscode", + "path": "", + "kind": { + "type": "dir", + "children": [ + { + "id": 35, + "filename": "settings.json", + "path": "/.vscode", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/.vscode/settings.json" + } + } + ] + } + }, + { + "id": 3, + "filename": "README.md", + "path": "", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/README.md" + } + }, + { + "id": 4, + "filename": "advent-of-code-2022", + "path": "", + "kind": { + "type": "dir", + "children": [ + { + "id": 31, + "filename": "day1.dk", + "path": "/advent-of-code-2022", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/advent-of-code-2022/day1.dk" + } + }, + { + "id": 32, + "filename": "day2.dk", + "path": "/advent-of-code-2022", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/advent-of-code-2022/day2.dk" + } + } + ] + } + }, + { + "id": 5, + "filename": "c", + "path": "", + "kind": { + "type": "dir", + "children": [ + { + "id": 18, + "filename": "__init__.py", + "path": "/c", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/c/__init__.py" + } + }, + { + "id": 19, + "filename": "c_generator.py", + "path": "/c", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/c/c_generator.py" + } + }, + { + "id": 20, + "filename": "runtime.c", + "path": "/c", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/c/runtime.c" + } + }, + { + "id": 21, + "filename": "runtime.h", + "path": "/c", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/c/runtime.h" + } + } + ] + } + }, + { + "id": 6, + "filename": "checker.py", + "path": "", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/checker.py" + } + }, + { + "id": 7, + "filename": "danskc", + "path": "", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/danskc" + } + }, + { + "id": 8, + "filename": "danskc.py", + "path": "", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/danskc.py" + } + }, + { + "id": 9, + "filename": "editors", + "path": "", + "kind": { + "type": "dir", + "children": [ + { + "id": 33, + "filename": "install_vscode.sh", + "path": "/editors", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/editors/install_vscode.sh" + } + }, + { + "id": 34, + "filename": "vscode", + "path": "/editors", + "kind": { + "type": "dir", + "children": [ + { + "id": 44, + "filename": ".gitignore", + "path": "/editors/vscode", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/editors/vscode/.gitignore" + } + }, + { + "id": 45, + "filename": ".vscode", + "path": "/editors/vscode", + "kind": { + "type": "dir", + "children": [ + { + "id": 90, + "filename": "launch.json", + "path": "/editors/vscode/.vscode", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/editors/vscode/.vscode/launch.json" + } + } + ] + } + }, + { + "id": 46, + "filename": ".vscodeignore", + "path": "/editors/vscode", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/editors/vscode/.vscodeignore" + } + }, + { + "id": 47, + "filename": "CHANGELOG.md", + "path": "/editors/vscode", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/editors/vscode/CHANGELOG.md" + } + }, + { + "id": 48, + "filename": "README.md", + "path": "/editors/vscode", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/editors/vscode/README.md" + } + }, + { + "id": 49, + "filename": "language-configuration.json", + "path": "/editors/vscode", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/editors/vscode/language-configuration.json" + } + }, + { + "id": 50, + "filename": "package.json", + "path": "/editors/vscode", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/editors/vscode/package.json" + } + }, + { + "id": 51, + "filename": "syntaxes", + "path": "/editors/vscode", + "kind": { + "type": "dir", + "children": [ + { + "id": 94, + "filename": "dansk.tmLanguage.json", + "path": "/editors/vscode/syntaxes", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/editors/vscode/syntaxes/dansk.tmLanguage.json" + } + } + ] + } + }, + { + "id": 52, + "filename": "vsc-extension-quickstart.md", + "path": "/editors/vscode", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/editors/vscode/vsc-extension-quickstart.md" + } + } + ] + } + } + ] + } + }, + { + "id": 10, + "filename": "examples", + "path": "", + "kind": { + "type": "dir", + "children": [ + { + "id": 16, + "filename": "adder.dk", + "path": "/examples", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/examples/adder.dk" + } + }, + { + "id": 17, + "filename": "main.dk", + "path": "/examples", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/examples/main.dk" + } + } + ] + } + }, + { + "id": 11, + "filename": "langdev-commits", + "path": "", + "kind": { + "type": "dir", + "children": [ + { + "id": 53, + "filename": "0001-Delete-clear.asm.patch", + "path": "/langdev-commits", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/langdev-commits/0001-Delete-clear.asm.patch" + } + }, + { + "id": 54, + "filename": "0001-added-3-clear-examples.patch", + "path": "/langdev-commits", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/langdev-commits/0001-added-3-clear-examples.patch" + } + }, + { + "id": 55, + "filename": "0001-added-clear-example.patch", + "path": "/langdev-commits", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/langdev-commits/0001-added-clear-example.patch" + } + }, + { + "id": 56, + "filename": "0001-added-danskc.patch", + "path": "/langdev-commits", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/langdev-commits/0001-added-danskc.patch" + } + }, + { + "id": 57, + "filename": "0001-added-debug-flag.patch", + "path": "/langdev-commits", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/langdev-commits/0001-added-debug-flag.patch" + } + }, + { + "id": 58, + "filename": "0001-added-resources-to-readme.patch", + "path": "/langdev-commits", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/langdev-commits/0001-added-resources-to-readme.patch" + } + }, + { + "id": 59, + "filename": "0001-added-speedrun-language.patch", + "path": "/langdev-commits", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/langdev-commits/0001-added-speedrun-language.patch" + } + }, + { + "id": 60, + "filename": "0001-added.patch", + "path": "/langdev-commits", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/langdev-commits/0001-added.patch" + } + }, + { + "id": 61, + "filename": "0001-asmmebler.patch", + "path": "/langdev-commits", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/langdev-commits/0001-asmmebler.patch" + } + }, + { + "id": 62, + "filename": "0001-codesplit.patch", + "path": "/langdev-commits", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/langdev-commits/0001-codesplit.patch" + } + }, + { + "id": 63, + "filename": "0001-deleted-generator.patch", + "path": "/langdev-commits", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/langdev-commits/0001-deleted-generator.patch" + } + }, + { + "id": 64, + "filename": "0001-hashmaps-get-set.patch", + "path": "/langdev-commits", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/langdev-commits/0001-hashmaps-get-set.patch" + } + }, + { + "id": 65, + "filename": "0001-hello-rust.patch", + "path": "/langdev-commits", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/langdev-commits/0001-hello-rust.patch" + } + }, + { + "id": 66, + "filename": "0001-last-bit-of-c-runtime.patch", + "path": "/langdev-commits", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/langdev-commits/0001-last-bit-of-c-runtime.patch" + } + }, + { + "id": 67, + "filename": "0001-move-inside-package-folder.patch", + "path": "/langdev-commits", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/langdev-commits/0001-move-inside-package-folder.patch" + } + }, + { + "id": 68, + "filename": "0001-nice.patch", + "path": "/langdev-commits", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/langdev-commits/0001-nice.patch" + } + }, + { + "id": 69, + "filename": "0001-no-more-c.patch", + "path": "/langdev-commits", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/langdev-commits/0001-no-more-c.patch" + } + }, + { + "id": 70, + "filename": "0001-no-more-runtime.patch", + "path": "/langdev-commits", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/langdev-commits/0001-no-more-runtime.patch" + } + }, + { + "id": 71, + "filename": "0001-no-more-vm.patch", + "path": "/langdev-commits", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/langdev-commits/0001-no-more-vm.patch" + } + }, + { + "id": 72, + "filename": "0001-offset-at-start.patch", + "path": "/langdev-commits", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/langdev-commits/0001-offset-at-start.patch" + } + }, + { + "id": 73, + "filename": "0001-parser-done.patch", + "path": "/langdev-commits", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/langdev-commits/0001-parser-done.patch" + } + }, + { + "id": 74, + "filename": "0001-properly.patch", + "path": "/langdev-commits", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/langdev-commits/0001-properly.patch" + } + }, + { + "id": 75, + "filename": "0001-remove-not.patch", + "path": "/langdev-commits", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/langdev-commits/0001-remove-not.patch" + } + }, + { + "id": 76, + "filename": "0001-removed-debug-prints.patch", + "path": "/langdev-commits", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/langdev-commits/0001-removed-debug-prints.patch" + } + }, + { + "id": 77, + "filename": "0001-rename-parsings-to-parsed.patch", + "path": "/langdev-commits", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/langdev-commits/0001-rename-parsings-to-parsed.patch" + } + }, + { + "id": 78, + "filename": "0001-rename-to-use-_-instead-of.patch", + "path": "/langdev-commits", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/langdev-commits/0001-rename-to-use-_-instead-of.patch" + } + }, + { + "id": 79, + "filename": "0001-renamed-because-name-collision-and-mypy.patch", + "path": "/langdev-commits", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/langdev-commits/0001-renamed-because-name-collision-and-mypy.patch" + } + }, + { + "id": 80, + "filename": "0001-some-checking.patch", + "path": "/langdev-commits", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/langdev-commits/0001-some-checking.patch" + } + }, + { + "id": 81, + "filename": "0001-some-runtime.patch", + "path": "/langdev-commits", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/langdev-commits/0001-some-runtime.patch" + } + }, + { + "id": 82, + "filename": "0001-somthing-not-right.patch", + "path": "/langdev-commits", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/langdev-commits/0001-somthing-not-right.patch" + } + }, + { + "id": 83, + "filename": "0001-string-impl.patch", + "path": "/langdev-commits", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/langdev-commits/0001-string-impl.patch" + } + }, + { + "id": 84, + "filename": "0001-type-type-checking-needed.patch", + "path": "/langdev-commits", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/langdev-commits/0001-type-type-checking-needed.patch" + } + }, + { + "id": 85, + "filename": "0001-updated-to-use-new-jmp-instructions.patch", + "path": "/langdev-commits", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/langdev-commits/0001-updated-to-use-new-jmp-instructions.patch" + } + }, + { + "id": 86, + "filename": "0001-vm-in-rust.patch", + "path": "/langdev-commits", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/langdev-commits/0001-vm-in-rust.patch" + } + }, + { + "id": 87, + "filename": "0001-whaa.patch", + "path": "/langdev-commits", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/langdev-commits/0001-whaa.patch" + } + }, + { + "id": 88, + "filename": "0001-works-now.patch", + "path": "/langdev-commits", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/langdev-commits/0001-works-now.patch" + } + }, + { + "id": 89, + "filename": "0001-yee.patch", + "path": "/langdev-commits", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/langdev-commits/0001-yee.patch" + } + } + ] + } + }, + { + "id": 12, + "filename": "parser_.py", + "path": "", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/parser_.py" + } + }, + { + "id": 13, + "filename": "tests", + "path": "", + "kind": { + "type": "dir", + "children": [ + { + "id": 25, + "filename": "brugerdefinirede_typer.dk", + "path": "/tests", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/tests/brugerdefinirede_typer.dk" + } + }, + { + "id": 26, + "filename": "funktioner.dk", + "path": "/tests", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/tests/funktioner.dk" + } + }, + { + "id": 27, + "filename": "generiske.dk", + "path": "/tests", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/tests/generiske.dk" + } + }, + { + "id": 28, + "filename": "hvis_ellers.dk", + "path": "/tests", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/tests/hvis_ellers.dk" + } + }, + { + "id": 29, + "filename": "returner.dk", + "path": "/tests", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/tests/returner.dk" + } + }, + { + "id": 30, + "filename": "tom_liste_type_hint.dk", + "path": "/tests", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/tests/tom_liste_type_hint.dk" + } + } + ] + } + }, + { + "id": 14, + "filename": "tokenizer.py", + "path": "", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/tokenizer.py" + } + }, + { + "id": 15, + "filename": "virtual_computer", + "path": "", + "kind": { + "type": "dir", + "children": [ + { + "id": 22, + "filename": "README.md", + "path": "/virtual_computer", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/virtual_computer/README.md" + } + }, + { + "id": 23, + "filename": "asm-grammar.txt", + "path": "/virtual_computer", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/virtual_computer/asm-grammar.txt" + } + }, + { + "id": 24, + "filename": "assembler", + "path": "/virtual_computer", + "kind": { + "type": "dir", + "children": [ + { + "id": 36, + "filename": "__init__.py", + "path": "/virtual_computer/assembler", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/virtual_computer/assembler/__init__.py" + } + }, + { + "id": 37, + "filename": "__main__.py", + "path": "/virtual_computer/assembler", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/virtual_computer/assembler/__main__.py" + } + }, + { + "id": 38, + "filename": "checker.py", + "path": "/virtual_computer/assembler", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/virtual_computer/assembler/checker.py" + } + }, + { + "id": 39, + "filename": "examples", + "path": "/virtual_computer/assembler", + "kind": { + "type": "dir", + "children": [ + { + "id": 91, + "filename": "clear_fast.asm", + "path": "/virtual_computer/assembler/examples", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/virtual_computer/assembler/examples/clear_fast.asm" + } + }, + { + "id": 92, + "filename": "clear_regular.asm", + "path": "/virtual_computer/assembler/examples", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/virtual_computer/assembler/examples/clear_regular.asm" + } + }, + { + "id": 93, + "filename": "clear_slow.asm", + "path": "/virtual_computer/assembler/examples", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/virtual_computer/assembler/examples/clear_slow.asm" + } + } + ] + } + }, + { + "id": 40, + "filename": "generator.py", + "path": "/virtual_computer/assembler", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/virtual_computer/assembler/generator.py" + } + }, + { + "id": 41, + "filename": "parser.py", + "path": "/virtual_computer/assembler", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/virtual_computer/assembler/parser.py" + } + }, + { + "id": 42, + "filename": "spec.py", + "path": "/virtual_computer/assembler", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/virtual_computer/assembler/spec.py" + } + }, + { + "id": 43, + "filename": "symbols.py", + "path": "/virtual_computer/assembler", + "kind": { + "type": "file", + "url": "https://raw.githubusercontent.com/SimonFJ20/danskc/main/virtual_computer/assembler/symbols.py" + } + } + ] + } + } + ] + } + } + ] + } +} as INode; diff --git a/style.css b/style.css new file mode 100644 index 0000000..acca699 --- /dev/null +++ b/style.css @@ -0,0 +1,15 @@ +:root { + color-scheme: light dark; +} + +* { + box-sizing: border-box; +} + +body { + margin: 0; + height: 100vh; + line-height: 1.6em; + max-width: 1000px; + margin: auto; +}