diff --git a/components.json b/components.json
deleted file mode 100644
index 8d886db..0000000
--- a/components.json
+++ /dev/null
@@ -1,25 +0,0 @@
-{
- "$schema": "https://ui.shadcn.com/schema.json",
- "style": "base-nova",
- "rsc": true,
- "tsx": true,
- "tailwind": {
- "config": "",
- "css": "src/app/globals.css",
- "baseColor": "neutral",
- "cssVariables": true,
- "prefix": ""
- },
- "iconLibrary": "lucide",
- "rtl": false,
- "aliases": {
- "components": "@/components",
- "utils": "@/lib/utils",
- "ui": "@/components/ui",
- "lib": "@/lib",
- "hooks": "@/hooks"
- },
- "menuColor": "default",
- "menuAccent": "subtle",
- "registries": {}
-}
diff --git a/package-lock.json b/package-lock.json
index 26ed653..34f7ef8 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,75 +1,92 @@
{
- "name": "diagram-comment-tool",
+ "name": "commenting-visual-explainers",
"version": "0.1.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
- "name": "diagram-comment-tool",
+ "name": "commenting-visual-explainers",
"version": "0.1.0",
"dependencies": {
- "@base-ui/react": "^1.3.0",
"@neondatabase/serverless": "^1.0.2",
- "class-variance-authority": "^0.7.1",
- "clsx": "^2.1.1",
- "lucide-react": "^0.577.0",
"next": "16.1.6",
"react": "19.2.3",
- "react-dom": "19.2.3",
- "shadcn": "^4.0.6",
- "tailwind-merge": "^3.5.0",
- "tw-animate-css": "^1.4.0"
+ "react-dom": "19.2.3"
},
"devDependencies": {
- "@tailwindcss/postcss": "^4",
+ "@types/jsdom": "^28.0.1",
"@types/node": "^20",
"@types/react": "^19",
"@types/react-dom": "^19",
"dotenv": "^17.3.1",
+ "esbuild": "^0.27.4",
"eslint": "^9",
"eslint-config-next": "16.1.6",
- "tailwindcss": "^4",
- "typescript": "5.9.3"
+ "jsdom": "^27.0.1",
+ "typescript": "5.9.3",
+ "vitest": "^3.2.4"
}
},
- "node_modules/@alloc/quick-lru": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
- "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
+ "node_modules/@asamuzakjp/css-color": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-4.1.2.tgz",
+ "integrity": "sha512-NfBUvBaYgKIuq6E/RBLY1m0IohzNHAYyaJGuTK79Z23uNwmz2jl1mPsC5ZxCCxylinKhT1Amn5oNTlx1wN8cQg==",
"dev": true,
"license": "MIT",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "dependencies": {
+ "@csstools/css-calc": "^3.0.0",
+ "@csstools/css-color-parser": "^4.0.1",
+ "@csstools/css-parser-algorithms": "^4.0.0",
+ "@csstools/css-tokenizer": "^4.0.0",
+ "lru-cache": "^11.2.5"
}
},
- "node_modules/@antfu/ni": {
- "version": "25.0.0",
- "resolved": "https://registry.npmjs.org/@antfu/ni/-/ni-25.0.0.tgz",
- "integrity": "sha512-9q/yCljni37pkMr4sPrI3G4jqdIk074+iukc5aFJl7kmDCCsiJrbZ6zKxnES1Gwg+i9RcDZwvktl23puGslmvA==",
+ "node_modules/@asamuzakjp/css-color/node_modules/lru-cache": {
+ "version": "11.2.7",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.7.tgz",
+ "integrity": "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": "20 || >=22"
+ }
+ },
+ "node_modules/@asamuzakjp/dom-selector": {
+ "version": "6.8.1",
+ "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-6.8.1.tgz",
+ "integrity": "sha512-MvRz1nCqW0fsy8Qz4dnLIvhOlMzqDVBabZx6lH+YywFDdjXhMY37SmpV1XFX3JzG5GWHn63j6HX6QPr3lZXHvQ==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "ansis": "^4.0.0",
- "fzf": "^0.5.2",
- "package-manager-detector": "^1.3.0",
- "tinyexec": "^1.0.1"
- },
- "bin": {
- "na": "bin/na.mjs",
- "nci": "bin/nci.mjs",
- "ni": "bin/ni.mjs",
- "nlx": "bin/nlx.mjs",
- "nr": "bin/nr.mjs",
- "nun": "bin/nun.mjs",
- "nup": "bin/nup.mjs"
+ "@asamuzakjp/nwsapi": "^2.3.9",
+ "bidi-js": "^1.0.3",
+ "css-tree": "^3.1.0",
+ "is-potential-custom-element-name": "^1.0.1",
+ "lru-cache": "^11.2.6"
}
},
+ "node_modules/@asamuzakjp/dom-selector/node_modules/lru-cache": {
+ "version": "11.2.7",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.7.tgz",
+ "integrity": "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": "20 || >=22"
+ }
+ },
+ "node_modules/@asamuzakjp/nwsapi": {
+ "version": "2.3.9",
+ "resolved": "https://registry.npmjs.org/@asamuzakjp/nwsapi/-/nwsapi-2.3.9.tgz",
+ "integrity": "sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@babel/code-frame": {
"version": "7.29.0",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz",
"integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"@babel/helper-validator-identifier": "^7.28.5",
@@ -84,6 +101,7 @@
"version": "7.29.0",
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz",
"integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">=6.9.0"
@@ -93,8 +111,8 @@
"version": "7.29.0",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz",
"integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==",
+ "dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@babel/code-frame": "^7.29.0",
"@babel/generator": "^7.29.0",
@@ -124,6 +142,7 @@
"version": "7.29.1",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz",
"integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"@babel/parser": "^7.29.0",
@@ -136,22 +155,11 @@
"node": ">=6.9.0"
}
},
- "node_modules/@babel/helper-annotate-as-pure": {
- "version": "7.27.3",
- "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz",
- "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==",
- "license": "MIT",
- "dependencies": {
- "@babel/types": "^7.27.3"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
"node_modules/@babel/helper-compilation-targets": {
"version": "7.28.6",
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz",
"integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"@babel/compat-data": "^7.28.6",
@@ -164,53 +172,21 @@
"node": ">=6.9.0"
}
},
- "node_modules/@babel/helper-create-class-features-plugin": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.6.tgz",
- "integrity": "sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-annotate-as-pure": "^7.27.3",
- "@babel/helper-member-expression-to-functions": "^7.28.5",
- "@babel/helper-optimise-call-expression": "^7.27.1",
- "@babel/helper-replace-supers": "^7.28.6",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1",
- "@babel/traverse": "^7.28.6",
- "semver": "^6.3.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
"node_modules/@babel/helper-globals": {
"version": "7.28.0",
"resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz",
"integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">=6.9.0"
}
},
- "node_modules/@babel/helper-member-expression-to-functions": {
- "version": "7.28.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.28.5.tgz",
- "integrity": "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==",
- "license": "MIT",
- "dependencies": {
- "@babel/traverse": "^7.28.5",
- "@babel/types": "^7.28.5"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
"node_modules/@babel/helper-module-imports": {
"version": "7.28.6",
"resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz",
"integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"@babel/traverse": "^7.28.6",
@@ -224,6 +200,7 @@
"version": "7.28.6",
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz",
"integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"@babel/helper-module-imports": "^7.28.6",
@@ -237,61 +214,11 @@
"@babel/core": "^7.0.0"
}
},
- "node_modules/@babel/helper-optimise-call-expression": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz",
- "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==",
- "license": "MIT",
- "dependencies": {
- "@babel/types": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-plugin-utils": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz",
- "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==",
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-replace-supers": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.28.6.tgz",
- "integrity": "sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-member-expression-to-functions": "^7.28.5",
- "@babel/helper-optimise-call-expression": "^7.27.1",
- "@babel/traverse": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/helper-skip-transparent-expression-wrappers": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz",
- "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==",
- "license": "MIT",
- "dependencies": {
- "@babel/traverse": "^7.27.1",
- "@babel/types": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
"node_modules/@babel/helper-string-parser": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
"integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">=6.9.0"
@@ -301,6 +228,7 @@
"version": "7.28.5",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
"integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">=6.9.0"
@@ -310,6 +238,7 @@
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz",
"integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">=6.9.0"
@@ -319,6 +248,7 @@
"version": "7.28.6",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz",
"integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"@babel/template": "^7.28.6",
@@ -332,6 +262,7 @@
"version": "7.29.0",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz",
"integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"@babel/types": "^7.29.0"
@@ -343,103 +274,11 @@
"node": ">=6.0.0"
}
},
- "node_modules/@babel/plugin-syntax-jsx": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.28.6.tgz",
- "integrity": "sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-typescript": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.28.6.tgz",
- "integrity": "sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-modules-commonjs": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.28.6.tgz",
- "integrity": "sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-module-transforms": "^7.28.6",
- "@babel/helper-plugin-utils": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-typescript": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.28.6.tgz",
- "integrity": "sha512-0YWL2RFxOqEm9Efk5PvreamxPME8OyY0wM5wh5lHjF+VtVhdneCWGzZeSqzOfiobVqQaNCd2z0tQvnI9DaPWPw==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-annotate-as-pure": "^7.27.3",
- "@babel/helper-create-class-features-plugin": "^7.28.6",
- "@babel/helper-plugin-utils": "^7.28.6",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1",
- "@babel/plugin-syntax-typescript": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/preset-typescript": {
- "version": "7.28.5",
- "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.28.5.tgz",
- "integrity": "sha512-+bQy5WOI2V6LJZpPVxY+yp66XdZ2yifu0Mc1aP5CQKgjn4QM5IN2i5fAZ4xKop47pr8rpVhiAeu+nDQa12C8+g==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1",
- "@babel/helper-validator-option": "^7.27.1",
- "@babel/plugin-syntax-jsx": "^7.27.1",
- "@babel/plugin-transform-modules-commonjs": "^7.27.1",
- "@babel/plugin-transform-typescript": "^7.28.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/runtime": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz",
- "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==",
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
"node_modules/@babel/template": {
"version": "7.28.6",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz",
"integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"@babel/code-frame": "^7.28.6",
@@ -454,6 +293,7 @@
"version": "7.29.0",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz",
"integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"@babel/code-frame": "^7.29.0",
@@ -472,6 +312,7 @@
"version": "7.29.0",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz",
"integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"@babel/helper-string-parser": "^7.27.1",
@@ -481,255 +322,144 @@
"node": ">=6.9.0"
}
},
- "node_modules/@base-ui/react": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/@base-ui/react/-/react-1.3.0.tgz",
- "integrity": "sha512-FwpKqZbPz14AITp1CVgf4AjhKPe1OeeVKSBMdgD10zbFlj3QSWelmtCMLi2+/PFZZcIm3l87G7rwtCZJwHyXWA==",
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.28.6",
- "@base-ui/utils": "0.2.6",
- "@floating-ui/react-dom": "^2.1.8",
- "@floating-ui/utils": "^0.2.11",
- "tabbable": "^6.4.0",
- "use-sync-external-store": "^1.6.0"
- },
+ "node_modules/@csstools/color-helpers": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-6.0.2.tgz",
+ "integrity": "sha512-LMGQLS9EuADloEFkcTBR3BwV/CGHV7zyDxVRtVDTwdI2Ca4it0CCVTT9wCkxSgokjE5Ho41hEPgb8OEUwoXr6Q==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "license": "MIT-0",
"engines": {
- "node": ">=14.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/mui-org"
+ "node": ">=20.19.0"
+ }
+ },
+ "node_modules/@csstools/css-calc": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-3.1.1.tgz",
+ "integrity": "sha512-HJ26Z/vmsZQqs/o3a6bgKslXGFAungXGbinULZO3eMsOyNJHeBBZfup5FiZInOghgoM4Hwnmw+OgbJCNg1wwUQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=20.19.0"
},
"peerDependencies": {
- "@types/react": "^17 || ^18 || ^19",
- "react": "^17 || ^18 || ^19",
- "react-dom": "^17 || ^18 || ^19"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
+ "@csstools/css-parser-algorithms": "^4.0.0",
+ "@csstools/css-tokenizer": "^4.0.0"
}
},
- "node_modules/@base-ui/utils": {
- "version": "0.2.6",
- "resolved": "https://registry.npmjs.org/@base-ui/utils/-/utils-0.2.6.tgz",
- "integrity": "sha512-yQ+qeuqohwhsNpoYDqqXaLllYAkPCP4vYdDrVo8FQXaAPfHWm1pG/Vm+jmGTA5JFS0BAIjookyapuJFY8F9PIw==",
+ "node_modules/@csstools/css-color-parser": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-4.0.2.tgz",
+ "integrity": "sha512-0GEfbBLmTFf0dJlpsNU7zwxRIH0/BGEMuXLTCvFYxuL1tNhqzTbtnFICyJLTNK4a+RechKP75e7w42ClXSnJQw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
"license": "MIT",
"dependencies": {
- "@babel/runtime": "^7.28.6",
- "@floating-ui/utils": "^0.2.11",
- "reselect": "^5.1.1",
- "use-sync-external-store": "^1.6.0"
+ "@csstools/color-helpers": "^6.0.2",
+ "@csstools/css-calc": "^3.1.1"
+ },
+ "engines": {
+ "node": ">=20.19.0"
},
"peerDependencies": {
- "@types/react": "^17 || ^18 || ^19",
- "react": "^17 || ^18 || ^19",
- "react-dom": "^17 || ^18 || ^19"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
+ "@csstools/css-parser-algorithms": "^4.0.0",
+ "@csstools/css-tokenizer": "^4.0.0"
}
},
- "node_modules/@dotenvx/dotenvx": {
- "version": "1.55.1",
- "resolved": "https://registry.npmjs.org/@dotenvx/dotenvx/-/dotenvx-1.55.1.tgz",
- "integrity": "sha512-WEuKyoe9CA7dfcFBnNbL0ndbCNcptaEYBygfFo9X1qEG+HD7xku4CYIplw6sbAHJavesZWbVBHeRSpvri0eKqw==",
- "license": "BSD-3-Clause",
- "dependencies": {
- "commander": "^11.1.0",
- "dotenv": "^17.2.1",
- "eciesjs": "^0.4.10",
- "execa": "^5.1.1",
- "fdir": "^6.2.0",
- "ignore": "^5.3.0",
- "object-treeify": "1.1.33",
- "picomatch": "^4.0.2",
- "which": "^4.0.0"
- },
- "bin": {
- "dotenvx": "src/cli/dotenvx.js"
- },
- "funding": {
- "url": "https://dotenvx.com"
- }
- },
- "node_modules/@dotenvx/dotenvx/node_modules/commander": {
- "version": "11.1.0",
- "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz",
- "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==",
- "license": "MIT",
- "engines": {
- "node": ">=16"
- }
- },
- "node_modules/@dotenvx/dotenvx/node_modules/execa": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
- "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
- "license": "MIT",
- "dependencies": {
- "cross-spawn": "^7.0.3",
- "get-stream": "^6.0.0",
- "human-signals": "^2.1.0",
- "is-stream": "^2.0.0",
- "merge-stream": "^2.0.0",
- "npm-run-path": "^4.0.1",
- "onetime": "^5.1.2",
- "signal-exit": "^3.0.3",
- "strip-final-newline": "^2.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sindresorhus/execa?sponsor=1"
- }
- },
- "node_modules/@dotenvx/dotenvx/node_modules/fdir": {
- "version": "6.5.0",
- "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
- "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
- "license": "MIT",
- "engines": {
- "node": ">=12.0.0"
- },
- "peerDependencies": {
- "picomatch": "^3 || ^4"
- },
- "peerDependenciesMeta": {
- "picomatch": {
- "optional": true
- }
- }
- },
- "node_modules/@dotenvx/dotenvx/node_modules/get-stream": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
- "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
- "license": "MIT",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/@dotenvx/dotenvx/node_modules/human-signals": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
- "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
- "license": "Apache-2.0",
- "engines": {
- "node": ">=10.17.0"
- }
- },
- "node_modules/@dotenvx/dotenvx/node_modules/is-stream": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
- "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/@dotenvx/dotenvx/node_modules/isexe": {
- "version": "3.1.5",
- "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.5.tgz",
- "integrity": "sha512-6B3tLtFqtQS4ekarvLVMZ+X+VlvQekbe4taUkf/rhVO3d/h0M2rfARm/pXLcPEsjjMsFgrFgSrhQIxcSVrBz8w==",
- "license": "BlueOak-1.0.0",
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@dotenvx/dotenvx/node_modules/npm-run-path": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
- "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
- "license": "MIT",
- "dependencies": {
- "path-key": "^3.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/@dotenvx/dotenvx/node_modules/onetime": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
- "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
- "license": "MIT",
- "dependencies": {
- "mimic-fn": "^2.1.0"
- },
- "engines": {
- "node": ">=6"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/@dotenvx/dotenvx/node_modules/picomatch": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
- "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
- "license": "MIT",
- "peer": true,
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/jonschlinkert"
- }
- },
- "node_modules/@dotenvx/dotenvx/node_modules/signal-exit": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
- "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
- "license": "ISC"
- },
- "node_modules/@dotenvx/dotenvx/node_modules/strip-final-newline": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
- "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/@dotenvx/dotenvx/node_modules/which": {
+ "node_modules/@csstools/css-parser-algorithms": {
"version": "4.0.0",
- "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz",
- "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==",
- "license": "ISC",
- "dependencies": {
- "isexe": "^3.1.1"
- },
- "bin": {
- "node-which": "bin/which.js"
- },
- "engines": {
- "node": "^16.13.0 || >=18.0.0"
- }
- },
- "node_modules/@ecies/ciphers": {
- "version": "0.2.5",
- "resolved": "https://registry.npmjs.org/@ecies/ciphers/-/ciphers-0.2.5.tgz",
- "integrity": "sha512-GalEZH4JgOMHYYcYmVqnFirFsjZHeoGMDt9IxEnM9F7GRUUyUksJ7Ou53L83WHJq3RWKD3AcBpo0iQh0oMpf8A==",
+ "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-4.0.0.tgz",
+ "integrity": "sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
"license": "MIT",
"engines": {
- "bun": ">=1",
- "deno": ">=2",
- "node": ">=16"
+ "node": ">=20.19.0"
},
"peerDependencies": {
- "@noble/ciphers": "^1.0.0"
+ "@csstools/css-tokenizer": "^4.0.0"
+ }
+ },
+ "node_modules/@csstools/css-syntax-patches-for-csstree": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.1.1.tgz",
+ "integrity": "sha512-BvqN0AMWNAnLk9G8jnUT77D+mUbY/H2b3uDTvg2isJkHaOufUE2R3AOwxWo7VBQKT1lOdwdvorddo2B/lk64+w==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "license": "MIT-0",
+ "peerDependencies": {
+ "css-tree": "^3.2.1"
+ },
+ "peerDependenciesMeta": {
+ "css-tree": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@csstools/css-tokenizer": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-4.0.0.tgz",
+ "integrity": "sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=20.19.0"
}
},
"node_modules/@emnapi/core": {
@@ -765,6 +495,448 @@
"tslib": "^2.4.0"
}
},
+ "node_modules/@esbuild/aix-ppc64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.4.tgz",
+ "integrity": "sha512-cQPwL2mp2nSmHHJlCyoXgHGhbEPMrEEU5xhkcy3Hs/O7nGZqEpZ2sUtLaL9MORLtDfRvVl2/3PAuEkYZH0Ty8Q==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.4.tgz",
+ "integrity": "sha512-X9bUgvxiC8CHAGKYufLIHGXPJWnr0OCdR0anD2e21vdvgCI8lIfqFbnoeOz7lBjdrAGUhqLZLcQo6MLhTO2DKQ==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.4.tgz",
+ "integrity": "sha512-gdLscB7v75wRfu7QSm/zg6Rx29VLdy9eTr2t44sfTW7CxwAtQghZ4ZnqHk3/ogz7xao0QAgrkradbBzcqFPasw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.4.tgz",
+ "integrity": "sha512-PzPFnBNVF292sfpfhiyiXCGSn9HZg5BcAz+ivBuSsl6Rk4ga1oEXAamhOXRFyMcjwr2DVtm40G65N3GLeH1Lvw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.4.tgz",
+ "integrity": "sha512-b7xaGIwdJlht8ZFCvMkpDN6uiSmnxxK56N2GDTMYPr2/gzvfdQN8rTfBsvVKmIVY/X7EM+/hJKEIbbHs9oA4tQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.4.tgz",
+ "integrity": "sha512-sR+OiKLwd15nmCdqpXMnuJ9W2kpy0KigzqScqHI3Hqwr7IXxBp3Yva+yJwoqh7rE8V77tdoheRYataNKL4QrPw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.4.tgz",
+ "integrity": "sha512-jnfpKe+p79tCnm4GVav68A7tUFeKQwQyLgESwEAUzyxk/TJr4QdGog9sqWNcUbr/bZt/O/HXouspuQDd9JxFSw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.4.tgz",
+ "integrity": "sha512-2kb4ceA/CpfUrIcTUl1wrP/9ad9Atrp5J94Lq69w7UwOMolPIGrfLSvAKJp0RTvkPPyn6CIWrNy13kyLikZRZQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.4.tgz",
+ "integrity": "sha512-aBYgcIxX/wd5n2ys0yESGeYMGF+pv6g0DhZr3G1ZG4jMfruU9Tl1i2Z+Wnj9/KjGz1lTLCcorqE2viePZqj4Eg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.4.tgz",
+ "integrity": "sha512-7nQOttdzVGth1iz57kxg9uCz57dxQLHWxopL6mYuYthohPKEK0vU0C3O21CcBK6KDlkYVcnDXY099HcCDXd9dA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.4.tgz",
+ "integrity": "sha512-oPtixtAIzgvzYcKBQM/qZ3R+9TEUd1aNJQu0HhGyqtx6oS7qTpvjheIWBbes4+qu1bNlo2V4cbkISr8q6gRBFA==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.4.tgz",
+ "integrity": "sha512-8mL/vh8qeCoRcFH2nM8wm5uJP+ZcVYGGayMavi8GmRJjuI3g1v6Z7Ni0JJKAJW+m0EtUuARb6Lmp4hMjzCBWzA==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.4.tgz",
+ "integrity": "sha512-1RdrWFFiiLIW7LQq9Q2NES+HiD4NyT8Itj9AUeCl0IVCA459WnPhREKgwrpaIfTOe+/2rdntisegiPWn/r/aAw==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.4.tgz",
+ "integrity": "sha512-tLCwNG47l3sd9lpfyx9LAGEGItCUeRCWeAx6x2Jmbav65nAwoPXfewtAdtbtit/pJFLUWOhpv0FpS6GQAmPrHA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.4.tgz",
+ "integrity": "sha512-BnASypppbUWyqjd1KIpU4AUBiIhVr6YlHx/cnPgqEkNoVOhHg+YiSVxM1RLfiy4t9cAulbRGTNCKOcqHrEQLIw==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.4.tgz",
+ "integrity": "sha512-+eUqgb/Z7vxVLezG8bVB9SfBie89gMueS+I0xYh2tJdw3vqA/0ImZJ2ROeWwVJN59ihBeZ7Tu92dF/5dy5FttA==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.4.tgz",
+ "integrity": "sha512-S5qOXrKV8BQEzJPVxAwnryi2+Iq5pB40gTEIT69BQONqR7JH1EPIcQ/Uiv9mCnn05jff9umq/5nqzxlqTOg9NA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-arm64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.4.tgz",
+ "integrity": "sha512-xHT8X4sb0GS8qTqiwzHqpY00C95DPAq7nAwX35Ie/s+LO9830hrMd3oX0ZMKLvy7vsonee73x0lmcdOVXFzd6Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.4.tgz",
+ "integrity": "sha512-RugOvOdXfdyi5Tyv40kgQnI0byv66BFgAqjdgtAKqHoZTbTF2QqfQrFwa7cHEORJf6X2ht+l9ABLMP0dnKYsgg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-arm64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.4.tgz",
+ "integrity": "sha512-2MyL3IAaTX+1/qP0O1SwskwcwCoOI4kV2IBX1xYnDDqthmq5ArrW94qSIKCAuRraMgPOmG0RDTA74mzYNQA9ow==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.4.tgz",
+ "integrity": "sha512-u8fg/jQ5aQDfsnIV6+KwLOf1CmJnfu1ShpwqdwC0uA7ZPwFws55Ngc12vBdeUdnuWoQYx/SOQLGDcdlfXhYmXQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openharmony-arm64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.4.tgz",
+ "integrity": "sha512-JkTZrl6VbyO8lDQO3yv26nNr2RM2yZzNrNHEsj9bm6dOwwu9OYN28CjzZkH57bh4w0I2F7IodpQvUAEd1mbWXg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.4.tgz",
+ "integrity": "sha512-/gOzgaewZJfeJTlsWhvUEmUG4tWEY2Spp5M20INYRg2ZKl9QPO3QEEgPeRtLjEWSW8FilRNacPOg8R1uaYkA6g==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.4.tgz",
+ "integrity": "sha512-Z9SExBg2y32smoDQdf1HRwHRt6vAHLXcxD2uGgO/v2jK7Y718Ix4ndsbNMU/+1Qiem9OiOdaqitioZwxivhXYg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.4.tgz",
+ "integrity": "sha512-DAyGLS0Jz5G5iixEbMHi5KdiApqHBWMGzTtMiJ72ZOLhbu/bzxgAe8Ue8CTS3n3HbIUHQz/L51yMdGMeoxXNJw==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.4.tgz",
+ "integrity": "sha512-+knoa0BDoeXgkNvvV1vvbZX4+hizelrkwmGJBdT17t8FNPwG2lKemmuMZlmaNQ3ws3DKKCxpb4zRZEIp3UxFCg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/@eslint-community/eslint-utils": {
"version": "4.9.1",
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz",
@@ -909,56 +1081,6 @@
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
- "node_modules/@floating-ui/core": {
- "version": "1.7.5",
- "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.5.tgz",
- "integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==",
- "license": "MIT",
- "dependencies": {
- "@floating-ui/utils": "^0.2.11"
- }
- },
- "node_modules/@floating-ui/dom": {
- "version": "1.7.6",
- "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz",
- "integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==",
- "license": "MIT",
- "dependencies": {
- "@floating-ui/core": "^1.7.5",
- "@floating-ui/utils": "^0.2.11"
- }
- },
- "node_modules/@floating-ui/react-dom": {
- "version": "2.1.8",
- "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.8.tgz",
- "integrity": "sha512-cC52bHwM/n/CxS87FH0yWdngEZrjdtLW/qVruo68qg+prK7ZQ4YGdut2GyDVpoGeAYe/h899rVeOVm6Oi40k2A==",
- "license": "MIT",
- "dependencies": {
- "@floating-ui/dom": "^1.7.6"
- },
- "peerDependencies": {
- "react": ">=16.8.0",
- "react-dom": ">=16.8.0"
- }
- },
- "node_modules/@floating-ui/utils": {
- "version": "0.2.11",
- "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.11.tgz",
- "integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==",
- "license": "MIT"
- },
- "node_modules/@hono/node-server": {
- "version": "1.19.11",
- "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.11.tgz",
- "integrity": "sha512-dr8/3zEaB+p0D2n/IUrlPF1HZm586qgJNXK1a9fhg/PzdtkK7Ksd5l312tJX2yBuALqDYBlG20QEbayqPyxn+g==",
- "license": "MIT",
- "engines": {
- "node": ">=18.14.1"
- },
- "peerDependencies": {
- "hono": "^4"
- }
- },
"node_modules/@humanfs/core": {
"version": "0.19.1",
"resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
@@ -1481,7 +1603,10 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-1.0.2.tgz",
"integrity": "sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==",
+ "dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"engines": {
"node": ">=18"
}
@@ -1490,7 +1615,10 @@
"version": "5.1.21",
"resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.21.tgz",
"integrity": "sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ==",
+ "dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"dependencies": {
"@inquirer/core": "^10.3.2",
"@inquirer/type": "^3.0.10"
@@ -1511,7 +1639,10 @@
"version": "10.3.2",
"resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.3.2.tgz",
"integrity": "sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A==",
+ "dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"dependencies": {
"@inquirer/ansi": "^1.0.2",
"@inquirer/figures": "^1.0.15",
@@ -1538,7 +1669,10 @@
"version": "1.0.15",
"resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.15.tgz",
"integrity": "sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==",
+ "dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"engines": {
"node": ">=18"
}
@@ -1547,7 +1681,10 @@
"version": "3.0.10",
"resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.10.tgz",
"integrity": "sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA==",
+ "dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"engines": {
"node": ">=18"
},
@@ -1564,6 +1701,7 @@
"version": "0.3.13",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
"integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.5.0",
@@ -1574,6 +1712,7 @@
"version": "2.3.5",
"resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
"integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.5",
@@ -1584,6 +1723,7 @@
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">=6.0.0"
@@ -1593,85 +1733,28 @@
"version": "1.5.5",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
"integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
+ "dev": true,
"license": "MIT"
},
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.31",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
"integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/resolve-uri": "^3.1.0",
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
- "node_modules/@modelcontextprotocol/sdk": {
- "version": "1.27.1",
- "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.27.1.tgz",
- "integrity": "sha512-sr6GbP+4edBwFndLbM60gf07z0FQ79gaExpnsjMGePXqFcSSb7t6iscpjk9DhFhwd+mTEQrzNafGP8/iGGFYaA==",
- "license": "MIT",
- "dependencies": {
- "@hono/node-server": "^1.19.9",
- "ajv": "^8.17.1",
- "ajv-formats": "^3.0.1",
- "content-type": "^1.0.5",
- "cors": "^2.8.5",
- "cross-spawn": "^7.0.5",
- "eventsource": "^3.0.2",
- "eventsource-parser": "^3.0.0",
- "express": "^5.2.1",
- "express-rate-limit": "^8.2.1",
- "hono": "^4.11.4",
- "jose": "^6.1.3",
- "json-schema-typed": "^8.0.2",
- "pkce-challenge": "^5.0.0",
- "raw-body": "^3.0.0",
- "zod": "^3.25 || ^4.0",
- "zod-to-json-schema": "^3.25.1"
- },
- "engines": {
- "node": ">=18"
- },
- "peerDependencies": {
- "@cfworker/json-schema": "^4.1.1",
- "zod": "^3.25 || ^4.0"
- },
- "peerDependenciesMeta": {
- "@cfworker/json-schema": {
- "optional": true
- },
- "zod": {
- "optional": false
- }
- }
- },
- "node_modules/@modelcontextprotocol/sdk/node_modules/ajv": {
- "version": "8.18.0",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz",
- "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==",
- "license": "MIT",
- "dependencies": {
- "fast-deep-equal": "^3.1.3",
- "fast-uri": "^3.0.1",
- "json-schema-traverse": "^1.0.0",
- "require-from-string": "^2.0.2"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/epoberezkin"
- }
- },
- "node_modules/@modelcontextprotocol/sdk/node_modules/json-schema-traverse": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
- "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
- "license": "MIT"
- },
"node_modules/@mswjs/interceptors": {
"version": "0.41.3",
"resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.41.3.tgz",
"integrity": "sha512-cXu86tF4VQVfwz8W1SPbhoRyHJkti6mjH/XJIxp40jhO4j2k1m4KYrEykxqWPkFF3vrK4rgQppBh//AwyGSXPA==",
+ "dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"dependencies": {
"@open-draft/deferred-promise": "^2.2.0",
"@open-draft/logger": "^0.3.0",
@@ -1863,50 +1946,11 @@
"node": ">= 10"
}
},
- "node_modules/@noble/ciphers": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-1.3.0.tgz",
- "integrity": "sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw==",
- "license": "MIT",
- "peer": true,
- "engines": {
- "node": "^14.21.3 || >=16"
- },
- "funding": {
- "url": "https://paulmillr.com/funding/"
- }
- },
- "node_modules/@noble/curves": {
- "version": "1.9.7",
- "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.7.tgz",
- "integrity": "sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw==",
- "license": "MIT",
- "dependencies": {
- "@noble/hashes": "1.8.0"
- },
- "engines": {
- "node": "^14.21.3 || >=16"
- },
- "funding": {
- "url": "https://paulmillr.com/funding/"
- }
- },
- "node_modules/@noble/hashes": {
- "version": "1.8.0",
- "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz",
- "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==",
- "license": "MIT",
- "engines": {
- "node": "^14.21.3 || >=16"
- },
- "funding": {
- "url": "https://paulmillr.com/funding/"
- }
- },
"node_modules/@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
"integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"@nodelib/fs.stat": "2.0.5",
@@ -1920,6 +1964,7 @@
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
"integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">= 8"
@@ -1929,6 +1974,7 @@
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
"integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"@nodelib/fs.scandir": "2.1.5",
@@ -1952,13 +1998,19 @@
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz",
"integrity": "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==",
- "license": "MIT"
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "peer": true
},
"node_modules/@open-draft/logger": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/@open-draft/logger/-/logger-0.3.0.tgz",
"integrity": "sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==",
+ "dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"dependencies": {
"is-node-process": "^1.2.0",
"outvariant": "^1.4.0"
@@ -1968,86 +2020,29 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@open-draft/until/-/until-2.1.0.tgz",
"integrity": "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==",
- "license": "MIT"
- },
- "node_modules/@rtsao/scc": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz",
- "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@sec-ant/readable-stream": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz",
- "integrity": "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==",
- "license": "MIT"
- },
- "node_modules/@sindresorhus/merge-streams": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz",
- "integrity": "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==",
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/@swc/helpers": {
- "version": "0.5.15",
- "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz",
- "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==",
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.8.0"
- }
- },
- "node_modules/@tailwindcss/node": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.2.1.tgz",
- "integrity": "sha512-jlx6sLk4EOwO6hHe1oCGm1Q4AN/s0rSrTTPBGPM0/RQ6Uylwq17FuU8IeJJKEjtc6K6O07zsvP+gDO6MMWo7pg==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "@jridgewell/remapping": "^2.3.5",
- "enhanced-resolve": "^5.19.0",
- "jiti": "^2.6.1",
- "lightningcss": "1.31.1",
- "magic-string": "^0.30.21",
- "source-map-js": "^1.2.1",
- "tailwindcss": "4.2.1"
- }
+ "optional": true,
+ "peer": true
},
- "node_modules/@tailwindcss/oxide": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.2.1.tgz",
- "integrity": "sha512-yv9jeEFWnjKCI6/T3Oq50yQEOqmpmpfzG1hcZsAOaXFQPfzWprWrlHSdGPEF3WQTi8zu8ohC9Mh9J470nT5pUw==",
+ "node_modules/@rollup/rollup-android-arm-eabi": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz",
+ "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==",
+ "cpu": [
+ "arm"
+ ],
"dev": true,
"license": "MIT",
- "engines": {
- "node": ">= 20"
- },
- "optionalDependencies": {
- "@tailwindcss/oxide-android-arm64": "4.2.1",
- "@tailwindcss/oxide-darwin-arm64": "4.2.1",
- "@tailwindcss/oxide-darwin-x64": "4.2.1",
- "@tailwindcss/oxide-freebsd-x64": "4.2.1",
- "@tailwindcss/oxide-linux-arm-gnueabihf": "4.2.1",
- "@tailwindcss/oxide-linux-arm64-gnu": "4.2.1",
- "@tailwindcss/oxide-linux-arm64-musl": "4.2.1",
- "@tailwindcss/oxide-linux-x64-gnu": "4.2.1",
- "@tailwindcss/oxide-linux-x64-musl": "4.2.1",
- "@tailwindcss/oxide-wasm32-wasi": "4.2.1",
- "@tailwindcss/oxide-win32-arm64-msvc": "4.2.1",
- "@tailwindcss/oxide-win32-x64-msvc": "4.2.1"
- }
+ "optional": true,
+ "os": [
+ "android"
+ ]
},
- "node_modules/@tailwindcss/oxide-android-arm64": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.2.1.tgz",
- "integrity": "sha512-eZ7G1Zm5EC8OOKaesIKuw77jw++QJ2lL9N+dDpdQiAB/c/B2wDh0QPFHbkBVrXnwNugvrbJFk1gK2SsVjwWReg==",
+ "node_modules/@rollup/rollup-android-arm64": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz",
+ "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==",
"cpu": [
"arm64"
],
@@ -2056,15 +2051,12 @@
"optional": true,
"os": [
"android"
- ],
- "engines": {
- "node": ">= 20"
- }
+ ]
},
- "node_modules/@tailwindcss/oxide-darwin-arm64": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.2.1.tgz",
- "integrity": "sha512-q/LHkOstoJ7pI1J0q6djesLzRvQSIfEto148ppAd+BVQK0JYjQIFSK3JgYZJa+Yzi0DDa52ZsQx2rqytBnf8Hw==",
+ "node_modules/@rollup/rollup-darwin-arm64": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz",
+ "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==",
"cpu": [
"arm64"
],
@@ -2073,15 +2065,12 @@
"optional": true,
"os": [
"darwin"
- ],
- "engines": {
- "node": ">= 20"
- }
+ ]
},
- "node_modules/@tailwindcss/oxide-darwin-x64": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.2.1.tgz",
- "integrity": "sha512-/f/ozlaXGY6QLbpvd/kFTro2l18f7dHKpB+ieXz+Cijl4Mt9AI2rTrpq7V+t04nK+j9XBQHnSMdeQRhbGyt6fw==",
+ "node_modules/@rollup/rollup-darwin-x64": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz",
+ "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==",
"cpu": [
"x64"
],
@@ -2090,15 +2079,26 @@
"optional": true,
"os": [
"darwin"
- ],
- "engines": {
- "node": ">= 20"
- }
+ ]
},
- "node_modules/@tailwindcss/oxide-freebsd-x64": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.2.1.tgz",
- "integrity": "sha512-5e/AkgYJT/cpbkys/OU2Ei2jdETCLlifwm7ogMC7/hksI2fC3iiq6OcXwjibcIjPung0kRtR3TxEITkqgn0TcA==",
+ "node_modules/@rollup/rollup-freebsd-arm64": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz",
+ "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-x64": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz",
+ "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==",
"cpu": [
"x64"
],
@@ -2107,15 +2107,12 @@
"optional": true,
"os": [
"freebsd"
- ],
- "engines": {
- "node": ">= 20"
- }
+ ]
},
- "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.2.1.tgz",
- "integrity": "sha512-Uny1EcVTTmerCKt/1ZuKTkb0x8ZaiuYucg2/kImO5A5Y/kBz41/+j0gxUZl+hTF3xkWpDmHX+TaWhOtba2Fyuw==",
+ "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz",
+ "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==",
"cpu": [
"arm"
],
@@ -2124,15 +2121,26 @@
"optional": true,
"os": [
"linux"
- ],
- "engines": {
- "node": ">= 20"
- }
+ ]
},
- "node_modules/@tailwindcss/oxide-linux-arm64-gnu": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.2.1.tgz",
- "integrity": "sha512-CTrwomI+c7n6aSSQlsPL0roRiNMDQ/YzMD9EjcR+H4f0I1SQ8QqIuPnsVp7QgMkC1Qi8rtkekLkOFjo7OlEFRQ==",
+ "node_modules/@rollup/rollup-linux-arm-musleabihf": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz",
+ "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-gnu": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz",
+ "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==",
"cpu": [
"arm64"
],
@@ -2141,15 +2149,12 @@
"optional": true,
"os": [
"linux"
- ],
- "engines": {
- "node": ">= 20"
- }
+ ]
},
- "node_modules/@tailwindcss/oxide-linux-arm64-musl": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.2.1.tgz",
- "integrity": "sha512-WZA0CHRL/SP1TRbA5mp9htsppSEkWuQ4KsSUumYQnyl8ZdT39ntwqmz4IUHGN6p4XdSlYfJwM4rRzZLShHsGAQ==",
+ "node_modules/@rollup/rollup-linux-arm64-musl": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz",
+ "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==",
"cpu": [
"arm64"
],
@@ -2158,15 +2163,110 @@
"optional": true,
"os": [
"linux"
- ],
- "engines": {
- "node": ">= 20"
- }
+ ]
},
- "node_modules/@tailwindcss/oxide-linux-x64-gnu": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.2.1.tgz",
- "integrity": "sha512-qMFzxI2YlBOLW5PhblzuSWlWfwLHaneBE0xHzLrBgNtqN6mWfs+qYbhryGSXQjFYB1Dzf5w+LN5qbUTPhW7Y5g==",
+ "node_modules/@rollup/rollup-linux-loong64-gnu": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz",
+ "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-loong64-musl": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz",
+ "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-ppc64-gnu": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz",
+ "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-ppc64-musl": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz",
+ "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-gnu": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz",
+ "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-musl": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz",
+ "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-s390x-gnu": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz",
+ "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-gnu": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz",
+ "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==",
"cpu": [
"x64"
],
@@ -2175,15 +2275,12 @@
"optional": true,
"os": [
"linux"
- ],
- "engines": {
- "node": ">= 20"
- }
+ ]
},
- "node_modules/@tailwindcss/oxide-linux-x64-musl": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.2.1.tgz",
- "integrity": "sha512-5r1X2FKnCMUPlXTWRYpHdPYUY6a1Ar/t7P24OuiEdEOmms5lyqjDRvVY1yy9Rmioh+AunQ0rWiOTPE8F9A3v5g==",
+ "node_modules/@rollup/rollup-linux-x64-musl": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz",
+ "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==",
"cpu": [
"x64"
],
@@ -2192,45 +2289,40 @@
"optional": true,
"os": [
"linux"
- ],
- "engines": {
- "node": ">= 20"
- }
+ ]
},
- "node_modules/@tailwindcss/oxide-wasm32-wasi": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.2.1.tgz",
- "integrity": "sha512-MGFB5cVPvshR85MTJkEvqDUnuNoysrsRxd6vnk1Lf2tbiqNlXpHYZqkqOQalydienEWOHHFyyuTSYRsLfxFJ2Q==",
- "bundleDependencies": [
- "@napi-rs/wasm-runtime",
- "@emnapi/core",
- "@emnapi/runtime",
- "@tybys/wasm-util",
- "@emnapi/wasi-threads",
- "tslib"
- ],
+ "node_modules/@rollup/rollup-openbsd-x64": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz",
+ "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==",
"cpu": [
- "wasm32"
+ "x64"
],
"dev": true,
"license": "MIT",
"optional": true,
- "dependencies": {
- "@emnapi/core": "^1.8.1",
- "@emnapi/runtime": "^1.8.1",
- "@emnapi/wasi-threads": "^1.1.0",
- "@napi-rs/wasm-runtime": "^1.1.1",
- "@tybys/wasm-util": "^0.10.1",
- "tslib": "^2.8.1"
- },
- "engines": {
- "node": ">=14.0.0"
- }
+ "os": [
+ "openbsd"
+ ]
},
- "node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.2.1.tgz",
- "integrity": "sha512-YlUEHRHBGnCMh4Nj4GnqQyBtsshUPdiNroZj8VPkvTZSoHsilRCwXcVKnG9kyi0ZFAS/3u+qKHBdDc81SADTRA==",
+ "node_modules/@rollup/rollup-openharmony-arm64": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz",
+ "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-arm64-msvc": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz",
+ "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==",
"cpu": [
"arm64"
],
@@ -2239,15 +2331,26 @@
"optional": true,
"os": [
"win32"
- ],
- "engines": {
- "node": ">= 20"
- }
+ ]
},
- "node_modules/@tailwindcss/oxide-win32-x64-msvc": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.2.1.tgz",
- "integrity": "sha512-rbO34G5sMWWyrN/idLeVxAZgAKWrn5LiR3/I90Q9MkA67s6T1oB0xtTe+0heoBvHSpbU9Mk7i6uwJnpo4u21XQ==",
+ "node_modules/@rollup/rollup-win32-ia32-msvc": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz",
+ "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-x64-gnu": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz",
+ "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==",
"cpu": [
"x64"
],
@@ -2256,98 +2359,36 @@
"optional": true,
"os": [
"win32"
- ],
- "engines": {
- "node": ">= 20"
- }
+ ]
},
- "node_modules/@tailwindcss/postcss": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.2.1.tgz",
- "integrity": "sha512-OEwGIBnXnj7zJeonOh6ZG9woofIjGrd2BORfvE5p9USYKDCZoQmfqLcfNiRWoJlRWLdNPn2IgVZuWAOM4iTYMw==",
+ "node_modules/@rollup/rollup-win32-x64-msvc": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz",
+ "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==",
+ "cpu": [
+ "x64"
+ ],
"dev": true,
"license": "MIT",
- "dependencies": {
- "@alloc/quick-lru": "^5.2.0",
- "@tailwindcss/node": "4.2.1",
- "@tailwindcss/oxide": "4.2.1",
- "postcss": "^8.5.6",
- "tailwindcss": "4.2.1"
- }
+ "optional": true,
+ "os": [
+ "win32"
+ ]
},
- "node_modules/@ts-morph/common": {
- "version": "0.27.0",
- "resolved": "https://registry.npmjs.org/@ts-morph/common/-/common-0.27.0.tgz",
- "integrity": "sha512-Wf29UqxWDpc+i61k3oIOzcUfQt79PIT9y/MWfAGlrkjg6lBC1hwDECLXPVJAhWjiGbfBCxZd65F/LIZF3+jeJQ==",
- "license": "MIT",
- "dependencies": {
- "fast-glob": "^3.3.3",
- "minimatch": "^10.0.1",
- "path-browserify": "^1.0.1"
- }
+ "node_modules/@rtsao/scc": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz",
+ "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==",
+ "dev": true,
+ "license": "MIT"
},
- "node_modules/@ts-morph/common/node_modules/balanced-match": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
- "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
- "license": "MIT",
- "engines": {
- "node": "18 || 20 || >=22"
- }
- },
- "node_modules/@ts-morph/common/node_modules/brace-expansion": {
- "version": "5.0.4",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz",
- "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==",
- "license": "MIT",
+ "node_modules/@swc/helpers": {
+ "version": "0.5.15",
+ "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz",
+ "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==",
+ "license": "Apache-2.0",
"dependencies": {
- "balanced-match": "^4.0.2"
- },
- "engines": {
- "node": "18 || 20 || >=22"
- }
- },
- "node_modules/@ts-morph/common/node_modules/fast-glob": {
- "version": "3.3.3",
- "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
- "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
- "license": "MIT",
- "dependencies": {
- "@nodelib/fs.stat": "^2.0.2",
- "@nodelib/fs.walk": "^1.2.3",
- "glob-parent": "^5.1.2",
- "merge2": "^1.3.0",
- "micromatch": "^4.0.8"
- },
- "engines": {
- "node": ">=8.6.0"
- }
- },
- "node_modules/@ts-morph/common/node_modules/glob-parent": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
- "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
- "license": "ISC",
- "dependencies": {
- "is-glob": "^4.0.1"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/@ts-morph/common/node_modules/minimatch": {
- "version": "10.2.4",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz",
- "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==",
- "license": "BlueOak-1.0.0",
- "dependencies": {
- "brace-expansion": "^5.0.2"
- },
- "engines": {
- "node": "18 || 20 || >=22"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
+ "tslib": "^2.8.0"
}
},
"node_modules/@tybys/wasm-util": {
@@ -2361,6 +2402,24 @@
"tslib": "^2.4.0"
}
},
+ "node_modules/@types/chai": {
+ "version": "5.2.3",
+ "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz",
+ "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/deep-eql": "*",
+ "assertion-error": "^2.0.1"
+ }
+ },
+ "node_modules/@types/deep-eql": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz",
+ "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@types/estree": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
@@ -2368,6 +2427,26 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@types/jsdom": {
+ "version": "28.0.1",
+ "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-28.0.1.tgz",
+ "integrity": "sha512-GJq2QE4TAZ5ajSoCasn5DOFm8u1mI3tIFvM5tIq3W5U/RTB6gsHwc6Yhpl91X9VSDOUVblgXmG+2+sSvFQrdlw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*",
+ "@types/tough-cookie": "*",
+ "parse5": "^7.0.0",
+ "undici-types": "^7.21.0"
+ }
+ },
+ "node_modules/@types/jsdom/node_modules/undici-types": {
+ "version": "7.24.5",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.5.tgz",
+ "integrity": "sha512-kNh333UBSbgK35OIW7FwJTr9tTfVIG51Fm1tSVT7m8foPHfDVjsb7OIee/q/rs3bB2aV/3qOPgG5mHNWl1odiA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@types/json-schema": {
"version": "7.0.15",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
@@ -2406,9 +2485,8 @@
"version": "19.2.14",
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz",
"integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==",
- "devOptional": true,
+ "dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"csstype": "^3.2.2"
}
@@ -2427,12 +2505,16 @@
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/@types/statuses/-/statuses-2.0.6.tgz",
"integrity": "sha512-xMAgYwceFhRA2zY+XbEA7mxYbA093wdiW8Vu6gZPGWy9cmOyU9XesH1tNcEWsKFd5Vzrqx5T3D38PWx1FIIXkA==",
- "license": "MIT"
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "peer": true
},
- "node_modules/@types/validate-npm-package-name": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/@types/validate-npm-package-name/-/validate-npm-package-name-4.0.2.tgz",
- "integrity": "sha512-lrpDziQipxCEeK5kWxvljWYhUvOiB2A9izZd9B2AFarYAkqZshb4lPbRs7zKEic6eGtH8V/2qJW+dPp9OtF6bw==",
+ "node_modules/@types/tough-cookie": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz",
+ "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==",
+ "dev": true,
"license": "MIT"
},
"node_modules/@typescript-eslint/eslint-plugin": {
@@ -2480,7 +2562,6 @@
"integrity": "sha512-XZzOmihLIr8AD1b9hL9ccNMzEMWt/dE2u7NyTY9jJG6YNiNthaD5XtUHVF2uCXZ15ng+z2hT3MVuxnUYhq6k1g==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@typescript-eslint/scope-manager": "8.57.0",
"@typescript-eslint/types": "8.57.0",
@@ -3000,17 +3081,119 @@
"win32"
]
},
- "node_modules/accepts": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz",
- "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==",
+ "node_modules/@vitest/expect": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.4.tgz",
+ "integrity": "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "mime-types": "^3.0.0",
- "negotiator": "^1.0.0"
+ "@types/chai": "^5.2.2",
+ "@vitest/spy": "3.2.4",
+ "@vitest/utils": "3.2.4",
+ "chai": "^5.2.0",
+ "tinyrainbow": "^2.0.0"
},
- "engines": {
- "node": ">= 0.6"
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/mocker": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.4.tgz",
+ "integrity": "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/spy": "3.2.4",
+ "estree-walker": "^3.0.3",
+ "magic-string": "^0.30.17"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ },
+ "peerDependencies": {
+ "msw": "^2.4.9",
+ "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0"
+ },
+ "peerDependenciesMeta": {
+ "msw": {
+ "optional": true
+ },
+ "vite": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@vitest/pretty-format": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.4.tgz",
+ "integrity": "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tinyrainbow": "^2.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/runner": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.4.tgz",
+ "integrity": "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/utils": "3.2.4",
+ "pathe": "^2.0.3",
+ "strip-literal": "^3.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/snapshot": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.4.tgz",
+ "integrity": "sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/pretty-format": "3.2.4",
+ "magic-string": "^0.30.17",
+ "pathe": "^2.0.3"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/spy": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.4.tgz",
+ "integrity": "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tinyspy": "^4.0.3"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/utils": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.4.tgz",
+ "integrity": "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/pretty-format": "3.2.4",
+ "loupe": "^3.1.4",
+ "tinyrainbow": "^2.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
}
},
"node_modules/acorn": {
@@ -3019,7 +3202,6 @@
"integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==",
"dev": true,
"license": "MIT",
- "peer": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -3041,6 +3223,7 @@
"version": "7.1.4",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
"integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">= 14"
@@ -3063,61 +3246,11 @@
"url": "https://github.com/sponsors/epoberezkin"
}
},
- "node_modules/ajv-formats": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz",
- "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==",
- "license": "MIT",
- "dependencies": {
- "ajv": "^8.0.0"
- },
- "peerDependencies": {
- "ajv": "^8.0.0"
- },
- "peerDependenciesMeta": {
- "ajv": {
- "optional": true
- }
- }
- },
- "node_modules/ajv-formats/node_modules/ajv": {
- "version": "8.18.0",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz",
- "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==",
- "license": "MIT",
- "dependencies": {
- "fast-deep-equal": "^3.1.3",
- "fast-uri": "^3.0.1",
- "json-schema-traverse": "^1.0.0",
- "require-from-string": "^2.0.2"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/epoberezkin"
- }
- },
- "node_modules/ajv-formats/node_modules/json-schema-traverse": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
- "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
- "license": "MIT"
- },
- "node_modules/ansi-regex": {
- "version": "6.2.2",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz",
- "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==",
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-regex?sponsor=1"
- }
- },
"node_modules/ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"color-convert": "^2.0.1"
@@ -3129,19 +3262,11 @@
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
- "node_modules/ansis": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/ansis/-/ansis-4.2.0.tgz",
- "integrity": "sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==",
- "license": "ISC",
- "engines": {
- "node": ">=14"
- }
- },
"node_modules/argparse": {
"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/aria-query": {
@@ -3314,16 +3439,14 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/ast-types": {
- "version": "0.16.1",
- "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz",
- "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==",
+ "node_modules/assertion-error": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz",
+ "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==",
+ "dev": true,
"license": "MIT",
- "dependencies": {
- "tslib": "^2.0.1"
- },
"engines": {
- "node": ">=4"
+ "node": ">=12"
}
},
"node_modules/ast-types-flow": {
@@ -3398,28 +3521,14 @@
"node": ">=6.0.0"
}
},
- "node_modules/body-parser": {
- "version": "2.2.2",
- "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz",
- "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==",
+ "node_modules/bidi-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz",
+ "integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "bytes": "^3.1.2",
- "content-type": "^1.0.5",
- "debug": "^4.4.3",
- "http-errors": "^2.0.0",
- "iconv-lite": "^0.7.0",
- "on-finished": "^2.4.1",
- "qs": "^6.14.1",
- "raw-body": "^3.0.1",
- "type-is": "^2.0.1"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
+ "require-from-string": "^2.0.2"
}
},
"node_modules/brace-expansion": {
@@ -3437,6 +3546,7 @@
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"fill-range": "^7.1.1"
@@ -3449,6 +3559,7 @@
"version": "4.28.1",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz",
"integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==",
+ "dev": true,
"funding": [
{
"type": "opencollective",
@@ -3464,7 +3575,6 @@
}
],
"license": "MIT",
- "peer": true,
"dependencies": {
"baseline-browser-mapping": "^2.9.0",
"caniuse-lite": "^1.0.30001759",
@@ -3479,28 +3589,14 @@
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
}
},
- "node_modules/bundle-name": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz",
- "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==",
- "license": "MIT",
- "dependencies": {
- "run-applescript": "^7.0.0"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/bytes": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
- "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
+ "node_modules/cac": {
+ "version": "6.7.14",
+ "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz",
+ "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==",
+ "dev": true,
"license": "MIT",
"engines": {
- "node": ">= 0.8"
+ "node": ">=8"
}
},
"node_modules/call-bind": {
@@ -3526,6 +3622,7 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
@@ -3539,6 +3636,7 @@
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
"integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.2",
@@ -3555,6 +3653,7 @@
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
"integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
@@ -3580,6 +3679,23 @@
],
"license": "CC-BY-4.0"
},
+ "node_modules/chai": {
+ "version": "5.3.3",
+ "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz",
+ "integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "assertion-error": "^2.0.1",
+ "check-error": "^2.1.1",
+ "deep-eql": "^5.0.1",
+ "loupe": "^3.1.0",
+ "pathval": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
@@ -3597,50 +3713,24 @@
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
- "node_modules/class-variance-authority": {
- "version": "0.7.1",
- "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz",
- "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==",
- "license": "Apache-2.0",
- "dependencies": {
- "clsx": "^2.1.1"
- },
- "funding": {
- "url": "https://polar.sh/cva"
- }
- },
- "node_modules/cli-cursor": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz",
- "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==",
- "license": "MIT",
- "dependencies": {
- "restore-cursor": "^5.0.0"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/cli-spinners": {
- "version": "2.9.2",
- "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz",
- "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==",
+ "node_modules/check-error": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.3.tgz",
+ "integrity": "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==",
+ "dev": true,
"license": "MIT",
"engines": {
- "node": ">=6"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "node": ">= 16"
}
},
"node_modules/cli-width": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz",
"integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==",
+ "dev": true,
"license": "ISC",
+ "optional": true,
+ "peer": true,
"engines": {
"node": ">= 12"
}
@@ -3655,7 +3745,10 @@
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
"integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "dev": true,
"license": "ISC",
+ "optional": true,
+ "peer": true,
"dependencies": {
"string-width": "^4.2.0",
"strip-ansi": "^6.0.1",
@@ -3669,7 +3762,10 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"engines": {
"node": ">=8"
}
@@ -3678,13 +3774,19 @@
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
- "license": "MIT"
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "peer": true
},
"node_modules/cliui/node_modules/string-width": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
@@ -3698,7 +3800,10 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"dependencies": {
"ansi-regex": "^5.0.1"
},
@@ -3710,7 +3815,10 @@
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"dependencies": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
@@ -3723,25 +3831,11 @@
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
- "node_modules/clsx": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
- "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/code-block-writer": {
- "version": "13.0.3",
- "resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-13.0.3.tgz",
- "integrity": "sha512-Oofo0pq3IKnsFtuHqSF7TqBfr71aeyZDVJ0HpmqB7FBM2qEigL0iPONSCZSO9pE9dZTAxANe5XHG9Uy0YMv8cg==",
- "license": "MIT"
- },
"node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"color-name": "~1.1.4"
@@ -3754,17 +3848,9 @@
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true,
"license": "MIT"
},
- "node_modules/commander": {
- "version": "14.0.3",
- "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz",
- "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==",
- "license": "MIT",
- "engines": {
- "node": ">=20"
- }
- },
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@@ -3772,99 +3858,18 @@
"dev": true,
"license": "MIT"
},
- "node_modules/content-disposition": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz",
- "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==",
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
- }
- },
- "node_modules/content-type": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
- "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
"node_modules/convert-source-map": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
"integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "dev": true,
"license": "MIT"
},
- "node_modules/cookie": {
- "version": "0.7.2",
- "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
- "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/cookie-signature": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz",
- "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==",
- "license": "MIT",
- "engines": {
- "node": ">=6.6.0"
- }
- },
- "node_modules/cors": {
- "version": "2.8.6",
- "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz",
- "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==",
- "license": "MIT",
- "dependencies": {
- "object-assign": "^4",
- "vary": "^1"
- },
- "engines": {
- "node": ">= 0.10"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
- }
- },
- "node_modules/cosmiconfig": {
- "version": "9.0.1",
- "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.1.tgz",
- "integrity": "sha512-hr4ihw+DBqcvrsEDioRO31Z17x71pUYoNe/4h6Z0wB72p7MU7/9gH8Q3s12NFhHPfYBBOV3qyfUxmr/Yn3shnQ==",
- "license": "MIT",
- "dependencies": {
- "env-paths": "^2.2.1",
- "import-fresh": "^3.3.0",
- "js-yaml": "^4.1.0",
- "parse-json": "^5.2.0"
- },
- "engines": {
- "node": ">=14"
- },
- "funding": {
- "url": "https://github.com/sponsors/d-fischer"
- },
- "peerDependencies": {
- "typescript": ">=4.9.5"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
- }
- },
"node_modules/cross-spawn": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"path-key": "^3.1.0",
@@ -3875,23 +3880,51 @@
"node": ">= 8"
}
},
- "node_modules/cssesc": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
- "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
+ "node_modules/css-tree": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.2.1.tgz",
+ "integrity": "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==",
+ "dev": true,
"license": "MIT",
- "bin": {
- "cssesc": "bin/cssesc"
+ "dependencies": {
+ "mdn-data": "2.27.1",
+ "source-map-js": "^1.2.1"
},
"engines": {
- "node": ">=4"
+ "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0"
+ }
+ },
+ "node_modules/cssstyle": {
+ "version": "5.3.7",
+ "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-5.3.7.tgz",
+ "integrity": "sha512-7D2EPVltRrsTkhpQmksIu+LxeWAIEk6wRDMJ1qljlv+CKHJM+cJLlfhWIzNA44eAsHXSNe3+vO6DW1yCYx8SuQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@asamuzakjp/css-color": "^4.1.1",
+ "@csstools/css-syntax-patches-for-csstree": "^1.0.21",
+ "css-tree": "^3.1.0",
+ "lru-cache": "^11.2.4"
+ },
+ "engines": {
+ "node": ">=20"
+ }
+ },
+ "node_modules/cssstyle/node_modules/lru-cache": {
+ "version": "11.2.7",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.7.tgz",
+ "integrity": "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": "20 || >=22"
}
},
"node_modules/csstype": {
"version": "3.2.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
"integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
- "devOptional": true,
+ "dev": true,
"license": "MIT"
},
"node_modules/damerau-levenshtein": {
@@ -3901,13 +3934,28 @@
"dev": true,
"license": "BSD-2-Clause"
},
- "node_modules/data-uri-to-buffer": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
- "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==",
+ "node_modules/data-urls": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-6.0.1.tgz",
+ "integrity": "sha512-euIQENZg6x8mj3fO6o9+fOW8MimUI4PpD/fZBhJfeioZVy9TUpM4UY7KjQNVZFlqwJ0UdzRDzkycB997HEq1BQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "whatwg-mimetype": "^5.0.0",
+ "whatwg-url": "^15.1.0"
+ },
+ "engines": {
+ "node": ">=20"
+ }
+ },
+ "node_modules/data-urls/node_modules/whatwg-mimetype": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-5.0.0.tgz",
+ "integrity": "sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==",
+ "dev": true,
"license": "MIT",
"engines": {
- "node": ">= 12"
+ "node": ">=20"
}
},
"node_modules/data-view-buffer": {
@@ -3968,6 +4016,7 @@
"version": "4.4.3",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
@@ -3981,18 +4030,21 @@
}
}
},
- "node_modules/dedent": {
- "version": "1.7.2",
- "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.2.tgz",
- "integrity": "sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA==",
+ "node_modules/decimal.js": {
+ "version": "10.6.0",
+ "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz",
+ "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/deep-eql": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz",
+ "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==",
+ "dev": true,
"license": "MIT",
- "peerDependencies": {
- "babel-plugin-macros": "^3.1.0"
- },
- "peerDependenciesMeta": {
- "babel-plugin-macros": {
- "optional": true
- }
+ "engines": {
+ "node": ">=6"
}
},
"node_modules/deep-is": {
@@ -4002,43 +4054,6 @@
"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/default-browser": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.5.0.tgz",
- "integrity": "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==",
- "license": "MIT",
- "dependencies": {
- "bundle-name": "^4.1.0",
- "default-browser-id": "^5.0.0"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/default-browser-id": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.1.tgz",
- "integrity": "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==",
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/define-data-property": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
@@ -4057,18 +4072,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/define-lazy-prop": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz",
- "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==",
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/define-properties": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
@@ -4087,34 +4090,16 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/depd": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
- "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
"node_modules/detect-libc": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
"integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
- "devOptional": true,
"license": "Apache-2.0",
+ "optional": true,
"engines": {
"node": ">=8"
}
},
- "node_modules/diff": {
- "version": "8.0.3",
- "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.3.tgz",
- "integrity": "sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ==",
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">=0.3.1"
- }
- },
"node_modules/doctrine": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
@@ -4132,6 +4117,7 @@
"version": "17.3.1",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.3.1.tgz",
"integrity": "sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA==",
+ "dev": true,
"license": "BSD-2-Clause",
"engines": {
"node": ">=12"
@@ -4144,6 +4130,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.1",
@@ -4154,33 +4141,11 @@
"node": ">= 0.4"
}
},
- "node_modules/eciesjs": {
- "version": "0.4.18",
- "resolved": "https://registry.npmjs.org/eciesjs/-/eciesjs-0.4.18.tgz",
- "integrity": "sha512-wG99Zcfcys9fZux7Cft8BAX/YrOJLJSZ3jyYPfhZHqN2E+Ffx+QXBDsv3gubEgPtV6dTzJMSQUwk1H98/t/0wQ==",
- "license": "MIT",
- "dependencies": {
- "@ecies/ciphers": "^0.2.5",
- "@noble/ciphers": "^1.3.0",
- "@noble/curves": "^1.9.7",
- "@noble/hashes": "^1.8.0"
- },
- "engines": {
- "bun": ">=1",
- "deno": ">=2",
- "node": ">=16"
- }
- },
- "node_modules/ee-first": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
- "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
- "license": "MIT"
- },
"node_modules/electron-to-chromium": {
"version": "1.5.313",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.313.tgz",
"integrity": "sha512-QBMrTWEf00GXZmJyx2lbYD45jpI3TUFnNIzJ5BBc8piGUDwMPa1GV6HJWTZVvY/eiN3fSopl7NRbgGp9sZ9LTA==",
+ "dev": true,
"license": "ISC"
},
"node_modules/emoji-regex": {
@@ -4190,45 +4155,17 @@
"dev": true,
"license": "MIT"
},
- "node_modules/encodeurl": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
- "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/enhanced-resolve": {
- "version": "5.20.0",
- "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.20.0.tgz",
- "integrity": "sha512-/ce7+jQ1PQ6rVXwe+jKEg5hW5ciicHwIQUagZkp6IufBoY3YDgdTTY1azVs0qoRgVmvsNB+rbjLJxDAeHHtwsQ==",
+ "node_modules/entities": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz",
+ "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==",
"dev": true,
- "license": "MIT",
- "dependencies": {
- "graceful-fs": "^4.2.4",
- "tapable": "^2.3.0"
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.12"
},
- "engines": {
- "node": ">=10.13.0"
- }
- },
- "node_modules/env-paths": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
- "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/error-ex": {
- "version": "1.3.4",
- "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz",
- "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==",
- "license": "MIT",
- "dependencies": {
- "is-arrayish": "^0.2.1"
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/es-abstract": {
@@ -4304,6 +4241,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
@@ -4313,6 +4251,7 @@
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
@@ -4347,10 +4286,18 @@
"node": ">= 0.4"
}
},
+ "node_modules/es-module-lexer": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz",
+ "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/es-object-atoms": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0"
@@ -4406,21 +4353,58 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/esbuild": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.4.tgz",
+ "integrity": "sha512-Rq4vbHnYkK5fws5NF7MYTU68FPRE1ajX7heQ/8QXXWqNgqqJ/GkmmyxIzUnf2Sr/bakf8l54716CcMGHYhMrrQ==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.27.4",
+ "@esbuild/android-arm": "0.27.4",
+ "@esbuild/android-arm64": "0.27.4",
+ "@esbuild/android-x64": "0.27.4",
+ "@esbuild/darwin-arm64": "0.27.4",
+ "@esbuild/darwin-x64": "0.27.4",
+ "@esbuild/freebsd-arm64": "0.27.4",
+ "@esbuild/freebsd-x64": "0.27.4",
+ "@esbuild/linux-arm": "0.27.4",
+ "@esbuild/linux-arm64": "0.27.4",
+ "@esbuild/linux-ia32": "0.27.4",
+ "@esbuild/linux-loong64": "0.27.4",
+ "@esbuild/linux-mips64el": "0.27.4",
+ "@esbuild/linux-ppc64": "0.27.4",
+ "@esbuild/linux-riscv64": "0.27.4",
+ "@esbuild/linux-s390x": "0.27.4",
+ "@esbuild/linux-x64": "0.27.4",
+ "@esbuild/netbsd-arm64": "0.27.4",
+ "@esbuild/netbsd-x64": "0.27.4",
+ "@esbuild/openbsd-arm64": "0.27.4",
+ "@esbuild/openbsd-x64": "0.27.4",
+ "@esbuild/openharmony-arm64": "0.27.4",
+ "@esbuild/sunos-x64": "0.27.4",
+ "@esbuild/win32-arm64": "0.27.4",
+ "@esbuild/win32-ia32": "0.27.4",
+ "@esbuild/win32-x64": "0.27.4"
+ }
+ },
"node_modules/escalade": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
"integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
}
},
- "node_modules/escape-html": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
- "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
- "license": "MIT"
- },
"node_modules/escape-string-regexp": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
@@ -4440,7 +4424,6 @@
"integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.8.0",
"@eslint-community/regexpp": "^4.12.1",
@@ -4626,7 +4609,6 @@
"integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@rtsao/scc": "^1.1.0",
"array-includes": "^3.1.9",
@@ -4820,19 +4802,6 @@
"url": "https://opencollective.com/eslint"
}
},
- "node_modules/esprima": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
- "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
- "license": "BSD-2-Clause",
- "bin": {
- "esparse": "bin/esparse.js",
- "esvalidate": "bin/esvalidate.js"
- },
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/esquery": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz",
@@ -4869,6 +4838,16 @@
"node": ">=4.0"
}
},
+ "node_modules/estree-walker": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
+ "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0"
+ }
+ },
"node_modules/esutils": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
@@ -4879,128 +4858,21 @@
"node": ">=0.10.0"
}
},
- "node_modules/etag": {
- "version": "1.8.1",
- "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
- "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
- "license": "MIT",
+ "node_modules/expect-type": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz",
+ "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==",
+ "dev": true,
+ "license": "Apache-2.0",
"engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/eventsource": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.7.tgz",
- "integrity": "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==",
- "license": "MIT",
- "dependencies": {
- "eventsource-parser": "^3.0.1"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/eventsource-parser": {
- "version": "3.0.6",
- "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.6.tgz",
- "integrity": "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==",
- "license": "MIT",
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/execa": {
- "version": "9.6.1",
- "resolved": "https://registry.npmjs.org/execa/-/execa-9.6.1.tgz",
- "integrity": "sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA==",
- "license": "MIT",
- "dependencies": {
- "@sindresorhus/merge-streams": "^4.0.0",
- "cross-spawn": "^7.0.6",
- "figures": "^6.1.0",
- "get-stream": "^9.0.0",
- "human-signals": "^8.0.1",
- "is-plain-obj": "^4.1.0",
- "is-stream": "^4.0.1",
- "npm-run-path": "^6.0.0",
- "pretty-ms": "^9.2.0",
- "signal-exit": "^4.1.0",
- "strip-final-newline": "^4.0.0",
- "yoctocolors": "^2.1.1"
- },
- "engines": {
- "node": "^18.19.0 || >=20.5.0"
- },
- "funding": {
- "url": "https://github.com/sindresorhus/execa?sponsor=1"
- }
- },
- "node_modules/express": {
- "version": "5.2.1",
- "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz",
- "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "accepts": "^2.0.0",
- "body-parser": "^2.2.1",
- "content-disposition": "^1.0.0",
- "content-type": "^1.0.5",
- "cookie": "^0.7.1",
- "cookie-signature": "^1.2.1",
- "debug": "^4.4.0",
- "depd": "^2.0.0",
- "encodeurl": "^2.0.0",
- "escape-html": "^1.0.3",
- "etag": "^1.8.1",
- "finalhandler": "^2.1.0",
- "fresh": "^2.0.0",
- "http-errors": "^2.0.0",
- "merge-descriptors": "^2.0.0",
- "mime-types": "^3.0.0",
- "on-finished": "^2.4.1",
- "once": "^1.4.0",
- "parseurl": "^1.3.3",
- "proxy-addr": "^2.0.7",
- "qs": "^6.14.0",
- "range-parser": "^1.2.1",
- "router": "^2.2.0",
- "send": "^1.1.0",
- "serve-static": "^2.2.0",
- "statuses": "^2.0.1",
- "type-is": "^2.0.1",
- "vary": "^1.1.2"
- },
- "engines": {
- "node": ">= 18"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
- }
- },
- "node_modules/express-rate-limit": {
- "version": "8.3.1",
- "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.3.1.tgz",
- "integrity": "sha512-D1dKN+cmyPWuvB+G2SREQDzPY1agpBIcTa9sJxOPMCNeH3gwzhqJRDWCXW3gg0y//+LQ/8j52JbMROWyrKdMdw==",
- "license": "MIT",
- "dependencies": {
- "ip-address": "10.1.0"
- },
- "engines": {
- "node": ">= 16"
- },
- "funding": {
- "url": "https://github.com/sponsors/express-rate-limit"
- },
- "peerDependencies": {
- "express": ">= 4.11"
+ "node": ">=12.0.0"
}
},
"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": {
@@ -5047,69 +4919,16 @@
"dev": true,
"license": "MIT"
},
- "node_modules/fast-uri": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz",
- "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/fastify"
- },
- {
- "type": "opencollective",
- "url": "https://opencollective.com/fastify"
- }
- ],
- "license": "BSD-3-Clause"
- },
"node_modules/fastq": {
"version": "1.20.1",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz",
"integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==",
+ "dev": true,
"license": "ISC",
"dependencies": {
"reusify": "^1.0.4"
}
},
- "node_modules/fetch-blob": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
- "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/jimmywarting"
- },
- {
- "type": "paypal",
- "url": "https://paypal.me/jimmywarting"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "node-domexception": "^1.0.0",
- "web-streams-polyfill": "^3.0.3"
- },
- "engines": {
- "node": "^12.20 || >= 14.13"
- }
- },
- "node_modules/figures": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/figures/-/figures-6.1.0.tgz",
- "integrity": "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==",
- "license": "MIT",
- "dependencies": {
- "is-unicode-supported": "^2.0.0"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/file-entry-cache": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
@@ -5127,6 +4946,7 @@
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"to-regex-range": "^5.0.1"
@@ -5135,27 +4955,6 @@
"node": ">=8"
}
},
- "node_modules/finalhandler": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz",
- "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==",
- "license": "MIT",
- "dependencies": {
- "debug": "^4.4.0",
- "encodeurl": "^2.0.0",
- "escape-html": "^1.0.3",
- "on-finished": "^2.4.1",
- "parseurl": "^1.3.3",
- "statuses": "^2.0.1"
- },
- "engines": {
- "node": ">= 18.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
- }
- },
"node_modules/find-up": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
@@ -5210,54 +5009,26 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/formdata-polyfill": {
- "version": "4.0.10",
- "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
- "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "hasInstallScript": true,
"license": "MIT",
- "dependencies": {
- "fetch-blob": "^3.1.2"
- },
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
"engines": {
- "node": ">=12.20.0"
- }
- },
- "node_modules/forwarded": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
- "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/fresh": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz",
- "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/fs-extra": {
- "version": "11.3.4",
- "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.4.tgz",
- "integrity": "sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA==",
- "license": "MIT",
- "dependencies": {
- "graceful-fs": "^4.2.0",
- "jsonfile": "^6.0.1",
- "universalify": "^2.0.0"
- },
- "engines": {
- "node": ">=14.14"
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/function-bind": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "dev": true,
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -5294,18 +5065,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/fuzzysort": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/fuzzysort/-/fuzzysort-3.1.0.tgz",
- "integrity": "sha512-sR9BNCjBg6LNgwvxlBd0sBABvQitkLzoVY9MYYROQVX/FvfJ4Mai9LsGhDgd8qYdds0bY77VzYd5iuB+v5rwQQ==",
- "license": "MIT"
- },
- "node_modules/fzf": {
- "version": "0.5.2",
- "resolved": "https://registry.npmjs.org/fzf/-/fzf-0.5.2.tgz",
- "integrity": "sha512-Tt4kuxLXFKHy8KT40zwsUPUkg1CrsgY25FxA2U/j/0WgEDCk3ddc/zLTCCcbSHX9FcKtLuVaDGtGE/STWC+j3Q==",
- "license": "BSD-3-Clause"
- },
"node_modules/generator-function": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz",
@@ -5320,6 +5079,7 @@
"version": "1.0.0-beta.2",
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
"integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">=6.9.0"
@@ -5329,27 +5089,19 @@
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "dev": true,
"license": "ISC",
+ "optional": true,
+ "peer": true,
"engines": {
"node": "6.* || 8.* || >= 10.*"
}
},
- "node_modules/get-east-asian-width": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.5.0.tgz",
- "integrity": "sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==",
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/get-intrinsic": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.2",
@@ -5370,22 +5122,11 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/get-own-enumerable-keys": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/get-own-enumerable-keys/-/get-own-enumerable-keys-1.0.0.tgz",
- "integrity": "sha512-PKsK2FSrQCyxcGHsGrLDcK0lx+0Ke+6e8KFFozA9/fIQLhQzPaRvJFdcz7+Axg3jUH/Mq+NI4xa5u/UT2tQskA==",
- "license": "MIT",
- "engines": {
- "node": ">=14.16"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/get-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"dunder-proto": "^1.0.1",
@@ -5395,22 +5136,6 @@
"node": ">= 0.4"
}
},
- "node_modules/get-stream": {
- "version": "9.0.1",
- "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz",
- "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==",
- "license": "MIT",
- "dependencies": {
- "@sec-ant/readable-stream": "^0.4.1",
- "is-stream": "^4.0.1"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/get-symbol-description": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz",
@@ -5489,6 +5214,7 @@
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
@@ -5497,17 +5223,14 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/graceful-fs": {
- "version": "4.2.11",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
- "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
- "license": "ISC"
- },
"node_modules/graphql": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/graphql/-/graphql-16.13.1.tgz",
"integrity": "sha512-gGgrVCoDKlIZ8fIqXBBb0pPKqDgki0Z/FSKNiQzSGj2uEYHr1tq5wmBegGwJx6QB5S5cM0khSBpi/JFHMCvsmQ==",
+ "dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"engines": {
"node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0"
}
@@ -5568,6 +5291,7 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
@@ -5596,6 +5320,7 @@
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"function-bind": "^1.1.2"
@@ -5608,7 +5333,10 @@
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/headers-polyfill/-/headers-polyfill-4.0.3.tgz",
"integrity": "sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ==",
- "license": "MIT"
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "peer": true
},
"node_modules/hermes-estree": {
"version": "0.25.1",
@@ -5627,40 +5355,38 @@
"hermes-estree": "0.25.1"
}
},
- "node_modules/hono": {
- "version": "4.12.7",
- "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.7.tgz",
- "integrity": "sha512-jq9l1DM0zVIvsm3lv9Nw9nlJnMNPOcAtsbsgiUhWcFzPE99Gvo6yRTlszSLLYacMeQ6quHD6hMfId8crVHvexw==",
- "license": "MIT",
- "peer": true,
- "engines": {
- "node": ">=16.9.0"
- }
- },
- "node_modules/http-errors": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz",
- "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==",
+ "node_modules/html-encoding-sniffer": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz",
+ "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "depd": "~2.0.0",
- "inherits": "~2.0.4",
- "setprototypeof": "~1.2.0",
- "statuses": "~2.0.2",
- "toidentifier": "~1.0.1"
+ "whatwg-encoding": "^3.1.1"
},
"engines": {
- "node": ">= 0.8"
+ "node": ">=18"
+ }
+ },
+ "node_modules/http-proxy-agent": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
+ "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "^7.1.0",
+ "debug": "^4.3.4"
},
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
+ "engines": {
+ "node": ">= 14"
}
},
"node_modules/https-proxy-agent": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
"integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"agent-base": "^7.1.2",
@@ -5670,35 +5396,11 @@
"node": ">= 14"
}
},
- "node_modules/human-signals": {
- "version": "8.0.1",
- "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-8.0.1.tgz",
- "integrity": "sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==",
- "license": "Apache-2.0",
- "engines": {
- "node": ">=18.18.0"
- }
- },
- "node_modules/iconv-lite": {
- "version": "0.7.2",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz",
- "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==",
- "license": "MIT",
- "dependencies": {
- "safer-buffer": ">= 2.1.2 < 3.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
- }
- },
"node_modules/ignore": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
"integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">= 4"
@@ -5708,6 +5410,7 @@
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
"integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"parent-module": "^1.0.0",
@@ -5730,12 +5433,6 @@
"node": ">=0.8.19"
}
},
- "node_modules/inherits": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
- "license": "ISC"
- },
"node_modules/internal-slot": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz",
@@ -5751,24 +5448,6 @@
"node": ">= 0.4"
}
},
- "node_modules/ip-address": {
- "version": "10.1.0",
- "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz",
- "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==",
- "license": "MIT",
- "engines": {
- "node": ">= 12"
- }
- },
- "node_modules/ipaddr.js": {
- "version": "1.9.1",
- "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
- "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.10"
- }
- },
"node_modules/is-array-buffer": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz",
@@ -5787,12 +5466,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/is-arrayish": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
- "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
- "license": "MIT"
- },
"node_modules/is-async-function": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz",
@@ -5933,25 +5606,11 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/is-docker": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz",
- "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==",
- "license": "MIT",
- "bin": {
- "is-docker": "cli.js"
- },
- "engines": {
- "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
@@ -5977,7 +5636,10 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"engines": {
"node": ">=8"
}
@@ -6006,6 +5668,7 @@
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"is-extglob": "^2.1.1"
@@ -6014,48 +5677,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/is-in-ssh": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-in-ssh/-/is-in-ssh-1.0.0.tgz",
- "integrity": "sha512-jYa6Q9rH90kR1vKB6NM7qqd1mge3Fx4Dhw5TVlK1MUBqhEOuCagrEHMevNuCcbECmXZ0ThXkRm+Ymr51HwEPAw==",
- "license": "MIT",
- "engines": {
- "node": ">=20"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/is-inside-container": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz",
- "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==",
- "license": "MIT",
- "dependencies": {
- "is-docker": "^3.0.0"
- },
- "bin": {
- "is-inside-container": "cli.js"
- },
- "engines": {
- "node": ">=14.16"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/is-interactive": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz",
- "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==",
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/is-map": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz",
@@ -6086,12 +5707,16 @@
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/is-node-process/-/is-node-process-1.2.0.tgz",
"integrity": "sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==",
- "license": "MIT"
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "peer": true
},
"node_modules/is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">=0.12.0"
@@ -6114,34 +5739,11 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/is-obj": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-3.0.0.tgz",
- "integrity": "sha512-IlsXEHOjtKhpN8r/tRFj2nDyTmHvcfNeu/nrRIcXE17ROeatXchkojffa1SpdqW4cr/Fj6QkEf/Gn4zf6KKvEQ==",
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/is-plain-obj": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz",
- "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==",
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/is-promise": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz",
- "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==",
+ "node_modules/is-potential-custom-element-name": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz",
+ "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==",
+ "dev": true,
"license": "MIT"
},
"node_modules/is-regex": {
@@ -6163,18 +5765,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/is-regexp": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-3.1.0.tgz",
- "integrity": "sha512-rbku49cWloU5bSMI+zaRaXdQHXnthP6DZ/vLnfdSKyL4zUzuWnomtOEiZZOd+ioQ+avFo/qau3KPTc7Fjy1uPA==",
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/is-set": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz",
@@ -6204,18 +5794,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/is-stream": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz",
- "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==",
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/is-string": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz",
@@ -6267,18 +5845,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/is-unicode-supported": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz",
- "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==",
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/is-weakmap": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz",
@@ -6325,21 +5891,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/is-wsl": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.1.tgz",
- "integrity": "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==",
- "license": "MIT",
- "dependencies": {
- "is-inside-container": "^1.0.0"
- },
- "engines": {
- "node": ">=16"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/isarray": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
@@ -6351,6 +5902,7 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true,
"license": "ISC"
},
"node_modules/iterator.prototype": {
@@ -6377,29 +5929,24 @@
"integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==",
"dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"bin": {
"jiti": "lib/jiti-cli.mjs"
}
},
- "node_modules/jose": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/jose/-/jose-6.2.1.tgz",
- "integrity": "sha512-jUaKr1yrbfaImV7R2TN/b3IcZzsw38/chqMpo2XJ7i2F8AfM/lA4G1goC3JVEwg0H7UldTmSt3P68nt31W7/mw==",
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/panva"
- }
- },
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "dev": true,
"license": "MIT"
},
"node_modules/js-yaml": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
"integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"argparse": "^2.0.1"
@@ -6408,10 +5955,64 @@
"js-yaml": "bin/js-yaml.js"
}
},
+ "node_modules/jsdom": {
+ "version": "27.0.1",
+ "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-27.0.1.tgz",
+ "integrity": "sha512-SNSQteBL1IlV2zqhwwolaG9CwhIhTvVHWg3kTss/cLE7H/X4644mtPQqYvCfsSrGQWt9hSZcgOXX8bOZaMN+kA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@asamuzakjp/dom-selector": "^6.7.2",
+ "cssstyle": "^5.3.1",
+ "data-urls": "^6.0.0",
+ "decimal.js": "^10.6.0",
+ "html-encoding-sniffer": "^4.0.0",
+ "http-proxy-agent": "^7.0.2",
+ "https-proxy-agent": "^7.0.6",
+ "is-potential-custom-element-name": "^1.0.1",
+ "parse5": "^8.0.0",
+ "rrweb-cssom": "^0.8.0",
+ "saxes": "^6.0.0",
+ "symbol-tree": "^3.2.4",
+ "tough-cookie": "^6.0.0",
+ "w3c-xmlserializer": "^5.0.0",
+ "webidl-conversions": "^8.0.0",
+ "whatwg-encoding": "^3.1.1",
+ "whatwg-mimetype": "^4.0.0",
+ "whatwg-url": "^15.1.0",
+ "ws": "^8.18.3",
+ "xml-name-validator": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=20"
+ },
+ "peerDependencies": {
+ "canvas": "^3.0.0"
+ },
+ "peerDependenciesMeta": {
+ "canvas": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jsdom/node_modules/parse5": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.0.tgz",
+ "integrity": "sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "entities": "^6.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/inikulin/parse5?sponsor=1"
+ }
+ },
"node_modules/jsesc": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
"integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
+ "dev": true,
"license": "MIT",
"bin": {
"jsesc": "bin/jsesc"
@@ -6427,12 +6028,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/json-parse-even-better-errors": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
- "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
- "license": "MIT"
- },
"node_modules/json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
@@ -6440,12 +6035,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/json-schema-typed": {
- "version": "8.0.2",
- "resolved": "https://registry.npmjs.org/json-schema-typed/-/json-schema-typed-8.0.2.tgz",
- "integrity": "sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==",
- "license": "BSD-2-Clause"
- },
"node_modules/json-stable-stringify-without-jsonify": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
@@ -6457,6 +6046,7 @@
"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"
@@ -6465,18 +6055,6 @@
"node": ">=6"
}
},
- "node_modules/jsonfile": {
- "version": "6.2.0",
- "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz",
- "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==",
- "license": "MIT",
- "dependencies": {
- "universalify": "^2.0.0"
- },
- "optionalDependencies": {
- "graceful-fs": "^4.1.6"
- }
- },
"node_modules/jsx-ast-utils": {
"version": "3.3.5",
"resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz",
@@ -6503,15 +6081,6 @@
"json-buffer": "3.0.1"
}
},
- "node_modules/kleur": {
- "version": "4.1.5",
- "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
- "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/language-subtag-registry": {
"version": "0.3.23",
"resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz",
@@ -6552,6 +6121,8 @@
"integrity": "sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ==",
"dev": true,
"license": "MPL-2.0",
+ "optional": true,
+ "peer": true,
"dependencies": {
"detect-libc": "^2.0.3"
},
@@ -6589,6 +6160,7 @@
"os": [
"android"
],
+ "peer": true,
"engines": {
"node": ">= 12.0.0"
},
@@ -6610,6 +6182,7 @@
"os": [
"darwin"
],
+ "peer": true,
"engines": {
"node": ">= 12.0.0"
},
@@ -6631,6 +6204,7 @@
"os": [
"darwin"
],
+ "peer": true,
"engines": {
"node": ">= 12.0.0"
},
@@ -6652,6 +6226,7 @@
"os": [
"freebsd"
],
+ "peer": true,
"engines": {
"node": ">= 12.0.0"
},
@@ -6673,6 +6248,7 @@
"os": [
"linux"
],
+ "peer": true,
"engines": {
"node": ">= 12.0.0"
},
@@ -6694,6 +6270,7 @@
"os": [
"linux"
],
+ "peer": true,
"engines": {
"node": ">= 12.0.0"
},
@@ -6715,6 +6292,7 @@
"os": [
"linux"
],
+ "peer": true,
"engines": {
"node": ">= 12.0.0"
},
@@ -6736,6 +6314,7 @@
"os": [
"linux"
],
+ "peer": true,
"engines": {
"node": ">= 12.0.0"
},
@@ -6757,6 +6336,7 @@
"os": [
"linux"
],
+ "peer": true,
"engines": {
"node": ">= 12.0.0"
},
@@ -6778,6 +6358,7 @@
"os": [
"win32"
],
+ "peer": true,
"engines": {
"node": ">= 12.0.0"
},
@@ -6799,6 +6380,7 @@
"os": [
"win32"
],
+ "peer": true,
"engines": {
"node": ">= 12.0.0"
},
@@ -6807,12 +6389,6 @@
"url": "https://opencollective.com/parcel"
}
},
- "node_modules/lines-and-columns": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
- "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
- "license": "MIT"
- },
"node_modules/locate-path": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
@@ -6836,46 +6412,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/log-symbols": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz",
- "integrity": "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==",
- "license": "MIT",
- "dependencies": {
- "chalk": "^5.3.0",
- "is-unicode-supported": "^1.3.0"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/log-symbols/node_modules/chalk": {
- "version": "5.6.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz",
- "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==",
- "license": "MIT",
- "engines": {
- "node": "^12.17.0 || ^14.13 || >=16.0.0"
- },
- "funding": {
- "url": "https://github.com/chalk/chalk?sponsor=1"
- }
- },
- "node_modules/log-symbols/node_modules/is-unicode-supported": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz",
- "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==",
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/loose-envify": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
@@ -6889,24 +6425,23 @@
"loose-envify": "cli.js"
}
},
+ "node_modules/loupe": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz",
+ "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/lru-cache": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
"integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "dev": true,
"license": "ISC",
"dependencies": {
"yallist": "^3.0.2"
}
},
- "node_modules/lucide-react": {
- "version": "0.577.0",
- "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.577.0.tgz",
- "integrity": "sha512-4LjoFv2eEPwYDPg/CUdBJQSDfPyzXCRrVW1X7jrx/trgxnxkHFjnVZINbzvzxjN70dxychOfg+FTYwBiS3pQ5A==",
- "license": "ISC",
- "peerDependencies": {
- "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
- }
- },
"node_modules/magic-string": {
"version": "0.30.21",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
@@ -6921,42 +6456,24 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
- "node_modules/media-typer": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz",
- "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/merge-descriptors": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz",
- "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==",
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/merge-stream": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
- "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
- "license": "MIT"
+ "node_modules/mdn-data": {
+ "version": "2.27.1",
+ "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz",
+ "integrity": "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==",
+ "dev": true,
+ "license": "CC0-1.0"
},
"node_modules/merge2": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
"integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">= 8"
@@ -6966,6 +6483,7 @@
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"braces": "^3.0.3",
@@ -6975,52 +6493,6 @@
"node": ">=8.6"
}
},
- "node_modules/mime-db": {
- "version": "1.54.0",
- "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
- "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/mime-types": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz",
- "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==",
- "license": "MIT",
- "dependencies": {
- "mime-db": "^1.54.0"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
- }
- },
- "node_modules/mimic-fn": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
- "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/mimic-function": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz",
- "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==",
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/minimatch": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
@@ -7038,6 +6510,7 @@
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
+ "dev": true,
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -7047,14 +6520,18 @@
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true,
"license": "MIT"
},
"node_modules/msw": {
"version": "2.12.10",
"resolved": "https://registry.npmjs.org/msw/-/msw-2.12.10.tgz",
"integrity": "sha512-G3VUymSE0/iegFnuipujpwyTM2GuZAKXNeerUSrG2+Eg391wW63xFs5ixWsK9MWzr1AGoSkYGmyAzNgbR3+urw==",
+ "dev": true,
"hasInstallScript": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"dependencies": {
"@inquirer/confirm": "^5.0.0",
"@mswjs/interceptors": "^0.41.2",
@@ -7097,7 +6574,10 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz",
"integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==",
+ "dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"engines": {
"node": ">=18"
},
@@ -7110,7 +6590,10 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz",
"integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==",
+ "dev": true,
"license": "ISC",
+ "optional": true,
+ "peer": true,
"engines": {
"node": "^18.17.0 || >=20.5.0"
}
@@ -7156,15 +6639,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/negotiator": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz",
- "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
"node_modules/next": {
"version": "16.1.6",
"resolved": "https://registry.npmjs.org/next/-/next-16.1.6.tgz",
@@ -7246,26 +6720,6 @@
"node": "^10 || ^12 || >=14"
}
},
- "node_modules/node-domexception": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
- "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
- "deprecated": "Use your platform's native DOMException instead",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/jimmywarting"
- },
- {
- "type": "github",
- "url": "https://paypal.me/jimmywarting"
- }
- ],
- "license": "MIT",
- "engines": {
- "node": ">=10.5.0"
- }
- },
"node_modules/node-exports-info": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/node-exports-info/-/node-exports-info-1.6.0.tgz",
@@ -7285,62 +6739,18 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/node-fetch": {
- "version": "3.3.2",
- "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
- "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
- "license": "MIT",
- "dependencies": {
- "data-uri-to-buffer": "^4.0.0",
- "fetch-blob": "^3.1.4",
- "formdata-polyfill": "^4.0.10"
- },
- "engines": {
- "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/node-fetch"
- }
- },
"node_modules/node-releases": {
"version": "2.0.36",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz",
"integrity": "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==",
+ "dev": true,
"license": "MIT"
},
- "node_modules/npm-run-path": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz",
- "integrity": "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==",
- "license": "MIT",
- "dependencies": {
- "path-key": "^4.0.0",
- "unicorn-magic": "^0.3.0"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/npm-run-path/node_modules/path-key": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz",
- "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==",
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
@@ -7350,6 +6760,7 @@
"version": "1.13.4",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
"integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
@@ -7368,15 +6779,6 @@
"node": ">= 0.4"
}
},
- "node_modules/object-treeify": {
- "version": "1.1.33",
- "resolved": "https://registry.npmjs.org/object-treeify/-/object-treeify-1.1.33.tgz",
- "integrity": "sha512-EFVjAYfzWqWsBMRHPMAXLCDIJnpMhdWAqR7xG6M6a2cs6PMFpl/+Z20w9zDW4vkxOFfddegBKq9Rehd0bxWE7A==",
- "license": "MIT",
- "engines": {
- "node": ">= 10"
- }
- },
"node_modules/object.assign": {
"version": "4.1.7",
"resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz",
@@ -7467,62 +6869,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/on-finished": {
- "version": "2.4.1",
- "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
- "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
- "license": "MIT",
- "dependencies": {
- "ee-first": "1.1.1"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/once": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
- "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
- "license": "ISC",
- "dependencies": {
- "wrappy": "1"
- }
- },
- "node_modules/onetime": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz",
- "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==",
- "license": "MIT",
- "dependencies": {
- "mimic-function": "^5.0.0"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/open": {
- "version": "11.0.0",
- "resolved": "https://registry.npmjs.org/open/-/open-11.0.0.tgz",
- "integrity": "sha512-smsWv2LzFjP03xmvFoJ331ss6h+jixfA4UUV/Bsiyuu4YJPfN+FIQGOIiv4w9/+MoHkfkJ22UIaQWRVFRfH6Vw==",
- "license": "MIT",
- "dependencies": {
- "default-browser": "^5.4.0",
- "define-lazy-prop": "^3.0.0",
- "is-in-ssh": "^1.0.0",
- "is-inside-container": "^1.0.0",
- "powershell-utils": "^0.1.0",
- "wsl-utils": "^0.3.0"
- },
- "engines": {
- "node": ">=20"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/optionator": {
"version": "0.9.4",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
@@ -7541,46 +6887,14 @@
"node": ">= 0.8.0"
}
},
- "node_modules/ora": {
- "version": "8.2.0",
- "resolved": "https://registry.npmjs.org/ora/-/ora-8.2.0.tgz",
- "integrity": "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==",
- "license": "MIT",
- "dependencies": {
- "chalk": "^5.3.0",
- "cli-cursor": "^5.0.0",
- "cli-spinners": "^2.9.2",
- "is-interactive": "^2.0.0",
- "is-unicode-supported": "^2.0.0",
- "log-symbols": "^6.0.0",
- "stdin-discarder": "^0.2.2",
- "string-width": "^7.2.0",
- "strip-ansi": "^7.1.0"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/ora/node_modules/chalk": {
- "version": "5.6.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz",
- "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==",
- "license": "MIT",
- "engines": {
- "node": "^12.17.0 || ^14.13 || >=16.0.0"
- },
- "funding": {
- "url": "https://github.com/chalk/chalk?sponsor=1"
- }
- },
"node_modules/outvariant": {
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/outvariant/-/outvariant-1.4.3.tgz",
"integrity": "sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==",
- "license": "MIT"
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "peer": true
},
"node_modules/own-keys": {
"version": "1.0.1",
@@ -7632,16 +6946,11 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/package-manager-detector": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.6.0.tgz",
- "integrity": "sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==",
- "license": "MIT"
- },
"node_modules/parent-module": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
"integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"callsites": "^3.0.0"
@@ -7650,51 +6959,19 @@
"node": ">=6"
}
},
- "node_modules/parse-json": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
- "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
+ "node_modules/parse5": {
+ "version": "7.3.0",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz",
+ "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "@babel/code-frame": "^7.0.0",
- "error-ex": "^1.3.1",
- "json-parse-even-better-errors": "^2.3.0",
- "lines-and-columns": "^1.1.6"
- },
- "engines": {
- "node": ">=8"
+ "entities": "^6.0.0"
},
"funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "url": "https://github.com/inikulin/parse5?sponsor=1"
}
},
- "node_modules/parse-ms": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz",
- "integrity": "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==",
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/parseurl": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
- "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/path-browserify": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz",
- "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==",
- "license": "MIT"
- },
"node_modules/path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
@@ -7709,6 +6986,7 @@
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@@ -7725,8 +7003,28 @@
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz",
"integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "peer": true
+ },
+ "node_modules/pathe": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
+ "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
+ "dev": true,
"license": "MIT"
},
+ "node_modules/pathval": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz",
+ "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14.16"
+ }
+ },
"node_modules/pg-int8": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz",
@@ -7768,6 +7066,7 @@
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">=8.6"
@@ -7776,15 +7075,6 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
- "node_modules/pkce-challenge": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.1.tgz",
- "integrity": "sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==",
- "license": "MIT",
- "engines": {
- "node": ">=16.20.0"
- }
- },
"node_modules/possible-typed-array-names": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
@@ -7799,6 +7089,7 @@
"version": "8.5.8",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz",
"integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==",
+ "dev": true,
"funding": [
{
"type": "opencollective",
@@ -7823,19 +7114,6 @@
"node": "^10 || ^12 || >=14"
}
},
- "node_modules/postcss-selector-parser": {
- "version": "7.1.1",
- "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz",
- "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==",
- "license": "MIT",
- "dependencies": {
- "cssesc": "^3.0.0",
- "util-deprecate": "^1.0.2"
- },
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/postgres-array": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz",
@@ -7875,18 +7153,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/powershell-utils": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/powershell-utils/-/powershell-utils-0.1.0.tgz",
- "integrity": "sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A==",
- "license": "MIT",
- "engines": {
- "node": ">=20"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/prelude-ls": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
@@ -7897,43 +7163,6 @@
"node": ">= 0.8.0"
}
},
- "node_modules/pretty-ms": {
- "version": "9.3.0",
- "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.3.0.tgz",
- "integrity": "sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==",
- "license": "MIT",
- "dependencies": {
- "parse-ms": "^4.0.0"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/prompts": {
- "version": "2.4.2",
- "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
- "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==",
- "license": "MIT",
- "dependencies": {
- "kleur": "^3.0.3",
- "sisteransi": "^1.0.5"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/prompts/node_modules/kleur": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
- "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/prop-types": {
"version": "15.8.1",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
@@ -7946,19 +7175,6 @@
"react-is": "^16.13.1"
}
},
- "node_modules/proxy-addr": {
- "version": "2.0.7",
- "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
- "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
- "license": "MIT",
- "dependencies": {
- "forwarded": "0.2.0",
- "ipaddr.js": "1.9.1"
- },
- "engines": {
- "node": ">= 0.10"
- }
- },
"node_modules/punycode": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
@@ -7969,25 +7185,11 @@
"node": ">=6"
}
},
- "node_modules/qs": {
- "version": "6.15.0",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz",
- "integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==",
- "license": "BSD-3-Clause",
- "dependencies": {
- "side-channel": "^1.1.0"
- },
- "engines": {
- "node": ">=0.6"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/queue-microtask": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
"integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "dev": true,
"funding": [
{
"type": "github",
@@ -8004,36 +7206,11 @@
],
"license": "MIT"
},
- "node_modules/range-parser": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
- "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/raw-body": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz",
- "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==",
- "license": "MIT",
- "dependencies": {
- "bytes": "~3.1.2",
- "http-errors": "~2.0.1",
- "iconv-lite": "~0.7.0",
- "unpipe": "~1.0.0"
- },
- "engines": {
- "node": ">= 0.10"
- }
- },
"node_modules/react": {
"version": "19.2.3",
"resolved": "https://registry.npmjs.org/react/-/react-19.2.3.tgz",
"integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==",
"license": "MIT",
- "peer": true,
"engines": {
"node": ">=0.10.0"
}
@@ -8043,7 +7220,6 @@
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.3.tgz",
"integrity": "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==",
"license": "MIT",
- "peer": true,
"dependencies": {
"scheduler": "^0.27.0"
},
@@ -8058,22 +7234,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/recast": {
- "version": "0.23.11",
- "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.11.tgz",
- "integrity": "sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==",
- "license": "MIT",
- "dependencies": {
- "ast-types": "^0.16.1",
- "esprima": "~4.0.0",
- "source-map": "~0.6.1",
- "tiny-invariant": "^1.3.3",
- "tslib": "^2.0.1"
- },
- "engines": {
- "node": ">= 4"
- }
- },
"node_modules/reflect.getprototypeof": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
@@ -8122,7 +7282,10 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+ "dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"engines": {
"node": ">=0.10.0"
}
@@ -8131,17 +7294,12 @@
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
- "node_modules/reselect": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz",
- "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==",
- "license": "MIT"
- },
"node_modules/resolve": {
"version": "1.22.11",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz",
@@ -8167,6 +7325,7 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">=4"
@@ -8182,80 +7341,83 @@
"url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
}
},
- "node_modules/restore-cursor": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz",
- "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==",
- "license": "MIT",
- "dependencies": {
- "onetime": "^7.0.0",
- "signal-exit": "^4.1.0"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/rettime": {
"version": "0.10.1",
"resolved": "https://registry.npmjs.org/rettime/-/rettime-0.10.1.tgz",
"integrity": "sha512-uyDrIlUEH37cinabq0AX4QbgV4HbFZ/gqoiunWQ1UqBtRvTTytwhNYjE++pO/MjPTZL5KQCf2bEoJ/BJNVQ5Kw==",
- "license": "MIT"
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "peer": true
},
"node_modules/reusify": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
"integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==",
+ "dev": true,
"license": "MIT",
"engines": {
"iojs": ">=1.0.0",
"node": ">=0.10.0"
}
},
- "node_modules/router": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz",
- "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==",
+ "node_modules/rollup": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz",
+ "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "debug": "^4.4.0",
- "depd": "^2.0.0",
- "is-promise": "^4.0.0",
- "parseurl": "^1.3.3",
- "path-to-regexp": "^8.0.0"
+ "@types/estree": "1.0.8"
+ },
+ "bin": {
+ "rollup": "dist/bin/rollup"
},
"engines": {
- "node": ">= 18"
- }
- },
- "node_modules/router/node_modules/path-to-regexp": {
- "version": "8.3.0",
- "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz",
- "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==",
- "license": "MIT",
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
- }
- },
- "node_modules/run-applescript": {
- "version": "7.1.0",
- "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz",
- "integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==",
- "license": "MIT",
- "engines": {
- "node": ">=18"
+ "node": ">=18.0.0",
+ "npm": ">=8.0.0"
},
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "optionalDependencies": {
+ "@rollup/rollup-android-arm-eabi": "4.59.0",
+ "@rollup/rollup-android-arm64": "4.59.0",
+ "@rollup/rollup-darwin-arm64": "4.59.0",
+ "@rollup/rollup-darwin-x64": "4.59.0",
+ "@rollup/rollup-freebsd-arm64": "4.59.0",
+ "@rollup/rollup-freebsd-x64": "4.59.0",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.59.0",
+ "@rollup/rollup-linux-arm-musleabihf": "4.59.0",
+ "@rollup/rollup-linux-arm64-gnu": "4.59.0",
+ "@rollup/rollup-linux-arm64-musl": "4.59.0",
+ "@rollup/rollup-linux-loong64-gnu": "4.59.0",
+ "@rollup/rollup-linux-loong64-musl": "4.59.0",
+ "@rollup/rollup-linux-ppc64-gnu": "4.59.0",
+ "@rollup/rollup-linux-ppc64-musl": "4.59.0",
+ "@rollup/rollup-linux-riscv64-gnu": "4.59.0",
+ "@rollup/rollup-linux-riscv64-musl": "4.59.0",
+ "@rollup/rollup-linux-s390x-gnu": "4.59.0",
+ "@rollup/rollup-linux-x64-gnu": "4.59.0",
+ "@rollup/rollup-linux-x64-musl": "4.59.0",
+ "@rollup/rollup-openbsd-x64": "4.59.0",
+ "@rollup/rollup-openharmony-arm64": "4.59.0",
+ "@rollup/rollup-win32-arm64-msvc": "4.59.0",
+ "@rollup/rollup-win32-ia32-msvc": "4.59.0",
+ "@rollup/rollup-win32-x64-gnu": "4.59.0",
+ "@rollup/rollup-win32-x64-msvc": "4.59.0",
+ "fsevents": "~2.3.2"
}
},
+ "node_modules/rrweb-cssom": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz",
+ "integrity": "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/run-parallel": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
"integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "dev": true,
"funding": [
{
"type": "github",
@@ -8334,8 +7496,22 @@
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "dev": true,
"license": "MIT"
},
+ "node_modules/saxes": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz",
+ "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "xmlchars": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=v12.22.7"
+ }
+ },
"node_modules/scheduler": {
"version": "0.27.0",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
@@ -8346,56 +7522,12 @@
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
}
},
- "node_modules/send": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz",
- "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==",
- "license": "MIT",
- "dependencies": {
- "debug": "^4.4.3",
- "encodeurl": "^2.0.0",
- "escape-html": "^1.0.3",
- "etag": "^1.8.1",
- "fresh": "^2.0.0",
- "http-errors": "^2.0.1",
- "mime-types": "^3.0.2",
- "ms": "^2.1.3",
- "on-finished": "^2.4.1",
- "range-parser": "^1.2.1",
- "statuses": "^2.0.2"
- },
- "engines": {
- "node": ">= 18"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
- }
- },
- "node_modules/serve-static": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz",
- "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==",
- "license": "MIT",
- "dependencies": {
- "encodeurl": "^2.0.0",
- "escape-html": "^1.0.3",
- "parseurl": "^1.3.3",
- "send": "^1.2.0"
- },
- "engines": {
- "node": ">= 18"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
- }
- },
"node_modules/set-function-length": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
@@ -8445,109 +7577,6 @@
"node": ">= 0.4"
}
},
- "node_modules/setprototypeof": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
- "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
- "license": "ISC"
- },
- "node_modules/shadcn": {
- "version": "4.0.6",
- "resolved": "https://registry.npmjs.org/shadcn/-/shadcn-4.0.6.tgz",
- "integrity": "sha512-20M3ZsQPas+0QLVzrfrya2V3nryQiIPQsnJaOJg+Ylk24GtJa1vXGOLB7xwKuvWoMzM0YSLuCaoibW/NuHdDyA==",
- "license": "MIT",
- "dependencies": {
- "@antfu/ni": "^25.0.0",
- "@babel/core": "^7.28.0",
- "@babel/parser": "^7.28.0",
- "@babel/plugin-transform-typescript": "^7.28.0",
- "@babel/preset-typescript": "^7.27.1",
- "@dotenvx/dotenvx": "^1.48.4",
- "@modelcontextprotocol/sdk": "^1.26.0",
- "@types/validate-npm-package-name": "^4.0.2",
- "browserslist": "^4.26.2",
- "commander": "^14.0.0",
- "cosmiconfig": "^9.0.0",
- "dedent": "^1.6.0",
- "deepmerge": "^4.3.1",
- "diff": "^8.0.2",
- "execa": "^9.6.0",
- "fast-glob": "^3.3.3",
- "fs-extra": "^11.3.1",
- "fuzzysort": "^3.1.0",
- "https-proxy-agent": "^7.0.6",
- "kleur": "^4.1.5",
- "msw": "^2.10.4",
- "node-fetch": "^3.3.2",
- "open": "^11.0.0",
- "ora": "^8.2.0",
- "postcss": "^8.5.6",
- "postcss-selector-parser": "^7.1.0",
- "prompts": "^2.4.2",
- "recast": "^0.23.11",
- "stringify-object": "^5.0.0",
- "tailwind-merge": "^3.0.1",
- "ts-morph": "^26.0.0",
- "tsconfig-paths": "^4.2.0",
- "validate-npm-package-name": "^7.0.1",
- "zod": "^3.24.1",
- "zod-to-json-schema": "^3.24.6"
- },
- "bin": {
- "shadcn": "dist/index.js"
- }
- },
- "node_modules/shadcn/node_modules/fast-glob": {
- "version": "3.3.3",
- "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
- "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
- "license": "MIT",
- "dependencies": {
- "@nodelib/fs.stat": "^2.0.2",
- "@nodelib/fs.walk": "^1.2.3",
- "glob-parent": "^5.1.2",
- "merge2": "^1.3.0",
- "micromatch": "^4.0.8"
- },
- "engines": {
- "node": ">=8.6.0"
- }
- },
- "node_modules/shadcn/node_modules/glob-parent": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
- "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
- "license": "ISC",
- "dependencies": {
- "is-glob": "^4.0.1"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/shadcn/node_modules/tsconfig-paths": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz",
- "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==",
- "license": "MIT",
- "dependencies": {
- "json5": "^2.2.2",
- "minimist": "^1.2.6",
- "strip-bom": "^3.0.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/shadcn/node_modules/zod": {
- "version": "3.25.76",
- "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
- "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/colinhacks"
- }
- },
"node_modules/sharp": {
"version": "0.34.5",
"resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz",
@@ -8610,6 +7639,7 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"shebang-regex": "^3.0.0"
@@ -8622,6 +7652,7 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@@ -8631,6 +7662,7 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
"integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
@@ -8650,6 +7682,7 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
"integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
@@ -8666,6 +7699,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
"integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
@@ -8684,6 +7718,7 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
"integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
@@ -8699,11 +7734,21 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/siginfo": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz",
+ "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==",
+ "dev": true,
+ "license": "ISC"
+ },
"node_modules/signal-exit": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
"integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+ "dev": true,
"license": "ISC",
+ "optional": true,
+ "peer": true,
"engines": {
"node": ">=14"
},
@@ -8711,21 +7756,6 @@
"url": "https://github.com/sponsors/isaacs"
}
},
- "node_modules/sisteransi": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
- "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==",
- "license": "MIT"
- },
- "node_modules/source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/source-map-js": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
@@ -8742,26 +7772,31 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/stackback": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz",
+ "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/statuses": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
"integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==",
+ "dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"engines": {
"node": ">= 0.8"
}
},
- "node_modules/stdin-discarder": {
- "version": "0.2.2",
- "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz",
- "integrity": "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==",
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
+ "node_modules/std-env": {
+ "version": "3.10.0",
+ "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz",
+ "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/stop-iteration-iterator": {
"version": "1.1.0",
@@ -8781,30 +7816,10 @@
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz",
"integrity": "sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==",
- "license": "MIT"
- },
- "node_modules/string-width": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz",
- "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==",
+ "dev": true,
"license": "MIT",
- "dependencies": {
- "emoji-regex": "^10.3.0",
- "get-east-asian-width": "^1.0.0",
- "strip-ansi": "^7.1.0"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/string-width/node_modules/emoji-regex": {
- "version": "10.6.0",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz",
- "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==",
- "license": "MIT"
+ "optional": true,
+ "peer": true
},
"node_modules/string.prototype.includes": {
"version": "2.0.1",
@@ -8919,59 +7934,16 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/stringify-object": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-5.0.0.tgz",
- "integrity": "sha512-zaJYxz2FtcMb4f+g60KsRNFOpVMUyuJgA51Zi5Z1DOTC3S59+OQiVOzE9GZt0x72uBGWKsQIuBKeF9iusmKFsg==",
- "license": "BSD-2-Clause",
- "dependencies": {
- "get-own-enumerable-keys": "^1.0.0",
- "is-obj": "^3.0.0",
- "is-regexp": "^3.1.0"
- },
- "engines": {
- "node": ">=14.16"
- },
- "funding": {
- "url": "https://github.com/yeoman/stringify-object?sponsor=1"
- }
- },
- "node_modules/strip-ansi": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz",
- "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==",
- "license": "MIT",
- "dependencies": {
- "ansi-regex": "^6.2.2"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/strip-ansi?sponsor=1"
- }
- },
"node_modules/strip-bom": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
"integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">=4"
}
},
- "node_modules/strip-final-newline": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-4.0.0.tgz",
- "integrity": "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==",
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/strip-json-comments": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
@@ -8985,6 +7957,26 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/strip-literal": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-3.1.0.tgz",
+ "integrity": "sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "js-tokens": "^9.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
+ "node_modules/strip-literal/node_modules/js-tokens": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz",
+ "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/styled-jsx": {
"version": "5.1.6",
"resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz",
@@ -9034,17 +8026,21 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/tabbable": {
- "version": "6.4.0",
- "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.4.0.tgz",
- "integrity": "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==",
+ "node_modules/symbol-tree": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
+ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==",
+ "dev": true,
"license": "MIT"
},
"node_modules/tagged-tag": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/tagged-tag/-/tagged-tag-1.0.0.tgz",
"integrity": "sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==",
+ "dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"engines": {
"node": ">=20"
},
@@ -9052,52 +8048,13 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/tailwind-merge": {
- "version": "3.5.0",
- "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.5.0.tgz",
- "integrity": "sha512-I8K9wewnVDkL1NTGoqWmVEIlUcB9gFriAEkXkfCjX5ib8ezGxtR3xD7iZIxrfArjEsH7F1CHD4RFUtxefdqV/A==",
- "license": "MIT",
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/dcastil"
- }
- },
- "node_modules/tailwindcss": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.2.1.tgz",
- "integrity": "sha512-/tBrSQ36vCleJkAOsy9kbNTgaxvGbyOamC30PRePTQe/o1MFwEKHQk4Cn7BNGaPtjp+PuUrByJehM1hgxfq4sw==",
+ "node_modules/tinybench": {
+ "version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz",
+ "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==",
"dev": true,
"license": "MIT"
},
- "node_modules/tapable": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz",
- "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/webpack"
- }
- },
- "node_modules/tiny-invariant": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz",
- "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==",
- "license": "MIT"
- },
- "node_modules/tinyexec": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.4.tgz",
- "integrity": "sha512-u9r3uZC0bdpGOXtlxUIdwf9pkmvhqJdrVCH9fapQtgy/OeTTMZ1nqH7agtvEfmGui6e1XxjcdrlxvxJvc3sMqw==",
- "license": "MIT",
- "engines": {
- "node": ">=18"
- }
- },
"node_modules/tinyglobby": {
"version": "0.2.15",
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
@@ -9139,7 +8096,6 @@
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true,
"license": "MIT",
- "peer": true,
"engines": {
"node": ">=12"
},
@@ -9147,10 +8103,41 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
+ "node_modules/tinypool": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz",
+ "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.0.0 || >=20.0.0"
+ }
+ },
+ "node_modules/tinyrainbow": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz",
+ "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/tinyspy": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-4.0.4.tgz",
+ "integrity": "sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
"node_modules/tldts": {
"version": "7.0.25",
"resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.25.tgz",
"integrity": "sha512-keinCnPbwXEUG3ilrWQZU+CqcTTzHq9m2HhoUP2l7Xmi8l1LuijAXLpAJ5zRW+ifKTNscs4NdCkfkDCBYm352w==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"tldts-core": "^7.0.25"
@@ -9163,12 +8150,14 @@
"version": "7.0.25",
"resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.25.tgz",
"integrity": "sha512-ZjCZK0rppSBu7rjHYDYsEaMOIbbT+nWF57hKkv4IUmZWBNrBWBOjIElc0mKRgLM8bm7x/BBlof6t2gi/Oq/Asw==",
+ "dev": true,
"license": "MIT"
},
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"is-number": "^7.0.0"
@@ -9177,19 +8166,11 @@
"node": ">=8.0"
}
},
- "node_modules/toidentifier": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
- "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
- "license": "MIT",
- "engines": {
- "node": ">=0.6"
- }
- },
"node_modules/tough-cookie": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.1.tgz",
"integrity": "sha512-LktZQb3IeoUWB9lqR5EWTHgW/VTITCXg4D21M+lvybRVdylLrRMnqaIONLVb5mav8vM19m44HIcGq4qASeu2Qw==",
+ "dev": true,
"license": "BSD-3-Clause",
"dependencies": {
"tldts": "^7.0.5"
@@ -9198,6 +8179,19 @@
"node": ">=16"
}
},
+ "node_modules/tr46": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-6.0.0.tgz",
+ "integrity": "sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "punycode": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=20"
+ }
+ },
"node_modules/ts-api-utils": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz",
@@ -9211,16 +8205,6 @@
"typescript": ">=4.8.4"
}
},
- "node_modules/ts-morph": {
- "version": "26.0.0",
- "resolved": "https://registry.npmjs.org/ts-morph/-/ts-morph-26.0.0.tgz",
- "integrity": "sha512-ztMO++owQnz8c/gIENcM9XfCEzgoGphTv+nKpYNM1bgsdOVC/jRZuEBf6N+mLLDNg68Kl+GgUZfOySaRiG1/Ug==",
- "license": "MIT",
- "dependencies": {
- "@ts-morph/common": "~0.27.0",
- "code-block-writer": "^13.0.3"
- }
- },
"node_modules/tsconfig-paths": {
"version": "3.15.0",
"resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz",
@@ -9253,15 +8237,6 @@
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
"license": "0BSD"
},
- "node_modules/tw-animate-css": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/tw-animate-css/-/tw-animate-css-1.4.0.tgz",
- "integrity": "sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ==",
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/Wombosvideo"
- }
- },
"node_modules/type-check": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
@@ -9279,7 +8254,10 @@
"version": "5.4.4",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.4.4.tgz",
"integrity": "sha512-JnTrzGu+zPV3aXIUhnyWJj4z/wigMsdYajGLIYakqyOW1nPllzXEJee0QQbHj+CTIQtXGlAjuK0UY+2xTyjVAw==",
+ "dev": true,
"license": "(MIT OR CC0-1.0)",
+ "optional": true,
+ "peer": true,
"dependencies": {
"tagged-tag": "^1.0.0"
},
@@ -9290,20 +8268,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/type-is": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz",
- "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==",
- "license": "MIT",
- "dependencies": {
- "content-type": "^1.0.5",
- "media-typer": "^1.1.0",
- "mime-types": "^3.0.0"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
"node_modules/typed-array-buffer": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz",
@@ -9386,9 +8350,8 @@
"version": "5.9.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
- "devOptional": true,
+ "dev": true,
"license": "Apache-2.0",
- "peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -9446,36 +8409,6 @@
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
"license": "MIT"
},
- "node_modules/unicorn-magic": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz",
- "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==",
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/universalify": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
- "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
- "license": "MIT",
- "engines": {
- "node": ">= 10.0.0"
- }
- },
- "node_modules/unpipe": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
- "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
"node_modules/unrs-resolver": {
"version": "1.11.1",
"resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz",
@@ -9515,7 +8448,10 @@
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/until-async/-/until-async-3.0.2.tgz",
"integrity": "sha512-IiSk4HlzAMqTUseHHe3VhIGyuFmN90zMTpD3Z3y8jeQbzLIq500MVM7Jq2vUAnTKAFPJrqwkzr6PoTcPhGcOiw==",
+ "dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"funding": {
"url": "https://github.com/sponsors/kettanaito"
}
@@ -9524,6 +8460,7 @@
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz",
"integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==",
+ "dev": true,
"funding": [
{
"type": "opencollective",
@@ -9560,52 +8497,307 @@
"punycode": "^2.1.0"
}
},
- "node_modules/use-sync-external-store": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz",
- "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==",
+ "node_modules/vite": {
+ "version": "7.3.1",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz",
+ "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==",
+ "dev": true,
"license": "MIT",
+ "dependencies": {
+ "esbuild": "^0.27.0",
+ "fdir": "^6.5.0",
+ "picomatch": "^4.0.3",
+ "postcss": "^8.5.6",
+ "rollup": "^4.43.0",
+ "tinyglobby": "^0.2.15"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ },
+ "funding": {
+ "url": "https://github.com/vitejs/vite?sponsor=1"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ },
"peerDependencies": {
- "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ "@types/node": "^20.19.0 || >=22.12.0",
+ "jiti": ">=1.21.0",
+ "less": "^4.0.0",
+ "lightningcss": "^1.21.0",
+ "sass": "^1.70.0",
+ "sass-embedded": "^1.70.0",
+ "stylus": ">=0.54.8",
+ "sugarss": "^5.0.0",
+ "terser": "^5.16.0",
+ "tsx": "^4.8.1",
+ "yaml": "^2.4.2"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "jiti": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "lightningcss": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "sass-embedded": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ },
+ "tsx": {
+ "optional": true
+ },
+ "yaml": {
+ "optional": true
+ }
}
},
- "node_modules/util-deprecate": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
+ "node_modules/vite-node": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.2.4.tgz",
+ "integrity": "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cac": "^6.7.14",
+ "debug": "^4.4.1",
+ "es-module-lexer": "^1.7.0",
+ "pathe": "^2.0.3",
+ "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0"
+ },
+ "bin": {
+ "vite-node": "vite-node.mjs"
+ },
+ "engines": {
+ "node": "^18.0.0 || ^20.0.0 || >=22.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/vite/node_modules/fdir": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
+ "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "picomatch": "^3 || ^4"
+ },
+ "peerDependenciesMeta": {
+ "picomatch": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/vite/node_modules/picomatch": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
+ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/vitest": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.4.tgz",
+ "integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/chai": "^5.2.2",
+ "@vitest/expect": "3.2.4",
+ "@vitest/mocker": "3.2.4",
+ "@vitest/pretty-format": "^3.2.4",
+ "@vitest/runner": "3.2.4",
+ "@vitest/snapshot": "3.2.4",
+ "@vitest/spy": "3.2.4",
+ "@vitest/utils": "3.2.4",
+ "chai": "^5.2.0",
+ "debug": "^4.4.1",
+ "expect-type": "^1.2.1",
+ "magic-string": "^0.30.17",
+ "pathe": "^2.0.3",
+ "picomatch": "^4.0.2",
+ "std-env": "^3.9.0",
+ "tinybench": "^2.9.0",
+ "tinyexec": "^0.3.2",
+ "tinyglobby": "^0.2.14",
+ "tinypool": "^1.1.1",
+ "tinyrainbow": "^2.0.0",
+ "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0",
+ "vite-node": "3.2.4",
+ "why-is-node-running": "^2.3.0"
+ },
+ "bin": {
+ "vitest": "vitest.mjs"
+ },
+ "engines": {
+ "node": "^18.0.0 || ^20.0.0 || >=22.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ },
+ "peerDependencies": {
+ "@edge-runtime/vm": "*",
+ "@types/debug": "^4.1.12",
+ "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
+ "@vitest/browser": "3.2.4",
+ "@vitest/ui": "3.2.4",
+ "happy-dom": "*",
+ "jsdom": "*"
+ },
+ "peerDependenciesMeta": {
+ "@edge-runtime/vm": {
+ "optional": true
+ },
+ "@types/debug": {
+ "optional": true
+ },
+ "@types/node": {
+ "optional": true
+ },
+ "@vitest/browser": {
+ "optional": true
+ },
+ "@vitest/ui": {
+ "optional": true
+ },
+ "happy-dom": {
+ "optional": true
+ },
+ "jsdom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/vitest/node_modules/picomatch": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
+ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/vitest/node_modules/tinyexec": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz",
+ "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==",
+ "dev": true,
"license": "MIT"
},
- "node_modules/validate-npm-package-name": {
- "version": "7.0.2",
- "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-7.0.2.tgz",
- "integrity": "sha512-hVDIBwsRruT73PbK7uP5ebUt+ezEtCmzZz3F59BSr2F6OVFnJ/6h8liuvdLrQ88Xmnk6/+xGGuq+pG9WwTuy3A==",
- "license": "ISC",
+ "node_modules/w3c-xmlserializer": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz",
+ "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "xml-name-validator": "^5.0.0"
+ },
"engines": {
- "node": "^20.17.0 || >=22.9.0"
+ "node": ">=18"
}
},
- "node_modules/vary": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
- "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
- "license": "MIT",
+ "node_modules/webidl-conversions": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-8.0.1.tgz",
+ "integrity": "sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==",
+ "dev": true,
+ "license": "BSD-2-Clause",
"engines": {
- "node": ">= 0.8"
+ "node": ">=20"
}
},
- "node_modules/web-streams-polyfill": {
- "version": "3.3.3",
- "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
- "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==",
+ "node_modules/whatwg-encoding": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz",
+ "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==",
+ "deprecated": "Use @exodus/bytes instead for a more spec-conformant and faster implementation",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "iconv-lite": "0.6.3"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/whatwg-encoding/node_modules/iconv-lite": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
+ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/whatwg-mimetype": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz",
+ "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==",
+ "dev": true,
"license": "MIT",
"engines": {
- "node": ">= 8"
+ "node": ">=18"
+ }
+ },
+ "node_modules/whatwg-url": {
+ "version": "15.1.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-15.1.0.tgz",
+ "integrity": "sha512-2ytDk0kiEj/yu90JOAp44PVPUkO9+jVhyf+SybKlRHSDlvOOZhdPIrr7xTH64l4WixO2cP+wQIcgujkGBPPz6g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tr46": "^6.0.0",
+ "webidl-conversions": "^8.0.0"
+ },
+ "engines": {
+ "node": ">=20"
}
},
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
"license": "ISC",
"dependencies": {
"isexe": "^2.0.0"
@@ -9706,6 +8898,23 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/why-is-node-running": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz",
+ "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "siginfo": "^2.0.0",
+ "stackback": "0.0.2"
+ },
+ "bin": {
+ "why-is-node-running": "cli.js"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/word-wrap": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
@@ -9720,7 +8929,10 @@
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
"integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+ "dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"dependencies": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
@@ -9734,7 +8946,10 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"engines": {
"node": ">=8"
}
@@ -9743,13 +8958,19 @@
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
- "license": "MIT"
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "peer": true
},
"node_modules/wrap-ansi/node_modules/string-width": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
@@ -9763,7 +8984,10 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"dependencies": {
"ansi-regex": "^5.0.1"
},
@@ -9771,28 +8995,45 @@
"node": ">=8"
}
},
- "node_modules/wrappy": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
- "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
- "license": "ISC"
- },
- "node_modules/wsl-utils": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.3.1.tgz",
- "integrity": "sha512-g/eziiSUNBSsdDJtCLB8bdYEUMj4jR7AGeUo96p/3dTafgjHhpF4RiCFPiRILwjQoDXx5MqkBr4fwWtR3Ky4Wg==",
+ "node_modules/ws": {
+ "version": "8.19.0",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz",
+ "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==",
+ "dev": true,
"license": "MIT",
- "dependencies": {
- "is-wsl": "^3.1.0",
- "powershell-utils": "^0.1.0"
- },
"engines": {
- "node": ">=20"
+ "node": ">=10.0.0"
},
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": ">=5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
}
},
+ "node_modules/xml-name-validator": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz",
+ "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/xmlchars": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
+ "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
@@ -9806,7 +9047,10 @@
"version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "dev": true,
"license": "ISC",
+ "optional": true,
+ "peer": true,
"engines": {
"node": ">=10"
}
@@ -9815,13 +9059,17 @@
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+ "dev": true,
"license": "ISC"
},
"node_modules/yargs": {
"version": "17.7.2",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
"integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"dependencies": {
"cliui": "^8.0.1",
"escalade": "^3.1.1",
@@ -9839,7 +9087,10 @@
"version": "21.1.1",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
"integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "dev": true,
"license": "ISC",
+ "optional": true,
+ "peer": true,
"engines": {
"node": ">=12"
}
@@ -9848,7 +9099,10 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"engines": {
"node": ">=8"
}
@@ -9857,13 +9111,19 @@
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
- "license": "MIT"
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "peer": true
},
"node_modules/yargs/node_modules/string-width": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
@@ -9877,7 +9137,10 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"dependencies": {
"ansi-regex": "^5.0.1"
},
@@ -9898,23 +9161,14 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/yoctocolors": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.2.tgz",
- "integrity": "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==",
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/yoctocolors-cjs": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.3.tgz",
"integrity": "sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==",
+ "dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"engines": {
"node": ">=18"
},
@@ -9926,21 +9180,12 @@
"version": "4.3.6",
"resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz",
"integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==",
+ "dev": true,
"license": "MIT",
- "peer": true,
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}
},
- "node_modules/zod-to-json-schema": {
- "version": "3.25.1",
- "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.1.tgz",
- "integrity": "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==",
- "license": "ISC",
- "peerDependencies": {
- "zod": "^3.25 || ^4"
- }
- },
"node_modules/zod-validation-error": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz",
diff --git a/package.json b/package.json
index 3ed8a92..94a3fa7 100644
--- a/package.json
+++ b/package.json
@@ -1,5 +1,5 @@
{
- "name": "diagram-comment-tool",
+ "name": "commenting-visual-explainers",
"version": "0.1.0",
"private": true,
"scripts": {
@@ -7,30 +7,29 @@
"build": "next build",
"start": "next start",
"lint": "eslint",
+ "test": "vitest run",
+ "test:watch": "vitest",
+ "build:widget": "esbuild src/widget/index.ts --bundle --format=iife --outfile=public/widget.js --minify",
+ "dev:widget": "esbuild src/widget/index.ts --bundle --format=iife --outfile=public/widget.js --watch",
"db:migrate": "npx tsx scripts/migrate.ts"
},
"dependencies": {
- "@base-ui/react": "^1.3.0",
"@neondatabase/serverless": "^1.0.2",
- "class-variance-authority": "^0.7.1",
- "clsx": "^2.1.1",
- "lucide-react": "^0.577.0",
"next": "16.1.6",
"react": "19.2.3",
- "react-dom": "19.2.3",
- "shadcn": "^4.0.6",
- "tailwind-merge": "^3.5.0",
- "tw-animate-css": "^1.4.0"
+ "react-dom": "19.2.3"
},
"devDependencies": {
- "@tailwindcss/postcss": "^4",
+ "@types/jsdom": "^28.0.1",
"@types/node": "^20",
"@types/react": "^19",
"@types/react-dom": "^19",
"dotenv": "^17.3.1",
+ "esbuild": "^0.27.4",
"eslint": "^9",
"eslint-config-next": "16.1.6",
- "tailwindcss": "^4",
- "typescript": "5.9.3"
+ "jsdom": "^27.0.1",
+ "typescript": "5.9.3",
+ "vitest": "^3.2.4"
}
}
diff --git a/postcss.config.mjs b/postcss.config.mjs
deleted file mode 100644
index 61e3684..0000000
--- a/postcss.config.mjs
+++ /dev/null
@@ -1,7 +0,0 @@
-const config = {
- plugins: {
- "@tailwindcss/postcss": {},
- },
-};
-
-export default config;
diff --git a/public/file.svg b/public/file.svg
deleted file mode 100644
index 004145c..0000000
--- a/public/file.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/public/globe.svg b/public/globe.svg
deleted file mode 100644
index 567f17b..0000000
--- a/public/globe.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/public/next.svg b/public/next.svg
deleted file mode 100644
index 5174b28..0000000
--- a/public/next.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/public/test-diagram.html b/public/test-diagram.html
deleted file mode 100644
index eb563ac..0000000
--- a/public/test-diagram.html
+++ /dev/null
@@ -1,969 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
- APIの仕組み
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- テクノロジー
-
-
- APIの仕組み
-
-
- 「APIって何?」と聞かれて、うまく答えられない。
- ひとことで言うと ──
-
-
-
-
-
-
-
-
-
-
- API = ソフトウェアの「注文窓口」
-
-
- 中身を知らなくても、決まった形で頼めば結果が届く
-
-
-
-
-
-
-
-
-
-
-
あなたのアプリ
-
「天気を教えて」
-
-
-
-
-
-
-
-
-
-
-
API
-
注文を届け、結果を返す
-
レストランのウェイター役
-
-
-
-
-
-
-
-
-
-
-
サービス
-
処理して結果を返す
-
-
-
-
-
-
-
- 結果(レスポンス)があなたのアプリに届く
-
-
-
-
-
-
-
-
-
-
- 天気予報
-
-
-
- Googleログイン
-
-
-
- オンライン決済
-
-
-
- 地図・ナビ
-
-
-
-
-
-
- ここから先で、この仕組みをひとつずつ丁寧に解説していきます。
-
-
-
-
-
-
-
-
-
-
- API(エーピーアイ)は Application Programming Interface(アプリケーション・プログラミング・インターフェース)の略称です。正式名称を聞いても「何のこと?」と思いますよね。
-
-
-
- まずは日常のたとえで考えてみましょう。レストランに行った場面を想像してください。
-
-
-
- あなた(お客さん)は、厨房に直接入って料理を作ることはできません。厨房のルールも、調理器具の使い方も知りません。でも、ウェイターに「パスタをください」と注文すれば、厨房で作られた料理があなたのテーブルに届きます。厨房の中で何が起きているかを知る必要はありません。
-
-
-
-
-
レストランで考えるAPIの役割
-
-
-
-
-
-
-
-
あなた
-
お客さん
-
「パスタください」
-
-
-
-
-
-
-
-
-
-
-
API
-
ウェイター
-
注文を伝え、料理を届ける
-
-
-
-
-
-
-
-
-
-
-
サーバー
-
厨房
-
パスタを作って渡す
-
-
-
-
-
-
- 料理(レスポンス)があなたのテーブルに届く
-
-
-
-
-
- この比喩がAPIの本質をほぼ言い当てています。あなた(アプリ)は、厨房(サーバー)の中で何が起きているかを知る必要がありません。ウェイター(API)に決まった形式で注文を伝えれば、結果が返ってくる。これがAPIです。
-
-
-
-
-
-
-
-
-
-
ここがポイント
-
- APIは「仲介役」です。相手の内部構造を知らなくても、決まったルールで話しかければ結果が返ってくる。これがAPIの本質です。この「決まったルール」のことを、エンジニアは「インターフェース(Interface)」と呼びます。
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- レストランのたとえで、ざっくりとしたイメージはつかめましたか? ここからもう少しだけ正確に説明します。
-
-
-
- APIとは、ひとことで言えば「ソフトウェア同士が会話するための窓口」です。あなたが使っているアプリの裏側で、別のサービスのデータや機能を借りてくるための「取り決め」と考えてください。
-
-
-
-
技術的な定義
-
- API = あるソフトウェアの機能を、
- 別のソフトウェアから使えるようにする仕組み
-
-
出典: MDN Web Docs — Web API の紹介
-
-
-
- これだけだとまだ抽象的に感じるかもしれません。では、APIがある世界とない世界を比べてみましょう。
-
-
-
-
-
-
-
-
- BEFORE — APIがない世界
-
-
- -
-
- 天気情報が欲しければ、自分で気象観測の仕組みを構築する
-
- -
-
- 決済機能が欲しければ、クレジットカード処理を自前で開発する
-
- -
-
- 地図を表示したければ、地図データを自分で作成・更新する
-
- -
-
- ユーザー認証はパスワード管理からセキュリティ対策まで全部自前
-
-
-
-
- 膨大な開発コストと時間。バグのリスクも高い。
-
-
-
-
-
-
-
- AFTER — APIがある世界
-
-
- -
-
- 天気情報は天気予報APIに問い合わせるだけで取得できる
-
- -
-
- 決済はStripe APIに任せれば数行のコードで完成
-
- -
-
- 地図はGoogle Maps APIで高品質な地図を即表示できる
-
- -
-
- ログインはGoogleやAppleのAPIで安全に認証できる
-
-
-
-
- 「自分が本当に作るべきもの」に集中できる。
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
APIの仕組み — リクエストとレスポンス
-
-
-
- APIでのやり取りは、実はとてもシンプルです。基本は「聞く(リクエスト)」と「答える(レスポンス)」の2つだけ。
-
-
-
- リクエスト(Request)とは、「こういう情報をください」「この処理をしてください」とAPIに送るメッセージのことです。レスポンス(Response)は、APIがその要求に対して返す結果です。この2つのやり取りを分解すると、4つのステップになります。
-
-
-
-
-
APIリクエスト〜レスポンスの流れ
-
-
-
-
1
-
-
リクエスト送信
-
あなたのアプリが
「こういう情報ください」
とAPIに送る
-
-
-
-
-
-
-
-
-
2
-
-
APIが受け取る
-
リクエストの内容を
チェック・認証する
(門番の役割)
-
-
-
-
-
-
-
-
-
3
-
-
サーバーが処理
-
データベース検索や
計算など、実際の
処理を実行する
-
-
-
-
-
-
-
-
-
4
-
-
レスポンス返却
-
処理結果をあなたの
アプリに返す
(料理が届く瞬間)
-
-
-
-
-
- 言葉だけだとまだピンとこないかもしれません。では、実際のコードで見てみましょう。たとえば、天気予報APIから東京の天気を取得するコードは、たったこれだけです。
-
-
-
-
-
-
- JavaScript — 天気予報APIの呼び出し例
-
-
// 1. APIにリクエストを送る(「東京の天気を教えて」と聞く)
-const response = await fetch("https://api.weather.example.com/current?city=tokyo");
-
-// 2. レスポンスをJSON形式(データの構造)に変換する
-const data = await response.json();
-
-// 3. 必要なデータを取り出して使う
-console.log(data.temperature); // → "22°C"
-console.log(data.condition); // → "晴れ"
-console.log(data.humidity); // → "65%"
-
-
-
-
-
-
- コードの解説(1行ずつ読み解く)
-
-
-
- 1
- fetch() は「指定したURLに問い合わせる」命令。URLの末尾にある ?city=tokyo が「東京の情報が欲しい」というリクエストの中身です。レストランのたとえで言えば「パスタください」にあたる部分。
-
-
- 2
- 返ってきたデータは機械向けの生データなので、.json() で人間が読みやすい形(JSON = JavaScript Object Notation)に変換します。JSONは「名前: 値」の組み合わせでデータを表現する書式で、Web業界で最も広く使われています。
-
-
- 3
- 変換したデータから data.temperature のように、ドット(.)で区切って欲しい情報を名前で取り出します。辞書で単語を引くのに似ています。
-
-
-
-
-
- ターミナル(コマンドを入力する黒い画面)からもAPIを試せます。curl(カール)というコマンドを使うと、たった1行でAPIにリクエストを送れます。
-
-
-
-
-
-
-
-
- ターミナル — curlコマンドでAPIを叩く
-
-
-
$ curl https://api.weather.example.com/current?city=tokyo
-
-# 返ってくるレスポンス(JSON形式)
-{
- "city": "東京",
- "temperature": "22°C",
- "condition": "晴れ",
- "humidity": "65%"
-}
-
-
-
-
-
-
-
-
-
ちょっと補足: URLの構造
-
- https://api.weather.example.com/current?city=tokyo のURLは、大きく3つの部分に分かれます。api.weather.example.com がAPIの住所(ベースURL)、/current が「何を」(現在の天気)、?city=tokyo が「どこの」(東京)というパラメータです。レストランで例えると「〇〇レストランの(住所)、メインメニューから(何を)、パスタを(詳細)」に対応します。
-
-
-
-
-
-
- では、このAPIのレスポンスが実際のアプリではどう表示されるのでしょうか? あなたが見ている天気アプリの画面を覗いてみましょう。
-
-
-
-
-
-
-
-
- weather-app.example.com
-
-
-
-
-
現在地: 東京
-
-
- 22°C
-
-
晴れ
-
-
-
-
-
-
-
-
-
-
-
-
APIの結果 → アプリの画面
-
- 上の天気アプリは、裏側で temperature: "22°C" や condition: "晴れ" というAPIレスポンスを受け取り、見やすいデザインに変換して表示しています。あなたが普段見ているきれいな画面の裏側では、こうしたAPIのやり取りが行われているのです。
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
身近なAPIの例 — 実はあなたも毎日使っている
-
-
-
- 「API」と聞くとプログラマーの専門用語に聞こえるかもしれません。しかし、あなたがスマホで何気なくやっている日常の操作の裏側では、たくさんのAPIが動いています。「あなたが見ている画面」の裏側で、APIが何をしているのかを図解します。
-
-
-
-
-
-
-
-
東京
-
-
- 22°C
-
-
晴れ
-
-
-
-
-
- 天気予報アプリ
-
-
裏側でAPIがやっていること
-
気象庁のサーバーに「東京の最新天気データをください」とリクエストを送り、気温・天候・湿度・風速などのデータをJSON形式で受け取っている
-
-
-
-
-
-
-
アカウントにログイン
-
-
-
メールアドレスで登録
-
-
-
- 「Googleでログイン」ボタン
-
-
裏側でAPIがやっていること
-
GoogleのOAuth API(オーオース = 認可の仕組み)に「このユーザーの身元を確認してください」と問い合わせ、認証トークン(本人確認済みの証)を受け取っている
-
-
-
-
-
-
-
-
-
-
お支払い完了
-
¥1,980
-
VISA **** 4242
-
-
-
- オンライン決済
-
-
裏側でAPIがやっていること
-
Stripe等の決済APIが、クレジットカード会社のサーバーと暗号化通信を行い、与信確認(この人は支払える?)→ 決済処理 → 結果通知を実行している
-
出典: Stripe API 公式ドキュメント
-
-
-
-
-
-
-
-
- 地図・ナビアプリ
-
-
裏側でAPIがやっていること
-
Google Maps APIが地図画像の取得、現在の交通情報の取得、経路計算をそれぞれ別のAPIに問い合わせ、統合して表示している
-
-
-
-
-
-
-
-
-
-
-
気づきましたか?
-
- 上の4つの例に共通しているのは、あなたがAPIの存在を意識していないということです。天気を確認するとき「今からAPIを呼ぶぞ」とは思いませんよね。優れたAPIは、ユーザーにその存在を感じさせません。まるで空気のように、裏側で静かに仕事をしているのです。
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ここまで読んで「APIは便利そうだ」と感じてもらえたと思います。では、開発者の視点から見たとき、APIを使うことで具体的にどのくらいの効果があるのか。数字と一緒に見てみましょう。
-
-
-
-
-
50回+
-
あなたが1日に
APIを使っている回数
-
-
-
24,000+
-
世界で公開されている
APIの数
-
出典: ProgrammableWeb
-
-
-
-
-
-
-
-
-
-
-
開発スピードが上がる
-
決済、認証、地図、翻訳...。これらをゼロから作ると何ヶ月もかかりますが、APIを使えば数日〜数時間で実装できます。車を作りたいとき、エンジンから設計する必要はないのです。
-
-
-
-
-
-
-
-
-
品質が担保される
-
Google Maps、Stripe、AWSなど、各分野の専門企業が何千人体制で開発・運用しているAPIの品質は、個人や小さなチームで再現できるレベルではありません。その品質を「借りる」ことができます。
-
-
-
-
-
-
-
-
-
保守の手間が減る
-
API提供元がバグ修正・機能改善・セキュリティ更新を継続的に行ってくれます。あなたはAPIを「使うだけ」。自分でゼロから作った機能は、自分でずっと面倒を見続ける必要があります。
-
-
-
-
-
-
-
-
-
レゴのように拡張できる
-
APIはレゴブロックのように組み合わせられます。たとえば「翻訳API + 音声合成API」を組み合わせれば、多言語音声読み上げ機能が作れます。1つのAPIだけでは実現できない価値が、組み合わせで生まれるのです。
-
-
-
-
-
-
-
-
-
-
-
-
-
- APIについて学び始めると、多くの人が同じところでつまずきます。ここでは、初学者が陥りがちな3つの誤解を取り上げて、正しい理解に修正します。
-
-
-
-
-
-
-
-
-
誤解: 「APIはプログラマーだけが使うもの」
-
-
-
-
-
-
-
-
実際は:
-
- あなたも毎日APIを使っています。朝、天気アプリを開く。SNSにログインする。電子マネーで買い物する。これらの操作はすべて、裏側でAPIが動いています。プログラマーが「APIを使う」のは、この仕組みのコードを書いている側にいるだけの話。気づかないうちにAPIの恩恵を毎日受けているのです。
-
-
-
-
-
-
-
-
-
-
-
-
誤解: 「APIって難しい技術でしょ?」
-
-
-
-
-
-
-
-
実際は:
-
- APIの概念自体は「注文して結果を受け取る」というシンプルな仕組みです。レストランで注文できるなら、APIの概念は理解できます。先ほどのコード例のように、実際のプログラムも数行で書けることがほとんどです。難しいのはAPIそのものではなく、「APIで何を作るか」を考える部分。道具はシンプル、使いこなすセンスが問われるということです。
-
-
-
-
-
-
-
-
-
-
-
-
誤解: 「APIを使うと個人情報が漏れそうで怖い」
-
-
-
-
-
-
-
-
実際は:
-
- 適切に設計されたAPIは、必要最小限の情報だけをやり取りします。たとえば銀行のAPIが口座残高を返す際、パスワードや暗証番号は一切含まれません。APIはデータの「窓口」であり、「何の情報を公開し、何を隠すか」を厳密に制御できます。むしろ、データベースに直接触るよりもAPIを介した方が安全なのです。レストランのたとえで言えば、お客さんが直接厨房に入るより、ウェイターを通した方が厨房の秩序が保たれるのと同じです。
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
まとめ — 覚えておきたい3つのこと
-
-
-
- 長い図解を読んでいただきありがとうございます。最後に、この記事で伝えたかったことを3つに絞ってまとめます。
-
-
-
-
-
-
01
-
-
APIは「ソフトウェアの窓口」
-
- レストランのウェイターのように、あなた(アプリ)とサーバーの間を取り持つ仲介役。相手の内部構造を知らなくても、決まったルール(インターフェース)で話しかければ結果が返ってきます。
-
-
-
-
-
-
-
-
02
-
-
あなたはすでにAPIユーザー
-
- 天気予報、SNSログイン、地図検索、オンライン決済。気づかないうちに、あなたの日常はAPIに支えられています。APIは特別な人だけのものではなく、全員の生活を支える仕組みです。
-
-
-
-
-
-
-
-
03
-
-
APIで「車輪の再発明」がなくなる
-
- すでにある優れた機能をAPIで借りることで、自分は「自分にしか作れない部分」に集中できます。開発スピードが上がり、品質も上がり、保守の手間も減る。これがAPIの最大の恩恵です。
-
-
-
-
-
-
-
-
-
APIは「知っている」だけで世界が広がる概念です。
-
- 次にアプリを使うとき、「この裏側でどんなAPIが動いているんだろう?」と想像してみてください。天気予報の数字も、ログインボタンも、決済完了の画面も、すべてAPIが繋いでいます。テクノロジーの見え方が、少しだけ変わるはずです。
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/public/test.html b/public/test.html
deleted file mode 100644
index f094bf9..0000000
--- a/public/test.html
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
-
- FB Tool Test
-
-
-
- FBツール テストページ
- このページはFBツールの動作確認用です。テキストを選択してコメントを追加できます。
-
- サンプルテキスト
- AI-Driven Schoolは、AI時代に最適化した企画スキルと開発スキルを実践的に学ぶ6ヶ月間のオンラインプログラムです。講義設計・運営ドキュメント・CS・マーケティング・ツール開発をこのリポジトリで管理しています。
- 受講生はチームワークを通じて、実践的なプロジェクトに取り組みます。フィードバックは成長の鍵であり、適切なタイミングで的確なコメントを届けることが重要です。
- カリキュラムは全12回で構成され、毎月のテーマに沿って段階的にスキルを積み上げていきます。各回の講義では座学とワークを組み合わせ、すぐに使える知識と経験を提供します。
-
- フォーカス連動テスト
- サイドバーのカードをクリックすると、対応するハイライト箇所にスクロールします。逆に、本文のハイライトをクリックするとサイドバーのカードにスクロールします。カードにホバーするとハイライトがパルスで点滅します。
-
- リサイズテスト
- サイドバーの左端にマウスを当てるとカーソルが左右矢印に変わります。ドラッグで幅を変更でき、300pxから800pxの範囲で調整可能です。変更した幅はページをリロードしても維持されます。
-
-
-
-
diff --git a/public/vercel.svg b/public/vercel.svg
deleted file mode 100644
index 7705396..0000000
--- a/public/vercel.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/public/widget.js b/public/widget.js
index c4f8b25..37c37e0 100644
--- a/public/widget.js
+++ b/public/widget.js
@@ -1,926 +1,2 @@
-/**
- * Icons: Lucide (https://lucide.dev)
- * ISC License - Copyright (c) Lucide Contributors 2026
- */
-(function () {
- 'use strict';
-
- var SCRIPT = document.currentScript;
- var API_BASE = SCRIPT ? SCRIPT.src.replace(/\/widget\.js.*$/, '') : '';
- var API_TOKEN = SCRIPT ? (SCRIPT.dataset.token || '') : '';
- var USERNAME_KEY = 'fb-username';
- var SIDEBAR_WIDTH_KEY = 'fb-sidebar-width';
- var PRIORITY_CYCLE = { must: 'better', better: 'want', want: 'must' };
- var PRIORITY_COLORS = {
- must: { bg: '#ef4444', text: '#fff', light: 'rgba(239,68,68,0.1)', border: 'rgba(239,68,68,0.3)' },
- better: { bg: '#f59e0b', text: '#fff', light: 'rgba(245,158,11,0.1)', border: 'rgba(245,158,11,0.3)' },
- want: { bg: '#22c55e', text: '#fff', light: 'rgba(34,197,94,0.1)', border: 'rgba(34,197,94,0.3)' },
- };
-
- var SVG = {
- message: '',
- check: '',
- rotateCcw: '',
- pencil: '',
- trash: '',
- user: '',
- x: '',
- panelRight: '',
- };
-
- function icon(name, size, strokeWidth) {
- size = size || 14;
- strokeWidth = strokeWidth || 2;
- return (SVG[name] || '').replace(/SIZE/g, size).replace(/SW/g, strokeWidth);
- }
-
- var state = {
- username: localStorage.getItem(USERNAME_KEY) || '',
- comments: [],
- filter: 'unresolved',
- sidebarOpen: false,
- selectedText: '',
- selectedQuoteContext: { beforeText: '', afterText: '' },
- selectedRect: null,
- popupContent: '',
- editingId: null,
- editContent: '',
- editPriority: 'want',
- replyingTo: null,
- replyText: '',
- editingName: false,
- nameInput: '',
- popupPriority: 'must',
- sidebarWidth: parseInt(localStorage.getItem(SIDEBAR_WIDTH_KEY), 10) || 400,
- };
-
- var slug = (function () {
- return window.location.href
- .replace(/^https?:\/\//, '')
- .replace(/[^a-zA-Z0-9\u3040-\u309F\u30A0-\u30FF\u4E00-\u9FFF]/g, '_')
- .substring(0, 100);
- })();
-
- function genId() {
- return Date.now().toString(36) + Math.random().toString(36).substring(2, 8);
- }
-
- function esc(s) {
- var d = document.createElement('div');
- d.textContent = s;
- return d.innerHTML;
- }
-
- function fmtTime(ts) {
- var d = Date.now() - ts;
- if (d < 60000) return 'たった今';
- if (d < 3600000) return Math.floor(d / 60000) + '分前';
- if (d < 86400000) return Math.floor(d / 3600000) + '時間前';
- return new Date(ts).toLocaleDateString('ja-JP', { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' });
- }
-
- // ===== API =====
- function api(method, params) {
- var url = API_BASE + '/api/comments';
- var hdrs = { 'Content-Type': 'application/json' };
- if (API_TOKEN) hdrs['Authorization'] = 'Bearer ' + API_TOKEN;
- var opts = { method: method, headers: hdrs };
- if (method === 'GET') {
- url += '?slug=' + encodeURIComponent(params.slug);
- } else if (method === 'DELETE') {
- url += '?id=' + encodeURIComponent(params.id);
- } else {
- opts.body = JSON.stringify(params);
- }
- return fetch(url, opts).then(function (r) { return r.json(); });
- }
-
- function loadComments() {
- return api('GET', { slug: slug }).then(function (c) {
- if (Array.isArray(c)) state.comments = c;
- render();
- applyHighlights();
- }).catch(function () {
- render();
- applyHighlights();
- });
- }
-
- // ===== CSS =====
- function injectStyles() {
- var style = document.createElement('style');
- style.id = 'fb-widget-styles';
- style.textContent = [
- ':root{--fb-bg:#ffffff;--fb-fg:#0a0a0a;--fb-muted:#f5f5f5;--fb-muted-fg:#737373;--fb-border:#e5e5e5;--fb-primary:#171717;--fb-primary-fg:#fafafa;--fb-accent:#3b82f6;--fb-destructive:#ef4444;--fb-font:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Hiragino Sans",sans-serif}',
-
- /* Toggle button */
- '#fb-toggle{position:fixed;right:0;top:50%;transform:translateY(-50%);width:36px;background:var(--fb-bg);border:1px solid var(--fb-border);border-right:none;border-radius:8px 0 0 8px;cursor:pointer;z-index:99999;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;font-family:var(--fb-font);transition:all .15s;box-shadow:-2px 0 8px rgba(0,0,0,0.06);padding:8px 0}',
- '#fb-toggle:hover{background:var(--fb-muted);box-shadow:-2px 0 12px rgba(0,0,0,0.1)}',
- '#fb-toggle .fb-toggle-icon{color:var(--fb-muted-fg);display:flex;align-items:center;justify-content:center;position:relative}',
- '#fb-toggle .fb-toggle-label{font-size:10px;color:var(--fb-accent);font-weight:700;writing-mode:vertical-rl;letter-spacing:1px;line-height:1;white-space:nowrap}',
- '#fb-toggle .fb-badge{position:absolute;top:-6px;left:-6px;background:var(--fb-destructive);color:#fff;font-size:9px;font-weight:700;min-width:16px;height:16px;border-radius:8px;display:flex;align-items:center;justify-content:center;padding:0 3px;line-height:1}',
-
- /* Sidebar */
- '#fb-sidebar{position:fixed;top:0;height:100vh;background:rgba(245,245,245,0.5);border-left:1px solid var(--fb-border);z-index:99998;transition:right .3s ease;display:flex;flex-direction:column;font-family:var(--fb-font);font-size:14px;color:var(--fb-fg)}',
- '#fb-sidebar *{box-sizing:border-box}',
-
- /* Resize handle */
- '.fb-resize-handle{position:absolute;left:-3px;top:0;width:6px;height:100%;cursor:col-resize;z-index:1}',
- '.fb-resize-handle:hover{background:rgba(59,130,246,0.15)}',
- '.fb-resize-handle.active{background:rgba(59,130,246,0.3)}',
- 'body.fb-resizing{cursor:col-resize !important;-webkit-user-select:none !important;user-select:none !important}',
- 'body.fb-resizing *{cursor:col-resize !important}',
-
- /* Header */
- '.fb-header{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-bottom:1px solid var(--fb-border)}',
- '.fb-header-left{display:flex;align-items:center;gap:8px}',
- '.fb-header-title{font-size:14px;font-weight:700;color:var(--fb-accent)}',
- '.fb-header-count{background:var(--fb-muted);color:var(--fb-muted-fg);font-size:11px;padding:1px 7px;border-radius:10px}',
- '.fb-header-actions{display:flex;align-items:center;gap:2px}',
- '.fb-hdr-btn{background:none;border:none;cursor:pointer;padding:6px;border-radius:6px;color:var(--fb-muted-fg);transition:all .15s;display:inline-flex;align-items:center;gap:4px;font-family:var(--fb-font);font-size:12px}',
- '.fb-hdr-btn:hover{background:var(--fb-muted);color:var(--fb-fg)}',
-
- /* User row */
- '.fb-user-row{display:flex;align-items:center;padding:8px 16px;border-bottom:1px solid var(--fb-border);font-size:13px;color:var(--fb-muted-fg);cursor:pointer;transition:color .15s;gap:6px}',
- '.fb-user-row:hover{color:var(--fb-fg)}',
-
- /* Filters */
- '.fb-filters{display:flex;border-bottom:1px solid var(--fb-border)}',
- '.fb-filter{flex:1;padding:10px 0;text-align:center;font-size:13px;color:var(--fb-muted-fg);border:none;background:none;cursor:pointer;border-bottom:2px solid transparent;transition:all .15s;font-family:var(--fb-font)}',
- '.fb-filter:hover{color:var(--fb-fg)}',
- '.fb-filter.active{color:var(--fb-fg);border-bottom-color:var(--fb-accent)}',
- '.fb-filter .cnt{font-size:11px;margin-left:4px;padding:1px 5px;border-radius:8px;background:var(--fb-muted);color:var(--fb-muted-fg)}',
- '.fb-filter.active .cnt{background:rgba(59,130,246,0.1);color:var(--fb-accent)}',
-
- /* List */
- '.fb-list{flex:1;overflow-y:auto;padding:8px}',
- '.fb-empty{text-align:center;padding:60px 20px;color:var(--fb-muted-fg);font-size:13px}',
- '.fb-empty svg{margin:0 auto 12px;display:block;color:var(--fb-border)}',
-
- /* Card */
- '.fb-card{background:var(--fb-bg);border:1px solid var(--fb-border);border-left:3px solid var(--fb-border);border-radius:12px;padding:14px;margin-bottom:6px;transition:box-shadow .3s,background .3s;cursor:pointer}',
- '.fb-card:hover{box-shadow:0 1px 3px rgba(0,0,0,0.05)}',
- '.fb-card.resolved{opacity:.5}',
-
- /* Card header */
- '.fb-card-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:4px}',
- '.fb-card-head-left{display:flex;align-items:center;gap:6px}',
- '.fb-avatar{width:22px;height:22px;border-radius:50%;background:var(--fb-primary);color:var(--fb-primary-fg);display:flex;align-items:center;justify-content:center;font-size:10px;font-weight:700;flex-shrink:0}',
- '.fb-author{font-size:13px;font-weight:700;color:var(--fb-fg)}',
- '.fb-time{font-size:11px;color:var(--fb-muted-fg)}',
- '.fb-resolved-mark{font-size:11px;color:#22c55e;margin-left:4px;display:inline-flex;align-items:center;gap:2px}',
-
- /* Priority badge */
- '.fb-badge-p{font-size:11px;font-weight:700;padding:2px 8px;border-radius:4px;color:#fff;cursor:default;transition:all .15s}',
- '.fb-badge-p.own{cursor:pointer}',
- '.fb-badge-p.own:hover{transform:scale(1.1);box-shadow:0 0 0 2px rgba(0,0,0,0.08)}',
-
- /* Quote */
- '.fb-quote{font-size:12px;color:var(--fb-muted-fg);padding:6px 10px;background:var(--fb-muted);border-left:2px solid var(--fb-primary);border-radius:0 4px 4px 0;margin-bottom:8px;font-style:italic;line-height:1.5;cursor:pointer;transition:background .15s}',
- '.fb-quote:hover{background:var(--fb-border)}',
-
- /* Body */
- '.fb-body{font-size:13px;color:var(--fb-muted-fg);line-height:1.6;margin-bottom:6px;white-space:pre-wrap}',
-
- /* Actions */
- '.fb-actions{display:flex;gap:2px;flex-wrap:wrap}',
- '.fb-act{font-size:12px;color:#a3a3a3;background:none;border:none;padding:4px 8px;border-radius:4px;cursor:pointer;transition:all .15s;display:inline-flex;align-items:center;gap:3px;font-family:var(--fb-font)}',
- '.fb-act:hover{color:var(--fb-fg)}',
- '.fb-act.del:hover{color:var(--fb-destructive)}',
- '.fb-act.res:hover{color:#22c55e}',
-
- /* Replies */
- '.fb-replies{margin-top:8px;padding-top:8px;border-top:1px solid var(--fb-muted)}',
- '.fb-reply-item{display:flex;gap:8px;padding:6px 0}',
- '.fb-reply-item+.fb-reply-item{border-top:1px solid var(--fb-muted)}',
- '.fb-reply-avatar{width:20px;height:20px;border-radius:50%;background:var(--fb-primary);color:var(--fb-primary-fg);display:flex;align-items:center;justify-content:center;font-size:9px;font-weight:700;flex-shrink:0;margin-top:2px}',
- '.fb-reply-meta{font-size:12px;color:var(--fb-muted-fg);margin-bottom:2px}',
- '.fb-reply-meta strong{color:#525252;font-weight:700}',
- '.fb-reply-text{font-size:13px;color:var(--fb-muted-fg);line-height:1.5}',
-
- /* Reply input */
- '.fb-reply-input{display:flex;gap:8px;margin-top:8px}',
- '.fb-reply-input textarea{flex:1;padding:8px 10px;border:1px solid var(--fb-border);border-radius:6px;font-size:13px;font-family:var(--fb-font);resize:none;outline:none;min-height:36px;color:var(--fb-fg)}',
- '.fb-reply-input textarea:focus{border-color:var(--fb-accent)}',
- '.fb-reply-input button{padding:6px 14px;background:var(--fb-primary);color:var(--fb-primary-fg);border:none;border-radius:6px;font-size:12px;cursor:pointer;font-family:var(--fb-font);align-self:flex-end}',
- '.fb-reply-input button:disabled{opacity:.4;cursor:default}',
-
- /* Edit area */
- '.fb-edit-area textarea{width:100%;padding:8px 10px;border:1px solid var(--fb-border);border-radius:6px;font-size:13px;font-family:var(--fb-font);resize:vertical;outline:none;min-height:50px;margin-bottom:6px;color:var(--fb-fg)}',
- '.fb-edit-area textarea:focus{border-color:var(--fb-accent)}',
- '.fb-edit-btns{display:flex;gap:6px}',
- '.fb-edit-btns button{padding:4px 12px;border-radius:6px;font-size:12px;cursor:pointer;border:1px solid var(--fb-border);background:var(--fb-bg);color:var(--fb-muted-fg);font-family:var(--fb-font)}',
- '.fb-edit-btns button.save{background:var(--fb-primary);color:var(--fb-primary-fg);border-color:var(--fb-primary)}',
- '.fb-edit-pri{display:flex;gap:4px;margin-bottom:6px}',
- '.fb-edit-pri button{padding:2px 10px;border-radius:4px;font-size:11px;font-weight:700;cursor:pointer;border:1px solid var(--fb-border);background:var(--fb-bg);color:var(--fb-muted-fg);font-family:var(--fb-font);transition:all .15s}',
-
- /* Popup */
- '.fb-popup{position:fixed;z-index:100000;width:400px;background:var(--fb-bg);border:1px solid var(--fb-border);border-radius:12px;padding:16px;box-shadow:0 10px 25px rgba(0,0,0,0.1);font-family:var(--fb-font);display:none}',
- '.fb-popup.show{display:block}',
- '.fb-popup-head{margin-bottom:10px}',
- '.fb-popup-head span{font-size:14px;font-weight:700;color:var(--fb-fg)}',
- '.fb-popup-quote{font-size:13px;color:var(--fb-muted-fg);padding:8px 12px;background:var(--fb-muted);border-left:2px solid var(--fb-accent);border-radius:0 6px 6px 0;margin-bottom:10px;font-style:italic;line-height:1.5}',
- '.fb-popup textarea{width:100%;min-height:70px;padding:10px 12px;border:1px solid var(--fb-border);border-radius:8px;font-size:14px;font-family:var(--fb-font);resize:vertical;outline:none;margin-bottom:10px;color:var(--fb-fg)}',
- '.fb-popup textarea:focus{border-color:var(--fb-accent)}',
- '.fb-popup textarea::placeholder{color:var(--fb-muted-fg)}',
- '.fb-popup-pri{display:flex;gap:6px;margin-bottom:10px}',
- '.fb-popup-pri button{flex:1;padding:7px 8px;border-radius:8px;font-size:13px;font-weight:600;cursor:pointer;border:2px solid transparent;transition:all .15s;font-family:var(--fb-font)}',
- '.fb-popup-actions{display:flex;gap:8px;justify-content:flex-end}',
- '.fb-popup-actions button{padding:8px 18px;border-radius:8px;font-size:13px;font-weight:600;cursor:pointer;transition:all .15s;font-family:var(--fb-font)}',
- '.fb-popup-actions .cancel{background:none;border:1px solid var(--fb-border);color:var(--fb-muted-fg)}',
- '.fb-popup-actions .cancel:hover{background:var(--fb-muted);color:var(--fb-fg)}',
- '.fb-popup-actions .submit{border:none;color:#fff}',
-
- /* Name dialog */
- '.fb-name-overlay{position:fixed;inset:0;background:rgba(0,0,0,0.4);display:flex;align-items:center;justify-content:center;z-index:100001}',
- '.fb-name-box{background:var(--fb-bg);border-radius:12px;padding:28px;width:360px;box-shadow:0 20px 40px rgba(0,0,0,0.15)}',
- '.fb-name-box h2{font-size:18px;font-weight:700;margin:0 0 6px;color:var(--fb-fg)}',
- '.fb-name-box p{font-size:14px;color:var(--fb-muted-fg);margin:0 0 16px}',
- '.fb-name-box input{width:100%;padding:10px 14px;border:1px solid var(--fb-border);border-radius:8px;font-size:15px;outline:none;margin-bottom:12px;font-family:var(--fb-font);color:var(--fb-fg)}',
- '.fb-name-box input:focus{border-color:var(--fb-accent)}',
- '.fb-name-box input::placeholder{color:var(--fb-muted-fg)}',
- '.fb-name-box button{width:100%;padding:10px;background:var(--fb-primary);color:var(--fb-primary-fg);border:none;border-radius:8px;font-size:14px;font-weight:600;cursor:pointer;font-family:var(--fb-font)}',
- '.fb-name-box button:disabled{opacity:.4;cursor:default}',
-
- /* Inline name edit */
- '.fb-name-input{width:100%;padding:4px 8px;border:1px solid var(--fb-border);border-radius:4px;font-size:12px;outline:none;font-family:var(--fb-font);color:var(--fb-fg)}',
- '.fb-name-input:focus{border-color:var(--fb-accent)}',
-
- /* Highlights */
- '.fb-highlight{padding:1px 0;cursor:pointer;transition:background .15s}',
- '.fb-highlight-must{background:rgba(239,68,68,0.15);border-bottom:2px solid #ef4444}',
- '.fb-highlight-must:hover{background:rgba(239,68,68,0.25)}',
- '.fb-highlight-better{background:rgba(245,158,11,0.15);border-bottom:2px solid #f59e0b}',
- '.fb-highlight-better:hover{background:rgba(245,158,11,0.25)}',
- '.fb-highlight-want{background:rgba(34,197,94,0.15);border-bottom:2px solid #22c55e}',
- '.fb-highlight-want:hover{background:rgba(34,197,94,0.25)}',
-
- '@keyframes fb-pulse{0%,100%{opacity:1}50%{opacity:0.4}}',
- '.fb-highlight.fb-pulse{animation:fb-pulse 1s ease-in-out infinite}',
- '.fb-card.fb-focused{box-shadow:0 0 0 2px var(--fb-accent);background:rgba(59,130,246,0.04)}',
-
- '#fb-sidebar svg,#fb-toggle svg,.fb-popup svg{pointer-events:none}',
- ].join('\n');
- document.head.appendChild(style);
- }
-
- // ===== DOM =====
- function el(tag, attrs, children) {
- var e = document.createElement(tag);
- if (attrs) Object.keys(attrs).forEach(function (k) {
- if (k === 'className') e.className = attrs[k];
- else if (k === 'innerHTML') e.innerHTML = attrs[k];
- else if (k.startsWith('on')) e.addEventListener(k.substring(2).toLowerCase(), attrs[k]);
- else e.setAttribute(k, attrs[k]);
- });
- if (children) {
- if (typeof children === 'string') e.textContent = children;
- else if (Array.isArray(children)) children.forEach(function (c) { if (c) e.appendChild(c); });
- else e.appendChild(children);
- }
- return e;
- }
-
- // ===== Render =====
- function render() {
- renderToggle();
- renderSidebar();
- renderPopup();
- renderNameDialog();
- }
-
- function renderToggle() {
- var btn = document.getElementById('fb-toggle');
- if (!btn) {
- btn = el('button', { id: 'fb-toggle', onClick: toggleSidebar });
- document.body.appendChild(btn);
- }
- var unresolvedCount = state.comments.filter(function (c) { return !c.parentId && !c.resolved; }).length;
- var h = '' + icon('panelRight', 16);
- if (unresolvedCount > 0) h += '' + unresolvedCount + '';
- h += '';
- h += 'コメント';
- btn.innerHTML = h;
- btn.style.display = state.sidebarOpen ? 'none' : '';
- }
-
- function applySidebarWidth() {
- var sb = document.getElementById('fb-sidebar');
- if (!sb) return;
- var w = state.sidebarWidth;
- sb.style.width = w + 'px';
- sb.style.right = state.sidebarOpen ? '0px' : (-(w + 20)) + 'px';
- document.body.style.marginRight = state.sidebarOpen ? w + 'px' : '';
- }
-
- function toggleSidebar() {
- state.sidebarOpen = !state.sidebarOpen;
- var btn = document.getElementById('fb-toggle');
- if (btn) btn.style.display = state.sidebarOpen ? 'none' : '';
- document.body.style.transition = 'margin-right 0.3s ease';
- applySidebarWidth();
- }
-
- function topLevel() { return state.comments.filter(function (c) { return !c.parentId; }); }
- function getReplies(id) { return state.comments.filter(function (c) { return c.parentId === id; }).sort(function (a, b) { return a.timestamp - b.timestamp; }); }
-
- function filtered() {
- var tl = topLevel();
- if (state.filter === 'resolved') return tl.filter(function (c) { return c.resolved; });
- if (state.filter === 'all') return tl;
- return tl.filter(function (c) { return !c.resolved; });
- }
-
- function renderSidebar() {
- var sb = document.getElementById('fb-sidebar');
- var isNew = !sb;
- if (isNew) {
- sb = el('div', { id: 'fb-sidebar' });
- document.body.appendChild(sb);
- sb.addEventListener('mouseover', function (e) {
- var card = e.target.closest('.fb-card');
- if (!card) return;
- var mark = document.querySelector('.fb-highlight[data-comment-id="' + card.dataset.id + '"]');
- if (mark) mark.classList.add('fb-pulse');
- });
- sb.addEventListener('mouseout', function (e) {
- var card = e.target.closest('.fb-card');
- if (!card) return;
- if (e.relatedTarget && card.contains(e.relatedTarget)) return;
- var mark = document.querySelector('.fb-highlight[data-comment-id="' + card.dataset.id + '"]');
- if (mark) mark.classList.remove('fb-pulse');
- });
- }
- applySidebarWidth();
-
- var tl = topLevel();
- var counts = {
- unresolved: tl.filter(function (c) { return !c.resolved; }).length,
- resolved: tl.filter(function (c) { return c.resolved; }).length,
- all: tl.length,
- };
-
- var html = '';
-
- // Header
- html += '';
-
- // User
- if (state.username) {
- if (state.editingName) {
- html += '';
- } else {
- html += '' + icon('user', 14) + esc(state.username) + '
';
- }
- }
-
- // Filters
- html += '';
- ['unresolved', 'resolved', 'all'].forEach(function (f) {
- var label = f === 'unresolved' ? '未解決' : f === 'resolved' ? '解決済' : 'すべて';
- html += '';
- });
- html += '
';
-
- // List
- var items = filtered().sort(function (a, b) { return b.timestamp - a.timestamp; });
- html += '';
- if (items.length === 0) {
- html += '
' + icon('message', 40) + 'コメントはまだありません
テキストを選択してコメントを追加
';
- } else {
- items.forEach(function (c) { html += renderCard(c); });
- }
- html += '
';
-
- sb.innerHTML = html;
- if (isNew) bindSidebarEvents(sb);
- }
-
- function renderCard(c) {
- var isOwn = c.author === state.username;
- var pc = PRIORITY_COLORS[c.priority] || PRIORITY_COLORS.want;
-
- var h = '';
-
- // Header
- h += '
';
- h += '
' + esc(c.author.charAt(0)) + '
';
- h += '
' + esc(c.author) + '';
- h += '
' + fmtTime(c.timestamp) + '';
- if (c.resolved) h += '
' + icon('check', 12) + ' 解決済';
- h += '
';
- h += '
' + esc(c.priority.charAt(0).toUpperCase() + c.priority.slice(1)) + '';
- h += '
';
-
- // Quote
- if (c.quote) {
- var q = c.quote.length > 100 ? c.quote.substring(0, 100) + '...' : c.quote;
- h += '
' + esc(q) + '
';
- }
-
- // Body / Edit
- if (state.editingId === c.id) {
- h += '
';
- h += '
';
- ['must', 'better', 'want'].forEach(function (p) {
- var sel = state.editPriority === p;
- var pc2 = PRIORITY_COLORS[p];
- h += '';
- });
- h += '
';
- h += '
';
- h += '
';
- h += '
';
- } else {
- h += '
' + esc(c.content) + '
';
- }
-
- // Actions
- if (state.editingId !== c.id) {
- h += '
';
- h += '';
- h += '';
- if (isOwn) h += '';
- if (isOwn) h += '';
- h += '
';
- }
-
- // Replies
- var replies = getReplies(c.id);
- if (replies.length > 0) {
- h += '
';
- replies.forEach(function (r) {
- var isOwnReply = r.author === state.username;
- h += '
' + esc(r.author.charAt(0)) + '
' + esc(r.author) + ' · ' + fmtTime(r.timestamp) + '
';
- if (state.editingId === r.id) {
- h += '
';
- } else {
- h += '
' + esc(r.content) + '
';
- h += '
';
- h += '';
- if (isOwnReply) h += '';
- if (isOwnReply) h += '';
- h += '
';
- }
- h += '
';
- });
- h += '
';
- }
-
- // Reply input
- if (state.replyingTo === c.id) {
- h += '
';
- }
-
- h += '
';
- return h;
- }
-
- function bindSidebarEvents(sb) {
- sb.addEventListener('click', function (e) {
- var t = e.target.closest('[data-action]');
- if (t) {
- var action = t.dataset.action;
- var id = t.dataset.id;
-
- if (action === 'close') { toggleSidebar(); }
- else if (action === 'edit-name') { state.editingName = true; state.nameInput = state.username; render(); }
- else if (action === 'cycle' && id) { cyclePriority(id); }
- else if (action === 'scroll-quote' && id) { scrollToQuote(id); }
- else if (action === 'reply' && id) { state.replyingTo = state.replyingTo === id ? null : id; state.replyText = ''; render(); }
- else if (action === 'resolve' && id) { resolveComment(id); }
- else if (action === 'edit' && id) { var c = state.comments.find(function (x) { return x.id === id; }); if (c) { state.editingId = id; state.editContent = c.content; state.editPriority = c.priority; render(); } }
- else if (action === 'delete' && id) { deleteComment(id); }
- else if (action === 'delete-reply' && id) { deleteReply(id); }
- else if (action === 'cancel-edit') { state.editingId = null; render(); }
- else if (action === 'save-edit' && id) { saveEdit(id); }
- else if (action === 'submit-reply' && id) { submitReply(id); }
- else if (action === 'set-edit-pri') { state.editPriority = t.dataset.pri; render(); }
- return;
- }
- var filterBtn = e.target.closest('[data-filter]');
- if (filterBtn) { state.filter = filterBtn.dataset.filter; render(); return; }
-
- var card = e.target.closest('.fb-card');
- if (card && card.dataset.id) {
- scrollToQuote(card.dataset.id);
- }
- });
-
- sb.addEventListener('mousedown', function (e) {
- if (!e.target.closest('.fb-resize-handle')) return;
- e.preventDefault();
- var startX = e.clientX;
- var startWidth = state.sidebarWidth;
- var handle = e.target.closest('.fb-resize-handle');
- document.body.classList.add('fb-resizing');
- handle.classList.add('active');
- function onMove(ev) {
- state.sidebarWidth = Math.min(800, Math.max(300, startWidth + (startX - ev.clientX)));
- var s = document.getElementById('fb-sidebar');
- if (s) s.style.width = state.sidebarWidth + 'px';
- document.body.style.transition = 'none';
- document.body.style.marginRight = state.sidebarWidth + 'px';
- }
- function onUp() {
- document.removeEventListener('mousemove', onMove);
- document.removeEventListener('mouseup', onUp);
- document.body.classList.remove('fb-resizing');
- handle.classList.remove('active');
- document.body.style.transition = '';
- localStorage.setItem(SIDEBAR_WIDTH_KEY, String(state.sidebarWidth));
- }
- document.addEventListener('mousemove', onMove);
- document.addEventListener('mouseup', onUp);
- });
-
- sb.addEventListener('input', function (e) {
- var t = e.target;
- if (t.dataset.action === 'name-input') { state.nameInput = t.value; }
- else if (t.dataset.action === 'edit-textarea') { state.editContent = t.value; }
- else if (t.dataset.action === 'reply-textarea') { state.replyText = t.value; var btn = sb.querySelector('[data-action="submit-reply"]'); if (btn) btn.disabled = !state.replyText.trim(); }
- });
-
- sb.addEventListener('keydown', function (e) {
- var t = e.target;
- if (t.dataset.action === 'name-input') {
- if (e.key === 'Enter') { finishNameEdit(); }
- else if (e.key === 'Escape') { state.editingName = false; render(); }
- }
- if (t.dataset.action === 'reply-textarea' && (e.metaKey || e.ctrlKey) && e.key === 'Enter') {
- var id = sb.querySelector('[data-action="submit-reply"]')?.dataset.id;
- if (id) submitReply(id);
- }
- });
-
- sb.addEventListener('blur', function (e) {
- if (e.target.dataset?.action === 'name-input') { finishNameEdit(); }
- }, true);
-
- }
-
- // ===== Popup =====
- function renderPopup() {
- var popup = document.getElementById('fb-popup');
- var isNew = !popup;
- if (isNew) {
- popup = el('div', { id: 'fb-popup', className: 'fb-popup' });
- document.body.appendChild(popup);
- popup.addEventListener('click', function (e) {
- var t = e.target.closest('[data-action]');
- if (!t) return;
- if (t.dataset.action === 'cancel-popup') { closePopup(); }
- else if (t.dataset.action === 'set-popup-pri') { state.popupPriority = t.dataset.pri; render(); }
- else if (t.dataset.action === 'submit-popup') { submitComment(state.popupPriority); }
- });
- popup.addEventListener('input', function (e) {
- if (e.target.dataset.action === 'popup-textarea') state.popupContent = e.target.value;
- });
- popup.addEventListener('keydown', function (e) {
- if (e.target.dataset.action === 'popup-textarea' && (e.metaKey || e.ctrlKey) && e.key === 'Enter') {
- submitComment(state.popupPriority);
- }
- });
- }
- if (!state.selectedRect) { popup.classList.remove('show'); return; }
- popup.classList.add('show');
-
- var q = state.selectedText.length > 120 ? state.selectedText.substring(0, 120) + '...' : state.selectedText;
- var selPc = PRIORITY_COLORS[state.popupPriority];
- var h = '';
- h += '';
- h += '';
- h += '';
- h += '';
- popup.innerHTML = h;
-
- var rect = state.selectedRect;
- var pw = 400, ph = 300, m = 12;
- var top = rect.bottom + m;
- if (top + ph > window.innerHeight) top = rect.top - ph - m;
- if (top < m) top = Math.max(m, (window.innerHeight - ph) / 2);
- var availW = state.sidebarOpen ? window.innerWidth - state.sidebarWidth : window.innerWidth;
- var left = Math.max(m, Math.min(rect.left, availW - pw - m));
- popup.style.top = top + 'px';
- popup.style.left = left + 'px';
- }
-
- function closePopup() {
- state.selectedText = '';
- state.selectedRect = null;
- state.popupContent = '';
- state.popupPriority = 'must';
- render();
- }
-
- function renderNameDialog() {
- var existing = document.getElementById('fb-name-overlay');
- if (state.username) { if (existing) existing.remove(); return; }
- if (existing) return;
- var overlay = el('div', { id: 'fb-name-overlay', className: 'fb-name-overlay' });
- overlay.innerHTML = '';
- document.body.appendChild(overlay);
- var input = document.getElementById('fb-name-field');
- var btn = document.getElementById('fb-name-submit');
- input.addEventListener('input', function () { btn.disabled = !input.value.trim(); });
- input.addEventListener('keydown', function (e) { if (e.key === 'Enter' && input.value.trim()) { setName(input.value.trim()); } });
- btn.addEventListener('click', function () { if (input.value.trim()) setName(input.value.trim()); });
- setTimeout(function () { input.focus(); }, 100);
- }
-
- function setName(name) {
- state.username = name;
- localStorage.setItem(USERNAME_KEY, name);
- var overlay = document.getElementById('fb-name-overlay');
- if (overlay) overlay.remove();
- render();
- }
-
- function finishNameEdit() {
- if (state.nameInput.trim() && state.nameInput.trim() !== state.username) {
- var oldName = state.username;
- state.username = state.nameInput.trim();
- localStorage.setItem(USERNAME_KEY, state.username);
- api('PUT', { id: '_rename', author: state.username, oldAuthor: oldName, projectSlug: slug }).then(loadComments);
- }
- state.editingName = false;
- render();
- }
-
- // ===== Actions =====
- function submitComment(priority) {
- if (!state.username || !state.selectedText) return;
- var c = {
- id: genId(), author: state.username, type: 'comment',
- quote: state.selectedText, quoteContext: state.selectedQuoteContext,
- content: state.popupContent.trim(),
- priority: priority, parentId: null, pageUrl: window.location.href,
- projectSlug: slug, timestamp: Date.now(),
- };
- state.comments.push(c);
- closePopup();
- applyHighlights();
- api('POST', c).then(loadComments);
- }
-
- function resolveComment(id) {
- var c = state.comments.find(function (x) { return x.id === id; });
- if (!c) return;
- var now = !c.resolved;
- c.resolved = now;
- c.resolvedBy = now ? state.username : null;
- c.resolvedAt = now ? Date.now() : null;
- render(); applyHighlights();
- api('PUT', { id: id, resolved: now, resolvedBy: c.resolvedBy, resolvedAt: c.resolvedAt });
- }
-
- function cyclePriority(id) {
- var c = state.comments.find(function (x) { return x.id === id; });
- if (!c || c.author !== state.username) return;
- c.priority = PRIORITY_CYCLE[c.priority] || 'must';
- render(); applyHighlights();
- api('PUT', { id: id, priority: c.priority });
- }
-
- function deleteComment(id) {
- state.comments = state.comments.filter(function (c) { return c.id !== id && c.parentId !== id; });
- render(); applyHighlights();
- api('DELETE', { id: id });
- }
-
- function deleteReply(id) {
- state.comments = state.comments.filter(function (c) { return c.id !== id; });
- render();
- api('DELETE', { id: id });
- }
-
- function saveEdit(id) {
- var c = state.comments.find(function (x) { return x.id === id; });
- if (!c) return;
- c.content = state.editContent;
- c.priority = state.editPriority;
- state.editingId = null;
- render(); applyHighlights();
- api('PUT', { id: id, content: c.content, priority: c.priority });
- }
-
- function submitReply(parentId) {
- if (!state.replyText.trim() || !state.username) return;
- var r = {
- id: genId(), author: state.username, type: 'comment',
- quote: '', quoteContext: { beforeText: '', afterText: '' },
- content: state.replyText.trim(), priority: 'want',
- parentId: parentId, pageUrl: window.location.href,
- projectSlug: slug, timestamp: Date.now(),
- };
- state.comments.push(r);
- state.replyingTo = null;
- state.replyText = '';
- render();
- api('POST', r);
- }
-
- // ===== Text Selection =====
- function setupTextSelection() {
- document.addEventListener('mouseup', function (e) {
- if (e.target.closest('#fb-sidebar,#fb-toggle,#fb-popup')) return;
- var sel = window.getSelection();
- var text = sel?.toString().trim();
- if (!text || !sel || sel.rangeCount === 0 || !state.username) return;
- var range = sel.getRangeAt(0);
- state.selectedText = text.replace(/[\s\u00A0]+/g, ' ').substring(0, 200);
- state.selectedRect = range.getBoundingClientRect();
- state.selectedQuoteContext = getQuoteContext(range);
- state.popupContent = '';
- render();
- });
- document.addEventListener('mousedown', function (e) {
- if (e.target.closest('#fb-popup')) return;
- if (state.selectedRect) closePopup();
- });
- }
-
- function getQuoteContext(range) {
- var before = '', after = '';
- try {
- var br = document.createRange();
- br.setStart(document.body, 0);
- br.setEnd(range.startContainer, range.startOffset);
- before = br.toString().slice(-50).replace(/[\s\u00A0]+/g, ' ').trim();
- var ar = document.createRange();
- ar.setStart(range.endContainer, range.endOffset);
- ar.setEnd(document.body, document.body.childNodes.length);
- after = ar.toString().slice(0, 50).replace(/[\s\u00A0]+/g, ' ').trim();
- } catch (e) { /* ignore */ }
- return { beforeText: before, afterText: after };
- }
-
- // ===== Highlights =====
- function collectTextNodes() {
- var nodes = [];
- var tw = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT, {
- acceptNode: function (n) {
- var p = n.parentElement;
- if (!p) return NodeFilter.FILTER_REJECT;
- if (p.tagName === 'SCRIPT' || p.tagName === 'STYLE') return NodeFilter.FILTER_REJECT;
- if (p.closest('#fb-sidebar,#fb-toggle,#fb-popup,.fb-highlight')) return NodeFilter.FILTER_REJECT;
- return NodeFilter.FILTER_ACCEPT;
- }
- });
- var n;
- while ((n = tw.nextNode())) nodes.push(n);
- return nodes;
- }
-
- function mapNormToOrig(orig, normStart, normEnd) {
- var ws = /[\s\u00A0]+/g;
- var normalized = orig.replace(ws, ' ');
- if (normStart >= normalized.length) return null;
- var origIdx = 0, normIdx = 0;
- var origStart = -1, origEnd = -1;
- while (origIdx < orig.length) {
- if (normIdx === normStart && origStart === -1) origStart = origIdx;
- if (normIdx === normEnd) { origEnd = origIdx; break; }
- if (normIdx < normalized.length && orig[origIdx] === normalized[normIdx]) {
- origIdx++; normIdx++;
- } else {
- origIdx++;
- }
- }
- if (origEnd === -1 && normIdx >= normEnd) origEnd = origIdx;
- if (origStart === -1 || origEnd === -1 || origStart >= origEnd) return null;
- return [origStart, origEnd];
- }
-
- function wrapTextRange(node, start, end, comment) {
- var orig = node.textContent;
- var before = document.createTextNode(orig.substring(0, start));
- var mark = document.createElement('mark');
- mark.className = 'fb-highlight fb-highlight-' + comment.priority;
- mark.dataset.commentId = comment.id;
- mark.textContent = orig.substring(start, end);
- (function (id) {
- mark.addEventListener('click', function () { scrollToCard(id); });
- })(comment.id);
- var after = document.createTextNode(orig.substring(end));
- node.parentNode.insertBefore(before, node);
- node.parentNode.insertBefore(mark, node);
- node.parentNode.insertBefore(after, node);
- node.parentNode.removeChild(node);
- }
-
- function applyHighlights() {
- document.querySelectorAll('.fb-highlight').forEach(function (el) {
- var t = document.createTextNode(el.textContent);
- el.parentNode.replaceChild(t, el);
- });
- document.body.normalize();
-
- state.comments.filter(function (c) { return !c.parentId && !c.resolved && c.quote && c.quote.length >= 2; }).forEach(function (c) {
- var search = c.quote.replace(/[\s\u00A0]+/g, ' ').trim();
- var textNodes = collectTextNodes();
- var found = false;
-
- for (var i = 0; i < textNodes.length; i++) {
- var node = textNodes[i];
- var orig = node.textContent;
-
- var di = orig.indexOf(search);
- if (di !== -1) {
- try { wrapTextRange(node, di, di + search.length, c); found = true; } catch (e) {}
- break;
- }
-
- var norm = orig.replace(/[\s\u00A0]+/g, ' ');
- var ni = norm.indexOf(search);
- if (ni === -1) continue;
- var range = mapNormToOrig(orig, ni, ni + search.length);
- if (range) {
- try { wrapTextRange(node, range[0], range[1], c); found = true; } catch (e) {}
- break;
- }
- }
-
- if (!found) {
- var concat = '';
- var nodeMap = [];
- for (var j = 0; j < textNodes.length; j++) {
- var s = concat.length;
- concat += textNodes[j].textContent;
- nodeMap.push({ node: textNodes[j], start: s, end: concat.length });
- }
- var concatNorm = concat.replace(/[\s\u00A0]+/g, ' ');
- var ci = concatNorm.indexOf(search);
- if (ci !== -1) {
- var range = mapNormToOrig(concat, ci, ci + search.length);
- if (range) {
- var mStart = range[0], mEnd = range[1];
- for (var k = nodeMap.length - 1; k >= 0; k--) {
- var nm = nodeMap[k];
- if (nm.end <= mStart || nm.start >= mEnd) continue;
- var ls = Math.max(0, mStart - nm.start);
- var le = Math.min(nm.node.textContent.length, mEnd - nm.start);
- try { wrapTextRange(nm.node, ls, le, c); } catch (e) {}
- }
- }
- }
- }
- });
- }
-
- var PRIORITY_FLASH = { must: 'rgba(239,68,68,0.4)', better: 'rgba(245,158,11,0.4)', want: 'rgba(34,197,94,0.4)' };
-
- function scrollToQuote(id) {
- var mark = document.querySelector('.fb-highlight[data-comment-id="' + id + '"]');
- if (!mark) return;
- mark.scrollIntoView({ behavior: 'smooth', block: 'center' });
- var c = state.comments.find(function (x) { return x.id === id; });
- var flashColor = c ? (PRIORITY_FLASH[c.priority] || PRIORITY_FLASH.want) : PRIORITY_FLASH.want;
- var orig = mark.style.backgroundColor;
- mark.style.backgroundColor = flashColor;
- mark.style.transition = 'background-color 0.3s';
- setTimeout(function () { mark.style.backgroundColor = orig; }, 1500);
- }
-
- function scrollToCard(id) {
- var wasClosed = !state.sidebarOpen;
- if (wasClosed) { toggleSidebar(); }
- setTimeout(function () {
- var card = document.querySelector('.fb-card[data-id="' + id + '"]');
- if (!card) return;
- card.scrollIntoView({ behavior: 'smooth', block: 'center' });
- card.classList.add('fb-focused');
- setTimeout(function () { card.classList.remove('fb-focused'); }, 1500);
- }, wasClosed ? 350 : 0);
- }
-
- // ===== Init =====
- function init() {
- injectStyles();
- render();
- setupTextSelection();
- loadComments();
- }
-
- if (document.readyState === 'loading') {
- document.addEventListener('DOMContentLoaded', init);
- } else {
- init();
- }
-})();
+"use strict";(()=>{var k={must:{bg:"#ef4444",text:"#fff",light:"rgba(239,68,68,0.1)",border:"rgba(239,68,68,0.3)"},better:{bg:"#f59e0b",text:"#fff",light:"rgba(245,158,11,0.1)",border:"rgba(245,158,11,0.3)"},want:{bg:"#22c55e",text:"#fff",light:"rgba(34,197,94,0.1)",border:"rgba(34,197,94,0.3)"}};var _={must:"better",better:"want",want:"must"};var S="fb-username",M="fb-sidebar-width";function W(t){return t.replace(/^https?:\/\//,"").replace(/[^a-zA-Z0-9\u3040-\u309F\u30A0-\u30FF\u4E00-\u9FFF]/g,"_").substring(0,100)}function z(){return Date.now().toString(36)+Math.random().toString(36).substring(2,8)}function j(t){let e={"Content-Type":"application/json"};return t&&(e.Authorization="Bearer "+t),e}var q="",F="";function D(t,e){q=t,F=e}function y(t,e){let n=q+"/api/comments",r=j(F),s={method:t,headers:r};return t==="GET"?n+="?slug="+encodeURIComponent(e.slug):t==="DELETE"?n+="?id="+encodeURIComponent(e.id):s.body=JSON.stringify(e),fetch(n,s).then(i=>i.json())}var o={username:localStorage.getItem(S)||"",comments:[],filter:"unresolved",sidebarOpen:!1,selectedText:"",selectedQuoteContext:{beforeText:"",afterText:""},selectedRect:null,popupContent:"",editingId:null,editContent:"",editPriority:"want",replyingTo:null,replyText:"",editingName:!1,nameInput:"",popupPriority:"must",sidebarWidth:parseInt(localStorage.getItem(M)||"",10)||400},I=W(window.location.href);function U(){let t=document.createElement("style");t.id="fb-widget-styles",t.textContent=[':root{--fb-bg:#ffffff;--fb-fg:#0a0a0a;--fb-muted:#f5f5f5;--fb-muted-fg:#737373;--fb-border:#e5e5e5;--fb-primary:#171717;--fb-primary-fg:#fafafa;--fb-accent:#3b82f6;--fb-destructive:#ef4444;--fb-font:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Hiragino Sans",sans-serif}',"#fb-toggle{position:fixed;right:0;top:50%;transform:translateY(-50%);width:36px;background:var(--fb-bg);border:1px solid var(--fb-border);border-right:none;border-radius:8px 0 0 8px;cursor:pointer;z-index:99999;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;font-family:var(--fb-font);transition:all .15s;box-shadow:-2px 0 8px rgba(0,0,0,0.06);padding:8px 0}","#fb-toggle:hover{background:var(--fb-muted);box-shadow:-2px 0 12px rgba(0,0,0,0.1)}","#fb-toggle .fb-toggle-icon{color:var(--fb-muted-fg);display:flex;align-items:center;justify-content:center;position:relative}","#fb-toggle .fb-toggle-label{font-size:10px;color:var(--fb-accent);font-weight:700;writing-mode:vertical-rl;letter-spacing:1px;line-height:1;white-space:nowrap}","#fb-toggle .fb-badge{position:absolute;top:-6px;left:-6px;background:var(--fb-destructive);color:#fff;font-size:9px;font-weight:700;min-width:16px;height:16px;border-radius:8px;display:flex;align-items:center;justify-content:center;padding:0 3px;line-height:1}","#fb-sidebar{position:fixed;top:0;height:100vh;background:rgba(245,245,245,0.5);border-left:1px solid var(--fb-border);z-index:99998;transition:right .3s ease;display:flex;flex-direction:column;font-family:var(--fb-font);font-size:14px;color:var(--fb-fg)}","#fb-sidebar *{box-sizing:border-box}",".fb-resize-handle{position:absolute;left:-3px;top:0;width:6px;height:100%;cursor:col-resize;z-index:1}",".fb-resize-handle:hover{background:rgba(59,130,246,0.15)}",".fb-resize-handle.active{background:rgba(59,130,246,0.3)}","body.fb-resizing{cursor:col-resize !important;-webkit-user-select:none !important;user-select:none !important}","body.fb-resizing *{cursor:col-resize !important}",".fb-header{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-bottom:1px solid var(--fb-border)}",".fb-header-left{display:flex;align-items:center;gap:8px}",".fb-header-title{font-size:14px;font-weight:700;color:var(--fb-accent)}",".fb-header-count{background:var(--fb-muted);color:var(--fb-muted-fg);font-size:11px;padding:1px 7px;border-radius:10px}",".fb-header-actions{display:flex;align-items:center;gap:2px}",".fb-hdr-btn{background:none;border:none;cursor:pointer;padding:6px;border-radius:6px;color:var(--fb-muted-fg);transition:all .15s;display:inline-flex;align-items:center;gap:4px;font-family:var(--fb-font);font-size:12px}",".fb-hdr-btn:hover{background:var(--fb-muted);color:var(--fb-fg)}",".fb-user-row{display:flex;align-items:center;padding:8px 16px;border-bottom:1px solid var(--fb-border);font-size:13px;color:var(--fb-muted-fg);cursor:pointer;transition:color .15s;gap:6px}",".fb-user-row:hover{color:var(--fb-fg)}",".fb-filters{display:flex;border-bottom:1px solid var(--fb-border)}",".fb-filter{flex:1;padding:10px 0;text-align:center;font-size:13px;color:var(--fb-muted-fg);border:none;background:none;cursor:pointer;border-bottom:2px solid transparent;transition:all .15s;font-family:var(--fb-font)}",".fb-filter:hover{color:var(--fb-fg)}",".fb-filter.active{color:var(--fb-fg);border-bottom-color:var(--fb-accent)}",".fb-filter .cnt{font-size:11px;margin-left:4px;padding:1px 5px;border-radius:8px;background:var(--fb-muted);color:var(--fb-muted-fg)}",".fb-filter.active .cnt{background:rgba(59,130,246,0.1);color:var(--fb-accent)}",".fb-list{flex:1;overflow-y:auto;padding:8px}",".fb-empty{text-align:center;padding:60px 20px;color:var(--fb-muted-fg);font-size:13px}",".fb-empty svg{margin:0 auto 12px;display:block;color:var(--fb-border)}",".fb-card{background:var(--fb-bg);border:1px solid var(--fb-border);border-left:3px solid var(--fb-border);border-radius:12px;padding:14px;margin-bottom:6px;transition:box-shadow .3s,background .3s;cursor:pointer}",".fb-card:hover{box-shadow:0 1px 3px rgba(0,0,0,0.05)}",".fb-card.resolved{opacity:.5}",".fb-card-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:4px}",".fb-card-head-left{display:flex;align-items:center;gap:6px}",".fb-avatar{width:22px;height:22px;border-radius:50%;background:var(--fb-primary);color:var(--fb-primary-fg);display:flex;align-items:center;justify-content:center;font-size:10px;font-weight:700;flex-shrink:0}",".fb-author{font-size:13px;font-weight:700;color:var(--fb-fg)}",".fb-time{font-size:11px;color:var(--fb-muted-fg)}",".fb-resolved-mark{font-size:11px;color:#22c55e;margin-left:4px;display:inline-flex;align-items:center;gap:2px}",".fb-badge-p{font-size:11px;font-weight:700;padding:2px 8px;border-radius:4px;color:#fff;cursor:default;transition:all .15s}",".fb-badge-p.own{cursor:pointer}",".fb-badge-p.own:hover{transform:scale(1.1);box-shadow:0 0 0 2px rgba(0,0,0,0.08)}",".fb-quote{font-size:12px;color:var(--fb-muted-fg);padding:6px 10px;background:var(--fb-muted);border-left:2px solid var(--fb-primary);border-radius:0 4px 4px 0;margin-bottom:8px;font-style:italic;line-height:1.5;cursor:pointer;transition:background .15s}",".fb-quote:hover{background:var(--fb-border)}",".fb-body{font-size:13px;color:var(--fb-muted-fg);line-height:1.6;margin-bottom:6px;white-space:pre-wrap}",".fb-actions{display:flex;gap:2px;flex-wrap:wrap}",".fb-act{font-size:12px;color:#a3a3a3;background:none;border:none;padding:4px 8px;border-radius:4px;cursor:pointer;transition:all .15s;display:inline-flex;align-items:center;gap:3px;font-family:var(--fb-font)}",".fb-act:hover{color:var(--fb-fg)}",".fb-act.del:hover{color:var(--fb-destructive)}",".fb-act.res:hover{color:#22c55e}",".fb-replies{margin-top:8px;padding-top:8px;border-top:1px solid var(--fb-muted)}",".fb-reply-item{display:flex;gap:8px;padding:6px 0}",".fb-reply-item+.fb-reply-item{border-top:1px solid var(--fb-muted)}",".fb-reply-avatar{width:20px;height:20px;border-radius:50%;background:var(--fb-primary);color:var(--fb-primary-fg);display:flex;align-items:center;justify-content:center;font-size:9px;font-weight:700;flex-shrink:0;margin-top:2px}",".fb-reply-meta{font-size:12px;color:var(--fb-muted-fg);margin-bottom:2px}",".fb-reply-meta strong{color:#525252;font-weight:700}",".fb-reply-text{font-size:13px;color:var(--fb-muted-fg);line-height:1.5}",".fb-reply-input{display:flex;gap:8px;margin-top:8px}",".fb-reply-input textarea{flex:1;padding:8px 10px;border:1px solid var(--fb-border);border-radius:6px;font-size:13px;font-family:var(--fb-font);resize:none;outline:none;min-height:36px;color:var(--fb-fg)}",".fb-reply-input textarea:focus{border-color:var(--fb-accent)}",".fb-reply-input button{padding:6px 14px;background:var(--fb-primary);color:var(--fb-primary-fg);border:none;border-radius:6px;font-size:12px;cursor:pointer;font-family:var(--fb-font);align-self:flex-end}",".fb-reply-input button:disabled{opacity:.4;cursor:default}",".fb-edit-area textarea{width:100%;padding:8px 10px;border:1px solid var(--fb-border);border-radius:6px;font-size:13px;font-family:var(--fb-font);resize:vertical;outline:none;min-height:50px;margin-bottom:6px;color:var(--fb-fg)}",".fb-edit-area textarea:focus{border-color:var(--fb-accent)}",".fb-edit-btns{display:flex;gap:6px}",".fb-edit-btns button{padding:4px 12px;border-radius:6px;font-size:12px;cursor:pointer;border:1px solid var(--fb-border);background:var(--fb-bg);color:var(--fb-muted-fg);font-family:var(--fb-font)}",".fb-edit-btns button.save{background:var(--fb-primary);color:var(--fb-primary-fg);border-color:var(--fb-primary)}",".fb-edit-pri{display:flex;gap:4px;margin-bottom:6px}",".fb-edit-pri button{padding:2px 10px;border-radius:4px;font-size:11px;font-weight:700;cursor:pointer;border:1px solid var(--fb-border);background:var(--fb-bg);color:var(--fb-muted-fg);font-family:var(--fb-font);transition:all .15s}",".fb-popup{position:fixed;z-index:100000;width:400px;background:var(--fb-bg);border:1px solid var(--fb-border);border-radius:12px;padding:16px;box-shadow:0 10px 25px rgba(0,0,0,0.1);font-family:var(--fb-font);display:none}",".fb-popup.show{display:block}",".fb-popup-head{margin-bottom:10px}",".fb-popup-head span{font-size:14px;font-weight:700;color:var(--fb-fg)}",".fb-popup-quote{font-size:13px;color:var(--fb-muted-fg);padding:8px 12px;background:var(--fb-muted);border-left:2px solid var(--fb-accent);border-radius:0 6px 6px 0;margin-bottom:10px;font-style:italic;line-height:1.5}",".fb-popup textarea{width:100%;min-height:70px;padding:10px 12px;border:1px solid var(--fb-border);border-radius:8px;font-size:14px;font-family:var(--fb-font);resize:vertical;outline:none;margin-bottom:10px;color:var(--fb-fg)}",".fb-popup textarea:focus{border-color:var(--fb-accent)}",".fb-popup textarea::placeholder{color:var(--fb-muted-fg)}",".fb-popup-pri{display:flex;gap:6px;margin-bottom:10px}",".fb-popup-pri button{flex:1;padding:7px 8px;border-radius:8px;font-size:13px;font-weight:600;cursor:pointer;border:2px solid transparent;transition:all .15s;font-family:var(--fb-font)}",".fb-popup-actions{display:flex;gap:8px;justify-content:flex-end}",".fb-popup-actions button{padding:8px 18px;border-radius:8px;font-size:13px;font-weight:600;cursor:pointer;transition:all .15s;font-family:var(--fb-font)}",".fb-popup-actions .cancel{background:none;border:1px solid var(--fb-border);color:var(--fb-muted-fg)}",".fb-popup-actions .cancel:hover{background:var(--fb-muted);color:var(--fb-fg)}",".fb-popup-actions .submit{border:none;color:#fff}",".fb-name-overlay{position:fixed;inset:0;background:rgba(0,0,0,0.4);display:flex;align-items:center;justify-content:center;z-index:100001}",".fb-name-box{background:var(--fb-bg);border-radius:12px;padding:28px;width:360px;box-shadow:0 20px 40px rgba(0,0,0,0.15)}",".fb-name-box h2{font-size:18px;font-weight:700;margin:0 0 6px;color:var(--fb-fg)}",".fb-name-box p{font-size:14px;color:var(--fb-muted-fg);margin:0 0 16px}",".fb-name-box input{width:100%;padding:10px 14px;border:1px solid var(--fb-border);border-radius:8px;font-size:15px;outline:none;margin-bottom:12px;font-family:var(--fb-font);color:var(--fb-fg)}",".fb-name-box input:focus{border-color:var(--fb-accent)}",".fb-name-box input::placeholder{color:var(--fb-muted-fg)}",".fb-name-box button{width:100%;padding:10px;background:var(--fb-primary);color:var(--fb-primary-fg);border:none;border-radius:8px;font-size:14px;font-weight:600;cursor:pointer;font-family:var(--fb-font)}",".fb-name-box button:disabled{opacity:.4;cursor:default}",".fb-name-input{width:100%;padding:4px 8px;border:1px solid var(--fb-border);border-radius:4px;font-size:12px;outline:none;font-family:var(--fb-font);color:var(--fb-fg)}",".fb-name-input:focus{border-color:var(--fb-accent)}",".fb-highlight{padding:1px 0;cursor:pointer;transition:background .15s}",".fb-highlight-must{background:rgba(239,68,68,0.15);border-bottom:2px solid #ef4444}",".fb-highlight-must:hover{background:rgba(239,68,68,0.25)}",".fb-highlight-better{background:rgba(245,158,11,0.15);border-bottom:2px solid #f59e0b}",".fb-highlight-better:hover{background:rgba(245,158,11,0.25)}",".fb-highlight-want{background:rgba(34,197,94,0.15);border-bottom:2px solid #22c55e}",".fb-highlight-want:hover{background:rgba(34,197,94,0.25)}","@keyframes fb-pulse{0%,100%{opacity:1}50%{opacity:0.4}}",".fb-highlight.fb-pulse{animation:fb-pulse 1s ease-in-out infinite}",".fb-card.fb-focused{box-shadow:0 0 0 2px var(--fb-accent);background:rgba(59,130,246,0.04)}","#fb-sidebar svg,#fb-toggle svg,.fb-popup svg{pointer-events:none}"].join(`
+`),document.head.appendChild(t)}function w(t,e,n){let r=document.createElement(t);return e&&Object.keys(e).forEach(s=>{let i=e[s];s==="className"?r.className=i:s==="innerHTML"?r.innerHTML=i:s.startsWith("on")&&typeof i=="function"?r.addEventListener(s.substring(2).toLowerCase(),i):r.setAttribute(s,String(i))}),n!=null&&(typeof n=="string"?r.textContent=n:Array.isArray(n)?n.forEach(s=>{s&&r.appendChild(s)}):r.appendChild(n)),r}function f(t){let e=document.createElement("div");return e.textContent=t,e.innerHTML}var lt={message:'',check:'',rotateCcw:'',pencil:'',trash:'',user:'',x:'',panelRight:''};function b(t,e=14,n=2){return(lt[t]||"").replace(/SIZE/g,String(e)).replace(/SW/g,String(n))}function Y(t){let e=document.getElementById("fb-toggle");e||(e=w("button",{id:"fb-toggle",onClick:t}),document.body.appendChild(e));let n=o.comments.filter(s=>!s.parentId&&!s.resolved).length,r=''+b("panelRight",16);n>0&&(r+=''+n+""),r+="",r+='\u30B3\u30E1\u30F3\u30C8',e.innerHTML=r,e.style.display=o.sidebarOpen?"none":""}function A(t){let e=Date.now()-t;return e<6e4?"\u305F\u3063\u305F\u4ECA":e<36e5?Math.floor(e/6e4)+"\u5206\u524D":e<864e5?Math.floor(e/36e5)+"\u6642\u9593\u524D":new Date(t).toLocaleDateString("ja-JP",{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"})}function Z(t){let e=t.author===o.username,n=k[t.priority]||k.want,r='';if(r+='
',r+='
'+f(t.author.charAt(0))+"
",r+='
'+f(t.author)+"",r+='
'+A(t.timestamp)+"",t.resolved&&(r+='
'+b("check",12)+" \u89E3\u6C7A\u6E08"),r+="
",r+='
'+f(t.priority.charAt(0).toUpperCase()+t.priority.slice(1))+"",r+="
",t.quote){let i=t.quote.length>100?t.quote.substring(0,100)+"...":t.quote;r+='
'+f(i)+"
"}o.editingId===t.id?(r+='
',r+='
',["must","better","want"].forEach(i=>{let d=o.editPriority===i,a=k[i];r+='"}),r+="
",r+='
",r+='
',r+="
"):r+='
'+f(t.content)+"
",o.editingId!==t.id&&(r+='
',r+='",r+='",e&&(r+='"),e&&(r+='"),r+="
");let s=o.comments.filter(i=>i.parentId===t.id).sort((i,d)=>i.timestamp-d.timestamp);return s.length>0&&(r+='
',s.forEach(i=>{let d=i.author===o.username;r+='
'+f(i.author.charAt(0))+'
'+f(i.author)+" · "+A(i.timestamp)+"
",o.editingId===i.id?r+='
':(r+='
'+f(i.content)+"
",r+='
',r+='",d&&(r+='"),d&&(r+='"),r+="
"),r+="
"}),r+="
"),o.replyingTo===t.id&&(r+='
"),r+="
",r}function Q(){let t=document.getElementById("fb-sidebar");if(!t)return;let e=o.sidebarWidth;t.style.width=e+"px",t.style.right=o.sidebarOpen?"0px":-(e+20)+"px",document.body.style.marginRight=o.sidebarOpen?e+"px":""}function L(){o.sidebarOpen=!o.sidebarOpen;let t=document.getElementById("fb-toggle");t&&(t.style.display=o.sidebarOpen?"none":""),document.body.style.transition="margin-right 0.3s ease",Q()}function K(){return o.comments.filter(t=>!t.parentId)}function pt(){let t=K();return o.filter==="resolved"?t.filter(e=>e.resolved):o.filter==="all"?t:t.filter(e=>!e.resolved)}function V(t){let e=document.getElementById("fb-sidebar"),n=!e;n&&(e=w("div",{id:"fb-sidebar"}),document.body.appendChild(e),e.addEventListener("mouseover",a=>{let l=a.target.closest(".fb-card");if(!l)return;let p=document.querySelector('.fb-highlight[data-comment-id="'+l.dataset.id+'"]');p&&p.classList.add("fb-pulse")}),e.addEventListener("mouseout",a=>{let l=a.target.closest(".fb-card");if(!l||a.relatedTarget&&l.contains(a.relatedTarget))return;let p=document.querySelector('.fb-highlight[data-comment-id="'+l.dataset.id+'"]');p&&p.classList.remove("fb-pulse")})),Q();let r=K(),s={unresolved:r.filter(a=>!a.resolved).length,resolved:r.filter(a=>a.resolved).length,all:r.length},i='';i+='",o.username&&(o.editingName?i+='':i+=''+b("user",14)+f(o.username)+"
"),i+='',["unresolved","resolved","all"].forEach(a=>{let l=a==="unresolved"?"\u672A\u89E3\u6C7A":a==="resolved"?"\u89E3\u6C7A\u6E08":"\u3059\u3079\u3066";i+='"}),i+="
";let d=pt().sort((a,l)=>l.timestamp-a.timestamp);i+='',d.length===0?i+='
'+b("message",40)+'\u30B3\u30E1\u30F3\u30C8\u306F\u307E\u3060\u3042\u308A\u307E\u305B\u3093
\u30C6\u30AD\u30B9\u30C8\u3092\u9078\u629E\u3057\u3066\u30B3\u30E1\u30F3\u30C8\u3092\u8FFD\u52A0
':d.forEach(a=>{i+=Z(a)}),i+="
",e.innerHTML=i,n&&ft(e,t)}var g=null;function G(t){g=t}function ft(t,e){t.addEventListener("click",n=>{let r=n.target.closest("[data-action]");if(r){let d=r.dataset.action,a=r.dataset.id;if(d==="close")g?.toggleSidebar();else if(d==="edit-name")o.editingName=!0,o.nameInput=o.username,e();else if(d==="cycle"&&a)g?.cyclePriority(a);else if(d==="scroll-quote"&&a)g?.scrollToQuote(a);else if(d==="reply"&&a)o.replyingTo=o.replyingTo===a?null:a,o.replyText="",e();else if(d==="resolve"&&a)g?.resolveComment(a);else if(d==="edit"&&a){let l=o.comments.find(p=>p.id===a);l&&(o.editingId=a,o.editContent=l.content,o.editPriority=l.priority,e())}else d==="delete"&&a?g?.deleteComment(a):d==="delete-reply"&&a?g?.deleteReply(a):d==="cancel-edit"?(o.editingId=null,e()):d==="save-edit"&&a?g?.saveEdit(a):d==="submit-reply"&&a?g?.submitReply(a):d==="set-edit-pri"&&(o.editPriority=r.dataset.pri,e());return}let s=n.target.closest("[data-filter]");if(s){o.filter=s.dataset.filter,e();return}let i=n.target.closest(".fb-card");i&&i.dataset.id&&g?.scrollToQuote(i.dataset.id)}),t.addEventListener("mousedown",n=>{if(!n.target.closest(".fb-resize-handle"))return;n.preventDefault();let r=n.clientX,s=o.sidebarWidth,i=n.target.closest(".fb-resize-handle");document.body.classList.add("fb-resizing"),i.classList.add("active");function d(l){o.sidebarWidth=Math.min(800,Math.max(300,s+(r-l.clientX)));let p=document.getElementById("fb-sidebar");p&&(p.style.width=o.sidebarWidth+"px"),document.body.style.transition="none",document.body.style.marginRight=o.sidebarWidth+"px"}function a(){document.removeEventListener("mousemove",d),document.removeEventListener("mouseup",a),document.body.classList.remove("fb-resizing"),i.classList.remove("active"),document.body.style.transition="",localStorage.setItem(M,String(o.sidebarWidth))}document.addEventListener("mousemove",d),document.addEventListener("mouseup",a)}),t.addEventListener("input",n=>{let r=n.target;if(r.dataset.action==="name-input")o.nameInput=r.value;else if(r.dataset.action==="edit-textarea")o.editContent=r.value;else if(r.dataset.action==="reply-textarea"){o.replyText=r.value;let s=t.querySelector('[data-action="submit-reply"]');s&&(s.disabled=!o.replyText.trim())}}),t.addEventListener("keydown",n=>{let r=n.target;if(r.dataset.action==="name-input"&&(n.key==="Enter"?g?.finishNameEdit():n.key==="Escape"&&(o.editingName=!1,e())),r.dataset.action==="reply-textarea"&&(n.metaKey||n.ctrlKey)&&n.key==="Enter"){let s=t.querySelector('[data-action="submit-reply"]')?.dataset.id;s&&g?.submitReply(s)}}),t.addEventListener("blur",n=>{n.target.dataset?.action==="name-input"&&g?.finishNameEdit()},!0)}function J(t,e,n){let r=document.getElementById("fb-popup");if(!r&&(r=w("div",{id:"fb-popup",className:"fb-popup"}),document.body.appendChild(r),r.addEventListener("click",c=>{let h=c.target.closest("[data-action]");h&&(h.dataset.action==="cancel-popup"?e():h.dataset.action==="set-popup-pri"?(o.popupPriority=h.dataset.pri,t()):h.dataset.action==="submit-popup"&&n(o.popupPriority))}),r.addEventListener("input",c=>{c.target.dataset.action==="popup-textarea"&&(o.popupContent=c.target.value)}),r.addEventListener("keydown",c=>{c.target.dataset.action==="popup-textarea"&&(c.metaKey||c.ctrlKey)&&c.key==="Enter"&&n(o.popupPriority)})),!o.selectedRect){r.classList.remove("show");return}r.classList.add("show");let i=o.selectedText.length>120?o.selectedText.substring(0,120)+"...":o.selectedText,d=k[o.popupPriority],a='';a+='",a+='",a+='",a+='",r.innerHTML=a;let l=o.selectedRect,p=400,x=300,m=12,v=l.bottom+m;v+x>window.innerHeight&&(v=l.top-x-m),v\u3088\u3046\u3053\u305D
\u30B3\u30E1\u30F3\u30C8\u306B\u8868\u793A\u3055\u308C\u308B\u540D\u524D\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044\u3002
',document.body.appendChild(n);let r=document.getElementById("fb-name-field"),s=document.getElementById("fb-name-submit");r.addEventListener("input",()=>{s.disabled=!r.value.trim()}),r.addEventListener("keydown",i=>{i.key==="Enter"&&r.value.trim()&&X(r.value.trim(),t)}),s.addEventListener("click",()=>{r.value.trim()&&X(r.value.trim(),t)}),setTimeout(()=>{r.focus()},100)}function X(t,e){o.username=t,localStorage.setItem(S,t);let n=document.getElementById("fb-name-overlay");n&&n.remove(),e()}var tt=null,et=null;function rt(t,e){tt=t,et=e}function u(){Y(L),V(u),J(u,tt,et),$(u)}function ct(){let t=[],e=document.createTreeWalker(document.body,NodeFilter.SHOW_TEXT,{acceptNode(r){let s=r.parentElement;return!s||s.tagName==="SCRIPT"||s.tagName==="STYLE"||s.closest("#fb-sidebar,#fb-toggle,#fb-popup,.fb-highlight")?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT}}),n;for(;n=e.nextNode();)t.push(n);return t}function ot(t,e,n){let r=t.replace(/[\s\u00A0]+/g," ");if(e>=r.length)return null;let s=0,i=0,d=-1,a=-1;for(;s=n&&(a=s),d===-1||a===-1||d>=a?null:[d,a]}function H(t,e,n,r,s){let i=t.textContent,d=document.createTextNode(i.substring(0,e)),a=document.createElement("mark");a.className="fb-highlight fb-highlight-"+r.priority,a.dataset.commentId=r.id,a.textContent=i.substring(e,n),a.addEventListener("click",()=>{s(r.id)});let l=document.createTextNode(i.substring(n));t.parentNode.insertBefore(d,t),t.parentNode.insertBefore(a,t),t.parentNode.insertBefore(l,t),t.parentNode.removeChild(t)}function T(t){document.querySelectorAll(".fb-highlight").forEach(e=>{let n=document.createTextNode(e.textContent||"");e.parentNode.replaceChild(n,e)}),document.body.normalize(),o.comments.filter(e=>!e.parentId&&!e.resolved&&e.quote&&e.quote.length>=2).forEach(e=>{let n=e.quote.replace(/[\s\u00A0]+/g," ").trim(),r=ct(),s=!1;for(let i=0;i=0;v--){let E=d[v];if(E.end<=x||E.start>=m)continue;let P=Math.max(0,x-E.start),c=Math.min(E.node.textContent.length,m-E.start);try{H(E.node,P,c,e,t)}catch{}}}}}})}var N={must:"rgba(239,68,68,0.4)",better:"rgba(245,158,11,0.4)",want:"rgba(34,197,94,0.4)"};function nt(t){let e=document.querySelector('.fb-highlight[data-comment-id="'+t+'"]');if(!e)return;e.scrollIntoView({behavior:"smooth",block:"center"});let n=o.comments.find(i=>i.id===t),r=n&&N[n.priority]||N.want,s=e.style.backgroundColor;e.style.backgroundColor=r,e.style.transition="background-color 0.3s",setTimeout(()=>{e.style.backgroundColor=s},1500)}function it(t,e){let n=!o.sidebarOpen;n&&e(),setTimeout(()=>{let r=document.querySelector('.fb-card[data-id="'+t+'"]');r&&(r.scrollIntoView({behavior:"smooth",block:"center"}),r.classList.add("fb-focused"),setTimeout(()=>{r.classList.remove("fb-focused")},1500))},n?350:0)}function bt(t){let e="",n="";try{let r=document.createRange();r.setStart(document.body,0),r.setEnd(t.startContainer,t.startOffset),e=r.toString().slice(-50).replace(/[\s\u00A0]+/g," ").trim();let s=document.createRange();s.setStart(t.endContainer,t.endOffset),s.setEnd(document.body,document.body.childNodes.length),n=s.toString().slice(0,50).replace(/[\s\u00A0]+/g," ").trim()}catch{}return{beforeText:e,afterText:n}}function at(t,e){document.addEventListener("mouseup",n=>{if(n.target.closest("#fb-sidebar,#fb-toggle,#fb-popup"))return;let r=window.getSelection(),s=r?.toString().trim();if(!s||!r||r.rangeCount===0||!o.username)return;let i=r.getRangeAt(0);o.selectedText=s.replace(/[\s\u00A0]+/g," ").substring(0,200),o.selectedRect=i.getBoundingClientRect(),o.selectedQuoteContext=bt(i),o.popupContent="",t()}),document.addEventListener("mousedown",n=>{n.target.closest("#fb-popup")||o.selectedRect&&e()})}var R=document.currentScript,ut=R?R.src.replace(/\/widget\.js.*$/,""):"",mt=R&&R.dataset.token||"";D(ut,mt);function B(){return y("GET",{slug:I}).then(t=>{Array.isArray(t)&&(o.comments=t),u(),T(C)}).catch(()=>{u(),T(C)})}function O(){o.selectedText="",o.selectedRect=null,o.popupContent="",o.popupPriority="must",u()}function gt(t){if(!o.username||!o.selectedText)return;let e={id:z(),author:o.username,type:"comment",quote:o.selectedText,quoteContext:o.selectedQuoteContext,content:o.popupContent.trim(),priority:t,parentId:null,pageUrl:window.location.href,projectSlug:I,timestamp:Date.now(),resolved:!1,resolvedBy:null,resolvedAt:null,updatedAt:null};o.comments.push(e),O(),T(C),y("POST",e).then(B)}function xt(t){let e=o.comments.find(r=>r.id===t);if(!e)return;let n=!e.resolved;e.resolved=n,e.resolvedBy=n?o.username:null,e.resolvedAt=n?Date.now():null,u(),T(C),y("PUT",{id:t,action:"resolve",resolved:n,resolvedBy:e.resolvedBy,resolvedAt:e.resolvedAt})}function vt(t){let e=o.comments.find(n=>n.id===t);!e||e.author!==o.username||(e.priority=_[e.priority]||"must",u(),T(C),y("PUT",{id:t,action:"cyclePriority",priority:e.priority}))}function ht(t){o.comments=o.comments.filter(e=>e.id!==t&&e.parentId!==t),u(),T(C),y("DELETE",{id:t})}function yt(t){o.comments=o.comments.filter(e=>e.id!==t),u(),y("DELETE",{id:t})}function Et(t){let e=o.comments.find(n=>n.id===t);e&&(e.content=o.editContent,e.priority=o.editPriority,o.editingId=null,u(),T(C),y("PUT",{id:t,action:"edit",content:e.content,priority:e.priority}))}function wt(t){if(!o.replyText.trim()||!o.username)return;let e={id:z(),author:o.username,type:"comment",quote:"",quoteContext:{beforeText:"",afterText:""},content:o.replyText.trim(),priority:"want",parentId:t,pageUrl:window.location.href,projectSlug:I,timestamp:Date.now(),resolved:!1,resolvedBy:null,resolvedAt:null,updatedAt:null};o.comments.push(e),o.replyingTo=null,o.replyText="",u(),y("POST",e)}function Tt(){if(o.nameInput.trim()&&o.nameInput.trim()!==o.username){let t=o.username;o.username=o.nameInput.trim(),localStorage.setItem(S,o.username),y("PUT",{id:"_rename",action:"rename",author:o.username,oldAuthor:t,projectSlug:I}).then(B)}o.editingName=!1,u()}function C(t){it(t,L)}rt(O,gt);G({toggleSidebar:L,cyclePriority:vt,scrollToQuote:nt,resolveComment:xt,deleteComment:ht,deleteReply:yt,saveEdit:Et,submitReply:wt,finishNameEdit:Tt});function st(){U(),u(),at(u,O),B()}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",st):st();})();
diff --git a/public/window.svg b/public/window.svg
deleted file mode 100644
index b2b2a44..0000000
--- a/public/window.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/src/app/api/comments/route.ts b/src/app/api/comments/route.ts
index deb6c06..e7c6023 100644
--- a/src/app/api/comments/route.ts
+++ b/src/app/api/comments/route.ts
@@ -1,5 +1,6 @@
import { NextRequest, NextResponse } from 'next/server';
import { getDb } from '@/lib/db';
+import type { Comment } from '@/shared/types';
function corsHeaders() {
return {
@@ -56,35 +57,52 @@ export async function POST(request: NextRequest) {
return json({ ok: true });
}
+type PutAction = 'edit' | 'resolve' | 'cyclePriority' | 'rename';
+
export async function PUT(request: NextRequest) {
if (!verifyToken(request)) return json({ error: 'Unauthorized' }, 403);
const body = await request.json();
- const { id, ...updates } = body;
+ const { id, action } = body as { id: string; action: PutAction; [key: string]: unknown };
if (!id) return json({ error: 'id is required' }, 400);
+ if (!action) return json({ error: 'action is required' }, 400);
const sql = getDb();
- if (updates.content !== undefined && updates.priority !== undefined) {
- await sql`
- UPDATE comments SET content = ${updates.content}, priority = ${updates.priority}, updated_at = ${Date.now()} WHERE id = ${id}
- `;
- } else if (updates.resolved !== undefined) {
- await sql`
- UPDATE comments SET resolved = ${updates.resolved}, resolved_by = ${updates.resolvedBy || null}, resolved_at = ${updates.resolvedAt || null} WHERE id = ${id}
- `;
- } else if (updates.priority !== undefined) {
- await sql`
- UPDATE comments SET priority = ${updates.priority} WHERE id = ${id}
- `;
- } else if (updates.author !== undefined) {
- const slug = updates.projectSlug;
- const oldAuthor = updates.oldAuthor;
- if (slug && oldAuthor) {
+ switch (action) {
+ case 'edit': {
+ const { content, priority } = body;
+ if (content === undefined || priority === undefined) return json({ error: 'content and priority are required for edit' }, 400);
await sql`
- UPDATE comments SET author = ${updates.author} WHERE project_slug = ${slug} AND author = ${oldAuthor}
+ UPDATE comments SET content = ${content}, priority = ${priority}, updated_at = ${Date.now()} WHERE id = ${id}
`;
+ break;
}
+ case 'resolve': {
+ const { resolved, resolvedBy, resolvedAt } = body;
+ await sql`
+ UPDATE comments SET resolved = ${resolved}, resolved_by = ${resolvedBy || null}, resolved_at = ${resolvedAt || null} WHERE id = ${id}
+ `;
+ break;
+ }
+ case 'cyclePriority': {
+ const { priority } = body;
+ if (!priority) return json({ error: 'priority is required for cyclePriority' }, 400);
+ await sql`
+ UPDATE comments SET priority = ${priority} WHERE id = ${id}
+ `;
+ break;
+ }
+ case 'rename': {
+ const { author, oldAuthor, projectSlug } = body;
+ if (!author || !oldAuthor || !projectSlug) return json({ error: 'author, oldAuthor, projectSlug are required for rename' }, 400);
+ await sql`
+ UPDATE comments SET author = ${author} WHERE project_slug = ${projectSlug} AND author = ${oldAuthor}
+ `;
+ break;
+ }
+ default:
+ return json({ error: `Unknown action: ${action}` }, 400);
}
return json({ ok: true });
@@ -101,24 +119,24 @@ export async function DELETE(request: NextRequest) {
return json({ ok: true });
}
-function toComment(row: Record) {
+function toComment(row: Record): Comment {
return {
id: row.id as string,
author: row.author as string,
- type: row.type as string,
- quote: row.quote as string,
+ type: (row.type as Comment['type']) || 'comment',
+ quote: (row.quote as string) || '',
quoteContext: {
- beforeText: row.quote_context_before as string,
- afterText: row.quote_context_after as string,
+ beforeText: (row.quote_context_before as string) || '',
+ afterText: (row.quote_context_after as string) || '',
},
- content: row.content as string,
- priority: row.priority as string,
+ content: (row.content as string) || '',
+ priority: (row.priority as Comment['priority']) || 'want',
parentId: (row.parent_id as string) || null,
- resolved: row.resolved as boolean,
+ resolved: (row.resolved as boolean) || false,
resolvedBy: (row.resolved_by as string) || null,
resolvedAt: row.resolved_at ? Number(row.resolved_at) : null,
timestamp: Number(row.timestamp),
updatedAt: row.updated_at ? Number(row.updated_at) : null,
- pageUrl: row.page_url as string,
+ pageUrl: (row.page_url as string) || '',
};
}
diff --git a/src/app/api/fetch-page/route.ts b/src/app/api/fetch-page/route.ts
deleted file mode 100644
index 5bbdb02..0000000
--- a/src/app/api/fetch-page/route.ts
+++ /dev/null
@@ -1,92 +0,0 @@
-import { NextRequest, NextResponse } from 'next/server';
-
-const BLOCKED_HOSTS = new Set([
- 'localhost',
- '127.0.0.1',
- '0.0.0.0',
- '::1',
- '[::1]',
-]);
-
-function isPrivateIP(hostname: string): boolean {
- if (BLOCKED_HOSTS.has(hostname)) return true;
-
- const parts = hostname.split('.').map(Number);
- if (parts.length !== 4 || parts.some((p) => isNaN(p))) return false;
-
- if (parts[0] === 10) return true;
- if (parts[0] === 172 && parts[1] >= 16 && parts[1] <= 31) return true;
- if (parts[0] === 192 && parts[1] === 168) return true;
- if (parts[0] === 169 && parts[1] === 254) return true;
- if (parts[0] === 0) return true;
-
- return false;
-}
-
-function validateUrl(raw: string): { ok: true; url: URL } | { ok: false; reason: string } {
- let parsed: URL;
- try {
- parsed = new URL(raw);
- } catch {
- return { ok: false, reason: 'Invalid URL' };
- }
-
- if (parsed.protocol !== 'https:') {
- return { ok: false, reason: 'Only https:// URLs are allowed' };
- }
-
- if (isPrivateIP(parsed.hostname)) {
- return { ok: false, reason: 'Private/reserved addresses are not allowed' };
- }
-
- return { ok: true, url: parsed };
-}
-
-function escapeHtmlAttr(s: string): string {
- return s
- .replace(/&/g, '&')
- .replace(/"/g, '"')
- .replace(//g, '>');
-}
-
-function verifyToken(request: NextRequest): boolean {
- const token = process.env.API_TOKEN;
- if (!token) return true;
-
- const auth = request.headers.get('Authorization');
- if (!auth?.startsWith('Bearer ')) return false;
-
- return auth.slice(7) === token;
-}
-
-export async function GET(request: NextRequest) {
- if (!verifyToken(request)) {
- return NextResponse.json({ error: 'Unauthorized' }, { status: 403 });
- }
-
- const raw = request.nextUrl.searchParams.get('url');
- if (!raw) {
- return NextResponse.json({ error: 'url parameter is required' }, { status: 400 });
- }
-
- const result = validateUrl(raw);
- if (!result.ok) {
- return NextResponse.json({ error: result.reason }, { status: 403 });
- }
-
- try {
- const res = await fetch(result.url.href, { next: { revalidate: 60 } });
- const html = await res.text();
-
- const baseTag = ``;
- const injected = html.replace('', `${baseTag}`);
-
- return new NextResponse(injected, {
- headers: { 'Content-Type': 'text/html; charset=utf-8' },
- });
- } catch (e) {
- const msg = e instanceof Error ? e.message : 'Unknown error';
- return NextResponse.json({ error: msg }, { status: 500 });
- }
-}
diff --git a/src/app/favicon.ico b/src/app/favicon.ico
deleted file mode 100644
index 718d6fe..0000000
Binary files a/src/app/favicon.ico and /dev/null differ
diff --git a/src/app/globals.css b/src/app/globals.css
deleted file mode 100644
index a8da733..0000000
--- a/src/app/globals.css
+++ /dev/null
@@ -1,129 +0,0 @@
-@import "tailwindcss";
-@import "tw-animate-css";
-@import "shadcn/tailwind.css";
-
-@custom-variant dark (&:is(.dark *));
-
-@theme inline {
- --color-background: var(--background);
- --color-foreground: var(--foreground);
- --font-sans: var(--font-sans);
- --font-mono: var(--font-geist-mono);
- --color-sidebar-ring: var(--sidebar-ring);
- --color-sidebar-border: var(--sidebar-border);
- --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
- --color-sidebar-accent: var(--sidebar-accent);
- --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
- --color-sidebar-primary: var(--sidebar-primary);
- --color-sidebar-foreground: var(--sidebar-foreground);
- --color-sidebar: var(--sidebar);
- --color-chart-5: var(--chart-5);
- --color-chart-4: var(--chart-4);
- --color-chart-3: var(--chart-3);
- --color-chart-2: var(--chart-2);
- --color-chart-1: var(--chart-1);
- --color-ring: var(--ring);
- --color-input: var(--input);
- --color-border: var(--border);
- --color-destructive: var(--destructive);
- --color-accent-foreground: var(--accent-foreground);
- --color-accent: var(--accent);
- --color-muted-foreground: var(--muted-foreground);
- --color-muted: var(--muted);
- --color-secondary-foreground: var(--secondary-foreground);
- --color-secondary: var(--secondary);
- --color-primary-foreground: var(--primary-foreground);
- --color-primary: var(--primary);
- --color-popover-foreground: var(--popover-foreground);
- --color-popover: var(--popover);
- --color-card-foreground: var(--card-foreground);
- --color-card: var(--card);
- --radius-sm: calc(var(--radius) * 0.6);
- --radius-md: calc(var(--radius) * 0.8);
- --radius-lg: var(--radius);
- --radius-xl: calc(var(--radius) * 1.4);
- --radius-2xl: calc(var(--radius) * 1.8);
- --radius-3xl: calc(var(--radius) * 2.2);
- --radius-4xl: calc(var(--radius) * 2.6);
-}
-
-:root {
- --background: oklch(1 0 0);
- --foreground: oklch(0.145 0 0);
- --card: oklch(1 0 0);
- --card-foreground: oklch(0.145 0 0);
- --popover: oklch(1 0 0);
- --popover-foreground: oklch(0.145 0 0);
- --primary: oklch(0.205 0 0);
- --primary-foreground: oklch(0.985 0 0);
- --secondary: oklch(0.97 0 0);
- --secondary-foreground: oklch(0.205 0 0);
- --muted: oklch(0.97 0 0);
- --muted-foreground: oklch(0.556 0 0);
- --accent: oklch(0.97 0 0);
- --accent-foreground: oklch(0.205 0 0);
- --destructive: oklch(0.577 0.245 27.325);
- --border: oklch(0.922 0 0);
- --input: oklch(0.922 0 0);
- --ring: oklch(0.708 0 0);
- --chart-1: oklch(0.809 0.105 251.813);
- --chart-2: oklch(0.623 0.214 259.815);
- --chart-3: oklch(0.546 0.245 262.881);
- --chart-4: oklch(0.488 0.243 264.376);
- --chart-5: oklch(0.424 0.199 265.638);
- --radius: 0.625rem;
- --sidebar: oklch(0.985 0 0);
- --sidebar-foreground: oklch(0.145 0 0);
- --sidebar-primary: oklch(0.205 0 0);
- --sidebar-primary-foreground: oklch(0.985 0 0);
- --sidebar-accent: oklch(0.97 0 0);
- --sidebar-accent-foreground: oklch(0.205 0 0);
- --sidebar-border: oklch(0.922 0 0);
- --sidebar-ring: oklch(0.708 0 0);
-}
-
-.dark {
- --background: oklch(0.145 0 0);
- --foreground: oklch(0.985 0 0);
- --card: oklch(0.205 0 0);
- --card-foreground: oklch(0.985 0 0);
- --popover: oklch(0.205 0 0);
- --popover-foreground: oklch(0.985 0 0);
- --primary: oklch(0.922 0 0);
- --primary-foreground: oklch(0.205 0 0);
- --secondary: oklch(0.269 0 0);
- --secondary-foreground: oklch(0.985 0 0);
- --muted: oklch(0.269 0 0);
- --muted-foreground: oklch(0.708 0 0);
- --accent: oklch(0.269 0 0);
- --accent-foreground: oklch(0.985 0 0);
- --destructive: oklch(0.704 0.191 22.216);
- --border: oklch(1 0 0 / 10%);
- --input: oklch(1 0 0 / 15%);
- --ring: oklch(0.556 0 0);
- --chart-1: oklch(0.809 0.105 251.813);
- --chart-2: oklch(0.623 0.214 259.815);
- --chart-3: oklch(0.546 0.245 262.881);
- --chart-4: oklch(0.488 0.243 264.376);
- --chart-5: oklch(0.424 0.199 265.638);
- --sidebar: oklch(0.205 0 0);
- --sidebar-foreground: oklch(0.985 0 0);
- --sidebar-primary: oklch(0.488 0.243 264.376);
- --sidebar-primary-foreground: oklch(0.985 0 0);
- --sidebar-accent: oklch(0.269 0 0);
- --sidebar-accent-foreground: oklch(0.985 0 0);
- --sidebar-border: oklch(1 0 0 / 10%);
- --sidebar-ring: oklch(0.556 0 0);
-}
-
-@layer base {
- * {
- @apply border-border outline-ring/50;
- }
- body {
- @apply bg-background text-foreground;
- }
- html {
- @apply font-sans;
- }
-}
\ No newline at end of file
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index b59fc4a..233c549 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -1,35 +1,11 @@
-import type { Metadata } from 'next';
-import { Geist, Geist_Mono } from 'next/font/google';
-import { TooltipProvider } from '@/components/ui/tooltip';
-import './globals.css';
-
-const geistSans = Geist({
- variable: '--font-geist-sans',
- subsets: ['latin'],
-});
-
-const geistMono = Geist_Mono({
- variable: '--font-geist-mono',
- subsets: ['latin'],
-});
-
-export const metadata: Metadata = {
- title: 'FB Tool',
- description: 'Feedback Tool for reviewing web pages',
-};
-
export default function RootLayout({
children,
-}: Readonly<{
+}: {
children: React.ReactNode;
-}>) {
+}) {
return (
-
- {children}
-
+ {children}
);
}
diff --git a/src/app/page.tsx b/src/app/page.tsx
deleted file mode 100644
index 1f2e5f0..0000000
--- a/src/app/page.tsx
+++ /dev/null
@@ -1,41 +0,0 @@
-'use client';
-
-import { useState, useRef, useCallback } from 'react';
-import { StoreProvider, useStore } from '@/lib/store';
-import { ContentViewer, ContentViewerHandle } from '@/components/content-viewer';
-import { CommentSidebar } from '@/components/comment-sidebar';
-import { NameDialog } from '@/components/name-dialog';
-
-function AppContent() {
- const { username } = useStore();
- const [sidebarOpen, setSidebarOpen] = useState(true);
- const viewerRef = useRef(null);
-
- const handleScrollToQuote = useCallback((commentId: string) => {
- viewerRef.current?.scrollToQuote(commentId);
- }, []);
-
- return (
- <>
- {!username && }
-
-
-
-
-
setSidebarOpen(!sidebarOpen)}
- onScrollToQuote={handleScrollToQuote}
- />
-
- >
- );
-}
-
-export default function Page() {
- return (
-
-
-
- );
-}
diff --git a/src/components/comment-card.tsx b/src/components/comment-card.tsx
deleted file mode 100644
index b614b5c..0000000
--- a/src/components/comment-card.tsx
+++ /dev/null
@@ -1,253 +0,0 @@
-'use client';
-
-import { useState } from 'react';
-import { Comment, Priority } from '@/lib/types';
-import { useStore } from '@/lib/store';
-import { Badge } from '@/components/ui/badge';
-import { Button } from '@/components/ui/button';
-import { Textarea } from '@/components/ui/textarea';
-import { cn } from '@/lib/utils';
-import { MessageSquare, Check, RotateCcw, Pencil, Trash2 } from 'lucide-react';
-
-const PRIORITY_CONFIG: Record = {
- must: { label: 'Must', badgeClass: 'bg-red-500 text-white border-red-500', borderClass: 'border-l-red-500' },
- better: { label: 'Better', badgeClass: 'bg-amber-500 text-white border-amber-500', borderClass: 'border-l-amber-500' },
- want: { label: 'Want', badgeClass: 'bg-green-500 text-white border-green-500', borderClass: 'border-l-green-500' },
-};
-
-function formatTime(ts: number): string {
- const diff = Date.now() - ts;
- if (diff < 60_000) return 'たった今';
- if (diff < 3_600_000) return `${Math.floor(diff / 60_000)}分前`;
- if (diff < 86_400_000) return `${Math.floor(diff / 3_600_000)}時間前`;
- return new Date(ts).toLocaleDateString('ja-JP', {
- month: 'short',
- day: 'numeric',
- hour: '2-digit',
- minute: '2-digit',
- });
-}
-
-interface CommentCardProps {
- comment: Comment;
- replies: Comment[];
- onScrollToQuote?: (commentId: string) => void;
-}
-
-export function CommentCard({ comment, replies, onScrollToQuote }: CommentCardProps) {
- const store = useStore();
- const [editing, setEditing] = useState(false);
- const [editContent, setEditContent] = useState(comment.content);
- const [editPriority, setEditPriority] = useState(comment.priority);
- const [replyText, setReplyText] = useState('');
- const [showReply, setShowReply] = useState(false);
-
- const isOwn = comment.author === store.username;
- const isStrikethrough = comment.type === 'strikethrough';
- const priorityCfg = PRIORITY_CONFIG[comment.priority];
-
- const handleSaveEdit = () => {
- store.editComment(comment.id, editContent, editPriority);
- setEditing(false);
- };
-
- const handleSubmitReply = () => {
- if (!replyText.trim()) return;
- store.addComment({
- quote: '',
- quoteContext: { beforeText: '', afterText: '' },
- content: replyText.trim(),
- priority: 'want',
- parentId: comment.id,
- });
- setReplyText('');
- setShowReply(false);
- };
-
- return (
-
- {/* Header */}
-
-
-
- {comment.author.charAt(0)}
-
-
{comment.author}
-
{formatTime(comment.timestamp)}
- {comment.resolved && (
-
✓ 解決済
- )}
-
- {isStrikethrough ? (
-
- 取消
-
- ) : (
-
isOwn && store.cyclePriority(comment.id)}
- title={isOwn ? 'クリックで優先度を変更' : ''}
- >
- {priorityCfg.label}
-
- )}
-
-
- {/* Quote */}
- {comment.quote && (
-
onScrollToQuote?.(comment.id)}
- >
- “{comment.quote.length > 100 ? comment.quote.substring(0, 100) + '...' : comment.quote}”
-
- )}
-
- {/* Body / Edit */}
- {editing ? (
-
-
- {(['must', 'better', 'want'] as Priority[]).map((p) => (
-
- ))}
-
-
- ) : (
-
- {comment.content}
-
- )}
-
- {/* Actions */}
- {!editing && (
-
-
-
- {isOwn && !isStrikethrough && (
-
- )}
- {isOwn && (
-
- )}
-
- )}
-
- {/* Replies */}
- {replies.length > 0 && (
-
- {replies.map((r) => (
-
-
- {r.author.charAt(0)}
-
-
-
- {r.author} · {formatTime(r.timestamp)}
-
-
{r.content}
-
-
- ))}
-
- )}
-
- {/* Reply Input */}
- {showReply && (
-
- )}
-
- );
-}
diff --git a/src/components/comment-sidebar.tsx b/src/components/comment-sidebar.tsx
deleted file mode 100644
index fd93b3b..0000000
--- a/src/components/comment-sidebar.tsx
+++ /dev/null
@@ -1,195 +0,0 @@
-'use client';
-
-import { useMemo, useState } from 'react';
-import { useStore } from '@/lib/store';
-import { CommentCard } from './comment-card';
-import { ExportButtons } from './export-buttons';
-import { ScrollArea } from '@/components/ui/scroll-area';
-import { Button } from '@/components/ui/button';
-import { Input } from '@/components/ui/input';
-import { FilterMode } from '@/lib/types';
-import { cn } from '@/lib/utils';
-import { PanelRightClose, PanelRightOpen, MessageSquare, User } from 'lucide-react';
-
-const FILTERS: { value: FilterMode; label: string }[] = [
- { value: 'unresolved', label: '未解決' },
- { value: 'resolved', label: '解決済' },
- { value: 'all', label: 'すべて' },
-];
-
-interface CommentSidebarProps {
- open: boolean;
- onToggle: () => void;
- onScrollToQuote?: (commentId: string) => void;
-}
-
-export function CommentSidebar({ open, onToggle, onScrollToQuote }: CommentSidebarProps) {
- const { username, comments, filter, setFilter, setUsername } = useStore();
- const [editingName, setEditingName] = useState(false);
- const [nameInput, setNameInput] = useState('');
-
- const topLevel = useMemo(
- () => comments.filter((c) => !c.parentId),
- [comments]
- );
-
- const filtered = useMemo(() => {
- if (filter === 'all') return topLevel;
- if (filter === 'resolved') return topLevel.filter((c) => c.resolved);
- return topLevel.filter((c) => !c.resolved);
- }, [topLevel, filter]);
-
- const counts = useMemo(() => ({
- unresolved: topLevel.filter((c) => !c.resolved).length,
- resolved: topLevel.filter((c) => c.resolved).length,
- all: topLevel.length,
- }), [topLevel]);
-
- const getReplies = (parentId: string) =>
- comments
- .filter((c) => c.parentId === parentId)
- .sort((a, b) => a.timestamp - b.timestamp);
-
- const handleNameEdit = () => {
- if (nameInput.trim()) {
- setUsername(nameInput.trim());
- }
- setEditingName(false);
- };
-
- if (!open) {
- return (
-
- );
- }
-
- return (
-
- {/* Header */}
-
-
- FB Tool
-
- {counts.all}
-
-
-
-
-
- {/* User */}
- {username && (
-
- {editingName ? (
- setNameInput(e.target.value)}
- className="h-7 text-xs"
- autoFocus
- onKeyDown={(e) => {
- if (e.key === 'Enter') handleNameEdit();
- if (e.key === 'Escape') setEditingName(false);
- }}
- onBlur={handleNameEdit}
- />
- ) : (
-
- )}
-
- )}
-
- {/* Filter Tabs */}
-
- {FILTERS.map((f) => (
-
- ))}
-
-
- {/* Comment List */}
-
-
- {filtered.length === 0 ? (
-
-
-
- {filter === 'unresolved'
- ? 'コメントはまだありません'
- : filter === 'resolved'
- ? '解決済みのコメントはありません'
- : 'コメントはまだありません'}
-
-
- 左側のテキストを選択してコメントを追加
-
-
- ) : (
- filtered
- .sort((a, b) => b.timestamp - a.timestamp)
- .map((c) => (
-
- ))
- )}
-
-
-
- );
-}
diff --git a/src/components/content-viewer.tsx b/src/components/content-viewer.tsx
deleted file mode 100644
index e978698..0000000
--- a/src/components/content-viewer.tsx
+++ /dev/null
@@ -1,185 +0,0 @@
-'use client';
-
-import { useRef, useEffect, useCallback, useState, forwardRef, useImperativeHandle } from 'react';
-import { useStore } from '@/lib/store';
-import { SelectionPopup } from './selection-popup';
-
-export interface ContentViewerHandle {
- scrollToQuote: (commentId: string) => void;
-}
-
-export const ContentViewer = forwardRef(function ContentViewer(_, ref) {
- const { targetUrl, comments } = useStore();
- const iframeRef = useRef(null);
- const containerRef = useRef(null);
- const [ready, setReady] = useState(false);
- const [error, setError] = useState(null);
-
- const scrollToQuote = useCallback((commentId: string) => {
- const iframe = iframeRef.current;
- if (!iframe?.contentDocument) return;
-
- const mark = iframe.contentDocument.querySelector(
- `.fb-highlight[data-comment-id="${commentId}"], .fb-strikethrough[data-comment-id="${commentId}"]`
- );
- if (!mark) return;
-
- mark.scrollIntoView({ behavior: 'smooth', block: 'center' });
-
- const el = mark as HTMLElement;
- const origBg = el.style.backgroundColor;
- el.style.backgroundColor = 'rgba(59, 130, 246, 0.4)';
- el.style.transition = 'background-color 0.3s';
- setTimeout(() => {
- el.style.backgroundColor = origBg;
- }, 1500);
- }, []);
-
- useImperativeHandle(ref, () => ({ scrollToQuote }), [scrollToQuote]);
-
- useEffect(() => {
- if (!targetUrl) return;
- const iframe = iframeRef.current;
- if (!iframe) return;
-
- setReady(false);
- const headers: Record = {};
- const token = process.env.NEXT_PUBLIC_API_TOKEN;
- if (token) headers['Authorization'] = `Bearer ${token}`;
-
- fetch(`/api/fetch-page?url=${encodeURIComponent(targetUrl)}`, { headers })
- .then((res) => {
- if (!res.ok) throw new Error(`HTTP ${res.status}`);
- return res.text();
- })
- .then((html) => {
- const doc = iframe.contentDocument;
- if (!doc) return;
- doc.open();
- doc.write(html);
- doc.close();
- setTimeout(() => setReady(true), 300);
- })
- .catch((e) => setError(e.message));
- }, [targetUrl]);
-
- const applyHighlights = useCallback(() => {
- const iframe = iframeRef.current;
- if (!iframe?.contentDocument?.body) return;
-
- const doc = iframe.contentDocument;
- doc.querySelectorAll('.fb-highlight, .fb-strikethrough').forEach((el) => {
- const text = el.textContent || '';
- const textNode = doc.createTextNode(text);
- el.parentNode?.replaceChild(textNode, el);
- });
- doc.body.normalize();
-
- const style = doc.getElementById('fb-highlight-styles') || doc.createElement('style');
- style.id = 'fb-highlight-styles';
- style.textContent = `
- .fb-highlight {
- background: rgba(59, 130, 246, 0.15);
- border-bottom: 2px solid rgb(59, 130, 246);
- padding: 1px 0;
- cursor: pointer;
- transition: background 0.15s;
- }
- .fb-highlight:hover { background: rgba(59, 130, 246, 0.25); }
- .fb-strikethrough {
- text-decoration: line-through;
- text-decoration-color: rgb(239, 68, 68);
- text-decoration-thickness: 2px;
- opacity: 0.6;
- cursor: pointer;
- }
- `;
- if (!doc.getElementById('fb-highlight-styles')) {
- doc.head.appendChild(style);
- }
-
- const topLevel = comments.filter((c) => !c.parentId && !c.resolved && c.quote);
- topLevel.forEach((comment) => {
- const searchText = comment.quote.replace(/[\s\u00A0]+/g, ' ').trim();
- if (searchText.length < 2) return;
-
- const walker = doc.createTreeWalker(doc.body, NodeFilter.SHOW_TEXT, {
- acceptNode: (node) => {
- const parent = (node as Text).parentElement;
- if (!parent) return NodeFilter.FILTER_REJECT;
- if (parent.tagName === 'SCRIPT' || parent.tagName === 'STYLE') return NodeFilter.FILTER_REJECT;
- if (parent.closest('.fb-highlight, .fb-strikethrough')) return NodeFilter.FILTER_REJECT;
- return NodeFilter.FILTER_ACCEPT;
- },
- });
-
- let node: Text | null;
- while ((node = walker.nextNode() as Text | null)) {
- const nodeText = node.textContent?.replace(/[\s\u00A0]+/g, ' ') || '';
- const idx = nodeText.indexOf(searchText);
- if (idx === -1) continue;
-
- const originalText = node.textContent || '';
- const origIdx = originalText.indexOf(searchText.charAt(0));
- if (origIdx === -1) continue;
-
- try {
- const before = doc.createTextNode(originalText.substring(0, origIdx));
- const mark = doc.createElement('mark');
- mark.className = comment.type === 'strikethrough' ? 'fb-strikethrough' : 'fb-highlight';
- mark.dataset.commentId = comment.id;
- mark.textContent = originalText.substring(origIdx, origIdx + searchText.length);
- const after = doc.createTextNode(originalText.substring(origIdx + searchText.length));
-
- const parent = node.parentNode;
- if (parent) {
- parent.insertBefore(before, node);
- parent.insertBefore(mark, node);
- parent.insertBefore(after, node);
- parent.removeChild(node);
- }
- } catch {
- // skip
- }
- break;
- }
- });
- }, [comments]);
-
- useEffect(() => {
- if (ready) applyHighlights();
- }, [ready, applyHighlights]);
-
- if (!targetUrl) {
- return (
-
-
-
URLが指定されていません
-
?url=https://... をURLに追加してください
-
-
- );
- }
-
- if (error) {
- return (
-
-
-
ページの読み込みに失敗しました
-
{error}
-
-
- );
- }
-
- return (
-
-
-
-
- );
-});
diff --git a/src/components/export-buttons.tsx b/src/components/export-buttons.tsx
deleted file mode 100644
index 3e25aa9..0000000
--- a/src/components/export-buttons.tsx
+++ /dev/null
@@ -1,91 +0,0 @@
-'use client';
-
-import { useStore } from '@/lib/store';
-import { Button } from '@/components/ui/button';
-import { Download } from 'lucide-react';
-import { Comment, Priority } from '@/lib/types';
-
-function buildMarkdown(comments: Comment[], targetUrl: string): string {
- const priorityOrder: Record = { must: 1, better: 2, want: 3 };
- const topLevel = comments
- .filter((c) => !c.parentId)
- .sort((a, b) => priorityOrder[a.priority] - priorityOrder[b.priority]);
-
- let md = `# フィードバック\n\nURL: ${targetUrl || '不明'}\nエクスポート日時: ${new Date().toLocaleString('ja-JP')}\n\n---\n\n`;
-
- const groups: Record = { must: [], better: [], want: [] };
- topLevel.forEach((c) => groups[c.priority]?.push(c));
-
- const labels: Record = { must: 'MUST', better: 'BETTER', want: 'WANT' };
-
- (['must', 'better', 'want'] as Priority[]).forEach((p) => {
- if (groups[p].length === 0) return;
- md += `## ${labels[p]}\n\n`;
- groups[p].forEach((c) => {
- md += `### ${c.content}\n\n`;
- if (c.quote) md += `> ${c.quote}\n\n`;
- md += `- 投稿者: ${c.author}\n`;
- md += `- ステータス: ${c.resolved ? '解決済み' : '未解決'}\n\n`;
- const replies = comments.filter((r) => r.parentId === c.id);
- if (replies.length > 0) {
- md += `**返信:**\n\n`;
- replies.forEach((r) => { md += `- ${r.author}: ${r.content}\n`; });
- md += '\n';
- }
- });
- });
-
- return md;
-}
-
-function buildJson(comments: Comment[], targetUrl: string): string {
- return JSON.stringify({
- projectUrl: targetUrl,
- exportedAt: new Date().toISOString(),
- commentsCount: comments.filter((c) => !c.parentId).length,
- comments: comments.map((c) => ({
- id: c.id, author: c.author, type: c.type, priority: c.priority,
- content: c.content, quote: c.quote || null, parentId: c.parentId,
- resolved: c.resolved, timestamp: c.timestamp,
- })),
- }, null, 2);
-}
-
-function downloadFile(content: string, filename: string, mimeType: string) {
- const blob = new Blob([content], { type: mimeType });
- const url = URL.createObjectURL(blob);
- const a = document.createElement('a');
- a.href = url;
- a.download = filename;
- document.body.appendChild(a);
- a.click();
- document.body.removeChild(a);
- URL.revokeObjectURL(url);
-}
-
-function DownloadButton({ label, ext, mime, buildFn }: {
- label: string; ext: string; mime: string; buildFn: () => string;
-}) {
- return (
-
- );
-}
-
-export function ExportButtons() {
- const { comments, targetUrl } = useStore();
-
- return (
-
- buildJson(comments, targetUrl)} />
- buildMarkdown(comments, targetUrl)} />
-
- );
-}
diff --git a/src/components/name-dialog.tsx b/src/components/name-dialog.tsx
deleted file mode 100644
index c9da8ab..0000000
--- a/src/components/name-dialog.tsx
+++ /dev/null
@@ -1,51 +0,0 @@
-'use client';
-
-import { useState } from 'react';
-import { useStore } from '@/lib/store';
-import {
- Dialog,
- DialogContent,
- DialogHeader,
- DialogTitle,
- DialogDescription,
-} from '@/components/ui/dialog';
-import { Input } from '@/components/ui/input';
-import { Button } from '@/components/ui/button';
-
-export function NameDialog() {
- const { username, setUsername } = useStore();
- const [name, setName] = useState('');
-
- if (username) return null;
-
- return (
-
- );
-}
diff --git a/src/components/selection-popup.tsx b/src/components/selection-popup.tsx
deleted file mode 100644
index 60adc4a..0000000
--- a/src/components/selection-popup.tsx
+++ /dev/null
@@ -1,204 +0,0 @@
-'use client';
-
-import { useState, useEffect, useCallback, useRef } from 'react';
-import { useStore } from '@/lib/store';
-import { Priority } from '@/lib/types';
-import { Textarea } from '@/components/ui/textarea';
-import { Button } from '@/components/ui/button';
-import { X, Strikethrough } from 'lucide-react';
-
-interface SelectionState {
- text: string;
- quoteContext: { beforeText: string; afterText: string };
- rect: DOMRect;
- iframeOffset: { top: number; left: number };
-}
-
-function getQuoteContext(range: Range, contextLength = 50) {
- let beforeText = '';
- let afterText = '';
- try {
- const doc = range.startContainer.ownerDocument;
- if (!doc?.body) return { beforeText, afterText };
-
- const beforeRange = doc.createRange();
- beforeRange.setStart(doc.body, 0);
- beforeRange.setEnd(range.startContainer, range.startOffset);
- beforeText = beforeRange.toString().slice(-contextLength).replace(/[\s\u00A0]+/g, ' ').trim();
-
- const afterRange = doc.createRange();
- afterRange.setStart(range.endContainer, range.endOffset);
- afterRange.setEnd(doc.body, doc.body.childNodes.length);
- afterText = afterRange.toString().slice(0, contextLength).replace(/[\s\u00A0]+/g, ' ').trim();
- } catch {
- // ignore
- }
- return { beforeText, afterText };
-}
-
-interface SelectionPopupProps {
- containerRef: React.RefObject;
- iframeRef: React.RefObject;
- ready: boolean;
-}
-
-export function SelectionPopup({ containerRef, iframeRef, ready }: SelectionPopupProps) {
- const store = useStore();
- const [selection, setSelection] = useState(null);
- const [content, setContent] = useState('');
- const popupRef = useRef(null);
-
- const handleIframeMouseUp = useCallback(() => {
- const iframe = iframeRef.current;
- if (!iframe?.contentWindow) return;
-
- const sel = iframe.contentWindow.getSelection();
- const text = sel?.toString().trim();
- if (!text || text.length === 0 || !sel || sel.rangeCount === 0) return;
-
- const range = sel.getRangeAt(0);
- const rect = range.getBoundingClientRect();
- const ctx = getQuoteContext(range);
-
- const iframeRect = iframe.getBoundingClientRect();
-
- setSelection({
- text: text.replace(/[\s\u00A0]+/g, ' ').substring(0, 200),
- quoteContext: ctx,
- rect,
- iframeOffset: { top: iframeRect.top, left: iframeRect.left },
- });
- setContent('');
- }, [iframeRef]);
-
- useEffect(() => {
- if (!ready) return;
- const iframe = iframeRef.current;
- const doc = iframe?.contentDocument;
- if (!doc) return;
-
- const onMouseUp = () => handleIframeMouseUp();
- const onMouseDown = (e: MouseEvent) => {
- if (popupRef.current?.contains(e.target as Node)) return;
- setSelection(null);
- };
-
- doc.addEventListener('mouseup', onMouseUp);
- doc.addEventListener('mousedown', onMouseDown);
-
- return () => {
- doc.removeEventListener('mouseup', onMouseUp);
- doc.removeEventListener('mousedown', onMouseDown);
- };
- }, [ready, iframeRef, handleIframeMouseUp]);
-
- const submit = (priority: Priority) => {
- if (!selection) return;
- store.addComment({
- quote: selection.text,
- quoteContext: selection.quoteContext,
- content: content.trim(),
- priority,
- type: 'comment',
- });
- setSelection(null);
- setContent('');
- };
-
- const submitStrikethrough = () => {
- if (!selection) return;
- store.addComment({
- quote: selection.text,
- quoteContext: selection.quoteContext,
- content: '',
- priority: 'must',
- type: 'strikethrough',
- });
- setSelection(null);
- setContent('');
- };
-
- if (!selection) return null;
-
- const popupHeight = 340;
- const popupWidth = 420;
- const margin = 12;
-
- const selBottom = selection.iframeOffset.top + selection.rect.bottom;
- const selTop = selection.iframeOffset.top + selection.rect.top;
-
- let top: number;
- if (selBottom + margin + popupHeight <= window.innerHeight) {
- top = selBottom + margin;
- } else if (selTop - margin - popupHeight >= 0) {
- top = selTop - margin - popupHeight;
- } else {
- top = Math.max(margin, (window.innerHeight - popupHeight) / 2);
- }
-
- const maxLeft = (containerRef.current?.getBoundingClientRect().right ?? window.innerWidth) - popupWidth - margin;
- const left = Math.max(margin, Math.min(selection.iframeOffset.left + selection.rect.left, maxLeft));
-
- return (
-
-
- コメントを追加
-
-
-
-
- “{selection.text.length > 120 ? selection.text.substring(0, 120) + '...' : selection.text}”
-
-
-
- );
-}
diff --git a/src/components/ui/badge.tsx b/src/components/ui/badge.tsx
deleted file mode 100644
index b20959d..0000000
--- a/src/components/ui/badge.tsx
+++ /dev/null
@@ -1,52 +0,0 @@
-import { mergeProps } from "@base-ui/react/merge-props"
-import { useRender } from "@base-ui/react/use-render"
-import { cva, type VariantProps } from "class-variance-authority"
-
-import { cn } from "@/lib/utils"
-
-const badgeVariants = cva(
- "group/badge inline-flex h-5 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3!",
- {
- variants: {
- variant: {
- default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80",
- secondary:
- "bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80",
- destructive:
- "bg-destructive/10 text-destructive focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:focus-visible:ring-destructive/40 [a]:hover:bg-destructive/20",
- outline:
- "border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground",
- ghost:
- "hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50",
- link: "text-primary underline-offset-4 hover:underline",
- },
- },
- defaultVariants: {
- variant: "default",
- },
- }
-)
-
-function Badge({
- className,
- variant = "default",
- render,
- ...props
-}: useRender.ComponentProps<"span"> & VariantProps) {
- return useRender({
- defaultTagName: "span",
- props: mergeProps<"span">(
- {
- className: cn(badgeVariants({ variant }), className),
- },
- props
- ),
- render,
- state: {
- slot: "badge",
- variant,
- },
- })
-}
-
-export { Badge, badgeVariants }
diff --git a/src/components/ui/button.tsx b/src/components/ui/button.tsx
deleted file mode 100644
index ded01b2..0000000
--- a/src/components/ui/button.tsx
+++ /dev/null
@@ -1,60 +0,0 @@
-"use client"
-
-import { Button as ButtonPrimitive } from "@base-ui/react/button"
-import { cva, type VariantProps } from "class-variance-authority"
-
-import { cn } from "@/lib/utils"
-
-const buttonVariants = cva(
- "group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
- {
- variants: {
- variant: {
- default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80",
- outline:
- "border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",
- secondary:
- "bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
- ghost:
- "hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50",
- destructive:
- "bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40",
- link: "text-primary underline-offset-4 hover:underline",
- },
- size: {
- default:
- "h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
- xs: "h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",
- sm: "h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5",
- lg: "h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3",
- icon: "size-8",
- "icon-xs":
- "size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3",
- "icon-sm":
- "size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg",
- "icon-lg": "size-9",
- },
- },
- defaultVariants: {
- variant: "default",
- size: "default",
- },
- }
-)
-
-function Button({
- className,
- variant = "default",
- size = "default",
- ...props
-}: ButtonPrimitive.Props & VariantProps) {
- return (
-
- )
-}
-
-export { Button, buttonVariants }
diff --git a/src/components/ui/card.tsx b/src/components/ui/card.tsx
deleted file mode 100644
index 9bd5a25..0000000
--- a/src/components/ui/card.tsx
+++ /dev/null
@@ -1,103 +0,0 @@
-import * as React from "react"
-
-import { cn } from "@/lib/utils"
-
-function Card({
- className,
- size = "default",
- ...props
-}: React.ComponentProps<"div"> & { size?: "default" | "sm" }) {
- return (
- img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl",
- className
- )}
- {...props}
- />
- )
-}
-
-function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
- return (
-
- )
-}
-
-function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
- return (
-
- )
-}
-
-function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
- return (
-
- )
-}
-
-function CardAction({ className, ...props }: React.ComponentProps<"div">) {
- return (
-
- )
-}
-
-function CardContent({ className, ...props }: React.ComponentProps<"div">) {
- return (
-
- )
-}
-
-function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
- return (
-
- )
-}
-
-export {
- Card,
- CardHeader,
- CardFooter,
- CardTitle,
- CardAction,
- CardDescription,
- CardContent,
-}
diff --git a/src/components/ui/dialog.tsx b/src/components/ui/dialog.tsx
deleted file mode 100644
index 807e1fa..0000000
--- a/src/components/ui/dialog.tsx
+++ /dev/null
@@ -1,157 +0,0 @@
-"use client"
-
-import * as React from "react"
-import { Dialog as DialogPrimitive } from "@base-ui/react/dialog"
-
-import { cn } from "@/lib/utils"
-import { Button } from "@/components/ui/button"
-import { XIcon } from "lucide-react"
-
-function Dialog({ ...props }: DialogPrimitive.Root.Props) {
- return
-}
-
-function DialogTrigger({ ...props }: DialogPrimitive.Trigger.Props) {
- return
-}
-
-function DialogPortal({ ...props }: DialogPrimitive.Portal.Props) {
- return
-}
-
-function DialogClose({ ...props }: DialogPrimitive.Close.Props) {
- return
-}
-
-function DialogOverlay({
- className,
- ...props
-}: DialogPrimitive.Backdrop.Props) {
- return (
-
- )
-}
-
-function DialogContent({
- className,
- children,
- showCloseButton = true,
- ...props
-}: DialogPrimitive.Popup.Props & {
- showCloseButton?: boolean
-}) {
- return (
-
-
-
- {children}
- {showCloseButton && (
-
- }
- >
-
- Close
-
- )}
-
-
- )
-}
-
-function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
- return (
-
- )
-}
-
-function DialogFooter({
- className,
- showCloseButton = false,
- children,
- ...props
-}: React.ComponentProps<"div"> & {
- showCloseButton?: boolean
-}) {
- return (
-
- {children}
- {showCloseButton && (
- }>
- Close
-
- )}
-
- )
-}
-
-function DialogTitle({ className, ...props }: DialogPrimitive.Title.Props) {
- return (
-
- )
-}
-
-function DialogDescription({
- className,
- ...props
-}: DialogPrimitive.Description.Props) {
- return (
-
- )
-}
-
-export {
- Dialog,
- DialogClose,
- DialogContent,
- DialogDescription,
- DialogFooter,
- DialogHeader,
- DialogOverlay,
- DialogPortal,
- DialogTitle,
- DialogTrigger,
-}
diff --git a/src/components/ui/input.tsx b/src/components/ui/input.tsx
deleted file mode 100644
index 7d21bab..0000000
--- a/src/components/ui/input.tsx
+++ /dev/null
@@ -1,20 +0,0 @@
-import * as React from "react"
-import { Input as InputPrimitive } from "@base-ui/react/input"
-
-import { cn } from "@/lib/utils"
-
-function Input({ className, type, ...props }: React.ComponentProps<"input">) {
- return (
-
- )
-}
-
-export { Input }
diff --git a/src/components/ui/scroll-area.tsx b/src/components/ui/scroll-area.tsx
deleted file mode 100644
index 84c1e9f..0000000
--- a/src/components/ui/scroll-area.tsx
+++ /dev/null
@@ -1,55 +0,0 @@
-"use client"
-
-import * as React from "react"
-import { ScrollArea as ScrollAreaPrimitive } from "@base-ui/react/scroll-area"
-
-import { cn } from "@/lib/utils"
-
-function ScrollArea({
- className,
- children,
- ...props
-}: ScrollAreaPrimitive.Root.Props) {
- return (
-
-
- {children}
-
-
-
-
- )
-}
-
-function ScrollBar({
- className,
- orientation = "vertical",
- ...props
-}: ScrollAreaPrimitive.Scrollbar.Props) {
- return (
-
-
-
- )
-}
-
-export { ScrollArea, ScrollBar }
diff --git a/src/components/ui/separator.tsx b/src/components/ui/separator.tsx
deleted file mode 100644
index 6e1369e..0000000
--- a/src/components/ui/separator.tsx
+++ /dev/null
@@ -1,25 +0,0 @@
-"use client"
-
-import { Separator as SeparatorPrimitive } from "@base-ui/react/separator"
-
-import { cn } from "@/lib/utils"
-
-function Separator({
- className,
- orientation = "horizontal",
- ...props
-}: SeparatorPrimitive.Props) {
- return (
-
- )
-}
-
-export { Separator }
diff --git a/src/components/ui/tabs.tsx b/src/components/ui/tabs.tsx
deleted file mode 100644
index 56c4288..0000000
--- a/src/components/ui/tabs.tsx
+++ /dev/null
@@ -1,82 +0,0 @@
-"use client"
-
-import { Tabs as TabsPrimitive } from "@base-ui/react/tabs"
-import { cva, type VariantProps } from "class-variance-authority"
-
-import { cn } from "@/lib/utils"
-
-function Tabs({
- className,
- orientation = "horizontal",
- ...props
-}: TabsPrimitive.Root.Props) {
- return (
-
- )
-}
-
-const tabsListVariants = cva(
- "group/tabs-list inline-flex w-fit items-center justify-center rounded-lg p-[3px] text-muted-foreground group-data-horizontal/tabs:h-8 group-data-vertical/tabs:h-fit group-data-vertical/tabs:flex-col data-[variant=line]:rounded-none",
- {
- variants: {
- variant: {
- default: "bg-muted",
- line: "gap-1 bg-transparent",
- },
- },
- defaultVariants: {
- variant: "default",
- },
- }
-)
-
-function TabsList({
- className,
- variant = "default",
- ...props
-}: TabsPrimitive.List.Props & VariantProps
) {
- return (
-
- )
-}
-
-function TabsTrigger({ className, ...props }: TabsPrimitive.Tab.Props) {
- return (
-
- )
-}
-
-function TabsContent({ className, ...props }: TabsPrimitive.Panel.Props) {
- return (
-
- )
-}
-
-export { Tabs, TabsList, TabsTrigger, TabsContent, tabsListVariants }
diff --git a/src/components/ui/textarea.tsx b/src/components/ui/textarea.tsx
deleted file mode 100644
index 04d27f7..0000000
--- a/src/components/ui/textarea.tsx
+++ /dev/null
@@ -1,18 +0,0 @@
-import * as React from "react"
-
-import { cn } from "@/lib/utils"
-
-function Textarea({ className, ...props }: React.ComponentProps<"textarea">) {
- return (
-
- )
-}
-
-export { Textarea }
diff --git a/src/components/ui/tooltip.tsx b/src/components/ui/tooltip.tsx
deleted file mode 100644
index 69e8a82..0000000
--- a/src/components/ui/tooltip.tsx
+++ /dev/null
@@ -1,66 +0,0 @@
-"use client"
-
-import { Tooltip as TooltipPrimitive } from "@base-ui/react/tooltip"
-
-import { cn } from "@/lib/utils"
-
-function TooltipProvider({
- delay = 0,
- ...props
-}: TooltipPrimitive.Provider.Props) {
- return (
-
- )
-}
-
-function Tooltip({ ...props }: TooltipPrimitive.Root.Props) {
- return
-}
-
-function TooltipTrigger({ ...props }: TooltipPrimitive.Trigger.Props) {
- return
-}
-
-function TooltipContent({
- className,
- side = "top",
- sideOffset = 4,
- align = "center",
- alignOffset = 0,
- children,
- ...props
-}: TooltipPrimitive.Popup.Props &
- Pick<
- TooltipPrimitive.Positioner.Props,
- "align" | "alignOffset" | "side" | "sideOffset"
- >) {
- return (
-
-
-
- {children}
-
-
-
-
- )
-}
-
-export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }
diff --git a/src/lib/storage.ts b/src/lib/storage.ts
deleted file mode 100644
index 6ad336b..0000000
--- a/src/lib/storage.ts
+++ /dev/null
@@ -1,61 +0,0 @@
-import { Comment } from './types';
-
-const USERNAME_KEY = 'fb-username';
-
-function authHeaders(): Record {
- const token = process.env.NEXT_PUBLIC_API_TOKEN;
- if (!token) return {};
- return { Authorization: `Bearer ${token}` };
-}
-
-export function getUsername(): string | null {
- if (typeof window === 'undefined') return null;
- return localStorage.getItem(USERNAME_KEY);
-}
-
-export function setUsername(name: string): void {
- localStorage.setItem(USERNAME_KEY, name);
-}
-
-export async function fetchComments(projectSlug: string): Promise {
- const res = await fetch(`/api/comments?slug=${encodeURIComponent(projectSlug)}`, {
- headers: { ...authHeaders() },
- });
- if (!res.ok) return [];
- return res.json();
-}
-
-export async function createComment(comment: Comment, projectSlug: string): Promise {
- await fetch('/api/comments', {
- method: 'POST',
- headers: { 'Content-Type': 'application/json', ...authHeaders() },
- body: JSON.stringify({ ...comment, projectSlug }),
- });
-}
-
-export async function updateComment(id: string, updates: Record): Promise {
- await fetch('/api/comments', {
- method: 'PUT',
- headers: { 'Content-Type': 'application/json', ...authHeaders() },
- body: JSON.stringify({ id, ...updates }),
- });
-}
-
-export async function deleteComment(id: string): Promise {
- await fetch(`/api/comments?id=${encodeURIComponent(id)}`, {
- method: 'DELETE',
- headers: { ...authHeaders() },
- });
-}
-
-export async function renameAuthor(projectSlug: string, oldAuthor: string, newAuthor: string): Promise {
- await fetch('/api/comments', {
- method: 'PUT',
- headers: { 'Content-Type': 'application/json', ...authHeaders() },
- body: JSON.stringify({ id: '_rename', author: newAuthor, oldAuthor, projectSlug }),
- });
-}
-
-export function generateId(): string {
- return Date.now().toString(36) + Math.random().toString(36).substring(2, 8);
-}
diff --git a/src/lib/store.tsx b/src/lib/store.tsx
deleted file mode 100644
index 76d5a31..0000000
--- a/src/lib/store.tsx
+++ /dev/null
@@ -1,213 +0,0 @@
-'use client';
-
-import {
- createContext,
- useContext,
- useState,
- useCallback,
- useEffect,
- ReactNode,
-} from 'react';
-import { Comment, Priority, FilterMode, CommentType } from './types';
-import * as storage from './storage';
-
-function slugify(url: string): string {
- return url
- .replace(/^https?:\/\//, '')
- .replace(/[^a-zA-Z0-9\u3040-\u309F\u30A0-\u30FF\u4E00-\u9FFF]/g, '_')
- .substring(0, 100);
-}
-
-interface StoreState {
- username: string | null;
- targetUrl: string;
- projectSlug: string;
- comments: Comment[];
- filter: FilterMode;
- loading: boolean;
-}
-
-interface StoreActions {
- setUsername: (name: string) => void;
- addComment: (params: {
- quote: string;
- quoteContext: { beforeText: string; afterText: string };
- content: string;
- priority: Priority;
- type?: CommentType;
- parentId?: string | null;
- }) => void;
- editComment: (id: string, content: string, priority: Priority) => void;
- deleteComment: (id: string) => void;
- resolveComment: (id: string) => void;
- cyclePriority: (id: string) => void;
- setFilter: (filter: FilterMode) => void;
-}
-
-const StoreContext = createContext<(StoreState & StoreActions) | null>(null);
-
-export function StoreProvider({ children }: { children: ReactNode }) {
- const [targetUrl, setTargetUrl] = useState('');
- const [projectSlug, setProjectSlug] = useState('');
- const [username, setUsernameState] = useState(null);
- const [comments, setComments] = useState([]);
- const [filter, setFilter] = useState('unresolved');
- const [loading, setLoading] = useState(true);
-
- useEffect(() => {
- setUsernameState(storage.getUsername());
-
- const params = new URLSearchParams(window.location.search);
- const url = params.get('url') || '';
- if (url) {
- const slug = slugify(url);
- setTargetUrl(url);
- setProjectSlug(slug);
- storage.fetchComments(slug).then((c) => {
- setComments(c);
- setLoading(false);
- });
- } else {
- setLoading(false);
- }
- }, []);
-
- const refreshComments = useCallback(async () => {
- if (!projectSlug) return;
- const c = await storage.fetchComments(projectSlug);
- setComments(c);
- }, [projectSlug]);
-
- const setUsername = useCallback(async (name: string) => {
- const oldName = storage.getUsername();
- storage.setUsername(name);
- setUsernameState(name);
- if (oldName && projectSlug) {
- await storage.renameAuthor(projectSlug, oldName, name);
- await refreshComments();
- }
- }, [projectSlug, refreshComments]);
-
- const addComment = useCallback(
- async (params: {
- quote: string;
- quoteContext: { beforeText: string; afterText: string };
- content: string;
- priority: Priority;
- type?: CommentType;
- parentId?: string | null;
- }) => {
- if (!username || !projectSlug) return;
- const newComment: Comment = {
- id: storage.generateId(),
- author: username,
- type: params.type || 'comment',
- quote: params.quote,
- quoteContext: params.quoteContext,
- content: params.content,
- priority: params.priority,
- parentId: params.parentId || null,
- resolved: false,
- resolvedBy: null,
- resolvedAt: null,
- timestamp: Date.now(),
- updatedAt: null,
- pageUrl: targetUrl,
- };
- setComments((prev) => [...prev, newComment]);
- await storage.createComment(newComment, projectSlug);
- },
- [username, targetUrl, projectSlug]
- );
-
- const editComment = useCallback(
- async (id: string, content: string, priority: Priority) => {
- setComments((prev) =>
- prev.map((c) => (c.id === id ? { ...c, content, priority, updatedAt: Date.now() } : c))
- );
- await storage.updateComment(id, { content, priority });
- },
- []
- );
-
- const deleteComment = useCallback(
- async (id: string) => {
- setComments((prev) => prev.filter((c) => c.id !== id && c.parentId !== id));
- await storage.deleteComment(id);
- },
- []
- );
-
- const resolveComment = useCallback(
- async (id: string) => {
- if (!username) return;
- let updates: Record | null = null;
- setComments((prev) =>
- prev.map((c) => {
- if (c.id !== id) return c;
- const nowResolved = !c.resolved;
- updates = {
- resolved: nowResolved,
- resolvedBy: nowResolved ? username : null,
- resolvedAt: nowResolved ? Date.now() : null,
- };
- return { ...c, ...updates };
- })
- );
- if (updates) {
- await storage.updateComment(id, updates);
- }
- },
- [username]
- );
-
- const cyclePriority = useCallback(
- async (id: string) => {
- const cycle: Record = {
- must: 'better',
- better: 'want',
- want: 'must',
- };
- let newPriority: Priority | null = null;
- setComments((prev) =>
- prev.map((c) => {
- if (c.id !== id) return c;
- newPriority = cycle[c.priority];
- return { ...c, priority: newPriority };
- })
- );
- if (newPriority) {
- await storage.updateComment(id, { priority: newPriority });
- }
- },
- []
- );
-
- return (
-
- {children}
-
- );
-}
-
-export function useStore() {
- const ctx = useContext(StoreContext);
- if (!ctx) throw new Error('useStore must be used within StoreProvider');
- return ctx;
-}
diff --git a/src/lib/utils.ts b/src/lib/utils.ts
deleted file mode 100644
index bd0c391..0000000
--- a/src/lib/utils.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import { clsx, type ClassValue } from "clsx"
-import { twMerge } from "tailwind-merge"
-
-export function cn(...inputs: ClassValue[]) {
- return twMerge(clsx(inputs))
-}
diff --git a/src/shared/api-client.ts b/src/shared/api-client.ts
new file mode 100644
index 0000000..e551e32
--- /dev/null
+++ b/src/shared/api-client.ts
@@ -0,0 +1,5 @@
+export function authHeaders(token: string): Record {
+ const hdrs: Record = { 'Content-Type': 'application/json' };
+ if (token) hdrs['Authorization'] = 'Bearer ' + token;
+ return hdrs;
+}
diff --git a/src/shared/constants.ts b/src/shared/constants.ts
new file mode 100644
index 0000000..b2a130c
--- /dev/null
+++ b/src/shared/constants.ts
@@ -0,0 +1,61 @@
+import type { Priority } from './types';
+
+export const PRIORITY_COLORS: Record<
+ Priority,
+ { bg: string; text: string; light: string; border: string }
+> = {
+ must: {
+ bg: '#ef4444',
+ text: '#fff',
+ light: 'rgba(239,68,68,0.1)',
+ border: 'rgba(239,68,68,0.3)',
+ },
+ better: {
+ bg: '#f59e0b',
+ text: '#fff',
+ light: 'rgba(245,158,11,0.1)',
+ border: 'rgba(245,158,11,0.3)',
+ },
+ want: {
+ bg: '#22c55e',
+ text: '#fff',
+ light: 'rgba(34,197,94,0.1)',
+ border: 'rgba(34,197,94,0.3)',
+ },
+};
+
+export const PRIORITY_LABELS: Record = {
+ must: 'Must',
+ better: 'Better',
+ want: 'Want',
+};
+
+export const PRIORITY_CYCLE: Record = {
+ must: 'better',
+ better: 'want',
+ want: 'must',
+};
+
+export const HIGHLIGHT_COLORS: Record<
+ Priority,
+ { bg: string; hoverBg: string; border: string }
+> = {
+ must: {
+ bg: 'rgba(239,68,68,0.15)',
+ hoverBg: 'rgba(239,68,68,0.25)',
+ border: '#ef4444',
+ },
+ better: {
+ bg: 'rgba(245,158,11,0.15)',
+ hoverBg: 'rgba(245,158,11,0.25)',
+ border: '#f59e0b',
+ },
+ want: {
+ bg: 'rgba(34,197,94,0.15)',
+ hoverBg: 'rgba(34,197,94,0.25)',
+ border: '#22c55e',
+ },
+};
+
+export const USERNAME_KEY = 'fb-username';
+export const SIDEBAR_WIDTH_KEY = 'fb-sidebar-width';
diff --git a/src/shared/slug.ts b/src/shared/slug.ts
new file mode 100644
index 0000000..3bf7a65
--- /dev/null
+++ b/src/shared/slug.ts
@@ -0,0 +1,10 @@
+export function slugify(url: string): string {
+ return url
+ .replace(/^https?:\/\//, '')
+ .replace(/[^a-zA-Z0-9\u3040-\u309F\u30A0-\u30FF\u4E00-\u9FFF]/g, '_')
+ .substring(0, 100);
+}
+
+export function generateId(): string {
+ return Date.now().toString(36) + Math.random().toString(36).substring(2, 8);
+}
diff --git a/src/shared/time.ts b/src/shared/time.ts
new file mode 100644
index 0000000..da10abb
--- /dev/null
+++ b/src/shared/time.ts
@@ -0,0 +1,12 @@
+export function fmtTime(ts: number): string {
+ const d = Date.now() - ts;
+ if (d < 60000) return 'たった今';
+ if (d < 3600000) return Math.floor(d / 60000) + '分前';
+ if (d < 86400000) return Math.floor(d / 3600000) + '時間前';
+ return new Date(ts).toLocaleDateString('ja-JP', {
+ month: 'short',
+ day: 'numeric',
+ hour: '2-digit',
+ minute: '2-digit',
+ });
+}
diff --git a/src/lib/types.ts b/src/shared/types.ts
similarity index 100%
rename from src/lib/types.ts
rename to src/shared/types.ts
diff --git a/src/widget/api.ts b/src/widget/api.ts
new file mode 100644
index 0000000..ea72945
--- /dev/null
+++ b/src/widget/api.ts
@@ -0,0 +1,23 @@
+import { authHeaders } from '../shared/api-client';
+
+let apiBase = '';
+let apiToken = '';
+
+export function initApi(base: string, token: string): void {
+ apiBase = base;
+ apiToken = token;
+}
+
+export function api(method: string, params: Record): Promise {
+ let url = apiBase + '/api/comments';
+ const hdrs = authHeaders(apiToken);
+ const opts: RequestInit = { method, headers: hdrs };
+ if (method === 'GET') {
+ url += '?slug=' + encodeURIComponent(params.slug as string);
+ } else if (method === 'DELETE') {
+ url += '?id=' + encodeURIComponent(params.id as string);
+ } else {
+ opts.body = JSON.stringify(params);
+ }
+ return fetch(url, opts).then((r) => r.json());
+}
diff --git a/src/widget/dom.ts b/src/widget/dom.ts
new file mode 100644
index 0000000..109bf44
--- /dev/null
+++ b/src/widget/dom.ts
@@ -0,0 +1,24 @@
+type Attrs = Record;
+
+export function el(tag: string, attrs?: Attrs | null, children?: string | Node | (Node | null)[] | null): HTMLElement {
+ const e = document.createElement(tag);
+ if (attrs) Object.keys(attrs).forEach((k) => {
+ const v = attrs[k];
+ if (k === 'className') e.className = v as string;
+ else if (k === 'innerHTML') e.innerHTML = v as string;
+ else if (k.startsWith('on') && typeof v === 'function') e.addEventListener(k.substring(2).toLowerCase(), v as EventListener);
+ else e.setAttribute(k, String(v));
+ });
+ if (children != null) {
+ if (typeof children === 'string') e.textContent = children;
+ else if (Array.isArray(children)) children.forEach((c) => { if (c) e.appendChild(c); });
+ else e.appendChild(children);
+ }
+ return e;
+}
+
+export function esc(s: string): string {
+ const d = document.createElement('div');
+ d.textContent = s;
+ return d.innerHTML;
+}
diff --git a/src/widget/highlight.ts b/src/widget/highlight.ts
new file mode 100644
index 0000000..756baba
--- /dev/null
+++ b/src/widget/highlight.ts
@@ -0,0 +1,110 @@
+import { state, type FbComment } from './state';
+
+function collectTextNodes(): Text[] {
+ const nodes: Text[] = [];
+ const tw = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT, {
+ acceptNode(n) {
+ const p = n.parentElement;
+ if (!p) return NodeFilter.FILTER_REJECT;
+ if (p.tagName === 'SCRIPT' || p.tagName === 'STYLE') return NodeFilter.FILTER_REJECT;
+ if (p.closest('#fb-sidebar,#fb-toggle,#fb-popup,.fb-highlight')) return NodeFilter.FILTER_REJECT;
+ return NodeFilter.FILTER_ACCEPT;
+ }
+ });
+ let n: Node | null;
+ while ((n = tw.nextNode())) nodes.push(n as Text);
+ return nodes;
+}
+
+export function mapNormToOrig(orig: string, normStart: number, normEnd: number): [number, number] | null {
+ const normalized = orig.replace(/[\s\u00A0]+/g, ' ');
+ if (normStart >= normalized.length) return null;
+ let origIdx = 0, normIdx = 0;
+ let origStart = -1, origEnd = -1;
+ while (origIdx < orig.length) {
+ if (normIdx === normStart && origStart === -1) origStart = origIdx;
+ if (normIdx === normEnd) { origEnd = origIdx; break; }
+ if (normIdx < normalized.length && orig[origIdx] === normalized[normIdx]) {
+ origIdx++; normIdx++;
+ } else {
+ origIdx++;
+ }
+ }
+ if (origEnd === -1 && normIdx >= normEnd) origEnd = origIdx;
+ if (origStart === -1 || origEnd === -1 || origStart >= origEnd) return null;
+ return [origStart, origEnd];
+}
+
+function wrapTextRange(node: Text, start: number, end: number, comment: FbComment, onClickHighlight: (id: string) => void): void {
+ const orig = node.textContent!;
+ const before = document.createTextNode(orig.substring(0, start));
+ const mark = document.createElement('mark');
+ mark.className = 'fb-highlight fb-highlight-' + comment.priority;
+ mark.dataset.commentId = comment.id;
+ mark.textContent = orig.substring(start, end);
+ mark.addEventListener('click', () => { onClickHighlight(comment.id); });
+ const after = document.createTextNode(orig.substring(end));
+ node.parentNode!.insertBefore(before, node);
+ node.parentNode!.insertBefore(mark, node);
+ node.parentNode!.insertBefore(after, node);
+ node.parentNode!.removeChild(node);
+}
+
+export function applyHighlights(onClickHighlight: (id: string) => void): void {
+ document.querySelectorAll('.fb-highlight').forEach((el) => {
+ const t = document.createTextNode(el.textContent || '');
+ el.parentNode!.replaceChild(t, el);
+ });
+ document.body.normalize();
+
+ state.comments.filter((c) => !c.parentId && !c.resolved && c.quote && c.quote.length >= 2).forEach((c) => {
+ const search = c.quote.replace(/[\s\u00A0]+/g, ' ').trim();
+ const textNodes = collectTextNodes();
+ let found = false;
+
+ for (let i = 0; i < textNodes.length; i++) {
+ const node = textNodes[i];
+ const orig = node.textContent!;
+
+ const di = orig.indexOf(search);
+ if (di !== -1) {
+ try { wrapTextRange(node, di, di + search.length, c, onClickHighlight); found = true; } catch (_) { /* ignore */ }
+ break;
+ }
+
+ const norm = orig.replace(/[\s\u00A0]+/g, ' ');
+ const ni = norm.indexOf(search);
+ if (ni === -1) continue;
+ const range = mapNormToOrig(orig, ni, ni + search.length);
+ if (range) {
+ try { wrapTextRange(node, range[0], range[1], c, onClickHighlight); found = true; } catch (_) { /* ignore */ }
+ break;
+ }
+ }
+
+ if (!found) {
+ let concat = '';
+ const nodeMap: Array<{ node: Text; start: number; end: number }> = [];
+ for (let j = 0; j < textNodes.length; j++) {
+ const s = concat.length;
+ concat += textNodes[j].textContent;
+ nodeMap.push({ node: textNodes[j], start: s, end: concat.length });
+ }
+ const concatNorm = concat.replace(/[\s\u00A0]+/g, ' ');
+ const ci = concatNorm.indexOf(search);
+ if (ci !== -1) {
+ const range = mapNormToOrig(concat, ci, ci + search.length);
+ if (range) {
+ const mStart = range[0], mEnd = range[1];
+ for (let k = nodeMap.length - 1; k >= 0; k--) {
+ const nm = nodeMap[k];
+ if (nm.end <= mStart || nm.start >= mEnd) continue;
+ const ls = Math.max(0, mStart - nm.start);
+ const le = Math.min(nm.node.textContent!.length, mEnd - nm.start);
+ try { wrapTextRange(nm.node, ls, le, c, onClickHighlight); } catch (_) { /* ignore */ }
+ }
+ }
+ }
+ }
+ });
+}
diff --git a/src/widget/icons.ts b/src/widget/icons.ts
new file mode 100644
index 0000000..d4b29ee
--- /dev/null
+++ b/src/widget/icons.ts
@@ -0,0 +1,14 @@
+export const SVG: Record = {
+ message: '',
+ check: '',
+ rotateCcw: '',
+ pencil: '',
+ trash: '',
+ user: '',
+ x: '',
+ panelRight: '',
+};
+
+export function icon(name: string, size = 14, strokeWidth = 2): string {
+ return (SVG[name] || '').replace(/SIZE/g, String(size)).replace(/SW/g, String(strokeWidth));
+}
diff --git a/src/widget/index.ts b/src/widget/index.ts
new file mode 100644
index 0000000..d62d960
--- /dev/null
+++ b/src/widget/index.ts
@@ -0,0 +1,158 @@
+/**
+ * Icons: Lucide (https://lucide.dev)
+ * ISC License - Copyright (c) Lucide Contributors 2026
+ */
+
+// document.currentScript は IIFE 先頭でキャプチャ必須(esbuild の import 巻き上げ前に実行される)
+const SCRIPT = document.currentScript as HTMLScriptElement | null;
+const API_BASE = SCRIPT ? SCRIPT.src.replace(/\/widget\.js.*$/, '') : '';
+const API_TOKEN = SCRIPT ? (SCRIPT.dataset.token || '') : '';
+
+import type { Priority } from '../shared/types';
+import { USERNAME_KEY, PRIORITY_CYCLE } from '../shared/constants';
+import { generateId } from '../shared/slug';
+import { initApi, api } from './api';
+import { state, slug, type FbComment } from './state';
+import { injectStyles } from './styles';
+import { render, toggleSidebar, setRenderDeps } from './render/index';
+import { setSidebarActions } from './render/sidebar';
+import { applyHighlights } from './highlight';
+import { scrollToQuote, scrollToCard } from './scroll';
+import { setupTextSelection } from './selection';
+
+initApi(API_BASE, API_TOKEN);
+
+function loadComments(): Promise {
+ return api('GET', { slug }).then((c) => {
+ if (Array.isArray(c)) state.comments = c;
+ render();
+ applyHighlights(onClickHighlight);
+ }).catch(() => {
+ render();
+ applyHighlights(onClickHighlight);
+ });
+}
+
+function closePopup(): void {
+ state.selectedText = '';
+ state.selectedRect = null;
+ state.popupContent = '';
+ state.popupPriority = 'must';
+ render();
+}
+
+function submitComment(priority: Priority): void {
+ if (!state.username || !state.selectedText) return;
+ const c: FbComment = {
+ id: generateId(), author: state.username, type: 'comment',
+ quote: state.selectedText, quoteContext: state.selectedQuoteContext,
+ content: state.popupContent.trim(),
+ priority, parentId: null, pageUrl: window.location.href,
+ projectSlug: slug, timestamp: Date.now(),
+ resolved: false, resolvedBy: null, resolvedAt: null, updatedAt: null,
+ };
+ state.comments.push(c);
+ closePopup();
+ applyHighlights(onClickHighlight);
+ api('POST', c as unknown as Record).then(loadComments);
+}
+
+function resolveComment(id: string): void {
+ const c = state.comments.find((x) => x.id === id);
+ if (!c) return;
+ const now = !c.resolved;
+ c.resolved = now;
+ c.resolvedBy = now ? state.username : null;
+ c.resolvedAt = now ? Date.now() : null;
+ render(); applyHighlights(onClickHighlight);
+ api('PUT', { id, action: 'resolve', resolved: now, resolvedBy: c.resolvedBy, resolvedAt: c.resolvedAt });
+}
+
+function cyclePriority(id: string): void {
+ const c = state.comments.find((x) => x.id === id);
+ if (!c || c.author !== state.username) return;
+ c.priority = PRIORITY_CYCLE[c.priority] || 'must';
+ render(); applyHighlights(onClickHighlight);
+ api('PUT', { id, action: 'cyclePriority', priority: c.priority });
+}
+
+function deleteComment(id: string): void {
+ state.comments = state.comments.filter((c) => c.id !== id && c.parentId !== id);
+ render(); applyHighlights(onClickHighlight);
+ api('DELETE', { id });
+}
+
+function deleteReply(id: string): void {
+ state.comments = state.comments.filter((c) => c.id !== id);
+ render();
+ api('DELETE', { id });
+}
+
+function saveEdit(id: string): void {
+ const c = state.comments.find((x) => x.id === id);
+ if (!c) return;
+ c.content = state.editContent;
+ c.priority = state.editPriority;
+ state.editingId = null;
+ render(); applyHighlights(onClickHighlight);
+ api('PUT', { id, action: 'edit', content: c.content, priority: c.priority });
+}
+
+function submitReply(parentId: string): void {
+ if (!state.replyText.trim() || !state.username) return;
+ const r: FbComment = {
+ id: generateId(), author: state.username, type: 'comment',
+ quote: '', quoteContext: { beforeText: '', afterText: '' },
+ content: state.replyText.trim(), priority: 'want',
+ parentId, pageUrl: window.location.href,
+ projectSlug: slug, timestamp: Date.now(),
+ resolved: false, resolvedBy: null, resolvedAt: null, updatedAt: null,
+ };
+ state.comments.push(r);
+ state.replyingTo = null;
+ state.replyText = '';
+ render();
+ api('POST', r as unknown as Record);
+}
+
+function finishNameEdit(): void {
+ if (state.nameInput.trim() && state.nameInput.trim() !== state.username) {
+ const oldName = state.username;
+ state.username = state.nameInput.trim();
+ localStorage.setItem(USERNAME_KEY, state.username);
+ api('PUT', { id: '_rename', action: 'rename', author: state.username, oldAuthor: oldName, projectSlug: slug }).then(loadComments);
+ }
+ state.editingName = false;
+ render();
+}
+
+function onClickHighlight(id: string): void {
+ scrollToCard(id, toggleSidebar);
+}
+
+// Wire up dependencies before first render
+setRenderDeps(closePopup, submitComment);
+setSidebarActions({
+ toggleSidebar,
+ cyclePriority,
+ scrollToQuote,
+ resolveComment,
+ deleteComment,
+ deleteReply,
+ saveEdit,
+ submitReply,
+ finishNameEdit,
+});
+
+function init(): void {
+ injectStyles();
+ render();
+ setupTextSelection(render, closePopup);
+ loadComments();
+}
+
+if (document.readyState === 'loading') {
+ document.addEventListener('DOMContentLoaded', init);
+} else {
+ init();
+}
diff --git a/src/widget/render/card.ts b/src/widget/render/card.ts
new file mode 100644
index 0000000..2fa28e9
--- /dev/null
+++ b/src/widget/render/card.ts
@@ -0,0 +1,79 @@
+import { PRIORITY_COLORS } from '../../shared/constants';
+import { fmtTime } from '../../shared/time';
+import { esc } from '../dom';
+import { icon } from '../icons';
+import { state, type FbComment } from '../state';
+
+export function renderCard(c: FbComment): string {
+ const isOwn = c.author === state.username;
+ const pc = PRIORITY_COLORS[c.priority] || PRIORITY_COLORS.want;
+
+ let h = '';
+
+ h += '
';
+ h += '
' + esc(c.author.charAt(0)) + '
';
+ h += '
' + esc(c.author) + '';
+ h += '
' + fmtTime(c.timestamp) + '';
+ if (c.resolved) h += '
' + icon('check', 12) + ' 解決済';
+ h += '
';
+ h += '
' + esc(c.priority.charAt(0).toUpperCase() + c.priority.slice(1)) + '';
+ h += '
';
+
+ if (c.quote) {
+ const q = c.quote.length > 100 ? c.quote.substring(0, 100) + '...' : c.quote;
+ h += '
' + esc(q) + '
';
+ }
+
+ if (state.editingId === c.id) {
+ h += '
';
+ h += '
';
+ (['must', 'better', 'want'] as const).forEach((p) => {
+ const sel = state.editPriority === p;
+ const pc2 = PRIORITY_COLORS[p];
+ h += '';
+ });
+ h += '
';
+ h += '
';
+ h += '
';
+ h += '
';
+ } else {
+ h += '
' + esc(c.content) + '
';
+ }
+
+ if (state.editingId !== c.id) {
+ h += '
';
+ h += '';
+ h += '';
+ if (isOwn) h += '';
+ if (isOwn) h += '';
+ h += '
';
+ }
+
+ const replies = state.comments.filter((r) => r.parentId === c.id).sort((a, b) => a.timestamp - b.timestamp);
+ if (replies.length > 0) {
+ h += '
';
+ replies.forEach((r) => {
+ const isOwnReply = r.author === state.username;
+ h += '
' + esc(r.author.charAt(0)) + '
' + esc(r.author) + ' · ' + fmtTime(r.timestamp) + '
';
+ if (state.editingId === r.id) {
+ h += '
';
+ } else {
+ h += '
' + esc(r.content) + '
';
+ h += '
';
+ h += '';
+ if (isOwnReply) h += '';
+ if (isOwnReply) h += '';
+ h += '
';
+ }
+ h += '
';
+ });
+ h += '
';
+ }
+
+ if (state.replyingTo === c.id) {
+ h += '
';
+ }
+
+ h += '
';
+ return h;
+}
diff --git a/src/widget/render/index.ts b/src/widget/render/index.ts
new file mode 100644
index 0000000..50cd0fe
--- /dev/null
+++ b/src/widget/render/index.ts
@@ -0,0 +1,22 @@
+import type { Priority } from '../../shared/types';
+import { renderToggle } from './toggle';
+import { renderSidebar, toggleSidebar } from './sidebar';
+import { renderPopup } from './popup';
+import { renderNameDialog } from './name-dialog';
+
+let _closePopup: (() => void) | null = null;
+let _submitComment: ((priority: Priority) => void) | null = null;
+
+export function setRenderDeps(closePopup: () => void, submitComment: (priority: Priority) => void): void {
+ _closePopup = closePopup;
+ _submitComment = submitComment;
+}
+
+export function render(): void {
+ renderToggle(toggleSidebar);
+ renderSidebar(render);
+ renderPopup(render, _closePopup!, _submitComment!);
+ renderNameDialog(render);
+}
+
+export { toggleSidebar };
diff --git a/src/widget/render/name-dialog.ts b/src/widget/render/name-dialog.ts
new file mode 100644
index 0000000..05a9d5a
--- /dev/null
+++ b/src/widget/render/name-dialog.ts
@@ -0,0 +1,26 @@
+import { USERNAME_KEY } from '../../shared/constants';
+import { el } from '../dom';
+import { state } from '../state';
+
+export function renderNameDialog(onRender: () => void): void {
+ const existing = document.getElementById('fb-name-overlay');
+ if (state.username) { if (existing) existing.remove(); return; }
+ if (existing) return;
+ const overlay = el('div', { id: 'fb-name-overlay', className: 'fb-name-overlay' });
+ overlay.innerHTML = '';
+ document.body.appendChild(overlay);
+ const input = document.getElementById('fb-name-field') as HTMLInputElement;
+ const btn = document.getElementById('fb-name-submit') as HTMLButtonElement;
+ input.addEventListener('input', () => { btn.disabled = !input.value.trim(); });
+ input.addEventListener('keydown', (e) => { if (e.key === 'Enter' && input.value.trim()) { setName(input.value.trim(), onRender); } });
+ btn.addEventListener('click', () => { if (input.value.trim()) setName(input.value.trim(), onRender); });
+ setTimeout(() => { input.focus(); }, 100);
+}
+
+function setName(name: string, onRender: () => void): void {
+ state.username = name;
+ localStorage.setItem(USERNAME_KEY, name);
+ const overlay = document.getElementById('fb-name-overlay');
+ if (overlay) overlay.remove();
+ onRender();
+}
diff --git a/src/widget/render/popup.ts b/src/widget/render/popup.ts
new file mode 100644
index 0000000..1c45ac4
--- /dev/null
+++ b/src/widget/render/popup.ts
@@ -0,0 +1,61 @@
+import type { Priority } from '../../shared/types';
+import { PRIORITY_COLORS } from '../../shared/constants';
+import { el, esc } from '../dom';
+import { state } from '../state';
+
+export function renderPopup(onRender: () => void, closePopup: () => void, submitComment: (priority: Priority) => void): void {
+ let popup = document.getElementById('fb-popup');
+ const isNew = !popup;
+ if (isNew) {
+ popup = el('div', { id: 'fb-popup', className: 'fb-popup' });
+ document.body.appendChild(popup);
+ popup.addEventListener('click', (e) => {
+ const t = (e.target as HTMLElement).closest('[data-action]') as HTMLElement | null;
+ if (!t) return;
+ if (t.dataset.action === 'cancel-popup') { closePopup(); }
+ else if (t.dataset.action === 'set-popup-pri') { state.popupPriority = t.dataset.pri as Priority; onRender(); }
+ else if (t.dataset.action === 'submit-popup') { submitComment(state.popupPriority); }
+ });
+ popup.addEventListener('input', (e) => {
+ if ((e.target as HTMLElement).dataset.action === 'popup-textarea') state.popupContent = (e.target as HTMLTextAreaElement).value;
+ });
+ popup.addEventListener('keydown', (e) => {
+ if ((e.target as HTMLElement).dataset.action === 'popup-textarea' && (e.metaKey || e.ctrlKey) && e.key === 'Enter') {
+ submitComment(state.popupPriority);
+ }
+ });
+ }
+ if (!state.selectedRect) { popup!.classList.remove('show'); return; }
+ popup!.classList.add('show');
+
+ const q = state.selectedText.length > 120 ? state.selectedText.substring(0, 120) + '...' : state.selectedText;
+ const selPc = PRIORITY_COLORS[state.popupPriority];
+ let h = '';
+ h += '';
+ h += '';
+ h += '';
+ h += '';
+ popup!.innerHTML = h;
+
+ const rect = state.selectedRect;
+ const pw = 400, ph = 300, m = 12;
+ let top = rect.bottom + m;
+ if (top + ph > window.innerHeight) top = rect.top - ph - m;
+ if (top < m) top = Math.max(m, (window.innerHeight - ph) / 2);
+ const availW = state.sidebarOpen ? window.innerWidth - state.sidebarWidth : window.innerWidth;
+ const left = Math.max(m, Math.min(rect.left, availW - pw - m));
+ popup!.style.top = top + 'px';
+ popup!.style.left = left + 'px';
+}
diff --git a/src/widget/render/sidebar.ts b/src/widget/render/sidebar.ts
new file mode 100644
index 0000000..312ab7f
--- /dev/null
+++ b/src/widget/render/sidebar.ts
@@ -0,0 +1,197 @@
+import type { Priority, FilterMode } from '../../shared/types';
+import { SIDEBAR_WIDTH_KEY } from '../../shared/constants';
+import { el, esc } from '../dom';
+import { icon } from '../icons';
+import { state } from '../state';
+import { renderCard } from './card';
+
+function applySidebarWidth(): void {
+ const sb = document.getElementById('fb-sidebar');
+ if (!sb) return;
+ const w = state.sidebarWidth;
+ sb.style.width = w + 'px';
+ sb.style.right = state.sidebarOpen ? '0px' : (-(w + 20)) + 'px';
+ document.body.style.marginRight = state.sidebarOpen ? w + 'px' : '';
+}
+
+export function toggleSidebar(): void {
+ state.sidebarOpen = !state.sidebarOpen;
+ const btn = document.getElementById('fb-toggle');
+ if (btn) btn.style.display = state.sidebarOpen ? 'none' : '';
+ document.body.style.transition = 'margin-right 0.3s ease';
+ applySidebarWidth();
+}
+
+function topLevel() { return state.comments.filter((c) => !c.parentId); }
+
+function filtered() {
+ const tl = topLevel();
+ if (state.filter === 'resolved') return tl.filter((c) => c.resolved);
+ if (state.filter === 'all') return tl;
+ return tl.filter((c) => !c.resolved);
+}
+
+export function renderSidebar(onRender: () => void): void {
+ let sb = document.getElementById('fb-sidebar');
+ const isNew = !sb;
+ if (isNew) {
+ sb = el('div', { id: 'fb-sidebar' });
+ document.body.appendChild(sb);
+ sb.addEventListener('mouseover', (e) => {
+ const card = (e.target as HTMLElement).closest('.fb-card') as HTMLElement | null;
+ if (!card) return;
+ const mark = document.querySelector('.fb-highlight[data-comment-id="' + card.dataset.id + '"]');
+ if (mark) mark.classList.add('fb-pulse');
+ });
+ sb.addEventListener('mouseout', (e) => {
+ const card = (e.target as HTMLElement).closest('.fb-card') as HTMLElement | null;
+ if (!card) return;
+ if (e.relatedTarget && card.contains(e.relatedTarget as Node)) return;
+ const mark = document.querySelector('.fb-highlight[data-comment-id="' + card.dataset.id + '"]');
+ if (mark) mark.classList.remove('fb-pulse');
+ });
+ }
+ applySidebarWidth();
+
+ const tl = topLevel();
+ const counts = {
+ unresolved: tl.filter((c) => !c.resolved).length,
+ resolved: tl.filter((c) => c.resolved).length,
+ all: tl.length,
+ };
+
+ let html = '';
+
+ html += '';
+
+ if (state.username) {
+ if (state.editingName) {
+ html += '';
+ } else {
+ html += '' + icon('user', 14) + esc(state.username) + '
';
+ }
+ }
+
+ html += '';
+ (['unresolved', 'resolved', 'all'] as const).forEach((f) => {
+ const label = f === 'unresolved' ? '未解決' : f === 'resolved' ? '解決済' : 'すべて';
+ html += '';
+ });
+ html += '
';
+
+ const items = filtered().sort((a, b) => b.timestamp - a.timestamp);
+ html += '';
+ if (items.length === 0) {
+ html += '
' + icon('message', 40) + 'コメントはまだありません
テキストを選択してコメントを追加
';
+ } else {
+ items.forEach((c) => { html += renderCard(c); });
+ }
+ html += '
';
+
+ sb!.innerHTML = html;
+ if (isNew) bindSidebarEvents(sb!, onRender);
+}
+
+export interface SidebarActions {
+ toggleSidebar: () => void;
+ cyclePriority: (id: string) => void;
+ scrollToQuote: (id: string) => void;
+ resolveComment: (id: string) => void;
+ deleteComment: (id: string) => void;
+ deleteReply: (id: string) => void;
+ saveEdit: (id: string) => void;
+ submitReply: (id: string) => void;
+ finishNameEdit: () => void;
+}
+
+let _actions: SidebarActions | null = null;
+
+export function setSidebarActions(actions: SidebarActions): void {
+ _actions = actions;
+}
+
+function bindSidebarEvents(sb: HTMLElement, onRender: () => void): void {
+ sb.addEventListener('click', (e) => {
+ const t = (e.target as HTMLElement).closest('[data-action]') as HTMLElement | null;
+ if (t) {
+ const action = t.dataset.action;
+ const id = t.dataset.id;
+
+ if (action === 'close') { _actions?.toggleSidebar(); }
+ else if (action === 'edit-name') { state.editingName = true; state.nameInput = state.username; onRender(); }
+ else if (action === 'cycle' && id) { _actions?.cyclePriority(id); }
+ else if (action === 'scroll-quote' && id) { _actions?.scrollToQuote(id); }
+ else if (action === 'reply' && id) { state.replyingTo = state.replyingTo === id ? null : id; state.replyText = ''; onRender(); }
+ else if (action === 'resolve' && id) { _actions?.resolveComment(id); }
+ else if (action === 'edit' && id) { const c = state.comments.find((x) => x.id === id); if (c) { state.editingId = id; state.editContent = c.content; state.editPriority = c.priority; onRender(); } }
+ else if (action === 'delete' && id) { _actions?.deleteComment(id); }
+ else if (action === 'delete-reply' && id) { _actions?.deleteReply(id); }
+ else if (action === 'cancel-edit') { state.editingId = null; onRender(); }
+ else if (action === 'save-edit' && id) { _actions?.saveEdit(id); }
+ else if (action === 'submit-reply' && id) { _actions?.submitReply(id); }
+ else if (action === 'set-edit-pri') { state.editPriority = t.dataset.pri as Priority; onRender(); }
+ return;
+ }
+ const filterBtn = (e.target as HTMLElement).closest('[data-filter]') as HTMLElement | null;
+ if (filterBtn) { state.filter = filterBtn.dataset.filter as FilterMode; onRender(); return; }
+
+ const card = (e.target as HTMLElement).closest('.fb-card') as HTMLElement | null;
+ if (card && card.dataset.id) {
+ _actions?.scrollToQuote(card.dataset.id);
+ }
+ });
+
+ sb.addEventListener('mousedown', (e) => {
+ if (!(e.target as HTMLElement).closest('.fb-resize-handle')) return;
+ e.preventDefault();
+ const startX = e.clientX;
+ const startWidth = state.sidebarWidth;
+ const handle = (e.target as HTMLElement).closest('.fb-resize-handle')!;
+ document.body.classList.add('fb-resizing');
+ handle.classList.add('active');
+ function onMove(ev: MouseEvent) {
+ state.sidebarWidth = Math.min(800, Math.max(300, startWidth + (startX - ev.clientX)));
+ const s = document.getElementById('fb-sidebar');
+ if (s) s.style.width = state.sidebarWidth + 'px';
+ document.body.style.transition = 'none';
+ document.body.style.marginRight = state.sidebarWidth + 'px';
+ }
+ function onUp() {
+ document.removeEventListener('mousemove', onMove);
+ document.removeEventListener('mouseup', onUp);
+ document.body.classList.remove('fb-resizing');
+ handle.classList.remove('active');
+ document.body.style.transition = '';
+ localStorage.setItem(SIDEBAR_WIDTH_KEY, String(state.sidebarWidth));
+ }
+ document.addEventListener('mousemove', onMove);
+ document.addEventListener('mouseup', onUp);
+ });
+
+ sb.addEventListener('input', (e) => {
+ const t = e.target as HTMLInputElement;
+ if (t.dataset.action === 'name-input') { state.nameInput = t.value; }
+ else if (t.dataset.action === 'edit-textarea') { state.editContent = t.value; }
+ else if (t.dataset.action === 'reply-textarea') { state.replyText = t.value; const btn = sb.querySelector('[data-action="submit-reply"]') as HTMLButtonElement | null; if (btn) btn.disabled = !state.replyText.trim(); }
+ });
+
+ sb.addEventListener('keydown', (e) => {
+ const t = e.target as HTMLElement;
+ if (t.dataset.action === 'name-input') {
+ if (e.key === 'Enter') { _actions?.finishNameEdit(); }
+ else if (e.key === 'Escape') { state.editingName = false; onRender(); }
+ }
+ if (t.dataset.action === 'reply-textarea' && (e.metaKey || e.ctrlKey) && e.key === 'Enter') {
+ const id = (sb.querySelector('[data-action="submit-reply"]') as HTMLElement | null)?.dataset.id;
+ if (id) _actions?.submitReply(id);
+ }
+ });
+
+ sb.addEventListener('blur', (e) => {
+ if ((e.target as HTMLElement).dataset?.action === 'name-input') { _actions?.finishNameEdit(); }
+ }, true);
+}
diff --git a/src/widget/render/toggle.ts b/src/widget/render/toggle.ts
new file mode 100644
index 0000000..8b60127
--- /dev/null
+++ b/src/widget/render/toggle.ts
@@ -0,0 +1,18 @@
+import { el } from '../dom';
+import { icon } from '../icons';
+import { state } from '../state';
+
+export function renderToggle(toggleSidebar: () => void): void {
+ let btn = document.getElementById('fb-toggle');
+ if (!btn) {
+ btn = el('button', { id: 'fb-toggle', onClick: toggleSidebar });
+ document.body.appendChild(btn);
+ }
+ const unresolvedCount = state.comments.filter((c) => !c.parentId && !c.resolved).length;
+ let h = '' + icon('panelRight', 16);
+ if (unresolvedCount > 0) h += '' + unresolvedCount + '';
+ h += '';
+ h += 'コメント';
+ btn.innerHTML = h;
+ btn.style.display = state.sidebarOpen ? 'none' : '';
+}
diff --git a/src/widget/scroll.ts b/src/widget/scroll.ts
new file mode 100644
index 0000000..2f45f06
--- /dev/null
+++ b/src/widget/scroll.ts
@@ -0,0 +1,32 @@
+import type { Priority } from '../shared/types';
+import { state } from './state';
+
+const PRIORITY_FLASH: Record = {
+ must: 'rgba(239,68,68,0.4)',
+ better: 'rgba(245,158,11,0.4)',
+ want: 'rgba(34,197,94,0.4)',
+};
+
+export function scrollToQuote(id: string): void {
+ const mark = document.querySelector('.fb-highlight[data-comment-id="' + id + '"]') as HTMLElement | null;
+ if (!mark) return;
+ mark.scrollIntoView({ behavior: 'smooth', block: 'center' });
+ const c = state.comments.find((x) => x.id === id);
+ const flashColor = c ? (PRIORITY_FLASH[c.priority] || PRIORITY_FLASH.want) : PRIORITY_FLASH.want;
+ const orig = mark.style.backgroundColor;
+ mark.style.backgroundColor = flashColor;
+ mark.style.transition = 'background-color 0.3s';
+ setTimeout(() => { mark.style.backgroundColor = orig; }, 1500);
+}
+
+export function scrollToCard(id: string, toggleSidebar: () => void): void {
+ const wasClosed = !state.sidebarOpen;
+ if (wasClosed) { toggleSidebar(); }
+ setTimeout(() => {
+ const card = document.querySelector('.fb-card[data-id="' + id + '"]') as HTMLElement | null;
+ if (!card) return;
+ card.scrollIntoView({ behavior: 'smooth', block: 'center' });
+ card.classList.add('fb-focused');
+ setTimeout(() => { card.classList.remove('fb-focused'); }, 1500);
+ }, wasClosed ? 350 : 0);
+}
diff --git a/src/widget/selection.ts b/src/widget/selection.ts
new file mode 100644
index 0000000..20b9494
--- /dev/null
+++ b/src/widget/selection.ts
@@ -0,0 +1,35 @@
+import { state, type QuoteContext } from './state';
+
+export function getQuoteContext(range: Range): QuoteContext {
+ let before = '', after = '';
+ try {
+ const br = document.createRange();
+ br.setStart(document.body, 0);
+ br.setEnd(range.startContainer, range.startOffset);
+ before = br.toString().slice(-50).replace(/[\s\u00A0]+/g, ' ').trim();
+ const ar = document.createRange();
+ ar.setStart(range.endContainer, range.endOffset);
+ ar.setEnd(document.body, document.body.childNodes.length);
+ after = ar.toString().slice(0, 50).replace(/[\s\u00A0]+/g, ' ').trim();
+ } catch (_) { /* ignore */ }
+ return { beforeText: before, afterText: after };
+}
+
+export function setupTextSelection(onRender: () => void, closePopup: () => void): void {
+ document.addEventListener('mouseup', (e) => {
+ if ((e.target as HTMLElement).closest('#fb-sidebar,#fb-toggle,#fb-popup')) return;
+ const sel = window.getSelection();
+ const text = sel?.toString().trim();
+ if (!text || !sel || sel.rangeCount === 0 || !state.username) return;
+ const range = sel.getRangeAt(0);
+ state.selectedText = text.replace(/[\s\u00A0]+/g, ' ').substring(0, 200);
+ state.selectedRect = range.getBoundingClientRect();
+ state.selectedQuoteContext = getQuoteContext(range);
+ state.popupContent = '';
+ onRender();
+ });
+ document.addEventListener('mousedown', (e) => {
+ if ((e.target as HTMLElement).closest('#fb-popup')) return;
+ if (state.selectedRect) closePopup();
+ });
+}
diff --git a/src/widget/state.ts b/src/widget/state.ts
new file mode 100644
index 0000000..c76ee9d
--- /dev/null
+++ b/src/widget/state.ts
@@ -0,0 +1,68 @@
+import type { Priority, FilterMode } from '../shared/types';
+import { USERNAME_KEY, SIDEBAR_WIDTH_KEY } from '../shared/constants';
+import { slugify } from '../shared/slug';
+
+export interface QuoteContext {
+ beforeText: string;
+ afterText: string;
+}
+
+export interface FbComment {
+ id: string;
+ author: string;
+ type: string;
+ quote: string;
+ quoteContext: QuoteContext;
+ content: string;
+ priority: Priority;
+ parentId: string | null;
+ resolved: boolean;
+ resolvedBy: string | null;
+ resolvedAt: number | null;
+ timestamp: number;
+ updatedAt: number | null;
+ pageUrl: string;
+ projectSlug?: string;
+}
+
+export interface WidgetState {
+ username: string;
+ comments: FbComment[];
+ filter: FilterMode;
+ sidebarOpen: boolean;
+ selectedText: string;
+ selectedQuoteContext: QuoteContext;
+ selectedRect: DOMRect | null;
+ popupContent: string;
+ editingId: string | null;
+ editContent: string;
+ editPriority: Priority;
+ replyingTo: string | null;
+ replyText: string;
+ editingName: boolean;
+ nameInput: string;
+ popupPriority: Priority;
+ sidebarWidth: number;
+}
+
+export const state: WidgetState = {
+ username: localStorage.getItem(USERNAME_KEY) || '',
+ comments: [],
+ filter: 'unresolved',
+ sidebarOpen: false,
+ selectedText: '',
+ selectedQuoteContext: { beforeText: '', afterText: '' },
+ selectedRect: null,
+ popupContent: '',
+ editingId: null,
+ editContent: '',
+ editPriority: 'want',
+ replyingTo: null,
+ replyText: '',
+ editingName: false,
+ nameInput: '',
+ popupPriority: 'must',
+ sidebarWidth: parseInt(localStorage.getItem(SIDEBAR_WIDTH_KEY) || '', 10) || 400,
+};
+
+export const slug = slugify(window.location.href);
diff --git a/src/widget/styles.ts b/src/widget/styles.ts
new file mode 100644
index 0000000..054cc5b
--- /dev/null
+++ b/src/widget/styles.ts
@@ -0,0 +1,136 @@
+export function injectStyles(): void {
+ const style = document.createElement('style');
+ style.id = 'fb-widget-styles';
+ style.textContent = [
+ ':root{--fb-bg:#ffffff;--fb-fg:#0a0a0a;--fb-muted:#f5f5f5;--fb-muted-fg:#737373;--fb-border:#e5e5e5;--fb-primary:#171717;--fb-primary-fg:#fafafa;--fb-accent:#3b82f6;--fb-destructive:#ef4444;--fb-font:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Hiragino Sans",sans-serif}',
+
+ '#fb-toggle{position:fixed;right:0;top:50%;transform:translateY(-50%);width:36px;background:var(--fb-bg);border:1px solid var(--fb-border);border-right:none;border-radius:8px 0 0 8px;cursor:pointer;z-index:99999;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;font-family:var(--fb-font);transition:all .15s;box-shadow:-2px 0 8px rgba(0,0,0,0.06);padding:8px 0}',
+ '#fb-toggle:hover{background:var(--fb-muted);box-shadow:-2px 0 12px rgba(0,0,0,0.1)}',
+ '#fb-toggle .fb-toggle-icon{color:var(--fb-muted-fg);display:flex;align-items:center;justify-content:center;position:relative}',
+ '#fb-toggle .fb-toggle-label{font-size:10px;color:var(--fb-accent);font-weight:700;writing-mode:vertical-rl;letter-spacing:1px;line-height:1;white-space:nowrap}',
+ '#fb-toggle .fb-badge{position:absolute;top:-6px;left:-6px;background:var(--fb-destructive);color:#fff;font-size:9px;font-weight:700;min-width:16px;height:16px;border-radius:8px;display:flex;align-items:center;justify-content:center;padding:0 3px;line-height:1}',
+
+ '#fb-sidebar{position:fixed;top:0;height:100vh;background:rgba(245,245,245,0.5);border-left:1px solid var(--fb-border);z-index:99998;transition:right .3s ease;display:flex;flex-direction:column;font-family:var(--fb-font);font-size:14px;color:var(--fb-fg)}',
+ '#fb-sidebar *{box-sizing:border-box}',
+
+ '.fb-resize-handle{position:absolute;left:-3px;top:0;width:6px;height:100%;cursor:col-resize;z-index:1}',
+ '.fb-resize-handle:hover{background:rgba(59,130,246,0.15)}',
+ '.fb-resize-handle.active{background:rgba(59,130,246,0.3)}',
+ 'body.fb-resizing{cursor:col-resize !important;-webkit-user-select:none !important;user-select:none !important}',
+ 'body.fb-resizing *{cursor:col-resize !important}',
+
+ '.fb-header{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-bottom:1px solid var(--fb-border)}',
+ '.fb-header-left{display:flex;align-items:center;gap:8px}',
+ '.fb-header-title{font-size:14px;font-weight:700;color:var(--fb-accent)}',
+ '.fb-header-count{background:var(--fb-muted);color:var(--fb-muted-fg);font-size:11px;padding:1px 7px;border-radius:10px}',
+ '.fb-header-actions{display:flex;align-items:center;gap:2px}',
+ '.fb-hdr-btn{background:none;border:none;cursor:pointer;padding:6px;border-radius:6px;color:var(--fb-muted-fg);transition:all .15s;display:inline-flex;align-items:center;gap:4px;font-family:var(--fb-font);font-size:12px}',
+ '.fb-hdr-btn:hover{background:var(--fb-muted);color:var(--fb-fg)}',
+
+ '.fb-user-row{display:flex;align-items:center;padding:8px 16px;border-bottom:1px solid var(--fb-border);font-size:13px;color:var(--fb-muted-fg);cursor:pointer;transition:color .15s;gap:6px}',
+ '.fb-user-row:hover{color:var(--fb-fg)}',
+
+ '.fb-filters{display:flex;border-bottom:1px solid var(--fb-border)}',
+ '.fb-filter{flex:1;padding:10px 0;text-align:center;font-size:13px;color:var(--fb-muted-fg);border:none;background:none;cursor:pointer;border-bottom:2px solid transparent;transition:all .15s;font-family:var(--fb-font)}',
+ '.fb-filter:hover{color:var(--fb-fg)}',
+ '.fb-filter.active{color:var(--fb-fg);border-bottom-color:var(--fb-accent)}',
+ '.fb-filter .cnt{font-size:11px;margin-left:4px;padding:1px 5px;border-radius:8px;background:var(--fb-muted);color:var(--fb-muted-fg)}',
+ '.fb-filter.active .cnt{background:rgba(59,130,246,0.1);color:var(--fb-accent)}',
+
+ '.fb-list{flex:1;overflow-y:auto;padding:8px}',
+ '.fb-empty{text-align:center;padding:60px 20px;color:var(--fb-muted-fg);font-size:13px}',
+ '.fb-empty svg{margin:0 auto 12px;display:block;color:var(--fb-border)}',
+
+ '.fb-card{background:var(--fb-bg);border:1px solid var(--fb-border);border-left:3px solid var(--fb-border);border-radius:12px;padding:14px;margin-bottom:6px;transition:box-shadow .3s,background .3s;cursor:pointer}',
+ '.fb-card:hover{box-shadow:0 1px 3px rgba(0,0,0,0.05)}',
+ '.fb-card.resolved{opacity:.5}',
+
+ '.fb-card-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:4px}',
+ '.fb-card-head-left{display:flex;align-items:center;gap:6px}',
+ '.fb-avatar{width:22px;height:22px;border-radius:50%;background:var(--fb-primary);color:var(--fb-primary-fg);display:flex;align-items:center;justify-content:center;font-size:10px;font-weight:700;flex-shrink:0}',
+ '.fb-author{font-size:13px;font-weight:700;color:var(--fb-fg)}',
+ '.fb-time{font-size:11px;color:var(--fb-muted-fg)}',
+ '.fb-resolved-mark{font-size:11px;color:#22c55e;margin-left:4px;display:inline-flex;align-items:center;gap:2px}',
+
+ '.fb-badge-p{font-size:11px;font-weight:700;padding:2px 8px;border-radius:4px;color:#fff;cursor:default;transition:all .15s}',
+ '.fb-badge-p.own{cursor:pointer}',
+ '.fb-badge-p.own:hover{transform:scale(1.1);box-shadow:0 0 0 2px rgba(0,0,0,0.08)}',
+
+ '.fb-quote{font-size:12px;color:var(--fb-muted-fg);padding:6px 10px;background:var(--fb-muted);border-left:2px solid var(--fb-primary);border-radius:0 4px 4px 0;margin-bottom:8px;font-style:italic;line-height:1.5;cursor:pointer;transition:background .15s}',
+ '.fb-quote:hover{background:var(--fb-border)}',
+
+ '.fb-body{font-size:13px;color:var(--fb-muted-fg);line-height:1.6;margin-bottom:6px;white-space:pre-wrap}',
+
+ '.fb-actions{display:flex;gap:2px;flex-wrap:wrap}',
+ '.fb-act{font-size:12px;color:#a3a3a3;background:none;border:none;padding:4px 8px;border-radius:4px;cursor:pointer;transition:all .15s;display:inline-flex;align-items:center;gap:3px;font-family:var(--fb-font)}',
+ '.fb-act:hover{color:var(--fb-fg)}',
+ '.fb-act.del:hover{color:var(--fb-destructive)}',
+ '.fb-act.res:hover{color:#22c55e}',
+
+ '.fb-replies{margin-top:8px;padding-top:8px;border-top:1px solid var(--fb-muted)}',
+ '.fb-reply-item{display:flex;gap:8px;padding:6px 0}',
+ '.fb-reply-item+.fb-reply-item{border-top:1px solid var(--fb-muted)}',
+ '.fb-reply-avatar{width:20px;height:20px;border-radius:50%;background:var(--fb-primary);color:var(--fb-primary-fg);display:flex;align-items:center;justify-content:center;font-size:9px;font-weight:700;flex-shrink:0;margin-top:2px}',
+ '.fb-reply-meta{font-size:12px;color:var(--fb-muted-fg);margin-bottom:2px}',
+ '.fb-reply-meta strong{color:#525252;font-weight:700}',
+ '.fb-reply-text{font-size:13px;color:var(--fb-muted-fg);line-height:1.5}',
+
+ '.fb-reply-input{display:flex;gap:8px;margin-top:8px}',
+ '.fb-reply-input textarea{flex:1;padding:8px 10px;border:1px solid var(--fb-border);border-radius:6px;font-size:13px;font-family:var(--fb-font);resize:none;outline:none;min-height:36px;color:var(--fb-fg)}',
+ '.fb-reply-input textarea:focus{border-color:var(--fb-accent)}',
+ '.fb-reply-input button{padding:6px 14px;background:var(--fb-primary);color:var(--fb-primary-fg);border:none;border-radius:6px;font-size:12px;cursor:pointer;font-family:var(--fb-font);align-self:flex-end}',
+ '.fb-reply-input button:disabled{opacity:.4;cursor:default}',
+
+ '.fb-edit-area textarea{width:100%;padding:8px 10px;border:1px solid var(--fb-border);border-radius:6px;font-size:13px;font-family:var(--fb-font);resize:vertical;outline:none;min-height:50px;margin-bottom:6px;color:var(--fb-fg)}',
+ '.fb-edit-area textarea:focus{border-color:var(--fb-accent)}',
+ '.fb-edit-btns{display:flex;gap:6px}',
+ '.fb-edit-btns button{padding:4px 12px;border-radius:6px;font-size:12px;cursor:pointer;border:1px solid var(--fb-border);background:var(--fb-bg);color:var(--fb-muted-fg);font-family:var(--fb-font)}',
+ '.fb-edit-btns button.save{background:var(--fb-primary);color:var(--fb-primary-fg);border-color:var(--fb-primary)}',
+ '.fb-edit-pri{display:flex;gap:4px;margin-bottom:6px}',
+ '.fb-edit-pri button{padding:2px 10px;border-radius:4px;font-size:11px;font-weight:700;cursor:pointer;border:1px solid var(--fb-border);background:var(--fb-bg);color:var(--fb-muted-fg);font-family:var(--fb-font);transition:all .15s}',
+
+ '.fb-popup{position:fixed;z-index:100000;width:400px;background:var(--fb-bg);border:1px solid var(--fb-border);border-radius:12px;padding:16px;box-shadow:0 10px 25px rgba(0,0,0,0.1);font-family:var(--fb-font);display:none}',
+ '.fb-popup.show{display:block}',
+ '.fb-popup-head{margin-bottom:10px}',
+ '.fb-popup-head span{font-size:14px;font-weight:700;color:var(--fb-fg)}',
+ '.fb-popup-quote{font-size:13px;color:var(--fb-muted-fg);padding:8px 12px;background:var(--fb-muted);border-left:2px solid var(--fb-accent);border-radius:0 6px 6px 0;margin-bottom:10px;font-style:italic;line-height:1.5}',
+ '.fb-popup textarea{width:100%;min-height:70px;padding:10px 12px;border:1px solid var(--fb-border);border-radius:8px;font-size:14px;font-family:var(--fb-font);resize:vertical;outline:none;margin-bottom:10px;color:var(--fb-fg)}',
+ '.fb-popup textarea:focus{border-color:var(--fb-accent)}',
+ '.fb-popup textarea::placeholder{color:var(--fb-muted-fg)}',
+ '.fb-popup-pri{display:flex;gap:6px;margin-bottom:10px}',
+ '.fb-popup-pri button{flex:1;padding:7px 8px;border-radius:8px;font-size:13px;font-weight:600;cursor:pointer;border:2px solid transparent;transition:all .15s;font-family:var(--fb-font)}',
+ '.fb-popup-actions{display:flex;gap:8px;justify-content:flex-end}',
+ '.fb-popup-actions button{padding:8px 18px;border-radius:8px;font-size:13px;font-weight:600;cursor:pointer;transition:all .15s;font-family:var(--fb-font)}',
+ '.fb-popup-actions .cancel{background:none;border:1px solid var(--fb-border);color:var(--fb-muted-fg)}',
+ '.fb-popup-actions .cancel:hover{background:var(--fb-muted);color:var(--fb-fg)}',
+ '.fb-popup-actions .submit{border:none;color:#fff}',
+
+ '.fb-name-overlay{position:fixed;inset:0;background:rgba(0,0,0,0.4);display:flex;align-items:center;justify-content:center;z-index:100001}',
+ '.fb-name-box{background:var(--fb-bg);border-radius:12px;padding:28px;width:360px;box-shadow:0 20px 40px rgba(0,0,0,0.15)}',
+ '.fb-name-box h2{font-size:18px;font-weight:700;margin:0 0 6px;color:var(--fb-fg)}',
+ '.fb-name-box p{font-size:14px;color:var(--fb-muted-fg);margin:0 0 16px}',
+ '.fb-name-box input{width:100%;padding:10px 14px;border:1px solid var(--fb-border);border-radius:8px;font-size:15px;outline:none;margin-bottom:12px;font-family:var(--fb-font);color:var(--fb-fg)}',
+ '.fb-name-box input:focus{border-color:var(--fb-accent)}',
+ '.fb-name-box input::placeholder{color:var(--fb-muted-fg)}',
+ '.fb-name-box button{width:100%;padding:10px;background:var(--fb-primary);color:var(--fb-primary-fg);border:none;border-radius:8px;font-size:14px;font-weight:600;cursor:pointer;font-family:var(--fb-font)}',
+ '.fb-name-box button:disabled{opacity:.4;cursor:default}',
+
+ '.fb-name-input{width:100%;padding:4px 8px;border:1px solid var(--fb-border);border-radius:4px;font-size:12px;outline:none;font-family:var(--fb-font);color:var(--fb-fg)}',
+ '.fb-name-input:focus{border-color:var(--fb-accent)}',
+
+ '.fb-highlight{padding:1px 0;cursor:pointer;transition:background .15s}',
+ '.fb-highlight-must{background:rgba(239,68,68,0.15);border-bottom:2px solid #ef4444}',
+ '.fb-highlight-must:hover{background:rgba(239,68,68,0.25)}',
+ '.fb-highlight-better{background:rgba(245,158,11,0.15);border-bottom:2px solid #f59e0b}',
+ '.fb-highlight-better:hover{background:rgba(245,158,11,0.25)}',
+ '.fb-highlight-want{background:rgba(34,197,94,0.15);border-bottom:2px solid #22c55e}',
+ '.fb-highlight-want:hover{background:rgba(34,197,94,0.25)}',
+
+ '@keyframes fb-pulse{0%,100%{opacity:1}50%{opacity:0.4}}',
+ '.fb-highlight.fb-pulse{animation:fb-pulse 1s ease-in-out infinite}',
+ '.fb-card.fb-focused{box-shadow:0 0 0 2px var(--fb-accent);background:rgba(59,130,246,0.04)}',
+
+ '#fb-sidebar svg,#fb-toggle svg,.fb-popup svg{pointer-events:none}',
+ ].join('\n');
+ document.head.appendChild(style);
+}
diff --git a/tests/shared.unit.test.ts b/tests/shared.unit.test.ts
new file mode 100644
index 0000000..94bea9c
--- /dev/null
+++ b/tests/shared.unit.test.ts
@@ -0,0 +1,129 @@
+import { describe, test, expect, vi, beforeEach, afterEach } from 'vitest';
+import { slugify, generateId } from '../src/shared/slug';
+import { fmtTime } from '../src/shared/time';
+import { PRIORITY_CYCLE, PRIORITY_COLORS, HIGHLIGHT_COLORS } from '../src/shared/constants';
+import { authHeaders } from '../src/shared/api-client';
+import { mapNormToOrig } from '../src/widget/highlight';
+
+describe('slugify', () => {
+ test('HTTP プレフィックスを除去する', () => {
+ expect(slugify('https://example.com/page')).toBe('example_com_page');
+ });
+
+ test('日本語文字を保持する', () => {
+ const result = slugify('https://example.com/テスト');
+ expect(result).toContain('テスト');
+ });
+
+ test('100文字で切り詰める', () => {
+ const long = 'https://example.com/' + 'a'.repeat(200);
+ expect(slugify(long).length).toBe(100);
+ });
+
+ test('記号をアンダースコアに変換する', () => {
+ expect(slugify('https://a.b/c?d=e&f=g')).toBe('a_b_c_d_e_f_g');
+ });
+});
+
+describe('generateId', () => {
+ test('文字列を返す', () => {
+ expect(typeof generateId()).toBe('string');
+ });
+
+ test('一意性がある(100回生成してユニーク)', () => {
+ const ids = new Set(Array.from({ length: 100 }, () => generateId()));
+ expect(ids.size).toBe(100);
+ });
+});
+
+describe('fmtTime', () => {
+ let realNow: () => number;
+
+ beforeEach(() => {
+ realNow = Date.now;
+ vi.spyOn(Date, 'now').mockReturnValue(1700000000000);
+ });
+
+ afterEach(() => {
+ vi.restoreAllMocks();
+ });
+
+ test('1分未満は「たった今」', () => {
+ expect(fmtTime(1700000000000 - 30000)).toBe('たった今');
+ });
+
+ test('1時間未満は「N分前」', () => {
+ expect(fmtTime(1700000000000 - 300000)).toBe('5分前');
+ });
+
+ test('24時間未満は「N時間前」', () => {
+ expect(fmtTime(1700000000000 - 7200000)).toBe('2時間前');
+ });
+
+ test('24時間以上は日時文字列', () => {
+ const result = fmtTime(1700000000000 - 86400000 * 2);
+ expect(result).toMatch(/\d+月/);
+ });
+});
+
+describe('PRIORITY_CYCLE', () => {
+ test('must → better → want → must の循環', () => {
+ expect(PRIORITY_CYCLE.must).toBe('better');
+ expect(PRIORITY_CYCLE.better).toBe('want');
+ expect(PRIORITY_CYCLE.want).toBe('must');
+ });
+
+ test('3つの優先度が全て定義されている', () => {
+ expect(Object.keys(PRIORITY_CYCLE)).toEqual(['must', 'better', 'want']);
+ });
+});
+
+describe('PRIORITY_COLORS', () => {
+ test('3つの優先度が全て定義されている', () => {
+ expect(Object.keys(PRIORITY_COLORS)).toEqual(['must', 'better', 'want']);
+ });
+
+ test('各色に bg, text, light, border がある', () => {
+ for (const p of ['must', 'better', 'want'] as const) {
+ expect(PRIORITY_COLORS[p]).toHaveProperty('bg');
+ expect(PRIORITY_COLORS[p]).toHaveProperty('text');
+ expect(PRIORITY_COLORS[p]).toHaveProperty('light');
+ expect(PRIORITY_COLORS[p]).toHaveProperty('border');
+ }
+ });
+});
+
+describe('HIGHLIGHT_COLORS', () => {
+ test('3つの優先度が全て定義されている', () => {
+ expect(Object.keys(HIGHLIGHT_COLORS)).toEqual(['must', 'better', 'want']);
+ });
+});
+
+describe('authHeaders', () => {
+ test('トークンありの場合 Authorization を含む', () => {
+ const h = authHeaders('my-token');
+ expect(h['Authorization']).toBe('Bearer my-token');
+ expect(h['Content-Type']).toBe('application/json');
+ });
+
+ test('トークンなしの場合 Authorization を含まない', () => {
+ const h = authHeaders('');
+ expect(h['Authorization']).toBeUndefined();
+ expect(h['Content-Type']).toBe('application/json');
+ });
+});
+
+describe('mapNormToOrig', () => {
+ test('空白なしの単純マッチ', () => {
+ expect(mapNormToOrig('hello world', 0, 5)).toEqual([0, 5]);
+ });
+
+ test('余分な空白がある場合の正規化マッチ', () => {
+ // 正規化後のインデックス 6-11 は orig で 6-12 に対応(余分な空白を含む)
+ expect(mapNormToOrig('hello world', 6, 11)).toEqual([6, 12]);
+ });
+
+ test('範囲外の normStart は null を返す', () => {
+ expect(mapNormToOrig('short', 100, 105)).toBeNull();
+ });
+});
diff --git a/tests/widget.integration.test.ts b/tests/widget.integration.test.ts
new file mode 100644
index 0000000..9112db3
--- /dev/null
+++ b/tests/widget.integration.test.ts
@@ -0,0 +1,168 @@
+import { describe, test, expect, beforeEach, vi } from 'vitest';
+import { readFileSync } from 'fs';
+import { resolve } from 'path';
+
+const WIDGET_JS = readFileSync(
+ resolve(__dirname, '../public/widget.js'),
+ 'utf-8'
+);
+
+function loadWidget() {
+ document.head.innerHTML = '';
+ document.body.innerHTML = 'テストテキスト
';
+
+ const script = document.createElement('script');
+ script.src = 'https://my-app.vercel.app/widget.js';
+ script.dataset.token = 'test-token-abc';
+ Object.defineProperty(document, 'currentScript', {
+ value: script,
+ writable: true,
+ configurable: true,
+ });
+
+ window.localStorage.clear();
+
+ vi.stubGlobal(
+ 'fetch',
+ vi.fn(() =>
+ Promise.resolve({
+ json: () => Promise.resolve([]),
+ ok: true,
+ })
+ )
+ );
+
+ // eslint-disable-next-line no-eval
+ eval(WIDGET_JS);
+}
+
+describe('widget.js 初期化', () => {
+ beforeEach(() => {
+ loadWidget();
+ });
+
+ test('トグルボタンが DOM に追加される', () => {
+ const toggle = document.getElementById('fb-toggle');
+ expect(toggle).toBeTruthy();
+ expect(toggle!.tagName).toBe('BUTTON');
+ });
+
+ test('サイドバーが DOM に追加される', () => {
+ const sidebar = document.getElementById('fb-sidebar');
+ expect(sidebar).toBeTruthy();
+ });
+
+ test('スタイルが注入される', () => {
+ const style = document.getElementById('fb-widget-styles');
+ expect(style).toBeTruthy();
+ expect(style!.tagName).toBe('STYLE');
+ });
+
+ test('CSS 変数が定義されている', () => {
+ const style = document.getElementById('fb-widget-styles');
+ const css = style!.textContent || '';
+ expect(css).toContain('--fb-bg');
+ expect(css).toContain('--fb-fg');
+ expect(css).toContain('--fb-accent');
+ expect(css).toContain('--fb-border');
+ expect(css).toContain('--fb-muted');
+ expect(css).toContain('--fb-primary');
+ expect(css).toContain('--fb-destructive');
+ });
+
+ test('トグルボタンに「コメント」ラベルがある', () => {
+ const toggle = document.getElementById('fb-toggle');
+ expect(toggle!.innerHTML).toContain('コメント');
+ });
+
+ test('サイドバーにフィルタボタンがある', () => {
+ const sidebar = document.getElementById('fb-sidebar');
+ const html = sidebar!.innerHTML;
+ expect(html).toContain('未解決');
+ expect(html).toContain('解決済');
+ expect(html).toContain('すべて');
+ });
+
+ test('サイドバーにリサイズハンドルがある', () => {
+ const sidebar = document.getElementById('fb-sidebar');
+ const handle = sidebar!.querySelector('.fb-resize-handle');
+ expect(handle).toBeTruthy();
+ });
+
+ test('サイドバーは初期状態で非表示(右にオフセット)', () => {
+ const sidebar = document.getElementById('fb-sidebar') as HTMLElement;
+ const right = parseInt(sidebar.style.right, 10);
+ expect(right).toBeLessThan(0);
+ });
+
+ test('名前未入力時に名前入力ダイアログが表示される', () => {
+ const overlay = document.getElementById('fb-name-overlay');
+ expect(overlay).toBeTruthy();
+ expect(overlay!.innerHTML).toContain('ようこそ');
+ });
+});
+
+describe('widget.js ハイライト CSS', () => {
+ beforeEach(() => {
+ loadWidget();
+ });
+
+ test('ハイライトスタイルが優先度別に3色定義されている', () => {
+ const style = document.getElementById('fb-widget-styles');
+ const css = style!.textContent || '';
+ expect(css).toContain('.fb-highlight-must');
+ expect(css).toContain('.fb-highlight-better');
+ expect(css).toContain('.fb-highlight-want');
+ });
+
+ test('カードスタイルが定義されている', () => {
+ const style = document.getElementById('fb-widget-styles');
+ const css = style!.textContent || '';
+ expect(css).toContain('.fb-card');
+ expect(css).toContain('.fb-card-head');
+ expect(css).toContain('.fb-badge-p');
+ });
+
+ test('ポップアップスタイルが定義されている', () => {
+ const style = document.getElementById('fb-widget-styles');
+ const css = style!.textContent || '';
+ expect(css).toContain('.fb-popup');
+ expect(css).toContain('.fb-popup-pri');
+ expect(css).toContain('.fb-popup-actions');
+ });
+});
+
+describe('widget.js コメントなし状態', () => {
+ beforeEach(() => {
+ loadWidget();
+ });
+
+ test('コメントゼロ時にサイドバーに空状態メッセージが表示される', () => {
+ const sidebar = document.getElementById('fb-sidebar');
+ const html = sidebar!.innerHTML;
+ expect(html).toContain('コメントはまだありません');
+ });
+
+ test('コメントゼロ時にバッジが表示されない', () => {
+ const toggle = document.getElementById('fb-toggle');
+ expect(toggle!.querySelector('.fb-badge')).toBeNull();
+ });
+});
+
+describe('widget.js SVG アイコン', () => {
+ beforeEach(() => {
+ loadWidget();
+ });
+
+ test('トグルボタンに SVG アイコンが含まれる', () => {
+ const toggle = document.getElementById('fb-toggle');
+ expect(toggle!.innerHTML).toContain('