From 47bb30e04d0f38993a943267b3903509f5a9e9eb Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Sat, 2 Aug 2025 12:38:47 +0200 Subject: [PATCH 01/20] Add ace editor in settings --- package-lock.json | 161 +++++++++++++++++++++++++++++++++++++++++++- package.json | 2 + source/options.html | 3 + source/options.js | 29 +++----- 4 files changed, 172 insertions(+), 23 deletions(-) diff --git a/package-lock.json b/package-lock.json index ec3706f..a5c2e0f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,13 @@ { - "name": "SimRepo", + "name": "similar-repositories-extension", "lockfileVersion": 3, "requires": true, "packages": { "": { "dependencies": { + "@codemirror/lang-yaml": "^6.1.2", "@primer/octicons": "^19.15.2", + "codemirror": "^6.0.2", "gh-lang-colors": "^0.1.11", "webext-base-css": "^2.0.1", "webext-options-sync": "^4.2.3" @@ -49,6 +51,102 @@ "node": ">=6.9.0" } }, + "node_modules/@codemirror/autocomplete": { + "version": "6.18.6", + "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.18.6.tgz", + "integrity": "sha512-PHHBXFomUs5DF+9tCOM/UoW6XQ4R44lLNNhRaW9PKPTU0D7lIjRg3ElxaJnTwsl/oHiR93WSXDBrekhoUGCPtg==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.17.0", + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@codemirror/commands": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.8.1.tgz", + "integrity": "sha512-KlGVYufHMQzxbdQONiLyGQDUW0itrLZwq3CcY7xpv9ZLRHqzkBSoteocBHtMCoY7/Ci4xhzSrToIeLg7FxHuaw==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.4.0", + "@codemirror/view": "^6.27.0", + "@lezer/common": "^1.1.0" + } + }, + "node_modules/@codemirror/lang-yaml": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/@codemirror/lang-yaml/-/lang-yaml-6.1.2.tgz", + "integrity": "sha512-dxrfG8w5Ce/QbT7YID7mWZFKhdhsaTNOYjOkSIMt1qmC4VQnXSDSYVHHHn8k6kJUfIhtLo8t1JJgltlxWdsITw==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.2.0", + "@lezer/lr": "^1.0.0", + "@lezer/yaml": "^1.0.0" + } + }, + "node_modules/@codemirror/language": { + "version": "6.11.2", + "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.11.2.tgz", + "integrity": "sha512-p44TsNArL4IVXDTbapUmEkAlvWs2CFQbcfc0ymDsis1kH2wh0gcY96AS29c/vp2d0y2Tquk1EDSaawpzilUiAw==", + "license": "MIT", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.23.0", + "@lezer/common": "^1.1.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0", + "style-mod": "^4.0.0" + } + }, + "node_modules/@codemirror/lint": { + "version": "6.8.5", + "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.8.5.tgz", + "integrity": "sha512-s3n3KisH7dx3vsoeGMxsbRAgKe4O1vbrnKBClm99PU0fWxmxsx5rR2PfqQgIt+2MMJBHbiJ5rfIdLYfB9NNvsA==", + "license": "MIT", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.35.0", + "crelt": "^1.0.5" + } + }, + "node_modules/@codemirror/search": { + "version": "6.5.11", + "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.11.tgz", + "integrity": "sha512-KmWepDE6jUdL6n8cAAqIpRmLPBZ5ZKnicE8oGU/s3QrAVID+0VhLFrzUucVKHG5035/BSykhExDL/Xm7dHthiA==", + "license": "MIT", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "crelt": "^1.0.5" + } + }, + "node_modules/@codemirror/state": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.5.2.tgz", + "integrity": "sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA==", + "license": "MIT", + "dependencies": { + "@marijn/find-cluster-break": "^1.0.0" + } + }, + "node_modules/@codemirror/view": { + "version": "6.38.1", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.38.1.tgz", + "integrity": "sha512-RmTOkE7hRU3OVREqFVITWHz6ocgBjv08GoePscAakgVQfciA3SGCEk7mb9IzwW61cKKmlTpHXG6DUE5Ubx+MGQ==", + "license": "MIT", + "dependencies": { + "@codemirror/state": "^6.5.0", + "crelt": "^1.0.6", + "style-mod": "^4.1.0", + "w3c-keyname": "^2.2.4" + } + }, "node_modules/@csstools/css-parser-algorithms": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.5.tgz", @@ -397,19 +495,37 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.3.tgz", "integrity": "sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA==", - "dev": true, "license": "MIT" }, + "node_modules/@lezer/highlight": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.1.tgz", + "integrity": "sha512-Z5duk4RN/3zuVO7Jq0pGLJ3qynpxUVsh7IbUbGj88+uV2ApSAn6kWg2au3iJb+0Zi7kKtqffIESgNcRXWZWmSA==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.0.0" + } + }, "node_modules/@lezer/lr": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.2.tgz", "integrity": "sha512-pu0K1jCIdnQ12aWNaAVU5bzi7Bd1w54J3ECgANPmYLtQKP0HBj2cE/5coBD66MT10xbtIuUr7tg0Shbsvk0mDA==", - "dev": true, "license": "MIT", "dependencies": { "@lezer/common": "^1.0.0" } }, + "node_modules/@lezer/yaml": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@lezer/yaml/-/yaml-1.0.3.tgz", + "integrity": "sha512-GuBLekbw9jDBDhGur82nuwkxKQ+a3W5H0GfaAthDXcAu+XdpS43VlnxA9E9hllkpSP5ellRDKjLLj7Lu9Wr6xA==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.4.0" + } + }, "node_modules/@lmdb/lmdb-darwin-arm64": { "version": "2.8.5", "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-arm64/-/lmdb-darwin-arm64-2.8.5.tgz", @@ -494,6 +610,12 @@ "win32" ] }, + "node_modules/@marijn/find-cluster-break": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz", + "integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==", + "license": "MIT" + }, "node_modules/@mischnic/json-sourcemap": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/@mischnic/json-sourcemap/-/json-sourcemap-0.1.1.tgz", @@ -2963,6 +3085,21 @@ "node": ">=0.8" } }, + "node_modules/codemirror": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-6.0.2.tgz", + "integrity": "sha512-VhydHotNW5w1UGK0Qj96BwSk/Zqbp9WbnyK2W/eVMv4QyF41INRGpjUhFJY7/uDNuudSc33a/PKr4iDqRduvHw==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/commands": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/lint": "^6.0.0", + "@codemirror/search": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -3044,6 +3181,12 @@ } } }, + "node_modules/crelt": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", + "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==", + "license": "MIT" + }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -5155,6 +5298,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/style-mod": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.2.tgz", + "integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==", + "license": "MIT" + }, "node_modules/stylelint": { "version": "16.21.0", "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.21.0.tgz", @@ -5548,6 +5697,12 @@ "node": ">= 4" } }, + "node_modules/w3c-keyname": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", + "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==", + "license": "MIT" + }, "node_modules/weak-lru-cache": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/weak-lru-cache/-/weak-lru-cache-1.2.2.tgz", diff --git a/package.json b/package.json index 26b2af1..119d677 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,9 @@ } }, "dependencies": { + "@codemirror/lang-yaml": "^6.1.2", "@primer/octicons": "^19.15.2", + "codemirror": "^6.0.2", "gh-lang-colors": "^0.1.11", "webext-base-css": "^2.0.1", "webext-options-sync": "^4.2.3" diff --git a/source/options.html b/source/options.html index 745dc0d..6649b88 100644 --- a/source/options.html +++ b/source/options.html @@ -35,4 +35,7 @@

Notice Content

