diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 84c3daf8..16b36d85 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -40,7 +40,7 @@ jobs: - uses: actions/setup-node@v6 with: cache-dependency-path: ./website/package-lock.json - node-version: 20 + node-version: 22 cache: npm - name: Install dependencies @@ -48,7 +48,6 @@ jobs: - name: Build website run: npm run build env: - GOOGLE_SCRIPT_URL: ${{ secrets.GOOGLE_SCRIPT_URL }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Upload Build Artifact diff --git a/.github/workflows/pr-build-website.yml b/.github/workflows/pr-build-website.yml index 071965db..23601176 100644 --- a/.github/workflows/pr-build-website.yml +++ b/.github/workflows/pr-build-website.yml @@ -33,7 +33,7 @@ jobs: - uses: actions/setup-node@v6 with: cache-dependency-path: ./website/package-lock.json - node-version: 20 + node-version: 22 cache: npm - name: Install dependencies diff --git a/website/docusaurus.config.ts b/website/docusaurus.config.ts index 1187a8f9..207833d9 100644 --- a/website/docusaurus.config.ts +++ b/website/docusaurus.config.ts @@ -292,10 +292,6 @@ const config: Config = { darkTheme: prismThemes.dracula, }, } satisfies Preset.ThemeConfig, - - customFields: { - googleScriptUrl: process.env.GOOGLE_SCRIPT_URL, - }, }; export default config; diff --git a/website/google-apps-script.js b/website/google-apps-script.js deleted file mode 100644 index 8eac394c..00000000 --- a/website/google-apps-script.js +++ /dev/null @@ -1,68 +0,0 @@ -/** - * DO NOT DELETE THIS FILE - * Google Apps Script to handle feedback submissions. - * - * INSTRUCTIONS: - * 1. Open your Google Sheet. - * 2. Go to Extensions > Apps Script. - * 3. Paste this code into the editor. - * 4. Save the project. - * 5. Click "Deploy" > "New deployment". - * 6. Select type: "Web app". - * 7. Description: "Feedback Widget API". - * 8. Execute as: "Me" (your email). - * 9. Who has access: "Anyone" (IMPORTANT). - * 10. Click "Deploy" and copy the "Web app URL". - */ - - -function doPost(e) { - const lock = LockService.getScriptLock(); - lock.tryLock(10000); - - try { - const doc = SpreadsheetApp.getActiveSpreadsheet(); - const sheet = doc.getSheetByName('Feedback') || doc.insertSheet('Feedback'); - - // Add headers if they don't exist - if (sheet.getLastRow() === 0) { - sheet.appendRow(['Timestamp', 'Page URL', 'Vote', 'Comment', 'User Agent']); - } - - const headers = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0]; - const nextRow = sheet.getLastRow() + 1; - - // Parse the request body - const data = JSON.parse(e.postData.contents); - - const newRow = [ - new Date(), - data.url || 'Unknown', - data.vote || 'Unknown', - data.comment || '', - data.userAgent || '' - ]; - - sheet.appendRow(newRow); - - return ContentService - .createTextOutput(JSON.stringify({ 'result': 'success', 'row': nextRow })) - .setMimeType(ContentService.MimeType.JSON); - - } catch (e) { - return ContentService - .createTextOutput(JSON.stringify({ 'result': 'error', 'error': e })) - .setMimeType(ContentService.MimeType.JSON); - } finally { - lock.releaseLock(); - } -} - -// Handle CORS preflight requests -function doOptions(e) { - return ContentService.createTextOutput("") - .setMimeType(ContentService.MimeType.JSON) - .appendHeader("Access-Control-Allow-Origin", "*") - .appendHeader("Access-Control-Allow-Methods", "POST") - .appendHeader("Access-Control-Allow-Headers", "Content-Type"); -} diff --git a/website/package-lock.json b/website/package-lock.json index 3bea6084..d5130f67 100644 --- a/website/package-lock.json +++ b/website/package-lock.json @@ -17,7 +17,7 @@ "@mdx-js/react": "^3.0.0", "clsx": "^2.0.0", "image-size": "file:vendor/image-size", - "mermaid": "^11.16.1", + "mermaid": "^12.1.0", "prism-react-renderer": "^2.3.0", "react": "^18.3.1", "react-dom": "^18.3.1" @@ -27,7 +27,7 @@ "@docusaurus/tsconfig": "^3.10.2", "@docusaurus/types": "^3.10.2", "@types/node": "^25.5.2", - "dotenv": "^17.3.1", + "dotenv": "^18.0.7", "patch-package": "^8.0.0", "ts-node": "^10.9.2", "typescript": "~6.0.2" @@ -2021,10 +2021,41 @@ "integrity": "sha512-jigsZK+sMF/cuiB7sERuo9V7N9jx+dhmHHnQyDSVdpZwVutaBu7WvNYqMDLSgFgfB30n452TP3vjDAvFC973mA==", "license": "MIT" }, + "node_modules/@chevrotain/cst-dts-gen": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-13.2.0.tgz", + "integrity": "sha512-bA9dvWlhAUcHkNwU+8w9yiUxJPlj/Lm3VqS7MD+NbIR/7LmpNLuK/AWNFdCo/T3SK5ND0/UHf3IJvl/Jn/i6yg==", + "license": "Apache-2.0", + "dependencies": { + "@chevrotain/gast": "13.2.0", + "@chevrotain/types": "13.2.0" + } + }, + "node_modules/@chevrotain/gast": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-13.2.0.tgz", + "integrity": "sha512-bCARdAsG+eEbOveSXcOAC7pVxA04I1ionzeMOwIYf5NX7SaS7zgn4Dgug2BSqoL+iyKeMNSorQjsFSHJHsCNwg==", + "license": "Apache-2.0", + "dependencies": { + "@chevrotain/types": "13.2.0" + } + }, + "node_modules/@chevrotain/regexp-to-ast": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/@chevrotain/regexp-to-ast/-/regexp-to-ast-13.2.0.tgz", + "integrity": "sha512-kxpUkLtiaK09ph+dib+Yvm+3sWSnuwlo25gqfKRgTPNmF6H7uW4gVkMjaRdtnN783S9sM6vUNWh9CsxYX4QwKw==", + "license": "Apache-2.0" + }, "node_modules/@chevrotain/types": { - "version": "11.1.2", - "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-11.1.2.tgz", - "integrity": "sha512-U+HFai5+zmJCkK86QsaJtoITlboZHBqrVketcO2ROv865xfCMSFpELQoz1GkX5GzME8pTa+3kbKrZHQtI0gdbw==", + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-13.2.0.tgz", + "integrity": "sha512-7qrYHRlKfWf2AvBfJi5eVOrKAkbxvMFsy/iIHTGIiApNcEecCaVIdR+mIQhyCBsTDJxBz4JWXHMo6krbhR9hVg==", + "license": "Apache-2.0" + }, + "node_modules/@chevrotain/utils": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-13.2.0.tgz", + "integrity": "sha512-SzKYY68rseOrb9KILVzPsl6SjkQtdWw01SRGB5aCVI5kFcHltQsOYV3JB0Ffst72DgkvHCyDQ0NLwxtmCCf97Q==", "license": "Apache-2.0" }, "node_modules/@colors/colors": { @@ -4964,12 +4995,15 @@ } }, "node_modules/@mermaid-js/parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-1.2.1.tgz", - "integrity": "sha512-n12NohV3mrUyUL2o93IgG/ifeW9FTyeJn3zDxkhwa8MJ9Fxg3HQMlA3RiGmD/3UnJvheztkjjQAjA2T4LmUcpw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-2.0.1.tgz", + "integrity": "sha512-j37dj/h6p6pots1L7pLPPNuABEEu9WP4OYg9pW1g+nYG331j0+3canE9OagtYdytYvdSAMG+2fKU5cxep6LgjA==", "license": "MIT", "dependencies": { - "@chevrotain/types": "~11.1.2" + "@chevrotain/types": "~13.2.0" + }, + "engines": { + "node": ">=22.12.0" } }, "node_modules/@napi-rs/wasm-runtime": { @@ -7585,6 +7619,22 @@ "url": "https://github.com/sponsors/fb55" } }, + "node_modules/chevrotain": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-13.2.0.tgz", + "integrity": "sha512-GTouk5YzgBxlTPCaDn5q0q2EJKkrYmnPF+HmF8v0Qo4r3iyPG7HJivkN1wthCXZcm3sIcZFpGTRovLPNdJNRCA==", + "license": "Apache-2.0", + "dependencies": { + "@chevrotain/cst-dts-gen": "13.2.0", + "@chevrotain/gast": "13.2.0", + "@chevrotain/regexp-to-ast": "13.2.0", + "@chevrotain/types": "13.2.0", + "@chevrotain/utils": "13.2.0" + }, + "engines": { + "node": ">=22.0.0" + } + }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", @@ -9452,11 +9502,14 @@ } }, "node_modules/dotenv": { - "version": "17.3.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.3.1.tgz", - "integrity": "sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA==", + "version": "18.0.8", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-18.0.8.tgz", + "integrity": "sha512-2KDeoFoK/zRtcnbunCDlLG5VWVMcyqeQc6iK65o231nfNAcuGrKoqUQfJFUtBI+QlShk5HKIHxwebBtUl3rEfA==", "dev": true, "license": "BSD-2-Clause", + "bin": { + "dotenv": "dist/index.cjs" + }, "engines": { "node": ">=12" }, @@ -9502,6 +9555,12 @@ "integrity": "sha512-lEcqhErbHjXRvd41rnWLpzbyU/IXfIYo7QwaFWmxGeLiLyY2TBCdHnWY88vB+p3ubnihRypDm66panXl7TylLA==", "license": "ISC" }, + "node_modules/elkjs": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/elkjs/-/elkjs-0.9.3.tgz", + "integrity": "sha512-f/ZeWvW/BCXbhGEf1Ujp29EASo/lk1FDnETgNKwJrsVvGZhUWCZyg3xLJjAsxfOmt8KjswHmI5EwCQcPMpOYhQ==", + "license": "EPL-2.0" + }, "node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", @@ -10076,15 +10135,6 @@ ], "license": "BSD-3-Clause" }, - "node_modules/fastdom": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fastdom/-/fastdom-1.0.12.tgz", - "integrity": "sha512-LB+xjSTEbjHE1cWsxu+tN2Xqr1kpi+V9aADI7sVM5ZMaXyYGPHULQMzpJMYqOTULK/73pUkWVzzObFRBkPr+hg==", - "license": "MIT", - "dependencies": { - "strictdom": "^1.0.1" - } - }, "node_modules/fastq": { "version": "1.20.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", @@ -12580,16 +12630,17 @@ } }, "node_modules/mermaid": { - "version": "11.17.2", - "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.17.2.tgz", - "integrity": "sha512-V6K3C8EBdEsPFZXSKMJe6ppQOENxuHARr9GvHX4hh47lAbhMRD9qf4oEK7LoaRQxULMa80/qt5gHO73aCleBBg==", + "version": "12.2.0", + "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-12.2.0.tgz", + "integrity": "sha512-w7nr/SFrLO7BaVTs3dQTvYSV6nYSBj0Yy9DjBhsIJtAcHqRzXSq4Pg32ujHZ/AdWsAMNEvvhbm5dt9E2tOiHzw==", "license": "MIT", "dependencies": { "@braintree/sanitize-url": "^7.1.2", "@iconify/utils": "^3.0.2", - "@mermaid-js/parser": "^1.2.1", + "@mermaid-js/parser": "^2.0.1", "@types/d3": "^7.4.3", "@upsetjs/venn.js": "^2.0.0", + "chevrotain": "~13.2.0", "cytoscape": "^3.34.0", "cytoscape-cose-bilkent": "^4.1.0", "cytoscape-fcose": "^2.2.0", @@ -12597,16 +12648,19 @@ "d3-sankey": "^0.12.3", "dagre-d3-es": "7.0.14", "dayjs": "^1.11.21", - "dompurify": "^3.3.3", + "dompurify": "^3.4.12", + "elkjs": "^0.9.3", "es-toolkit": "^1.45.1", - "fastdom": "1.0.12", - "katex": "^0.16.47", + "katex": "^0.18.0", "khroma": "^2.1.0", "marked": "^16.3.0", "roughjs": "^4.6.6", "stylis": "^4.3.6", "ts-dedent": "^2.2.0", "uuid": "^11.1.0 || ^12 || ^13 || ^14.0.0" + }, + "engines": { + "node": ">=22.12.0" } }, "node_modules/methods": { @@ -18343,12 +18397,6 @@ "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", "license": "MIT" }, - "node_modules/strictdom": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strictdom/-/strictdom-1.0.1.tgz", - "integrity": "sha512-cEmp9QeXXRmjj/rVp9oyiqcvyocWab/HaoN4+bwFeZ7QzykJD6L3yD4v12K1x0tHpqRqVpJevN3gW7kyM39Bqg==", - "license": "MIT" - }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", diff --git a/website/package.json b/website/package.json index 5840cd21..592bb558 100644 --- a/website/package.json +++ b/website/package.json @@ -58,7 +58,7 @@ ] }, "engines": { - "node": ">=20.0" + "node": ">=22.12.0" }, "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e", "resolutions": { diff --git a/website/src/components/FeedbackWidget/index.tsx b/website/src/components/FeedbackWidget/index.tsx deleted file mode 100644 index 184dc25e..00000000 --- a/website/src/components/FeedbackWidget/index.tsx +++ /dev/null @@ -1,121 +0,0 @@ -import React, { useState } from 'react'; -import clsx from 'clsx'; -import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; - -export default function FeedbackWidget() { - const { siteConfig } = useDocusaurusContext(); - const GOOGLE_SCRIPT_URL = siteConfig.customFields?.googleScriptUrl as string; - - const [vote, setVote] = useState(null); - const [comment, setComment] = useState(''); - const [submitted, setSubmitted] = useState(false); - const [submitting, setSubmitting] = useState(false); - - const handleVote = (value: 'yes' | 'no') => { - setVote(value); - if (value === 'yes') { - submitFeedback(value, ''); - } - }; - - const submitFeedback = async (voteValue: string, commentValue: string) => { - setSubmitting(true); - try { - const data = { - url: window.location.href, - vote: voteValue, - comment: commentValue, - userAgent: navigator.userAgent, - }; - - await fetch(GOOGLE_SCRIPT_URL, { - method: 'POST', - mode: 'no-cors', - headers: { - 'Content-Type': 'text/plain;charset=utf-8', - }, - body: JSON.stringify(data), - }); - - setSubmitted(true); - } catch (error) { - setSubmitted(true); - } finally { - setSubmitting(false); - } - }; - - const handleCommentSubmit = (e: React.FormEvent) => { - e.preventDefault(); - if (vote) { - submitFeedback(vote, comment); - } - }; - - if (submitted) { - return ( -
-
-

Thanks for your feedback! 🙏🏽

-
-
- ); - } - - return ( -
-
- {!vote ? ( -
- Was this helpful? -
- - -
-
- ) : ( -
-

- {vote === 'yes' ? 'What was most helpful?' : 'How can we improve this page?'} -

-