diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index 850616003e..783ed45606 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -1069,6 +1069,9 @@ importers: '@rush-temp/text': specifier: file:./projects/text.tgz version: file:projects/text.tgz(@babel/core@7.23.9)(@jest/types@29.6.3)(@types/node@20.11.19)(babel-jest@29.7.0(@babel/core@7.23.9))(bufferutil@4.0.8)(esbuild@0.24.2)(prosemirror-inputrules@1.4.0)(prosemirror-model@1.22.3)(prosemirror-state@1.4.3)(prosemirror-view@1.34.2)(ts-node@10.9.2(@types/node@20.11.19)(typescript@5.3.3))(utf-8-validate@6.0.4) + '@rush-temp/text-core': + specifier: file:./projects/text-core.tgz + version: file:projects/text-core.tgz(@babel/core@7.23.9)(@jest/types@29.6.3)(@types/node@20.11.19)(babel-jest@29.7.0(@babel/core@7.23.9))(bufferutil@4.0.8)(esbuild@0.24.2)(ts-node@10.9.2(@types/node@20.11.19)(typescript@5.3.3))(utf-8-validate@6.0.4) '@rush-temp/text-editor': specifier: file:./projects/text-editor.tgz version: file:projects/text-editor.tgz(@babel/core@7.23.9)(@jest/types@29.6.3)(@types/node@20.11.19)(babel-jest@29.7.0(@babel/core@7.23.9))(esbuild@0.24.2)(ts-node@10.9.2(@types/node@20.11.19)(typescript@5.3.3)) @@ -1273,9 +1276,6 @@ importers: '@types/cors': specifier: ^2.8.12 version: 2.8.17 - '@types/crypto-js': - specifier: ^4.1.1 - version: 4.2.2 '@types/csvtojson': specifier: ^2.0.0 version: 2.0.3 @@ -1394,8 +1394,8 @@ importers: specifier: ^8.3.1 version: 8.3.4 '@types/web-push': - specifier: ~3.6.3 - version: 3.6.3 + specifier: ^3.6.4 + version: 3.6.4 '@types/ws': specifier: ^8.5.11 version: 8.5.11 @@ -1490,7 +1490,7 @@ importers: specifier: ^3.1.5 version: 3.1.8(encoding@0.1.13) crypto-js: - specifier: ^4.1.1 + specifier: ^4.2.0 version: 4.2.0 css-loader: specifier: ^5.2.1 @@ -1667,8 +1667,8 @@ importers: specifier: ^1.1.1 version: 1.1.1 intl-messageformat: - specifier: ^9.7.1 - version: 9.13.0 + specifier: ^10.7.14 + version: 10.7.14 itty-router: specifier: ^5.0.18 version: 5.0.18 @@ -1729,6 +1729,9 @@ importers: markdown-it: specifier: ^14.0.0 version: 14.0.0 + md5.js: + specifier: ^1.3.5 + version: 1.3.5 mermaid: specifier: ~11.4.1 version: 11.4.1 @@ -1928,7 +1931,7 @@ importers: specifier: ^8.3.2 version: 8.3.2 web-push: - specifier: ~3.6.7 + specifier: ^3.6.7 version: 3.6.7 webpack: specifier: ^5.97.1 @@ -2928,20 +2931,20 @@ packages: resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} engines: {node: '>=14'} - '@formatjs/ecma402-abstract@1.11.4': - resolution: {integrity: sha512-EBikYFp2JCdIfGEb5G9dyCkTGDmC57KSHhRQOC3aYxoPWVZvfWCDjZwkGYHN7Lis/fmuWl906bnNTJifDQ3sXw==} + '@formatjs/ecma402-abstract@2.3.2': + resolution: {integrity: sha512-6sE5nyvDloULiyOMbOTJEEgWL32w+VHkZQs8S02Lnn8Y/O5aQhjOEXwWzvR7SsBE/exxlSpY2EsWZgqHbtLatg==} - '@formatjs/fast-memoize@1.2.1': - resolution: {integrity: sha512-Rg0e76nomkz3vF9IPlKeV+Qynok0r7YZjL6syLz4/urSg0IbjPZCB/iYUMNsYA643gh4mgrX3T7KEIFIxJBQeg==} + '@formatjs/fast-memoize@2.2.6': + resolution: {integrity: sha512-luIXeE2LJbQnnzotY1f2U2m7xuQNj2DA8Vq4ce1BY9ebRZaoPB1+8eZ6nXpLzsxuW5spQxr7LdCg+CApZwkqkw==} - '@formatjs/icu-messageformat-parser@2.1.0': - resolution: {integrity: sha512-Qxv/lmCN6hKpBSss2uQ8IROVnta2r9jd3ymUEIjm2UyIkUCHVcbUVRGL/KS/wv7876edvsPe+hjHVJ4z8YuVaw==} + '@formatjs/icu-messageformat-parser@2.11.0': + resolution: {integrity: sha512-Hp81uTjjdTk3FLh/dggU5NK7EIsVWc5/ZDWrIldmf2rBuPejuZ13CZ/wpVE2SToyi4EiroPTQ1XJcJuZFIxTtw==} - '@formatjs/icu-skeleton-parser@1.3.6': - resolution: {integrity: sha512-I96mOxvml/YLrwU2Txnd4klA7V8fRhb6JG/4hm3VMNmeJo1F03IpV2L3wWt7EweqNLES59SZ4d6hVOPCSf80Bg==} + '@formatjs/icu-skeleton-parser@1.8.12': + resolution: {integrity: sha512-QRAY2jC1BomFQHYDMcZtClqHR55EEnB96V7Xbk/UiBodsuFc5kujybzt87+qj1KqmJozFhk6n4KiT1HKwAkcfg==} - '@formatjs/intl-localematcher@0.2.25': - resolution: {integrity: sha512-YmLcX70BxoSopLFdLr1Ds99NdlTI2oWoLbaUW2M406lxOIPzE1KQhRz2fPUkq34xVZQaihCoU29h0KK7An3bhA==} + '@formatjs/intl-localematcher@0.5.10': + resolution: {integrity: sha512-af3qATX+m4Rnd9+wHcjJ4w2ijq+rAVP3CCinJQvFv1kgSu1W6jypUmvleJxcewdxmutM8dmIRZFxO/IQBZmP2Q==} '@gar/promisify@1.1.3': resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==} @@ -3808,7 +3811,7 @@ packages: version: 0.0.0 '@rush-temp/account@file:projects/account.tgz': - resolution: {integrity: sha512-aFUxA1twR0m+7sDVFXyKoeVQtVLMrr973LpLK6LHrRa+PD010X6+AyoOkkyVJKFN0Q6zu2Oqz88PsEt50Z2Mjg==, tarball: file:projects/account.tgz} + resolution: {integrity: sha512-xWdmeIZiSKL5eyvVHNUEnn/GXGsaNkayjxoDW+ydFB1GwUWExvSTA7OOs9mfG+IwLNU08GNKNGBYGM3XKZ2PsA==, tarball: file:projects/account.tgz} version: 0.0.0 '@rush-temp/activity-assets@file:projects/activity-assets.tgz': @@ -3936,7 +3939,7 @@ packages: version: 0.0.0 '@rush-temp/cloud-transactor@file:projects/cloud-transactor.tgz': - resolution: {integrity: sha512-sz4uAEfFOZfE7TOae+sv+RWlxunC4WlsQ7GTOX+kE+KDTNJK/r3d7+yIR/O3iDd4nsbLO/Al/9Z+wMZDXsmJcw==, tarball: file:projects/cloud-transactor.tgz} + resolution: {integrity: sha512-RmuejZDmaNRcHOCurZBKIHOgqyfTwUNtJdhzJEANVw3XAbuapCjlaCwmtK5bad2D6S1+VrHrXoF4vw4FamxZkw==, tarball: file:projects/cloud-transactor.tgz} version: 0.0.0 '@rush-temp/collaboration@file:projects/collaboration.tgz': @@ -3956,11 +3959,11 @@ packages: version: 0.0.0 '@rush-temp/contact-resources@file:projects/contact-resources.tgz': - resolution: {integrity: sha512-NwGEZHpomoqLYe2i/Z3Wm9xLB1Cl7okFToLBn51JWhFebje+20w47PFde2tUX77f5bfYuLJ0ykZbKnfDbFz9TA==, tarball: file:projects/contact-resources.tgz} + resolution: {integrity: sha512-sOoou1UaCHSN/qYHhEiWyiPICxmqP2p+ACDAeVzhU8fuUa5tejlzuANOdiEYqz4c8+u/NhlCQHd7G7G5WjMPpg==, tarball: file:projects/contact-resources.tgz} version: 0.0.0 '@rush-temp/contact@file:projects/contact.tgz': - resolution: {integrity: sha512-sjRtgKszoagGm79PFQKes/sfRMcddH1qEMG3/xKuRLKlVcVJJ56twJaCCUeXP+7MsXMH5eEcS3sNCIdtznuASg==, tarball: file:projects/contact.tgz} + resolution: {integrity: sha512-59CabCDtmhSMmziQMA8E7sB/xLjRibcfTjx/EuYh4trtpfOawQ6lVZSljJ3Fr3huHHg4A8A14L71MC4PgPSepQ==, tarball: file:projects/contact.tgz} version: 0.0.0 '@rush-temp/controlled-documents-assets@file:projects/controlled-documents-assets.tgz': @@ -4536,7 +4539,7 @@ packages: version: 0.0.0 '@rush-temp/platform@file:projects/platform.tgz': - resolution: {integrity: sha512-GyVd1NUl00O73Bwq0b/KFXhAfrko5BnqcN9ak+WWmDjHqi4CsWUfYm6ol5B7rbC38dqXXD4yBad/iEgywLliXA==, tarball: file:projects/platform.tgz} + resolution: {integrity: sha512-BlslXnvEEebr3t7GEdTHD5HcoOTdez1j6Fb8Q6KctCunFjTeRtN5vtsutv2ZR+ChIGgZ5seZ6DOUFNM1MJf4ew==, tarball: file:projects/platform.tgz} version: 0.0.0 '@rush-temp/pod-account@file:projects/pod-account.tgz': @@ -4592,7 +4595,7 @@ packages: version: 0.0.0 '@rush-temp/pod-ses@file:projects/pod-ses.tgz': - resolution: {integrity: sha512-P+HVwQR4SO6F4EXl5ReGR6hbng8CKsl4IK6Ww6u7yhNh1x7YGKzmV7UMRjSUc7qsNu4CzOhF7AYatCB602ANjA==, tarball: file:projects/pod-ses.tgz} + resolution: {integrity: sha512-gVCpGeUc+IsGfdCD84Sp+PcY21yRBkUhwfMUUC8VXcjf5MiayypLcc8pIGD2ufGGRJRAI3+clxIfiVc29ofBxw==, tarball: file:projects/pod-ses.tgz} version: 0.0.0 '@rush-temp/pod-sign@file:projects/pod-sign.tgz': @@ -4740,7 +4743,7 @@ packages: version: 0.0.0 '@rush-temp/server-activity-resources@file:projects/server-activity-resources.tgz': - resolution: {integrity: sha512-+UU7f65uCYtxuk56pj1bJ2ZaE6YHxVubtTfbsrLa8ZAGUOvWjrxY37B8j8GfcgGioL6PESsB12uEZIvghnNNaQ==, tarball: file:projects/server-activity-resources.tgz} + resolution: {integrity: sha512-pzbXI3TbbMXYv/qVmx97uHJD8IOrI7glY8HsD1Np0PAGqzGpWBOm1j6oHKjO/WvfXPCvbmBRBvir22/+IdeXKA==, tarball: file:projects/server-activity-resources.tgz} version: 0.0.0 '@rush-temp/server-activity@file:projects/server-activity.tgz': @@ -4784,7 +4787,7 @@ packages: version: 0.0.0 '@rush-temp/server-chunter-resources@file:projects/server-chunter-resources.tgz': - resolution: {integrity: sha512-Kpp8RTEJ+z5d8Rq7HbOhui8ZyV8OvKEXVkAXT80Ju/qhVnZ5Mnw/jk33dgwur1NPVjCWOK2SPECHf+eqzwXpBg==, tarball: file:projects/server-chunter-resources.tgz} + resolution: {integrity: sha512-anzs0C7AXicSpf9F+jjqdokc3cZunw5O8gC0095fQmEoOW94OmvTyboGrx8iK3i+iYam4Z6Bkt60rXRo3JvXZQ==, tarball: file:projects/server-chunter-resources.tgz} version: 0.0.0 '@rush-temp/server-chunter@file:projects/server-chunter.tgz': @@ -4812,7 +4815,7 @@ packages: version: 0.0.0 '@rush-temp/server-controlled-documents-resources@file:projects/server-controlled-documents-resources.tgz': - resolution: {integrity: sha512-g27+rhbyGhRdYikNstWia5wPng1EUiDp4DoEu51KVFrE4MOeaEXvB85Zb/4Jxg1RL4H7P6o7VRABeVqv6fkqsg==, tarball: file:projects/server-controlled-documents-resources.tgz} + resolution: {integrity: sha512-mYK9xbNtII74MyRDJjutIBvUvdXfVeGwaixq9uRTVlqQsmb8oYvqVsTLLfmjL/e/eb1nmUPtnWh7sogkGYU/yA==, tarball: file:projects/server-controlled-documents-resources.tgz} version: 0.0.0 '@rush-temp/server-controlled-documents@file:projects/server-controlled-documents.tgz': @@ -4860,7 +4863,7 @@ packages: version: 0.0.0 '@rush-temp/server-gmail-resources@file:projects/server-gmail-resources.tgz': - resolution: {integrity: sha512-V9M3+rquV4MPbPtmwWPdekguzA5WKJRDvU7xtpYKQSJ7J7hkLPKNah4GtSjin0opg6lTgtoAJUQaYLKheeCCbA==, tarball: file:projects/server-gmail-resources.tgz} + resolution: {integrity: sha512-B+iAjGb/dbs1BhVc2MmYZxv2LrHQk/IH3UazglCC7v3Nu5x6ny4oMPCHXqv7W7MMVjIzqt60Wsw7spkvyS1CSA==, tarball: file:projects/server-gmail-resources.tgz} version: 0.0.0 '@rush-temp/server-gmail@file:projects/server-gmail.tgz': @@ -4912,7 +4915,7 @@ packages: version: 0.0.0 '@rush-temp/server-notification-resources@file:projects/server-notification-resources.tgz': - resolution: {integrity: sha512-DhxiRHwKgwqkX4WP2ZmqGL7fHs0Ev3rtxHT/uylk5SPCPbKmBe20xyEzheSahP0Vm6kIS9XerGQuxGrI31eVBw==, tarball: file:projects/server-notification-resources.tgz} + resolution: {integrity: sha512-sLf+6eAqeGkx+28mefySh7RB9mMnEh5Cuw/Q036PALbzj/1tihPIIxlst9kMZAYgGr7WRaZGDGK4Pq2yxfCrPQ==, tarball: file:projects/server-notification-resources.tgz} version: 0.0.0 '@rush-temp/server-notification@file:projects/server-notification.tgz': @@ -4972,7 +4975,7 @@ packages: version: 0.0.0 '@rush-temp/server-telegram-resources@file:projects/server-telegram-resources.tgz': - resolution: {integrity: sha512-VsEVxoPM/hyelQa9/rQFzo+vbS8ixxU4RvVWdM0ae9HJuaEyszX4y9GheG/SDMa0NzCtyOOLf9KqL3ohGpkWRg==, tarball: file:projects/server-telegram-resources.tgz} + resolution: {integrity: sha512-2zGK/gI0mG8ZvEUYDK0lt8m525blawYUmk64vMfYF0K7hkOmKaE+aSECh6UJozxuxURpyNNzi/9R0SNnMyfXKw==, tarball: file:projects/server-telegram-resources.tgz} version: 0.0.0 '@rush-temp/server-telegram@file:projects/server-telegram.tgz': @@ -4984,7 +4987,7 @@ packages: version: 0.0.0 '@rush-temp/server-time-resources@file:projects/server-time-resources.tgz': - resolution: {integrity: sha512-WePYLAz/QHfFL+jMa/ZE6JQIvNYK4tGBs4ur6UBG3inJigtt9p7AR4PO+nr7dtGZqG8RT0T0TrGREcdV7pX5Gw==, tarball: file:projects/server-time-resources.tgz} + resolution: {integrity: sha512-N9YLO1krTVoyAYV78E8sW2mDjSuJ/wHD9EHPAZO6AHxtoFmzlMPJaLprjGf7bWIemiGyAZKcAFhmpu0RSlaYGA==, tarball: file:projects/server-time-resources.tgz} version: 0.0.0 '@rush-temp/server-time@file:projects/server-time.tgz': @@ -5000,7 +5003,7 @@ packages: version: 0.0.0 '@rush-temp/server-tracker-resources@file:projects/server-tracker-resources.tgz': - resolution: {integrity: sha512-VmLhXIzNRo1VeABIkcyYrRK7P2+OtDpXpYCrutGgmUqT+ioPHxaefntsS+wzItpblY78u4DJYSIkfOhtQXCTtg==, tarball: file:projects/server-tracker-resources.tgz} + resolution: {integrity: sha512-Npz6QfpPLP18rNxIGzNvjKf4QEhT8ywVdlYNt7e4QGvA1zetFDava2Cg0QpN31LZue8pTDCC3T94kBQMUiUfqg==, tarball: file:projects/server-tracker-resources.tgz} version: 0.0.0 '@rush-temp/server-tracker@file:projects/server-tracker.tgz': @@ -5139,6 +5142,10 @@ packages: resolution: {integrity: sha512-noV3nlBP0OvM6i4C5YUevkhltHxG/2bct4pusP3O3AEQ7Za+A4qwzpsE08pHfA9f9pedEG677GE4EmG9x61rVQ==, tarball: file:projects/tests-sanity.tgz} version: 0.0.0 + '@rush-temp/text-core@file:projects/text-core.tgz': + resolution: {integrity: sha512-piWZZp7T/zx+IKTP7fQGdY2schRbTEF2k0YuwXHkipp5MCA3BQLfy9VaZxAo5D4jhg0xySc1grVUfAqoOJIv8g==, tarball: file:projects/text-core.tgz} + version: 0.0.0 + '@rush-temp/text-editor-assets@file:projects/text-editor-assets.tgz': resolution: {integrity: sha512-HrJXNpWkSNwguy4rSL6Cihc3/1eTmi0KQAmyLix1ci88uOK/9kKga7lMnKAsuobrB9DjbuLgPpcEMNpavMi13w==, tarball: file:projects/text-editor-assets.tgz} version: 0.0.0 @@ -5156,7 +5163,7 @@ packages: version: 0.0.0 '@rush-temp/text@file:projects/text.tgz': - resolution: {integrity: sha512-p2TRL6FgtqVBooDf+E5A4HB+45VS03IvNxudhC9gCotewS726ZLOxl2XdfeuYB2rHYbzdmmiG2zb8GbPwqTkOw==, tarball: file:projects/text.tgz} + resolution: {integrity: sha512-3aISTkQPGhn/Af7odByrglZazlbus1nu5kHvq77BZ0LJZ2lVZDZ5eTf0/EH6IpvGkmSvkEmkVJUl/bG/5Z7urA==, tarball: file:projects/text.tgz} version: 0.0.0 '@rush-temp/theme@file:projects/theme.tgz': @@ -6254,8 +6261,8 @@ packages: '@types/verror@1.10.10': resolution: {integrity: sha512-l4MM0Jppn18hb9xmM6wwD1uTdShpf9Pn80aXTStnK1C94gtPvJcV2FrDmbOQUAQfJ1cKZHktkQUDwEqaAKXMMg==} - '@types/web-push@3.6.3': - resolution: {integrity: sha512-v3oT4mMJsHeJ/rraliZ+7TbZtr5bQQuxcgD7C3/1q/zkAj29c8RE0F9lVZVu3hiQe5Z9fYcBreV7TLnfKR+4mg==} + '@types/web-push@3.6.4': + resolution: {integrity: sha512-GnJmSr40H3RAnj0s34FNTcJi1hmWFV5KXugE0mYWnYhgTAHLJ/dJKAwDmvPJYMke0RplY2XE9LnM4hqSqKIjhQ==} '@types/webidl-conversions@7.0.3': resolution: {integrity: sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==} @@ -9137,6 +9144,10 @@ packages: has-unicode@2.0.1: resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} + hash-base@3.1.0: + resolution: {integrity: sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==} + engines: {node: '>=4'} + hasown@2.0.1: resolution: {integrity: sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==} engines: {node: '>= 0.4'} @@ -9283,10 +9294,6 @@ packages: resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} engines: {node: '>= 6'} - https-proxy-agent@7.0.4: - resolution: {integrity: sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==} - engines: {node: '>= 14'} - https-proxy-agent@7.0.5: resolution: {integrity: sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==} engines: {node: '>= 14'} @@ -9398,8 +9405,8 @@ packages: resolution: {integrity: sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==} engines: {node: '>=10.13.0'} - intl-messageformat@9.13.0: - resolution: {integrity: sha512-7sGC7QnSQGa5LZP7bXLDhVDtQOeKGeBFGHF2Y8LVBwYZoQZCgWeKoPGTa5GMG8g/TzDgeXuYJQis7Ggiw2xTOw==} + intl-messageformat@10.7.14: + resolution: {integrity: sha512-mMGnE4E1otdEutV5vLUdCxRJygHB5ozUBxsPB5qhitewssrS/qGruq9bmvIRkkGsNeK5ZWLfYRld18UHGTIifQ==} invert-kv@2.0.0: resolution: {integrity: sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==} @@ -10351,6 +10358,9 @@ packages: resolution: {integrity: sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==} engines: {node: '>=10'} + md5.js@1.3.5: + resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==} + md5@2.3.0: resolution: {integrity: sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==} @@ -13590,7 +13600,7 @@ snapshots: '@smithy/util-middleware': 3.0.0 '@smithy/util-retry': 3.0.0 '@smithy/util-utf8': 3.0.0 - tslib: 2.6.2 + tslib: 2.7.0 transitivePeerDependencies: - aws-crt @@ -13891,7 +13901,7 @@ snapshots: '@smithy/property-provider': 3.0.0 '@smithy/shared-ini-file-loader': 3.0.0 '@smithy/types': 3.0.0 - tslib: 2.6.2 + tslib: 2.7.0 '@aws-sdk/types@3.577.0': dependencies: @@ -14541,29 +14551,31 @@ snapshots: '@fastify/busboy@2.1.1': {} - '@formatjs/ecma402-abstract@1.11.4': + '@formatjs/ecma402-abstract@2.3.2': dependencies: - '@formatjs/intl-localematcher': 0.2.25 - tslib: 2.6.2 + '@formatjs/fast-memoize': 2.2.6 + '@formatjs/intl-localematcher': 0.5.10 + decimal.js: 10.4.3 + tslib: 2.7.0 - '@formatjs/fast-memoize@1.2.1': + '@formatjs/fast-memoize@2.2.6': dependencies: - tslib: 2.6.2 + tslib: 2.7.0 - '@formatjs/icu-messageformat-parser@2.1.0': + '@formatjs/icu-messageformat-parser@2.11.0': dependencies: - '@formatjs/ecma402-abstract': 1.11.4 - '@formatjs/icu-skeleton-parser': 1.3.6 - tslib: 2.6.2 + '@formatjs/ecma402-abstract': 2.3.2 + '@formatjs/icu-skeleton-parser': 1.8.12 + tslib: 2.7.0 - '@formatjs/icu-skeleton-parser@1.3.6': + '@formatjs/icu-skeleton-parser@1.8.12': dependencies: - '@formatjs/ecma402-abstract': 1.11.4 - tslib: 2.6.2 + '@formatjs/ecma402-abstract': 2.3.2 + tslib: 2.7.0 - '@formatjs/intl-localematcher@0.2.25': + '@formatjs/intl-localematcher@0.5.10': dependencies: - tslib: 2.6.2 + tslib: 2.7.0 '@gar/promisify@1.1.3': {} @@ -15760,10 +15772,12 @@ snapshots: '@rush-temp/account@file:projects/account.tgz(@babel/core@7.23.9)(@jest/types@29.6.3)(@types/node@20.11.19)(babel-jest@29.7.0(@babel/core@7.23.9))(esbuild@0.24.2)(gcp-metadata@5.3.0(encoding@0.1.13))(snappy@7.2.2)(socks@2.8.3)(ts-node@10.9.2(@types/node@20.11.19)(typescript@5.3.3))': dependencies: + '@types/crypto-js': 4.2.2 '@types/jest': 29.5.12 '@types/otp-generator': 4.0.2 '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.3.3))(eslint@8.56.0)(typescript@5.3.3) '@typescript-eslint/parser': 6.21.0(eslint@8.56.0)(typescript@5.3.3) + crypto-js: 4.2.0 eslint: 8.56.0 eslint-config-standard-with-typescript: 40.0.0(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.3.3))(eslint@8.56.0)(typescript@5.3.3))(eslint-plugin-import@2.29.1(eslint@8.56.0))(eslint-plugin-n@15.7.0(eslint@8.56.0))(eslint-plugin-promise@6.1.1(eslint@8.56.0))(eslint@8.56.0)(typescript@5.3.3) eslint-plugin-import: 2.29.1(eslint@8.56.0) @@ -16925,9 +16939,11 @@ snapshots: '@rush-temp/contact-resources@file:projects/contact-resources.tgz(@babel/core@7.23.9)(@jest/types@29.6.3)(@types/node@20.11.19)(babel-jest@29.7.0(@babel/core@7.23.9))(esbuild@0.24.2)(postcss-load-config@4.0.2(postcss@8.4.35)(ts-node@10.9.2(@types/node@20.11.19)(typescript@5.3.3)))(postcss@8.4.35)(ts-node@10.9.2(@types/node@20.11.19)(typescript@5.3.3))': dependencies: + '@types/crypto-js': 4.2.2 '@types/jest': 29.5.12 '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.3.3))(eslint@8.56.0)(typescript@5.3.3) '@typescript-eslint/parser': 6.21.0(eslint@8.56.0)(typescript@5.3.3) + crypto-js: 4.2.0 eslint: 8.56.0 eslint-config-standard-with-typescript: 40.0.0(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.3.3))(eslint@8.56.0)(typescript@5.3.3))(eslint-plugin-import@2.29.1(eslint@8.56.0))(eslint-plugin-n@15.7.0(eslint@8.56.0))(eslint-plugin-promise@6.1.1(eslint@8.56.0))(eslint@8.56.0)(typescript@5.3.3) eslint-plugin-import: 2.29.1(eslint@8.56.0) @@ -16969,13 +16985,13 @@ snapshots: '@types/jest': 29.5.12 '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.3.3))(eslint@8.56.0)(typescript@5.3.3) '@typescript-eslint/parser': 6.21.0(eslint@8.56.0)(typescript@5.3.3) - crypto-js: 4.2.0 eslint: 8.56.0 eslint-config-standard-with-typescript: 40.0.0(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.3.3))(eslint@8.56.0)(typescript@5.3.3))(eslint-plugin-import@2.29.1(eslint@8.56.0))(eslint-plugin-n@15.7.0(eslint@8.56.0))(eslint-plugin-promise@6.1.1(eslint@8.56.0))(eslint@8.56.0)(typescript@5.3.3) eslint-plugin-import: 2.29.1(eslint@8.56.0) eslint-plugin-n: 15.7.0(eslint@8.56.0) eslint-plugin-promise: 6.1.1(eslint@8.56.0) jest: 29.7.0(@types/node@20.11.19)(ts-node@10.9.2(@types/node@20.11.19)(typescript@5.3.3)) + md5.js: 1.3.5 prettier: 3.2.5 ts-jest: 29.1.2(@babel/core@7.23.9)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(esbuild@0.24.2)(jest@29.7.0(@types/node@20.11.19)(ts-node@10.9.2(@types/node@20.11.19)(typescript@5.3.3)))(typescript@5.3.3) typescript: 5.3.3 @@ -20207,7 +20223,7 @@ snapshots: eslint-plugin-import: 2.29.1(eslint@8.56.0) eslint-plugin-n: 15.7.0(eslint@8.56.0) eslint-plugin-promise: 6.1.1(eslint@8.56.0) - intl-messageformat: 9.13.0 + intl-messageformat: 10.7.14 jest: 29.7.0(@types/node@20.11.19)(ts-node@10.9.2(@types/node@20.11.19)(typescript@5.3.3)) prettier: 3.2.5 ts-jest: 29.1.2(@babel/core@7.23.9)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(esbuild@0.24.2)(jest@29.7.0(@types/node@20.11.19)(ts-node@10.9.2(@types/node@20.11.19)(typescript@5.3.3)))(typescript@5.3.3) @@ -20816,6 +20832,7 @@ snapshots: '@types/express': 4.17.21 '@types/jest': 29.5.12 '@types/node': 20.11.19 + '@types/web-push': 3.6.4 '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.3.3))(eslint@8.56.0)(typescript@5.3.3) '@typescript-eslint/parser': 6.21.0(eslint@8.56.0)(typescript@5.3.3) aws-sdk: 2.1664.0 @@ -20835,6 +20852,7 @@ snapshots: ts-jest: 29.1.2(@babel/core@7.23.9)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(esbuild@0.24.2)(jest@29.7.0(@types/node@20.11.19)(ts-node@10.9.2(@types/node@20.11.19)(typescript@5.3.3)))(typescript@5.3.3) ts-node: 10.9.2(@types/node@20.11.19)(typescript@5.3.3) typescript: 5.3.3 + web-push: 3.6.7 transitivePeerDependencies: - '@babel/core' - '@jest/types' @@ -23122,7 +23140,6 @@ snapshots: '@rush-temp/server-notification-resources@file:projects/server-notification-resources.tgz(@babel/core@7.23.9)(@jest/types@29.6.3)(@types/node@20.11.19)(babel-jest@29.7.0(@babel/core@7.23.9))(esbuild@0.24.2)(ts-node@10.9.2(@types/node@20.11.19)(typescript@5.3.3))': dependencies: '@types/jest': 29.5.12 - '@types/web-push': 3.6.3 '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.3.3))(eslint@8.56.0)(typescript@5.3.3) '@typescript-eslint/parser': 6.21.0(eslint@8.56.0)(typescript@5.3.3) eslint: 8.56.0 @@ -23134,7 +23151,6 @@ snapshots: prettier: 3.2.5 ts-jest: 29.1.2(@babel/core@7.23.9)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(esbuild@0.24.2)(jest@29.7.0(@types/node@20.11.19)(ts-node@10.9.2(@types/node@20.11.19)(typescript@5.3.3)))(typescript@5.3.3) typescript: 5.3.3 - web-push: 3.6.7 transitivePeerDependencies: - '@babel/core' - '@jest/types' @@ -24705,6 +24721,37 @@ snapshots: transitivePeerDependencies: - supports-color + '@rush-temp/text-core@file:projects/text-core.tgz(@babel/core@7.23.9)(@jest/types@29.6.3)(@types/node@20.11.19)(babel-jest@29.7.0(@babel/core@7.23.9))(bufferutil@4.0.8)(esbuild@0.24.2)(ts-node@10.9.2(@types/node@20.11.19)(typescript@5.3.3))(utf-8-validate@6.0.4)': + dependencies: + '@types/jest': 29.5.12 + '@types/markdown-it': 13.0.8 + '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.3.3))(eslint@8.56.0)(typescript@5.6.2) + '@typescript-eslint/parser': 6.21.0(eslint@8.56.0)(typescript@5.6.2) + eslint: 8.56.0 + eslint-config-standard-with-typescript: 40.0.0(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.3.3))(eslint@8.56.0)(typescript@5.3.3))(eslint-plugin-import@2.29.1(eslint@8.56.0))(eslint-plugin-n@15.7.0(eslint@8.56.0))(eslint-plugin-promise@6.1.1(eslint@8.56.0))(eslint@8.56.0)(typescript@5.6.2) + eslint-plugin-import: 2.29.1(eslint@8.56.0) + eslint-plugin-n: 15.7.0(eslint@8.56.0) + eslint-plugin-promise: 6.1.1(eslint@8.56.0) + fast-equals: 5.0.1 + jest: 29.7.0(@types/node@20.11.19)(ts-node@10.9.2(@types/node@20.11.19)(typescript@5.3.3)) + jest-environment-jsdom: 29.7.0(bufferutil@4.0.8)(utf-8-validate@6.0.4) + prettier: 3.2.5 + ts-jest: 29.1.2(@babel/core@7.23.9)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(esbuild@0.24.2)(jest@29.7.0(@types/node@20.11.19)(ts-node@10.9.2(@types/node@20.11.19)(typescript@5.3.3)))(typescript@5.6.2) + typescript: 5.6.2 + transitivePeerDependencies: + - '@babel/core' + - '@jest/types' + - '@types/node' + - babel-jest + - babel-plugin-macros + - bufferutil + - canvas + - esbuild + - node-notifier + - supports-color + - ts-node + - utf-8-validate + '@rush-temp/text-editor-assets@file:projects/text-editor-assets.tgz(@babel/core@7.23.9)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(esbuild@0.24.2)(ts-node@10.9.2(@types/node@20.11.19)(typescript@5.3.3))': dependencies: '@types/jest': 29.5.12 @@ -25866,7 +25913,7 @@ snapshots: '@aws-crypto/crc32': 3.0.0 '@smithy/types': 3.0.0 '@smithy/util-hex-encoding': 3.0.0 - tslib: 2.6.2 + tslib: 2.7.0 '@smithy/eventstream-serde-browser@3.0.0': dependencies: @@ -26952,7 +26999,7 @@ snapshots: '@types/verror@1.10.10': optional: true - '@types/web-push@3.6.3': + '@types/web-push@3.6.4': dependencies: '@types/node': 20.11.19 @@ -29182,7 +29229,7 @@ snapshots: dot-case@3.0.4: dependencies: no-case: 3.0.4 - tslib: 2.6.2 + tslib: 2.7.0 dot-prop@6.0.1: dependencies: @@ -30656,6 +30703,12 @@ snapshots: has-unicode@2.0.1: {} + hash-base@3.1.0: + dependencies: + inherits: 2.0.4 + readable-stream: 3.6.2 + safe-buffer: 5.2.1 + hasown@2.0.1: dependencies: function-bind: 1.1.2 @@ -30849,13 +30902,6 @@ snapshots: transitivePeerDependencies: - supports-color - https-proxy-agent@7.0.4: - dependencies: - agent-base: 7.1.1 - debug: 4.3.5 - transitivePeerDependencies: - - supports-color - https-proxy-agent@7.0.5: dependencies: agent-base: 7.1.1 @@ -30956,12 +31002,12 @@ snapshots: interpret@3.1.1: {} - intl-messageformat@9.13.0: + intl-messageformat@10.7.14: dependencies: - '@formatjs/ecma402-abstract': 1.11.4 - '@formatjs/fast-memoize': 1.2.1 - '@formatjs/icu-messageformat-parser': 2.1.0 - tslib: 2.6.2 + '@formatjs/ecma402-abstract': 2.3.2 + '@formatjs/fast-memoize': 2.2.6 + '@formatjs/icu-messageformat-parser': 2.11.0 + tslib: 2.7.0 invert-kv@2.0.0: {} @@ -32189,6 +32235,12 @@ snapshots: escape-string-regexp: 4.0.0 optional: true + md5.js@1.3.5: + dependencies: + hash-base: 3.1.0 + inherits: 2.0.4 + safe-buffer: 5.2.1 + md5@2.3.0: dependencies: charenc: 0.0.2 @@ -32911,7 +32963,7 @@ snapshots: pascal-case@3.1.2: dependencies: no-case: 3.0.4 - tslib: 2.6.2 + tslib: 2.7.0 passport-custom@1.1.1: dependencies: @@ -35104,7 +35156,7 @@ snapshots: dependencies: asn1.js: 5.4.1 http_ece: 1.2.0 - https-proxy-agent: 7.0.4 + https-proxy-agent: 7.0.5 jws: 4.0.0 minimist: 1.2.8 transitivePeerDependencies: diff --git a/dev/base-image/print.Dockerfile b/dev/base-image/print.Dockerfile index d077652b13..95deef3851 100644 --- a/dev/base-image/print.Dockerfile +++ b/dev/base-image/print.Dockerfile @@ -1,5 +1,9 @@ FROM hardcoreeng/base +# Chromium hangs when usging LD_PRELOAD and MALLOC_CONF +ENV LD_PRELOAD= +ENV MALLOC_CONF= + # We don't need the standalone Chromium ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true # Set executable path for puppeteer diff --git a/dev/tool/src/index.ts b/dev/tool/src/index.ts index 97b17e971b..4095fac8cd 100644 --- a/dev/tool/src/index.ts +++ b/dev/tool/src/index.ts @@ -1197,12 +1197,14 @@ export function devTool ( .description('copy files from s3 to datalake') .option('-w, --workspace ', 'Selected workspace only', '') .option('-c, --concurrency ', 'Number of files being processed concurrently', '10') + .option('-s, --skip ', 'Number of workspaces to skip', '0') .option('-e, --existing', 'Copy existing blobs', false) - .action(async (cmd: { workspace: string, concurrency: string, existing: boolean }) => { + .action(async (cmd: { workspace: string, concurrency: string, existing: boolean, skip: string }) => { const params = { concurrency: parseInt(cmd.concurrency), existing: cmd.existing } + const skip = parseInt(cmd.skip) const storageConfig = storageConfigFromEnv(process.env.STORAGE) @@ -1245,6 +1247,11 @@ export function devTool ( let index = 0 for (const workspace of workspaces) { index++ + if (index <= skip) { + toolCtx.info('processing workspace', { workspace: workspace.workspace, index, count }) + continue + } + toolCtx.info('processing workspace', { workspace: workspace.workspace, index, diff --git a/dev/tool/src/storage.ts b/dev/tool/src/storage.ts index e4afd9bb51..9d550abdbc 100644 --- a/dev/tool/src/storage.ts +++ b/dev/tool/src/storage.ts @@ -23,6 +23,7 @@ import { RateLimiter } from '@hcengineering/core' import { type DatalakeClient } from '@hcengineering/datalake' +import { type UploadObjectParams } from '@hcengineering/datalake/types/client' import { DOMAIN_ATTACHMENT } from '@hcengineering/model-attachment' import { type S3Config, type S3Service } from '@hcengineering/s3' import { @@ -32,7 +33,7 @@ import { type UploadedObjectInfo } from '@hcengineering/server-core' import { type Db } from 'mongodb' -import { PassThrough } from 'stream' +import { PassThrough, type Readable } from 'stream' export interface MoveFilesParams { concurrency: number @@ -400,14 +401,11 @@ export async function copyBlobToDatalake ( type: stat.contentType, size: stat.size } + const readable = await adapter.get(ctx, workspaceId, objectName) try { - readable.on('end', () => { - readable.destroy() - }) console.log('uploading huge blob', objectName, Math.round(stat.size / 1024 / 1024), 'MB') - const stream = readable.pipe(new PassThrough()) - await datalake.uploadMultipart(ctx, workspaceId, objectName, stream, metadata) + await uploadMultipart(ctx, datalake, workspaceId, objectName, readable, metadata) console.log('done', objectName) } finally { readable.destroy() @@ -416,6 +414,51 @@ export async function copyBlobToDatalake ( } } +function uploadMultipart ( + ctx: MeasureContext, + datalake: DatalakeClient, + workspaceId: WorkspaceId, + objectName: string, + stream: Readable, + metadata: UploadObjectParams +): Promise { + return new Promise((resolve, reject) => { + const passthrough = new PassThrough() + + const cleanup = (): void => { + stream.removeAllListeners() + passthrough.removeAllListeners() + stream.destroy() + passthrough.destroy() + } + + stream.on('error', (err) => { + ctx.error('error reading blob', { err }) + cleanup() + reject(err) + }) + passthrough.on('error', (err) => { + ctx.error('error reading blob', { err }) + cleanup() + reject(err) + }) + + stream.pipe(passthrough) + + datalake + .uploadMultipart(ctx, workspaceId, objectName, passthrough, metadata) + .then(() => { + cleanup() + resolve() + }) + .catch((err) => { + ctx.error('failed to upload blob', { err }) + cleanup() + reject(err) + }) + }) +} + export function formatSize (size: number): string { const units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'] const pow = size === 0 ? 0 : Math.floor(Math.log(size) / Math.log(1024)) diff --git a/packages/core/src/utils.ts b/packages/core/src/utils.ts index 61289073fc..45e5a8b943 100644 --- a/packages/core/src/utils.ts +++ b/packages/core/src/utils.ts @@ -904,3 +904,18 @@ export class TimeRateLimiter { } } } + +export function combineAttributes ( + attributes: any[], + key: string, + operator: '$push' | '$pull', + arrayKey: '$each' | '$in' +): any[] { + return Array.from( + new Set( + attributes.flatMap((attr) => + Array.isArray(attr[operator]?.[key]?.[arrayKey]) ? attr[operator]?.[key]?.[arrayKey] : attr[operator]?.[key] + ) + ) + ).filter((v) => v != null) +} diff --git a/packages/platform/package.json b/packages/platform/package.json index 16dd58da9a..481b31dc5e 100644 --- a/packages/platform/package.json +++ b/packages/platform/package.json @@ -37,7 +37,7 @@ "typescript": "^5.3.3" }, "dependencies": { - "intl-messageformat": "^9.7.1" + "intl-messageformat": "^10.7.14" }, "repository": "https://github.com/hcengineering/platform", "publishConfig": { diff --git a/packages/presentation/src/components/PDFViewer.svelte b/packages/presentation/src/components/PDFViewer.svelte index fcfe753c57..450ae4ae0b 100644 --- a/packages/presentation/src/components/PDFViewer.svelte +++ b/packages/presentation/src/components/PDFViewer.svelte @@ -103,7 +103,7 @@ {#await srcRef then src} {#if !isLoading} - {#if src === ''} + {#if src === '' || src === undefined}
diff --git a/packages/text-core/.eslintrc.js b/packages/text-core/.eslintrc.js new file mode 100644 index 0000000000..72235dc283 --- /dev/null +++ b/packages/text-core/.eslintrc.js @@ -0,0 +1,7 @@ +module.exports = { + extends: ['./node_modules/@hcengineering/platform-rig/profiles/default/eslint.config.json'], + parserOptions: { + tsconfigRootDir: __dirname, + project: './tsconfig.json' + } +} diff --git a/packages/text-core/config/rig.json b/packages/text-core/config/rig.json new file mode 100644 index 0000000000..0110930f55 --- /dev/null +++ b/packages/text-core/config/rig.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json", + "rigPackageName": "@hcengineering/platform-rig" +} diff --git a/packages/text-core/jest.config.js b/packages/text-core/jest.config.js new file mode 100644 index 0000000000..2cfd408b67 --- /dev/null +++ b/packages/text-core/jest.config.js @@ -0,0 +1,7 @@ +module.exports = { + preset: 'ts-jest', + testEnvironment: 'node', + testMatch: ['**/?(*.)+(spec|test).[jt]s?(x)'], + roots: ["./src"], + coverageReporters: ["text-summary", "html"] +} diff --git a/packages/text-core/package.json b/packages/text-core/package.json new file mode 100644 index 0000000000..f35b981066 --- /dev/null +++ b/packages/text-core/package.json @@ -0,0 +1,49 @@ +{ + "name": "@hcengineering/text-core", + "version": "0.6.0", + "main": "lib/index.js", + "svelte": "src/index.ts", + "types": "types/index.d.ts", + "files": [ + "lib/**/*", + "types/**/*", + "tsconfig.json" + ], + "author": "Anticrm Platform Contributors", + "license": "EPL-2.0", + "scripts": { + "build": "compile", + "test": "jest --passWithNoTests --silent", + "build:watch": "compile", + "format": "format src", + "_phase:build": "compile transpile src", + "_phase:test": "jest --passWithNoTests --silent", + "_phase:format": "format src", + "_phase:validate": "compile validate" + }, + "devDependencies": { + "@hcengineering/platform-rig": "^0.6.0", + "@typescript-eslint/eslint-plugin": "^6.11.0", + "eslint-plugin-import": "^2.26.0", + "eslint-plugin-promise": "^6.1.1", + "eslint-plugin-n": "^15.4.0", + "eslint": "^8.54.0", + "@typescript-eslint/parser": "^6.11.0", + "eslint-config-standard-with-typescript": "^40.0.0", + "prettier": "^3.1.0", + "typescript": "^5.3.3", + "jest": "^29.7.0", + "ts-jest": "^29.1.1", + "@types/jest": "^29.5.5", + "@types/markdown-it": "~13.0.0", + "jest-environment-jsdom": "^29.7.0" + }, + "dependencies": { + "@hcengineering/core": "^0.6.32", + "fast-equals": "^5.0.1" + }, + "repository": "https://github.com/hcengineering/platform", + "publishConfig": { + "registry": "https://npm.pkg.github.com" + } +} diff --git a/packages/text-core/src/index.ts b/packages/text-core/src/index.ts new file mode 100644 index 0000000000..5e2540fdb2 --- /dev/null +++ b/packages/text-core/src/index.ts @@ -0,0 +1,20 @@ +// +// Copyright © 2023 Hardcore Engineering Inc. +// +// Licensed under the Eclipse Public License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. You may +// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// +// See the License for the specific language governing permissions and +// limitations under the License. +// + +export * from './markup/dsl' +export * from './markup/model' +export * from './markup/reference' +export * from './markup/traverse' +export * from './markup/utils' diff --git a/packages/text/src/markup/__tests__/traverse.test.ts b/packages/text-core/src/markup/__tests__/traverse.test.ts similarity index 100% rename from packages/text/src/markup/__tests__/traverse.test.ts rename to packages/text-core/src/markup/__tests__/traverse.test.ts diff --git a/packages/text/src/markup/dsl.ts b/packages/text-core/src/markup/dsl.ts similarity index 100% rename from packages/text/src/markup/dsl.ts rename to packages/text-core/src/markup/dsl.ts diff --git a/packages/text/src/markup/model.ts b/packages/text-core/src/markup/model.ts similarity index 100% rename from packages/text/src/markup/model.ts rename to packages/text-core/src/markup/model.ts diff --git a/packages/text/src/markup/reference.ts b/packages/text-core/src/markup/reference.ts similarity index 100% rename from packages/text/src/markup/reference.ts rename to packages/text-core/src/markup/reference.ts diff --git a/packages/text/src/markup/traverse.ts b/packages/text-core/src/markup/traverse.ts similarity index 100% rename from packages/text/src/markup/traverse.ts rename to packages/text-core/src/markup/traverse.ts diff --git a/packages/text-core/src/markup/utils.ts b/packages/text-core/src/markup/utils.ts new file mode 100644 index 0000000000..37d25af4ed --- /dev/null +++ b/packages/text-core/src/markup/utils.ts @@ -0,0 +1,402 @@ +// +// Copyright © 2024 Hardcore Engineering Inc. +// +// Licensed under the Eclipse Public License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. You may +// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import { Markup } from '@hcengineering/core' + +import { deepEqual } from 'fast-equals' +import { nodeDoc, nodeParagraph, nodeText } from './dsl' +import { MarkupMark, MarkupMarkType, MarkupNode, MarkupNodeType, emptyMarkupNode, type AttrValue } from './model' +import { traverseNode } from './traverse' + +/** @public */ +export const EmptyMarkup: Markup = jsonToMarkup(emptyMarkupNode()) + +/** @public */ +export function isEmptyMarkup (markup: Markup | undefined): boolean { + if (markup === undefined || markup === null || markup === '') { + return true + } + return isEmptyNode(markupToJSON(markup)) +} + +/** @public */ +export function areEqualMarkups (markup1: Markup, markup2: Markup): boolean { + if (markup1 === markup2) { + return true + } + + const node1 = markupToJSON(markup1) + const node2 = markupToJSON(markup2) + + if (isEmptyNode(node1) && isEmptyNode(node2)) { + return true + } + + return equalNodes(node1, node2) +} + +/** @public */ +export function areEqualJson (json1: MarkupNode, json2: MarkupNode): boolean { + return equalNodes(json1, json2) +} + +function equalNodes (node1: MarkupNode, node2: MarkupNode): boolean { + if (node1.type !== node2.type) return false + + const text1 = node1.text ?? '' + const text2 = node2.text ?? '' + if (text1 !== text2) return false + + if (!equalArrays(node1.content, node2.content, equalNodes)) return false + if (!equalArrays(node1.marks, node2.marks, equalMarks)) return false + if (!equalRecords(node1.attrs, node2.attrs)) return false + + return true +} + +function equalArrays (a: T[] | undefined, b: T[] | undefined, equal: (a: T, b: T) => boolean): boolean { + if (a === b) return true + const arr1 = a ?? [] + const arr2 = b ?? [] + if (arr1.length !== arr2.length) return false + return arr1.every((item1, i) => equal(item1, arr2[i])) +} + +function equalRecords (a: Record | undefined, b: Record | undefined): boolean { + if (a === b) return true + a = Object.fromEntries(Object.entries(a ?? {}).filter(([_, v]) => v != null)) + b = Object.fromEntries(Object.entries(b ?? {}).filter(([_, v]) => v != null)) + return deepEqual(a, b) +} + +export function equalMarks (a: MarkupMark, b: MarkupMark): boolean { + return a.type === b.type && equalRecords(a.attrs, b.attrs) +} + +const emptyNodes = [MarkupNodeType.hard_break] + +const nonEmptyNodes = [ + MarkupNodeType.horizontal_rule, + MarkupNodeType.image, + MarkupNodeType.reference, + MarkupNodeType.subLink, + MarkupNodeType.table +] + +/** @public */ +export function isEmptyNode (node: MarkupNode): boolean { + if (emptyNodes.includes(node.type)) return true + if (nonEmptyNodes.includes(node.type)) return false + if (node.text !== undefined && node.text?.trim().length > 0) return false + + const content = node.content ?? [] + return content.every(isEmptyNode) +} + +// Markup + +/** @public */ +export function jsonToMarkup (json: MarkupNode): Markup { + return JSON.stringify(json) +} + +/** @public */ +export function markupToJSON (markup: Markup): MarkupNode { + if (markup == null || markup === '') { + return emptyMarkupNode() + } + + try { + // Ideally Markup should contain only serialized JSON + // But there seem to be some cases when it contains HTML or plain text + // So we need to handle those cases and produce valid MarkupNode + if (markup.startsWith('{')) { + return JSON.parse(markup) as MarkupNode + } else { + return nodeDoc(nodeParagraph(nodeText(markup))) + } + } catch (error) { + return emptyMarkupNode() + } +} + +// UTILS + +const ELLIPSIS_CHAR = '…' +const WHITESPACE = ' ' + +/** @public */ +export function stripTags (markup: Markup, textLimit = 0): string { + const parsed = markupToJSON(markup) + + const textParts: string[] = [] + let charCount = 0 + let isHardStop = false + + const pushText = (text: string): void => { + if (textLimit > 0 && charCount + text.length > textLimit) { + const toAddCount = textLimit - charCount + const textPart = text.substring(0, toAddCount) + textParts.push(textPart) + textParts.push(ELLIPSIS_CHAR) + isHardStop = true + } else { + textParts.push(text) + charCount += text.length + } + } + + traverseNode(parsed, (node, parent): boolean => { + if (isHardStop) { + return false + } + + if (node.type === MarkupNodeType.text) { + const text = node.text ?? '' + pushText(text) + return false + } else if ( + node.type === MarkupNodeType.paragraph || + node.type === MarkupNodeType.table || + node.type === MarkupNodeType.doc || + node.type === MarkupNodeType.blockquote + ) { + if (textParts.length > 0 && textParts[textParts.length - 1] !== WHITESPACE) { + textParts.push(WHITESPACE) + charCount++ + } + } else if (node.type === MarkupNodeType.reference) { + const label = `${node.attrs?.label ?? ''}` + pushText(label.length > 0 ? `@${label}` : '') + } + return true + }) + + const result = textParts.join('') + return result +} + +class NodeBuilder { + textParts: string[] = [] + + constructor (private readonly addTags: boolean) {} + + addText (text: string): void { + this.textParts.push(text) + } + + addTag (text: string, newLine: boolean = false): void { + if (this.addTags) { + this.textParts.push(text) + } + if (!this.addTags && newLine) { + this.textParts.push('\n') + } + } + + toText (): string { + return this.textParts.join('') + } +} + +function addMark (builder: NodeBuilder, mark?: MarkupMark, next?: () => void): void { + if (mark != null) { + const attrs = mark.attrs ?? {} + + if (mark.type === MarkupMarkType.bold) { + builder.addTag('') + next?.() + builder.addTag('') + } else if (mark.type === MarkupMarkType.code) { + builder.addTag('') + next?.() + builder.addTag('') + } else if (mark.type === MarkupMarkType.em) { + builder.addTag('') + next?.() + builder.addTag('') + } else if (mark.type === MarkupMarkType.link) { + builder.addTag(``) + next?.() + builder.addTag('') + } else if (mark.type === MarkupMarkType.strike) { + builder.addTag('') + next?.() + builder.addTag('') + } else if (mark.type === MarkupMarkType.underline) { + builder.addTag('') + next?.() + builder.addTag('') + } else { + builder.addTag(`unknown mark: "${mark.type as string}"`, false) + next?.() + } + } +} + +function addMarks (builder: NodeBuilder, marks: MarkupMark[], next?: () => void): void { + if (marks.length > 0) { + const mark = marks[0] + const others = marks.slice(1) + + if (others.length > 0) { + addMark(builder, mark, () => { + addMarks(builder, others, next) + }) + } + } +} + +function addNodeContent (builder: NodeBuilder, node?: MarkupNode): void { + if (node == null) return + + const attrs = node.attrs ?? {} + const nodes = node.content ?? [] + + if (node.type === MarkupNodeType.doc) { + nodes.forEach((childNode) => { + addNode(builder, childNode) + }) + } else if (node.type === MarkupNodeType.text) { + builder.addText(node.text ?? '') + } else if (node.type === MarkupNodeType.paragraph) { + builder.addTag('

