diff --git a/bun.lock b/bun.lock index b34a8f2ae..5bac150a7 100644 --- a/bun.lock +++ b/bun.lock @@ -8,7 +8,6 @@ "@ai-sdk/openai": "^2.0.52", "@emotion/react": "^11.14.0", "@emotion/styled": "^11.14.1", - "@types/react-syntax-highlighter": "^15.5.13", "ai": "^5.0.72", "ai-tokenizer": "^1.0.3", "chalk": "^5.6.2", @@ -17,6 +16,7 @@ "diff": "^8.0.2", "disposablestack": "^1.1.7", "electron-updater": "^6.6.2", + "escape-html": "^1.0.3", "jsonc-parser": "^3.3.1", "lru-cache": "^11.2.2", "markdown-it": "^14.1.0", @@ -29,7 +29,6 @@ "react-dnd-html5-backend": "^16.0.1", "react-dom": "^18.2.0", "react-markdown": "^10.1.0", - "react-syntax-highlighter": "^15.6.6", "rehype-katex": "^7.0.1", "rehype-raw": "^7.0.0", "rehype-sanitize": "^6.0.0", @@ -56,6 +55,7 @@ "@testing-library/react": "^16.3.0", "@types/bun": "^1.2.23", "@types/diff": "^8.0.0", + "@types/escape-html": "^1.0.4", "@types/jest": "^30.0.0", "@types/katex": "^0.16.7", "@types/markdown-it": "^14.1.2", @@ -684,6 +684,8 @@ "@types/doctrine": ["@types/doctrine@0.0.9", "", {}, "sha512-eOIHzCUSH7SMfonMG1LsC2f8vxBFtho6NGBznK41R84YzPuvSBzrhEps33IsQiOW9+VL6NQ9DbjQJznk/S4uRA=="], + "@types/escape-html": ["@types/escape-html@1.0.4", "", {}, "sha512-qZ72SFTgUAZ5a7Tj6kf2SHLetiH5S6f8G5frB2SPQ3EyF02kxdyBFf4Tz4banE3xCgGnKgWLt//a6VuYHKYJTg=="], + "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], "@types/estree-jsx": ["@types/estree-jsx@1.0.5", "", { "dependencies": { "@types/estree": "*" } }, "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg=="], @@ -738,8 +740,6 @@ "@types/react-dom": ["@types/react-dom@18.3.7", "", { "peerDependencies": { "@types/react": "^18.0.0" } }, "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ=="], - "@types/react-syntax-highlighter": ["@types/react-syntax-highlighter@15.5.13", "", { "dependencies": { "@types/react": "*" } }, "sha512-uLGJ87j6Sz8UaBAooU0T6lWJ0dBmjZgN1PZTrj05TNql2/XpC6+4HhMT5syIdFUUt+FASfCeLLv4kBygNU+8qA=="], - "@types/resolve": ["@types/resolve@1.20.6", "", {}, "sha512-A4STmOXPhMUtHH+S6ymgE2GiBSMqf4oTvcQZMcHzokuTLVYzXTB8ttjcgxOVaAp2lGwEdzZ0J+cRbbeevQj1UQ=="], "@types/responselike": ["@types/responselike@1.0.3", "", { "dependencies": { "@types/node": "*" } }, "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw=="], @@ -1020,13 +1020,13 @@ "char-regex": ["char-regex@2.0.2", "", {}, "sha512-cbGOjAptfM2LVmWhwRFHEKTPkLwNddVmuqYZQt895yXwAsWsXObCG+YN4DGQ/JBtT4GP1a1lPPdio2z413LmTg=="], - "character-entities": ["character-entities@1.2.4", "", {}, "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw=="], + "character-entities": ["character-entities@2.0.2", "", {}, "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ=="], "character-entities-html4": ["character-entities-html4@2.1.0", "", {}, "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA=="], - "character-entities-legacy": ["character-entities-legacy@1.1.4", "", {}, "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA=="], + "character-entities-legacy": ["character-entities-legacy@3.0.0", "", {}, "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ=="], - "character-reference-invalid": ["character-reference-invalid@1.1.4", "", {}, "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg=="], + "character-reference-invalid": ["character-reference-invalid@2.0.1", "", {}, "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw=="], "check-error": ["check-error@2.1.1", "", {}, "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw=="], @@ -1328,6 +1328,8 @@ "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], + "escape-html": ["escape-html@1.0.3", "", {}, "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="], + "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], "eslint": ["eslint@9.37.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.0", "@eslint/config-helpers": "^0.4.0", "@eslint/core": "^0.16.0", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "9.37.0", "@eslint/plugin-kit": "^0.4.0", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.4.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-XyLmROnACWqSxiGYArdef1fItQd47weqB7iwtfr9JHwRrqIXZdcFMvvEcL9xHCmL0SNsOvF0c42lWyM1U5dgig=="], @@ -1388,8 +1390,6 @@ "fastq": ["fastq@1.19.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ=="], - "fault": ["fault@1.0.4", "", { "dependencies": { "format": "^0.2.0" } }, "sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA=="], - "fb-watchman": ["fb-watchman@2.0.2", "", { "dependencies": { "bser": "2.1.1" } }, "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA=="], "fd-slicer": ["fd-slicer@1.1.0", "", { "dependencies": { "pend": "~1.2.0" } }, "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g=="], @@ -1426,8 +1426,6 @@ "form-data": ["form-data@4.0.4", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow=="], - "format": ["format@0.2.2", "", {}, "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww=="], - "fromentries": ["fromentries@1.3.2", "", {}, "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg=="], "fs-constants": ["fs-constants@1.0.0", "", {}, "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="], @@ -1522,7 +1520,7 @@ "hast-util-is-element": ["hast-util-is-element@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g=="], - "hast-util-parse-selector": ["hast-util-parse-selector@2.2.5", "", {}, "sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ=="], + "hast-util-parse-selector": ["hast-util-parse-selector@4.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A=="], "hast-util-raw": ["hast-util-raw@9.1.0", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "@ungap/structured-clone": "^1.0.0", "hast-util-from-parse5": "^8.0.0", "hast-util-to-parse5": "^8.0.0", "html-void-elements": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "parse5": "^7.0.0", "unist-util-position": "^5.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0", "web-namespaces": "^2.0.0", "zwitch": "^2.0.0" } }, "sha512-Y8/SBAHkZGoNkpzqqfCldijcuUKh7/su31kEBp67cFY09Wy0mTRgtsLYsiIxMJxlu0f6AA5SUTbDR8K0rxnbUw=="], @@ -1538,11 +1536,7 @@ "hast-util-whitespace": ["hast-util-whitespace@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw=="], - "hastscript": ["hastscript@6.0.0", "", { "dependencies": { "@types/hast": "^2.0.0", "comma-separated-tokens": "^1.0.0", "hast-util-parse-selector": "^2.0.0", "property-information": "^5.0.0", "space-separated-tokens": "^1.0.0" } }, "sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w=="], - - "highlight.js": ["highlight.js@10.7.3", "", {}, "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A=="], - - "highlightjs-vue": ["highlightjs-vue@1.0.0", "", {}, "sha512-PDEfEF102G23vHmPhLyPboFCD+BkMGu+GuJe2d9/eH4FsCwvgBpnc9n0pGE+ffKdph38s6foEZiEjdgHdzp+IA=="], + "hastscript": ["hastscript@9.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-parse-selector": "^4.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0" } }, "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w=="], "hoist-non-react-statics": ["hoist-non-react-statics@3.3.2", "", { "dependencies": { "react-is": "^16.7.0" } }, "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw=="], @@ -1598,9 +1592,9 @@ "internmap": ["internmap@2.0.3", "", {}, "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg=="], - "is-alphabetical": ["is-alphabetical@1.0.4", "", {}, "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg=="], + "is-alphabetical": ["is-alphabetical@2.0.1", "", {}, "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ=="], - "is-alphanumerical": ["is-alphanumerical@1.0.4", "", { "dependencies": { "is-alphabetical": "^1.0.0", "is-decimal": "^1.0.0" } }, "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A=="], + "is-alphanumerical": ["is-alphanumerical@2.0.1", "", { "dependencies": { "is-alphabetical": "^2.0.0", "is-decimal": "^2.0.0" } }, "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw=="], "is-arguments": ["is-arguments@1.2.0", "", { "dependencies": { "call-bound": "^1.0.2", "has-tostringtag": "^1.0.2" } }, "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA=="], @@ -1626,7 +1620,7 @@ "is-date-object": ["is-date-object@1.1.0", "", { "dependencies": { "call-bound": "^1.0.2", "has-tostringtag": "^1.0.2" } }, "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg=="], - "is-decimal": ["is-decimal@1.0.4", "", {}, "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw=="], + "is-decimal": ["is-decimal@2.0.1", "", {}, "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A=="], "is-docker": ["is-docker@2.2.1", "", { "bin": { "is-docker": "cli.js" } }, "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ=="], @@ -1642,7 +1636,7 @@ "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], - "is-hexadecimal": ["is-hexadecimal@1.0.4", "", {}, "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw=="], + "is-hexadecimal": ["is-hexadecimal@2.0.1", "", {}, "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg=="], "is-map": ["is-map@2.0.3", "", {}, "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw=="], @@ -1868,8 +1862,6 @@ "lowercase-keys": ["lowercase-keys@2.0.0", "", {}, "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA=="], - "lowlight": ["lowlight@1.20.0", "", { "dependencies": { "fault": "^1.0.0", "highlight.js": "~10.7.0" } }, "sha512-8Ktj+prEb1RoCPkEOrPMYUN/nCggB7qAWe3a7OpMjWQkh3l2RD5wKRQ+o8Q8YuI9RG/xs95waaI/E6ym/7NsTw=="], - "lru-cache": ["lru-cache@11.2.2", "", {}, "sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg=="], "lz-string": ["lz-string@1.5.0", "", { "bin": { "lz-string": "bin/bin.js" } }, "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ=="], @@ -2100,7 +2092,7 @@ "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="], - "parse-entities": ["parse-entities@2.0.0", "", { "dependencies": { "character-entities": "^1.0.0", "character-entities-legacy": "^1.0.0", "character-reference-invalid": "^1.0.0", "is-alphanumerical": "^1.0.0", "is-decimal": "^1.0.0", "is-hexadecimal": "^1.0.0" } }, "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ=="], + "parse-entities": ["parse-entities@4.0.2", "", { "dependencies": { "@types/unist": "^2.0.0", "character-entities-legacy": "^3.0.0", "character-reference-invalid": "^2.0.0", "decode-named-character-reference": "^1.0.0", "is-alphanumerical": "^2.0.0", "is-decimal": "^2.0.0", "is-hexadecimal": "^2.0.0" } }, "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw=="], "parse-json": ["parse-json@5.2.0", "", { "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" } }, "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg=="], @@ -2166,8 +2158,6 @@ "pretty-format": ["pretty-format@30.2.0", "", { "dependencies": { "@jest/schemas": "30.0.5", "ansi-styles": "^5.2.0", "react-is": "^18.3.1" } }, "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA=="], - "prismjs": ["prismjs@1.30.0", "", {}, "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw=="], - "process": ["process@0.11.10", "", {}, "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A=="], "process-nextick-args": ["process-nextick-args@2.0.1", "", {}, "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="], @@ -2228,8 +2218,6 @@ "react-style-singleton": ["react-style-singleton@2.2.3", "", { "dependencies": { "get-nonce": "^1.0.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ=="], - "react-syntax-highlighter": ["react-syntax-highlighter@15.6.6", "", { "dependencies": { "@babel/runtime": "^7.3.1", "highlight.js": "^10.4.1", "highlightjs-vue": "^1.0.0", "lowlight": "^1.17.0", "prismjs": "^1.30.0", "refractor": "^3.6.0" }, "peerDependencies": { "react": ">= 0.14.0" } }, "sha512-DgXrc+AZF47+HvAPEmn7Ua/1p10jNoVZVI/LoPiYdtY+OM+/nG5yefLHKJwdKqY1adMuHFbeyBaG9j64ML7vTw=="], - "read-config-file": ["read-config-file@6.3.2", "", { "dependencies": { "config-file-ts": "^0.2.4", "dotenv": "^9.0.2", "dotenv-expand": "^5.1.0", "js-yaml": "^4.1.0", "json5": "^2.2.0", "lazy-val": "^1.0.4" } }, "sha512-M80lpCjnE6Wt6zb98DoW8WHR09nzMSpu8XHtPkiTHrJ5Az9CybfeQhTJ8D7saeBHpGhLPIVyA8lcL6ZmdKwY6Q=="], "readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="], @@ -2246,8 +2234,6 @@ "reflect.getprototypeof": ["reflect.getprototypeof@1.0.10", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.9", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.7", "get-proto": "^1.0.1", "which-builtin-type": "^1.2.1" } }, "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw=="], - "refractor": ["refractor@3.6.0", "", { "dependencies": { "hastscript": "^6.0.0", "parse-entities": "^2.0.0", "prismjs": "~1.27.0" } }, "sha512-MY9W41IOWxxk31o+YvFCNyNzdkc9M20NoZK5vq6jkv4I/uh2zkWcfudj0Q1fovjUQJrNewS9NMzeTtqPf+n5EA=="], - "regex": ["regex@6.0.1", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-uorlqlzAKjKQZ5P+kTJr3eeJGSVroLKoHmquUj4zHWuR+hEyNqlXsSKlYYF5F4NI6nl7tWCs0apKJ0lmfsXAPA=="], "regex-recursion": ["regex-recursion@6.0.2", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg=="], @@ -2638,8 +2624,6 @@ "xmlbuilder": ["xmlbuilder@15.1.1", "", {}, "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg=="], - "xtend": ["xtend@4.0.2", "", {}, "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="], - "y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="], "yaku": ["yaku@0.16.7", "", {}, "sha512-Syu3IB3rZvKvYk7yTiyl1bo/jiEFaaStrgv1V2TIJTqYPStSMQVO8EQjg/z+DRzLq/4LIIharNT3iH1hylEIRw=="], @@ -2850,8 +2834,6 @@ "d3-sankey/d3-shape": ["d3-shape@1.3.7", "", { "dependencies": { "d3-path": "1" } }, "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw=="], - "decode-named-character-reference/character-entities": ["character-entities@2.0.2", "", {}, "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ=="], - "default-require-extensions/strip-bom": ["strip-bom@4.0.0", "", {}, "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w=="], "dom-serializer/domelementtype": ["domelementtype@2.3.0", "", {}, "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="], @@ -2916,20 +2898,8 @@ "hasha/type-fest": ["type-fest@0.8.1", "", {}, "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA=="], - "hast-util-from-dom/hastscript": ["hastscript@9.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-parse-selector": "^4.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0" } }, "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w=="], - - "hast-util-from-parse5/hastscript": ["hastscript@9.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-parse-selector": "^4.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0" } }, "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w=="], - "hast-util-to-parse5/property-information": ["property-information@6.5.0", "", {}, "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig=="], - "hastscript/@types/hast": ["@types/hast@2.3.10", "", { "dependencies": { "@types/unist": "^2" } }, "sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw=="], - - "hastscript/comma-separated-tokens": ["comma-separated-tokens@1.0.8", "", {}, "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw=="], - - "hastscript/property-information": ["property-information@5.6.0", "", { "dependencies": { "xtend": "^4.0.0" } }, "sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA=="], - - "hastscript/space-separated-tokens": ["space-separated-tokens@1.1.5", "", {}, "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA=="], - "hoist-non-react-statics/react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="], "hosted-git-info/lru-cache": ["lru-cache@6.0.0", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA=="], @@ -3062,8 +3032,6 @@ "mdast-util-find-and-replace/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="], - "mdast-util-mdx-jsx/parse-entities": ["parse-entities@4.0.2", "", { "dependencies": { "@types/unist": "^2.0.0", "character-entities-legacy": "^3.0.0", "character-reference-invalid": "^2.0.0", "decode-named-character-reference": "^1.0.0", "is-alphanumerical": "^2.0.0", "is-decimal": "^2.0.0", "is-hexadecimal": "^2.0.0" } }, "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw=="], - "mermaid/stylis": ["stylis@4.3.6", "", {}, "sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ=="], "mermaid/uuid": ["uuid@11.1.0", "", { "bin": { "uuid": "dist/esm/bin/uuid" } }, "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A=="], @@ -3082,6 +3050,8 @@ "nyc/yargs": ["yargs@15.4.1", "", { "dependencies": { "cliui": "^6.0.0", "decamelize": "^1.2.0", "find-up": "^4.1.0", "get-caller-file": "^2.0.1", "require-directory": "^2.1.1", "require-main-filename": "^2.0.0", "set-blocking": "^2.0.0", "string-width": "^4.2.0", "which-module": "^2.0.0", "y18n": "^4.0.0", "yargs-parser": "^18.1.2" } }, "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A=="], + "parse-entities/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], + "parse5/entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="], "path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], @@ -3106,8 +3076,6 @@ "redent/strip-indent": ["strip-indent@3.0.0", "", { "dependencies": { "min-indent": "^1.0.0" } }, "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ=="], - "refractor/prismjs": ["prismjs@1.27.0", "", {}, "sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA=="], - "rimraf/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], "rollup/fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], @@ -3128,8 +3096,6 @@ "string-length/strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="], - "stringify-entities/character-entities-legacy": ["character-entities-legacy@3.0.0", "", {}, "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ=="], - "tar/minipass": ["minipass@5.0.0", "", {}, "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ=="], "tar-stream/readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="], @@ -3394,12 +3360,6 @@ "glob/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], - "hast-util-from-dom/hastscript/hast-util-parse-selector": ["hast-util-parse-selector@4.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A=="], - - "hast-util-from-parse5/hastscript/hast-util-parse-selector": ["hast-util-parse-selector@4.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A=="], - - "hastscript/@types/hast/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], - "istanbul-lib-report/make-dir/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="], "jest-changed-files/jest-util/@jest/types": ["@jest/types@30.2.0", "", { "dependencies": { "@jest/pattern": "30.0.1", "@jest/schemas": "30.0.5", "@types/istanbul-lib-coverage": "^2.0.6", "@types/istanbul-reports": "^3.0.4", "@types/node": "*", "@types/yargs": "^17.0.33", "chalk": "^4.1.2" } }, "sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg=="], @@ -3556,18 +3516,6 @@ "jest/@jest/types/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], - "mdast-util-mdx-jsx/parse-entities/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], - - "mdast-util-mdx-jsx/parse-entities/character-entities-legacy": ["character-entities-legacy@3.0.0", "", {}, "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ=="], - - "mdast-util-mdx-jsx/parse-entities/character-reference-invalid": ["character-reference-invalid@2.0.1", "", {}, "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw=="], - - "mdast-util-mdx-jsx/parse-entities/is-alphanumerical": ["is-alphanumerical@2.0.1", "", { "dependencies": { "is-alphabetical": "^2.0.0", "is-decimal": "^2.0.0" } }, "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw=="], - - "mdast-util-mdx-jsx/parse-entities/is-decimal": ["is-decimal@2.0.1", "", {}, "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A=="], - - "mdast-util-mdx-jsx/parse-entities/is-hexadecimal": ["is-hexadecimal@2.0.1", "", {}, "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg=="], - "mlly/pkg-types/confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="], "nyc/find-up/locate-path": ["locate-path@5.0.0", "", { "dependencies": { "p-locate": "^4.1.0" } }, "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g=="], @@ -3808,8 +3756,6 @@ "jest/@jest/types/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], - "mdast-util-mdx-jsx/parse-entities/is-alphanumerical/is-alphabetical": ["is-alphabetical@2.0.1", "", {}, "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ=="], - "nyc/find-up/locate-path/p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="], "nyc/yargs/cliui/wrap-ansi": ["wrap-ansi@6.2.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA=="], diff --git a/package.json b/package.json index eea0b9840..bf82e642c 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,6 @@ "@ai-sdk/openai": "^2.0.52", "@emotion/react": "^11.14.0", "@emotion/styled": "^11.14.1", - "@types/react-syntax-highlighter": "^15.5.13", "ai": "^5.0.72", "ai-tokenizer": "^1.0.3", "chalk": "^5.6.2", @@ -46,6 +45,7 @@ "diff": "^8.0.2", "disposablestack": "^1.1.7", "electron-updater": "^6.6.2", + "escape-html": "^1.0.3", "jsonc-parser": "^3.3.1", "lru-cache": "^11.2.2", "markdown-it": "^14.1.0", @@ -58,7 +58,6 @@ "react-dnd-html5-backend": "^16.0.1", "react-dom": "^18.2.0", "react-markdown": "^10.1.0", - "react-syntax-highlighter": "^15.6.6", "rehype-katex": "^7.0.1", "rehype-raw": "^7.0.0", "rehype-sanitize": "^6.0.0", @@ -85,6 +84,7 @@ "@testing-library/react": "^16.3.0", "@types/bun": "^1.2.23", "@types/diff": "^8.0.0", + "@types/escape-html": "^1.0.4", "@types/jest": "^30.0.0", "@types/katex": "^0.16.7", "@types/markdown-it": "^14.1.2", diff --git a/scripts/generate_prism_css.ts b/scripts/generate_prism_css.ts deleted file mode 100755 index 9ac077d33..000000000 --- a/scripts/generate_prism_css.ts +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/env bun - -/** - * Generates Prism CSS stylesheet from vscDarkPlus theme - * Used for syntax highlighting when react-syntax-highlighter has useInlineStyles={false} - * - * Strips backgrounds to preserve diff backgrounds in Review tab - * Omits font-family and font-size to inherit from parent components - */ - -import { vscDarkPlus } from "react-syntax-highlighter/dist/esm/styles/prism"; -import type { CSSProperties } from "react"; - -const OUTPUT_PATH = "src/styles/prism-syntax.css"; - -// Strip backgrounds like we do in syntaxHighlighting.ts -const syntaxStyleNoBackgrounds: Record = {}; -for (const [key, value] of Object.entries(vscDarkPlus as Record)) { - if (typeof value === "object" && value !== null) { - const { background, backgroundColor, ...rest } = value as Record; - if (Object.keys(rest).length > 0) { - syntaxStyleNoBackgrounds[key] = rest as CSSProperties; - } - } -} - -// Convert CSS properties object to CSS string -function cssPropertiesToString(props: CSSProperties, selector: string): string { - const entries = Object.entries(props) - .filter(([key]) => { - // Skip font-family and font-size - we want to inherit these - return key !== "fontFamily" && key !== "fontSize"; - }) - .map(([key, value]) => { - // Convert camelCase to kebab-case - const cssKey = key.replace(/([A-Z])/g, "-$1").toLowerCase(); - return ` ${cssKey}: ${value};`; - }); - - // Add background: transparent to pre/code elements to prevent double backgrounds - if (selector.startsWith("pre") || selector.startsWith("code")) { - entries.push(" background: transparent;"); - } - - return entries.join("\n"); -} - -// Generate CSS content -function generateCSS(): string { - const lines: string[] = [ - "/**", - " * Auto-generated Prism syntax highlighting styles", - " * Based on VS Code Dark+ theme with backgrounds removed", - " * Used when react-syntax-highlighter has useInlineStyles={false}", - " *", - " * Font family and size are intentionally omitted to inherit from parent.", - " * ", - " * To regenerate: bun run scripts/generate_prism_css.ts", - " */", - "", - ]; - - for (const [selector, props] of Object.entries(syntaxStyleNoBackgrounds)) { - const cssRules = cssPropertiesToString(props, selector); - if (cssRules.trim().length > 0) { - // Handle selectors that need .token prefix - let cssSelector = selector; - - // Add .token prefix for single-word selectors (token types) - if (!/[ >[\]:.]/.test(selector) && !selector.startsWith("pre") && !selector.startsWith("code")) { - cssSelector = `.token.${selector}`; - } - - lines.push(`${cssSelector} {`); - lines.push(cssRules); - lines.push("}"); - lines.push(""); - } - } - - return lines.join("\n"); -} - -async function main() { - console.log("Generating Prism CSS stylesheet..."); - - const css = generateCSS(); - - console.log(`Writing CSS to ${OUTPUT_PATH}...`); - await Bun.write(OUTPUT_PATH, css); - - console.log("✓ Prism CSS generated successfully"); -} - -main().catch((error) => { - console.error("Error generating Prism CSS:", error); - process.exit(1); -}); - diff --git a/src/App.tsx b/src/App.tsx index fb035ae66..45c382397 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -101,12 +101,31 @@ const globalStyles = css` } /* Search term highlighting - global for consistent styling across components */ - mark.search-highlight { + /* Applied to for plain text and for Shiki-highlighted code */ + mark.search-highlight, + span.search-highlight { background: rgba(255, 215, 0, 0.3); color: inherit; padding: 0; border-radius: 2px; } + + /* Override Shiki theme background to use our global color */ + .shiki, + .shiki pre { + background: var(--color-code-bg) !important; + } + + /* Global styling for markdown code blocks */ + pre code { + display: block; + background: var(--color-code-bg); + margin: 1em 0; + border-radius: 4px; + font-size: 12px; + padding: 12px; + overflow: auto; + } `; // Styled Components diff --git a/src/components/Messages/MarkdownComponents.tsx b/src/components/Messages/MarkdownComponents.tsx index af5079bd2..621ef309a 100644 --- a/src/components/Messages/MarkdownComponents.tsx +++ b/src/components/Messages/MarkdownComponents.tsx @@ -1,8 +1,11 @@ import type { ReactNode } from "react"; -import React from "react"; -import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"; -import { syntaxStyleNoBackgrounds } from "@/styles/syntaxHighlighting"; +import React, { useState, useEffect } from "react"; import { Mermaid } from "./Mermaid"; +import { + getShikiHighlighter, + mapToShikiLang, + SHIKI_THEME, +} from "@/utils/highlighting/shikiHighlighter"; interface CodeProps { node?: unknown; @@ -24,6 +27,63 @@ interface SummaryProps { children?: ReactNode; } +interface CodeBlockProps { + code: string; + language: string; +} + +/** + * CodeBlock component with async Shiki highlighting + * Reuses shared highlighter instance from diff rendering + */ +const CodeBlock: React.FC = ({ code, language }) => { + const [html, setHtml] = useState(null); + + useEffect(() => { + let cancelled = false; + + async function highlight() { + try { + const highlighter = await getShikiHighlighter(); + const shikiLang = mapToShikiLang(language); + + // codeToHtml lazy-loads languages automatically + const result = highlighter.codeToHtml(code, { + lang: shikiLang, + theme: SHIKI_THEME, + }); + + if (!cancelled) { + setHtml(result); + } + } catch (error) { + console.warn(`Failed to highlight code block (${language}):`, error); + if (!cancelled) { + setHtml(null); + } + } + } + + void highlight(); + + return () => { + cancelled = true; + }; + }, [code, language]); + + // Show loading state or fall back to plain code + if (html === null) { + return ( +
+        {code}
+      
+ ); + } + + // Render highlighted HTML + return
; +}; + // Custom components for markdown rendering export const markdownComponents = { // Pass through pre element - let code component handle the wrapping @@ -58,48 +118,29 @@ export const markdownComponents = { ), - // Custom code block renderer with syntax highlighting + // Custom code block renderer with async Shiki highlighting code: ({ inline, className, children, node, ...props }: CodeProps) => { const match = /language-(\w+)/.exec(className ?? ""); const language = match ? match[1] : ""; - // Better inline detection: check for multiline content + // Extract text content const childString = typeof children === "string" ? children : Array.isArray(children) ? children.join("") : ""; const hasMultipleLines = childString.includes("\n"); const isInline = inline ?? !hasMultipleLines; - if (!isInline && language) { - // Extract text content from children (react-markdown passes string or array of strings) - const code = - typeof children === "string" ? children : Array.isArray(children) ? children.join("") : ""; - - // Handle mermaid diagrams - if (language === "mermaid") { - return ; - } + // Handle mermaid diagrams specially + if (!isInline && language === "mermaid") { + return ; + } - // Code block with language - use syntax highlighter - return ( - - {code.replace(/\n$/, "")} - - ); + // Code blocks with language - use async Shiki highlighting + if (!isInline && language) { + return ; } + // Code blocks without language (global CSS provides styling) if (!isInline) { - // Code block without language - plain pre/code return (
           
