From 08a54f0d8faaa24c861c2fe6013c4b66e63dfa6e Mon Sep 17 00:00:00 2001 From: reiji-h Date: Wed, 19 Jun 2024 08:06:02 +0000 Subject: [PATCH 001/490] upgrade unified --- apps/app/package.json | 28 +- packages/presentation/package.json | 24 +- .../src/client/components/GrowiSlides.tsx | 2 +- packages/remark-attachment-refs/package.json | 8 +- packages/remark-drawio/package.json | 6 +- packages/remark-growi-directive/package.json | 22 +- packages/remark-lsx/package.json | 8 +- yarn.lock | 1764 +++++++++-------- 8 files changed, 1014 insertions(+), 848 deletions(-) diff --git a/apps/app/package.json b/apps/app/package.json index 6704d61801e..d4216d87646 100644 --- a/apps/app/package.json +++ b/apps/app/package.json @@ -120,7 +120,7 @@ "extensible-custom-error": "^0.0.7", "form-data": "^4.0.0", "graceful-fs": "^4.1.11", - "hast-util-select": "^5.0.5", + "hast-util-select": "^6.0.2", "helmet": "^4.6.0", "http-errors": "^2.0.0", "i18next": "^23.10.1", @@ -169,7 +169,7 @@ "react-error-boundary": "^3.1.4", "react-i18next": "^14.1.0", "react-image-crop": "^8.3.0", - "react-markdown": "^8.0.7", + "react-markdown": "^9.0.1", "react-multiline-clamp": "^2.0.0", "react-scroll": "^1.8.7", "react-stickynode": "^4.1.1", @@ -178,18 +178,18 @@ "reactstrap": "^9.2.2", "reconnecting-websocket": "^4.4.0", "redis": "^3.0.2", - "rehype-katex": "^6.0.2", - "rehype-raw": "^6.1.1", - "rehype-sanitize": "^5.0.1", - "rehype-slug": "^5.0.1", + "rehype-katex": "^7.0.0", + "rehype-raw": "^7.0.0", + "rehype-sanitize": "^6.0.0", + "rehype-slug": "^6.0.0", "rehype-toc": "^3.0.2", - "remark-breaks": "^3.0.2", - "remark-emoji": "^3.0.2", - "remark-frontmatter": "^4.0.1", - "remark-gfm": "^3.0.1", - "remark-math": "^5.1.1", - "remark-toc": "^8.0.1", - "remark-wiki-link": "^1.0.4", + "remark-breaks": "^4.0.0", + "remark-emoji": "^5.0.0", + "remark-frontmatter": "^5.0.0", + "remark-gfm": "^4.0.0", + "remark-math": "^6.0.0", + "remark-toc": "^9.0.0", + "remark-wiki-link": "^2.0.1", "sanitize-filename": "^1.6.3", "socket.io": "^4.7.5", "stream-to-promise": "^3.0.0", @@ -275,7 +275,7 @@ "react-hotkeys": "^2.0.0", "react-input-autosize": "^3.0.0", "react-toastify": "^9.1.3", - "rehype-rewrite": "^3.0.6", + "rehype-rewrite": "^4.0.2", "replacestream": "^4.0.3", "sass": "^1.53.0", "simple-load-script": "^1.0.2", diff --git a/packages/presentation/package.json b/packages/presentation/package.json index 20c89860346..24fe78f9622 100644 --- a/packages/presentation/package.json +++ b/packages/presentation/package.json @@ -43,19 +43,19 @@ "@marp-team/marpit": "^2.6.1", "@types/reveal.js": "^4.4.1", "eslint-plugin-regex": "^1.8.0", - "hast-util-sanitize": "^4.1.0", - "hast-util-select": "^5.0.5", - "mdast-util-frontmatter": "^1.0.0", - "mdast-util-gfm": "^2.0.1", - "mdast-util-to-markdown": "^1.3.0", - "react-markdown": "^8.0.7", - "remark-frontmatter": "^4.0.1", - "remark-parse": "^10.0.0", - "remark-stringify": "^10.0.0", + "hast-util-sanitize": "^5.0.1", + "hast-util-select": "^6.0.2", + "mdast-util-frontmatter": "^2.0.1", + "mdast-util-gfm": "^3.0.0", + "mdast-util-to-markdown": "^2.1.0", + "react-markdown": "^9.0.1", + "remark-frontmatter": "^5.0.0", + "remark-parse": "^11.0.0", + "remark-stringify": "^11.0.0", "reveal.js": "^4.4.0", - "unified": "^10.1.2", - "unist-util-find-after": "^4.0.0", - "unist-util-visit": "^4.0.0" + "unified": "^11.0.0", + "unist-util-find-after": "^5.0.0", + "unist-util-visit": "^5.0.0" }, "peerDependencies": { "next": "^14", diff --git a/packages/presentation/src/client/components/GrowiSlides.tsx b/packages/presentation/src/client/components/GrowiSlides.tsx index 71c79aef650..2e6fcfe768a 100644 --- a/packages/presentation/src/client/components/GrowiSlides.tsx +++ b/packages/presentation/src/client/components/GrowiSlides.tsx @@ -1,5 +1,5 @@ import Head from 'next/head'; -import { ReactMarkdown } from 'react-markdown/lib/react-markdown'; +import ReactMarkdown from 'react-markdown'; import type { PresentationOptions } from '../consts'; import { MARP_CONTAINER_CLASS_NAME, presentationMarpit, slideMarpit } from '../services/growi-marpit'; diff --git a/packages/remark-attachment-refs/package.json b/packages/remark-attachment-refs/package.json index 6e2540ac6fe..bc16ee25a82 100644 --- a/packages/remark-attachment-refs/package.json +++ b/packages/remark-attachment-refs/package.json @@ -49,7 +49,7 @@ "@growi/ui": "link:../ui", "axios": "^0.24.0", "bunyan": "^1.8.15", - "hast-util-select": "^5.0.5", + "hast-util-select": "^6.0.2", "mongoose": "^6.11.3", "swr": "^2.0.3", "universal-bunyan": "^0.9.2" @@ -57,11 +57,11 @@ "devDependencies": { "csstype": "^3.0.2", "eslint-plugin-regex": "^1.8.0", - "hast-util-sanitize": "^4.1.0", + "hast-util-sanitize": "^5.0.1", "hast-util-select": "^5.0.5", "npm-run-all": "^4.1.5", - "unified": "^10.1.2", - "unist-util-visit": "^4.0.0" + "unified": "^11.0.0", + "unist-util-visit": "^5.0.0" }, "peerDependencies": { "react": "^18.2.0", diff --git a/packages/remark-drawio/package.json b/packages/remark-drawio/package.json index 4fb96b6754b..370dc414da2 100644 --- a/packages/remark-drawio/package.json +++ b/packages/remark-drawio/package.json @@ -33,11 +33,11 @@ "dependencies": {}, "devDependencies": { "eslint-plugin-regex": "^1.8.0", - "hast-util-sanitize": "^4.1.0", + "hast-util-sanitize": "^5.0.1", "pako": "^2.1.0", "throttle-debounce": "^5.0.0", - "unified": "^10.1.2", - "unist-util-visit": "^4.0.0" + "unified": "^11.0.0", + "unist-util-visit": "^5.0.0" }, "peerDependencies": { "react": "^18.2.0", diff --git a/packages/remark-growi-directive/package.json b/packages/remark-growi-directive/package.json index 5c2a20ec845..cb7be01a87c 100644 --- a/packages/remark-growi-directive/package.json +++ b/packages/remark-growi-directive/package.json @@ -30,15 +30,15 @@ "dependencies": { "@types/mdast": "^3.0.0", "@types/unist": "^2.0.0", - "mdast-util-to-markdown": "^1.3.0", - "micromark-factory-space": "^1.0.0", - "micromark-factory-whitespace": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", + "mdast-util-to-markdown": "^2.1.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.1.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", "parse-entities": "^4.0.0", "stringify-entities": "^4.0.0", - "unified": "^10.0.0", + "unified": "^11.0.0", "unist-util-visit-parents": "^5.0.0", "uvu": "^0.5.0" }, @@ -47,14 +47,14 @@ "c8": "^7.0.0", "html-void-elements": "^2.0.0", "is-hidden": "^2.0.0", - "mdast-util-from-markdown": "^1.0.0", - "micromark": "^3.0.0", - "remark": "^14.0.0", + "mdast-util-from-markdown": "^2.0.1", + "micromark": "^4.0.0", + "remark": "^15.0.1", "rimraf": "^3.0.0", "tape": "^5.0.0", "to-vfile": "^7.0.0", "type-coverage": "^2.0.0", - "unist-util-remove-position": "^4.0.0" + "unist-util-remove-position": "^5.0.0" }, "typeCoverage": { "atLeast": 100, diff --git a/packages/remark-lsx/package.json b/packages/remark-lsx/package.json index 88b7af30a04..0c05c0eb73d 100644 --- a/packages/remark-lsx/package.json +++ b/packages/remark-lsx/package.json @@ -44,10 +44,10 @@ }, "devDependencies": { "eslint-plugin-regex": "^1.8.0", - "hast-util-sanitize": "^4.1.0", - "hast-util-select": "^5.0.5", - "unified": "^10.1.2", - "unist-util-visit": "^4.0.0" + "hast-util-sanitize": "^5.0.1", + "hast-util-select": "^6.0.2", + "unified": "^11.0.0", + "unist-util-visit": "^5.0.0" }, "peerDependencies": { "next": "^14", diff --git a/yarn.lock b/yarn.lock index 30163306a8f..72e357db1e3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2160,7 +2160,7 @@ "@growi/ui" "link:packages/ui" axios "^0.24.0" bunyan "^1.8.15" - hast-util-select "^5.0.5" + hast-util-select "^6.0.2" mongoose "^6.11.3" swr "^2.0.3" universal-bunyan "^0.9.2" @@ -2173,15 +2173,15 @@ dependencies: "@types/mdast" "^3.0.0" "@types/unist" "^2.0.0" - mdast-util-to-markdown "^1.3.0" - micromark-factory-space "^1.0.0" - micromark-factory-whitespace "^1.0.0" - micromark-util-character "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" + mdast-util-to-markdown "^2.1.0" + micromark-factory-space "^2.0.0" + micromark-factory-whitespace "^2.0.0" + micromark-util-character "^2.1.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" parse-entities "^4.0.0" stringify-entities "^4.0.0" - unified "^10.0.0" + unified "^11.0.0" unist-util-visit-parents "^5.0.0" uvu "^0.5.0" @@ -3305,6 +3305,11 @@ resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== +"@sindresorhus/is@^4.6.0": + version "4.6.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.6.0.tgz#3c7c9c46e678feefe7a2e5bb609d3dbd665ffb3f" + integrity sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw== + "@sinonjs/commons@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.0.tgz#beb434fe875d965265e04722ccfc21df7f755d72" @@ -4281,9 +4286,9 @@ integrity sha512-tyqlt2GtEBdsxJylh78zSxI/kOJK5Iz8Ta4Fxr8KLTP8mD/IgMa84D8EKPS/AWCp+MDoctgJyikrVWY28GKmcg== "@types/debug@^4.0.0": - version "4.1.7" - resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.7.tgz#7cc0ea761509124709b8b2d1090d8f6c17aadb82" - integrity sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg== + version "4.1.12" + resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.12.tgz#a155f21690871953410df4b6b6f53187f0500917" + integrity sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ== dependencies: "@types/ms" "*" @@ -4300,6 +4305,13 @@ "@types/estree" "*" "@types/json-schema" "*" +"@types/estree-jsx@^1.0.0": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@types/estree-jsx/-/estree-jsx-1.0.5.tgz#858a88ea20f34fe65111f005a689fa1ebf70dc18" + integrity sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg== + dependencies: + "@types/estree" "*" + "@types/estree@*", "@types/estree@1.0.5", "@types/estree@^1.0.0", "@types/estree@^1.0.1": version "1.0.5" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" @@ -4324,11 +4336,6 @@ "@types/qs" "*" "@types/serve-static" "*" -"@types/extend@^3.0.0": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@types/extend/-/extend-3.0.1.tgz#923dc2d707d944382433e01d6cc0c69030ab2c75" - integrity sha512-R1g/VyKFFI2HLC1QGAeTtCBWCo6n75l41OnsVYNbmKG+kempOESaodf6BeJyUM3Q0rKa/NQcTHbB2+66lNnxLw== - "@types/fs-extra@^11.0.1": version "11.0.4" resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-11.0.4.tgz#e16a863bb8843fba8c5004362b5a73e17becca45" @@ -4337,11 +4344,6 @@ "@types/jsonfile" "*" "@types/node" "*" -"@types/github-slugger@^1.0.0": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@types/github-slugger/-/github-slugger-1.3.0.tgz#16ab393b30d8ae2a111ac748a015ac05a1fc5524" - integrity sha512-J/rMZa7RqiH/rT29TEVZO4nBoDP9XJOjnbbIofg7GQKs4JIduEO3WLpte+6WeUz/TcrXKlY+bM7FYrp8yFB+3g== - "@types/glob@^7.1.3": version "7.2.0" resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.2.0.tgz#bc1b5bf3aa92f25bd5dd39f35c57361bdce5b2eb" @@ -4364,6 +4366,13 @@ dependencies: "@types/unist" "*" +"@types/hast@^3.0.0": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/hast/-/hast-3.0.4.tgz#1d6b39993b82cea6ad783945b0508c25903e15aa" + integrity sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ== + dependencies: + "@types/unist" "*" + "@types/hoist-non-react-statics@^3.3.4": version "3.3.5" resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.5.tgz#dab7867ef789d87e2b4b0003c9d65c49cc44a494" @@ -4440,10 +4449,10 @@ dependencies: "@types/node" "*" -"@types/katex@^0.11.0": - version "0.11.1" - resolved "https://registry.yarnpkg.com/@types/katex/-/katex-0.11.1.tgz#34de04477dcf79e2ef6c8d23b41a3d81f9ebeaf5" - integrity sha512-DUlIj2nk0YnJdlWgsFuVKcX27MLW0KbKmGVoUHmFr+74FYYNUDAaj9ZqTADvsbE8rfxuVmSFc7KczYn5Y09ozg== +"@types/katex@^0.16.0": + version "0.16.7" + resolved "https://registry.yarnpkg.com/@types/katex/-/katex-0.16.7.tgz#03ab680ab4fa4fbc6cb46ecf987ecad5d8019868" + integrity sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ== "@types/ldapjs@^1.0.9": version "1.0.11" @@ -4471,6 +4480,13 @@ dependencies: "@types/unist" "*" +"@types/mdast@^4.0.0", "@types/mdast@^4.0.4": + version "4.0.4" + resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-4.0.4.tgz#7ccf72edd2f1aa7dd3437e180c64373585804dd6" + integrity sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA== + dependencies: + "@types/unist" "*" + "@types/mime-types@^2.1.0": version "2.1.1" resolved "https://registry.yarnpkg.com/@types/mime-types/-/mime-types-2.1.1.tgz#d9ba43490fa3a3df958759adf69396c3532cf2c1" @@ -4499,9 +4515,9 @@ "@types/node" "*" "@types/ms@*": - version "0.7.31" - resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.31.tgz#31b7ca6407128a3d2bbc27fe2d21b345397f6197" - integrity sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA== + version "0.7.34" + resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.34.tgz#10964ba0dee6ac4cd462e2795b6bebd407303433" + integrity sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g== "@types/node-fetch@^2.5.0": version "2.6.8" @@ -4538,11 +4554,6 @@ resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e" integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA== -"@types/parse5@^6.0.0": - version "6.0.3" - resolved "https://registry.yarnpkg.com/@types/parse5/-/parse5-6.0.3.tgz#705bb349e789efa06f43f128cef51240753424cb" - integrity sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g== - "@types/path-browserify@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@types/path-browserify/-/path-browserify-1.0.0.tgz#294ec6e88b6b0d340a3897b7120e5b393f16690e" @@ -4567,7 +4578,7 @@ resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.3.2.tgz#fc8c2825e4ed2142473b4a81064e6e081463d1b3" integrity sha512-eI5Yrz3Qv4KPUa/nSIAi0h+qX0XyewOliug5F2QAtuRg6Kjg6jfmxe1GIwoIRhZspD1A0RP8ANrPwvEXXtRFog== -"@types/prop-types@*", "@types/prop-types@^15.0.0": +"@types/prop-types@*": version "15.7.5" resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf" integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w== @@ -4714,10 +4725,20 @@ dependencies: "@types/node" "*" -"@types/unist@*", "@types/unist@^2.0.0": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.3.tgz#9c088679876f374eb5983f150d4787aa6fb32d7e" - integrity sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ== +"@types/ungap__structured-clone@^1.0.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@types/ungap__structured-clone/-/ungap__structured-clone-1.2.0.tgz#12b9fd4ab3e6a82292d60048492b05eb75b4a48f" + integrity sha512-ZoaihZNLeZSxESbk9PUAPZOlSpcKx81I1+4emtULDVmBLkYutTcMlCj2K9VNlf9EWODxdO6gkAqEaLorXwZQVA== + +"@types/unist@*", "@types/unist@^3.0.0": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@types/unist/-/unist-3.0.2.tgz#6dd61e43ef60b34086287f83683a5c1b2dc53d20" + integrity sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ== + +"@types/unist@^2.0.0": + version "2.0.10" + resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.10.tgz#04ffa7f406ab628f7f7e97ca23e290cd8ab15efc" + integrity sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA== "@types/unzip-stream@^0.3.4": version "0.3.4" @@ -4912,6 +4933,11 @@ "@uiw/codemirror-extensions-basic-setup" "4.21.8" codemirror "^6.0.0" +"@ungap/structured-clone@^1.0.0", "@ungap/structured-clone@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" + integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== + "@vitejs/plugin-react@^4.0.3", "@vitejs/plugin-react@^4.3.0": version "4.3.0" resolved "https://registry.yarnpkg.com/@vitejs/plugin-react/-/plugin-react-4.3.0.tgz#f20ec2369a92d8abaaefa60da8b7157819d20481" @@ -6729,9 +6755,9 @@ comma-separated-tokens@^1.0.0: integrity sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw== comma-separated-tokens@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-2.0.2.tgz#d4c25abb679b7751c880be623c1179780fe1dd98" - integrity sha512-G5yTt3KQN4Yn7Yk4ed73hlZ1evrFKXeUW3086p3PRFNp7m2vIjI6Pg+Kgb+oyzhd9F2qdcoj67+y3SdxL5XWsg== + version "2.0.3" + resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz#4e89c9458acb61bc8fef19f4529973b2392839ee" + integrity sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg== commander@6.2.0: version "6.2.0" @@ -6763,7 +6789,7 @@ commander@^6.2.1: resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c" integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA== -commander@^8.0.0, commander@^8.3.0: +commander@^8.3.0: version "8.3.0" resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== @@ -7172,10 +7198,10 @@ css-select@^5.1.0: domutils "^3.0.1" nth-check "^2.0.1" -css-selector-parser@^1.0.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/css-selector-parser/-/css-selector-parser-1.4.1.tgz#03f9cb8a81c3e5ab2c51684557d5aaf6d2569759" - integrity sha512-HYPSb7y/Z7BNDCOrakL4raGO2zltZkbeXyAd6Tg9obzix6QhzxCotdBl6VT0Dv4vZfJGVz3WL/xaEI9Ly3ul0g== +css-selector-parser@^3.0.0: + version "3.0.5" + resolved "https://registry.yarnpkg.com/css-selector-parser/-/css-selector-parser-3.0.5.tgz#9b636ebccf7c4bcce5c1ac21ae27de9f01180ae9" + integrity sha512-3itoDFbKUNx1eKmVpYMFyqKX04Ww9osZ+dLgrk6GEv6KMVeXUhUnp4I5X+evw+u3ZxVU6RFXSSRxlTeMh8bA+g== css-tree@^2.2.1, css-tree@^2.3.1: version "2.3.1" @@ -7947,6 +7973,13 @@ detect-newline@^3.0.0: resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== +devlop@^1.0.0, devlop@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/devlop/-/devlop-1.1.0.tgz#4db7c2ca4dc6e0e834c30be70c94bbc976dc7018" + integrity sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA== + dependencies: + dequal "^2.0.0" + dezalgo@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.3.tgz#7f742de066fc748bc8db820569dddce49bf0d456" @@ -8224,12 +8257,17 @@ emoji-regex@^9.2.2: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== +emojilib@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/emojilib/-/emojilib-2.4.0.tgz#ac518a8bb0d5f76dda57289ccb2fdf9d39ae721e" + integrity sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw== + emojis-list@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== -emoticon@^4.0.0: +emoticon@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/emoticon/-/emoticon-4.0.1.tgz#2d2bbbf231ce3a5909e185bbb64a9da703a1e749" integrity sha512-dqx7eA9YaqyvYtUhJwT4rC1HIp82j5ybS1/vQ42ur+jBe17dJMwZE4+gvL1XadSFfxaPFFGt3Xsw+Y8akThDlw== @@ -8828,6 +8866,11 @@ estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== +estree-util-is-identifier-name@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz#0b5ef4c4ff13508b34dcd01ecfa945f61fce5dbd" + integrity sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg== + estree-walker@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" @@ -9712,10 +9755,10 @@ getpass@^0.1.1: dependencies: assert-plus "^1.0.0" -github-slugger@^1.0.0, github-slugger@^1.1.1: - version "1.4.0" - resolved "https://registry.yarnpkg.com/github-slugger/-/github-slugger-1.4.0.tgz#206eb96cdb22ee56fdc53a28d5a302338463444e" - integrity sha512-w0dzqw/nt51xMVmlaV1+JRzN+oCa1KfcgGEWhxUG16wbdA+Xnt/yoFO8Z8x/V82ZcZ0wy6ln9QDup5avbhiDhQ== +github-slugger@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/github-slugger/-/github-slugger-2.0.0.tgz#52cf2f9279a21eb6c59dd385b410f0c0adda8f1a" + integrity sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw== glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" @@ -10112,142 +10155,191 @@ hasown@^2.0.0, hasown@^2.0.1, hasown@^2.0.2: dependencies: function-bind "^1.1.2" -hast-to-hyperscript@^10.0.0: - version "10.0.1" - resolved "https://registry.yarnpkg.com/hast-to-hyperscript/-/hast-to-hyperscript-10.0.1.tgz#3decd7cb4654bca8883f6fcbd4fb3695628c4296" - integrity sha512-dhIVGoKCQVewFi+vz3Vt567E4ejMppS1haBRL6TEmeLeJVB1i/FJIIg/e6s1Bwn0g5qtYojHEKvyGA+OZuyifw== +hast-util-from-dom@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/hast-util-from-dom/-/hast-util-from-dom-5.0.0.tgz#d32edd25bf28f4b178b5ae318f8d05762e67bd16" + integrity sha512-d6235voAp/XR3Hh5uy7aGLbM3S4KamdW0WEgOaU1YoewnuYw4HXb5eRtv9g65m/RFGEfUY1Mw4UqCc5Y8L4Stg== dependencies: - "@types/unist" "^2.0.0" - comma-separated-tokens "^2.0.0" - property-information "^6.0.0" - space-separated-tokens "^2.0.0" - style-to-object "^0.3.0" - unist-util-is "^5.0.0" + "@types/hast" "^3.0.0" + hastscript "^8.0.0" web-namespaces "^2.0.0" -hast-util-from-parse5@^7.0.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/hast-util-from-parse5/-/hast-util-from-parse5-7.1.0.tgz#c129dd3a24dd8a867ab8a029ca47e27aa54864b7" - integrity sha512-m8yhANIAccpU4K6+121KpPP55sSl9/samzQSQGpb0mTExcNh2WlvjtMwSWFhg6uqD4Rr6Nfa8N6TMypQM51rzQ== +hast-util-from-html-isomorphic@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/hast-util-from-html-isomorphic/-/hast-util-from-html-isomorphic-2.0.0.tgz#b31baee386a899a2472326a3c5692f29f86d1d3c" + integrity sha512-zJfpXq44yff2hmE0XmwEOzdWin5xwH+QIhMLOScpX91e/NSGPsAzNCvLQDIEPyO2TXi+lBmU6hjLIhV8MwP2kw== dependencies: - "@types/hast" "^2.0.0" - "@types/parse5" "^6.0.0" - "@types/unist" "^2.0.0" - hastscript "^7.0.0" + "@types/hast" "^3.0.0" + hast-util-from-dom "^5.0.0" + hast-util-from-html "^2.0.0" + unist-util-remove-position "^5.0.0" + +hast-util-from-html@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/hast-util-from-html/-/hast-util-from-html-2.0.1.tgz#9cd38ee81bf40b2607368b92a04b0905fa987488" + integrity sha512-RXQBLMl9kjKVNkJTIO6bZyb2n+cUH8LFaSSzo82jiLT6Tfc+Pt7VQCS+/h3YwG4jaNE2TA2sdJisGWR+aJrp0g== + dependencies: + "@types/hast" "^3.0.0" + devlop "^1.1.0" + hast-util-from-parse5 "^8.0.0" + parse5 "^7.0.0" + vfile "^6.0.0" + vfile-message "^4.0.0" + +hast-util-from-parse5@^8.0.0: + version "8.0.1" + resolved "https://registry.yarnpkg.com/hast-util-from-parse5/-/hast-util-from-parse5-8.0.1.tgz#654a5676a41211e14ee80d1b1758c399a0327651" + integrity sha512-Er/Iixbc7IEa7r/XLtuG52zoqn/b3Xng/w6aZQ0xGVxzhw5xUFxcRqdPzP6yFi/4HBYRaifaI5fQ1RH8n0ZeOQ== + dependencies: + "@types/hast" "^3.0.0" + "@types/unist" "^3.0.0" + devlop "^1.0.0" + hastscript "^8.0.0" property-information "^6.0.0" - vfile "^5.0.0" - vfile-location "^4.0.0" + vfile "^6.0.0" + vfile-location "^5.0.0" web-namespaces "^2.0.0" -hast-util-has-property@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/hast-util-has-property/-/hast-util-has-property-2.0.0.tgz#c15cd6180f3e535540739fcc9787bcffb5708cae" - integrity sha512-4Qf++8o5v14us4Muv3HRj+Er6wTNGA/N9uCaZMty4JWvyFKLdhULrv4KE1b65AthsSO9TXSZnjuxS8ecIyhb0w== +hast-util-has-property@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/hast-util-has-property/-/hast-util-has-property-3.0.0.tgz#4e595e3cddb8ce530ea92f6fc4111a818d8e7f93" + integrity sha512-MNilsvEKLFpV604hwfhVStK0usFY/QmM5zX16bo7EjnAEGofr5YyI37kzopBlZJkHD4t887i+q/C8/tr5Q94cA== + dependencies: + "@types/hast" "^3.0.0" -hast-util-heading-rank@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/hast-util-heading-rank/-/hast-util-heading-rank-2.1.0.tgz#c39f34fa8330ebfec03a08b5d5019ed56122029c" - integrity sha512-w+Rw20Q/iWp2Bcnr6uTrYU6/ftZLbHKhvc8nM26VIWpDqDMlku2iXUVTeOlsdoih/UKQhY7PHQ+vZ0Aqq8bxtQ== +hast-util-heading-rank@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/hast-util-heading-rank/-/hast-util-heading-rank-3.0.0.tgz#2d5c6f2807a7af5c45f74e623498dd6054d2aba8" + integrity sha512-EJKb8oMUXVHcWZTDepnr+WNbfnXKFNf9duMesmr4S8SXTJBJ9M4Yok08pu9vxdJwdlGRhVumk9mEhkEvKGifwA== dependencies: - "@types/hast" "^2.0.0" + "@types/hast" "^3.0.0" -hast-util-is-element@^2.0.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/hast-util-is-element/-/hast-util-is-element-2.1.2.tgz#fc0b0dc7cef3895e839b8d66979d57b0338c68f3" - integrity sha512-thjnlGAnwP8ef/GSO1Q8BfVk2gundnc2peGQqEg2kUt/IqesiGg/5mSwN2fE7nLzy61pg88NG6xV+UrGOrx9EA== +hast-util-is-element@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/hast-util-is-element/-/hast-util-is-element-3.0.0.tgz#6e31a6532c217e5b533848c7e52c9d9369ca0932" + integrity sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g== dependencies: - "@types/hast" "^2.0.0" - "@types/unist" "^2.0.0" + "@types/hast" "^3.0.0" hast-util-parse-selector@^2.0.0: version "2.2.5" resolved "https://registry.yarnpkg.com/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz#d57c23f4da16ae3c63b3b6ca4616683313499c3a" integrity sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ== -hast-util-parse-selector@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/hast-util-parse-selector/-/hast-util-parse-selector-3.1.0.tgz#a519e27e8b61bd5a98fad494ed06131ce68d9c3f" - integrity sha512-AyjlI2pTAZEOeu7GeBPZhROx0RHBnydkQIXlhnFzDi0qfXTmGUWoCYZtomHbrdrheV4VFUlPcfJ6LMF5T6sQzg== +hast-util-parse-selector@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz#352879fa86e25616036037dd8931fb5f34cb4a27" + integrity sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A== dependencies: - "@types/hast" "^2.0.0" + "@types/hast" "^3.0.0" -hast-util-raw@^7.2.0: - version "7.2.1" - resolved "https://registry.yarnpkg.com/hast-util-raw/-/hast-util-raw-7.2.1.tgz#6e964cee098dbdd93d1b77cf180b5827d48048ab" - integrity sha512-wgtppqXVdXzkDXDFclLLdAyVUJSKMYYi6LWIAbA8oFqEdwksYIcPGM3RkKV1Dfn5GElvxhaOCs0jmCOMayxd3A== - dependencies: - "@types/hast" "^2.0.0" - "@types/parse5" "^6.0.0" - hast-util-from-parse5 "^7.0.0" - hast-util-to-parse5 "^7.0.0" - html-void-elements "^2.0.0" - parse5 "^6.0.0" - unist-util-position "^4.0.0" - unist-util-visit "^4.0.0" - vfile "^5.0.0" +hast-util-raw@^9.0.0: + version "9.0.4" + resolved "https://registry.yarnpkg.com/hast-util-raw/-/hast-util-raw-9.0.4.tgz#2da03e37c46eb1a6f1391f02f9b84ae65818f7ed" + integrity sha512-LHE65TD2YiNsHD3YuXcKPHXPLuYh/gjp12mOfU8jxSrm1f/yJpsb0F/KKljS6U9LJoP0Ux+tCe8iJ2AsPzTdgA== + dependencies: + "@types/hast" "^3.0.0" + "@types/unist" "^3.0.0" + "@ungap/structured-clone" "^1.0.0" + hast-util-from-parse5 "^8.0.0" + hast-util-to-parse5 "^8.0.0" + html-void-elements "^3.0.0" + mdast-util-to-hast "^13.0.0" + parse5 "^7.0.0" + unist-util-position "^5.0.0" + unist-util-visit "^5.0.0" + vfile "^6.0.0" web-namespaces "^2.0.0" zwitch "^2.0.0" -hast-util-sanitize@^4.0.0, hast-util-sanitize@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/hast-util-sanitize/-/hast-util-sanitize-4.1.0.tgz#d90f8521f5083547095c5c63a7e03150303e0286" - integrity sha512-Hd9tU0ltknMGRDv+d6Ro/4XKzBqQnP/EZrpiTbpFYfXv/uOhWeKc+2uajcbEvAEH98VZd7eII2PiXm13RihnLw== +hast-util-sanitize@^5.0.0, hast-util-sanitize@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/hast-util-sanitize/-/hast-util-sanitize-5.0.1.tgz#8e90068cd68e651c569960b77a1b25076579b4cf" + integrity sha512-IGrgWLuip4O2nq5CugXy4GI2V8kx4sFVy5Hd4vF7AR2gxS0N9s7nEAVUyeMtZKZvzrxVsHt73XdTsno1tClIkQ== dependencies: - "@types/hast" "^2.0.0" + "@types/hast" "^3.0.0" + "@ungap/structured-clone" "^1.2.0" + unist-util-position "^5.0.0" -hast-util-select@^5.0.5, hast-util-select@~5.0.1: - version "5.0.5" - resolved "https://registry.yarnpkg.com/hast-util-select/-/hast-util-select-5.0.5.tgz#be9ccb71d2278681ca024727f12abd4f93b3e9bc" - integrity sha512-QQhWMhgTFRhCaQdgTKzZ5g31GLQ9qRb1hZtDPMqQaOhpLBziWcshUS0uCR5IJ0U1jrK/mxg35fmcq+Dp/Cy2Aw== +hast-util-select@^6.0.0, hast-util-select@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/hast-util-select/-/hast-util-select-6.0.2.tgz#f1e6c583ab6227cb510383471328734342bd1d1c" + integrity sha512-hT/SD/d/Meu+iobvgkffo1QecV8WeKWxwsNMzcTJsKw1cKTQKSR/7ArJeURLNJF9HDjp9nVoORyNNJxrvBye8Q== dependencies: - "@types/hast" "^2.0.0" - "@types/unist" "^2.0.0" + "@types/hast" "^3.0.0" + "@types/unist" "^3.0.0" bcp-47-match "^2.0.0" comma-separated-tokens "^2.0.0" - css-selector-parser "^1.0.0" + css-selector-parser "^3.0.0" + devlop "^1.0.0" direction "^2.0.0" - hast-util-has-property "^2.0.0" - hast-util-to-string "^2.0.0" - hast-util-whitespace "^2.0.0" + hast-util-has-property "^3.0.0" + hast-util-to-string "^3.0.0" + hast-util-whitespace "^3.0.0" not "^0.1.0" nth-check "^2.0.0" property-information "^6.0.0" space-separated-tokens "^2.0.0" - unist-util-visit "^4.0.0" + unist-util-visit "^5.0.0" zwitch "^2.0.0" -hast-util-to-parse5@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/hast-util-to-parse5/-/hast-util-to-parse5-7.0.0.tgz#a39808e69005d10afeed1866029a1fb137df3f7c" - integrity sha512-YHiS6aTaZ3N0Q3nxaY/Tj98D6kM8QX5Q8xqgg8G45zR7PvWnPGPP0vcKCgb/moIydEJ/QWczVrX0JODCVeoV7A== +hast-util-to-jsx-runtime@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.0.tgz#3ed27caf8dc175080117706bf7269404a0aa4f7c" + integrity sha512-H/y0+IWPdsLLS738P8tDnrQ8Z+dj12zQQ6WC11TIM21C8WFVoIxcqWXf2H3hiTVZjF1AWqoimGwrTWecWrnmRQ== dependencies: - "@types/hast" "^2.0.0" - "@types/parse5" "^6.0.0" - hast-to-hyperscript "^10.0.0" + "@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 "^6.0.0" + space-separated-tokens "^2.0.0" + style-to-object "^1.0.0" + unist-util-position "^5.0.0" + vfile-message "^4.0.0" + +hast-util-to-parse5@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/hast-util-to-parse5/-/hast-util-to-parse5-8.0.0.tgz#477cd42d278d4f036bc2ea58586130f6f39ee6ed" + integrity sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw== + dependencies: + "@types/hast" "^3.0.0" + comma-separated-tokens "^2.0.0" + devlop "^1.0.0" property-information "^6.0.0" + space-separated-tokens "^2.0.0" web-namespaces "^2.0.0" zwitch "^2.0.0" -hast-util-to-string@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/hast-util-to-string/-/hast-util-to-string-2.0.0.tgz#b008b0a4ea472bf34dd390b7eea1018726ae152a" - integrity sha512-02AQ3vLhuH3FisaMM+i/9sm4OXGSq1UhOOCpTLLQtHdL3tZt7qil69r8M8iDkZYyC0HCFylcYoP+8IO7ddta1A== +hast-util-to-string@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/hast-util-to-string/-/hast-util-to-string-3.0.0.tgz#2a131948b4b1b26461a2c8ac876e2c88d02946bd" + integrity sha512-OGkAxX1Ua3cbcW6EJ5pT/tslVb90uViVkcJ4ZZIMW/R33DX/AkcJcRrPebPwJkHYwlDHXz4aIwvAAaAdtrACFA== dependencies: - "@types/hast" "^2.0.0" + "@types/hast" "^3.0.0" -hast-util-to-text@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/hast-util-to-text/-/hast-util-to-text-3.1.1.tgz#b7699a75f7a61af6e0befb67660cd78460d96dc6" - integrity sha512-7S3mOBxACy8syL45hCn3J7rHqYaXkxRfsX6LXEU5Shz4nt4GxdjtMUtG+T6G/ZLUHd7kslFAf14kAN71bz30xA== +hast-util-to-text@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/hast-util-to-text/-/hast-util-to-text-4.0.2.tgz#57b676931e71bf9cb852453678495b3080bfae3e" + integrity sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A== dependencies: - "@types/hast" "^2.0.0" - hast-util-is-element "^2.0.0" - unist-util-find-after "^4.0.0" + "@types/hast" "^3.0.0" + "@types/unist" "^3.0.0" + hast-util-is-element "^3.0.0" + unist-util-find-after "^5.0.0" -hast-util-whitespace@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/hast-util-whitespace/-/hast-util-whitespace-2.0.0.tgz#4fc1086467cc1ef5ba20673cb6b03cec3a970f1c" - integrity sha512-Pkw+xBHuV6xFeJprJe2BBEoDV+AvQySaz3pPDRUs5PNZEMQjpXJJueqrpcHIXxnWTcAGi/UOCgVShlkY6kLoqg== +hast-util-whitespace@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz#7778ed9d3c92dd9e8c5c8f648a49c21fc51cb621" + integrity sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw== + dependencies: + "@types/hast" "^3.0.0" hastscript@^6.0.0: version "6.0.0" @@ -10260,14 +10352,14 @@ hastscript@^6.0.0: property-information "^5.0.0" space-separated-tokens "^1.0.0" -hastscript@^7.0.0: - version "7.0.2" - resolved "https://registry.yarnpkg.com/hastscript/-/hastscript-7.0.2.tgz#d811fc040817d91923448a28156463b2e40d590a" - integrity sha512-uA8ooUY4ipaBvKcMuPehTAB/YfFLSSzCwFSwT6ltJbocFUKH/GDHLN+tflq7lSRf9H86uOuxOFkh1KgIy3Gg2g== +hastscript@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/hastscript/-/hastscript-8.0.0.tgz#4ef795ec8dee867101b9f23cc830d4baf4fd781a" + integrity sha512-dMOtzCEd3ABUeSIISmrETiKuyydk1w0pa+gE/uormcTpSYuaNJPbX1NU3JLyscSLjwAQM8bWMhhIlnCqnRvDTw== dependencies: - "@types/hast" "^2.0.0" + "@types/hast" "^3.0.0" comma-separated-tokens "^2.0.0" - hast-util-parse-selector "^3.0.0" + hast-util-parse-selector "^4.0.0" property-information "^6.0.0" space-separated-tokens "^2.0.0" @@ -10356,11 +10448,21 @@ html-tags@^3.3.1: resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.3.1.tgz#a04026a18c882e4bba8a01a3d39cfe465d40b5ce" integrity sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ== +html-url-attributes@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/html-url-attributes/-/html-url-attributes-3.0.0.tgz#fc4abf0c3fb437e2329c678b80abb3c62cff6f08" + integrity sha512-/sXbVCWayk6GDVg3ctOX6nxaVj7So40FcFAnWlWGNAB1LpYKcV5Cd10APjPjW80O7zYW2MsjBV4zZ7IZO5fVow== + html-void-elements@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-2.0.1.tgz#29459b8b05c200b6c5ee98743c41b979d577549f" integrity sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A== +html-void-elements@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-3.0.0.tgz#fc9dbd84af9e747249034d4d62602def6517f1d7" + integrity sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg== + htmlparser2@^8.0.1: version "8.0.2" resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-8.0.2.tgz#f002151705b383e62433b5cf466f5b716edaec21" @@ -10670,10 +10772,10 @@ ini@^4.1.1: resolved "https://registry.yarnpkg.com/ini/-/ini-4.1.1.tgz#d95b3d843b1e906e56d6747d5447904ff50ce7a1" integrity sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g== -inline-style-parser@0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.1.1.tgz#ec8a3b429274e9c0a1f1c4ffa9453a7fef72cea1" - integrity sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q== +inline-style-parser@0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.2.3.tgz#e35c5fb45f3a83ed7849fe487336eb7efa25971c" + integrity sha512-qlD8YNDqyTKTyuITrDOffsl6Tdhv+UC4hcdAVuQsK4IMQ99nSgd1MIA/Q+jQYoh9r3hVUXhYh7urSRmXPkW04g== inquirer@8.2.1: version "8.2.1" @@ -11901,21 +12003,7 @@ kareem@2.5.1: resolved "https://registry.yarnpkg.com/kareem/-/kareem-2.5.1.tgz#7b8203e11819a8e77a34b3517d3ead206764d15d" integrity sha512-7jFxRVm+jD+rkq3kY0iZDJfsO2/t4BBPeEb2qKn2lR/9KhuksYk5hxzfRYWMPV8P/x2d0kHD306YyWLzjjH+uA== -katex@^0.13.0: - version "0.13.24" - resolved "https://registry.yarnpkg.com/katex/-/katex-0.13.24.tgz#fe55455eb455698cb24b911a353d16a3c855d905" - integrity sha512-jZxYuKCma3VS5UuxOx/rFV1QyGSl3Uy/i0kTJF3HgQ5xMinCQVF8Zd4bMY/9aI9b9A2pjIBOsjSSm68ykTAr8w== - dependencies: - commander "^8.0.0" - -katex@^0.15.0: - version "0.15.6" - resolved "https://registry.yarnpkg.com/katex/-/katex-0.15.6.tgz#c4e2f6ced2ac4de1ef6f737fe7c67d3026baa0e5" - integrity sha512-UpzJy4yrnqnhXvRPhjEuLA4lcPn6eRngixW7Q3TJErjg3Aw2PuLFBzTkdUb89UtumxjhHTqL3a5GDGETMSwgJA== - dependencies: - commander "^8.0.0" - -katex@^0.16.9: +katex@^0.16.0, katex@^0.16.9: version "0.16.10" resolved "https://registry.yarnpkg.com/katex/-/katex-0.16.10.tgz#6f81b71ac37ff4ec7556861160f53bc5f058b185" integrity sha512-ZiqaC04tp2O5utMsl2TEZTXxa6WSC4yo0fv5ML++D3QZv/vx2Mct0mTlRx3O+uUkjfuAgOkzsCmq5MiUEsDDdA== @@ -12428,9 +12516,9 @@ longest-streak@^2.0.0: integrity sha512-vM6rUVCVUJJt33bnmHiZEvr7wPT78ztX7rojL+LW51bHtLh6HTjx84LA5W4+oa6aKEJA7jJu5LR6vQRBpA5DVg== longest-streak@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-3.0.1.tgz#c97315b7afa0e7d9525db9a5a2953651432bdc5d" - integrity sha512-cHlYSUpL2s7Fb3394mYxwTYj8niTaNHUCLr0qdiCXQfSjfuA7CKofpX2uSwEfFDQ0EB7JcnMnm+GjbqqoinYYg== + version "3.1.0" + resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-3.1.0.tgz#62fa67cd958742a1574af9f39866364102d90cd4" + integrity sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g== loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: version "1.4.0" @@ -12673,130 +12761,197 @@ md5@^2.2.1: crypt "~0.0.1" is-buffer "~1.1.1" -mdast-util-definitions@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/mdast-util-definitions/-/mdast-util-definitions-5.1.1.tgz#2c1d684b28e53f84938bb06317944bee8efa79db" - integrity sha512-rQ+Gv7mHttxHOBx2dkF4HWTg+EE+UR78ptQWDylzPKaQuVGdG4HIoY3SrS/pCp80nZ04greFvXbVFHT+uf0JVQ== - dependencies: - "@types/mdast" "^3.0.0" - "@types/unist" "^2.0.0" - unist-util-visit "^4.0.0" - -mdast-util-find-and-replace@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/mdast-util-find-and-replace/-/mdast-util-find-and-replace-2.2.0.tgz#6167edf16c2fd79e7213024544575f304151953f" - integrity sha512-bz8hUWkMX7UcasORORcyBEsTKJ+dBiFwRPrm43hHC9NMRylIMLbfO5rwfeCN+UtY4AAi7s8WqXftb9eX6ZsqCg== +mdast-util-find-and-replace@^3.0.0, mdast-util-find-and-replace@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.1.tgz#a6fc7b62f0994e973490e45262e4bc07607b04e0" + integrity sha512-SG21kZHGC3XRTSUhtofZkBzZTJNM5ecCi0SK2IMKmSXR8vO3peL+kb1O0z7Zl83jKtutG4k5Wv/W7V3/YHvzPA== dependencies: + "@types/mdast" "^4.0.0" escape-string-regexp "^5.0.0" - unist-util-is "^5.0.0" - unist-util-visit-parents "^5.0.0" + unist-util-is "^6.0.0" + unist-util-visit-parents "^6.0.0" -mdast-util-from-markdown@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/mdast-util-from-markdown/-/mdast-util-from-markdown-1.2.0.tgz#84df2924ccc6c995dec1e2368b2b208ad0a76268" - integrity sha512-iZJyyvKD1+K7QX1b5jXdE7Sc5dtoTry1vzV28UZZe8Z1xVnB/czKntJ7ZAkG0tANqRnBF6p3p7GpU1y19DTf2Q== +mdast-util-from-markdown@^2.0.0, mdast-util-from-markdown@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.1.tgz#32a6e8f512b416e1f51eb817fc64bd867ebcd9cc" + integrity sha512-aJEUyzZ6TzlsX2s5B4Of7lN7EQtAxvtradMMglCQDyaTFgse6CmtmdJ15ElnVRlCg1vpNyVtbem0PWzlNieZsA== dependencies: - "@types/mdast" "^3.0.0" - "@types/unist" "^2.0.0" + "@types/mdast" "^4.0.0" + "@types/unist" "^3.0.0" decode-named-character-reference "^1.0.0" - mdast-util-to-string "^3.1.0" - micromark "^3.0.0" - micromark-util-decode-numeric-character-reference "^1.0.0" - micromark-util-decode-string "^1.0.0" - micromark-util-normalize-identifier "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - unist-util-stringify-position "^3.0.0" - uvu "^0.5.0" - -mdast-util-frontmatter@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mdast-util-frontmatter/-/mdast-util-frontmatter-1.0.1.tgz#79c46d7414eb9d3acabe801ee4a70a70b75e5af1" - integrity sha512-JjA2OjxRqAa8wEG8hloD0uTU0kdn8kbtOWpPP94NBkfAlbxn4S8gCGf/9DwFtEeGPXrDcNXdiDjVaRdUFqYokw== + 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" + +mdast-util-frontmatter@^2.0.0, mdast-util-frontmatter@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/mdast-util-frontmatter/-/mdast-util-frontmatter-2.0.1.tgz#f5f929eb1eb36c8a7737475c7eb438261f964ee8" + integrity sha512-LRqI9+wdgC25P0URIJY9vwocIzCcksduHQ9OF2joxQoyTNVduwLAFUzjoopuRJbJAReaKrNQKAZKL3uCMugWJA== dependencies: - "@types/mdast" "^3.0.0" - mdast-util-to-markdown "^1.3.0" - micromark-extension-frontmatter "^1.0.0" + "@types/mdast" "^4.0.0" + devlop "^1.0.0" + escape-string-regexp "^5.0.0" + mdast-util-from-markdown "^2.0.0" + mdast-util-to-markdown "^2.0.0" + micromark-extension-frontmatter "^2.0.0" -mdast-util-gfm-autolink-literal@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-1.0.2.tgz#4032dcbaddaef7d4f2f3768ed830475bb22d3970" - integrity sha512-FzopkOd4xTTBeGXhXSBU0OCDDh5lUj2rd+HQqG92Ld+jL4lpUfgX2AT2OHAVP9aEeDKp7G92fuooSZcYJA3cRg== +mdast-util-gfm-autolink-literal@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.0.tgz#5baf35407421310a08e68c15e5d8821e8898ba2a" + integrity sha512-FyzMsduZZHSc3i0Px3PQcBT4WJY/X/RCtEJKuybiC6sjPqLv7h1yqAkmILZtuxMSsUyaLUWNp71+vQH2zqp5cg== dependencies: - "@types/mdast" "^3.0.0" + "@types/mdast" "^4.0.0" ccount "^2.0.0" - mdast-util-find-and-replace "^2.0.0" - micromark-util-character "^1.0.0" + devlop "^1.0.0" + mdast-util-find-and-replace "^3.0.0" + micromark-util-character "^2.0.0" -mdast-util-gfm-footnote@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-1.0.1.tgz#11d2d40a1a673a399c459e467fa85e00223191fe" - integrity sha512-p+PrYlkw9DeCRkTVw1duWqPRHX6Ywh2BNKJQcZbCwAuP/59B0Lk9kakuAd7KbQprVO4GzdW8eS5++A9PUSqIyw== +mdast-util-gfm-footnote@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.0.0.tgz#25a1753c7d16db8bfd53cd84fe50562bd1e6d6a9" + integrity sha512-5jOT2boTSVkMnQ7LTrd6n/18kqwjmuYqo7JUPe+tRCY6O7dAuTFMtTPauYYrMPpox9hlN0uOx/FL8XvEfG9/mQ== dependencies: - "@types/mdast" "^3.0.0" - mdast-util-to-markdown "^1.3.0" - micromark-util-normalize-identifier "^1.0.0" + "@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" -mdast-util-gfm-strikethrough@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-1.0.1.tgz#a4a74c36864ec6a6e3bbd31e1977f29beb475789" - integrity sha512-zKJbEPe+JP6EUv0mZ0tQUyLQOC+FADt0bARldONot/nefuISkaZFlmVK4tU6JgfyZGrky02m/I6PmehgAgZgqg== +mdast-util-gfm-strikethrough@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz#d44ef9e8ed283ac8c1165ab0d0dfd058c2764c16" + integrity sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg== dependencies: - "@types/mdast" "^3.0.0" - mdast-util-to-markdown "^1.3.0" + "@types/mdast" "^4.0.0" + mdast-util-from-markdown "^2.0.0" + mdast-util-to-markdown "^2.0.0" -mdast-util-gfm-table@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/mdast-util-gfm-table/-/mdast-util-gfm-table-1.0.4.tgz#0dbb25f04fd9c0877dc63b76203ecbdf5d945755" - integrity sha512-aEuoPwZyP4iIMkf2cLWXxx3EQ6Bmh2yKy9MVCg4i6Sd3cX80dcLEfXO/V4ul3pGH9czBK4kp+FAl+ZHmSUt9/w== +mdast-util-gfm-table@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz#7a435fb6223a72b0862b33afbd712b6dae878d38" + integrity sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg== dependencies: + "@types/mdast" "^4.0.0" + devlop "^1.0.0" markdown-table "^3.0.0" - mdast-util-from-markdown "^1.0.0" - mdast-util-to-markdown "^1.3.0" + mdast-util-from-markdown "^2.0.0" + mdast-util-to-markdown "^2.0.0" -mdast-util-gfm-task-list-item@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-1.0.1.tgz#6f35f09c6e2bcbe88af62fdea02ac199cc802c5c" - integrity sha512-KZ4KLmPdABXOsfnM6JHUIjxEvcx2ulk656Z/4Balw071/5qgnhz+H1uGtf2zIGnrnvDC8xR4Fj9uKbjAFGNIeA== +mdast-util-gfm-task-list-item@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz#e68095d2f8a4303ef24094ab642e1047b991a936" + integrity sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ== dependencies: - "@types/mdast" "^3.0.0" - mdast-util-to-markdown "^1.3.0" + "@types/mdast" "^4.0.0" + devlop "^1.0.0" + mdast-util-from-markdown "^2.0.0" + mdast-util-to-markdown "^2.0.0" -mdast-util-gfm@^2.0.0, mdast-util-gfm@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/mdast-util-gfm/-/mdast-util-gfm-2.0.2.tgz#e92f4d8717d74bdba6de57ed21cc8b9552e2d0b6" - integrity sha512-qvZ608nBppZ4icQlhQQIAdc6S3Ffj9RGmzwUKUWuEICFnd1LVkN3EktF7ZHAgfcEdvZB5owU9tQgt99e2TlLjg== - dependencies: - mdast-util-from-markdown "^1.0.0" - mdast-util-gfm-autolink-literal "^1.0.0" - mdast-util-gfm-footnote "^1.0.0" - mdast-util-gfm-strikethrough "^1.0.0" - mdast-util-gfm-table "^1.0.0" - mdast-util-gfm-task-list-item "^1.0.0" - mdast-util-to-markdown "^1.0.0" - -mdast-util-math@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/mdast-util-math/-/mdast-util-math-2.0.1.tgz#141b8e7e43731d2a7423c5eb8c0335c05d257ad2" - integrity sha512-ZZtjyRwobsiVg4bY0Q5CzAZztpbjRIA7ZlMMb0PNkwTXOnJTUoHvzBhVG95LIuek5Mlj1l2P+jBvWviqW7G+0A== +mdast-util-gfm@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/mdast-util-gfm/-/mdast-util-gfm-3.0.0.tgz#3f2aecc879785c3cb6a81ff3a243dc11eca61095" + integrity sha512-dgQEX5Amaq+DuUqf26jJqSK9qgixgd6rYDHAv4aTBuA92cTknZlKpPfa86Z/s8Dj8xsAQpFfBmPUHWJBWqS4Bw== + 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" + +mdast-util-math@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/mdast-util-math/-/mdast-util-math-3.0.0.tgz#8d79dd3baf8ab8ac781f62b8853768190b9a00b0" + integrity sha512-Tl9GBNeG/AhJnQM221bJR2HPvLOSnLE/T9cJI9tlc6zwQk2nPk/4f0cHkOdEixQPC/j8UtKDdITswvLAy1OZ1w== dependencies: - "@types/mdast" "^3.0.0" + "@types/hast" "^3.0.0" + "@types/mdast" "^4.0.0" + devlop "^1.0.0" longest-streak "^3.0.0" - mdast-util-to-markdown "^1.3.0" + mdast-util-from-markdown "^2.0.0" + mdast-util-to-markdown "^2.1.0" + unist-util-remove-position "^5.0.0" -mdast-util-to-hast@^12.1.0: - version "12.3.0" - resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-12.3.0.tgz#045d2825fb04374e59970f5b3f279b5700f6fb49" - integrity sha512-pits93r8PhnIoU4Vy9bjW39M2jJ6/tdHyja9rrot9uujkN7UTU9SDnE6WNJz/IGyQk3XHX6yNNtrBH6cQzm8Hw== +mdast-util-mdx-expression@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.0.tgz#4968b73724d320a379110d853e943a501bfd9d87" + integrity sha512-fGCu8eWdKUKNu5mohVGkhBXCXGnOTLuFqOvGMvdikr+J1w7lDJgxThOKpwRWzzbyXAU2hhSwsmssOY4yTokluw== dependencies: - "@types/hast" "^2.0.0" - "@types/mdast" "^3.0.0" - mdast-util-definitions "^5.0.0" - micromark-util-sanitize-uri "^1.1.0" + "@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" + +mdast-util-mdx-jsx@^3.0.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.1.2.tgz#daae777c72f9c4a106592e3025aa50fb26068e1b" + integrity sha512-eKMQDeywY2wlHc97k5eD8VC+9ASMjN8ItEZQNGwJ6E0XWKiW/Z0V5/H8pvoXUf+y+Mj0VIgeRRbujBmFn4FTyA== + 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-remove-position "^5.0.0" + unist-util-stringify-position "^4.0.0" + vfile-message "^4.0.0" + +mdast-util-mdxjs-esm@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz#019cfbe757ad62dd557db35a695e7314bcc9fa97" + integrity sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg== + 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" + +mdast-util-newline-to-break@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/mdast-util-newline-to-break/-/mdast-util-newline-to-break-2.0.0.tgz#4e73ef621b6b1a590240336cfe6c29915e198df0" + integrity sha512-MbgeFca0hLYIEx/2zGsszCSEJJ1JSCdiY5xQxRcLDDGa8EPvlLPupJ4DSajbMPAnC0je8jfb9TiUATnxxrHUog== + dependencies: + "@types/mdast" "^4.0.0" + mdast-util-find-and-replace "^3.0.0" + +mdast-util-phrasing@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz#7cc0a8dec30eaf04b7b1a9661a92adb3382aa6e3" + integrity sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w== + dependencies: + "@types/mdast" "^4.0.0" + unist-util-is "^6.0.0" + +mdast-util-to-hast@^13.0.0: + version "13.2.0" + resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz#5ca58e5b921cc0a3ded1bc02eed79a4fe4fe41f4" + integrity sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA== + 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-generated "^2.0.0" - unist-util-position "^4.0.0" - unist-util-visit "^4.0.0" + unist-util-position "^5.0.0" + unist-util-visit "^5.0.0" + vfile "^6.0.0" mdast-util-to-markdown@^0.6.5: version "0.6.5" @@ -12810,17 +12965,18 @@ mdast-util-to-markdown@^0.6.5: repeat-string "^1.0.0" zwitch "^1.0.0" -mdast-util-to-markdown@^1.0.0, mdast-util-to-markdown@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/mdast-util-to-markdown/-/mdast-util-to-markdown-1.3.0.tgz#38b6cdc8dc417de642a469c4fc2abdf8c931bd1e" - integrity sha512-6tUSs4r+KK4JGTTiQ7FfHmVOaDrLQJPmpjD6wPMlHGUVXoG9Vjc3jIeP+uyBWRf8clwB2blM+W7+KrlMYQnftA== +mdast-util-to-markdown@^2.0.0, mdast-util-to-markdown@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.0.tgz#9813f1d6e0cdaac7c244ec8c6dabfdb2102ea2b4" + integrity sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ== dependencies: - "@types/mdast" "^3.0.0" - "@types/unist" "^2.0.0" + "@types/mdast" "^4.0.0" + "@types/unist" "^3.0.0" longest-streak "^3.0.0" - mdast-util-to-string "^3.0.0" - micromark-util-decode-string "^1.0.0" - unist-util-visit "^4.0.0" + mdast-util-phrasing "^4.0.0" + mdast-util-to-string "^4.0.0" + micromark-util-decode-string "^2.0.0" + unist-util-visit "^5.0.0" zwitch "^2.0.0" mdast-util-to-string@^2.0.0: @@ -12828,29 +12984,30 @@ mdast-util-to-string@^2.0.0: resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz#b8cfe6a713e1091cb5b728fc48885a4767f8b97b" integrity sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w== -mdast-util-to-string@^3.0.0, mdast-util-to-string@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-3.1.0.tgz#56c506d065fbf769515235e577b5a261552d56e9" - integrity sha512-n4Vypz/DZgwo0iMHLQL49dJzlp7YtAJP+N07MZHpjPf/5XJuHUWstviF4Mn2jEiR/GNmtnRRqnwsXExk3igfFA== - -mdast-util-toc@^6.0.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/mdast-util-toc/-/mdast-util-toc-6.1.0.tgz#1f38419f5ce774449c8daa87b39a4d940b24be7c" - integrity sha512-0PuqZELXZl4ms1sF7Lqigrqik4Ll3UhbI+jdTrfw7pZ9QPawgl7LD4GQ8MkU7bT/EwiVqChNTbifa2jLLKo76A== +mdast-util-to-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz#7a5121475556a04e7eddeb67b264aae79d312814" + integrity sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg== dependencies: - "@types/extend" "^3.0.0" - "@types/github-slugger" "^1.0.0" - "@types/mdast" "^3.0.0" - extend "^3.0.0" - github-slugger "^1.0.0" - mdast-util-to-string "^3.1.0" - unist-util-is "^5.0.0" - unist-util-visit "^3.0.0" + "@types/mdast" "^4.0.0" -mdast-util-wiki-link@^0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/mdast-util-wiki-link/-/mdast-util-wiki-link-0.0.2.tgz#f9cb957febafa3ddc4cf1567ec159400217e1690" - integrity sha512-lSsR10/dPuYIxzjGZIGA4oYzsnEnqcsD6DTXL0pqdbBzNB9teKVZB2aIzZcUsdg31v/NoHOstkVwzbN6VrQLtw== +mdast-util-toc@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/mdast-util-toc/-/mdast-util-toc-7.1.0.tgz#d972d356ee8aa0b0e78153f77c4a00230e34a942" + integrity sha512-2TVKotOQzqdY7THOdn2gGzS9d1Sdd66bvxUyw3aNpWfcPXCLYSJCCgfPy30sEtuzkDraJgqF35dzgmz6xlvH/w== + dependencies: + "@types/mdast" "^4.0.0" + "@types/ungap__structured-clone" "^1.0.0" + "@ungap/structured-clone" "^1.0.0" + github-slugger "^2.0.0" + mdast-util-to-string "^4.0.0" + unist-util-is "^6.0.0" + unist-util-visit "^5.0.0" + +mdast-util-wiki-link@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/mdast-util-wiki-link/-/mdast-util-wiki-link-0.1.2.tgz#df664e4a22ef533666f5012cf0b34ba187b9f1c0" + integrity sha512-DTcDyOxKDo3pB3fc0zQlD8myfQjYkW4hazUKI9PUyhtoj9JBeHC2eIdlVXmaT22bZkFAVU2d47B6y2jVKGoUQg== dependencies: "@babel/runtime" "^7.12.1" mdast-util-to-markdown "^0.6.5" @@ -12980,130 +13137,129 @@ microbuffer@^1.0.0: resolved "https://registry.yarnpkg.com/microbuffer/-/microbuffer-1.0.0.tgz#8b3832ed40c87d51f47bb234913a698a756d19d2" integrity sha512-O/SUXauVN4x6RaEJFqSPcXNtLFL+QzJHKZlyDVYFwcDDRVca3Fa/37QXXC+4zAGGa4YhHrHxKXuuHvLDIQECtA== -micromark-core-commonmark@^1.0.0, micromark-core-commonmark@^1.0.1: - version "1.0.6" - resolved "https://registry.yarnpkg.com/micromark-core-commonmark/-/micromark-core-commonmark-1.0.6.tgz#edff4c72e5993d93724a3c206970f5a15b0585ad" - integrity sha512-K+PkJTxqjFfSNkfAhp4GB+cZPfQd6dxtTXnf+RjZOV7T4EEXnvgzOcnp+eSTmpGk9d1S9sL6/lqrgSNn/s0HZA== +micromark-core-commonmark@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/micromark-core-commonmark/-/micromark-core-commonmark-2.0.1.tgz#9a45510557d068605c6e9a80f282b2bb8581e43d" + integrity sha512-CUQyKr1e///ZODyD1U3xit6zXwy1a8q2a1S1HKtIlmgvurrEpaw/Y9y6KSIbF8P59cn/NjzHyO+Q2fAyYLQrAA== dependencies: decode-named-character-reference "^1.0.0" - micromark-factory-destination "^1.0.0" - micromark-factory-label "^1.0.0" - micromark-factory-space "^1.0.0" - micromark-factory-title "^1.0.0" - micromark-factory-whitespace "^1.0.0" - micromark-util-character "^1.0.0" - micromark-util-chunked "^1.0.0" - micromark-util-classify-character "^1.0.0" - micromark-util-html-tag-name "^1.0.0" - micromark-util-normalize-identifier "^1.0.0" - micromark-util-resolve-all "^1.0.0" - micromark-util-subtokenize "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.1" - uvu "^0.5.0" - -micromark-extension-frontmatter@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/micromark-extension-frontmatter/-/micromark-extension-frontmatter-1.1.1.tgz#2946643938e491374145d0c9aacc3249e38a865f" - integrity sha512-m2UH9a7n3W8VAH9JO9y01APpPKmNNNs71P0RbknEmYSaZU5Ghogv38BYO94AI5Xw6OYfxZRdHZZ2nYjs/Z+SZQ== + 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" + +micromark-extension-frontmatter@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/micromark-extension-frontmatter/-/micromark-extension-frontmatter-2.0.0.tgz#651c52ffa5d7a8eeed687c513cd869885882d67a" + integrity sha512-C4AkuM3dA58cgZha7zVnuVxBhDsbttIMiytjgsM2XbHAB2faRVaHRle40558FBN+DJcrLNCoqG5mlrpdU4cRtg== dependencies: fault "^2.0.0" - micromark-util-character "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" + micromark-util-character "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" -micromark-extension-gfm-autolink-literal@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-1.0.3.tgz#dc589f9c37eaff31a175bab49f12290edcf96058" - integrity sha512-i3dmvU0htawfWED8aHMMAzAVp/F0Z+0bPh3YrbTPPL1v4YAlCZpy5rBO5p0LPYiZo0zFVkoYh7vDU7yQSiCMjg== +micromark-extension-gfm-autolink-literal@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.0.0.tgz#f1e50b42e67d441528f39a67133eddde2bbabfd9" + integrity sha512-rTHfnpt/Q7dEAK1Y5ii0W8bhfJlVJFnJMHIPisfPK3gpVNuOP0VnRl96+YJ3RYWV/P4gFeQoGKNlT3RhuvpqAg== dependencies: - micromark-util-character "^1.0.0" - micromark-util-sanitize-uri "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - uvu "^0.5.0" + 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" -micromark-extension-gfm-footnote@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-1.0.4.tgz#cbfd8873b983e820c494498c6dac0105920818d5" - integrity sha512-E/fmPmDqLiMUP8mLJ8NbJWJ4bTw6tS+FEQS8CcuDtZpILuOb2kjLqPEeAePF1djXROHXChM/wPJw0iS4kHCcIg== - dependencies: - micromark-core-commonmark "^1.0.0" - micromark-factory-space "^1.0.0" - micromark-util-character "^1.0.0" - micromark-util-normalize-identifier "^1.0.0" - micromark-util-sanitize-uri "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - uvu "^0.5.0" - -micromark-extension-gfm-strikethrough@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-1.0.4.tgz#162232c284ffbedd8c74e59c1525bda217295e18" - integrity sha512-/vjHU/lalmjZCT5xt7CcHVJGq8sYRm80z24qAKXzaHzem/xsDYb2yLL+NNVbYvmpLx3O7SYPuGL5pzusL9CLIQ== - dependencies: - micromark-util-chunked "^1.0.0" - micromark-util-classify-character "^1.0.0" - micromark-util-resolve-all "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - uvu "^0.5.0" - -micromark-extension-gfm-table@^1.0.0: - version "1.0.6" - resolved "https://registry.yarnpkg.com/micromark-extension-gfm-table/-/micromark-extension-gfm-table-1.0.6.tgz#22b2b18dff9db39bdb29d6017e53bdd370672c8e" - integrity sha512-92pq7Q+T+4kXH4M6kL+pc8WU23Z9iuhcqmtYFWdFWjm73ZscFpH2xE28+XFpGWlvgq3LUwcN0XC0PGCicYFpgA== +micromark-extension-gfm-footnote@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.0.0.tgz#91afad310065a94b636ab1e9dab2c60d1aab953c" + integrity sha512-6Rzu0CYRKDv3BfLAUnZsSlzx3ak6HAoI85KTiijuKIz5UxZxbUI+pD6oHgw+6UtQuiRwnGRhzMmPRv4smcz0fg== + 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" + +micromark-extension-gfm-strikethrough@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.0.0.tgz#6917db8e320da70e39ffbf97abdbff83e6783e61" + integrity sha512-c3BR1ClMp5fxxmwP6AoOY2fXO9U8uFMKs4ADD66ahLTNcwzSCyRVU4k7LPV5Nxo/VJiR4TdzxRQY2v3qIUceCw== dependencies: - micromark-factory-space "^1.0.0" - micromark-util-character "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - uvu "^0.5.0" + 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" -micromark-extension-gfm-tagfilter@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-1.0.1.tgz#fb2e303f7daf616db428bb6a26e18fda14a90a4d" - integrity sha512-Ty6psLAcAjboRa/UKUbbUcwjVAv5plxmpUTy2XC/3nJFL37eHej8jrHrRzkqcpipJliuBH30DTs7+3wqNcQUVA== +micromark-extension-gfm-table@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.0.0.tgz#2cf3fe352d9e089b7ef5fff003bdfe0da29649b7" + integrity sha512-PoHlhypg1ItIucOaHmKE8fbin3vTLpDOUg8KAr8gRCF1MOZI9Nquq2i/44wFvviM4WuxJzc3demT8Y3dkfvYrw== dependencies: - micromark-util-types "^1.0.0" + 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" -micromark-extension-gfm-task-list-item@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-1.0.3.tgz#7683641df5d4a09795f353574d7f7f66e47b7fc4" - integrity sha512-PpysK2S1Q/5VXi72IIapbi/jliaiOFzv7THH4amwXeYXLq3l1uo8/2Be0Ac1rEwK20MQEsGH2ltAZLNY2KI/0Q== +micromark-extension-gfm-tagfilter@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz#f26d8a7807b5985fba13cf61465b58ca5ff7dc57" + integrity sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg== dependencies: - micromark-factory-space "^1.0.0" - micromark-util-character "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - uvu "^0.5.0" + micromark-util-types "^2.0.0" -micromark-extension-gfm@^2.0.0: +micromark-extension-gfm-task-list-item@^2.0.0: version "2.0.1" - resolved "https://registry.yarnpkg.com/micromark-extension-gfm/-/micromark-extension-gfm-2.0.1.tgz#40f3209216127a96297c54c67f5edc7ef2d1a2a2" - integrity sha512-p2sGjajLa0iYiGQdT0oelahRYtMWvLjy8J9LOCxzIQsllMCGLbsLW+Nc+N4vi02jcRJvedVJ68cjelKIO6bpDA== - dependencies: - micromark-extension-gfm-autolink-literal "^1.0.0" - micromark-extension-gfm-footnote "^1.0.0" - micromark-extension-gfm-strikethrough "^1.0.0" - micromark-extension-gfm-table "^1.0.0" - micromark-extension-gfm-tagfilter "^1.0.0" - micromark-extension-gfm-task-list-item "^1.0.0" - micromark-util-combine-extensions "^1.0.0" - micromark-util-types "^1.0.0" - -micromark-extension-math@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/micromark-extension-math/-/micromark-extension-math-2.0.2.tgz#bb7d28b907b17f1813dd3d0df2a6df6bb1a4d0e1" - integrity sha512-cFv2B/E4pFPBBFuGgLHkkNiFAIQv08iDgPH2HCuR2z3AUgMLecES5Cq7AVtwOtZeRrbA80QgMUk8VVW0Z+D2FA== - dependencies: - "@types/katex" "^0.11.0" - katex "^0.13.0" - micromark-factory-space "^1.0.0" - micromark-util-character "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - uvu "^0.5.0" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.0.1.tgz#ee8b208f1ced1eb9fb11c19a23666e59d86d4838" + integrity sha512-cY5PzGcnULaN5O7T+cOzfMoHjBW7j+T9D2sucA5d/KbsBTPcYdebm9zUd9zzdgJGCwahV+/W78Z3nbulBYVbTw== + 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" + +micromark-extension-gfm@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz#3e13376ab95dd7a5cfd0e29560dfe999657b3c5b" + integrity sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w== + 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" + +micromark-extension-math@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/micromark-extension-math/-/micromark-extension-math-3.0.0.tgz#c7a47d6ce990812243ad3946a30bb60e4c2a8c76" + integrity sha512-iJ2Q28vBoEovLN5o3GO12CpqorQRYDPT+p4zW50tGwTfJB+iv/VnB6Ini+gqa24K97DwptMBBIvVX6Bjk49oyQ== + dependencies: + "@types/katex" "^0.16.0" + devlop "^1.0.0" + katex "^0.16.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" micromark-extension-wiki-link@^0.0.4: version "0.0.4" @@ -13112,178 +13268,177 @@ micromark-extension-wiki-link@^0.0.4: dependencies: "@babel/runtime" "^7.12.1" -micromark-factory-destination@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/micromark-factory-destination/-/micromark-factory-destination-1.0.0.tgz#fef1cb59ad4997c496f887b6977aa3034a5a277e" - integrity sha512-eUBA7Rs1/xtTVun9TmV3gjfPz2wEwgK5R5xcbIM5ZYAtvGF6JkyaDsj0agx8urXnO31tEO6Ug83iVH3tdedLnw== +micromark-factory-destination@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/micromark-factory-destination/-/micromark-factory-destination-2.0.0.tgz#857c94debd2c873cba34e0445ab26b74f6a6ec07" + integrity sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA== dependencies: - micromark-util-character "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" + micromark-util-character "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" -micromark-factory-label@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/micromark-factory-label/-/micromark-factory-label-1.0.2.tgz#6be2551fa8d13542fcbbac478258fb7a20047137" - integrity sha512-CTIwxlOnU7dEshXDQ+dsr2n+yxpP0+fn271pu0bwDIS8uqfFcumXpj5mLn3hSC8iw2MUr6Gx8EcKng1dD7i6hg== +micromark-factory-label@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/micromark-factory-label/-/micromark-factory-label-2.0.0.tgz#17c5c2e66ce39ad6f4fc4cbf40d972f9096f726a" + integrity sha512-RR3i96ohZGde//4WSe/dJsxOX6vxIg9TimLAS3i4EhBAFx8Sm5SmqVfR8E87DPSR31nEAjZfbt91OMZWcNgdZw== dependencies: - micromark-util-character "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - uvu "^0.5.0" + devlop "^1.0.0" + micromark-util-character "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" -micromark-factory-space@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/micromark-factory-space/-/micromark-factory-space-1.0.0.tgz#cebff49968f2b9616c0fcb239e96685cb9497633" - integrity sha512-qUmqs4kj9a5yBnk3JMLyjtWYN6Mzfcx8uJfi5XAveBniDevmZasdGBba5b4QsvRcAkmvGo5ACmSUmyGiKTLZew== +micromark-factory-space@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz#5e7afd5929c23b96566d0e1ae018ae4fcf81d030" + integrity sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg== dependencies: - micromark-util-character "^1.0.0" - micromark-util-types "^1.0.0" + micromark-util-character "^2.0.0" + micromark-util-types "^2.0.0" -micromark-factory-title@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/micromark-factory-title/-/micromark-factory-title-1.0.2.tgz#7e09287c3748ff1693930f176e1c4a328382494f" - integrity sha512-zily+Nr4yFqgMGRKLpTVsNl5L4PMu485fGFDOQJQBl2NFpjGte1e86zC0da93wf97jrc4+2G2GQudFMHn3IX+A== +micromark-factory-title@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/micromark-factory-title/-/micromark-factory-title-2.0.0.tgz#726140fc77892af524705d689e1cf06c8a83ea95" + integrity sha512-jY8CSxmpWLOxS+t8W+FG3Xigc0RDQA9bKMY/EwILvsesiRniiVMejYTE4wumNc2f4UbAa4WsHqe3J1QS1sli+A== dependencies: - micromark-factory-space "^1.0.0" - micromark-util-character "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - uvu "^0.5.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" -micromark-factory-whitespace@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/micromark-factory-whitespace/-/micromark-factory-whitespace-1.0.0.tgz#e991e043ad376c1ba52f4e49858ce0794678621c" - integrity sha512-Qx7uEyahU1lt1RnsECBiuEbfr9INjQTGa6Err+gF3g0Tx4YEviPbqqGKNv/NrBaE7dVHdn1bVZKM/n5I/Bak7A== +micromark-factory-whitespace@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.0.tgz#9e92eb0f5468083381f923d9653632b3cfb5f763" + integrity sha512-28kbwaBjc5yAI1XadbdPYHX/eDnqaUFVikLwrO7FDnKG7lpgxnvk/XGRhX/PN0mOZ+dBSZ+LgunHS+6tYQAzhA== dependencies: - micromark-factory-space "^1.0.0" - micromark-util-character "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^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" -micromark-util-character@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/micromark-util-character/-/micromark-util-character-1.1.0.tgz#d97c54d5742a0d9611a68ca0cd4124331f264d86" - integrity sha512-agJ5B3unGNJ9rJvADMJ5ZiYjBRyDpzKAOk01Kpi1TKhlT1APx3XZk6eN7RtSz1erbWHC2L8T3xLZ81wdtGRZzg== +micromark-util-character@^2.0.0, micromark-util-character@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-character/-/micromark-util-character-2.1.0.tgz#31320ace16b4644316f6bf057531689c71e2aee1" + integrity sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ== dependencies: - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" -micromark-util-chunked@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/micromark-util-chunked/-/micromark-util-chunked-1.0.0.tgz#5b40d83f3d53b84c4c6bce30ed4257e9a4c79d06" - integrity sha512-5e8xTis5tEZKgesfbQMKRCyzvffRRUX+lK/y+DvsMFdabAicPkkZV6gO+FEWi9RfuKKoxxPwNL+dFF0SMImc1g== +micromark-util-chunked@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/micromark-util-chunked/-/micromark-util-chunked-2.0.0.tgz#e51f4db85fb203a79dbfef23fd41b2f03dc2ef89" + integrity sha512-anK8SWmNphkXdaKgz5hJvGa7l00qmcaUQoMYsBwDlSKFKjc6gjGXPDw3FNL3Nbwq5L8gE+RCbGqTw49FK5Qyvg== dependencies: - micromark-util-symbol "^1.0.0" + micromark-util-symbol "^2.0.0" -micromark-util-classify-character@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/micromark-util-classify-character/-/micromark-util-classify-character-1.0.0.tgz#cbd7b447cb79ee6997dd274a46fc4eb806460a20" - integrity sha512-F8oW2KKrQRb3vS5ud5HIqBVkCqQi224Nm55o5wYLzY/9PwHGXC01tr3d7+TqHHz6zrKQ72Okwtvm/xQm6OVNZA== +micromark-util-classify-character@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/micromark-util-classify-character/-/micromark-util-classify-character-2.0.0.tgz#8c7537c20d0750b12df31f86e976d1d951165f34" + integrity sha512-S0ze2R9GH+fu41FA7pbSqNWObo/kzwf8rN/+IGlW/4tC6oACOs8B++bh+i9bVyNnwCcuksbFwsBme5OCKXCwIw== dependencies: - micromark-util-character "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" + micromark-util-character "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" -micromark-util-combine-extensions@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/micromark-util-combine-extensions/-/micromark-util-combine-extensions-1.0.0.tgz#91418e1e74fb893e3628b8d496085639124ff3d5" - integrity sha512-J8H058vFBdo/6+AsjHp2NF7AJ02SZtWaVUjsayNFeAiydTxUwViQPxN0Hf8dp4FmCQi0UUFovFsEyRSUmFH3MA== +micromark-util-combine-extensions@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.0.tgz#75d6ab65c58b7403616db8d6b31315013bfb7ee5" + integrity sha512-vZZio48k7ON0fVS3CUgFatWHoKbbLTK/rT7pzpJ4Bjp5JjkZeasRfrS9wsBdDJK2cJLHMckXZdzPSSr1B8a4oQ== dependencies: - micromark-util-chunked "^1.0.0" - micromark-util-types "^1.0.0" + micromark-util-chunked "^2.0.0" + micromark-util-types "^2.0.0" -micromark-util-decode-numeric-character-reference@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-1.0.0.tgz#dcc85f13b5bd93ff8d2868c3dba28039d490b946" - integrity sha512-OzO9AI5VUtrTD7KSdagf4MWgHMtET17Ua1fIpXTpuhclCqD8egFWo85GxSGvxgkGS74bEahvtM0WP0HjvV0e4w== +micromark-util-decode-numeric-character-reference@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.1.tgz#2698bbb38f2a9ba6310e359f99fcb2b35a0d2bd5" + integrity sha512-bmkNc7z8Wn6kgjZmVHOX3SowGmVdhYS7yBpMnuMnPzDq/6xwVA604DuOXMZTO1lvq01g+Adfa0pE2UKGlxL1XQ== dependencies: - micromark-util-symbol "^1.0.0" + micromark-util-symbol "^2.0.0" -micromark-util-decode-string@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/micromark-util-decode-string/-/micromark-util-decode-string-1.0.2.tgz#942252ab7a76dec2dbf089cc32505ee2bc3acf02" - integrity sha512-DLT5Ho02qr6QWVNYbRZ3RYOSSWWFuH3tJexd3dgN1odEuPNxCngTCXJum7+ViRAd9BbdxCvMToPOD/IvVhzG6Q== +micromark-util-decode-string@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/micromark-util-decode-string/-/micromark-util-decode-string-2.0.0.tgz#7dfa3a63c45aecaa17824e656bcdb01f9737154a" + integrity sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA== dependencies: decode-named-character-reference "^1.0.0" - micromark-util-character "^1.0.0" - micromark-util-decode-numeric-character-reference "^1.0.0" - micromark-util-symbol "^1.0.0" + micromark-util-character "^2.0.0" + micromark-util-decode-numeric-character-reference "^2.0.0" + micromark-util-symbol "^2.0.0" -micromark-util-encode@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/micromark-util-encode/-/micromark-util-encode-1.0.1.tgz#2c1c22d3800870ad770ece5686ebca5920353383" - integrity sha512-U2s5YdnAYexjKDel31SVMPbfi+eF8y1U4pfiRW/Y8EFVCy/vgxk/2wWTxzcqE71LHtCuCzlBDRU2a5CQ5j+mQA== +micromark-util-encode@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/micromark-util-encode/-/micromark-util-encode-2.0.0.tgz#0921ac7953dc3f1fd281e3d1932decfdb9382ab1" + integrity sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA== -micromark-util-html-tag-name@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/micromark-util-html-tag-name/-/micromark-util-html-tag-name-1.1.0.tgz#eb227118befd51f48858e879b7a419fc0df20497" - integrity sha512-BKlClMmYROy9UiV03SwNmckkjn8QHVaWkqoAqzivabvdGcwNGMMMH/5szAnywmsTBUzDsU57/mFi0sp4BQO6dA== +micromark-util-html-tag-name@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.0.tgz#ae34b01cbe063363847670284c6255bb12138ec4" + integrity sha512-xNn4Pqkj2puRhKdKTm8t1YHC/BAjx6CEwRFXntTaRf/x16aqka6ouVoutm+QdkISTlT7e2zU7U4ZdlDLJd2Mcw== -micromark-util-normalize-identifier@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-1.0.0.tgz#4a3539cb8db954bbec5203952bfe8cedadae7828" - integrity sha512-yg+zrL14bBTFrQ7n35CmByWUTFsgst5JhA4gJYoty4Dqzj4Z4Fr/DHekSS5aLfH9bdlfnSvKAWsAgJhIbogyBg== +micromark-util-normalize-identifier@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.0.tgz#91f9a4e65fe66cc80c53b35b0254ad67aa431d8b" + integrity sha512-2xhYT0sfo85FMrUPtHcPo2rrp1lwbDEEzpx7jiH2xXJLqBuy4H0GgXk5ToU8IEwoROtXuL8ND0ttVa4rNqYK3w== dependencies: - micromark-util-symbol "^1.0.0" + micromark-util-symbol "^2.0.0" -micromark-util-resolve-all@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/micromark-util-resolve-all/-/micromark-util-resolve-all-1.0.0.tgz#a7c363f49a0162e931960c44f3127ab58f031d88" - integrity sha512-CB/AGk98u50k42kvgaMM94wzBqozSzDDaonKU7P7jwQIuH2RU0TeBqGYJz2WY1UdihhjweivStrJ2JdkdEmcfw== +micromark-util-resolve-all@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.0.tgz#189656e7e1a53d0c86a38a652b284a252389f364" + integrity sha512-6KU6qO7DZ7GJkaCgwBNtplXCvGkJToU86ybBAUdavvgsCiG8lSSvYxr9MhwmQ+udpzywHsl4RpGJsYWG1pDOcA== dependencies: - micromark-util-types "^1.0.0" + micromark-util-types "^2.0.0" -micromark-util-sanitize-uri@^1.0.0, micromark-util-sanitize-uri@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.1.0.tgz#f12e07a85106b902645e0364feb07cf253a85aee" - integrity sha512-RoxtuSCX6sUNtxhbmsEFQfWzs8VN7cTctmBPvYivo98xb/kDEoTCtJQX5wyzIYEmk/lvNFTat4hL8oW0KndFpg== +micromark-util-sanitize-uri@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.0.tgz#ec8fbf0258e9e6d8f13d9e4770f9be64342673de" + integrity sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw== dependencies: - micromark-util-character "^1.0.0" - micromark-util-encode "^1.0.0" - micromark-util-symbol "^1.0.0" + micromark-util-character "^2.0.0" + micromark-util-encode "^2.0.0" + micromark-util-symbol "^2.0.0" -micromark-util-subtokenize@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/micromark-util-subtokenize/-/micromark-util-subtokenize-1.0.2.tgz#ff6f1af6ac836f8bfdbf9b02f40431760ad89105" - integrity sha512-d90uqCnXp/cy4G881Ub4psE57Sf8YD0pim9QdjCRNjfas2M1u6Lbt+XZK9gnHL2XFhnozZiEdCa9CNfXSfQ6xA== +micromark-util-subtokenize@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/micromark-util-subtokenize/-/micromark-util-subtokenize-2.0.1.tgz#76129c49ac65da6e479c09d0ec4b5f29ec6eace5" + integrity sha512-jZNtiFl/1aY73yS3UGQkutD0UbhTt68qnRpw2Pifmz5wV9h8gOVsN70v+Lq/f1rKaU/W8pxRe8y8Q9FX1AOe1Q== dependencies: - micromark-util-chunked "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - uvu "^0.5.0" + devlop "^1.0.0" + micromark-util-chunked "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" -micromark-util-symbol@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/micromark-util-symbol/-/micromark-util-symbol-1.0.1.tgz#b90344db62042ce454f351cf0bebcc0a6da4920e" - integrity sha512-oKDEMK2u5qqAptasDAwWDXq0tG9AssVwAx3E9bBF3t/shRIGsWIRG+cGafs2p/SnDSOecnt6hZPCE2o6lHfFmQ== +micromark-util-symbol@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz#12225c8f95edf8b17254e47080ce0862d5db8044" + integrity sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw== -micromark-util-types@^1.0.0, micromark-util-types@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/micromark-util-types/-/micromark-util-types-1.0.2.tgz#f4220fdb319205812f99c40f8c87a9be83eded20" - integrity sha512-DCfg/T8fcrhrRKTPjRrw/5LLvdGV7BHySf/1LOZx7TzWZdYRjogNtyNq885z3nNallwr3QUKARjqvHqX1/7t+w== +micromark-util-types@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/micromark-util-types/-/micromark-util-types-2.0.0.tgz#63b4b7ffeb35d3ecf50d1ca20e68fc7caa36d95e" + integrity sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w== -micromark@^3.0.0: - version "3.0.10" - resolved "https://registry.yarnpkg.com/micromark/-/micromark-3.0.10.tgz#1eac156f0399d42736458a14b0ca2d86190b457c" - integrity sha512-ryTDy6UUunOXy2HPjelppgJ2sNfcPz1pLlMdA6Rz9jPzhLikWXv/irpWV/I2jd68Uhmny7hHxAlAhk4+vWggpg== +micromark@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/micromark/-/micromark-4.0.0.tgz#84746a249ebd904d9658cfabc1e8e5f32cbc6249" + integrity sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ== dependencies: "@types/debug" "^4.0.0" debug "^4.0.0" decode-named-character-reference "^1.0.0" - micromark-core-commonmark "^1.0.1" - micromark-factory-space "^1.0.0" - micromark-util-character "^1.0.0" - micromark-util-chunked "^1.0.0" - micromark-util-combine-extensions "^1.0.0" - micromark-util-decode-numeric-character-reference "^1.0.0" - micromark-util-encode "^1.0.0" - micromark-util-normalize-identifier "^1.0.0" - micromark-util-resolve-all "^1.0.0" - micromark-util-sanitize-uri "^1.0.0" - micromark-util-subtokenize "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.1" - uvu "^0.5.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" micromatch@4.0.2: version "4.0.2" @@ -13925,12 +14080,15 @@ node-cron@^3.0.2: dependencies: uuid "8.3.2" -node-emoji@^1.11.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-1.11.0.tgz#69a0150e6946e2f115e9d7ea4df7971e2628301c" - integrity sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A== +node-emoji@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-2.1.3.tgz#93cfabb5cc7c3653aa52f29d6ffb7927d8047c06" + integrity sha512-E2WEOVsgs7O16zsURJ/eH8BqhF029wGpEOnv7Urwdo2wmQanOACwJQh0devF9D9RhoZru0+9JXIS0dBXIAz+lA== dependencies: - lodash "^4.17.21" + "@sindresorhus/is" "^4.6.0" + char-regex "^1.0.2" + emojilib "^2.4.0" + skin-tone "^2.0.0" node-fetch-h2@^2.3.0: version "2.3.0" @@ -14557,9 +14715,9 @@ parse-entities@^2.0.0: is-hexadecimal "^1.0.0" parse-entities@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-4.0.0.tgz#f67c856d4e3fe19b1a445c3fabe78dcdc1053eeb" - integrity sha512-5nk9Fn03x3rEhGaX1FU6IDwG/k+GxLXlFAkgrbM1asuAFl3BhdQWvASaIsmwWypRNcZKHPYnIuOSfIWEyEQnPQ== + version "4.0.1" + resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-4.0.1.tgz#4e2a01111fb1c986549b944af39eeda258fc9e4e" + integrity sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w== dependencies: "@types/unist" "^2.0.0" character-entities "^2.0.0" @@ -14620,7 +14778,7 @@ parse5@^5.1.1: resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178" integrity sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug== -parse5@^6.0.0, parse5@^6.0.1: +parse5@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== @@ -15106,7 +15264,7 @@ prompts@^2.0.1: kleur "^3.0.2" sisteransi "^1.0.0" -prop-types@^15.0.0, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: +prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== @@ -15123,9 +15281,9 @@ property-information@^5.0.0: xtend "^4.0.0" property-information@^6.0.0: - version "6.1.1" - resolved "https://registry.yarnpkg.com/property-information/-/property-information-6.1.1.tgz#5ca85510a3019726cb9afed4197b7b8ac5926a22" - integrity sha512-hrzC564QIl0r0vy4l6MvRLhafmUowhO/O3KgVSoXIbbA2Sz4j8HGpJc6T2cubRVwMwpdiG/vKGfhT4IixmKN9w== + version "6.5.0" + resolved "https://registry.yarnpkg.com/property-information/-/property-information-6.5.0.tgz#6212fbb52ba757e92ef4fb9d657563b933b7ffec" + integrity sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig== proxy-addr@~2.0.7: version "2.0.7" @@ -15458,26 +15616,21 @@ react-lifecycles-compat@^3.0.4: resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== -react-markdown@^8.0.7: - version "8.0.7" - resolved "https://registry.yarnpkg.com/react-markdown/-/react-markdown-8.0.7.tgz#c8dbd1b9ba5f1c5e7e5f2a44de465a3caafdf89b" - integrity sha512-bvWbzG4MtOU62XqBx3Xx+zB2raaFFsq4mYiAzfjXJMEz2sixgeAfraA3tvzULF02ZdOMUOKTBFFaZJDDrq+BJQ== - dependencies: - "@types/hast" "^2.0.0" - "@types/prop-types" "^15.0.0" - "@types/unist" "^2.0.0" - comma-separated-tokens "^2.0.0" - hast-util-whitespace "^2.0.0" - prop-types "^15.0.0" - property-information "^6.0.0" - react-is "^18.0.0" - remark-parse "^10.0.0" - remark-rehype "^10.0.0" - space-separated-tokens "^2.0.0" - style-to-object "^0.4.0" - unified "^10.0.0" - unist-util-visit "^4.0.0" - vfile "^5.0.0" +react-markdown@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/react-markdown/-/react-markdown-9.0.1.tgz#c05ddbff67fd3b3f839f8c648e6fb35d022397d1" + integrity sha512-186Gw/vF1uRkydbsOIkcGXw7aHq0sZOCRFFjGrr7b9+nVZg4UfA4enXCaxm4fUzecU38sWfrNDitGhshuU7rdg== + dependencies: + "@types/hast" "^3.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" react-multiline-clamp@^2.0.0: version "2.0.0" @@ -15927,69 +16080,55 @@ regexp.prototype.flags@^1.3.0, regexp.prototype.flags@^1.4.1, regexp.prototype.f es-errors "^1.3.0" set-function-name "^2.0.1" -rehype-katex@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/rehype-katex/-/rehype-katex-6.0.2.tgz#20197bbc10bdf79f6b999bffa6689d7f17226c35" - integrity sha512-C4gDAlS1+l0hJqctyiU64f9CvT00S03qV1T6HiMzbSuLBgWUtcqydWHY9OpKrm0SpkK16FNd62CDKyWLwV2ppg== - dependencies: - "@types/hast" "^2.0.0" - "@types/katex" "^0.11.0" - hast-util-to-text "^3.1.0" - katex "^0.15.0" - rehype-parse "^8.0.0" - unified "^10.0.0" - unist-util-remove-position "^4.0.0" - unist-util-visit "^4.0.0" - -rehype-parse@^8.0.0: - version "8.0.4" - resolved "https://registry.yarnpkg.com/rehype-parse/-/rehype-parse-8.0.4.tgz#3d17c9ff16ddfef6bbcc8e6a25a99467b482d688" - integrity sha512-MJJKONunHjoTh4kc3dsM1v3C9kGrrxvA3U8PxZlP2SjH8RNUSrb+lF7Y0KVaUDnGH2QZ5vAn7ulkiajM9ifuqg== - dependencies: - "@types/hast" "^2.0.0" - hast-util-from-parse5 "^7.0.0" - parse5 "^6.0.0" - unified "^10.0.0" - -rehype-raw@^6.1.1: - version "6.1.1" - resolved "https://registry.yarnpkg.com/rehype-raw/-/rehype-raw-6.1.1.tgz#81bbef3793bd7abacc6bf8335879d1b6c868c9d4" - integrity sha512-d6AKtisSRtDRX4aSPsJGTfnzrX2ZkHQLE5kiUuGOeEoLpbEulFF4hj0mLPbsa+7vmguDKOVVEQdHKDSwoaIDsQ== +rehype-katex@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/rehype-katex/-/rehype-katex-7.0.0.tgz#f5e9e2825981175a7b0a4d58ed9816c33576dfed" + integrity sha512-h8FPkGE00r2XKU+/acgqwWUlyzve1IiOKwsEkg4pDL3k48PiE0Pt+/uLtVHDVkN1yA4iurZN6UES8ivHVEQV6Q== + dependencies: + "@types/hast" "^3.0.0" + "@types/katex" "^0.16.0" + hast-util-from-html-isomorphic "^2.0.0" + hast-util-to-text "^4.0.0" + katex "^0.16.0" + unist-util-visit-parents "^6.0.0" + vfile "^6.0.0" + +rehype-raw@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/rehype-raw/-/rehype-raw-7.0.0.tgz#59d7348fd5dbef3807bbaa1d443efd2dd85ecee4" + integrity sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww== dependencies: - "@types/hast" "^2.0.0" - hast-util-raw "^7.2.0" - unified "^10.0.0" + "@types/hast" "^3.0.0" + hast-util-raw "^9.0.0" + vfile "^6.0.0" -rehype-rewrite@^3.0.6: - version "3.0.6" - resolved "https://registry.yarnpkg.com/rehype-rewrite/-/rehype-rewrite-3.0.6.tgz#21e86982c7f2c169121bf10dd191f3768c6a6b29" - integrity sha512-REDTNCvsKcAazy8IQWzKp66AhSUDSOIKssSCqNqCcT9sN7JCwAAm3mWGTUdUzq80ABuy8d0D6RBwbnewu1aY1g== +rehype-rewrite@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/rehype-rewrite/-/rehype-rewrite-4.0.2.tgz#7b094bb586dfda83333994cb3dbb01cb1e8c361d" + integrity sha512-rjLJ3z6fIV11phwCqHp/KRo8xuUCO8o9bFJCNw5o6O2wlLk6g8r323aRswdGBQwfXPFYeSuZdAjp4tzo6RGqEg== dependencies: - hast-util-select "~5.0.1" - unified "~10.1.1" - unist-util-visit "~4.1.0" + hast-util-select "^6.0.0" + unified "^11.0.3" + unist-util-visit "^5.0.0" -rehype-sanitize@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/rehype-sanitize/-/rehype-sanitize-5.0.1.tgz#dac01a7417bdd329260c74c74449697b4be5eb56" - integrity sha512-da/jIOjq8eYt/1r9GN6GwxIR3gde7OZ+WV8pheu1tL8K0D9KxM2AyMh+UEfke+FfdM3PvGHeYJU0Td5OWa7L5A== +rehype-sanitize@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/rehype-sanitize/-/rehype-sanitize-6.0.0.tgz#16e95f4a67a69cbf0f79e113c8e0df48203db73c" + integrity sha512-CsnhKNsyI8Tub6L4sm5ZFsme4puGfc6pYylvXo1AeqaGbjOYyzNv3qZPwvs0oMJ39eryyeOdmxwUIo94IpEhqg== dependencies: - "@types/hast" "^2.0.0" - hast-util-sanitize "^4.0.0" - unified "^10.0.0" + "@types/hast" "^3.0.0" + hast-util-sanitize "^5.0.0" -rehype-slug@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/rehype-slug/-/rehype-slug-5.0.1.tgz#6e732d0c55b3b1e34187e74b7363fb53229e5f52" - integrity sha512-X5v3wV/meuOX9NFcGhJvUpEjIvQl2gDvjg3z40RVprYFt7q3th4qMmYLULiu3gXvbNX1ppx+oaa6JyY1W67pTA== +rehype-slug@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/rehype-slug/-/rehype-slug-6.0.0.tgz#1d21cf7fc8a83ef874d873c15e6adaee6344eaf1" + integrity sha512-lWyvf/jwu+oS5+hL5eClVd3hNdmwM1kAC0BUvEGD19pajQMIzcNUd/k9GsfQ+FfECvX+JE+e9/btsKH0EjJT6A== dependencies: - "@types/hast" "^2.0.0" - github-slugger "^1.1.1" - hast-util-has-property "^2.0.0" - hast-util-heading-rank "^2.0.0" - hast-util-to-string "^2.0.0" - unified "^10.0.0" - unist-util-visit "^4.0.0" + "@types/hast" "^3.0.0" + github-slugger "^2.0.0" + hast-util-heading-rank "^3.0.0" + hast-util-to-string "^3.0.0" + unist-util-visit "^5.0.0" rehype-toc@^3.0.2: version "3.0.2" @@ -15998,109 +16137,114 @@ rehype-toc@^3.0.2: dependencies: "@jsdevtools/rehype-toc" "3.0.2" -remark-breaks@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/remark-breaks/-/remark-breaks-3.0.2.tgz#f466b9d3474d7323146c0149fc1496dabadd908e" - integrity sha512-x96YDJ9X+Ry0/JNZFKfr1hpcAKvGYWfUTszxY9RbxKEqq6uzPPoLCuHdZsLPZZUdAv3nCROyc7FPrQLWr2rxyw== +remark-breaks@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/remark-breaks/-/remark-breaks-4.0.0.tgz#dcc19a2891733906f3b97eaa8acb8621e8da8852" + integrity sha512-IjEjJOkH4FuJvHZVIW0QCDWxcG96kCq7An/KVH2NfJe6rKZU2AsHeB3OEjPNRxi4QC34Xdx7I2KGYn6IpT7gxQ== dependencies: - "@types/mdast" "^3.0.0" - unified "^10.0.0" - unist-util-visit "^4.0.0" + "@types/mdast" "^4.0.0" + mdast-util-newline-to-break "^2.0.0" + unified "^11.0.0" -remark-emoji@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/remark-emoji/-/remark-emoji-3.0.2.tgz#786e88af1ecae682d74d7e1219989f34708205da" - integrity sha512-hEgxEv2sBtvhT3tNG/tQeeFY3EbslftaOoG14dDZndLo25fWJ6Fbg4ukFbIotOWWrfXyASjXjyHT+6n366k3mg== +remark-emoji@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/remark-emoji/-/remark-emoji-5.0.0.tgz#14bd520b765cea3f00228258926ed59ad8125729" + integrity sha512-LCVYkHja10TXgrpHDB4AGYmYv9GtqiSebjyhK8aihuzJlZvrvkE2cndQmnK40Ch5ez/WtujcrcDa7nXVH6Jwcg== dependencies: - emoticon "^4.0.0" - node-emoji "^1.11.0" - unist-util-visit "^4.1.0" + "@types/mdast" "^4.0.4" + emoticon "^4.0.1" + mdast-util-find-and-replace "^3.0.1" + node-emoji "^2.1.3" + unified "^11.0.4" -remark-frontmatter@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/remark-frontmatter/-/remark-frontmatter-4.0.1.tgz#84560f7ccef114ef076d3d3735be6d69f8922309" - integrity sha512-38fJrB0KnmD3E33a5jZC/5+gGAC2WKNiPw1/fdXJvijBlhA7RCsvJklrYJakS0HedninvaCYW8lQGf9C918GfA== +remark-frontmatter@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/remark-frontmatter/-/remark-frontmatter-5.0.0.tgz#b68d61552a421ec412c76f4f66c344627dc187a2" + integrity sha512-XTFYvNASMe5iPN0719nPrdItC9aU0ssC4v14mH1BCi1u0n1gAocqcujWUrByftZTbLhRtiKRyjYTSIOcr69UVQ== dependencies: - "@types/mdast" "^3.0.0" - mdast-util-frontmatter "^1.0.0" - micromark-extension-frontmatter "^1.0.0" - unified "^10.0.0" + "@types/mdast" "^4.0.0" + mdast-util-frontmatter "^2.0.0" + micromark-extension-frontmatter "^2.0.0" + unified "^11.0.0" -remark-gfm@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/remark-gfm/-/remark-gfm-3.0.1.tgz#0b180f095e3036545e9dddac0e8df3fa5cfee54f" - integrity sha512-lEFDoi2PICJyNrACFOfDD3JlLkuSbOa5Wd8EPt06HUdptv8Gn0bxYTdbU/XXQ3swAPkEaGxxPN9cbnMHvVu1Ig== +remark-gfm@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/remark-gfm/-/remark-gfm-4.0.0.tgz#aea777f0744701aa288b67d28c43565c7e8c35de" + integrity sha512-U92vJgBPkbw4Zfu/IiW2oTZLSL3Zpv+uI7My2eq8JxKgqraFdU8YUGicEJCEgSbeaG+QDFqIcwwfMTOEelPxuA== dependencies: - "@types/mdast" "^3.0.0" - mdast-util-gfm "^2.0.0" - micromark-extension-gfm "^2.0.0" - unified "^10.0.0" + "@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" -remark-math@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/remark-math/-/remark-math-5.1.1.tgz#459e798d978d4ca032e745af0bac81ddcdf94964" - integrity sha512-cE5T2R/xLVtfFI4cCePtiRn+e6jKMtFDR3P8V3qpv8wpKjwvHoBA4eJzvX+nVrnlNy0911bdGmuspCSwetfYHw== +remark-math@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/remark-math/-/remark-math-6.0.0.tgz#0acdf74675f1c195fea6efffa78582f7ed7fc0d7" + integrity sha512-MMqgnP74Igy+S3WwnhQ7kqGlEerTETXMvJhrUzDikVZ2/uogJCb+WHUg97hK9/jcfc0dkD73s3LN8zU49cTEtA== dependencies: - "@types/mdast" "^3.0.0" - mdast-util-math "^2.0.0" - micromark-extension-math "^2.0.0" - unified "^10.0.0" + "@types/mdast" "^4.0.0" + mdast-util-math "^3.0.0" + micromark-extension-math "^3.0.0" + unified "^11.0.0" -remark-parse@^10.0.0: - version "10.0.1" - resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-10.0.1.tgz#6f60ae53edbf0cf38ea223fe643db64d112e0775" - integrity sha512-1fUyHr2jLsVOkhbvPRBJ5zTKZZyD6yZzYaWCS6BPBdQ8vEMBCH+9zNCDA6tET/zHCi/jLqjCWtlJZUPk+DbnFw== +remark-parse@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-11.0.0.tgz#aa60743fcb37ebf6b069204eb4da304e40db45a1" + integrity sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA== dependencies: - "@types/mdast" "^3.0.0" - mdast-util-from-markdown "^1.0.0" - unified "^10.0.0" + "@types/mdast" "^4.0.0" + mdast-util-from-markdown "^2.0.0" + micromark-util-types "^2.0.0" + unified "^11.0.0" -remark-rehype@^10.0.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/remark-rehype/-/remark-rehype-10.1.0.tgz#32dc99d2034c27ecaf2e0150d22a6dcccd9a6279" - integrity sha512-EFmR5zppdBp0WQeDVZ/b66CWJipB2q2VLNFMabzDSGR66Z2fQii83G5gTBbgGEnEEA0QRussvrFHxk1HWGJskw== +remark-rehype@^11.0.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/remark-rehype/-/remark-rehype-11.1.0.tgz#d5f264f42bcbd4d300f030975609d01a1697ccdc" + integrity sha512-z3tJrAs2kIs1AqIIy6pzHmAHlF1hWQ+OdY4/hv+Wxe35EhyLKcajL33iUEn3ScxtFox9nUvRufR/Zre8Q08H/g== dependencies: - "@types/hast" "^2.0.0" - "@types/mdast" "^3.0.0" - mdast-util-to-hast "^12.1.0" - unified "^10.0.0" + "@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" -remark-stringify@^10.0.0: - version "10.0.2" - resolved "https://registry.yarnpkg.com/remark-stringify/-/remark-stringify-10.0.2.tgz#50414a6983f5008eb9e72eed05f980582d1f69d7" - integrity sha512-6wV3pvbPvHkbNnWB0wdDvVFHOe1hBRAx1Q/5g/EpH4RppAII6J8Gnwe7VbHuXaoKIF6LAg6ExTel/+kNqSQ7lw== +remark-stringify@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/remark-stringify/-/remark-stringify-11.0.0.tgz#4c5b01dd711c269df1aaae11743eb7e2e7636fd3" + integrity sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw== dependencies: - "@types/mdast" "^3.0.0" - mdast-util-to-markdown "^1.0.0" - unified "^10.0.0" + "@types/mdast" "^4.0.0" + mdast-util-to-markdown "^2.0.0" + unified "^11.0.0" -remark-toc@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/remark-toc/-/remark-toc-8.0.1.tgz#f3e07ea13734f1c531e3d3460e58babe31d17cd7" - integrity sha512-7he2VOm/cy13zilnOTZcyAoyoolV26ULlon6XyCFU+vG54Z/LWJnwphj/xKIDLOt66QmJUgTyUvLVHi2aAElyg== +remark-toc@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/remark-toc/-/remark-toc-9.0.0.tgz#7197950fe218a725e3f122a48495cb0dbd4026d0" + integrity sha512-KJ9txbo33GjDAV1baHFze7ij4G8c7SGYoY8Kzsm2gzFpbhL/bSoVpMMzGa3vrNDSWASNd/3ppAqL7cP2zD6JIA== dependencies: - "@types/mdast" "^3.0.0" - mdast-util-toc "^6.0.0" - unified "^10.0.0" + "@types/mdast" "^4.0.0" + mdast-util-toc "^7.0.0" -remark-wiki-link@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/remark-wiki-link/-/remark-wiki-link-1.0.4.tgz#f3ac7688ce822e494bb3732a5957082293a59a42" - integrity sha512-kLgRlXn5cBMa3Fa+OgcI6L4yyYdI74TdIiynBtOvrZN9q7o4mDCYrfAAt7VgLvQyuLBrPARPM1g67ZuAWA1yFg== +remark-wiki-link@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/remark-wiki-link/-/remark-wiki-link-2.0.1.tgz#52ffdcfe16e3e018874b890387ea02668e882d10" + integrity sha512-F8Eut1E7GWfFm4ZDTI6/4ejeZEHZgnVk6E933Yqd/ssYsc4AyI32aGakxwsGcEzbbE7dkWi1EfLlGAdGgOZOsA== dependencies: "@babel/runtime" "^7.4.4" - mdast-util-wiki-link "^0.0.2" + mdast-util-wiki-link "^0.1.2" micromark-extension-wiki-link "^0.0.4" -remark@^14.0.0: - version "14.0.2" - resolved "https://registry.yarnpkg.com/remark/-/remark-14.0.2.tgz#4a1833f7441a5c29e44b37bb1843fb820797b40f" - integrity sha512-A3ARm2V4BgiRXaUo5K0dRvJ1lbogrbXnhkJRmD0yw092/Yl0kOCZt1k9ZeElEwkZsWGsMumz6qL5MfNJH9nOBA== +remark@^15.0.1: + version "15.0.1" + resolved "https://registry.yarnpkg.com/remark/-/remark-15.0.1.tgz#ac7e7563260513b66426bc47f850e7aa5862c37c" + integrity sha512-Eht5w30ruCXgFmxVUSlNWQ9iiimq07URKeFS3hNc8cUWy1llX4KDWfyEDZRycMc+znsN9Ux5/tJ/BFdgdOwA3A== dependencies: - "@types/mdast" "^3.0.0" - remark-parse "^10.0.0" - remark-stringify "^10.0.0" - unified "^10.0.0" + "@types/mdast" "^4.0.0" + remark-parse "^11.0.0" + remark-stringify "^11.0.0" + unified "^11.0.0" remove-trailing-separator@^1.0.1: version "1.1.0" @@ -16805,6 +16949,13 @@ sisteransi@^1.0.0: resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.0.tgz#77d9622ff909080f1c19e5f4a1df0c1b0a27b88c" integrity sha512-N+z4pHB4AmUv0SjveWRd6q1Nj5w62m5jodv+GD8lvmbY/83T/rpbJGZOnK5T149OldDj4Db07BSv9xY4K6NTPQ== +skin-tone@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/skin-tone/-/skin-tone-2.0.0.tgz#4e3933ab45c0d4f4f781745d64b9f4c208e41237" + integrity sha512-kUMbT1oBJCpgrnKoSr0o6wPtvRWT9W9UKvGLwfJYO2WuahZRHOpEyL1ckyMGgMWh0UdpmaoFqKKD29WTomNEGA== + dependencies: + unicode-emoji-modifier-base "^1.0.0" + slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" @@ -17017,9 +17168,9 @@ space-separated-tokens@^1.0.0: integrity sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA== space-separated-tokens@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-2.0.1.tgz#43193cec4fb858a2ce934b7f98b7f2c18107098b" - integrity sha512-ekwEbFp5aqSPKaqeY1PGrlGQxPNaq+Cnx4+bE2D8sciBQrHpbwoBbawqTN2+6jPs9IdWxxiUcN0K2pkczD3zmw== + version "2.0.2" + resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz#1ecd9d2350a3844572c3f4a312bceb018348859f" + integrity sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q== sparse-bitfield@^3.0.3: version "3.0.3" @@ -17352,9 +17503,9 @@ string_decoder@~1.1.1: safe-buffer "~5.1.0" stringify-entities@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/stringify-entities/-/stringify-entities-4.0.3.tgz#cfabd7039d22ad30f3cc435b0ca2c1574fc88ef8" - integrity sha512-BP9nNHMhhfcMbiuQKCqMjhDP5yBCAxsPu4pHFFzJ6Alo9dZgY4VLDPutXqIjpRiMoKdp7Av85Gr73Q5uH9k7+g== + version "4.0.4" + resolved "https://registry.yarnpkg.com/stringify-entities/-/stringify-entities-4.0.4.tgz#b3b79ef5f277cc4ac73caeb0236c5ba939b3a4f3" + integrity sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg== dependencies: character-entities-html4 "^2.0.0" character-entities-legacy "^3.0.0" @@ -17457,19 +17608,12 @@ style-mod@^4.0.0: resolved "https://registry.yarnpkg.com/style-mod/-/style-mod-4.0.3.tgz#136c4abc905f82a866a18b39df4dc08ec762b1ad" integrity sha512-78Jv8kYJdjbvRwwijtCevYADfsI0lGzYJe4mMFdceO8l75DFFDoqBhR1jVDicDRRaX4//g1u9wKeo+ztc2h1Rw== -style-to-object@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/style-to-object/-/style-to-object-0.3.0.tgz#b1b790d205991cc783801967214979ee19a76e46" - integrity sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA== - dependencies: - inline-style-parser "0.1.1" - -style-to-object@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/style-to-object/-/style-to-object-0.4.1.tgz#53cf856f7cf7f172d72939d9679556469ba5de37" - integrity sha512-HFpbb5gr2ypci7Qw+IOhnP2zOU7e77b+rzM+wTzXzfi1PrtBCX0E7Pk4wL4iTLnhzZ+JgEGAhX81ebTg/aYjQw== +style-to-object@^1.0.0: + version "1.0.6" + resolved "https://registry.yarnpkg.com/style-to-object/-/style-to-object-1.0.6.tgz#0c28aed8be1813d166c60d962719b2907c26547b" + integrity sha512-khxq+Qm3xEyZfKd/y9L3oIWQimxuc4STrQKtQn8aSDRHb8mFgpukgX1hdzfrMEW6JCjyJ8p89x+IUMVnCBI1PA== dependencies: - inline-style-parser "0.1.1" + inline-style-parser "0.2.3" styled-jsx@5.1.1: version "5.1.1" @@ -18109,9 +18253,9 @@ trim-newlines@^3.0.0: integrity sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw== trough@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/trough/-/trough-2.1.0.tgz#0f7b511a4fde65a46f18477ab38849b22c554876" - integrity sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g== + version "2.2.0" + resolved "https://registry.yarnpkg.com/trough/-/trough-2.2.0.tgz#94a60bd6bd375c152c1df911a4b11d5b0256f50f" + integrity sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw== truncate-utf8-bytes@^1.0.0: version "1.0.2" @@ -18513,18 +18657,23 @@ undici@^5.5.1: dependencies: "@fastify/busboy" "^2.0.0" -unified@^10.0.0, unified@^10.1.2, unified@~10.1.1: - version "10.1.2" - resolved "https://registry.yarnpkg.com/unified/-/unified-10.1.2.tgz#b1d64e55dafe1f0b98bb6c719881103ecf6c86df" - integrity sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q== +unicode-emoji-modifier-base@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unicode-emoji-modifier-base/-/unicode-emoji-modifier-base-1.0.0.tgz#dbbd5b54ba30f287e2a8d5a249da6c0cef369459" + integrity sha512-yLSH4py7oFH3oG/9K+XWrz1pSi3dfUrWEnInbxMfArOfc1+33BlGPQtLsOYwvdMy11AwUBetYuaRxSPqgkq+8g== + +unified@^11.0.0, unified@^11.0.3, unified@^11.0.4: + version "11.0.4" + resolved "https://registry.yarnpkg.com/unified/-/unified-11.0.4.tgz#f4be0ac0fe4c88cb873687c07c64c49ed5969015" + integrity sha512-apMPnyLjAX+ty4OrNap7yumyVAMlKx5IWU2wlzzUdYJO9A8f1p9m/gywF/GM2ZDFcjQPrx59Mc90KwmxsoklxQ== dependencies: - "@types/unist" "^2.0.0" + "@types/unist" "^3.0.0" bail "^2.0.0" + devlop "^1.0.0" extend "^3.0.0" - is-buffer "^2.0.0" is-plain-obj "^4.0.0" trough "^2.0.0" - vfile "^5.0.0" + vfile "^6.0.0" union-value@^1.0.0: version "1.0.1" @@ -18557,18 +18706,13 @@ unique-string@^2.0.0: dependencies: crypto-random-string "^2.0.0" -unist-util-find-after@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/unist-util-find-after/-/unist-util-find-after-4.0.0.tgz#1101cebf5fed88ae3c6f3fa676e86fd5772a4f32" - integrity sha512-gfpsxKQde7atVF30n5Gff2fQhAc4/HTOV4CvkXpTg9wRfQhZWdXitpyXHWB6YcYgnsxLx+4gGHeVjCTAAp9sjw== +unist-util-find-after@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/unist-util-find-after/-/unist-util-find-after-5.0.0.tgz#3fccc1b086b56f34c8b798e1ff90b5c54468e896" + integrity sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ== dependencies: - "@types/unist" "^2.0.0" - unist-util-is "^5.0.0" - -unist-util-generated@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unist-util-generated/-/unist-util-generated-2.0.0.tgz#86fafb77eb6ce9bfa6b663c3f5ad4f8e56a60113" - integrity sha512-TiWE6DVtVe7Ye2QxOVW9kqybs6cZexNwTwSMVgkfjEReqy/xwGpAXb99OxktoWwmL+Z+Epb0Dn8/GNDYP1wnUw== + "@types/unist" "^3.0.0" + unist-util-is "^6.0.0" unist-util-is@^4.0.0: version "4.1.0" @@ -18580,20 +18724,27 @@ unist-util-is@^5.0.0: resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-5.1.1.tgz#e8aece0b102fa9bc097b0fef8f870c496d4a6236" integrity sha512-F5CZ68eYzuSvJjGhCLPL3cYx45IxkqXSetCcRgUXtbcm50X2L9oOWQlfUfDdAf+6Pd27YDblBfdtmsThXmwpbQ== -unist-util-position@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/unist-util-position/-/unist-util-position-4.0.3.tgz#5290547b014f6222dff95c48d5c3c13a88fadd07" - integrity sha512-p/5EMGIa1qwbXjA+QgcBXaPWjSnZfQ2Sc3yBEEfgPwsEmJd8Qh+DSk3LGnmOM4S1bY2C0AjmMnB8RuEYxpPwXQ== +unist-util-is@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-6.0.0.tgz#b775956486aff107a9ded971d996c173374be424" + integrity sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw== dependencies: - "@types/unist" "^2.0.0" + "@types/unist" "^3.0.0" -unist-util-remove-position@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/unist-util-remove-position/-/unist-util-remove-position-4.0.1.tgz#d5b46a7304ac114c8d91990ece085ca7c2c135c8" - integrity sha512-0yDkppiIhDlPrfHELgB+NLQD5mfjup3a8UYclHruTJWmY74je8g+CIFr79x5f6AkmzSwlvKLbs63hC0meOMowQ== +unist-util-position@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/unist-util-position/-/unist-util-position-5.0.0.tgz#678f20ab5ca1207a97d7ea8a388373c9cf896be4" + integrity sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA== dependencies: - "@types/unist" "^2.0.0" - unist-util-visit "^4.0.0" + "@types/unist" "^3.0.0" + +unist-util-remove-position@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/unist-util-remove-position/-/unist-util-remove-position-5.0.0.tgz#fea68a25658409c9460408bc6b4991b965b52163" + integrity sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q== + dependencies: + "@types/unist" "^3.0.0" + unist-util-visit "^5.0.0" unist-util-stringify-position@^3.0.0: version "3.0.2" @@ -18602,6 +18753,13 @@ unist-util-stringify-position@^3.0.0: dependencies: "@types/unist" "^2.0.0" +unist-util-stringify-position@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz#449c6e21a880e0855bf5aabadeb3a740314abac2" + integrity sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ== + dependencies: + "@types/unist" "^3.0.0" + unist-util-visit-parents@^3.0.0: version "3.1.1" resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz#65a6ce698f78a6b0f56aa0e88f13801886cdaef6" @@ -18610,15 +18768,7 @@ unist-util-visit-parents@^3.0.0: "@types/unist" "^2.0.0" unist-util-is "^4.0.0" -unist-util-visit-parents@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-4.1.1.tgz#e83559a4ad7e6048a46b1bdb22614f2f3f4724f2" - integrity sha512-1xAFJXAKpnnJl8G7K5KgU7FY55y3GcLIXqkzUj5QF/QVP7biUm0K0O2oqVkYsdjzJKifYeWn9+o6piAK2hGSHw== - dependencies: - "@types/unist" "^2.0.0" - unist-util-is "^5.0.0" - -unist-util-visit-parents@^5.0.0, unist-util-visit-parents@^5.1.1: +unist-util-visit-parents@^5.0.0: version "5.1.1" resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-5.1.1.tgz#868f353e6fce6bf8fa875b251b0f4fec3be709bb" integrity sha512-gks4baapT/kNRaWxuGkl5BIhoanZo7sC/cUT/JToSRNL1dYoXRFl75d++NkjYk4TAu2uv2Px+l8guMajogeuiw== @@ -18626,6 +18776,14 @@ unist-util-visit-parents@^5.0.0, unist-util-visit-parents@^5.1.1: "@types/unist" "^2.0.0" unist-util-is "^5.0.0" +unist-util-visit-parents@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz#4d5f85755c3b8f0dc69e21eca5d6d82d22162815" + integrity sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw== + dependencies: + "@types/unist" "^3.0.0" + unist-util-is "^6.0.0" + unist-util-visit@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-2.0.3.tgz#c3703893146df47203bb8a9795af47d7b971208c" @@ -18635,23 +18793,14 @@ unist-util-visit@^2.0.2: unist-util-is "^4.0.0" unist-util-visit-parents "^3.0.0" -unist-util-visit@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-3.1.0.tgz#9420d285e1aee938c7d9acbafc8e160186dbaf7b" - integrity sha512-Szoh+R/Ll68QWAyQyZZpQzZQm2UPbxibDvaY8Xc9SUtYgPsDzx5AWSk++UUt2hJuow8mvwR+rG+LQLw+KsuAKA== - dependencies: - "@types/unist" "^2.0.0" - unist-util-is "^5.0.0" - unist-util-visit-parents "^4.0.0" - -unist-util-visit@^4.0.0, unist-util-visit@^4.1.0, unist-util-visit@~4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-4.1.1.tgz#1c4842d70bd3df6cc545276f5164f933390a9aad" - integrity sha512-n9KN3WV9k4h1DxYR1LoajgN93wpEi/7ZplVe02IoB4gH5ctI1AaF2670BLHQYbwj+pY83gFtyeySFiyMHJklrg== +unist-util-visit@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-5.0.0.tgz#a7de1f31f72ffd3519ea71814cccf5fd6a9217d6" + integrity sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg== dependencies: - "@types/unist" "^2.0.0" - unist-util-is "^5.0.0" - unist-util-visit-parents "^5.1.1" + "@types/unist" "^3.0.0" + unist-util-is "^6.0.0" + unist-util-visit-parents "^6.0.0" universal-bunyan@^0.9.2: version "0.9.2" @@ -18896,13 +19045,13 @@ verror@^1.10.1, verror@^1.8.1: core-util-is "1.0.2" extsprintf "^1.2.0" -vfile-location@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-4.0.1.tgz#06f2b9244a3565bef91f099359486a08b10d3a95" - integrity sha512-JDxPlTbZrZCQXogGheBHjbRWjESSPEak770XwWPfw5mTc1v1nWGLB/apzZxsx8a0SJVfF8HK8ql8RD308vXRUw== +vfile-location@^5.0.0: + version "5.0.2" + resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-5.0.2.tgz#220d9ca1ab6f8b2504a4db398f7ebc149f9cb464" + integrity sha512-NXPYyxyBSH7zB5U6+3uDdd6Nybz6o6/od9rk8bp9H8GR3L+cm/fC0uUTbqBmUTnMCUDslAGBOIKNfvvb+gGlDg== dependencies: - "@types/unist" "^2.0.0" - vfile "^5.0.0" + "@types/unist" "^3.0.0" + vfile "^6.0.0" vfile-message@^3.0.0: version "3.1.2" @@ -18912,7 +19061,15 @@ vfile-message@^3.0.0: "@types/unist" "^2.0.0" unist-util-stringify-position "^3.0.0" -vfile@^5.0.0, vfile@^5.1.0: +vfile-message@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-4.0.2.tgz#c883c9f677c72c166362fd635f21fc165a7d1181" + integrity sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw== + dependencies: + "@types/unist" "^3.0.0" + unist-util-stringify-position "^4.0.0" + +vfile@^5.1.0: version "5.3.4" resolved "https://registry.yarnpkg.com/vfile/-/vfile-5.3.4.tgz#bbb8c96b956693bbf70b2c67fdb5781dff769b93" integrity sha512-KI+7cnst03KbEyN1+JE504zF5bJBZa+J+CrevLeyIMq0aPU681I2rQ5p4PlnQ6exFtWiUrg26QUdFMnAKR6PIw== @@ -18922,6 +19079,15 @@ vfile@^5.0.0, vfile@^5.1.0: unist-util-stringify-position "^3.0.0" vfile-message "^3.0.0" +vfile@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/vfile/-/vfile-6.0.1.tgz#1e8327f41eac91947d4fe9d237a2dd9209762536" + integrity sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw== + dependencies: + "@types/unist" "^3.0.0" + unist-util-stringify-position "^4.0.0" + vfile-message "^4.0.0" + vite-node@1.5.3: version "1.5.3" resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-1.5.3.tgz#498f4eb6f4e37ff95f66ffb9c905708a75f84b2e" @@ -19617,6 +19783,6 @@ zwitch@^1.0.0: integrity sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw== zwitch@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-2.0.2.tgz#91f8d0e901ffa3d66599756dde7f57b17c95dce1" - integrity sha512-JZxotl7SxAJH0j7dN4pxsTV6ZLXoLdGME+PsjkL/DaBrVryK9kTGq06GfKrwcSOqypP+fdXGoCHE36b99fWVoA== + version "2.0.4" + resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-2.0.4.tgz#c827d4b0acb76fc3e685a4c6ec2902d51070e9d7" + integrity sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A== From 9c7961bf3aaeffa427ee1cc6c895bc15cf3ec39a Mon Sep 17 00:00:00 2001 From: reiji-h Date: Wed, 19 Jun 2024 09:28:35 +0000 Subject: [PATCH 002/490] add vitest for remark-growi-directive package --- packages/remark-growi-directive/vitest.config.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 packages/remark-growi-directive/vitest.config.ts diff --git a/packages/remark-growi-directive/vitest.config.ts b/packages/remark-growi-directive/vitest.config.ts new file mode 100644 index 00000000000..bafe002885e --- /dev/null +++ b/packages/remark-growi-directive/vitest.config.ts @@ -0,0 +1,13 @@ +import tsconfigPaths from 'vite-tsconfig-paths'; +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + plugins: [ + tsconfigPaths(), + ], + test: { + environment: 'node', + clearMocks: true, + globals: true, + }, +}); From 6150bb7fcdc65ffa4c73c4dabdf1b4bf72cbea7e Mon Sep 17 00:00:00 2001 From: reiji-h Date: Fri, 28 Jun 2024 07:51:24 +0000 Subject: [PATCH 003/490] upgrade to v11 --- .../src/mdast-util-growi-directive/index.js | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/packages/remark-growi-directive/src/mdast-util-growi-directive/index.js b/packages/remark-growi-directive/src/mdast-util-growi-directive/index.js index b6bd2945cf6..5870697e225 100644 --- a/packages/remark-growi-directive/src/mdast-util-growi-directive/index.js +++ b/packages/remark-growi-directive/src/mdast-util-growi-directive/index.js @@ -14,9 +14,6 @@ * @typedef {LeafDirective|TextDirective} Directive */ -import { checkQuote } from 'mdast-util-to-markdown/lib/util/check-quote.js'; -import { containerPhrasing } from 'mdast-util-to-markdown/lib/util/container-phrasing.js'; -import { track } from 'mdast-util-to-markdown/lib/util/track.js'; import { parseEntities } from 'parse-entities'; import { stringifyEntitiesLight } from 'stringify-entities'; @@ -110,14 +107,14 @@ function exitName(token) { /** @type {FromMarkdownHandle} */ function enterAttributes() { - this.setData('directiveAttributes', []); + this.data.directiveAttributes = []; this.buffer(); // Capture EOLs } /** @type {FromMarkdownHandle} */ function exitAttributeValue(token) { const list = /** @type {Array.<[string, string]>} */ ( - this.getData('directiveAttributes') + this.data.directiveAttributes ); list[list.length - 1][1] = parseEntities(this.sliceSerialize(token)); } @@ -125,7 +122,7 @@ function exitAttributeValue(token) { /** @type {FromMarkdownHandle} */ function exitAttributeName(token) { const list = /** @type {Array.<[string, string]>} */ ( - this.getData('directiveAttributes') + this.data.directiveAttributes ); // Attribute names in CommonMark are significantly limited, so character @@ -136,7 +133,7 @@ function exitAttributeName(token) { /** @type {FromMarkdownHandle} */ function exitAttributes() { const list = /** @type {Array.<[string, string]>} */ ( - this.getData('directiveAttributes') + this.data.directiveAttributes ); /** @type {Record.} */ const cleaned = {}; @@ -148,7 +145,7 @@ function exitAttributes() { cleaned[attribute[0]] = attribute[1]; } - this.setData('directiveAttributes'); + this.data.directiveAttributes = []; this.resume(); // Drop EOLs const node = /** @type {Directive} */ (this.stack[this.stack.length - 1]); node.attributes = cleaned; @@ -164,7 +161,7 @@ function exit(token) { * @param {Directive} node */ function handleDirective(node, _, context, safeOptions) { - const tracker = track(safeOptions); + const tracker = context.createtracker(safeOptions); const sequence = fence(node); const exit = context.enter(node.type); let value = tracker.move(sequence + (node.name || '')); @@ -176,7 +173,7 @@ function handleDirective(node, _, context, safeOptions) { const subexit = context.enter(`${node.type}Label`); value += tracker.move('['); value += tracker.move( - containerPhrasing(label, context, { + context.containerPhrasing(label, { ...tracker.current(), before: value, after: ']', @@ -204,7 +201,7 @@ function peekDirective() { * @returns {string} */ function attributes(node, context) { - const quote = checkQuote(context); + const quote = context.options.quote || '"'; const subset = node.type === DirectiveType.Text ? [quote] : [quote, '\n', '\r']; const attrs = node.attributes || {}; /** @type {Array.} */ From 60ec67f8367fea5f872b9b37fe4d6db9d25392ad Mon Sep 17 00:00:00 2001 From: reiji-h Date: Fri, 28 Jun 2024 08:31:43 +0000 Subject: [PATCH 004/490] upgrade packages --- packages/remark-growi-directive/package.json | 8 ++-- yarn.lock | 48 ++++++-------------- 2 files changed, 18 insertions(+), 38 deletions(-) diff --git a/packages/remark-growi-directive/package.json b/packages/remark-growi-directive/package.json index cb7be01a87c..f2211a9f36f 100644 --- a/packages/remark-growi-directive/package.json +++ b/packages/remark-growi-directive/package.json @@ -28,8 +28,8 @@ "lint:fix": "yarn eslint \"**/*.{cjs, js,jsx,ts,tsx}\" --fix" }, "dependencies": { - "@types/mdast": "^3.0.0", - "@types/unist": "^2.0.0", + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", "mdast-util-to-markdown": "^2.1.0", "micromark-factory-space": "^2.0.0", "micromark-factory-whitespace": "^2.0.0", @@ -39,12 +39,12 @@ "parse-entities": "^4.0.0", "stringify-entities": "^4.0.0", "unified": "^11.0.0", - "unist-util-visit-parents": "^5.0.0", + "unist-util-visit-parents": "^6.0.0", "uvu": "^0.5.0" }, "devDependencies": { "@types/tape": "^4.0.0", - "c8": "^7.0.0", + "c8": "^8.0.0", "html-void-elements": "^2.0.0", "is-hidden": "^2.0.0", "mdast-util-from-markdown": "^2.0.1", diff --git a/yarn.lock b/yarn.lock index fb75288f6ac..c897118bd03 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2171,8 +2171,8 @@ "@growi/remark-growi-directive@link:packages/remark-growi-directive": version "0.9.0" dependencies: - "@types/mdast" "^3.0.0" - "@types/unist" "^2.0.0" + "@types/mdast" "^4.0.0" + "@types/unist" "^3.0.0" mdast-util-to-markdown "^2.1.0" micromark-factory-space "^2.0.0" micromark-factory-whitespace "^2.0.0" @@ -2182,7 +2182,7 @@ parse-entities "^4.0.0" stringify-entities "^4.0.0" unified "^11.0.0" - unist-util-visit-parents "^5.0.0" + unist-util-visit-parents "^6.0.0" uvu "^0.5.0" "@growi/remark-lsx@link:packages/remark-lsx": @@ -4473,13 +4473,6 @@ resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.178.tgz#341f6d2247db528d4a13ddbb374bcdc80406f4f8" integrity sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw== -"@types/mdast@^3.0.0": - version "3.0.10" - resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.10.tgz#4724244a82a4598884cbbe9bcfd73dff927ee8af" - integrity sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA== - dependencies: - "@types/unist" "*" - "@types/mdast@^4.0.0", "@types/mdast@^4.0.4": version "4.0.4" resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-4.0.4.tgz#7ccf72edd2f1aa7dd3437e180c64373585804dd6" @@ -6137,23 +6130,23 @@ bytes@3.1.2: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== -c8@^7.0.0: - version "7.13.0" - resolved "https://registry.yarnpkg.com/c8/-/c8-7.13.0.tgz#a2a70a851278709df5a9247d62d7f3d4bcb5f2e4" - integrity sha512-/NL4hQTv1gBL6J6ei80zu3IiTrmePDKXKXOTLpHvcIWZTVYQlDhVWjjWvkhICylE8EwwnMVzDZugCvdx0/DIIA== +c8@^8.0.0: + version "8.0.1" + resolved "https://registry.yarnpkg.com/c8/-/c8-8.0.1.tgz#bafd60be680e66c5530ee69f621e45b1364af9fd" + integrity sha512-EINpopxZNH1mETuI0DzRA4MZpAUH+IFiRhnmFD3vFr3vdrgxqi3VfE3KL0AIL+zDq8rC9bZqwM/VDmmoe04y7w== dependencies: "@bcoe/v8-coverage" "^0.2.3" "@istanbuljs/schema" "^0.1.3" find-up "^5.0.0" foreground-child "^2.0.0" istanbul-lib-coverage "^3.2.0" - istanbul-lib-report "^3.0.0" - istanbul-reports "^3.1.4" + istanbul-lib-report "^3.0.1" + istanbul-reports "^3.1.6" rimraf "^3.0.2" test-exclude "^6.0.0" v8-to-istanbul "^9.0.0" - yargs "^16.2.0" - yargs-parser "^20.2.9" + yargs "^17.7.2" + yargs-parser "^21.1.1" cac@^6.7.14: version "6.7.14" @@ -11308,7 +11301,7 @@ istanbul-lib-source-maps@^5.0.4: debug "^4.1.1" istanbul-lib-coverage "^3.0.0" -istanbul-reports@^3.1.3, istanbul-reports@^3.1.4, istanbul-reports@^3.1.6: +istanbul-reports@^3.1.3, istanbul-reports@^3.1.6: version "3.1.7" resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.7.tgz#daed12b9e1dca518e15c056e1e537e741280fa0b" integrity sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g== @@ -18682,11 +18675,6 @@ unist-util-is@^4.0.0: resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-4.1.0.tgz#976e5f462a7a5de73d94b706bac1b90671b57797" integrity sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg== -unist-util-is@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-5.1.1.tgz#e8aece0b102fa9bc097b0fef8f870c496d4a6236" - integrity sha512-F5CZ68eYzuSvJjGhCLPL3cYx45IxkqXSetCcRgUXtbcm50X2L9oOWQlfUfDdAf+6Pd27YDblBfdtmsThXmwpbQ== - unist-util-is@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-6.0.0.tgz#b775956486aff107a9ded971d996c173374be424" @@ -18731,14 +18719,6 @@ unist-util-visit-parents@^3.0.0: "@types/unist" "^2.0.0" unist-util-is "^4.0.0" -unist-util-visit-parents@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-5.1.1.tgz#868f353e6fce6bf8fa875b251b0f4fec3be709bb" - integrity sha512-gks4baapT/kNRaWxuGkl5BIhoanZo7sC/cUT/JToSRNL1dYoXRFl75d++NkjYk4TAu2uv2Px+l8guMajogeuiw== - dependencies: - "@types/unist" "^2.0.0" - unist-util-is "^5.0.0" - unist-util-visit-parents@^6.0.0: version "6.0.1" resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz#4d5f85755c3b8f0dc69e21eca5d6d82d22162815" @@ -19640,7 +19620,7 @@ yargs@^15.1.0: y18n "^4.0.0" yargs-parser "^18.1.2" -yargs@^16.0.0, yargs@^16.2.0: +yargs@^16.0.0: version "16.2.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== @@ -19653,7 +19633,7 @@ yargs@^16.0.0, yargs@^16.2.0: y18n "^5.0.5" yargs-parser "^20.2.2" -yargs@^17.0.1, yargs@^17.3.1, yargs@^17.7.1, yargs@~17.7.1: +yargs@^17.0.1, yargs@^17.3.1, yargs@^17.7.1, yargs@^17.7.2, yargs@~17.7.1: version "17.7.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== From af4cf0ddb9bca37fbf027cb0b245b3f29f7d0dc2 Mon Sep 17 00:00:00 2001 From: reiji-h Date: Fri, 28 Jun 2024 08:34:11 +0000 Subject: [PATCH 005/490] clean code --- .../src/mdast-util-growi-directive/index.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/remark-growi-directive/src/mdast-util-growi-directive/index.js b/packages/remark-growi-directive/src/mdast-util-growi-directive/index.js index 5870697e225..58ccd161d81 100644 --- a/packages/remark-growi-directive/src/mdast-util-growi-directive/index.js +++ b/packages/remark-growi-directive/src/mdast-util-growi-directive/index.js @@ -6,9 +6,11 @@ * @typedef {import('mdast-util-from-markdown').Extension} FromMarkdownExtension * @typedef {import('mdast-util-from-markdown').CompileContext} CompileContext * @typedef {import('mdast-util-from-markdown').Token} Token - * @typedef {import('mdast-util-to-markdown/lib/types.js').Handle} ToMarkdownHandle - * @typedef {import('mdast-util-to-markdown/lib/types.js').Context} Context - * @typedef {import('mdast-util-to-markdown/lib/types.js').Options} ToMarkdownExtension + * @typedef {import('mdast-util-to-markdown').Handle} ToMarkdownHandle + * @typedef {import('mdast-util-to-markdown').Context} Context + * @typedef {import('mdast-util-to-markdown').Options} ToMarkdownExtension + * @typedef {import()} + * * @typedef {import('./complex-types').LeafDirective} LeafDirective * @typedef {import('./complex-types').TextDirective} TextDirective * @typedef {LeafDirective|TextDirective} Directive From dd5ebb18247e804d9f1d4970588d38ff64dc9d59 Mon Sep 17 00:00:00 2001 From: reiji-h Date: Fri, 28 Jun 2024 09:21:27 +0000 Subject: [PATCH 006/490] update package import --- .../micromark-extension-growi-directive/lib/directive-leaf.js | 3 +-- .../micromark-extension-growi-directive/lib/directive-text.js | 3 +-- .../lib/factory-attributes.js | 3 +-- .../micromark-extension-growi-directive/lib/factory-label.js | 4 +--- .../micromark-extension-growi-directive/lib/factory-name.js | 2 +- .../src/micromark-extension-growi-directive/lib/syntax.js | 2 +- .../src/micromark-factory-attributes-devider/index.js | 2 +- 7 files changed, 7 insertions(+), 12 deletions(-) diff --git a/packages/remark-growi-directive/src/micromark-extension-growi-directive/lib/directive-leaf.js b/packages/remark-growi-directive/src/micromark-extension-growi-directive/lib/directive-leaf.js index 7a8766d7807..fdd83cec4d7 100644 --- a/packages/remark-growi-directive/src/micromark-extension-growi-directive/lib/directive-leaf.js +++ b/packages/remark-growi-directive/src/micromark-extension-growi-directive/lib/directive-leaf.js @@ -6,8 +6,7 @@ import { factorySpace } from 'micromark-factory-space'; import { markdownLineEnding } from 'micromark-util-character'; -import { codes } from 'micromark-util-symbol/codes.js'; -import { types } from 'micromark-util-symbol/types.js'; +import { codes, types } from 'micromark-util-symbol'; import { ok as assert } from 'uvu/assert'; import { factoryAttributes } from './factory-attributes.js'; diff --git a/packages/remark-growi-directive/src/micromark-extension-growi-directive/lib/directive-text.js b/packages/remark-growi-directive/src/micromark-extension-growi-directive/lib/directive-text.js index 5f30ec21a4c..c2b695c0841 100644 --- a/packages/remark-growi-directive/src/micromark-extension-growi-directive/lib/directive-text.js +++ b/packages/remark-growi-directive/src/micromark-extension-growi-directive/lib/directive-text.js @@ -5,8 +5,7 @@ * @typedef {import('micromark-util-types').State} State */ -import { codes } from 'micromark-util-symbol/codes.js'; -import { types } from 'micromark-util-symbol/types.js'; +import { codes, types } from 'micromark-util-symbol'; import { ok as assert } from 'uvu/assert'; import { factoryAttributes } from './factory-attributes.js'; diff --git a/packages/remark-growi-directive/src/micromark-extension-growi-directive/lib/factory-attributes.js b/packages/remark-growi-directive/src/micromark-extension-growi-directive/lib/factory-attributes.js index 31b94919770..7cc8ee22d32 100644 --- a/packages/remark-growi-directive/src/micromark-extension-growi-directive/lib/factory-attributes.js +++ b/packages/remark-growi-directive/src/micromark-extension-growi-directive/lib/factory-attributes.js @@ -11,8 +11,7 @@ import { markdownLineEndingOrSpace, markdownSpace, } from 'micromark-util-character'; -import { codes } from 'micromark-util-symbol/codes.js'; -import { types } from 'micromark-util-symbol/types.js'; +import { codes, types } from 'micromark-util-symbol'; import { ok as assert } from 'uvu/assert'; import { markdownLineEndingOrSpaceOrComma, factoryAttributesDevider } from '../../micromark-factory-attributes-devider/index.js'; diff --git a/packages/remark-growi-directive/src/micromark-extension-growi-directive/lib/factory-label.js b/packages/remark-growi-directive/src/micromark-extension-growi-directive/lib/factory-label.js index 34d3abb792b..032974c555d 100644 --- a/packages/remark-growi-directive/src/micromark-extension-growi-directive/lib/factory-label.js +++ b/packages/remark-growi-directive/src/micromark-extension-growi-directive/lib/factory-label.js @@ -5,9 +5,7 @@ */ import { markdownLineEnding } from 'micromark-util-character'; -import { codes } from 'micromark-util-symbol/codes.js'; -import { constants } from 'micromark-util-symbol/constants.js'; -import { types } from 'micromark-util-symbol/types.js'; +import { codes, constants, types } from 'micromark-util-symbol'; import { ok as assert } from 'uvu/assert'; // This is a fork of: diff --git a/packages/remark-growi-directive/src/micromark-extension-growi-directive/lib/factory-name.js b/packages/remark-growi-directive/src/micromark-extension-growi-directive/lib/factory-name.js index 077cb1cd6bb..c53ff92029e 100644 --- a/packages/remark-growi-directive/src/micromark-extension-growi-directive/lib/factory-name.js +++ b/packages/remark-growi-directive/src/micromark-extension-growi-directive/lib/factory-name.js @@ -5,7 +5,7 @@ */ import { asciiAlpha, asciiAlphanumeric } from 'micromark-util-character'; -import { codes } from 'micromark-util-symbol/codes.js'; +import { codes } from 'micromark-util-symbol'; /** * @this {TokenizeContext} diff --git a/packages/remark-growi-directive/src/micromark-extension-growi-directive/lib/syntax.js b/packages/remark-growi-directive/src/micromark-extension-growi-directive/lib/syntax.js index 3a14e76c0a1..6d41fbd8de1 100644 --- a/packages/remark-growi-directive/src/micromark-extension-growi-directive/lib/syntax.js +++ b/packages/remark-growi-directive/src/micromark-extension-growi-directive/lib/syntax.js @@ -2,7 +2,7 @@ * @typedef {import('micromark-util-types').Extension} Extension */ -import { codes } from 'micromark-util-symbol/codes.js'; +import { codes } from 'micromark-util-symbol'; import { directiveLeaf } from './directive-leaf.js'; import { directiveText } from './directive-text.js'; diff --git a/packages/remark-growi-directive/src/micromark-factory-attributes-devider/index.js b/packages/remark-growi-directive/src/micromark-factory-attributes-devider/index.js index 464167887af..cbdacce8a68 100644 --- a/packages/remark-growi-directive/src/micromark-factory-attributes-devider/index.js +++ b/packages/remark-growi-directive/src/micromark-factory-attributes-devider/index.js @@ -4,7 +4,7 @@ */ import { factorySpace } from 'micromark-factory-space'; import { markdownLineEnding, markdownSpace } from 'micromark-util-character'; -import { codes } from 'micromark-util-symbol/codes.js'; +import { codes } from 'micromark-util-symbol'; export function markdownLineEndingOrSpaceOrComma(code) { return code !== null && (code < codes.nul || code === codes.space || code === codes.comma); From 57900019cfad90a8c0b30c03cc57928c5a98ea87 Mon Sep 17 00:00:00 2001 From: reiji-h Date: Fri, 5 Jul 2024 10:01:13 +0000 Subject: [PATCH 007/490] fix test - removePosition is changed --- .../src/mdast-util-growi-directive/index.js | 3 +- .../test/mdast-util-growi-directive.test.js | 51 +++++++++---------- 2 files changed, 24 insertions(+), 30 deletions(-) diff --git a/packages/remark-growi-directive/src/mdast-util-growi-directive/index.js b/packages/remark-growi-directive/src/mdast-util-growi-directive/index.js index 58ccd161d81..2e348540cfb 100644 --- a/packages/remark-growi-directive/src/mdast-util-growi-directive/index.js +++ b/packages/remark-growi-directive/src/mdast-util-growi-directive/index.js @@ -9,7 +9,6 @@ * @typedef {import('mdast-util-to-markdown').Handle} ToMarkdownHandle * @typedef {import('mdast-util-to-markdown').Context} Context * @typedef {import('mdast-util-to-markdown').Options} ToMarkdownExtension - * @typedef {import()} * * @typedef {import('./complex-types').LeafDirective} LeafDirective * @typedef {import('./complex-types').TextDirective} TextDirective @@ -163,7 +162,7 @@ function exit(token) { * @param {Directive} node */ function handleDirective(node, _, context, safeOptions) { - const tracker = context.createtracker(safeOptions); + const tracker = context.createTracker(safeOptions); const sequence = fence(node); const exit = context.enter(node.type); let value = tracker.move(sequence + (node.name || '')); diff --git a/packages/remark-growi-directive/test/mdast-util-growi-directive.test.js b/packages/remark-growi-directive/test/mdast-util-growi-directive.test.js index b7c974348f9..79fc5e32d24 100644 --- a/packages/remark-growi-directive/test/mdast-util-growi-directive.test.js +++ b/packages/remark-growi-directive/test/mdast-util-growi-directive.test.js @@ -87,14 +87,15 @@ test('markdown -> mdast', (t) => { 'should support directives (leaf)', ); + let tree = fromMarkdown('x $a[b *c*\nd]', { + extensions: [directive()], + mdastExtensions: [directiveFromMarkdown], + }); + + removePosition(tree, { force: true }); + t.deepEqual( - removePosition( - fromMarkdown('x $a[b *c*\nd]', { - extensions: [directive()], - mdastExtensions: [directiveFromMarkdown], - }), - true, - ), + tree, { type: 'root', children: [ @@ -119,22 +120,15 @@ test('markdown -> mdast', (t) => { 'should support content in a label', ); - const hoge = removePosition( - fromMarkdown('x $a(#b.c.d e=f g="h&i&unknown;j")', { - extensions: [directive()], - mdastExtensions: [directiveFromMarkdown], - }), - true, - ); + tree = fromMarkdown('x $a(#b.c.d e=f g="h&i&unknown;j")', { + extensions: [directive()], + mdastExtensions: [directiveFromMarkdown], + }); + + removePosition(tree, { force: true }); t.deepEqual( - removePosition( - fromMarkdown('x $a(#b.c.d e=f g="h&i&unknown;j")', { - extensions: [directive()], - mdastExtensions: [directiveFromMarkdown], - }), - true, - ), + tree, { type: 'root', children: [ @@ -157,14 +151,15 @@ test('markdown -> mdast', (t) => { 'should support attributes', ); + tree = fromMarkdown('$a(b\nc="d\ne")', { + extensions: [directive()], + mdastExtensions: [directiveFromMarkdown], + }); + + removePosition(tree, { force: true }); + t.deepEqual( - removePosition( - fromMarkdown('$a(b\nc="d\ne")', { - extensions: [directive()], - mdastExtensions: [directiveFromMarkdown], - }), - true, - ), + tree, { type: 'root', children: [ From a2276670f922f7c975451ec50f921ae52ecb44ab Mon Sep 17 00:00:00 2001 From: reiji-h Date: Tue, 9 Jul 2024 04:08:06 +0000 Subject: [PATCH 008/490] setting avoid ESM error --- apps/app/next.config.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/apps/app/next.config.js b/apps/app/next.config.js index 52d73a1a211..54ef997cdd1 100644 --- a/apps/app/next.config.js +++ b/apps/app/next.config.js @@ -48,6 +48,14 @@ const getTranspilePackages = () => { 'emoticon', 'direction', // for hast-util-select 'bcp-47-match', // for hast-util-select + 'parse-entities', + 'character-reference-invalid', + 'is-hexadecimal', + 'is-alphabetical', + 'is-alphanumerical', + 'github-slugger', + 'html-url-attributes', + 'estree-util-is-identifier-name', ...listPrefixedPackages(['remark-', 'rehype-', 'hast-', 'mdast-', 'micromark-', 'unist-']), ]; From 22bc9b928a0645f2d5af6f8b11f86151f6e87ebe Mon Sep 17 00:00:00 2001 From: reiji-h Date: Tue, 9 Jul 2024 05:05:56 +0000 Subject: [PATCH 009/490] delete unused config --- packages/remark-growi-directive/vitest.config.ts | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 packages/remark-growi-directive/vitest.config.ts diff --git a/packages/remark-growi-directive/vitest.config.ts b/packages/remark-growi-directive/vitest.config.ts deleted file mode 100644 index bafe002885e..00000000000 --- a/packages/remark-growi-directive/vitest.config.ts +++ /dev/null @@ -1,13 +0,0 @@ -import tsconfigPaths from 'vite-tsconfig-paths'; -import { defineConfig } from 'vitest/config'; - -export default defineConfig({ - plugins: [ - tsconfigPaths(), - ], - test: { - environment: 'node', - clearMocks: true, - globals: true, - }, -}); From 21a07598910ae8f034c8bb4f7a44ec3ae5a10e5f Mon Sep 17 00:00:00 2001 From: reiji-h Date: Fri, 12 Jul 2024 07:24:34 +0000 Subject: [PATCH 010/490] add vitest --- packages/remark-growi-directive/tsconfig.json | 5 +++++ packages/remark-growi-directive/vitest.config.ts | 13 +++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 packages/remark-growi-directive/vitest.config.ts diff --git a/packages/remark-growi-directive/tsconfig.json b/packages/remark-growi-directive/tsconfig.json index 721f71631f1..e79e06ea807 100644 --- a/packages/remark-growi-directive/tsconfig.json +++ b/packages/remark-growi-directive/tsconfig.json @@ -1,6 +1,11 @@ { "$schema": "http://json.schemastore.org/tsconfig", "extends": "../../tsconfig.base.json", + "compilerOptions": { + "types": [ + "vitest/globals" + ], + }, "include": [ "src" ], diff --git a/packages/remark-growi-directive/vitest.config.ts b/packages/remark-growi-directive/vitest.config.ts new file mode 100644 index 00000000000..bafe002885e --- /dev/null +++ b/packages/remark-growi-directive/vitest.config.ts @@ -0,0 +1,13 @@ +import tsconfigPaths from 'vite-tsconfig-paths'; +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + plugins: [ + tsconfigPaths(), + ], + test: { + environment: 'node', + clearMocks: true, + globals: true, + }, +}); From e4ec7c998aa0a335d0deae4531b665dc319c9cea Mon Sep 17 00:00:00 2001 From: reiji-h Date: Fri, 12 Jul 2024 08:53:03 +0000 Subject: [PATCH 011/490] update vitest --- .../test/remark-growi-directive.test.js | 40 +++++++++---------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/packages/remark-growi-directive/test/remark-growi-directive.test.js b/packages/remark-growi-directive/test/remark-growi-directive.test.js index 1ed23eb4dfd..3cbbb870181 100644 --- a/packages/remark-growi-directive/test/remark-growi-directive.test.js +++ b/packages/remark-growi-directive/test/remark-growi-directive.test.js @@ -7,34 +7,32 @@ import path from 'node:path'; import { isHidden } from 'is-hidden'; import { remark } from 'remark'; -import test from 'tape'; import { readSync } from 'to-vfile'; import { unified } from 'unified'; +import { describe, it, expect } from 'vitest'; import { remarkGrowiDirectivePlugin } from '../src/remark-growi-directive.js'; -test('directive()', (t) => { - t.doesNotThrow(() => { - remark().use(remarkGrowiDirectivePlugin).freeze(); - }, 'should not throw if not passed options'); +describe('directive()', () => { + it('should not throw if not passed options', () => { + expect(() => { + remark().use(remarkGrowiDirectivePlugin).freeze(); + }).not.toThrow(); + }); - t.doesNotThrow(() => { - unified().use(remarkGrowiDirectivePlugin).freeze(); - }, 'should not throw if without parser or compiler'); - - t.end(); + it('should not throw if without parser or compiler', () => { + expect(() => { + unified().use(remarkGrowiDirectivePlugin).freeze(); + }).not.toThrow(); + }); }); -test('fixtures', (t) => { +describe('fixtures', () => { const base = path.join('test', 'fixtures'); const entries = fs.readdirSync(base).filter(d => !isHidden(d)); - t.plan(entries.length); - - let index = -1; - while (++index < entries.length) { - const fixture = entries[index]; - t.test(fixture, (st) => { + entries.forEach((fixture) => { + it(`should handle ${fixture}`, () => { const file = readSync(path.join(base, fixture, 'input.md')); const input = String(file); const outputPath = path.join(base, fixture, 'output.md'); @@ -62,10 +60,8 @@ test('fixtures', (t) => { output = input; } - st.deepEqual(actual, expected, 'tree'); - st.equal(String(proc.processSync(file)), output, 'process'); - - st.end(); + expect(actual).toEqual(expected); + expect(String(proc.processSync(file))).toBe(output); }); - } + }); }); From 3b6d4dc18715b0949e0c49e69c84b8e98b4a50d7 Mon Sep 17 00:00:00 2001 From: reiji-h Date: Fri, 12 Jul 2024 08:59:16 +0000 Subject: [PATCH 012/490] use vitest --- .../test/mdast-util-growi-directive.test.js | 857 ++++++++---------- 1 file changed, 402 insertions(+), 455 deletions(-) diff --git a/packages/remark-growi-directive/test/mdast-util-growi-directive.test.js b/packages/remark-growi-directive/test/mdast-util-growi-directive.test.js index b7c974348f9..8fcc7190368 100644 --- a/packages/remark-growi-directive/test/mdast-util-growi-directive.test.js +++ b/packages/remark-growi-directive/test/mdast-util-growi-directive.test.js @@ -1,19 +1,21 @@ import { fromMarkdown } from 'mdast-util-from-markdown'; import { toMarkdown } from 'mdast-util-to-markdown'; -import test from 'tape'; import { removePosition } from 'unist-util-remove-position'; +import { describe, it, expect } from 'vitest'; import { DirectiveType } from '../src/mdast-util-growi-directive/consts.js'; import { directiveFromMarkdown, directiveToMarkdown } from '../src/mdast-util-growi-directive/index.js'; import { directive } from '../src/micromark-extension-growi-directive/index.js'; -test('markdown -> mdast', (t) => { - t.deepEqual( - fromMarkdown('a $b[c](d) e.', { - extensions: [directive()], - mdastExtensions: [directiveFromMarkdown], - }).children[0], - { + +describe('markdown -> mdast', () => { + it('should support directives (text)', () => { + expect( + fromMarkdown('a $b[c](d) e.', { + extensions: [directive()], + mdastExtensions: [directiveFromMarkdown], + }).children[0], + ).toEqual({ type: 'paragraph', children: [ { @@ -56,16 +58,16 @@ test('markdown -> mdast', (t) => { start: { line: 1, column: 1, offset: 0 }, end: { line: 1, column: 14, offset: 13 }, }, - }, - 'should support directives (text)', - ); + }); + }); - t.deepEqual( - fromMarkdown('$a[b](c)', { - extensions: [directive()], - mdastExtensions: [directiveFromMarkdown], - }).children[0], - { + it('should support directives (leaf)', () => { + expect( + fromMarkdown('$a[b](c)', { + extensions: [directive()], + mdastExtensions: [directiveFromMarkdown], + }).children[0], + ).toEqual({ type: DirectiveType.Leaf, name: 'a', attributes: { c: '' }, @@ -83,19 +85,19 @@ test('markdown -> mdast', (t) => { start: { line: 1, column: 1, offset: 0 }, end: { line: 1, column: 9, offset: 8 }, }, - }, - 'should support directives (leaf)', - ); - - t.deepEqual( - removePosition( - fromMarkdown('x $a[b *c*\nd]', { - extensions: [directive()], - mdastExtensions: [directiveFromMarkdown], - }), - true, - ), - { + }); + }); + + it('should support content in a label', () => { + expect( + removePosition( + fromMarkdown('x $a[b *c*\nd]', { + extensions: [directive()], + mdastExtensions: [directiveFromMarkdown], + }), + true, + ), + ).toEqual({ type: 'root', children: [ { @@ -115,27 +117,19 @@ test('markdown -> mdast', (t) => { ], }, ], - }, - 'should support content in a label', - ); - - const hoge = removePosition( - fromMarkdown('x $a(#b.c.d e=f g="h&i&unknown;j")', { - extensions: [directive()], - mdastExtensions: [directiveFromMarkdown], - }), - true, - ); - - t.deepEqual( - removePosition( - fromMarkdown('x $a(#b.c.d e=f g="h&i&unknown;j")', { - extensions: [directive()], - mdastExtensions: [directiveFromMarkdown], - }), - true, - ), - { + }); + }); + + it('should support attributes', () => { + expect( + removePosition( + fromMarkdown('x $a(#b.c.d e=f g="h&i&unknown;j")', { + extensions: [directive()], + mdastExtensions: [directiveFromMarkdown], + }), + true, + ), + ).toEqual({ type: 'root', children: [ { @@ -153,19 +147,19 @@ test('markdown -> mdast', (t) => { ], }, ], - }, - 'should support attributes', - ); - - t.deepEqual( - removePosition( - fromMarkdown('$a(b\nc="d\ne")', { - extensions: [directive()], - mdastExtensions: [directiveFromMarkdown], - }), - true, - ), - { + }); + }); + + it('should support EOLs in attributes', () => { + expect( + removePosition( + fromMarkdown('$a(b\nc="d\ne")', { + extensions: [directive()], + mdastExtensions: [directiveFromMarkdown], + }), + true, + ), + ).toEqual({ type: 'root', children: [ { @@ -180,416 +174,369 @@ test('markdown -> mdast', (t) => { ], }, ], - }, - 'should support EOLs in attributes', - ); - - t.end(); + }); + }); }); -test('mdast -> markdown', (t) => { - t.deepEqual( - toMarkdown( - { - type: 'paragraph', - children: [ - { type: 'text', value: 'a ' }, - // @ts-expect-error: `children`, `name` missing. - { type: DirectiveType.Text }, - { type: 'text', value: ' b.' }, - ], - }, - { extensions: [directiveToMarkdown] }, - ), - 'a $ b.\n', - 'should try to serialize a directive (text) w/o `name`', - ); - - t.deepEqual( - toMarkdown( - { - type: 'paragraph', - children: [ - { type: 'text', value: 'a ' }, - // @ts-expect-error: `children` missing. - { type: DirectiveType.Text, name: 'b' }, - { type: 'text', value: ' c.' }, - ], - }, - { extensions: [directiveToMarkdown] }, - ), - 'a $b c.\n', - 'should serialize a directive (text) w/ `name`', - ); - - t.deepEqual( - toMarkdown( - { - type: 'paragraph', - children: [ - { type: 'text', value: 'a ' }, - { - type: DirectiveType.Text, - name: 'b', - children: [{ type: 'text', value: 'c' }], - }, - { type: 'text', value: ' d.' }, - ], - }, - { extensions: [directiveToMarkdown] }, - ), - 'a $b[c] d.\n', - 'should serialize a directive (text) w/ `children`', - ); - - t.deepEqual( - toMarkdown( - { - type: 'paragraph', - children: [ - { type: 'text', value: 'a ' }, - { - type: DirectiveType.Text, - name: 'b', - children: [{ type: 'text', value: 'c[d]e' }], - }, - { type: 'text', value: ' f.' }, - ], - }, - { extensions: [directiveToMarkdown] }, - ), - 'a $b[c\\[d\\]e] f.\n', - 'should escape brackets in a directive (text) label', - ); - - t.deepEqual( - toMarkdown( - { - type: 'paragraph', - children: [ - { type: 'text', value: 'a ' }, - { - type: DirectiveType.Text, - name: 'b', - children: [{ type: 'text', value: 'c\nd' }], - }, - { type: 'text', value: ' e.' }, - ], - }, - { extensions: [directiveToMarkdown] }, - ), - 'a $b[c\nd] e.\n', - 'should support EOLs in a directive (text) label', - ); - - t.deepEqual( - toMarkdown( - { - type: 'paragraph', - children: [ - { type: 'text', value: 'a ' }, - { - type: DirectiveType.Text, - name: 'b', - // @ts-expect-error: should contain only `string`s - attributes: { - c: 'd', e: 'f', g: '', h: null, i: undefined, j: 2, +describe('mdast -> markdown', () => { + it('should try to serialize a directive (text) w/o `name`', () => { + expect( + toMarkdown( + { + type: 'paragraph', + children: [ + { type: 'text', value: 'a ' }, + // @ts-expect-error: `children`, `name` missing. + { type: DirectiveType.Text }, + { type: 'text', value: ' b.' }, + ], + }, + { extensions: [directiveToMarkdown] }, + ), + ).toBe('a $ b.\n'); + }); + + it('should serialize a directive (text) w/ `name`', () => { + expect( + toMarkdown( + { + type: 'paragraph', + children: [ + { type: 'text', value: 'a ' }, + // @ts-expect-error: `children` missing. + { type: DirectiveType.Text, name: 'b' }, + { type: 'text', value: ' c.' }, + ], + }, + { extensions: [directiveToMarkdown] }, + ), + ).toBe('a $b c.\n'); + }); + + it('should serialize a directive (text) w/ `children`', () => { + expect( + toMarkdown( + { + type: 'paragraph', + children: [ + { type: 'text', value: 'a ' }, + { + type: DirectiveType.Text, + name: 'b', + children: [{ type: 'text', value: 'c' }], }, - children: [], - }, - { type: 'text', value: ' k.' }, - ], - }, - { extensions: [directiveToMarkdown] }, - ), - 'a $b(c="d" e="f" g j="2") k.\n', - 'should serialize a directive (text) w/ `attributes`', - ); - - t.deepEqual( - toMarkdown( - { - type: 'paragraph', - children: [ - { type: 'text', value: 'a ' }, - { - type: DirectiveType.Text, - name: 'b', - attributes: { '#d': '', '.a.b.c': '', key: 'value' }, - children: [], - }, - { type: 'text', value: ' k.' }, - ], - }, - { extensions: [directiveToMarkdown] }, - ), - 'a $b(#d .a.b.c key="value") k.\n', - 'should serialize a directive (text) w/ hash, dot notation attributes', - ); - - t.deepEqual( - toMarkdown( - { - type: 'paragraph', - children: [ - { type: 'text', value: 'a ' }, - { - type: DirectiveType.Text, - name: 'b', - attributes: { x: 'y"\'\r\nz' }, - children: [], - }, - { type: 'text', value: ' k.' }, - ], - }, - { extensions: [directiveToMarkdown] }, - ), - 'a $b(x="y"\'\r\nz") k.\n', - 'should encode the quote in an attribute value (text)', - ); - - t.deepEqual( - toMarkdown( - { - type: 'paragraph', - children: [ - { type: 'text', value: 'a ' }, - { - type: DirectiveType.Text, - name: 'b', - attributes: { x: 'y"\'\r\nz' }, - children: [], - }, - { type: 'text', value: ' k.' }, - ], - }, - { extensions: [directiveToMarkdown] }, - ), - 'a $b(x="y"\'\r\nz") k.\n', - 'should encode the quote in an attribute value (text)', - ); - - t.deepEqual( - toMarkdown( - { - type: 'paragraph', - children: [ - { type: 'text', value: 'a ' }, - { - type: DirectiveType.Text, - name: 'b', - attributes: { id: 'c#d' }, - children: [], - }, - { type: 'text', value: ' e.' }, - ], - }, - { extensions: [directiveToMarkdown] }, - ), - 'a $b(id="c#d") e.\n', - 'should not use the `id` shortcut if impossible characters exist', - ); - - t.deepEqual( - toMarkdown( - { - type: 'paragraph', - children: [ - { type: 'text', value: 'a ' }, - { - type: DirectiveType.Text, - name: 'b', - attributes: { 'c.d': '', 'e { + expect( + toMarkdown( + { + type: 'paragraph', + children: [ + { type: 'text', value: 'a ' }, + { + type: DirectiveType.Text, + name: 'b', + children: [{ type: 'text', value: 'c[d]e' }], }, - children: [], - }, - { type: 'text', value: ' k.' }, - ], - }, - { extensions: [directiveToMarkdown] }, - ), - 'a $b(c.d e f { + expect( + toMarkdown( + { + type: 'paragraph', + children: [ + { type: 'text', value: 'a ' }, + { + type: DirectiveType.Text, + name: 'b', + children: [{ type: 'text', value: 'c\nd' }], + }, + { type: 'text', value: ' e.' }, + ], + }, + { extensions: [directiveToMarkdown] }, + ), + ).toBe('a $b[c\nd] e.\n'); + }); + + it('should serialize a directive (text) w/ `attributes`', () => { + expect( + toMarkdown( + { + type: 'paragraph', + children: [ + { type: 'text', value: 'a ' }, + { + type: DirectiveType.Text, + name: 'b', + // @ts-expect-error: should contain only `string`s + attributes: { + c: 'd', e: 'f', g: '', h: null, i: undefined, j: 2, + }, + children: [], + }, + { type: 'text', value: ' k.' }, + ], + }, + { extensions: [directiveToMarkdown] }, + ), + ).toBe('a $b(c="d" e="f" g j="2") k.\n'); + }); + + it('should serialize a directive (text) w/ hash, dot notation attributes', () => { + expect( + toMarkdown( + { + type: 'paragraph', + children: [ + { type: 'text', value: 'a ' }, + { + type: DirectiveType.Text, + name: 'b', + attributes: { '#d': '', '.a.b.c': '', key: 'value' }, + children: [], + }, + { type: 'text', value: ' k.' }, + ], + }, + { extensions: [directiveToMarkdown] }, + ), + ).toBe('a $b(#d .a.b.c key="value") k.\n'); + }); + + it('should encode the quote in an attribute value (text)', () => { + expect( + toMarkdown( + { + type: 'paragraph', + children: [ + { type: 'text', value: 'a ' }, + { + type: DirectiveType.Text, + name: 'b', + attributes: { x: 'y"\'\r\nz' }, + children: [], + }, + { type: 'text', value: ' k.' }, + ], + }, + { extensions: [directiveToMarkdown] }, + ), + ).toBe('a $b(x="y"\'\r\nz") k.\n'); + }); + + it('should not use the `id` shortcut if impossible characters exist', () => { + expect( + toMarkdown( + { + type: 'paragraph', + children: [ + { type: 'text', value: 'a ' }, + { + type: DirectiveType.Text, + name: 'b', + attributes: { id: 'c#d' }, + children: [], + }, + { type: 'text', value: ' e.' }, + ], + }, + { extensions: [directiveToMarkdown] }, + ), + ).toBe('a $b(id="c#d") e.\n'); + }); + + it('should not use the `class` shortcut if impossible characters exist', () => { + expect( + toMarkdown( + { + type: 'paragraph', + children: [ + { type: 'text', value: 'a ' }, + { + type: DirectiveType.Text, + name: 'b', + attributes: { 'c.d': '', 'e { + expect( + toMarkdown( + { + type: 'paragraph', + children: [ + { type: 'text', value: 'a ' }, + { + type: DirectiveType.Text, + name: 'b', + attributes: { + 'c.d': '', e: '', 'f { // @ts-expect-error: `children`, `name` missing. - toMarkdown({ type: DirectiveType.Leaf }, { extensions: [directiveToMarkdown] }), - '$\n', - 'should try to serialize a directive (leaf) w/o `name`', - ); - - t.deepEqual( - toMarkdown( - // @ts-expect-error: `children` missing. - { type: DirectiveType.Leaf, name: 'a' }, - { extensions: [directiveToMarkdown] }, - ), - '$a\n', - 'should serialize a directive (leaf) w/ `name`', - ); - - t.deepEqual( - toMarkdown( - { - type: DirectiveType.Leaf, - name: 'a', - children: [{ type: 'text', value: 'b' }], - }, - { extensions: [directiveToMarkdown] }, - ), - '$a[b]\n', - 'should serialize a directive (leaf) w/ `children`', - ); - - t.deepEqual( - toMarkdown( - { - type: DirectiveType.Leaf, - name: 'a', - children: [{ type: 'text', value: 'b' }], - }, - { extensions: [directiveToMarkdown] }, - ), - '$a[b]\n', - 'should serialize a directive (leaf) w/ `children`', - ); - - t.deepEqual( - toMarkdown( - { - type: DirectiveType.Leaf, - name: 'a', - children: [{ type: 'text', value: 'b\nc' }], - }, - { extensions: [directiveToMarkdown] }, - ), - '$a[b c]\n', - 'should serialize a directive (leaf) w/ EOLs in `children`', - ); - - t.deepEqual( - toMarkdown( - { - type: DirectiveType.Leaf, - name: 'a', - attributes: { '#b': '', '.c.d': '', key: 'e\nf' }, - children: [], - }, - { extensions: [directiveToMarkdown] }, - ), - '$a(#b .c.d key="e f")\n', - 'should serialize a directive (leaf) w/ EOLs in `attributes`', - ); - - t.deepEqual( - toMarkdown( - { - type: 'paragraph', - children: [{ type: 'text', value: 'a$b' }], - }, - { extensions: [directiveToMarkdown] }, - ), - 'a\\$b\n', - 'should escape a `:` in phrasing when followed by an alpha', - ); - - t.deepEqual( - toMarkdown( - { + expect( + toMarkdown( + { type: DirectiveType.Leaf }, + { extensions: [directiveToMarkdown] }, + ), + ).toBe('$\n'); + }); + + it('should serialize a directive (leaf) w/ `name`', () => { + // @ts-expect-error: `children` missing. + expect( + toMarkdown( + { type: DirectiveType.Leaf, name: 'a' }, + { extensions: [directiveToMarkdown] }, + ), + ).toBe('$a\n'); + }); + + it('should serialize a directive (leaf) w/ `children`', () => { + expect( + toMarkdown( + { + type: DirectiveType.Leaf, + name: 'a', + children: [{ type: 'text', value: 'b' }], + }, + { extensions: [directiveToMarkdown] }, + ), + ).toBe('$a[b]\n'); + }); + + it('should serialize a directive (leaf) w/ EOLs in `children`', () => { + expect( + toMarkdown( + { + type: DirectiveType.Leaf, + name: 'a', + children: [{ type: 'text', value: 'b\nc' }], + }, + { extensions: [directiveToMarkdown] }, + ), + ).toBe('$a[b c]\n'); + }); + + it('should serialize a directive (leaf) w/ EOLs in `attributes`', () => { + expect( + toMarkdown( + { + type: DirectiveType.Leaf, + name: 'a', + attributes: { '#b': '', '.c.d': '', key: 'e\nf' }, + children: [], + }, + { extensions: [directiveToMarkdown] }, + ), + ).toEqual('$a(#b .c.d key="e f")\n'); + }); + + it('should escape a `:` in phrasing when followed by an alpha', () => { + expect( + toMarkdown( + { + type: 'paragraph', + children: [{ type: 'text', value: 'a$b' }], + }, + { extensions: [directiveToMarkdown] }, + ), + ).toEqual('a\\$b\n'); + }); + + it('should not escape a `:` in phrasing when followed by a non-alpha', () => { + expect( + toMarkdown({ type: 'paragraph', children: [{ type: 'text', value: 'a$9' }], - }, - { extensions: [directiveToMarkdown] }, - ), - 'a$9\n', - 'should not escape a `:` in phrasing when followed by a non-alpha', - ); + }, { extensions: [directiveToMarkdown] }), + ).toBe('a$9\n'); + }); - t.deepEqual( - toMarkdown( - { + it('should not escape a `:` in phrasing when preceded by a colon', () => { + expect( + toMarkdown({ type: 'paragraph', children: [{ type: 'text', value: 'a$c' }], - }, - { extensions: [directiveToMarkdown] }, - ), - 'a\\$c\n', - 'should not escape a `:` in phrasing when preceded by a colon', - ); - - t.deepEqual( - toMarkdown( - { - type: 'paragraph', - children: [{ type: 'text', value: '$\na' }], - }, - { extensions: [directiveToMarkdown] }, - ), - '$\na\n', - 'should not escape a `:` at a break', - ); + }, { extensions: [directiveToMarkdown] }), + ).toBe('a\\$c\n'); + }); - t.deepEqual( - toMarkdown( - { - type: 'paragraph', - children: [{ type: 'text', value: '$a' }], - }, - { extensions: [directiveToMarkdown] }, - ), - '\\$a\n', - 'should not escape a `:` at a break when followed by an alpha', - ); - - t.deepEqual( - toMarkdown( - { + it('should not escape a `:` at a break', () => { + expect( + toMarkdown( + { + type: 'paragraph', + children: [{ type: 'text', value: '$\na' }], + }, + { extensions: [directiveToMarkdown] }, + ), + ).toBe('$\na\n'); + }); + + it('should not escape a `:` at a break when followed by an alpha', () => { + expect( + toMarkdown( + { + type: 'paragraph', + children: [{ type: 'text', value: '$a' }], + }, + { extensions: [directiveToMarkdown] }, + ), + ).toBe('\\$a\n'); + }); + + it('should escape a `:` at a break when followed by a colon', () => { + expect( + toMarkdown({ type: 'paragraph', children: [{ type: 'text', value: '$\na' }], - }, - { extensions: [directiveToMarkdown] }, - ), - '$\na\n', - 'should escape a `:` at a break when followed by a colon', - ); + }, { extensions: [directiveToMarkdown] }), + ).toBe('$\na\n'); + }); - t.deepEqual( - toMarkdown( - { + it('should escape a `:` after a text directive', () => { + expect( + toMarkdown({ type: 'paragraph', children: [ { type: DirectiveType.Text, name: 'red', children: [] }, { type: 'text', value: '$' }, ], - }, - { extensions: [directiveToMarkdown] }, - ), - '$red$\n', - 'should escape a `:` after a text directive', - ); + }, { extensions: [directiveToMarkdown] }), + ).toBe('$red$\n'); + }); - t.end(); }); From 781835fe332b1790b787a61d1b610f124df9a84a Mon Sep 17 00:00:00 2001 From: reiji-h Date: Tue, 16 Jul 2024 05:27:35 +0000 Subject: [PATCH 013/490] use vitest --- ...icromark-extension-growi-directive.test.js | 1512 ++++++++--------- 1 file changed, 664 insertions(+), 848 deletions(-) diff --git a/packages/remark-growi-directive/test/micromark-extension-growi-directive.test.js b/packages/remark-growi-directive/test/micromark-extension-growi-directive.test.js index 7dc509f24c4..732e417c2f9 100644 --- a/packages/remark-growi-directive/test/micromark-extension-growi-directive.test.js +++ b/packages/remark-growi-directive/test/micromark-extension-growi-directive.test.js @@ -5,410 +5,331 @@ import { htmlVoidElements } from 'html-void-elements'; import { micromark } from 'micromark'; -import test from 'tape'; +import { describe, it, expect } from 'vitest'; import { DirectiveType } from '../src/mdast-util-growi-directive/consts.js'; import { directive as syntax, directiveHtml as html } from '../src/micromark-extension-growi-directive/index.js'; -const own = {}.hasOwnProperty; - -test('micromark-extension-directive (syntax)', (t) => { - t.test('text', (t) => { - t.equal( - micromark('\\$a', options()), - '

$a

', - 'should support an escaped colon which would otherwise be a directive', - ); - - t.equal( - micromark('\\$$a', options()), - '

$

', - 'should support a directive after an escaped colon', - ); - - // t.equal( - // micromark('a :$b', options()), - // '

a :$b

', - // 'should not support a directive after a colon', - // ); - - t.equal( - micromark('$', options()), - '

$

', - 'should not support a colon not followed by an alpha', - ); - - t.equal( - micromark('a $a', options()), - '

a

', - 'should support a colon followed by an alpha', - ); - - t.equal( - micromark('$9', options()), - '

$9

', - 'should not support a colon followed by a digit', - ); - - t.equal( - micromark('$-', options()), - '

$-

', - 'should not support a colon followed by a dash', - ); - - t.equal( - micromark('$_', options()), - '

$_

', - 'should not support a colon followed by an underscore', - ); - - t.equal( - micromark('a $a9', options()), - '

a

', - 'should support a digit in a name', - ); - - t.equal( - micromark('a $a-b', options()), - '

a

', - 'should support a dash in a name', - ); - - t.equal( - micromark('$a-', options()), - '

$a-

', - 'should *not* support a dash at the end of a name', - ); - - t.equal( - micromark('a $a_b', options()), - '

a

', - 'should support an underscore in a name', - ); - - t.equal( - micromark('$a_', options()), - '

$a_

', - 'should *not* support an underscore at the end of a name', - ); - - t.equal( - micromark('$a$', options()), - '

$a$

', - 'should *not* support a colon right after a name', - ); - - t.equal( - micromark('_$directive_', options()), - '

$directive

', - 'should not interfere w/ emphasis (`_`)', - ); - - t.equal( - micromark('$a[', options()), - '

[

', - 'should support a name followed by an unclosed `[`', - ); - - t.equal( - micromark('$a(', options()), - '

(

', - 'should support a name followed by an unclosed `(`', - ); - - t.equal( - micromark('$a[b', options()), - '

[b

', - 'should support a name followed by an unclosed `[` w/ content', - ); - - t.equal( - micromark('$a(b', options()), - '

(b

', - 'should support a name followed by an unclosed `(` w/ content', - ); - - t.equal( - micromark('a $a[]', options()), - '

a

', - 'should support an empty label', - ); - - t.equal( - micromark('a $a[ \t]', options()), - '

a

', - 'should support a whitespace only label', - ); - - t.equal( - micromark('$a[\n]', options()), - '

', - 'should support an eol in an label', - ); - - t.equal( - micromark('$a[a b c]asd', options()), - '

asd

', - 'should support content in an label', - ); - - t.equal( - micromark('$a[a *b* c]asd', options()), - '

asd

', - 'should support markdown in an label', - ); - - t.equal( - micromark('a $b[c :d[e] f] g', options()), - '

a g

', - 'should support a directive in an label', - ); - - t.equal( - micromark('$a[]asd', options()), - '

asd

', - 'should support content after a label', - ); - t.equal( - micromark('a $a()', options()), - '

a

', - 'should support empty attributes', - ); +const own = {}.hasOwnProperty; - t.equal( - micromark('a $a( \t)', options()), - '

a

', - 'should support whitespace only attributes', - ); - t.equal( - micromark('$a(\n)', options()), - '

', - 'should support an eol in attributes', - ); +describe('micromark-extension-directive (syntax)', () => { + describe('text', () => { + it('should support an escaped colon which would otherwise be a directive', () => { + expect(micromark('\\$a', options())).toBe('

$a

'); + }); - t.equal( - micromark('a $a(a b c)', options()), - '

a

', - 'should support attributes w/o values', - ); + it('should support a directive after an escaped colon', () => { + expect(micromark('\\$$a', options())).toBe('

$

'); + }); - t.equal( - micromark('a $a(a=b c=d)', options()), - '

a

', - 'should support attributes w/ unquoted values', - ); + // it('should not support a directive after a colon', () => { + // expect(micromark('a :$b', options())).toBe('

a :$b

'); + // }); - t.equal( - micromark('a $a(.a .b)', options()), - '

a

', - 'should support attributes w/ class shortcut', - ); + it('should not support a colon not followed by an alpha', () => { + expect(micromark('$', options())).toBe('

$

'); + }); - t.equal( - micromark('a $a(.a.b)', options()), - '

a

', - 'should support attributes w/ class shortcut w/o whitespace between', - ); + it('should support a colon followed by an alpha', () => { + expect(micromark('a $a', options())).toBe('

a

'); + }); - t.equal( - micromark('a $a(#a #b)', options()), - '

a

', - 'should support attributes w/ id shortcut', - ); + it('should not support a colon followed by a digit', () => { + expect(micromark('$9', options())).toBe('

$9

'); + }); - t.equal( - micromark('a $a(#a#b)', options()), - '

a

', - 'should support attributes w/ id shortcut w/o whitespace between', - ); + it('should not support a colon followed by a dash', () => { + expect(micromark('$-', options())).toBe('

$-

'); + }); - t.equal( - micromark('a $a(#a.b.c#d e f=g #h.i.j)', options()), - '

a

', - 'should support attributes w/ shortcuts combined w/ other attributes', - ); + it('should not support a colon followed by an underscore', () => { + expect(micromark('$_', options())).toBe('

$_

'); + }); - t.equal( - micromark('a $a(..b)', options()), - '

a

', - 'should support attrs which starts w/ continuous dots', - ); + it('should support a digit in a name', () => { + expect(micromark('a $a9', options())).toBe('

a

'); + }); - t.equal( - micromark('a $a(.#b)', options()), - '

a

', - 'should support attrs which start w/ `#`', - ); + it('should support a dash in a name', () => { + expect(micromark('a $a-b', options())).toBe('

a

'); + }); - t.equal( - micromark('a $a(.)', options()), - '

a

', - 'should support attrs w/ (`.`)', - ); + it('should *not* support a dash at the end of a name', () => { + expect(micromark('$a-', options())).toBe('

$a-

'); + }); - t.equal( - micromark('a $a(.a=b)', options()), - '

a

', - 'should support with the attr `(.a=b)`', - ); + it('should support an underscore in a name', () => { + expect(micromark('a $a_b', options())).toBe('

a

'); + }); - t.equal( - micromark('a $a(.a"b)', options()), - '

a

', - 'should support with the attr `(.a"b)`', - ); + it('should *not* support an underscore at the end of a name', () => { + expect(micromark('$a_', options())).toBe('

$a_

'); + }); - t.equal( - micromark('a $a(.aa

', - 'should support with the attr `(.a { + expect(micromark('$a$', options())).toBe('

$a$

'); + }); - t.equal( - micromark('a $a(.a💚b)', options()), - '

a

', - 'should support most characters in shortcuts', - ); + it('should not interfere w/ emphasis (`_`)', () => { + expect(micromark('_$directive_', options())).toBe('

$directive

'); + }); - t.equal( - micromark('a $a(_)', options()), - '

a

', - 'should support an underscore in attribute names', - ); + it('should support a name followed by an unclosed `[`', () => { + expect(micromark('$a[', options())).toBe('

[

'); + }); - t.equal( - micromark('a $a(xml:lang)', options()), - '

a

', - 'should support a colon in attribute names', - ); + it('should support a name followed by an unclosed `(`', () => { + expect(micromark('$a(', options())).toBe('

(

'); + }); - t.equal( - micromark('a $a(a="b" c="d e f")', options()), - '

a

', - 'should support double quoted attributes', - ); + it('should support a name followed by an unclosed `[` w/ content', () => { + expect(micromark('$a[b', options())).toBe('

[b

'); + }); - t.equal( - micromark("a $a(a='b' c='d e f')", options()), - '

a

', - 'should support single quoted attributes', - ); + it('should support a name followed by an unclosed `(` w/ content', () => { + expect(micromark('$a(b', options())).toBe('

(b

'); + }); - t.equal( - micromark('a $a(a = b c\t=\t\'d\' f =\r"g")', options()), - '

a

', - 'should support whitespace around initializers', - ); + it('should support an empty label', () => { + expect(micromark('a $a[]', options())).toBe('

a

'); + }); - t.equal( - micromark('$a(b==)', options()), - '

(b==)

', - 'should not support `=` to start an unquoted attribute value', - ); + it('should support a whitespace only label', () => { + expect(micromark('a $a[ \t]', options())).toBe('

a

'); + }); - t.equal( - micromark('$a(b=)', options()), - '

(b=)

', - 'should not support a missing attribute value after `=`', - ); + it('should support an eol in an label', () => { + expect(micromark('$a[\n]', options())).toBe('

'); + }); - t.equal( - micromark("$a(b=c')", options()), - "

(b=c')

", - 'should not support an apostrophe in an unquoted attribute value', - ); + it('should support content in an label', () => { + expect(micromark('$a[a b c]asd', options())).toBe('

asd

'); + }); - t.equal( - micromark('$a(b=c`)', options()), - '

(b=c`)

', - 'should not support a grave accent in an unquoted attribute value', - ); - - t.equal( - micromark('a $a(b💚=a💚b)', options()), - '

a

', - 'should support most other characters in attribute keys', - ); - - t.equal( - micromark('a $a(b=a💚b)', options()), - '

a

', - 'should support most other characters in unquoted attribute values', - ); - - t.equal( - micromark('$a(b="c', options()), - '

(b="c

', - 'should not support an EOF in a quoted attribute value', - ); + it('should support markdown in an label', () => { + expect(micromark('$a[a *b* c]asd', options())).toBe('

asd

'); + }); - t.equal( - micromark('a $a(b="a💚b")', options()), - '

a

', - 'should support most other characters in quoted attribute values', - ); - - t.equal( - micromark('$a(b="\nc\r d")', options()), - '

', - 'should support EOLs in quoted attribute values', - ); + // == Resolved as text directive + // t.equal( + // micromark('$a[]asd', options()), + // '

$a[]asd

', + // 'should not support content after a label', + // ); - t.equal( - micromark('$a(b="c"', options()), - '

(b="c"

', - 'should not support an EOF after a quoted attribute value', - ); + it('should support a directive in an label', () => { + expect( + micromark('a $b[c :d[e] f] g', options()), + ).toBe('

a g

'); + }); + + it('should support content after a label', () => { + expect( + micromark('$a[]asd', options()), + ).toBe('

asd

'); + }); + + it('should support empty attributes', () => { + expect( + micromark('a $a()', options()), + ).toBe('

a

'); + }); + + it('should support whitespace only attributes', () => { + expect( + micromark('a $a( \t)', options()), + ).toBe('

a

'); + }); + + it('should support an eol in attributes', () => { + expect(micromark('$a(\n)', options())).toBe('

'); + }); + + it('should support attributes w/o values', () => { + expect(micromark('a $a(a b c)', options())).toBe('

a

'); + }); + + it('should support attributes w/ unquoted values', () => { + expect(micromark('a $a(a=b c=d)', options())).toBe('

a

'); + }); + + it('should support attributes w/ class shortcut', () => { + expect(micromark('a $a(.a .b)', options())).toBe('

a

'); + }); + + it('should support attributes w/ class shortcut w/o whitespace between', () => { + expect(micromark('a $a(.a.b)', options())).toBe('

a

'); + }); + + it('should support attributes w/ id shortcut', () => { + expect(micromark('a $a(#a #b)', options())).toBe('

a

'); + }); + + it('should support attributes w/ id shortcut w/o whitespace between', () => { + expect(micromark('a $a(#a#b)', options())).toBe('

a

'); + }); + + it('should support attributes w/ shortcuts combined w/ other attributes', () => { + expect(micromark('a $a(#a.b.c#d e f=g #h.i.j)', options())).toBe('

a

'); + }); + + it('should support attrs which starts w/ continuous dots', () => { + expect(micromark('a $a(..b)', options())).toBe('

a

'); + }); + + it('should support attrs which start w/ `#`', () => { + expect(micromark('a $a(.#b)', options())).toBe('

a

'); + }); + + it('should support attrs w/ (`.`)', () => { + expect(micromark('a $a(.)', options())).toBe('

a

'); + }); + + it('should support with the attr `(.a=b)`', () => { + expect(micromark('a $a(.a=b)', options())).toBe('

a

'); + }); + + it('should support with the attr `(.a"b)`', () => { + expect( + micromark('a $a(.a"b)', options()), + ).toBe('

a

'); + }); + + it('should support with the attr `(.a { + expect( + micromark('a $a(.aa

'); + }); + + it('should support most characters in shortcuts', () => { + expect( + micromark('a $a(.a💚b)', options()), + ).toBe('

a

'); + }); + + it('should support an underscore in attribute names', () => { + expect( + micromark('a $a(_)', options()), + ).toBe('

a

'); + }); + + it('should support a colon in attribute names', () => { + expect( + micromark('a $a(xml:lang)', options()), + ).toBe('

a

'); + }); + + it('should support double quoted attributes', () => { + expect( + micromark('a $a(a="b" c="d e f")', options()), + ).toBe('

a

'); + }); + + it('should support single quoted attributes', () => { + expect( + micromark("a $a(a='b' c='d e f')", options()), + ).toBe('

a

'); + }); + + it('should support whitespace around initializers', () => { + expect( + micromark('a $a(a = b c\t=\t\'d\' f =\r"g")', options()), + ).toBe('

a

'); + }); + + it('should not support `=` to start an unquoted attribute value', () => { + expect(micromark('$a(b==)', options())).toBe('

(b==)

'); + }); + + it('should not support a missing attribute value after `=`', () => { + expect(micromark('$a(b=)', options())).toBe('

(b=)

'); + }); + + it('should not support an apostrophe in an unquoted attribute value', () => { + expect(micromark("$a(b=c')", options())).toBe("

(b=c')

"); + }); + + it('should not support a grave accent in an unquoted attribute value', () => { + expect(micromark('$a(b=c`)', options())).toBe('

(b=c`)

'); + }); + + it('should support most other characters in attribute keys', () => { + expect( + micromark('a $a(b💚=a💚b)', options()), + ).toBe('

a

'); + }); + + it('should support most other characters in unquoted attribute values', () => { + expect( + micromark('a $a(b=a💚b)', options()), + ).toBe('

a

'); + }); + + it('should not support an EOF in a quoted attribute value', () => { + expect( + micromark('$a(b="c', options()), + ).toBe('

(b="c

'); + }); + + it('should support most other characters in quoted attribute values', () => { + expect( + micromark('a $a(b="a💚b")', options()), + ).toBe('

a

'); + }); + + it('should support EOLs in quoted attribute values', () => { + expect( + micromark('$a(b="\nc\r d")', options()), + ).toBe( + '

', + ); + }); + + it('should not support an EOF after a quoted attribute value', () => { + expect( + micromark('$a(b="c"', options()), + ).toBe( + '

(b="c"

', + ); + }); - t.end(); }); - t.test('leaf', (t) => { - t.equal(micromark('$b', options()), '', 'should support a directive'); + describe('leaf', () => { - t.equal( - micromark(':', options()), - '

:

', - 'should not support one colon', - ); + it('should support a directive', () => { + expect(micromark('$b', options())).toBe(''); + }); - t.equal( - micromark('::', options()), - '

::

', - 'should not support two colons not followed by an alpha', - ); + it('should not support one colon', () => { + expect(micromark(':', options())).toBe('

:

'); + }); - t.equal( - micromark('$a', options()), - '', - 'should support two colons followed by an alpha', - ); + it('should not support two colons not followed by an alpha', () => { + expect(micromark('::', options())).toBe('

::

'); + }); - t.equal( - micromark('$9', options()), - '

$9

', - 'should not support two colons followed by a digit', - ); + it('should support two colons followed by an alpha', () => { + expect(micromark('$a', options())).toBe(''); + }); - t.equal( - micromark('$-', options()), - '

$-

', - 'should not support two colons followed by a dash', - ); + it('should not support two colons followed by a digit', () => { + expect(micromark('$9', options())).toBe('

$9

'); + }); - t.equal( - micromark('$a9', options()), - '', - 'should support a digit in a name', - ); + it('should not support two colons followed by a dash', () => { + expect(micromark('$-', options())).toBe('

$-

'); + }); - t.equal( - micromark('$a-b', options()), - '', - 'should support a dash in a name', - ); + it('should support a digit in a name', () => { + expect(micromark('$a9', options())).toBe(''); + }); + + it('should support a dash in a name', () => { + expect(micromark('$a-b', options())).toBe(''); + }); // == Resolved as text directive // t.equal( @@ -438,13 +359,13 @@ test('micromark-extension-directive (syntax)', (t) => { // 'should not support a name followed by an unclosed `{` w/ content', // ); - t.equal(micromark('$a[]', options()), '', 'should support an empty label'); + it('should support an empty label', () => { + expect(micromark('$a[]', options())).toBe(''); + }); - t.equal( - micromark('$a[ \t]', options()), - '', - 'should support a whitespace only label', - ); + it('should support a whitespace only label', () => { + expect(micromark('$a[ \t]', options())).toBe(''); + }); // == Resolved as text directive // t.equal( @@ -453,17 +374,13 @@ test('micromark-extension-directive (syntax)', (t) => { // 'should not support an eol in an label', // ); - t.equal( - micromark('$a[a b c]', options()), - '', - 'should support content in an label', - ); + it('should support content in an label', () => { + expect(micromark('$a[a b c]', options())).toBe(''); + }); - t.equal( - micromark('$a[a *b* c]', options()), - '', - 'should support markdown in an label', - ); + it('should support markdown in an label', () => { + expect(micromark('$a[a *b* c]', options())).toBe(''); + }); // == Resolved as text directive // t.equal( @@ -472,17 +389,13 @@ test('micromark-extension-directive (syntax)', (t) => { // 'should not support content after a label', // ); - t.equal( - micromark('$a()', options()), - '', - 'should support empty attributes', - ); + it('should support empty attributes', () => { + expect(micromark('$a()', options())).toBe(''); + }); - t.equal( - micromark('$a( \t)', options()), - '', - 'should support whitespace only attributes', - ); + it('should support whitespace only attributes', () => { + expect(micromark('$a( \t)', options())).toBe(''); + }); // == Resolved as text directive // t.equal( @@ -491,53 +404,37 @@ test('micromark-extension-directive (syntax)', (t) => { // 'should not support an eol in attributes', // ); - t.equal( - micromark('$a(a b c)', options()), - '', - 'should support attributes w/o values', - ); + it('should support attributes w/o values', () => { + expect(micromark('$a(a b c)', options())).toBe(''); + }); - t.equal( - micromark('$a(a=b c=d)', options()), - '', - 'should support attributes w/ unquoted values', - ); + it('should support attributes w/ unquoted values', () => { + expect(micromark('$a(a=b c=d)', options())).toBe(''); + }); - t.equal( - micromark('$a(.a .b)', options()), - '', - 'should support attributes w/ class shortcut', - ); + it('should support attributes w/ class shortcut', () => { + expect(micromark('$a(.a .b)', options())).toBe(''); + }); - t.equal( - micromark('$a(#a #b)', options()), - '', - 'should support attributes w/ id shortcut', - ); + it('should support attributes w/ id shortcut', () => { + expect(micromark('$a(#a #b)', options())).toBe(''); + }); - t.equal( - micromark('$a(.a💚b)', options()), - '', - 'should support most characters in shortcuts', - ); + it('should support most characters in shortcuts', () => { + expect(micromark('$a(.a💚b)', options())).toBe(''); + }); - t.equal( - micromark('$a(a="b" c="d e f")', options()), - '', - 'should support double quoted attributes', - ); + it('should support double quoted attributes', () => { + expect(micromark('$a(a="b" c="d e f")', options())).toBe(''); + }); - t.equal( - micromark("$a(a='b' c='d e f')", options()), - '', - 'should support single quoted attributes', - ); + it('should support single quoted attributes', () => { + expect(micromark("$a(a='b' c='d e f')", options())).toBe(''); + }); - t.equal( - micromark("$a(a = b c\t=\t'd')", options()), - '', - 'should support whitespace around initializers', - ); + it('should support whitespace around initializers', () => { + expect(micromark("$a(a = b c\t=\t'd')", options())).toBe(''); + }); // == Resolved as text directive // t.equal( @@ -553,17 +450,13 @@ test('micromark-extension-directive (syntax)', (t) => { // 'should not support `=` to start an unquoted attribute value', // ); - t.equal( - micromark('$a(b💚=a💚b)', options()), - '', - 'should support most other characters in attribute keys', - ); + it('should support most other characters in attribute keys', () => { + expect(micromark('$a(b💚=a💚b)', options())).toBe(''); + }); - t.equal( - micromark('$a(b=a💚b)', options()), - '', - 'should support most other characters in unquoted attribute values', - ); + it('should support most other characters in unquoted attribute values', () => { + expect(micromark('$a(b=a💚b)', options())).toBe(''); + }); // == Resolved as text directive // t.equal( @@ -572,11 +465,9 @@ test('micromark-extension-directive (syntax)', (t) => { // 'should not support an EOF in a quoted attribute value', // ); - t.equal( - micromark('$a(b="a💚b")', options()), - '', - 'should support most other characters in quoted attribute values', - ); + it('should support most other characters in quoted attribute values', () => { + expect(micromark('$a(b="a💚b")', options())).toBe(''); + }); // == Resolved as text directive // t.equal( @@ -591,311 +482,262 @@ test('micromark-extension-directive (syntax)', (t) => { // 'should not support an EOF after a quoted attribute value', // ); - t.equal( - micromark('$a(b=c) \t ', options()), - '', - 'should support whitespace after directives', - ); + it('should support whitespace after directives', () => { + expect(micromark('$a(b=c) \t ', options())).toBe(''); + }); - t.equal( - micromark('$a(b=c)\n>a', options()), - '
\n

a

\n
', - 'should support a block quote after a leaf', - ); + it('should support a block quote after a leaf', () => { + expect(micromark('$a(b=c)\n>a', options())).toBe('
\n

a

\n
'); + }); - t.equal( - micromark('$a(b=c)\n```js\na', options()), - '
a\n
\n', - 'should support code (fenced) after a leaf', - ); + it('should support code (fenced) after a leaf', () => { + expect(micromark('$a(b=c)\n```js\na', options())).toBe('
a\n
\n'); + }); - t.equal( - micromark('$a(b=c)\n a', options()), - '
a\n
', - 'should support code (indented) after a leaf', - ); + it('should support code (indented) after a leaf', () => { + expect(micromark('$a(b=c)\n a', options())).toBe('
a\n
'); + }); - t.equal( - micromark('$a(b=c)\n[a]: b', options()), - '', - 'should support a definition after a leaf', - ); + it('should support a definition after a leaf', () => { + expect(micromark('$a(b=c)\n[a]: b', options())).toBe(''); + }); - t.equal( - micromark('$a(b=c)\n# a', options()), - '

a

', - 'should support a heading (atx) after a leaf', - ); + it('should support a heading (atx) after a leaf', () => { + expect(micromark('$a(b=c)\n# a', options())).toBe('

a

'); + }); - t.equal( - micromark('$a(b=c)\na\n=', options()), - '

a

', - 'should support a heading (setext) after a leaf', - ); + it('should support a heading (setext) after a leaf', () => { + expect(micromark('$a(b=c)\na\n=', options())).toBe('

a

'); + }); - t.equal( - micromark('$a(b=c)\n', options()), - '', - 'should support html after a leaf', - ); + it('should support html after a leaf', () => { + expect(micromark('$a(b=c)\n', options())).toBe(''); + }); - t.equal( - micromark('$a(b=c)\n* a', options()), - '
    \n
  • a
  • \n
', - 'should support a list after a leaf', - ); + it('should support a list after a leaf', () => { + expect(micromark('$a(b=c)\n* a', options())).toBe('
    \n
  • a
  • \n
'); + }); - t.equal( - micromark('$a(b=c)\na', options()), - '

a

', - 'should support a paragraph after a leaf', - ); + it('should support a paragraph after a leaf', () => { + expect(micromark('$a(b=c)\na', options())).toBe('

a

'); + }); - t.equal( - micromark('$a(b=c)\n***', options()), - '
', - 'should support a thematic break after a leaf', - ); + it('should support a thematic break after a leaf', () => { + expect(micromark('$a(b=c)\n***', options())).toBe('
'); + }); - t.equal( - micromark('>a\n$a(b=c)', options()), - '
\n

a

\n
\n', - 'should support a block quote before a leaf', - ); + it('should support a block quote before a leaf', () => { + expect(micromark('>a\n$a(b=c)', options())).toBe('
\n

a

\n
\n'); + }); - t.equal( - micromark('```js\na\n```\n$a(b=c)', options()), - '
a\n
\n', - 'should support code (fenced) before a leaf', - ); + it('should support code (fenced) before a leaf', () => { + expect(micromark('```js\na\n```\n$a(b=c)', options())).toBe('
a\n
\n'); + }); - t.equal( - micromark(' a\n$a(b=c)', options()), - '
a\n
\n', - 'should support code (indented) before a leaf', - ); + it('should support code (indented) before a leaf', () => { + expect(micromark(' a\n$a(b=c)', options())).toBe('
a\n
\n'); + }); - t.equal( - micromark('[a]: b\n$a(b=c)', options()), - '', - 'should support a definition before a leaf', - ); + it('should support a definition before a leaf', () => { + expect(micromark('[a]: b\n$a(b=c)', options())).toBe(''); + }); - t.equal( - micromark('# a\n$a(b=c)', options()), - '

a

\n', - 'should support a heading (atx) before a leaf', - ); + it('should support a heading (atx) before a leaf', () => { + expect(micromark('# a\n$a(b=c)', options())).toBe('

a

\n'); + }); - t.equal( - micromark('a\n=\n$a(b=c)', options()), - '

a

\n', - 'should support a heading (setext) before a leaf', - ); + it('should support a heading (setext) before a leaf', () => { + expect(micromark('a\n=\n$a(b=c)', options())).toBe('

a

\n'); + }); - t.equal( - micromark('\n$a(b=c)', options()), - '\n', - 'should support html before a leaf', - ); + it('should support html before a leaf', () => { + expect(micromark('\n$a(b=c)', options())).toBe('\n'); + }); - t.equal( - micromark('* a\n$a(b=c)', options()), - '
    \n
  • a
  • \n
\n', - 'should support a list before a leaf', - ); + it('should support a list before a leaf', () => { + expect(micromark('* a\n$a(b=c)', options())).toBe('
    \n
  • a
  • \n
\n'); + }); - t.equal( - micromark('a\n$a(b=c)', options()), - '

a

\n', - 'should support a paragraph before a leaf', - ); + it('should support a paragraph before a leaf', () => { + expect(micromark('a\n$a(b=c)', options())).toBe('

a

\n'); + }); - t.equal( - micromark('***\n$a(b=c)', options()), - '
\n', - 'should support a thematic break before a leaf', - ); + it('should support a thematic break before a leaf', () => { + expect(micromark('***\n$a(b=c)', options())).toBe('
\n'); + }); - t.equal( - micromark('> $a\nb', options({ '*': h })), - '
\n
\n

b

', - 'should not support lazyness (1)', - ); + it('should not support lazyness (1)', () => { + expect(micromark('> $a\nb', options({ '*': h }))).toBe('
\n
\n

b

'); + }); - t.equal( - micromark('> a\n$b', options({ '*': h })), - '
\n

a

\n
\n', - 'should not support lazyness (2)', - ); + it('should not support lazyness (2)', () => { + expect(micromark('> a\n$b', options({ '*': h }))).toBe('
\n

a

\n
\n'); + }); - t.end(); }); - t.end(); }); -test('micromark-extension-directive (compile)', (t) => { - t.equal( - micromark( +describe('micromark-extension-directive (compile)', () => { + + it('should support a directives (abbr)', () => { + expect( + micromark( + [ + 'a $abbr', + 'a $abbr[HTML]', + 'a $abbr(title="HyperText Markup Language")', + 'a $abbr[HTML](title="HyperText Markup Language")', + ].join('\n\n'), + options({ abbr }), + ), + ).toBe( [ - 'a $abbr', - 'a $abbr[HTML]', - 'a $abbr(title="HyperText Markup Language")', - 'a $abbr[HTML](title="HyperText Markup Language")', - ].join('\n\n'), - options({ abbr }), - ), - [ - '

a

', - '

a HTML

', - '

a

', - '

a HTML

', - ].join('\n'), - 'should support a directives (abbr)', - ); - - t.equal( - micromark( + '

a

', + '

a HTML

', + '

a

', + '

a HTML

', + ].join('\n'), + ); + }); + + it('should support directives (youtube)', () => { + expect( + micromark( + [ + 'Text:', + 'a $youtube', + 'a $youtube[Cat in a box a]', + 'a $youtube(v=1)', + 'a $youtube[Cat in a box b](v=2)', + 'Leaf:', + '$youtube', + '$youtube[Cat in a box c]', + '$youtube(v=3)', + '$youtube[Cat in a box d](v=4)', + ].join('\n\n'), + options({ youtube }), + ), + ).toBe( [ - 'Text:', - 'a $youtube', - 'a $youtube[Cat in a box a]', - 'a $youtube(v=1)', - 'a $youtube[Cat in a box b](v=2)', - 'Leaf:', - '$youtube', - '$youtube[Cat in a box c]', - '$youtube(v=3)', - '$youtube[Cat in a box d](v=4)', - ].join('\n\n'), - options({ youtube }), - ), - [ - '

Text:

', - '

a

', - '

a

', - '

a

', - '

a

', - '

Leaf:

', - '', - '', - ].join('\n'), - 'should support directives (youtube)', - ); - - t.equal( - micromark( + '

Text:

', + '

a

', + '

a

', + '

a

', + '

a

', + '

Leaf:

', + '', + '', + ].join('\n'), + ); + }); + + it('should support directives (lsx)', () => { + expect( + micromark( + [ + 'Text:', + 'a $lsx', + 'a $lsx()', + 'a $lsx(num=1)', + 'a $lsx(/)', + 'a $lsx(/,num=5,depth=1)', + 'a $lsx(/, num=5, depth=1)', + 'a $lsx(💚)', + 'Leaf:', + '$lsx', + '$lsx()', + '$lsx(num=1)', + '$lsx(/)', + '$lsx(/,num=5,depth=1)', + '$lsx(/, num=5, depth=1)', + '$lsx(💚)', + ].join('\n\n'), + options({ lsx }), + ), + ).toBe( [ - 'Text:', - 'a $lsx', - 'a $lsx()', - 'a $lsx(num=1)', - 'a $lsx(/)', - 'a $lsx(/,num=5,depth=1)', - 'a $lsx(/, num=5, depth=1)', - 'a $lsx(💚)', - 'Leaf:', - '$lsx', - '$lsx()', - '$lsx(num=1)', - '$lsx(/)', - '$lsx(/,num=5,depth=1)', - '$lsx(/, num=5, depth=1)', - '$lsx(💚)', - ].join('\n\n'), - options({ lsx }), - ), - [ - '

Text:

', - '

a

', - '

a

', - '

a

', - '

a

', - '

a

', - '

a

', - '

a

', - '

Leaf:

', - '', - '', - '', - '', - '', - '', - '', - ].join('\n'), - 'should support directives (lsx)', - ); - - t.equal( - micromark('a $youtube[Cat in a box]\n$br a', options({ youtube, '*': h })), - '

a Cat in a box\n
a

', - 'should support fall through directives (`*`)', - ); - - t.equal( - micromark('a $a[$img(src="x" alt=y)](href="z")', options({ '*': h })), - '

a y

', - 'should support fall through directives (`*`)', - ); - - t.end(); + '

Text:

', + '

a

', + '

a

', + '

a

', + '

a

', + '

a

', + '

a

', + '

a

', + '

Leaf:

', + '', + '', + '', + '', + '', + '', + '', + ].join('\n'), + ); + }); + + it('should support fall through directives (`*`)', () => { + expect( + micromark('a $youtube[Cat in a box]\n$br a', options({ youtube, '*': h })), + ).toBe('

a Cat in a box\n
a

'); + }); + + it('should support fall through directives (`*`)', () => { + expect( + micromark('a $a[$img(src="x" alt=y)](href="z")', options({ '*': h })), + ).toBe('

a y

'); + }); + }); -test('content', (t) => { - t.equal( - micromark('a $abbr[x\\&y&z]', options({ abbr })), - '

a x&y&z

', - 'should support character escapes and character references in label', - ); - - t.equal( - micromark('a $abbr[x\\[y\\]z]', options({ abbr })), - '

a x[y]z

', - 'should support escaped brackets in a label', - ); - - t.equal( - micromark('a $abbr[x[y]z]', options({ abbr })), - '

a x[y]z

', - 'should support balanced brackets in a label', - ); - - t.equal( - micromark( +describe('content', () => { + + it('should support character escapes and character references in label', () => { + expect(micromark('a $abbr[x\\&y&z]', options({ abbr }))) + .toBe('

a x&y&z

'); + }); + + it('should support escaped brackets in a label', () => { + expect(micromark('a $abbr[x\\[y\\]z]', options({ abbr }))) + .toBe('

a x[y]z

'); + }); + + it('should support balanced brackets in a label', () => { + expect(micromark('a $abbr[x[y]z]', options({ abbr }))) + .toBe('

a x[y]z

'); + }); + + it('should support balanced brackets in a label, 32 levels deep', () => { + expect(micromark( 'a $abbr[1[2[3[4[5[6[7[8[9[10[11[12[13[14[15[16[17[18[19[20[21[22[23[24[25[26[27[28[29[30[31[32[x]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]', options({ abbr }), - ), - '

a 1[2[3[4[5[6[7[8[9[10[11[12[13[14[15[16[17[18[19[20[21[22[23[24[25[26[27[28[29[30[31[32[x]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]

', - 'should support balanced brackets in a label, 32 levels deep', - ); + )).toBe('

a 1[2[3[4[5[6[7[8[9[10[11[12[13[14[15[16[17[18[19[20[21[22[23[24[25[26[27[28[29[30[31[32[x]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]

'); + }); - t.equal( - micromark( + it('should *not* support balanced brackets in a label, 33 levels deep', () => { + expect(micromark( '$abbr[1[2[3[4[5[6[7[8[9[10[11[12[13[14[15[16[17[18[19[20[21[22[23[24[25[26[27[28[29[30[31[32[33[x]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]', options({ abbr }), - ), - '

[1[2[3[4[5[6[7[8[9[10[11[12[13[14[15[16[17[18[19[20[21[22[23[24[25[26[27[28[29[30[31[32[33[x]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]

', - 'should *not* support balanced brackets in a label, 33 levels deep', - ); - - t.equal( - micromark('$abbr[a\nb\rc]', options({ abbr })), - '

a\nb\rc

', - 'should support EOLs in a label', - ); - - t.equal( - micromark('$abbr[\na\r]', options({ abbr })), - '

\na\r

', - 'should support EOLs at the edges of a label (1)', - ); - - t.equal( - micromark('$abbr[\n]', options({ abbr })), - '

\n

', - 'should support EOLs at the edges of a label (2)', - ); + )).toBe( + '

[1[2[3[4[5[6[7[8[9[10[11[12[13[14[15[16[17[18[19[20[21[22[23[24[25[26[27[28[29[30[31[32[33[x]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]

', + ); + }); + + it('should support EOLs in a label', () => { + expect(micromark('$abbr[a\nb\rc]', options({ abbr }))) + .toBe('

a\nb\rc

'); + }); + + it('should support EOLs at the edges of a label (1)', () => { + expect(micromark('$abbr[\na\r]', options({ abbr }))) + .toBe('

\na\r

'); + }); + + it('should support EOLs at the edges of a label (2)', () => { + expect(micromark('$abbr[\n]', options({ abbr }))) + .toBe('

\n

'); + }); // == does not work but I don't know why.. -- 2022.08.12 Yuki Takei // t.equal( @@ -904,149 +746,123 @@ test('content', (t) => { // 'should support EOLs around nested directives', // ); - t.equal( - micromark('$abbr[$abbr[\n]]', options({ abbr })), - '

\n

', - 'should support EOLs inside nested directives (1)', - ); - - t.equal( - micromark('$abbr[$abbr[a\nb]]', options({ abbr })), - '

a\nb

', - 'should support EOLs inside nested directives (2)', - ); - - t.equal( - micromark('$abbr[$abbr[\nb\n]]', options({ abbr })), - '

\nb\n

', - 'should support EOLs inside nested directives (3)', - ); - - t.equal( - micromark('$abbr[$abbr[\\\n]]', options({ abbr })), - '


\n

', - 'should support EOLs inside nested directives (4)', - ); - - t.equal( - micromark('a $abbr[a *b* **c** d]', options({ abbr })), - '

a a b c d

', - 'should support markdown in a label', - ); - - t.equal( - micromark('a $abbr(title=a'b)', options({ abbr })), - '

a

', - 'should support character references in unquoted attribute values', - ); - - t.equal( - micromark('a $abbr(title="a'b")', options({ abbr })), - '

a

', - 'should support character references in double attribute values', - ); - - t.equal( - micromark("a $abbr(title='a'b')", options({ abbr })), - '

a

', - 'should support character references in single attribute values', - ); - - t.equal( - micromark('a $abbr(title="a&somethingelse;b")', options({ abbr })), - '

a

', - 'should support unknown character references in attribute values', - ); - - t.equal( - micromark('$span(a\nb)', options({ '*': h })), - '

', - 'should support EOLs between attributes', - ); - - t.equal( - micromark('$span(\na\n)', options({ '*': h })), - '

', - 'should support EOLs at the edges of attributes', - ); - - t.equal( - micromark('$span(a\r= b)', options({ '*': h })), - '

', - 'should support EOLs before initializer', - ); - - t.equal( - micromark('$span(a=\r\nb)', options({ '*': h })), - '

', - 'should support EOLs after initializer', - ); - - t.equal( - micromark('$span(a=b\nc)', options({ '*': h })), - '

', - 'should support EOLs between an unquoted attribute value and a next attribute name', - ); - - t.equal( - micromark('$span(a="b\nc")', options({ '*': h })), - '

', - 'should support EOLs in a double quoted attribute value', - ); - - t.equal( - micromark("$span(a='b\nc')", options({ '*': h })), - '

', - 'should support EOLs in a single quoted attribute value', - ); - - t.equal( - micromark('a $span(#a#b)', options({ '*': h })), - '

a

', - 'should support attrs which contains `#` (1)', - ); - - t.equal( - micromark('a $span(id=a id="b" #c#d)', options({ '*': h })), - '

a

', - 'should support attrs which contains `#` (2)', - ); - - t.equal( - micromark('a $span(.a.b)', options({ '*': h })), - '

a

', - 'should support attrs with dot notation', - ); - - t.test('spec for growi plugin', (t) => { - t.equal( - micromark('a $lsx(/Sandbox)', options()), - '

a

', - 'should support name with slash', - ); + it('should support EOLs inside nested directives (1)', () => { + expect(micromark('$abbr[$abbr[\n]]', options({ abbr }))) + .toBe('

\n

'); + }); - t.equal( - micromark('a $lsx(key=value, reverse)', options()), - '

a

', - 'should support name=value and an attribute w/o value', - ); + it('should support EOLs inside nested directives (2)', () => { + expect(micromark('$abbr[$abbr[a\nb]]', options({ abbr }))) + .toBe('

a\nb

'); + }); - t.equal( - micromark('a $lsx(key=value, reverse, reverse2)', options()), - '

a

', - 'should support consecutive attributes w/o value', - ); + it('should support EOLs inside nested directives (3)', () => { + expect(micromark('$abbr[$abbr[\nb\n]]', options({ abbr }))) + .toBe('

\nb\n

'); + }); - t.equal( - micromark('a $lsx(/Sandbox, key=value, reverse)', options()), - '

a

', - 'should support name=value after an empty value attribute', - ); + it('should support EOLs inside nested directives (4)', () => { + expect(micromark('$abbr[$abbr[\\\n]]', options({ abbr }))) + .toBe('


\n

'); + }); + + it('should support markdown in a label', () => { + expect(micromark('a $abbr[a *b* **c** d]', options({ abbr }))) + .toBe('

a a b c d

'); + }); + + it('should support character references in unquoted attribute values', () => { + expect(micromark('a $abbr(title=a'b)', options({ abbr }))) + .toBe('

a

'); + }); + + it('should support character references in double attribute values', () => { + expect(micromark('a $abbr(title="a'b")', options({ abbr }))) + .toBe('

a

'); + }); + + it('should support character references in single attribute values', () => { + expect(micromark("a $abbr(title='a'b')", options({ abbr }))) + .toBe('

a

'); + }); + + it('should support unknown character references in attribute values', () => { + expect(micromark('a $abbr(title="a&somethingelse;b")', options({ abbr }))) + .toBe('

a

'); + }); + + it('should support EOLs between attributes', () => { + expect(micromark('$span(a\nb)', options({ '*': h }))) + .toBe('

'); + }); + + it('should support EOLs at the edges of attributes', () => { + expect(micromark('$span(\na\n)', options({ '*': h }))) + .toBe('

'); + }); + + it('should support EOLs before initializer', () => { + expect(micromark('$span(a\r= b)', options({ '*': h }))) + .toBe('

'); + }); + + it('should support EOLs after initializer', () => { + expect(micromark('$span(a=\r\nb)', options({ '*': h }))) + .toBe('

'); + }); + + it('should support EOLs between an unquoted attribute value and a next attribute name', () => { + expect(micromark('$span(a=b\nc)', options({ '*': h }))) + .toBe('

'); + }); + + it('should support EOLs in a double quoted attribute value', () => { + expect(micromark('$span(a="b\nc")', options({ '*': h }))) + .toBe('

'); + }); + + it('should support EOLs in a single quoted attribute value', () => { + expect(micromark("$span(a='b\nc')", options({ '*': h }))) + .toBe('

'); + }); + + it('should support attrs which contains `#` (1)', () => { + expect(micromark('a $span(#a#b)', options({ '*': h }))) + .toBe('

a

'); + }); + + it('should support attrs which contains `#` (2)', () => { + expect(micromark('a $span(id=a id="b" #c#d)', options({ '*': h }))) + .toBe('

a

'); + }); + + it('should support attrs with dot notation', () => { + expect(micromark('a $span(.a.b)', options({ '*': h }))) + .toBe('

a

'); + }); - t.end(); + describe('spec for growi plugin', () => { + it('should support name with slash', () => { + expect(micromark('a $lsx(/Sandbox)', options())) + .toBe('

a

'); + }); + + it('should support name=value and an attribute w/o value', () => { + expect(micromark('a $lsx(key=value, reverse)', options())) + .toBe('

a

'); + }); + + it('should support consecutive attributes w/o value', () => { + expect(micromark('a $lsx(key=value, reverse, reverse2)', options())) + .toBe('

a

'); + }); + + it('should support name=value after an empty value attribute', () => { + expect(micromark('a $lsx(/Sandbox, key=value, reverse)', options())) + .toBe('

a

'); + }); }); - t.end(); }); /** @type {Handle} */ From b48d6f4d6478e6936b109a2473b926c5414c7303 Mon Sep 17 00:00:00 2001 From: reiji-h Date: Tue, 16 Jul 2024 06:14:14 +0000 Subject: [PATCH 014/490] remove tape package --- packages/remark-growi-directive/package.json | 4 +- yarn.lock | 118 ++----------------- 2 files changed, 10 insertions(+), 112 deletions(-) diff --git a/packages/remark-growi-directive/package.json b/packages/remark-growi-directive/package.json index 5c2a20ec845..0e72f4457b7 100644 --- a/packages/remark-growi-directive/package.json +++ b/packages/remark-growi-directive/package.json @@ -22,7 +22,7 @@ "dev": "yarn build", "watch": "yarn tsc -w", "test": "cross-env NODE_ENV=test npm run test-coverage", - "test-api": "tape --conditions development test/**.test.js", + "test-api": "vitest run --coverage", "test-coverage": "c8 --check-coverage --branches 100 --functions 100 --lines 100 --statements 100 --reporter lcov npm run test-api", "lint": "yarn eslint \"**/*.{cjs, js,jsx,ts,tsx}\"", "lint:fix": "yarn eslint \"**/*.{cjs, js,jsx,ts,tsx}\" --fix" @@ -43,7 +43,6 @@ "uvu": "^0.5.0" }, "devDependencies": { - "@types/tape": "^4.0.0", "c8": "^7.0.0", "html-void-elements": "^2.0.0", "is-hidden": "^2.0.0", @@ -51,7 +50,6 @@ "micromark": "^3.0.0", "remark": "^14.0.0", "rimraf": "^3.0.0", - "tape": "^5.0.0", "to-vfile": "^7.0.0", "type-coverage": "^2.0.0", "unist-util-remove-position": "^4.0.0" diff --git a/yarn.lock b/yarn.lock index c5607bcf82c..09ac4452ea8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2148,6 +2148,7 @@ "@growi/editor@link:packages/editor": version "1.0.0" dependencies: + lib0 "^0.2.94" markdown-table "^3.0.3" react "^18.2.0" react-dom "^18.2.0" @@ -4691,13 +4692,6 @@ dependencies: "@types/node" "*" -"@types/tape@^4.0.0": - version "4.13.2" - resolved "https://registry.yarnpkg.com/@types/tape/-/tape-4.13.2.tgz#77215c065b1c7840da3ca5e061337bb4c7258122" - integrity sha512-V1ez/RtYRGN9cNYApw5xf27DpMkTB0033X6a2i3KUmKhSojBfbWN0i3EgZxboUG96WJLHLdOyZ01aiZwVW5aSA== - dependencies: - "@types/node" "*" - "@types/throttle-debounce@^5.0.1": version "5.0.1" resolved "https://registry.yarnpkg.com/@types/throttle-debounce/-/throttle-debounce-5.0.1.tgz#8ce917e41580b2cf16f8ee840e227947f4152b04" @@ -5428,16 +5422,6 @@ array-unique@^0.3.2: resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" integrity sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ== -array.prototype.every@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/array.prototype.every/-/array.prototype.every-1.1.3.tgz#31f01b48e1160bc4b49ecab246bf7f765c6686f9" - integrity sha512-vWnriJI//SOMOWtXbU/VXhJ/InfnNHPF6BLKn5WfY8xXy+NWql0fUy20GO3sdqBhCAO+qw8S/E5nJiZX+QFdCA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.0" - is-string "^1.0.7" - array.prototype.flat@^1.2.3, array.prototype.flat@^1.2.5: version "1.3.2" resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz#1476217df8cff17d72ee8f3ba06738db5b387d18" @@ -7843,11 +7827,6 @@ define-property@^2.0.2: is-descriptor "^1.0.2" isobject "^3.0.1" -defined@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" - integrity sha512-Y2caI5+ZwS5c3RiNDJ6u53VhQHv+hHKwhkI1iHvceKUHw9Df6EK2zRLfjejRgMuCuxK7PfSWIMwWecceVvThjQ== - del@6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/del/-/del-6.0.0.tgz#0b40d0332cea743f1614f818be4feb717714c952" @@ -8098,13 +8077,6 @@ dotenv@^8.0.0, dotenv@^8.1.0, dotenv@^8.2.0: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.6.0.tgz#061af664d19f7f4d8fc6e4ff9b584ce237adcb8b" integrity sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g== -dotignore@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/dotignore/-/dotignore-0.1.2.tgz#f942f2200d28c3a76fbdd6f0ee9f3257c8a2e905" - integrity sha512-UGGGWfSauusaVJC+8fgV+NVvBXkCTmVv7sk6nojDZZvuOUNGUy0Zk4UpHQD6EDjS0jpBwcACvH4eofvyzBcRDw== - dependencies: - minimatch "^3.0.4" - downshift@^8.2.3: version "8.2.3" resolved "https://registry.yarnpkg.com/downshift/-/downshift-8.2.3.tgz#27106a5d9f408a6f6f9350ca465801d07e52db87" @@ -8330,7 +8302,7 @@ error-ex@^1.2.0, error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.19.0, es-abstract@^1.19.1, es-abstract@^1.19.2, es-abstract@^1.19.5, es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0, es-abstract@^1.4.3: +es-abstract@^1.19.1, es-abstract@^1.19.2, es-abstract@^1.19.5, es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0, es-abstract@^1.4.3: version "1.23.3" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.23.3.tgz#8f0c5a35cd215312573c5a27c87dfd6c881a0aa0" integrity sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A== @@ -9628,11 +9600,6 @@ get-intrinsic@^1.0.1, get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@ has-symbols "^1.0.3" hasown "^2.0.0" -get-package-type@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" - integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== - get-stdin@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" @@ -9993,14 +9960,6 @@ has-bigints@^1.0.2: resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== -has-dynamic-import@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/has-dynamic-import/-/has-dynamic-import-2.0.1.tgz#9bca87846aa264f2ad224fcd014946f5e5182f52" - integrity sha512-X3fbtsZmwb6W7fJGR9o7x65fZoodygCrZ3TVycvghP62yYQfS0t4RS0Qcz+j5tQYUKeSWS09tHkWW6WhFV3XhQ== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.1" - has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" @@ -14197,12 +14156,12 @@ object-hash@>=2.0.3, object-hash@^2.0.1: resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-2.2.0.tgz#5ad518581eefc443bd763472b8ff2e9c2c0d54a5" integrity sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw== -object-inspect@^1.12.0, object-inspect@^1.13.1, object-inspect@^1.9.0: +object-inspect@^1.13.1, object-inspect@^1.9.0: version "1.13.1" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== -object-is@^1.1.4, object-is@^1.1.5: +object-is@^1.1.4: version "1.1.5" resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== @@ -16240,13 +16199,6 @@ restore-cursor@^3.1.0: onetime "^5.1.0" signal-exit "^3.0.2" -resumer@^0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/resumer/-/resumer-0.0.0.tgz#f1e8f461e4064ba39e82af3cdc2a8c893d076759" - integrity sha512-Fn9X8rX8yYF4m81rZCK/5VmrmsSbqS/i3rDLl6ZZHAXgC2nTAx3dhwG8q8odP/RmdLa2YrybDJaAMg+X1ajY3w== - dependencies: - through "~2.3.4" - ret@~0.1.10: version "0.1.15" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" @@ -17240,7 +17192,7 @@ string-template@>=1.0.0: resolved "https://registry.yarnpkg.com/string-template/-/string-template-1.0.0.tgz#9e9f2233dc00f218718ec379a28a5673ecca8b96" integrity sha1-np8iM9wA8hhxjsN5oopWc+zKi5Y= -"string-width-cjs@npm:string-width@^4.2.0": +"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -17258,15 +17210,6 @@ string-width@=4.2.2: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.0" -"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - string-width@^5.0.1, string-width@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" @@ -17298,7 +17241,7 @@ string.prototype.padend@^3.0.0: es-abstract "^1.4.3" function-bind "^1.0.2" -string.prototype.trim@^1.2.5, string.prototype.trim@^1.2.9: +string.prototype.trim@^1.2.9: version "1.2.9" resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz#b6fa326d72d2c78b6df02f7759c73f8f6274faa4" integrity sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw== @@ -17350,7 +17293,7 @@ stringify-entities@^4.0.0: character-entities-html4 "^2.0.0" character-entities-legacy "^3.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -17364,13 +17307,6 @@ strip-ansi@^3.0.0: dependencies: ansi-regex "^2.0.0" -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - strip-ansi@^7.0.1, strip-ansi@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -17787,33 +17723,6 @@ tapable@^2.2.0: resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.0.tgz#5c373d281d9c672848213d0e037d1c4165ab426b" integrity sha512-FBk4IesMV1rBxX2tfiK8RAmogtWn53puLOQlvO8XuwlgxcYbP4mVPS9Ph4aeamSyyVjOl24aYWAuc8U5kCVwMw== -tape@^5.0.0: - version "5.5.3" - resolved "https://registry.yarnpkg.com/tape/-/tape-5.5.3.tgz#b6d6f3c99a7bade12b9dcf6ee2234b1dd35e5003" - integrity sha512-hPBJZBL9S7bH9vECg/KSM24slGYV589jJr4dmtiJrLD71AL66+8o4b9HdZazXZyvnilqA7eE8z5/flKiy0KsBg== - dependencies: - array.prototype.every "^1.1.3" - call-bind "^1.0.2" - deep-equal "^2.0.5" - defined "^1.0.0" - dotignore "^0.1.2" - for-each "^0.3.3" - get-package-type "^0.1.0" - glob "^7.2.0" - has "^1.0.3" - has-dynamic-import "^2.0.1" - inherits "^2.0.4" - is-regex "^1.1.4" - minimist "^1.2.6" - object-inspect "^1.12.0" - object-is "^1.1.5" - object-keys "^1.1.1" - object.assign "^4.1.2" - resolve "^2.0.0-next.3" - resumer "^0.0.0" - string.prototype.trim "^1.2.5" - through "^2.3.8" - tar-stream@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" @@ -17915,7 +17824,7 @@ through2@^2.0.0, through2@~2.0.0: readable-stream "~2.3.6" xtend "~4.0.1" -"through@>=2.2.7 <3", through@^2.3.6, through@^2.3.8, through@~2.3.4: +"through@>=2.2.7 <3", through@^2.3.6, through@^2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" @@ -19192,7 +19101,7 @@ word-wrap@^1.2.3: resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -19210,15 +19119,6 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" From 9a6918923649eaf143d67bb2c743bfd6dddf0c3f Mon Sep 17 00:00:00 2001 From: reiji-h Date: Tue, 16 Jul 2024 06:14:26 +0000 Subject: [PATCH 015/490] fix unused test --- ...icromark-extension-growi-directive.test.js | 107 +++++++----------- 1 file changed, 40 insertions(+), 67 deletions(-) diff --git a/packages/remark-growi-directive/test/micromark-extension-growi-directive.test.js b/packages/remark-growi-directive/test/micromark-extension-growi-directive.test.js index 732e417c2f9..9b0055d92cb 100644 --- a/packages/remark-growi-directive/test/micromark-extension-growi-directive.test.js +++ b/packages/remark-growi-directive/test/micromark-extension-growi-directive.test.js @@ -332,32 +332,24 @@ describe('micromark-extension-directive (syntax)', () => { }); // == Resolved as text directive - // t.equal( - // micromark('$a[', options()), - // '

$a[

', - // 'should not support a name followed by an unclosed `[`', - // ); + // it('should not support a name followed by an unclosed `[`', () => { + // expect(micromark('$a[', options())).toBe('

$a[

'); + // }); // == Resolved as text directive - // t.equal( - // micromark('$a{', options()), - // '

$a{

', - // 'should not support a name followed by an unclosed `{`', - // ); + // it('should not support a name followed by an unclosed `{`', () => { + // expect(micromark('$a{', options())).toBe('

$a{

'); + // }); // == Resolved as text directive - // t.equal( - // micromark('$a[b', options()), - // '

$a[b

', - // 'should not support a name followed by an unclosed `[` w/ content', - // ); + // it('should not support a name followed by an unclosed `[` w/ content', () => { + // expect(micromark('$a[b', options())).toBe('

$a[b

'); + // }); // == Resolved as text directive - // t.equal( - // micromark('$a{b', options()), - // '

$a{b

', - // 'should not support a name followed by an unclosed `{` w/ content', - // ); + // it('should not support a name followed by an unclosed `{` w/ content', () => { + // expect(micromark('$a{b', options())).toBe('

$a{b

'); + // }); it('should support an empty label', () => { expect(micromark('$a[]', options())).toBe(''); @@ -368,11 +360,9 @@ describe('micromark-extension-directive (syntax)', () => { }); // == Resolved as text directive - // t.equal( - // micromark('$a[\n]', options()), - // '

$a[\n]

', - // 'should not support an eol in an label', - // ); + // it('should not support an eol in an label', () => { + // expect(micromark('$a[\n]', options())).toBe('

$a[\n]

'); + // }); it('should support content in an label', () => { expect(micromark('$a[a b c]', options())).toBe(''); @@ -383,11 +373,9 @@ describe('micromark-extension-directive (syntax)', () => { }); // == Resolved as text directive - // t.equal( - // micromark('$a[]asd', options()), - // '

$a[]asd

', - // 'should not support content after a label', - // ); + // it('should not support content after a label', () => { + // expect(micromark('$a[]asd', options())).toBe('

$a[]asd

'); + // }); it('should support empty attributes', () => { expect(micromark('$a()', options())).toBe(''); @@ -398,11 +386,9 @@ describe('micromark-extension-directive (syntax)', () => { }); // == Resolved as text directive - // t.equal( - // micromark('$a(\n)', options()), - // '

$a(\n)

', - // 'should not support an eol in attributes', - // ); + // it('should not support an eol in attributes', () => { + // expect(micromark('$a(\n)', options())).toBe('

$a(\n)

'); + // }); it('should support attributes w/o values', () => { expect(micromark('$a(a b c)', options())).toBe(''); @@ -437,18 +423,14 @@ describe('micromark-extension-directive (syntax)', () => { }); // == Resolved as text directive - // t.equal( - // micromark('$a(f =\rg)', options()), - // '

$a(f =\rg)

', - // 'should not support EOLs around initializers', - // ); + // it('should not support EOLs around initializers', () => { + // expect(micromark('$a(f =\rg)', options())).toBe('

$a(f =\rg)

'); + // }); // == Resolved as text directive - // t.equal( - // micromark('$a(b==)', options()), - // '

$a(b==)

', - // 'should not support `=` to start an unquoted attribute value', - // ); + // it('should not support `=` to start an unquoted attribute value', () => { + // expect(micromark('$a(b==)', options())).toBe('

$a(b==)

'); + // }); it('should support most other characters in attribute keys', () => { expect(micromark('$a(b💚=a💚b)', options())).toBe(''); @@ -458,29 +440,21 @@ describe('micromark-extension-directive (syntax)', () => { expect(micromark('$a(b=a💚b)', options())).toBe(''); }); - // == Resolved as text directive - // t.equal( - // micromark('$a(b="c', options()), - // '

$a(b="c

', - // 'should not support an EOF in a quoted attribute value', - // ); + it('should not support an EOF in a quoted attribute value', () => { + expect(micromark('$a(b="c', options())).toBe('

(b="c

'); + }); it('should support most other characters in quoted attribute values', () => { expect(micromark('$a(b="a💚b")', options())).toBe(''); }); - // == Resolved as text directive - // t.equal( - // micromark('$a(b="\nc\r d")', options()), - // '

$a(b="\nc\rd")

', - // 'should not support EOLs in quoted attribute values', - // ); + it('should not support EOLs in quoted attribute values', () => { + expect(micromark('$a(b="\nc\r d")', options())).toBe('

'); + }); - // t.equal( - // micromark('$a(b="c"', options()), - // '

$a(b="c"

', - // 'should not support an EOF after a quoted attribute value', - // ); + it('should not support an EOF after a quoted attribute value', () => { + expect(micromark('$a(b="c"', options())).toBe('

(b="c"

'); + }); it('should support whitespace after directives', () => { expect(micromark('$a(b=c) \t ', options())).toBe(''); @@ -740,11 +714,10 @@ describe('content', () => { }); // == does not work but I don't know why.. -- 2022.08.12 Yuki Takei - // t.equal( - // micromark('$abbr[a\n$abbr[b]\nc]', options({ abbr })), - // '

a a\nb\nc a

', - // 'should support EOLs around nested directives', - // ); + // it('should support EOLs around nested directives', () => { + // expect(micromark('$abbr[a\n$abbr[b]\nc]', options({ abbr }))) + // .toBe('

a\nb\nc

'); + // }); it('should support EOLs inside nested directives (1)', () => { expect(micromark('$abbr[$abbr[\n]]', options({ abbr }))) From e58a941b6d95a07ec29f8448bb59c9447ec4e008 Mon Sep 17 00:00:00 2001 From: reiji-h Date: Tue, 16 Jul 2024 06:32:00 +0000 Subject: [PATCH 016/490] fix code --- packages/remark-growi-directive/package.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/remark-growi-directive/package.json b/packages/remark-growi-directive/package.json index e1744255e38..37aff994fbf 100644 --- a/packages/remark-growi-directive/package.json +++ b/packages/remark-growi-directive/package.json @@ -1,3 +1,5 @@ + +{ "name": "@growi/remark-growi-directive", "version": "0.9.0", "description": "Remark plugin to support GROWI original directive (forked from remark-directive@2.0.1)", @@ -42,7 +44,7 @@ "uvu": "^0.5.0" }, "devDependencies": { - "c8": "^8.0.0", + "c8": "^7.0.0", "html-void-elements": "^2.0.0", "is-hidden": "^2.0.0", "mdast-util-from-markdown": "^2.0.1", From 4935ffbbf4c3b5599a8dc577f69cf8aff0ef1ddf Mon Sep 17 00:00:00 2001 From: reiji-h Date: Tue, 16 Jul 2024 06:33:02 +0000 Subject: [PATCH 017/490] udpate packages in remark-growi-directive --- yarn.lock | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/yarn.lock b/yarn.lock index 73fb7616c7a..e1cba6c7d69 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6140,23 +6140,23 @@ bytes@3.1.2: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== -c8@^8.0.0: - version "8.0.1" - resolved "https://registry.yarnpkg.com/c8/-/c8-8.0.1.tgz#bafd60be680e66c5530ee69f621e45b1364af9fd" - integrity sha512-EINpopxZNH1mETuI0DzRA4MZpAUH+IFiRhnmFD3vFr3vdrgxqi3VfE3KL0AIL+zDq8rC9bZqwM/VDmmoe04y7w== +c8@^7.0.0: + version "7.14.0" + resolved "https://registry.yarnpkg.com/c8/-/c8-7.14.0.tgz#f368184c73b125a80565e9ab2396ff0be4d732f3" + integrity sha512-i04rtkkcNcCf7zsQcSv/T9EbUn4RXQ6mropeMcjFOsQXQ0iGLAr/xT6TImQg4+U9hmNpN9XdvPkjUL1IzbgxJw== dependencies: "@bcoe/v8-coverage" "^0.2.3" "@istanbuljs/schema" "^0.1.3" find-up "^5.0.0" foreground-child "^2.0.0" istanbul-lib-coverage "^3.2.0" - istanbul-lib-report "^3.0.1" - istanbul-reports "^3.1.6" + istanbul-lib-report "^3.0.0" + istanbul-reports "^3.1.4" rimraf "^3.0.2" test-exclude "^6.0.0" v8-to-istanbul "^9.0.0" - yargs "^17.7.2" - yargs-parser "^21.1.1" + yargs "^16.2.0" + yargs-parser "^20.2.9" cac@^6.7.14: version "6.7.14" @@ -11283,7 +11283,7 @@ istanbul-lib-source-maps@^5.0.4: debug "^4.1.1" istanbul-lib-coverage "^3.0.0" -istanbul-reports@^3.1.3, istanbul-reports@^3.1.6: +istanbul-reports@^3.1.3, istanbul-reports@^3.1.4, istanbul-reports@^3.1.6: version "3.1.7" resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.7.tgz#daed12b9e1dca518e15c056e1e537e741280fa0b" integrity sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g== @@ -19568,7 +19568,7 @@ yargs@^15.1.0: y18n "^4.0.0" yargs-parser "^18.1.2" -yargs@^16.0.0: +yargs@^16.0.0, yargs@^16.2.0: version "16.2.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== @@ -19581,7 +19581,7 @@ yargs@^16.0.0: y18n "^5.0.5" yargs-parser "^20.2.2" -yargs@^17.0.1, yargs@^17.3.1, yargs@^17.7.1, yargs@^17.7.2, yargs@~17.7.1: +yargs@^17.0.1, yargs@^17.3.1, yargs@^17.7.1, yargs@~17.7.1: version "17.7.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== From c2341f247c5135038c1a5a946f189e8e19f195d5 Mon Sep 17 00:00:00 2001 From: reiji-h Date: Tue, 16 Jul 2024 06:33:46 +0000 Subject: [PATCH 018/490] fix lint --- .../test/mdast-util-growi-directive.test.js | 43 ++++++++++--------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/packages/remark-growi-directive/test/mdast-util-growi-directive.test.js b/packages/remark-growi-directive/test/mdast-util-growi-directive.test.js index 13b19861e3e..5112aaddfbf 100644 --- a/packages/remark-growi-directive/test/mdast-util-growi-directive.test.js +++ b/packages/remark-growi-directive/test/mdast-util-growi-directive.test.js @@ -97,27 +97,28 @@ describe('markdown -> mdast', () => { it('should support content in a label', () => { expect(tree).toEqual( - { - type: 'root', - children: [ - { - type: 'paragraph', - children: [ - { type: 'text', value: 'x ' }, - { - type: DirectiveType.Text, - name: 'a', - attributes: {}, - children: [ - { type: 'text', value: 'b ' }, - { type: 'emphasis', children: [{ type: 'text', value: 'c' }] }, - { type: 'text', value: '\nd' }, - ], - }, - ], - }, - ], - }); + { + type: 'root', + children: [ + { + type: 'paragraph', + children: [ + { type: 'text', value: 'x ' }, + { + type: DirectiveType.Text, + name: 'a', + attributes: {}, + children: [ + { type: 'text', value: 'b ' }, + { type: 'emphasis', children: [{ type: 'text', value: 'c' }] }, + { type: 'text', value: '\nd' }, + ], + }, + ], + }, + ], + }, + ); }); tree = fromMarkdown('x $a(#b.c.d e=f g="h&i&unknown;j")', { From c01ed919110d061a3c161cf769da367bf875e54a Mon Sep 17 00:00:00 2001 From: reiji-h Date: Tue, 16 Jul 2024 06:36:59 +0000 Subject: [PATCH 019/490] fix packages error --- packages/remark-growi-directive/package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/remark-growi-directive/package.json b/packages/remark-growi-directive/package.json index 37aff994fbf..de0135a9590 100644 --- a/packages/remark-growi-directive/package.json +++ b/packages/remark-growi-directive/package.json @@ -1,4 +1,3 @@ - { "name": "@growi/remark-growi-directive", "version": "0.9.0", @@ -44,7 +43,7 @@ "uvu": "^0.5.0" }, "devDependencies": { - "c8": "^7.0.0", + "c8": "^8.0.0", "html-void-elements": "^2.0.0", "is-hidden": "^2.0.0", "mdast-util-from-markdown": "^2.0.1", From 5c10f06addca1b9e2154b534364b10052d95d7b4 Mon Sep 17 00:00:00 2001 From: reiji-h Date: Tue, 16 Jul 2024 06:38:04 +0000 Subject: [PATCH 020/490] fix packages error --- yarn.lock | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/yarn.lock b/yarn.lock index e1cba6c7d69..73fb7616c7a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6140,23 +6140,23 @@ bytes@3.1.2: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== -c8@^7.0.0: - version "7.14.0" - resolved "https://registry.yarnpkg.com/c8/-/c8-7.14.0.tgz#f368184c73b125a80565e9ab2396ff0be4d732f3" - integrity sha512-i04rtkkcNcCf7zsQcSv/T9EbUn4RXQ6mropeMcjFOsQXQ0iGLAr/xT6TImQg4+U9hmNpN9XdvPkjUL1IzbgxJw== +c8@^8.0.0: + version "8.0.1" + resolved "https://registry.yarnpkg.com/c8/-/c8-8.0.1.tgz#bafd60be680e66c5530ee69f621e45b1364af9fd" + integrity sha512-EINpopxZNH1mETuI0DzRA4MZpAUH+IFiRhnmFD3vFr3vdrgxqi3VfE3KL0AIL+zDq8rC9bZqwM/VDmmoe04y7w== dependencies: "@bcoe/v8-coverage" "^0.2.3" "@istanbuljs/schema" "^0.1.3" find-up "^5.0.0" foreground-child "^2.0.0" istanbul-lib-coverage "^3.2.0" - istanbul-lib-report "^3.0.0" - istanbul-reports "^3.1.4" + istanbul-lib-report "^3.0.1" + istanbul-reports "^3.1.6" rimraf "^3.0.2" test-exclude "^6.0.0" v8-to-istanbul "^9.0.0" - yargs "^16.2.0" - yargs-parser "^20.2.9" + yargs "^17.7.2" + yargs-parser "^21.1.1" cac@^6.7.14: version "6.7.14" @@ -11283,7 +11283,7 @@ istanbul-lib-source-maps@^5.0.4: debug "^4.1.1" istanbul-lib-coverage "^3.0.0" -istanbul-reports@^3.1.3, istanbul-reports@^3.1.4, istanbul-reports@^3.1.6: +istanbul-reports@^3.1.3, istanbul-reports@^3.1.6: version "3.1.7" resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.7.tgz#daed12b9e1dca518e15c056e1e537e741280fa0b" integrity sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g== @@ -19568,7 +19568,7 @@ yargs@^15.1.0: y18n "^4.0.0" yargs-parser "^18.1.2" -yargs@^16.0.0, yargs@^16.2.0: +yargs@^16.0.0: version "16.2.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== @@ -19581,7 +19581,7 @@ yargs@^16.0.0, yargs@^16.2.0: y18n "^5.0.5" yargs-parser "^20.2.2" -yargs@^17.0.1, yargs@^17.3.1, yargs@^17.7.1, yargs@~17.7.1: +yargs@^17.0.1, yargs@^17.3.1, yargs@^17.7.1, yargs@^17.7.2, yargs@~17.7.1: version "17.7.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== From 45bbfc7e27dc5745016bea9061e5349069298d17 Mon Sep 17 00:00:00 2001 From: reiji-h Date: Tue, 16 Jul 2024 07:49:09 +0000 Subject: [PATCH 021/490] fix lint in test --- .../test/mdast-util-growi-directive.test.js | 39 ++++++++++--------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/packages/remark-growi-directive/test/mdast-util-growi-directive.test.js b/packages/remark-growi-directive/test/mdast-util-growi-directive.test.js index 5112aaddfbf..dffc1c56324 100644 --- a/packages/remark-growi-directive/test/mdast-util-growi-directive.test.js +++ b/packages/remark-growi-directive/test/mdast-util-growi-directive.test.js @@ -88,14 +88,15 @@ describe('markdown -> mdast', () => { }); }); - let tree = fromMarkdown('x $a[b *c*\nd]', { - extensions: [directive()], - mdastExtensions: [directiveFromMarkdown], - }); - - removePosition(tree, { force: true }); it('should support content in a label', () => { + const tree = fromMarkdown('x $a[b *c*\nd]', { + extensions: [directive()], + mdastExtensions: [directiveFromMarkdown], + }); + + removePosition(tree, { force: true }); + expect(tree).toEqual( { type: 'root', @@ -121,14 +122,15 @@ describe('markdown -> mdast', () => { ); }); - tree = fromMarkdown('x $a(#b.c.d e=f g="h&i&unknown;j")', { - extensions: [directive()], - mdastExtensions: [directiveFromMarkdown], - }); - - removePosition(tree, { force: true }); it('should support attributes', () => { + const tree = fromMarkdown('x $a(#b.c.d e=f g="h&i&unknown;j")', { + extensions: [directive()], + mdastExtensions: [directiveFromMarkdown], + }); + + removePosition(tree, { force: true }); + expect(tree).toEqual({ type: 'root', children: [ @@ -150,14 +152,15 @@ describe('markdown -> mdast', () => { }); }); - tree = fromMarkdown('$a(b\nc="d\ne")', { - extensions: [directive()], - mdastExtensions: [directiveFromMarkdown], - }); - - removePosition(tree, { force: true }); it('should support EOLs in attributes', () => { + const tree = fromMarkdown('$a(b\nc="d\ne")', { + extensions: [directive()], + mdastExtensions: [directiveFromMarkdown], + }); + + removePosition(tree, { force: true }); + expect(tree).toEqual({ type: 'root', children: [ From c069b651f1e45ec2c3b9278c7be769fd9fb930bf Mon Sep 17 00:00:00 2001 From: reiji-h Date: Tue, 16 Jul 2024 08:57:34 +0000 Subject: [PATCH 022/490] remove vites import --- .../test/mdast-util-growi-directive.test.js | 5 ++--- .../test/micromark-extension-growi-directive.test.js | 1 - .../test/remark-growi-directive.test.js | 1 - 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/remark-growi-directive/test/mdast-util-growi-directive.test.js b/packages/remark-growi-directive/test/mdast-util-growi-directive.test.js index dffc1c56324..2bf57c9ca5f 100644 --- a/packages/remark-growi-directive/test/mdast-util-growi-directive.test.js +++ b/packages/remark-growi-directive/test/mdast-util-growi-directive.test.js @@ -1,7 +1,6 @@ import { fromMarkdown } from 'mdast-util-from-markdown'; import { toMarkdown } from 'mdast-util-to-markdown'; import { removePosition } from 'unist-util-remove-position'; -import { describe, it, expect } from 'vitest'; import { DirectiveType } from '../src/mdast-util-growi-directive/consts.js'; import { directiveFromMarkdown, directiveToMarkdown } from '../src/mdast-util-growi-directive/index.js'; @@ -463,7 +462,7 @@ describe('mdast -> markdown', () => { }, { extensions: [directiveToMarkdown] }, ), - ).toEqual('$a(#b .c.d key="e f")\n'); + ).toBe('$a(#b .c.d key="e f")\n'); }); it('should escape a `:` in phrasing when followed by an alpha', () => { @@ -475,7 +474,7 @@ describe('mdast -> markdown', () => { }, { extensions: [directiveToMarkdown] }, ), - ).toEqual('a\\$b\n'); + ).toBe('a\\$b\n'); }); it('should not escape a `:` in phrasing when followed by a non-alpha', () => { diff --git a/packages/remark-growi-directive/test/micromark-extension-growi-directive.test.js b/packages/remark-growi-directive/test/micromark-extension-growi-directive.test.js index 9b0055d92cb..50576281067 100644 --- a/packages/remark-growi-directive/test/micromark-extension-growi-directive.test.js +++ b/packages/remark-growi-directive/test/micromark-extension-growi-directive.test.js @@ -5,7 +5,6 @@ import { htmlVoidElements } from 'html-void-elements'; import { micromark } from 'micromark'; -import { describe, it, expect } from 'vitest'; import { DirectiveType } from '../src/mdast-util-growi-directive/consts.js'; import { directive as syntax, directiveHtml as html } from '../src/micromark-extension-growi-directive/index.js'; diff --git a/packages/remark-growi-directive/test/remark-growi-directive.test.js b/packages/remark-growi-directive/test/remark-growi-directive.test.js index 3cbbb870181..49856e54f82 100644 --- a/packages/remark-growi-directive/test/remark-growi-directive.test.js +++ b/packages/remark-growi-directive/test/remark-growi-directive.test.js @@ -9,7 +9,6 @@ import { isHidden } from 'is-hidden'; import { remark } from 'remark'; import { readSync } from 'to-vfile'; import { unified } from 'unified'; -import { describe, it, expect } from 'vitest'; import { remarkGrowiDirectivePlugin } from '../src/remark-growi-directive.js'; From c66c2e5df2b138b8d084e0826e39bd506f827241 Mon Sep 17 00:00:00 2001 From: reiji-h Date: Tue, 16 Jul 2024 09:29:51 +0000 Subject: [PATCH 023/490] fix import react-markdown --- apps/app/src/client/components/Page/SlideRenderer.tsx | 2 +- apps/app/src/client/components/PagePresentationModal.tsx | 2 +- .../client/components/ReactMarkdownComponents/Header.tsx | 2 +- .../ReactMarkdownComponents/TableWithEditButton.tsx | 2 +- apps/app/src/interfaces/renderer-options.ts | 7 ++----- packages/presentation/src/client/consts/index.ts | 2 +- 6 files changed, 7 insertions(+), 10 deletions(-) diff --git a/apps/app/src/client/components/Page/SlideRenderer.tsx b/apps/app/src/client/components/Page/SlideRenderer.tsx index aa975a4600a..58225dc1cb6 100644 --- a/apps/app/src/client/components/Page/SlideRenderer.tsx +++ b/apps/app/src/client/components/Page/SlideRenderer.tsx @@ -1,4 +1,4 @@ -import type { ReactMarkdownOptions } from 'react-markdown/lib/react-markdown'; +import type { Options as ReactMarkdownOptions } from 'react-markdown'; import { usePresentationViewOptions } from '~/stores/renderer'; diff --git a/apps/app/src/client/components/PagePresentationModal.tsx b/apps/app/src/client/components/PagePresentationModal.tsx index d55e400b003..7796841113c 100644 --- a/apps/app/src/client/components/PagePresentationModal.tsx +++ b/apps/app/src/client/components/PagePresentationModal.tsx @@ -5,7 +5,7 @@ import { useSlidesByFrontmatter } from '@growi/presentation/dist/services'; import { LoadingSpinner } from '@growi/ui/dist/components'; import { useFullScreen } from '@growi/ui/dist/utils'; import dynamic from 'next/dynamic'; -import type { ReactMarkdownOptions } from 'react-markdown/lib/react-markdown'; +import type { Options as ReactMarkdownOptions } from 'react-markdown'; import { Modal, ModalBody, } from 'reactstrap'; diff --git a/apps/app/src/client/components/ReactMarkdownComponents/Header.tsx b/apps/app/src/client/components/ReactMarkdownComponents/Header.tsx index d9872cebe00..816c1589873 100644 --- a/apps/app/src/client/components/ReactMarkdownComponents/Header.tsx +++ b/apps/app/src/client/components/ReactMarkdownComponents/Header.tsx @@ -2,8 +2,8 @@ import { useCallback, useEffect, useState } from 'react'; import type EventEmitter from 'events'; +import type { Element } from 'hast'; import { useRouter } from 'next/router'; -import type { Element } from 'react-markdown/lib/rehype-filter'; import { NextLink } from '~/components/ReactMarkdownComponents/NextLink'; import { diff --git a/apps/app/src/client/components/ReactMarkdownComponents/TableWithEditButton.tsx b/apps/app/src/client/components/ReactMarkdownComponents/TableWithEditButton.tsx index df04c3eecd0..aeaa6c234f0 100644 --- a/apps/app/src/client/components/ReactMarkdownComponents/TableWithEditButton.tsx +++ b/apps/app/src/client/components/ReactMarkdownComponents/TableWithEditButton.tsx @@ -2,7 +2,7 @@ import React, { useCallback } from 'react'; import type EventEmitter from 'events'; -import type { Element } from 'react-markdown/lib/rehype-filter'; +import type { Element } from 'hast'; import { useIsGuestUser, useIsReadOnlyUser, useIsSharedUser, useShareLinkId, diff --git a/apps/app/src/interfaces/renderer-options.ts b/apps/app/src/interfaces/renderer-options.ts index bb8f724bd64..d7fda5d4500 100644 --- a/apps/app/src/interfaces/renderer-options.ts +++ b/apps/app/src/interfaces/renderer-options.ts @@ -1,8 +1,6 @@ import type { ComponentType } from 'react'; -import type { SpecialComponents } from 'react-markdown/lib/ast-to-react'; -import type { NormalComponents } from 'react-markdown/lib/complex-types'; -import type { ReactMarkdownOptions } from 'react-markdown/lib/react-markdown'; +import type { Options as ReactMarkdownOptions, Components } from 'react-markdown'; import type { PluggableList } from 'unified'; export type RendererOptions = Omit & { @@ -10,8 +8,7 @@ export type RendererOptions = Omit - & SpecialComponents + Components & { [elem: string]: ComponentType, } diff --git a/packages/presentation/src/client/consts/index.ts b/packages/presentation/src/client/consts/index.ts index 29c0243ee53..dfb86f83ad1 100644 --- a/packages/presentation/src/client/consts/index.ts +++ b/packages/presentation/src/client/consts/index.ts @@ -1,4 +1,4 @@ -import type { ReactMarkdownOptions } from 'react-markdown/lib/react-markdown'; +import type { Options as ReactMarkdownOptions } from 'react-markdown'; import type { Options as RevealOptions } from 'reveal.js'; export type PresentationOptions = { From 04d272143ecf129acb2a50214e3ad15d001084ba Mon Sep 17 00:00:00 2001 From: reiji-h Date: Wed, 17 Jul 2024 07:27:07 +0000 Subject: [PATCH 024/490] header cannot receive level --- .../src/client/components/ReactMarkdownComponents/Header.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/apps/app/src/client/components/ReactMarkdownComponents/Header.tsx b/apps/app/src/client/components/ReactMarkdownComponents/Header.tsx index 816c1589873..c6583061d46 100644 --- a/apps/app/src/client/components/ReactMarkdownComponents/Header.tsx +++ b/apps/app/src/client/components/ReactMarkdownComponents/Header.tsx @@ -54,13 +54,12 @@ const EditLink = (props: EditLinkProps): JSX.Element => { type HeaderProps = { children: React.ReactNode, node: Element, - level: number, id?: string, } export const Header = (props: HeaderProps): JSX.Element => { const { - node, id, children, level, + node, id, children, } = props; const { data: isGuestUser } = useIsGuestUser(); @@ -73,7 +72,7 @@ export const Header = (props: HeaderProps): JSX.Element => { const [isActive, setActive] = useState(false); - const CustomTag = `h${level}` as keyof JSX.IntrinsicElements; + const CustomTag = node.tagName as keyof JSX.IntrinsicElements; const activateByHash = useCallback((url: string) => { try { From 9e0f52df70513a7b90b092f9922b75be579392e8 Mon Sep 17 00:00:00 2001 From: reiji-h Date: Wed, 17 Jul 2024 07:49:34 +0000 Subject: [PATCH 025/490] use import vitest --- .../test/mdast-util-growi-directive.test.js | 1 + .../test/micromark-extension-growi-directive.test.js | 1 + .../remark-growi-directive/test/remark-growi-directive.test.js | 2 ++ 3 files changed, 4 insertions(+) diff --git a/packages/remark-growi-directive/test/mdast-util-growi-directive.test.js b/packages/remark-growi-directive/test/mdast-util-growi-directive.test.js index 2bf57c9ca5f..85323ec8ad0 100644 --- a/packages/remark-growi-directive/test/mdast-util-growi-directive.test.js +++ b/packages/remark-growi-directive/test/mdast-util-growi-directive.test.js @@ -1,6 +1,7 @@ import { fromMarkdown } from 'mdast-util-from-markdown'; import { toMarkdown } from 'mdast-util-to-markdown'; import { removePosition } from 'unist-util-remove-position'; +import { describe, it, expect } from 'vitest'; import { DirectiveType } from '../src/mdast-util-growi-directive/consts.js'; import { directiveFromMarkdown, directiveToMarkdown } from '../src/mdast-util-growi-directive/index.js'; diff --git a/packages/remark-growi-directive/test/micromark-extension-growi-directive.test.js b/packages/remark-growi-directive/test/micromark-extension-growi-directive.test.js index 50576281067..9b0055d92cb 100644 --- a/packages/remark-growi-directive/test/micromark-extension-growi-directive.test.js +++ b/packages/remark-growi-directive/test/micromark-extension-growi-directive.test.js @@ -5,6 +5,7 @@ import { htmlVoidElements } from 'html-void-elements'; import { micromark } from 'micromark'; +import { describe, it, expect } from 'vitest'; import { DirectiveType } from '../src/mdast-util-growi-directive/consts.js'; import { directive as syntax, directiveHtml as html } from '../src/micromark-extension-growi-directive/index.js'; diff --git a/packages/remark-growi-directive/test/remark-growi-directive.test.js b/packages/remark-growi-directive/test/remark-growi-directive.test.js index 49856e54f82..4a4c30279e0 100644 --- a/packages/remark-growi-directive/test/remark-growi-directive.test.js +++ b/packages/remark-growi-directive/test/remark-growi-directive.test.js @@ -5,10 +5,12 @@ import fs from 'node:fs'; import path from 'node:path'; + import { isHidden } from 'is-hidden'; import { remark } from 'remark'; import { readSync } from 'to-vfile'; import { unified } from 'unified'; +import { describe, it, expect } from 'vitest'; import { remarkGrowiDirectivePlugin } from '../src/remark-growi-directive.js'; From a5bab3eaabe7daef7b5be5990a205e78c9da1471 Mon Sep 17 00:00:00 2001 From: reiji-h Date: Wed, 17 Jul 2024 10:17:39 +0000 Subject: [PATCH 026/490] Update for dependencies --- .../src/remark-growi-directive.js | 39 +++++++++---------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/packages/remark-growi-directive/src/remark-growi-directive.js b/packages/remark-growi-directive/src/remark-growi-directive.js index 67c34999a01..610d14cbe5d 100644 --- a/packages/remark-growi-directive/src/remark-growi-directive.js +++ b/packages/remark-growi-directive/src/remark-growi-directive.js @@ -1,7 +1,6 @@ /** * @typedef {import('mdast').Root} Root - * - * @typedef {import('mdast-util-directive')} DoNotTouchAsThisImportIncludesDirectivesInTree + * @typedef {import('unified').Processor} Processor */ import { directiveFromMarkdown, directiveToMarkdown } from './mdast-util-growi-directive/index.js'; @@ -10,26 +9,26 @@ import { directive } from './micromark-extension-growi-directive/index.js'; /** * Plugin to support GROWI plugin (`$lsx(/path, depth=2)`). * - * @type {import('unified').Plugin} + * Add support for generic directives. + * + * ###### Notes + * + * Doesn’t handle the directives: create your own plugin to do that. + * + * @returns {undefined} + * Nothing. */ export function remarkGrowiDirectivePlugin() { - const data = this.data(); - - add('micromarkExtensions', directive()); - add('fromMarkdownExtensions', directiveFromMarkdown); - add('toMarkdownExtensions', directiveToMarkdown); + // @ts-expect-error: TS is wrong about `this`. + // eslint-disable-next-line @typescript-eslint/no-this-alias + const self = /** @type {Processor} */ (this); + const data = self.data(); - /** - * @param {string} field - * @param {unknown} value - */ - function add(field, value) { - const list = /** @type {unknown[]} */ ( - // Other extensions - /* c8 ignore next 2 */ - data[field] ? data[field] : (data[field] = []) - ); + const micromarkExtensions = data.micromarkExtensions || (data.micromarkExtensions = []); + const fromMarkdownExtensions = data.fromMarkdownExtensions || (data.fromMarkdownExtensions = []); + const toMarkdownExtensions = data.toMarkdownExtensions || (data.toMarkdownExtensions = []); - list.push(value); - } + micromarkExtensions.push(directive()); + fromMarkdownExtensions.push(directiveFromMarkdown()); + toMarkdownExtensions.push(directiveToMarkdown()); } From cc9e1af637876f867f480cdce2e6e492a7e0c88c Mon Sep 17 00:00:00 2001 From: Yuki Takei Date: Thu, 18 Jul 2024 20:30:26 +0900 Subject: [PATCH 027/490] Create changeset --- .changeset/real-onions-vanish.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/real-onions-vanish.md diff --git a/.changeset/real-onions-vanish.md b/.changeset/real-onions-vanish.md new file mode 100644 index 00000000000..8a02e538b4d --- /dev/null +++ b/.changeset/real-onions-vanish.md @@ -0,0 +1,5 @@ +--- +"@growi/remark-growi-directive": minor +--- + +Convert unit test by tape to Vitest From 4d350ef5f9aefb7dcd98edb9b9fd47073ee22adc Mon Sep 17 00:00:00 2001 From: reiji-h Date: Fri, 19 Jul 2024 06:34:27 +0000 Subject: [PATCH 028/490] add type annotation --- apps/app/src/features/mermaid/services/mermaid.ts | 10 +++++----- .../services/renderer/remark-plugins/xsv-to-table.ts | 9 +++++---- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/apps/app/src/features/mermaid/services/mermaid.ts b/apps/app/src/features/mermaid/services/mermaid.ts index 19ab4cd4fe8..53bb9a7d42b 100644 --- a/apps/app/src/features/mermaid/services/mermaid.ts +++ b/apps/app/src/features/mermaid/services/mermaid.ts @@ -1,9 +1,9 @@ import type { Schema as SanitizeOption } from 'hast-util-sanitize'; -import { Plugin } from 'unified'; -import { Node } from 'unist'; +import type { Code } from 'mdast'; +import type { Plugin } from 'unified'; import { visit } from 'unist-util-visit'; -function rewriteNode(node: Node) { +function rewriteNode(node: Code) { // replace node const data = node.data ?? (node.data = {}); data.hName = 'mermaid'; @@ -12,8 +12,8 @@ function rewriteNode(node: Node) { export const remarkPlugin: Plugin = function() { return (tree) => { visit(tree, (node) => { - if (node.type === 'code' && node.lang === 'mermaid') { - rewriteNode(node); + if (node.type === 'code' && (node as Code).lang === 'mermaid') { + rewriteNode(node as Code); } }); }; diff --git a/apps/app/src/services/renderer/remark-plugins/xsv-to-table.ts b/apps/app/src/services/renderer/remark-plugins/xsv-to-table.ts index a8f443dd851..1c831bc63df 100644 --- a/apps/app/src/services/renderer/remark-plugins/xsv-to-table.ts +++ b/apps/app/src/services/renderer/remark-plugins/xsv-to-table.ts @@ -1,4 +1,5 @@ import csvToMarkdownTable from 'csv-to-markdown-table'; +import type { Code, Table } from 'mdast'; import { fromMarkdown } from 'mdast-util-from-markdown'; import { gfmTableFromMarkdown } from 'mdast-util-gfm-table'; import { gfmTable } from 'micromark-extension-gfm-table'; @@ -8,7 +9,7 @@ import { visit } from 'unist-util-visit'; type Lang = 'csv' | 'csv-h' | 'tsv' | 'tsv-h'; -function isXsv(lang: unknown): lang is Lang { +function isXsv(lang?: string | null | undefined): lang is Lang { return /^(csv|csv-h|tsv|tsv-h)$/.test(lang as string); } @@ -28,7 +29,7 @@ function rewriteNode(node: Node, lang: Lang) { // replace node if (tableTree.children[0] != null) { node.type = 'table'; - node.children = tableTree.children[0].children; + (node as Table).children = tableTree.children[0].children; } } @@ -36,8 +37,8 @@ export const remarkPlugin: Plugin = function() { return (tree) => { visit(tree, (node) => { if (node.type === 'code') { - if (isXsv(node.lang)) { - rewriteNode(node, node.lang); + if (isXsv((node as Code).lang)) { + rewriteNode((node as Code), (node as Code).lang as Lang); } } }); From 889b85810fd56d8d9929e24436f7e69b946e216d Mon Sep 17 00:00:00 2001 From: reiji-h Date: Fri, 19 Jul 2024 06:34:43 +0000 Subject: [PATCH 029/490] remvoe memo for setting components --- .../ReactMarkdownComponents/TableWithEditButton.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/app/src/client/components/ReactMarkdownComponents/TableWithEditButton.tsx b/apps/app/src/client/components/ReactMarkdownComponents/TableWithEditButton.tsx index aeaa6c234f0..e8bfc9e747e 100644 --- a/apps/app/src/client/components/ReactMarkdownComponents/TableWithEditButton.tsx +++ b/apps/app/src/client/components/ReactMarkdownComponents/TableWithEditButton.tsx @@ -22,7 +22,7 @@ type TableWithEditButtonProps = { className?: string } -export const TableWithEditButton = React.memo((props: TableWithEditButtonProps): JSX.Element => { +export const TableWithEditButton = (props: TableWithEditButtonProps): JSX.Element => { const { children, node, className } = props; @@ -53,5 +53,5 @@ export const TableWithEditButton = React.memo((props: TableWithEditButtonProps): ); -}); +}; TableWithEditButton.displayName = 'TableWithEditButton'; From 1288ecdbea468dbd7da42879ead587841c7a05cc Mon Sep 17 00:00:00 2001 From: reiji-h Date: Fri, 19 Jul 2024 06:35:59 +0000 Subject: [PATCH 030/490] fix type --- apps/app/src/client/services/renderer/renderer.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/app/src/client/services/renderer/renderer.tsx b/apps/app/src/client/services/renderer/renderer.tsx index 75567be59e8..b5cb77f8bb5 100644 --- a/apps/app/src/client/services/renderer/renderer.tsx +++ b/apps/app/src/client/services/renderer/renderer.tsx @@ -71,7 +71,7 @@ export const generateViewOptions = ( remarkPlugins.push(breaks); } - const rehypeSanitizePlugin: Pluggable | (() => void) = config.isEnabledXssPrevention + const rehypeSanitizePlugin: Pluggable | (() => void) = config.isEnabledXssPrevention ? [sanitize, deepmerge( getCommonSanitizeOption(config), presentation.sanitizeOption, @@ -129,7 +129,7 @@ export const generateTocOptions = (config: RendererConfig, tocNode: HtmlElementN // add remark plugins // remarkPlugins.push(); - const rehypeSanitizePlugin: Pluggable | (() => void) = config.isEnabledXssPrevention + const rehypeSanitizePlugin: Pluggable | (() => void) = config.isEnabledXssPrevention ? [sanitize, deepmerge( getCommonSanitizeOption(config), )] @@ -176,7 +176,7 @@ export const generateSimpleViewOptions = ( remarkPlugins.push(breaks); } - const rehypeSanitizePlugin: Pluggable | (() => void) = config.isEnabledXssPrevention + const rehypeSanitizePlugin: Pluggable | (() => void) = config.isEnabledXssPrevention ? [sanitize, deepmerge( getCommonSanitizeOption(config), presentation.sanitizeOption, @@ -227,7 +227,7 @@ export const generatePresentationViewOptions = ( const { rehypePlugins } = options; - const rehypeSanitizePlugin: Pluggable | (() => void) = config.isEnabledXssPrevention + const rehypeSanitizePlugin: Pluggable | (() => void) = config.isEnabledXssPrevention ? [sanitize, deepmerge( addLineNumberAttribute.sanitizeOption, )] @@ -265,7 +265,7 @@ export const generatePreviewOptions = (config: RendererConfig, pagePath: string) remarkPlugins.push(breaks); } - const rehypeSanitizePlugin: Pluggable | (() => void) = config.isEnabledXssPrevention + const rehypeSanitizePlugin: Pluggable | (() => void) = config.isEnabledXssPrevention ? [sanitize, deepmerge( getCommonSanitizeOption(config), drawio.sanitizeOption, From a5446a6c3e08e132e9536ea44594be19411d3865 Mon Sep 17 00:00:00 2001 From: reiji-h Date: Fri, 19 Jul 2024 06:37:18 +0000 Subject: [PATCH 031/490] split inilnecode in codeblock --- .../src/components/ReactMarkdownComponents/CodeBlock.tsx | 9 ++++----- apps/app/src/services/renderer/renderer.tsx | 5 +++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/apps/app/src/components/ReactMarkdownComponents/CodeBlock.tsx b/apps/app/src/components/ReactMarkdownComponents/CodeBlock.tsx index c6ac548e594..e7768296bf5 100644 --- a/apps/app/src/components/ReactMarkdownComponents/CodeBlock.tsx +++ b/apps/app/src/components/ReactMarkdownComponents/CodeBlock.tsx @@ -1,6 +1,5 @@ import type { ReactNode } from 'react'; -import type { CodeComponent, CodeProps } from 'react-markdown/lib/ast-to-react'; import { PrismAsyncLight } from 'react-syntax-highlighter'; import { oneDark } from 'react-syntax-highlighter/dist/cjs/styles/prism'; @@ -67,11 +66,11 @@ function CodeBlockSubstance({ lang, children }: { lang: string, children: ReactN ); } -export const CodeBlock: CodeComponent = ({ inline, className, children }: CodeProps) => { +export const InlineCodeBlock = ({ className, children }: { className: string, children: JSX.Element}): JSX.Element => { + return {children}; +}; - if (inline) { - return {children}; - } +export const CodeBlock = ({ className, children }: {className: string, children: JSX.Element}): JSX.Element => { // TODO: set border according to the value of 'customize:highlightJsStyleBorder' diff --git a/apps/app/src/services/renderer/renderer.tsx b/apps/app/src/services/renderer/renderer.tsx index 31c6a339ebe..150181e0c16 100644 --- a/apps/app/src/services/renderer/renderer.tsx +++ b/apps/app/src/services/renderer/renderer.tsx @@ -14,7 +14,7 @@ import deepmerge from 'ts-deepmerge'; import type { Pluggable, PluginTuple } from 'unified'; -import { CodeBlock } from '~/components/ReactMarkdownComponents/CodeBlock'; +import { InlineCodeBlock, CodeBlock } from '~/components/ReactMarkdownComponents/CodeBlock'; import { NextLink } from '~/components/ReactMarkdownComponents/NextLink'; import type { RendererOptions } from '~/interfaces/renderer-options'; import { RehypeSanitizeType } from '~/interfaces/services/rehype-sanitize'; @@ -111,6 +111,7 @@ export const generateCommonOptions = (pagePath: string|undefined): RendererOptio ], components: { a: NextLink, + inlinecode: InlineCodeBlock, code: CodeBlock, }, }; @@ -137,7 +138,7 @@ export const generateSSRViewOptions = ( remarkPlugins.push(breaks); } - const rehypeSanitizePlugin: Pluggable | (() => void) = config.isEnabledXssPrevention + const rehypeSanitizePlugin: Pluggable | (() => void) = config.isEnabledXssPrevention ? [sanitize, deepmerge( getCommonSanitizeOption(config), )] From 59ea1bb359ef0000b009276955fbea563af42505 Mon Sep 17 00:00:00 2001 From: reiji-h Date: Fri, 19 Jul 2024 07:51:17 +0000 Subject: [PATCH 032/490] add types --- .../renderer/remark-plugins/attachment.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/apps/app/src/services/renderer/remark-plugins/attachment.ts b/apps/app/src/services/renderer/remark-plugins/attachment.ts index cfc4e63a43d..da93cf1952a 100644 --- a/apps/app/src/services/renderer/remark-plugins/attachment.ts +++ b/apps/app/src/services/renderer/remark-plugins/attachment.ts @@ -1,8 +1,9 @@ import path from 'path'; -import { Schema as SanitizeOption } from 'hast-util-sanitize'; -import { Plugin } from 'unified'; -import { Node } from 'unist'; +import type { Schema as SanitizeOption } from 'hast-util-sanitize'; +import type { Link } from 'mdast'; +import type { Plugin } from 'unified'; +import type { Node } from 'unist'; import { visit } from 'unist-util-visit'; const SUPPORTED_ATTRIBUTES = ['attachmentId', 'url', 'attachmentName']; @@ -13,14 +14,14 @@ const isAttachmentLink = (url: string): boolean => { return attachmentUrlFormat.test(url); }; -const rewriteNode = (node: Node) => { +const rewriteNode = (node: Link) => { const attachmentId = path.basename(node.url as string); const data = node.data ?? (node.data = {}); data.hName = 'attachment'; data.hProperties = { attachmentId, url: node.url, - attachmentName: (node.children as any)[0]?.value, + attachmentName: node.children[0] ?? '', }; }; @@ -29,8 +30,8 @@ export const remarkPlugin: Plugin = () => { return (tree) => { visit(tree, (node) => { if (node.type === 'link') { - if (isAttachmentLink(node.url as string)) { - rewriteNode(node); + if (isAttachmentLink((node as Link).url as string)) { + rewriteNode(node as Link); } } }); From 80ef86c44d7e60eeee3dd4acf0a8d574107fa34f Mon Sep 17 00:00:00 2001 From: reiji-h Date: Fri, 19 Jul 2024 07:52:10 +0000 Subject: [PATCH 033/490] create remark-plugin for inlinecode --- .../remark-plugins/inline-codeblock.ts | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 apps/app/src/services/renderer/remark-plugins/inline-codeblock.ts diff --git a/apps/app/src/services/renderer/remark-plugins/inline-codeblock.ts b/apps/app/src/services/renderer/remark-plugins/inline-codeblock.ts new file mode 100644 index 00000000000..ffe7da0f00c --- /dev/null +++ b/apps/app/src/services/renderer/remark-plugins/inline-codeblock.ts @@ -0,0 +1,25 @@ + +import type { Schema as SanitizeOption } from 'hast-util-sanitize'; +import type { InlineCode } from 'mdast'; +import type { Plugin } from 'unified'; +import { visit } from 'unist-util-visit'; + +const rewriteNode = (node: InlineCode) => { + const data = node.data ?? (node.data = {}); + data.hName = 'inlinecode'; +}; + + +export const remarkPlugin: Plugin = () => { + return (tree) => { + visit(tree, (node) => { + if (node.type === 'inlineCode') { + rewriteNode(node as InlineCode); + } + }); + }; +}; + +export const sanitizeOption: SanitizeOption = { + tagNames: ['inlinecode'], +}; From 0bb2428885c3491d22879f509609cf6dbf326e3f Mon Sep 17 00:00:00 2001 From: reiji-h Date: Fri, 19 Jul 2024 07:52:19 +0000 Subject: [PATCH 034/490] update version --- .../src/mdast-util-growi-directive/index.js | 95 ++++++++++--------- 1 file changed, 50 insertions(+), 45 deletions(-) diff --git a/packages/remark-growi-directive/src/mdast-util-growi-directive/index.js b/packages/remark-growi-directive/src/mdast-util-growi-directive/index.js index 2e348540cfb..313e227b081 100644 --- a/packages/remark-growi-directive/src/mdast-util-growi-directive/index.js +++ b/packages/remark-growi-directive/src/mdast-util-growi-directive/index.js @@ -27,54 +27,59 @@ const shortcut = /^[^\t\n\r "#'.<=>`}]+$/; handleDirective.peek = peekDirective; /** @type {FromMarkdownExtension} */ -export const directiveFromMarkdown = { - canContainEols: [DirectiveType.Text], - enter: { - directiveLeaf: enterLeaf, - directiveLeafAttributes: enterAttributes, - - directiveText: enterText, - directiveTextAttributes: enterAttributes, - }, - exit: { - directiveLeaf: exit, - directiveLeafAttributeName: exitAttributeName, - directiveLeafAttributeValue: exitAttributeValue, - directiveLeafAttributes: exitAttributes, - directiveLeafName: exitName, - - directiveText: exit, - directiveTextAttributeName: exitAttributeName, - directiveTextAttributeValue: exitAttributeValue, - directiveTextAttributes: exitAttributes, - directiveTextName: exitName, - }, -}; - -/** @type {ToMarkdownExtension} */ -export const directiveToMarkdown = { - unsafe: [ - { - character: '\r', - inConstruct: [DirectiveType.Leaf], +export function directiveFromMarkdown() { + return { + canContainEols: [DirectiveType.Text], + enter: { + directiveLeaf: enterLeaf, + directiveLeafAttributes: enterAttributes, + + directiveText: enterText, + directiveTextAttributes: enterAttributes, }, - { - character: '\n', - inConstruct: [DirectiveType.Leaf], + exit: { + directiveLeaf: exit, + directiveLeafAttributeName: exitAttributeName, + directiveLeafAttributeValue: exitAttributeValue, + directiveLeafAttributes: exitAttributes, + directiveLeafName: exitName, + + directiveText: exit, + directiveTextAttributeName: exitAttributeName, + directiveTextAttributeValue: exitAttributeValue, + directiveTextAttributes: exitAttributes, + directiveTextName: exitName, + }, - { - before: '[^$]', - character: '$', - after: '[A-Za-z]', - inConstruct: ['phrasing'], + }; +} + +/** @type {ToMarkdownExtension} */ +export function directiveToMarkdown() { + return { + unsafe: [ + { + character: '\r', + inConstruct: [DirectiveType.Leaf], + }, + { + character: '\n', + inConstruct: [DirectiveType.Leaf], + }, + { + before: '[^$]', + character: '$', + after: '[A-Za-z]', + inConstruct: ['phrasing'], + }, + { atBreak: true, character: '$', after: '$' }, + ], + handlers: { + [DirectiveType.Leaf]: handleDirective, + [DirectiveType.Text]: handleDirective, }, - { atBreak: true, character: '$', after: '$' }, - ], - handlers: { - [DirectiveType.Leaf]: handleDirective, - [DirectiveType.Text]: handleDirective, - }, -}; + }; +} /** @type {FromMarkdownHandle} */ function enterLeaf(token) { From 0744ab4a1d0ade77ce52f12832d6922fafc5639b Mon Sep 17 00:00:00 2001 From: reiji-h Date: Fri, 19 Jul 2024 07:57:05 +0000 Subject: [PATCH 035/490] udpate version --- .../test/mdast-util-growi-directive.test.js | 56 +++++++++---------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/packages/remark-growi-directive/test/mdast-util-growi-directive.test.js b/packages/remark-growi-directive/test/mdast-util-growi-directive.test.js index 85323ec8ad0..795af05434e 100644 --- a/packages/remark-growi-directive/test/mdast-util-growi-directive.test.js +++ b/packages/remark-growi-directive/test/mdast-util-growi-directive.test.js @@ -13,7 +13,7 @@ describe('markdown -> mdast', () => { expect( fromMarkdown('a $b[c](d) e.', { extensions: [directive()], - mdastExtensions: [directiveFromMarkdown], + mdastExtensions: [directiveFromMarkdown()], }).children[0], ).toEqual({ type: 'paragraph', @@ -65,7 +65,7 @@ describe('markdown -> mdast', () => { expect( fromMarkdown('$a[b](c)', { extensions: [directive()], - mdastExtensions: [directiveFromMarkdown], + mdastExtensions: [directiveFromMarkdown()], }).children[0], ).toEqual({ type: DirectiveType.Leaf, @@ -92,7 +92,7 @@ describe('markdown -> mdast', () => { it('should support content in a label', () => { const tree = fromMarkdown('x $a[b *c*\nd]', { extensions: [directive()], - mdastExtensions: [directiveFromMarkdown], + mdastExtensions: [directiveFromMarkdown()], }); removePosition(tree, { force: true }); @@ -126,7 +126,7 @@ describe('markdown -> mdast', () => { it('should support attributes', () => { const tree = fromMarkdown('x $a(#b.c.d e=f g="h&i&unknown;j")', { extensions: [directive()], - mdastExtensions: [directiveFromMarkdown], + mdastExtensions: [directiveFromMarkdown()], }); removePosition(tree, { force: true }); @@ -156,7 +156,7 @@ describe('markdown -> mdast', () => { it('should support EOLs in attributes', () => { const tree = fromMarkdown('$a(b\nc="d\ne")', { extensions: [directive()], - mdastExtensions: [directiveFromMarkdown], + mdastExtensions: [directiveFromMarkdown()], }); removePosition(tree, { force: true }); @@ -193,7 +193,7 @@ describe('mdast -> markdown', () => { { type: 'text', value: ' b.' }, ], }, - { extensions: [directiveToMarkdown] }, + { extensions: [directiveToMarkdown()] }, ), ).toBe('a $ b.\n'); }); @@ -210,7 +210,7 @@ describe('mdast -> markdown', () => { { type: 'text', value: ' c.' }, ], }, - { extensions: [directiveToMarkdown] }, + { extensions: [directiveToMarkdown()] }, ), ).toBe('a $b c.\n'); }); @@ -230,7 +230,7 @@ describe('mdast -> markdown', () => { { type: 'text', value: ' d.' }, ], }, - { extensions: [directiveToMarkdown] }, + { extensions: [directiveToMarkdown()] }, ), ).toBe('a $b[c] d.\n'); }); @@ -250,7 +250,7 @@ describe('mdast -> markdown', () => { { type: 'text', value: ' f.' }, ], }, - { extensions: [directiveToMarkdown] }, + { extensions: [directiveToMarkdown()] }, ), ).toBe('a $b[c\\[d\\]e] f.\n'); }); @@ -270,7 +270,7 @@ describe('mdast -> markdown', () => { { type: 'text', value: ' e.' }, ], }, - { extensions: [directiveToMarkdown] }, + { extensions: [directiveToMarkdown()] }, ), ).toBe('a $b[c\nd] e.\n'); }); @@ -294,7 +294,7 @@ describe('mdast -> markdown', () => { { type: 'text', value: ' k.' }, ], }, - { extensions: [directiveToMarkdown] }, + { extensions: [directiveToMarkdown()] }, ), ).toBe('a $b(c="d" e="f" g j="2") k.\n'); }); @@ -315,7 +315,7 @@ describe('mdast -> markdown', () => { { type: 'text', value: ' k.' }, ], }, - { extensions: [directiveToMarkdown] }, + { extensions: [directiveToMarkdown()] }, ), ).toBe('a $b(#d .a.b.c key="value") k.\n'); }); @@ -336,7 +336,7 @@ describe('mdast -> markdown', () => { { type: 'text', value: ' k.' }, ], }, - { extensions: [directiveToMarkdown] }, + { extensions: [directiveToMarkdown()] }, ), ).toBe('a $b(x="y"\'\r\nz") k.\n'); }); @@ -357,7 +357,7 @@ describe('mdast -> markdown', () => { { type: 'text', value: ' e.' }, ], }, - { extensions: [directiveToMarkdown] }, + { extensions: [directiveToMarkdown()] }, ), ).toBe('a $b(id="c#d") e.\n'); }); @@ -378,7 +378,7 @@ describe('mdast -> markdown', () => { { type: 'text', value: ' g.' }, ], }, - { extensions: [directiveToMarkdown] }, + { extensions: [directiveToMarkdown()] }, ), ).toBe('a $b(c.d e markdown', () => { { type: 'text', value: ' k.' }, ], }, - { extensions: [directiveToMarkdown] }, + { extensions: [directiveToMarkdown()] }, ), ).toBe('a $b(c.d e f markdown', () => { expect( toMarkdown( { type: DirectiveType.Leaf }, - { extensions: [directiveToMarkdown] }, + { extensions: [directiveToMarkdown()] }, ), ).toBe('$\n'); }); @@ -421,7 +421,7 @@ describe('mdast -> markdown', () => { expect( toMarkdown( { type: DirectiveType.Leaf, name: 'a' }, - { extensions: [directiveToMarkdown] }, + { extensions: [directiveToMarkdown()] }, ), ).toBe('$a\n'); }); @@ -434,7 +434,7 @@ describe('mdast -> markdown', () => { name: 'a', children: [{ type: 'text', value: 'b' }], }, - { extensions: [directiveToMarkdown] }, + { extensions: [directiveToMarkdown()] }, ), ).toBe('$a[b]\n'); }); @@ -447,7 +447,7 @@ describe('mdast -> markdown', () => { name: 'a', children: [{ type: 'text', value: 'b\nc' }], }, - { extensions: [directiveToMarkdown] }, + { extensions: [directiveToMarkdown()] }, ), ).toBe('$a[b c]\n'); }); @@ -461,7 +461,7 @@ describe('mdast -> markdown', () => { attributes: { '#b': '', '.c.d': '', key: 'e\nf' }, children: [], }, - { extensions: [directiveToMarkdown] }, + { extensions: [directiveToMarkdown()] }, ), ).toBe('$a(#b .c.d key="e f")\n'); }); @@ -473,7 +473,7 @@ describe('mdast -> markdown', () => { type: 'paragraph', children: [{ type: 'text', value: 'a$b' }], }, - { extensions: [directiveToMarkdown] }, + { extensions: [directiveToMarkdown()] }, ), ).toBe('a\\$b\n'); }); @@ -483,7 +483,7 @@ describe('mdast -> markdown', () => { toMarkdown({ type: 'paragraph', children: [{ type: 'text', value: 'a$9' }], - }, { extensions: [directiveToMarkdown] }), + }, { extensions: [directiveToMarkdown()] }), ).toBe('a$9\n'); }); @@ -492,7 +492,7 @@ describe('mdast -> markdown', () => { toMarkdown({ type: 'paragraph', children: [{ type: 'text', value: 'a$c' }], - }, { extensions: [directiveToMarkdown] }), + }, { extensions: [directiveToMarkdown()] }), ).toBe('a\\$c\n'); }); @@ -503,7 +503,7 @@ describe('mdast -> markdown', () => { type: 'paragraph', children: [{ type: 'text', value: '$\na' }], }, - { extensions: [directiveToMarkdown] }, + { extensions: [directiveToMarkdown()] }, ), ).toBe('$\na\n'); }); @@ -515,7 +515,7 @@ describe('mdast -> markdown', () => { type: 'paragraph', children: [{ type: 'text', value: '$a' }], }, - { extensions: [directiveToMarkdown] }, + { extensions: [directiveToMarkdown()] }, ), ).toBe('\\$a\n'); }); @@ -525,7 +525,7 @@ describe('mdast -> markdown', () => { toMarkdown({ type: 'paragraph', children: [{ type: 'text', value: '$\na' }], - }, { extensions: [directiveToMarkdown] }), + }, { extensions: [directiveToMarkdown()] }), ).toBe('$\na\n'); }); @@ -537,7 +537,7 @@ describe('mdast -> markdown', () => { { type: DirectiveType.Text, name: 'red', children: [] }, { type: 'text', value: '$' }, ], - }, { extensions: [directiveToMarkdown] }), + }, { extensions: [directiveToMarkdown()] }), ).toBe('$red$\n'); }); From d95903c1234c65d627154e6f86a5ac93eb761765 Mon Sep 17 00:00:00 2001 From: reiji-h Date: Fri, 26 Jul 2024 06:03:03 +0000 Subject: [PATCH 036/490] fix import --- apps/app/src/services/renderer/rehype-plugins/add-class.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/apps/app/src/services/renderer/rehype-plugins/add-class.ts b/apps/app/src/services/renderer/rehype-plugins/add-class.ts index 9349e452153..b0d00d5339b 100644 --- a/apps/app/src/services/renderer/rehype-plugins/add-class.ts +++ b/apps/app/src/services/renderer/rehype-plugins/add-class.ts @@ -1,9 +1,8 @@ // See: https://github.com/martypdx/rehype-add-classes for the original implementation. // Re-implemeted in TypeScript. +import type { Nodes as HastNode, Element, Properties } from 'hast'; import { selectAll } from 'hast-util-select'; -import type { Node as HastNode, Element } from 'hast-util-select/lib/types'; -import { Properties } from 'hast-util-select/lib/types'; -import { Plugin } from 'unified'; +import type { Plugin } from 'unified'; export type SelectorName = string; // e.g. 'h1' export type ClassName = string; // e.g. 'header' From d6ef5fbeec638319f8199a22f4cc06b3dc05068c Mon Sep 17 00:00:00 2001 From: reiji-h Date: Fri, 26 Jul 2024 07:27:37 +0000 Subject: [PATCH 037/490] fix import --- .../src/services/renderer/rehype-plugins/relative-links.ts | 2 +- .../src/client/services/renderer/refs.ts | 6 +++--- packages/remark-lsx/src/client/services/renderer/lsx.ts | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/apps/app/src/services/renderer/rehype-plugins/relative-links.ts b/apps/app/src/services/renderer/rehype-plugins/relative-links.ts index aa55861b7c3..c1f24329649 100644 --- a/apps/app/src/services/renderer/rehype-plugins/relative-links.ts +++ b/apps/app/src/services/renderer/rehype-plugins/relative-links.ts @@ -1,7 +1,7 @@ import assert from 'assert'; +import type { Nodes as HastNode, Element } from 'hast'; import { selectAll } from 'hast-util-select'; -import type { Node as HastNode, Element } from 'hast-util-select/lib/types'; import isAbsolute from 'is-absolute-url'; import type { Plugin } from 'unified'; diff --git a/packages/remark-attachment-refs/src/client/services/renderer/refs.ts b/packages/remark-attachment-refs/src/client/services/renderer/refs.ts index 100e03208ba..a67741108ac 100644 --- a/packages/remark-attachment-refs/src/client/services/renderer/refs.ts +++ b/packages/remark-attachment-refs/src/client/services/renderer/refs.ts @@ -1,9 +1,9 @@ import { pathUtils } from '@growi/core/dist/utils'; import { remarkGrowiDirectivePluginType } from '@growi/remark-growi-directive'; -import { Schema as SanitizeOption } from 'hast-util-sanitize'; +import type { Nodes as HastNode } from 'hast'; +import type { Schema as SanitizeOption } from 'hast-util-sanitize'; import { selectAll } from 'hast-util-select'; -import type { Node as HastNode } from 'hast-util-select/lib/types'; -import { Plugin } from 'unified'; +import type { Plugin } from 'unified'; import { visit } from 'unist-util-visit'; import loggerFactory from '../../../utils/logger'; diff --git a/packages/remark-lsx/src/client/services/renderer/lsx.ts b/packages/remark-lsx/src/client/services/renderer/lsx.ts index 40ab3d5ce67..d978ff929dc 100644 --- a/packages/remark-lsx/src/client/services/renderer/lsx.ts +++ b/packages/remark-lsx/src/client/services/renderer/lsx.ts @@ -2,11 +2,11 @@ import assert from 'assert'; import { hasHeadingSlash, removeTrailingSlash, addTrailingSlash } from '@growi/core/dist/utils/path-utils'; import { remarkGrowiDirectivePluginType } from '@growi/remark-growi-directive'; -import { Schema as SanitizeOption } from 'hast-util-sanitize'; +import type { Nodes as HastNode } from 'hast'; +import type { Schema as SanitizeOption } from 'hast-util-sanitize'; import { selectAll } from 'hast-util-select'; -import type { Node as HastNode } from 'hast-util-select/lib/types'; import isAbsolute from 'is-absolute-url'; -import { Plugin } from 'unified'; +import type { Plugin } from 'unified'; import { visit } from 'unist-util-visit'; const NODE_NAME_PATTERN = new RegExp(/ls|lsx/); From 60ffe0405b14c6dcd20a604552e1fb1878f3592f Mon Sep 17 00:00:00 2001 From: reiji-h Date: Fri, 26 Jul 2024 07:30:21 +0000 Subject: [PATCH 038/490] Detect inline code blocks --- .../ReactMarkdownComponents/CodeBlock.tsx | 8 ++--- .../renderer/remark-plugins/codeblock.ts | 33 +++++++++++++++++++ .../remark-plugins/inline-codeblock.ts | 25 -------------- apps/app/src/services/renderer/renderer.tsx | 6 ++-- 4 files changed, 40 insertions(+), 32 deletions(-) create mode 100644 apps/app/src/services/renderer/remark-plugins/codeblock.ts delete mode 100644 apps/app/src/services/renderer/remark-plugins/inline-codeblock.ts diff --git a/apps/app/src/components/ReactMarkdownComponents/CodeBlock.tsx b/apps/app/src/components/ReactMarkdownComponents/CodeBlock.tsx index e7768296bf5..f17765425aa 100644 --- a/apps/app/src/components/ReactMarkdownComponents/CodeBlock.tsx +++ b/apps/app/src/components/ReactMarkdownComponents/CodeBlock.tsx @@ -65,14 +65,12 @@ function CodeBlockSubstance({ lang, children }: { lang: string, children: ReactN ); } - -export const InlineCodeBlock = ({ className, children }: { className: string, children: JSX.Element}): JSX.Element => { - return {children}; -}; - export const CodeBlock = ({ className, children }: {className: string, children: JSX.Element}): JSX.Element => { // TODO: set border according to the value of 'customize:highlightJsStyleBorder' + if (className === 'inline') { + return {children}; + } const match = /language-(\w+)(:?.+)?/.exec(className || ''); const lang = match && match[1] ? match[1] : ''; diff --git a/apps/app/src/services/renderer/remark-plugins/codeblock.ts b/apps/app/src/services/renderer/remark-plugins/codeblock.ts new file mode 100644 index 00000000000..4c6ff6491bc --- /dev/null +++ b/apps/app/src/services/renderer/remark-plugins/codeblock.ts @@ -0,0 +1,33 @@ + +import type { Root } from 'hast'; +import { selectAll } from 'hast-util-select'; +import type { InlineCode } from 'mdast'; +import type { Plugin } from 'unified'; +import { visit } from 'unist-util-visit'; + +import { addClassToProperties } from '../rehype-plugins/add-class'; + +export const remarkPlugin: Plugin = () => { + return (tree) => { + visit(tree, (node) => { + if (node.type === 'inlineCode') { + const data = (node as InlineCode).data || (node.data = {}); + // setting inline for rehypePlugin + data.hProperties = { inline: true }; + } + }); + }; +}; + +export const rehypePlugin: Plugin = () => { + return (tree: Root) => { + const codeElements = selectAll('code', tree); + codeElements.forEach((element) => { + // if inlineCode, properties.inline exists. + if (element.properties?.inline != null) { + element.properties.inline = true; + addClassToProperties(element.properties, 'inline'); + } + }); + }; +}; diff --git a/apps/app/src/services/renderer/remark-plugins/inline-codeblock.ts b/apps/app/src/services/renderer/remark-plugins/inline-codeblock.ts deleted file mode 100644 index ffe7da0f00c..00000000000 --- a/apps/app/src/services/renderer/remark-plugins/inline-codeblock.ts +++ /dev/null @@ -1,25 +0,0 @@ - -import type { Schema as SanitizeOption } from 'hast-util-sanitize'; -import type { InlineCode } from 'mdast'; -import type { Plugin } from 'unified'; -import { visit } from 'unist-util-visit'; - -const rewriteNode = (node: InlineCode) => { - const data = node.data ?? (node.data = {}); - data.hName = 'inlinecode'; -}; - - -export const remarkPlugin: Plugin = () => { - return (tree) => { - visit(tree, (node) => { - if (node.type === 'inlineCode') { - rewriteNode(node as InlineCode); - } - }); - }; -}; - -export const sanitizeOption: SanitizeOption = { - tagNames: ['inlinecode'], -}; diff --git a/apps/app/src/services/renderer/renderer.tsx b/apps/app/src/services/renderer/renderer.tsx index 150181e0c16..999f41d4cd9 100644 --- a/apps/app/src/services/renderer/renderer.tsx +++ b/apps/app/src/services/renderer/renderer.tsx @@ -14,7 +14,7 @@ import deepmerge from 'ts-deepmerge'; import type { Pluggable, PluginTuple } from 'unified'; -import { InlineCodeBlock, CodeBlock } from '~/components/ReactMarkdownComponents/CodeBlock'; +import { CodeBlock } from '~/components/ReactMarkdownComponents/CodeBlock'; import { NextLink } from '~/components/ReactMarkdownComponents/NextLink'; import type { RendererOptions } from '~/interfaces/renderer-options'; import { RehypeSanitizeType } from '~/interfaces/services/rehype-sanitize'; @@ -25,6 +25,7 @@ import { tagNames as recommendedTagNames, attributes as recommendedAttributes } import * as addClass from './rehype-plugins/add-class'; import { relativeLinks } from './rehype-plugins/relative-links'; import { relativeLinksByPukiwikiLikeLinker } from './rehype-plugins/relative-links-by-pukiwiki-like-linker'; +import * as codeBlocks from './remark-plugins/codeblock'; import { pukiwikiLikeLinker } from './remark-plugins/pukiwiki-like-linker'; import * as xsvToTable from './remark-plugins/xsv-to-table'; @@ -96,6 +97,7 @@ export const generateCommonOptions = (pagePath: string|undefined): RendererOptio pukiwikiLikeLinker, growiDirective, remarkFrontmatter, + codeBlocks.remarkPlugin, ], remarkRehypeOptions: { clobberPrefix: '', // remove clobber prefix @@ -108,10 +110,10 @@ export const generateCommonOptions = (pagePath: string|undefined): RendererOptio [addClass.rehypePlugin, { table: 'table table-bordered', }], + codeBlocks.rehypePlugin, ], components: { a: NextLink, - inlinecode: InlineCodeBlock, code: CodeBlock, }, }; From bccc12ddb076b2e80e790a646e77229de1a04a8f Mon Sep 17 00:00:00 2001 From: reiji-h Date: Fri, 2 Aug 2024 03:29:58 +0000 Subject: [PATCH 039/490] fix import type --- ...tive-links-by-pukiwiki-like-linker.spec.ts | 2 +- .../rehype-plugins/relative-links.spec.ts | 2 +- .../renderer/remark-plugins/attachment.ts | 13 ++++++++- .../renderer/remark-plugins/xsv-to-table.ts | 13 +++++---- .../src/services/renderer/remark-drawio.ts | 27 ++++++++++++++----- 5 files changed, 43 insertions(+), 14 deletions(-) diff --git a/apps/app/src/services/renderer/rehype-plugins/relative-links-by-pukiwiki-like-linker.spec.ts b/apps/app/src/services/renderer/rehype-plugins/relative-links-by-pukiwiki-like-linker.spec.ts index 4a44ef2ac11..c5be2056220 100644 --- a/apps/app/src/services/renderer/rehype-plugins/relative-links-by-pukiwiki-like-linker.spec.ts +++ b/apps/app/src/services/renderer/rehype-plugins/relative-links-by-pukiwiki-like-linker.spec.ts @@ -1,5 +1,5 @@ +import type { Nodes as HastNode } from 'hast'; import { select } from 'hast-util-select'; -import type { Node as HastNode } from 'hast-util-select/lib/types'; import parse from 'remark-parse'; import rehype from 'remark-rehype'; import { unified } from 'unified'; diff --git a/apps/app/src/services/renderer/rehype-plugins/relative-links.spec.ts b/apps/app/src/services/renderer/rehype-plugins/relative-links.spec.ts index 06885152df9..711cb28b479 100644 --- a/apps/app/src/services/renderer/rehype-plugins/relative-links.spec.ts +++ b/apps/app/src/services/renderer/rehype-plugins/relative-links.spec.ts @@ -1,6 +1,6 @@ +import type { Nodes as HastNode } from 'hast'; import { select } from 'hast-util-select'; -import type { Node as HastNode } from 'hast-util-select/lib/types'; import parse from 'remark-parse'; import remarkRehype from 'remark-rehype'; import { unified } from 'unified'; diff --git a/apps/app/src/services/renderer/remark-plugins/attachment.ts b/apps/app/src/services/renderer/remark-plugins/attachment.ts index da93cf1952a..403256080c4 100644 --- a/apps/app/src/services/renderer/remark-plugins/attachment.ts +++ b/apps/app/src/services/renderer/remark-plugins/attachment.ts @@ -3,9 +3,19 @@ import path from 'path'; import type { Schema as SanitizeOption } from 'hast-util-sanitize'; import type { Link } from 'mdast'; import type { Plugin } from 'unified'; -import type { Node } from 'unist'; import { visit } from 'unist-util-visit'; +declare module 'mdast' { + interface LinkData { + hName?: string, + hProperties?: { + attachmentId?: string, + url?: string, + attachmentName?: PhrasingContent, + } + } +} + const SUPPORTED_ATTRIBUTES = ['attachmentId', 'url', 'attachmentName']; const isAttachmentLink = (url: string): boolean => { @@ -16,6 +26,7 @@ const isAttachmentLink = (url: string): boolean => { const rewriteNode = (node: Link) => { const attachmentId = path.basename(node.url as string); + const data = node.data ?? (node.data = {}); data.hName = 'attachment'; data.hProperties = { diff --git a/apps/app/src/services/renderer/remark-plugins/xsv-to-table.ts b/apps/app/src/services/renderer/remark-plugins/xsv-to-table.ts index 1c831bc63df..1f0b622dea7 100644 --- a/apps/app/src/services/renderer/remark-plugins/xsv-to-table.ts +++ b/apps/app/src/services/renderer/remark-plugins/xsv-to-table.ts @@ -1,5 +1,8 @@ import csvToMarkdownTable from 'csv-to-markdown-table'; -import type { Code, Table } from 'mdast'; +import type { + Code, Parent, +} from 'mdast'; +import type { Options } from 'mdast-util-from-markdown'; import { fromMarkdown } from 'mdast-util-from-markdown'; import { gfmTableFromMarkdown } from 'mdast-util-gfm-table'; import { gfmTable } from 'micromark-extension-gfm-table'; @@ -14,7 +17,7 @@ function isXsv(lang?: string | null | undefined): lang is Lang { } function rewriteNode(node: Node, lang: Lang) { - const tableContents = node.value as string; + const tableContents = (node as Code).value as string; const tableDoc = csvToMarkdownTable( tableContents, @@ -24,12 +27,12 @@ function rewriteNode(node: Node, lang: Lang) { const tableTree = fromMarkdown(tableDoc, { extensions: [gfmTable], mdastExtensions: [gfmTableFromMarkdown], - }); + } as Options); // replace node if (tableTree.children[0] != null) { node.type = 'table'; - (node as Table).children = tableTree.children[0].children; + (node as Parent).children = (tableTree.children[0] as Parent).children; } } @@ -38,7 +41,7 @@ export const remarkPlugin: Plugin = function() { visit(tree, (node) => { if (node.type === 'code') { if (isXsv((node as Code).lang)) { - rewriteNode((node as Code), (node as Code).lang as Lang); + rewriteNode(node, (node as Code).lang as Lang); } } }); diff --git a/packages/remark-drawio/src/services/renderer/remark-drawio.ts b/packages/remark-drawio/src/services/renderer/remark-drawio.ts index 1400f256805..3a736e732ac 100644 --- a/packages/remark-drawio/src/services/renderer/remark-drawio.ts +++ b/packages/remark-drawio/src/services/renderer/remark-drawio.ts @@ -1,21 +1,36 @@ import type { Schema as SanitizeOption } from 'hast-util-sanitize'; +import type { + Code, Node, Parent, +} from 'mdast'; import type { Plugin } from 'unified'; -import type { Node } from 'unist'; import { visit } from 'unist-util-visit'; const SUPPORTED_ATTRIBUTES = ['diagramIndex', 'bol', 'eol']; +declare module 'mdast' { + interface Data { + hName?: string, + hProperties?: { + diagramIndex?: number, + bol?: number, + eol?: number, + key?: string, + } + } +} + type Lang = 'drawio'; -function isDrawioBlock(lang: unknown): lang is Lang { - return /^drawio$/.test(lang as string); +function isDrawioBlock(lang: string | undefined | null): lang is Lang { + return /^drawio$/.test(lang ?? ''); } function rewriteNode(node: Node, index: number) { - const data = node.data ?? (node.data = {}); node.type = 'paragraph'; - node.children = [{ type: 'text', value: node.value }]; + (node as Parent).children = [{ type: 'text', value: (node as Code).value }]; + + const data = node.data ?? (node.data = {}); data.hName = 'drawio'; data.hProperties = { diagramIndex: index, @@ -29,7 +44,7 @@ export const remarkPlugin: Plugin = function() { return (tree) => { visit(tree, (node, index) => { if (node.type === 'code') { - if (isDrawioBlock(node.lang)) { + if (isDrawioBlock((node as Code).lang)) { rewriteNode(node, index ?? 0); } } From b593ce3801e8e17e05d8340e61b464633c595171 Mon Sep 17 00:00:00 2001 From: reiji-h Date: Fri, 2 Aug 2024 06:30:25 +0000 Subject: [PATCH 040/490] need types annotation of growi-directive --- packages/remark-lsx/src/client/services/renderer/lsx.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/remark-lsx/src/client/services/renderer/lsx.ts b/packages/remark-lsx/src/client/services/renderer/lsx.ts index d978ff929dc..f97e8ac9f90 100644 --- a/packages/remark-lsx/src/client/services/renderer/lsx.ts +++ b/packages/remark-lsx/src/client/services/renderer/lsx.ts @@ -17,7 +17,8 @@ type DirectiveAttributes = Record export const remarkPlugin: Plugin = function() { return (tree) => { - visit(tree, (node) => { + // TODO: setting growi-directive types + visit(tree, (node: any) => { if (node.type === remarkGrowiDirectivePluginType.Text || node.type === remarkGrowiDirectivePluginType.Leaf) { if (typeof node.name !== 'string') { return; From 2b40ee569526cd07d9da87ea691f0ff839522279 Mon Sep 17 00:00:00 2001 From: reiji-h Date: Fri, 2 Aug 2024 06:38:53 +0000 Subject: [PATCH 041/490] add strict types --- .../src/services/renderer/rehype-plugins/relocate-toc.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/app/src/services/renderer/rehype-plugins/relocate-toc.ts b/apps/app/src/services/renderer/rehype-plugins/relocate-toc.ts index a24ed56dad7..5bad8339e61 100644 --- a/apps/app/src/services/renderer/rehype-plugins/relocate-toc.ts +++ b/apps/app/src/services/renderer/rehype-plugins/relocate-toc.ts @@ -1,6 +1,6 @@ -import rehypeToc, { type HtmlElementNode } from 'rehype-toc'; +import rehypeToc from 'rehype-toc'; +import type { HtmlElementNode } from 'rehype-toc'; import type { Plugin } from 'unified'; -import type { Node } from 'unist'; type StoreTocPluginParams = { storeTocNode: (toc: HtmlElementNode) => void, @@ -22,13 +22,13 @@ export const rehypePluginStore: Plugin<[StoreTocPluginParams]> = (options) => { // method for replace
    to
      -const replaceOlToUl = (children: Node[]) => { +const replaceOlToUl = (children: HtmlElementNode[]) => { children.forEach((child) => { if (child.type === 'element' && child.tagName === 'ol') { child.tagName = 'ul'; } if (child.children != null) { - replaceOlToUl(child.children as Node[]); + replaceOlToUl(child.children as HtmlElementNode[]); } }); }; From b0d357afe50c15efcf53c8ee73b735c0b06d6654 Mon Sep 17 00:00:00 2001 From: reiji-h Date: Fri, 2 Aug 2024 06:43:35 +0000 Subject: [PATCH 042/490] fix type error --- .../relative-links-by-pukiwiki-like-linker.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/app/src/services/renderer/rehype-plugins/relative-links-by-pukiwiki-like-linker.spec.ts b/apps/app/src/services/renderer/rehype-plugins/relative-links-by-pukiwiki-like-linker.spec.ts index c5be2056220..00cc267af70 100644 --- a/apps/app/src/services/renderer/rehype-plugins/relative-links-by-pukiwiki-like-linker.spec.ts +++ b/apps/app/src/services/renderer/rehype-plugins/relative-links-by-pukiwiki-like-linker.spec.ts @@ -1,4 +1,4 @@ -import type { Nodes as HastNode } from 'hast'; +import type { Nodes as HastNode, Text } from 'hast'; import { select } from 'hast-util-select'; import parse from 'remark-parse'; import rehype from 'remark-rehype'; @@ -45,7 +45,7 @@ describe('relativeLinksByPukiwikiLikeLinker', () => { expect(anchorElement?.children[0]).not.toBeNull(); expect(anchorElement?.children[0].type).toEqual('text'); - expect(anchorElement?.children[0].value).toEqual(expectedValue); + expect((anchorElement?.children[0] as HastNode as Text).value).toEqual(expectedValue); }); }); From 50c37d1e6049285b0d7889de10a14b72b61b72dc Mon Sep 17 00:00:00 2001 From: reiji-h Date: Fri, 2 Aug 2024 06:51:34 +0000 Subject: [PATCH 043/490] needs growi-directive types --- .../src/client/services/renderer/refs.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/remark-attachment-refs/src/client/services/renderer/refs.ts b/packages/remark-attachment-refs/src/client/services/renderer/refs.ts index a67741108ac..d476de2776f 100644 --- a/packages/remark-attachment-refs/src/client/services/renderer/refs.ts +++ b/packages/remark-attachment-refs/src/client/services/renderer/refs.ts @@ -24,7 +24,8 @@ type DirectiveAttributes = Record export const remarkPlugin: Plugin = function() { return (tree) => { - visit(tree, (node) => { + visit(tree, (node: any) => { + // TODO: growi-directive types if (node.type === remarkGrowiDirectivePluginType.Text || node.type === remarkGrowiDirectivePluginType.Leaf) { if (typeof node.name !== 'string') { return; From 17015d93fce989ace6c071776ba6ddbd4b5897b8 Mon Sep 17 00:00:00 2001 From: reiji-h Date: Fri, 2 Aug 2024 06:58:04 +0000 Subject: [PATCH 044/490] fix import type --- .../renderer/rehype-plugins/add-line-number-attribute.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/app/src/services/renderer/rehype-plugins/add-line-number-attribute.ts b/apps/app/src/services/renderer/rehype-plugins/add-line-number-attribute.ts index c13c70f2d7d..08e2b198f65 100644 --- a/apps/app/src/services/renderer/rehype-plugins/add-line-number-attribute.ts +++ b/apps/app/src/services/renderer/rehype-plugins/add-line-number-attribute.ts @@ -1,5 +1,5 @@ +import type { Element } from 'hast'; import type { Schema as SanitizeOption } from 'hast-util-sanitize'; -import type { Element } from 'hast-util-select/lib/types'; import type { Plugin } from 'unified'; import { visit, EXIT, CONTINUE } from 'unist-util-visit'; From d1e04750a9e17ae1bb50219214429a6511a6adda Mon Sep 17 00:00:00 2001 From: reiji-h Date: Fri, 2 Aug 2024 07:29:15 +0000 Subject: [PATCH 045/490] add types --- .../src/client/services/renderer/extract-sections.ts | 2 +- .../presentation/src/services/use-slides-by-frontmatter.ts | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/presentation/src/client/services/renderer/extract-sections.ts b/packages/presentation/src/client/services/renderer/extract-sections.ts index cfa1335ef5a..9a286e823dd 100644 --- a/packages/presentation/src/client/services/renderer/extract-sections.ts +++ b/packages/presentation/src/client/services/renderer/extract-sections.ts @@ -5,7 +5,7 @@ import { findAfter } from 'unist-util-find-after'; import { visit } from 'unist-util-visit'; -function wrapWithSection(parentNode: Parent, startElem: Node, endElem: Node | null, isDarkMode?: boolean): void { +function wrapWithSection(parentNode: Parent, startElem: Node, endElem: Node | undefined | null, isDarkMode?: boolean): void { const siblings = parentNode.children; const startIndex = siblings.indexOf(startElem); diff --git a/packages/presentation/src/services/use-slides-by-frontmatter.ts b/packages/presentation/src/services/use-slides-by-frontmatter.ts index b4a3ecd0a10..ef5566c59c2 100644 --- a/packages/presentation/src/services/use-slides-by-frontmatter.ts +++ b/packages/presentation/src/services/use-slides-by-frontmatter.ts @@ -1,5 +1,6 @@ import { useEffect, useState } from 'react'; +import type { Parent } from 'mdast'; import type { Processor } from 'unified'; type ParseResult = { @@ -43,7 +44,7 @@ const generateFrontmatterProcessor = async(opts?: ProcessorOpts) => { .use(remarkParse) .use(remarkStringify) .use(remarkFrontmatter, ['yaml']) - .use(() => ((obj) => { + .use(() => ((obj: Parent) => { if (obj.children[0]?.type === 'yaml') { const result = parseSlideFrontmatter(obj.children[0]?.value); opts?.onParsed?.(result); From 3bd967296bee5b0d5ec90f28228a528d1c749ad7 Mon Sep 17 00:00:00 2001 From: reiji-h Date: Fri, 2 Aug 2024 08:22:07 +0000 Subject: [PATCH 046/490] use memo component in ReactMarkdown --- .../ReactMarkdownComponents/TableWithEditButton.tsx | 5 ++--- .../src/client/components/RichSlideSection.tsx | 7 ++++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/app/src/client/components/ReactMarkdownComponents/TableWithEditButton.tsx b/apps/app/src/client/components/ReactMarkdownComponents/TableWithEditButton.tsx index 21b4b771265..2ae97ab4de1 100644 --- a/apps/app/src/client/components/ReactMarkdownComponents/TableWithEditButton.tsx +++ b/apps/app/src/client/components/ReactMarkdownComponents/TableWithEditButton.tsx @@ -23,8 +23,7 @@ type TableWithEditButtonProps = { className?: string } -export const TableWithEditButton = (props: TableWithEditButtonProps): JSX.Element => { - +export const TableWithEditButton = React.memo((props: TableWithEditButtonProps): JSX.Element => { const { children, node, className } = props; const { data: isGuestUser } = useIsGuestUser(); @@ -61,5 +60,5 @@ export const TableWithEditButton = (props: TableWithEditButtonProps): JSX.Elemen ); -}; +}) as typeof TableWithEditButton; TableWithEditButton.displayName = 'TableWithEditButton'; diff --git a/packages/presentation/src/client/components/RichSlideSection.tsx b/packages/presentation/src/client/components/RichSlideSection.tsx index eb2dc450e4e..a86c8f34fdd 100644 --- a/packages/presentation/src/client/components/RichSlideSection.tsx +++ b/packages/presentation/src/client/components/RichSlideSection.tsx @@ -1,4 +1,5 @@ -import React, { ReactNode } from 'react'; +import type { ReactNode } from 'react'; +import React from 'react'; type RichSlideSectionProps = { children: ReactNode, @@ -29,7 +30,7 @@ export const RichSlideSection = React.memo((props: RichSlideSectionProps): JSX.E {children} ); -}); +}) as typeof RichSlideSection; export const PresentationRichSlideSection = React.memo((props: RichSlideSectionProps): JSX.Element => { @@ -40,4 +41,4 @@ export const PresentationRichSlideSection = React.memo((props: RichSlideSectionP {children} ); -}); +}) as typeof PresentationRichSlideSection; From 6f4f271e142e0cb171dd53ecf1d21001acc81b74 Mon Sep 17 00:00:00 2001 From: reiji-h Date: Fri, 2 Aug 2024 10:00:32 +0000 Subject: [PATCH 047/490] ReactMarkdown Components is not React.Memo --- .../ReactMarkdownComponents/TableWithEditButton.tsx | 4 ++-- .../src/client/components/RichSlideSection.tsx | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/app/src/client/components/ReactMarkdownComponents/TableWithEditButton.tsx b/apps/app/src/client/components/ReactMarkdownComponents/TableWithEditButton.tsx index 2ae97ab4de1..4dcc3fcf527 100644 --- a/apps/app/src/client/components/ReactMarkdownComponents/TableWithEditButton.tsx +++ b/apps/app/src/client/components/ReactMarkdownComponents/TableWithEditButton.tsx @@ -23,7 +23,7 @@ type TableWithEditButtonProps = { className?: string } -export const TableWithEditButton = React.memo((props: TableWithEditButtonProps): JSX.Element => { +export const TableWithEditButton = (props: TableWithEditButtonProps): JSX.Element => { const { children, node, className } = props; const { data: isGuestUser } = useIsGuestUser(); @@ -60,5 +60,5 @@ export const TableWithEditButton = React.memo((props: TableWithEditButtonProps): ); -}) as typeof TableWithEditButton; +}; TableWithEditButton.displayName = 'TableWithEditButton'; diff --git a/packages/presentation/src/client/components/RichSlideSection.tsx b/packages/presentation/src/client/components/RichSlideSection.tsx index a86c8f34fdd..1bf03e4860c 100644 --- a/packages/presentation/src/client/components/RichSlideSection.tsx +++ b/packages/presentation/src/client/components/RichSlideSection.tsx @@ -2,7 +2,7 @@ import type { ReactNode } from 'react'; import React from 'react'; type RichSlideSectionProps = { - children: ReactNode, + children?: ReactNode, presentation?: boolean, } @@ -14,7 +14,7 @@ const OriginalRichSlideSection = React.memo((props: RichSlideSectionProps): JSX.
      - {children} + {children ?? <>}
      @@ -22,7 +22,7 @@ const OriginalRichSlideSection = React.memo((props: RichSlideSectionProps): JSX. ); }); -export const RichSlideSection = React.memo((props: RichSlideSectionProps): JSX.Element => { +export const RichSlideSection = (props: RichSlideSectionProps): JSX.Element => { const { children } = props; return ( @@ -30,10 +30,10 @@ export const RichSlideSection = React.memo((props: RichSlideSectionProps): JSX.E {children} ); -}) as typeof RichSlideSection; +}; -export const PresentationRichSlideSection = React.memo((props: RichSlideSectionProps): JSX.Element => { +export const PresentationRichSlideSection = (props: RichSlideSectionProps): JSX.Element => { const { children } = props; return ( @@ -41,4 +41,4 @@ export const PresentationRichSlideSection = React.memo((props: RichSlideSectionP {children} ); -}) as typeof PresentationRichSlideSection; +}; From 4742b45f00112d9bfd88e94d2ee52a9c340d4ddd Mon Sep 17 00:00:00 2001 From: reiji-h Date: Fri, 2 Aug 2024 10:00:43 +0000 Subject: [PATCH 048/490] add Processer type --- .../src/services/use-slides-by-frontmatter.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/presentation/src/services/use-slides-by-frontmatter.ts b/packages/presentation/src/services/use-slides-by-frontmatter.ts index ef5566c59c2..90d94f65cdd 100644 --- a/packages/presentation/src/services/use-slides-by-frontmatter.ts +++ b/packages/presentation/src/services/use-slides-by-frontmatter.ts @@ -1,6 +1,6 @@ import { useEffect, useState } from 'react'; -import type { Parent } from 'mdast'; +import type { Parent, Root } from 'mdast'; import type { Processor } from 'unified'; type ParseResult = { @@ -40,7 +40,7 @@ const generateFrontmatterProcessor = async(opts?: ProcessorOpts) => { const remarkStringify = (await import('remark-stringify')).default; const unified = (await import('unified')).unified; - return unified() + return (unified() .use(remarkParse) .use(remarkStringify) .use(remarkFrontmatter, ['yaml']) @@ -52,7 +52,7 @@ const generateFrontmatterProcessor = async(opts?: ProcessorOpts) => { else { opts?.onSkipped?.(); } - })); + }))); }; export type UseSlide = { @@ -66,7 +66,7 @@ export type UseSlide = { */ export const useSlidesByFrontmatter = (markdown?: string, isEnabledMarp?: boolean): UseSlide | undefined => { - const [processor, setProcessor] = useState(); + const [processor, setProcessor] = useState|undefined>(); const [parseResult, setParseResult] = useState(); useEffect(() => { From caaed9b77c668676887b1896f8306db41634d887 Mon Sep 17 00:00:00 2001 From: reiji-h Date: Fri, 2 Aug 2024 10:15:19 +0000 Subject: [PATCH 049/490] use React.memo component in ReactMarkdown --- .../ReactMarkdownComponents/TableWithEditButton.tsx | 4 ++-- .../src/client/components/RichSlideSection.tsx | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/app/src/client/components/ReactMarkdownComponents/TableWithEditButton.tsx b/apps/app/src/client/components/ReactMarkdownComponents/TableWithEditButton.tsx index 4dcc3fcf527..2ae97ab4de1 100644 --- a/apps/app/src/client/components/ReactMarkdownComponents/TableWithEditButton.tsx +++ b/apps/app/src/client/components/ReactMarkdownComponents/TableWithEditButton.tsx @@ -23,7 +23,7 @@ type TableWithEditButtonProps = { className?: string } -export const TableWithEditButton = (props: TableWithEditButtonProps): JSX.Element => { +export const TableWithEditButton = React.memo((props: TableWithEditButtonProps): JSX.Element => { const { children, node, className } = props; const { data: isGuestUser } = useIsGuestUser(); @@ -60,5 +60,5 @@ export const TableWithEditButton = (props: TableWithEditButtonProps): JSX.Elemen ); -}; +}) as typeof TableWithEditButton; TableWithEditButton.displayName = 'TableWithEditButton'; diff --git a/packages/presentation/src/client/components/RichSlideSection.tsx b/packages/presentation/src/client/components/RichSlideSection.tsx index 1bf03e4860c..6e5d6f2f1bc 100644 --- a/packages/presentation/src/client/components/RichSlideSection.tsx +++ b/packages/presentation/src/client/components/RichSlideSection.tsx @@ -22,7 +22,7 @@ const OriginalRichSlideSection = React.memo((props: RichSlideSectionProps): JSX. ); }); -export const RichSlideSection = (props: RichSlideSectionProps): JSX.Element => { +export const RichSlideSection = React.memo((props: RichSlideSectionProps): JSX.Element => { const { children } = props; return ( @@ -30,10 +30,10 @@ export const RichSlideSection = (props: RichSlideSectionProps): JSX.Element => { {children} ); -}; +}) as typeof RichSlideSection; -export const PresentationRichSlideSection = (props: RichSlideSectionProps): JSX.Element => { +export const PresentationRichSlideSection = React.memo((props: RichSlideSectionProps): JSX.Element => { const { children } = props; return ( @@ -41,4 +41,4 @@ export const PresentationRichSlideSection = (props: RichSlideSectionProps): JSX. {children} ); -}; +}) as typeof PresentationRichSlideSection; From 0de8aaf1d360c6d21b33198188a926e1ca4fb062 Mon Sep 17 00:00:00 2001 From: reiji-h Date: Tue, 6 Aug 2024 02:46:03 +0000 Subject: [PATCH 050/490] use option argument --- .../src/client/services/renderer/extract-sections.ts | 2 +- packages/remark-drawio/src/services/renderer/remark-drawio.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/presentation/src/client/services/renderer/extract-sections.ts b/packages/presentation/src/client/services/renderer/extract-sections.ts index 9a286e823dd..0553878c558 100644 --- a/packages/presentation/src/client/services/renderer/extract-sections.ts +++ b/packages/presentation/src/client/services/renderer/extract-sections.ts @@ -5,7 +5,7 @@ import { findAfter } from 'unist-util-find-after'; import { visit } from 'unist-util-visit'; -function wrapWithSection(parentNode: Parent, startElem: Node, endElem: Node | undefined | null, isDarkMode?: boolean): void { +function wrapWithSection(parentNode: Parent, startElem: Node, endElem?: Node | null, isDarkMode?: boolean): void { const siblings = parentNode.children; const startIndex = siblings.indexOf(startElem); diff --git a/packages/remark-drawio/src/services/renderer/remark-drawio.ts b/packages/remark-drawio/src/services/renderer/remark-drawio.ts index 3a736e732ac..7afa8403c28 100644 --- a/packages/remark-drawio/src/services/renderer/remark-drawio.ts +++ b/packages/remark-drawio/src/services/renderer/remark-drawio.ts @@ -21,7 +21,7 @@ declare module 'mdast' { type Lang = 'drawio'; -function isDrawioBlock(lang: string | undefined | null): lang is Lang { +function isDrawioBlock(lang?: string | null): lang is Lang { return /^drawio$/.test(lang ?? ''); } From c988e5f18be9ccc875f3efd8dbeb12f74d63e03d Mon Sep 17 00:00:00 2001 From: reiji-h Date: Tue, 6 Aug 2024 08:15:53 +0000 Subject: [PATCH 051/490] remove lint warning --- .../src/client/components/LsxPageList/LsxListView.tsx | 2 +- .../remark-lsx/src/client/components/LsxPageList/LsxPage.tsx | 2 +- packages/remark-lsx/src/client/utils/page-node.spec.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/remark-lsx/src/client/components/LsxPageList/LsxListView.tsx b/packages/remark-lsx/src/client/components/LsxPageList/LsxListView.tsx index 68d8ee5ac0d..76211a81c9f 100644 --- a/packages/remark-lsx/src/client/components/LsxPageList/LsxListView.tsx +++ b/packages/remark-lsx/src/client/components/LsxPageList/LsxListView.tsx @@ -1,7 +1,7 @@ import React, { useMemo } from 'react'; import type { PageNode } from '../../../interfaces/page-node'; -import { LsxContext } from '../lsx-context'; +import type { LsxContext } from '../lsx-context'; import { LsxPage } from './LsxPage'; diff --git a/packages/remark-lsx/src/client/components/LsxPageList/LsxPage.tsx b/packages/remark-lsx/src/client/components/LsxPageList/LsxPage.tsx index 31f14f3df4d..420b36e75c9 100644 --- a/packages/remark-lsx/src/client/components/LsxPageList/LsxPage.tsx +++ b/packages/remark-lsx/src/client/components/LsxPageList/LsxPage.tsx @@ -5,7 +5,7 @@ import { PageListMeta, PagePathLabel } from '@growi/ui/dist/components'; import Link from 'next/link'; import type { PageNode } from '../../../interfaces/page-node'; -import { LsxContext } from '../lsx-context'; +import type { LsxContext } from '../lsx-context'; import styles from './LsxPage.module.scss'; diff --git a/packages/remark-lsx/src/client/utils/page-node.spec.ts b/packages/remark-lsx/src/client/utils/page-node.spec.ts index 4463b3d9fdb..2e165ce04a3 100644 --- a/packages/remark-lsx/src/client/utils/page-node.spec.ts +++ b/packages/remark-lsx/src/client/utils/page-node.spec.ts @@ -2,7 +2,7 @@ import type { IPageHasId } from '@growi/core'; import { OptionParser } from '@growi/core/dist/remark-plugins'; import { mock } from 'vitest-mock-extended'; -import { PageNode } from '../../interfaces/page-node'; +import type { PageNode } from '../../interfaces/page-node'; import { generatePageNodeTree } from './page-node'; From 12d13bdb72b6d9db3a8625c5bd1942d1546a6b0f Mon Sep 17 00:00:00 2001 From: reiji-h Date: Tue, 6 Aug 2024 08:16:28 +0000 Subject: [PATCH 052/490] use ts --- packages/remark-growi-directive/src/index.js | 3 +- .../complex-types.d.ts | 32 ---- .../src/mdast-util-growi-directive/consts.js | 4 - .../src/mdast-util-growi-directive/index.ts | 169 ++++++++++++++++++ .../{ => lib}/index.js | 14 +- 5 files changed, 179 insertions(+), 43 deletions(-) delete mode 100644 packages/remark-growi-directive/src/mdast-util-growi-directive/complex-types.d.ts delete mode 100644 packages/remark-growi-directive/src/mdast-util-growi-directive/consts.js create mode 100644 packages/remark-growi-directive/src/mdast-util-growi-directive/index.ts rename packages/remark-growi-directive/src/mdast-util-growi-directive/{ => lib}/index.js (94%) diff --git a/packages/remark-growi-directive/src/index.js b/packages/remark-growi-directive/src/index.js index f0d2e1113c0..55d820a9e43 100644 --- a/packages/remark-growi-directive/src/index.js +++ b/packages/remark-growi-directive/src/index.js @@ -1,6 +1,5 @@ -import { DirectiveType } from './mdast-util-growi-directive/consts.js'; import { remarkGrowiDirectivePlugin } from './remark-growi-directive.js'; -export { DirectiveType as remarkGrowiDirectivePluginType }; +export { DirectiveType as remarkGrowiDirectivePluginType, LeafGrowiPluginDirective, TextGrowiPluginDirective } from './mdast-util-growi-directive'; export default remarkGrowiDirectivePlugin; diff --git a/packages/remark-growi-directive/src/mdast-util-growi-directive/complex-types.d.ts b/packages/remark-growi-directive/src/mdast-util-growi-directive/complex-types.d.ts deleted file mode 100644 index e5233741a21..00000000000 --- a/packages/remark-growi-directive/src/mdast-util-growi-directive/complex-types.d.ts +++ /dev/null @@ -1,32 +0,0 @@ -import type { PhrasingContent } from 'mdast'; -import type { Parent } from 'unist'; - -import { DirectiveType } from './consts.js'; - - -type DirectiveAttributes = Record - -interface DirectiveFields { - name: string - attributes?: DirectiveAttributes -} - -export interface TextDirective extends Parent, DirectiveFields { - type: DirectiveType.Text - children: PhrasingContent[] -} - -export interface LeafDirective extends Parent, DirectiveFields { - type: DirectiveType.Leaf - children: PhrasingContent[] -} - -declare module 'mdast' { - interface StaticPhrasingContentMap { - [DirectiveType.Text]: TextDirective - } - - interface BlockContentMap { - [DirectiveType.Leaf]: LeafDirective - } -} diff --git a/packages/remark-growi-directive/src/mdast-util-growi-directive/consts.js b/packages/remark-growi-directive/src/mdast-util-growi-directive/consts.js deleted file mode 100644 index 356f9727bc2..00000000000 --- a/packages/remark-growi-directive/src/mdast-util-growi-directive/consts.js +++ /dev/null @@ -1,4 +0,0 @@ -export const DirectiveType = Object.freeze({ - Text: 'textGrowiPluginDirective', - Leaf: 'leafGrowiPluginDirective', -}); diff --git a/packages/remark-growi-directive/src/mdast-util-growi-directive/index.ts b/packages/remark-growi-directive/src/mdast-util-growi-directive/index.ts new file mode 100644 index 00000000000..354b3ab955c --- /dev/null +++ b/packages/remark-growi-directive/src/mdast-util-growi-directive/index.ts @@ -0,0 +1,169 @@ +import type { + Data, + Parent, + PhrasingContent, +} from 'mdast'; + +import type { DirectiveType as DirectiveTypeObject } from './lib/index.js'; + +export type DirectiveType = typeof DirectiveTypeObject; + +export { directiveToMarkdown, directiveFromMarkdown } from './lib/index.js'; + +/** + * Fields shared by directives. + */ +interface DirectiveFields { + /** + * Directive name. + */ + name: string + + /** + * Directive attributes. + */ + attributes?: Record | null | undefined +} + +/** + * Markdown directive (leaf form). + */ +export interface LeafGrowiPluginDirective extends Parent, DirectiveFields { + /** + * Node type of leaf directive. + */ + type: DirectiveType['Leaf'] + + /** + * Children of leaf directive. + */ + children: PhrasingContent[] + + /** + * Data associated with the mdast leaf directive. + */ + data?: LeafGrowiPluginDirectiveData | undefined +} + +/** + * Info associated with mdast leaf directive nodes by the ecosystem. + */ +export type LeafGrowiPluginDirectiveData = Data + +/** + * Markdown directive (text form). + */ +export interface TextGrowiPluginDirective extends Parent, DirectiveFields { + /** + * Node type of text directive. + */ + type: DirectiveType['Text'] + + /** + * Children of text directive. + */ + children: PhrasingContent[] + + /** + * Data associated with the text leaf directive. + */ + data?: TextGrowiPluginDirectiveData | undefined +} + +/** + * Info associated with mdast text directive nodes by the ecosystem. + */ +export type TextGrowiPluginDirectiveData = Data + +/** + * Union of registered mdast directive nodes. + * + * It is not possible to register custom mdast directive node types. + */ +export type Directives = LeafGrowiPluginDirective | TextGrowiPluginDirective + +// Add custom data tracked to turn markdown into a tree. +declare module 'mdast-util-from-markdown' { + interface CompileData { + /** + * Attributes for current directive. + */ + directiveAttributes?: Array<[string, string]> | undefined + } +} + +// Add custom data tracked to turn a syntax tree into markdown. +declare module 'mdast-util-to-markdown' { + interface ConstructNameMap { + /** + * Whole leaf directive. + * + * ```markdown + * > | ::a + * ^^^ + * ``` + */ + leafGrowiPluginDirective: 'leafGrowiPluginDirective' + + /** + * Label of a leaf directive. + * + * ```markdown + * > | ::a[b] + * ^^^ + * ``` + */ + leafGrowiPluginDirectiveLabel: 'leafGrowiPluginDirectiveLabel' + + /** + * Whole text directive. + * + * ```markdown + * > | :a + * ^^ + * ``` + */ + textGrowiPluginDirective: 'textGrowiPluginDirective' + + /** + * Label of a text directive. + * + * ```markdown + * > | :a[b] + * ^^^ + * ``` + */ + textGrowiPluginDirectiveLabel: 'textGrowiPluginDirectiveLabel' + } +} + +// Add nodes to content, register `data` on paragraph. +declare module 'mdast' { + interface BlockContentMap { + /** + * Directive in flow content (such as in the root document, or block + * quotes), which contains nothing. + */ + leafGrowiPluginDirective: LeafGrowiPluginDirective + } + + interface PhrasingContentMap { + /** + * Directive in phrasing content (such as in paragraphs, headings). + */ + textGrowiPluginDirective: TextGrowiPluginDirective + } + + interface RootContentMap { + /** + * Directive in flow content (such as in the root document, or block + * quotes), which contains nothing. + */ + leafGrowiPluginDirective: LeafGrowiPluginDirective + + /** + * Directive in phrasing content (such as in paragraphs, headings). + */ + textGrowiPluginDirective: TextGrowiPluginDirective + } +} diff --git a/packages/remark-growi-directive/src/mdast-util-growi-directive/index.js b/packages/remark-growi-directive/src/mdast-util-growi-directive/lib/index.js similarity index 94% rename from packages/remark-growi-directive/src/mdast-util-growi-directive/index.js rename to packages/remark-growi-directive/src/mdast-util-growi-directive/lib/index.js index 2e348540cfb..2512cc9bd77 100644 --- a/packages/remark-growi-directive/src/mdast-util-growi-directive/index.js +++ b/packages/remark-growi-directive/src/mdast-util-growi-directive/lib/index.js @@ -10,20 +10,24 @@ * @typedef {import('mdast-util-to-markdown').Context} Context * @typedef {import('mdast-util-to-markdown').Options} ToMarkdownExtension * - * @typedef {import('./complex-types').LeafDirective} LeafDirective - * @typedef {import('./complex-types').TextDirective} TextDirective - * @typedef {LeafDirective|TextDirective} Directive + * @typedef {import('../types/index.js').LeafGrowiPluginDirective} LeafGrowiPluginDirective + * @typedef {import('../types/index.js').TextGrowiPluginDirective} TextGrowiPluginDirective + * @typedef {import('../types/index.js').Directives} Directives */ import { parseEntities } from 'parse-entities'; import { stringifyEntitiesLight } from 'stringify-entities'; -import { DirectiveType } from './consts.js'; - const own = {}.hasOwnProperty; const shortcut = /^[^\t\n\r "#'.<=>`}]+$/; + +export const DirectiveType = Object.freeze({ + Text: 'textGrowiPluginDirective', + Leaf: 'leafGrowiPluginDirective', +}); + handleDirective.peek = peekDirective; /** @type {FromMarkdownExtension} */ From 1c74bf6b5f4ef69961dac39df503af13dbdb6a49 Mon Sep 17 00:00:00 2001 From: reiji-h Date: Tue, 6 Aug 2024 08:16:51 +0000 Subject: [PATCH 053/490] can use js from ts --- packages/remark-growi-directive/tsconfig.build.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/remark-growi-directive/tsconfig.build.json b/packages/remark-growi-directive/tsconfig.build.json index 4ea7ba128d7..5641862c8bc 100644 --- a/packages/remark-growi-directive/tsconfig.build.json +++ b/packages/remark-growi-directive/tsconfig.build.json @@ -8,6 +8,7 @@ "noResolve": false, "preserveConstEnums": true, "sourceMap": false, - "noEmit": false + "noEmit": false, + "allowJs": true } } From f93de4c63f23af8aed9dc50e3db36aac9959c7a0 Mon Sep 17 00:00:00 2001 From: reiji-h Date: Tue, 13 Aug 2024 03:41:40 +0000 Subject: [PATCH 054/490] add visit type --- apps/app/src/features/mermaid/services/mermaid.ts | 6 +++--- .../renderer/rehype-plugins/relocate-toc.ts | 14 ++++++-------- .../services/renderer/remark-plugins/attachment.ts | 10 ++++------ .../services/renderer/remark-plugins/codeblock.ts | 10 ++++------ .../renderer/remark-plugins/xsv-to-table.ts | 14 +++++--------- .../src/services/renderer/remark-drawio.ts | 8 +++----- 6 files changed, 25 insertions(+), 37 deletions(-) diff --git a/apps/app/src/features/mermaid/services/mermaid.ts b/apps/app/src/features/mermaid/services/mermaid.ts index 53bb9a7d42b..53b78e7e31b 100644 --- a/apps/app/src/features/mermaid/services/mermaid.ts +++ b/apps/app/src/features/mermaid/services/mermaid.ts @@ -11,9 +11,9 @@ function rewriteNode(node: Code) { export const remarkPlugin: Plugin = function() { return (tree) => { - visit(tree, (node) => { - if (node.type === 'code' && (node as Code).lang === 'mermaid') { - rewriteNode(node as Code); + visit(tree, 'code', (node: Code) => { + if (node.lang === 'mermaid') { + rewriteNode(node); } }); }; diff --git a/apps/app/src/services/renderer/rehype-plugins/relocate-toc.ts b/apps/app/src/services/renderer/rehype-plugins/relocate-toc.ts index 5bad8339e61..2705a8579f1 100644 --- a/apps/app/src/services/renderer/rehype-plugins/relocate-toc.ts +++ b/apps/app/src/services/renderer/rehype-plugins/relocate-toc.ts @@ -1,6 +1,7 @@ import rehypeToc from 'rehype-toc'; import type { HtmlElementNode } from 'rehype-toc'; import type { Plugin } from 'unified'; +import { visit } from 'unist-util-visit'; type StoreTocPluginParams = { storeTocNode: (toc: HtmlElementNode) => void, @@ -22,13 +23,10 @@ export const rehypePluginStore: Plugin<[StoreTocPluginParams]> = (options) => { // method for replace
        to
          -const replaceOlToUl = (children: HtmlElementNode[]) => { - children.forEach((child) => { - if (child.type === 'element' && child.tagName === 'ol') { - child.tagName = 'ul'; - } - if (child.children != null) { - replaceOlToUl(child.children as HtmlElementNode[]); +const replaceOlToUl = (tree: HtmlElementNode) => { + visit(tree, 'element', (node: HtmlElementNode) => { + if (node.tagName === 'ol') { + node.tagName = 'ul'; } }); }; @@ -44,7 +42,7 @@ export const rehypePluginRestore: Plugin<[RestoreTocPluginParams]> = (options) = headings: ['h1', 'h2', 'h3'], customizeTOC: () => { if (tocNode != null) { - replaceOlToUl([tocNode]); // replace
            to
              + replaceOlToUl(tocNode); // replace
                to
                  // restore toc return tocNode; diff --git a/apps/app/src/services/renderer/remark-plugins/attachment.ts b/apps/app/src/services/renderer/remark-plugins/attachment.ts index 403256080c4..91cd8a3e700 100644 --- a/apps/app/src/services/renderer/remark-plugins/attachment.ts +++ b/apps/app/src/services/renderer/remark-plugins/attachment.ts @@ -25,7 +25,7 @@ const isAttachmentLink = (url: string): boolean => { }; const rewriteNode = (node: Link) => { - const attachmentId = path.basename(node.url as string); + const attachmentId = path.basename(node.url); const data = node.data ?? (node.data = {}); data.hName = 'attachment'; @@ -39,11 +39,9 @@ const rewriteNode = (node: Link) => { export const remarkPlugin: Plugin = () => { return (tree) => { - visit(tree, (node) => { - if (node.type === 'link') { - if (isAttachmentLink((node as Link).url as string)) { - rewriteNode(node as Link); - } + visit(tree, 'link', (node: Link) => { + if (isAttachmentLink(node.url)) { + rewriteNode(node); } }); }; diff --git a/apps/app/src/services/renderer/remark-plugins/codeblock.ts b/apps/app/src/services/renderer/remark-plugins/codeblock.ts index 4c6ff6491bc..e0290a12a06 100644 --- a/apps/app/src/services/renderer/remark-plugins/codeblock.ts +++ b/apps/app/src/services/renderer/remark-plugins/codeblock.ts @@ -9,12 +9,10 @@ import { addClassToProperties } from '../rehype-plugins/add-class'; export const remarkPlugin: Plugin = () => { return (tree) => { - visit(tree, (node) => { - if (node.type === 'inlineCode') { - const data = (node as InlineCode).data || (node.data = {}); - // setting inline for rehypePlugin - data.hProperties = { inline: true }; - } + visit(tree, 'inlineCode', (node: InlineCode) => { + const data = node.data || (node.data = {}); + // setting inline for rehypePlugin + data.hProperties = { inline: true }; }); }; }; diff --git a/apps/app/src/services/renderer/remark-plugins/xsv-to-table.ts b/apps/app/src/services/renderer/remark-plugins/xsv-to-table.ts index 1f0b622dea7..713746044f9 100644 --- a/apps/app/src/services/renderer/remark-plugins/xsv-to-table.ts +++ b/apps/app/src/services/renderer/remark-plugins/xsv-to-table.ts @@ -1,7 +1,5 @@ import csvToMarkdownTable from 'csv-to-markdown-table'; -import type { - Code, Parent, -} from 'mdast'; +import type { Code, Parent } from 'mdast'; import type { Options } from 'mdast-util-from-markdown'; import { fromMarkdown } from 'mdast-util-from-markdown'; import { gfmTableFromMarkdown } from 'mdast-util-gfm-table'; @@ -17,7 +15,7 @@ function isXsv(lang?: string | null | undefined): lang is Lang { } function rewriteNode(node: Node, lang: Lang) { - const tableContents = (node as Code).value as string; + const tableContents = (node as Code).value; const tableDoc = csvToMarkdownTable( tableContents, @@ -38,11 +36,9 @@ function rewriteNode(node: Node, lang: Lang) { export const remarkPlugin: Plugin = function() { return (tree) => { - visit(tree, (node) => { - if (node.type === 'code') { - if (isXsv((node as Code).lang)) { - rewriteNode(node, (node as Code).lang as Lang); - } + visit(tree, 'code', (node: Code) => { + if (isXsv(node.lang)) { + rewriteNode(node, node.lang); } }); }; diff --git a/packages/remark-drawio/src/services/renderer/remark-drawio.ts b/packages/remark-drawio/src/services/renderer/remark-drawio.ts index 7afa8403c28..9ddeac44bf3 100644 --- a/packages/remark-drawio/src/services/renderer/remark-drawio.ts +++ b/packages/remark-drawio/src/services/renderer/remark-drawio.ts @@ -42,11 +42,9 @@ function rewriteNode(node: Node, index: number) { export const remarkPlugin: Plugin = function() { return (tree) => { - visit(tree, (node, index) => { - if (node.type === 'code') { - if (isDrawioBlock((node as Code).lang)) { - rewriteNode(node, index ?? 0); - } + visit(tree, 'code', (node: Code, index) => { + if (isDrawioBlock(node.lang)) { + rewriteNode(node, index ?? 0); } }); }; From 6fd1338aea40afeb8cf74943dd271df88685abbf Mon Sep 17 00:00:00 2001 From: reiji-h Date: Tue, 13 Aug 2024 05:56:16 +0000 Subject: [PATCH 055/490] fix package usage and type --- .../services/renderer/remark-plugins/xsv-to-table.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/apps/app/src/services/renderer/remark-plugins/xsv-to-table.ts b/apps/app/src/services/renderer/remark-plugins/xsv-to-table.ts index 713746044f9..46f27810168 100644 --- a/apps/app/src/services/renderer/remark-plugins/xsv-to-table.ts +++ b/apps/app/src/services/renderer/remark-plugins/xsv-to-table.ts @@ -1,6 +1,5 @@ import csvToMarkdownTable from 'csv-to-markdown-table'; -import type { Code, Parent } from 'mdast'; -import type { Options } from 'mdast-util-from-markdown'; +import type { Code, Table } from 'mdast'; import { fromMarkdown } from 'mdast-util-from-markdown'; import { gfmTableFromMarkdown } from 'mdast-util-gfm-table'; import { gfmTable } from 'micromark-extension-gfm-table'; @@ -23,14 +22,14 @@ function rewriteNode(node: Node, lang: Lang) { lang === 'csv-h' || lang === 'tsv-h', ); const tableTree = fromMarkdown(tableDoc, { - extensions: [gfmTable], - mdastExtensions: [gfmTableFromMarkdown], - } as Options); + extensions: [gfmTable()], + mdastExtensions: [gfmTableFromMarkdown()], + }); // replace node if (tableTree.children[0] != null) { node.type = 'table'; - (node as Parent).children = (tableTree.children[0] as Parent).children; + (node as Table).children = (tableTree.children[0] as Table).children; } } From f6d4dba2cf115c167766ba6164cf3d7fda27f9e6 Mon Sep 17 00:00:00 2001 From: reiji-h Date: Tue, 13 Aug 2024 06:13:43 +0000 Subject: [PATCH 056/490] change type --- packages/remark-drawio/src/services/renderer/remark-drawio.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/remark-drawio/src/services/renderer/remark-drawio.ts b/packages/remark-drawio/src/services/renderer/remark-drawio.ts index 9ddeac44bf3..5182f0080ec 100644 --- a/packages/remark-drawio/src/services/renderer/remark-drawio.ts +++ b/packages/remark-drawio/src/services/renderer/remark-drawio.ts @@ -1,6 +1,6 @@ import type { Schema as SanitizeOption } from 'hast-util-sanitize'; import type { - Code, Node, Parent, + Code, Node, Paragraph, } from 'mdast'; import type { Plugin } from 'unified'; import { visit } from 'unist-util-visit'; @@ -28,7 +28,7 @@ function isDrawioBlock(lang?: string | null): lang is Lang { function rewriteNode(node: Node, index: number) { node.type = 'paragraph'; - (node as Parent).children = [{ type: 'text', value: (node as Code).value }]; + (node as Paragraph).children = [{ type: 'text', value: (node as Code).value }]; const data = node.data ?? (node.data = {}); data.hName = 'drawio'; From 6d67d7bedd801c3c37b841ea16a0aac99b59bd42 Mon Sep 17 00:00:00 2001 From: reiji-h Date: Tue, 13 Aug 2024 07:04:43 +0000 Subject: [PATCH 057/490] set exports --- packages/remark-growi-directive/src/index.js | 8 +++++++- .../src/mdast-util-growi-directive/index.ts | 16 ++++++++++++---- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/packages/remark-growi-directive/src/index.js b/packages/remark-growi-directive/src/index.js index 55d820a9e43..e95742ea2ae 100644 --- a/packages/remark-growi-directive/src/index.js +++ b/packages/remark-growi-directive/src/index.js @@ -1,5 +1,11 @@ import { remarkGrowiDirectivePlugin } from './remark-growi-directive.js'; -export { DirectiveType as remarkGrowiDirectivePluginType, LeafGrowiPluginDirective, TextGrowiPluginDirective } from './mdast-util-growi-directive'; +export { + DirectiveTypeObject as remarkGrowiDirectivePluginType, + LeafGrowiPluginDirective, + TextGrowiPluginDirective, + LeafGrowiPluginDirectiveData, + TextGrowiPluginDirectiveData, +} from './mdast-util-growi-directive'; export default remarkGrowiDirectivePlugin; diff --git a/packages/remark-growi-directive/src/mdast-util-growi-directive/index.ts b/packages/remark-growi-directive/src/mdast-util-growi-directive/index.ts index 354b3ab955c..a326d7e46f5 100644 --- a/packages/remark-growi-directive/src/mdast-util-growi-directive/index.ts +++ b/packages/remark-growi-directive/src/mdast-util-growi-directive/index.ts @@ -4,9 +4,10 @@ import type { PhrasingContent, } from 'mdast'; -import type { DirectiveType as DirectiveTypeObject } from './lib/index.js'; +import { DirectiveType as DirectiveTypeObject } from './lib/index.js'; -export type DirectiveType = typeof DirectiveTypeObject; +export { DirectiveTypeObject }; +type DirectiveType = typeof DirectiveTypeObject; export { directiveToMarkdown, directiveFromMarkdown } from './lib/index.js'; @@ -48,7 +49,10 @@ export interface LeafGrowiPluginDirective extends Parent, DirectiveFields { /** * Info associated with mdast leaf directive nodes by the ecosystem. */ -export type LeafGrowiPluginDirectiveData = Data +export interface LeafGrowiPluginDirectiveData extends Data { + hName?: string, + hProperties?: Record +} /** * Markdown directive (text form). @@ -73,7 +77,11 @@ export interface TextGrowiPluginDirective extends Parent, DirectiveFields { /** * Info associated with mdast text directive nodes by the ecosystem. */ -export type TextGrowiPluginDirectiveData = Data +export interface TextGrowiPluginDirectiveData extends Data { + hName?: string, + hProperties?: Record +} + /** * Union of registered mdast directive nodes. From cb0567bc3b13d5fa452a20b66ad089a973d05bcb Mon Sep 17 00:00:00 2001 From: reiji-h Date: Tue, 13 Aug 2024 07:07:19 +0000 Subject: [PATCH 058/490] add types --- .../src/client/services/renderer/refs.ts | 10 ++++++---- .../remark-lsx/src/client/services/renderer/lsx.ts | 14 ++++++++------ 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/packages/remark-attachment-refs/src/client/services/renderer/refs.ts b/packages/remark-attachment-refs/src/client/services/renderer/refs.ts index 100e03208ba..a57c88fa84a 100644 --- a/packages/remark-attachment-refs/src/client/services/renderer/refs.ts +++ b/packages/remark-attachment-refs/src/client/services/renderer/refs.ts @@ -1,9 +1,10 @@ import { pathUtils } from '@growi/core/dist/utils'; +import type { TextGrowiPluginDirective, LeafGrowiPluginDirective } from '@growi/remark-growi-directive'; import { remarkGrowiDirectivePluginType } from '@growi/remark-growi-directive'; -import { Schema as SanitizeOption } from 'hast-util-sanitize'; +import type { Nodes as HastNode } from 'hast'; +import type { Schema as SanitizeOption } from 'hast-util-sanitize'; import { selectAll } from 'hast-util-select'; -import type { Node as HastNode } from 'hast-util-select/lib/types'; -import { Plugin } from 'unified'; +import type { Plugin } from 'unified'; import { visit } from 'unist-util-visit'; import loggerFactory from '../../../utils/logger'; @@ -21,10 +22,11 @@ const REFS_IMG_SUPPORTED_ATTRIBUTES = [ ]; type DirectiveAttributes = Record +type GrowiPluginDirective = TextGrowiPluginDirective | LeafGrowiPluginDirective export const remarkPlugin: Plugin = function() { return (tree) => { - visit(tree, (node) => { + visit(tree, (node: GrowiPluginDirective) => { if (node.type === remarkGrowiDirectivePluginType.Text || node.type === remarkGrowiDirectivePluginType.Leaf) { if (typeof node.name !== 'string') { return; diff --git a/packages/remark-lsx/src/client/services/renderer/lsx.ts b/packages/remark-lsx/src/client/services/renderer/lsx.ts index 40ab3d5ce67..36117a9f86d 100644 --- a/packages/remark-lsx/src/client/services/renderer/lsx.ts +++ b/packages/remark-lsx/src/client/services/renderer/lsx.ts @@ -2,23 +2,25 @@ import assert from 'assert'; import { hasHeadingSlash, removeTrailingSlash, addTrailingSlash } from '@growi/core/dist/utils/path-utils'; import { remarkGrowiDirectivePluginType } from '@growi/remark-growi-directive'; -import { Schema as SanitizeOption } from 'hast-util-sanitize'; +import type { TextGrowiPluginDirective, LeafGrowiPluginDirective } from '@growi/remark-growi-directive'; +import type { Nodes as HastNode } from 'hast'; +import type { Schema as SanitizeOption } from 'hast-util-sanitize'; import { selectAll } from 'hast-util-select'; -import type { Node as HastNode } from 'hast-util-select/lib/types'; import isAbsolute from 'is-absolute-url'; -import { Plugin } from 'unified'; +import type { Plugin } from 'unified'; import { visit } from 'unist-util-visit'; const NODE_NAME_PATTERN = new RegExp(/ls|lsx/); const SUPPORTED_ATTRIBUTES = ['prefix', 'num', 'depth', 'sort', 'reverse', 'filter', 'except', 'isSharedPage']; type DirectiveAttributes = Record - +type GrowiPluginDirective = TextGrowiPluginDirective | LeafGrowiPluginDirective export const remarkPlugin: Plugin = function() { return (tree) => { - visit(tree, (node) => { - if (node.type === remarkGrowiDirectivePluginType.Text || node.type === remarkGrowiDirectivePluginType.Leaf) { + visit(tree, (node: GrowiPluginDirective) => { + if (node.type === remarkGrowiDirectivePluginType.Leaf || node.type === remarkGrowiDirectivePluginType.Text) { + if (typeof node.name !== 'string') { return; } From 2c8488a9e791f6196d58e583ba34f19d093c3da2 Mon Sep 17 00:00:00 2001 From: reiji-h Date: Tue, 13 Aug 2024 07:18:48 +0000 Subject: [PATCH 059/490] fix path --- packages/remark-growi-directive/src/remark-growi-directive.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/remark-growi-directive/src/remark-growi-directive.js b/packages/remark-growi-directive/src/remark-growi-directive.js index 610d14cbe5d..e936aeca041 100644 --- a/packages/remark-growi-directive/src/remark-growi-directive.js +++ b/packages/remark-growi-directive/src/remark-growi-directive.js @@ -3,7 +3,7 @@ * @typedef {import('unified').Processor} Processor */ -import { directiveFromMarkdown, directiveToMarkdown } from './mdast-util-growi-directive/index.js'; +import { directiveFromMarkdown, directiveToMarkdown } from './mdast-util-growi-directive/index'; import { directive } from './micromark-extension-growi-directive/index.js'; /** From 580e6c476842410f6d9c46b4229ce2b755313c4f Mon Sep 17 00:00:00 2001 From: reiji-h Date: Tue, 13 Aug 2024 07:25:05 +0000 Subject: [PATCH 060/490] fix path --- .../src/micromark-extension-growi-directive/lib/html.js | 2 +- .../test/mdast-util-growi-directive.test.js | 4 ++-- .../test/micromark-extension-growi-directive.test.js | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/remark-growi-directive/src/micromark-extension-growi-directive/lib/html.js b/packages/remark-growi-directive/src/micromark-extension-growi-directive/lib/html.js index 05a8d448560..1eb20b16cf5 100644 --- a/packages/remark-growi-directive/src/micromark-extension-growi-directive/lib/html.js +++ b/packages/remark-growi-directive/src/micromark-extension-growi-directive/lib/html.js @@ -23,7 +23,7 @@ import { parseEntities } from 'parse-entities'; import { ok as assert } from 'uvu/assert'; -import { DirectiveType } from '../../mdast-util-growi-directive/consts.js'; +import { DirectiveType } from '../../mdast-util-growi-directive/lib/index.js'; const own = {}.hasOwnProperty; diff --git a/packages/remark-growi-directive/test/mdast-util-growi-directive.test.js b/packages/remark-growi-directive/test/mdast-util-growi-directive.test.js index 795af05434e..cf5c00e2c0e 100644 --- a/packages/remark-growi-directive/test/mdast-util-growi-directive.test.js +++ b/packages/remark-growi-directive/test/mdast-util-growi-directive.test.js @@ -3,8 +3,8 @@ import { toMarkdown } from 'mdast-util-to-markdown'; import { removePosition } from 'unist-util-remove-position'; import { describe, it, expect } from 'vitest'; -import { DirectiveType } from '../src/mdast-util-growi-directive/consts.js'; -import { directiveFromMarkdown, directiveToMarkdown } from '../src/mdast-util-growi-directive/index.js'; +import { directiveFromMarkdown, directiveToMarkdown } from '../src/mdast-util-growi-directive/index'; +import { DirectiveType } from '../src/mdast-util-growi-directive/lib/index.js'; import { directive } from '../src/micromark-extension-growi-directive/index.js'; diff --git a/packages/remark-growi-directive/test/micromark-extension-growi-directive.test.js b/packages/remark-growi-directive/test/micromark-extension-growi-directive.test.js index 9b0055d92cb..8cb7585db78 100644 --- a/packages/remark-growi-directive/test/micromark-extension-growi-directive.test.js +++ b/packages/remark-growi-directive/test/micromark-extension-growi-directive.test.js @@ -7,7 +7,7 @@ import { htmlVoidElements } from 'html-void-elements'; import { micromark } from 'micromark'; import { describe, it, expect } from 'vitest'; -import { DirectiveType } from '../src/mdast-util-growi-directive/consts.js'; +import { DirectiveType } from '../src/mdast-util-growi-directive/lib/index.js'; import { directive as syntax, directiveHtml as html } from '../src/micromark-extension-growi-directive/index.js'; From b317766407946bbd25a10fe966e2f170faa5fb00 Mon Sep 17 00:00:00 2001 From: reiji-h Date: Tue, 13 Aug 2024 07:34:45 +0000 Subject: [PATCH 061/490] fix lint error --- .../src/client/components/RichSlideSection.tsx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/presentation/src/client/components/RichSlideSection.tsx b/packages/presentation/src/client/components/RichSlideSection.tsx index 6e5d6f2f1bc..6d9d83a7cc4 100644 --- a/packages/presentation/src/client/components/RichSlideSection.tsx +++ b/packages/presentation/src/client/components/RichSlideSection.tsx @@ -22,7 +22,8 @@ const OriginalRichSlideSection = React.memo((props: RichSlideSectionProps): JSX. ); }); -export const RichSlideSection = React.memo((props: RichSlideSectionProps): JSX.Element => { + +const RichSlideSectionNoMemorized = (props: RichSlideSectionProps): JSX.Element => { const { children } = props; return ( @@ -30,10 +31,11 @@ export const RichSlideSection = React.memo((props: RichSlideSectionProps): JSX.E {children} ); -}) as typeof RichSlideSection; +}; +export const RichSlideSection = React.memo(RichSlideSectionNoMemorized) as typeof RichSlideSectionNoMemorized; -export const PresentationRichSlideSection = React.memo((props: RichSlideSectionProps): JSX.Element => { +const PresentationRichSlideSectionNoMemorized = (props: RichSlideSectionProps): JSX.Element => { const { children } = props; return ( @@ -41,4 +43,5 @@ export const PresentationRichSlideSection = React.memo((props: RichSlideSectionP {children} ); -}) as typeof PresentationRichSlideSection; +}; +export const PresentationRichSlideSection = React.memo(PresentationRichSlideSectionNoMemorized) as typeof PresentationRichSlideSectionNoMemorized; From 0c37e3cf873a2ff99e106ba159218612ecb6314d Mon Sep 17 00:00:00 2001 From: reiji-h Date: Tue, 13 Aug 2024 07:35:15 +0000 Subject: [PATCH 062/490] fix lint error --- .../src/client/components/RichSlideSection.tsx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/presentation/src/client/components/RichSlideSection.tsx b/packages/presentation/src/client/components/RichSlideSection.tsx index 6e5d6f2f1bc..6d9d83a7cc4 100644 --- a/packages/presentation/src/client/components/RichSlideSection.tsx +++ b/packages/presentation/src/client/components/RichSlideSection.tsx @@ -22,7 +22,8 @@ const OriginalRichSlideSection = React.memo((props: RichSlideSectionProps): JSX. ); }); -export const RichSlideSection = React.memo((props: RichSlideSectionProps): JSX.Element => { + +const RichSlideSectionNoMemorized = (props: RichSlideSectionProps): JSX.Element => { const { children } = props; return ( @@ -30,10 +31,11 @@ export const RichSlideSection = React.memo((props: RichSlideSectionProps): JSX.E {children} ); -}) as typeof RichSlideSection; +}; +export const RichSlideSection = React.memo(RichSlideSectionNoMemorized) as typeof RichSlideSectionNoMemorized; -export const PresentationRichSlideSection = React.memo((props: RichSlideSectionProps): JSX.Element => { +const PresentationRichSlideSectionNoMemorized = (props: RichSlideSectionProps): JSX.Element => { const { children } = props; return ( @@ -41,4 +43,5 @@ export const PresentationRichSlideSection = React.memo((props: RichSlideSectionP {children} ); -}) as typeof PresentationRichSlideSection; +}; +export const PresentationRichSlideSection = React.memo(PresentationRichSlideSectionNoMemorized) as typeof PresentationRichSlideSectionNoMemorized; From bb6140fca5d7a0e67c693a9cb185a7026fb1525a Mon Sep 17 00:00:00 2001 From: reiji-h Date: Tue, 13 Aug 2024 09:23:06 +0000 Subject: [PATCH 063/490] fix lint error --- .../ReactMarkdownComponents/TableWithEditButton.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/app/src/client/components/ReactMarkdownComponents/TableWithEditButton.tsx b/apps/app/src/client/components/ReactMarkdownComponents/TableWithEditButton.tsx index 2ae97ab4de1..308351d4957 100644 --- a/apps/app/src/client/components/ReactMarkdownComponents/TableWithEditButton.tsx +++ b/apps/app/src/client/components/ReactMarkdownComponents/TableWithEditButton.tsx @@ -23,7 +23,7 @@ type TableWithEditButtonProps = { className?: string } -export const TableWithEditButton = React.memo((props: TableWithEditButtonProps): JSX.Element => { +const TableWithEditButtonNoMemorized = (props: TableWithEditButtonProps): JSX.Element => { const { children, node, className } = props; const { data: isGuestUser } = useIsGuestUser(); @@ -60,5 +60,6 @@ export const TableWithEditButton = React.memo((props: TableWithEditButtonProps): ); -}) as typeof TableWithEditButton; -TableWithEditButton.displayName = 'TableWithEditButton'; +}; +TableWithEditButtonNoMemorized.displayName = 'TableWithEditButton'; +export const TableWithEditButton = React.memo(TableWithEditButtonNoMemorized) as typeof TableWithEditButtonNoMemorized; From 5230a7d8135ab09a9d5451a5223cfabf57b8bb92 Mon Sep 17 00:00:00 2001 From: Yuki Takei Date: Tue, 13 Aug 2024 10:51:04 +0000 Subject: [PATCH 064/490] fix Attribute type --- apps/app/src/interfaces/services/rehype-sanitize.ts | 4 +++- apps/app/src/services/renderer/recommended-whitelist.ts | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/app/src/interfaces/services/rehype-sanitize.ts b/apps/app/src/interfaces/services/rehype-sanitize.ts index f44366bb965..248dd634610 100644 --- a/apps/app/src/interfaces/services/rehype-sanitize.ts +++ b/apps/app/src/interfaces/services/rehype-sanitize.ts @@ -1,4 +1,6 @@ -import type { Attributes } from 'hast-util-sanitize/lib'; +import type { defaultSchema } from 'hast-util-sanitize'; + +type Attributes = typeof defaultSchema.attributes; export const RehypeSanitizeType = { RECOMMENDED: 'Recommended', diff --git a/apps/app/src/services/renderer/recommended-whitelist.ts b/apps/app/src/services/renderer/recommended-whitelist.ts index 7e60ccb34cd..3bb238e6491 100644 --- a/apps/app/src/services/renderer/recommended-whitelist.ts +++ b/apps/app/src/services/renderer/recommended-whitelist.ts @@ -1,7 +1,8 @@ import { defaultSchema } from 'hast-util-sanitize'; -import type { Attributes } from 'hast-util-sanitize/lib'; import deepmerge from 'ts-deepmerge'; +type Attributes = typeof defaultSchema.attributes; + /** * reference: https://meta.stackexchange.com/questions/1777/what-html-tags-are-allowed-on-stack-exchange-sites, * https://github.com/jch/html-pipeline/blob/70b6903b025c668ff3c02a6fa382031661182147/lib/html/pipeline/sanitization_filter.rb#L41 From 9d35745d07f5482dd8981afeb06f6cd9d89af8fc Mon Sep 17 00:00:00 2001 From: Yuki Takei Date: Tue, 13 Aug 2024 10:51:09 +0000 Subject: [PATCH 065/490] fix test --- .../src/services/renderer/recommended-whitelist.spec.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/apps/app/src/services/renderer/recommended-whitelist.spec.ts b/apps/app/src/services/renderer/recommended-whitelist.spec.ts index c9b0eb8f9ee..e42b57037ba 100644 --- a/apps/app/src/services/renderer/recommended-whitelist.spec.ts +++ b/apps/app/src/services/renderer/recommended-whitelist.spec.ts @@ -14,6 +14,9 @@ describe('recommended-whitelist', () => { test('.attributes should return data attributes', () => { expect(attributes).not.toBeNull(); + + assert(attributes != null); + expect(Object.keys(attributes)).includes('*'); expect(attributes['*']).includes('alt'); expect(attributes['*']).includes('align'); @@ -25,12 +28,18 @@ describe('recommended-whitelist', () => { test('.attributes should return iframe attributes', () => { expect(attributes).not.toBeNull(); + + assert(attributes != null); + expect(Object.keys(attributes)).includes('iframe'); expect(attributes.iframe).includes('src'); }); test('.attributes should return video attributes', () => { expect(attributes).not.toBeNull(); + + assert(attributes != null); + expect(Object.keys(attributes)).includes('video'); expect(attributes.iframe).includes('src'); }); From 2ba18f2696cbd67d994f934c09b23620fb8e14aa Mon Sep 17 00:00:00 2001 From: reiji-h Date: Fri, 23 Aug 2024 06:22:11 +0000 Subject: [PATCH 066/490] add codeblock sanitize --- .../src/client/services/renderer/renderer.tsx | 5 ++++ .../ReactMarkdownComponents/CodeBlock.tsx | 12 ++++++++-- .../renderer/remark-plugins/codeblock.ts | 24 +++++++------------ apps/app/src/services/renderer/renderer.tsx | 5 ++-- apps/app/src/stores/renderer.tsx | 3 +-- 5 files changed, 26 insertions(+), 23 deletions(-) diff --git a/apps/app/src/client/services/renderer/renderer.tsx b/apps/app/src/client/services/renderer/renderer.tsx index b5cb77f8bb5..d9e5d0b2f8d 100644 --- a/apps/app/src/client/services/renderer/renderer.tsx +++ b/apps/app/src/client/services/renderer/renderer.tsx @@ -26,6 +26,7 @@ import * as addLineNumberAttribute from '~/services/renderer/rehype-plugins/add- import * as keywordHighlighter from '~/services/renderer/rehype-plugins/keyword-highlighter'; import * as relocateToc from '~/services/renderer/rehype-plugins/relocate-toc'; import * as attachment from '~/services/renderer/remark-plugins/attachment'; +import * as codeBlock from '~/services/renderer/remark-plugins/codeblock'; import * as plantuml from '~/services/renderer/remark-plugins/plantuml'; import * as xsvToTable from '~/services/renderer/remark-plugins/xsv-to-table'; import { @@ -80,6 +81,7 @@ export const generateViewOptions = ( attachment.sanitizeOption, lsxGrowiDirective.sanitizeOption, refsGrowiDirective.sanitizeOption, + codeBlock.sanitizeOption, )] : () => {}; @@ -132,6 +134,7 @@ export const generateTocOptions = (config: RendererConfig, tocNode: HtmlElementN const rehypeSanitizePlugin: Pluggable | (() => void) = config.isEnabledXssPrevention ? [sanitize, deepmerge( getCommonSanitizeOption(config), + codeBlock.sanitizeOption, )] : () => {}; @@ -185,6 +188,7 @@ export const generateSimpleViewOptions = ( attachment.sanitizeOption, lsxGrowiDirective.sanitizeOption, refsGrowiDirective.sanitizeOption, + codeBlock.sanitizeOption, )] : () => {}; @@ -274,6 +278,7 @@ export const generatePreviewOptions = (config: RendererConfig, pagePath: string) lsxGrowiDirective.sanitizeOption, refsGrowiDirective.sanitizeOption, addLineNumberAttribute.sanitizeOption, + codeBlock.sanitizeOption, )] : () => {}; diff --git a/apps/app/src/components/ReactMarkdownComponents/CodeBlock.tsx b/apps/app/src/components/ReactMarkdownComponents/CodeBlock.tsx index f17765425aa..6e01d0eeb55 100644 --- a/apps/app/src/components/ReactMarkdownComponents/CodeBlock.tsx +++ b/apps/app/src/components/ReactMarkdownComponents/CodeBlock.tsx @@ -65,10 +65,18 @@ function CodeBlockSubstance({ lang, children }: { lang: string, children: ReactN ); } -export const CodeBlock = ({ className, children }: {className: string, children: JSX.Element}): JSX.Element => { + +type CodeBlockProps = { + children: JSX.Element, + className?: string, + inline?: string, // "" or undefined +} + +export const CodeBlock = (props: CodeBlockProps): JSX.Element => { // TODO: set border according to the value of 'customize:highlightJsStyleBorder' - if (className === 'inline') { + const { className, children, inline } = props; + if (inline != null) { return {children}; } diff --git a/apps/app/src/services/renderer/remark-plugins/codeblock.ts b/apps/app/src/services/renderer/remark-plugins/codeblock.ts index e0290a12a06..becc93c7802 100644 --- a/apps/app/src/services/renderer/remark-plugins/codeblock.ts +++ b/apps/app/src/services/renderer/remark-plugins/codeblock.ts @@ -1,31 +1,23 @@ - -import type { Root } from 'hast'; -import { selectAll } from 'hast-util-select'; +import type { Schema as SanitizeOption } from 'hast-util-sanitize'; import type { InlineCode } from 'mdast'; import type { Plugin } from 'unified'; import { visit } from 'unist-util-visit'; -import { addClassToProperties } from '../rehype-plugins/add-class'; + +const SUPPORTED_CODE = ['inline']; export const remarkPlugin: Plugin = () => { return (tree) => { visit(tree, 'inlineCode', (node: InlineCode) => { const data = node.data || (node.data = {}); - // setting inline for rehypePlugin data.hProperties = { inline: true }; }); }; }; -export const rehypePlugin: Plugin = () => { - return (tree: Root) => { - const codeElements = selectAll('code', tree); - codeElements.forEach((element) => { - // if inlineCode, properties.inline exists. - if (element.properties?.inline != null) { - element.properties.inline = true; - addClassToProperties(element.properties, 'inline'); - } - }); - }; +export const sanitizeOption: SanitizeOption = { + tagNames: ['code'], + attributes: { + code: SUPPORTED_CODE, + }, }; diff --git a/apps/app/src/services/renderer/renderer.tsx b/apps/app/src/services/renderer/renderer.tsx index 999f41d4cd9..b78494b15e6 100644 --- a/apps/app/src/services/renderer/renderer.tsx +++ b/apps/app/src/services/renderer/renderer.tsx @@ -25,7 +25,7 @@ import { tagNames as recommendedTagNames, attributes as recommendedAttributes } import * as addClass from './rehype-plugins/add-class'; import { relativeLinks } from './rehype-plugins/relative-links'; import { relativeLinksByPukiwikiLikeLinker } from './rehype-plugins/relative-links-by-pukiwiki-like-linker'; -import * as codeBlocks from './remark-plugins/codeblock'; +import * as codeBlock from './remark-plugins/codeblock'; import { pukiwikiLikeLinker } from './remark-plugins/pukiwiki-like-linker'; import * as xsvToTable from './remark-plugins/xsv-to-table'; @@ -97,7 +97,7 @@ export const generateCommonOptions = (pagePath: string|undefined): RendererOptio pukiwikiLikeLinker, growiDirective, remarkFrontmatter, - codeBlocks.remarkPlugin, + codeBlock.remarkPlugin, ], remarkRehypeOptions: { clobberPrefix: '', // remove clobber prefix @@ -110,7 +110,6 @@ export const generateCommonOptions = (pagePath: string|undefined): RendererOptio [addClass.rehypePlugin, { table: 'table table-bordered', }], - codeBlocks.rehypePlugin, ], components: { a: NextLink, diff --git a/apps/app/src/stores/renderer.tsx b/apps/app/src/stores/renderer.tsx index 0fdfe9cf1b0..bd4a4776bd3 100644 --- a/apps/app/src/stores/renderer.tsx +++ b/apps/app/src/stores/renderer.tsx @@ -5,11 +5,10 @@ import useSWR, { type SWRConfiguration, type SWRResponse } from 'swr'; import { getGrowiFacade } from '~/features/growi-plugin/client/utils/growi-facade-utils'; import type { RendererOptions } from '~/interfaces/renderer-options'; - - import { useRendererConfig, } from '~/stores-universal/context'; + import { useCurrentPagePath } from './page'; import { useCurrentPageTocNode } from './ui'; From 761c3b92c61dda9841e55c95eaaccf9f115d5022 Mon Sep 17 00:00:00 2001 From: reiji-h Date: Fri, 23 Aug 2024 07:04:42 +0000 Subject: [PATCH 067/490] use value key for attachmentName --- .../services/renderer/remark-plugins/attachment.ts | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/apps/app/src/services/renderer/remark-plugins/attachment.ts b/apps/app/src/services/renderer/remark-plugins/attachment.ts index 91cd8a3e700..5c3084a11de 100644 --- a/apps/app/src/services/renderer/remark-plugins/attachment.ts +++ b/apps/app/src/services/renderer/remark-plugins/attachment.ts @@ -5,17 +5,6 @@ import type { Link } from 'mdast'; import type { Plugin } from 'unified'; import { visit } from 'unist-util-visit'; -declare module 'mdast' { - interface LinkData { - hName?: string, - hProperties?: { - attachmentId?: string, - url?: string, - attachmentName?: PhrasingContent, - } - } -} - const SUPPORTED_ATTRIBUTES = ['attachmentId', 'url', 'attachmentName']; const isAttachmentLink = (url: string): boolean => { @@ -32,7 +21,7 @@ const rewriteNode = (node: Link) => { data.hProperties = { attachmentId, url: node.url, - attachmentName: node.children[0] ?? '', + attachmentName: 'value' in node.children[0] ? node.children[0].value : '', }; }; From 62c964028089e076bea507c85d49c98bb0ad3f62 Mon Sep 17 00:00:00 2001 From: reiji-h Date: Fri, 23 Aug 2024 07:20:44 +0000 Subject: [PATCH 068/490] fix type check --- apps/app/src/services/renderer/remark-plugins/attachment.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/app/src/services/renderer/remark-plugins/attachment.ts b/apps/app/src/services/renderer/remark-plugins/attachment.ts index 5c3084a11de..9e77dad012f 100644 --- a/apps/app/src/services/renderer/remark-plugins/attachment.ts +++ b/apps/app/src/services/renderer/remark-plugins/attachment.ts @@ -15,13 +15,14 @@ const isAttachmentLink = (url: string): boolean => { const rewriteNode = (node: Link) => { const attachmentId = path.basename(node.url); + const attachmentName = node.children[0] != null && node.children[0].type === 'text' ? node.children[0].value : ''; const data = node.data ?? (node.data = {}); data.hName = 'attachment'; data.hProperties = { attachmentId, url: node.url, - attachmentName: 'value' in node.children[0] ? node.children[0].value : '', + attachmentName, }; }; From 14cad0ff98343b58c0f3901daf669057fe70ebcf Mon Sep 17 00:00:00 2001 From: reiji-h Date: Fri, 23 Aug 2024 08:27:48 +0000 Subject: [PATCH 069/490] dont use declare --- .../src/services/renderer/remark-drawio.ts | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/packages/remark-drawio/src/services/renderer/remark-drawio.ts b/packages/remark-drawio/src/services/renderer/remark-drawio.ts index 5182f0080ec..c3c21d4f6b3 100644 --- a/packages/remark-drawio/src/services/renderer/remark-drawio.ts +++ b/packages/remark-drawio/src/services/renderer/remark-drawio.ts @@ -1,3 +1,4 @@ +import type { Properties } from 'hast'; import type { Schema as SanitizeOption } from 'hast-util-sanitize'; import type { Code, Node, Paragraph, @@ -7,16 +8,9 @@ import { visit } from 'unist-util-visit'; const SUPPORTED_ATTRIBUTES = ['diagramIndex', 'bol', 'eol']; -declare module 'mdast' { - interface Data { - hName?: string, - hProperties?: { - diagramIndex?: number, - bol?: number, - eol?: number, - key?: string, - } - } +interface Data { + hName?: string, + hProperties?: Properties, } type Lang = 'drawio'; @@ -30,7 +24,7 @@ function rewriteNode(node: Node, index: number) { node.type = 'paragraph'; (node as Paragraph).children = [{ type: 'text', value: (node as Code).value }]; - const data = node.data ?? (node.data = {}); + const data: Data = node.data ?? (node.data = {}); data.hName = 'drawio'; data.hProperties = { diagramIndex: index, From 1d245b9e31c9b453d53a1dda4a01c936eb22cbd8 Mon Sep 17 00:00:00 2001 From: reiji-h Date: Fri, 23 Aug 2024 06:22:11 +0000 Subject: [PATCH 070/490] add codeblock sanitize --- .../src/client/services/renderer/renderer.tsx | 5 ++++ .../ReactMarkdownComponents/CodeBlock.tsx | 12 ++++++++-- .../renderer/remark-plugins/codeblock.ts | 24 +++++++------------ apps/app/src/services/renderer/renderer.tsx | 5 ++-- apps/app/src/stores/renderer.tsx | 3 +-- 5 files changed, 26 insertions(+), 23 deletions(-) diff --git a/apps/app/src/client/services/renderer/renderer.tsx b/apps/app/src/client/services/renderer/renderer.tsx index b5cb77f8bb5..d9e5d0b2f8d 100644 --- a/apps/app/src/client/services/renderer/renderer.tsx +++ b/apps/app/src/client/services/renderer/renderer.tsx @@ -26,6 +26,7 @@ import * as addLineNumberAttribute from '~/services/renderer/rehype-plugins/add- import * as keywordHighlighter from '~/services/renderer/rehype-plugins/keyword-highlighter'; import * as relocateToc from '~/services/renderer/rehype-plugins/relocate-toc'; import * as attachment from '~/services/renderer/remark-plugins/attachment'; +import * as codeBlock from '~/services/renderer/remark-plugins/codeblock'; import * as plantuml from '~/services/renderer/remark-plugins/plantuml'; import * as xsvToTable from '~/services/renderer/remark-plugins/xsv-to-table'; import { @@ -80,6 +81,7 @@ export const generateViewOptions = ( attachment.sanitizeOption, lsxGrowiDirective.sanitizeOption, refsGrowiDirective.sanitizeOption, + codeBlock.sanitizeOption, )] : () => {}; @@ -132,6 +134,7 @@ export const generateTocOptions = (config: RendererConfig, tocNode: HtmlElementN const rehypeSanitizePlugin: Pluggable | (() => void) = config.isEnabledXssPrevention ? [sanitize, deepmerge( getCommonSanitizeOption(config), + codeBlock.sanitizeOption, )] : () => {}; @@ -185,6 +188,7 @@ export const generateSimpleViewOptions = ( attachment.sanitizeOption, lsxGrowiDirective.sanitizeOption, refsGrowiDirective.sanitizeOption, + codeBlock.sanitizeOption, )] : () => {}; @@ -274,6 +278,7 @@ export const generatePreviewOptions = (config: RendererConfig, pagePath: string) lsxGrowiDirective.sanitizeOption, refsGrowiDirective.sanitizeOption, addLineNumberAttribute.sanitizeOption, + codeBlock.sanitizeOption, )] : () => {}; diff --git a/apps/app/src/components/ReactMarkdownComponents/CodeBlock.tsx b/apps/app/src/components/ReactMarkdownComponents/CodeBlock.tsx index f17765425aa..6e01d0eeb55 100644 --- a/apps/app/src/components/ReactMarkdownComponents/CodeBlock.tsx +++ b/apps/app/src/components/ReactMarkdownComponents/CodeBlock.tsx @@ -65,10 +65,18 @@ function CodeBlockSubstance({ lang, children }: { lang: string, children: ReactN ); } -export const CodeBlock = ({ className, children }: {className: string, children: JSX.Element}): JSX.Element => { + +type CodeBlockProps = { + children: JSX.Element, + className?: string, + inline?: string, // "" or undefined +} + +export const CodeBlock = (props: CodeBlockProps): JSX.Element => { // TODO: set border according to the value of 'customize:highlightJsStyleBorder' - if (className === 'inline') { + const { className, children, inline } = props; + if (inline != null) { return {children}; } diff --git a/apps/app/src/services/renderer/remark-plugins/codeblock.ts b/apps/app/src/services/renderer/remark-plugins/codeblock.ts index e0290a12a06..becc93c7802 100644 --- a/apps/app/src/services/renderer/remark-plugins/codeblock.ts +++ b/apps/app/src/services/renderer/remark-plugins/codeblock.ts @@ -1,31 +1,23 @@ - -import type { Root } from 'hast'; -import { selectAll } from 'hast-util-select'; +import type { Schema as SanitizeOption } from 'hast-util-sanitize'; import type { InlineCode } from 'mdast'; import type { Plugin } from 'unified'; import { visit } from 'unist-util-visit'; -import { addClassToProperties } from '../rehype-plugins/add-class'; + +const SUPPORTED_CODE = ['inline']; export const remarkPlugin: Plugin = () => { return (tree) => { visit(tree, 'inlineCode', (node: InlineCode) => { const data = node.data || (node.data = {}); - // setting inline for rehypePlugin data.hProperties = { inline: true }; }); }; }; -export const rehypePlugin: Plugin = () => { - return (tree: Root) => { - const codeElements = selectAll('code', tree); - codeElements.forEach((element) => { - // if inlineCode, properties.inline exists. - if (element.properties?.inline != null) { - element.properties.inline = true; - addClassToProperties(element.properties, 'inline'); - } - }); - }; +export const sanitizeOption: SanitizeOption = { + tagNames: ['code'], + attributes: { + code: SUPPORTED_CODE, + }, }; diff --git a/apps/app/src/services/renderer/renderer.tsx b/apps/app/src/services/renderer/renderer.tsx index 999f41d4cd9..b78494b15e6 100644 --- a/apps/app/src/services/renderer/renderer.tsx +++ b/apps/app/src/services/renderer/renderer.tsx @@ -25,7 +25,7 @@ import { tagNames as recommendedTagNames, attributes as recommendedAttributes } import * as addClass from './rehype-plugins/add-class'; import { relativeLinks } from './rehype-plugins/relative-links'; import { relativeLinksByPukiwikiLikeLinker } from './rehype-plugins/relative-links-by-pukiwiki-like-linker'; -import * as codeBlocks from './remark-plugins/codeblock'; +import * as codeBlock from './remark-plugins/codeblock'; import { pukiwikiLikeLinker } from './remark-plugins/pukiwiki-like-linker'; import * as xsvToTable from './remark-plugins/xsv-to-table'; @@ -97,7 +97,7 @@ export const generateCommonOptions = (pagePath: string|undefined): RendererOptio pukiwikiLikeLinker, growiDirective, remarkFrontmatter, - codeBlocks.remarkPlugin, + codeBlock.remarkPlugin, ], remarkRehypeOptions: { clobberPrefix: '', // remove clobber prefix @@ -110,7 +110,6 @@ export const generateCommonOptions = (pagePath: string|undefined): RendererOptio [addClass.rehypePlugin, { table: 'table table-bordered', }], - codeBlocks.rehypePlugin, ], components: { a: NextLink, diff --git a/apps/app/src/stores/renderer.tsx b/apps/app/src/stores/renderer.tsx index 0fdfe9cf1b0..bd4a4776bd3 100644 --- a/apps/app/src/stores/renderer.tsx +++ b/apps/app/src/stores/renderer.tsx @@ -5,11 +5,10 @@ import useSWR, { type SWRConfiguration, type SWRResponse } from 'swr'; import { getGrowiFacade } from '~/features/growi-plugin/client/utils/growi-facade-utils'; import type { RendererOptions } from '~/interfaces/renderer-options'; - - import { useRendererConfig, } from '~/stores-universal/context'; + import { useCurrentPagePath } from './page'; import { useCurrentPageTocNode } from './ui'; From 1e55f4cf1182e6352c531754c0e5895c1112ca9e Mon Sep 17 00:00:00 2001 From: reiji-h Date: Fri, 23 Aug 2024 07:04:42 +0000 Subject: [PATCH 071/490] use value key for attachmentName --- .../services/renderer/remark-plugins/attachment.ts | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/apps/app/src/services/renderer/remark-plugins/attachment.ts b/apps/app/src/services/renderer/remark-plugins/attachment.ts index 91cd8a3e700..5c3084a11de 100644 --- a/apps/app/src/services/renderer/remark-plugins/attachment.ts +++ b/apps/app/src/services/renderer/remark-plugins/attachment.ts @@ -5,17 +5,6 @@ import type { Link } from 'mdast'; import type { Plugin } from 'unified'; import { visit } from 'unist-util-visit'; -declare module 'mdast' { - interface LinkData { - hName?: string, - hProperties?: { - attachmentId?: string, - url?: string, - attachmentName?: PhrasingContent, - } - } -} - const SUPPORTED_ATTRIBUTES = ['attachmentId', 'url', 'attachmentName']; const isAttachmentLink = (url: string): boolean => { @@ -32,7 +21,7 @@ const rewriteNode = (node: Link) => { data.hProperties = { attachmentId, url: node.url, - attachmentName: node.children[0] ?? '', + attachmentName: 'value' in node.children[0] ? node.children[0].value : '', }; }; From c6991273e6eb194183db92be0527573bd15d49a2 Mon Sep 17 00:00:00 2001 From: reiji-h Date: Fri, 23 Aug 2024 07:20:44 +0000 Subject: [PATCH 072/490] fix type check --- apps/app/src/services/renderer/remark-plugins/attachment.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/app/src/services/renderer/remark-plugins/attachment.ts b/apps/app/src/services/renderer/remark-plugins/attachment.ts index 5c3084a11de..9e77dad012f 100644 --- a/apps/app/src/services/renderer/remark-plugins/attachment.ts +++ b/apps/app/src/services/renderer/remark-plugins/attachment.ts @@ -15,13 +15,14 @@ const isAttachmentLink = (url: string): boolean => { const rewriteNode = (node: Link) => { const attachmentId = path.basename(node.url); + const attachmentName = node.children[0] != null && node.children[0].type === 'text' ? node.children[0].value : ''; const data = node.data ?? (node.data = {}); data.hName = 'attachment'; data.hProperties = { attachmentId, url: node.url, - attachmentName: 'value' in node.children[0] ? node.children[0].value : '', + attachmentName, }; }; From 8165837785746692c5225224e7e5e9aff071e306 Mon Sep 17 00:00:00 2001 From: reiji-h Date: Fri, 23 Aug 2024 08:27:48 +0000 Subject: [PATCH 073/490] dont use declare --- .../src/services/renderer/remark-drawio.ts | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/packages/remark-drawio/src/services/renderer/remark-drawio.ts b/packages/remark-drawio/src/services/renderer/remark-drawio.ts index 5182f0080ec..c3c21d4f6b3 100644 --- a/packages/remark-drawio/src/services/renderer/remark-drawio.ts +++ b/packages/remark-drawio/src/services/renderer/remark-drawio.ts @@ -1,3 +1,4 @@ +import type { Properties } from 'hast'; import type { Schema as SanitizeOption } from 'hast-util-sanitize'; import type { Code, Node, Paragraph, @@ -7,16 +8,9 @@ import { visit } from 'unist-util-visit'; const SUPPORTED_ATTRIBUTES = ['diagramIndex', 'bol', 'eol']; -declare module 'mdast' { - interface Data { - hName?: string, - hProperties?: { - diagramIndex?: number, - bol?: number, - eol?: number, - key?: string, - } - } +interface Data { + hName?: string, + hProperties?: Properties, } type Lang = 'drawio'; @@ -30,7 +24,7 @@ function rewriteNode(node: Node, index: number) { node.type = 'paragraph'; (node as Paragraph).children = [{ type: 'text', value: (node as Code).value }]; - const data = node.data ?? (node.data = {}); + const data: Data = node.data ?? (node.data = {}); data.hName = 'drawio'; data.hProperties = { diagramIndex: index, From b283795ed650b6799a192b188e53c3279f7e9266 Mon Sep 17 00:00:00 2001 From: reiji-h <132258880+reiji-h@users.noreply.github.com> Date: Fri, 23 Aug 2024 17:51:19 +0900 Subject: [PATCH 074/490] Revert "fix: Type and linting for updating hast-util-sanitize" --- apps/app/src/interfaces/services/rehype-sanitize.ts | 4 +--- .../src/services/renderer/recommended-whitelist.spec.ts | 9 --------- apps/app/src/services/renderer/recommended-whitelist.ts | 3 +-- 3 files changed, 2 insertions(+), 14 deletions(-) diff --git a/apps/app/src/interfaces/services/rehype-sanitize.ts b/apps/app/src/interfaces/services/rehype-sanitize.ts index 248dd634610..f44366bb965 100644 --- a/apps/app/src/interfaces/services/rehype-sanitize.ts +++ b/apps/app/src/interfaces/services/rehype-sanitize.ts @@ -1,6 +1,4 @@ -import type { defaultSchema } from 'hast-util-sanitize'; - -type Attributes = typeof defaultSchema.attributes; +import type { Attributes } from 'hast-util-sanitize/lib'; export const RehypeSanitizeType = { RECOMMENDED: 'Recommended', diff --git a/apps/app/src/services/renderer/recommended-whitelist.spec.ts b/apps/app/src/services/renderer/recommended-whitelist.spec.ts index e42b57037ba..c9b0eb8f9ee 100644 --- a/apps/app/src/services/renderer/recommended-whitelist.spec.ts +++ b/apps/app/src/services/renderer/recommended-whitelist.spec.ts @@ -14,9 +14,6 @@ describe('recommended-whitelist', () => { test('.attributes should return data attributes', () => { expect(attributes).not.toBeNull(); - - assert(attributes != null); - expect(Object.keys(attributes)).includes('*'); expect(attributes['*']).includes('alt'); expect(attributes['*']).includes('align'); @@ -28,18 +25,12 @@ describe('recommended-whitelist', () => { test('.attributes should return iframe attributes', () => { expect(attributes).not.toBeNull(); - - assert(attributes != null); - expect(Object.keys(attributes)).includes('iframe'); expect(attributes.iframe).includes('src'); }); test('.attributes should return video attributes', () => { expect(attributes).not.toBeNull(); - - assert(attributes != null); - expect(Object.keys(attributes)).includes('video'); expect(attributes.iframe).includes('src'); }); diff --git a/apps/app/src/services/renderer/recommended-whitelist.ts b/apps/app/src/services/renderer/recommended-whitelist.ts index 3bb238e6491..7e60ccb34cd 100644 --- a/apps/app/src/services/renderer/recommended-whitelist.ts +++ b/apps/app/src/services/renderer/recommended-whitelist.ts @@ -1,8 +1,7 @@ import { defaultSchema } from 'hast-util-sanitize'; +import type { Attributes } from 'hast-util-sanitize/lib'; import deepmerge from 'ts-deepmerge'; -type Attributes = typeof defaultSchema.attributes; - /** * reference: https://meta.stackexchange.com/questions/1777/what-html-tags-are-allowed-on-stack-exchange-sites, * https://github.com/jch/html-pipeline/blob/70b6903b025c668ff3c02a6fa382031661182147/lib/html/pipeline/sanitization_filter.rb#L41 From 3ebb6fcb6a3e84fe6ab7fc4468e65446b4c4d920 Mon Sep 17 00:00:00 2001 From: reiji-h Date: Fri, 23 Aug 2024 09:02:11 +0000 Subject: [PATCH 075/490] fix miss revert --- apps/app/src/interfaces/services/rehype-sanitize.ts | 4 +++- .../src/services/renderer/recommended-whitelist.spec.ts | 9 +++++++++ apps/app/src/services/renderer/recommended-whitelist.ts | 3 ++- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/apps/app/src/interfaces/services/rehype-sanitize.ts b/apps/app/src/interfaces/services/rehype-sanitize.ts index f44366bb965..248dd634610 100644 --- a/apps/app/src/interfaces/services/rehype-sanitize.ts +++ b/apps/app/src/interfaces/services/rehype-sanitize.ts @@ -1,4 +1,6 @@ -import type { Attributes } from 'hast-util-sanitize/lib'; +import type { defaultSchema } from 'hast-util-sanitize'; + +type Attributes = typeof defaultSchema.attributes; export const RehypeSanitizeType = { RECOMMENDED: 'Recommended', diff --git a/apps/app/src/services/renderer/recommended-whitelist.spec.ts b/apps/app/src/services/renderer/recommended-whitelist.spec.ts index c9b0eb8f9ee..e42b57037ba 100644 --- a/apps/app/src/services/renderer/recommended-whitelist.spec.ts +++ b/apps/app/src/services/renderer/recommended-whitelist.spec.ts @@ -14,6 +14,9 @@ describe('recommended-whitelist', () => { test('.attributes should return data attributes', () => { expect(attributes).not.toBeNull(); + + assert(attributes != null); + expect(Object.keys(attributes)).includes('*'); expect(attributes['*']).includes('alt'); expect(attributes['*']).includes('align'); @@ -25,12 +28,18 @@ describe('recommended-whitelist', () => { test('.attributes should return iframe attributes', () => { expect(attributes).not.toBeNull(); + + assert(attributes != null); + expect(Object.keys(attributes)).includes('iframe'); expect(attributes.iframe).includes('src'); }); test('.attributes should return video attributes', () => { expect(attributes).not.toBeNull(); + + assert(attributes != null); + expect(Object.keys(attributes)).includes('video'); expect(attributes.iframe).includes('src'); }); diff --git a/apps/app/src/services/renderer/recommended-whitelist.ts b/apps/app/src/services/renderer/recommended-whitelist.ts index 7e60ccb34cd..3bb238e6491 100644 --- a/apps/app/src/services/renderer/recommended-whitelist.ts +++ b/apps/app/src/services/renderer/recommended-whitelist.ts @@ -1,7 +1,8 @@ import { defaultSchema } from 'hast-util-sanitize'; -import type { Attributes } from 'hast-util-sanitize/lib'; import deepmerge from 'ts-deepmerge'; +type Attributes = typeof defaultSchema.attributes; + /** * reference: https://meta.stackexchange.com/questions/1777/what-html-tags-are-allowed-on-stack-exchange-sites, * https://github.com/jch/html-pipeline/blob/70b6903b025c668ff3c02a6fa382031661182147/lib/html/pipeline/sanitization_filter.rb#L41 From 8370a735db352aae15d5e4cf14b05484d8a9abcd Mon Sep 17 00:00:00 2001 From: reiji-h Date: Fri, 23 Aug 2024 09:02:52 +0000 Subject: [PATCH 076/490] Revert "dont use declare" This reverts commit 14cad0ff98343b58c0f3901daf669057fe70ebcf. --- .../src/services/renderer/remark-drawio.ts | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/packages/remark-drawio/src/services/renderer/remark-drawio.ts b/packages/remark-drawio/src/services/renderer/remark-drawio.ts index c3c21d4f6b3..5182f0080ec 100644 --- a/packages/remark-drawio/src/services/renderer/remark-drawio.ts +++ b/packages/remark-drawio/src/services/renderer/remark-drawio.ts @@ -1,4 +1,3 @@ -import type { Properties } from 'hast'; import type { Schema as SanitizeOption } from 'hast-util-sanitize'; import type { Code, Node, Paragraph, @@ -8,9 +7,16 @@ import { visit } from 'unist-util-visit'; const SUPPORTED_ATTRIBUTES = ['diagramIndex', 'bol', 'eol']; -interface Data { - hName?: string, - hProperties?: Properties, +declare module 'mdast' { + interface Data { + hName?: string, + hProperties?: { + diagramIndex?: number, + bol?: number, + eol?: number, + key?: string, + } + } } type Lang = 'drawio'; @@ -24,7 +30,7 @@ function rewriteNode(node: Node, index: number) { node.type = 'paragraph'; (node as Paragraph).children = [{ type: 'text', value: (node as Code).value }]; - const data: Data = node.data ?? (node.data = {}); + const data = node.data ?? (node.data = {}); data.hName = 'drawio'; data.hProperties = { diagramIndex: index, From 9796bd54c95d3c1d2f36e403d1d864c42ae67ecf Mon Sep 17 00:00:00 2001 From: reiji-h Date: Fri, 23 Aug 2024 09:03:13 +0000 Subject: [PATCH 077/490] Revert "fix type check" This reverts commit 62c964028089e076bea507c85d49c98bb0ad3f62. --- apps/app/src/services/renderer/remark-plugins/attachment.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/app/src/services/renderer/remark-plugins/attachment.ts b/apps/app/src/services/renderer/remark-plugins/attachment.ts index 9e77dad012f..5c3084a11de 100644 --- a/apps/app/src/services/renderer/remark-plugins/attachment.ts +++ b/apps/app/src/services/renderer/remark-plugins/attachment.ts @@ -15,14 +15,13 @@ const isAttachmentLink = (url: string): boolean => { const rewriteNode = (node: Link) => { const attachmentId = path.basename(node.url); - const attachmentName = node.children[0] != null && node.children[0].type === 'text' ? node.children[0].value : ''; const data = node.data ?? (node.data = {}); data.hName = 'attachment'; data.hProperties = { attachmentId, url: node.url, - attachmentName, + attachmentName: 'value' in node.children[0] ? node.children[0].value : '', }; }; From 8af4a61df2846ffe0b3e371912c7a06fe7208c40 Mon Sep 17 00:00:00 2001 From: reiji-h Date: Fri, 23 Aug 2024 09:03:37 +0000 Subject: [PATCH 078/490] Revert "use value key for attachmentName" This reverts commit 761c3b92c61dda9841e55c95eaaccf9f115d5022. --- .../services/renderer/remark-plugins/attachment.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/apps/app/src/services/renderer/remark-plugins/attachment.ts b/apps/app/src/services/renderer/remark-plugins/attachment.ts index 5c3084a11de..91cd8a3e700 100644 --- a/apps/app/src/services/renderer/remark-plugins/attachment.ts +++ b/apps/app/src/services/renderer/remark-plugins/attachment.ts @@ -5,6 +5,17 @@ import type { Link } from 'mdast'; import type { Plugin } from 'unified'; import { visit } from 'unist-util-visit'; +declare module 'mdast' { + interface LinkData { + hName?: string, + hProperties?: { + attachmentId?: string, + url?: string, + attachmentName?: PhrasingContent, + } + } +} + const SUPPORTED_ATTRIBUTES = ['attachmentId', 'url', 'attachmentName']; const isAttachmentLink = (url: string): boolean => { @@ -21,7 +32,7 @@ const rewriteNode = (node: Link) => { data.hProperties = { attachmentId, url: node.url, - attachmentName: 'value' in node.children[0] ? node.children[0].value : '', + attachmentName: node.children[0] ?? '', }; }; From 5bb6b66b848542edc28b169bcf19b929aa4f0e79 Mon Sep 17 00:00:00 2001 From: reiji-h Date: Fri, 23 Aug 2024 09:03:58 +0000 Subject: [PATCH 079/490] Revert "add codeblock sanitize" This reverts commit 2ba18f2696cbd67d994f934c09b23620fb8e14aa. --- .../src/client/services/renderer/renderer.tsx | 5 ---- .../ReactMarkdownComponents/CodeBlock.tsx | 12 ++-------- .../renderer/remark-plugins/codeblock.ts | 24 ++++++++++++------- apps/app/src/services/renderer/renderer.tsx | 5 ++-- apps/app/src/stores/renderer.tsx | 3 ++- 5 files changed, 23 insertions(+), 26 deletions(-) diff --git a/apps/app/src/client/services/renderer/renderer.tsx b/apps/app/src/client/services/renderer/renderer.tsx index d9e5d0b2f8d..b5cb77f8bb5 100644 --- a/apps/app/src/client/services/renderer/renderer.tsx +++ b/apps/app/src/client/services/renderer/renderer.tsx @@ -26,7 +26,6 @@ import * as addLineNumberAttribute from '~/services/renderer/rehype-plugins/add- import * as keywordHighlighter from '~/services/renderer/rehype-plugins/keyword-highlighter'; import * as relocateToc from '~/services/renderer/rehype-plugins/relocate-toc'; import * as attachment from '~/services/renderer/remark-plugins/attachment'; -import * as codeBlock from '~/services/renderer/remark-plugins/codeblock'; import * as plantuml from '~/services/renderer/remark-plugins/plantuml'; import * as xsvToTable from '~/services/renderer/remark-plugins/xsv-to-table'; import { @@ -81,7 +80,6 @@ export const generateViewOptions = ( attachment.sanitizeOption, lsxGrowiDirective.sanitizeOption, refsGrowiDirective.sanitizeOption, - codeBlock.sanitizeOption, )] : () => {}; @@ -134,7 +132,6 @@ export const generateTocOptions = (config: RendererConfig, tocNode: HtmlElementN const rehypeSanitizePlugin: Pluggable | (() => void) = config.isEnabledXssPrevention ? [sanitize, deepmerge( getCommonSanitizeOption(config), - codeBlock.sanitizeOption, )] : () => {}; @@ -188,7 +185,6 @@ export const generateSimpleViewOptions = ( attachment.sanitizeOption, lsxGrowiDirective.sanitizeOption, refsGrowiDirective.sanitizeOption, - codeBlock.sanitizeOption, )] : () => {}; @@ -278,7 +274,6 @@ export const generatePreviewOptions = (config: RendererConfig, pagePath: string) lsxGrowiDirective.sanitizeOption, refsGrowiDirective.sanitizeOption, addLineNumberAttribute.sanitizeOption, - codeBlock.sanitizeOption, )] : () => {}; diff --git a/apps/app/src/components/ReactMarkdownComponents/CodeBlock.tsx b/apps/app/src/components/ReactMarkdownComponents/CodeBlock.tsx index 6e01d0eeb55..f17765425aa 100644 --- a/apps/app/src/components/ReactMarkdownComponents/CodeBlock.tsx +++ b/apps/app/src/components/ReactMarkdownComponents/CodeBlock.tsx @@ -65,18 +65,10 @@ function CodeBlockSubstance({ lang, children }: { lang: string, children: ReactN ); } - -type CodeBlockProps = { - children: JSX.Element, - className?: string, - inline?: string, // "" or undefined -} - -export const CodeBlock = (props: CodeBlockProps): JSX.Element => { +export const CodeBlock = ({ className, children }: {className: string, children: JSX.Element}): JSX.Element => { // TODO: set border according to the value of 'customize:highlightJsStyleBorder' - const { className, children, inline } = props; - if (inline != null) { + if (className === 'inline') { return {children}; } diff --git a/apps/app/src/services/renderer/remark-plugins/codeblock.ts b/apps/app/src/services/renderer/remark-plugins/codeblock.ts index becc93c7802..e0290a12a06 100644 --- a/apps/app/src/services/renderer/remark-plugins/codeblock.ts +++ b/apps/app/src/services/renderer/remark-plugins/codeblock.ts @@ -1,23 +1,31 @@ -import type { Schema as SanitizeOption } from 'hast-util-sanitize'; + +import type { Root } from 'hast'; +import { selectAll } from 'hast-util-select'; import type { InlineCode } from 'mdast'; import type { Plugin } from 'unified'; import { visit } from 'unist-util-visit'; - -const SUPPORTED_CODE = ['inline']; +import { addClassToProperties } from '../rehype-plugins/add-class'; export const remarkPlugin: Plugin = () => { return (tree) => { visit(tree, 'inlineCode', (node: InlineCode) => { const data = node.data || (node.data = {}); + // setting inline for rehypePlugin data.hProperties = { inline: true }; }); }; }; -export const sanitizeOption: SanitizeOption = { - tagNames: ['code'], - attributes: { - code: SUPPORTED_CODE, - }, +export const rehypePlugin: Plugin = () => { + return (tree: Root) => { + const codeElements = selectAll('code', tree); + codeElements.forEach((element) => { + // if inlineCode, properties.inline exists. + if (element.properties?.inline != null) { + element.properties.inline = true; + addClassToProperties(element.properties, 'inline'); + } + }); + }; }; diff --git a/apps/app/src/services/renderer/renderer.tsx b/apps/app/src/services/renderer/renderer.tsx index b78494b15e6..999f41d4cd9 100644 --- a/apps/app/src/services/renderer/renderer.tsx +++ b/apps/app/src/services/renderer/renderer.tsx @@ -25,7 +25,7 @@ import { tagNames as recommendedTagNames, attributes as recommendedAttributes } import * as addClass from './rehype-plugins/add-class'; import { relativeLinks } from './rehype-plugins/relative-links'; import { relativeLinksByPukiwikiLikeLinker } from './rehype-plugins/relative-links-by-pukiwiki-like-linker'; -import * as codeBlock from './remark-plugins/codeblock'; +import * as codeBlocks from './remark-plugins/codeblock'; import { pukiwikiLikeLinker } from './remark-plugins/pukiwiki-like-linker'; import * as xsvToTable from './remark-plugins/xsv-to-table'; @@ -97,7 +97,7 @@ export const generateCommonOptions = (pagePath: string|undefined): RendererOptio pukiwikiLikeLinker, growiDirective, remarkFrontmatter, - codeBlock.remarkPlugin, + codeBlocks.remarkPlugin, ], remarkRehypeOptions: { clobberPrefix: '', // remove clobber prefix @@ -110,6 +110,7 @@ export const generateCommonOptions = (pagePath: string|undefined): RendererOptio [addClass.rehypePlugin, { table: 'table table-bordered', }], + codeBlocks.rehypePlugin, ], components: { a: NextLink, diff --git a/apps/app/src/stores/renderer.tsx b/apps/app/src/stores/renderer.tsx index bd4a4776bd3..0fdfe9cf1b0 100644 --- a/apps/app/src/stores/renderer.tsx +++ b/apps/app/src/stores/renderer.tsx @@ -5,10 +5,11 @@ import useSWR, { type SWRConfiguration, type SWRResponse } from 'swr'; import { getGrowiFacade } from '~/features/growi-plugin/client/utils/growi-facade-utils'; import type { RendererOptions } from '~/interfaces/renderer-options'; + + import { useRendererConfig, } from '~/stores-universal/context'; - import { useCurrentPagePath } from './page'; import { useCurrentPageTocNode } from './ui'; From 50b3706ab86e55e241b494cc9925421ef2d298a6 Mon Sep 17 00:00:00 2001 From: reiji-h Date: Fri, 23 Aug 2024 09:40:29 +0000 Subject: [PATCH 080/490] copy file structure from mdast-util-directive --- .../src/mdast-util-growi-directive/{index.ts => index.d.ts} | 4 ++-- .../src/mdast-util-growi-directive/index.js | 2 ++ packages/remark-growi-directive/tsconfig.build.json | 3 +-- packages/remark-lsx/src/client/services/renderer/lsx.ts | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) rename packages/remark-growi-directive/src/mdast-util-growi-directive/{index.ts => index.d.ts} (98%) create mode 100644 packages/remark-growi-directive/src/mdast-util-growi-directive/index.js diff --git a/packages/remark-growi-directive/src/mdast-util-growi-directive/index.ts b/packages/remark-growi-directive/src/mdast-util-growi-directive/index.d.ts similarity index 98% rename from packages/remark-growi-directive/src/mdast-util-growi-directive/index.ts rename to packages/remark-growi-directive/src/mdast-util-growi-directive/index.d.ts index a326d7e46f5..199c278bbae 100644 --- a/packages/remark-growi-directive/src/mdast-util-growi-directive/index.ts +++ b/packages/remark-growi-directive/src/mdast-util-growi-directive/index.d.ts @@ -6,10 +6,10 @@ import type { import { DirectiveType as DirectiveTypeObject } from './lib/index.js'; +export { directiveFromMarkdown, directiveToMarkdown } from './lib/index.js'; export { DirectiveTypeObject }; -type DirectiveType = typeof DirectiveTypeObject; -export { directiveToMarkdown, directiveFromMarkdown } from './lib/index.js'; +type DirectiveType = typeof DirectiveTypeObject; /** * Fields shared by directives. diff --git a/packages/remark-growi-directive/src/mdast-util-growi-directive/index.js b/packages/remark-growi-directive/src/mdast-util-growi-directive/index.js new file mode 100644 index 00000000000..8ba5be9361c --- /dev/null +++ b/packages/remark-growi-directive/src/mdast-util-growi-directive/index.js @@ -0,0 +1,2 @@ +export { directiveFromMarkdown, directiveToMarkdown } from './lib/index.js'; +export { DirectiveType as DirectiveTypeObject } from './lib/index.js'; diff --git a/packages/remark-growi-directive/tsconfig.build.json b/packages/remark-growi-directive/tsconfig.build.json index 5641862c8bc..4ea7ba128d7 100644 --- a/packages/remark-growi-directive/tsconfig.build.json +++ b/packages/remark-growi-directive/tsconfig.build.json @@ -8,7 +8,6 @@ "noResolve": false, "preserveConstEnums": true, "sourceMap": false, - "noEmit": false, - "allowJs": true + "noEmit": false } } diff --git a/packages/remark-lsx/src/client/services/renderer/lsx.ts b/packages/remark-lsx/src/client/services/renderer/lsx.ts index 36117a9f86d..741ed86fedb 100644 --- a/packages/remark-lsx/src/client/services/renderer/lsx.ts +++ b/packages/remark-lsx/src/client/services/renderer/lsx.ts @@ -1,8 +1,8 @@ import assert from 'assert'; import { hasHeadingSlash, removeTrailingSlash, addTrailingSlash } from '@growi/core/dist/utils/path-utils'; -import { remarkGrowiDirectivePluginType } from '@growi/remark-growi-directive'; import type { TextGrowiPluginDirective, LeafGrowiPluginDirective } from '@growi/remark-growi-directive'; +import { remarkGrowiDirectivePluginType } from '@growi/remark-growi-directive'; import type { Nodes as HastNode } from 'hast'; import type { Schema as SanitizeOption } from 'hast-util-sanitize'; import { selectAll } from 'hast-util-select'; From 15941d6d690e71ee7aeea07c40daea63499b6430 Mon Sep 17 00:00:00 2001 From: reiji-h Date: Fri, 23 Aug 2024 09:59:37 +0000 Subject: [PATCH 081/490] add export --- .../src/mdast-util-growi-directive/index.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/remark-growi-directive/src/mdast-util-growi-directive/index.js b/packages/remark-growi-directive/src/mdast-util-growi-directive/index.js index 8ba5be9361c..d1f8eca218d 100644 --- a/packages/remark-growi-directive/src/mdast-util-growi-directive/index.js +++ b/packages/remark-growi-directive/src/mdast-util-growi-directive/index.js @@ -1,2 +1,8 @@ export { directiveFromMarkdown, directiveToMarkdown } from './lib/index.js'; export { DirectiveType as DirectiveTypeObject } from './lib/index.js'; +export { + LeafGrowiPluginDirective, + TextGrowiPluginDirective, + LeafGrowiPluginDirectiveData, + TextGrowiPluginDirectiveData, +} from './index'; From e3b5ebe65f9c4a3f158bb47d41aaae920978099c Mon Sep 17 00:00:00 2001 From: reiji-h Date: Mon, 26 Aug 2024 03:34:52 +0000 Subject: [PATCH 082/490] change file type --- .../{index.d.ts => index.ts} | 0 .../mdast-util-growi-directive/lib/index.js | 18 ++++++++++-------- 2 files changed, 10 insertions(+), 8 deletions(-) rename packages/remark-growi-directive/src/mdast-util-growi-directive/{index.d.ts => index.ts} (100%) diff --git a/packages/remark-growi-directive/src/mdast-util-growi-directive/index.d.ts b/packages/remark-growi-directive/src/mdast-util-growi-directive/index.ts similarity index 100% rename from packages/remark-growi-directive/src/mdast-util-growi-directive/index.d.ts rename to packages/remark-growi-directive/src/mdast-util-growi-directive/index.ts diff --git a/packages/remark-growi-directive/src/mdast-util-growi-directive/lib/index.js b/packages/remark-growi-directive/src/mdast-util-growi-directive/lib/index.js index 4096cc95f8c..e4a4f8b86a7 100644 --- a/packages/remark-growi-directive/src/mdast-util-growi-directive/lib/index.js +++ b/packages/remark-growi-directive/src/mdast-util-growi-directive/lib/index.js @@ -1,14 +1,16 @@ /** - * @typedef {import('mdast').BlockContent} BlockContent - * @typedef {import('mdast').Root} Root + * @typedef {import('mdast').Node} Node * @typedef {import('mdast').Paragraph} Paragraph - * @typedef {import('mdast-util-from-markdown').Handle} FromMarkdownHandle - * @typedef {import('mdast-util-from-markdown').Extension} FromMarkdownExtension + * * @typedef {import('mdast-util-from-markdown').CompileContext} CompileContext + * @typedef {import('mdast-util-from-markdown').Extension} FromMarkdownExtension + * @typedef {import('mdast-util-from-markdown').Handle} FromMarkdownHandle * @typedef {import('mdast-util-from-markdown').Token} Token + * + * @typedef {import('mdast-util-to-markdown').ConstructName} ConstructName * @typedef {import('mdast-util-to-markdown').Handle} ToMarkdownHandle - * @typedef {import('mdast-util-to-markdown').Context} Context * @typedef {import('mdast-util-to-markdown').Options} ToMarkdownExtension + * @typedef {import('mdast-util-to-markdown').State} State * * @typedef {import('../types/index.js').LeafGrowiPluginDirective} LeafGrowiPluginDirective * @typedef {import('../types/index.js').TextGrowiPluginDirective} TextGrowiPluginDirective @@ -207,11 +209,11 @@ function peekDirective() { /** * @param {Directive} node - * @param {Context} context + * @param {State} state * @returns {string} */ -function attributes(node, context) { - const quote = context.options.quote || '"'; +function attributes(node, state) { + const quote = state.options.quote || '"'; const subset = node.type === DirectiveType.Text ? [quote] : [quote, '\n', '\r']; const attrs = node.attributes || {}; /** @type {Array.} */ From 4309cfa1faa7145a35ff2e8855bf1230b12bf85b Mon Sep 17 00:00:00 2001 From: reiji-h Date: Mon, 26 Aug 2024 04:04:43 +0000 Subject: [PATCH 083/490] fix import path --- packages/remark-growi-directive/src/remark-growi-directive.js | 2 +- .../test/mdast-util-growi-directive.test.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/remark-growi-directive/src/remark-growi-directive.js b/packages/remark-growi-directive/src/remark-growi-directive.js index e936aeca041..610d14cbe5d 100644 --- a/packages/remark-growi-directive/src/remark-growi-directive.js +++ b/packages/remark-growi-directive/src/remark-growi-directive.js @@ -3,7 +3,7 @@ * @typedef {import('unified').Processor} Processor */ -import { directiveFromMarkdown, directiveToMarkdown } from './mdast-util-growi-directive/index'; +import { directiveFromMarkdown, directiveToMarkdown } from './mdast-util-growi-directive/index.js'; import { directive } from './micromark-extension-growi-directive/index.js'; /** diff --git a/packages/remark-growi-directive/test/mdast-util-growi-directive.test.js b/packages/remark-growi-directive/test/mdast-util-growi-directive.test.js index cf5c00e2c0e..69a4ea71876 100644 --- a/packages/remark-growi-directive/test/mdast-util-growi-directive.test.js +++ b/packages/remark-growi-directive/test/mdast-util-growi-directive.test.js @@ -3,7 +3,7 @@ import { toMarkdown } from 'mdast-util-to-markdown'; import { removePosition } from 'unist-util-remove-position'; import { describe, it, expect } from 'vitest'; -import { directiveFromMarkdown, directiveToMarkdown } from '../src/mdast-util-growi-directive/index'; +import { directiveFromMarkdown, directiveToMarkdown } from '../src/mdast-util-growi-directive/index.js'; import { DirectiveType } from '../src/mdast-util-growi-directive/lib/index.js'; import { directive } from '../src/micromark-extension-growi-directive/index.js'; From 81863d7cc743432778d23572e58d3219c3d8047b Mon Sep 17 00:00:00 2001 From: reiji-h Date: Mon, 26 Aug 2024 09:00:15 +0000 Subject: [PATCH 084/490] use postbuild and declaration --- packages/remark-growi-directive/package.json | 2 ++ .../src/mdast-util-growi-directive/{index.ts => index.d.ts} | 0 .../src/mdast-util-growi-directive/index.js | 6 ------ 3 files changed, 2 insertions(+), 6 deletions(-) rename packages/remark-growi-directive/src/mdast-util-growi-directive/{index.ts => index.d.ts} (100%) diff --git a/packages/remark-growi-directive/package.json b/packages/remark-growi-directive/package.json index de0135a9590..61b7acaef64 100644 --- a/packages/remark-growi-directive/package.json +++ b/packages/remark-growi-directive/package.json @@ -17,7 +17,9 @@ "main": "dist/index.js", "typings": "dist/index.d.ts", "scripts": { + "cp:declaration": "cp -RT ./src/mdast-util-growi-directive/index.d.ts ./dist/mdast-util-growi-directive/index.d.ts", "build": "yarn tsc -p tsconfig.build.json", + "postbuild": "yarn cp:declaration", "clean": "shx rm -rf dist", "dev": "yarn build", "watch": "yarn tsc -w", diff --git a/packages/remark-growi-directive/src/mdast-util-growi-directive/index.ts b/packages/remark-growi-directive/src/mdast-util-growi-directive/index.d.ts similarity index 100% rename from packages/remark-growi-directive/src/mdast-util-growi-directive/index.ts rename to packages/remark-growi-directive/src/mdast-util-growi-directive/index.d.ts diff --git a/packages/remark-growi-directive/src/mdast-util-growi-directive/index.js b/packages/remark-growi-directive/src/mdast-util-growi-directive/index.js index d1f8eca218d..8ba5be9361c 100644 --- a/packages/remark-growi-directive/src/mdast-util-growi-directive/index.js +++ b/packages/remark-growi-directive/src/mdast-util-growi-directive/index.js @@ -1,8 +1,2 @@ export { directiveFromMarkdown, directiveToMarkdown } from './lib/index.js'; export { DirectiveType as DirectiveTypeObject } from './lib/index.js'; -export { - LeafGrowiPluginDirective, - TextGrowiPluginDirective, - LeafGrowiPluginDirectiveData, - TextGrowiPluginDirectiveData, -} from './index'; From 1834459cc54366df297adbb15fc144fb52b0d537 Mon Sep 17 00:00:00 2001 From: reiji-h Date: Mon, 26 Aug 2024 09:12:46 +0000 Subject: [PATCH 085/490] use shx --- packages/remark-growi-directive/package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/remark-growi-directive/package.json b/packages/remark-growi-directive/package.json index 61b7acaef64..bd11654335e 100644 --- a/packages/remark-growi-directive/package.json +++ b/packages/remark-growi-directive/package.json @@ -17,9 +17,8 @@ "main": "dist/index.js", "typings": "dist/index.d.ts", "scripts": { - "cp:declaration": "cp -RT ./src/mdast-util-growi-directive/index.d.ts ./dist/mdast-util-growi-directive/index.d.ts", "build": "yarn tsc -p tsconfig.build.json", - "postbuild": "yarn cp:declaration", + "postbuild": "shx cp ./src/mdast-util-growi-directive/index.d.ts ./dist/mdast-util-growi-directive/index.d.ts", "clean": "shx rm -rf dist", "dev": "yarn build", "watch": "yarn tsc -w", From c862036558aba15db6dbcdc008f30bc417198243 Mon Sep 17 00:00:00 2001 From: Yuki Takei Date: Tue, 27 Aug 2024 11:35:57 +0000 Subject: [PATCH 086/490] add openai package --- apps/app/package.json | 1 + yarn.lock | 82 ++++++++++++++++++++++++++++--------------- 2 files changed, 55 insertions(+), 28 deletions(-) diff --git a/apps/app/package.json b/apps/app/package.json index 0377efc8eea..85c29fde666 100644 --- a/apps/app/package.json +++ b/apps/app/package.json @@ -153,6 +153,7 @@ "node-cron": "^3.0.2", "nodemailer": "^6.9.14", "nodemailer-ses-transport": "~1.5.0", + "openai": "^4.56.0", "openid-client": "^5.4.0", "p-retry": "^4.0.0", "passport": "^0.6.0", diff --git a/yarn.lock b/yarn.lock index 0486e40c545..042a3f5389f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4532,6 +4532,14 @@ "@types/node" "*" form-data "^4.0.0" +"@types/node-fetch@^2.6.4": + version "2.6.11" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.11.tgz#9b39b78665dae0e82a08f02f4967d62c66f95d24" + integrity sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g== + dependencies: + "@types/node" "*" + form-data "^4.0.0" + "@types/node@*", "@types/node@>=10.0.0", "@types/node@>=12", "@types/node@>=12.0.0", "@types/node@>=8.9.0", "@types/node@^20.14.0": version "20.14.0" resolved "https://registry.yarnpkg.com/@types/node/-/node-20.14.0.tgz#49ceec7b34f8621470cff44677fa9d461a477f17" @@ -4549,6 +4557,13 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.5.tgz#0dd636fe7b2c6055cbed0d4ca3b7fb540f130a96" integrity sha512-LMy+vDDcQR48EZdEx5wRX1q/sEl6NdGuHXPnfeL8ixkwCOSZ2qnIyIZmcCbdX0MeRqHhAcHmX+haCbrS8Run+A== +"@types/node@^18.11.18": + version "18.19.46" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.46.tgz#51801396c01153e0626e36f43386e83bc768b072" + integrity sha512-vnRgMS7W6cKa1/0G3/DTtQYpVrZ8c0Xm6UkLaVFrb9jtcVC3okokW09Ki1Qdrj9ISokszD69nY4WDLRlvHlhAA== + dependencies: + undici-types "~5.26.4" + "@types/node@^18.17.5": version "18.18.3" resolved "https://registry.yarnpkg.com/@types/node/-/node-18.18.3.tgz#e5188135fc2909b46530c798ef49be65083be3fd" @@ -9402,6 +9417,11 @@ forever-agent@~0.6.1: resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= +form-data-encoder@1.7.2: + version "1.7.2" + resolved "https://registry.yarnpkg.com/form-data-encoder/-/form-data-encoder-1.7.2.tgz#1f1ae3dccf58ed4690b86d87e4f57c654fbab040" + integrity sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A== + form-data@^2.5.0: version "2.5.1" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.1.tgz#f2cbec57b5e59e23716e128fe44d4e5dd23895f4" @@ -9434,6 +9454,14 @@ format@^0.2.0: resolved "https://registry.yarnpkg.com/format/-/format-0.2.2.tgz#d6170107e9efdc4ed30c9dc39016df942b5cb58b" integrity sha1-1hcBB+nv3E7TDJ3DkBbflCtctYs= +formdata-node@^4.3.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/formdata-node/-/formdata-node-4.4.1.tgz#23f6a5cb9cb55315912cbec4ff7b0f59bbd191e2" + integrity sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ== + dependencies: + node-domexception "1.0.0" + web-streams-polyfill "4.0.0-beta.3" + forwarded@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" @@ -13924,6 +13952,11 @@ node-cron@^3.0.2: dependencies: uuid "8.3.2" +node-domexception@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" + integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== + node-emoji@^1.11.0: version "1.11.0" resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-1.11.0.tgz#69a0150e6946e2f115e9d7ea4df7971e2628301c" @@ -14350,6 +14383,19 @@ open@^8.0.0, open@^8.4.0: is-docker "^2.1.1" is-wsl "^2.2.0" +openai@^4.56.0: + version "4.56.0" + resolved "https://registry.yarnpkg.com/openai/-/openai-4.56.0.tgz#07d3982544cabd5781127288a8dfcceb7319a4cf" + integrity sha512-zcag97+3bG890MNNa0DQD9dGmmTWL8unJdNkulZzWRXrl+QeD+YkBI4H58rJcwErxqGK6a0jVPZ4ReJjhDGcmw== + dependencies: + "@types/node" "^18.11.18" + "@types/node-fetch" "^2.6.4" + abort-controller "^3.0.0" + agentkeepalive "^4.2.1" + form-data-encoder "1.7.2" + formdata-node "^4.3.2" + node-fetch "^2.6.7" + opener@^1.5.2: version "1.5.2" resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598" @@ -17252,7 +17298,7 @@ string-template@>=1.0.0: resolved "https://registry.yarnpkg.com/string-template/-/string-template-1.0.0.tgz#9e9f2233dc00f218718ec379a28a5673ecca8b96" integrity sha1-np8iM9wA8hhxjsN5oopWc+zKi5Y= -"string-width-cjs@npm:string-width@^4.2.0": +"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -17270,15 +17316,6 @@ string-width@=4.2.2: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.0" -"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - string-width@^5.0.1, string-width@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" @@ -17362,7 +17399,7 @@ stringify-entities@^4.0.0: character-entities-html4 "^2.0.0" character-entities-legacy "^3.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -17376,13 +17413,6 @@ strip-ansi@^3.0.0: dependencies: ansi-regex "^2.0.0" -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - strip-ansi@^7.0.1, strip-ansi@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -19057,6 +19087,11 @@ web-namespaces@^2.0.0: resolved "https://registry.yarnpkg.com/web-namespaces/-/web-namespaces-2.0.1.tgz#1010ff7c650eccb2592cebeeaf9a1b253fd40692" integrity sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ== +web-streams-polyfill@4.0.0-beta.3: + version "4.0.0-beta.3" + resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz#2898486b74f5156095e473efe989dcf185047a38" + integrity sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug== + web-worker@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/web-worker/-/web-worker-1.2.0.tgz#5d85a04a7fbc1e7db58f66595d7a3ac7c9c180da" @@ -19204,7 +19239,7 @@ word-wrap@^1.2.3: resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -19222,15 +19257,6 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" From 8069858f1326b37243b469069b4b6bf996eb2de2 Mon Sep 17 00:00:00 2001 From: Yuki Takei Date: Tue, 27 Aug 2024 11:36:35 +0000 Subject: [PATCH 087/490] impl OpenaiService.embed --- apps/app/src/server/service/openai/index.ts | 1 + apps/app/src/server/service/openai/openai.ts | 30 ++++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 apps/app/src/server/service/openai/index.ts create mode 100644 apps/app/src/server/service/openai/openai.ts diff --git a/apps/app/src/server/service/openai/index.ts b/apps/app/src/server/service/openai/index.ts new file mode 100644 index 00000000000..e919f9e4296 --- /dev/null +++ b/apps/app/src/server/service/openai/index.ts @@ -0,0 +1 @@ +export * from './openai'; diff --git a/apps/app/src/server/service/openai/openai.ts b/apps/app/src/server/service/openai/openai.ts new file mode 100644 index 00000000000..b4462198c02 --- /dev/null +++ b/apps/app/src/server/service/openai/openai.ts @@ -0,0 +1,30 @@ +import { OpenAI } from 'openai'; + +export interface IOpenaiService { + embed: (user: string, input: string) => Promise; +} + +class OpenaiService implements IOpenaiService { + + client: OpenAI; + + constructor() { + this.client = new OpenAI({ + apiKey: process.env.OPENAI_API_KEY, // This is the default and can be omitted + }); + } + + async embed(userId: string, input: string): Promise { + const result = await this.client.embeddings.create({ + input, + model: 'text-embedding-3-large', + dimensions: process.env.OPENAI_DIMENSIONS as unknown as number, + user: userId, + }); + + return result.data; + } + +} + +export const openaiService = new OpenaiService(); From 1c2a47794d5537c72e7eb473296cfabf934a3b30 Mon Sep 17 00:00:00 2001 From: Yuki Takei Date: Tue, 27 Aug 2024 13:28:24 +0000 Subject: [PATCH 088/490] fix openai.ts --- apps/app/src/server/service/openai/openai.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/app/src/server/service/openai/openai.ts b/apps/app/src/server/service/openai/openai.ts index b4462198c02..9a5e048cc8a 100644 --- a/apps/app/src/server/service/openai/openai.ts +++ b/apps/app/src/server/service/openai/openai.ts @@ -1,7 +1,7 @@ import { OpenAI } from 'openai'; export interface IOpenaiService { - embed: (user: string, input: string) => Promise; + embed: (username: string, input: string) => Promise; } class OpenaiService implements IOpenaiService { @@ -14,12 +14,12 @@ class OpenaiService implements IOpenaiService { }); } - async embed(userId: string, input: string): Promise { + async embed(username: string, input: string): Promise { const result = await this.client.embeddings.create({ input, model: 'text-embedding-3-large', - dimensions: process.env.OPENAI_DIMENSIONS as unknown as number, - user: userId, + dimensions: Number(process.env.OPENAI_DIMENSIONS), + user: username, }); return result.data; From 235c3351ffa3bc32873796b5c1eff90705c7d558 Mon Sep 17 00:00:00 2001 From: Yuki Takei Date: Tue, 27 Aug 2024 13:36:46 +0000 Subject: [PATCH 089/490] store embedded body --- apps/app/resource/search/mappings-es7.json | 4 ++++ apps/app/resource/search/mappings-es8.json | 4 ++++ .../service/search-delegator/bulk-write.d.ts | 2 ++ .../service/search-delegator/elasticsearch.ts | 17 ++++++++++++++++- 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/apps/app/resource/search/mappings-es7.json b/apps/app/resource/search/mappings-es7.json index 1a481b29a26..f8e48a47fa9 100644 --- a/apps/app/resource/search/mappings-es7.json +++ b/apps/app/resource/search/mappings-es7.json @@ -64,6 +64,10 @@ } } }, + "body_embedded": { + "type": "dense_vector", + "dims": 768 + }, "comments": { "type": "text", "fields": { diff --git a/apps/app/resource/search/mappings-es8.json b/apps/app/resource/search/mappings-es8.json index f99934a70f3..36eaab49d5a 100644 --- a/apps/app/resource/search/mappings-es8.json +++ b/apps/app/resource/search/mappings-es8.json @@ -64,6 +64,10 @@ } } }, + "body_embedded": { + "type": "dense_vector", + "dims": 768 + }, "comments": { "type": "text", "fields": { diff --git a/apps/app/src/server/service/search-delegator/bulk-write.d.ts b/apps/app/src/server/service/search-delegator/bulk-write.d.ts index b6fe0f157d9..fcabdcdda4b 100644 --- a/apps/app/src/server/service/search-delegator/bulk-write.d.ts +++ b/apps/app/src/server/service/search-delegator/bulk-write.d.ts @@ -21,6 +21,7 @@ export type AggregatedPage = Pick 0 ? page.comments : undefined, comment_count: page.commentsCount, @@ -479,6 +480,19 @@ class ElasticsearchDelegator implements SearchDelegator Date: Tue, 27 Aug 2024 13:42:21 +0000 Subject: [PATCH 090/490] fix type --- apps/app/src/server/service/search-delegator/bulk-write.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/app/src/server/service/search-delegator/bulk-write.d.ts b/apps/app/src/server/service/search-delegator/bulk-write.d.ts index fcabdcdda4b..0bd189973d1 100644 --- a/apps/app/src/server/service/search-delegator/bulk-write.d.ts +++ b/apps/app/src/server/service/search-delegator/bulk-write.d.ts @@ -21,7 +21,7 @@ export type AggregatedPage = Pick Date: Tue, 27 Aug 2024 15:17:02 +0000 Subject: [PATCH 091/490] impl GET: /_api/v3/openai/chat --- apps/app/src/server/routes/apiv3/index.js | 3 ++ .../src/server/routes/apiv3/openai/chat.ts | 42 +++++++++++++++++++ .../src/server/routes/apiv3/openai/index.ts | 10 +++++ 3 files changed, 55 insertions(+) create mode 100644 apps/app/src/server/routes/apiv3/openai/chat.ts create mode 100644 apps/app/src/server/routes/apiv3/openai/index.ts diff --git a/apps/app/src/server/routes/apiv3/index.js b/apps/app/src/server/routes/apiv3/index.js index de89bfdd80c..112f3abce0b 100644 --- a/apps/app/src/server/routes/apiv3/index.js +++ b/apps/app/src/server/routes/apiv3/index.js @@ -8,6 +8,7 @@ import * as registerFormValidator from '../../middlewares/register-form-validato import g2gTransfer from './g2g-transfer'; import importRoute from './import'; +import openai from './openai'; import pageListing from './page-listing'; import securitySettings from './security-settings'; import * as userActivation from './user-activation'; @@ -119,5 +120,7 @@ module.exports = (crowi, app) => { router.use('/questionnaire', require('~/features/questionnaire/server/routes/apiv3/questionnaire')(crowi)); router.use('/templates', require('~/features/templates/server/routes/apiv3')(crowi)); + router.use('/openai', openai(crowi)); + return [router, routerForAdmin, routerForAuth]; }; diff --git a/apps/app/src/server/routes/apiv3/openai/chat.ts b/apps/app/src/server/routes/apiv3/openai/chat.ts new file mode 100644 index 00000000000..6798a8810eb --- /dev/null +++ b/apps/app/src/server/routes/apiv3/openai/chat.ts @@ -0,0 +1,42 @@ +import type { Request, RequestHandler } from 'express'; +import type { ValidationChain } from 'express-validator'; + +import type Crowi from '~/server/crowi'; +import loggerFactory from '~/utils/logger'; + +import { apiV3FormValidator } from '../../../middlewares/apiv3-form-validator'; +import type { ApiV3Response } from '../interfaces/apiv3-response'; + + +const logger = loggerFactory('growi:routes:apiv3:openai:chat'); + + +type ReqParams = { + // +} + +type Req = Request + +type ChatHandlersFactory = (crowi: Crowi) => RequestHandler[]; + +export const chatHandlersFactory: ChatHandlersFactory = (crowi) => { + const accessTokenParser = require('../../../middlewares/access-token-parser')(crowi); + const loginRequiredStrictly = require('../../../middlewares/login-required')(crowi); + + // define validators for req.body + const validator: ValidationChain[] = []; + + return [ + accessTokenParser, loginRequiredStrictly, validator, apiV3FormValidator, + async(req: Req, res: ApiV3Response) => { + + try { + return res.apiv3({}); + } + catch (err) { + logger.error(err); + return res.apiv3Err(err); + } + }, + ]; +}; diff --git a/apps/app/src/server/routes/apiv3/openai/index.ts b/apps/app/src/server/routes/apiv3/openai/index.ts new file mode 100644 index 00000000000..55052a734d0 --- /dev/null +++ b/apps/app/src/server/routes/apiv3/openai/index.ts @@ -0,0 +1,10 @@ +import express from 'express'; + +import { chatHandlersFactory } from './chat'; + +const router = express.Router(); + +module.exports = (crowi) => { + router.get('/chat', chatHandlersFactory(crowi)); + return router; +}; From 1a79013f45519dbe38eefb9107fb005ef0a83570 Mon Sep 17 00:00:00 2001 From: Shun Miyazawa Date: Tue, 27 Aug 2024 15:47:59 +0000 Subject: [PATCH 092/490] get -> post --- apps/app/src/server/routes/apiv3/openai/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/app/src/server/routes/apiv3/openai/index.ts b/apps/app/src/server/routes/apiv3/openai/index.ts index 55052a734d0..302fd0a8404 100644 --- a/apps/app/src/server/routes/apiv3/openai/index.ts +++ b/apps/app/src/server/routes/apiv3/openai/index.ts @@ -5,6 +5,6 @@ import { chatHandlersFactory } from './chat'; const router = express.Router(); module.exports = (crowi) => { - router.get('/chat', chatHandlersFactory(crowi)); + router.post('/chat', chatHandlersFactory(crowi)); return router; }; From a150ec2936b9e730cc2a592e3f38873d738a4f0e Mon Sep 17 00:00:00 2001 From: Shun Miyazawa Date: Tue, 27 Aug 2024 16:08:45 +0000 Subject: [PATCH 093/490] Use OpenAI API --- .../src/server/routes/apiv3/openai/chat.ts | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/apps/app/src/server/routes/apiv3/openai/chat.ts b/apps/app/src/server/routes/apiv3/openai/chat.ts index 6798a8810eb..45cf5fa913c 100644 --- a/apps/app/src/server/routes/apiv3/openai/chat.ts +++ b/apps/app/src/server/routes/apiv3/openai/chat.ts @@ -1,21 +1,21 @@ import type { Request, RequestHandler } from 'express'; import type { ValidationChain } from 'express-validator'; +import { body } from 'express-validator'; import type Crowi from '~/server/crowi'; +import { openaiService } from '~/server/service/openai'; import loggerFactory from '~/utils/logger'; import { apiV3FormValidator } from '../../../middlewares/apiv3-form-validator'; import type { ApiV3Response } from '../interfaces/apiv3-response'; - const logger = loggerFactory('growi:routes:apiv3:openai:chat'); - -type ReqParams = { - // +type ReqBody = { + prompt: string, } -type Req = Request +type Req = Request type ChatHandlersFactory = (crowi: Crowi) => RequestHandler[]; @@ -23,15 +23,20 @@ export const chatHandlersFactory: ChatHandlersFactory = (crowi) => { const accessTokenParser = require('../../../middlewares/access-token-parser')(crowi); const loginRequiredStrictly = require('../../../middlewares/login-required')(crowi); - // define validators for req.body - const validator: ValidationChain[] = []; + const validator: ValidationChain[] = [ + body('prompt').isString().withMessage('prompt must be string'), + ]; return [ accessTokenParser, loginRequiredStrictly, validator, apiV3FormValidator, async(req: Req, res: ApiV3Response) => { - try { - return res.apiv3({}); + const chatCompletion = await openaiService.client.chat.completions.create({ + messages: [{ role: 'assistant', content: req.body.prompt }], + model: 'gpt-3.5-turbo-0125', + }); + + return res.apiv3({ assistantMessage: chatCompletion.choices[0].message.content }); } catch (err) { logger.error(err); From 0a066d654eb87d0194bdffa28aac8e1d7081d55b Mon Sep 17 00:00:00 2001 From: Shun Miyazawa Date: Tue, 27 Aug 2024 17:46:41 +0000 Subject: [PATCH 094/490] prompt -> userMessage --- apps/app/src/server/routes/apiv3/openai/chat.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/app/src/server/routes/apiv3/openai/chat.ts b/apps/app/src/server/routes/apiv3/openai/chat.ts index 45cf5fa913c..f72ba777b7d 100644 --- a/apps/app/src/server/routes/apiv3/openai/chat.ts +++ b/apps/app/src/server/routes/apiv3/openai/chat.ts @@ -12,7 +12,7 @@ import type { ApiV3Response } from '../interfaces/apiv3-response'; const logger = loggerFactory('growi:routes:apiv3:openai:chat'); type ReqBody = { - prompt: string, + userMessage: string, } type Req = Request @@ -24,7 +24,7 @@ export const chatHandlersFactory: ChatHandlersFactory = (crowi) => { const loginRequiredStrictly = require('../../../middlewares/login-required')(crowi); const validator: ValidationChain[] = [ - body('prompt').isString().withMessage('prompt must be string'), + body('userMessage').isString().withMessage('userMessage must be string'), ]; return [ @@ -32,7 +32,7 @@ export const chatHandlersFactory: ChatHandlersFactory = (crowi) => { async(req: Req, res: ApiV3Response) => { try { const chatCompletion = await openaiService.client.chat.completions.create({ - messages: [{ role: 'assistant', content: req.body.prompt }], + messages: [{ role: 'assistant', content: req.body.userMessage }], model: 'gpt-3.5-turbo-0125', }); From 4da035ed21cef8f6ed91aec433d8ed55b4073559 Mon Sep 17 00:00:00 2001 From: Shun Miyazawa Date: Tue, 27 Aug 2024 18:14:53 +0000 Subject: [PATCH 095/490] impl RagPrompt --- .../components/PageControls/PageControls.tsx | 6 +- .../PageControls/RagPromptButton.module.scss | 12 ++++ .../PageControls/RagPromptButton.tsx | 28 +++++++++ .../components/RagPrompt/RagPromptModal.tsx | 59 +++++++++++++++++++ .../app/src/components/Layout/BasicLayout.tsx | 3 +- apps/app/src/stores/rag-prompt.ts | 26 ++++++++ 6 files changed, 132 insertions(+), 2 deletions(-) create mode 100644 apps/app/src/client/components/PageControls/RagPromptButton.module.scss create mode 100644 apps/app/src/client/components/PageControls/RagPromptButton.tsx create mode 100644 apps/app/src/client/components/RagPrompt/RagPromptModal.tsx create mode 100644 apps/app/src/stores/rag-prompt.ts diff --git a/apps/app/src/client/components/PageControls/PageControls.tsx b/apps/app/src/client/components/PageControls/PageControls.tsx index e895cb7fad9..50e35d584b0 100644 --- a/apps/app/src/client/components/PageControls/PageControls.tsx +++ b/apps/app/src/client/components/PageControls/PageControls.tsx @@ -36,6 +36,7 @@ import { import { BookmarkButtons } from './BookmarkButtons'; import LikeButtons from './LikeButtons'; +import RagPromptButton from './RagPromptButton'; import SearchButton from './SearchButton'; import SeenUserInfo from './SeenUserInfo'; import SubscribeButton from './SubscribeButton'; @@ -282,7 +283,10 @@ const PageControlsSubstance = (props: PageControlsSubstanceProps): JSX.Element = return (
                  { isViewMode && isDeviceLargerThanMd && !isSearchPage && !isSearchPage && ( - + <> + + + )} {revisionId != null && !isViewMode && _isIPageInfoForOperation && ( diff --git a/apps/app/src/client/components/PageControls/RagPromptButton.module.scss b/apps/app/src/client/components/PageControls/RagPromptButton.module.scss new file mode 100644 index 00000000000..97bf2fc077e --- /dev/null +++ b/apps/app/src/client/components/PageControls/RagPromptButton.module.scss @@ -0,0 +1,12 @@ +@use '@growi/core-styles/scss/bootstrap/init' as bs; +@use '@growi/ui/scss/atoms/btn-muted'; +@use './button-styles'; + +.btn-rag-prompt :global { + @extend %btn-basis; +} + +// == Colors +.btn-rag-prompt { + @include btn-muted.colorize(bs.$success); +} diff --git a/apps/app/src/client/components/PageControls/RagPromptButton.tsx b/apps/app/src/client/components/PageControls/RagPromptButton.tsx new file mode 100644 index 00000000000..0d19c92c430 --- /dev/null +++ b/apps/app/src/client/components/PageControls/RagPromptButton.tsx @@ -0,0 +1,28 @@ +import React, { useCallback } from 'react'; + +import { useRagPromptModal } from '~/stores/rag-prompt'; + +import styles from './RagPromptButton.module.scss'; + +const RagPromptButton = (): JSX.Element => { + + const { open: openRagPromptModal } = useRagPromptModal(); + + const ragPromptButtonClickHandler = useCallback(() => { + openRagPromptModal(); + }, [openRagPromptModal]); + + + return ( + + ); +}; + +export default RagPromptButton; diff --git a/apps/app/src/client/components/RagPrompt/RagPromptModal.tsx b/apps/app/src/client/components/RagPrompt/RagPromptModal.tsx new file mode 100644 index 00000000000..c3fa8f95844 --- /dev/null +++ b/apps/app/src/client/components/RagPrompt/RagPromptModal.tsx @@ -0,0 +1,59 @@ + +import React, { useState } from 'react'; + +import { Modal, ModalBody, ModalHeader } from 'reactstrap'; + +import { apiv3Post } from '~/client/util/apiv3-client'; +import { useRagPromptModal } from '~/stores/rag-prompt'; + +const RagPromptModal = (): JSX.Element => { + const [userMessage, setUserMessage] = useState(''); + const [assistantMessage, setAssistantMessage] = useState(''); + + const { data: ragPromptModalData, close: closeRagPromptModal } = useRagPromptModal(); + + const onClickSubmitUserMessageHandler = async() => { + try { + const res = await apiv3Post('/openai/chat', { userMessage }); + setAssistantMessage(res.data.assistantMessage); + } + catch (err) { + // + } + }; + + return ( + + + + Chat + + +

                  + { assistantMessage } +

                  + +
                  + setUserMessage(e.target.value)} + /> + +
                  +
                  +
                  + ); +}; + +export default RagPromptModal; diff --git a/apps/app/src/components/Layout/BasicLayout.tsx b/apps/app/src/components/Layout/BasicLayout.tsx index 6fd416b58ca..f7a13307643 100644 --- a/apps/app/src/components/Layout/BasicLayout.tsx +++ b/apps/app/src/components/Layout/BasicLayout.tsx @@ -34,7 +34,7 @@ const DeleteBookmarkFolderModal = dynamic( () => import('~/client/components/DeleteBookmarkFolderModal').then(mod => mod.DeleteBookmarkFolderModal), { ssr: false }, ); const SearchModal = dynamic(() => import('../../features/search/client/components/SearchModal'), { ssr: false }); - +const RagPromptModal = dynamic(() => import('~/client/components/RagPrompt/RagPromptModal'), { ssr: false }); type Props = { children?: ReactNode @@ -67,6 +67,7 @@ export const BasicLayout = ({ children, className }: Props): JSX.Element => { + diff --git a/apps/app/src/stores/rag-prompt.ts b/apps/app/src/stores/rag-prompt.ts new file mode 100644 index 00000000000..040fddfdf1b --- /dev/null +++ b/apps/app/src/stores/rag-prompt.ts @@ -0,0 +1,26 @@ +import { useCallback } from 'react'; + +import { useSWRStatic } from '@growi/core/dist/swr'; +import type { SWRResponse } from 'swr'; + + +type RagPromptMoldalStatus = { + isOpened: boolean, +} + +type RagPromptUtils = { + open(): void + close(): void +} +export const useRagPromptModal = (status?: RagPromptMoldalStatus): SWRResponse & RagPromptUtils => { + const initialStatus = { isOpened: false }; + const swrResponse = useSWRStatic('RagPromptModal', status, { fallbackData: initialStatus }); + + return { + ...swrResponse, + open: useCallback(() => { + swrResponse.mutate({ isOpened: true }); + }, [swrResponse]), + close: useCallback(() => swrResponse.mutate({ isOpened: false }), [swrResponse]), + }; +}; From 1d16f5999881e426974fbca87ff07ab511716bf6 Mon Sep 17 00:00:00 2001 From: Yuki Takei Date: Wed, 28 Aug 2024 01:20:52 +0000 Subject: [PATCH 096/490] implement appendVectorScore --- apps/app/src/server/routes/search.ts | 8 +++---- .../service/search-delegator/elasticsearch.ts | 23 ++++++++++++++++++- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/apps/app/src/server/routes/search.ts b/apps/app/src/server/routes/search.ts index 1c5a7a171e4..aa75115140f 100644 --- a/apps/app/src/server/routes/search.ts +++ b/apps/app/src/server/routes/search.ts @@ -109,7 +109,7 @@ module.exports = function(crowi, app) { api.search = async function(req, res) { const user = req.user; const { - q = null, nq = null, type = null, sort = null, order = null, + q = null, nq = null, type = null, sort = null, order = null, vector = null, } = req.query; let paginateOpts; @@ -135,15 +135,15 @@ module.exports = function(crowi, app) { ] : null; const searchOpts = { - ...paginateOpts, type, sort, order, + ...paginateOpts, type, sort, order, vector, }; let searchResult; let delegatorName; try { - const keyword = decodeURIComponent(q); + const query = decodeURIComponent(q); const nqName = nq ?? decodeURIComponent(nq); - [searchResult, delegatorName] = await searchService.searchKeyword(keyword, nqName, user, userGroups, searchOpts); + [searchResult, delegatorName] = await searchService.searchKeyword(query, nqName, user, userGroups, searchOpts); } catch (err) { logger.error('Failed to search', err); diff --git a/apps/app/src/server/service/search-delegator/elasticsearch.ts b/apps/app/src/server/service/search-delegator/elasticsearch.ts index fc2d5ab2b9f..b972c71b3a2 100644 --- a/apps/app/src/server/service/search-delegator/elasticsearch.ts +++ b/apps/app/src/server/service/search-delegator/elasticsearch.ts @@ -847,6 +847,20 @@ class ElasticsearchDelegator implements SearchDelegator { + const queryVector = (await openaiService.embed(username, queryString))[0].embedding; + + query.body.query = { + script_score: { + query: { ...query.body.query }, + script: { + source: "cosineSimilarity(params.query_vector, doc['body_embedded']) + 1.0", + params: { query_vector: queryVector }, + }, + }, + }; + } + appendHighlight(query) { query.body.highlight = { fragmenter: 'simple', @@ -877,6 +891,7 @@ class ElasticsearchDelegator implements SearchDelegator Date: Wed, 28 Aug 2024 02:05:29 +0000 Subject: [PATCH 097/490] rag-prompt -> rag-search --- .../components/PageControls/PageControls.tsx | 4 +-- .../PageControls/RagPromptButton.tsx | 28 ------------------- ...odule.scss => RagSearchButton.module.scss} | 4 +-- .../PageControls/RagSearchButton.tsx | 28 +++++++++++++++++++ .../RagSearchModal.tsx} | 10 +++---- .../app/src/components/Layout/BasicLayout.tsx | 4 +-- .../stores/{rag-prompt.ts => rag-search.ts} | 8 +++--- 7 files changed, 43 insertions(+), 43 deletions(-) delete mode 100644 apps/app/src/client/components/PageControls/RagPromptButton.tsx rename apps/app/src/client/components/PageControls/{RagPromptButton.module.scss => RagSearchButton.module.scss} (82%) create mode 100644 apps/app/src/client/components/PageControls/RagSearchButton.tsx rename apps/app/src/client/components/{RagPrompt/RagPromptModal.tsx => RagSearch/RagSearchModal.tsx} (80%) rename apps/app/src/stores/{rag-prompt.ts => rag-search.ts} (60%) diff --git a/apps/app/src/client/components/PageControls/PageControls.tsx b/apps/app/src/client/components/PageControls/PageControls.tsx index 50e35d584b0..498576816bc 100644 --- a/apps/app/src/client/components/PageControls/PageControls.tsx +++ b/apps/app/src/client/components/PageControls/PageControls.tsx @@ -36,7 +36,7 @@ import { import { BookmarkButtons } from './BookmarkButtons'; import LikeButtons from './LikeButtons'; -import RagPromptButton from './RagPromptButton'; +import RagSearchButton from './RagSearchButton'; import SearchButton from './SearchButton'; import SeenUserInfo from './SeenUserInfo'; import SubscribeButton from './SubscribeButton'; @@ -285,7 +285,7 @@ const PageControlsSubstance = (props: PageControlsSubstanceProps): JSX.Element = { isViewMode && isDeviceLargerThanMd && !isSearchPage && !isSearchPage && ( <> - + )} diff --git a/apps/app/src/client/components/PageControls/RagPromptButton.tsx b/apps/app/src/client/components/PageControls/RagPromptButton.tsx deleted file mode 100644 index 0d19c92c430..00000000000 --- a/apps/app/src/client/components/PageControls/RagPromptButton.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import React, { useCallback } from 'react'; - -import { useRagPromptModal } from '~/stores/rag-prompt'; - -import styles from './RagPromptButton.module.scss'; - -const RagPromptButton = (): JSX.Element => { - - const { open: openRagPromptModal } = useRagPromptModal(); - - const ragPromptButtonClickHandler = useCallback(() => { - openRagPromptModal(); - }, [openRagPromptModal]); - - - return ( - - ); -}; - -export default RagPromptButton; diff --git a/apps/app/src/client/components/PageControls/RagPromptButton.module.scss b/apps/app/src/client/components/PageControls/RagSearchButton.module.scss similarity index 82% rename from apps/app/src/client/components/PageControls/RagPromptButton.module.scss rename to apps/app/src/client/components/PageControls/RagSearchButton.module.scss index 97bf2fc077e..e34b17ef216 100644 --- a/apps/app/src/client/components/PageControls/RagPromptButton.module.scss +++ b/apps/app/src/client/components/PageControls/RagSearchButton.module.scss @@ -2,11 +2,11 @@ @use '@growi/ui/scss/atoms/btn-muted'; @use './button-styles'; -.btn-rag-prompt :global { +.btn-rag-search :global { @extend %btn-basis; } // == Colors -.btn-rag-prompt { +.btn-rag-search { @include btn-muted.colorize(bs.$success); } diff --git a/apps/app/src/client/components/PageControls/RagSearchButton.tsx b/apps/app/src/client/components/PageControls/RagSearchButton.tsx new file mode 100644 index 00000000000..8a2ae4f1063 --- /dev/null +++ b/apps/app/src/client/components/PageControls/RagSearchButton.tsx @@ -0,0 +1,28 @@ +import React, { useCallback } from 'react'; + +import { useRagSearchModal } from '~/stores/rag-search'; + +import styles from './RagSearchButton.module.scss'; + +const RagSearchButton = (): JSX.Element => { + + const { open: openRagSearchModal } = useRagSearchModal(); + + const ragSearchButtonClickHandler = useCallback(() => { + openRagSearchModal(); + }, [openRagSearchModal]); + + + return ( + + ); +}; + +export default RagSearchButton; diff --git a/apps/app/src/client/components/RagPrompt/RagPromptModal.tsx b/apps/app/src/client/components/RagSearch/RagSearchModal.tsx similarity index 80% rename from apps/app/src/client/components/RagPrompt/RagPromptModal.tsx rename to apps/app/src/client/components/RagSearch/RagSearchModal.tsx index c3fa8f95844..721ee01c852 100644 --- a/apps/app/src/client/components/RagPrompt/RagPromptModal.tsx +++ b/apps/app/src/client/components/RagSearch/RagSearchModal.tsx @@ -4,13 +4,13 @@ import React, { useState } from 'react'; import { Modal, ModalBody, ModalHeader } from 'reactstrap'; import { apiv3Post } from '~/client/util/apiv3-client'; -import { useRagPromptModal } from '~/stores/rag-prompt'; +import { useRagSearchModal } from '~/stores/rag-search'; -const RagPromptModal = (): JSX.Element => { +const RagSearchModal = (): JSX.Element => { const [userMessage, setUserMessage] = useState(''); const [assistantMessage, setAssistantMessage] = useState(''); - const { data: ragPromptModalData, close: closeRagPromptModal } = useRagPromptModal(); + const { data: ragSearchModalData, close: closeRagSearchModal } = useRagSearchModal(); const onClickSubmitUserMessageHandler = async() => { try { @@ -23,7 +23,7 @@ const RagPromptModal = (): JSX.Element => { }; return ( - + Chat @@ -56,4 +56,4 @@ const RagPromptModal = (): JSX.Element => { ); }; -export default RagPromptModal; +export default RagSearchModal; diff --git a/apps/app/src/components/Layout/BasicLayout.tsx b/apps/app/src/components/Layout/BasicLayout.tsx index f7a13307643..556d868adb1 100644 --- a/apps/app/src/components/Layout/BasicLayout.tsx +++ b/apps/app/src/components/Layout/BasicLayout.tsx @@ -34,7 +34,7 @@ const DeleteBookmarkFolderModal = dynamic( () => import('~/client/components/DeleteBookmarkFolderModal').then(mod => mod.DeleteBookmarkFolderModal), { ssr: false }, ); const SearchModal = dynamic(() => import('../../features/search/client/components/SearchModal'), { ssr: false }); -const RagPromptModal = dynamic(() => import('~/client/components/RagPrompt/RagPromptModal'), { ssr: false }); +const RagSearchModal = dynamic(() => import('~/client/components/RagSearch/RagSearchModal'), { ssr: false }); type Props = { children?: ReactNode @@ -67,7 +67,7 @@ export const BasicLayout = ({ children, className }: Props): JSX.Element => { - + diff --git a/apps/app/src/stores/rag-prompt.ts b/apps/app/src/stores/rag-search.ts similarity index 60% rename from apps/app/src/stores/rag-prompt.ts rename to apps/app/src/stores/rag-search.ts index 040fddfdf1b..be1ae094579 100644 --- a/apps/app/src/stores/rag-prompt.ts +++ b/apps/app/src/stores/rag-search.ts @@ -4,17 +4,17 @@ import { useSWRStatic } from '@growi/core/dist/swr'; import type { SWRResponse } from 'swr'; -type RagPromptMoldalStatus = { +type RagSearchMoldalStatus = { isOpened: boolean, } -type RagPromptUtils = { +type RagSearchUtils = { open(): void close(): void } -export const useRagPromptModal = (status?: RagPromptMoldalStatus): SWRResponse & RagPromptUtils => { +export const useRagSearchModal = (status?: RagSearchMoldalStatus): SWRResponse & RagSearchUtils => { const initialStatus = { isOpened: false }; - const swrResponse = useSWRStatic('RagPromptModal', status, { fallbackData: initialStatus }); + const swrResponse = useSWRStatic('RagSearchModal', status, { fallbackData: initialStatus }); return { ...swrResponse, From 4303d0167f0790b416822f4d7c39d87420abf7b6 Mon Sep 17 00:00:00 2001 From: Yuki Takei Date: Wed, 28 Aug 2024 04:22:30 +0000 Subject: [PATCH 098/490] omit unused components --- .../client/components/SearchForm.module.scss | 36 ----- apps/app/src/client/components/SearchForm.tsx | 143 ------------------ 2 files changed, 179 deletions(-) delete mode 100644 apps/app/src/client/components/SearchForm.module.scss delete mode 100644 apps/app/src/client/components/SearchForm.tsx diff --git a/apps/app/src/client/components/SearchForm.module.scss b/apps/app/src/client/components/SearchForm.module.scss deleted file mode 100644 index 335d5bae86d..00000000000 --- a/apps/app/src/client/components/SearchForm.module.scss +++ /dev/null @@ -1,36 +0,0 @@ -@use '@growi/core-styles/scss/bootstrap/init' as bs; - -.grw-search-table { - caption { - display: table-header-group; - } -} - -@include bs.media-breakpoint-down(sm) { - .grw-search-table { - th { - text-align: right; - } - - td { - overflow-wrap: anywhere; - white-space: normal !important; - } - - @include bs.media-breakpoint-down(xs) { - th, - td { - display: block; - } - - th { - text-align: left; - } - - td { - padding-top: 0 !important; - border-top: none !important; - } - } - } -} diff --git a/apps/app/src/client/components/SearchForm.tsx b/apps/app/src/client/components/SearchForm.tsx deleted file mode 100644 index 099cf333902..00000000000 --- a/apps/app/src/client/components/SearchForm.tsx +++ /dev/null @@ -1,143 +0,0 @@ -import React, { - FC, forwardRef, ForwardRefRenderFunction, useImperativeHandle, - useRef, useState, -} from 'react'; - -import { useTranslation } from 'next-i18next'; - -import { IFocusable } from '~/client/interfaces/focusable'; -import { TypeaheadProps } from '~/client/interfaces/react-bootstrap-typeahead'; -import { IPageWithSearchMeta } from '~/interfaces/search'; - -import SearchTypeahead from './SearchTypeahead'; - -import styles from './SearchForm.module.scss'; - - -type SearchFormHelpProps = { - isReachable: boolean, -} - -const SearchFormHelp: FC = React.memo((props: SearchFormHelpProps) => { - const { t } = useTranslation(); - - const { isReachable } = props; - - if (!isReachable) { - return ( - <> -
                  Error occured on Search Service
                  - Try to reconnect from management page. - - ); - } - - return ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                  -
                  search{ t('search_help.title') }
                  -
                  - word1 word2

                  - ({ t('search_help.and.syntax help') }) -
                  { t('search_help.and.desc', { word1: 'word1', word2: 'word2' }) }
                  - "This is GROWI"

                  - ({ t('search_help.phrase.syntax help') }) -
                  { t('search_help.phrase.desc', { phrase: 'This is GROWI' }) }
                  -keyword
                  { t('search_help.exclude.desc', { word: 'keyword' }) }
                  prefix:/user/
                  { t('search_help.prefix.desc', { path: '/user/' }) }
                  -prefix:/user/
                  { t('search_help.exclude_prefix.desc', { path: '/user/' }) }
                  tag:wiki
                  { t('search_help.tag.desc', { tag: 'wiki' }) }
                  -tag:wiki
                  { t('search_help.exclude_tag.desc', { tag: 'wiki' }) }
                  - ); -}); - -SearchFormHelp.displayName = 'SearchFormHelp'; - - -type Props = TypeaheadProps & { - isSearchServiceReachable: boolean, - - keywordOnInit?: string, - disableIncrementalSearch?: boolean, - onChange?: (data: IPageWithSearchMeta[]) => void, - onSubmit?: (input: string) => void, -}; - - -const SearchForm: ForwardRefRenderFunction = (props: Props, ref) => { - const { t } = useTranslation(); - const { - isSearchServiceReachable, - keywordOnInit, - disableIncrementalSearch, - dropup, onChange, onBlur, onFocus, onSubmit, onInputChange, - } = props; - - const [searchError, setSearchError] = useState(null); - - const searchTyheaheadRef = useRef(null); - - // publish focus() - useImperativeHandle(ref, () => ({ - focus() { - const instance = searchTyheaheadRef?.current; - if (instance != null) { - instance.focus(); - } - }, - })); - - const placeholder = isSearchServiceReachable - ? 'Search ...' - : 'Error on Search Service'; - - const emptyLabel = (searchError != null) - ? 'Error on searching.' - : t('search.search page bodies'); - - return ( - setSearchError(err)} - onBlur={onBlur} - onFocus={onFocus} - keywordOnInit={keywordOnInit} - disableIncrementalSearch={disableIncrementalSearch} - helpElement={} - /> - ); -}; - -export default forwardRef(SearchForm); From c7dea253e543d78c5ef85b30d175a1e85612b172 Mon Sep 17 00:00:00 2001 From: Yuki Takei Date: Wed, 28 Aug 2024 04:22:30 +0000 Subject: [PATCH 099/490] support `@ai` mode --- .../search/client/components/SearchModal.tsx | 14 ++++++++++++-- apps/app/src/server/service/search.ts | 8 +++++++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/apps/app/src/features/search/client/components/SearchModal.tsx b/apps/app/src/features/search/client/components/SearchModal.tsx index 9d2bf8e1c29..edb2544b80f 100644 --- a/apps/app/src/features/search/client/components/SearchModal.tsx +++ b/apps/app/src/features/search/client/components/SearchModal.tsx @@ -16,7 +16,9 @@ import { SearchMethodMenuItem } from './SearchMethodMenuItem'; import { SearchResultMenuItem } from './SearchResultMenuItem'; const SearchModal = (): JSX.Element => { + const [searchKeyword, setSearchKeyword] = useState(''); + const [isMenthionedToAi, setMenthionedToAi] = useState(false); const { data: searchModalData, close: closeSearchModal } = useSearchModal(); @@ -32,7 +34,9 @@ const SearchModal = (): JSX.Element => { }, [closeSearchModal, router]); const submitHandler = useCallback(() => { - router.push(`/_search?q=${searchKeyword}`); + const url = new URL('_search', 'http://example.com'); + url.searchParams.set('q', searchKeyword); + router.push(url.pathname + url.search); closeSearchModal(); }, [closeSearchModal, router, searchKeyword]); @@ -60,6 +64,10 @@ const SearchModal = (): JSX.Element => { } }, [searchModalData?.isOpened, searchModalData?.searchKeyword]); + useEffect(() => { + setMenthionedToAi(searchKeyword.includes('@ai')); + }, [searchKeyword]); + return ( @@ -77,7 +85,9 @@ const SearchModal = (): JSX.Element => { }) => (
                  - search + + {isMenthionedToAi ? 'psychology' : 'search'} + { let queryString = _queryString.trim(); - queryString = queryString.replace(/\s+/g, ' '); + queryString = queryString + .replace(/\s+@ai\s+/g, ' ') // omit '@ai' keyword + .replace(/\s+/g, ' '); return queryString; }; @@ -300,6 +302,10 @@ class SearchService implements SearchQueryParser, SearchResolver { throw err; } + if (keyword.includes('@ai')) { + searchOpts.vector = true; + } + let delegator: SearchDelegator; let data: SearchableData; // resolve From 84029581e12007687d1923ab76755e3669cc8212 Mon Sep 17 00:00:00 2001 From: Yuki Takei Date: Wed, 28 Aug 2024 08:53:08 +0000 Subject: [PATCH 100/490] add an utility --- .../features/search/client/components/SearchModal.tsx | 9 ++++++--- apps/app/src/features/search/utils/ai.ts | 7 +++++++ apps/app/src/server/service/search.ts | 6 +++--- 3 files changed, 16 insertions(+), 6 deletions(-) create mode 100644 apps/app/src/features/search/utils/ai.ts diff --git a/apps/app/src/features/search/client/components/SearchModal.tsx b/apps/app/src/features/search/client/components/SearchModal.tsx index edb2544b80f..92b66e1d696 100644 --- a/apps/app/src/features/search/client/components/SearchModal.tsx +++ b/apps/app/src/features/search/client/components/SearchModal.tsx @@ -7,6 +7,7 @@ import Downshift, { type DownshiftState, type StateChangeOptions } from 'downshi import { useRouter } from 'next/router'; import { Modal, ModalBody } from 'reactstrap'; +import { isIncludeAiMenthion, removeAiMenthion } from '../../utils/ai'; import type { DownshiftItem } from '../interfaces/downshift'; import { useSearchModal } from '../stores/search'; @@ -65,9 +66,11 @@ const SearchModal = (): JSX.Element => { }, [searchModalData?.isOpened, searchModalData?.searchKeyword]); useEffect(() => { - setMenthionedToAi(searchKeyword.includes('@ai')); + setMenthionedToAi(isIncludeAiMenthion(searchKeyword)); }, [searchKeyword]); + const searchKeywordWithoutAi = removeAiMenthion(searchKeyword); + return ( @@ -107,12 +110,12 @@ const SearchModal = (): JSX.Element => {
                  diff --git a/apps/app/src/features/search/utils/ai.ts b/apps/app/src/features/search/utils/ai.ts new file mode 100644 index 00000000000..a31ccbc648a --- /dev/null +++ b/apps/app/src/features/search/utils/ai.ts @@ -0,0 +1,7 @@ +export const isIncludeAiMenthion = (keyword: string): boolean => { + return keyword.match(/(^|\s)@ai(\s|$)/) != null; +}; + +export const removeAiMenthion = (keyword: string): string => { + return keyword.replaceAll(/(^|\s)@ai(\s|$)/g, ''); +}; diff --git a/apps/app/src/server/service/search.ts b/apps/app/src/server/service/search.ts index 3a9ef6859ea..9c564c60b27 100644 --- a/apps/app/src/server/service/search.ts +++ b/apps/app/src/server/service/search.ts @@ -4,6 +4,7 @@ import mongoose from 'mongoose'; import { FilterXSS } from 'xss'; import { CommentEvent, commentEvent } from '~/features/comment/server'; +import { isIncludeAiMenthion, removeAiMenthion } from '~/features/search/utils/ai'; import { SearchDelegatorName } from '~/interfaces/named-query'; import type { IFormattedSearchResult, IPageWithSearchMeta, ISearchResult } from '~/interfaces/search'; import loggerFactory from '~/utils/logger'; @@ -39,8 +40,7 @@ const filterXss = new FilterXSS(filterXssOptions); const normalizeQueryString = (_queryString: string): string => { let queryString = _queryString.trim(); - queryString = queryString - .replace(/\s+@ai\s+/g, ' ') // omit '@ai' keyword + queryString = removeAiMenthion(queryString) .replace(/\s+/g, ' '); return queryString; @@ -302,7 +302,7 @@ class SearchService implements SearchQueryParser, SearchResolver { throw err; } - if (keyword.includes('@ai')) { + if (isIncludeAiMenthion(keyword)) { searchOpts.vector = true; } From b2b807a597479e66509343b75f5d538cc5ea87b9 Mon Sep 17 00:00:00 2001 From: Yuki Takei Date: Wed, 28 Aug 2024 08:53:15 +0000 Subject: [PATCH 101/490] clean import lines --- apps/app/src/stores/search.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/app/src/stores/search.tsx b/apps/app/src/stores/search.tsx index 23886ec4c32..91935290ecf 100644 --- a/apps/app/src/stores/search.tsx +++ b/apps/app/src/stores/search.tsx @@ -1,7 +1,9 @@ -import useSWR, { mutate, SWRResponse } from 'swr'; +import type { SWRResponse } from 'swr'; +import useSWR, { mutate } from 'swr'; import { apiGet } from '~/client/util/apiv1-client'; -import { IFormattedSearchResult, SORT_AXIS, SORT_ORDER } from '~/interfaces/search'; +import type { IFormattedSearchResult } from '~/interfaces/search'; +import { SORT_AXIS, SORT_ORDER } from '~/interfaces/search'; export type ISearchConfigurations = { From aadb14d2278b73ef52d4a9ad0a6892a256488a0d Mon Sep 17 00:00:00 2001 From: Yuki Takei Date: Wed, 28 Aug 2024 09:17:48 +0000 Subject: [PATCH 102/490] improve searching by vector --- .../service/search-delegator/elasticsearch.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/app/src/server/service/search-delegator/elasticsearch.ts b/apps/app/src/server/service/search-delegator/elasticsearch.ts index b972c71b3a2..8bc7db5a118 100644 --- a/apps/app/src/server/service/search-delegator/elasticsearch.ts +++ b/apps/app/src/server/service/search-delegator/elasticsearch.ts @@ -854,7 +854,7 @@ class ElasticsearchDelegator implements SearchDelegator Date: Wed, 28 Aug 2024 12:01:45 +0000 Subject: [PATCH 103/490] refactor --- .../src/server/routes/apiv3/openai/chat.ts | 6 +-- .../service/openai/assistant/assistant.ts | 46 +++++++++++++++++++ .../server/service/openai/assistant/index.ts | 1 + apps/app/src/server/service/openai/client.ts | 5 ++ .../src/server/service/openai/embeddings.ts | 14 ++++++ apps/app/src/server/service/openai/index.ts | 3 +- apps/app/src/server/service/openai/openai.ts | 30 ------------ .../service/search-delegator/elasticsearch.ts | 6 +-- 8 files changed, 74 insertions(+), 37 deletions(-) create mode 100644 apps/app/src/server/service/openai/assistant/assistant.ts create mode 100644 apps/app/src/server/service/openai/assistant/index.ts create mode 100644 apps/app/src/server/service/openai/client.ts create mode 100644 apps/app/src/server/service/openai/embeddings.ts delete mode 100644 apps/app/src/server/service/openai/openai.ts diff --git a/apps/app/src/server/routes/apiv3/openai/chat.ts b/apps/app/src/server/routes/apiv3/openai/chat.ts index f72ba777b7d..38b562eeca3 100644 --- a/apps/app/src/server/routes/apiv3/openai/chat.ts +++ b/apps/app/src/server/routes/apiv3/openai/chat.ts @@ -3,7 +3,7 @@ import type { ValidationChain } from 'express-validator'; import { body } from 'express-validator'; import type Crowi from '~/server/crowi'; -import { openaiService } from '~/server/service/openai'; +import { openaiClient } from '~/server/service/openai'; import loggerFactory from '~/utils/logger'; import { apiV3FormValidator } from '../../../middlewares/apiv3-form-validator'; @@ -31,9 +31,9 @@ export const chatHandlersFactory: ChatHandlersFactory = (crowi) => { accessTokenParser, loginRequiredStrictly, validator, apiV3FormValidator, async(req: Req, res: ApiV3Response) => { try { - const chatCompletion = await openaiService.client.chat.completions.create({ + const chatCompletion = await openaiClient.chat.completions.create({ messages: [{ role: 'assistant', content: req.body.userMessage }], - model: 'gpt-3.5-turbo-0125', + model: 'gpt-4o', }); return res.apiv3({ assistantMessage: chatCompletion.choices[0].message.content }); diff --git a/apps/app/src/server/service/openai/assistant/assistant.ts b/apps/app/src/server/service/openai/assistant/assistant.ts new file mode 100644 index 00000000000..706766ee67d --- /dev/null +++ b/apps/app/src/server/service/openai/assistant/assistant.ts @@ -0,0 +1,46 @@ +import type OpenAI from 'openai'; + +import { configManager } from '../../config-manager'; +import { openaiClient } from '../client'; + +const findAssistantByName = async(assistantName: string): Promise => { + + // declare finder + const findAssistant = async(assistants: OpenAI.Beta.Assistants.AssistantsPage): Promise => { + const found = assistants.data.find(assistant => assistant.name === assistantName); + + if (found != null) { + return found; + } + + // recursively find assistant + if (assistants.hasNextPage()) { + return findAssistant(await assistants.getNextPage()); + } + }; + + const storedAssistants = await openaiClient.beta.assistants.list({ order: 'desc' }); + + return findAssistant(storedAssistants); +}; + +const getOrCreateAssistant = async(): Promise => { + + const appSiteUrl = configManager.getConfig('crowi', 'app:siteUrl'); + const assistantName = `GROWI OpenAI Assistant for ${appSiteUrl}`; + + const assistantOnRemote = await findAssistantByName(assistantName); + if (assistantOnRemote != null) { + // store + return assistantOnRemote; + } + + const newAssistant = await openaiClient.beta.assistants.create({ + name: assistantName, + model: 'gpt-4o', + }); + + return newAssistant; +}; + +export const defaultAssistant = getOrCreateAssistant(); diff --git a/apps/app/src/server/service/openai/assistant/index.ts b/apps/app/src/server/service/openai/assistant/index.ts new file mode 100644 index 00000000000..d2549ef13ab --- /dev/null +++ b/apps/app/src/server/service/openai/assistant/index.ts @@ -0,0 +1 @@ +export * from './assistant'; diff --git a/apps/app/src/server/service/openai/client.ts b/apps/app/src/server/service/openai/client.ts new file mode 100644 index 00000000000..928362bc3d3 --- /dev/null +++ b/apps/app/src/server/service/openai/client.ts @@ -0,0 +1,5 @@ +import OpenAI from 'openai'; + +export const openaiClient = new OpenAI({ + apiKey: process.env.OPENAI_API_KEY, // This is the default and can be omitted +}); diff --git a/apps/app/src/server/service/openai/embeddings.ts b/apps/app/src/server/service/openai/embeddings.ts new file mode 100644 index 00000000000..57406081bc2 --- /dev/null +++ b/apps/app/src/server/service/openai/embeddings.ts @@ -0,0 +1,14 @@ +import type { OpenAI } from 'openai'; + +import { openaiClient } from './client'; + +export const embed = async(username: string, input: string): Promise => { + const result = await openaiClient.embeddings.create({ + input, + model: 'text-embedding-3-large', + dimensions: Number(process.env.OPENAI_DIMENSIONS), + user: username, + }); + + return result.data; +}; diff --git a/apps/app/src/server/service/openai/index.ts b/apps/app/src/server/service/openai/index.ts index e919f9e4296..59c90e77b69 100644 --- a/apps/app/src/server/service/openai/index.ts +++ b/apps/app/src/server/service/openai/index.ts @@ -1 +1,2 @@ -export * from './openai'; +export * from './embeddings'; +export * from './client'; diff --git a/apps/app/src/server/service/openai/openai.ts b/apps/app/src/server/service/openai/openai.ts deleted file mode 100644 index 9a5e048cc8a..00000000000 --- a/apps/app/src/server/service/openai/openai.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { OpenAI } from 'openai'; - -export interface IOpenaiService { - embed: (username: string, input: string) => Promise; -} - -class OpenaiService implements IOpenaiService { - - client: OpenAI; - - constructor() { - this.client = new OpenAI({ - apiKey: process.env.OPENAI_API_KEY, // This is the default and can be omitted - }); - } - - async embed(username: string, input: string): Promise { - const result = await this.client.embeddings.create({ - input, - model: 'text-embedding-3-large', - dimensions: Number(process.env.OPENAI_DIMENSIONS), - user: username, - }); - - return result.data; - } - -} - -export const openaiService = new OpenaiService(); diff --git a/apps/app/src/server/service/search-delegator/elasticsearch.ts b/apps/app/src/server/service/search-delegator/elasticsearch.ts index 8bc7db5a118..bcb7b456e8e 100644 --- a/apps/app/src/server/service/search-delegator/elasticsearch.ts +++ b/apps/app/src/server/service/search-delegator/elasticsearch.ts @@ -20,7 +20,7 @@ import type { PageModel } from '../../models/page'; import { createBatchStream } from '../../util/batch-stream'; import { configManager } from '../config-manager'; import type { UpdateOrInsertPagesOpts } from '../interfaces/search'; -import { openaiService } from '../openai'; +import { embed } from '../openai'; import { aggregatePipelineToIndex } from './aggregate-to-index'; import type { AggregatedPage, BulkWriteBody, BulkWriteCommand } from './bulk-write'; @@ -485,7 +485,7 @@ class ElasticsearchDelegator implements SearchDelegator { - const queryVector = (await openaiService.embed(username, queryString))[0].embedding; + const queryVector = (await embed(username, queryString))[0].embedding; query.body.query = { script_score: { From 75b1e89f15b7074334f924a9499a43a3fe38a0be Mon Sep 17 00:00:00 2001 From: Yuki Takei Date: Wed, 28 Aug 2024 13:50:08 +0000 Subject: [PATCH 104/490] refactor --- .../service/openai/assistant/assistant.ts | 44 ++++++++++++++++--- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/apps/app/src/server/service/openai/assistant/assistant.ts b/apps/app/src/server/service/openai/assistant/assistant.ts index 706766ee67d..482ed42eebb 100644 --- a/apps/app/src/server/service/openai/assistant/assistant.ts +++ b/apps/app/src/server/service/openai/assistant/assistant.ts @@ -3,6 +3,15 @@ import type OpenAI from 'openai'; import { configManager } from '../../config-manager'; import { openaiClient } from '../client'; + +const AssistantType = { + SEARCH: 'Search', + CHAT: 'Chat', +} as const; + +type AssistantType = typeof AssistantType[keyof typeof AssistantType]; + + const findAssistantByName = async(assistantName: string): Promise => { // declare finder @@ -24,14 +33,12 @@ const findAssistantByName = async(assistantName: string): Promise => { - +const getOrCreateAssistant = async(type: AssistantType): Promise => { const appSiteUrl = configManager.getConfig('crowi', 'app:siteUrl'); - const assistantName = `GROWI OpenAI Assistant for ${appSiteUrl}`; + const assistantName = `GROWI ${type} Assistant for ${appSiteUrl}`; const assistantOnRemote = await findAssistantByName(assistantName); if (assistantOnRemote != null) { - // store return assistantOnRemote; } @@ -43,4 +50,31 @@ const getOrCreateAssistant = async(): Promise => { return newAssistant; }; -export const defaultAssistant = getOrCreateAssistant(); +let searchAssistant: OpenAI.Beta.Assistant | undefined; +export const getOrCreateSearchAssistant = async(): Promise => { + if (searchAssistant != null) { + return searchAssistant; + } + + searchAssistant = await getOrCreateAssistant(AssistantType.SEARCH); + openaiClient.beta.assistants.update(searchAssistant.id, { + instructions: process.env.OPENAI_SEARCH_ASSISTANT_INSTRUCTIONS, + }); + + return searchAssistant; +}; + + +let chatAssistant: OpenAI.Beta.Assistant | undefined; +export const getOrCreateChatAssistant = async(): Promise => { + if (chatAssistant != null) { + return chatAssistant; + } + + chatAssistant = await getOrCreateAssistant(AssistantType.SEARCH); + openaiClient.beta.assistants.update(chatAssistant.id, { + instructions: process.env.OPENAI_CHAT_ASSISTANT_INSTRUCTIONS, + }); + + return chatAssistant; +}; From 57ba31bdcdbf4c4ea282da2c929f4ada4dc7563a Mon Sep 17 00:00:00 2001 From: Shun Miyazawa Date: Wed, 28 Aug 2024 15:24:19 +0000 Subject: [PATCH 105/490] impl fileUpload --- .../src/server/service/openai/file-upload.ts | 24 +++++++++++++++++++ apps/app/src/server/service/openai/index.ts | 1 + .../service/search-delegator/elasticsearch.ts | 12 +++++++++- 3 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 apps/app/src/server/service/openai/file-upload.ts diff --git a/apps/app/src/server/service/openai/file-upload.ts b/apps/app/src/server/service/openai/file-upload.ts new file mode 100644 index 00000000000..b12643e365f --- /dev/null +++ b/apps/app/src/server/service/openai/file-upload.ts @@ -0,0 +1,24 @@ +import { Readable } from 'stream'; + +import type { IPageHasId } from '@growi/core'; +import { toFile } from 'openai'; + +import { openaiClient } from './client'; + +type PageToUpload = Omit & { revision: { body: string } }; + +export const fileUpload = async(pages: PageToUpload[]): Promise => { + const vectorStoreId = process.env.OPENAI_VECTOR_STORE_ID; + if (vectorStoreId == null) { + return; + } + + const filesPromise = pages.map(async(page) => { + const file = await toFile(Readable.from(page.revision.body), `${page._id}.md`); + return file; + }); + + const files = await Promise.all(filesPromise); + + await openaiClient.beta.vectorStores.fileBatches.uploadAndPoll(vectorStoreId, { files }); +}; diff --git a/apps/app/src/server/service/openai/index.ts b/apps/app/src/server/service/openai/index.ts index 59c90e77b69..b5feacf4f96 100644 --- a/apps/app/src/server/service/openai/index.ts +++ b/apps/app/src/server/service/openai/index.ts @@ -1,2 +1,3 @@ export * from './embeddings'; +export * from './file-upload'; export * from './client'; diff --git a/apps/app/src/server/service/search-delegator/elasticsearch.ts b/apps/app/src/server/service/search-delegator/elasticsearch.ts index bcb7b456e8e..02f700c1251 100644 --- a/apps/app/src/server/service/search-delegator/elasticsearch.ts +++ b/apps/app/src/server/service/search-delegator/elasticsearch.ts @@ -20,7 +20,7 @@ import type { PageModel } from '../../models/page'; import { createBatchStream } from '../../util/batch-stream'; import { configManager } from '../config-manager'; import type { UpdateOrInsertPagesOpts } from '../interfaces/search'; -import { embed } from '../openai'; +import { embed, fileUpload } from '../openai'; import { aggregatePipelineToIndex } from './aggregate-to-index'; import type { AggregatedPage, BulkWriteBody, BulkWriteCommand } from './bulk-write'; @@ -493,6 +493,15 @@ class ElasticsearchDelegator implements SearchDelegator Date: Wed, 28 Aug 2024 16:11:32 +0000 Subject: [PATCH 106/490] create keywordsForVector --- .../service/search-delegator/elasticsearch.ts | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/apps/app/src/server/service/search-delegator/elasticsearch.ts b/apps/app/src/server/service/search-delegator/elasticsearch.ts index 02f700c1251..d8c2f955f1b 100644 --- a/apps/app/src/server/service/search-delegator/elasticsearch.ts +++ b/apps/app/src/server/service/search-delegator/elasticsearch.ts @@ -20,7 +20,8 @@ import type { PageModel } from '../../models/page'; import { createBatchStream } from '../../util/batch-stream'; import { configManager } from '../config-manager'; import type { UpdateOrInsertPagesOpts } from '../interfaces/search'; -import { embed, fileUpload } from '../openai'; +import { embed, openaiClient, fileUpload } from '../openai'; +import { getOrCreateSearchAssistant } from '../openai/assistant'; import { aggregatePipelineToIndex } from './aggregate-to-index'; import type { AggregatedPage, BulkWriteBody, BulkWriteCommand } from './bulk-write'; @@ -858,6 +859,28 @@ class ElasticsearchDelegator implements SearchDelegator { + + const searchAssistant = await getOrCreateSearchAssistant(); + + // generate keywords for vector + const run = await openaiClient.beta.threads.createAndRunPoll({ + assistant_id: searchAssistant.id, + thread: { + messages: [ + { role: 'user', content: 'globalLang: "en_US", userLang: "ja_JP", user_input: "武井さんがジョインしたのはいつですか?"' }, + { role: 'assistant', content: '武井さん 武井 takei yuki ジョイン join 入社 加入 雇用開始 年月日 start date join employee' }, + { role: 'user', content: `globalLang: "en_US", userLang: "ja_JP", user_input: "${queryString}"` }, + ], + }, + }); + const messages = await openaiClient.beta.threads.messages.list(run.thread_id, { + limit: 1, + }); + const content = messages.data[0].content[0]; + const keywordsForVector = content.type === 'text' ? content.text.value : queryString; + + logger.debug('keywordsFor: ', keywordsForVector); + const queryVector = (await embed(username, queryString))[0].embedding; query.body.query = { From 4cf7b63f504d686a4fd037ea38de6b3a699876cf Mon Sep 17 00:00:00 2001 From: Shun Miyazawa Date: Wed, 28 Aug 2024 16:32:18 +0000 Subject: [PATCH 107/490] username as optional --- apps/app/src/server/service/openai/embeddings.ts | 2 +- apps/app/src/server/service/search-delegator/bulk-write.d.ts | 2 +- apps/app/src/server/service/search-delegator/elasticsearch.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/app/src/server/service/openai/embeddings.ts b/apps/app/src/server/service/openai/embeddings.ts index 57406081bc2..6ac6d655e3d 100644 --- a/apps/app/src/server/service/openai/embeddings.ts +++ b/apps/app/src/server/service/openai/embeddings.ts @@ -2,7 +2,7 @@ import type { OpenAI } from 'openai'; import { openaiClient } from './client'; -export const embed = async(username: string, input: string): Promise => { +export const embed = async(input: string, username?: string): Promise => { const result = await openaiClient.embeddings.create({ input, model: 'text-embedding-3-large', diff --git a/apps/app/src/server/service/search-delegator/bulk-write.d.ts b/apps/app/src/server/service/search-delegator/bulk-write.d.ts index 0bd189973d1..81e11fa7c73 100644 --- a/apps/app/src/server/service/search-delegator/bulk-write.d.ts +++ b/apps/app/src/server/service/search-delegator/bulk-write.d.ts @@ -15,7 +15,7 @@ export type AggregatedPage = Pick Date: Wed, 28 Aug 2024 16:34:51 +0000 Subject: [PATCH 108/490] fix types --- .../src/server/service/search-delegator/elasticsearch.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/app/src/server/service/search-delegator/elasticsearch.ts b/apps/app/src/server/service/search-delegator/elasticsearch.ts index 9a406c73967..67506580188 100644 --- a/apps/app/src/server/service/search-delegator/elasticsearch.ts +++ b/apps/app/src/server/service/search-delegator/elasticsearch.ts @@ -858,7 +858,7 @@ class ElasticsearchDelegator implements SearchDelegator { + async appendVectorScore(query, queryString: string, username?: string): Promise { const searchAssistant = await getOrCreateSearchAssistant(); @@ -881,7 +881,7 @@ class ElasticsearchDelegator implements SearchDelegator Date: Wed, 28 Aug 2024 16:35:10 +0000 Subject: [PATCH 109/490] hasing username --- apps/app/src/server/service/openai/embeddings.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/apps/app/src/server/service/openai/embeddings.ts b/apps/app/src/server/service/openai/embeddings.ts index 6ac6d655e3d..21c69fcb4ac 100644 --- a/apps/app/src/server/service/openai/embeddings.ts +++ b/apps/app/src/server/service/openai/embeddings.ts @@ -1,13 +1,25 @@ +import crypto from 'crypto'; + import type { OpenAI } from 'openai'; import { openaiClient } from './client'; + +const hasher = crypto.createHash('sha256'); + export const embed = async(input: string, username?: string): Promise => { + let user; + + if (username != null) { + hasher.update(username); + user = hasher.digest('hex'); + } + const result = await openaiClient.embeddings.create({ input, model: 'text-embedding-3-large', dimensions: Number(process.env.OPENAI_DIMENSIONS), - user: username, + user, }); return result.data; From e7b0313b064e1ec3c5a40d12c0ef37ca5d4def8b Mon Sep 17 00:00:00 2001 From: Yuki Takei Date: Wed, 28 Aug 2024 17:05:23 +0000 Subject: [PATCH 110/490] BugFix --- apps/app/src/server/service/openai/embeddings.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/app/src/server/service/openai/embeddings.ts b/apps/app/src/server/service/openai/embeddings.ts index 21c69fcb4ac..98e66d5cd9e 100644 --- a/apps/app/src/server/service/openai/embeddings.ts +++ b/apps/app/src/server/service/openai/embeddings.ts @@ -5,12 +5,11 @@ import type { OpenAI } from 'openai'; import { openaiClient } from './client'; -const hasher = crypto.createHash('sha256'); - export const embed = async(input: string, username?: string): Promise => { let user; if (username != null) { + const hasher = crypto.createHash('sha256'); hasher.update(username); user = hasher.digest('hex'); } From 06d8b320f5b45a572455463865f80c254e6738ee Mon Sep 17 00:00:00 2001 From: Yuki Takei Date: Wed, 28 Aug 2024 17:16:06 +0000 Subject: [PATCH 111/490] filter empty page --- apps/app/src/server/service/openai/file-upload.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/apps/app/src/server/service/openai/file-upload.ts b/apps/app/src/server/service/openai/file-upload.ts index b12643e365f..7a6e3703d54 100644 --- a/apps/app/src/server/service/openai/file-upload.ts +++ b/apps/app/src/server/service/openai/file-upload.ts @@ -13,10 +13,12 @@ export const fileUpload = async(pages: PageToUpload[]): Promise => { return; } - const filesPromise = pages.map(async(page) => { - const file = await toFile(Readable.from(page.revision.body), `${page._id}.md`); - return file; - }); + const filesPromise = pages + .filter(pages => pages.revision.body.length > 0) + .map(async(page) => { + const file = await toFile(Readable.from(page.revision.body), `${page._id}.md`); + return file; + }); const files = await Promise.all(filesPromise); From 7b866ef3a37245bc0e9edca1a9ff0582d34aaf92 Mon Sep 17 00:00:00 2001 From: Yuki Takei Date: Wed, 28 Aug 2024 17:18:49 +0000 Subject: [PATCH 112/490] return when files is empty --- apps/app/src/server/service/openai/file-upload.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/app/src/server/service/openai/file-upload.ts b/apps/app/src/server/service/openai/file-upload.ts index 7a6e3703d54..6185915480a 100644 --- a/apps/app/src/server/service/openai/file-upload.ts +++ b/apps/app/src/server/service/openai/file-upload.ts @@ -20,6 +20,10 @@ export const fileUpload = async(pages: PageToUpload[]): Promise => { return file; }); + if (filesPromise.length === 0) { + return; + } + const files = await Promise.all(filesPromise); await openaiClient.beta.vectorStores.fileBatches.uploadAndPoll(vectorStoreId, { files }); From 35e65b42b9cd1ce8d34c8919bf0db1f86fc0bc0b Mon Sep 17 00:00:00 2001 From: Shun Miyazawa Date: Wed, 28 Aug 2024 18:13:25 +0000 Subject: [PATCH 113/490] refactor --- .../src/server/routes/apiv3/openai/chat.ts | 35 ++++++++++++++++--- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/apps/app/src/server/routes/apiv3/openai/chat.ts b/apps/app/src/server/routes/apiv3/openai/chat.ts index 38b562eeca3..4764dde83b4 100644 --- a/apps/app/src/server/routes/apiv3/openai/chat.ts +++ b/apps/app/src/server/routes/apiv3/openai/chat.ts @@ -4,6 +4,7 @@ import { body } from 'express-validator'; import type Crowi from '~/server/crowi'; import { openaiClient } from '~/server/service/openai'; +import { getOrCreateSearchAssistant } from '~/server/service/openai/assistant'; import loggerFactory from '~/utils/logger'; import { apiV3FormValidator } from '../../../middlewares/apiv3-form-validator'; @@ -13,6 +14,7 @@ const logger = loggerFactory('growi:routes:apiv3:openai:chat'); type ReqBody = { userMessage: string, + threadId?: string, } type Req = Request @@ -25,18 +27,41 @@ export const chatHandlersFactory: ChatHandlersFactory = (crowi) => { const validator: ValidationChain[] = [ body('userMessage').isString().withMessage('userMessage must be string'), + body('threadId').optional().isString().withMessage('threadId must be string'), ]; return [ accessTokenParser, loginRequiredStrictly, validator, apiV3FormValidator, async(req: Req, res: ApiV3Response) => { + const assistantId = process.env.OPENAI_ASSISTANT_ID; + const vectorStoreId = process.env.OPENAI_VECTOR_STORE_ID; + if (assistantId == null || vectorStoreId == null) { + return res.apiv3Err('OPENAI_ASSISTANT_ID or OPENAI_VECTOR_STORE_ID is not setup', 503); + } + try { - const chatCompletion = await openaiClient.chat.completions.create({ - messages: [{ role: 'assistant', content: req.body.userMessage }], - model: 'gpt-4o', - }); + await getOrCreateSearchAssistant(); + + const threadId = req.body.threadId; + const thread = threadId == null + ? await openaiClient.beta.threads.create({ + messages: [{ role: 'assistant', content: req.body.userMessage }], + tool_resources: { + file_search: { + vector_store_ids: [vectorStoreId], + }, + }, + }) + : await openaiClient.beta.threads.retrieve(threadId); + + const run = await openaiClient.beta.threads.runs.createAndPoll(thread.id, { assistant_id: assistantId }); + + if (run.status === 'completed') { + const messages = await openaiClient.beta.threads.messages.list(run.thread_id); + return res.apiv3({ messages }); + } - return res.apiv3({ assistantMessage: chatCompletion.choices[0].message.content }); + return res.apiv3({}); } catch (err) { logger.error(err); From c0d922bad194562f23e86bef8b18c139f6d94985 Mon Sep 17 00:00:00 2001 From: Yuki Takei Date: Wed, 28 Aug 2024 19:10:39 +0000 Subject: [PATCH 114/490] use chat assistant --- apps/app/src/server/routes/apiv3/openai/chat.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/app/src/server/routes/apiv3/openai/chat.ts b/apps/app/src/server/routes/apiv3/openai/chat.ts index 4764dde83b4..faf6bfd0d21 100644 --- a/apps/app/src/server/routes/apiv3/openai/chat.ts +++ b/apps/app/src/server/routes/apiv3/openai/chat.ts @@ -4,7 +4,7 @@ import { body } from 'express-validator'; import type Crowi from '~/server/crowi'; import { openaiClient } from '~/server/service/openai'; -import { getOrCreateSearchAssistant } from '~/server/service/openai/assistant'; +import { getOrCreateChatAssistant } from '~/server/service/openai/assistant'; import loggerFactory from '~/utils/logger'; import { apiV3FormValidator } from '../../../middlewares/apiv3-form-validator'; @@ -40,7 +40,7 @@ export const chatHandlersFactory: ChatHandlersFactory = (crowi) => { } try { - await getOrCreateSearchAssistant(); + const assistant = await getOrCreateChatAssistant(); const threadId = req.body.threadId; const thread = threadId == null From a3922d285593c27b8eef5f605ded70079b60b45d Mon Sep 17 00:00:00 2001 From: Yuki Takei Date: Wed, 28 Aug 2024 19:10:49 +0000 Subject: [PATCH 115/490] BugFix --- apps/app/src/server/routes/apiv3/openai/chat.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/apps/app/src/server/routes/apiv3/openai/chat.ts b/apps/app/src/server/routes/apiv3/openai/chat.ts index faf6bfd0d21..3e52acd5846 100644 --- a/apps/app/src/server/routes/apiv3/openai/chat.ts +++ b/apps/app/src/server/routes/apiv3/openai/chat.ts @@ -33,10 +33,9 @@ export const chatHandlersFactory: ChatHandlersFactory = (crowi) => { return [ accessTokenParser, loginRequiredStrictly, validator, apiV3FormValidator, async(req: Req, res: ApiV3Response) => { - const assistantId = process.env.OPENAI_ASSISTANT_ID; const vectorStoreId = process.env.OPENAI_VECTOR_STORE_ID; - if (assistantId == null || vectorStoreId == null) { - return res.apiv3Err('OPENAI_ASSISTANT_ID or OPENAI_VECTOR_STORE_ID is not setup', 503); + if (vectorStoreId == null) { + return res.apiv3Err('OPENAI_VECTOR_STORE_ID is not setup', 503); } try { From 22b81f04838c4177a661574713023651316a06c5 Mon Sep 17 00:00:00 2001 From: Yuki Takei Date: Wed, 28 Aug 2024 19:11:07 +0000 Subject: [PATCH 116/490] modify listing order --- apps/app/src/server/routes/apiv3/openai/chat.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/app/src/server/routes/apiv3/openai/chat.ts b/apps/app/src/server/routes/apiv3/openai/chat.ts index 3e52acd5846..31c106f9c1e 100644 --- a/apps/app/src/server/routes/apiv3/openai/chat.ts +++ b/apps/app/src/server/routes/apiv3/openai/chat.ts @@ -53,10 +53,13 @@ export const chatHandlersFactory: ChatHandlersFactory = (crowi) => { }) : await openaiClient.beta.threads.retrieve(threadId); - const run = await openaiClient.beta.threads.runs.createAndPoll(thread.id, { assistant_id: assistantId }); + const run = await openaiClient.beta.threads.runs.createAndPoll(thread.id, { assistant_id: assistant.id }); if (run.status === 'completed') { - const messages = await openaiClient.beta.threads.messages.list(run.thread_id); + const messages = await openaiClient.beta.threads.messages.list(run.thread_id, { + limit: 1, + order: 'desc', + }); return res.apiv3({ messages }); } From 2edba00434b917aae4846686c4e98859859fa9c8 Mon Sep 17 00:00:00 2001 From: Yuki Takei Date: Wed, 28 Aug 2024 19:15:36 +0000 Subject: [PATCH 117/490] BugFix --- apps/app/src/server/service/openai/assistant/assistant.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/app/src/server/service/openai/assistant/assistant.ts b/apps/app/src/server/service/openai/assistant/assistant.ts index 482ed42eebb..b5063f395e5 100644 --- a/apps/app/src/server/service/openai/assistant/assistant.ts +++ b/apps/app/src/server/service/openai/assistant/assistant.ts @@ -71,7 +71,7 @@ export const getOrCreateChatAssistant = async(): Promise return chatAssistant; } - chatAssistant = await getOrCreateAssistant(AssistantType.SEARCH); + chatAssistant = await getOrCreateAssistant(AssistantType.CHAT); openaiClient.beta.assistants.update(chatAssistant.id, { instructions: process.env.OPENAI_CHAT_ASSISTANT_INSTRUCTIONS, }); From c1c15fd1d8e02092d42323da0094ed44445737fd Mon Sep 17 00:00:00 2001 From: Yuki Takei Date: Wed, 28 Aug 2024 19:42:11 +0000 Subject: [PATCH 118/490] add suffix to assistant name --- apps/app/src/server/service/openai/assistant/assistant.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/app/src/server/service/openai/assistant/assistant.ts b/apps/app/src/server/service/openai/assistant/assistant.ts index b5063f395e5..4550312498e 100644 --- a/apps/app/src/server/service/openai/assistant/assistant.ts +++ b/apps/app/src/server/service/openai/assistant/assistant.ts @@ -35,7 +35,7 @@ const findAssistantByName = async(assistantName: string): Promise => { const appSiteUrl = configManager.getConfig('crowi', 'app:siteUrl'); - const assistantName = `GROWI ${type} Assistant for ${appSiteUrl}`; + const assistantName = `GROWI ${type} Assistant for ${appSiteUrl} ${process.env.OPENAI_ASSISTANT_NAME_SUFFIX}`; const assistantOnRemote = await findAssistantByName(assistantName); if (assistantOnRemote != null) { From 3cea1edd2db0849baec3741e67e96feb4c34f4db Mon Sep 17 00:00:00 2001 From: Yuki Takei Date: Wed, 28 Aug 2024 19:59:36 +0000 Subject: [PATCH 119/490] enable fil_search tool in assistants --- apps/app/src/server/service/openai/assistant/assistant.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/app/src/server/service/openai/assistant/assistant.ts b/apps/app/src/server/service/openai/assistant/assistant.ts index 4550312498e..4b1d5f4c6bd 100644 --- a/apps/app/src/server/service/openai/assistant/assistant.ts +++ b/apps/app/src/server/service/openai/assistant/assistant.ts @@ -59,6 +59,7 @@ export const getOrCreateSearchAssistant = async(): Promise chatAssistant = await getOrCreateAssistant(AssistantType.CHAT); openaiClient.beta.assistants.update(chatAssistant.id, { instructions: process.env.OPENAI_CHAT_ASSISTANT_INSTRUCTIONS, + tools: [{ type: 'file_search' }], }); return chatAssistant; From ee45b1995d2e5701cc827fd07188c44875f1194d Mon Sep 17 00:00:00 2001 From: Shun Miyazawa Date: Wed, 28 Aug 2024 20:32:48 +0000 Subject: [PATCH 120/490] Assistant message results are displayed to the client --- .../components/RagSearch/RagSearchModal.tsx | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/apps/app/src/client/components/RagSearch/RagSearchModal.tsx b/apps/app/src/client/components/RagSearch/RagSearchModal.tsx index 721ee01c852..5f58da9b28c 100644 --- a/apps/app/src/client/components/RagSearch/RagSearchModal.tsx +++ b/apps/app/src/client/components/RagSearch/RagSearchModal.tsx @@ -1,4 +1,3 @@ - import React, { useState } from 'react'; import { Modal, ModalBody, ModalHeader } from 'reactstrap'; @@ -8,14 +7,23 @@ import { useRagSearchModal } from '~/stores/rag-search'; const RagSearchModal = (): JSX.Element => { const [userMessage, setUserMessage] = useState(''); - const [assistantMessage, setAssistantMessage] = useState(''); + const [assistantMessage, setAssistantMessage] = useState>([]); const { data: ragSearchModalData, close: closeRagSearchModal } = useRagSearchModal(); const onClickSubmitUserMessageHandler = async() => { try { const res = await apiv3Post('/openai/chat', { userMessage }); - setAssistantMessage(res.data.assistantMessage); + const assistantMessageData = res.data.messages; + + const messages: string[] = []; + for (const message of assistantMessageData.data.reverse()) { + messages.push(`${message.role} > ${message.content[0].text.value}`); + } + + setAssistantMessage(messages); + setUserMessage(''); + } catch (err) { // @@ -40,6 +48,7 @@ const RagSearchModal = (): JSX.Element => { placeholder="検索結果を生成するためのメッセージを入力してください" aria-label="Recipient's username" aria-describedby="button-addon2" + value={userMessage} onChange={e => setUserMessage(e.target.value)} /> +
                  + + +
                  +
                  +
                  +
                  +

                  {t('security_settings.session')}

                  From fd93ee85f5dc716e9c8e791431be96fe06c2303a Mon Sep 17 00:00:00 2001 From: WNomunomu Date: Thu, 12 Sep 2024 02:56:46 +0000 Subject: [PATCH 148/490] create excludeReadOnlyUserWhenCommentNotAllowed method --- .../middlewares/exclude-read-only-user.ts | 28 +++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/apps/app/src/server/middlewares/exclude-read-only-user.ts b/apps/app/src/server/middlewares/exclude-read-only-user.ts index 20197dfde9a..ca28f1305bc 100644 --- a/apps/app/src/server/middlewares/exclude-read-only-user.ts +++ b/apps/app/src/server/middlewares/exclude-read-only-user.ts @@ -1,9 +1,12 @@ import { ErrorV3 } from '@growi/core/dist/models'; -import { NextFunction, Response } from 'express'; -import { Request } from 'express-validator/src/base'; +import type { NextFunction, Response } from 'express'; +import type { Request } from 'express-validator/src/base'; import loggerFactory from '~/utils/logger'; +import { configManager } from '../service/config-manager'; + + const logger = loggerFactory('growi:middleware:exclude-read-only-user'); export const excludeReadOnlyUser = (req: Request, res: Response & { apiv3Err }, next: () => NextFunction): NextFunction => { @@ -23,3 +26,24 @@ export const excludeReadOnlyUser = (req: Request, res: Response & { apiv3Err }, return next(); }; + +const excludeReadOnlyUserWhenCommentNotAllowed = (req: Request, res: Response & { apiv3Err }, next: () => NextFunction): NextFunction => { + const user = req.user; + + const isRomUserAllowedToComment = configManager.getConfig('crowi', 'security:isRomUserAllowedToComment'); + + if (user == null) { + logger.warn('req.user is null'); + return next(); + } + + if (user.readOnly && !isRomUserAllowedToComment) { + const message = 'This user is read only user and comment is not allowed'; + logger.warn(message); + + return res.apiv3Err(new ErrorV3(message, 'validation_failed')); + } + + return next(); + +}; From bb1e5ae06fa7836652a655d5bc55188cff88a800 Mon Sep 17 00:00:00 2001 From: WNomunomu Date: Thu, 12 Sep 2024 02:57:52 +0000 Subject: [PATCH 149/490] add config for new settings --- .../client/services/AdminGeneralSecurityContainer.js | 11 +++++++++++ apps/app/src/server/models/config.ts | 1 + .../server/routes/apiv3/security-settings/index.js | 2 ++ 3 files changed, 14 insertions(+) diff --git a/apps/app/src/client/services/AdminGeneralSecurityContainer.js b/apps/app/src/client/services/AdminGeneralSecurityContainer.js index aefa9692d80..766aeeb2a1d 100644 --- a/apps/app/src/client/services/AdminGeneralSecurityContainer.js +++ b/apps/app/src/client/services/AdminGeneralSecurityContainer.js @@ -41,6 +41,7 @@ export default class AdminGeneralSecurityContainer extends Container { isShowRestrictedByGroup: false, isUsersHomepageDeletionEnabled: false, isForceDeleteUserHomepageOnUserDeletion: false, + isRomUserAllowedToComment: false, isLocalEnabled: false, isLdapEnabled: false, isSamlEnabled: false, @@ -79,6 +80,7 @@ export default class AdminGeneralSecurityContainer extends Container { isShowRestrictedByGroup: !generalSetting.hideRestrictedByGroup, isUsersHomepageDeletionEnabled: generalSetting.isUsersHomepageDeletionEnabled, isForceDeleteUserHomepageOnUserDeletion: generalSetting.isForceDeleteUserHomepageOnUserDeletion, + isRomUserAllowedToComment: generalSetting.isRomUserAllowedToComment, sessionMaxAge: generalSetting.sessionMaxAge, wikiMode: generalSetting.wikiMode, disableLinkSharing: shareLinkSetting.disableLinkSharing, @@ -220,6 +222,14 @@ export default class AdminGeneralSecurityContainer extends Container { this.setState({ isForceDeleteUserHomepageOnUserDeletion: !this.state.isForceDeleteUserHomepageOnUserDeletion }); } + /** + * Switch isForceDeleteUserHomepageOnUserDeletion + */ + switchIsRomUserAllowedToComment() { + this.setState({ isRomUserAllowedToComment: !this.state.isRomUserAllowedToComment }); + } + + /** * Update restrictGuestMode * @memberOf AdminGeneralSecuritySContainer @@ -239,6 +249,7 @@ export default class AdminGeneralSecurityContainer extends Container { hideRestrictedByOwner: !this.state.isShowRestrictedByOwner, isUsersHomepageDeletionEnabled: this.state.isUsersHomepageDeletionEnabled, isForceDeleteUserHomepageOnUserDeletion: this.state.isForceDeleteUserHomepageOnUserDeletion, + isRomUserAllowedToComment: this.state.isRomUserAllowedToComment, }; requestParams = await removeNullPropertyFromObject(requestParams); diff --git a/apps/app/src/server/models/config.ts b/apps/app/src/server/models/config.ts index eeb85f88d99..56fff940795 100644 --- a/apps/app/src/server/models/config.ts +++ b/apps/app/src/server/models/config.ts @@ -75,6 +75,7 @@ export const defaultCrowiConfigs: { [key: string]: any } = { 'security:disableLinkSharing' : false, 'security:user-homepage-deletion:isEnabled': false, 'security:user-homepage-deletion:isForceDeleteUserHomepageOnUserDeletion': false, + 'security:isRomUserAllowedToComment': false, 'security:passport-local:isEnabled' : true, 'security:passport-ldap:isEnabled' : false, diff --git a/apps/app/src/server/routes/apiv3/security-settings/index.js b/apps/app/src/server/routes/apiv3/security-settings/index.js index c0f12deb1c4..6d943e6c81b 100644 --- a/apps/app/src/server/routes/apiv3/security-settings/index.js +++ b/apps/app/src/server/routes/apiv3/security-settings/index.js @@ -637,6 +637,7 @@ module.exports = (crowi) => { 'security:user-homepage-deletion:isForceDeleteUserHomepageOnUserDeletion': req.body.isUsersHomepageDeletionEnabled ? req.body.isForceDeleteUserHomepageOnUserDeletion : false, + 'security:isRomUserAllowedToComment': req.body.isRomUserAllowedToComment, }; // Validate delete config @@ -670,6 +671,7 @@ module.exports = (crowi) => { isUsersHomepageDeletionEnabled: await configManager.getConfig('crowi', 'security:user-homepage-deletion:isEnabled'), isForceDeleteUserHomepageOnUserDeletion: await configManager.getConfig('crowi', 'security:user-homepage-deletion:isForceDeleteUserHomepageOnUserDeletion'), + isRomUserAllowedToComment: await configManager.getConfig('crowi', 'security:isRomUserAllowedToComment'), }; const parameters = { action: SupportedAction.ACTION_ADMIN_SECURITY_SETTINGS_UPDATE }; From d94dd260a62e5b92772b8c23ed6e9437c23a2428 Mon Sep 17 00:00:00 2001 From: WNomunomu Date: Thu, 12 Sep 2024 03:47:45 +0000 Subject: [PATCH 150/490] apply excludeReadOnlyUserWhenCommentNotAllowed method --- apps/app/src/server/routes/index.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/app/src/server/routes/index.js b/apps/app/src/server/routes/index.js index 050c16abeac..c8346bcf232 100644 --- a/apps/app/src/server/routes/index.js +++ b/apps/app/src/server/routes/index.js @@ -5,7 +5,7 @@ import { middlewareFactory as rateLimiterFactory } from '~/features/rate-limiter import { generateAddActivityMiddleware } from '../middlewares/add-activity'; import apiV1FormValidator from '../middlewares/apiv1-form-validator'; -import { excludeReadOnlyUser } from '../middlewares/exclude-read-only-user'; +import { excludeReadOnlyUser, excludeReadOnlyUserWhenCommentNotAllowed } from '../middlewares/exclude-read-only-user'; import injectResetOrderByTokenMiddleware from '../middlewares/inject-reset-order-by-token-middleware'; import injectUserRegistrationOrderByTokenMiddleware from '../middlewares/inject-user-registration-order-by-token-middleware'; import * as loginFormValidator from '../middlewares/login-form-validator'; @@ -131,9 +131,9 @@ module.exports = function(crowi, app) { apiV1Router.get('/tags.search' , accessTokenParser, loginRequired, tag.api.search); apiV1Router.post('/tags.update' , accessTokenParser, loginRequiredStrictly, excludeReadOnlyUser, addActivity, tag.api.update); apiV1Router.get('/comments.get' , accessTokenParser , loginRequired , comment.api.get); - apiV1Router.post('/comments.add' , comment.api.validators.add(), accessTokenParser , loginRequiredStrictly , excludeReadOnlyUser, addActivity, comment.api.add); - apiV1Router.post('/comments.update' , comment.api.validators.add(), accessTokenParser , loginRequiredStrictly , excludeReadOnlyUser, addActivity, comment.api.update); - apiV1Router.post('/comments.remove' , accessTokenParser , loginRequiredStrictly , excludeReadOnlyUser, addActivity, comment.api.remove); + apiV1Router.post('/comments.add' , comment.api.validators.add(), accessTokenParser , loginRequiredStrictly , excludeReadOnlyUserWhenCommentNotAllowed, addActivity, comment.api.add); + apiV1Router.post('/comments.update' , comment.api.validators.add(), accessTokenParser , loginRequiredStrictly , excludeReadOnlyUserWhenCommentNotAllowed, addActivity, comment.api.update); + apiV1Router.post('/comments.remove' , accessTokenParser , loginRequiredStrictly , excludeReadOnlyUserWhenCommentNotAllowed, addActivity, comment.api.remove); apiV1Router.post('/attachments.uploadProfileImage' , uploads.single('file'), autoReap, accessTokenParser, loginRequiredStrictly , excludeReadOnlyUser, attachmentApi.uploadProfileImage); apiV1Router.post('/attachments.remove' , accessTokenParser , loginRequiredStrictly , excludeReadOnlyUser, addActivity ,attachmentApi.remove); From 6ed132ca4297dd1a16c911cba729cda42b8cc209 Mon Sep 17 00:00:00 2001 From: WNomunomu Date: Thu, 12 Sep 2024 03:48:05 +0000 Subject: [PATCH 151/490] add NotAvailableWhenReadOnlyUserNotAllowedToComment component --- .../NotAvailableForReadOnlyUser.tsx | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/apps/app/src/client/components/NotAvailableForReadOnlyUser.tsx b/apps/app/src/client/components/NotAvailableForReadOnlyUser.tsx index d71ac4170ca..4154ae164e7 100644 --- a/apps/app/src/client/components/NotAvailableForReadOnlyUser.tsx +++ b/apps/app/src/client/components/NotAvailableForReadOnlyUser.tsx @@ -26,3 +26,24 @@ export const NotAvailableForReadOnlyUser: React.FC<{ ); }); NotAvailableForReadOnlyUser.displayName = 'NotAvailableForReadOnlyUser'; + + +export const NotAvailableWhenReadOnlyUserNotAllowedToComment: React.FC<{ + children: JSX.Element +}> = React.memo(({ children }) => { + const { t } = useTranslation(); + const { data: isReadOnlyUser } = useIsReadOnlyUser(); + + const isDisabled = !!isReadOnlyUser; + const title = t('Not available for read only user'); + + return ( + + {children} + + ); +}); From 7e746eedb8828787a411282ff5d9ec353c2d670e Mon Sep 17 00:00:00 2001 From: WNomunomu Date: Thu, 12 Sep 2024 03:48:51 +0000 Subject: [PATCH 152/490] improve the way to switch isRomUserAllowedToComment --- .../client/components/Admin/Security/SecuritySetting.jsx | 8 ++++---- .../src/client/services/AdminGeneralSecurityContainer.js | 6 +++--- apps/app/src/server/middlewares/exclude-read-only-user.ts | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/app/src/client/components/Admin/Security/SecuritySetting.jsx b/apps/app/src/client/components/Admin/Security/SecuritySetting.jsx index 5fa1bac5d11..33f0c2f3c7c 100644 --- a/apps/app/src/client/components/Admin/Security/SecuritySetting.jsx +++ b/apps/app/src/client/components/Admin/Security/SecuritySetting.jsx @@ -526,15 +526,15 @@ class SecuritySetting extends React.Component { aria-expanded="true" > - {isRomUserAllowedToComment === true && t('security_settings.rom_users_comment.deny')} - {isRomUserAllowedToComment === false && t('security_settings.rom_users_comment.accept')} + {isRomUserAllowedToComment === true && t('security_settings.rom_users_comment.accept')} + {isRomUserAllowedToComment === false && t('security_settings.rom_users_comment.deny')}
                  - -
                  diff --git a/apps/app/src/client/services/AdminGeneralSecurityContainer.js b/apps/app/src/client/services/AdminGeneralSecurityContainer.js index 766aeeb2a1d..70438a375d7 100644 --- a/apps/app/src/client/services/AdminGeneralSecurityContainer.js +++ b/apps/app/src/client/services/AdminGeneralSecurityContainer.js @@ -223,10 +223,10 @@ export default class AdminGeneralSecurityContainer extends Container { } /** - * Switch isForceDeleteUserHomepageOnUserDeletion + * switch isRomUserAllowedToComment */ - switchIsRomUserAllowedToComment() { - this.setState({ isRomUserAllowedToComment: !this.state.isRomUserAllowedToComment }); + switchIsRomUserAllowedToComment(bool) { + this.setState({ isRomUserAllowedToComment: bool }); } diff --git a/apps/app/src/server/middlewares/exclude-read-only-user.ts b/apps/app/src/server/middlewares/exclude-read-only-user.ts index ca28f1305bc..23955ec6635 100644 --- a/apps/app/src/server/middlewares/exclude-read-only-user.ts +++ b/apps/app/src/server/middlewares/exclude-read-only-user.ts @@ -27,7 +27,7 @@ export const excludeReadOnlyUser = (req: Request, res: Response & { apiv3Err }, return next(); }; -const excludeReadOnlyUserWhenCommentNotAllowed = (req: Request, res: Response & { apiv3Err }, next: () => NextFunction): NextFunction => { +export const excludeReadOnlyUserWhenCommentNotAllowed = (req: Request, res: Response & { apiv3Err }, next: () => NextFunction): NextFunction => { const user = req.user; const isRomUserAllowedToComment = configManager.getConfig('crowi', 'security:isRomUserAllowedToComment'); From 248373d0d23ac5b28fe0434ea769cf177d4f2cd3 Mon Sep 17 00:00:00 2001 From: WNomunomu Date: Thu, 12 Sep 2024 05:07:40 +0000 Subject: [PATCH 153/490] create swr hooks to fetch data --- .../NotAvailableForReadOnlyUser.tsx | 19 +++++++++++++---- apps/app/src/stores/security-setting.ts | 21 +++++++++++++++++++ 2 files changed, 36 insertions(+), 4 deletions(-) create mode 100644 apps/app/src/stores/security-setting.ts diff --git a/apps/app/src/client/components/NotAvailableForReadOnlyUser.tsx b/apps/app/src/client/components/NotAvailableForReadOnlyUser.tsx index 4154ae164e7..84f783e7b90 100644 --- a/apps/app/src/client/components/NotAvailableForReadOnlyUser.tsx +++ b/apps/app/src/client/components/NotAvailableForReadOnlyUser.tsx @@ -3,6 +3,7 @@ import React from 'react'; import { useTranslation } from 'next-i18next'; import { useIsReadOnlyUser } from '~/stores-universal/context'; +import { useSecuritySettings } from '~/stores/security-setting'; import { NotAvailable } from './NotAvailable'; @@ -27,15 +28,24 @@ export const NotAvailableForReadOnlyUser: React.FC<{ }); NotAvailableForReadOnlyUser.displayName = 'NotAvailableForReadOnlyUser'; - -export const NotAvailableWhenReadOnlyUserNotAllowedToComment: React.FC<{ +export const NotAvailableIfReadOnlyUserNotAllowedToComment: React.FC<{ children: JSX.Element }> = React.memo(({ children }) => { const { t } = useTranslation(); const { data: isReadOnlyUser } = useIsReadOnlyUser(); - const isDisabled = !!isReadOnlyUser; - const title = t('Not available for read only user'); + const { data: securitySettings } = useSecuritySettings(); + + if (securitySettings == null) { + return; + } + + const isRomUserAllowedToComment = securitySettings.generalSetting.isRomUserAllowedToComment; + + console.log(isRomUserAllowedToComment); + + const isDisabled = !!isReadOnlyUser && !isRomUserAllowedToComment; + const title = t('Not available for read only user if not allowed to comment'); return ( ); }); +NotAvailableIfReadOnlyUserNotAllowedToComment.displayName = 'NotAvailableIfReadOnlyUserNotAllowedToComment'; diff --git a/apps/app/src/stores/security-setting.ts b/apps/app/src/stores/security-setting.ts new file mode 100644 index 00000000000..606d485d1ee --- /dev/null +++ b/apps/app/src/stores/security-setting.ts @@ -0,0 +1,21 @@ +import type { SWRResponse } from 'swr'; +import useSWRImmutable from 'swr/immutable'; + +import { apiv3Get } from '~/client/util/apiv3-client'; + + +// const response = await apiv3Get('/security-setting/'); +// const { generalSetting, shareLinkSetting, generalAuth } = response.data.securityParams; + +export const useSecuritySettings = (): SWRResponse => { + const swrResponse = useSWRImmutable( + '/security-setting/', + (endpoint) => { + return apiv3Get(endpoint).then(response => response.data.securityParams); + }, + ); + + return { + ...swrResponse, + }; +}; From d3c2f2bd0d04128262bca61086a7868e72a69ac8 Mon Sep 17 00:00:00 2001 From: WNomunomu Date: Thu, 12 Sep 2024 05:08:29 +0000 Subject: [PATCH 154/490] rename the component and the method --- .../src/client/components/PageComment/CommentEditor.tsx | 7 ++++--- apps/app/src/server/middlewares/exclude-read-only-user.ts | 2 +- apps/app/src/server/routes/index.js | 8 ++++---- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/apps/app/src/client/components/PageComment/CommentEditor.tsx b/apps/app/src/client/components/PageComment/CommentEditor.tsx index f4f2a12ec1c..e56b28de0fc 100644 --- a/apps/app/src/client/components/PageComment/CommentEditor.tsx +++ b/apps/app/src/client/components/PageComment/CommentEditor.tsx @@ -32,7 +32,8 @@ import { useCommentEditorDirtyMap } from '~/stores/ui'; import loggerFactory from '~/utils/logger'; import { NotAvailableForGuest } from '../NotAvailableForGuest'; -import { NotAvailableForReadOnlyUser } from '../NotAvailableForReadOnlyUser'; +import { NotAvailableIfReadOnlyUserNotAllowedToComment } from '../NotAvailableForReadOnlyUser'; +// import { NotAvailableIfReadOnlyUserNotAllowedToComment } from '../NotAvailableIfReadOnlyUserNotAllowedToComment'; import { CommentPreview } from './CommentPreview'; import { SwitchingButtonGroup } from './SwitchingButtonGroup'; @@ -330,7 +331,7 @@ export const CommentEditorPre = (props: CommentEditorProps): JSX.Element => { return ( - + - + ); diff --git a/apps/app/src/server/middlewares/exclude-read-only-user.ts b/apps/app/src/server/middlewares/exclude-read-only-user.ts index 23955ec6635..ab9d419c1a1 100644 --- a/apps/app/src/server/middlewares/exclude-read-only-user.ts +++ b/apps/app/src/server/middlewares/exclude-read-only-user.ts @@ -27,7 +27,7 @@ export const excludeReadOnlyUser = (req: Request, res: Response & { apiv3Err }, return next(); }; -export const excludeReadOnlyUserWhenCommentNotAllowed = (req: Request, res: Response & { apiv3Err }, next: () => NextFunction): NextFunction => { +export const excludeReadOnlyUserIfCommentNotAllowed = (req: Request, res: Response & { apiv3Err }, next: () => NextFunction): NextFunction => { const user = req.user; const isRomUserAllowedToComment = configManager.getConfig('crowi', 'security:isRomUserAllowedToComment'); diff --git a/apps/app/src/server/routes/index.js b/apps/app/src/server/routes/index.js index c8346bcf232..cefbaf685e6 100644 --- a/apps/app/src/server/routes/index.js +++ b/apps/app/src/server/routes/index.js @@ -5,7 +5,7 @@ import { middlewareFactory as rateLimiterFactory } from '~/features/rate-limiter import { generateAddActivityMiddleware } from '../middlewares/add-activity'; import apiV1FormValidator from '../middlewares/apiv1-form-validator'; -import { excludeReadOnlyUser, excludeReadOnlyUserWhenCommentNotAllowed } from '../middlewares/exclude-read-only-user'; +import { excludeReadOnlyUser, excludeReadOnlyUserIfCommentNotAllowed } from '../middlewares/exclude-read-only-user'; import injectResetOrderByTokenMiddleware from '../middlewares/inject-reset-order-by-token-middleware'; import injectUserRegistrationOrderByTokenMiddleware from '../middlewares/inject-user-registration-order-by-token-middleware'; import * as loginFormValidator from '../middlewares/login-form-validator'; @@ -131,9 +131,9 @@ module.exports = function(crowi, app) { apiV1Router.get('/tags.search' , accessTokenParser, loginRequired, tag.api.search); apiV1Router.post('/tags.update' , accessTokenParser, loginRequiredStrictly, excludeReadOnlyUser, addActivity, tag.api.update); apiV1Router.get('/comments.get' , accessTokenParser , loginRequired , comment.api.get); - apiV1Router.post('/comments.add' , comment.api.validators.add(), accessTokenParser , loginRequiredStrictly , excludeReadOnlyUserWhenCommentNotAllowed, addActivity, comment.api.add); - apiV1Router.post('/comments.update' , comment.api.validators.add(), accessTokenParser , loginRequiredStrictly , excludeReadOnlyUserWhenCommentNotAllowed, addActivity, comment.api.update); - apiV1Router.post('/comments.remove' , accessTokenParser , loginRequiredStrictly , excludeReadOnlyUserWhenCommentNotAllowed, addActivity, comment.api.remove); + apiV1Router.post('/comments.add' , comment.api.validators.add(), accessTokenParser , loginRequiredStrictly , excludeReadOnlyUserIfCommentNotAllowed, addActivity, comment.api.add); + apiV1Router.post('/comments.update' , comment.api.validators.add(), accessTokenParser , loginRequiredStrictly , excludeReadOnlyUserIfCommentNotAllowed, addActivity, comment.api.update); + apiV1Router.post('/comments.remove' , accessTokenParser , loginRequiredStrictly , excludeReadOnlyUserIfCommentNotAllowed, addActivity, comment.api.remove); apiV1Router.post('/attachments.uploadProfileImage' , uploads.single('file'), autoReap, accessTokenParser, loginRequiredStrictly , excludeReadOnlyUser, attachmentApi.uploadProfileImage); apiV1Router.post('/attachments.remove' , accessTokenParser , loginRequiredStrictly , excludeReadOnlyUser, addActivity ,attachmentApi.remove); From 4a35004d5dcc1fa18344a03d5797fb362c99896a Mon Sep 17 00:00:00 2001 From: WNomunomu Date: Thu, 12 Sep 2024 05:08:41 +0000 Subject: [PATCH 155/490] add params --- apps/app/src/server/routes/apiv3/security-settings/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/app/src/server/routes/apiv3/security-settings/index.js b/apps/app/src/server/routes/apiv3/security-settings/index.js index 6d943e6c81b..d5dac4be17b 100644 --- a/apps/app/src/server/routes/apiv3/security-settings/index.js +++ b/apps/app/src/server/routes/apiv3/security-settings/index.js @@ -364,6 +364,7 @@ module.exports = (crowi) => { isUsersHomepageDeletionEnabled: await configManager.getConfig('crowi', 'security:user-homepage-deletion:isEnabled'), isForceDeleteUserHomepageOnUserDeletion: await configManager.getConfig('crowi', 'security:user-homepage-deletion:isForceDeleteUserHomepageOnUserDeletion'), + isRomUserAllowedToComment: await configManager.getConfig('crowi', 'security:isRomUserAllowedToComment'), wikiMode: await configManager.getConfig('crowi', 'security:wikiMode'), sessionMaxAge: await configManager.getConfig('crowi', 'security:sessionMaxAge'), }, From 224e90922caeee099c9c36afdce64bc338e37d7e Mon Sep 17 00:00:00 2001 From: nHigashiWeseek Date: Thu, 12 Sep 2024 05:36:00 +0000 Subject: [PATCH 156/490] update recent change when page delete --- apps/app/src/client/components/PageDeleteModal.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/app/src/client/components/PageDeleteModal.tsx b/apps/app/src/client/components/PageDeleteModal.tsx index d8c9a168931..96415532cc0 100644 --- a/apps/app/src/client/components/PageDeleteModal.tsx +++ b/apps/app/src/client/components/PageDeleteModal.tsx @@ -17,10 +17,9 @@ import { apiPost } from '~/client/util/apiv1-client'; import { apiv3Post } from '~/client/util/apiv3-client'; import type { IDeleteSinglePageApiv1Result, IDeleteManyPageApiv3Result } from '~/interfaces/page'; import { usePageDeleteModal } from '~/stores/modal'; -import { useSWRxPageInfoForList } from '~/stores/page-listing'; +import { useSWRxPageInfoForList, useSWRINFxRecentlyUpdated } from '~/stores/page-listing'; import loggerFactory from '~/utils/logger'; - import ApiErrorMessageList from './PageManagement/ApiErrorMessageList'; const { isTrashPage } = pagePathUtils; @@ -51,6 +50,7 @@ const PageDeleteModal: FC = () => { const { t } = useTranslation(); const { data: deleteModalData, close: closeDeleteModal } = usePageDeleteModal(); + const { mutate: mutateRecentlyUpdated } = useSWRINFxRecentlyUpdated(20, true); const isOpened = deleteModalData?.isOpened ?? false; @@ -146,6 +146,7 @@ const PageDeleteModal: FC = () => { onDeleted(data.paths, data.isRecursively, data.isCompletely); } closeDeleteModal(); + mutateRecentlyUpdated(); } catch (err) { setErrs([err]); @@ -174,6 +175,7 @@ const PageDeleteModal: FC = () => { } closeDeleteModal(); + mutateRecentlyUpdated(); } catch (err) { setErrs([err]); From 7a126a1facd70956838b51efe60878057532d151 Mon Sep 17 00:00:00 2001 From: nHigashiWeseek Date: Thu, 12 Sep 2024 05:36:13 +0000 Subject: [PATCH 157/490] update recent change when page duplicate --- .../src/client/components/PageDuplicateModal.tsx | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/apps/app/src/client/components/PageDuplicateModal.tsx b/apps/app/src/client/components/PageDuplicateModal.tsx index 5b4c2708e9a..066f1db0d23 100644 --- a/apps/app/src/client/components/PageDuplicateModal.tsx +++ b/apps/app/src/client/components/PageDuplicateModal.tsx @@ -12,12 +12,12 @@ import { apiv3Get, apiv3Post } from '~/client/util/apiv3-client'; import { toastError } from '~/client/util/toastr'; import { useIsSearchServiceReachable, useSiteUrl } from '~/stores-universal/context'; import { usePageDuplicateModal } from '~/stores/modal'; +import { useSWRINFxRecentlyUpdated } from '~/stores/page-listing'; import DuplicatePathsTable from './DuplicatedPathsTable'; import ApiErrorMessageList from './PageManagement/ApiErrorMessageList'; import PagePathAutoComplete from './PagePathAutoComplete'; - const PageDuplicateModal = (): JSX.Element => { const { t } = useTranslation(); @@ -38,6 +38,7 @@ const PageDuplicateModal = (): JSX.Element => { const [isDuplicateRecursively, setIsDuplicateRecursively] = useState(true); const [isDuplicateRecursivelyWithoutExistPath, setIsDuplicateRecursivelyWithoutExistPath] = useState(true); const [onlyDuplicateUserRelatedResources, setOnlyDuplicateUserRelatedResources] = useState(false); + const { mutate: mutateRecentlyUpdated } = useSWRINFxRecentlyUpdated(20, true); const updateSubordinatedList = useCallback(async() => { if (page == null) { @@ -126,11 +127,20 @@ const PageDuplicateModal = (): JSX.Element => { onDuplicated(fromPath, toPath); } closeDuplicateModal(); + mutateRecentlyUpdated(); } catch (err) { setErrs(err); } - }, [closeDuplicateModal, duplicateModalData?.opts?.onDuplicated, isDuplicateRecursively, page, pageNameInput, onlyDuplicateUserRelatedResources]); + }, [ + closeDuplicateModal, + duplicateModalData?.opts?.onDuplicated, + isDuplicateRecursively, + page, + pageNameInput, + onlyDuplicateUserRelatedResources, + mutateRecentlyUpdated, + ]); useEffect(() => { if (isOpened) { From 3e6012621ced2f04acdc0d132a19752ac330ddf5 Mon Sep 17 00:00:00 2001 From: nHigashiWeseek Date: Thu, 12 Sep 2024 05:36:26 +0000 Subject: [PATCH 158/490] update recent change when page renamed --- .../src/client/components/PageRenameModal.tsx | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/apps/app/src/client/components/PageRenameModal.tsx b/apps/app/src/client/components/PageRenameModal.tsx index 9a81275e70c..3c39b4249db 100644 --- a/apps/app/src/client/components/PageRenameModal.tsx +++ b/apps/app/src/client/components/PageRenameModal.tsx @@ -15,6 +15,7 @@ import { toastError } from '~/client/util/toastr'; import { useSiteUrl, useIsSearchServiceReachable } from '~/stores-universal/context'; import { usePageRenameModal } from '~/stores/modal'; import { useSWRxPageInfo } from '~/stores/page'; +import { useSWRINFxRecentlyUpdated } from '~/stores/page-listing'; import DuplicatedPathsTable from './DuplicatedPathsTable'; import ApiErrorMessageList from './PageManagement/ApiErrorMessageList'; @@ -39,6 +40,8 @@ const PageRenameModal = (): JSX.Element => { const shouldFetch = isOpened && page != null && !isIPageInfoForEntity(page.meta); const { data: pageInfo } = useSWRxPageInfo(shouldFetch ? page?.data._id : null); + const { mutate: mutateRecentlyUpdated } = useSWRINFxRecentlyUpdated(20, true); + if (page != null && pageInfo != null) { page.meta = pageInfo; } @@ -121,11 +124,22 @@ const PageRenameModal = (): JSX.Element => { onRenamed(path); } closeRenameModal(); + mutateRecentlyUpdated(); } catch (err) { setErrs(err); } - }, [closeRenameModal, canRename, isRemainMetadata, isRenameRecursively, isRenameRedirect, page, pageNameInput, renameModalData?.opts?.onRenamed]); + }, [ + closeRenameModal, + canRename, + isRemainMetadata, + isRenameRecursively, + isRenameRedirect, + page, + pageNameInput, + renameModalData?.opts?.onRenamed, + mutateRecentlyUpdated, + ]); const checkExistPaths = useCallback(async(fromPath, toPath) => { if (page == null) { From 2ba6c96c8d395856aeb6ddcd00c0304c7dc74777 Mon Sep 17 00:00:00 2001 From: nHigashiWeseek Date: Thu, 12 Sep 2024 05:36:44 +0000 Subject: [PATCH 159/490] update recent change when page put back --- apps/app/src/client/components/PutbackPageModal.jsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/apps/app/src/client/components/PutbackPageModal.jsx b/apps/app/src/client/components/PutbackPageModal.jsx index c34dfadd733..cbcbf7341fb 100644 --- a/apps/app/src/client/components/PutbackPageModal.jsx +++ b/apps/app/src/client/components/PutbackPageModal.jsx @@ -9,6 +9,8 @@ import { import { apiPost } from '~/client/util/apiv1-client'; import { usePutBackPageModal } from '~/stores/modal'; import { mutateAllPageInfo } from '~/stores/page'; +import { useSWRINFxRecentlyUpdated } from '~/stores/page-listing'; + import ApiErrorMessageList from './PageManagement/ApiErrorMessageList'; @@ -25,6 +27,8 @@ const PutBackPageModal = () => { const [isPutbackRecursively, setIsPutbackRecursively] = useState(true); + const { mutate: mutateRecentlyUpdated } = useSWRINFxRecentlyUpdated(20, true); + function changeIsPutbackRecursivelyHandler() { setIsPutbackRecursively(!isPutbackRecursively); } @@ -47,6 +51,7 @@ const PutBackPageModal = () => { onPutBacked(response.page.path); } closePutBackPageModal(); + mutateRecentlyUpdated(); } catch (err) { setTargetPath(err.data); From 4554888083c86fc6bf2a2e3f6d7752b58ee0b2ff Mon Sep 17 00:00:00 2001 From: nHigashiWeseek Date: Thu, 12 Sep 2024 05:36:54 +0000 Subject: [PATCH 160/490] update recent change when page created --- .../client/services/create-page/use-create-page.tsx | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/apps/app/src/client/services/create-page/use-create-page.tsx b/apps/app/src/client/services/create-page/use-create-page.tsx index 306e6b8a091..568d1bc83e6 100644 --- a/apps/app/src/client/services/create-page/use-create-page.tsx +++ b/apps/app/src/client/services/create-page/use-create-page.tsx @@ -9,6 +9,7 @@ import type { IApiv3PageCreateParams } from '~/interfaces/apiv3'; import { EditorMode, useEditorMode } from '~/stores-universal/ui'; import { useGrantedGroupsInheritanceSelectModal } from '~/stores/modal'; import { useCurrentPagePath } from '~/stores/page'; +import { useSWRINFxRecentlyUpdated } from '~/stores/page-listing'; import { useIsUntitledPage } from '~/stores/ui'; import { createPage } from './create-page'; @@ -57,6 +58,8 @@ export const useCreatePage: UseCreatePage = () => { const [isCreating, setCreating] = useState(false); + const { mutate: mutateRecentlyUpdated } = useSWRINFxRecentlyUpdated(20, true); + const create: CreatePage = useCallback(async(params, opts = {}) => { const { onCreationStart, onCreated, onAborted, onTerminated, @@ -114,6 +117,7 @@ export const useCreatePage: UseCreatePage = () => { } onCreated?.(); + mutateRecentlyUpdated(); } catch (err) { throw err; @@ -135,7 +139,14 @@ export const useCreatePage: UseCreatePage = () => { } await _create(); - }, [currentPagePath, mutateEditorMode, router, t, closeGrantedGroupsInheritanceSelectModal, mutateIsUntitledPage, openGrantedGroupsInheritanceSelectModal]); + }, [ + currentPagePath, + mutateEditorMode, + router, t, + closeGrantedGroupsInheritanceSelectModal, + mutateIsUntitledPage, openGrantedGroupsInheritanceSelectModal, + mutateRecentlyUpdated, + ]); return { isCreating, From bb00d61ce97a988319ffabe5dd905e1f891ca519 Mon Sep 17 00:00:00 2001 From: nHigashiWeseek Date: Thu, 12 Sep 2024 05:37:09 +0000 Subject: [PATCH 161/490] update recent change when page updated --- .../app/src/client/services/update-page/use-update-page.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/app/src/client/services/update-page/use-update-page.tsx b/apps/app/src/client/services/update-page/use-update-page.tsx index 7764991c394..074e7690fea 100644 --- a/apps/app/src/client/services/update-page/use-update-page.tsx +++ b/apps/app/src/client/services/update-page/use-update-page.tsx @@ -1,6 +1,7 @@ import { useCallback } from 'react'; import type { IApiv3PageUpdateParams, IApiv3PageUpdateResponse } from '~/interfaces/apiv3'; +import { useSWRINFxRecentlyUpdated } from '~/stores/page-listing'; import { useIsUntitledPage } from '~/stores/ui'; import { updatePage } from './update-page'; @@ -11,15 +12,16 @@ type UseUpdatePage = (params: IApiv3PageUpdateParams) => Promise { const { mutate: mutateUntitledPage } = useIsUntitledPage(); - + const { mutate: mutateRecentlyUpdated } = useSWRINFxRecentlyUpdated(20, true); const updatePageExt: UseUpdatePage = useCallback(async(params) => { const result = await updatePage(params); // set false to isUntitledPage mutateUntitledPage(false); + mutateRecentlyUpdated(); return result; - }, [mutateUntitledPage]); + }, [mutateUntitledPage, mutateRecentlyUpdated]); return updatePageExt; }; From 1d6e23f091b03f5b80f429d2ab986770f04ecc01 Mon Sep 17 00:00:00 2001 From: nHigashiWeseek Date: Thu, 12 Sep 2024 05:41:13 +0000 Subject: [PATCH 162/490] update recent change when page published --- .../src/components/PageView/PageAlerts/WipPageAlert.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/app/src/components/PageView/PageAlerts/WipPageAlert.tsx b/apps/app/src/components/PageView/PageAlerts/WipPageAlert.tsx index 83afa5f82b0..65b8312a94b 100644 --- a/apps/app/src/components/PageView/PageAlerts/WipPageAlert.tsx +++ b/apps/app/src/components/PageView/PageAlerts/WipPageAlert.tsx @@ -3,12 +3,15 @@ import React, { useCallback } from 'react'; import { useTranslation } from 'react-i18next'; import { useSWRMUTxCurrentPage, useSWRxCurrentPage } from '~/stores/page'; +import { useSWRINFxRecentlyUpdated } from '~/stores/page-listing'; export const WipPageAlert = (): JSX.Element => { const { t } = useTranslation(); const { data: currentPage } = useSWRxCurrentPage(); const { trigger: mutateCurrentPage } = useSWRMUTxCurrentPage(); + const { mutate: mutateRecentlyUpdated } = useSWRINFxRecentlyUpdated(20, true); + const clickPagePublishButton = useCallback(async() => { const pageId = currentPage?._id; @@ -28,12 +31,14 @@ export const WipPageAlert = (): JSX.Element => { const toastSuccess = (await import('~/client/util/toastr')).toastSuccess; toastSuccess(t('wip_page.success_publish_page')); + + mutateRecentlyUpdated(); } catch { const toastError = (await import('~/client/util/toastr')).toastError; toastError(t('wip_page.fail_publish_page')); } - }, [currentPage?._id, mutateCurrentPage, t]); + }, [currentPage?._id, mutateCurrentPage, t, mutateRecentlyUpdated]); if (!currentPage?.wip) { From 25652ed3c393e19897f9db5e836a0a09ed592ce8 Mon Sep 17 00:00:00 2001 From: WNomunomu Date: Thu, 12 Sep 2024 06:29:44 +0000 Subject: [PATCH 163/490] remove unnecessary hooks --- apps/app/src/stores/security-setting.ts | 21 --------------------- 1 file changed, 21 deletions(-) delete mode 100644 apps/app/src/stores/security-setting.ts diff --git a/apps/app/src/stores/security-setting.ts b/apps/app/src/stores/security-setting.ts deleted file mode 100644 index 606d485d1ee..00000000000 --- a/apps/app/src/stores/security-setting.ts +++ /dev/null @@ -1,21 +0,0 @@ -import type { SWRResponse } from 'swr'; -import useSWRImmutable from 'swr/immutable'; - -import { apiv3Get } from '~/client/util/apiv3-client'; - - -// const response = await apiv3Get('/security-setting/'); -// const { generalSetting, shareLinkSetting, generalAuth } = response.data.securityParams; - -export const useSecuritySettings = (): SWRResponse => { - const swrResponse = useSWRImmutable( - '/security-setting/', - (endpoint) => { - return apiv3Get(endpoint).then(response => response.data.securityParams); - }, - ); - - return { - ...swrResponse, - }; -}; From dffa4ea753dad4dc9e7e4b194708f40bc22ae171 Mon Sep 17 00:00:00 2001 From: WNomunomu Date: Thu, 12 Sep 2024 06:30:08 +0000 Subject: [PATCH 164/490] use server side props instead of api --- .../components/NotAvailableForReadOnlyUser.tsx | 12 ++---------- apps/app/src/client/components/PageComment.tsx | 6 +++--- apps/app/src/pages/[[...path]].page.tsx | 7 +++++++ apps/app/src/stores-universal/context.tsx | 4 ++++ 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/apps/app/src/client/components/NotAvailableForReadOnlyUser.tsx b/apps/app/src/client/components/NotAvailableForReadOnlyUser.tsx index 84f783e7b90..4d6f0c12035 100644 --- a/apps/app/src/client/components/NotAvailableForReadOnlyUser.tsx +++ b/apps/app/src/client/components/NotAvailableForReadOnlyUser.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { useTranslation } from 'next-i18next'; -import { useIsReadOnlyUser } from '~/stores-universal/context'; +import { useIsReadOnlyUser, useIsRomUserAllowedToComment } from '~/stores-universal/context'; import { useSecuritySettings } from '~/stores/security-setting'; import { NotAvailable } from './NotAvailable'; @@ -34,15 +34,7 @@ export const NotAvailableIfReadOnlyUserNotAllowedToComment: React.FC<{ const { t } = useTranslation(); const { data: isReadOnlyUser } = useIsReadOnlyUser(); - const { data: securitySettings } = useSecuritySettings(); - - if (securitySettings == null) { - return; - } - - const isRomUserAllowedToComment = securitySettings.generalSetting.isRomUserAllowedToComment; - - console.log(isRomUserAllowedToComment); + const { data: isRomUserAllowedToComment } = useIsRomUserAllowedToComment(); const isDisabled = !!isReadOnlyUser && !isRomUserAllowedToComment; const title = t('Not available for read only user if not allowed to comment'); diff --git a/apps/app/src/client/components/PageComment.tsx b/apps/app/src/client/components/PageComment.tsx index 616f2b4594b..2546812699a 100644 --- a/apps/app/src/client/components/PageComment.tsx +++ b/apps/app/src/client/components/PageComment.tsx @@ -20,7 +20,7 @@ import type { ICommentHasId, ICommentHasIdList } from '../../interfaces/comment' import { useSWRxPageComment } from '../../stores/comment'; import { NotAvailableForGuest } from './NotAvailableForGuest'; -import { NotAvailableForReadOnlyUser } from './NotAvailableForReadOnlyUser'; +import { NotAvailableIfReadOnlyUserNotAllowedToComment } from './NotAvailableForReadOnlyUser'; import { Comment } from './PageComment/Comment'; import { CommentEditor } from './PageComment/CommentEditor'; import { DeleteCommentModal } from './PageComment/DeleteCommentModal'; @@ -183,7 +183,7 @@ export const PageComment: FC = memo((props: PageCommentProps): {(!isReadOnly && !showEditorIds.has(comment._id)) && (
                  - + - +
                  )} diff --git a/apps/app/src/pages/[[...path]].page.tsx b/apps/app/src/pages/[[...path]].page.tsx index 4dd4124783e..47902e2c1b8 100644 --- a/apps/app/src/pages/[[...path]].page.tsx +++ b/apps/app/src/pages/[[...path]].page.tsx @@ -45,6 +45,7 @@ import { useIsUploadAllFileAllowed, useIsUploadEnabled, useElasticsearchMaxBodyLengthToIndex, useIsLocalAccountRegistrationEnabled, + useIsRomUserAllowedToComment, } from '~/stores-universal/context'; import { useEditingMarkdown } from '~/stores/editor'; import { @@ -164,6 +165,8 @@ type Props = CommonProps & { elasticsearchMaxBodyLengthToIndex: number, isEnabledMarp: boolean, + isRomUserAllowedToComment: boolean, + sidebarConfig: ISidebarConfig, isSlackConfigured: boolean, @@ -242,6 +245,8 @@ const Page: NextPageWithLayout = (props: Props) => { useIsLocalAccountRegistrationEnabled(props.isLocalAccountRegistrationEnabled); + useIsRomUserAllowedToComment(props.isRomUserAllowedToComment); + const { pageWithMeta } = props; const pageId = pageWithMeta?.data._id; @@ -551,6 +556,8 @@ function injectServerConfigurations(context: GetServerSidePropsContext, props: P props.isSearchScopeChildrenAsDefault = configManager.getConfig('crowi', 'customize:isSearchScopeChildrenAsDefault'); props.elasticsearchMaxBodyLengthToIndex = configManager.getConfig('crowi', 'app:elasticsearchMaxBodyLengthToIndex'); + props.isRomUserAllowedToComment = configManager.getConfig('crowi', 'security:isRomUserAllowedToComment'); + props.isSlackConfigured = crowi.slackIntegrationService.isSlackConfigured; // props.isMailerSetup = mailService.isMailerSetup; props.isAclEnabled = aclService.isAclEnabled(); diff --git a/apps/app/src/stores-universal/context.tsx b/apps/app/src/stores-universal/context.tsx index c020cb75720..06ffcfaf619 100644 --- a/apps/app/src/stores-universal/context.tsx +++ b/apps/app/src/stores-universal/context.tsx @@ -208,6 +208,10 @@ export const useIsLocalAccountRegistrationEnabled = (initialData?: boolean): SWR return useContextSWR('isLocalAccountRegistrationEnabled', initialData); }; +export const useIsRomUserAllowedToComment = (initialData?: boolean): SWRResponse => { + return useContextSWR('isRomUserAllowedToComment', initialData); +}; + /** ********************************************************** * Computed contexts *********************************************************** */ From 6d4303c204e67a7e1596486d8f029f2c97296083 Mon Sep 17 00:00:00 2001 From: WNomunomu Date: Thu, 12 Sep 2024 06:36:13 +0000 Subject: [PATCH 165/490] add translation data --- apps/app/public/static/locales/en_US/admin.json | 8 ++++---- apps/app/public/static/locales/fr_FR/admin.json | 8 ++++---- apps/app/public/static/locales/ja_JP/admin.json | 4 ++-- apps/app/public/static/locales/zh_CN/admin.json | 8 ++++---- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/apps/app/public/static/locales/en_US/admin.json b/apps/app/public/static/locales/en_US/admin.json index 45e54b1300e..ff2e4e9abf0 100644 --- a/apps/app/public/static/locales/en_US/admin.json +++ b/apps/app/public/static/locales/en_US/admin.json @@ -15,7 +15,7 @@ "scope_of_page_disclosure": "Scope of page disclosure", "set_point": "Set point", "Guest Users Access": "Guest users access", - "readonly_users_access": "", + "readonly_users_access": "ROM users' access", "always_hidden": "Always hidden", "always_displayed": "Always displayed", "displayed_or_hidden": "Hidden / Displayed", @@ -38,7 +38,7 @@ "page_delete_rights": "Delete rights", "page_delete": "Page Delete", "page_delete_completely": "Page Delete Completely", - "comment_manage_rights": "", + "comment_manage_rights": "Comment management rights", "other_options": "Other options", "deletion_explanation": "Restricts users who can trash the selected single page.", "complete_deletion_explanation": "Restricts users who can completely delete selected single page.", @@ -88,8 +88,8 @@ "readonly": "Accept (Guests can read only)" }, "rom_users_comment": { - "deny": "拒否 (ROMユーザーのコメント禁止)", - "accept": "許可 (ROMユーザーもコメント可能)" + "deny": "Deny (Prohibit ROM users from comment management)", + "accept": "Allow (ROM users can manage comments)" }, "registration_mode": { "open": "Open (Anyone can register)", diff --git a/apps/app/public/static/locales/fr_FR/admin.json b/apps/app/public/static/locales/fr_FR/admin.json index 994fbdd4580..233af730d06 100644 --- a/apps/app/public/static/locales/fr_FR/admin.json +++ b/apps/app/public/static/locales/fr_FR/admin.json @@ -15,7 +15,7 @@ "scope_of_page_disclosure": "Confidentialité de la page", "set_point": "Valeur", "Guest Users Access": "Accès invité", - "readonly_users_access": "", + "readonly_users_access": "Accès des utilisateurs ROM", "always_hidden": "Toujours caché", "always_displayed": "Toujours affiché", "displayed_or_hidden": "Caché / Affiché", @@ -38,7 +38,7 @@ "page_delete_rights": "Droits de suppression", "page_delete": "Suppression de page", "page_delete_completely": "Suppression complète de page", - "comment_manage_rights": "", + "comment_manage_rights": "Droits de gestion des commentaires", "other_options": "Paramètres supplémentaires", "deletion_explanation": "Restreindre les utilisateurs pouvant supprimer une page.", "complete_deletion_explanation": "Restreindre les utilisateurs pouvant supprimer complètement une page.", @@ -88,8 +88,8 @@ "readonly": "Autoriser (Lecture seule)" }, "rom_users_comment": { - "deny": "拒否 (ROMユーザーのコメント禁止)", - "accept": "許可 (ROMユーザーもコメント可能)" + "deny": "Refuser (Interdire la gestion des commentaires aux utilisateurs ROM)", + "accept": "Autoriser (Les utilisateurs ROM peuvent gérer les commentaires)" }, "registration_mode": { "open": "Ouvert (Tout le monde peut s'inscrire)", diff --git a/apps/app/public/static/locales/ja_JP/admin.json b/apps/app/public/static/locales/ja_JP/admin.json index 5d8465a9ee2..006cec44ef3 100644 --- a/apps/app/public/static/locales/ja_JP/admin.json +++ b/apps/app/public/static/locales/ja_JP/admin.json @@ -97,8 +97,8 @@ "readonly": "許可 (ゲストユーザーも閲覧のみ可能)" }, "rom_users_comment": { - "deny": "拒否 (ROMユーザーのコメントを禁止)", - "accept": "許可 (ROMユーザーもコメント可能)" + "deny": "拒否 (ROMユーザーのコメント操作を禁止)", + "accept": "許可 (ROMユーザーもコメント操作可能)" }, "registration_mode": { "open": "公開 (だれでも登録可能)", diff --git a/apps/app/public/static/locales/zh_CN/admin.json b/apps/app/public/static/locales/zh_CN/admin.json index 8e0909f4783..5ef03bf1ef5 100644 --- a/apps/app/public/static/locales/zh_CN/admin.json +++ b/apps/app/public/static/locales/zh_CN/admin.json @@ -27,7 +27,7 @@ "always_hidden": "总是隐藏", "displayed_or_hidden": "隐藏 / 显示", "Guest Users Access": "来宾用户访问", - "readonly_users_access": "", + "readonly_users_access": "ROM用户的访问", "Fixed by env var": "这是由env var%s=%s修复的。", "register_limitation": "注册限制", "register_limitation_desc": "限制新用户注册", @@ -47,7 +47,7 @@ "page_delete_rights": "删除权限", "page_delete": "删除", "page_delete_completely": "彻底删除", - "comment_manage_rights": "", + "comment_manage_rights": "评论管理权限", "other_options": "其他选项", "deletion_explanation": "限制用户对选定的单一页面进行垃圾处理。", "complete_deletion_explanation": "限制可以完全删除所选单页的用户。", @@ -97,8 +97,8 @@ "readonly": "接受(来宾可以只读)" }, "rom_users_comment": { - "deny": "拒否 (ROMユーザーのコメント禁止)", - "accept": "許可 (ROMユーザーもコメント可能)" + "deny": "拒绝 (禁止ROM用户操作评论)", + "accept": "允许 (ROM用户可以管理评论)" }, "registration_mode": { "open": "打开(任何人都可以注册)", From abc1b02923774907d9030218cecfd2e17a230052 Mon Sep 17 00:00:00 2001 From: WNomunomu Date: Thu, 12 Sep 2024 06:37:48 +0000 Subject: [PATCH 166/490] remove unnecessary parts --- apps/app/src/client/components/PageComment/CommentEditor.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/app/src/client/components/PageComment/CommentEditor.tsx b/apps/app/src/client/components/PageComment/CommentEditor.tsx index e56b28de0fc..72e47800b68 100644 --- a/apps/app/src/client/components/PageComment/CommentEditor.tsx +++ b/apps/app/src/client/components/PageComment/CommentEditor.tsx @@ -33,7 +33,6 @@ import loggerFactory from '~/utils/logger'; import { NotAvailableForGuest } from '../NotAvailableForGuest'; import { NotAvailableIfReadOnlyUserNotAllowedToComment } from '../NotAvailableForReadOnlyUser'; -// import { NotAvailableIfReadOnlyUserNotAllowedToComment } from '../NotAvailableIfReadOnlyUserNotAllowedToComment'; import { CommentPreview } from './CommentPreview'; import { SwitchingButtonGroup } from './SwitchingButtonGroup'; From 98c445011ede0dd16713fcb4721224b5fc38e237 Mon Sep 17 00:00:00 2001 From: WNomunomu Date: Thu, 12 Sep 2024 06:45:04 +0000 Subject: [PATCH 167/490] remove unnecessary parts --- apps/app/src/client/components/NotAvailableForReadOnlyUser.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/app/src/client/components/NotAvailableForReadOnlyUser.tsx b/apps/app/src/client/components/NotAvailableForReadOnlyUser.tsx index 4d6f0c12035..4676713abc1 100644 --- a/apps/app/src/client/components/NotAvailableForReadOnlyUser.tsx +++ b/apps/app/src/client/components/NotAvailableForReadOnlyUser.tsx @@ -3,7 +3,6 @@ import React from 'react'; import { useTranslation } from 'next-i18next'; import { useIsReadOnlyUser, useIsRomUserAllowedToComment } from '~/stores-universal/context'; -import { useSecuritySettings } from '~/stores/security-setting'; import { NotAvailable } from './NotAvailable'; From a14139b485bf45fdcd105b80efc50882f7d2688b Mon Sep 17 00:00:00 2001 From: WNomunomu Date: Thu, 12 Sep 2024 06:51:18 +0000 Subject: [PATCH 168/490] set the color of dropdown when it is clicked --- apps/app/src/styles/_dropdown.scss | 16 ++++++++++++++++ apps/app/src/styles/style-app.scss | 1 + 2 files changed, 17 insertions(+) create mode 100644 apps/app/src/styles/_dropdown.scss diff --git a/apps/app/src/styles/_dropdown.scss b/apps/app/src/styles/_dropdown.scss new file mode 100644 index 00000000000..1afb12a5730 --- /dev/null +++ b/apps/app/src/styles/_dropdown.scss @@ -0,0 +1,16 @@ +@use '@growi/core-styles/scss/bootstrap/init' as bs; + + +// == Colors +@include bs.color-mode(light) { + .dropdown-item:active{ + color: #403c39; + background-color: #efeeed; + } +} + +@include bs.color-mode(dark) { + .dropdown-item:active{ + background-color: #535c5a; + } +} diff --git a/apps/app/src/styles/style-app.scss b/apps/app/src/styles/style-app.scss index 39f71b3fc6f..58aeb6f06e6 100644 --- a/apps/app/src/styles/style-app.scss +++ b/apps/app/src/styles/style-app.scss @@ -26,6 +26,7 @@ @import 'modal'; @import 'share-link'; @import 'marker'; +@import 'dropdown'; /* * for Guest User Mode From 4de2874f2b7a65d9d57eb802aeb4f74896759171 Mon Sep 17 00:00:00 2001 From: WNomunomu Date: Thu, 12 Sep 2024 07:11:53 +0000 Subject: [PATCH 169/490] use css variables --- apps/app/src/styles/_dropdown.scss | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/app/src/styles/_dropdown.scss b/apps/app/src/styles/_dropdown.scss index 1afb12a5730..07c8bd0914d 100644 --- a/apps/app/src/styles/_dropdown.scss +++ b/apps/app/src/styles/_dropdown.scss @@ -4,13 +4,13 @@ // == Colors @include bs.color-mode(light) { .dropdown-item:active{ - color: #403c39; - background-color: #efeeed; + --bs-dropdown-link-active-color: #{( bs.$gray-600 )}; + --bs-dropdown-link-active-bg: #{( bs.$gray-200 )}; } } @include bs.color-mode(dark) { .dropdown-item:active{ - background-color: #535c5a; + --bs-dropdown-link-active-bg: #{( bs.$gray-700 )}; } } From fea838944def721d42920360a8522feec4075603 Mon Sep 17 00:00:00 2001 From: WNomunomu Date: Thu, 12 Sep 2024 07:21:13 +0000 Subject: [PATCH 170/490] restrict editing and deleting comments --- .../components/PageComment/CommentControl.tsx | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/apps/app/src/client/components/PageComment/CommentControl.tsx b/apps/app/src/client/components/PageComment/CommentControl.tsx index e9d77a0049e..c31665062a4 100644 --- a/apps/app/src/client/components/PageComment/CommentControl.tsx +++ b/apps/app/src/client/components/PageComment/CommentControl.tsx @@ -1,5 +1,6 @@ import React from 'react'; +import { NotAvailableIfReadOnlyUserNotAllowedToComment } from '../NotAvailableForReadOnlyUser'; type CommentControlProps = { onClickEditBtn: () => void, @@ -13,17 +14,21 @@ export const CommentControl = (props: CommentControlProps): JSX.Element => { return ( // The page-comment-control class is imported from Comment.module.scss
                  - - + + <> + + + +
                  ); From 203ddb24820eeaea5a80c2c9ffaf3cc74334fe59 Mon Sep 17 00:00:00 2001 From: WNomunomu Date: Thu, 12 Sep 2024 07:28:54 +0000 Subject: [PATCH 171/490] add translation data --- apps/app/public/static/locales/en_US/translation.json | 3 ++- apps/app/public/static/locales/fr_FR/translation.json | 3 ++- apps/app/public/static/locales/ja_JP/translation.json | 3 ++- apps/app/public/static/locales/zh_CN/translation.json | 3 ++- apps/app/src/client/components/NotAvailableForReadOnlyUser.tsx | 2 +- 5 files changed, 9 insertions(+), 5 deletions(-) diff --git a/apps/app/public/static/locales/en_US/translation.json b/apps/app/public/static/locales/en_US/translation.json index dad0a32962a..a143b220b5a 100644 --- a/apps/app/public/static/locales/en_US/translation.json +++ b/apps/app/public/static/locales/en_US/translation.json @@ -349,7 +349,8 @@ "display_the_page_when_posting_this_comment": "Display the page when posting this comment", "no_user_found": "No user found", "reply": "Reply", - "delete_comment": "Delete comment?" + "delete_comment": "Delete comment?", + "comment_management_is_not_allowed": "Comment management is not allowed." }, "page_api_error": { "notfound_or_forbidden": "Original page is not found or forbidden.", diff --git a/apps/app/public/static/locales/fr_FR/translation.json b/apps/app/public/static/locales/fr_FR/translation.json index cc49c7de7ed..e8a6881fccd 100644 --- a/apps/app/public/static/locales/fr_FR/translation.json +++ b/apps/app/public/static/locales/fr_FR/translation.json @@ -349,7 +349,8 @@ "display_the_page_when_posting_this_comment": "Afficher la page en postant le commentaire", "no_user_found": "Aucun utilisateur trouvé", "reply": "Répondre", - "delete_comment": "Supprimer?" + "delete_comment": "Supprimer?", + "comment_management_is_not_allowed": "La gestion des commentaires n'est pas autorisée." }, "page_api_error": { "notfound_or_forbidden": "Page originale introuvable ou accès restreint.", diff --git a/apps/app/public/static/locales/ja_JP/translation.json b/apps/app/public/static/locales/ja_JP/translation.json index b5852d9faa5..a828f0e7c91 100644 --- a/apps/app/public/static/locales/ja_JP/translation.json +++ b/apps/app/public/static/locales/ja_JP/translation.json @@ -382,7 +382,8 @@ "display_the_page_when_posting_this_comment": "投稿時のページを表示する", "no_user_found": "ユーザー名が見つかりません", "reply": "返信", - "delete_comment": "コメントを削除しますか?" + "delete_comment": "コメントを削除しますか?", + "comment_management_is_not_allowed": "コメントの操作が許可されていません。" }, "page_api_error": { "notfound_or_forbidden": "元のページが見つからないか、アクセス権がありません。", diff --git a/apps/app/public/static/locales/zh_CN/translation.json b/apps/app/public/static/locales/zh_CN/translation.json index 5b9ab7541c6..743b90f3903 100644 --- a/apps/app/public/static/locales/zh_CN/translation.json +++ b/apps/app/public/static/locales/zh_CN/translation.json @@ -339,7 +339,8 @@ "display_the_page_when_posting_this_comment": "Display the page when posting this comment", "no_user_found": "未找到用户名", "reply": "Reply", - "delete_comment": "Delete comment?" + "delete_comment": "Delete comment?", + "comment_management_is_not_allowed": "不允许操作评论。" }, "page_api_error": { "notfound_or_forbidden": "未找到或禁止原始页。", diff --git a/apps/app/src/client/components/NotAvailableForReadOnlyUser.tsx b/apps/app/src/client/components/NotAvailableForReadOnlyUser.tsx index 4676713abc1..89d72b424b9 100644 --- a/apps/app/src/client/components/NotAvailableForReadOnlyUser.tsx +++ b/apps/app/src/client/components/NotAvailableForReadOnlyUser.tsx @@ -36,7 +36,7 @@ export const NotAvailableIfReadOnlyUserNotAllowedToComment: React.FC<{ const { data: isRomUserAllowedToComment } = useIsRomUserAllowedToComment(); const isDisabled = !!isReadOnlyUser && !isRomUserAllowedToComment; - const title = t('Not available for read only user if not allowed to comment'); + const title = t('page_comment.comment_management_is_not_allowed'); return ( Date: Thu, 12 Sep 2024 10:18:57 +0000 Subject: [PATCH 172/490] Revert "Revert "Merge pull request #9098 from weseek/imprv/144244-153642-corrected-wording-on-management-screeen"" This reverts commit 5511beb789e5152090f5563bcacee3366acea281. --- apps/app/public/static/locales/en_US/commons.json | 2 +- apps/app/public/static/locales/fr_FR/commons.json | 2 +- apps/app/public/static/locales/ja_JP/commons.json | 2 +- apps/app/public/static/locales/zh_CN/commons.json | 2 +- .../client/components/Admin/G2GDataTransfer.tsx | 6 +++++- .../src/client/components/DataTransferForm.tsx | 5 ++++- apps/app/src/stores-universal/context.tsx | 15 +++++++++++++++ 7 files changed, 28 insertions(+), 6 deletions(-) diff --git a/apps/app/public/static/locales/en_US/commons.json b/apps/app/public/static/locales/en_US/commons.json index eb6c0c50080..3e9e92d8e9c 100644 --- a/apps/app/public/static/locales/en_US/commons.json +++ b/apps/app/public/static/locales/en_US/commons.json @@ -157,6 +157,6 @@ "publish_transfer_key": "Publish transfer key", "transfer_key_limit": "Transfer keys are valid for 1 hour after issuance.", "once_transfer_key_used": "Once the transfer key is used for transfer, it cannot be used for any other transfer.", - "transfer_to_growi_cloud": "If you wish to transfer to GROWI.cloud, please click here." + "transfer_to_growi_cloud": "For more details, please click here." } } diff --git a/apps/app/public/static/locales/fr_FR/commons.json b/apps/app/public/static/locales/fr_FR/commons.json index 3771c037ee5..205f1532148 100644 --- a/apps/app/public/static/locales/fr_FR/commons.json +++ b/apps/app/public/static/locales/fr_FR/commons.json @@ -157,6 +157,6 @@ "publish_transfer_key": "Publier la clé de transfert", "transfer_key_limit": "Les clés de transfert sont valides durant une heure.", "once_transfer_key_used": "Les clés de transfert sont à usage unique.", - "transfer_to_growi_cloud": "Si vous souhaitez transférer depuis GROWI.cloud, cliquez ici." + "transfer_to_growi_cloud": "Pour plus de détails, veuillez cliquer ici." } } diff --git a/apps/app/public/static/locales/ja_JP/commons.json b/apps/app/public/static/locales/ja_JP/commons.json index f85a86db4f9..cd201e5ec03 100644 --- a/apps/app/public/static/locales/ja_JP/commons.json +++ b/apps/app/public/static/locales/ja_JP/commons.json @@ -159,6 +159,6 @@ "publish_transfer_key": "移行キーを発行する", "transfer_key_limit": "※ 移行キーの有効期限は発行から1時間となります。", "once_transfer_key_used": "※ 移行キーは一度移行に利用するとそれ以降はご利用いただけなくなります。", - "transfer_to_growi_cloud": "※ GROWI.cloud への移行を実施する場合はこちらをご確認ください。" + "transfer_to_growi_cloud": "※ 詳しくは こちら" } } diff --git a/apps/app/public/static/locales/zh_CN/commons.json b/apps/app/public/static/locales/zh_CN/commons.json index 9108400f2d3..677f7c63bca 100644 --- a/apps/app/public/static/locales/zh_CN/commons.json +++ b/apps/app/public/static/locales/zh_CN/commons.json @@ -160,6 +160,6 @@ "publish_transfer_key": "发布迁移密钥", "transfer_key_limit": "迁移密钥在签发后一小时内有效。", "once_transfer_key_used": "一旦迁移密钥被用于迁移,它将不再可用于进一步的迁移。", - "transfer_to_growi_cloud": "如果您希望迁移到GROWI.cloud,请点击这里。" + "transfer_to_growi_cloud": "有关更多详情,请点击此处。" } } diff --git a/apps/app/src/client/components/Admin/G2GDataTransfer.tsx b/apps/app/src/client/components/Admin/G2GDataTransfer.tsx index a61650af4a8..515d1b6d0bc 100644 --- a/apps/app/src/client/components/Admin/G2GDataTransfer.tsx +++ b/apps/app/src/client/components/Admin/G2GDataTransfer.tsx @@ -8,6 +8,7 @@ import { useGenerateTransferKey } from '~/client/services/g2g-transfer'; import { apiv3Get, apiv3Post } from '~/client/util/apiv3-client'; import { toastError, toastSuccess } from '~/client/util/toastr'; import { G2G_PROGRESS_STATUS, type G2GProgress } from '~/interfaces/g2g-transfer'; +import { useGrowiHelpDomain } from '~/stores-universal/context'; import { useAdminSocket } from '~/stores/socket-io'; import CustomCopyToClipBoard from '../Common/CustomCopyToClipBoard'; @@ -123,6 +124,8 @@ const G2GDataTransfer = (): JSX.Element => { } }, [setTransferring, startTransferKey, selectedCollections, optionsMap]); + const { data: growiHelpDomain } = useGrowiHelpDomain(); + // File upload // const onChangeFileUploadTypeHandler = useCallback((e: ChangeEvent, type: string) => { // setFileUploadType(type); @@ -275,7 +278,8 @@ const G2GDataTransfer = (): JSX.Element => {

                  {t('commons:g2g_data_transfer.transfer_key_limit')}

                  {t('commons:g2g_data_transfer.once_transfer_key_used')}

                  -

                  {t('commons:g2g_data_transfer.transfer_to_growi_cloud')}

                  + {/* eslint-disable-next-line react/no-danger */} +

                  ); diff --git a/apps/app/src/client/components/DataTransferForm.tsx b/apps/app/src/client/components/DataTransferForm.tsx index a5f7c18ed26..e52a0609f98 100644 --- a/apps/app/src/client/components/DataTransferForm.tsx +++ b/apps/app/src/client/components/DataTransferForm.tsx @@ -3,12 +3,14 @@ import React from 'react'; import { useTranslation } from 'next-i18next'; import { useGenerateTransferKey } from '~/client/services/g2g-transfer'; +import { useGrowiHelpDomain } from '~/stores-universal/context'; import CustomCopyToClipBoard from './Common/CustomCopyToClipBoard'; const DataTransferForm = (): JSX.Element => { const { t } = useTranslation('commons'); const { transferKey, generateTransferKey } = useGenerateTransferKey(); + const { data: growiHelpDomain } = useGrowiHelpDomain(); return (
                  @@ -33,7 +35,8 @@ const DataTransferForm = (): JSX.Element => {

                  {t('g2g_data_transfer.transfer_key_limit')}

                  {t('g2g_data_transfer.once_transfer_key_used')}

                  -

                  {t('g2g_data_transfer.transfer_to_growi_cloud')}

                  + {/* eslint-disable-next-line react/no-danger */} +

                  ); diff --git a/apps/app/src/stores-universal/context.tsx b/apps/app/src/stores-universal/context.tsx index c020cb75720..c0c3046bede 100644 --- a/apps/app/src/stores-universal/context.tsx +++ b/apps/app/src/stores-universal/context.tsx @@ -285,3 +285,18 @@ export const useAcceptedUploadFileType = (): SWRResponse => { + const { data: growiCloudUri } = useGrowiCloudUri(); + const { data: growiAppIdForGrowiCloud } = useGrowiAppIdForGrowiCloud(); + + return useSWRImmutable( + [growiCloudUri, growiAppIdForGrowiCloud], + ([growiCloudUri, growiAppIdForGrowiCloud]) => { + if (growiCloudUri != null && growiAppIdForGrowiCloud != null) { + return 'growi.cloud/help'; + } + return 'docs.growi.org'; + }, + ); +}; From 8b6588a37a3f77ae4240bdc73d9723e4baf097f4 Mon Sep 17 00:00:00 2001 From: WNomunomu Date: Fri, 13 Sep 2024 01:04:26 +0000 Subject: [PATCH 173/490] move scss files to core-styles package --- apps/app/src/styles/_dropdown.scss | 16 ---------------- apps/app/src/styles/style-app.scss | 1 - .../scss/bootstrap/theming/_dropdown-dark.scss | 5 +++++ .../scss/bootstrap/theming/_dropdown-light.scss | 6 ++++++ .../scss/bootstrap/theming/apply-dark.scss | 1 + .../scss/bootstrap/theming/apply-light.scss | 1 + 6 files changed, 13 insertions(+), 17 deletions(-) delete mode 100644 apps/app/src/styles/_dropdown.scss create mode 100644 packages/core-styles/scss/bootstrap/theming/_dropdown-dark.scss create mode 100644 packages/core-styles/scss/bootstrap/theming/_dropdown-light.scss diff --git a/apps/app/src/styles/_dropdown.scss b/apps/app/src/styles/_dropdown.scss deleted file mode 100644 index 07c8bd0914d..00000000000 --- a/apps/app/src/styles/_dropdown.scss +++ /dev/null @@ -1,16 +0,0 @@ -@use '@growi/core-styles/scss/bootstrap/init' as bs; - - -// == Colors -@include bs.color-mode(light) { - .dropdown-item:active{ - --bs-dropdown-link-active-color: #{( bs.$gray-600 )}; - --bs-dropdown-link-active-bg: #{( bs.$gray-200 )}; - } -} - -@include bs.color-mode(dark) { - .dropdown-item:active{ - --bs-dropdown-link-active-bg: #{( bs.$gray-700 )}; - } -} diff --git a/apps/app/src/styles/style-app.scss b/apps/app/src/styles/style-app.scss index 58aeb6f06e6..39f71b3fc6f 100644 --- a/apps/app/src/styles/style-app.scss +++ b/apps/app/src/styles/style-app.scss @@ -26,7 +26,6 @@ @import 'modal'; @import 'share-link'; @import 'marker'; -@import 'dropdown'; /* * for Guest User Mode diff --git a/packages/core-styles/scss/bootstrap/theming/_dropdown-dark.scss b/packages/core-styles/scss/bootstrap/theming/_dropdown-dark.scss new file mode 100644 index 00000000000..9ed2c53ac6a --- /dev/null +++ b/packages/core-styles/scss/bootstrap/theming/_dropdown-dark.scss @@ -0,0 +1,5 @@ +@use '@growi/core-styles/scss/bootstrap/init' as bs; + +.dropdown-item:active{ + --bs-dropdown-link-active-bg: #{( bs.$gray-700 )}; +} diff --git a/packages/core-styles/scss/bootstrap/theming/_dropdown-light.scss b/packages/core-styles/scss/bootstrap/theming/_dropdown-light.scss new file mode 100644 index 00000000000..37bdfcc4d6d --- /dev/null +++ b/packages/core-styles/scss/bootstrap/theming/_dropdown-light.scss @@ -0,0 +1,6 @@ +@use '@growi/core-styles/scss/bootstrap/init' as bs; + +.dropdown-item:active{ + --bs-dropdown-link-active-color: #{( bs.$gray-600 )}; + --bs-dropdown-link-active-bg: #{( bs.$gray-200 )}; +} diff --git a/packages/core-styles/scss/bootstrap/theming/apply-dark.scss b/packages/core-styles/scss/bootstrap/theming/apply-dark.scss index b865a11c9bc..e0606b2ae67 100644 --- a/packages/core-styles/scss/bootstrap/theming/apply-dark.scss +++ b/packages/core-styles/scss/bootstrap/theming/apply-dark.scss @@ -5,3 +5,4 @@ @import './pagination'; @import './progress'; @import './list-group'; +@import './dropdown-dark'; diff --git a/packages/core-styles/scss/bootstrap/theming/apply-light.scss b/packages/core-styles/scss/bootstrap/theming/apply-light.scss index ccbdfdf640a..630e4de1241 100644 --- a/packages/core-styles/scss/bootstrap/theming/apply-light.scss +++ b/packages/core-styles/scss/bootstrap/theming/apply-light.scss @@ -5,3 +5,4 @@ @import './pagination'; @import './progress'; @import './list-group'; +@import './dropdown-light'; From 8d2559760fc44b3174f74707378bec94ea4ece1b Mon Sep 17 00:00:00 2001 From: shironegi39 Date: Fri, 13 Sep 2024 01:10:17 +0000 Subject: [PATCH 174/490] fix Variable --- apps/app/public/static/locales/en_US/commons.json | 2 +- apps/app/public/static/locales/fr_FR/commons.json | 2 +- apps/app/public/static/locales/ja_JP/commons.json | 2 +- apps/app/public/static/locales/zh_CN/commons.json | 2 +- apps/app/src/client/components/Admin/G2GDataTransfer.tsx | 6 +++--- apps/app/src/client/components/DataTransferForm.tsx | 6 +++--- apps/app/src/stores-universal/context.tsx | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/apps/app/public/static/locales/en_US/commons.json b/apps/app/public/static/locales/en_US/commons.json index 3e9e92d8e9c..3c4a41f028f 100644 --- a/apps/app/public/static/locales/en_US/commons.json +++ b/apps/app/public/static/locales/en_US/commons.json @@ -157,6 +157,6 @@ "publish_transfer_key": "Publish transfer key", "transfer_key_limit": "Transfer keys are valid for 1 hour after issuance.", "once_transfer_key_used": "Once the transfer key is used for transfer, it cannot be used for any other transfer.", - "transfer_to_growi_cloud": "For more details, please click here." + "transfer_to_growi_cloud": "For more details, please click here." } } diff --git a/apps/app/public/static/locales/fr_FR/commons.json b/apps/app/public/static/locales/fr_FR/commons.json index 205f1532148..32a394618e6 100644 --- a/apps/app/public/static/locales/fr_FR/commons.json +++ b/apps/app/public/static/locales/fr_FR/commons.json @@ -157,6 +157,6 @@ "publish_transfer_key": "Publier la clé de transfert", "transfer_key_limit": "Les clés de transfert sont valides durant une heure.", "once_transfer_key_used": "Les clés de transfert sont à usage unique.", - "transfer_to_growi_cloud": "Pour plus de détails, veuillez cliquer ici." + "transfer_to_growi_cloud": "Pour plus de détails, veuillez cliquer ici." } } diff --git a/apps/app/public/static/locales/ja_JP/commons.json b/apps/app/public/static/locales/ja_JP/commons.json index cd201e5ec03..2dce88cacf5 100644 --- a/apps/app/public/static/locales/ja_JP/commons.json +++ b/apps/app/public/static/locales/ja_JP/commons.json @@ -159,6 +159,6 @@ "publish_transfer_key": "移行キーを発行する", "transfer_key_limit": "※ 移行キーの有効期限は発行から1時間となります。", "once_transfer_key_used": "※ 移行キーは一度移行に利用するとそれ以降はご利用いただけなくなります。", - "transfer_to_growi_cloud": "※ 詳しくは こちら" + "transfer_to_growi_cloud": "※ 詳しくは こちら" } } diff --git a/apps/app/public/static/locales/zh_CN/commons.json b/apps/app/public/static/locales/zh_CN/commons.json index 677f7c63bca..11c0c595de3 100644 --- a/apps/app/public/static/locales/zh_CN/commons.json +++ b/apps/app/public/static/locales/zh_CN/commons.json @@ -160,6 +160,6 @@ "publish_transfer_key": "发布迁移密钥", "transfer_key_limit": "迁移密钥在签发后一小时内有效。", "once_transfer_key_used": "一旦迁移密钥被用于迁移,它将不再可用于进一步的迁移。", - "transfer_to_growi_cloud": "有关更多详情,请点击此处。" + "transfer_to_growi_cloud": "有关更多详情,请点击此处。" } } diff --git a/apps/app/src/client/components/Admin/G2GDataTransfer.tsx b/apps/app/src/client/components/Admin/G2GDataTransfer.tsx index 515d1b6d0bc..df2c2922775 100644 --- a/apps/app/src/client/components/Admin/G2GDataTransfer.tsx +++ b/apps/app/src/client/components/Admin/G2GDataTransfer.tsx @@ -8,7 +8,7 @@ import { useGenerateTransferKey } from '~/client/services/g2g-transfer'; import { apiv3Get, apiv3Post } from '~/client/util/apiv3-client'; import { toastError, toastSuccess } from '~/client/util/toastr'; import { G2G_PROGRESS_STATUS, type G2GProgress } from '~/interfaces/g2g-transfer'; -import { useGrowiHelpDomain } from '~/stores-universal/context'; +import { useGrowiDocumentationUrl } from '~/stores-universal/context'; import { useAdminSocket } from '~/stores/socket-io'; import CustomCopyToClipBoard from '../Common/CustomCopyToClipBoard'; @@ -124,7 +124,7 @@ const G2GDataTransfer = (): JSX.Element => { } }, [setTransferring, startTransferKey, selectedCollections, optionsMap]); - const { data: growiHelpDomain } = useGrowiHelpDomain(); + const { data: documentationUrl } = useGrowiDocumentationUrl(); // File upload // const onChangeFileUploadTypeHandler = useCallback((e: ChangeEvent, type: string) => { @@ -279,7 +279,7 @@ const G2GDataTransfer = (): JSX.Element => {

                  {t('commons:g2g_data_transfer.transfer_key_limit')}

                  {t('commons:g2g_data_transfer.once_transfer_key_used')}

                  {/* eslint-disable-next-line react/no-danger */} -

                  +

                  ); diff --git a/apps/app/src/client/components/DataTransferForm.tsx b/apps/app/src/client/components/DataTransferForm.tsx index e52a0609f98..a552325f150 100644 --- a/apps/app/src/client/components/DataTransferForm.tsx +++ b/apps/app/src/client/components/DataTransferForm.tsx @@ -3,14 +3,14 @@ import React from 'react'; import { useTranslation } from 'next-i18next'; import { useGenerateTransferKey } from '~/client/services/g2g-transfer'; -import { useGrowiHelpDomain } from '~/stores-universal/context'; +import { useGrowiDocumentationUrl } from '~/stores-universal/context'; import CustomCopyToClipBoard from './Common/CustomCopyToClipBoard'; const DataTransferForm = (): JSX.Element => { const { t } = useTranslation('commons'); const { transferKey, generateTransferKey } = useGenerateTransferKey(); - const { data: growiHelpDomain } = useGrowiHelpDomain(); + const { data: documentationUrl } = useGrowiDocumentationUrl(); return (
                  @@ -36,7 +36,7 @@ const DataTransferForm = (): JSX.Element => {

                  {t('g2g_data_transfer.transfer_key_limit')}

                  {t('g2g_data_transfer.once_transfer_key_used')}

                  {/* eslint-disable-next-line react/no-danger */} -

                  +

                  ); diff --git a/apps/app/src/stores-universal/context.tsx b/apps/app/src/stores-universal/context.tsx index c0c3046bede..613d028969c 100644 --- a/apps/app/src/stores-universal/context.tsx +++ b/apps/app/src/stores-universal/context.tsx @@ -286,7 +286,7 @@ export const useAcceptedUploadFileType = (): SWRResponse => { +export const useGrowiDocumentationUrl = (): SWRResponse<'growi.cloud/help' | 'docs.growi.org', Error> => { const { data: growiCloudUri } = useGrowiCloudUri(); const { data: growiAppIdForGrowiCloud } = useGrowiAppIdForGrowiCloud(); From 96eb778f417f50c4ea6272ad41301a67c51f6136 Mon Sep 17 00:00:00 2001 From: shironegi39 Date: Fri, 13 Sep 2024 01:29:11 +0000 Subject: [PATCH 175/490] fix SWRHook --- apps/app/src/stores-universal/context.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/app/src/stores-universal/context.tsx b/apps/app/src/stores-universal/context.tsx index 613d028969c..6ed2f25dd41 100644 --- a/apps/app/src/stores-universal/context.tsx +++ b/apps/app/src/stores-universal/context.tsx @@ -291,7 +291,7 @@ export const useGrowiDocumentationUrl = (): SWRResponse<'growi.cloud/help' | 'do const { data: growiAppIdForGrowiCloud } = useGrowiAppIdForGrowiCloud(); return useSWRImmutable( - [growiCloudUri, growiAppIdForGrowiCloud], + ['growiDocumentationUrl', growiCloudUri, growiAppIdForGrowiCloud], ([growiCloudUri, growiAppIdForGrowiCloud]) => { if (growiCloudUri != null && growiAppIdForGrowiCloud != null) { return 'growi.cloud/help'; From dbb2ff30151761c42811f233925db5ded5caf918 Mon Sep 17 00:00:00 2001 From: shironegi39 Date: Fri, 13 Sep 2024 01:40:12 +0000 Subject: [PATCH 176/490] fix Hook --- apps/app/src/stores-universal/context.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/app/src/stores-universal/context.tsx b/apps/app/src/stores-universal/context.tsx index 6ed2f25dd41..bdf619940ec 100644 --- a/apps/app/src/stores-universal/context.tsx +++ b/apps/app/src/stores-universal/context.tsx @@ -291,7 +291,7 @@ export const useGrowiDocumentationUrl = (): SWRResponse<'growi.cloud/help' | 'do const { data: growiAppIdForGrowiCloud } = useGrowiAppIdForGrowiCloud(); return useSWRImmutable( - ['growiDocumentationUrl', growiCloudUri, growiAppIdForGrowiCloud], + ['documentationUrl', growiCloudUri, growiAppIdForGrowiCloud], ([growiCloudUri, growiAppIdForGrowiCloud]) => { if (growiCloudUri != null && growiAppIdForGrowiCloud != null) { return 'growi.cloud/help'; From 81f62eac934607953878e9593fb7535a807ec33b Mon Sep 17 00:00:00 2001 From: Shun Miyazawa Date: Fri, 13 Sep 2024 02:13:51 +0000 Subject: [PATCH 177/490] Implement OpenAI menu --- .../public/static/locales/en_US/admin.json | 3 ++ .../public/static/locales/fr_FR/admin.json | 3 ++ .../public/static/locales/ja_JP/admin.json | 3 ++ .../public/static/locales/zh_CN/admin.json | 3 ++ .../Admin/Common/AdminNavigation.tsx | 3 ++ apps/app/src/pages/admin/openai.page.tsx | 50 +++++++++++++++++++ 6 files changed, 65 insertions(+) create mode 100644 apps/app/src/pages/admin/openai.page.tsx diff --git a/apps/app/public/static/locales/en_US/admin.json b/apps/app/public/static/locales/en_US/admin.json index 09433239904..9f342267c9b 100644 --- a/apps/app/public/static/locales/en_US/admin.json +++ b/apps/app/public/static/locales/en_US/admin.json @@ -1132,5 +1132,8 @@ }, "forbidden_page": { "do_not_have_admin_permission": "Users without administrative rights cannot access the administration screen" + }, + "openai_management": { + "openai_management": "OpenAI Management" } } diff --git a/apps/app/public/static/locales/fr_FR/admin.json b/apps/app/public/static/locales/fr_FR/admin.json index 039612cce57..f09cf973568 100644 --- a/apps/app/public/static/locales/fr_FR/admin.json +++ b/apps/app/public/static/locales/fr_FR/admin.json @@ -1131,5 +1131,8 @@ }, "forbidden_page": { "do_not_have_admin_permission": "Seul les administrateurs peuvent accéder à cette page." + }, + "openai_management": { + "openai_management": "Gestion de l'OpenAI" } } diff --git a/apps/app/public/static/locales/ja_JP/admin.json b/apps/app/public/static/locales/ja_JP/admin.json index f8933ec5ea6..1cd685920fc 100644 --- a/apps/app/public/static/locales/ja_JP/admin.json +++ b/apps/app/public/static/locales/ja_JP/admin.json @@ -1142,5 +1142,8 @@ }, "forbidden_page": { "do_not_have_admin_permission": "管理者権限のないユーザーでは管理画面にはアクセスできません" + }, + "openai_management": { + "openai_management": "OpenAI 管理" } } diff --git a/apps/app/public/static/locales/zh_CN/admin.json b/apps/app/public/static/locales/zh_CN/admin.json index 4eeb37300cd..8fba679e006 100644 --- a/apps/app/public/static/locales/zh_CN/admin.json +++ b/apps/app/public/static/locales/zh_CN/admin.json @@ -1141,5 +1141,8 @@ }, "forbidden_page": { "do_not_have_admin_permission": "没有管理权限的用户无法访问管理屏幕" + }, + "openai_management": { + "openai_management": "OpenAI 管理层" } } diff --git a/apps/app/src/components/Admin/Common/AdminNavigation.tsx b/apps/app/src/components/Admin/Common/AdminNavigation.tsx index aca4e1ed54a..d51940889b8 100644 --- a/apps/app/src/components/Admin/Common/AdminNavigation.tsx +++ b/apps/app/src/components/Admin/Common/AdminNavigation.tsx @@ -32,6 +32,7 @@ const MenuLabel = ({ menu }: { menu: string }) => { case 'user-groups': return <>group{ t('user_group_management.user_group_management') }; case 'audit-log': return <>feed{ t('audit_log_management.audit_log')}; case 'plugins': return <>extension{ t('plugins.plugins')}; + case 'openai': return <>psychology{ t('openai_management.openai_management')}; case 'search': return <>search{ t('full_text_search_management.full_text_search_management') }; case 'cloud': return <>share{ t('cloud_setting_management.to_cloud_settings')} ; default: return <>home{ t('wiki_management_homepage') }; @@ -106,6 +107,7 @@ export const AdminNavigation = (): JSX.Element => { + {growiCloudUri != null && growiAppIdForGrowiCloud != null && ( @@ -159,6 +161,7 @@ export const AdminNavigation = (): JSX.Element => { {isActiveMenu('/audit-log') && } {isActiveMenu('/plugins') && } {isActiveMenu('/data-transfer') && } + {isActiveMenu('/oepnai') && } {/* eslint-enable no-multi-spaces */} diff --git a/apps/app/src/pages/admin/openai.page.tsx b/apps/app/src/pages/admin/openai.page.tsx new file mode 100644 index 00000000000..582fd94d6e4 --- /dev/null +++ b/apps/app/src/pages/admin/openai.page.tsx @@ -0,0 +1,50 @@ +import type { + NextPage, GetServerSideProps, GetServerSidePropsContext, +} from 'next'; +import { useTranslation } from 'next-i18next'; +import dynamic from 'next/dynamic'; +import Head from 'next/head'; + +import type { CrowiRequest } from '~/interfaces/crowi-request'; +import type { CommonProps } from '~/pages/utils/commons'; +import { generateCustomTitle } from '~/pages/utils/commons'; + +import { retrieveServerSideProps } from '../../utils/admin-page-util'; + +const AdminLayout = dynamic(() => import('~/components/Layout/AdminLayout'), { ssr: false }); +const ForbiddenPage = dynamic(() => import('~/client/components/Admin/ForbiddenPage').then(mod => mod.ForbiddenPage), { ssr: false }); + +type Props = CommonProps & { + // +}; + +const AdminOpenaiPage: NextPage = (props) => { + const { t } = useTranslation('admin'); + + const title = t('openai_management.openai_management'); + const headTitle = generateCustomTitle(props, title); + + if (props.isAccessDeniedForNonAdminUser) { + return ; + } + + return ( + + + {headTitle} + + + ); +}; + +const injectServerConfigurations = async(context: GetServerSidePropsContext, props: Props): Promise => { + const req: CrowiRequest = context.req as CrowiRequest; + const { crowi } = req; +}; + +export const getServerSideProps: GetServerSideProps = async(context: GetServerSidePropsContext) => { + const props = await retrieveServerSideProps(context, injectServerConfigurations); + return props; +}; + +export default AdminOpenaiPage; From d2a811f401f63f2d3871924978852110a212cd39 Mon Sep 17 00:00:00 2001 From: nHigashiWeseek Date: Fri, 13 Sep 2024 03:14:17 +0000 Subject: [PATCH 178/490] convert to original --- .../src/client/components/PageDeleteModal.tsx | 6 ++---- .../src/client/components/PageDuplicateModal.tsx | 14 ++------------ .../src/client/components/PageRenameModal.tsx | 16 +--------------- .../src/client/components/PutbackPageModal.jsx | 5 ----- .../services/create-page/use-create-page.tsx | 13 +------------ .../services/update-page/use-update-page.tsx | 6 ++---- .../PageView/PageAlerts/WipPageAlert.tsx | 7 +------ 7 files changed, 9 insertions(+), 58 deletions(-) diff --git a/apps/app/src/client/components/PageDeleteModal.tsx b/apps/app/src/client/components/PageDeleteModal.tsx index 96415532cc0..d8c9a168931 100644 --- a/apps/app/src/client/components/PageDeleteModal.tsx +++ b/apps/app/src/client/components/PageDeleteModal.tsx @@ -17,9 +17,10 @@ import { apiPost } from '~/client/util/apiv1-client'; import { apiv3Post } from '~/client/util/apiv3-client'; import type { IDeleteSinglePageApiv1Result, IDeleteManyPageApiv3Result } from '~/interfaces/page'; import { usePageDeleteModal } from '~/stores/modal'; -import { useSWRxPageInfoForList, useSWRINFxRecentlyUpdated } from '~/stores/page-listing'; +import { useSWRxPageInfoForList } from '~/stores/page-listing'; import loggerFactory from '~/utils/logger'; + import ApiErrorMessageList from './PageManagement/ApiErrorMessageList'; const { isTrashPage } = pagePathUtils; @@ -50,7 +51,6 @@ const PageDeleteModal: FC = () => { const { t } = useTranslation(); const { data: deleteModalData, close: closeDeleteModal } = usePageDeleteModal(); - const { mutate: mutateRecentlyUpdated } = useSWRINFxRecentlyUpdated(20, true); const isOpened = deleteModalData?.isOpened ?? false; @@ -146,7 +146,6 @@ const PageDeleteModal: FC = () => { onDeleted(data.paths, data.isRecursively, data.isCompletely); } closeDeleteModal(); - mutateRecentlyUpdated(); } catch (err) { setErrs([err]); @@ -175,7 +174,6 @@ const PageDeleteModal: FC = () => { } closeDeleteModal(); - mutateRecentlyUpdated(); } catch (err) { setErrs([err]); diff --git a/apps/app/src/client/components/PageDuplicateModal.tsx b/apps/app/src/client/components/PageDuplicateModal.tsx index 066f1db0d23..5b4c2708e9a 100644 --- a/apps/app/src/client/components/PageDuplicateModal.tsx +++ b/apps/app/src/client/components/PageDuplicateModal.tsx @@ -12,12 +12,12 @@ import { apiv3Get, apiv3Post } from '~/client/util/apiv3-client'; import { toastError } from '~/client/util/toastr'; import { useIsSearchServiceReachable, useSiteUrl } from '~/stores-universal/context'; import { usePageDuplicateModal } from '~/stores/modal'; -import { useSWRINFxRecentlyUpdated } from '~/stores/page-listing'; import DuplicatePathsTable from './DuplicatedPathsTable'; import ApiErrorMessageList from './PageManagement/ApiErrorMessageList'; import PagePathAutoComplete from './PagePathAutoComplete'; + const PageDuplicateModal = (): JSX.Element => { const { t } = useTranslation(); @@ -38,7 +38,6 @@ const PageDuplicateModal = (): JSX.Element => { const [isDuplicateRecursively, setIsDuplicateRecursively] = useState(true); const [isDuplicateRecursivelyWithoutExistPath, setIsDuplicateRecursivelyWithoutExistPath] = useState(true); const [onlyDuplicateUserRelatedResources, setOnlyDuplicateUserRelatedResources] = useState(false); - const { mutate: mutateRecentlyUpdated } = useSWRINFxRecentlyUpdated(20, true); const updateSubordinatedList = useCallback(async() => { if (page == null) { @@ -127,20 +126,11 @@ const PageDuplicateModal = (): JSX.Element => { onDuplicated(fromPath, toPath); } closeDuplicateModal(); - mutateRecentlyUpdated(); } catch (err) { setErrs(err); } - }, [ - closeDuplicateModal, - duplicateModalData?.opts?.onDuplicated, - isDuplicateRecursively, - page, - pageNameInput, - onlyDuplicateUserRelatedResources, - mutateRecentlyUpdated, - ]); + }, [closeDuplicateModal, duplicateModalData?.opts?.onDuplicated, isDuplicateRecursively, page, pageNameInput, onlyDuplicateUserRelatedResources]); useEffect(() => { if (isOpened) { diff --git a/apps/app/src/client/components/PageRenameModal.tsx b/apps/app/src/client/components/PageRenameModal.tsx index 3c39b4249db..9a81275e70c 100644 --- a/apps/app/src/client/components/PageRenameModal.tsx +++ b/apps/app/src/client/components/PageRenameModal.tsx @@ -15,7 +15,6 @@ import { toastError } from '~/client/util/toastr'; import { useSiteUrl, useIsSearchServiceReachable } from '~/stores-universal/context'; import { usePageRenameModal } from '~/stores/modal'; import { useSWRxPageInfo } from '~/stores/page'; -import { useSWRINFxRecentlyUpdated } from '~/stores/page-listing'; import DuplicatedPathsTable from './DuplicatedPathsTable'; import ApiErrorMessageList from './PageManagement/ApiErrorMessageList'; @@ -40,8 +39,6 @@ const PageRenameModal = (): JSX.Element => { const shouldFetch = isOpened && page != null && !isIPageInfoForEntity(page.meta); const { data: pageInfo } = useSWRxPageInfo(shouldFetch ? page?.data._id : null); - const { mutate: mutateRecentlyUpdated } = useSWRINFxRecentlyUpdated(20, true); - if (page != null && pageInfo != null) { page.meta = pageInfo; } @@ -124,22 +121,11 @@ const PageRenameModal = (): JSX.Element => { onRenamed(path); } closeRenameModal(); - mutateRecentlyUpdated(); } catch (err) { setErrs(err); } - }, [ - closeRenameModal, - canRename, - isRemainMetadata, - isRenameRecursively, - isRenameRedirect, - page, - pageNameInput, - renameModalData?.opts?.onRenamed, - mutateRecentlyUpdated, - ]); + }, [closeRenameModal, canRename, isRemainMetadata, isRenameRecursively, isRenameRedirect, page, pageNameInput, renameModalData?.opts?.onRenamed]); const checkExistPaths = useCallback(async(fromPath, toPath) => { if (page == null) { diff --git a/apps/app/src/client/components/PutbackPageModal.jsx b/apps/app/src/client/components/PutbackPageModal.jsx index cbcbf7341fb..c34dfadd733 100644 --- a/apps/app/src/client/components/PutbackPageModal.jsx +++ b/apps/app/src/client/components/PutbackPageModal.jsx @@ -9,8 +9,6 @@ import { import { apiPost } from '~/client/util/apiv1-client'; import { usePutBackPageModal } from '~/stores/modal'; import { mutateAllPageInfo } from '~/stores/page'; -import { useSWRINFxRecentlyUpdated } from '~/stores/page-listing'; - import ApiErrorMessageList from './PageManagement/ApiErrorMessageList'; @@ -27,8 +25,6 @@ const PutBackPageModal = () => { const [isPutbackRecursively, setIsPutbackRecursively] = useState(true); - const { mutate: mutateRecentlyUpdated } = useSWRINFxRecentlyUpdated(20, true); - function changeIsPutbackRecursivelyHandler() { setIsPutbackRecursively(!isPutbackRecursively); } @@ -51,7 +47,6 @@ const PutBackPageModal = () => { onPutBacked(response.page.path); } closePutBackPageModal(); - mutateRecentlyUpdated(); } catch (err) { setTargetPath(err.data); diff --git a/apps/app/src/client/services/create-page/use-create-page.tsx b/apps/app/src/client/services/create-page/use-create-page.tsx index 568d1bc83e6..306e6b8a091 100644 --- a/apps/app/src/client/services/create-page/use-create-page.tsx +++ b/apps/app/src/client/services/create-page/use-create-page.tsx @@ -9,7 +9,6 @@ import type { IApiv3PageCreateParams } from '~/interfaces/apiv3'; import { EditorMode, useEditorMode } from '~/stores-universal/ui'; import { useGrantedGroupsInheritanceSelectModal } from '~/stores/modal'; import { useCurrentPagePath } from '~/stores/page'; -import { useSWRINFxRecentlyUpdated } from '~/stores/page-listing'; import { useIsUntitledPage } from '~/stores/ui'; import { createPage } from './create-page'; @@ -58,8 +57,6 @@ export const useCreatePage: UseCreatePage = () => { const [isCreating, setCreating] = useState(false); - const { mutate: mutateRecentlyUpdated } = useSWRINFxRecentlyUpdated(20, true); - const create: CreatePage = useCallback(async(params, opts = {}) => { const { onCreationStart, onCreated, onAborted, onTerminated, @@ -117,7 +114,6 @@ export const useCreatePage: UseCreatePage = () => { } onCreated?.(); - mutateRecentlyUpdated(); } catch (err) { throw err; @@ -139,14 +135,7 @@ export const useCreatePage: UseCreatePage = () => { } await _create(); - }, [ - currentPagePath, - mutateEditorMode, - router, t, - closeGrantedGroupsInheritanceSelectModal, - mutateIsUntitledPage, openGrantedGroupsInheritanceSelectModal, - mutateRecentlyUpdated, - ]); + }, [currentPagePath, mutateEditorMode, router, t, closeGrantedGroupsInheritanceSelectModal, mutateIsUntitledPage, openGrantedGroupsInheritanceSelectModal]); return { isCreating, diff --git a/apps/app/src/client/services/update-page/use-update-page.tsx b/apps/app/src/client/services/update-page/use-update-page.tsx index 074e7690fea..7764991c394 100644 --- a/apps/app/src/client/services/update-page/use-update-page.tsx +++ b/apps/app/src/client/services/update-page/use-update-page.tsx @@ -1,7 +1,6 @@ import { useCallback } from 'react'; import type { IApiv3PageUpdateParams, IApiv3PageUpdateResponse } from '~/interfaces/apiv3'; -import { useSWRINFxRecentlyUpdated } from '~/stores/page-listing'; import { useIsUntitledPage } from '~/stores/ui'; import { updatePage } from './update-page'; @@ -12,16 +11,15 @@ type UseUpdatePage = (params: IApiv3PageUpdateParams) => Promise { const { mutate: mutateUntitledPage } = useIsUntitledPage(); - const { mutate: mutateRecentlyUpdated } = useSWRINFxRecentlyUpdated(20, true); + const updatePageExt: UseUpdatePage = useCallback(async(params) => { const result = await updatePage(params); // set false to isUntitledPage mutateUntitledPage(false); - mutateRecentlyUpdated(); return result; - }, [mutateUntitledPage, mutateRecentlyUpdated]); + }, [mutateUntitledPage]); return updatePageExt; }; diff --git a/apps/app/src/components/PageView/PageAlerts/WipPageAlert.tsx b/apps/app/src/components/PageView/PageAlerts/WipPageAlert.tsx index 65b8312a94b..83afa5f82b0 100644 --- a/apps/app/src/components/PageView/PageAlerts/WipPageAlert.tsx +++ b/apps/app/src/components/PageView/PageAlerts/WipPageAlert.tsx @@ -3,15 +3,12 @@ import React, { useCallback } from 'react'; import { useTranslation } from 'react-i18next'; import { useSWRMUTxCurrentPage, useSWRxCurrentPage } from '~/stores/page'; -import { useSWRINFxRecentlyUpdated } from '~/stores/page-listing'; export const WipPageAlert = (): JSX.Element => { const { t } = useTranslation(); const { data: currentPage } = useSWRxCurrentPage(); const { trigger: mutateCurrentPage } = useSWRMUTxCurrentPage(); - const { mutate: mutateRecentlyUpdated } = useSWRINFxRecentlyUpdated(20, true); - const clickPagePublishButton = useCallback(async() => { const pageId = currentPage?._id; @@ -31,14 +28,12 @@ export const WipPageAlert = (): JSX.Element => { const toastSuccess = (await import('~/client/util/toastr')).toastSuccess; toastSuccess(t('wip_page.success_publish_page')); - - mutateRecentlyUpdated(); } catch { const toastError = (await import('~/client/util/toastr')).toastError; toastError(t('wip_page.fail_publish_page')); } - }, [currentPage?._id, mutateCurrentPage, t, mutateRecentlyUpdated]); + }, [currentPage?._id, mutateCurrentPage, t]); if (!currentPage?.wip) { From ffd1c0ab70898984a44b7c62e13812207be1d840 Mon Sep 17 00:00:00 2001 From: moekumasaka Date: Fri, 13 Sep 2024 04:25:56 +0000 Subject: [PATCH 179/490] =?UTF-8?q?tab=20=E3=82=92=20dropdown=20list=20?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Admin/Notification/NotificationSetting.jsx | 10 ++++++++-- .../components/CustomNavigation/CustomNav.module.scss | 3 +++ .../client/components/CustomNavigation/CustomNav.tsx | 6 +++--- .../src/client/components/DescendantsPageListModal.tsx | 5 +++-- 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/apps/app/src/client/components/Admin/Notification/NotificationSetting.jsx b/apps/app/src/client/components/Admin/Notification/NotificationSetting.jsx index 357d214912c..b9dc3314c4a 100644 --- a/apps/app/src/client/components/Admin/Notification/NotificationSetting.jsx +++ b/apps/app/src/client/components/Admin/Notification/NotificationSetting.jsx @@ -14,7 +14,7 @@ import { toastError } from '~/client/util/toastr'; import { toArrayIfNot } from '~/utils/array-utils'; import loggerFactory from '~/utils/logger'; -import { CustomNavTab } from '../../CustomNavigation/CustomNav'; +import CustomNav from '../../CustomNavigation/CustomNav'; import { withUnstatedContainers } from '../../UnstatedUtils'; @@ -155,7 +155,13 @@ function NotificationSetting(props) {

                  {t('notification_settings.notification_settings')}

                  - + diff --git a/apps/app/src/client/components/CustomNavigation/CustomNav.module.scss b/apps/app/src/client/components/CustomNavigation/CustomNav.module.scss index 0b5ae9b999b..2accc25615e 100644 --- a/apps/app/src/client/components/CustomNavigation/CustomNav.module.scss +++ b/apps/app/src/client/components/CustomNavigation/CustomNav.module.scss @@ -14,5 +14,8 @@ border-bottom: 3px solid; transition: 0.3s ease-in-out; } +} +.dropdown-menu :global { + width: 100%; } diff --git a/apps/app/src/client/components/CustomNavigation/CustomNav.tsx b/apps/app/src/client/components/CustomNavigation/CustomNav.tsx index 6a4090bf96e..06e33549d40 100644 --- a/apps/app/src/client/components/CustomNavigation/CustomNav.tsx +++ b/apps/app/src/client/components/CustomNavigation/CustomNav.tsx @@ -61,7 +61,7 @@ export const CustomNavDropdown = (props: CustomNavDropdownProps): JSX.Element => { Icon != null && } {i18n} -
                  +
                  {Object.entries(navTabMapping).map(([key, value]) => { const isActive = activeTab === key; @@ -162,8 +162,8 @@ export const CustomNavTab = (props: CustomNavTabProps): JSX.Element => { const inactiveClassnames: string[] = []; if (breakpointToHideInactiveTabsDown != null) { const breakpointOneLevelLarger = getBreakpointOneLevelLarger(breakpointToHideInactiveTabsDown); - inactiveClassnames.push('d-none'); - inactiveClassnames.push(`d-${breakpointOneLevelLarger}-block`); + // inactiveClassnames.push('d-none'); + // inactiveClassnames.push(`d-${breakpointOneLevelLarger}-block`); } return ( diff --git a/apps/app/src/client/components/DescendantsPageListModal.tsx b/apps/app/src/client/components/DescendantsPageListModal.tsx index 93a29fea195..8b151070c37 100644 --- a/apps/app/src/client/components/DescendantsPageListModal.tsx +++ b/apps/app/src/client/components/DescendantsPageListModal.tsx @@ -11,7 +11,7 @@ import { import { useIsSharedUser } from '~/stores-universal/context'; import { useDescendantsPageListModal } from '~/stores/modal'; -import { CustomNavTab } from './CustomNavigation/CustomNav'; +import CustomNav, { CustomNavTab } from './CustomNavigation/CustomNav'; import CustomTabContent from './CustomNavigation/CustomTabContent'; import type { DescendantsPageListProps } from './DescendantsPageList'; import ExpandOrContractButton from './ExpandOrContractButton'; @@ -94,10 +94,11 @@ export const DescendantsPageListModal = (): JSX.Element => { className={`grw-descendants-page-list-modal ${styles['grw-descendants-page-list-modal']} ${isWindowExpanded ? 'grw-modal-expanded' : ''} `} > - setActiveTab(v)} hideBorderBottom /> From dad37dd5367315bcb29efb2a63f3edaf1c1cc3ba Mon Sep 17 00:00:00 2001 From: WNomunomu Date: Fri, 13 Sep 2024 05:40:54 +0000 Subject: [PATCH 180/490] add prefix --- .../core-styles/scss/bootstrap/theming/_dropdown-dark.scss | 2 +- .../core-styles/scss/bootstrap/theming/_dropdown-light.scss | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/core-styles/scss/bootstrap/theming/_dropdown-dark.scss b/packages/core-styles/scss/bootstrap/theming/_dropdown-dark.scss index 9ed2c53ac6a..0bc530340a5 100644 --- a/packages/core-styles/scss/bootstrap/theming/_dropdown-dark.scss +++ b/packages/core-styles/scss/bootstrap/theming/_dropdown-dark.scss @@ -1,5 +1,5 @@ @use '@growi/core-styles/scss/bootstrap/init' as bs; .dropdown-item:active{ - --bs-dropdown-link-active-bg: #{( bs.$gray-700 )}; + --#{$prefix}dropdown-link-active-bg: #{( bs.$gray-700 )}; } diff --git a/packages/core-styles/scss/bootstrap/theming/_dropdown-light.scss b/packages/core-styles/scss/bootstrap/theming/_dropdown-light.scss index 37bdfcc4d6d..a207b0154ac 100644 --- a/packages/core-styles/scss/bootstrap/theming/_dropdown-light.scss +++ b/packages/core-styles/scss/bootstrap/theming/_dropdown-light.scss @@ -1,6 +1,6 @@ @use '@growi/core-styles/scss/bootstrap/init' as bs; .dropdown-item:active{ - --bs-dropdown-link-active-color: #{( bs.$gray-600 )}; - --bs-dropdown-link-active-bg: #{( bs.$gray-200 )}; + --#{$prefix}dropdown-link-active-color: #{( bs.$gray-600 )}; + --#{$prefix}dropdown-link-active-bg: #{( bs.$gray-200 )}; } From 0cf029b2ce7cf9c19176accbfb90b6f2bc491a9c Mon Sep 17 00:00:00 2001 From: Shun Miyazawa Date: Fri, 13 Sep 2024 06:05:30 +0000 Subject: [PATCH 181/490] OpenAI -> AI Search --- apps/app/public/static/locales/en_US/admin.json | 4 ++-- apps/app/public/static/locales/fr_FR/admin.json | 4 ++-- apps/app/public/static/locales/ja_JP/admin.json | 4 ++-- apps/app/public/static/locales/zh_CN/admin.json | 4 ++-- apps/app/src/components/Admin/Common/AdminNavigation.tsx | 6 +++--- .../src/pages/admin/{openai.page.tsx => ai-search.page.tsx} | 6 +++--- 6 files changed, 14 insertions(+), 14 deletions(-) rename apps/app/src/pages/admin/{openai.page.tsx => ai-search.page.tsx} (90%) diff --git a/apps/app/public/static/locales/en_US/admin.json b/apps/app/public/static/locales/en_US/admin.json index 9f342267c9b..67802a84101 100644 --- a/apps/app/public/static/locales/en_US/admin.json +++ b/apps/app/public/static/locales/en_US/admin.json @@ -1133,7 +1133,7 @@ "forbidden_page": { "do_not_have_admin_permission": "Users without administrative rights cannot access the administration screen" }, - "openai_management": { - "openai_management": "OpenAI Management" + "ai_search_management": { + "ai_search_management": "AI Search Management" } } diff --git a/apps/app/public/static/locales/fr_FR/admin.json b/apps/app/public/static/locales/fr_FR/admin.json index f09cf973568..473f98b1885 100644 --- a/apps/app/public/static/locales/fr_FR/admin.json +++ b/apps/app/public/static/locales/fr_FR/admin.json @@ -1132,7 +1132,7 @@ "forbidden_page": { "do_not_have_admin_permission": "Seul les administrateurs peuvent accéder à cette page." }, - "openai_management": { - "openai_management": "Gestion de l'OpenAI" + "ai_search_management": { + "ai_search_management": "Gestion de la recherche en IA" } } diff --git a/apps/app/public/static/locales/ja_JP/admin.json b/apps/app/public/static/locales/ja_JP/admin.json index 1cd685920fc..4ba45bf4d29 100644 --- a/apps/app/public/static/locales/ja_JP/admin.json +++ b/apps/app/public/static/locales/ja_JP/admin.json @@ -1143,7 +1143,7 @@ "forbidden_page": { "do_not_have_admin_permission": "管理者権限のないユーザーでは管理画面にはアクセスできません" }, - "openai_management": { - "openai_management": "OpenAI 管理" + "ai_search_management": { + "ai_search_management": "AI 検索管理" } } diff --git a/apps/app/public/static/locales/zh_CN/admin.json b/apps/app/public/static/locales/zh_CN/admin.json index 8fba679e006..dab22f862f7 100644 --- a/apps/app/public/static/locales/zh_CN/admin.json +++ b/apps/app/public/static/locales/zh_CN/admin.json @@ -1142,7 +1142,7 @@ "forbidden_page": { "do_not_have_admin_permission": "没有管理权限的用户无法访问管理屏幕" }, - "openai_management": { - "openai_management": "OpenAI 管理层" + "ai_search_management": { + "ai_search_management": "AI 搜索管理" } } diff --git a/apps/app/src/components/Admin/Common/AdminNavigation.tsx b/apps/app/src/components/Admin/Common/AdminNavigation.tsx index d51940889b8..71991161c8a 100644 --- a/apps/app/src/components/Admin/Common/AdminNavigation.tsx +++ b/apps/app/src/components/Admin/Common/AdminNavigation.tsx @@ -32,7 +32,7 @@ const MenuLabel = ({ menu }: { menu: string }) => { case 'user-groups': return <>group{ t('user_group_management.user_group_management') }; case 'audit-log': return <>feed{ t('audit_log_management.audit_log')}; case 'plugins': return <>extension{ t('plugins.plugins')}; - case 'openai': return <>psychology{ t('openai_management.openai_management')}; + case 'ai-search': return <>psychology{ t('ai_search_management.ai_search_management')}; case 'search': return <>search{ t('full_text_search_management.full_text_search_management') }; case 'cloud': return <>share{ t('cloud_setting_management.to_cloud_settings')} ; default: return <>home{ t('wiki_management_homepage') }; @@ -107,7 +107,7 @@ export const AdminNavigation = (): JSX.Element => { - + {growiCloudUri != null && growiAppIdForGrowiCloud != null && ( @@ -161,7 +161,7 @@ export const AdminNavigation = (): JSX.Element => { {isActiveMenu('/audit-log') && } {isActiveMenu('/plugins') && } {isActiveMenu('/data-transfer') && } - {isActiveMenu('/oepnai') && } + {isActiveMenu('/ai-search') && } {/* eslint-enable no-multi-spaces */} diff --git a/apps/app/src/pages/admin/openai.page.tsx b/apps/app/src/pages/admin/ai-search.page.tsx similarity index 90% rename from apps/app/src/pages/admin/openai.page.tsx rename to apps/app/src/pages/admin/ai-search.page.tsx index 582fd94d6e4..faa629534b5 100644 --- a/apps/app/src/pages/admin/openai.page.tsx +++ b/apps/app/src/pages/admin/ai-search.page.tsx @@ -18,10 +18,10 @@ type Props = CommonProps & { // }; -const AdminOpenaiPage: NextPage = (props) => { +const AdminAiSearchPage: NextPage = (props) => { const { t } = useTranslation('admin'); - const title = t('openai_management.openai_management'); + const title = t('ai_search_management.ai_search_management'); const headTitle = generateCustomTitle(props, title); if (props.isAccessDeniedForNonAdminUser) { @@ -47,4 +47,4 @@ export const getServerSideProps: GetServerSideProps = async(context: GetServerSi return props; }; -export default AdminOpenaiPage; +export default AdminAiSearchPage; From 3ed9f72c2bbcf8541d7399b0ad3d111903aa0747 Mon Sep 17 00:00:00 2001 From: nHigashiWeseek Date: Fri, 13 Sep 2024 06:51:42 +0000 Subject: [PATCH 182/490] add mutate to action --- .../src/client/components/DescendantsPageList.tsx | 10 ++++++---- .../Navbar/GrowiContextualSubNavigation.tsx | 9 ++++++--- .../src/client/components/PageEditor/PageEditor.tsx | 8 ++++++-- .../components/SearchPage/SearchResultContent.tsx | 13 ++++++++----- .../components/SearchPage/SearchResultList.tsx | 13 +++++++++---- .../TreeItem/NewPageInput/use-new-page-input.tsx | 9 ++++++--- .../components/PageView/PageAlerts/WipPageAlert.tsx | 8 ++++++-- 7 files changed, 47 insertions(+), 23 deletions(-) diff --git a/apps/app/src/client/components/DescendantsPageList.tsx b/apps/app/src/client/components/DescendantsPageList.tsx index 57e2aca6bc0..41824139ff4 100644 --- a/apps/app/src/client/components/DescendantsPageList.tsx +++ b/apps/app/src/client/components/DescendantsPageList.tsx @@ -14,7 +14,7 @@ import type { OnDeletedFunction, OnPutBackedFunction } from '~/interfaces/ui'; import { useIsGuestUser, useIsReadOnlyUser, useIsSharedUser } from '~/stores-universal/context'; import { mutatePageTree, - useSWRxPageInfoForList, useSWRxPageList, + useSWRxPageInfoForList, useSWRxPageList, useSWRINFxRecentlyUpdated, } from '~/stores/page-listing'; import type { ForceHideMenuItems } from './Common/Dropdown/PageItemControl'; @@ -47,6 +47,7 @@ const DescendantsPageListSubstance = (props: SubstanceProps): JSX.Element => { const pageIds = pagingResult?.items?.map(page => page._id); const { injectTo } = useSWRxPageInfoForList(pageIds, null, true, true); + const { mutate: mutateRecentlyUpdated } = useSWRINFxRecentlyUpdated(20, true); let pageWithMetas: IDataWithMeta[] = []; @@ -67,21 +68,22 @@ const DescendantsPageListSubstance = (props: SubstanceProps): JSX.Element => { else { toastSuccess(t('deleted_pages_completely', { path })); } - + mutateRecentlyUpdated(); mutatePageTree(); if (onPagesDeleted != null) { onPagesDeleted(...args); } - }, [onPagesDeleted, t]); + }, [onPagesDeleted, mutateRecentlyUpdated, t]); const pagePutBackedHandler: OnPutBackedFunction = useCallback((path) => { toastSuccess(t('page_has_been_reverted', { path })); + mutateRecentlyUpdated(); mutatePageTree(); if (onPagePutBacked != null) { onPagePutBacked(path); } - }, [onPagePutBacked, t]); + }, [onPagePutBacked, mutateRecentlyUpdated, t]); if (pagingResult == null) { return ( diff --git a/apps/app/src/client/components/Navbar/GrowiContextualSubNavigation.tsx b/apps/app/src/client/components/Navbar/GrowiContextualSubNavigation.tsx index adbb5555ef7..9a71fd51c83 100644 --- a/apps/app/src/client/components/Navbar/GrowiContextualSubNavigation.tsx +++ b/apps/app/src/client/components/Navbar/GrowiContextualSubNavigation.tsx @@ -34,7 +34,7 @@ import { import { useSWRMUTxCurrentPage, useCurrentPageId, useSWRxPageInfo, } from '~/stores/page'; -import { mutatePageTree } from '~/stores/page-listing'; +import { mutatePageTree, useSWRINFxRecentlyUpdated } from '~/stores/page-listing'; import { useIsAbleToShowPageManagement, useIsAbleToChangeEditorMode, @@ -247,6 +247,7 @@ const GrowiContextualSubNavigation = (props: GrowiContextualSubNavigationProps): const { open: openRenameModal } = usePageRenameModal(); const { open: openDeleteModal } = usePageDeleteModal(); const { mutate: mutatePageInfo } = useSWRxPageInfo(pageId); + const { mutate: mutateRecentlyUpdated } = useSWRINFxRecentlyUpdated(20, true); const [isStickyActive, setStickyActive] = useState(false); @@ -271,9 +272,10 @@ const GrowiContextualSubNavigation = (props: GrowiContextualSubNavigationProps): mutateCurrentPage(); mutatePageInfo(); mutatePageTree(); + mutateRecentlyUpdated(); }; openRenameModal(page, { onRenamed: renamedHandler }); - }, [mutateCurrentPage, mutatePageInfo, openRenameModal]); + }, [mutateCurrentPage, mutatePageInfo, openRenameModal, mutateRecentlyUpdated]); const deleteItemClickedHandler = useCallback((pageWithMeta: IPageWithMeta) => { const deletedHandler: OnDeletedFunction = (pathOrPathsToDelete, isRecursively, isCompletely) => { @@ -294,9 +296,10 @@ const GrowiContextualSubNavigation = (props: GrowiContextualSubNavigationProps): mutateCurrentPage(); mutatePageInfo(); mutatePageTree(); + mutateRecentlyUpdated(); }; openDeleteModal([pageWithMeta], { onDeleted: deletedHandler }); - }, [currentPathname, mutateCurrentPage, openDeleteModal, router, mutatePageInfo]); + }, [currentPathname, mutateCurrentPage, openDeleteModal, router, mutatePageInfo, mutateRecentlyUpdated]); const switchContentWidthHandler = useCallback(async(pageId: string, value: boolean) => { if (!isSharedPage) { diff --git a/apps/app/src/client/components/PageEditor/PageEditor.tsx b/apps/app/src/client/components/PageEditor/PageEditor.tsx index 77f272f88a2..48a34a0fefc 100644 --- a/apps/app/src/client/components/PageEditor/PageEditor.tsx +++ b/apps/app/src/client/components/PageEditor/PageEditor.tsx @@ -41,7 +41,7 @@ import { import { useCurrentPagePath, useSWRxCurrentPage, useCurrentPageId, useIsNotFound, useTemplateBodyData, useSWRxCurrentGrantData, } from '~/stores/page'; -import { mutatePageTree } from '~/stores/page-listing'; +import { mutatePageTree, useSWRINFxRecentlyUpdated } from '~/stores/page-listing'; import { usePreviewOptions } from '~/stores/renderer'; import { useIsUntitledPage, useSelectedGrant } from '~/stores/ui'; import { useEditingUsers } from '~/stores/use-editing-users'; @@ -165,6 +165,8 @@ export const PageEditor = React.memo((props: Props): JSX.Element => { const scrollEditorHandlerThrottle = useMemo(() => throttle(25, scrollEditorHandler), [scrollEditorHandler]); const scrollPreviewHandlerThrottle = useMemo(() => throttle(25, scrollPreviewHandler), [scrollPreviewHandler]); + const { mutate: mutateRecentlyUpdated } = useSWRINFxRecentlyUpdated(20, true); + const save: Save = useCallback(async(revisionId, markdown, opts, onConflict) => { if (pageId == null || selectedGrant == null) { @@ -190,6 +192,8 @@ export const PageEditor = React.memo((props: Props): JSX.Element => { // to sync revision id with page tree: https://github.com/weseek/growi/pull/7227 mutatePageTree(); + + mutateRecentlyUpdated(); // sync current grant data after update mutateIsGrantNormalized(); @@ -211,7 +215,7 @@ export const PageEditor = React.memo((props: Props): JSX.Element => { finally { mutateWaitingSaveProcessing(false); } - }, [pageId, selectedGrant, mutateWaitingSaveProcessing, updatePage, mutateIsGrantNormalized, t]); + }, [pageId, selectedGrant, mutateWaitingSaveProcessing, updatePage, mutateIsGrantNormalized, mutateRecentlyUpdated, t]); const saveAndReturnToViewHandler = useCallback(async(opts: SaveOptions) => { const markdown = codeMirrorEditor?.getDoc(); diff --git a/apps/app/src/client/components/SearchPage/SearchResultContent.tsx b/apps/app/src/client/components/SearchPage/SearchResultContent.tsx index dcf5b33dd04..8ec3f6b4ccf 100644 --- a/apps/app/src/client/components/SearchPage/SearchResultContent.tsx +++ b/apps/app/src/client/components/SearchPage/SearchResultContent.tsx @@ -21,7 +21,7 @@ import { useCurrentUser } from '~/stores-universal/context'; import { usePageDuplicateModal, usePageRenameModal, usePageDeleteModal, } from '~/stores/modal'; -import { mutatePageList, mutatePageTree } from '~/stores/page-listing'; +import { mutatePageList, mutatePageTree, useSWRINFxRecentlyUpdated } from '~/stores/page-listing'; import { useSearchResultOptions } from '~/stores/renderer'; import { mutateSearching } from '~/stores/search'; @@ -126,7 +126,7 @@ export const SearchResultContent: FC = (props: Props) => { const { open: openDeleteModal } = usePageDeleteModal(); const { data: rendererOptions } = useSearchResultOptions(pageWithMeta.data.path, highlightKeywords); const { data: currentUser } = useCurrentUser(); - + const { mutate: mutateRecentlyUpdated } = useSWRINFxRecentlyUpdated(20, true); const shouldExpandContent = useShouldExpandContent(page); const duplicateItemClickedHandler = useCallback(async(pageToDuplicate) => { @@ -135,22 +135,24 @@ export const SearchResultContent: FC = (props: Props) => { toastSuccess(t('duplicated_pages', { fromPath })); mutatePageTree(); + mutateRecentlyUpdated(); mutateSearching(); mutatePageList(); }; openDuplicateModal(pageToDuplicate, { onDuplicated: duplicatedHandler }); - }, [openDuplicateModal, t]); + }, [openDuplicateModal, mutateRecentlyUpdated, t]); const renameItemClickedHandler = useCallback((pageToRename: IPageToRenameWithMeta) => { const renamedHandler: OnRenamedFunction = (path) => { toastSuccess(t('renamed_pages', { path })); mutatePageTree(); + mutateRecentlyUpdated(); mutateSearching(); mutatePageList(); }; openRenameModal(pageToRename, { onRenamed: renamedHandler }); - }, [openRenameModal, t]); + }, [openRenameModal, mutateRecentlyUpdated, t]); const onDeletedHandler: OnDeletedFunction = useCallback((pathOrPathsToDelete, isRecursively, isCompletely) => { if (typeof pathOrPathsToDelete !== 'string') { @@ -165,9 +167,10 @@ export const SearchResultContent: FC = (props: Props) => { toastSuccess(t('deleted_pages', { path })); } mutatePageTree(); + mutateRecentlyUpdated(); mutateSearching(); mutatePageList(); - }, [t]); + }, [mutateRecentlyUpdated, t]); const deleteItemClickedHandler = useCallback((pageToDelete: IPageToDeleteWithMeta) => { openDeleteModal([pageToDelete], { onDeleted: onDeletedHandler }); diff --git a/apps/app/src/client/components/SearchPage/SearchResultList.tsx b/apps/app/src/client/components/SearchPage/SearchResultList.tsx index 2315973edc5..1a465b85f66 100644 --- a/apps/app/src/client/components/SearchPage/SearchResultList.tsx +++ b/apps/app/src/client/components/SearchPage/SearchResultList.tsx @@ -12,7 +12,7 @@ import type { ISelectable, ISelectableAll } from '~/client/interfaces/selectable import { toastSuccess } from '~/client/util/toastr'; import type { IPageSearchMeta, IPageWithSearchMeta } from '~/interfaces/search'; import { useIsGuestUser, useIsReadOnlyUser } from '~/stores-universal/context'; -import { mutatePageTree, useSWRxPageInfoForList } from '~/stores/page-listing'; +import { mutatePageTree, useSWRxPageInfoForList, useSWRINFxRecentlyUpdated } from '~/stores/page-listing'; import { mutateSearching } from '~/stores/search'; import type { ForceHideMenuItems } from '../Common/Dropdown/PageItemControl'; @@ -89,20 +89,24 @@ const SearchResultListSubstance: ForwardRefRenderFunction }); } + const { mutate: mutateRecentlyUpdated } = useSWRINFxRecentlyUpdated(20, true); + // eslint-disable-next-line @typescript-eslint/no-unused-vars const duplicatedHandler = useCallback((fromPath, toPath) => { toastSuccess(t('duplicated_pages', { fromPath })); mutatePageTree(); + mutateRecentlyUpdated(); mutateSearching(); - }, [t]); + }, [t, mutateRecentlyUpdated]); const renamedHandler = useCallback((path) => { toastSuccess(t('renamed_pages', { path })); mutatePageTree(); + mutateRecentlyUpdated(); mutateSearching(); - }, [t]); + }, [t, mutateRecentlyUpdated]); const deletedHandler = useCallback((pathOrPathsToDelete, isRecursively, isCompletely) => { if (typeof pathOrPathsToDelete !== 'string') { @@ -118,8 +122,9 @@ const SearchResultListSubstance: ForwardRefRenderFunction toastSuccess(t('deleted_pages', { path })); } mutatePageTree(); + mutateRecentlyUpdated(); mutateSearching(); - }, [t]); + }, [t, mutateRecentlyUpdated]); return (
                    diff --git a/apps/app/src/client/components/TreeItem/NewPageInput/use-new-page-input.tsx b/apps/app/src/client/components/TreeItem/NewPageInput/use-new-page-input.tsx index fe76ef2e20e..bba087e21fd 100644 --- a/apps/app/src/client/components/TreeItem/NewPageInput/use-new-page-input.tsx +++ b/apps/app/src/client/components/TreeItem/NewPageInput/use-new-page-input.tsx @@ -11,12 +11,12 @@ import { useRect } from '@growi/ui/dist/utils'; import { useTranslation } from 'next-i18next'; import { debounce } from 'throttle-debounce'; +import { AutosizeSubmittableInput, getAdjustedMaxWidthForAutosizeInput } from '~/client/components/Common/SubmittableInput'; import { useCreatePage } from '~/client/services/create-page'; import { toastWarning, toastError, toastSuccess } from '~/client/util/toastr'; import type { InputValidationResult } from '~/client/util/use-input-validator'; import { ValidationTarget, useInputValidator } from '~/client/util/use-input-validator'; -import { AutosizeSubmittableInput, getAdjustedMaxWidthForAutosizeInput } from '~/client/components/Common/SubmittableInput'; -import { mutatePageTree } from '~/stores/page-listing'; +import { mutatePageTree, useSWRINFxRecentlyUpdated } from '~/stores/page-listing'; import { usePageTreeDescCountMap } from '~/stores/ui'; import { shouldCreateWipPage } from '../../../../utils/should-create-wip-page'; @@ -89,6 +89,8 @@ export const useNewPageInput = (): UseNewPageInput => { setShowInput(false); }, []); + const { mutate: mutateRecentlyUpdated } = useSWRINFxRecentlyUpdated(20, true); + const create = useCallback(async(inputText) => { if (inputText.trim() === '') { return cancel(); @@ -123,6 +125,7 @@ export const useNewPageInput = (): UseNewPageInput => { skipTransition: true, onCreated: () => { mutatePageTree(); + mutateRecentlyUpdated(); if (!hasDescendants) { stateHandlers?.setIsOpen(true); @@ -139,7 +142,7 @@ export const useNewPageInput = (): UseNewPageInput => { finally { setProcessingSubmission(false); } - }, [cancel, hasDescendants, page.path, stateHandlers, t, createPage]); + }, [cancel, hasDescendants, page.path, stateHandlers, t, createPage, mutateRecentlyUpdated]); const inputContainerClass = newPageInputStyles['new-page-input-container'] ?? ''; const isInvalid = validationResult != null; diff --git a/apps/app/src/components/PageView/PageAlerts/WipPageAlert.tsx b/apps/app/src/components/PageView/PageAlerts/WipPageAlert.tsx index 83afa5f82b0..2a452b2bd82 100644 --- a/apps/app/src/components/PageView/PageAlerts/WipPageAlert.tsx +++ b/apps/app/src/components/PageView/PageAlerts/WipPageAlert.tsx @@ -3,12 +3,14 @@ import React, { useCallback } from 'react'; import { useTranslation } from 'react-i18next'; import { useSWRMUTxCurrentPage, useSWRxCurrentPage } from '~/stores/page'; - +import { useSWRINFxRecentlyUpdated } from '~/stores/page-listing'; export const WipPageAlert = (): JSX.Element => { const { t } = useTranslation(); const { data: currentPage } = useSWRxCurrentPage(); const { trigger: mutateCurrentPage } = useSWRMUTxCurrentPage(); + const { mutate: mutateRecentlyUpdated } = useSWRINFxRecentlyUpdated(20, true); + const clickPagePublishButton = useCallback(async() => { const pageId = currentPage?._id; @@ -26,6 +28,8 @@ export const WipPageAlert = (): JSX.Element => { const mutatePageTree = (await import('~/stores/page-listing')).mutatePageTree; await mutatePageTree(); + await mutateRecentlyUpdated(); + const toastSuccess = (await import('~/client/util/toastr')).toastSuccess; toastSuccess(t('wip_page.success_publish_page')); } @@ -33,7 +37,7 @@ export const WipPageAlert = (): JSX.Element => { const toastError = (await import('~/client/util/toastr')).toastError; toastError(t('wip_page.fail_publish_page')); } - }, [currentPage?._id, mutateCurrentPage, t]); + }, [currentPage?._id, mutateCurrentPage, t, mutateRecentlyUpdated]); if (!currentPage?.wip) { From 723004de9b96bbb72275e51f7b232c1249cfedd1 Mon Sep 17 00:00:00 2001 From: shironegi39 Date: Fri, 13 Sep 2024 06:55:48 +0000 Subject: [PATCH 183/490] Fixed to not update notification counts when PrimaryItem is clicked or hovered. --- .../PrimaryItemForNotification.tsx | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/apps/app/src/client/components/Sidebar/InAppNotification/PrimaryItemForNotification.tsx b/apps/app/src/client/components/Sidebar/InAppNotification/PrimaryItemForNotification.tsx index c4717949716..353ee29cadd 100644 --- a/apps/app/src/client/components/Sidebar/InAppNotification/PrimaryItemForNotification.tsx +++ b/apps/app/src/client/components/Sidebar/InAppNotification/PrimaryItemForNotification.tsx @@ -1,15 +1,11 @@ import { memo, useCallback, useEffect } from 'react'; -import { apiv3Post } from '~/client/util/apiv3-client'; import { SidebarContentsType } from '~/interfaces/ui'; import { useSWRxInAppNotificationStatus } from '~/stores/in-app-notification'; import { useDefaultSocket } from '~/stores/socket-io'; -import loggerFactory from '~/utils/logger'; import { PrimaryItem, type Props } from '../SidebarNav/PrimaryItem'; -const logger = loggerFactory('growi:PrimaryItemsForNotification'); - type PrimaryItemForNotificationProps = Omit // TODO(after v7 release): https://redmine.weseek.co.jp/issues/138463 @@ -22,20 +18,9 @@ export const PrimaryItemForNotification = memo((props: PrimaryItemForNotificatio const badgeContents = notificationCount != null && notificationCount > 0 ? notificationCount : undefined; - const updateNotificationStatus = useCallback(async() => { - try { - await apiv3Post('/in-app-notification/read'); - mutateNotificationCount(); - } - catch (err) { - logger.error(err); - } - }, [mutateNotificationCount]); - const itemHoverHandler = useCallback((contents: SidebarContentsType) => { onHover?.(contents); - updateNotificationStatus(); - }, [onHover, updateNotificationStatus]); + }, [onHover]); useEffect(() => { if (socket != null) { @@ -57,7 +42,6 @@ export const PrimaryItemForNotification = memo((props: PrimaryItemForNotificatio label="In-App Notification" iconName="notifications" badgeContents={badgeContents} - onClick={updateNotificationStatus} onHover={itemHoverHandler} /> ); From af77550c4f3d3e0046a7b444d7d12b733dcbe3fd Mon Sep 17 00:00:00 2001 From: WNomunomu Date: Fri, 13 Sep 2024 07:11:06 +0000 Subject: [PATCH 184/490] modify the conditional branching before executing the process --- apps/app/src/server/service/page/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/app/src/server/service/page/index.ts b/apps/app/src/server/service/page/index.ts index c984553bc79..3b5fdc7acb7 100644 --- a/apps/app/src/server/service/page/index.ts +++ b/apps/app/src/server/service/page/index.ts @@ -4109,7 +4109,7 @@ class PageService implements IPageService { } // 3. Update scopes for descendants - if (options.overwriteScopesOfDescendants) { + if (options.overwriteScopesOfDescendants && shouldBeOnTree) { await this.applyScopesToDescendantsWithStream(currentPage, user); } From 05f6989bca45fc3515da8bbc9c0230a7df2ff4f3 Mon Sep 17 00:00:00 2001 From: moekumasaka Date: Fri, 13 Sep 2024 07:45:14 +0000 Subject: [PATCH 185/490] add breakpoint to hide dropdown --- .../components/CustomNavigation/CustomNav.tsx | 23 +++++++++++++++---- .../components/DescendantsPageListModal.tsx | 11 ++++++--- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/apps/app/src/client/components/CustomNavigation/CustomNav.tsx b/apps/app/src/client/components/CustomNavigation/CustomNav.tsx index 06e33549d40..7763e775d1e 100644 --- a/apps/app/src/client/components/CustomNavigation/CustomNav.tsx +++ b/apps/app/src/client/components/CustomNavigation/CustomNav.tsx @@ -33,11 +33,13 @@ type CustomNavDropdownProps = { navTabMapping: ICustomNavTabMappings, activeTab: string, onNavSelected?: (selectedTabKey: string) => void, + breakpointToHideDropDown?: Breakpoint, }; export const CustomNavDropdown = (props: CustomNavDropdownProps): JSX.Element => { const { activeTab, navTabMapping, onNavSelected, + breakpointToHideDropDown, } = props; const { Icon, i18n } = navTabMapping[activeTab]; @@ -48,10 +50,17 @@ export const CustomNavDropdown = (props: CustomNavDropdownProps): JSX.Element => } }, [onNavSelected]); + // Set classes to hide dropdown + const dropdownVisibilityClassnames: string[] = []; + if (breakpointToHideDropDown != null) { + const breakpointOneLevelLarger = getBreakpointOneLevelLarger(breakpointToHideDropDown); + dropdownVisibilityClassnames.push(`d-${breakpointOneLevelLarger}-none`); + } + return (
                    -
                    +
                    { !hideBorderBottom &&
                    }
                  ); diff --git a/apps/app/src/client/components/DescendantsPageListModal.tsx b/apps/app/src/client/components/DescendantsPageListModal.tsx index 8b151070c37..19b36bc0c01 100644 --- a/apps/app/src/client/components/DescendantsPageListModal.tsx +++ b/apps/app/src/client/components/DescendantsPageListModal.tsx @@ -11,7 +11,7 @@ import { import { useIsSharedUser } from '~/stores-universal/context'; import { useDescendantsPageListModal } from '~/stores/modal'; -import CustomNav, { CustomNavTab } from './CustomNavigation/CustomNav'; +import { CustomNavDropdown, CustomNavTab } from './CustomNavigation/CustomNav'; import CustomTabContent from './CustomNavigation/CustomTabContent'; import type { DescendantsPageListProps } from './DescendantsPageList'; import ExpandOrContractButton from './ExpandOrContractButton'; @@ -94,16 +94,21 @@ export const DescendantsPageListModal = (): JSX.Element => { className={`grw-descendants-page-list-modal ${styles['grw-descendants-page-list-modal']} ${isWindowExpanded ? 'grw-modal-expanded' : ''} `} > - setActiveTab(v)} hideBorderBottom /> + setActiveTab(v)} + /> From 1522272b83c14da04eb0cb10a232ad3929f32a7b Mon Sep 17 00:00:00 2001 From: reiji-h Date: Fri, 13 Sep 2024 07:49:39 +0000 Subject: [PATCH 186/490] remove unused package --- apps/app/next.config.js | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/app/next.config.js b/apps/app/next.config.js index 0d34cba9115..54ef997cdd1 100644 --- a/apps/app/next.config.js +++ b/apps/app/next.config.js @@ -56,7 +56,6 @@ const getTranspilePackages = () => { 'github-slugger', 'html-url-attributes', 'estree-util-is-identifier-name', - '@microflash/remark-callout-directives', ...listPrefixedPackages(['remark-', 'rehype-', 'hast-', 'mdast-', 'micromark-', 'unist-']), ]; From 8dd73a4731976c0eaeb6c1907db6b70f51b15c41 Mon Sep 17 00:00:00 2001 From: moekumasaka Date: Tue, 17 Sep 2024 02:07:20 +0000 Subject: [PATCH 187/490] add useIsDeviceLargerThanLg to DescendantsPageListModal --- .../components/CustomNavigation/CustomNav.tsx | 16 ++------- .../components/DescendantsPageListModal.tsx | 33 +++++++++++-------- 2 files changed, 22 insertions(+), 27 deletions(-) diff --git a/apps/app/src/client/components/CustomNavigation/CustomNav.tsx b/apps/app/src/client/components/CustomNavigation/CustomNav.tsx index 7763e775d1e..1735525ff67 100644 --- a/apps/app/src/client/components/CustomNavigation/CustomNav.tsx +++ b/apps/app/src/client/components/CustomNavigation/CustomNav.tsx @@ -50,17 +50,11 @@ export const CustomNavDropdown = (props: CustomNavDropdownProps): JSX.Element => } }, [onNavSelected]); - // Set classes to hide dropdown - const dropdownVisibilityClassnames: string[] = []; - if (breakpointToHideDropDown != null) { - const breakpointOneLevelLarger = getBreakpointOneLevelLarger(breakpointToHideDropDown); - dropdownVisibilityClassnames.push(`d-${breakpointOneLevelLarger}-none`); - } return (
                  -
                  +
                  { !hideBorderBottom &&
                  }
                  ); diff --git a/apps/app/src/client/components/DescendantsPageListModal.tsx b/apps/app/src/client/components/DescendantsPageListModal.tsx index 19b36bc0c01..a32ddf52adc 100644 --- a/apps/app/src/client/components/DescendantsPageListModal.tsx +++ b/apps/app/src/client/components/DescendantsPageListModal.tsx @@ -10,6 +10,7 @@ import { import { useIsSharedUser } from '~/stores-universal/context'; import { useDescendantsPageListModal } from '~/stores/modal'; +import { useIsDeviceLargerThanLg } from '~/stores/ui'; import { CustomNavDropdown, CustomNavTab } from './CustomNavigation/CustomNav'; import CustomTabContent from './CustomNavigation/CustomTabContent'; @@ -34,6 +35,8 @@ export const DescendantsPageListModal = (): JSX.Element => { const { events } = useRouter(); + const { data: isDeviceLargerThanLg } = useIsDeviceLargerThanLg(); + useEffect(() => { events.on('routeChangeStart', close); return () => { @@ -94,21 +97,25 @@ export const DescendantsPageListModal = (): JSX.Element => { className={`grw-descendants-page-list-modal ${styles['grw-descendants-page-list-modal']} ${isWindowExpanded ? 'grw-modal-expanded' : ''} `} > - setActiveTab(v)} - hideBorderBottom - /> + {isDeviceLargerThanLg && ( + setActiveTab(v)} + hideBorderBottom + /> + )} - setActiveTab(v)} - /> + {!isDeviceLargerThanLg && ( + setActiveTab(v)} + /> + )} From f90e05fbfa2e5ba55b95a5d8c65d162ed4fbf5ac Mon Sep 17 00:00:00 2001 From: Shun Miyazawa Date: Tue, 17 Sep 2024 02:25:29 +0000 Subject: [PATCH 188/490] ai-search -> ai-integration --- apps/app/public/static/locales/en_US/admin.json | 4 ++-- apps/app/public/static/locales/fr_FR/admin.json | 4 ++-- apps/app/public/static/locales/ja_JP/admin.json | 4 ++-- apps/app/public/static/locales/zh_CN/admin.json | 4 ++-- apps/app/src/components/Admin/Common/AdminNavigation.tsx | 6 +++--- .../admin/{ai-search.page.tsx => ai-integration.page.tsx} | 6 +++--- 6 files changed, 14 insertions(+), 14 deletions(-) rename apps/app/src/pages/admin/{ai-search.page.tsx => ai-integration.page.tsx} (90%) diff --git a/apps/app/public/static/locales/en_US/admin.json b/apps/app/public/static/locales/en_US/admin.json index 67802a84101..46faff8dcc3 100644 --- a/apps/app/public/static/locales/en_US/admin.json +++ b/apps/app/public/static/locales/en_US/admin.json @@ -1133,7 +1133,7 @@ "forbidden_page": { "do_not_have_admin_permission": "Users without administrative rights cannot access the administration screen" }, - "ai_search_management": { - "ai_search_management": "AI Search Management" + "ai_integration": { + "ai_integration": "AI Integration" } } diff --git a/apps/app/public/static/locales/fr_FR/admin.json b/apps/app/public/static/locales/fr_FR/admin.json index 473f98b1885..2d045c25991 100644 --- a/apps/app/public/static/locales/fr_FR/admin.json +++ b/apps/app/public/static/locales/fr_FR/admin.json @@ -1132,7 +1132,7 @@ "forbidden_page": { "do_not_have_admin_permission": "Seul les administrateurs peuvent accéder à cette page." }, - "ai_search_management": { - "ai_search_management": "Gestion de la recherche en IA" + "ai_integration": { + "ai_integration": "Intégration de l'IA" } } diff --git a/apps/app/public/static/locales/ja_JP/admin.json b/apps/app/public/static/locales/ja_JP/admin.json index 4ba45bf4d29..b31ee3ece1a 100644 --- a/apps/app/public/static/locales/ja_JP/admin.json +++ b/apps/app/public/static/locales/ja_JP/admin.json @@ -1143,7 +1143,7 @@ "forbidden_page": { "do_not_have_admin_permission": "管理者権限のないユーザーでは管理画面にはアクセスできません" }, - "ai_search_management": { - "ai_search_management": "AI 検索管理" + "ai_integration": { + "ai_integration": "AI 連携" } } diff --git a/apps/app/public/static/locales/zh_CN/admin.json b/apps/app/public/static/locales/zh_CN/admin.json index dab22f862f7..5b6f3328097 100644 --- a/apps/app/public/static/locales/zh_CN/admin.json +++ b/apps/app/public/static/locales/zh_CN/admin.json @@ -1142,7 +1142,7 @@ "forbidden_page": { "do_not_have_admin_permission": "没有管理权限的用户无法访问管理屏幕" }, - "ai_search_management": { - "ai_search_management": "AI 搜索管理" + "ai_integration": { + "ai_integration": "AI 集成" } } diff --git a/apps/app/src/components/Admin/Common/AdminNavigation.tsx b/apps/app/src/components/Admin/Common/AdminNavigation.tsx index 71991161c8a..ec683204c9b 100644 --- a/apps/app/src/components/Admin/Common/AdminNavigation.tsx +++ b/apps/app/src/components/Admin/Common/AdminNavigation.tsx @@ -32,7 +32,7 @@ const MenuLabel = ({ menu }: { menu: string }) => { case 'user-groups': return <>group{ t('user_group_management.user_group_management') }; case 'audit-log': return <>feed{ t('audit_log_management.audit_log')}; case 'plugins': return <>extension{ t('plugins.plugins')}; - case 'ai-search': return <>psychology{ t('ai_search_management.ai_search_management')}; + case 'ai-integration': return <>psychology{ t('ai_integration.ai_integration')}; case 'search': return <>search{ t('full_text_search_management.full_text_search_management') }; case 'cloud': return <>share{ t('cloud_setting_management.to_cloud_settings')} ; default: return <>home{ t('wiki_management_homepage') }; @@ -107,7 +107,7 @@ export const AdminNavigation = (): JSX.Element => { - + {growiCloudUri != null && growiAppIdForGrowiCloud != null && ( @@ -161,7 +161,7 @@ export const AdminNavigation = (): JSX.Element => { {isActiveMenu('/audit-log') && } {isActiveMenu('/plugins') && } {isActiveMenu('/data-transfer') && } - {isActiveMenu('/ai-search') && } + {isActiveMenu('/ai-integration') && } {/* eslint-enable no-multi-spaces */} diff --git a/apps/app/src/pages/admin/ai-search.page.tsx b/apps/app/src/pages/admin/ai-integration.page.tsx similarity index 90% rename from apps/app/src/pages/admin/ai-search.page.tsx rename to apps/app/src/pages/admin/ai-integration.page.tsx index faa629534b5..3664bc5c8bc 100644 --- a/apps/app/src/pages/admin/ai-search.page.tsx +++ b/apps/app/src/pages/admin/ai-integration.page.tsx @@ -18,10 +18,10 @@ type Props = CommonProps & { // }; -const AdminAiSearchPage: NextPage = (props) => { +const AdminAiIntegrationPage: NextPage = (props) => { const { t } = useTranslation('admin'); - const title = t('ai_search_management.ai_search_management'); + const title = t('ai_integration.ai_integration'); const headTitle = generateCustomTitle(props, title); if (props.isAccessDeniedForNonAdminUser) { @@ -47,4 +47,4 @@ export const getServerSideProps: GetServerSideProps = async(context: GetServerSi return props; }; -export default AdminAiSearchPage; +export default AdminAiIntegrationPage; From fc201e758067c4addc0aeb9819b0f7bc2a165c34 Mon Sep 17 00:00:00 2001 From: moekumasaka Date: Tue, 17 Sep 2024 03:08:39 +0000 Subject: [PATCH 189/490] remove breakpointToHideDropDown --- apps/app/src/client/components/CustomNavigation/CustomNav.tsx | 3 --- apps/app/src/client/components/DescendantsPageListModal.tsx | 1 - 2 files changed, 4 deletions(-) diff --git a/apps/app/src/client/components/CustomNavigation/CustomNav.tsx b/apps/app/src/client/components/CustomNavigation/CustomNav.tsx index 1735525ff67..da5aa094d64 100644 --- a/apps/app/src/client/components/CustomNavigation/CustomNav.tsx +++ b/apps/app/src/client/components/CustomNavigation/CustomNav.tsx @@ -33,13 +33,11 @@ type CustomNavDropdownProps = { navTabMapping: ICustomNavTabMappings, activeTab: string, onNavSelected?: (selectedTabKey: string) => void, - breakpointToHideDropDown?: Breakpoint, }; export const CustomNavDropdown = (props: CustomNavDropdownProps): JSX.Element => { const { activeTab, navTabMapping, onNavSelected, - breakpointToHideDropDown, } = props; const { Icon, i18n } = navTabMapping[activeTab]; @@ -50,7 +48,6 @@ export const CustomNavDropdown = (props: CustomNavDropdownProps): JSX.Element => } }, [onNavSelected]); - return (
                  -
                  +
                  {Object.entries(navTabMapping).map(([key, value]) => { const isActive = activeTab === key; From 98c5be23804e3450e3a6d2af423c446171799089 Mon Sep 17 00:00:00 2001 From: Shun Miyazawa Date: Tue, 17 Sep 2024 05:41:58 +0000 Subject: [PATCH 192/490] implementation ai integration disable mode --- apps/app/.env.development | 1 + .../public/static/locales/en_US/admin.json | 3 +- .../public/static/locales/fr_FR/admin.json | 3 +- .../public/static/locales/ja_JP/admin.json | 3 +- .../public/static/locales/zh_CN/admin.json | 3 +- .../AiIntegrationDisableMode.tsx | 28 +++++++++++++++++++ .../src/pages/admin/ai-integration.page.tsx | 12 +++++++- apps/app/src/server/service/config-loader.ts | 12 ++++++++ 8 files changed, 60 insertions(+), 5 deletions(-) create mode 100644 apps/app/src/client/components/Admin/AiIntegration/AiIntegrationDisableMode.tsx diff --git a/apps/app/.env.development b/apps/app/.env.development index ba49ca0b1c6..f343dc6fc17 100644 --- a/apps/app/.env.development +++ b/apps/app/.env.development @@ -30,3 +30,4 @@ QUESTIONNAIRE_SERVER_ORIGIN="http://host.docker.internal:3003" # AUDIT_LOG_ACTION_GROUP_SIZE=SMALL # AUDIT_LOG_ADDITIONAL_ACTIONS= # AUDIT_LOG_EXCLUDE_ACTIONS= +AI_ENABLED = true diff --git a/apps/app/public/static/locales/en_US/admin.json b/apps/app/public/static/locales/en_US/admin.json index 46faff8dcc3..917782fba48 100644 --- a/apps/app/public/static/locales/en_US/admin.json +++ b/apps/app/public/static/locales/en_US/admin.json @@ -1134,6 +1134,7 @@ "do_not_have_admin_permission": "Users without administrative rights cannot access the administration screen" }, "ai_integration": { - "ai_integration": "AI Integration" + "ai_integration": "AI Integration", + "disable_mode_explanation": "Currently, AI integration is disabled. To enable it, please set the environment variable AI_ENABLED to true." } } diff --git a/apps/app/public/static/locales/fr_FR/admin.json b/apps/app/public/static/locales/fr_FR/admin.json index 2d045c25991..452070d44b6 100644 --- a/apps/app/public/static/locales/fr_FR/admin.json +++ b/apps/app/public/static/locales/fr_FR/admin.json @@ -1133,6 +1133,7 @@ "do_not_have_admin_permission": "Seul les administrateurs peuvent accéder à cette page." }, "ai_integration": { - "ai_integration": "Intégration de l'IA" + "ai_integration": "Intégration de l'IA", + "disable_mode_explanation": "Actuellement, l'intégration de l'IA est désactivée. Pour l'activer, veuillez définir la variable d'environnement AI_ENABLED sur true" } } diff --git a/apps/app/public/static/locales/ja_JP/admin.json b/apps/app/public/static/locales/ja_JP/admin.json index b31ee3ece1a..61c186ac1bb 100644 --- a/apps/app/public/static/locales/ja_JP/admin.json +++ b/apps/app/public/static/locales/ja_JP/admin.json @@ -1144,6 +1144,7 @@ "do_not_have_admin_permission": "管理者権限のないユーザーでは管理画面にはアクセスできません" }, "ai_integration": { - "ai_integration": "AI 連携" + "ai_integration": "AI 連携", + "disable_mode_explanation": "現在、AI 連携は無効になっています。有効にする場合は環境変数 AI_ENABLED を true に設定してください。" } } diff --git a/apps/app/public/static/locales/zh_CN/admin.json b/apps/app/public/static/locales/zh_CN/admin.json index 5b6f3328097..260ea663213 100644 --- a/apps/app/public/static/locales/zh_CN/admin.json +++ b/apps/app/public/static/locales/zh_CN/admin.json @@ -1143,6 +1143,7 @@ "do_not_have_admin_permission": "没有管理权限的用户无法访问管理屏幕" }, "ai_integration": { - "ai_integration": "AI 集成" + "ai_integration": "AI 集成", + "disable_mode_explanation": "目前,AI 集成已禁用。要启用它,请将环境变量 AI_ENABLED 设置为 true”" } } diff --git a/apps/app/src/client/components/Admin/AiIntegration/AiIntegrationDisableMode.tsx b/apps/app/src/client/components/Admin/AiIntegration/AiIntegrationDisableMode.tsx new file mode 100644 index 00000000000..d6a336979bd --- /dev/null +++ b/apps/app/src/client/components/Admin/AiIntegration/AiIntegrationDisableMode.tsx @@ -0,0 +1,28 @@ +import type { FC } from 'react'; +import React from 'react'; + +import { useTranslation } from 'react-i18next'; + +export const AiIntegrationDisableMode: FC = () => { + const { t } = useTranslation('admin'); + + return ( +
                  +
                  +
                  +
                  +
                  + {/* error icon large */} +

                  error

                  +

                  {t('ai_integration.ai_integration')}

                  +

                  +

                  +
                  +
                  +
                  +
                  + ); +}; diff --git a/apps/app/src/pages/admin/ai-integration.page.tsx b/apps/app/src/pages/admin/ai-integration.page.tsx index 3664bc5c8bc..440a7c29fcf 100644 --- a/apps/app/src/pages/admin/ai-integration.page.tsx +++ b/apps/app/src/pages/admin/ai-integration.page.tsx @@ -13,9 +13,12 @@ import { retrieveServerSideProps } from '../../utils/admin-page-util'; const AdminLayout = dynamic(() => import('~/components/Layout/AdminLayout'), { ssr: false }); const ForbiddenPage = dynamic(() => import('~/client/components/Admin/ForbiddenPage').then(mod => mod.ForbiddenPage), { ssr: false }); +const AiIntegrationDisableMode = dynamic( + () => import('~/client/components/Admin/AiIntegration/AiIntegrationDisableMode').then(mod => mod.AiIntegrationDisableMode), { ssr: false }, +); type Props = CommonProps & { - // + aiEnabled: boolean, }; const AdminAiIntegrationPage: NextPage = (props) => { @@ -33,6 +36,10 @@ const AdminAiIntegrationPage: NextPage = (props) => { {headTitle} + {props.aiEnabled + ? <> // TODO: implement admin page + : + } ); }; @@ -40,6 +47,9 @@ const AdminAiIntegrationPage: NextPage = (props) => { const injectServerConfigurations = async(context: GetServerSidePropsContext, props: Props): Promise => { const req: CrowiRequest = context.req as CrowiRequest; const { crowi } = req; + const { configManager } = crowi; + + props.aiEnabled = configManager.getConfig('crowi', 'app:aiEnabled'); }; export const getServerSideProps: GetServerSideProps = async(context: GetServerSidePropsContext) => { diff --git a/apps/app/src/server/service/config-loader.ts b/apps/app/src/server/service/config-loader.ts index eb87b79f67c..8c3cbc6e99e 100644 --- a/apps/app/src/server/service/config-loader.ts +++ b/apps/app/src/server/service/config-loader.ts @@ -736,6 +736,18 @@ const ENV_VAR_NAME_TO_CONFIG_INFO = { type: ValueType.NUMBER, default: 172800, // 2 days }, + AI_ENABLED: { + ns: 'crowi', + key: 'app:aiEnabled', + type: ValueType.BOOLEAN, + default: false, + }, + AI_SERVICE_TYPE: { + ns: 'crowi', + key: 'app:aiServiceType', + type: ValueType.STRING, + default: null, + }, OPENAI_API_KEY: { ns: 'crowi', key: 'app:openaiApiKey', From 79e69108bb9c5d3f6113eebd17313344d9132d94 Mon Sep 17 00:00:00 2001 From: Shun Miyazawa Date: Tue, 17 Sep 2024 05:44:45 +0000 Subject: [PATCH 193/490] Comment out openai-related code --- .../service/search-delegator/elasticsearch.ts | 124 +++++++++--------- 1 file changed, 62 insertions(+), 62 deletions(-) diff --git a/apps/app/src/server/service/search-delegator/elasticsearch.ts b/apps/app/src/server/service/search-delegator/elasticsearch.ts index 67506580188..17a89d770f8 100644 --- a/apps/app/src/server/service/search-delegator/elasticsearch.ts +++ b/apps/app/src/server/service/search-delegator/elasticsearch.ts @@ -20,8 +20,8 @@ import type { PageModel } from '../../models/page'; import { createBatchStream } from '../../util/batch-stream'; import { configManager } from '../config-manager'; import type { UpdateOrInsertPagesOpts } from '../interfaces/search'; -import { embed, openaiClient, fileUpload } from '../openai'; -import { getOrCreateSearchAssistant } from '../openai/assistant'; +// // import { embed, openaiClient, fileUpload } from '../openai'; +// import { getOrCreateSearchAssistant } from '../openai/assistant'; import { aggregatePipelineToIndex } from './aggregate-to-index'; import type { AggregatedPage, BulkWriteBody, BulkWriteCommand } from './bulk-write'; @@ -481,27 +481,27 @@ class ElasticsearchDelegator implements SearchDelegator { - - const searchAssistant = await getOrCreateSearchAssistant(); - - // generate keywords for vector - const run = await openaiClient.beta.threads.createAndRunPoll({ - assistant_id: searchAssistant.id, - thread: { - messages: [ - { role: 'user', content: 'globalLang: "en_US", userLang: "ja_JP", user_input: "武井さんがジョインしたのはいつですか?"' }, - { role: 'assistant', content: '武井さん 武井 takei yuki ジョイン join 入社 加入 雇用開始 年月日 start date join employee' }, - { role: 'user', content: `globalLang: "en_US", userLang: "ja_JP", user_input: "${queryString}"` }, - ], - }, - }); - const messages = await openaiClient.beta.threads.messages.list(run.thread_id, { - limit: 1, - }); - const content = messages.data[0].content[0]; - const keywordsForVector = content.type === 'text' ? content.text.value : queryString; - - logger.debug('keywordsFor: ', keywordsForVector); - - const queryVector = (await embed(queryString, username))[0].embedding; - - query.body.query = { - script_score: { - query: { ...query.body.query }, - script: { - source: "cosineSimilarity(params.query_vector, 'body_embedded') + 1.0", - params: { query_vector: queryVector }, - }, - }, - }; - } + // async appendVectorScore(query, queryString: string, username?: string): Promise { + + // const searchAssistant = await getOrCreateSearchAssistant(); + + // // generate keywords for vector + // const run = await openaiClient.beta.threads.createAndRunPoll({ + // assistant_id: searchAssistant.id, + // thread: { + // messages: [ + // { role: 'user', content: 'globalLang: "en_US", userLang: "ja_JP", user_input: "武井さんがジョインしたのはいつですか?"' }, + // { role: 'assistant', content: '武井さん 武井 takei yuki ジョイン join 入社 加入 雇用開始 年月日 start date join employee' }, + // { role: 'user', content: `globalLang: "en_US", userLang: "ja_JP", user_input: "${queryString}"` }, + // ], + // }, + // }); + // const messages = await openaiClient.beta.threads.messages.list(run.thread_id, { + // limit: 1, + // }); + // const content = messages.data[0].content[0]; + // const keywordsForVector = content.type === 'text' ? content.text.value : queryString; + + // logger.debug('keywordsFor: ', keywordsForVector); + + // const queryVector = (await embed(queryString, username))[0].embedding; + + // query.body.query = { + // script_score: { + // query: { ...query.body.query }, + // script: { + // source: "cosineSimilarity(params.query_vector, 'body_embedded') + 1.0", + // params: { query_vector: queryVector }, + // }, + // }, + // }; + // } appendHighlight(query) { query.body.highlight = { @@ -928,8 +928,8 @@ class ElasticsearchDelegator implements SearchDelegator Date: Tue, 17 Sep 2024 05:45:39 +0000 Subject: [PATCH 194/490] rm env --- apps/app/.env.development | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/app/.env.development b/apps/app/.env.development index f343dc6fc17..ba49ca0b1c6 100644 --- a/apps/app/.env.development +++ b/apps/app/.env.development @@ -30,4 +30,3 @@ QUESTIONNAIRE_SERVER_ORIGIN="http://host.docker.internal:3003" # AUDIT_LOG_ACTION_GROUP_SIZE=SMALL # AUDIT_LOG_ADDITIONAL_ACTIONS= # AUDIT_LOG_EXCLUDE_ACTIONS= -AI_ENABLED = true From 510e6e4ffe17161c0497af29dd87fe6a4f125b1e Mon Sep 17 00:00:00 2001 From: shironegi39 Date: Tue, 17 Sep 2024 07:46:41 +0000 Subject: [PATCH 195/490] fix Query parameter --- .../Sidebar/InAppNotification/InAppNotificationSubstance.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/app/src/client/components/Sidebar/InAppNotification/InAppNotificationSubstance.tsx b/apps/app/src/client/components/Sidebar/InAppNotification/InAppNotificationSubstance.tsx index 1142aa0bc74..82306d7d86b 100644 --- a/apps/app/src/client/components/Sidebar/InAppNotification/InAppNotificationSubstance.tsx +++ b/apps/app/src/client/components/Sidebar/InAppNotification/InAppNotificationSubstance.tsx @@ -42,7 +42,7 @@ export const InAppNotificationContent = (props: InAppNotificationContentProps): const { data: inAppNotificationData, mutate: mutateInAppNotificationData } = useSWRxInAppNotifications( 6, undefined, - isUnopendNotificationsVisible ? InAppNotificationStatuses.STATUS_UNOPENED : undefined, + isUnopendNotificationsVisible ? InAppNotificationStatuses.STATUS_UNREAD : undefined, { keepPreviousData: true }, ); From fe3ad75b3e13873a64b9b3ea887c6483c068c4ae Mon Sep 17 00:00:00 2001 From: Yuki Takei Date: Tue, 17 Sep 2024 07:53:12 +0000 Subject: [PATCH 196/490] remove unnecessary class --- .../client/components/Navbar/GrowiContextualSubNavigation.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/app/src/client/components/Navbar/GrowiContextualSubNavigation.tsx b/apps/app/src/client/components/Navbar/GrowiContextualSubNavigation.tsx index e9063e68d64..fc670197621 100644 --- a/apps/app/src/client/components/Navbar/GrowiContextualSubNavigation.tsx +++ b/apps/app/src/client/components/Navbar/GrowiContextualSubNavigation.tsx @@ -351,7 +351,7 @@ const GrowiContextualSubNavigation = (props: GrowiContextualSubNavigationProps): setStickyActive(status.status === Sticky.STATUS_FIXED)} - innerActiveClass="w-100 position-abolute end-0" + innerActiveClass="w-100 end-0" > From 7d998a01bfcca32263d47c6b5840d5dc552dba77 Mon Sep 17 00:00:00 2001 From: Yuki Takei Date: Tue, 17 Sep 2024 07:54:24 +0000 Subject: [PATCH 197/490] set maxWidth --- apps/app/src/client/components/PageHeader/PageTitleHeader.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/app/src/client/components/PageHeader/PageTitleHeader.tsx b/apps/app/src/client/components/PageHeader/PageTitleHeader.tsx index e0bca67d386..df72f58e108 100644 --- a/apps/app/src/client/components/PageHeader/PageTitleHeader.tsx +++ b/apps/app/src/client/components/PageHeader/PageTitleHeader.tsx @@ -129,6 +129,7 @@ export const PageTitleHeader = (props: Props): JSX.Element => { ${isRenameInputShown ? 'invisible' : ''} text-truncate ${isMovable ? 'border border-2 rounded-2' : ''} ${borderColorClass} `} + style={{ maxWidth: inputMaxWidth }} onClick={onClickPageTitle} > {pageTitle} From 125062ad0d91d5ff2479f26ad0d7b3fee8518cc5 Mon Sep 17 00:00:00 2001 From: Shun Miyazawa Date: Tue, 17 Sep 2024 08:57:00 +0000 Subject: [PATCH 198/490] openai -> ai-integration --- .../server/routes/apiv3/{openai => ai-integration}/chat.ts | 2 +- .../server/routes/apiv3/{openai => ai-integration}/index.ts | 0 apps/app/src/server/routes/apiv3/index.js | 4 ++-- 3 files changed, 3 insertions(+), 3 deletions(-) rename apps/app/src/server/routes/apiv3/{openai => ai-integration}/chat.ts (97%) rename apps/app/src/server/routes/apiv3/{openai => ai-integration}/index.ts (100%) diff --git a/apps/app/src/server/routes/apiv3/openai/chat.ts b/apps/app/src/server/routes/apiv3/ai-integration/chat.ts similarity index 97% rename from apps/app/src/server/routes/apiv3/openai/chat.ts rename to apps/app/src/server/routes/apiv3/ai-integration/chat.ts index e3da7b5449d..bc6e290a438 100644 --- a/apps/app/src/server/routes/apiv3/openai/chat.ts +++ b/apps/app/src/server/routes/apiv3/ai-integration/chat.ts @@ -11,7 +11,7 @@ import loggerFactory from '~/utils/logger'; import { apiV3FormValidator } from '../../../middlewares/apiv3-form-validator'; import type { ApiV3Response } from '../interfaces/apiv3-response'; -const logger = loggerFactory('growi:routes:apiv3:openai:chat'); +const logger = loggerFactory('growi:routes:apiv3:ai-integration:chat'); type ReqBody = { userMessage: string, diff --git a/apps/app/src/server/routes/apiv3/openai/index.ts b/apps/app/src/server/routes/apiv3/ai-integration/index.ts similarity index 100% rename from apps/app/src/server/routes/apiv3/openai/index.ts rename to apps/app/src/server/routes/apiv3/ai-integration/index.ts diff --git a/apps/app/src/server/routes/apiv3/index.js b/apps/app/src/server/routes/apiv3/index.js index 112f3abce0b..fe8095a219b 100644 --- a/apps/app/src/server/routes/apiv3/index.js +++ b/apps/app/src/server/routes/apiv3/index.js @@ -6,9 +6,9 @@ import injectUserRegistrationOrderByTokenMiddleware from '../../middlewares/inje import * as loginFormValidator from '../../middlewares/login-form-validator'; import * as registerFormValidator from '../../middlewares/register-form-validator'; +import aiIntegration from './ai-integration'; import g2gTransfer from './g2g-transfer'; import importRoute from './import'; -import openai from './openai'; import pageListing from './page-listing'; import securitySettings from './security-settings'; import * as userActivation from './user-activation'; @@ -120,7 +120,7 @@ module.exports = (crowi, app) => { router.use('/questionnaire', require('~/features/questionnaire/server/routes/apiv3/questionnaire')(crowi)); router.use('/templates', require('~/features/templates/server/routes/apiv3')(crowi)); - router.use('/openai', openai(crowi)); + router.use('/ai-integration', aiIntegration(crowi)); return [router, routerForAdmin, routerForAuth]; }; From 707f096f2da04c06698fab760ecb8c52d9bb1b5d Mon Sep 17 00:00:00 2001 From: Yuki Takei Date: Tue, 17 Sep 2024 09:12:03 +0000 Subject: [PATCH 199/490] add faker --- package.json | 1 + yarn.lock | 36 ++++++++---------------------------- 2 files changed, 9 insertions(+), 28 deletions(-) diff --git a/package.json b/package.json index 3646f522a09..e961fddd927 100644 --- a/package.json +++ b/package.json @@ -81,6 +81,7 @@ "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-rulesdir": "^0.2.2", "eslint-plugin-vitest": "^0.2.3", + "@faker-js/faker": "^9.0.1", "glob": "^8.1.0", "mock-require": "^3.0.3", "nodemon": "^3.1.3", diff --git a/yarn.lock b/yarn.lock index 6dbf75b544b..6eeeaf9941f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2079,6 +2079,11 @@ resolved "https://registry.yarnpkg.com/@exodus/schemasafe/-/schemasafe-1.1.1.tgz#006ab8b33b1aec6d2992c75e5918c65197388aa2" integrity sha512-Pd7+aGvWIaTDL5ecV4ZBEtBrjXnk8/ly5xyHbikxVhgcq7qhihzHWHbcYmFupQBT2A5ggNZGvT7Bpj0M6AKHjA== +"@faker-js/faker@^9.0.1": + version "9.0.1" + resolved "https://registry.yarnpkg.com/@faker-js/faker/-/faker-9.0.1.tgz#5e201ffc4524d00a200c648d2be55be6e25b3c3e" + integrity sha512-4mDeYIgM3By7X6t5E6eYwLAa+2h4DeZDF7thhzIg6XB76jeEvMwadYAMCFJL/R4AnEBcAUO9+gL0vhy3s+qvZA== + "@fastify/busboy@^2.0.0": version "2.1.1" resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-2.1.1.tgz#b9da6a878a371829a0502c9b6c1c143ef6663f4d" @@ -17066,7 +17071,7 @@ string-template@>=1.0.0: resolved "https://registry.yarnpkg.com/string-template/-/string-template-1.0.0.tgz#9e9f2233dc00f218718ec379a28a5673ecca8b96" integrity sha1-np8iM9wA8hhxjsN5oopWc+zKi5Y= -"string-width-cjs@npm:string-width@^4.2.0": +"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -17084,15 +17089,6 @@ string-width@=4.2.2: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.0" -"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - string-width@^5.0.1, string-width@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" @@ -17176,7 +17172,7 @@ stringify-entities@^4.0.0: character-entities-html4 "^2.0.0" character-entities-legacy "^3.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -17190,13 +17186,6 @@ strip-ansi@^3.0.0: dependencies: ansi-regex "^2.0.0" -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - strip-ansi@^7.0.1, strip-ansi@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -18978,7 +18967,7 @@ word-wrap@^1.2.3: resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -18996,15 +18985,6 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" From 69eecf97a3d502ea1aa63de82372d79384312a23 Mon Sep 17 00:00:00 2001 From: shironegi39 Date: Tue, 17 Sep 2024 09:17:31 +0000 Subject: [PATCH 200/490] Synchronize notification counts --- .../InAppNotification/InAppNotificationElm.tsx | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/apps/app/src/client/components/InAppNotification/InAppNotificationElm.tsx b/apps/app/src/client/components/InAppNotification/InAppNotificationElm.tsx index 9048acb0e46..a9ad5bdbb68 100644 --- a/apps/app/src/client/components/InAppNotification/InAppNotificationElm.tsx +++ b/apps/app/src/client/components/InAppNotification/InAppNotificationElm.tsx @@ -1,10 +1,13 @@ -import React, { FC } from 'react'; +import type { FC } from 'react'; +import React from 'react'; import type { HasObjectId } from '@growi/core'; import { UserPicture } from '@growi/ui/dist/components'; import { apiv3Post } from '~/client/util/apiv3-client'; -import { IInAppNotification, InAppNotificationStatuses } from '~/interfaces/in-app-notification'; +import type { IInAppNotification } from '~/interfaces/in-app-notification'; +import { InAppNotificationStatuses } from '~/interfaces/in-app-notification'; +import { useSWRxInAppNotificationStatus } from '~/stores/in-app-notification'; import { useModelNotification } from './PageNotification'; @@ -21,16 +24,18 @@ const InAppNotificationElm: FC = (props: Props) => { const Notification = modelNotificationUtils?.Notification; const publishOpen = modelNotificationUtils?.publishOpen; + const { mutate: mutateNotificationCount } = useSWRxInAppNotificationStatus(); if (Notification == null || publishOpen == null) { return <>; } const clickHandler = async(notification: IInAppNotification & HasObjectId): Promise => { - if (notification.status === InAppNotificationStatuses.STATUS_UNOPENED) { + if (notification.status === InAppNotificationStatuses.STATUS_UNREAD) { // set notification status "OPEND" await apiv3Post('/in-app-notification/open', { id: notification._id }); onUnopenedNotificationOpend?.(); + mutateNotificationCount(); } publishOpen(); @@ -59,7 +64,7 @@ const InAppNotificationElm: FC = (props: Props) => {
                  clickHandler(notification)} style={{ cursor: 'pointer' }}>
                  Date: Tue, 17 Sep 2024 09:58:56 +0000 Subject: [PATCH 201/490] fb --- .../client/components/DescendantsPageList.tsx | 11 +++++------ .../Navbar/GrowiContextualSubNavigation.tsx | 11 +++++------ .../client/components/PageEditor/PageEditor.tsx | 8 +++----- .../SearchPage/SearchResultContent.tsx | 16 ++++++++-------- .../components/SearchPage/SearchResultList.tsx | 16 +++++++--------- .../TreeItem/NewPageInput/use-new-page-input.tsx | 8 +++----- .../PageView/PageAlerts/WipPageAlert.tsx | 9 ++++----- apps/app/src/stores/page-listing.tsx | 13 ++++++++++++- 8 files changed, 47 insertions(+), 45 deletions(-) diff --git a/apps/app/src/client/components/DescendantsPageList.tsx b/apps/app/src/client/components/DescendantsPageList.tsx index 41824139ff4..ce3b962923c 100644 --- a/apps/app/src/client/components/DescendantsPageList.tsx +++ b/apps/app/src/client/components/DescendantsPageList.tsx @@ -14,7 +14,7 @@ import type { OnDeletedFunction, OnPutBackedFunction } from '~/interfaces/ui'; import { useIsGuestUser, useIsReadOnlyUser, useIsSharedUser } from '~/stores-universal/context'; import { mutatePageTree, - useSWRxPageInfoForList, useSWRxPageList, useSWRINFxRecentlyUpdated, + useSWRxPageInfoForList, useSWRxPageList, mutateSWRINFxRecentlyUpdated, } from '~/stores/page-listing'; import type { ForceHideMenuItems } from './Common/Dropdown/PageItemControl'; @@ -47,7 +47,6 @@ const DescendantsPageListSubstance = (props: SubstanceProps): JSX.Element => { const pageIds = pagingResult?.items?.map(page => page._id); const { injectTo } = useSWRxPageInfoForList(pageIds, null, true, true); - const { mutate: mutateRecentlyUpdated } = useSWRINFxRecentlyUpdated(20, true); let pageWithMetas: IDataWithMeta[] = []; @@ -68,22 +67,22 @@ const DescendantsPageListSubstance = (props: SubstanceProps): JSX.Element => { else { toastSuccess(t('deleted_pages_completely', { path })); } - mutateRecentlyUpdated(); + mutateSWRINFxRecentlyUpdated(); mutatePageTree(); if (onPagesDeleted != null) { onPagesDeleted(...args); } - }, [onPagesDeleted, mutateRecentlyUpdated, t]); + }, [onPagesDeleted, t]); const pagePutBackedHandler: OnPutBackedFunction = useCallback((path) => { toastSuccess(t('page_has_been_reverted', { path })); - mutateRecentlyUpdated(); + mutateSWRINFxRecentlyUpdated(); mutatePageTree(); if (onPagePutBacked != null) { onPagePutBacked(path); } - }, [onPagePutBacked, mutateRecentlyUpdated, t]); + }, [onPagePutBacked, t]); if (pagingResult == null) { return ( diff --git a/apps/app/src/client/components/Navbar/GrowiContextualSubNavigation.tsx b/apps/app/src/client/components/Navbar/GrowiContextualSubNavigation.tsx index 9a71fd51c83..a6f9cbf93d9 100644 --- a/apps/app/src/client/components/Navbar/GrowiContextualSubNavigation.tsx +++ b/apps/app/src/client/components/Navbar/GrowiContextualSubNavigation.tsx @@ -34,7 +34,7 @@ import { import { useSWRMUTxCurrentPage, useCurrentPageId, useSWRxPageInfo, } from '~/stores/page'; -import { mutatePageTree, useSWRINFxRecentlyUpdated } from '~/stores/page-listing'; +import { mutatePageTree, mutateSWRINFxRecentlyUpdated } from '~/stores/page-listing'; import { useIsAbleToShowPageManagement, useIsAbleToChangeEditorMode, @@ -247,7 +247,6 @@ const GrowiContextualSubNavigation = (props: GrowiContextualSubNavigationProps): const { open: openRenameModal } = usePageRenameModal(); const { open: openDeleteModal } = usePageDeleteModal(); const { mutate: mutatePageInfo } = useSWRxPageInfo(pageId); - const { mutate: mutateRecentlyUpdated } = useSWRINFxRecentlyUpdated(20, true); const [isStickyActive, setStickyActive] = useState(false); @@ -272,10 +271,10 @@ const GrowiContextualSubNavigation = (props: GrowiContextualSubNavigationProps): mutateCurrentPage(); mutatePageInfo(); mutatePageTree(); - mutateRecentlyUpdated(); + mutateSWRINFxRecentlyUpdated(); }; openRenameModal(page, { onRenamed: renamedHandler }); - }, [mutateCurrentPage, mutatePageInfo, openRenameModal, mutateRecentlyUpdated]); + }, [mutateCurrentPage, mutatePageInfo, openRenameModal]); const deleteItemClickedHandler = useCallback((pageWithMeta: IPageWithMeta) => { const deletedHandler: OnDeletedFunction = (pathOrPathsToDelete, isRecursively, isCompletely) => { @@ -296,10 +295,10 @@ const GrowiContextualSubNavigation = (props: GrowiContextualSubNavigationProps): mutateCurrentPage(); mutatePageInfo(); mutatePageTree(); - mutateRecentlyUpdated(); + mutateSWRINFxRecentlyUpdated(); }; openDeleteModal([pageWithMeta], { onDeleted: deletedHandler }); - }, [currentPathname, mutateCurrentPage, openDeleteModal, router, mutatePageInfo, mutateRecentlyUpdated]); + }, [currentPathname, mutateCurrentPage, openDeleteModal, router, mutatePageInfo]); const switchContentWidthHandler = useCallback(async(pageId: string, value: boolean) => { if (!isSharedPage) { diff --git a/apps/app/src/client/components/PageEditor/PageEditor.tsx b/apps/app/src/client/components/PageEditor/PageEditor.tsx index 48a34a0fefc..c2b3d6fa4f3 100644 --- a/apps/app/src/client/components/PageEditor/PageEditor.tsx +++ b/apps/app/src/client/components/PageEditor/PageEditor.tsx @@ -41,7 +41,7 @@ import { import { useCurrentPagePath, useSWRxCurrentPage, useCurrentPageId, useIsNotFound, useTemplateBodyData, useSWRxCurrentGrantData, } from '~/stores/page'; -import { mutatePageTree, useSWRINFxRecentlyUpdated } from '~/stores/page-listing'; +import { mutatePageTree, mutateSWRINFxRecentlyUpdated } from '~/stores/page-listing'; import { usePreviewOptions } from '~/stores/renderer'; import { useIsUntitledPage, useSelectedGrant } from '~/stores/ui'; import { useEditingUsers } from '~/stores/use-editing-users'; @@ -165,8 +165,6 @@ export const PageEditor = React.memo((props: Props): JSX.Element => { const scrollEditorHandlerThrottle = useMemo(() => throttle(25, scrollEditorHandler), [scrollEditorHandler]); const scrollPreviewHandlerThrottle = useMemo(() => throttle(25, scrollPreviewHandler), [scrollPreviewHandler]); - const { mutate: mutateRecentlyUpdated } = useSWRINFxRecentlyUpdated(20, true); - const save: Save = useCallback(async(revisionId, markdown, opts, onConflict) => { if (pageId == null || selectedGrant == null) { @@ -193,7 +191,7 @@ export const PageEditor = React.memo((props: Props): JSX.Element => { // to sync revision id with page tree: https://github.com/weseek/growi/pull/7227 mutatePageTree(); - mutateRecentlyUpdated(); + mutateSWRINFxRecentlyUpdated(); // sync current grant data after update mutateIsGrantNormalized(); @@ -215,7 +213,7 @@ export const PageEditor = React.memo((props: Props): JSX.Element => { finally { mutateWaitingSaveProcessing(false); } - }, [pageId, selectedGrant, mutateWaitingSaveProcessing, updatePage, mutateIsGrantNormalized, mutateRecentlyUpdated, t]); + }, [pageId, selectedGrant, mutateWaitingSaveProcessing, updatePage, mutateIsGrantNormalized, t]); const saveAndReturnToViewHandler = useCallback(async(opts: SaveOptions) => { const markdown = codeMirrorEditor?.getDoc(); diff --git a/apps/app/src/client/components/SearchPage/SearchResultContent.tsx b/apps/app/src/client/components/SearchPage/SearchResultContent.tsx index 8ec3f6b4ccf..810daa310dc 100644 --- a/apps/app/src/client/components/SearchPage/SearchResultContent.tsx +++ b/apps/app/src/client/components/SearchPage/SearchResultContent.tsx @@ -21,7 +21,7 @@ import { useCurrentUser } from '~/stores-universal/context'; import { usePageDuplicateModal, usePageRenameModal, usePageDeleteModal, } from '~/stores/modal'; -import { mutatePageList, mutatePageTree, useSWRINFxRecentlyUpdated } from '~/stores/page-listing'; +import { mutatePageList, mutatePageTree, mutateSWRINFxRecentlyUpdated } from '~/stores/page-listing'; import { useSearchResultOptions } from '~/stores/renderer'; import { mutateSearching } from '~/stores/search'; @@ -126,7 +126,7 @@ export const SearchResultContent: FC = (props: Props) => { const { open: openDeleteModal } = usePageDeleteModal(); const { data: rendererOptions } = useSearchResultOptions(pageWithMeta.data.path, highlightKeywords); const { data: currentUser } = useCurrentUser(); - const { mutate: mutateRecentlyUpdated } = useSWRINFxRecentlyUpdated(20, true); + const shouldExpandContent = useShouldExpandContent(page); const duplicateItemClickedHandler = useCallback(async(pageToDuplicate) => { @@ -135,24 +135,24 @@ export const SearchResultContent: FC = (props: Props) => { toastSuccess(t('duplicated_pages', { fromPath })); mutatePageTree(); - mutateRecentlyUpdated(); + mutateSWRINFxRecentlyUpdated(); mutateSearching(); mutatePageList(); }; openDuplicateModal(pageToDuplicate, { onDuplicated: duplicatedHandler }); - }, [openDuplicateModal, mutateRecentlyUpdated, t]); + }, [openDuplicateModal, t]); const renameItemClickedHandler = useCallback((pageToRename: IPageToRenameWithMeta) => { const renamedHandler: OnRenamedFunction = (path) => { toastSuccess(t('renamed_pages', { path })); mutatePageTree(); - mutateRecentlyUpdated(); + mutateSWRINFxRecentlyUpdated(); mutateSearching(); mutatePageList(); }; openRenameModal(pageToRename, { onRenamed: renamedHandler }); - }, [openRenameModal, mutateRecentlyUpdated, t]); + }, [openRenameModal, t]); const onDeletedHandler: OnDeletedFunction = useCallback((pathOrPathsToDelete, isRecursively, isCompletely) => { if (typeof pathOrPathsToDelete !== 'string') { @@ -167,10 +167,10 @@ export const SearchResultContent: FC = (props: Props) => { toastSuccess(t('deleted_pages', { path })); } mutatePageTree(); - mutateRecentlyUpdated(); + mutateSWRINFxRecentlyUpdated(); mutateSearching(); mutatePageList(); - }, [mutateRecentlyUpdated, t]); + }, [t]); const deleteItemClickedHandler = useCallback((pageToDelete: IPageToDeleteWithMeta) => { openDeleteModal([pageToDelete], { onDeleted: onDeletedHandler }); diff --git a/apps/app/src/client/components/SearchPage/SearchResultList.tsx b/apps/app/src/client/components/SearchPage/SearchResultList.tsx index 1a465b85f66..ad7f0ddeb42 100644 --- a/apps/app/src/client/components/SearchPage/SearchResultList.tsx +++ b/apps/app/src/client/components/SearchPage/SearchResultList.tsx @@ -12,7 +12,7 @@ import type { ISelectable, ISelectableAll } from '~/client/interfaces/selectable import { toastSuccess } from '~/client/util/toastr'; import type { IPageSearchMeta, IPageWithSearchMeta } from '~/interfaces/search'; import { useIsGuestUser, useIsReadOnlyUser } from '~/stores-universal/context'; -import { mutatePageTree, useSWRxPageInfoForList, useSWRINFxRecentlyUpdated } from '~/stores/page-listing'; +import { mutatePageTree, useSWRxPageInfoForList, mutateSWRINFxRecentlyUpdated } from '~/stores/page-listing'; import { mutateSearching } from '~/stores/search'; import type { ForceHideMenuItems } from '../Common/Dropdown/PageItemControl'; @@ -89,24 +89,22 @@ const SearchResultListSubstance: ForwardRefRenderFunction }); } - const { mutate: mutateRecentlyUpdated } = useSWRINFxRecentlyUpdated(20, true); - // eslint-disable-next-line @typescript-eslint/no-unused-vars const duplicatedHandler = useCallback((fromPath, toPath) => { toastSuccess(t('duplicated_pages', { fromPath })); mutatePageTree(); - mutateRecentlyUpdated(); + mutateSWRINFxRecentlyUpdated(); mutateSearching(); - }, [t, mutateRecentlyUpdated]); + }, [t]); const renamedHandler = useCallback((path) => { toastSuccess(t('renamed_pages', { path })); mutatePageTree(); - mutateRecentlyUpdated(); + mutateSWRINFxRecentlyUpdated(); mutateSearching(); - }, [t, mutateRecentlyUpdated]); + }, [t]); const deletedHandler = useCallback((pathOrPathsToDelete, isRecursively, isCompletely) => { if (typeof pathOrPathsToDelete !== 'string') { @@ -122,9 +120,9 @@ const SearchResultListSubstance: ForwardRefRenderFunction toastSuccess(t('deleted_pages', { path })); } mutatePageTree(); - mutateRecentlyUpdated(); + mutateSWRINFxRecentlyUpdated(); mutateSearching(); - }, [t, mutateRecentlyUpdated]); + }, [t]); return (
                    diff --git a/apps/app/src/client/components/TreeItem/NewPageInput/use-new-page-input.tsx b/apps/app/src/client/components/TreeItem/NewPageInput/use-new-page-input.tsx index bba087e21fd..1c2b31b7f16 100644 --- a/apps/app/src/client/components/TreeItem/NewPageInput/use-new-page-input.tsx +++ b/apps/app/src/client/components/TreeItem/NewPageInput/use-new-page-input.tsx @@ -16,7 +16,7 @@ import { useCreatePage } from '~/client/services/create-page'; import { toastWarning, toastError, toastSuccess } from '~/client/util/toastr'; import type { InputValidationResult } from '~/client/util/use-input-validator'; import { ValidationTarget, useInputValidator } from '~/client/util/use-input-validator'; -import { mutatePageTree, useSWRINFxRecentlyUpdated } from '~/stores/page-listing'; +import { mutatePageTree, mutateSWRINFxRecentlyUpdated } from '~/stores/page-listing'; import { usePageTreeDescCountMap } from '~/stores/ui'; import { shouldCreateWipPage } from '../../../../utils/should-create-wip-page'; @@ -89,8 +89,6 @@ export const useNewPageInput = (): UseNewPageInput => { setShowInput(false); }, []); - const { mutate: mutateRecentlyUpdated } = useSWRINFxRecentlyUpdated(20, true); - const create = useCallback(async(inputText) => { if (inputText.trim() === '') { return cancel(); @@ -125,7 +123,7 @@ export const useNewPageInput = (): UseNewPageInput => { skipTransition: true, onCreated: () => { mutatePageTree(); - mutateRecentlyUpdated(); + mutateSWRINFxRecentlyUpdated(); if (!hasDescendants) { stateHandlers?.setIsOpen(true); @@ -142,7 +140,7 @@ export const useNewPageInput = (): UseNewPageInput => { finally { setProcessingSubmission(false); } - }, [cancel, hasDescendants, page.path, stateHandlers, t, createPage, mutateRecentlyUpdated]); + }, [cancel, hasDescendants, page.path, stateHandlers, t, createPage]); const inputContainerClass = newPageInputStyles['new-page-input-container'] ?? ''; const isInvalid = validationResult != null; diff --git a/apps/app/src/components/PageView/PageAlerts/WipPageAlert.tsx b/apps/app/src/components/PageView/PageAlerts/WipPageAlert.tsx index 2a452b2bd82..798c2288e00 100644 --- a/apps/app/src/components/PageView/PageAlerts/WipPageAlert.tsx +++ b/apps/app/src/components/PageView/PageAlerts/WipPageAlert.tsx @@ -3,14 +3,12 @@ import React, { useCallback } from 'react'; import { useTranslation } from 'react-i18next'; import { useSWRMUTxCurrentPage, useSWRxCurrentPage } from '~/stores/page'; -import { useSWRINFxRecentlyUpdated } from '~/stores/page-listing'; + export const WipPageAlert = (): JSX.Element => { const { t } = useTranslation(); const { data: currentPage } = useSWRxCurrentPage(); const { trigger: mutateCurrentPage } = useSWRMUTxCurrentPage(); - const { mutate: mutateRecentlyUpdated } = useSWRINFxRecentlyUpdated(20, true); - const clickPagePublishButton = useCallback(async() => { const pageId = currentPage?._id; @@ -28,7 +26,8 @@ export const WipPageAlert = (): JSX.Element => { const mutatePageTree = (await import('~/stores/page-listing')).mutatePageTree; await mutatePageTree(); - await mutateRecentlyUpdated(); + const mutateSWRINFxRecentlyUpdated = (await import('~/stores/page-listing')).mutateSWRINFxRecentlyUpdated; + await mutateSWRINFxRecentlyUpdated(); const toastSuccess = (await import('~/client/util/toastr')).toastSuccess; toastSuccess(t('wip_page.success_publish_page')); @@ -37,7 +36,7 @@ export const WipPageAlert = (): JSX.Element => { const toastError = (await import('~/client/util/toastr')).toastError; toastError(t('wip_page.fail_publish_page')); } - }, [currentPage?._id, mutateCurrentPage, t, mutateRecentlyUpdated]); + }, [currentPage?._id, mutateCurrentPage, t]); if (!currentPage?.wip) { diff --git a/apps/app/src/stores/page-listing.tsx b/apps/app/src/stores/page-listing.tsx index ae8c1e82b87..9d2193ce9a5 100644 --- a/apps/app/src/stores/page-listing.tsx +++ b/apps/app/src/stores/page-listing.tsx @@ -7,9 +7,10 @@ import type { import useSWR, { mutate, type SWRConfiguration, type SWRResponse, type Arguments, } from 'swr'; +import { cache } from 'swr/_internal'; import useSWRImmutable from 'swr/immutable'; import type { SWRInfiniteResponse } from 'swr/infinite'; -import useSWRInfinite from 'swr/infinite'; +import useSWRInfinite from 'swr/infinite'; // eslint-disable-line import type { IPagingResult } from '~/interfaces/paging-result'; @@ -54,6 +55,16 @@ export const useSWRINFxRecentlyUpdated = (limit: number, includeWipPage?: boolea ); }; +export const mutateSWRINFxRecentlyUpdated = async(): Promise => { + const promises: Promise[] = []; + for (const key of cache.keys()) { + if (key.includes('/pages/recent')) { + promises.push(mutate(key)); + } + } + return Promise.all(promises); +}; + export const mutatePageList = async(): Promise => { return mutate( key => Array.isArray(key) && key[0] === '/pages/list', From 1799502e6387fd25ed69323f3134850d1a091935 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Sep 2024 00:23:30 +0000 Subject: [PATCH 202/490] ci(deps-dev): bump vite from 5.2.9 to 5.2.14 Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.2.9 to 5.2.14. - [Release notes](https://github.com/vitejs/vite/releases) - [Changelog](https://github.com/vitejs/vite/blob/v5.2.14/packages/vite/CHANGELOG.md) - [Commits](https://github.com/vitejs/vite/commits/v5.2.14/packages/vite) --- updated-dependencies: - dependency-name: vite dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 3646f522a09..7b083462b3a 100644 --- a/package.json +++ b/package.json @@ -100,7 +100,7 @@ "tsconfig-paths": "^4.2.0", "typescript": "~5.0.0", "typescript-transform-paths": "^3.4.7", - "vite": "^5.2.9", + "vite": "^5.2.14", "vite-plugin-dts": "^3.8.3", "vite-tsconfig-paths": "^4.3.2", "vitest": "~1.6.0", diff --git a/yarn.lock b/yarn.lock index 6dbf75b544b..bbb8c3eb4c0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18734,10 +18734,10 @@ vite-tsconfig-paths@^4.3.2: globrex "^0.1.2" tsconfck "^3.0.3" -vite@^5.0.0, vite@^5.2.9: - version "5.2.9" - resolved "https://registry.yarnpkg.com/vite/-/vite-5.2.9.tgz#cd9a356c6ff5f7456c09c5ce74068ffa8df743d9" - integrity sha512-uOQWfuZBlc6Y3W/DTuQ1Sr+oIXWvqljLvS881SVmAj00d5RdgShLcuXWxseWPd4HXwiYBFW/vXHfKFeqj9uQnw== +vite@^5.0.0, vite@^5.2.14: + version "5.2.14" + resolved "https://registry.yarnpkg.com/vite/-/vite-5.2.14.tgz#fd5f60facf6b5f90ec7da6323c467a365d380c3d" + integrity sha512-TFQLuwWLPms+NBNlh0D9LZQ+HXW471COABxw/9TEUBrjuHMo9BrYBPrN/SYAwIuVL+rLerycxiLT41t4f5MZpA== dependencies: esbuild "^0.20.1" postcss "^8.4.38" From 08b9825ac0766ab82d10ac57c2bc364503f3568f Mon Sep 17 00:00:00 2001 From: Shun Miyazawa Date: Wed, 18 Sep 2024 01:54:13 +0000 Subject: [PATCH 203/490] create PUT: /_api/v3/ai-integration/recreate-vector-store --- .../routes/apiv3/ai-integration/index.ts | 2 ++ .../ai-integration/recreate-vector-store.ts | 31 +++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 apps/app/src/server/routes/apiv3/ai-integration/recreate-vector-store.ts diff --git a/apps/app/src/server/routes/apiv3/ai-integration/index.ts b/apps/app/src/server/routes/apiv3/ai-integration/index.ts index 302fd0a8404..24a5ebf0096 100644 --- a/apps/app/src/server/routes/apiv3/ai-integration/index.ts +++ b/apps/app/src/server/routes/apiv3/ai-integration/index.ts @@ -1,10 +1,12 @@ import express from 'express'; import { chatHandlersFactory } from './chat'; +import { recreateVectorStoreHandlersFactory } from './recreate-vector-store'; const router = express.Router(); module.exports = (crowi) => { router.post('/chat', chatHandlersFactory(crowi)); + router.put('/recreate-vector-store', recreateVectorStoreHandlersFactory(crowi)); return router; }; diff --git a/apps/app/src/server/routes/apiv3/ai-integration/recreate-vector-store.ts b/apps/app/src/server/routes/apiv3/ai-integration/recreate-vector-store.ts new file mode 100644 index 00000000000..bb5228b7fa5 --- /dev/null +++ b/apps/app/src/server/routes/apiv3/ai-integration/recreate-vector-store.ts @@ -0,0 +1,31 @@ +import type { Request, RequestHandler } from 'express'; +import type { ValidationChain } from 'express-validator'; + +import type Crowi from '~/server/crowi'; +import loggerFactory from '~/utils/logger'; + +import { apiV3FormValidator } from '../../../middlewares/apiv3-form-validator'; +import type { ApiV3Response } from '../interfaces/apiv3-response'; + +const logger = loggerFactory('growi:routes:apiv3:ai-integration:recreate-vector-store'); + +type Req = Request + +type RecreateVectorStoreFactory = (crowi: Crowi) => RequestHandler[]; + +export const recreateVectorStoreHandlersFactory: RecreateVectorStoreFactory = (crowi) => { + const accessTokenParser = require('~/server/middlewares/access-token-parser')(crowi); + const loginRequiredStrictly = require('~/server/middlewares/login-required')(crowi); + const adminRequired = require('~/server/middlewares/admin-required')(crowi); + + const validator: ValidationChain[] = [ + // + ]; + + return [ + accessTokenParser, loginRequiredStrictly, adminRequired, validator, apiV3FormValidator, + async(req: Req, res: ApiV3Response) => { + return res.apiv3({}); + }, + ]; +}; From 3ab8713379d8c08c0b37c8708357e7253127f018 Mon Sep 17 00:00:00 2001 From: moekumasaka Date: Wed, 18 Sep 2024 04:08:11 +0000 Subject: [PATCH 204/490] manually close the dropdown --- .../src/client/components/CustomNavigation/CustomNav.tsx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/apps/app/src/client/components/CustomNavigation/CustomNav.tsx b/apps/app/src/client/components/CustomNavigation/CustomNav.tsx index 02254e604ca..3c25b9ca7ba 100644 --- a/apps/app/src/client/components/CustomNavigation/CustomNav.tsx +++ b/apps/app/src/client/components/CustomNavigation/CustomNav.tsx @@ -44,6 +44,8 @@ export const CustomNavDropdown = (props: CustomNavDropdownProps): JSX.Element => const [isDropdownOpen, setIsDropdownOpen] = useState(false); + const dropdownButtonRef = useRef(null); + const handleDropdownToggle = () => { setIsDropdownOpen(prev => !prev); }; @@ -52,12 +54,17 @@ export const CustomNavDropdown = (props: CustomNavDropdownProps): JSX.Element => if (onNavSelected != null) { onNavSelected(key); } + // Manually close the dropdown setIsDropdownOpen(false); + if (dropdownButtonRef.current) { + dropdownButtonRef.current.classList.remove('show'); + } }, [onNavSelected]); return (
                    + +

                    + {t('ai_integration.rebuild_vector_store_explanation1')}
                    + {t('ai_integration.rebuild_vector_store_explanation2')}
                    +

                    +
                    +
                  +
                  + ); +}; diff --git a/apps/app/src/pages/admin/ai-integration.page.tsx b/apps/app/src/pages/admin/ai-integration.page.tsx index 440a7c29fcf..a43d5061113 100644 --- a/apps/app/src/pages/admin/ai-integration.page.tsx +++ b/apps/app/src/pages/admin/ai-integration.page.tsx @@ -13,6 +13,7 @@ import { retrieveServerSideProps } from '../../utils/admin-page-util'; const AdminLayout = dynamic(() => import('~/components/Layout/AdminLayout'), { ssr: false }); const ForbiddenPage = dynamic(() => import('~/client/components/Admin/ForbiddenPage').then(mod => mod.ForbiddenPage), { ssr: false }); +const AiIntegration = dynamic(() => import('~/client/components/Admin/AiIntegration/AiIntegration').then(mod => mod.AiIntegration), { ssr: false }); const AiIntegrationDisableMode = dynamic( () => import('~/client/components/Admin/AiIntegration/AiIntegrationDisableMode').then(mod => mod.AiIntegrationDisableMode), { ssr: false }, ); @@ -21,7 +22,7 @@ type Props = CommonProps & { aiEnabled: boolean, }; -const AdminAiIntegrationPage: NextPage = (props) => { +const AdminAiIntegrationPage: NextPage = (props: Props) => { const { t } = useTranslation('admin'); const title = t('ai_integration.ai_integration'); @@ -37,7 +38,7 @@ const AdminAiIntegrationPage: NextPage = (props) => { {headTitle} {props.aiEnabled - ? <> // TODO: implement admin page + ? : } From db45ae62893873af7c35e81d578a2d69dfbda1b8 Mon Sep 17 00:00:00 2001 From: Shun Miyazawa Date: Wed, 18 Sep 2024 07:10:33 +0000 Subject: [PATCH 208/490] Add TODO --- .../src/client/components/Admin/AiIntegration/AiIntegration.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/app/src/client/components/Admin/AiIntegration/AiIntegration.tsx b/apps/app/src/client/components/Admin/AiIntegration/AiIntegration.tsx index 99d36b5bcdc..2492e74add9 100644 --- a/apps/app/src/client/components/Admin/AiIntegration/AiIntegration.tsx +++ b/apps/app/src/client/components/Admin/AiIntegration/AiIntegration.tsx @@ -28,6 +28,7 @@ export const AiIntegration = (): JSX.Element => {
                  + {/* TODO: https://redmine.weseek.co.jp/issues/153978 */}
                  diff --git a/apps/app/src/stores-universal/context.tsx b/apps/app/src/stores-universal/context.tsx index bdf619940ec..7ea875f50d7 100644 --- a/apps/app/src/stores-universal/context.tsx +++ b/apps/app/src/stores-universal/context.tsx @@ -286,7 +286,7 @@ export const useAcceptedUploadFileType = (): SWRResponse => { +export const useGrowiDocumentationUrl = (): SWRResponse<'https://growi.cloud/help' | 'https://docs.growi.org', Error> => { const { data: growiCloudUri } = useGrowiCloudUri(); const { data: growiAppIdForGrowiCloud } = useGrowiAppIdForGrowiCloud(); @@ -294,9 +294,9 @@ export const useGrowiDocumentationUrl = (): SWRResponse<'growi.cloud/help' | 'do ['documentationUrl', growiCloudUri, growiAppIdForGrowiCloud], ([growiCloudUri, growiAppIdForGrowiCloud]) => { if (growiCloudUri != null && growiAppIdForGrowiCloud != null) { - return 'growi.cloud/help'; + return 'https://growi.cloud/help'; } - return 'docs.growi.org'; + return 'https://docs.growi.org'; }, ); }; From f1d56618d5c04c6ccc25aa90fecec2f3ef80e307 Mon Sep 17 00:00:00 2001 From: Yuki Takei Date: Mon, 23 Sep 2024 16:37:10 +0000 Subject: [PATCH 264/490] improve swr hook to ensure retuened data is not undefined --- .../components/Admin/G2GDataTransfer.tsx | 2 +- .../client/components/DataTransferForm.tsx | 2 +- apps/app/src/stores-universal/context.tsx | 25 +++++++++++-------- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/apps/app/src/client/components/Admin/G2GDataTransfer.tsx b/apps/app/src/client/components/Admin/G2GDataTransfer.tsx index a246b0ed157..8f1e1a12f6b 100644 --- a/apps/app/src/client/components/Admin/G2GDataTransfer.tsx +++ b/apps/app/src/client/components/Admin/G2GDataTransfer.tsx @@ -282,7 +282,7 @@ const G2GDataTransfer = (): JSX.Element => { className="mb-0" // eslint-disable-next-line react/no-danger dangerouslySetInnerHTML={{ - __html: t('commons:g2g_data_transfer.transfer_to_growi_cloud', { documentationUrl: documentationUrl || 'https://docs.growi.org' }), + __html: t('commons:g2g_data_transfer.transfer_to_growi_cloud', { documentationUrl }), }} />
                  diff --git a/apps/app/src/client/components/DataTransferForm.tsx b/apps/app/src/client/components/DataTransferForm.tsx index 437c93fe3d0..80a72052689 100644 --- a/apps/app/src/client/components/DataTransferForm.tsx +++ b/apps/app/src/client/components/DataTransferForm.tsx @@ -39,7 +39,7 @@ const DataTransferForm = (): JSX.Element => { className="mb-0" // eslint-disable-next-line react/no-danger dangerouslySetInnerHTML={{ - __html: t('g2g_data_transfer.transfer_to_growi_cloud', { documentationUrl: documentationUrl || 'https://docs.growi.org' }), + __html: t('g2g_data_transfer.transfer_to_growi_cloud', { documentationUrl }), }} />
                  diff --git a/apps/app/src/stores-universal/context.tsx b/apps/app/src/stores-universal/context.tsx index 7ea875f50d7..c32045ddd20 100644 --- a/apps/app/src/stores-universal/context.tsx +++ b/apps/app/src/stores-universal/context.tsx @@ -1,5 +1,3 @@ -import { useCallback, useEffect } from 'react'; - import type EventEmitter from 'events'; import { AcceptedUploadFileType } from '@growi/core'; @@ -286,17 +284,22 @@ export const useAcceptedUploadFileType = (): SWRResponse => { +// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types +export const useGrowiDocumentationUrl = () => { const { data: growiCloudUri } = useGrowiCloudUri(); - const { data: growiAppIdForGrowiCloud } = useGrowiAppIdForGrowiCloud(); - return useSWRImmutable( - ['documentationUrl', growiCloudUri, growiAppIdForGrowiCloud], - ([growiCloudUri, growiAppIdForGrowiCloud]) => { - if (growiCloudUri != null && growiAppIdForGrowiCloud != null) { - return 'https://growi.cloud/help'; - } - return 'https://docs.growi.org'; + return useSWR( + ['documentationUrl', growiCloudUri], + ([, growiCloudUri]) => { + const url = growiCloudUri != null + ? new URL('/help', growiCloudUri) + : new URL('https://docs.growi.org'); + return url.toString(); + }, + { + fallbackData: 'https://docs.growi.org', + revalidateOnFocus: false, + revalidateOnReconnect: false, }, ); }; From 5edf9bf3813fefc8069ac3388c7fb05693978af4 Mon Sep 17 00:00:00 2001 From: Yuki Takei Date: Mon, 23 Sep 2024 16:37:38 +0000 Subject: [PATCH 265/490] inject app:growiCloudUri --- apps/app/src/pages/admin/data-transfer.page.tsx | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/apps/app/src/pages/admin/data-transfer.page.tsx b/apps/app/src/pages/admin/data-transfer.page.tsx index bb208cb428b..982757f9dd8 100644 --- a/apps/app/src/pages/admin/data-transfer.page.tsx +++ b/apps/app/src/pages/admin/data-transfer.page.tsx @@ -9,8 +9,9 @@ import Head from 'next/head'; import type { Container } from 'unstated'; import { Provider } from 'unstated'; +import type { CrowiRequest } from '~/interfaces/crowi-request'; import type { CommonProps } from '~/pages/utils/commons'; -import { useCurrentUser } from '~/stores-universal/context'; +import { useCurrentUser, useGrowiCloudUri } from '~/stores-universal/context'; import { retrieveServerSideProps } from '../../utils/admin-page-util'; @@ -25,6 +26,7 @@ type Props = CommonProps; const DataTransferPage: NextPage = (props) => { const { t } = useTranslation('commons'); useCurrentUser(props.currentUser ?? null); + useGrowiCloudUri(props.growiCloudUri); const title = t('g2g_data_transfer.data_transfer'); @@ -54,9 +56,15 @@ const DataTransferPage: NextPage = (props) => { ); }; +const injectServerConfigurations = async(context: GetServerSidePropsContext, props: Props): Promise => { + const req: CrowiRequest = context.req as CrowiRequest; + const { crowi } = req; + + props.growiCloudUri = await crowi.configManager.getConfig('crowi', 'app:growiCloudUri'); +}; export const getServerSideProps: GetServerSideProps = async(context: GetServerSidePropsContext) => { - const props = await retrieveServerSideProps(context); + const props = await retrieveServerSideProps(context, injectServerConfigurations); return props; }; From 955ffe87366e791807431c30c85e836e328c39cb Mon Sep 17 00:00:00 2001 From: moekumasaka Date: Tue, 24 Sep 2024 01:17:18 +0000 Subject: [PATCH 266/490] add w-100 to dropdown menu --- .../client/components/CustomNavigation/CustomNav.module.scss | 4 ---- apps/app/src/client/components/CustomNavigation/CustomNav.tsx | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/apps/app/src/client/components/CustomNavigation/CustomNav.module.scss b/apps/app/src/client/components/CustomNavigation/CustomNav.module.scss index 2accc25615e..42ac2f29349 100644 --- a/apps/app/src/client/components/CustomNavigation/CustomNav.module.scss +++ b/apps/app/src/client/components/CustomNavigation/CustomNav.module.scss @@ -15,7 +15,3 @@ transition: 0.3s ease-in-out; } } - -.dropdown-menu :global { - width: 100%; -} diff --git a/apps/app/src/client/components/CustomNavigation/CustomNav.tsx b/apps/app/src/client/components/CustomNavigation/CustomNav.tsx index 64d2a83a3dc..3fc12e81cfa 100644 --- a/apps/app/src/client/components/CustomNavigation/CustomNav.tsx +++ b/apps/app/src/client/components/CustomNavigation/CustomNav.tsx @@ -77,7 +77,7 @@ export const CustomNavDropdown = (props: CustomNavDropdownProps): JSX.Element => { Icon != null && } {i18n} -
                  +
                  {Object.entries(navTabMapping).map(([key, value]) => { const isActive = activeTab === key; From 014987700f08c61ab076c056fcf95aedb432d516 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 24 Sep 2024 05:02:08 +0000 Subject: [PATCH 267/490] ci(deps): bump rollup from 4.22.0 to 4.22.4 Bumps [rollup](https://github.com/rollup/rollup) from 4.22.0 to 4.22.4. - [Release notes](https://github.com/rollup/rollup/releases) - [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md) - [Commits](https://github.com/rollup/rollup/compare/v4.22.0...v4.22.4) --- updated-dependencies: - dependency-name: rollup dependency-type: indirect ... Signed-off-by: dependabot[bot] --- yarn.lock | 196 +++++++++++++++++++++++++++--------------------------- 1 file changed, 98 insertions(+), 98 deletions(-) diff --git a/yarn.lock b/yarn.lock index acc71a4d919..d2ab2d476a0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3246,85 +3246,85 @@ estree-walker "^2.0.2" picomatch "^2.3.1" -"@rollup/rollup-android-arm-eabi@4.22.0": - version "4.22.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.22.0.tgz#e8c16c336f060b4cb592f62eb4f0e543d79d51fe" - integrity sha512-/IZQvg6ZR0tAkEi4tdXOraQoWeJy9gbQ/cx4I7k9dJaCk9qrXEcdouxRVz5kZXt5C2bQ9pILoAA+KB4C/d3pfw== - -"@rollup/rollup-android-arm64@4.22.0": - version "4.22.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.22.0.tgz#7a44160a14017fa744912d7037c7d81d6f8a46e7" - integrity sha512-ETHi4bxrYnvOtXeM7d4V4kZWixib2jddFacJjsOjwbgYSRsyXYtZHC4ht134OsslPIcnkqT+TKV4eU8rNBKyyQ== - -"@rollup/rollup-darwin-arm64@4.22.0": - version "4.22.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.22.0.tgz#6122dc37d4a09521d8abe18925956d3b46cfbac9" - integrity sha512-ZWgARzhSKE+gVUX7QWaECoRQsPwaD8ZR0Oxb3aUpzdErTvlEadfQpORPXkKSdKbFci9v8MJfkTtoEHnnW9Ulng== - -"@rollup/rollup-darwin-x64@4.22.0": - version "4.22.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.22.0.tgz#453f345899cbf544aa0d6f5808d24d2e42f605b7" - integrity sha512-h0ZAtOfHyio8Az6cwIGS+nHUfRMWBDO5jXB8PQCARVF6Na/G6XS2SFxDl8Oem+S5ZsHQgtsI7RT4JQnI1qrlaw== - -"@rollup/rollup-linux-arm-gnueabihf@4.22.0": - version "4.22.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.22.0.tgz#3a32fa4e80a62a6d733014838b1123fe76b060fe" - integrity sha512-9pxQJSPwFsVi0ttOmqLY4JJ9pg9t1gKhK0JDbV1yUEETSx55fdyCjt39eBQ54OQCzAF0nVGO6LfEH1KnCPvelA== - -"@rollup/rollup-linux-arm-musleabihf@4.22.0": - version "4.22.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.22.0.tgz#55d3953c54419e93efe124882a3103c8a2f65641" - integrity sha512-YJ5Ku5BmNJZb58A4qSEo3JlIG4d3G2lWyBi13ABlXzO41SsdnUKi3HQHe83VpwBVG4jHFTW65jOQb8qyoR+qzg== - -"@rollup/rollup-linux-arm64-gnu@4.22.0": - version "4.22.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.22.0.tgz#cd626963b9962baf8e09d792e67b87269a5bcfff" - integrity sha512-U4G4u7f+QCqHlVg1Nlx+qapZy+QoG+NV6ux+upo/T7arNGwKvKP2kmGM4W5QTbdewWFgudQxi3kDNST9GT1/mg== - -"@rollup/rollup-linux-arm64-musl@4.22.0": - version "4.22.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.22.0.tgz#ad209270c9937a27346fce5b0670cbdfb1e6a0a6" - integrity sha512-aQpNlKmx3amwkA3a5J6nlXSahE1ijl0L9KuIjVOUhfOh7uw2S4piR3mtpxpRtbnK809SBtyPsM9q15CPTsY7HQ== - -"@rollup/rollup-linux-powerpc64le-gnu@4.22.0": - version "4.22.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.22.0.tgz#fdd173929a5bba8b7e8b37314380213d9604088f" - integrity sha512-9fx6Zj/7vve/Fp4iexUFRKb5+RjLCff6YTRQl4CoDhdMfDoobWmhAxQWV3NfShMzQk1Q/iCnageFyGfqnsmeqQ== - -"@rollup/rollup-linux-riscv64-gnu@4.22.0": - version "4.22.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.22.0.tgz#90b11314fbf45d04083f658e08dc3b32fd713061" - integrity sha512-VWQiCcN7zBgZYLjndIEh5tamtnKg5TGxyZPWcN9zBtXBwfcGSZ5cHSdQZfQH/GB4uRxk0D3VYbOEe/chJhPGLQ== - -"@rollup/rollup-linux-s390x-gnu@4.22.0": - version "4.22.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.22.0.tgz#46bb2f1135aeec646b720d6032d7c86915f8b2ec" - integrity sha512-EHmPnPWvyYqncObwqrosb/CpH3GOjE76vWVs0g4hWsDRUVhg61hBmlVg5TPXqF+g+PvIbqkC7i3h8wbn4Gp2Fg== - -"@rollup/rollup-linux-x64-gnu@4.22.0": - version "4.22.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.22.0.tgz#d731a19af5f05eabcba871bda2eeb2fa8c8adb67" - integrity sha512-tsSWy3YQzmpjDKnQ1Vcpy3p9Z+kMFbSIesCdMNgLizDWFhrLZIoN21JSq01g+MZMDFF+Y1+4zxgrlqPjid5ohg== - -"@rollup/rollup-linux-x64-musl@4.22.0": - version "4.22.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.22.0.tgz#5438b2dc38fe467444cf769146098be083022d0f" - integrity sha512-anr1Y11uPOQrpuU8XOikY5lH4Qu94oS6j0xrulHk3NkLDq19MlX8Ng/pVipjxBJ9a2l3+F39REZYyWQFkZ4/fw== - -"@rollup/rollup-win32-arm64-msvc@4.22.0": - version "4.22.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.22.0.tgz#6bd66c198f80c8e7050cfd901701cfb9555d768a" - integrity sha512-7LB+Bh+Ut7cfmO0m244/asvtIGQr5pG5Rvjz/l1Rnz1kDzM02pSX9jPaS0p+90H5I1x4d1FkCew+B7MOnoatNw== - -"@rollup/rollup-win32-ia32-msvc@4.22.0": - version "4.22.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.22.0.tgz#58daea1f1e65143c44c8f3311f30ff8eefa62bae" - integrity sha512-+3qZ4rer7t/QsC5JwMpcvCVPRcJt1cJrYS/TMJZzXIJbxWFQEVhrIc26IhB+5Z9fT9umfVc+Es2mOZgl+7jdJQ== - -"@rollup/rollup-win32-x64-msvc@4.22.0": - version "4.22.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.22.0.tgz#956948629f6b87de0bdf526b28d940221540bbb6" - integrity sha512-YdicNOSJONVx/vuPkgPTyRoAPx3GbknBZRCOUkK84FJ/YTfs/F0vl/YsMscrB6Y177d+yDRcj+JWMPMCgshwrA== +"@rollup/rollup-android-arm-eabi@4.22.4": + version "4.22.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.22.4.tgz#8b613b9725e8f9479d142970b106b6ae878610d5" + integrity sha512-Fxamp4aEZnfPOcGA8KSNEohV8hX7zVHOemC8jVBoBUHu5zpJK/Eu3uJwt6BMgy9fkvzxDaurgj96F/NiLukF2w== + +"@rollup/rollup-android-arm64@4.22.4": + version "4.22.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.22.4.tgz#654ca1049189132ff602bfcf8df14c18da1f15fb" + integrity sha512-VXoK5UMrgECLYaMuGuVTOx5kcuap1Jm8g/M83RnCHBKOqvPPmROFJGQaZhGccnsFtfXQ3XYa4/jMCJvZnbJBdA== + +"@rollup/rollup-darwin-arm64@4.22.4": + version "4.22.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.22.4.tgz#6d241d099d1518ef0c2205d96b3fa52e0fe1954b" + integrity sha512-xMM9ORBqu81jyMKCDP+SZDhnX2QEVQzTcC6G18KlTQEzWK8r/oNZtKuZaCcHhnsa6fEeOBionoyl5JsAbE/36Q== + +"@rollup/rollup-darwin-x64@4.22.4": + version "4.22.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.22.4.tgz#42bd19d292a57ee11734c980c4650de26b457791" + integrity sha512-aJJyYKQwbHuhTUrjWjxEvGnNNBCnmpHDvrb8JFDbeSH3m2XdHcxDd3jthAzvmoI8w/kSjd2y0udT+4okADsZIw== + +"@rollup/rollup-linux-arm-gnueabihf@4.22.4": + version "4.22.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.22.4.tgz#f23555ee3d8fe941c5c5fd458cd22b65eb1c2232" + integrity sha512-j63YtCIRAzbO+gC2L9dWXRh5BFetsv0j0va0Wi9epXDgU/XUi5dJKo4USTttVyK7fGw2nPWK0PbAvyliz50SCQ== + +"@rollup/rollup-linux-arm-musleabihf@4.22.4": + version "4.22.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.22.4.tgz#f3bbd1ae2420f5539d40ac1fde2b38da67779baa" + integrity sha512-dJnWUgwWBX1YBRsuKKMOlXCzh2Wu1mlHzv20TpqEsfdZLb3WoJW2kIEsGwLkroYf24IrPAvOT/ZQ2OYMV6vlrg== + +"@rollup/rollup-linux-arm64-gnu@4.22.4": + version "4.22.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.22.4.tgz#7abe900120113e08a1f90afb84c7c28774054d15" + integrity sha512-AdPRoNi3NKVLolCN/Sp4F4N1d98c4SBnHMKoLuiG6RXgoZ4sllseuGioszumnPGmPM2O7qaAX/IJdeDU8f26Aw== + +"@rollup/rollup-linux-arm64-musl@4.22.4": + version "4.22.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.22.4.tgz#9e655285c8175cd44f57d6a1e8e5dedfbba1d820" + integrity sha512-Gl0AxBtDg8uoAn5CCqQDMqAx22Wx22pjDOjBdmG0VIWX3qUBHzYmOKh8KXHL4UpogfJ14G4wk16EQogF+v8hmA== + +"@rollup/rollup-linux-powerpc64le-gnu@4.22.4": + version "4.22.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.22.4.tgz#9a79ae6c9e9d8fe83d49e2712ecf4302db5bef5e" + integrity sha512-3aVCK9xfWW1oGQpTsYJJPF6bfpWfhbRnhdlyhak2ZiyFLDaayz0EP5j9V1RVLAAxlmWKTDfS9wyRyY3hvhPoOg== + +"@rollup/rollup-linux-riscv64-gnu@4.22.4": + version "4.22.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.22.4.tgz#67ac70eca4ace8e2942fabca95164e8874ab8128" + integrity sha512-ePYIir6VYnhgv2C5Xe9u+ico4t8sZWXschR6fMgoPUK31yQu7hTEJb7bCqivHECwIClJfKgE7zYsh1qTP3WHUA== + +"@rollup/rollup-linux-s390x-gnu@4.22.4": + version "4.22.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.22.4.tgz#9f883a7440f51a22ed7f99e1d070bd84ea5005fc" + integrity sha512-GqFJ9wLlbB9daxhVlrTe61vJtEY99/xB3C8e4ULVsVfflcpmR6c8UZXjtkMA6FhNONhj2eA5Tk9uAVw5orEs4Q== + +"@rollup/rollup-linux-x64-gnu@4.22.4": + version "4.22.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.22.4.tgz#70116ae6c577fe367f58559e2cffb5641a1dd9d0" + integrity sha512-87v0ol2sH9GE3cLQLNEy0K/R0pz1nvg76o8M5nhMR0+Q+BBGLnb35P0fVz4CQxHYXaAOhE8HhlkaZfsdUOlHwg== + +"@rollup/rollup-linux-x64-musl@4.22.4": + version "4.22.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.22.4.tgz#f473f88219feb07b0b98b53a7923be716d1d182f" + integrity sha512-UV6FZMUgePDZrFjrNGIWzDo/vABebuXBhJEqrHxrGiU6HikPy0Z3LfdtciIttEUQfuDdCn8fqh7wiFJjCNwO+g== + +"@rollup/rollup-win32-arm64-msvc@4.22.4": + version "4.22.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.22.4.tgz#4349482d17f5d1c58604d1c8900540d676f420e0" + integrity sha512-BjI+NVVEGAXjGWYHz/vv0pBqfGoUH0IGZ0cICTn7kB9PyjrATSkX+8WkguNjWoj2qSr1im/+tTGRaY+4/PdcQw== + +"@rollup/rollup-win32-ia32-msvc@4.22.4": + version "4.22.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.22.4.tgz#a6fc39a15db618040ec3c2a24c1e26cb5f4d7422" + integrity sha512-SiWG/1TuUdPvYmzmYnmd3IEifzR61Tragkbx9D3+R8mzQqDBz8v+BvZNDlkiTtI9T15KYZhP0ehn3Dld4n9J5g== + +"@rollup/rollup-win32-x64-msvc@4.22.4": + version "4.22.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.22.4.tgz#3dd5d53e900df2a40841882c02e56f866c04d202" + integrity sha512-j8pPKp53/lq9lMXN57S8cFz0MynJk8OWNuUnXct/9KCpKU7DgU3bYMJhwWmcqC0UU29p8Lr0/7KEVcaM6bf47Q== "@rushstack/eslint-patch@^1.1.3": version "1.1.3" @@ -16084,28 +16084,28 @@ rollup-plugin-node-externals@^6.1.1: integrity sha512-127OFMkpH5rBVlRHRBDUMk1m1sGuzbGy7so5aj/IkpUb2r3+wOWjR/erUzd2ChEQWPsxsyQG6xpYYvPBAdcBRA== rollup@^4.20.0: - version "4.22.0" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.22.0.tgz#23cd9e4565a458587683accc34a054660c01f351" - integrity sha512-W21MUIFPZ4+O2Je/EU+GP3iz7PH4pVPUXSbEZdatQnxo29+3rsUjgrJmzuAZU24z7yRAnFN6ukxeAhZh/c7hzg== + version "4.22.4" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.22.4.tgz#4135a6446671cd2a2453e1ad42a45d5973ec3a0f" + integrity sha512-vD8HJ5raRcWOyymsR6Z3o6+RzfEPCnVLMFJ6vRslO1jt4LO6dUo5Qnpg7y4RkZFM2DMe3WUirkI5c16onjrc6A== dependencies: "@types/estree" "1.0.5" optionalDependencies: - "@rollup/rollup-android-arm-eabi" "4.22.0" - "@rollup/rollup-android-arm64" "4.22.0" - "@rollup/rollup-darwin-arm64" "4.22.0" - "@rollup/rollup-darwin-x64" "4.22.0" - "@rollup/rollup-linux-arm-gnueabihf" "4.22.0" - "@rollup/rollup-linux-arm-musleabihf" "4.22.0" - "@rollup/rollup-linux-arm64-gnu" "4.22.0" - "@rollup/rollup-linux-arm64-musl" "4.22.0" - "@rollup/rollup-linux-powerpc64le-gnu" "4.22.0" - "@rollup/rollup-linux-riscv64-gnu" "4.22.0" - "@rollup/rollup-linux-s390x-gnu" "4.22.0" - "@rollup/rollup-linux-x64-gnu" "4.22.0" - "@rollup/rollup-linux-x64-musl" "4.22.0" - "@rollup/rollup-win32-arm64-msvc" "4.22.0" - "@rollup/rollup-win32-ia32-msvc" "4.22.0" - "@rollup/rollup-win32-x64-msvc" "4.22.0" + "@rollup/rollup-android-arm-eabi" "4.22.4" + "@rollup/rollup-android-arm64" "4.22.4" + "@rollup/rollup-darwin-arm64" "4.22.4" + "@rollup/rollup-darwin-x64" "4.22.4" + "@rollup/rollup-linux-arm-gnueabihf" "4.22.4" + "@rollup/rollup-linux-arm-musleabihf" "4.22.4" + "@rollup/rollup-linux-arm64-gnu" "4.22.4" + "@rollup/rollup-linux-arm64-musl" "4.22.4" + "@rollup/rollup-linux-powerpc64le-gnu" "4.22.4" + "@rollup/rollup-linux-riscv64-gnu" "4.22.4" + "@rollup/rollup-linux-s390x-gnu" "4.22.4" + "@rollup/rollup-linux-x64-gnu" "4.22.4" + "@rollup/rollup-linux-x64-musl" "4.22.4" + "@rollup/rollup-win32-arm64-msvc" "4.22.4" + "@rollup/rollup-win32-ia32-msvc" "4.22.4" + "@rollup/rollup-win32-x64-msvc" "4.22.4" fsevents "~2.3.2" run-async@^2.4.0: From 72a2c00b353395a5442f7b13520b2a08d530cd51 Mon Sep 17 00:00:00 2001 From: Shun Miyazawa Date: Tue, 24 Sep 2024 05:39:57 +0000 Subject: [PATCH 268/490] Impl 153988 --- .../service/openai/openai-client-delegator.ts | 9 ++++- apps/app/src/server/service/openai/openai.ts | 38 +++++++++++++++---- 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/apps/app/src/server/service/openai/openai-client-delegator.ts b/apps/app/src/server/service/openai/openai-client-delegator.ts index a4e005d790d..737a0c72647 100644 --- a/apps/app/src/server/service/openai/openai-client-delegator.ts +++ b/apps/app/src/server/service/openai/openai-client-delegator.ts @@ -1,4 +1,5 @@ import OpenAI from 'openai'; +import { type Uploadable } from 'openai/uploads'; import { aiServiceType as serviceType, aiServiceTypes } from '~/interfaces/ai'; import { configManager } from '~/server/service/config-manager'; @@ -16,7 +17,7 @@ export default class OpenaiClient { const aiServiceType = configManager.getConfig('crowi', 'app:aiServiceType'); if (!aiEnabled) { - throw new Error('I_ENABLED is not true'); + throw new Error('AI_ENABLED is not true'); } if (aiServiceType == null || !aiServiceTypes.includes(aiServiceType)) { @@ -59,4 +60,10 @@ export default class OpenaiClient { : null; } + async uploadAndPoll(files: Uploadable[]): Promise { + return this.isOpenai + ? this.client.beta.vectorStores.fileBatches.uploadAndPoll(this.openaiVectorStoreId, { files }) + : null; + } + } diff --git a/apps/app/src/server/service/openai/openai.ts b/apps/app/src/server/service/openai/openai.ts index 2fc5f33eb99..bb291bfd5fe 100644 --- a/apps/app/src/server/service/openai/openai.ts +++ b/apps/app/src/server/service/openai/openai.ts @@ -1,3 +1,11 @@ +import { Readable } from 'stream'; + +import { PageGrant } from '@growi/core'; +import type { HydratedDocument } from 'mongoose'; +import mongoose from 'mongoose'; +import { toFile } from 'openai'; + +import type { PageDocument, PageModel } from '~/server/models/page'; import { configManager } from '~/server/service/config-manager'; import OpenaiClient from './openai-client-delegator'; @@ -19,17 +27,31 @@ class OpenaiService implements IOpenaiService { async rebuildVectorStore() { // Delete an existing VectorStoreFile - const vectorStoreFileData = await this.client.getVectorStoreFiles(); - const vectorStoreFiles = vectorStoreFileData?.data; - if (vectorStoreFiles != null && vectorStoreFiles.length > 0) { - vectorStoreFiles.forEach(async(vectorStoreFile) => { - await this.client.deleteVectorStoreFiles(vectorStoreFile.id); - }); - } + // const vectorStoreFileData = await this.client.getVectorStoreFiles(); + // const vectorStoreFiles = vectorStoreFileData?.data; + // if (vectorStoreFiles != null && vectorStoreFiles.length > 0) { + // vectorStoreFiles.forEach(async(vectorStoreFile) => { + // await this.client.deleteVectorStoreFiles(vectorStoreFile.id); + // }); + // } // Create all public pages VectorStoreFile - // TODO: https://redmine.weseek.co.jp/issues/153988 + const page = mongoose.model, PageModel>('Page'); + const allPublicPages = await page.find({ grant: PageGrant.GRANT_PUBLIC }).populate('revision'); + + const filesPromise = allPublicPages + .filter(page => page.revision?.body != null && page.revision.body.length > 0) + .map(async(page) => { + const file = await toFile(Readable.from(page.revision.body), `${page._id}.md`); + return file; + }); + + if (filesPromise.length === 0) { + return; + } + const files = await Promise.all(filesPromise); + await this.client.uploadAndPoll(files); } } From 237fd8fc0626d5e3bcf01f479346956b57881a01 Mon Sep 17 00:00:00 2001 From: Shun Miyazawa Date: Tue, 24 Sep 2024 05:48:06 +0000 Subject: [PATCH 269/490] install @azure/identity --- apps/app/package.json | 2 +- yarn.lock | 56 ++++++++++++++----------------------------- 2 files changed, 19 insertions(+), 39 deletions(-) diff --git a/apps/app/package.json b/apps/app/package.json index 9355c23c15c..e9719e1c92f 100644 --- a/apps/app/package.json +++ b/apps/app/package.json @@ -63,7 +63,7 @@ "@akebifiky/remark-simple-plantuml": "^1.0.2", "@aws-sdk/client-s3": "3.454.0", "@aws-sdk/s3-request-presigner": "3.454.0", - "@azure/identity": "^4.3.0", + "@azure/identity": "^4.4.1", "@azure/storage-blob": "^12.16.0", "@browser-bunyan/console-formatted-stream": "^1.8.0", "@elastic/elasticsearch7": "npm:@elastic/elasticsearch@^7.17.0", diff --git a/yarn.lock b/yarn.lock index f7694aff2ab..e85772aad11 100644 --- a/yarn.lock +++ b/yarn.lock @@ -851,10 +851,10 @@ "@azure/abort-controller" "^2.0.0" tslib "^2.6.2" -"@azure/identity@^4.3.0": - version "4.3.0" - resolved "https://registry.yarnpkg.com/@azure/identity/-/identity-4.3.0.tgz#e8da6b3bf1df4de1511e813a7166a4b5b4a99ca1" - integrity sha512-LHZ58/RsIpIWa4hrrE2YuJ/vzG1Jv9f774RfTTAVDZDriubvJ0/S5u4pnw4akJDlS0TiJb6VMphmVUFsWmgodQ== +"@azure/identity@^4.4.1": + version "4.4.1" + resolved "https://registry.yarnpkg.com/@azure/identity/-/identity-4.4.1.tgz#490fa2ad26786229afa36411892bb53dfa3478d3" + integrity sha512-DwnG4cKFEM7S3T+9u05NstXU/HN0dk45kPOinUyNKsn5VWwpXd9sbPKEg6kgJzGbm1lMuhx9o31PVbCtM5sfBA== dependencies: "@azure/abort-controller" "^1.0.0" "@azure/core-auth" "^1.5.0" @@ -863,7 +863,7 @@ "@azure/core-tracing" "^1.0.0" "@azure/core-util" "^1.3.0" "@azure/logger" "^1.0.0" - "@azure/msal-browser" "^3.11.1" + "@azure/msal-browser" "^3.14.0" "@azure/msal-node" "^2.9.2" events "^3.0.0" jws "^4.0.0" @@ -878,18 +878,23 @@ dependencies: tslib "^2.2.0" -"@azure/msal-browser@^3.11.1": - version "3.17.0" - resolved "https://registry.yarnpkg.com/@azure/msal-browser/-/msal-browser-3.17.0.tgz#dee9ccae586239e7e0708b261f7ffa5bc7e00fb7" - integrity sha512-csccKXmW2z7EkZ0I3yAoW/offQt+JECdTIV/KrnRoZyM7wCSsQWODpwod8ZhYy7iOyamcHApR9uCh0oD1M+0/A== +"@azure/msal-browser@^3.14.0": + version "3.24.0" + resolved "https://registry.yarnpkg.com/@azure/msal-browser/-/msal-browser-3.24.0.tgz#3208047672d0b0c943b0bef5f995d510d6582ae4" + integrity sha512-JGNV9hTYAa7lsum9IMIibn2kKczAojNihGo1hi7pG0kNrcKej530Fl6jxwM05A44/6I079CSn6WxYxbVhKUmWg== dependencies: - "@azure/msal-common" "14.12.0" + "@azure/msal-common" "14.15.0" "@azure/msal-common@14.12.0": version "14.12.0" resolved "https://registry.yarnpkg.com/@azure/msal-common/-/msal-common-14.12.0.tgz#844abe269b071f8fa8949dadc2a7b65bbb147588" integrity sha512-IDDXmzfdwmDkv4SSmMEyAniJf6fDu3FJ7ncOjlxkDuT85uSnLEhZi3fGZpoR7T4XZpOMx9teM9GXBgrfJgyeBw== +"@azure/msal-common@14.15.0": + version "14.15.0" + resolved "https://registry.yarnpkg.com/@azure/msal-common/-/msal-common-14.15.0.tgz#0e27ac0bb88fe100f4f8d1605b64d5c268636a55" + integrity sha512-ImAQHxmpMneJ/4S8BRFhjt1MZ3bppmpRPYYNyzeQPeFN288YKbb8TmmISQEbtfkQ1BPASvYZU5doIZOPBAqENQ== + "@azure/msal-node@^2.9.2": version "2.9.2" resolved "https://registry.yarnpkg.com/@azure/msal-node/-/msal-node-2.9.2.tgz#e6d3c1661012c1bd0ef68e328f73a2fdede52931" @@ -17023,7 +17028,7 @@ string-template@>=1.0.0: resolved "https://registry.yarnpkg.com/string-template/-/string-template-1.0.0.tgz#9e9f2233dc00f218718ec379a28a5673ecca8b96" integrity sha1-np8iM9wA8hhxjsN5oopWc+zKi5Y= -"string-width-cjs@npm:string-width@^4.2.0": +"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -17041,15 +17046,6 @@ string-width@=4.2.2: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.0" -"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - string-width@^5.0.1, string-width@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" @@ -17133,7 +17129,7 @@ stringify-entities@^4.0.0: character-entities-html4 "^2.0.0" character-entities-legacy "^3.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -17147,13 +17143,6 @@ strip-ansi@^3.0.0: dependencies: ansi-regex "^2.0.0" -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - strip-ansi@^7.0.1, strip-ansi@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -18940,7 +18929,7 @@ word-wrap@^1.2.3: resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -18958,15 +18947,6 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" From f7682110a5c312a5e907d41d24021e1b1cc123c9 Mon Sep 17 00:00:00 2001 From: Shun Miyazawa Date: Tue, 24 Sep 2024 05:56:35 +0000 Subject: [PATCH 270/490] Support for Azure OpenAI --- .../service/openai/openai-client-delegator.ts | 28 +++++++++---------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/apps/app/src/server/service/openai/openai-client-delegator.ts b/apps/app/src/server/service/openai/openai-client-delegator.ts index 737a0c72647..300aa11eb4b 100644 --- a/apps/app/src/server/service/openai/openai-client-delegator.ts +++ b/apps/app/src/server/service/openai/openai-client-delegator.ts @@ -1,4 +1,5 @@ -import OpenAI from 'openai'; +import { DefaultAzureCredential, getBearerTokenProvider } from '@azure/identity'; +import OpenAI, { AzureOpenAI } from 'openai'; import { type Uploadable } from 'openai/uploads'; import { aiServiceType as serviceType, aiServiceTypes } from '~/interfaces/ai'; @@ -6,7 +7,7 @@ import { configManager } from '~/server/service/config-manager'; export default class OpenaiClient { - private client: OpenAI; + private client: OpenAI | AzureOpenAI; private isOpenai: boolean; @@ -44,26 +45,23 @@ export default class OpenaiClient { // Retrieve Azure OpenAI related values from environment variables else { - // + const credential = new DefaultAzureCredential(); + const scope = 'https://cognitiveservices.azure.com/.default'; + const azureADTokenProvider = getBearerTokenProvider(credential, scope); + this.client = new AzureOpenAI({ azureADTokenProvider }); } } - async getVectorStoreFiles(): Promise { - return this.isOpenai - ? this.client.beta.vectorStores.files.list(this.openaiVectorStoreId) - : null; + async getVectorStoreFiles(): Promise { + return this.client.beta.vectorStores.files.list(this.openaiVectorStoreId); } - async deleteVectorStoreFiles(fileId: string): Promise { - return this.isOpenai - ? this.client.beta.vectorStores.files.del(this.openaiVectorStoreId, fileId) - : null; + async deleteVectorStoreFiles(fileId: string): Promise { + return this.client.beta.vectorStores.files.del(this.openaiVectorStoreId, fileId); } - async uploadAndPoll(files: Uploadable[]): Promise { - return this.isOpenai - ? this.client.beta.vectorStores.fileBatches.uploadAndPoll(this.openaiVectorStoreId, { files }) - : null; + async uploadAndPoll(files: Uploadable[]): Promise { + return this.client.beta.vectorStores.fileBatches.uploadAndPoll(this.openaiVectorStoreId, { files }); } } From 1cc5b0fc755db0af8df287ef20d0ad6cbad00fd9 Mon Sep 17 00:00:00 2001 From: shironegi39 Date: Tue, 24 Sep 2024 06:21:44 +0000 Subject: [PATCH 271/490] Add props to installer page --- apps/app/src/pages/installer.page.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/app/src/pages/installer.page.tsx b/apps/app/src/pages/installer.page.tsx index 957059dfe75..72b3da418a2 100644 --- a/apps/app/src/pages/installer.page.tsx +++ b/apps/app/src/pages/installer.page.tsx @@ -11,7 +11,7 @@ import Head from 'next/head'; import { NoLoginLayout } from '~/components/Layout/NoLoginLayout'; import type { CrowiRequest } from '~/interfaces/crowi-request'; import { - useCsrfToken, useAppTitle, useSiteUrl, useConfidential, + useCsrfToken, useAppTitle, useSiteUrl, useConfidential, useGrowiCloudUri, } from '~/stores-universal/context'; import type { CommonProps } from './utils/commons'; @@ -57,6 +57,7 @@ const InstallerPage: NextPage = (props: Props) => { useSiteUrl(props.siteUrl); useConfidential(props.confidential); useCsrfToken(props.csrfToken); + useGrowiCloudUri(props.growiCloudUri); const title = generateCustomTitle(props, t('installer.title')); const classNames: string[] = []; From 461ca6a5421d5cfed4b144c0c0180e9fc4acb30e Mon Sep 17 00:00:00 2001 From: moekumasaka Date: Tue, 24 Sep 2024 07:39:50 +0000 Subject: [PATCH 272/490] fix queryByTestId to getByTestId --- .../app/src/client/components/DescendantsPageListModal.spec.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/app/src/client/components/DescendantsPageListModal.spec.tsx b/apps/app/src/client/components/DescendantsPageListModal.spec.tsx index 3d465c3c25f..a81da6ee461 100644 --- a/apps/app/src/client/components/DescendantsPageListModal.spec.tsx +++ b/apps/app/src/client/components/DescendantsPageListModal.spec.tsx @@ -59,7 +59,7 @@ describe('DescendantsPageListModal.tsx', () => { it('should render CustomNavDropdown on devices smaller than lg', () => { render(); - expect(screen.queryByTestId('custom-nav-dropdown')).not.toBeNull(); + expect(screen.getByTestId('custom-nav-dropdown')).not.toBeNull(); }); it('should not render CustomNavTab', () => { From cd2110a107d9cc53c550a4460496e3af6c561e0c Mon Sep 17 00:00:00 2001 From: Yuki Takei Date: Tue, 24 Sep 2024 08:39:21 +0000 Subject: [PATCH 273/490] update conditions for automatic queue --- .github/mergify.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/mergify.yml b/.github/mergify.yml index eaa719767e9..890bee65f01 100644 --- a/.github/mergify.yml +++ b/.github/mergify.yml @@ -23,6 +23,7 @@ pull_request_rules: - name: Automatic queue to merge conditions: - '#approved-reviews-by >= 1' + - '#changes-requested-reviews-by = 0' - '#review-requested = 0' - check-success = check-title actions: From 1ea32d3a9675b548ac0945d77559473d7cac148a Mon Sep 17 00:00:00 2001 From: shironegi39 Date: Tue, 24 Sep 2024 09:13:54 +0000 Subject: [PATCH 274/490] add migration script --- ...ppnotifications-from-unread-to-unopened.js | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 apps/app/src/migrations/20240924181317changed-status-in-inappnotifications-from-unread-to-unopened.js diff --git a/apps/app/src/migrations/20240924181317changed-status-in-inappnotifications-from-unread-to-unopened.js b/apps/app/src/migrations/20240924181317changed-status-in-inappnotifications-from-unread-to-unopened.js new file mode 100644 index 00000000000..5dd4431bf88 --- /dev/null +++ b/apps/app/src/migrations/20240924181317changed-status-in-inappnotifications-from-unread-to-unopened.js @@ -0,0 +1,27 @@ +import loggerFactory from '~/utils/logger'; + +const logger = loggerFactory('growi:non-null-granted-groups'); + +module.exports = { + async up(db) { + logger.info('Apply migration'); + + const unreadInAppnotifications = await await db.collection('inappnotifications'); + await unreadInAppnotifications.updateMany( + { status: { $eq: 'UNREAD' } }, + [ + { + $set: { + status: 'UNOPENED', + }, + }, + ], + ); + + logger.info('Migration has successfully applied'); + }, + + async down() { + // No rollback + }, +}; From 50ecb618a912bfeb3bb51f045f29c271ba12b227 Mon Sep 17 00:00:00 2001 From: shironegi39 Date: Tue, 24 Sep 2024 09:15:25 +0000 Subject: [PATCH 275/490] fix migration script --- ...ged-status-in-inappnotifications-from-unread-to-unopened.js} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename apps/app/src/migrations/{20240924181317changed-status-in-inappnotifications-from-unread-to-unopened.js => 20240924181317-changed-status-in-inappnotifications-from-unread-to-unopened.js} (83%) diff --git a/apps/app/src/migrations/20240924181317changed-status-in-inappnotifications-from-unread-to-unopened.js b/apps/app/src/migrations/20240924181317-changed-status-in-inappnotifications-from-unread-to-unopened.js similarity index 83% rename from apps/app/src/migrations/20240924181317changed-status-in-inappnotifications-from-unread-to-unopened.js rename to apps/app/src/migrations/20240924181317-changed-status-in-inappnotifications-from-unread-to-unopened.js index 5dd4431bf88..ac68118802d 100644 --- a/apps/app/src/migrations/20240924181317changed-status-in-inappnotifications-from-unread-to-unopened.js +++ b/apps/app/src/migrations/20240924181317-changed-status-in-inappnotifications-from-unread-to-unopened.js @@ -1,6 +1,6 @@ import loggerFactory from '~/utils/logger'; -const logger = loggerFactory('growi:non-null-granted-groups'); +const logger = loggerFactory('growi:changed-status-in-inappnotifications-from-unread-to-unopened'); module.exports = { async up(db) { From 57e966df7872c50b8da53cc4610cced19d5a5d8c Mon Sep 17 00:00:00 2001 From: Shun Miyazawa Date: Tue, 24 Sep 2024 09:51:11 +0000 Subject: [PATCH 276/490] Add todo --- apps/app/src/server/service/openai/openai.ts | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/apps/app/src/server/service/openai/openai.ts b/apps/app/src/server/service/openai/openai.ts index bb291bfd5fe..853a3c45bda 100644 --- a/apps/app/src/server/service/openai/openai.ts +++ b/apps/app/src/server/service/openai/openai.ts @@ -26,14 +26,7 @@ class OpenaiService implements IOpenaiService { } async rebuildVectorStore() { - // Delete an existing VectorStoreFile - // const vectorStoreFileData = await this.client.getVectorStoreFiles(); - // const vectorStoreFiles = vectorStoreFileData?.data; - // if (vectorStoreFiles != null && vectorStoreFiles.length > 0) { - // vectorStoreFiles.forEach(async(vectorStoreFile) => { - // await this.client.deleteVectorStoreFiles(vectorStoreFile.id); - // }); - // } + // TODO: https://redmine.weseek.co.jp/issues/154364 // Create all public pages VectorStoreFile const page = mongoose.model, PageModel>('Page'); From 93e6e9d14243395d4de38f94c8986b3e5e55e2a4 Mon Sep 17 00:00:00 2001 From: Shun Miyazawa Date: Tue, 24 Sep 2024 09:52:15 +0000 Subject: [PATCH 277/490] Simpler --- .../server/service/openai/openai-client-delegator.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/app/src/server/service/openai/openai-client-delegator.ts b/apps/app/src/server/service/openai/openai-client-delegator.ts index 300aa11eb4b..1a1745f5d31 100644 --- a/apps/app/src/server/service/openai/openai-client-delegator.ts +++ b/apps/app/src/server/service/openai/openai-client-delegator.ts @@ -9,8 +9,6 @@ export default class OpenaiClient { private client: OpenAI | AzureOpenAI; - private isOpenai: boolean; - private openaiVectorStoreId: string; constructor() { @@ -25,10 +23,8 @@ export default class OpenaiClient { throw new Error('AI_SERVICE_TYPE is missing or contains an invalid value'); } - this.isOpenai = aiServiceType === serviceType.OPEN_AI; - // Retrieve OpenAI related values from environment variables - if (this.isOpenai) { + if (aiServiceType === serviceType.OPEN_AI) { const apiKey = configManager.getConfig('crowi', 'app:openaiApiKey'); const vectorStoreId = configManager.getConfig('crowi', 'app:openaiVectorStoreId'); @@ -60,6 +56,10 @@ export default class OpenaiClient { return this.client.beta.vectorStores.files.del(this.openaiVectorStoreId, fileId); } + async deleteFile(fileId: string): Promise { + return this.client.files.del(fileId); + } + async uploadAndPoll(files: Uploadable[]): Promise { return this.client.beta.vectorStores.fileBatches.uploadAndPoll(this.openaiVectorStoreId, { files }); } From 80e9fdad4bdc8aab20177601c728051123340191 Mon Sep 17 00:00:00 2001 From: Yuki Takei Date: Tue, 24 Sep 2024 12:16:13 +0000 Subject: [PATCH 278/490] rewrite test with faker --- .../PageHeader/PageTitleHeader.spec.tsx | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/apps/app/src/client/components/PageHeader/PageTitleHeader.spec.tsx b/apps/app/src/client/components/PageHeader/PageTitleHeader.spec.tsx index 82a5a030cc8..02c1ebbfe5a 100644 --- a/apps/app/src/client/components/PageHeader/PageTitleHeader.spec.tsx +++ b/apps/app/src/client/components/PageHeader/PageTitleHeader.spec.tsx @@ -1,11 +1,13 @@ import '@testing-library/jest-dom/vitest'; +import { faker } from '@faker-js/faker'; import type { IPagePopulatedToShowRevision } from '@growi/core'; import { fireEvent, render, screen, waitFor, } from '@testing-library/react'; import { mock } from 'vitest-mock-extended'; + import { EditorMode } from '~/stores-universal/ui'; import { PageTitleHeader } from './PageTitleHeader'; @@ -32,7 +34,7 @@ describe('PageTitleHeader Component with untitled page', () => { it('should render the textbox correctly', async() => { // arrange const currentPage = mock({ - _id: 'dummy-id', + _id: faker.database.mongodbObjectId(), path: '/path/to/page/Untitled-1', }); @@ -63,9 +65,10 @@ describe('PageTitleHeader Component', () => { it('should render the title correctly', async() => { // arrange + const pageTitle = faker.lorem.slug(); const currentPage = mock({ - _id: 'dummy-id', - path: '/path/to/page/page-title', + _id: faker.database.mongodbObjectId(), + path: `/path/to/page/${pageTitle}`, }); // act @@ -73,7 +76,7 @@ describe('PageTitleHeader Component', () => { // assert // header should be rendered - const headerElement = screen.getByText('page-title'); + const headerElement = screen.getByText(pageTitle); await waitFor(() => { expect(headerElement).toBeInTheDocument(); expect(headerElement).not.toHaveClass('invisible'); @@ -85,15 +88,16 @@ describe('PageTitleHeader Component', () => { it('should render text input after clicking', async() => { // arrange + const pageTitle = faker.lorem.slug(); const currentPage = mock({ - _id: 'dummy-id', - path: '/path/to/page/page-title', + _id: faker.database.mongodbObjectId(), + path: `/path/to/page/${pageTitle}`, }); // act render(); - const headerElement = screen.getByText('page-title'); + const headerElement = screen.getByText(pageTitle); await waitFor(() => expect(headerElement).toBeInTheDocument()); // click @@ -103,7 +107,7 @@ describe('PageTitleHeader Component', () => { const inputElement = screen.getByRole('textbox'); await waitFor(() => { expect(inputElement).toBeInTheDocument(); - expect(inputElement).toHaveValue('page-title'); + expect(inputElement).toHaveValue(pageTitle); expect(headerElement).toHaveClass('invisible'); }); }); From d8de69a260e81b4ec1f3214bf2dc087c42e0aab8 Mon Sep 17 00:00:00 2001 From: Yuki Takei Date: Tue, 24 Sep 2024 14:48:30 +0000 Subject: [PATCH 279/490] WIP: implement SWR hook to subscribe --- .../src/features/openai/chat/stores/thread.ts | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 apps/app/src/features/openai/chat/stores/thread.ts diff --git a/apps/app/src/features/openai/chat/stores/thread.ts b/apps/app/src/features/openai/chat/stores/thread.ts new file mode 100644 index 00000000000..4f3314ec9ca --- /dev/null +++ b/apps/app/src/features/openai/chat/stores/thread.ts @@ -0,0 +1,32 @@ +import useSWRSubscription from 'swr/subscription'; + +// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types +export const useSWRSUBxOpenaiRun = (threadId: string, runId: string) => { + return useSWRSubscription( + ['openaiRun', threadId, runId], + ([, threadId, runId], { next }) => { + + // SSEを実装したサーバに接続する + const eventSource = new EventSource(`/_api/v3/openai/thread/${threadId}/run/${runId}/subscribe`); + + // TODO: Error handling + // eventSource.onerror = () => { + // }; + + eventSource.onmessage = (event) => { + console.log({ event }); + + // const parsedData = JSON.parse(event.data); + + // if (parsedData.event === 'error') { + // next(parsedData.error); + // return; + // } + + // next(null, parsedData.data); + }; + + return () => eventSource.close(); + }, + ); +}; From 7feac994bf55eda61472e4d737f2334af91cc2b9 Mon Sep 17 00:00:00 2001 From: Yuki Takei Date: Tue, 24 Sep 2024 23:42:28 +0000 Subject: [PATCH 280/490] update next-env.d.ts --- apps/app/next-env.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/app/next-env.d.ts b/apps/app/next-env.d.ts index 4f11a03dc6c..a4a7b3f5cfa 100644 --- a/apps/app/next-env.d.ts +++ b/apps/app/next-env.d.ts @@ -2,4 +2,4 @@ /// // NOTE: This file should not be edited -// see https://nextjs.org/docs/basic-features/typescript for more information. +// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information. From 7c8d25949e862170d072e6761fb42d82598cdf8c Mon Sep 17 00:00:00 2001 From: moekumasaka Date: Wed, 25 Sep 2024 01:57:50 +0000 Subject: [PATCH 281/490] fix PageAccessoriesModal --- .../PageAccessoriesModal.module.scss | 4 +++ .../PageAccessoriesModal.tsx | 33 ++++++++++++++----- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/apps/app/src/client/components/PageAccessoriesModal/PageAccessoriesModal.module.scss b/apps/app/src/client/components/PageAccessoriesModal/PageAccessoriesModal.module.scss index cb6ee432f19..0886c4b8330 100644 --- a/apps/app/src/client/components/PageAccessoriesModal/PageAccessoriesModal.module.scss +++ b/apps/app/src/client/components/PageAccessoriesModal/PageAccessoriesModal.module.scss @@ -9,6 +9,10 @@ padding: 25px 30px; } + .grw-tab-content-style-md-down { + padding-top: 25px; + } + .grw-modal-body-style { max-height: calc(100vh - 100px); } diff --git a/apps/app/src/client/components/PageAccessoriesModal/PageAccessoriesModal.tsx b/apps/app/src/client/components/PageAccessoriesModal/PageAccessoriesModal.tsx index 4d889439da6..aa19ddbec41 100644 --- a/apps/app/src/client/components/PageAccessoriesModal/PageAccessoriesModal.tsx +++ b/apps/app/src/client/components/PageAccessoriesModal/PageAccessoriesModal.tsx @@ -10,8 +10,9 @@ import { useDisableLinkSharing, useIsGuestUser, useIsReadOnlyUser, useIsSharedUser, } from '~/stores-universal/context'; import { usePageAccessoriesModal, PageAccessoriesModalContents } from '~/stores/modal'; +import { useIsDeviceLargerThanLg } from '~/stores/ui'; -import { CustomNavTab } from '../CustomNavigation/CustomNav'; +import { CustomNavDropdown, CustomNavTab } from '../CustomNavigation/CustomNav'; import CustomTabContent from '../CustomNavigation/CustomTabContent'; import ExpandOrContractButton from '../ExpandOrContractButton'; @@ -35,6 +36,7 @@ export const PageAccessoriesModal = (): JSX.Element => { const { data: isGuestUser } = useIsGuestUser(); const { data: isReadOnlyUser } = useIsReadOnlyUser(); const { data: isLinkSharingDisabled } = useDisableLinkSharing(); + const { data: isDeviceLargerThanLg } = useIsDeviceLargerThanLg(); const { data: status, close, selectContents } = usePageAccessoriesModal(); @@ -93,17 +95,30 @@ export const PageAccessoriesModal = (): JSX.Element => { data-testid="page-accessories-modal" className={`grw-page-accessories-modal ${styles['grw-page-accessories-modal']} ${isWindowExpanded ? 'grw-modal-expanded' : ''} `} > - - + {isDeviceLargerThanLg && ( + + )} + + + {!isDeviceLargerThanLg && ( + + )} + - - - ); From 9a1fbf8083f345756604799ee70a4f18b3fcc8ae Mon Sep 17 00:00:00 2001 From: Shun Miyazawa Date: Wed, 25 Sep 2024 03:18:27 +0000 Subject: [PATCH 282/490] imprv client type --- .../src/server/service/openai/openai-client-delegator.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/apps/app/src/server/service/openai/openai-client-delegator.ts b/apps/app/src/server/service/openai/openai-client-delegator.ts index 1a1745f5d31..5c3319f3cbe 100644 --- a/apps/app/src/server/service/openai/openai-client-delegator.ts +++ b/apps/app/src/server/service/openai/openai-client-delegator.ts @@ -5,9 +5,11 @@ import { type Uploadable } from 'openai/uploads'; import { aiServiceType as serviceType, aiServiceTypes } from '~/interfaces/ai'; import { configManager } from '~/server/service/config-manager'; +type Client = isOpenai extends true ? OpenAI : AzureOpenAI; + export default class OpenaiClient { - private client: OpenAI | AzureOpenAI; + private client: Client; private openaiVectorStoreId: string; @@ -36,7 +38,7 @@ export default class OpenaiClient { this.openaiVectorStoreId = vectorStoreId; // initialize client - this.client = new OpenAI({ apiKey }); + this.client = new OpenAI({ apiKey }) as Client; } // Retrieve Azure OpenAI related values from environment variables @@ -44,7 +46,7 @@ export default class OpenaiClient { const credential = new DefaultAzureCredential(); const scope = 'https://cognitiveservices.azure.com/.default'; const azureADTokenProvider = getBearerTokenProvider(credential, scope); - this.client = new AzureOpenAI({ azureADTokenProvider }); + this.client = new AzureOpenAI({ azureADTokenProvider }) as Client; } } From a447a9692bd727f4427c2cdd0488a51e5bba5f4b Mon Sep 17 00:00:00 2001 From: Shun Miyazawa Date: Wed, 25 Sep 2024 07:52:26 +0000 Subject: [PATCH 283/490] impl --- .../routes/apiv3/openai/rebuild-vector-store.ts | 2 +- .../src/server/routes/apiv3/page/update-page.ts | 8 ++++++++ apps/app/src/server/service/openai/openai.ts | 17 ++++++++++++++--- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/apps/app/src/server/routes/apiv3/openai/rebuild-vector-store.ts b/apps/app/src/server/routes/apiv3/openai/rebuild-vector-store.ts index c62057ef188..4445ba0d8b5 100644 --- a/apps/app/src/server/routes/apiv3/openai/rebuild-vector-store.ts +++ b/apps/app/src/server/routes/apiv3/openai/rebuild-vector-store.ts @@ -28,7 +28,7 @@ export const rebuildVectorStoreHandlersFactory: RebuildVectorStoreFactory = (cro async(req: Request, res: ApiV3Response) => { try { - await openaiService.rebuildVectorStore(); + await openaiService.rebuildVectorStoreAll(); return res.apiv3({}); } diff --git a/apps/app/src/server/routes/apiv3/page/update-page.ts b/apps/app/src/server/routes/apiv3/page/update-page.ts index 1c3dbb40974..b59c54baf3d 100644 --- a/apps/app/src/server/routes/apiv3/page/update-page.ts +++ b/apps/app/src/server/routes/apiv3/page/update-page.ts @@ -18,6 +18,8 @@ import { generateAddActivityMiddleware } from '~/server/middlewares/add-activity import { GlobalNotificationSettingEvent } from '~/server/models/GlobalNotificationSetting'; import type { PageDocument, PageModel } from '~/server/models/page'; import { serializePageSecurely, serializeRevisionSecurely } from '~/server/models/serializers'; +import { configManager } from '~/server/service/config-manager'; +import { openaiService } from '~/server/service/openai/openai'; import { preNotifyService } from '~/server/service/pre-notify'; import { normalizeLatestRevisionIfBroken } from '~/server/service/revision/normalize-latest-revision-if-broken'; import { getYjsService } from '~/server/service/yjs'; @@ -114,6 +116,12 @@ export const updatePageHandlersFactory: UpdatePageHandlersFactory = (crowi) => { logger.error('Create user notification failed', err); } } + + // Rebuild vector store file + const aiEnabled = configManager.getConfig('crowi', 'app:aiEnabled'); + if (aiEnabled) { + await openaiService.rebuildVectorStore(updatedPage); + } } const addActivity = generateAddActivityMiddleware(crowi); diff --git a/apps/app/src/server/service/openai/openai.ts b/apps/app/src/server/service/openai/openai.ts index 853a3c45bda..ad27d206d91 100644 --- a/apps/app/src/server/service/openai/openai.ts +++ b/apps/app/src/server/service/openai/openai.ts @@ -1,6 +1,6 @@ import { Readable } from 'stream'; -import { PageGrant } from '@growi/core'; +import { PageGrant, isPopulated } from '@growi/core'; import type { HydratedDocument } from 'mongoose'; import mongoose from 'mongoose'; import { toFile } from 'openai'; @@ -11,7 +11,8 @@ import { configManager } from '~/server/service/config-manager'; import OpenaiClient from './openai-client-delegator'; export interface IOpenaiService { - rebuildVectorStore(): Promise; + rebuildVectorStoreAll(): Promise; + rebuildVectorStore(page: PageDocument): Promise; } class OpenaiService implements IOpenaiService { @@ -25,7 +26,7 @@ class OpenaiService implements IOpenaiService { this.client = new OpenaiClient(); } - async rebuildVectorStore() { + async rebuildVectorStoreAll() { // TODO: https://redmine.weseek.co.jp/issues/154364 // Create all public pages VectorStoreFile @@ -47,6 +48,16 @@ class OpenaiService implements IOpenaiService { await this.client.uploadAndPoll(files); } + async rebuildVectorStore(page: PageDocument) { + // delete vector store file + + // create vector store file + if (page.grant === PageGrant.GRANT_PUBLIC && page.revision != null && isPopulated(page?.revision)) { + const file = await toFile(Readable.from(page.revision.body), `${page._id}.md`); + await this.client.uploadAndPoll([file]); + } + } + } export const openaiService = new OpenaiService(); From a97ebb16b61de7687eadb845571c0a76fc0cb09c Mon Sep 17 00:00:00 2001 From: Shun Miyazawa Date: Wed, 25 Sep 2024 08:20:14 +0000 Subject: [PATCH 284/490] Delete existing vector store file on page refresh --- .../src/server/service/openai/openai-client-delegator.ts | 4 ++++ apps/app/src/server/service/openai/openai.ts | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/apps/app/src/server/service/openai/openai-client-delegator.ts b/apps/app/src/server/service/openai/openai-client-delegator.ts index 5c3319f3cbe..aaa2cbd31ac 100644 --- a/apps/app/src/server/service/openai/openai-client-delegator.ts +++ b/apps/app/src/server/service/openai/openai-client-delegator.ts @@ -50,6 +50,10 @@ export default class OpenaiClient { } } + async getFileList(): Promise { + return this.client.files.list(); + } + async getVectorStoreFiles(): Promise { return this.client.beta.vectorStores.files.list(this.openaiVectorStoreId); } diff --git a/apps/app/src/server/service/openai/openai.ts b/apps/app/src/server/service/openai/openai.ts index ad27d206d91..9dda28f99ea 100644 --- a/apps/app/src/server/service/openai/openai.ts +++ b/apps/app/src/server/service/openai/openai.ts @@ -50,6 +50,12 @@ class OpenaiService implements IOpenaiService { async rebuildVectorStore(page: PageDocument) { // delete vector store file + const files = await this.client.getFileList(); + files.data.forEach(async(file) => { + if (file.filename === `${page._id}.md`) { + await this.client.deleteFile(file.id); + } + }); // create vector store file if (page.grant === PageGrant.GRANT_PUBLIC && page.revision != null && isPopulated(page?.revision)) { From 55318b544ed028a51ac26f006bb4227dac840e50 Mon Sep 17 00:00:00 2001 From: nHigashiWeseek Date: Wed, 25 Sep 2024 08:28:02 +0000 Subject: [PATCH 285/490] sprit markdown by token count --- apps/app/next-env.d.ts | 2 +- apps/app/package.json | 1 + apps/app/src/server/service/page-spritter.ts | 174 ++++++++++++++++++ .../integration/service/page-sprit.test.ts | 78 ++++++++ yarn.lock | 36 +--- 5 files changed, 262 insertions(+), 29 deletions(-) create mode 100644 apps/app/src/server/service/page-spritter.ts create mode 100644 apps/app/test/integration/service/page-sprit.test.ts diff --git a/apps/app/next-env.d.ts b/apps/app/next-env.d.ts index 4f11a03dc6c..a4a7b3f5cfa 100644 --- a/apps/app/next-env.d.ts +++ b/apps/app/next-env.d.ts @@ -2,4 +2,4 @@ /// // NOTE: This file should not be edited -// see https://nextjs.org/docs/basic-features/typescript for more information. +// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information. diff --git a/apps/app/package.json b/apps/app/package.json index e3f932030d1..5976ec44035 100644 --- a/apps/app/package.json +++ b/apps/app/package.json @@ -63,6 +63,7 @@ "@azure/identity": "^4.3.0", "@azure/storage-blob": "^12.16.0", "@browser-bunyan/console-formatted-stream": "^1.8.0", + "@dqbd/tiktoken": "^1.0.16", "@elastic/elasticsearch7": "npm:@elastic/elasticsearch@^7.17.0", "@elastic/elasticsearch8": "npm:@elastic/elasticsearch@^8.7.0", "@godaddy/terminus": "^4.9.0", diff --git a/apps/app/src/server/service/page-spritter.ts b/apps/app/src/server/service/page-spritter.ts new file mode 100644 index 00000000000..286458e6f1b --- /dev/null +++ b/apps/app/src/server/service/page-spritter.ts @@ -0,0 +1,174 @@ +import type { Tiktoken, TiktokenModel } from '@dqbd/tiktoken'; +import { encoding_for_model } from '@dqbd/tiktoken'; // eslint-disable-line +import type { Root, Content, Heading } from 'mdast'; +import remarkParse from 'remark-parse'; +import remarkStringify from 'remark-stringify'; +import { unified } from 'unified'; + +/** + * Interface representing a section + */ +interface Section { + heading: Heading | null; + content: Content[]; +} + +/** + * Function to recursively split Markdown content by header sections so that each section has a token count below the specified maximum + * + * @param model - The name of the model to use (e.g., 'gpt-4') + * @param markdownContent - The Markdown content to split + * @param maxTokens - The maximum number of tokens per section (default: 100) + * @returns An array of split Markdown sections + */ +export function splitMarkdownByTokens( + model: TiktokenModel, + markdownContent: string, + maxTokens = 100, +): string[] { + // Obtain encoding based on the model + const encoding: Tiktoken = encoding_for_model(model); + + // Parse Markdown into AST + const processor = unified().use(remarkParse); + const tree = processor.parse(markdownContent) as Root; + + /** + * Function to stringify a node + * @param node - The node to stringify + * @returns The Markdown string of the node + */ + const stringify = (node: Root): string => { + return unified().use(remarkStringify).stringify(node); + }; + + /** + * Function to get the token count of a text + * @param text - The text to calculate token count for + * @returns The number of tokens + */ + const getTokenCount = (text: string): number => { + return encoding.encode(text).length; + }; + + /** + * Function to split nodes into sections based on headers + * @param nodes - The array of nodes to split + * @returns An array of sections + */ + const splitSections = (nodes: Content[]): Section[] => { + const sections: Section[] = []; + let currentSection: Section = { heading: null, content: [] }; + + for (const node of nodes) { + if (node.type === 'heading') { + // Start a new section + if (currentSection.heading || currentSection.content.length > 0) { + sections.push(currentSection); + } + currentSection = { heading: node as Heading, content: [] }; + } + else { + currentSection.content.push(node); + } + } + + // Add the last section + if (currentSection.heading || currentSection.content.length > 0) { + sections.push(currentSection); + } + + return sections; + }; + + /** + * Function to recursively process sections + * @param sections - The array of sections to process + * @returns An array of split Markdown strings + */ + const processSections = (sections: Section[]): string[] => { + const results: string[] = []; + + for (const section of sections) { + const nodes: Content[] = []; + if (section.heading) { + nodes.push(section.heading); + } + nodes.push(...section.content); + + const subtree: Root = { type: 'root', children: nodes }; + const content = stringify(subtree); + const tokenCount = getTokenCount(content); + + if (tokenCount <= maxTokens) { + results.push(content); + } + else if (section.content.some(child => child.type === 'heading')) { + // Split into subsections + const subsections = splitSections(section.content); + results.push(...processSections(subsections)); + } + else { + // Split by paragraphs + const paragraphs = splitByParagraphs(nodes); + results.push(...paragraphs); + } + } + + return results; + }; + + /** + * Function to split nodes by paragraphs + * @param nodes - The array of nodes to split + * @returns An array of split Markdown strings + */ + const splitByParagraphs = (nodes: Content[]): string[] => { + const results: string[] = []; + let currentNodes: Content[] = []; + let currentTokenCount = 0; + + for (const node of nodes) { + const nodeContent = stringify({ type: 'root', children: [node] }); + const nodeTokenCount = getTokenCount(nodeContent); + + if (currentTokenCount + nodeTokenCount <= maxTokens) { + currentNodes.push(node); + currentTokenCount += nodeTokenCount; + } + else { + if (currentNodes.length > 0) { + const chunk = stringify({ type: 'root', children: currentNodes }); + results.push(chunk); + currentNodes = []; + currentTokenCount = 0; + } + if (nodeTokenCount > maxTokens) { + // If a single node exceeds maxTokens, add it as is + results.push(nodeContent); + } + else { + currentNodes.push(node); + currentTokenCount = nodeTokenCount; + } + } + } + + if (currentNodes.length > 0) { + const chunk = stringify({ type: 'root', children: currentNodes }); + results.push(chunk); + } + + return results; + }; + + // Get initial sections + const initialSections = splitSections(tree.children); + // Process sections + const result = processSections(initialSections); + + // Free the encoding + encoding.free(); + + return result; +} diff --git a/apps/app/test/integration/service/page-sprit.test.ts b/apps/app/test/integration/service/page-sprit.test.ts new file mode 100644 index 00000000000..a489ff22345 --- /dev/null +++ b/apps/app/test/integration/service/page-sprit.test.ts @@ -0,0 +1,78 @@ +import type { TiktokenModel } from '@dqbd/tiktoken'; + +import { splitMarkdownByTokens } from '../../../src/server/service/page-spritter'; + +describe('splitMarkdownByTokens', () => { + const model: TiktokenModel = 'gpt-3.5-turbo'; + + test('Returns without splitting when token count is below the maximum', () => { + const markdownContent = '# Heading\n\nThis is a test.'; + const result = splitMarkdownByTokens(model, markdownContent, 1000); + expect(result).toHaveLength(1); + expect(result[0]).toBe(markdownContent); + }); + + test('Splits by sections when token count exceeds the maximum', () => { + const markdownContent = ` +# Heading1 + +This is the content of section 1. + +# Heading2 + +This is the content of section 2. + +# Heading3 + +This is the content of section 3. + `; + const result = splitMarkdownByTokens(model, markdownContent, 10); // Set a small maxTokens + expect(result).toHaveLength(3); + expect(result[0]).toContain('Heading1'); + expect(result[1]).toContain('Heading2'); + expect(result[2]).toContain('Heading3'); + }); + + test('Recursively splits into subsections', () => { + const markdownContent = ` +# Heading1 + +## Subheading1-1 + +Content1-1 + +## Subheading1-2 + +Content1-2 + +# Heading2 + +Content2 + `; + const result = splitMarkdownByTokens(model, markdownContent, 20); + expect(result.length).toBeGreaterThan(2); + expect(result.some(chunk => chunk.includes('Subheading1-1'))).toBe(true); + expect(result.some(chunk => chunk.includes('Subheading1-2'))).toBe(true); + }); + + test('Splits by paragraphs', () => { + const markdownContent = ` +# Heading + +${'Long paragraph. '.repeat(50)} + `; + const result = splitMarkdownByTokens(model, markdownContent, 50); + expect(result.length).toBeGreaterThan(1); + }); + + test('Adds a single node as is when it exceeds maxTokens', () => { + const markdownContent = ` +# Heading + +${'Very long paragraph. '.repeat(200)} + `; + const result = splitMarkdownByTokens(model, markdownContent, 50); + expect(result).toHaveLength(1); + expect(result[0]).toContain('Very long paragraph.'); + }); +}); diff --git a/yarn.lock b/yarn.lock index acc71a4d919..3660a0474c4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1860,6 +1860,11 @@ resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== +"@dqbd/tiktoken@^1.0.16": + version "1.0.16" + resolved "https://registry.yarnpkg.com/@dqbd/tiktoken/-/tiktoken-1.0.16.tgz#374c201d84158b50babff84e77aa3504564f510b" + integrity sha512-4uIrs5qxAwFVFFEP507HZIZhGOsgfaEMEWDXWalr+v+XP+wJwP60EVmkZtQyQe70IsKGVkx5umBxw4NfmU0pPg== + "@dual-bundle/import-meta-resolve@^4.0.0": version "4.1.0" resolved "https://registry.yarnpkg.com/@dual-bundle/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz#519c1549b0e147759e7825701ecffd25e5819f7b" @@ -16996,7 +17001,7 @@ string-template@>=1.0.0: resolved "https://registry.yarnpkg.com/string-template/-/string-template-1.0.0.tgz#9e9f2233dc00f218718ec379a28a5673ecca8b96" integrity sha1-np8iM9wA8hhxjsN5oopWc+zKi5Y= -"string-width-cjs@npm:string-width@^4.2.0": +"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -17014,15 +17019,6 @@ string-width@=4.2.2: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.0" -"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - string-width@^5.0.1, string-width@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" @@ -17106,7 +17102,7 @@ stringify-entities@^4.0.0: character-entities-html4 "^2.0.0" character-entities-legacy "^3.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -17120,13 +17116,6 @@ strip-ansi@^3.0.0: dependencies: ansi-regex "^2.0.0" -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - strip-ansi@^7.0.1, strip-ansi@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -18921,7 +18910,7 @@ word-wrap@^1.2.3: resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -18939,15 +18928,6 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" From 43e88ef18dbd2cf0f1877a5c52443126155fe154 Mon Sep 17 00:00:00 2001 From: nHigashiWeseek Date: Wed, 25 Sep 2024 08:54:15 +0000 Subject: [PATCH 286/490] change to async function --- apps/app/src/server/service/page-spritter.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/app/src/server/service/page-spritter.ts b/apps/app/src/server/service/page-spritter.ts index 286458e6f1b..676e8b51895 100644 --- a/apps/app/src/server/service/page-spritter.ts +++ b/apps/app/src/server/service/page-spritter.ts @@ -1,7 +1,7 @@ import type { Tiktoken, TiktokenModel } from '@dqbd/tiktoken'; import { encoding_for_model } from '@dqbd/tiktoken'; // eslint-disable-line import type { Root, Content, Heading } from 'mdast'; -import remarkParse from 'remark-parse'; +// import remarkParse from 'remark-parse'; import remarkStringify from 'remark-stringify'; import { unified } from 'unified'; @@ -21,14 +21,14 @@ interface Section { * @param maxTokens - The maximum number of tokens per section (default: 100) * @returns An array of split Markdown sections */ -export function splitMarkdownByTokens( +export async function splitMarkdownByTokens( model: TiktokenModel, markdownContent: string, maxTokens = 100, -): string[] { +): Promise { // Obtain encoding based on the model const encoding: Tiktoken = encoding_for_model(model); - + const remarkParse = (await import('remark-parse')).default; // Parse Markdown into AST const processor = unified().use(remarkParse); const tree = processor.parse(markdownContent) as Root; From 7fe49b90e585824511e8913f06704a364cf05b36 Mon Sep 17 00:00:00 2001 From: nHigashiWeseek Date: Wed, 25 Sep 2024 08:54:45 +0000 Subject: [PATCH 287/490] remove comment --- apps/app/src/server/service/page-spritter.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/app/src/server/service/page-spritter.ts b/apps/app/src/server/service/page-spritter.ts index 676e8b51895..d0d2464d1ee 100644 --- a/apps/app/src/server/service/page-spritter.ts +++ b/apps/app/src/server/service/page-spritter.ts @@ -1,7 +1,6 @@ import type { Tiktoken, TiktokenModel } from '@dqbd/tiktoken'; import { encoding_for_model } from '@dqbd/tiktoken'; // eslint-disable-line import type { Root, Content, Heading } from 'mdast'; -// import remarkParse from 'remark-parse'; import remarkStringify from 'remark-stringify'; import { unified } from 'unified'; From 2e8ee0c98632ff59a9513ded1b58a4c797477c90 Mon Sep 17 00:00:00 2001 From: nHigashiWeseek Date: Wed, 25 Sep 2024 09:01:54 +0000 Subject: [PATCH 288/490] change --- apps/app/src/server/service/page-spritter.ts | 5 ++++- .../integration/service/page-sprit.test.ts | 22 ++++++++++--------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/apps/app/src/server/service/page-spritter.ts b/apps/app/src/server/service/page-spritter.ts index d0d2464d1ee..8b138ae7d73 100644 --- a/apps/app/src/server/service/page-spritter.ts +++ b/apps/app/src/server/service/page-spritter.ts @@ -27,7 +27,10 @@ export async function splitMarkdownByTokens( ): Promise { // Obtain encoding based on the model const encoding: Tiktoken = encoding_for_model(model); - const remarkParse = (await import('remark-parse')).default; + + // Dynamically import remark-parse + const { default: remarkParse } = await import('remark-parse'); + // Parse Markdown into AST const processor = unified().use(remarkParse); const tree = processor.parse(markdownContent) as Root; diff --git a/apps/app/test/integration/service/page-sprit.test.ts b/apps/app/test/integration/service/page-sprit.test.ts index a489ff22345..80e48a4c34b 100644 --- a/apps/app/test/integration/service/page-sprit.test.ts +++ b/apps/app/test/integration/service/page-sprit.test.ts @@ -1,3 +1,5 @@ +// test/integration/service/page-spritter.test.ts + import type { TiktokenModel } from '@dqbd/tiktoken'; import { splitMarkdownByTokens } from '../../../src/server/service/page-spritter'; @@ -5,14 +7,14 @@ import { splitMarkdownByTokens } from '../../../src/server/service/page-spritter describe('splitMarkdownByTokens', () => { const model: TiktokenModel = 'gpt-3.5-turbo'; - test('Returns without splitting when token count is below the maximum', () => { + test('Returns without splitting when token count is below the maximum', async() => { const markdownContent = '# Heading\n\nThis is a test.'; - const result = splitMarkdownByTokens(model, markdownContent, 1000); + const result = await splitMarkdownByTokens(model, markdownContent, 1000); expect(result).toHaveLength(1); expect(result[0]).toBe(markdownContent); }); - test('Splits by sections when token count exceeds the maximum', () => { + test('Splits by sections when token count exceeds the maximum', async() => { const markdownContent = ` # Heading1 @@ -26,14 +28,14 @@ This is the content of section 2. This is the content of section 3. `; - const result = splitMarkdownByTokens(model, markdownContent, 10); // Set a small maxTokens + const result = await splitMarkdownByTokens(model, markdownContent, 10); // Set a small maxTokens expect(result).toHaveLength(3); expect(result[0]).toContain('Heading1'); expect(result[1]).toContain('Heading2'); expect(result[2]).toContain('Heading3'); }); - test('Recursively splits into subsections', () => { + test('Recursively splits into subsections', async() => { const markdownContent = ` # Heading1 @@ -49,29 +51,29 @@ Content1-2 Content2 `; - const result = splitMarkdownByTokens(model, markdownContent, 20); + const result = await splitMarkdownByTokens(model, markdownContent, 20); expect(result.length).toBeGreaterThan(2); expect(result.some(chunk => chunk.includes('Subheading1-1'))).toBe(true); expect(result.some(chunk => chunk.includes('Subheading1-2'))).toBe(true); }); - test('Splits by paragraphs', () => { + test('Splits by paragraphs', async() => { const markdownContent = ` # Heading ${'Long paragraph. '.repeat(50)} `; - const result = splitMarkdownByTokens(model, markdownContent, 50); + const result = await splitMarkdownByTokens(model, markdownContent, 50); expect(result.length).toBeGreaterThan(1); }); - test('Adds a single node as is when it exceeds maxTokens', () => { + test('Adds a single node as is when it exceeds maxTokens', async() => { const markdownContent = ` # Heading ${'Very long paragraph. '.repeat(200)} `; - const result = splitMarkdownByTokens(model, markdownContent, 50); + const result = await splitMarkdownByTokens(model, markdownContent, 50); expect(result).toHaveLength(1); expect(result[0]).toContain('Very long paragraph.'); }); From 6c839eed27b18a32553f9601d59b769026f378ef Mon Sep 17 00:00:00 2001 From: nHigashiWeseek Date: Wed, 25 Sep 2024 09:08:23 +0000 Subject: [PATCH 289/490] change --- apps/app/src/server/service/page-spritter.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/app/src/server/service/page-spritter.ts b/apps/app/src/server/service/page-spritter.ts index 8b138ae7d73..dbeb8f40d82 100644 --- a/apps/app/src/server/service/page-spritter.ts +++ b/apps/app/src/server/service/page-spritter.ts @@ -1,8 +1,6 @@ import type { Tiktoken, TiktokenModel } from '@dqbd/tiktoken'; import { encoding_for_model } from '@dqbd/tiktoken'; // eslint-disable-line import type { Root, Content, Heading } from 'mdast'; -import remarkStringify from 'remark-stringify'; -import { unified } from 'unified'; /** * Interface representing a section @@ -29,7 +27,9 @@ export async function splitMarkdownByTokens( const encoding: Tiktoken = encoding_for_model(model); // Dynamically import remark-parse - const { default: remarkParse } = await import('remark-parse'); + const remarkParse = (await import('remark-parse')).default; + const remarkStringify = (await import('remark-stringify')).default; + const unified = (await import('unified')).unified; // Parse Markdown into AST const processor = unified().use(remarkParse); From f5e389b2eb28831fe694195b85256c0d2a1945e8 Mon Sep 17 00:00:00 2001 From: Shun Miyazawa Date: Wed, 25 Sep 2024 09:11:29 +0000 Subject: [PATCH 290/490] add logger --- apps/app/config/logger/config.dev.js | 2 +- apps/app/src/server/service/openai/openai.ts | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/apps/app/config/logger/config.dev.js b/apps/app/config/logger/config.dev.js index 66a9ec2f1f1..47a9767231b 100644 --- a/apps/app/config/logger/config.dev.js +++ b/apps/app/config/logger/config.dev.js @@ -43,5 +43,5 @@ module.exports = { // 'growi:cli:StickyStretchableScroller': 'debug', // 'growi:cli:ItemsTree': 'debug', 'growi:searchResultList': 'debug', - + 'growi:service:openai': 'debug', }; diff --git a/apps/app/src/server/service/openai/openai.ts b/apps/app/src/server/service/openai/openai.ts index 9dda28f99ea..6ac9286405c 100644 --- a/apps/app/src/server/service/openai/openai.ts +++ b/apps/app/src/server/service/openai/openai.ts @@ -7,9 +7,12 @@ import { toFile } from 'openai'; import type { PageDocument, PageModel } from '~/server/models/page'; import { configManager } from '~/server/service/config-manager'; +import loggerFactory from '~/utils/logger'; import OpenaiClient from './openai-client-delegator'; +const logger = loggerFactory('growi:service:openai'); + export interface IOpenaiService { rebuildVectorStoreAll(): Promise; rebuildVectorStore(page: PageDocument): Promise; @@ -49,18 +52,21 @@ class OpenaiService implements IOpenaiService { } async rebuildVectorStore(page: PageDocument) { + // delete vector store file const files = await this.client.getFileList(); files.data.forEach(async(file) => { if (file.filename === `${page._id}.md`) { - await this.client.deleteFile(file.id); + const res = await this.client.deleteFile(file.id); + logger.debug('delete vector store: ', res); } }); // create vector store file if (page.grant === PageGrant.GRANT_PUBLIC && page.revision != null && isPopulated(page?.revision)) { const file = await toFile(Readable.from(page.revision.body), `${page._id}.md`); - await this.client.uploadAndPoll([file]); + const res = await this.client.uploadAndPoll([file]); + logger.debug('create vector store: ', res); } } From dacf0353bb0a33406ed4bff3282abe1806611689 Mon Sep 17 00:00:00 2001 From: Shun Miyazawa Date: Wed, 25 Sep 2024 09:25:14 +0000 Subject: [PATCH 291/490] add trycatch --- apps/app/src/server/routes/apiv3/page/update-page.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/app/src/server/routes/apiv3/page/update-page.ts b/apps/app/src/server/routes/apiv3/page/update-page.ts index b59c54baf3d..1c5f92f6f66 100644 --- a/apps/app/src/server/routes/apiv3/page/update-page.ts +++ b/apps/app/src/server/routes/apiv3/page/update-page.ts @@ -120,7 +120,12 @@ export const updatePageHandlersFactory: UpdatePageHandlersFactory = (crowi) => { // Rebuild vector store file const aiEnabled = configManager.getConfig('crowi', 'app:aiEnabled'); if (aiEnabled) { - await openaiService.rebuildVectorStore(updatedPage); + try { + await openaiService.rebuildVectorStore(updatedPage); + } + catch (err) { + logger.error('Rebuild vector store failed', err); + } } } From bf07ed4ad9b874c5939688e6204a810cdfe7b6f1 Mon Sep 17 00:00:00 2001 From: nHigashiWeseek Date: Wed, 25 Sep 2024 09:41:32 +0000 Subject: [PATCH 292/490] change directory --- apps/app/src/server/{service => util}/page-spritter.ts | 0 apps/app/test/integration/service/page-sprit.test.ts | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename apps/app/src/server/{service => util}/page-spritter.ts (100%) diff --git a/apps/app/src/server/service/page-spritter.ts b/apps/app/src/server/util/page-spritter.ts similarity index 100% rename from apps/app/src/server/service/page-spritter.ts rename to apps/app/src/server/util/page-spritter.ts diff --git a/apps/app/test/integration/service/page-sprit.test.ts b/apps/app/test/integration/service/page-sprit.test.ts index 80e48a4c34b..7cbe6ab21b4 100644 --- a/apps/app/test/integration/service/page-sprit.test.ts +++ b/apps/app/test/integration/service/page-sprit.test.ts @@ -2,7 +2,7 @@ import type { TiktokenModel } from '@dqbd/tiktoken'; -import { splitMarkdownByTokens } from '../../../src/server/service/page-spritter'; +import { splitMarkdownByTokens } from '../../../src/server/util/page-spritter'; describe('splitMarkdownByTokens', () => { const model: TiktokenModel = 'gpt-3.5-turbo'; From 0c7d9154d9598688350a8405b8fb3a099abcb4aa Mon Sep 17 00:00:00 2001 From: Shun Miyazawa Date: Wed, 25 Sep 2024 09:52:56 +0000 Subject: [PATCH 293/490] not optional --- apps/app/src/server/service/openai/openai.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/app/src/server/service/openai/openai.ts b/apps/app/src/server/service/openai/openai.ts index 6ac9286405c..dd813273587 100644 --- a/apps/app/src/server/service/openai/openai.ts +++ b/apps/app/src/server/service/openai/openai.ts @@ -63,7 +63,7 @@ class OpenaiService implements IOpenaiService { }); // create vector store file - if (page.grant === PageGrant.GRANT_PUBLIC && page.revision != null && isPopulated(page?.revision)) { + if (page.grant === PageGrant.GRANT_PUBLIC && page.revision != null && isPopulated(page.revision)) { const file = await toFile(Readable.from(page.revision.body), `${page._id}.md`); const res = await this.client.uploadAndPoll([file]); logger.debug('create vector store: ', res); From ef090ce2276508de06c0b4be92fbd3ce5ca72813 Mon Sep 17 00:00:00 2001 From: nHigashiWeseek Date: Wed, 25 Sep 2024 10:07:30 +0000 Subject: [PATCH 294/490] fb --- apps/app/src/stores/page-listing.tsx | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/apps/app/src/stores/page-listing.tsx b/apps/app/src/stores/page-listing.tsx index 367d0cf0fde..4e35562c243 100644 --- a/apps/app/src/stores/page-listing.tsx +++ b/apps/app/src/stores/page-listing.tsx @@ -55,16 +55,12 @@ export const useSWRINFxRecentlyUpdated = (limit: number, includeWipPage?: boolea ); }; -export const mutateRecentlyUpdated = async(): Promise => { - const mutations: Promise[] = []; - +export const mutateRecentlyUpdated = async(): Promise => { for (const key of cache.keys()) { if (key.includes('/pages/recent')) { - mutations.push(mutate(key)); + mutate(key); } } - - return Promise.all(mutations); }; export const mutatePageList = async(): Promise => { From dd35b1d76c4a56cb7c7093651edf493b548fc995 Mon Sep 17 00:00:00 2001 From: Yuki Takei Date: Wed, 25 Sep 2024 12:03:13 +0000 Subject: [PATCH 295/490] Merge master into dev/7.1.x --- .github/mergify.yml | 1 + .github/workflows/release-slackbot-proxy.yml | 2 +- .github/workflows/release.yml | 2 +- apps/app/docker/README.md | 2 +- apps/app/next-env.d.ts | 2 +- apps/app/package.json | 14 +- .../public/static/locales/en_US/commons.json | 2 +- .../public/static/locales/fr_FR/commons.json | 2 +- .../public/static/locales/ja_JP/commons.json | 2 +- .../public/static/locales/zh_CN/commons.json | 2 +- .../components/Admin/G2GDataTransfer.tsx | 11 +- .../Notification/NotificationSetting.jsx | 10 +- .../Common/Dropdown/PageItemControl.spec.tsx | 5 +- .../CustomNavigation/CustomNav.module.scss | 1 - .../components/CustomNavigation/CustomNav.tsx | 22 +- .../client/components/DataTransferForm.tsx | 10 +- .../DescendantsPageListModal.module.scss | 4 + .../DescendantsPageListModal.spec.tsx | 70 + .../components/DescendantsPageListModal.tsx | 34 +- .../Navbar/GrowiContextualSubNavigation.tsx | 6 +- .../PageHeader/PageTitleHeader.spec.tsx | 115 ++ .../components/PageHeader/PageTitleHeader.tsx | 1 + .../src/pages/admin/data-transfer.page.tsx | 12 +- apps/app/src/pages/installer.page.tsx | 3 +- apps/app/src/stores-universal/context.tsx | 22 +- .../download-mongo-binary/vitest.config.ts | 29 +- apps/app/vitest.config.components.ts | 19 - apps/app/vitest.config.integ.ts | 23 - apps/app/vitest.config.ts | 19 - apps/app/vitest.workspace.mts | 65 + package.json | 15 +- .../bootstrap/theming/_dropdown-dark.scss | 5 + .../bootstrap/theming/_dropdown-light.scss | 6 + .../scss/bootstrap/theming/apply-dark.scss | 1 + .../scss/bootstrap/theming/apply-light.scss | 1 + .../pluginkit/src/v4/utils/template.spec.ts | 81 + packages/pluginkit/vitest.config.ts | 15 +- vitest.workspace.ts => vitest.workspace.mts | 2 + yarn.lock | 1589 +++++++---------- 39 files changed, 1200 insertions(+), 1027 deletions(-) create mode 100644 apps/app/src/client/components/DescendantsPageListModal.spec.tsx create mode 100644 apps/app/src/client/components/PageHeader/PageTitleHeader.spec.tsx delete mode 100644 apps/app/vitest.config.components.ts delete mode 100644 apps/app/vitest.config.integ.ts delete mode 100644 apps/app/vitest.config.ts create mode 100644 apps/app/vitest.workspace.mts create mode 100644 packages/core-styles/scss/bootstrap/theming/_dropdown-dark.scss create mode 100644 packages/core-styles/scss/bootstrap/theming/_dropdown-light.scss create mode 100644 packages/pluginkit/src/v4/utils/template.spec.ts rename vitest.workspace.ts => vitest.workspace.mts (54%) diff --git a/.github/mergify.yml b/.github/mergify.yml index eaa719767e9..890bee65f01 100644 --- a/.github/mergify.yml +++ b/.github/mergify.yml @@ -23,6 +23,7 @@ pull_request_rules: - name: Automatic queue to merge conditions: - '#approved-reviews-by >= 1' + - '#changes-requested-reviews-by = 0' - '#review-requested = 0' - check-success = check-title actions: diff --git a/.github/workflows/release-slackbot-proxy.yml b/.github/workflows/release-slackbot-proxy.yml index 95290d4e114..01fbfe4eb86 100644 --- a/.github/workflows/release-slackbot-proxy.yml +++ b/.github/workflows/release-slackbot-proxy.yml @@ -41,7 +41,7 @@ jobs: credentials_json: '${{ secrets.GCP_SA_KEY_SLACKBOT_PROXY }}' - name: Setup gcloud - uses: google-github-actions/setup-gcloud@v1 + uses: google-github-actions/setup-gcloud@v2 - name: Configure docker for gcloud run: | diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d8b0bfcbdc4..65a4196d298 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -64,7 +64,7 @@ jobs: commit_message: Release v${{ steps.package-json.outputs.packageVersion }} tagging_message: v${{ steps.package-json.outputs.packageVersion }} - - uses: softprops/action-gh-release@v1 + - uses: softprops/action-gh-release@v2 with: body: ${{ github.event.pull_request.body }} tag_name: v${{ steps.package-json.outputs.packageVersion }} diff --git a/apps/app/docker/README.md b/apps/app/docker/README.md index b54a51e6f40..22bb186f042 100644 --- a/apps/app/docker/README.md +++ b/apps/app/docker/README.md @@ -4,7 +4,7 @@ GROWI Official docker image [![Actions Status](https://github.com/weseek/growi/workflows/Release/badge.svg)](https://github.com/weseek/growi/actions) [![docker-pulls](https://img.shields.io/docker/pulls/weseek/growi.svg)](https://hub.docker.com/r/weseek/growi/) [![](https://images.microbadger.com/badges/image/weseek/growi.svg)](https://microbadger.com/images/weseek/growi) -![GROWI-x-docker](https://user-images.githubusercontent.com/1638767/38307565-105956e2-384f-11e8-8534-b1128522d68d.png) +![GROWI-x-docker](https://github.com/user-attachments/assets/1a82236d-5a85-4a2e-842a-971b4c1625e6) Supported tags and respective Dockerfile links diff --git a/apps/app/next-env.d.ts b/apps/app/next-env.d.ts index 4f11a03dc6c..a4a7b3f5cfa 100644 --- a/apps/app/next-env.d.ts +++ b/apps/app/next-env.d.ts @@ -2,4 +2,4 @@ /// // NOTE: This file should not be edited -// see https://nextjs.org/docs/basic-features/typescript for more information. +// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information. diff --git a/apps/app/package.json b/apps/app/package.json index 65894f5cc66..428699d4138 100644 --- a/apps/app/package.json +++ b/apps/app/package.json @@ -35,12 +35,9 @@ "prelint:swagger2openapi": "yarn openapi:v3", "test": "run-p test:*", "test:jest": "cross-env NODE_ENV=test TS_NODE_PROJECT=test/integration/tsconfig.json jest", - "test:vitest": "run-p vitest:run vitest:run:integ vitest:run:components", + "test:vitest": "vitest run --coverage", "jest:run": "cross-env NODE_ENV=test TS_NODE_PROJECT=test/integration/tsconfig.json jest --passWithNoTests -- ", "reg:run": "reg-suit run", - "vitest:run": "vitest run config src --coverage", - "vitest:run:integ": "vitest run -c vitest.config.integ.ts src --coverage", - "vitest:run:components": "vitest run -c vitest.config.components.ts src --coverage", "previtest:run:integ": "vitest run -c test-with-vite/download-mongo-binary/vitest.config.ts test-with-vite/download-mongo-binary", "//// misc": "", "console": "yarn repl", @@ -143,7 +140,7 @@ "multer": "~1.4.0", "multer-autoreap": "^1.0.3", "mustache": "^4.2.0", - "next": "^14.1.3", + "next": "^14.2.13", "next-dynamic-loading-props": "^0.1.1", "next-i18next": "^15.2.0", "next-superjson": "^0.0.4", @@ -229,13 +226,16 @@ "@popperjs/core": "^2.11.8", "@swc-node/jest": "^1.8.1", "@swc/jest": "^0.2.36", - "@testing-library/react": "^14.1.2", + "@testing-library/dom": "^10.4.0", + "@testing-library/jest-dom": "^6.5.0", + "@testing-library/react": "^16.0.1", "@testing-library/user-event": "^14.5.2", "@types/express": "^4.17.21", "@types/jest": "^29.5.2", "@types/react-input-autosize": "^2.2.4", "@types/react-scroll": "^1.8.4", "@types/react-stickynode": "^4.0.3", + "@types/testing-library__dom": "^7.5.0", "@types/throttle-debounce": "^5.0.1", "@types/unzip-stream": "^0.3.4", "@types/url-join": "^4.0.2", @@ -249,7 +249,7 @@ "eslint-plugin-regex": "^1.8.0", "fslightbox-react": "^1.7.6", "handsontable": "=6.2.2", - "happy-dom": "^13.2.0", + "happy-dom": "^15.7.4", "i18next-chained-backend": "^4.6.2", "i18next-hmr": "^3.0.4", "i18next-http-backend": "^2.5.0", diff --git a/apps/app/public/static/locales/en_US/commons.json b/apps/app/public/static/locales/en_US/commons.json index eb6c0c50080..75292103da5 100644 --- a/apps/app/public/static/locales/en_US/commons.json +++ b/apps/app/public/static/locales/en_US/commons.json @@ -157,6 +157,6 @@ "publish_transfer_key": "Publish transfer key", "transfer_key_limit": "Transfer keys are valid for 1 hour after issuance.", "once_transfer_key_used": "Once the transfer key is used for transfer, it cannot be used for any other transfer.", - "transfer_to_growi_cloud": "If you wish to transfer to GROWI.cloud, please click here." + "transfer_to_growi_cloud": "For more details, please click here." } } diff --git a/apps/app/public/static/locales/fr_FR/commons.json b/apps/app/public/static/locales/fr_FR/commons.json index 3771c037ee5..fe4ba0dc668 100644 --- a/apps/app/public/static/locales/fr_FR/commons.json +++ b/apps/app/public/static/locales/fr_FR/commons.json @@ -157,6 +157,6 @@ "publish_transfer_key": "Publier la clé de transfert", "transfer_key_limit": "Les clés de transfert sont valides durant une heure.", "once_transfer_key_used": "Les clés de transfert sont à usage unique.", - "transfer_to_growi_cloud": "Si vous souhaitez transférer depuis GROWI.cloud, cliquez ici." + "transfer_to_growi_cloud": "Pour plus de détails, veuillez cliquer ici." } } diff --git a/apps/app/public/static/locales/ja_JP/commons.json b/apps/app/public/static/locales/ja_JP/commons.json index f85a86db4f9..fe569c6301c 100644 --- a/apps/app/public/static/locales/ja_JP/commons.json +++ b/apps/app/public/static/locales/ja_JP/commons.json @@ -159,6 +159,6 @@ "publish_transfer_key": "移行キーを発行する", "transfer_key_limit": "※ 移行キーの有効期限は発行から1時間となります。", "once_transfer_key_used": "※ 移行キーは一度移行に利用するとそれ以降はご利用いただけなくなります。", - "transfer_to_growi_cloud": "※ GROWI.cloud への移行を実施する場合はこちらをご確認ください。" + "transfer_to_growi_cloud": "※ 詳しくは GROWI お引越し機能をご確認ください。" } } diff --git a/apps/app/public/static/locales/zh_CN/commons.json b/apps/app/public/static/locales/zh_CN/commons.json index 9108400f2d3..11c0c595de3 100644 --- a/apps/app/public/static/locales/zh_CN/commons.json +++ b/apps/app/public/static/locales/zh_CN/commons.json @@ -160,6 +160,6 @@ "publish_transfer_key": "发布迁移密钥", "transfer_key_limit": "迁移密钥在签发后一小时内有效。", "once_transfer_key_used": "一旦迁移密钥被用于迁移,它将不再可用于进一步的迁移。", - "transfer_to_growi_cloud": "如果您希望迁移到GROWI.cloud,请点击这里。" + "transfer_to_growi_cloud": "有关更多详情,请点击此处。" } } diff --git a/apps/app/src/client/components/Admin/G2GDataTransfer.tsx b/apps/app/src/client/components/Admin/G2GDataTransfer.tsx index a61650af4a8..8f1e1a12f6b 100644 --- a/apps/app/src/client/components/Admin/G2GDataTransfer.tsx +++ b/apps/app/src/client/components/Admin/G2GDataTransfer.tsx @@ -8,6 +8,7 @@ import { useGenerateTransferKey } from '~/client/services/g2g-transfer'; import { apiv3Get, apiv3Post } from '~/client/util/apiv3-client'; import { toastError, toastSuccess } from '~/client/util/toastr'; import { G2G_PROGRESS_STATUS, type G2GProgress } from '~/interfaces/g2g-transfer'; +import { useGrowiDocumentationUrl } from '~/stores-universal/context'; import { useAdminSocket } from '~/stores/socket-io'; import CustomCopyToClipBoard from '../Common/CustomCopyToClipBoard'; @@ -123,6 +124,8 @@ const G2GDataTransfer = (): JSX.Element => { } }, [setTransferring, startTransferKey, selectedCollections, optionsMap]); + const { data: documentationUrl } = useGrowiDocumentationUrl(); + // File upload // const onChangeFileUploadTypeHandler = useCallback((e: ChangeEvent, type: string) => { // setFileUploadType(type); @@ -275,7 +278,13 @@ const G2GDataTransfer = (): JSX.Element => {

                  {t('commons:g2g_data_transfer.transfer_key_limit')}

                  {t('commons:g2g_data_transfer.once_transfer_key_used')}

                  -

                  {t('commons:g2g_data_transfer.transfer_to_growi_cloud')}

                  +

                  ); diff --git a/apps/app/src/client/components/Admin/Notification/NotificationSetting.jsx b/apps/app/src/client/components/Admin/Notification/NotificationSetting.jsx index 357d214912c..b9dc3314c4a 100644 --- a/apps/app/src/client/components/Admin/Notification/NotificationSetting.jsx +++ b/apps/app/src/client/components/Admin/Notification/NotificationSetting.jsx @@ -14,7 +14,7 @@ import { toastError } from '~/client/util/toastr'; import { toArrayIfNot } from '~/utils/array-utils'; import loggerFactory from '~/utils/logger'; -import { CustomNavTab } from '../../CustomNavigation/CustomNav'; +import CustomNav from '../../CustomNavigation/CustomNav'; import { withUnstatedContainers } from '../../UnstatedUtils'; @@ -155,7 +155,13 @@ function NotificationSetting(props) {

                  {t('notification_settings.notification_settings')}

                  - + diff --git a/apps/app/src/client/components/Common/Dropdown/PageItemControl.spec.tsx b/apps/app/src/client/components/Common/Dropdown/PageItemControl.spec.tsx index e85c064af3c..af94193c66e 100644 --- a/apps/app/src/client/components/Common/Dropdown/PageItemControl.spec.tsx +++ b/apps/app/src/client/components/Common/Dropdown/PageItemControl.spec.tsx @@ -1,7 +1,8 @@ import { type IPageInfoForOperation } from '@growi/core/dist/interfaces'; import { - fireEvent, render, screen, within, -} from '@testing-library/react'; + fireEvent, screen, within, +} from '@testing-library/dom'; +import { render } from '@testing-library/react'; import { mock } from 'vitest-mock-extended'; import { PageItemControl } from './PageItemControl'; diff --git a/apps/app/src/client/components/CustomNavigation/CustomNav.module.scss b/apps/app/src/client/components/CustomNavigation/CustomNav.module.scss index 0b5ae9b999b..42ac2f29349 100644 --- a/apps/app/src/client/components/CustomNavigation/CustomNav.module.scss +++ b/apps/app/src/client/components/CustomNavigation/CustomNav.module.scss @@ -14,5 +14,4 @@ border-bottom: 3px solid; transition: 0.3s ease-in-out; } - } diff --git a/apps/app/src/client/components/CustomNavigation/CustomNav.tsx b/apps/app/src/client/components/CustomNavigation/CustomNav.tsx index 6a4090bf96e..3fc12e81cfa 100644 --- a/apps/app/src/client/components/CustomNavigation/CustomNav.tsx +++ b/apps/app/src/client/components/CustomNavigation/CustomNav.tsx @@ -42,26 +42,42 @@ export const CustomNavDropdown = (props: CustomNavDropdownProps): JSX.Element => const { Icon, i18n } = navTabMapping[activeTab]; + const [isDropdownOpen, setIsDropdownOpen] = useState(false); + + const dropdownButtonRef = useRef(null); + + const toggleDropdown = () => { + setIsDropdownOpen(prev => !prev); + }; + const menuItemClickHandler = useCallback((key) => { if (onNavSelected != null) { onNavSelected(key); } + // Manually close the dropdown + setIsDropdownOpen(false); + if (dropdownButtonRef.current) { + dropdownButtonRef.current.classList.remove('show'); + } }, [onNavSelected]); return (
                  -
                  +
                  {Object.entries(navTabMapping).map(([key, value]) => { const isActive = activeTab === key; @@ -167,7 +183,7 @@ export const CustomNavTab = (props: CustomNavTabProps): JSX.Element => { } return ( -
                  +