+
+ + diff --git a/source/options.js b/source/options.js index 909725d..74fd9d5 100644 --- a/source/options.js +++ b/source/options.js @@ -2,26 +2,15 @@ import 'webext-base-css'; import './options.css'; import { optionsStorage } from './options-storage.js'; -const rangeInputs = [...document.querySelectorAll('input[type="range"][name^="color"]')]; -const numberInputs = [...document.querySelectorAll('input[type="number"][name^="color"]')]; -const output = document.querySelector('.color-output'); +import {EditorView, basicSetup} from "codemirror" +import {yaml} from "@codemirror/lang-yaml" -function updateOutputColor() { - output.style.backgroundColor = `rgb(${rangeInputs[0].value}, ${rangeInputs[1].value}, ${rangeInputs[2].value})`; -} +let editor = document.getElementById('editor'); -function updateInputField(event) { - numberInputs[rangeInputs.indexOf(event.currentTarget)].value = event.currentTarget.value; -} +const view = new EditorView({ + parent: editor, + doc: `name: Ferdinand\nage: 93`, + extensions: [basicSetup, yaml()] +}) -for (const input of rangeInputs) { - input.addEventListener('input', updateOutputColor); - input.addEventListener('input', updateInputField); -} - -async function init() { - await optionsStorage.syncForm('#options-form'); - updateOutputColor(); -} - -init(); +console.log("successfully loaded options.js"); From aeee4873e4e0d594653e52b1c3d52ab7f4c38395 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Sat, 2 Aug 2025 12:58:36 +0200 Subject: [PATCH 02/20] Add schema --- package-lock.json | 854 +++++++++++++++++++++++++++++++++++++++++++++- package.json | 2 + source/options.js | 14 +- 3 files changed, 866 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index a5c2e0f..ac94bdd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,8 @@ "@codemirror/lang-yaml": "^6.1.2", "@primer/octicons": "^19.15.2", "codemirror": "^6.0.2", + "codemirror-json-schema": "^0.8.1", + "codemirror-json5": "^1.0.3", "gh-lang-colors": "^0.1.11", "webext-base-css": "^2.0.1", "webext-options-sync": "^4.2.3" @@ -75,6 +77,17 @@ "@lezer/common": "^1.1.0" } }, + "node_modules/@codemirror/lang-json": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@codemirror/lang-json/-/lang-json-6.0.2.tgz", + "integrity": "sha512-x2OtO+AvwEHrEwR0FyyPtfDUiloG3rnVTSZV1W8UteaLL8/MajQd8DpvUb2YVzC+/T18aSDv0H9mu+xw0EStoQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "@codemirror/language": "^6.0.0", + "@lezer/json": "^1.0.0" + } + }, "node_modules/@codemirror/lang-yaml": { "version": "6.1.2", "resolved": "https://registry.npmjs.org/@codemirror/lang-yaml/-/lang-yaml-6.1.2.tgz", @@ -506,6 +519,18 @@ "@lezer/common": "^1.0.0" } }, + "node_modules/@lezer/json": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@lezer/json/-/json-1.0.3.tgz", + "integrity": "sha512-BP9KzdF9Y35PDpv04r0VeSTKDeox5vVr3efE7eBbx3r4s3oNLfunchejZhjArmeieBH+nVOpgIiBJpEAv8ilqQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, "node_modules/@lezer/lr": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.2.tgz", @@ -2533,6 +2558,101 @@ "object-assign": "^4.1.1" } }, + "node_modules/@sagold/json-pointer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@sagold/json-pointer/-/json-pointer-5.1.2.tgz", + "integrity": "sha512-+wAhJZBXa6MNxRScg6tkqEbChEHMgVZAhTHVJ60Y7sbtXtu9XA49KfUkdWlS2x78D6H9nryiKePiYozumauPfA==", + "license": "MIT" + }, + "node_modules/@sagold/json-query": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@sagold/json-query/-/json-query-6.2.0.tgz", + "integrity": "sha512-7bOIdUE6eHeoWtFm8TvHQHfTVSZuCs+3RpOKmZCDBIOrxpvF/rNFTeuvIyjHva/RR0yVS3kQtr+9TW72LQEZjA==", + "license": "MIT", + "dependencies": { + "@sagold/json-pointer": "^5.1.2", + "ebnf": "^1.9.1" + } + }, + "node_modules/@shikijs/core": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.29.2.tgz", + "integrity": "sha512-vju0lY9r27jJfOY4Z7+Rt/nIOjzJpZ3y+nYpqtUZInVoXQ/TJZcfGnNOGnKjFdVZb8qexiCuSlZRKcGfhhTTZQ==", + "license": "MIT", + "dependencies": { + "@shikijs/engine-javascript": "1.29.2", + "@shikijs/engine-oniguruma": "1.29.2", + "@shikijs/types": "1.29.2", + "@shikijs/vscode-textmate": "^10.0.1", + "@types/hast": "^3.0.4", + "hast-util-to-html": "^9.0.4" + } + }, + "node_modules/@shikijs/engine-javascript": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-1.29.2.tgz", + "integrity": "sha512-iNEZv4IrLYPv64Q6k7EPpOCE/nuvGiKl7zxdq0WFuRPF5PAE9PRo2JGq/d8crLusM59BRemJ4eOqrFrC4wiQ+A==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "1.29.2", + "@shikijs/vscode-textmate": "^10.0.1", + "oniguruma-to-es": "^2.2.0" + } + }, + "node_modules/@shikijs/engine-oniguruma": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.29.2.tgz", + "integrity": "sha512-7iiOx3SG8+g1MnlzZVDYiaeHe7Ez2Kf2HrJzdmGwkRisT7r4rak0e655AcM/tF9JG/kg5fMNYlLLKglbN7gBqA==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "1.29.2", + "@shikijs/vscode-textmate": "^10.0.1" + } + }, + "node_modules/@shikijs/langs": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-1.29.2.tgz", + "integrity": "sha512-FIBA7N3LZ+223U7cJDUYd5shmciFQlYkFXlkKVaHsCPgfVLiO+e12FmQE6Tf9vuyEsFe3dIl8qGWKXgEHL9wmQ==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "1.29.2" + } + }, + "node_modules/@shikijs/markdown-it": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/@shikijs/markdown-it/-/markdown-it-1.29.2.tgz", + "integrity": "sha512-RPHqGU8RGQZ2TGMnEqLnSyM9CjPSjb0f8bwSLnJgBmWPWguoygoaFyYkXG0kwMtBtChNYsqQz1C0fLcbo6dY8g==", + "license": "MIT", + "dependencies": { + "markdown-it": "^14.1.0", + "shiki": "1.29.2" + } + }, + "node_modules/@shikijs/themes": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-1.29.2.tgz", + "integrity": "sha512-i9TNZlsq4uoyqSbluIcZkmPL9Bfi3djVxRnofUHwvx/h6SRW3cwgBC5SML7vsDcWyukY0eCzVN980rqP6qNl9g==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "1.29.2" + } + }, + "node_modules/@shikijs/types": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.29.2.tgz", + "integrity": "sha512-VJjK0eIijTZf0QSTODEXCqinjBn0joAHQ+aPSBzrv4O2d/QSbsMw+ZeSRx03kV34Hy7NzUvV/7NqfYGRLrASmw==", + "license": "MIT", + "dependencies": { + "@shikijs/vscode-textmate": "^10.0.1", + "@types/hast": "^3.0.4" + } + }, + "node_modules/@shikijs/vscode-textmate": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz", + "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==", + "license": "MIT" + }, "node_modules/@swc/core": { "version": "1.12.7", "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.12.7.tgz", @@ -2776,6 +2896,15 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", @@ -2783,6 +2912,27 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "license": "ISC" + }, "node_modules/acorn": { "version": "8.15.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", @@ -2853,7 +3003,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, "license": "Python-2.0" }, "node_modules/array-union": { @@ -2914,6 +3063,12 @@ ], "license": "MIT" }, + "node_modules/best-effort-json-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/best-effort-json-parser/-/best-effort-json-parser-1.2.1.tgz", + "integrity": "sha512-UICSLibQdzS1f+PBsi3u2YE3SsdXcWicHUg3IMvfuaePS2AYnZJdJeKhGv5OM8/mqJwPt79aDrEJ1oa84tELvw==", + "license": "BSD-2-Clause" + }, "node_modules/brace-expansion": { "version": "1.1.12", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", @@ -3048,6 +3203,16 @@ ], "license": "CC-BY-4.0" }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -3065,6 +3230,26 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/chrome-trace-event": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", @@ -3100,6 +3285,52 @@ "@codemirror/view": "^6.0.0" } }, + "node_modules/codemirror-json-schema": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/codemirror-json-schema/-/codemirror-json-schema-0.8.1.tgz", + "integrity": "sha512-4lKPjW+nugNAmM5MsggJyn6TUxYdCCwAJIr9T4cZeTFPdkbBvPteCOGtDedrTOIeTC2ZFJtVg7VHIXnYU32t8w==", + "license": "MIT", + "dependencies": { + "@sagold/json-pointer": "^5.1.1", + "@shikijs/markdown-it": "^1.22.2", + "best-effort-json-parser": "^1.1.2", + "json-schema": "^0.4.0", + "json-schema-library": "^9.3.5", + "loglevel": "^1.9.1", + "markdown-it": "^14.1.0", + "shiki": "^1.22.2", + "yaml": "^2.3.4" + }, + "optionalDependencies": { + "@codemirror/autocomplete": "^6.16.2", + "@codemirror/lang-json": "^6.0.1", + "@codemirror/lang-yaml": "^6.1.1", + "codemirror-json5": "^1.0.3", + "json5": "^2.2.3" + }, + "peerDependencies": { + "@codemirror/language": "^6.10.2", + "@codemirror/lint": "^6.8.0", + "@codemirror/state": "^6.4.1", + "@codemirror/view": "^6.27.0", + "@lezer/common": "^1.2.1" + } + }, + "node_modules/codemirror-json5": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/codemirror-json5/-/codemirror-json5-1.0.3.tgz", + "integrity": "sha512-HmmoYO2huQxoaoG5ARKjqQc9mz7/qmNPvMbISVfIE2Gk1+4vZQg9X3G6g49MYM5IK00Ol3aijd7OKrySuOkA7Q==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0", + "@lezer/highlight": "^1.0.0", + "json5": "^2.2.1", + "lezer-json5": "^2.0.2" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -3127,6 +3358,16 @@ "dev": true, "license": "MIT" }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/commander": { "version": "12.1.0", "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", @@ -3264,6 +3505,24 @@ "dev": true, "license": "MIT" }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/detect-libc": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", @@ -3277,6 +3536,19 @@ "node": ">=0.10" } }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "license": "MIT", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -3290,6 +3562,12 @@ "node": ">=8" } }, + "node_modules/discontinuous-range": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", + "integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==", + "license": "MIT" + }, "node_modules/dom-form-serializer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dom-form-serializer/-/dom-form-serializer-2.0.0.tgz", @@ -3325,6 +3603,15 @@ "url": "https://dotenvx.com" } }, + "node_modules/ebnf": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ebnf/-/ebnf-1.9.1.tgz", + "integrity": "sha512-uW2UKSsuty9ANJ3YByIQE4ANkD8nqUPO7r6Fwcc1ADKPe9FRdcPpMl3VEput4JSvKBJ4J86npIC2MLP0pYkCuw==", + "license": "MIT", + "bin": { + "ebnf": "dist/bin.js" + } + }, "node_modules/electron-to-chromium": { "version": "1.5.177", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.177.tgz", @@ -3339,6 +3626,24 @@ "dev": true, "license": "MIT" }, + "node_modules/emoji-regex-xs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex-xs/-/emoji-regex-xs-1.0.0.tgz", + "integrity": "sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==", + "license": "MIT" + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/env-paths": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", @@ -3537,11 +3842,16 @@ "node": ">=0.10.0" } }, + "node_modules/fast-copy": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.2.tgz", + "integrity": "sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==", + "license": "MIT" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, "license": "MIT" }, "node_modules/fast-glob": { @@ -3810,6 +4120,42 @@ "node": ">=8" } }, + "node_modules/hast-util-to-html": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz", + "integrity": "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-whitespace": "^3.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "stringify-entities": "^4.0.0", + "zwitch": "^2.0.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hookified": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/hookified/-/hookified-1.10.0.tgz", @@ -3830,6 +4176,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/html-void-elements": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", + "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -3999,6 +4355,27 @@ "node": "^18.17.0 || >=20.5.0" } }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "license": "(AFL-2.1 OR BSD-3-Clause)" + }, + "node_modules/json-schema-library": { + "version": "9.3.5", + "resolved": "https://registry.npmjs.org/json-schema-library/-/json-schema-library-9.3.5.tgz", + "integrity": "sha512-5eBDx7cbfs+RjylsVO+N36b0GOPtv78rfqgf2uON+uaHUIC62h63Y8pkV2ovKbaL4ZpQcHp21968x5nx/dFwqQ==", + "license": "MIT", + "dependencies": { + "@sagold/json-pointer": "^5.1.2", + "@sagold/json-query": "^6.1.3", + "deepmerge": "^4.3.1", + "fast-copy": "^3.0.2", + "fast-deep-equal": "^3.1.3", + "smtp-address-parser": "1.0.10", + "valid-url": "^1.0.9" + } + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -4017,7 +4394,6 @@ "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, "license": "MIT", "bin": { "json5": "lib/cli.js" @@ -4067,6 +4443,15 @@ "node": ">= 0.8.0" } }, + "node_modules/lezer-json5": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lezer-json5/-/lezer-json5-2.0.2.tgz", + "integrity": "sha512-NRmtBlKW/f8mA7xatKq8IUOq045t8GVHI4kZXrUtYYUdiVeGiO6zKGAV7/nUAnf5q+rYTY+SWX/gvQdFXMjNxQ==", + "license": "MIT", + "dependencies": { + "@lezer/lr": "^1.0.0" + } + }, "node_modules/lightningcss": { "version": "1.30.1", "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz", @@ -4323,6 +4708,15 @@ "dev": true, "license": "MIT" }, + "node_modules/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "license": "MIT", + "dependencies": { + "uc.micro": "^2.0.0" + } + }, "node_modules/lmdb": { "version": "2.8.5", "resolved": "https://registry.npmjs.org/lmdb/-/lmdb-2.8.5.tgz", @@ -4386,6 +4780,19 @@ "dev": true, "license": "MIT" }, + "node_modules/loglevel": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.9.2.tgz", + "integrity": "sha512-HgMmCqIJSAKqo68l0rS2AanEWfkxaZ5wNiEFb5ggm08lDs9Xl2KxBlX3PTcaD2chBM1gXAYf491/M2Rv8Jwayg==", + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + }, + "funding": { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/loglevel" + } + }, "node_modules/lz-string": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", @@ -4395,6 +4802,23 @@ "lz-string": "bin/bin.js" } }, + "node_modules/markdown-it": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, "node_modules/mathml-tag-names": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz", @@ -4406,6 +4830,27 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/mdast-util-to-hast": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", + "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/mdn-data": { "version": "2.12.2", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.12.2.tgz", @@ -4413,6 +4858,12 @@ "dev": true, "license": "CC0-1.0" }, + "node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "license": "MIT" + }, "node_modules/memorystream": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", @@ -4445,6 +4896,95 @@ "node": ">= 8" } }, + "node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", + "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, "node_modules/micromatch": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", @@ -4472,6 +5012,12 @@ "node": "*" } }, + "node_modules/moo": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz", + "integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==", + "license": "BSD-3-Clause" + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -4565,6 +5111,34 @@ "dev": true, "license": "MIT" }, + "node_modules/nearley": { + "version": "2.20.1", + "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz", + "integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==", + "license": "MIT", + "dependencies": { + "commander": "^2.19.0", + "moo": "^0.5.0", + "railroad-diagrams": "^1.0.0", + "randexp": "0.4.6" + }, + "bin": { + "nearley-railroad": "bin/nearley-railroad.js", + "nearley-test": "bin/nearley-test.js", + "nearley-unparse": "bin/nearley-unparse.js", + "nearleyc": "bin/nearleyc.js" + }, + "funding": { + "type": "individual", + "url": "https://nearley.js.org/#give-to-nearley" + } + }, + "node_modules/nearley/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "license": "MIT" + }, "node_modules/node-addon-api": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", @@ -4732,6 +5306,17 @@ "node": ">=0.10.0" } }, + "node_modules/oniguruma-to-es": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-2.3.0.tgz", + "integrity": "sha512-bwALDxriqfKGfUufKGGepCzu9x7nJQuoRoAFp4AnwehhC2crqrDIAP/uN2qdlsAvSMpeRC3+Yzhqc7hLmle5+g==", + "license": "MIT", + "dependencies": { + "emoji-regex-xs": "^1.0.0", + "regex": "^5.1.1", + "regex-recursion": "^5.1.1" + } + }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -5019,6 +5604,16 @@ "node": ">= 0.8.0" } }, + "node_modules/property-information": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", + "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -5029,6 +5624,15 @@ "node": ">=6" } }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -5050,6 +5654,25 @@ ], "license": "MIT" }, + "node_modules/railroad-diagrams": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", + "integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==", + "license": "CC0-1.0" + }, + "node_modules/randexp": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", + "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", + "license": "MIT", + "dependencies": { + "discontinuous-range": "1.0.0", + "ret": "~0.1.10" + }, + "engines": { + "node": ">=0.12" + } + }, "node_modules/react-refresh": { "version": "0.16.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.16.0.tgz", @@ -5081,6 +5704,31 @@ "dev": true, "license": "MIT" }, + "node_modules/regex": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/regex/-/regex-5.1.1.tgz", + "integrity": "sha512-dN5I359AVGPnwzJm2jN1k0W9LPZ+ePvoOeVMMfqIMFz53sSwXkxaJoxr50ptnsC771lK95BnTrVSZxq0b9yCGw==", + "license": "MIT", + "dependencies": { + "regex-utilities": "^2.3.0" + } + }, + "node_modules/regex-recursion": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/regex-recursion/-/regex-recursion-5.1.1.tgz", + "integrity": "sha512-ae7SBCbzVNrIjgSbh7wMznPcQel1DNlDtzensnFxpiNpXt1U2ju/bHugH422r+4LAVS1FpW1YCwilmnNsjum9w==", + "license": "MIT", + "dependencies": { + "regex": "^5.1.1", + "regex-utilities": "^2.3.0" + } + }, + "node_modules/regex-utilities": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/regex-utilities/-/regex-utilities-2.3.0.tgz", + "integrity": "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==", + "license": "MIT" + }, "node_modules/require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", @@ -5101,6 +5749,15 @@ "node": ">=4" } }, + "node_modules/ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "license": "MIT", + "engines": { + "node": ">=0.12" + } + }, "node_modules/reusify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", @@ -5206,6 +5863,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/shiki": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.29.2.tgz", + "integrity": "sha512-njXuliz/cP+67jU2hukkxCNuH1yUi4QfdZZY+sMr5PPrIyXSu5iTb/qYC4BiWWB0vZ+7TbdvYUCeL23zpwCfbg==", + "license": "MIT", + "dependencies": { + "@shikijs/core": "1.29.2", + "@shikijs/engine-javascript": "1.29.2", + "@shikijs/engine-oniguruma": "1.29.2", + "@shikijs/langs": "1.29.2", + "@shikijs/themes": "1.29.2", + "@shikijs/types": "1.29.2", + "@shikijs/vscode-textmate": "^10.0.1", + "@types/hast": "^3.0.4" + } + }, "node_modules/signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", @@ -5247,6 +5920,18 @@ "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, + "node_modules/smtp-address-parser": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/smtp-address-parser/-/smtp-address-parser-1.0.10.tgz", + "integrity": "sha512-Osg9LmvGeAG/hyao4mldbflLOkkr3a+h4m1lwKCK5U8M6ZAr7tdXEz/+/vr752TSGE4MNUlUl9cIK2cB8cgzXg==", + "license": "MIT", + "dependencies": { + "nearley": "^2.20.1" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -5257,6 +5942,16 @@ "node": ">=0.10.0" } }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -5272,6 +5967,20 @@ "node": ">=8" } }, + "node_modules/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "license": "MIT", + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -5594,6 +6303,16 @@ "node": ">=8.0" } }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", @@ -5627,6 +6346,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "license": "MIT" + }, "node_modules/uint8array-extras": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/uint8array-extras/-/uint8array-extras-1.4.0.tgz", @@ -5639,6 +6364,74 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/update-browserslist-db": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", @@ -5697,6 +6490,39 @@ "node": ">= 4" } }, + "node_modules/valid-url": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/valid-url/-/valid-url-1.0.9.tgz", + "integrity": "sha512-QQDsV8OnSf5Uc30CKSwG9lnhMPe6exHtTXLRYX8uMwKENy640pU+2BgBL0LRbDh/eYRahNCS7aewCx0wf3NYVA==" + }, + "node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/w3c-keyname": { "version": "2.2.8", "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", @@ -5816,6 +6642,18 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/yaml": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.0.tgz", + "integrity": "sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", @@ -5828,6 +6666,16 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } } } } diff --git a/package.json b/package.json index 119d677..8846f80 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,8 @@ "@codemirror/lang-yaml": "^6.1.2", "@primer/octicons": "^19.15.2", "codemirror": "^6.0.2", + "codemirror-json-schema": "^0.8.1", + "codemirror-json5": "^1.0.3", "gh-lang-colors": "^0.1.11", "webext-base-css": "^2.0.1", "webext-options-sync": "^4.2.3" diff --git a/source/options.js b/source/options.js index 74fd9d5..0b8685f 100644 --- a/source/options.js +++ b/source/options.js @@ -4,13 +4,25 @@ import { optionsStorage } from './options-storage.js'; import {EditorView, basicSetup} from "codemirror" import {yaml} from "@codemirror/lang-yaml" +import { yamlSchema } from 'codemirror-json-schema/yaml'; + +const schema = { + type: "object", + description: "Root configuration object", + properties: { + example: { + type: "boolean", + description: "Enable or disable the example feature", + }, + }, +}; let editor = document.getElementById('editor'); const view = new EditorView({ parent: editor, doc: `name: Ferdinand\nage: 93`, - extensions: [basicSetup, yaml()] + extensions: [basicSetup, yaml(), yamlSchema(schema)] }) console.log("successfully loaded options.js"); From b1941609ae37c86702f167eed4aa0503a4625e6d Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Sun, 3 Aug 2025 01:44:05 +0200 Subject: [PATCH 03/20] Improve settings usability --- source/options-storage.js | 12 ++++-- source/options.css | 70 +++---------------------------- source/options.html | 33 --------------- source/options.js | 87 +++++++++++++++++++++++++++++++++------ 4 files changed, 89 insertions(+), 113 deletions(-) diff --git a/source/options-storage.js b/source/options-storage.js index f07a7a1..f0f6cb6 100644 --- a/source/options-storage.js +++ b/source/options-storage.js @@ -2,10 +2,14 @@ import OptionsSync from 'webext-options-sync'; const optionsStorage = new OptionsSync({ defaults: { - colorRed: 244, - colorGreen: 67, - colorBlue: 54, - text: 'Set a text!', + similarEnabled: true, + similarCount: 5, + // similarShowArchived: true, + + homepageEnabled: true, + homepageCount: 90, + poolSize: 3.0, + // homepageShowArchived: true, }, migrations: [ OptionsSync.migrations.removeUnused, diff --git a/source/options.css b/source/options.css index c50dc9b..9ff957c 100644 --- a/source/options.css +++ b/source/options.css @@ -1,66 +1,8 @@ -html { - min-width: 550px; - overflow-x: hidden; /* Required to hide horizontal scroll on Firefox */ -} - -/* For use with screen readers */ -.sr-only { - display: none; -} - -/* Hide spinbox for number inputs */ -input::-webkit-outer-spin-button, -input::-webkit-inner-spin-button { - appearance: none; +html, body { + padding: 0; margin: 0; -} - -input[type='number'] { - appearance: textfield; -} - -input[type='number'], -input[type='text'] { - padding: 0.25rem 0.375rem; -} - -.color-picker { - display: flex; -} - -.color-inputs { - flex: 1; -} - -.color-input { - display: flex; - padding: 0.25rem; - align-items: center; -} - -.color-input input[type='range'] { - flex: 1; - margin: 0 0.5rem; -} - -.color-input input[type='number'] { - width: calc(3ch + 1rem); -} - -.color-output { - width: 86px; - height: 86px; - margin: 0.5rem; -} - -/* Firefox only */ -.only-firefox { - display: none; -} - -/* stylelint-disable-next-line at-rule-no-vendor-prefix */ -@-moz-document url-prefix('') { - .only-firefox { - display: block; - } + min-width: 100%; + min-height: max(100%, 40rem); + max-width: 100%; + max-height: 100%; } diff --git a/source/options.html b/source/options.html index 6649b88..02b8a5b 100644 --- a/source/options.html +++ b/source/options.html @@ -2,39 +2,6 @@ Options -

