this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat(forms): support basic markdown in authored content

+784 -18
+13 -9
app/(creator)/forms/[id]/responses/[responseId]/page.tsx
··· 5 5 import { Badge } from "@/components/ui/badge"; 6 6 import { Button } from "@/components/ui/button"; 7 7 import { Card } from "@/components/ui/card"; 8 + import { AuthoredMarkdown } from "@/components/ui/authored-markdown"; 8 9 import { AGREEMENT_ANSWER_VALUES } from "@/lib/blocks"; 9 10 import { getServerAuthSession } from "@/lib/auth"; 10 11 import { AppError } from "@/lib/errors"; ··· 145 146 {block.title || t("responseDetail.contextTitle")} 146 147 </h2> 147 148 {block.description ? ( 148 - <p className="mt-3 text-sm leading-7 text-[var(--muted)]"> 149 - {block.description} 150 - </p> 149 + <AuthoredMarkdown 150 + content={block.description} 151 + className="mt-3 text-sm leading-7 text-[var(--muted)]" 152 + /> 151 153 ) : null} 152 154 {"body" in block.config ? ( 153 - <p className="mt-4 text-base leading-8 text-[var(--ink)]/85"> 154 - {block.config.body} 155 - </p> 155 + <AuthoredMarkdown 156 + content={block.config.body} 157 + className="mt-4 text-base leading-8 text-[var(--ink)]/85" 158 + /> 156 159 ) : null} 157 160 </Card> 158 161 ); ··· 172 175 {block.title} 173 176 </h2> 174 177 {block.description ? ( 175 - <p className="mt-3 text-sm leading-7 text-[var(--muted)]"> 176 - {block.description} 177 - </p> 178 + <AuthoredMarkdown 179 + content={block.description} 180 + className="mt-3 text-sm leading-7 text-[var(--muted)]" 181 + /> 178 182 ) : null} 179 183 <div className="mt-6 rounded-[18px] border border-[color:var(--line)] bg-[var(--bg-strong)] px-5 py-4 text-[var(--ink)]"> 180 184 {Array.isArray(answer) ? (
+5 -3
app/(creator)/forms/[id]/responses/page.tsx
··· 8 8 import { Badge } from "@/components/ui/badge"; 9 9 import { Button } from "@/components/ui/button"; 10 10 import { Card } from "@/components/ui/card"; 11 + import { AuthoredMarkdown } from "@/components/ui/authored-markdown"; 11 12 import { ScrollHintPanel } from "@/components/ui/scroll-hint-panel"; 12 13 import { 13 14 AGREEMENT_ANSWER_VALUES, ··· 225 226 {summary.block.title} 226 227 </h2> 227 228 {summary.block.description ? ( 228 - <p className="mt-3 text-sm leading-7 text-[var(--muted)]"> 229 - {summary.block.description} 230 - </p> 229 + <AuthoredMarkdown 230 + content={summary.block.description} 231 + className="mt-3 text-sm leading-7 text-[var(--muted)]" 232 + /> 231 233 ) : null} 232 234 233 235 <div className="mt-6 flex flex-wrap gap-2">
+196
bun.lock
··· 24 24 "react": "19.2.5", 25 25 "react-day-picker": "9.14.0", 26 26 "react-dom": "19.2.5", 27 + "react-markdown": "^10.1.0", 28 + "remark-gfm": "^4.0.1", 27 29 "tailwind-merge": "3.5.0", 28 30 "xlsx": "0.18.5", 29 31 "yaml": "2.8.3", ··· 362 364 363 365 "@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="], 364 366 367 + "@types/debug": ["@types/debug@4.1.13", "", { "dependencies": { "@types/ms": "*" } }, "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw=="], 368 + 365 369 "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], 370 + 371 + "@types/estree-jsx": ["@types/estree-jsx@1.0.5", "", { "dependencies": { "@types/estree": "*" } }, "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg=="], 372 + 373 + "@types/hast": ["@types/hast@3.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ=="], 366 374 367 375 "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], 368 376 369 377 "@types/json5": ["@types/json5@0.0.29", "", {}, "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ=="], 370 378 379 + "@types/mdast": ["@types/mdast@4.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA=="], 380 + 381 + "@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="], 382 + 371 383 "@types/node": ["@types/node@25.6.0", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ=="], 372 384 373 385 "@types/pg": ["@types/pg@8.20.0", "", { "dependencies": { "@types/node": "*", "pg-protocol": "*", "pg-types": "^2.2.0" } }, "sha512-bEPFOaMAHTEP1EzpvHTbmwR8UsFyHSKsRisLIHVMXnpNefSbGA1bD6CVy+qKjGSqmZqNqBDV2azOBo8TgkcVow=="], ··· 375 387 "@types/react": ["@types/react@19.2.14", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w=="], 376 388 377 389 "@types/react-dom": ["@types/react-dom@19.2.3", "", { "peerDependencies": { "@types/react": "^19.2.0" } }, "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ=="], 390 + 391 + "@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="], 378 392 379 393 "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.58.1", "", { "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.58.1", "@typescript-eslint/type-utils": "8.58.1", "@typescript-eslint/utils": "8.58.1", "@typescript-eslint/visitor-keys": "8.58.1", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.58.1", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-eSkwoemjo76bdXl2MYqtxg51HNwUSkWfODUOQ3PaTLZGh9uIWWFZIjyjaJnex7wXDu+TRx+ATsnSxdN9YWfRTQ=="], 380 394 ··· 396 410 397 411 "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.58.1", "", { "dependencies": { "@typescript-eslint/types": "8.58.1", "eslint-visitor-keys": "^5.0.0" } }, "sha512-y+vH7QE8ycjoa0bWciFg7OpFcipUuem1ujhrdLtq1gByKwfbC7bPeKsiny9e0urg93DqwGcHey+bGRKCnF1nZQ=="], 398 412 413 + "@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="], 414 + 399 415 "@unrs/resolver-binding-android-arm-eabi": ["@unrs/resolver-binding-android-arm-eabi@1.11.1", "", { "os": "android", "cpu": "arm" }, "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw=="], 400 416 401 417 "@unrs/resolver-binding-android-arm64": ["@unrs/resolver-binding-android-arm64@1.11.1", "", { "os": "android", "cpu": "arm64" }, "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g=="], ··· 478 494 479 495 "axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="], 480 496 497 + "bail": ["bail@2.0.2", "", {}, "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw=="], 498 + 481 499 "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], 482 500 483 501 "baseline-browser-mapping": ["baseline-browser-mapping@2.10.16", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-Lyf3aK28zpsD1yQMiiHD4RvVb6UdMoo8xzG2XzFIfR9luPzOpcBlAsT/qfB1XWS1bxWT+UtE4WmQgsp297FYOA=="], ··· 502 520 503 521 "caniuse-lite": ["caniuse-lite@1.0.30001787", "", {}, "sha512-mNcrMN9KeI68u7muanUpEejSLghOKlVhRqS/Za2IeyGllJ9I9otGpR9g3nsw7n4W378TE/LyIteA0+/FOZm4Kg=="], 504 522 523 + "ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="], 524 + 505 525 "cfb": ["cfb@1.2.2", "", { "dependencies": { "adler-32": "~1.3.0", "crc-32": "~1.2.0" } }, "sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA=="], 506 526 507 527 "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], 508 528 529 + "character-entities": ["character-entities@2.0.2", "", {}, "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ=="], 530 + 531 + "character-entities-html4": ["character-entities-html4@2.1.0", "", {}, "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA=="], 532 + 533 + "character-entities-legacy": ["character-entities-legacy@3.0.0", "", {}, "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ=="], 534 + 535 + "character-reference-invalid": ["character-reference-invalid@2.0.1", "", {}, "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw=="], 536 + 509 537 "chart.js": ["chart.js@4.5.1", "", { "dependencies": { "@kurkle/color": "^0.3.0" } }, "sha512-GIjfiT9dbmHRiYi6Nl2yFCq7kkwdkp1W/lp2J99rX0yo9tgJGn3lKQATztIjb5tVtevcBtIdICNWqlq5+E8/Pw=="], 510 538 511 539 "chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="], ··· 523 551 "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], 524 552 525 553 "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], 554 + 555 + "comma-separated-tokens": ["comma-separated-tokens@2.0.3", "", {}, "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="], 526 556 527 557 "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="], 528 558 ··· 554 584 555 585 "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], 556 586 587 + "decode-named-character-reference": ["decode-named-character-reference@1.3.0", "", { "dependencies": { "character-entities": "^2.0.0" } }, "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q=="], 588 + 557 589 "deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="], 558 590 559 591 "deepmerge-ts": ["deepmerge-ts@7.1.5", "", {}, "sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw=="], ··· 566 598 567 599 "denque": ["denque@2.1.0", "", {}, "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw=="], 568 600 601 + "dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="], 602 + 569 603 "destr": ["destr@2.0.5", "", {}, "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA=="], 570 604 571 605 "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], 572 606 573 607 "detect-node-es": ["detect-node-es@1.1.0", "", {}, "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ=="], 608 + 609 + "devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="], 574 610 575 611 "doctrine": ["doctrine@2.1.0", "", { "dependencies": { "esutils": "^2.0.2" } }, "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw=="], 576 612 ··· 640 676 641 677 "estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="], 642 678 679 + "estree-util-is-identifier-name": ["estree-util-is-identifier-name@3.0.0", "", {}, "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg=="], 680 + 643 681 "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="], 644 682 645 683 "exsolve": ["exsolve@1.0.8", "", {}, "sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA=="], 684 + 685 + "extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="], 646 686 647 687 "fast-check": ["fast-check@3.23.2", "", { "dependencies": { "pure-rand": "^6.1.0" } }, "sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A=="], 648 688 ··· 732 772 733 773 "hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="], 734 774 775 + "hast-util-to-jsx-runtime": ["hast-util-to-jsx-runtime@2.3.6", "", { "dependencies": { "@types/estree": "^1.0.0", "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "comma-separated-tokens": "^2.0.0", "devlop": "^1.0.0", "estree-util-is-identifier-name": "^3.0.0", "hast-util-whitespace": "^3.0.0", "mdast-util-mdx-expression": "^2.0.0", "mdast-util-mdx-jsx": "^3.0.0", "mdast-util-mdxjs-esm": "^2.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "style-to-js": "^1.0.0", "unist-util-position": "^5.0.0", "vfile-message": "^4.0.0" } }, "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg=="], 776 + 777 + "hast-util-whitespace": ["hast-util-whitespace@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw=="], 778 + 735 779 "hermes-estree": ["hermes-estree@0.25.1", "", {}, "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw=="], 736 780 737 781 "hermes-parser": ["hermes-parser@0.25.1", "", { "dependencies": { "hermes-estree": "0.25.1" } }, "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA=="], 738 782 739 783 "hono": ["hono@4.12.12", "", {}, "sha512-p1JfQMKaceuCbpJKAPKVqyqviZdS0eUxH9v82oWo1kb9xjQ5wA6iP3FNVAPDFlz5/p7d45lO+BpSk1tuSZMF4Q=="], 740 784 785 + "html-url-attributes": ["html-url-attributes@3.0.1", "", {}, "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ=="], 786 + 741 787 "http-status-codes": ["http-status-codes@2.3.0", "", {}, "sha512-RJ8XvFvpPM/Dmc5SV+dC4y5PCeOhT3x1Hq0NU3rjGeg5a/CqlhZ7uudknPwZFz4aeAXDcbAyaeP7GAo9lvngtA=="], 742 788 743 789 "iconv-lite": ["iconv-lite@0.7.2", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw=="], ··· 748 794 749 795 "imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="], 750 796 797 + "inline-style-parser": ["inline-style-parser@0.2.7", "", {}, "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA=="], 798 + 751 799 "internal-slot": ["internal-slot@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "hasown": "^2.0.2", "side-channel": "^1.1.0" } }, "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw=="], 752 800 801 + "is-alphabetical": ["is-alphabetical@2.0.1", "", {}, "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ=="], 802 + 803 + "is-alphanumerical": ["is-alphanumerical@2.0.1", "", { "dependencies": { "is-alphabetical": "^2.0.0", "is-decimal": "^2.0.0" } }, "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw=="], 804 + 753 805 "is-array-buffer": ["is-array-buffer@3.0.5", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "get-intrinsic": "^1.2.6" } }, "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A=="], 754 806 755 807 "is-async-function": ["is-async-function@2.1.1", "", { "dependencies": { "async-function": "^1.0.0", "call-bound": "^1.0.3", "get-proto": "^1.0.1", "has-tostringtag": "^1.0.2", "safe-regex-test": "^1.1.0" } }, "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ=="], ··· 767 819 "is-data-view": ["is-data-view@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "get-intrinsic": "^1.2.6", "is-typed-array": "^1.1.13" } }, "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw=="], 768 820 769 821 "is-date-object": ["is-date-object@1.1.0", "", { "dependencies": { "call-bound": "^1.0.2", "has-tostringtag": "^1.0.2" } }, "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg=="], 822 + 823 + "is-decimal": ["is-decimal@2.0.1", "", {}, "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A=="], 770 824 771 825 "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], 772 826 ··· 776 830 777 831 "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], 778 832 833 + "is-hexadecimal": ["is-hexadecimal@2.0.1", "", {}, "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg=="], 834 + 779 835 "is-map": ["is-map@2.0.3", "", {}, "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw=="], 780 836 781 837 "is-negative-zero": ["is-negative-zero@2.0.3", "", {}, "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw=="], ··· 783 839 "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], 784 840 785 841 "is-number-object": ["is-number-object@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw=="], 842 + 843 + "is-plain-obj": ["is-plain-obj@4.1.0", "", {}, "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg=="], 786 844 787 845 "is-property": ["is-property@1.0.2", "", {}, "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g=="], 788 846 ··· 868 926 869 927 "long": ["long@5.3.2", "", {}, "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="], 870 928 929 + "longest-streak": ["longest-streak@3.1.0", "", {}, "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="], 930 + 871 931 "loose-envify": ["loose-envify@1.4.0", "", { "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, "bin": { "loose-envify": "cli.js" } }, "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q=="], 872 932 873 933 "lru-cache": ["lru-cache@6.0.0", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA=="], ··· 878 938 879 939 "magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], 880 940 941 + "markdown-table": ["markdown-table@3.0.4", "", {}, "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw=="], 942 + 881 943 "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="], 882 944 945 + "mdast-util-find-and-replace": ["mdast-util-find-and-replace@3.0.2", "", { "dependencies": { "@types/mdast": "^4.0.0", "escape-string-regexp": "^5.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg=="], 946 + 947 + "mdast-util-from-markdown": ["mdast-util-from-markdown@2.0.3", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "mdast-util-to-string": "^4.0.0", "micromark": "^4.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-decode-string": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q=="], 948 + 949 + "mdast-util-gfm": ["mdast-util-gfm@3.1.0", "", { "dependencies": { "mdast-util-from-markdown": "^2.0.0", "mdast-util-gfm-autolink-literal": "^2.0.0", "mdast-util-gfm-footnote": "^2.0.0", "mdast-util-gfm-strikethrough": "^2.0.0", "mdast-util-gfm-table": "^2.0.0", "mdast-util-gfm-task-list-item": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ=="], 950 + 951 + "mdast-util-gfm-autolink-literal": ["mdast-util-gfm-autolink-literal@2.0.1", "", { "dependencies": { "@types/mdast": "^4.0.0", "ccount": "^2.0.0", "devlop": "^1.0.0", "mdast-util-find-and-replace": "^3.0.0", "micromark-util-character": "^2.0.0" } }, "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ=="], 952 + 953 + "mdast-util-gfm-footnote": ["mdast-util-gfm-footnote@2.1.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "devlop": "^1.1.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0" } }, "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ=="], 954 + 955 + "mdast-util-gfm-strikethrough": ["mdast-util-gfm-strikethrough@2.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg=="], 956 + 957 + "mdast-util-gfm-table": ["mdast-util-gfm-table@2.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "markdown-table": "^3.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg=="], 958 + 959 + "mdast-util-gfm-task-list-item": ["mdast-util-gfm-task-list-item@2.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ=="], 960 + 961 + "mdast-util-mdx-expression": ["mdast-util-mdx-expression@2.0.1", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ=="], 962 + 963 + "mdast-util-mdx-jsx": ["mdast-util-mdx-jsx@3.2.0", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "ccount": "^2.0.0", "devlop": "^1.1.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0", "parse-entities": "^4.0.0", "stringify-entities": "^4.0.0", "unist-util-stringify-position": "^4.0.0", "vfile-message": "^4.0.0" } }, "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q=="], 964 + 965 + "mdast-util-mdxjs-esm": ["mdast-util-mdxjs-esm@2.0.1", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg=="], 966 + 967 + "mdast-util-phrasing": ["mdast-util-phrasing@4.1.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "unist-util-is": "^6.0.0" } }, "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w=="], 968 + 969 + "mdast-util-to-hast": ["mdast-util-to-hast@13.2.1", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "@ungap/structured-clone": "^1.0.0", "devlop": "^1.0.0", "micromark-util-sanitize-uri": "^2.0.0", "trim-lines": "^3.0.0", "unist-util-position": "^5.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" } }, "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA=="], 970 + 971 + "mdast-util-to-markdown": ["mdast-util-to-markdown@2.1.2", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "longest-streak": "^3.0.0", "mdast-util-phrasing": "^4.0.0", "mdast-util-to-string": "^4.0.0", "micromark-util-classify-character": "^2.0.0", "micromark-util-decode-string": "^2.0.0", "unist-util-visit": "^5.0.0", "zwitch": "^2.0.0" } }, "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA=="], 972 + 973 + "mdast-util-to-string": ["mdast-util-to-string@4.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0" } }, "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg=="], 974 + 883 975 "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], 884 976 977 + "micromark": ["micromark@4.0.2", "", { "dependencies": { "@types/debug": "^4.0.0", "debug": "^4.0.0", "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "micromark-core-commonmark": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-combine-extensions": "^2.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-encode": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-resolve-all": "^2.0.0", "micromark-util-sanitize-uri": "^2.0.0", "micromark-util-subtokenize": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA=="], 978 + 979 + "micromark-core-commonmark": ["micromark-core-commonmark@2.0.3", "", { "dependencies": { "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "micromark-factory-destination": "^2.0.0", "micromark-factory-label": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-factory-title": "^2.0.0", "micromark-factory-whitespace": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-classify-character": "^2.0.0", "micromark-util-html-tag-name": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-resolve-all": "^2.0.0", "micromark-util-subtokenize": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg=="], 980 + 981 + "micromark-extension-gfm": ["micromark-extension-gfm@3.0.0", "", { "dependencies": { "micromark-extension-gfm-autolink-literal": "^2.0.0", "micromark-extension-gfm-footnote": "^2.0.0", "micromark-extension-gfm-strikethrough": "^2.0.0", "micromark-extension-gfm-table": "^2.0.0", "micromark-extension-gfm-tagfilter": "^2.0.0", "micromark-extension-gfm-task-list-item": "^2.0.0", "micromark-util-combine-extensions": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w=="], 982 + 983 + "micromark-extension-gfm-autolink-literal": ["micromark-extension-gfm-autolink-literal@2.1.0", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-sanitize-uri": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw=="], 984 + 985 + "micromark-extension-gfm-footnote": ["micromark-extension-gfm-footnote@2.1.0", "", { "dependencies": { "devlop": "^1.0.0", "micromark-core-commonmark": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-sanitize-uri": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw=="], 986 + 987 + "micromark-extension-gfm-strikethrough": ["micromark-extension-gfm-strikethrough@2.1.0", "", { "dependencies": { "devlop": "^1.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-classify-character": "^2.0.0", "micromark-util-resolve-all": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw=="], 988 + 989 + "micromark-extension-gfm-table": ["micromark-extension-gfm-table@2.1.1", "", { "dependencies": { "devlop": "^1.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg=="], 990 + 991 + "micromark-extension-gfm-tagfilter": ["micromark-extension-gfm-tagfilter@2.0.0", "", { "dependencies": { "micromark-util-types": "^2.0.0" } }, "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg=="], 992 + 993 + "micromark-extension-gfm-task-list-item": ["micromark-extension-gfm-task-list-item@2.1.0", "", { "dependencies": { "devlop": "^1.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw=="], 994 + 995 + "micromark-factory-destination": ["micromark-factory-destination@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA=="], 996 + 997 + "micromark-factory-label": ["micromark-factory-label@2.0.1", "", { "dependencies": { "devlop": "^1.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg=="], 998 + 999 + "micromark-factory-space": ["micromark-factory-space@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg=="], 1000 + 1001 + "micromark-factory-title": ["micromark-factory-title@2.0.1", "", { "dependencies": { "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw=="], 1002 + 1003 + "micromark-factory-whitespace": ["micromark-factory-whitespace@2.0.1", "", { "dependencies": { "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ=="], 1004 + 1005 + "micromark-util-character": ["micromark-util-character@2.1.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q=="], 1006 + 1007 + "micromark-util-chunked": ["micromark-util-chunked@2.0.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0" } }, "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA=="], 1008 + 1009 + "micromark-util-classify-character": ["micromark-util-classify-character@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q=="], 1010 + 1011 + "micromark-util-combine-extensions": ["micromark-util-combine-extensions@2.0.1", "", { "dependencies": { "micromark-util-chunked": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg=="], 1012 + 1013 + "micromark-util-decode-numeric-character-reference": ["micromark-util-decode-numeric-character-reference@2.0.2", "", { "dependencies": { "micromark-util-symbol": "^2.0.0" } }, "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw=="], 1014 + 1015 + "micromark-util-decode-string": ["micromark-util-decode-string@2.0.1", "", { "dependencies": { "decode-named-character-reference": "^1.0.0", "micromark-util-character": "^2.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-symbol": "^2.0.0" } }, "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ=="], 1016 + 1017 + "micromark-util-encode": ["micromark-util-encode@2.0.1", "", {}, "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw=="], 1018 + 1019 + "micromark-util-html-tag-name": ["micromark-util-html-tag-name@2.0.1", "", {}, "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA=="], 1020 + 1021 + "micromark-util-normalize-identifier": ["micromark-util-normalize-identifier@2.0.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0" } }, "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q=="], 1022 + 1023 + "micromark-util-resolve-all": ["micromark-util-resolve-all@2.0.1", "", { "dependencies": { "micromark-util-types": "^2.0.0" } }, "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg=="], 1024 + 1025 + "micromark-util-sanitize-uri": ["micromark-util-sanitize-uri@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-encode": "^2.0.0", "micromark-util-symbol": "^2.0.0" } }, "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ=="], 1026 + 1027 + "micromark-util-subtokenize": ["micromark-util-subtokenize@2.1.0", "", { "dependencies": { "devlop": "^1.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA=="], 1028 + 1029 + "micromark-util-symbol": ["micromark-util-symbol@2.0.1", "", {}, "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q=="], 1030 + 1031 + "micromark-util-types": ["micromark-util-types@2.0.2", "", {}, "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA=="], 1032 + 885 1033 "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], 886 1034 887 1035 "minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="], ··· 954 1102 955 1103 "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="], 956 1104 1105 + "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=="], 1106 + 957 1107 "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], 958 1108 959 1109 "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], ··· 1016 1166 1017 1167 "proper-lockfile": ["proper-lockfile@4.1.2", "", { "dependencies": { "graceful-fs": "^4.2.4", "retry": "^0.12.0", "signal-exit": "^3.0.2" } }, "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA=="], 1018 1168 1169 + "property-information": ["property-information@7.1.0", "", {}, "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ=="], 1170 + 1019 1171 "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], 1020 1172 1021 1173 "pure-rand": ["pure-rand@6.1.0", "", {}, "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA=="], ··· 1031 1183 "react-dom": ["react-dom@19.2.5", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.5" } }, "sha512-J5bAZz+DXMMwW/wV3xzKke59Af6CHY7G4uYLN1OvBcKEsWOs4pQExj86BBKamxl/Ik5bx9whOrvBlSDfWzgSag=="], 1032 1184 1033 1185 "react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="], 1186 + 1187 + "react-markdown": ["react-markdown@10.1.0", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "hast-util-to-jsx-runtime": "^2.0.0", "html-url-attributes": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.0.0", "unified": "^11.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" }, "peerDependencies": { "@types/react": ">=18", "react": ">=18" } }, "sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ=="], 1034 1188 1035 1189 "react-remove-scroll": ["react-remove-scroll@2.7.2", "", { "dependencies": { "react-remove-scroll-bar": "^2.3.7", "react-style-singleton": "^2.2.3", "tslib": "^2.1.0", "use-callback-ref": "^1.3.3", "use-sidecar": "^1.1.3" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q=="], 1036 1190 ··· 1044 1198 1045 1199 "regexp.prototype.flags": ["regexp.prototype.flags@1.5.4", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-errors": "^1.3.0", "get-proto": "^1.0.1", "gopd": "^1.2.0", "set-function-name": "^2.0.2" } }, "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA=="], 1046 1200 1201 + "remark-gfm": ["remark-gfm@4.0.1", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-gfm": "^3.0.0", "micromark-extension-gfm": "^3.0.0", "remark-parse": "^11.0.0", "remark-stringify": "^11.0.0", "unified": "^11.0.0" } }, "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg=="], 1202 + 1203 + "remark-parse": ["remark-parse@11.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-from-markdown": "^2.0.0", "micromark-util-types": "^2.0.0", "unified": "^11.0.0" } }, "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA=="], 1204 + 1205 + "remark-rehype": ["remark-rehype@11.1.2", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "mdast-util-to-hast": "^13.0.0", "unified": "^11.0.0", "vfile": "^6.0.0" } }, "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw=="], 1206 + 1207 + "remark-stringify": ["remark-stringify@11.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-to-markdown": "^2.0.0", "unified": "^11.0.0" } }, "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw=="], 1208 + 1047 1209 "remeda": ["remeda@2.33.4", "", {}, "sha512-ygHswjlc/opg2VrtiYvUOPLjxjtdKvjGz1/plDhkG66hjNjFr1xmfrs2ClNFo/E6TyUFiwYNh53bKV26oBoMGQ=="], 1048 1210 1049 1211 "require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="], ··· 1098 1260 1099 1261 "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], 1100 1262 1263 + "space-separated-tokens": ["space-separated-tokens@2.0.2", "", {}, "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q=="], 1264 + 1101 1265 "split2": ["split2@4.2.0", "", {}, "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg=="], 1102 1266 1103 1267 "sqlstring": ["sqlstring@2.3.3", "", {}, "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg=="], ··· 1121 1285 "string.prototype.trimend": ["string.prototype.trimend@1.0.9", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ=="], 1122 1286 1123 1287 "string.prototype.trimstart": ["string.prototype.trimstart@1.0.8", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg=="], 1288 + 1289 + "stringify-entities": ["stringify-entities@4.0.4", "", { "dependencies": { "character-entities-html4": "^2.0.0", "character-entities-legacy": "^3.0.0" } }, "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg=="], 1124 1290 1125 1291 "strip-bom": ["strip-bom@3.0.0", "", {}, "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA=="], 1126 1292 1127 1293 "strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="], 1128 1294 1295 + "style-to-js": ["style-to-js@1.1.21", "", { "dependencies": { "style-to-object": "1.0.14" } }, "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ=="], 1296 + 1297 + "style-to-object": ["style-to-object@1.0.14", "", { "dependencies": { "inline-style-parser": "0.2.7" } }, "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw=="], 1298 + 1129 1299 "styled-jsx": ["styled-jsx@5.1.6", "", { "dependencies": { "client-only": "0.0.1" }, "peerDependencies": { "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" } }, "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA=="], 1130 1300 1131 1301 "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], ··· 1144 1314 1145 1315 "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], 1146 1316 1317 + "trim-lines": ["trim-lines@3.0.1", "", {}, "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg=="], 1318 + 1319 + "trough": ["trough@2.2.0", "", {}, "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw=="], 1320 + 1147 1321 "ts-api-utils": ["ts-api-utils@2.5.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA=="], 1148 1322 1149 1323 "tsconfig-paths": ["tsconfig-paths@3.15.0", "", { "dependencies": { "@types/json5": "^0.0.29", "json5": "^1.0.2", "minimist": "^1.2.6", "strip-bom": "^3.0.0" } }, "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg=="], ··· 1168 1342 1169 1343 "undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="], 1170 1344 1345 + "unified": ["unified@11.0.5", "", { "dependencies": { "@types/unist": "^3.0.0", "bail": "^2.0.0", "devlop": "^1.0.0", "extend": "^3.0.0", "is-plain-obj": "^4.0.0", "trough": "^2.0.0", "vfile": "^6.0.0" } }, "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA=="], 1346 + 1347 + "unist-util-is": ["unist-util-is@6.0.1", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g=="], 1348 + 1349 + "unist-util-position": ["unist-util-position@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA=="], 1350 + 1351 + "unist-util-stringify-position": ["unist-util-stringify-position@4.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ=="], 1352 + 1353 + "unist-util-visit": ["unist-util-visit@5.1.0", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg=="], 1354 + 1355 + "unist-util-visit-parents": ["unist-util-visit-parents@6.0.2", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0" } }, "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ=="], 1356 + 1171 1357 "unrs-resolver": ["unrs-resolver@1.11.1", "", { "dependencies": { "napi-postinstall": "^0.3.0" }, "optionalDependencies": { "@unrs/resolver-binding-android-arm-eabi": "1.11.1", "@unrs/resolver-binding-android-arm64": "1.11.1", "@unrs/resolver-binding-darwin-arm64": "1.11.1", "@unrs/resolver-binding-darwin-x64": "1.11.1", "@unrs/resolver-binding-freebsd-x64": "1.11.1", "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", "@unrs/resolver-binding-linux-x64-musl": "1.11.1", "@unrs/resolver-binding-wasm32-wasi": "1.11.1", "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" } }, "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg=="], 1172 1358 1173 1359 "update-browserslist-db": ["update-browserslist-db@1.2.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w=="], ··· 1181 1367 "uuid": ["uuid@8.3.2", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="], 1182 1368 1183 1369 "valibot": ["valibot@1.2.0", "", { "peerDependencies": { "typescript": ">=5" }, "optionalPeers": ["typescript"] }, "sha512-mm1rxUsmOxzrwnX5arGS+U4T25RdvpPjPN4yR0u9pUBov9+zGVtO84tif1eY4r6zWxVxu3KzIyknJy3rxfRZZg=="], 1370 + 1371 + "vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="], 1372 + 1373 + "vfile-message": ["vfile-message@4.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw=="], 1184 1374 1185 1375 "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], 1186 1376 ··· 1214 1404 1215 1405 "zod-validation-error": ["zod-validation-error@4.0.2", "", { "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" } }, "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ=="], 1216 1406 1407 + "zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="], 1408 + 1217 1409 "@auth/core/jose": ["jose@6.2.2", "", {}, "sha512-d7kPDd34KO/YnzaDOlikGpOurfF0ByC2sEV4cANCtdqLlTfBlw2p14O/5d/zv40gJPbIQxfES3nSx1/oYNyuZQ=="], 1218 1410 1219 1411 "@auth/core/preact": ["preact@10.24.3", "", {}, "sha512-Z2dPnBnMUfyQfSQ+GBdsGa16hz35YmLmtTLhM169uW944hYL6xzTYkJjC07j+Wosz733pMWx0fgON3JNw1jJQA=="], ··· 1266 1458 1267 1459 "is-bun-module/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], 1268 1460 1461 + "mdast-util-find-and-replace/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="], 1462 + 1269 1463 "micromatch/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="], 1270 1464 1271 1465 "next/postcss": ["postcss@8.4.31", "", { "dependencies": { "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } }, "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ=="], 1272 1466 1273 1467 "nypm/citty": ["citty@0.2.2", "", {}, "sha512-+6vJA3L98yv+IdfKGZHBNiGW5KHn22e/JwID0Strsz8h4S/csAu/OuICwxrg44k5MRiZHWIo8XXuJgQTriRP4w=="], 1468 + 1469 + "parse-entities/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], 1274 1470 1275 1471 "pg-types/postgres-array": ["postgres-array@2.0.0", "", {}, "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA=="], 1276 1472
+6
components/form-builder-panels.tsx
··· 961 961 ) 962 962 } 963 963 /> 964 + <p className="text-xs text-[var(--muted)]"> 965 + {t("builder.markdownHelp")} 966 + </p> 964 967 </label> 965 968 ) : null} 966 969 ··· 973 976 value={(blockDraft.config as TextBlockConfig).body} 974 977 onChange={(event) => updateConfig({ body: event.target.value })} 975 978 /> 979 + <p className="text-xs text-[var(--muted)]"> 980 + {t("builder.markdownHelp")} 981 + </p> 976 982 </label> 977 983 ) : null} 978 984
+9 -6
components/public-form-runner.tsx
··· 22 22 import { Button, buttonVariants } from "@/components/ui/button"; 23 23 import { Card } from "@/components/ui/card"; 24 24 import { DatePickerInput } from "@/components/ui/date-picker-input"; 25 + import { AuthoredMarkdown } from "@/components/ui/authored-markdown"; 25 26 import { Input } from "@/components/ui/input"; 26 27 import { ToastViewport, type ToastData } from "@/components/ui/toast"; 27 28 import { Textarea } from "@/components/ui/textarea"; ··· 572 573 <h2 className="font-display text-3xl leading-tight text-[var(--ink)] sm:text-4xl"> 573 574 {currentBlock.title || t("publicRunner.defaultTextTitle")} 574 575 </h2> 575 - <p className="mt-4 whitespace-pre-wrap text-base leading-7 text-[var(--ink)]/82"> 576 - {(currentBlock.config as TextBlockConfig).body} 577 - </p> 576 + <AuthoredMarkdown 577 + content={(currentBlock.config as TextBlockConfig).body} 578 + className="mt-4 text-base leading-7 text-[var(--ink)]/82" 579 + /> 578 580 </div> 579 581 ) : ( 580 582 <div className="flex min-h-[240px] flex-col justify-center py-2"> ··· 590 592 {currentBlock.title} 591 593 </h2> 592 594 {currentBlock.description ? ( 593 - <p className="mt-3 text-base leading-7 text-[var(--muted)]"> 594 - {currentBlock.description} 595 - </p> 595 + <AuthoredMarkdown 596 + content={currentBlock.description} 597 + className="mt-3 text-base leading-7 text-[var(--muted)]" 598 + /> 596 599 ) : null} 597 600 598 601 <div className="mt-6 space-y-3">
+64
components/ui/authored-markdown.test.tsx
··· 1 + import { describe, expect, test } from "bun:test"; 2 + import { renderToStaticMarkup } from "react-dom/server"; 3 + 4 + import { 5 + AuthoredMarkdown, 6 + isSafeMarkdownHref, 7 + } from "@/components/ui/authored-markdown"; 8 + 9 + describe("AuthoredMarkdown", () => { 10 + test("renders the supported markdown subset", () => { 11 + const markup = renderToStaticMarkup( 12 + <AuthoredMarkdown 13 + content={ 14 + "_italic_ **bold** ~~crossed out~~ `code`\n\n[ok](https://example.com)\n\n## Heading\n\n- first\n- second" 15 + } 16 + />, 17 + ); 18 + 19 + expect(markup).toContain("<em"); 20 + expect(markup).toContain("<strong"); 21 + expect(markup).toContain("<del"); 22 + expect(markup).toContain("<code"); 23 + expect(markup).toContain('href="https://example.com"'); 24 + expect(markup).toContain("<h2"); 25 + expect(markup).toContain("<ul"); 26 + expect(markup).toContain("<li"); 27 + }); 28 + 29 + test("keeps plain text content readable", () => { 30 + const markup = renderToStaticMarkup( 31 + <AuthoredMarkdown content={"Plain text still works."} />, 32 + ); 33 + 34 + expect(markup).toContain("Plain text still works."); 35 + }); 36 + 37 + test("does not render unsafe links as anchors", () => { 38 + const markup = renderToStaticMarkup( 39 + <AuthoredMarkdown content={"[bad](javascript:alert(1))"} />, 40 + ); 41 + 42 + expect(markup).not.toContain("<a"); 43 + expect(markup).toContain("<span>bad</span>"); 44 + }); 45 + 46 + test("does not render raw html as active markup", () => { 47 + const markup = renderToStaticMarkup( 48 + <AuthoredMarkdown content={"<script>alert(1)</script>"} />, 49 + ); 50 + 51 + expect(markup).not.toContain("<script>"); 52 + expect(markup).toContain("&lt;script&gt;alert(1)&lt;/script&gt;"); 53 + }); 54 + }); 55 + 56 + describe("isSafeMarkdownHref", () => { 57 + test("accepts http and https urls only", () => { 58 + expect(isSafeMarkdownHref("https://example.com")).toBe(true); 59 + expect(isSafeMarkdownHref("http://example.com")).toBe(true); 60 + expect(isSafeMarkdownHref("mailto:test@example.com")).toBe(false); 61 + expect(isSafeMarkdownHref("javascript:alert(1)")).toBe(false); 62 + expect(isSafeMarkdownHref("/relative")).toBe(false); 63 + }); 64 + });
+230
components/ui/authored-markdown.tsx
··· 1 + import type { ComponentPropsWithoutRef, JSX } from "react"; 2 + import ReactMarkdown from "react-markdown"; 3 + import remarkGfm from "remark-gfm"; 4 + 5 + import { cn } from "@/lib/utils"; 6 + 7 + const allowedElements = [ 8 + "p", 9 + "em", 10 + "strong", 11 + "del", 12 + "code", 13 + "a", 14 + "ul", 15 + "ol", 16 + "li", 17 + "h1", 18 + "h2", 19 + "h3", 20 + "h4", 21 + "h5", 22 + "h6", 23 + "br", 24 + ] as const; 25 + 26 + export function isSafeMarkdownHref(href: string | null | undefined) { 27 + if (!href) { 28 + return false; 29 + } 30 + 31 + try { 32 + const url = new URL(href); 33 + return url.protocol === "http:" || url.protocol === "https:"; 34 + } catch { 35 + return false; 36 + } 37 + } 38 + 39 + type AuthoredMarkdownProps = { 40 + content: string; 41 + className?: string; 42 + }; 43 + 44 + type MarkdownComponentProps<Tag extends keyof JSX.IntrinsicElements> = 45 + ComponentPropsWithoutRef<Tag> & { 46 + node?: unknown; 47 + }; 48 + 49 + function MarkdownParagraph({ 50 + className, 51 + node, 52 + ...props 53 + }: MarkdownComponentProps<"p">) { 54 + void node; 55 + 56 + return ( 57 + <p 58 + className={cn( 59 + "whitespace-pre-wrap text-inherit [&:not(:first-child)]:mt-4", 60 + className, 61 + )} 62 + {...props} 63 + /> 64 + ); 65 + } 66 + 67 + function MarkdownHeading({ 68 + className, 69 + node, 70 + ...props 71 + }: MarkdownComponentProps<"h2">) { 72 + void node; 73 + 74 + return ( 75 + <h2 76 + className={cn( 77 + "font-display text-2xl leading-tight text-[var(--ink)] [&:not(:first-child)]:mt-6", 78 + className, 79 + )} 80 + {...props} 81 + /> 82 + ); 83 + } 84 + 85 + function MarkdownList({ 86 + className, 87 + node, 88 + ...props 89 + }: MarkdownComponentProps<"ul">) { 90 + void node; 91 + 92 + return ( 93 + <ul 94 + className={cn( 95 + "ml-5 list-disc space-y-2 text-inherit [&:not(:first-child)]:mt-4", 96 + className, 97 + )} 98 + {...props} 99 + /> 100 + ); 101 + } 102 + 103 + function MarkdownOrderedList({ 104 + className, 105 + node, 106 + ...props 107 + }: MarkdownComponentProps<"ol">) { 108 + void node; 109 + 110 + return ( 111 + <ol 112 + className={cn( 113 + "ml-5 list-decimal space-y-2 text-inherit [&:not(:first-child)]:mt-4", 114 + className, 115 + )} 116 + {...props} 117 + /> 118 + ); 119 + } 120 + 121 + function MarkdownListItem({ 122 + className, 123 + node, 124 + ...props 125 + }: MarkdownComponentProps<"li">) { 126 + void node; 127 + 128 + return <li className={cn("pl-1", className)} {...props} />; 129 + } 130 + 131 + function MarkdownCode({ 132 + className, 133 + node, 134 + ...props 135 + }: MarkdownComponentProps<"code">) { 136 + void node; 137 + 138 + return ( 139 + <code 140 + className={cn( 141 + "rounded bg-[var(--surface-strong)] px-1.5 py-0.5 font-mono text-[0.95em] text-[var(--ink)]", 142 + className, 143 + )} 144 + {...props} 145 + /> 146 + ); 147 + } 148 + 149 + function MarkdownLink({ 150 + href, 151 + className, 152 + children, 153 + node, 154 + ...props 155 + }: MarkdownComponentProps<"a">) { 156 + void node; 157 + 158 + if (!isSafeMarkdownHref(href)) { 159 + return <span className={className}>{children}</span>; 160 + } 161 + 162 + return ( 163 + <a 164 + href={href} 165 + target="_blank" 166 + rel="noreferrer" 167 + className={cn( 168 + "font-medium text-[var(--accent)] underline decoration-current underline-offset-4", 169 + className, 170 + )} 171 + style={{ textDecorationLine: "underline" }} 172 + {...props} 173 + > 174 + {children} 175 + </a> 176 + ); 177 + } 178 + 179 + export function AuthoredMarkdown({ 180 + content, 181 + className, 182 + }: AuthoredMarkdownProps) { 183 + return ( 184 + <div className={cn("break-words text-inherit", className)}> 185 + <ReactMarkdown 186 + remarkPlugins={[remarkGfm]} 187 + allowedElements={[...allowedElements]} 188 + unwrapDisallowed 189 + components={{ 190 + p: MarkdownParagraph, 191 + h1: MarkdownHeading, 192 + h2: MarkdownHeading, 193 + h3: MarkdownHeading, 194 + h4: MarkdownHeading, 195 + h5: MarkdownHeading, 196 + h6: MarkdownHeading, 197 + ul: MarkdownList, 198 + ol: MarkdownOrderedList, 199 + li: MarkdownListItem, 200 + code: MarkdownCode, 201 + a: MarkdownLink, 202 + del: ({ className: nextClassName, node, ...props }) => { 203 + void node; 204 + 205 + return ( 206 + <del className={cn("line-through", nextClassName)} {...props} /> 207 + ); 208 + }, 209 + em: ({ className: nextClassName, node, ...props }) => { 210 + void node; 211 + 212 + return <em className={cn("italic", nextClassName)} {...props} />; 213 + }, 214 + strong: ({ className: nextClassName, node, ...props }) => { 215 + void node; 216 + 217 + return ( 218 + <strong 219 + className={cn("font-semibold", nextClassName)} 220 + {...props} 221 + /> 222 + ); 223 + }, 224 + }} 225 + > 226 + {content} 227 + </ReactMarkdown> 228 + </div> 229 + ); 230 + }
+1
locales/en.yml
··· 161 161 regexValidation: Validate with regex 162 162 regexPattern: Regex pattern 163 163 regexHelp: Use a custom regex to constrain accepted answers for this text question. 164 + markdownHelp: Supports basic Markdown 164 165 checkboxLabel: Checkbox label 165 166 choiceOptions: Choice options 166 167 addOption: Add option
+1
locales/ru.yml
··· 161 161 regexValidation: Проверять регулярным выражением 162 162 regexPattern: Regex-шаблон 163 163 regexHelp: Используйте собственный regex, чтобы ограничить формат ответа в этом текстовом вопросе. 164 + markdownHelp: Поддерживается базовый Markdown 164 165 checkboxLabel: Текст галочки 165 166 choiceOptions: Варианты ответа 166 167 addOption: Добавить вариант
+2
openspec/changes/archive/2026-04-14-support-basic-markdown-in-form-content/.openspec.yaml
··· 1 + schema: spec-driven 2 + created: 2026-04-13
+85
openspec/changes/archive/2026-04-14-support-basic-markdown-in-form-content/design.md
··· 1 + ## Context 2 + 3 + Lively Forms currently stores author-written content such as question descriptions and text block bodies as plain strings and renders them directly in the public runner and creator-facing response review screens. This keeps storage simple, but it prevents authors from adding lightweight structure or emphasis without introducing custom styling or extra blocks. 4 + 5 + This change needs to improve readability while preserving the existing data model and avoiding unsafe HTML rendering. The same authored content appears in multiple UI surfaces, so the rendering approach should be shared rather than duplicated. The requested scope is limited to author-written content only; respondent-submitted free-form answers remain plain text. 6 + 7 + ## Goals / Non-Goals 8 + 9 + **Goals:** 10 + - Support a constrained Markdown subset for question descriptions and text block bodies. 11 + - Render authored Markdown consistently in the public runner and creator response review/detail views. 12 + - Keep existing stored content as plain strings with no schema or content migration requirements. 13 + - Prevent unsafe HTML injection and keep output visually consistent with the current product style. 14 + - Make the supported Markdown surface explicit so authors know what formatting is expected to work. 15 + 16 + **Non-Goals:** 17 + - Rendering Markdown in respondent-submitted short-text or long-text answers. 18 + - Supporting raw HTML, images, tables, blockquotes, or arbitrary Markdown extensions. 19 + - Building a full rich-text editor or live WYSIWYG authoring experience. 20 + - Changing branching, validation, submission storage, or response export behavior. 21 + 22 + ## Decisions 23 + 24 + ### 1. Use a shared Markdown rendering utility for authored content only 25 + A single shared renderer should be introduced for author-written text fields that are intended for display content, specifically question descriptions and text block bodies. This avoids duplicating parsing and styling rules across the public runner and creator review screens. 26 + 27 + **Why:** Consistency and security are easier to maintain when all authored Markdown goes through one rendering path. 28 + 29 + **Alternatives considered:** 30 + - Render Markdown separately in each surface: rejected because it risks inconsistent formatting and repeated sanitization logic. 31 + - Store pre-rendered HTML in the database: rejected because it complicates sanitization, migrations, and future rendering changes. 32 + 33 + ### 2. Support only a small, explicit Markdown subset 34 + The renderer should support emphasis, strong text, inline code, links, unordered/ordered lists, and heading-like sections. Raw HTML must remain disabled. 35 + 36 + **Why:** This matches the requested use cases while keeping author expectations narrow and reducing the chance of broken or surprising rendering. 37 + 38 + **Alternatives considered:** 39 + - Full CommonMark support: rejected because it adds complexity and exposes formatting behaviors the product is not prepared to style or validate well. 40 + - A smaller subset without lists/headings: rejected because basic structure is part of the requested value. 41 + 42 + ### 3. Prefer a safe parser-based implementation over ad hoc regex replacement 43 + Implementation should use a Markdown parser that can disable raw HTML and map only approved elements into styled React output, or an equivalent constrained renderer with the same guarantees. 44 + 45 + **Why:** Lists, nested emphasis, and links are error-prone to parse safely with regex-based replacements. A parser-based approach is more predictable and easier to test. 46 + 47 + **Alternatives considered:** 48 + - Hand-rolled regex conversion: rejected because it is fragile for overlapping syntax and introduces security and maintenance risks. 49 + - Allow raw HTML and sanitize afterward: rejected because the feature does not need HTML and disabling it entirely is safer. 50 + 51 + ### 4. Keep authored content editable as plain text in existing inputs 52 + Creators should continue typing Markdown into the existing description/body fields; this change should not require a new editor control or a storage format change. Small helper copy can document the supported syntax. 53 + 54 + **Why:** The feature is about display capability, not editing workflow redesign. 55 + 56 + **Alternatives considered:** 57 + - Introduce a dedicated Markdown editor or preview panel: rejected for now because it increases scope and UI complexity. 58 + 59 + ### 5. Leave respondent answers as plain text in review surfaces 60 + Submitted short-text and long-text answers should continue to render with plain-text semantics, even when they contain Markdown-like syntax. 61 + 62 + **Why:** This matches the requested scope, avoids ambiguity about author intent versus respondent input, and prevents creators from accidentally treating respondent text as formatted content. 63 + 64 + **Alternatives considered:** 65 + - Render free-form answers as Markdown too: rejected for this change because it expands scope and changes the semantics of stored answers. 66 + 67 + ## Risks / Trade-offs 68 + 69 + - **Risk:** Different surfaces could style the same Markdown differently. → **Mitigation:** Use one shared renderer component or utility with shared element mappings. 70 + - **Risk:** Authors may expect unsupported Markdown features to work. → **Mitigation:** Document the supported subset in builder help text and keep unsupported syntax visible as plain text rather than failing silently. 71 + - **Risk:** Links could be abused with unsafe protocols. → **Mitigation:** Permit only safe `http` and `https` URLs and render invalid links as plain text. 72 + - **Risk:** Heading support could visually overpower current layouts. → **Mitigation:** Map section-style headings to restrained typography that fits existing runner and review surfaces. 73 + - **Risk:** A new dependency could add bundle size. → **Mitigation:** Keep the implementation narrowly scoped and reuse it only where authored Markdown is needed. 74 + 75 + ## Migration Plan 76 + 77 + - No data migration is required because authored content remains stored in the existing string fields. 78 + - Deploy the shared renderer and update the relevant UI surfaces to use it. 79 + - Add or update tests covering supported syntax, unsupported syntax, and link safety. 80 + - If rollback is needed, switch the affected surfaces back to plain text rendering; stored content remains compatible. 81 + 82 + ## Open Questions 83 + 84 + - Whether builder inputs should include inline helper text only or also a lightweight preview in a later change. 85 + - Whether section-style headings should support only one or two heading levels for tighter visual consistency.
+27
openspec/changes/archive/2026-04-14-support-basic-markdown-in-form-content/proposal.md
··· 1 + ## Why 2 + 3 + Form authors currently have only plain text for question descriptions and text blocks, which makes it hard to add light emphasis, inline code, links, and readable structure without over-designing the UI. Adding a small, well-defined Markdown subset improves clarity for respondents while keeping authored content safe, simple, and predictable. 4 + 5 + ## What Changes 6 + 7 + - Add support for a basic Markdown subset in author-written form content, specifically question descriptions and text block bodies. 8 + - Render the supported Markdown consistently in the public runner and creator response review surfaces where the same authored content is shown. 9 + - Limit supported formatting to lightweight constructs: italic, bold, inline code, links, lists, and section-style headings. 10 + - Keep respondent-submitted short and long text answers as plain text in review screens for this change. 11 + - Preserve existing plain-text content behavior so forms without Markdown continue to render normally. 12 + 13 + ## Capabilities 14 + 15 + ### New Capabilities 16 + - `markdown-form-content`: Safe rendering rules for basic Markdown in author-written form content. 17 + 18 + ### Modified Capabilities 19 + - `anonymous-form-runner`: Author-written descriptions and text content shown to respondents must render the supported Markdown subset. 20 + - `response-review`: Author-written descriptions and text content shown in creator review views must render the supported Markdown subset consistently. 21 + 22 + ## Impact 23 + 24 + - Affected code: public runner rendering, response review/detail rendering, form builder settings/help text, shared content rendering utilities, validation or sanitization helpers. 25 + - Data model: no new persisted content fields are required because existing description/body fields already store plain strings. 26 + - Dependencies: may require a lightweight Markdown parser/sanitizer or a constrained in-house renderer. 27 + - Security: rendered Markdown must be sanitized and limited to the approved subset to avoid unsafe HTML injection.
+12
openspec/changes/archive/2026-04-14-support-basic-markdown-in-form-content/specs/anonymous-form-runner/spec.md
··· 1 + ## ADDED Requirements 2 + 3 + ### Requirement: Runner renders authored Markdown content consistently 4 + The system SHALL render the supported authored Markdown subset in the public runner wherever question descriptions or text block bodies are shown to respondents. 5 + 6 + #### Scenario: Respondent views a formatted text block 7 + - **WHEN** a published form contains a text block body with supported Markdown 8 + - **THEN** the runner shows the formatted body content instead of displaying the Markdown syntax literally 9 + 10 + #### Scenario: Respondent views a formatted question description 11 + - **WHEN** a published form contains a question description with supported Markdown 12 + - **THEN** the runner shows the formatted description consistently with the shared authored Markdown rules
+30
openspec/changes/archive/2026-04-14-support-basic-markdown-in-form-content/specs/markdown-form-content/spec.md
··· 1 + ## ADDED Requirements 2 + 3 + ### Requirement: Author-written form content supports a safe basic Markdown subset 4 + The system SHALL support a safe basic Markdown subset for author-written form content fields that are intended for display, including question descriptions and text block bodies. The supported subset SHALL include italic text, bold text, inline code, links, unordered and ordered lists, and section-style headings. 5 + 6 + #### Scenario: Author formats a question description with emphasis and code 7 + - **WHEN** a creator saves a question description containing `_italic_`, `**bold**`, or `` `code` `` syntax 8 + - **THEN** the system renders that authored content with the corresponding emphasis styles in supported display surfaces 9 + 10 + #### Scenario: Author formats content with lists and sections 11 + - **WHEN** a creator saves a text block body containing headings or ordered or unordered lists 12 + - **THEN** the system renders those structures as readable sections and lists in supported display surfaces 13 + 14 + ### Requirement: Markdown rendering remains safe and constrained 15 + The system SHALL treat author-written Markdown as constrained formatted content rather than executable HTML. The system SHALL NOT render raw HTML from authored content and SHALL only allow safe links to be rendered as interactive anchors. 16 + 17 + #### Scenario: Author enters raw HTML 18 + - **WHEN** a creator saves author-written content containing raw HTML tags or attributes 19 + - **THEN** the system does not execute or render that HTML as active markup 20 + 21 + #### Scenario: Author enters an unsafe link target 22 + - **WHEN** a creator saves Markdown content containing a link with an unsafe or unsupported target 23 + - **THEN** the system does not render that link as an unsafe interactive anchor 24 + 25 + ### Requirement: Existing plain text content remains compatible 26 + The system SHALL preserve existing plain text content behavior for forms that do not use Markdown syntax and SHALL continue storing authored content in the existing text fields. 27 + 28 + #### Scenario: Form content contains no Markdown syntax 29 + - **WHEN** a creator saves plain text descriptions and text block bodies without Markdown formatting 30 + - **THEN** the system renders the content normally without requiring any content migration or author action
+12
openspec/changes/archive/2026-04-14-support-basic-markdown-in-form-content/specs/response-review/spec.md
··· 1 + ## ADDED Requirements 2 + 3 + ### Requirement: Response review renders authored Markdown context consistently 4 + The system SHALL render the supported authored Markdown subset in creator-facing response review surfaces wherever question descriptions or text block bodies are shown as form context. 5 + 6 + #### Scenario: Creator reviews a response with formatted question context 7 + - **WHEN** an authenticated creator opens a response that includes a question description with supported Markdown 8 + - **THEN** the response review UI shows the formatted description instead of raw Markdown syntax 9 + 10 + #### Scenario: Creator reviews a response with formatted text block context 11 + - **WHEN** an authenticated creator opens a response or question summary that includes a text block body with supported Markdown 12 + - **THEN** the response review UI shows the formatted text block content consistently with the shared authored Markdown rules
+22
openspec/changes/archive/2026-04-14-support-basic-markdown-in-form-content/tasks.md
··· 1 + ## 1. Markdown rendering foundation 2 + 3 + - [x] 1.1 Choose and add the safe Markdown parsing/rendering dependency or shared implementation for the approved subset. 4 + - [x] 1.2 Build a shared authored-content Markdown renderer that disables raw HTML and restricts rendered output to the approved elements. 5 + - [x] 1.3 Add shared link-safety handling so only safe `http` and `https` links render as interactive anchors. 6 + 7 + ## 2. Public and creator surface adoption 8 + 9 + - [x] 2.1 Update the public runner to render question descriptions and text block bodies with the shared authored Markdown renderer. 10 + - [x] 2.2 Update creator response detail and question-centric review surfaces to render authored descriptions and text block bodies with the same renderer. 11 + - [x] 2.3 Keep respondent-submitted short-text and long-text answers rendered as plain text in review surfaces. 12 + 13 + ## 3. Authoring guidance and validation 14 + 15 + - [x] 3.1 Add concise builder help text that explains the supported Markdown subset for author-written descriptions and text content. 16 + - [x] 3.2 Ensure unsupported or unsafe authored content degrades safely without executing HTML or unsafe links. 17 + 18 + ## 4. Verification 19 + 20 + - [x] 4.1 Add or update tests covering supported formatting, plain-text compatibility, and unsafe content handling. 21 + - [x] 4.2 Verify formatted authored content renders consistently in the runner and creator review views. 22 + - [x] 4.3 Run the production build and fix any type, styling, or rendering issues introduced by the change.
+11
openspec/specs/anonymous-form-runner/spec.md
··· 131 131 #### Scenario: Client and server evaluate the same rule set 132 132 - **WHEN** a respondent completes and submits a branched form using supported advanced operators 133 133 - **THEN** the submission validation path accepts or rejects the route using the same branching semantics as the public runner 134 + 135 + ### Requirement: Runner renders authored Markdown content consistently 136 + The system SHALL render the supported authored Markdown subset in the public runner wherever question descriptions or text block bodies are shown to respondents. 137 + 138 + #### Scenario: Respondent views a formatted text block 139 + - **WHEN** a published form contains a text block body with supported Markdown 140 + - **THEN** the runner shows the formatted body content instead of displaying the Markdown syntax literally 141 + 142 + #### Scenario: Respondent views a formatted question description 143 + - **WHEN** a published form contains a question description with supported Markdown 144 + - **THEN** the runner shows the formatted description consistently with the shared authored Markdown rules
+30
openspec/specs/markdown-form-content/spec.md
··· 1 + ## ADDED Requirements 2 + 3 + ### Requirement: Author-written form content supports a safe basic Markdown subset 4 + The system SHALL support a safe basic Markdown subset for author-written form content fields that are intended for display, including question descriptions and text block bodies. The supported subset SHALL include italic text, bold text, inline code, links, unordered and ordered lists, and section-style headings. 5 + 6 + #### Scenario: Author formats a question description with emphasis and code 7 + - **WHEN** a creator saves a question description containing `_italic_`, `**bold**`, or `` `code` `` syntax 8 + - **THEN** the system renders that authored content with the corresponding emphasis styles in supported display surfaces 9 + 10 + #### Scenario: Author formats content with lists and sections 11 + - **WHEN** a creator saves a text block body containing headings or ordered or unordered lists 12 + - **THEN** the system renders those structures as readable sections and lists in supported display surfaces 13 + 14 + ### Requirement: Markdown rendering remains safe and constrained 15 + The system SHALL treat author-written Markdown as constrained formatted content rather than executable HTML. The system SHALL NOT render raw HTML from authored content and SHALL only allow safe links to be rendered as interactive anchors. 16 + 17 + #### Scenario: Author enters raw HTML 18 + - **WHEN** a creator saves author-written content containing raw HTML tags or attributes 19 + - **THEN** the system does not execute or render that HTML as active markup 20 + 21 + #### Scenario: Author enters an unsafe link target 22 + - **WHEN** a creator saves Markdown content containing a link with an unsafe or unsupported target 23 + - **THEN** the system does not render that link as an unsafe interactive anchor 24 + 25 + ### Requirement: Existing plain text content remains compatible 26 + The system SHALL preserve existing plain text content behavior for forms that do not use Markdown syntax and SHALL continue storing authored content in the existing text fields. 27 + 28 + #### Scenario: Form content contains no Markdown syntax 29 + - **WHEN** a creator saves plain text descriptions and text block bodies without Markdown formatting 30 + - **THEN** the system renders the content normally without requiring any content migration or author action
+11
openspec/specs/response-review/spec.md
··· 84 84 - **WHEN** an authenticated creator views a question that has no answers yet 85 85 - **THEN** the system shows an empty summary state for that question instead of failing or hiding the block 86 86 87 + ### Requirement: Response review renders authored Markdown context consistently 88 + The system SHALL render the supported authored Markdown subset in creator-facing response review surfaces wherever question descriptions or text block bodies are shown as form context. 89 + 90 + #### Scenario: Creator reviews a response with formatted question context 91 + - **WHEN** an authenticated creator opens a response that includes a question description with supported Markdown 92 + - **THEN** the response review UI shows the formatted description instead of raw Markdown syntax 93 + 94 + #### Scenario: Creator reviews a response with formatted text block context 95 + - **WHEN** an authenticated creator opens a response or question summary that includes a text block body with supported Markdown 96 + - **THEN** the response review UI shows the formatted text block content consistently with the shared authored Markdown rules 97 +
+3
package.json
··· 17 17 "dev": "next dev", 18 18 "build": "node scripts/validate-translations.mjs && next build", 19 19 "start": "next start", 20 + "test": "bun test", 20 21 "lint": "eslint . --max-warnings=0", 21 22 "typecheck": "tsc --noEmit", 22 23 "format": "prettier --write .", ··· 64 65 "react": "19.2.5", 65 66 "react-day-picker": "9.14.0", 66 67 "react-dom": "19.2.5", 68 + "react-markdown": "^10.1.0", 69 + "remark-gfm": "^4.0.1", 67 70 "tailwind-merge": "3.5.0", 68 71 "xlsx": "0.18.5", 69 72 "yaml": "2.8.3",
+1
tsconfig.json
··· 26 26 "next-env.d.ts", 27 27 "**/*.ts", 28 28 "**/*.tsx", 29 + "**/*.d.ts", 29 30 ".next/types/**/*.ts", 30 31 ".next/dev/types/**/*.ts", 31 32 "**/*.mts"
+13
types/bun-test.d.ts
··· 1 + declare module "bun:test" { 2 + type Matcher = { 3 + toContain: (value: unknown) => void; 4 + toBe: (value: unknown) => void; 5 + not: { 6 + toContain: (value: unknown) => void; 7 + }; 8 + }; 9 + 10 + export function describe(name: string, fn: () => void): void; 11 + export function test(name: string, fn: () => void): void; 12 + export function expect(value: unknown): Matcher; 13 + }