') + nodes.forEach((childNode) => { + addNode(builder, childNode) + }) + builder.addTag('

') + } else if (node.type === MarkupNodeType.blockquote) { + builder.addTag('
') + nodes.forEach((childNode) => { + addNode(builder, childNode) + }) + builder.addTag('
') + } else if (node.type === MarkupNodeType.horizontal_rule) { + builder.addTag('
') + } else if (node.type === MarkupNodeType.heading) { + const level = toNumber(node.attrs?.level) ?? 1 + builder.addTag(``) + nodes.forEach((childNode) => { + addNode(builder, childNode) + }) + builder.addTag(``) + } else if (node.type === MarkupNodeType.code_block) { + builder.addTag('
')
+    nodes.forEach((childNode) => {
+      addNode(builder, childNode)
+    })
+    builder.addTag('
') + } else if (node.type === MarkupNodeType.image) { + const src = toString(attrs.src) + const alt = toString(attrs.alt) + builder.addText(`${alt}`) + } else if (node.type === MarkupNodeType.reference) { + const label = toString(attrs.label) + builder.addText(label !== undefined ? `@${label}` : '') + } else if (node.type === MarkupNodeType.hard_break) { + builder.addTag('
') + } else if (node.type === MarkupNodeType.ordered_list) { + builder.addTag('
    ') + nodes.forEach((childNode) => { + addNode(builder, childNode) + }) + builder.addTag('
') + } else if (node.type === MarkupNodeType.bullet_list) { + builder.addTag('
    ') + nodes.forEach((childNode) => { + addNode(builder, childNode) + }) + builder.addTag('
') + } else if (node.type === MarkupNodeType.list_item) { + builder.addTag('
  • ') + nodes.forEach((childNode) => { + addNode(builder, childNode) + }) + builder.addTag('
  • ') + } else if (node.type === MarkupNodeType.subLink) { + builder.addTag('') + nodes.forEach((childNode) => { + addNode(builder, childNode) + }) + builder.addTag('') + } else if (node.type === MarkupNodeType.table) { + builder.addTag('') + nodes.forEach((childNode) => { + addNode(builder, childNode) + }) + builder.addTag('
    ') + } else if (node.type === MarkupNodeType.table_row) { + builder.addTag('') + nodes.forEach((childNode) => { + addNode(builder, childNode) + }) + builder.addTag('') + } else if (node.type === MarkupNodeType.table_cell) { + builder.addTag('') + nodes.forEach((childNode) => { + addNode(builder, childNode) + }) + builder.addTag('') + } else if (node.type === MarkupNodeType.table_header) { + builder.addTag('') + nodes.forEach((childNode) => { + addNode(builder, childNode) + }) + builder.addTag('') + } else { + builder.addText(`unknown node: "${node.type}"`) + nodes.forEach((childNode) => { + addNode(builder, childNode) + }) + } +} + +function addNode (builder: NodeBuilder, node: MarkupNode): void { + const marks = node.marks ?? [] + + if (marks.length > 0) { + addMarks(builder, marks, () => { + addNodeContent(builder, node) + }) + } else { + addNodeContent(builder, node) + } +} + +function toString (value: AttrValue | undefined): string | undefined { + return value !== undefined ? `${value}` : undefined +} + +function toNumber (value: AttrValue | undefined): number | undefined { + if (typeof value === 'boolean') { + return value ? 1 : 0 + } + + return value !== undefined ? (typeof value === 'string' ? parseInt(value) : value) : undefined +} + +export function markupToHTML (markup: Markup): string { + const jsonModel = markupToJSON(markup) + const builder = new NodeBuilder(true) + addNode(builder, jsonModel) + return builder.toText() +} + +export function markupToText (markup: Markup): string { + const jsonModel = markupToJSON(markup) + const builder = new NodeBuilder(false) + addNode(builder, jsonModel) + return builder.toText() +} diff --git a/packages/text-core/tsconfig.json b/packages/text-core/tsconfig.json new file mode 100644 index 0000000000..59e4fd4297 --- /dev/null +++ b/packages/text-core/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "./node_modules/@hcengineering/platform-rig/profiles/default/tsconfig.json", + + "compilerOptions": { + "rootDir": "./src", + "outDir": "./lib", + "declarationDir": "./types", + "tsBuildInfoFile": ".build/build.tsbuildinfo" + } +} \ No newline at end of file diff --git a/packages/text/package.json b/packages/text/package.json index 0147c859eb..1052dffa53 100644 --- a/packages/text/package.json +++ b/packages/text/package.json @@ -40,6 +40,7 @@ }, "dependencies": { "@hcengineering/core": "^0.6.32", + "@hcengineering/text-core": "^0.6.0", "@tiptap/core": "^2.6.6", "@tiptap/html": "^2.6.6", "@tiptap/pm": "^2.6.6", diff --git a/packages/text/src/index.ts b/packages/text/src/index.ts index b3601a4b99..00756c4f12 100644 --- a/packages/text/src/index.ts +++ b/packages/text/src/index.ts @@ -14,13 +14,9 @@ // export * from './extensions' -export * from './markup/dsl' -export * from './markup/model' -export * from './markup/reference' -export * from './markup/traverse' -export * from './markup/utils' +export * from '@hcengineering/text-core' export * from './nodes' -// export * from './ydoc' +export * from './markup/utils' export * from './marks/code' export * from './marks/colors' export * from './marks/noteBase' diff --git a/packages/text/src/markdown/index.ts b/packages/text/src/markdown/index.ts index 8a6b2c053c..37fcca8bbd 100644 --- a/packages/text/src/markdown/index.ts +++ b/packages/text/src/markdown/index.ts @@ -1,9 +1,8 @@ +import { MarkupNode, markupToJSON } from '@hcengineering/text-core' import { Extensions } from '@tiptap/core' import { defaultExtensions } from '../extensions' import { MarkdownParser } from './parser' import { MarkdownState, storeMarks, storeNodes } from './serializer' -import { MarkupNode } from '../markup/model' -import { markupToJSON } from '../markup/utils' /** * @public diff --git a/packages/text/src/markdown/marks.ts b/packages/text/src/markdown/marks.ts index e0577ed6e1..4d7535f76b 100644 --- a/packages/text/src/markdown/marks.ts +++ b/packages/text/src/markdown/marks.ts @@ -1,5 +1,5 @@ import { deepEqual } from 'fast-equals' -import { MarkupMark, MarkupMarkType, MarkupNode } from '../markup/model' +import { MarkupMark, MarkupMarkType, MarkupNode } from '@hcengineering/text-core' export function traverseMarks (node: MarkupNode, f: (el: MarkupMark) => void): void { node.marks?.forEach(f) diff --git a/packages/text/src/markdown/node.ts b/packages/text/src/markdown/node.ts index 0c3b5131ac..3efe06c967 100644 --- a/packages/text/src/markdown/node.ts +++ b/packages/text/src/markdown/node.ts @@ -1,4 +1,4 @@ -import { Attrs, MarkupNode } from '../markup/model' +import { Attrs, MarkupNode } from '@hcengineering/text-core' export function traverseMarkupNode (node: MarkupNode, f: (el: MarkupNode) => void): void { f(node) diff --git a/packages/text/src/markdown/parser.ts b/packages/text/src/markdown/parser.ts index 2e187e61e1..e517a82d7d 100644 --- a/packages/text/src/markdown/parser.ts +++ b/packages/text/src/markdown/parser.ts @@ -3,10 +3,10 @@ import MarkdownIt, { type Token } from 'markdown-it' import type { RuleCore } from 'markdown-it/lib/parser_core' import type StateCore from 'markdown-it/lib/rules_core/state_core' +import { Attrs, AttrValue, MarkupMark, MarkupMarkType, MarkupNode, MarkupNodeType } from '@hcengineering/text-core' +import { htmlToJSON } from '../markup/utils' import { addToSet, removeFromSet, sameSet } from './marks' import { messageContent } from './node' -import { Attrs, AttrValue, MarkupMark, MarkupMarkType, MarkupNode, MarkupNodeType } from '../markup/model' -import { htmlToJSON } from '../markup/utils' interface ParsingBlockRule { block: MarkupNodeType diff --git a/packages/text/src/markdown/serializer.ts b/packages/text/src/markdown/serializer.ts index f3d8fa58fc..b3c7b9695c 100644 --- a/packages/text/src/markdown/serializer.ts +++ b/packages/text/src/markdown/serializer.ts @@ -1,8 +1,8 @@ +import { MarkupMark, MarkupNode, MarkupNodeType } from '@hcengineering/text-core' import { generateHTML } from '@tiptap/html' +import { defaultExtensions } from '../extensions' import { isInSet, markEq } from './marks' import { messageContent, nodeAttrs } from './node' -import { MarkupMark, MarkupNode, MarkupNodeType } from '../markup/model' -import { defaultExtensions } from '../extensions' type FirstDelim = (i: number, attrs?: Record, parentAttrs?: Record) => string interface IState { diff --git a/packages/text/src/markup/__tests__/dsl.test.ts b/packages/text/src/markup/__tests__/dsl.test.ts index e4b63d595c..2458a48b36 100644 --- a/packages/text/src/markup/__tests__/dsl.test.ts +++ b/packages/text/src/markup/__tests__/dsl.test.ts @@ -1,5 +1,13 @@ -import { nodeDoc, nodeImage, nodeParagraph, nodeReference, nodeText, markLink, markUnderline } from '../dsl' -import { MarkupNodeType } from '../model' +import { + markLink, + markUnderline, + MarkupNodeType, + nodeDoc, + nodeImage, + nodeParagraph, + nodeReference, + nodeText +} from '@hcengineering/text-core' import { jsonToHTML } from '../utils' describe('dsl', () => { diff --git a/packages/text/src/markup/__tests__/utils.test.ts b/packages/text/src/markup/__tests__/utils.test.ts index fe9ee6f9e5..e115620b39 100644 --- a/packages/text/src/markup/__tests__/utils.test.ts +++ b/packages/text/src/markup/__tests__/utils.test.ts @@ -17,28 +17,34 @@ // limitations under the License. // -import { Editor, getSchema } from '@tiptap/core' -import { MarkupMarkType, MarkupNode, MarkupNodeType } from '../model' import { areEqualMarkups, + isEmptyMarkup, + isEmptyNode, + jsonToMarkup, + MarkupMarkType, + MarkupNode, + MarkupNodeType, + markupToJSON, + nodeDoc, + nodeParagraph, + nodeText, + markupToHTML +} from '@hcengineering/text-core' +import { Editor, getSchema } from '@tiptap/core' +import { ServerKit } from '../../kits/server-kit' +import { getMarkup, htmlToJSON, htmlToMarkup, htmlToPmNode, - isEmptyMarkup, - isEmptyNode, jsonToHTML, - jsonToMarkup, jsonToText, - markupToHTML, - markupToJSON, markupToPmNode, pmNodeToHTML, pmNodeToJSON, pmNodeToMarkup } from '../utils' -import { ServerKit } from '../../kits/server-kit' -import { nodeDoc, nodeParagraph, nodeText } from '../dsl' // mock tiptap functions jest.mock('@tiptap/html', () => ({ diff --git a/packages/text/src/markup/utils.ts b/packages/text/src/markup/utils.ts index 016a4c64ee..e8e93cb773 100644 --- a/packages/text/src/markup/utils.ts +++ b/packages/text/src/markup/utils.ts @@ -18,13 +18,18 @@ import { Editor, Extensions, getSchema } from '@tiptap/core' import { generateHTML, generateJSON } from '@tiptap/html' import { Node as ProseMirrorNode, Schema } from '@tiptap/pm/model' -import { deepEqual } from 'fast-equals' +import { + MarkupNode, + emptyMarkupNode, + jsonToMarkup, + markupToJSON, + nodeDoc, + nodeParagraph, + nodeText +} from '@hcengineering/text-core' import { defaultExtensions } from '../extensions' -import { nodeDoc, nodeParagraph, nodeText } from './dsl' -import { MarkupMark, MarkupNode, MarkupNodeType, emptyMarkupNode } from './model' /** @public */ -export const EmptyMarkup: Markup = jsonToMarkup(emptyMarkupNode()) const defaultSchema = getSchema(defaultExtensions) /** @public */ @@ -32,88 +37,6 @@ export function getMarkup (editor?: Editor): Markup { return jsonToMarkup(editor?.getJSON() as MarkupNode) } -/** @public */ -export function isEmptyMarkup (markup: Markup | undefined): boolean { - if (markup === undefined || markup === null || markup === '') { - return true - } - return isEmptyNode(markupToJSON(markup)) -} - -/** @public */ -export function areEqualMarkups (markup1: Markup, markup2: Markup): boolean { - if (markup1 === markup2) { - return true - } - - const node1 = markupToJSON(markup1) - const node2 = markupToJSON(markup2) - - if (isEmptyNode(node1) && isEmptyNode(node2)) { - return true - } - - return equalNodes(node1, node2) -} - -/** @public */ -export function areEqualJson (json1: MarkupNode, json2: MarkupNode): boolean { - return equalNodes(json1, json2) -} - -function equalNodes (node1: MarkupNode, node2: MarkupNode): boolean { - if (node1.type !== node2.type) return false - - const text1 = node1.text ?? '' - const text2 = node2.text ?? '' - if (text1 !== text2) return false - - if (!equalArrays(node1.content, node2.content, equalNodes)) return false - if (!equalArrays(node1.marks, node2.marks, equalMarks)) return false - if (!equalRecords(node1.attrs, node2.attrs)) return false - - return true -} - -function equalArrays (a: T[] | undefined, b: T[] | undefined, equal: (a: T, b: T) => boolean): boolean { - if (a === b) return true - const arr1 = a ?? [] - const arr2 = b ?? [] - if (arr1.length !== arr2.length) return false - return arr1.every((item1, i) => equal(item1, arr2[i])) -} - -function equalRecords (a: Record | undefined, b: Record | undefined): boolean { - if (a === b) return true - a = Object.fromEntries(Object.entries(a ?? {}).filter(([_, v]) => v != null)) - b = Object.fromEntries(Object.entries(b ?? {}).filter(([_, v]) => v != null)) - return deepEqual(a, b) -} - -function equalMarks (a: MarkupMark, b: MarkupMark): boolean { - return a.type === b.type && equalRecords(a.attrs, b.attrs) -} - -const emptyNodes = [MarkupNodeType.hard_break] - -const nonEmptyNodes = [ - MarkupNodeType.horizontal_rule, - MarkupNodeType.image, - MarkupNodeType.reference, - MarkupNodeType.subLink, - MarkupNodeType.table -] - -/** @public */ -export function isEmptyNode (node: MarkupNode): boolean { - if (emptyNodes.includes(node.type)) return true - if (nonEmptyNodes.includes(node.type)) return false - if (node.text !== undefined && node.text?.trim().length > 0) return false - - const content = node.content ?? [] - return content.every(isEmptyNode) -} - // Markup /** @public */ @@ -127,15 +50,8 @@ export function markupToPmNode (markup: Markup, schema?: Schema, extensions?: Ex return jsonToPmNode(json, schema, extensions) } -// JSON - /** @public */ -export function jsonToMarkup (json: MarkupNode): Markup { - return JSON.stringify(json) -} - -/** @public */ -export function markupToJSON (markup: Markup): MarkupNode { +export function markupHtmlToJSON (markup: Markup): MarkupNode { if (markup == null || markup === '') { return emptyMarkupNode() } @@ -178,10 +94,10 @@ export function pmNodeToText (node: ProseMirrorNode): string { return jsonToText(node.toJSON()) } -export function markupToText (markup: Markup, schema?: Schema, extensions?: Extensions): string { - const pmNode = markupToPmNode(markup, schema, extensions) - return pmNode.textBetween(0, pmNode.content.size, '\n', '') -} +// export function markupToText (markup: Markup, schema?: Schema, extensions?: Extensions): string { +// const pmNode = markupToPmNode(markup, schema, extensions) +// return pmNode.textBetween(0, pmNode.content.size, '\n', '') +// } // HTML @@ -191,11 +107,11 @@ export function htmlToMarkup (html: string, extensions?: Extensions): Markup { return jsonToMarkup(json) } -/** @public */ -export function markupToHTML (markup: Markup, extensions?: Extensions): string { - const json = markupToJSON(markup) - return jsonToHTML(json, extensions) -} +// /** @public */ +// export function markupToHTML (markup: Markup, extensions?: Extensions): string { +// const json = markupToJSON(markup) +// return jsonToHTML(json, extensions) +// } /** @public */ export function htmlToJSON (html: string, extensions?: Extensions): MarkupNode { @@ -221,55 +137,3 @@ export function pmNodeToHTML (node: ProseMirrorNode, extensions?: Extensions): s extensions ??= defaultExtensions return generateHTML(node.toJSON(), extensions) } - -// UTILS - -const ELLIPSIS_CHAR = '…' -const WHITESPACE = ' ' - -/** @public */ -export function stripTags (markup: Markup, textLimit = 0, extensions: Extensions | undefined = undefined): string { - const schema = extensions === undefined ? defaultSchema : getSchema(extensions) - const parsed = markupToPmNode(markup, schema) - - const textParts: string[] = [] - let charCount = 0 - let isHardStop = false - - const pushText = (text: string): void => { - if (textLimit > 0 && charCount + text.length > textLimit) { - const toAddCount = textLimit - charCount - const textPart = text.substring(0, toAddCount) - textParts.push(textPart) - textParts.push(ELLIPSIS_CHAR) - isHardStop = true - } else { - textParts.push(text) - charCount += text.length - } - } - - parsed.descendants((node, _pos, parent): boolean => { - if (isHardStop) { - return false - } - - if (node.type.isText) { - const text = node.text ?? '' - pushText(text) - return false - } else if (node.type.isBlock) { - if (textParts.length > 0 && textParts[textParts.length - 1] !== WHITESPACE) { - textParts.push(WHITESPACE) - charCount++ - } - } else if (node.type.name === 'reference') { - const label = node.attrs.label ?? '' - pushText(label.length > 0 ? `@${label}` : '') - } - return true - }) - - const result = textParts.join('') - return result -} diff --git a/plugins/contact-resources/package.json b/plugins/contact-resources/package.json index 1a512f0d18..76cde76241 100644 --- a/plugins/contact-resources/package.json +++ b/plugins/contact-resources/package.json @@ -35,7 +35,8 @@ "jest": "^29.7.0", "ts-jest": "^29.1.1", "@types/jest": "^29.5.5", - "svelte-eslint-parser": "^0.33.1" + "svelte-eslint-parser": "^0.33.1", + "@types/crypto-js": "^4.2.2" }, "dependencies": { "@hcengineering/activity": "^0.6.0", @@ -60,6 +61,7 @@ "@hcengineering/view": "^0.6.13", "@hcengineering/view-resources": "^0.6.0", "@hcengineering/workbench": "^0.6.16", - "svelte": "^4.2.19" + "svelte": "^4.2.19", + "crypto-js": "^4.2.0" } } diff --git a/plugins/contact-resources/src/components/SelectAvatarPopup.svelte b/plugins/contact-resources/src/components/SelectAvatarPopup.svelte index cbd6dec1a4..6c86063c76 100644 --- a/plugins/contact-resources/src/components/SelectAvatarPopup.svelte +++ b/plugins/contact-resources/src/components/SelectAvatarPopup.svelte @@ -15,7 +15,9 @@