diff --git a/src/components/RightSidebar/CodeReview/HunkViewer.tsx b/src/components/RightSidebar/CodeReview/HunkViewer.tsx
index 307caa982..c27cb50de 100644
--- a/src/components/RightSidebar/CodeReview/HunkViewer.tsx
+++ b/src/components/RightSidebar/CodeReview/HunkViewer.tsx
@@ -8,9 +8,8 @@ import type { DiffHunk } from "@/types/review";
 import { SelectableDiffRenderer } from "../../shared/DiffRenderer";
 import {
   type SearchHighlightConfig,
-  highlightSearchMatches,
+  highlightSearchInText,
 } from "@/utils/highlighting/highlightSearchTerms";
-import { escapeHtml } from "@/utils/highlighting/highlightDiffChunk";
 import { Tooltip, TooltipWrapper } from "../../Tooltip";
 import { usePersistedState } from "@/hooks/usePersistedState";
 import { getReviewExpandStateKey } from "@/constants/storage";
@@ -212,7 +211,7 @@ export const HunkViewer = React.memo(
       if (!searchConfig) {
         return hunk.filePath;
       }
-      return highlightSearchMatches(escapeHtml(hunk.filePath), searchConfig);
+      return highlightSearchInText(hunk.filePath, searchConfig);
     }, [hunk.filePath, searchConfig]);
 
     // Persist manual expand/collapse state across remounts per workspace