Options are not implemented yet. Stay tuned!

- -
-

Color Picker

-
-
- - - -
-
-
-

Notice Content

-
- -
-
-
diff --git a/source/options.js b/source/options.js index 0b8685f..58615f4 100644 --- a/source/options.js +++ b/source/options.js @@ -2,27 +2,90 @@ import 'webext-base-css'; import './options.css'; import { optionsStorage } from './options-storage.js'; -import {EditorView, basicSetup} from "codemirror" -import {yaml} from "@codemirror/lang-yaml" +import { basicSetup } from "codemirror" +import {EditorView, keymap } from "@codemirror/view" +import { yaml } from "@codemirror/lang-yaml" import { yamlSchema } from 'codemirror-json-schema/yaml'; +import { indentWithTab } from "@codemirror/commands" const schema = { - type: "object", - description: "Root configuration object", - properties: { - example: { - type: "boolean", - description: "Enable or disable the example feature", + type: "object", + description: "Extension settings", + properties: { + similar: { + type: "object", + description: "Settings for showing similar projects in the sidebar of a repository.", + properties: { + enabled: { + type: "boolean", + description: "Whether to show similar repositories", + default: true, + }, + count: { + type: "integer", + description: "Number of similar items to show", + default: 5, + minimum: 1, + }, + // showArchived: { + // type: "boolean", + // description: "Whether to include archived repositories in the list of similar projects", + // default: true, + // }, + }, + required: [], + }, + homepage: { + type: "object", + description: "Settings for homepage recommendations", + properties: { + enabled: { + type: "boolean", + description: "Enable or disable the homepage feature", + default: true, + }, + count: { + type: "integer", + description: "Number of items to display on the homepage. Since they are loaded 30 by 30, this would benefit being a multiple of 30.", + default: 90, + minimum: 1, + }, + poolSize: { + type: "number", + description: "Size ratio of a pool against the count of recommendations shown. Recommendations are randomly selected from the pool. If you find the homepage recommendations to be too repetitive, increase this value.", + default: 3.0, + minimum: 1.0, + maximum: 10.0, + }, + // showArchived: { + // type: "boolean", + // description: "Whether to include archived repositories in the homepage recommendations", + // default: false, + // }, + }, + required: [], + }, }, - }, + required: [], }; let editor = document.getElementById('editor'); +function defaultCode() { + let code = "# Welcome the SimRepo's settings\n# See the readme for a complete example of a valid config\n# If you want to reset settings, just clear everything and the default configuration will be restored.\n\n" + for (const [key, prop] of Object.entries(schema.properties)) { + code += `\n# ${prop.description}\n${key}:\n`; + for (const [subKey, subProp] of Object.entries(prop.properties)) { + code += ` # ${subProp.description}\n ${subKey}: ${JSON.stringify(subProp.default)}\n\n`; + } + } + return code; +} + const view = new EditorView({ - parent: editor, - doc: `name: Ferdinand\nage: 93`, - extensions: [basicSetup, yaml(), yamlSchema(schema)] + parent: editor, + doc: defaultCode(), + extensions: [basicSetup, keymap.of([indentWithTab]), EditorView.lineWrapping, yaml(), yamlSchema(schema)] }) console.log("successfully loaded options.js"); From aa9401fa817de3893e93815d98a49b6e0e031a8a Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Sun, 3 Aug 2025 02:05:59 +0200 Subject: [PATCH 04/20] Reset settings when cleared --- source/options.js | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/source/options.js b/source/options.js index 58615f4..82b39e9 100644 --- a/source/options.js +++ b/source/options.js @@ -3,7 +3,7 @@ import './options.css'; import { optionsStorage } from './options-storage.js'; import { basicSetup } from "codemirror" -import {EditorView, keymap } from "@codemirror/view" +import { EditorView, keymap } from "@codemirror/view" import { yaml } from "@codemirror/lang-yaml" import { yamlSchema } from 'codemirror-json-schema/yaml'; import { indentWithTab } from "@codemirror/commands" @@ -72,7 +72,7 @@ const schema = { let editor = document.getElementById('editor'); function defaultCode() { - let code = "# Welcome the SimRepo's settings\n# See the readme for a complete example of a valid config\n# If you want to reset settings, just clear everything and the default configuration will be restored.\n\n" + let code = "# Welcome the SimRepo's settings\n# See the readme for a complete example of a valid config\n# If you want to reset settings, just clear everything and the default configuration will be restored.\n# Settings are saved automatically\n\n" for (const [key, prop] of Object.entries(schema.properties)) { code += `\n# ${prop.description}\n${key}:\n`; for (const [subKey, subProp] of Object.entries(prop.properties)) { @@ -82,10 +82,22 @@ function defaultCode() { return code; } +const resetOnEmpty = EditorView.updateListener.of((update) => { + if (update.docChanged) { + const currentContent = update.state.doc.toString().trim(); + if (currentContent === "") { + // Reset the editor content to default + update.view.dispatch({ + changes: { from: 0, to: 0, insert: defaultCode() }, + }); + } + } +}); + const view = new EditorView({ parent: editor, doc: defaultCode(), - extensions: [basicSetup, keymap.of([indentWithTab]), EditorView.lineWrapping, yaml(), yamlSchema(schema)] + extensions: [basicSetup, keymap.of([indentWithTab]), resetOnEmpty, EditorView.lineWrapping, yaml(), yamlSchema(schema)] }) console.log("successfully loaded options.js"); From b0ef42fb0879beabaf831fff05921fd40afe5c82 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Sun, 3 Aug 2025 19:02:06 +0200 Subject: [PATCH 05/20] Store settings --- package-lock.json | 3 +- package.json | 3 +- source/options-storage.js | 5 +- source/options.js | 104 ++++++++++++++++++++++++++++++++++---- 4 files changed, 101 insertions(+), 14 deletions(-) diff --git a/package-lock.json b/package-lock.json index ac94bdd..5c1a7e0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,8 @@ "codemirror-json5": "^1.0.3", "gh-lang-colors": "^0.1.11", "webext-base-css": "^2.0.1", - "webext-options-sync": "^4.2.3" + "webext-options-sync": "^4.2.3", + "yaml": "^2.8.0" }, "devDependencies": { "@eslint/eslintrc": "^3.3.1", diff --git a/package.json b/package.json index 8846f80..60092e4 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,8 @@ "codemirror-json5": "^1.0.3", "gh-lang-colors": "^0.1.11", "webext-base-css": "^2.0.1", - "webext-options-sync": "^4.2.3" + "webext-options-sync": "^4.2.3", + "yaml": "^2.8.0" }, "devDependencies": { "@eslint/eslintrc": "^3.3.1", diff --git a/source/options-storage.js b/source/options-storage.js index f0f6cb6..3da1a73 100644 --- a/source/options-storage.js +++ b/source/options-storage.js @@ -2,12 +2,15 @@ import OptionsSync from 'webext-options-sync'; const optionsStorage = new OptionsSync({ defaults: { + optionsYaml: "", + similarEnabled: true, similarCount: 5, // similarShowArchived: true, homepageEnabled: true, - homepageCount: 90, + homepageCount: 25, + homepageStarsToLoad: 60, poolSize: 3.0, // homepageShowArchived: true, }, diff --git a/source/options.js b/source/options.js index 82b39e9..01913d6 100644 --- a/source/options.js +++ b/source/options.js @@ -7,6 +7,9 @@ import { EditorView, keymap } from "@codemirror/view" import { yaml } from "@codemirror/lang-yaml" import { yamlSchema } from 'codemirror-json-schema/yaml'; import { indentWithTab } from "@codemirror/commands" +import { ensureSyntaxTree, syntaxTree, syntaxTreeAvailable } from "@codemirror/language"; +import YAML from 'yaml'; +import { optionsStorage } from './options-storage.js'; const schema = { type: "object", @@ -46,9 +49,16 @@ const schema = { }, count: { type: "integer", - description: "Number of items to display on the homepage. Since they are loaded 30 by 30, this would benefit being a multiple of 30.", - default: 90, + description: "Number of items to display on the homepage", + default: 25, + maximum: 150, + }, + starsToLoad: { + type: "integer", + description: "Number of your latest stars to load in order to provide you recommendations. Since repositories with less than 150 stars won't be used, the actual number may be less. Stars are loaded 30 by 30 so this would benefit being a multiple of 30.", + default: 60, minimum: 1, + maximum: 120, }, poolSize: { type: "number", @@ -71,12 +81,37 @@ const schema = { let editor = document.getElementById('editor'); -function defaultCode() { - let code = "# Welcome the SimRepo's settings\n# See the readme for a complete example of a valid config\n# If you want to reset settings, just clear everything and the default configuration will be restored.\n# Settings are saved automatically\n\n" +async function defaultCode() { + let options = await optionsStorage.getAll(); + + let code = "# Welcome the SimRepo's settings\n# If you want to reset settings, just clear everything and the default configuration will be restored.\n# Settings are saved automatically\n# Comments will NOT be saved\n\n" for (const [key, prop] of Object.entries(schema.properties)) { code += `\n# ${prop.description}\n${key}:\n`; for (const [subKey, subProp] of Object.entries(prop.properties)) { - code += ` # ${subProp.description}\n ${subKey}: ${JSON.stringify(subProp.default)}\n\n`; + let value = null; + switch ((key, subKey)) { + case ("similar", "enabled"): + value = options.similarEnabled; + break; + case ("similar", "count"): + value = options.similarCount; + break; + case ("homepage", "enabled"): + value = options.homepageEnabled; + break; + case ("homepage", "count"): + value = options.homepageCount; + break; + case ("homepage", "starsToLoad"): + value = options.homepageStarsToLoad; + break; + case ("homepage", "poolSize"): + value = options.homepagePoolSize; + break; + default: + value = "Unknown value. Open an issue on GitHub if you see this."; + } + code += ` # ${subProp.description}\n ${subKey}: ${value}\n\n`; } } return code; @@ -94,10 +129,57 @@ const resetOnEmpty = EditorView.updateListener.of((update) => { } }); -const view = new EditorView({ - parent: editor, - doc: defaultCode(), - extensions: [basicSetup, keymap.of([indentWithTab]), resetOnEmpty, EditorView.lineWrapping, yaml(), yamlSchema(schema)] -}) +let changed = false; +let saveTimeout = null; +const autoSave = EditorView.updateListener.of((update) => { + if (update.docChanged) { + document.title = "Options (unsaved)"; + changed = true; + if (saveTimeout) clearTimeout(saveTimeout); + saveTimeout = setTimeout(() => { + saveIfChanged(); + saveTimeout = null; + }, 1000); // 1 second after last edit + } +}); + +async function saveIfChanged() { + if (changed) { + const doc = view.state.doc.toString(); + try { + const parsed = YAML.parse(doc); + await optionsStorage.set({ + optionsYaml: doc, + similarEnabled: parsed.similar?.enabled ?? optionsStorage.defaults.similarEnabled, + similarCount: parsed.similar?.count ?? optionsStorage.defaults.similarCount, + homepageEnabled: parsed.homepage?.enabled ?? optionsStorage.defaults.homepageEnabled, + homepageCount: parsed.homepage?.count ?? optionsStorage.defaults.homepageCount, + homepageStarsToLoad: parsed.homepage?.starsToLoad ?? optionsStorage.defaults.homepageStarsToLoad, + homepagePoolSize: parsed.homepage?.poolSize ?? optionsStorage.defaults.homepagePoolSize, + }); + + let options = await optionsStorage.getAll(); + console.log("Settings saved:", options); + + changed = false; + document.title = "Options"; + } catch (e) { + console.error("YAML parse error β€” not saving:", e.message); + } + } +} + +window.addEventListener("beforeunload", () => { + saveIfChanged(); +}); + +var view = null; +async function init() { + view = new EditorView({ + parent: editor, + doc: await defaultCode(), + extensions: [basicSetup, keymap.of([indentWithTab]), resetOnEmpty, autoSave, EditorView.lineWrapping, yaml(), yamlSchema(schema)] + }) +} -console.log("successfully loaded options.js"); +init(); From 4304d6a320fdef97da07fc36ce949461190f8a87 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Sun, 3 Aug 2025 19:51:21 +0200 Subject: [PATCH 06/20] Add settings support --- source/content-repo.js | 10 +++++++++- source/content-stars.js | 41 ++++++++++++++++++++++++++++----------- source/options-storage.js | 2 +- source/options.js | 25 +++++++++--------------- 4 files changed, 49 insertions(+), 29 deletions(-) diff --git a/source/content-repo.js b/source/content-repo.js index dab10ff..bead099 100644 --- a/source/content-repo.js +++ b/source/content-repo.js @@ -1,6 +1,7 @@ import GH_LANG_COLORS from 'gh-lang-colors'; import octicons from "@primer/octicons"; import { getSimilarRepos, formatNumber, loadingSpinner } from './common.js'; +import { optionsStorage } from './options-storage.js'; var loading = false; var nextOffset = 0; @@ -148,6 +149,12 @@ async function getRepoId() { } export async function loadMoreRepos(resetOffset = false) { + let options = await optionsStorage.getAll(); + if (!options.similarEnabled) { + console.log("Similar repositories are disabled"); + return; + } + if (resetOffset) { nextOffset = 0; } @@ -178,8 +185,9 @@ export async function loadMoreRepos(resetOffset = false) { try { loading = true; let offset = nextOffset; + let limit = offset == 0 ? options.similarCount : 5; nextOffset += 5; - let response = await getSimilarRepos([repoId], offset, 5); + let response = await getSimilarRepos([repoId], offset, limit); loading = false; if (response.status === "success" && response.data !== undefined) { diff --git a/source/content-stars.js b/source/content-stars.js index db9ddcf..dc66a25 100644 --- a/source/content-stars.js +++ b/source/content-stars.js @@ -1,19 +1,22 @@ import octicons from "@primer/octicons"; import GH_LANG_COLORS from 'gh-lang-colors'; import { formatNumber, getSimilarRepos, loadingSpinner } from './common.js'; +import { optionsStorage } from "./options-storage.js"; export async function initHome() { - console.log("Producing recommendations on the homepage"); - - let latestStars = 30; + let options = await optionsStorage.getAll(); + if (!options.homepageEnabled) { + console.log("Homepage recommendations are disabled in options."); + return; + } + console.log("Producing recommendations on the homepage"); let container = document.querySelector('aside.feed-right-sidebar>div[aria-label="Explore repositories"]>div'); - if (!container) { // Fallback to creating a new container. Might be buggy if the structure changes. let aside = document.querySelector('aside.feed-right-sidebar'); let newContainer = document.createElement('div'); - newContainer.setAttribute("class", "mb-3 dashboard-changelog Failed to load recommendations. Please try again later or open an issue.
Details: ${error.message}`; @@ -55,14 +58,25 @@ export async function initStarsList() { console.log('πŸ’ˆ Found similar repos for homepage:', response); } -async function run(container, latestStars) { +function getRandomSubsetInOrder(array, count) { + const indices = new Set(); + while (indices.size < count) { + const i = Math.floor(Math.random() * array.length); + indices.add(i); + } + + const sortedIndices = Array.from(indices).sort((a, b) => a - b); + return sortedIndices.map(i => array[i]); +} + +async function run(container, options) { let login = document.querySelector('meta[name="user-login"]').getAttribute('content'); console.log("User login:", login); let after = null; let stars = new Set(); - while (stars.size < latestStars) { + while (stars.size < options.homepageStarsToLoad) { let url = `https://github.com/${login}?tab=stars`; if (after) { url += `&after=${after}`; @@ -78,7 +92,7 @@ async function run(container, latestStars) { let id = matches[1]; if (id) { stars.add(Number(id)); - if (stars.size >= latestStars) { + if (stars.size >= options.homepageStarsToLoad) { break; } } @@ -98,8 +112,13 @@ async function run(container, latestStars) { console.log("Collected stars:", stars); - let response = await getSimilarRepos(Array.from(stars), 0, 15); + let recommendationCount = Math.round(options.homepageCount * options.homepagePoolSize); + let response = await getSimilarRepos(Array.from(stars), 0, recommendationCount); console.log('πŸ’ˆ Found similar repos for homepage:', response); + if (options.homepagePoolSize > 1) { + response.data = getRandomSubsetInOrder(response.data, options.homepageCount); + console.log('πŸ’ˆ Created a subset of', options.homepageCount, 'repositories'); + } let innerHtml = ''; for (let i = 0; i < response.data.length; i++) { diff --git a/source/options-storage.js b/source/options-storage.js index 3da1a73..d37a878 100644 --- a/source/options-storage.js +++ b/source/options-storage.js @@ -11,7 +11,7 @@ const optionsStorage = new OptionsSync({ homepageEnabled: true, homepageCount: 25, homepageStarsToLoad: 60, - poolSize: 3.0, + homepagePoolSize: 3.0, // homepageShowArchived: true, }, migrations: [ diff --git a/source/options.js b/source/options.js index 01913d6..6c1673e 100644 --- a/source/options.js +++ b/source/options.js @@ -22,18 +22,15 @@ const schema = { enabled: { type: "boolean", description: "Whether to show similar repositories", - default: true, }, count: { type: "integer", description: "Number of similar items to show", - default: 5, minimum: 1, }, // showArchived: { // type: "boolean", // description: "Whether to include archived repositories in the list of similar projects", - // default: true, // }, }, required: [], @@ -45,32 +42,27 @@ const schema = { enabled: { type: "boolean", description: "Enable or disable the homepage feature", - default: true, }, count: { type: "integer", description: "Number of items to display on the homepage", - default: 25, maximum: 150, }, starsToLoad: { type: "integer", description: "Number of your latest stars to load in order to provide you recommendations. Since repositories with less than 150 stars won't be used, the actual number may be less. Stars are loaded 30 by 30 so this would benefit being a multiple of 30.", - default: 60, minimum: 1, maximum: 120, }, poolSize: { type: "number", description: "Size ratio of a pool against the count of recommendations shown. Recommendations are randomly selected from the pool. If you find the homepage recommendations to be too repetitive, increase this value.", - default: 3.0, minimum: 1.0, maximum: 10.0, }, // showArchived: { // type: "boolean", // description: "Whether to include archived repositories in the homepage recommendations", - // default: false, // }, }, required: [], @@ -83,29 +75,30 @@ let editor = document.getElementById('editor'); async function defaultCode() { let options = await optionsStorage.getAll(); + console.log("Default options:", options); - let code = "# Welcome the SimRepo's settings\n# If you want to reset settings, just clear everything and the default configuration will be restored.\n# Settings are saved automatically\n# Comments will NOT be saved\n\n" + let code = "# Welcome the SimRepo's options\n# If you want to reset options, just clear everything and the default configuration will be restored.\n# Options are saved automatically, but comments will be ignored\n# Options are experimental, feel free to open issues on GitHub if you find any\n\n" for (const [key, prop] of Object.entries(schema.properties)) { code += `\n# ${prop.description}\n${key}:\n`; for (const [subKey, subProp] of Object.entries(prop.properties)) { let value = null; - switch ((key, subKey)) { - case ("similar", "enabled"): + switch (`${key}.${subKey}`) { + case "similar.enabled": value = options.similarEnabled; break; - case ("similar", "count"): + case "similar.count": value = options.similarCount; break; - case ("homepage", "enabled"): + case "homepage.enabled": value = options.homepageEnabled; break; - case ("homepage", "count"): + case "homepage.count": value = options.homepageCount; break; - case ("homepage", "starsToLoad"): + case "homepage.starsToLoad": value = options.homepageStarsToLoad; break; - case ("homepage", "poolSize"): + case "homepage.poolSize": value = options.homepagePoolSize; break; default: From a540e2cefd25adb0f8d34d277ea9cba21cec31a4 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Sat, 1 Nov 2025 15:30:33 +0100 Subject: [PATCH 07/20] Add maintenance notice to README Added maintenance notice regarding server relocation. --- readme.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/readme.md b/readme.md index 4a77030..b615eaa 100644 --- a/readme.md +++ b/readme.md @@ -1,3 +1,11 @@ +

⚠️ NOVEMBER MAINTAINANCE ⚠️

+ +

+The API will be down for a few days as I'm moving my server to a new location. This project is still maintained, please do not open issues about this. +

+ + + # SimRepo [link-rgh]: https://github.com/sindresorhus/refined-github From 3d744f0de175e00442b54d2cd3facd0195d2cdce Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Thu, 6 Nov 2025 10:07:48 +0100 Subject: [PATCH 08/20] Remove November maintenance notice from README Removed maintenance notice from the README. --- readme.md | 8 -------- 1 file changed, 8 deletions(-) diff --git a/readme.md b/readme.md index b615eaa..4a77030 100644 --- a/readme.md +++ b/readme.md @@ -1,11 +1,3 @@ -

⚠️ NOVEMBER MAINTAINANCE ⚠️

- -

-The API will be down for a few days as I'm moving my server to a new location. This project is still maintained, please do not open issues about this. -

- - - # SimRepo [link-rgh]: https://github.com/sindresorhus/refined-github From 2fbcca8772ae8224e7451eb85a5ff3c490c85ec6 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Thu, 20 Nov 2025 15:25:59 +0100 Subject: [PATCH 09/20] Remove outline in settings --- source/options.css | 8 -------- source/options.html | 19 +++++++++++++++++-- source/options.js | 7 +------ 3 files changed, 18 insertions(+), 16 deletions(-) delete mode 100644 source/options.css diff --git a/source/options.css b/source/options.css deleted file mode 100644 index 9ff957c..0000000 --- a/source/options.css +++ /dev/null @@ -1,8 +0,0 @@ -html, body { - padding: 0; - margin: 0; - min-width: 100%; - min-height: max(100%, 40rem); - max-width: 100%; - max-height: 100%; -} diff --git a/source/options.html b/source/options.html index 02b8a5b..693cf58 100644 --- a/source/options.html +++ b/source/options.html @@ -2,7 +2,22 @@ Options -
+ - +
+ \ No newline at end of file diff --git a/source/options.js b/source/options.js index 6c1673e..4df8622 100644 --- a/source/options.js +++ b/source/options.js @@ -1,15 +1,10 @@ -import 'webext-base-css'; -import './options.css'; import { optionsStorage } from './options-storage.js'; - import { basicSetup } from "codemirror" import { EditorView, keymap } from "@codemirror/view" import { yaml } from "@codemirror/lang-yaml" import { yamlSchema } from 'codemirror-json-schema/yaml'; import { indentWithTab } from "@codemirror/commands" -import { ensureSyntaxTree, syntaxTree, syntaxTreeAvailable } from "@codemirror/language"; import YAML from 'yaml'; -import { optionsStorage } from './options-storage.js'; const schema = { type: "object", @@ -140,7 +135,7 @@ async function saveIfChanged() { if (changed) { const doc = view.state.doc.toString(); try { - const parsed = YAML.parse(doc); + const parsed = YAML.parse(doc); await optionsStorage.set({ optionsYaml: doc, similarEnabled: parsed.similar?.enabled ?? optionsStorage.defaults.similarEnabled, From b8a9c0b572de012cc433f62e0a8fac60bd5f805b Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Thu, 20 Nov 2025 19:13:29 +0100 Subject: [PATCH 10/20] Change repo URL --- source/background.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/background.js b/source/background.js index 107ef36..be12029 100644 --- a/source/background.js +++ b/source/background.js @@ -2,7 +2,7 @@ import { initCache } from './cache.js'; async function getClosestN(ids, offset = 0, limit = 10) { const apiKey = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3MiOiJyIn0.drJ8F-oa_6UfCpmKdv4Mbng_E8p71UrZAR895gKOOAk"; - const url = "https://simrepo.mub.lol/collections/repos/points/recommend"; + const url = "https://simrepo.dera.page/collections/repos/points/recommend"; let remainingIds = [...ids]; From a2e75fefc90ee563926042ec04aecdd11f7497c4 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Thu, 20 Nov 2025 19:26:42 +0100 Subject: [PATCH 11/20] Fix the homepage recommendations --- source/content-stars.js | 28 ++++++++++++---------------- source/content.js | 2 +- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/source/content-stars.js b/source/content-stars.js index dc66a25..4e314ee 100644 --- a/source/content-stars.js +++ b/source/content-stars.js @@ -11,22 +11,18 @@ export async function initHome() { } console.log("Producing recommendations on the homepage"); - let container = document.querySelector('aside.feed-right-sidebar>div[aria-label="Explore repositories"]>div'); - if (!container) { - // Fallback to creating a new container. Might be buggy if the structure changes. - let aside = document.querySelector('aside.feed-right-sidebar'); - let newContainer = document.createElement('div'); - newContainer.setAttribute("class", "mb-3 dashboard-changelog color-bg-default border color-border-default p-3 rounded-2"); - let title = document.createElement('h2'); - title.setAttribute("class", "f5 text-bold mb-3"); - title.textContent = "For you"; - newContainer.appendChild(title); - let newContainerInner = document.createElement('div'); - newContainer.appendChild(newContainerInner); - - aside.appendChild(newContainer); - container = newContainerInner; - } + + let aside = document.querySelector('aside.feed-right-column'); + let outerContainer = document.createElement('div'); + outerContainer.setAttribute("class", "mb-3 dashboard-changelog color-bg-default border color-border-muted p-3 rounded-3"); + let title = document.createElement('h2'); + title.setAttribute("class", "f5 text-bold mb-3 width-full dashboard-changelog__title"); + title.textContent = "For you"; + outerContainer.appendChild(title); + let container = document.createElement('div'); + outerContainer.appendChild(container); + + aside.appendChild(outerContainer); container.innerHTML = getLoadingHtml(options.homepageStarsToLoad); container.style.height = 'unset'; diff --git a/source/content.js b/source/content.js index 36df5fb..edec939 100644 --- a/source/content.js +++ b/source/content.js @@ -4,7 +4,7 @@ import { initHome, initStarsList } from './content-stars.js'; console.log('πŸ’ˆ Content script loaded for', chrome.runtime.getManifest().name); async function init() { - if (window.location.pathname === '/') { + if (window.location.pathname === '/' || window.location.pathname === '/feed') { await initHome(); } else if (window.location.pathname.startsWith('/stars/') && window.location.pathname.includes('/lists/')) { await initStarsList(); From 4d48a8c1476867e6a6e447e50f67e964f637c127 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Thu, 20 Nov 2025 19:35:51 +0100 Subject: [PATCH 12/20] Add redirect home to feed option --- source/content-stars.js | 5 +++++ source/options-storage.js | 1 + source/options.js | 10 +++++++++- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/source/content-stars.js b/source/content-stars.js index 4e314ee..a61bb1f 100644 --- a/source/content-stars.js +++ b/source/content-stars.js @@ -10,6 +10,11 @@ export async function initHome() { return; } + if (options.homepageRedirectToFeed && window.location.pathname === '/') { + window.location.replace('/feed'); + return; + } + console.log("Producing recommendations on the homepage"); let aside = document.querySelector('aside.feed-right-column'); diff --git a/source/options-storage.js b/source/options-storage.js index d37a878..6c968b9 100644 --- a/source/options-storage.js +++ b/source/options-storage.js @@ -13,6 +13,7 @@ const optionsStorage = new OptionsSync({ homepageStarsToLoad: 60, homepagePoolSize: 3.0, // homepageShowArchived: true, + homepageRedirectToFeed: false, }, migrations: [ OptionsSync.migrations.removeUnused, diff --git a/source/options.js b/source/options.js index 4df8622..e131277 100644 --- a/source/options.js +++ b/source/options.js @@ -55,13 +55,17 @@ const schema = { minimum: 1.0, maximum: 10.0, }, - // showArchived: { // type: "boolean", // description: "Whether to include archived repositories in the homepage recommendations", // }, + redirectToFeed: { + type: "boolean", + description: "Automatically redirect from the homepage to the feed page", + }, }, required: [], }, + }, required: [], }; @@ -96,6 +100,9 @@ async function defaultCode() { case "homepage.poolSize": value = options.homepagePoolSize; break; + case "homepage.redirectToFeed": + value = options.homepageRedirectToFeed; + break; default: value = "Unknown value. Open an issue on GitHub if you see this."; } @@ -144,6 +151,7 @@ async function saveIfChanged() { homepageCount: parsed.homepage?.count ?? optionsStorage.defaults.homepageCount, homepageStarsToLoad: parsed.homepage?.starsToLoad ?? optionsStorage.defaults.homepageStarsToLoad, homepagePoolSize: parsed.homepage?.poolSize ?? optionsStorage.defaults.homepagePoolSize, + homepageRedirectToFeed: parsed.homepage?.redirectToFeed ?? optionsStorage.defaults.homepageRedirectToFeed, }); let options = await optionsStorage.getAll(); From 4df938a47955c7be33783f23310b41123ab80874 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Thu, 20 Nov 2025 19:43:00 +0100 Subject: [PATCH 13/20] Prevent fetching similar repositories for private repositories and display an unavailability message. Fix #3 --- source/content-repo.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/source/content-repo.js b/source/content-repo.js index bead099..b65ae43 100644 --- a/source/content-repo.js +++ b/source/content-repo.js @@ -170,6 +170,13 @@ export async function loadMoreRepos(resetOffset = false) { container = document.querySelector('#similar-repos-container'); } + // Don't fetch if private + const isPrivate = document.querySelector('.Label.Label--secondary')?.textContent.trim() === 'Private'; + if (isPrivate) { + container.outerHTML = getErrorContainerHtml("Unavailable for private repositories."); + return; + } + // Don't fetch if less than 150 stars try { let starSpan = document.querySelector("span[id=\"repo-stars-counter-star\"]"); From 7e7df50443153ac47b236bdbad65bab1e14810db Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Thu, 20 Nov 2025 19:50:23 +0100 Subject: [PATCH 14/20] Allow not displaying the messages --- source/content-repo.js | 12 ++++++++++-- source/options-storage.js | 1 + source/options.js | 8 ++++++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/source/content-repo.js b/source/content-repo.js index b65ae43..2dca952 100644 --- a/source/content-repo.js +++ b/source/content-repo.js @@ -173,7 +173,11 @@ export async function loadMoreRepos(resetOffset = false) { // Don't fetch if private const isPrivate = document.querySelector('.Label.Label--secondary')?.textContent.trim() === 'Private'; if (isPrivate) { - container.outerHTML = getErrorContainerHtml("Unavailable for private repositories."); + if (options.similarShowUnavailable) { + container.outerHTML = getErrorContainerHtml("Unavailable for private repositories."); + } else { + container.remove(); + } return; } @@ -182,7 +186,11 @@ export async function loadMoreRepos(resetOffset = false) { let starSpan = document.querySelector("span[id=\"repo-stars-counter-star\"]"); let starsCount = starSpan ? parseInt(starSpan.getAttribute("title").replace(/,/g, '')) : 0; if (starsCount < 150) { - container.outerHTML = getErrorContainerHtml("Unavailable for repositories with less than 150 stars."); + if (options.similarShowUnavailable) { + container.outerHTML = getErrorContainerHtml("Unavailable for repositories with less than 150 stars."); + } else { + container.remove(); + } return; } } catch (error) { diff --git a/source/options-storage.js b/source/options-storage.js index 6c968b9..a4d4939 100644 --- a/source/options-storage.js +++ b/source/options-storage.js @@ -6,6 +6,7 @@ const optionsStorage = new OptionsSync({ similarEnabled: true, similarCount: 5, + similarShowUnavailable: true, // similarShowArchived: true, homepageEnabled: true, diff --git a/source/options.js b/source/options.js index e131277..b69e634 100644 --- a/source/options.js +++ b/source/options.js @@ -23,6 +23,10 @@ const schema = { description: "Number of similar items to show", minimum: 1, }, + showUnavailable: { + type: "boolean", + description: "Whether to show a notice when similar repositories are unavailable (e.g. private or < 150 stars)", + }, // showArchived: { // type: "boolean", // description: "Whether to include archived repositories in the list of similar projects", @@ -88,6 +92,9 @@ async function defaultCode() { case "similar.count": value = options.similarCount; break; + case "similar.showUnavailable": + value = options.similarShowUnavailable; + break; case "homepage.enabled": value = options.homepageEnabled; break; @@ -147,6 +154,7 @@ async function saveIfChanged() { optionsYaml: doc, similarEnabled: parsed.similar?.enabled ?? optionsStorage.defaults.similarEnabled, similarCount: parsed.similar?.count ?? optionsStorage.defaults.similarCount, + similarShowUnavailable: parsed.similar?.showUnavailable ?? optionsStorage.defaults.similarShowUnavailable, homepageEnabled: parsed.homepage?.enabled ?? optionsStorage.defaults.homepageEnabled, homepageCount: parsed.homepage?.count ?? optionsStorage.defaults.homepageCount, homepageStarsToLoad: parsed.homepage?.starsToLoad ?? optionsStorage.defaults.homepageStarsToLoad, From 5f9f8d38c7b904a3f54b3a78aa834f3ce7dba821 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Thu, 20 Nov 2025 19:58:52 +0100 Subject: [PATCH 15/20] Prevent useless reruns --- source/content.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/content.js b/source/content.js index edec939..cd56e9d 100644 --- a/source/content.js +++ b/source/content.js @@ -16,11 +16,11 @@ async function init() { init(); // Periodically check for url changes -let lastUrl = window.location.href; +let lastPathname = window.location.pathname; setInterval(() => { - const currentUrl = window.location.href; - if (currentUrl !== lastUrl) { - lastUrl = currentUrl; + const currentPathname = window.location.pathname; + if (currentPathname !== lastPathname) { + lastPathname = currentPathname; console.log('πŸ’ˆ URL changed, re-initializing...'); init(); } From bb9bfe20467f9b8d6ff8fb26715f3f6e7f2d5ea5 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Thu, 20 Nov 2025 20:03:48 +0100 Subject: [PATCH 16/20] Fix #8 --- source/content-repo.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/source/content-repo.js b/source/content-repo.js index 2dca952..7c0dfdd 100644 --- a/source/content-repo.js +++ b/source/content-repo.js @@ -225,7 +225,11 @@ export async function loadMoreRepos(resetOffset = false) { console.log('No similar repos found'); if (response.status === "error" && response.message) { - container.outerHTML = getErrorContainerHtml(`Error fetching similar repositories. Details:
${response.message}`); + if (response.message === "All provided IDs were invalid or caused errors.") { + container.outerHTML = getErrorContainerHtml("This repository got popular too recently! It will be included in the dataset soon."); + } else { + container.outerHTML = getErrorContainerHtml(`Error fetching similar repositories. Details:
${response.message}`); + } } else { container.outerHTML = getErrorContainerHtml("No similar repositories found. Try on older repositories."); } From ed87ab4c6f311585fefaa82925081d921a704cdc Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Thu, 20 Nov 2025 20:13:35 +0100 Subject: [PATCH 17/20] Prevent duplication --- source/content-repo.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/source/content-repo.js b/source/content-repo.js index 7c0dfdd..7e288a8 100644 --- a/source/content-repo.js +++ b/source/content-repo.js @@ -216,7 +216,11 @@ export async function loadMoreRepos(resetOffset = false) { let innerContainer = document.getElementById("similar-repos-inner-container"); if (innerContainer) { - innerContainer.insertAdjacentHTML('beforeend', getContainerInnerHtml(response.data)); + if (offset === 0) { + innerContainer.innerHTML = getContainerInnerHtml(response.data); + } else { + innerContainer.insertAdjacentHTML('beforeend', getContainerInnerHtml(response.data)); + } } else { container.outerHTML = getContainerHtml(response.data); setupCallback(); From 94cdca0c31f9da9b0acea1f92d4a56fa8d7e1b96 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Thu, 20 Nov 2025 23:05:13 +0100 Subject: [PATCH 18/20] Apply review suggestions --- source/content-repo.js | 4 ++-- source/content-stars.js | 3 ++- source/options.js | 15 +++++++-------- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/source/content-repo.js b/source/content-repo.js index 7e288a8..fceeb22 100644 --- a/source/content-repo.js +++ b/source/content-repo.js @@ -200,8 +200,8 @@ export async function loadMoreRepos(resetOffset = false) { try { loading = true; let offset = nextOffset; - let limit = offset == 0 ? options.similarCount : 5; - nextOffset += 5; + let limit = options.similarCount; + nextOffset += limit; let response = await getSimilarRepos([repoId], offset, limit); loading = false; diff --git a/source/content-stars.js b/source/content-stars.js index a61bb1f..883c808 100644 --- a/source/content-stars.js +++ b/source/content-stars.js @@ -60,8 +60,9 @@ export async function initStarsList() { } function getRandomSubsetInOrder(array, count) { + const actualCount = Math.min(count, array.length); const indices = new Set(); - while (indices.size < count) { + while (indices.size < actualCount) { const i = Math.floor(Math.random() * array.length); indices.add(i); } diff --git a/source/options.js b/source/options.js index b69e634..1b46d7a 100644 --- a/source/options.js +++ b/source/options.js @@ -80,7 +80,7 @@ async function defaultCode() { let options = await optionsStorage.getAll(); console.log("Default options:", options); - let code = "# Welcome the SimRepo's options\n# If you want to reset options, just clear everything and the default configuration will be restored.\n# Options are saved automatically, but comments will be ignored\n# Options are experimental, feel free to open issues on GitHub if you find any\n\n" + let code = "# Welcome to SimRepo's options\n# If you want to reset options, just clear everything and the default configuration will be restored.\n# Options are saved automatically, but comments will be ignored\n# Options are experimental, feel free to open issues on GitHub if you find any\n\n"; for (const [key, prop] of Object.entries(schema.properties)) { code += `\n# ${prop.description}\n${key}:\n`; for (const [subKey, subProp] of Object.entries(prop.properties)) { @@ -124,9 +124,12 @@ const resetOnEmpty = EditorView.updateListener.of((update) => { const currentContent = update.state.doc.toString().trim(); if (currentContent === "") { // Reset the editor content to default - update.view.dispatch({ - changes: { from: 0, to: 0, insert: defaultCode() }, - }); + (async () => { + const code = await defaultCode(); + update.view.dispatch({ + changes: { from: 0, to: 0, insert: code }, + }); + })(); } } }); @@ -173,10 +176,6 @@ async function saveIfChanged() { } } -window.addEventListener("beforeunload", () => { - saveIfChanged(); -}); - var view = null; async function init() { view = new EditorView({ From 58a73a9d5c96aa75c293a322afe1af77c443c99a Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Fri, 21 Nov 2025 10:15:40 +0100 Subject: [PATCH 19/20] Add settings button to content scripts for opening the extension options page. --- source/background.js | 92 +++++++++++++++++++++++------------------ source/common.js | 14 ++++++- source/content-repo.js | 18 +++++++- source/content-stars.js | 9 +++- source/content.css | 14 ++++++- source/manifest.json | 3 +- 6 files changed, 102 insertions(+), 48 deletions(-) diff --git a/source/background.js b/source/background.js index be12029..96f8210 100644 --- a/source/background.js +++ b/source/background.js @@ -53,52 +53,62 @@ async function getClosestN(ids, offset = 0, limit = 10) { throw new Error("All provided IDs were invalid or caused errors."); } -chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { - if (message.type === 'getSimilarRepos') { (async () => { - console.log('Received message to get similar repos:', message); - - const ids = message.repoIds; - const offset = Number(message.offset) || 0; - const limit = Number(message.limit) || 10; - - const cacheKey = `cache:getSimilarRepos:${ids.sort().join(',')}:${offset}:${limit}`; - - // Check cache first - chrome.storage.local.get([cacheKey], async (result) => { - const cached = result[cacheKey]; - if (cached) { - console.log('Serving from cache'); - sendResponse({ status: 'success', cached: cached.timestamp, data: cached.data }); - return; - } +async function handleGetSimilarReposMessage(message, sender, sendResponse) { + console.log('Received message to get similar repos:', message); + + const ids = message.repoIds; + const offset = Number(message.offset) || 0; + const limit = Number(message.limit) || 10; + + const cacheKey = `cache:getSimilarRepos:${ids.sort().join(',')}:${offset}:${limit}`; + + // Check cache first + chrome.storage.local.get([cacheKey], async (result) => { + const cached = result[cacheKey]; + if (cached) { + console.log('Serving from cache'); + sendResponse({ status: 'success', cached: cached.timestamp, data: cached.data }); + return; + } - if (!ids || ids.length === 0) { - sendResponse({ status: "unknown" }); - return; - } + if (!ids || ids.length === 0) { + sendResponse({ status: "unknown" }); + return; + } - let similarRepos; - try { - similarRepos = await getClosestN(ids, offset, limit); - } catch (error) { - console.error('Error fetching similar repos:', error); - sendResponse({ status: "error", message: error.message }); - return; - } - - // Cache the result - chrome.storage.local.set({ - [cacheKey]: { - data: similarRepos, - timestamp: Date.now() - } - }); + let similarRepos; + try { + similarRepos = await getClosestN(ids, offset, limit); + } catch (error) { + console.error('Error fetching similar repos:', error); + sendResponse({ status: "error", message: error.message }); + return; + } - sendResponse({ - status: similarRepos.length > 0 ? "success" : "error", + // Cache the result + chrome.storage.local.set({ + [cacheKey]: { data: similarRepos, - }); + timestamp: Date.now() + } + }); + + sendResponse({ + status: similarRepos.length > 0 ? "success" : "error", + data: similarRepos, }); + }); +} + +chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { + if (message.type === 'openOptionsPage') { + chrome.runtime.openOptionsPage(); + return; + } + + if (message.type === 'getSimilarRepos') { + (async () => { + await handleGetSimilarReposMessage(message, sender, sendResponse); })(); // Tell Chrome this is a synchronous response diff --git a/source/common.js b/source/common.js index eb6af96..ef16109 100644 --- a/source/common.js +++ b/source/common.js @@ -21,5 +21,17 @@ export function formatNumber(num) { } export function loadingSpinner(customClass = "", customStyle = "") { - return ``; + return ``; +} + +export function setupSettingsListener() { + const settingsBtn = document.querySelector('#simrepo-settings-btn'); + if (settingsBtn) { + settingsBtn.addEventListener('click', (e) => { + e.preventDefault(); + chrome.runtime.sendMessage({ type: "openOptionsPage" }); + }); + } else { + console.warn("No settings button"); + } } diff --git a/source/content-repo.js b/source/content-repo.js index fceeb22..fcfd5bc 100644 --- a/source/content-repo.js +++ b/source/content-repo.js @@ -1,6 +1,6 @@ import GH_LANG_COLORS from 'gh-lang-colors'; import octicons from "@primer/octicons"; -import { getSimilarRepos, formatNumber, loadingSpinner } from './common.js'; +import { getSimilarRepos, formatNumber, loadingSpinner, setupSettingsListener } from './common.js'; import { optionsStorage } from './options-storage.js'; var loading = false; @@ -76,6 +76,9 @@ function getContainerHtml(results) {

Similar repositories + + ${octicons.gear.toSVG()} +

@@ -93,6 +96,9 @@ function getLoadingContainerHtml() {

Similar repositories + + ${octicons.gear.toSVG()} +

@@ -113,6 +119,9 @@ function getErrorContainerHtml(error = "No similar repositories found.") {

Similar repositories + + ${octicons.gear.toSVG()} +

@@ -135,6 +144,8 @@ function setupCallback() { } }); } + + setupSettingsListener(); } async function getRepoId() { @@ -167,6 +178,7 @@ export async function loadMoreRepos(resetOffset = false) { if (!container) { const sidebar = document.querySelector('.Layout-sidebar > div'); sidebar.insertAdjacentHTML('beforeend', getLoadingContainerHtml()); + setupSettingsListener(); container = document.querySelector('#similar-repos-container'); } @@ -175,6 +187,7 @@ export async function loadMoreRepos(resetOffset = false) { if (isPrivate) { if (options.similarShowUnavailable) { container.outerHTML = getErrorContainerHtml("Unavailable for private repositories."); + setupSettingsListener(); } else { container.remove(); } @@ -188,6 +201,7 @@ export async function loadMoreRepos(resetOffset = false) { if (starsCount < 150) { if (options.similarShowUnavailable) { container.outerHTML = getErrorContainerHtml("Unavailable for repositories with less than 150 stars."); + setupSettingsListener(); } else { container.remove(); } @@ -237,10 +251,12 @@ export async function loadMoreRepos(resetOffset = false) { } else { container.outerHTML = getErrorContainerHtml("No similar repositories found. Try on older repositories."); } + setupSettingsListener(); } } catch (error) { console.error('Error fetching similar repos:', error); loading = false; container.outerHTML = getErrorContainerHtml(`Error fetching similar repositories. Details:
${error.message}`); + setupSettingsListener(); } } diff --git a/source/content-stars.js b/source/content-stars.js index 883c808..dadf3b2 100644 --- a/source/content-stars.js +++ b/source/content-stars.js @@ -1,6 +1,6 @@ import octicons from "@primer/octicons"; import GH_LANG_COLORS from 'gh-lang-colors'; -import { formatNumber, getSimilarRepos, loadingSpinner } from './common.js'; +import { formatNumber, getSimilarRepos, loadingSpinner, setupSettingsListener } from './common.js'; import { optionsStorage } from "./options-storage.js"; export async function initHome() { @@ -22,7 +22,10 @@ export async function initHome() { outerContainer.setAttribute("class", "mb-3 dashboard-changelog color-bg-default border color-border-muted p-3 rounded-3"); let title = document.createElement('h2'); title.setAttribute("class", "f5 text-bold mb-3 width-full dashboard-changelog__title"); - title.textContent = "For you"; + title.innerHTML = `For you + + ${octicons.gear.toSVG()} + `; outerContainer.appendChild(title); let container = document.createElement('div'); outerContainer.appendChild(container); @@ -33,6 +36,8 @@ export async function initHome() { container.style.height = 'unset'; container.style.overflow = 'unset'; + setupSettingsListener(); + try { await run(container, options); } catch (error) { diff --git a/source/content.css b/source/content.css index 2d9e458..b4c1b88 100644 --- a/source/content.css +++ b/source/content.css @@ -1,6 +1,6 @@ aside>div[aria-label="Explore repositories"]>div { - height: 0; - overflow: hidden; + height: 0; + overflow: hidden; } #similar-repos-container .pinned-item-meta+.pinned-item-meta { @@ -28,6 +28,16 @@ aside>div[aria-label="Explore repositories"]>div { animation: rotation 1s linear infinite; } +#similar-repos-container h2 { + display: flex; + justify-content: space-between; + align-items: center; +} + +#simrepo-settings-btn .octicon { + vertical-align: baseline; +} + @keyframes rotation { 0% { transform: rotate(0deg); diff --git a/source/manifest.json b/source/manifest.json index 019843b..a2c40b1 100644 --- a/source/manifest.json +++ b/source/manifest.json @@ -30,7 +30,8 @@ } ], "options_ui": { - "page": "options.html" + "page": "options.html", + "open_in_tab": true }, "background": { "service_worker": "background.js", From 64bdf08ebfb75f9aebfd255c8c6a3e1d2210be76 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Fri, 21 Nov 2025 10:21:33 +0100 Subject: [PATCH 20/20] Make options bigger --- source/options.html | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/source/options.html b/source/options.html index 693cf58..4593140 100644 --- a/source/options.html +++ b/source/options.html @@ -16,8 +16,12 @@ .ΝΌ1.cm-focused { outline: none !important; } + + .cm-editor { + font-size: 1rem; + }
- \ No newline at end of file +