diff --git a/src/components/shared/DiffRenderer.tsx b/src/components/shared/DiffRenderer.tsx
index d99c61f47..864f710f8 100644
--- a/src/components/shared/DiffRenderer.tsx
+++ b/src/components/shared/DiffRenderer.tsx
@@ -102,7 +102,8 @@ export const LineContent = styled.span<{ type: DiffLineType }>`
   }};
 
   /* Ensure Shiki spans don't interfere with diff backgrounds */
-  span {
+  /* Exclude search-highlight to allow search marking to show */
+  span:not(.search-highlight) {
     background: transparent !important;
   }
 `;
@@ -156,7 +157,7 @@ interface DiffRendererProps {
 
 /**
  * Hook to pre-process and highlight diff content in chunks
- * Runs once when content/language changes
+ * Runs once when content/language changes (NOT search - that's applied post-process)
  */
 function useHighlightedDiff(
   content: string,
@@ -176,7 +177,7 @@ function useHighlightedDiff(
       // Group into chunks
       const diffChunks = groupDiffLines(lines, oldStart, newStart);
 
-      // Highlight each chunk
+      // Highlight each chunk (without search decorations - those are applied later)
       const highlighted = await Promise.all(
         diffChunks.map((chunk) => highlightDiffChunk(chunk, language))
       );
diff --git a/src/styles/prism-syntax.css b/src/styles/prism-syntax.css
deleted file mode 100644
index a0ebbf57d..000000000
--- a/src/styles/prism-syntax.css
+++ /dev/null
@@ -1,357 +0,0 @@
-/**
- * Auto-generated Prism syntax highlighting styles
- * Based on VS Code Dark+ theme with backgrounds removed
- * Used when react-syntax-highlighter has useInlineStyles={false}
- *
- * Font family and size are intentionally omitted to inherit from parent.
- * 
- * To regenerate: bun run scripts/generate_prism_css.ts
- */
-
-pre[class*="language-"] {
-  color: #d4d4d4;
-  text-shadow: none;
-  direction: ltr;
-  text-align: left;
-  white-space: pre;
-  word-spacing: normal;
-  word-break: normal;
-  line-height: 1.5;
-  -moz-tab-size: 4;
-  -o-tab-size: 4;
-  tab-size: 4;
-  -webkit-hyphens: none;
-  -moz-hyphens: none;
-  ms-hyphens: none;
-  hyphens: none;
-  padding: 1em;
-  margin: 0.5em 0;
-  overflow: auto;
-  background: transparent;
-}
-
-code[class*="language-"] {
-  color: #d4d4d4;
-  text-shadow: none;
-  direction: ltr;
-  text-align: left;
-  white-space: pre;
-  word-spacing: normal;
-  word-break: normal;
-  line-height: 1.5;
-  -moz-tab-size: 4;
-  -o-tab-size: 4;
-  tab-size: 4;
-  -webkit-hyphens: none;
-  -moz-hyphens: none;
-  ms-hyphens: none;
-  hyphens: none;
-}
-
-pre[class*="language-"]::selection {
-  text-shadow: none;
-}
-
-code[class*="language-"]::selection {
-  text-shadow: none;
-}
-
-pre[class*="language-"] *::selection {
-  text-shadow: none;
-}
-
-code[class*="language-"] *::selection {
-  text-shadow: none;
-}
-
-:not(pre) > code[class*="language-"] {
-  padding: 0.1em 0.3em;
-  border-radius: 0.3em;
-  color: #db4c69;
-}
-
-.namespace {
-  -opacity: 0.7;
-}
-
-doctype.doctype-tag {
-  color: #569cd6;
-}
-
-doctype.name {
-  color: #9cdcfe;
-}
-
-.token.comment {
-  color: #6a9955;
-}
-
-.token.prolog {
-  color: #6a9955;
-}
-
-.token.punctuation {
-  color: #d4d4d4;
-}
-
-.language-html .language-css .token.punctuation {
-  color: #d4d4d4;
-}
-
-.language-html .language-javascript .token.punctuation {
-  color: #d4d4d4;
-}
-
-.token.property {
-  color: #9cdcfe;
-}
-
-.token.tag {
-  color: #569cd6;
-}
-
-.token.boolean {
-  color: #569cd6;
-}
-
-.token.number {
-  color: #b5cea8;
-}
-
-.token.constant {
-  color: #9cdcfe;
-}
-
-.token.symbol {
-  color: #b5cea8;
-}
-
-.token.inserted {
-  color: #b5cea8;
-}
-
-.token.unit {
-  color: #b5cea8;
-}
-
-.token.selector {
-  color: #d7ba7d;
-}
-
-.token.attr-name {
-  color: #9cdcfe;
-}
-
-.token.string {
-  color: #ce9178;
-}
-
-.token.char {
-  color: #ce9178;
-}
-
-.token.builtin {
-  color: #ce9178;
-}
-
-.token.deleted {
-  color: #ce9178;
-}
-
-.language-css .token.string.url {
-  text-decoration: underline;
-}
-
-.token.operator {
-  color: #d4d4d4;
-}
-
-.token.entity {
-  color: #569cd6;
-}
-
-operator.arrow {
-  color: #569cd6;
-}
-
-.token.atrule {
-  color: #ce9178;
-}
-
-atrule.rule {
-  color: #c586c0;
-}
-
-atrule.url {
-  color: #9cdcfe;
-}
-
-atrule.url.function {
-  color: #dcdcaa;
-}
-
-atrule.url.punctuation {
-  color: #d4d4d4;
-}
-
-.token.keyword {
-  color: #569cd6;
-}
-
-keyword.module {
-  color: #c586c0;
-}
-
-keyword.control-flow {
-  color: #c586c0;
-}
-
-.token.function {
-  color: #dcdcaa;
-}
-
-function.maybe-class-name {
-  color: #dcdcaa;
-}
-
-.token.regex {
-  color: #d16969;
-}
-
-.token.important {
-  color: #569cd6;
-}
-
-.token.italic {
-  font-style: italic;
-}
-
-.token.class-name {
-  color: #4ec9b0;
-}
-
-.token.maybe-class-name {
-  color: #4ec9b0;
-}
-
-.token.console {
-  color: #9cdcfe;
-}
-
-.token.parameter {
-  color: #9cdcfe;
-}
-
-.token.interpolation {
-  color: #9cdcfe;
-}
-
-punctuation.interpolation-punctuation {
-  color: #569cd6;
-}
-
-.token.variable {
-  color: #9cdcfe;
-}
-
-imports.maybe-class-name {
-  color: #9cdcfe;
-}
-
-exports.maybe-class-name {
-  color: #9cdcfe;
-}
-
-.token.escape {
-  color: #d7ba7d;
-}
-
-tag.punctuation {
-  color: #808080;
-}
-
-.token.cdata {
-  color: #808080;
-}
-
-.token.attr-value {
-  color: #ce9178;
-}
-
-attr-value.punctuation {
-  color: #ce9178;
-}
-
-attr-value.punctuation.attr-equals {
-  color: #d4d4d4;
-}
-
-.token.namespace {
-  color: #4ec9b0;
-}
-
-pre[class*="language-javascript"] {
-  color: #9cdcfe;
-}
-
-code[class*="language-javascript"] {
-  color: #9cdcfe;
-}
-
-pre[class*="language-jsx"] {
-  color: #9cdcfe;
-}
-
-code[class*="language-jsx"] {
-  color: #9cdcfe;
-}
-
-pre[class*="language-typescript"] {
-  color: #9cdcfe;
-}
-
-code[class*="language-typescript"] {
-  color: #9cdcfe;
-}
-
-pre[class*="language-tsx"] {
-  color: #9cdcfe;
-}
-
-code[class*="language-tsx"] {
-  color: #9cdcfe;
-}
-
-pre[class*="language-css"] {
-  color: #ce9178;
-}
-
-code[class*="language-css"] {
-  color: #ce9178;
-}
-
-pre[class*="language-html"] {
-  color: #d4d4d4;
-}
-
-code[class*="language-html"] {
-  color: #d4d4d4;
-}
-
-.language-regex .token.anchor {
-  color: #dcdcaa;
-}
-
-.language-html .token.punctuation {
-  color: #808080;
-}
-
-pre[class*="language-"] > code[class*="language-"] {
-  position: relative;
-  z-index: 1;
-}
-
-.line-highlight.line-highlight {
-  box-shadow: inset 5px 0 0 #f7d87c;
-  z-index: 0;
-}
diff --git a/src/styles/syntaxHighlighting.ts b/src/styles/syntaxHighlighting.ts
deleted file mode 100644
index d2302b93b..000000000
--- a/src/styles/syntaxHighlighting.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-/**
- * Shared syntax highlighting styles for code blocks and diffs
- * Based on VS Code's Dark+ theme, with backgrounds removed for flexibility
- */
-
-import type { CSSProperties } from "react";
-import { vscDarkPlus } from "react-syntax-highlighter/dist/esm/styles/prism";
-
-/**
- * Syntax style with colors only (backgrounds removed)
- * This allows us to apply syntax highlighting on top of diff backgrounds
- */
-export const syntaxStyleNoBackgrounds: Record = {};
-
-// Strip background colors from the theme while preserving syntax colors
-for (const [key, value] of Object.entries(vscDarkPlus as Record)) {
-  if (typeof value === "object" && value !== null) {
-    const { background, backgroundColor, ...rest } = value as Record;
-    syntaxStyleNoBackgrounds[key] = rest as CSSProperties;
-  }
-}
diff --git a/src/utils/highlighting/highlightDiffChunk.ts b/src/utils/highlighting/highlightDiffChunk.ts
index 9d5292692..cf1635331 100644
--- a/src/utils/highlighting/highlightDiffChunk.ts
+++ b/src/utils/highlighting/highlightDiffChunk.ts
@@ -1,4 +1,9 @@
-import { getShikiHighlighter, mapToShikiLang } from "./shikiHighlighter";
+import {
+  getShikiHighlighter,
+  mapToShikiLang,
+  SHIKI_THEME,
+  MAX_DIFF_SIZE_BYTES,
+} from "./shikiHighlighter";
 import type { DiffChunk } from "./diffChunking";
 
 /**
@@ -47,6 +52,16 @@ export async function highlightDiffChunk(
     };
   }
 
+  // Enforce size limit for performance
+  // Calculate size by summing line lengths + newlines (more performant than TextEncoder)
+  const sizeBytes =
+    chunk.lines.reduce((total, line) => total + line.length, 0) + chunk.lines.length - 1;
+  if (sizeBytes > MAX_DIFF_SIZE_BYTES) {
+    return createFallbackChunk(chunk);
+  }
+
+  const code = chunk.lines.join("\n");
+
   try {
     const highlighter = await getShikiHighlighter();
     const shikiLang = mapToShikiLang(language);
@@ -66,11 +81,9 @@ export async function highlightDiffChunk(
       }
     }
 
-    // Highlight entire chunk as one block
-    const code = chunk.lines.join("\n");
     const html = highlighter.codeToHtml(code, {
       lang: shikiLang,
-      theme: "dark-plus",
+      theme: SHIKI_THEME,
     });
 
     // Parse HTML to extract line contents
diff --git a/src/utils/highlighting/highlightSearchTerms.ts b/src/utils/highlighting/highlightSearchTerms.ts
index 32eff907d..74ca1c77c 100644
--- a/src/utils/highlighting/highlightSearchTerms.ts
+++ b/src/utils/highlighting/highlightSearchTerms.ts
@@ -5,6 +5,7 @@
 
 import { LRUCache } from "lru-cache";
 import CRC32 from "crc-32";
+import escapeHtml from "escape-html";
 
 export interface SearchHighlightConfig {
   searchTerm: string;
@@ -57,6 +58,73 @@ function walkTextNodes(node: Node, callback: (textNode: Text) => void): void {
   }
 }
 
+/**
+ * Highlight search matches in plain text by wrapping in  tags
+ * For use with non-HTML text like file paths
+ *
+ * @param text - Plain text to highlight
+ * @param config - Search configuration
+ * @returns HTML string with matches wrapped in 
+ */
+export function highlightSearchInText(text: string, config: SearchHighlightConfig): string {
+  const { searchTerm, useRegex, matchCase } = config;
+
+  // No highlighting if search term is empty
+  if (!searchTerm.trim()) {
+    return text;
+  }
+
+  try {
+    // Build regex pattern (with caching)
+    const regexCacheKey = `${searchTerm}:${useRegex}:${matchCase}`;
+    let pattern = regexCache.get(regexCacheKey);
+
+    if (!pattern) {
+      try {
+        pattern = useRegex
+          ? new RegExp(searchTerm, matchCase ? "g" : "gi")
+          : new RegExp(escapeRegex(searchTerm), matchCase ? "g" : "gi");
+        regexCache.set(regexCacheKey, pattern);
+      } catch {
+        // Invalid regex pattern - return original text
+        return text;
+      }
+    }
+
+    let result = "";
+    let lastIndex = 0;
+    pattern.lastIndex = 0;
+
+    let match;
+    while ((match = pattern.exec(text)) !== null) {
+      // Add text before match (escaped)
+      if (match.index > lastIndex) {
+        result += escapeHtml(text.slice(lastIndex, match.index));
+      }
+
+      // Add highlighted match (escaped)
+      result += `${escapeHtml(match[0])}`;
+
+      lastIndex = match.index + match[0].length;
+
+      // Prevent infinite loop on zero-length matches
+      if (match[0].length === 0) {
+        pattern.lastIndex++;
+      }
+    }
+
+    // Add remaining text after last match (escaped)
+    if (lastIndex < text.length) {
+      result += escapeHtml(text.slice(lastIndex));
+    }
+
+    return result;
+  } catch (error) {
+    console.warn("Failed to highlight search in text:", error);
+    return text;
+  }
+}
+
 /**
  * Wrap search matches in HTML with  tags
  * Preserves existing HTML structure (e.g., Shiki syntax highlighting)
diff --git a/src/utils/highlighting/shikiHighlighter.ts b/src/utils/highlighting/shikiHighlighter.ts
index d4465e795..ff8e7466e 100644
--- a/src/utils/highlighting/shikiHighlighter.ts
+++ b/src/utils/highlighting/shikiHighlighter.ts
@@ -1,5 +1,12 @@
 import { createHighlighter, type Highlighter } from "shiki";
 
+// Shiki theme used throughout the application
+export const SHIKI_THEME = "min-dark";
+
+// Maximum diff size to highlight (in bytes)
+// Diffs larger than this will fall back to plain text for performance
+export const MAX_DIFF_SIZE_BYTES = 4096; // 4kb
+
 // Singleton promise (cached to prevent race conditions)
 // Multiple concurrent calls will await the same Promise
 let highlighterPromise: Promise | null = null;
@@ -14,7 +21,7 @@ export async function getShikiHighlighter(): Promise {
   // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
   if (!highlighterPromise) {
     highlighterPromise = createHighlighter({
-      themes: ["dark-plus"],
+      themes: [SHIKI_THEME],
       langs: [], // Load languages on-demand via highlightDiffChunk
     });
   }