From 81ac18ee8bc71b2ac4f0ec7e58c2ba882399f01e Mon Sep 17 00:00:00 2001 From: Victor Ilyushchenko Date: Fri, 6 Dec 2024 16:23:48 +0300 Subject: [PATCH 1/3] UBERF-8614: Mermaidjs integration (#7272) Signed-off-by: Victor Ilyushchenko --- common/config/rush/pnpm-lock.yaml | 812 +++++++++++++++++- packages/theme/styles/prose.scss | 95 +- plugins/text-editor-assets/lang/en.json | 7 +- plugins/text-editor-assets/lang/ru.json | 7 +- plugins/text-editor-resources/package.json | 4 +- .../components/CollaborativeTextEditor.svelte | 8 +- .../src/components/extension/mermaid.ts | 711 +++++++++++++++ .../src/components/extensions.ts | 3 +- plugins/text-editor/src/plugin.ts | 3 +- 9 files changed, 1630 insertions(+), 20 deletions(-) create mode 100644 plugins/text-editor-resources/src/components/extension/mermaid.ts diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index bd4147298b..90e48e8d78 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -1954,6 +1954,17 @@ packages: '@jridgewell/trace-mapping': 0.3.22 dev: false + /@antfu/install-pkg@0.4.1: + resolution: {integrity: sha512-T7yB5QNG29afhWVkVq7XeIMBa5U/vs9mX69YqayXypPRmYzUmzwnYltplHmPtZ4HPCn+sQKeXW8I47wCbuBOjw==} + dependencies: + package-manager-detector: 0.2.6 + tinyexec: 0.3.1 + dev: false + + /@antfu/utils@0.7.10: + resolution: {integrity: sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==} + dev: false + /@anticrm/skillset@0.6.0: resolution: {integrity: sha512-k5/57q9ie73oCFKAxZrKy/BSnakiaVZsJmfjzmqhoko+3dZq2M2o/h1r+RSZrQ6re51iMqFdsVZAtfdPL15hjA==} dev: false @@ -2990,10 +3001,41 @@ packages: resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} dev: false + /@braintree/sanitize-url@7.1.0: + resolution: {integrity: sha512-o+UlMLt49RvtCASlOMW0AkHnabN9wR9rwCCherxO0yG4Npy34GkvrAqdXQvrhNs+jh+gkK8gB8Lf05qL/O7KWg==} + dev: false + /@bufbuild/protobuf@1.10.0: resolution: {integrity: sha512-QDdVFLoN93Zjg36NoQPZfsVH9tZew7wKDKyV5qRdj8ntT4wQCOradQjRaTdwMhWUYsgKsvCINKKm87FdEk96Ag==} dev: false + /@chevrotain/cst-dts-gen@11.0.3: + resolution: {integrity: sha512-BvIKpRLeS/8UbfxXxgC33xOumsacaeCKAjAeLyOn7Pcp95HiRbrpl14S+9vaZLolnbssPIUuiUd8IvgkRyt6NQ==} + dependencies: + '@chevrotain/gast': 11.0.3 + '@chevrotain/types': 11.0.3 + lodash-es: 4.17.21 + dev: false + + /@chevrotain/gast@11.0.3: + resolution: {integrity: sha512-+qNfcoNk70PyS/uxmj3li5NiECO+2YKZZQMbmjTqRI3Qchu8Hig/Q9vgkHpI3alNjr7M+a2St5pw5w5F6NL5/Q==} + dependencies: + '@chevrotain/types': 11.0.3 + lodash-es: 4.17.21 + dev: false + + /@chevrotain/regexp-to-ast@11.0.3: + resolution: {integrity: sha512-1fMHaBZxLFvWI067AVbGJav1eRY7N8DDvYCTwGBiE/ytKBgP8azTdgyrKyWZ9Mfh09eHWb5PgTSO8wi7U824RA==} + dev: false + + /@chevrotain/types@11.0.3: + resolution: {integrity: sha512-gsiM3G8b58kZC2HaWR50gu6Y1440cHiJ+i3JUvcp/35JchYejb2+5MVeJK0iKThYpAa/P2PYFV4hoi44HD+aHQ==} + dev: false + + /@chevrotain/utils@11.0.3: + resolution: {integrity: sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ==} + dev: false + /@cloudflare/kv-asset-handler@0.3.4: resolution: {integrity: sha512-YLPHc8yASwjNkmcDMQMY35yiWjoKAKnhUbPRszBRS0YgH+IXtsMp61j+yTcnCE3oO2DgP0U3iejLC8FTtKDC8Q==} engines: {node: '>=16.13'} @@ -4018,6 +4060,24 @@ packages: resolution: {integrity: sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==} dev: false + /@iconify/types@2.0.0: + resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} + dev: false + + /@iconify/utils@2.1.33: + resolution: {integrity: sha512-jP9h6v/g0BIZx0p7XGJJVtkVnydtbgTgt9mVNcGDYwaa7UhdHdI9dvoq+gKj9sijMSJKxUPEG2JyjsgXjxL7Kw==} + dependencies: + '@antfu/install-pkg': 0.4.1 + '@antfu/utils': 0.7.10 + '@iconify/types': 2.0.0 + debug: 4.3.7 + kolorist: 1.8.0 + local-pkg: 0.5.1 + mlly: 1.7.3 + transitivePeerDependencies: + - supports-color + dev: false + /@isaacs/cliui@8.0.2: resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} @@ -4759,6 +4819,12 @@ packages: resolution: {integrity: sha512-/gFguyJm1ng4Qr7VVH2vKO+zZcQd8wc3YafUfvBuYFX0Y5+CvrV+VNPEVkl5W/gUZF5KNKNZAiaHPULGPCIjyQ==} dev: false + /@mermaid-js/parser@0.3.0: + resolution: {integrity: sha512-HsvL6zgE5sUPGgkIDlmAWR1HTNHz2Iy11BAWPTa4Jjabkpguy4Ze2gzfLrg6pdRuBvFwgUYyxiaNqZwrEEXepA==} + dependencies: + langium: 3.0.0 + dev: false + /@mongodb-js/saslprep@1.1.4: resolution: {integrity: sha512-8zJ8N1x51xo9hwPh6AWnKdLGEC5N3lDa6kms1YHmFBoRhTpJR6HG8wWk0td1MVCu9cD4YBrvjZEtd5Obw0Fbnw==} dependencies: @@ -6406,6 +6472,185 @@ packages: csvtojson: 2.0.10 dev: false + /@types/d3-array@3.2.1: + resolution: {integrity: sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==} + dev: false + + /@types/d3-axis@3.0.6: + resolution: {integrity: sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==} + dependencies: + '@types/d3-selection': 3.0.11 + dev: false + + /@types/d3-brush@3.0.6: + resolution: {integrity: sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==} + dependencies: + '@types/d3-selection': 3.0.11 + dev: false + + /@types/d3-chord@3.0.6: + resolution: {integrity: sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==} + dev: false + + /@types/d3-color@3.1.3: + resolution: {integrity: sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==} + dev: false + + /@types/d3-contour@3.0.6: + resolution: {integrity: sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==} + dependencies: + '@types/d3-array': 3.2.1 + '@types/geojson': 7946.0.14 + dev: false + + /@types/d3-delaunay@6.0.4: + resolution: {integrity: sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==} + dev: false + + /@types/d3-dispatch@3.0.6: + resolution: {integrity: sha512-4fvZhzMeeuBJYZXRXrRIQnvUYfyXwYmLsdiN7XXmVNQKKw1cM8a5WdID0g1hVFZDqT9ZqZEY5pD44p24VS7iZQ==} + dev: false + + /@types/d3-drag@3.0.7: + resolution: {integrity: sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==} + dependencies: + '@types/d3-selection': 3.0.11 + dev: false + + /@types/d3-dsv@3.0.7: + resolution: {integrity: sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==} + dev: false + + /@types/d3-ease@3.0.2: + resolution: {integrity: sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==} + dev: false + + /@types/d3-fetch@3.0.7: + resolution: {integrity: sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==} + dependencies: + '@types/d3-dsv': 3.0.7 + dev: false + + /@types/d3-force@3.0.10: + resolution: {integrity: sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==} + dev: false + + /@types/d3-format@3.0.4: + resolution: {integrity: sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==} + dev: false + + /@types/d3-geo@3.1.0: + resolution: {integrity: sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==} + dependencies: + '@types/geojson': 7946.0.14 + dev: false + + /@types/d3-hierarchy@3.1.7: + resolution: {integrity: sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==} + dev: false + + /@types/d3-interpolate@3.0.4: + resolution: {integrity: sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==} + dependencies: + '@types/d3-color': 3.1.3 + dev: false + + /@types/d3-path@3.1.0: + resolution: {integrity: sha512-P2dlU/q51fkOc/Gfl3Ul9kicV7l+ra934qBFXCFhrZMOL6du1TM0pm1ThYvENukyOn5h9v+yMJ9Fn5JK4QozrQ==} + dev: false + + /@types/d3-polygon@3.0.2: + resolution: {integrity: sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==} + dev: false + + /@types/d3-quadtree@3.0.6: + resolution: {integrity: sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==} + dev: false + + /@types/d3-random@3.0.3: + resolution: {integrity: sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ==} + dev: false + + /@types/d3-scale-chromatic@3.1.0: + resolution: {integrity: sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==} + dev: false + + /@types/d3-scale@4.0.8: + resolution: {integrity: sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ==} + dependencies: + '@types/d3-time': 3.0.4 + dev: false + + /@types/d3-selection@3.0.11: + resolution: {integrity: sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==} + dev: false + + /@types/d3-shape@3.1.6: + resolution: {integrity: sha512-5KKk5aKGu2I+O6SONMYSNflgiP0WfZIQvVUMan50wHsLG1G94JlxEVnCpQARfTtzytuY0p/9PXXZb3I7giofIA==} + dependencies: + '@types/d3-path': 3.1.0 + dev: false + + /@types/d3-time-format@4.0.3: + resolution: {integrity: sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==} + dev: false + + /@types/d3-time@3.0.4: + resolution: {integrity: sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==} + dev: false + + /@types/d3-timer@3.0.2: + resolution: {integrity: sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==} + dev: false + + /@types/d3-transition@3.0.9: + resolution: {integrity: sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==} + dependencies: + '@types/d3-selection': 3.0.11 + dev: false + + /@types/d3-zoom@3.0.8: + resolution: {integrity: sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==} + dependencies: + '@types/d3-interpolate': 3.0.4 + '@types/d3-selection': 3.0.11 + dev: false + + /@types/d3@7.4.3: + resolution: {integrity: sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==} + dependencies: + '@types/d3-array': 3.2.1 + '@types/d3-axis': 3.0.6 + '@types/d3-brush': 3.0.6 + '@types/d3-chord': 3.0.6 + '@types/d3-color': 3.1.3 + '@types/d3-contour': 3.0.6 + '@types/d3-delaunay': 6.0.4 + '@types/d3-dispatch': 3.0.6 + '@types/d3-drag': 3.0.7 + '@types/d3-dsv': 3.0.7 + '@types/d3-ease': 3.0.2 + '@types/d3-fetch': 3.0.7 + '@types/d3-force': 3.0.10 + '@types/d3-format': 3.0.4 + '@types/d3-geo': 3.1.0 + '@types/d3-hierarchy': 3.1.7 + '@types/d3-interpolate': 3.0.4 + '@types/d3-path': 3.1.0 + '@types/d3-polygon': 3.0.2 + '@types/d3-quadtree': 3.0.6 + '@types/d3-random': 3.0.3 + '@types/d3-scale': 4.0.8 + '@types/d3-scale-chromatic': 3.1.0 + '@types/d3-selection': 3.0.11 + '@types/d3-shape': 3.1.6 + '@types/d3-time': 3.0.4 + '@types/d3-time-format': 4.0.3 + '@types/d3-timer': 3.0.2 + '@types/d3-transition': 3.0.9 + '@types/d3-zoom': 3.0.8 + dev: false + /@types/debug@4.1.12: resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} dependencies: @@ -6495,6 +6740,10 @@ packages: '@types/node': 20.11.19 dev: false + /@types/geojson@7946.0.14: + resolution: {integrity: sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==} + dev: false + /@types/graceful-fs@4.1.9: resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} dependencies: @@ -7814,6 +8063,12 @@ packages: hasBin: true dev: false + /acorn@8.14.0: + resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: false + /after-all-results@2.0.0: resolution: {integrity: sha512-2zHEyuhSJOuCrmas9YV0YL/MFCWLxe1dS6k/ENhgYrb/JqyMnadLN4iIAc9kkZrbElMDyyAGH/0J18OPErOWLg==} dev: false @@ -9036,6 +9291,26 @@ packages: lodash.some: 4.6.0 dev: false + /chevrotain-allstar@0.3.1(chevrotain@11.0.3): + resolution: {integrity: sha512-b7g+y9A0v4mxCW1qUhf3BSVPg+/NvGErk/dOkrDaHA0nQIQGAtrOjlX//9OQtRlSCy+x9rfB5N8yC71lH1nvMw==} + peerDependencies: + chevrotain: ^11.0.0 + dependencies: + chevrotain: 11.0.3 + lodash-es: 4.17.21 + dev: false + + /chevrotain@11.0.3: + resolution: {integrity: sha512-ci2iJH6LeIkvP9eJW6gpueU8cnZhv85ELY8w8WiFtNjMHA5ad6pQLaJo9mEly/9qUyCpvqX8/POVUTf18/HFdw==} + dependencies: + '@chevrotain/cst-dts-gen': 11.0.3 + '@chevrotain/gast': 11.0.3 + '@chevrotain/regexp-to-ast': 11.0.3 + '@chevrotain/types': 11.0.3 + '@chevrotain/utils': 11.0.3 + lodash-es: 4.17.21 + dev: false + /chokidar@3.6.0: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} @@ -9364,6 +9639,10 @@ packages: semver: 7.6.3 dev: false + /confbox@0.1.8: + resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} + dev: false + /config-file-ts@0.2.8-rc1: resolution: {integrity: sha512-GtNECbVI82bT4RiDIzBSVuTKoSHufnU7Ce7/42bkWZJZFLjmDF2WBpVsvRkhKCfKBnTBb3qZrBwPpFBU/Myvhg==} dependencies: @@ -9483,6 +9762,18 @@ packages: vary: 1.1.2 dev: false + /cose-base@1.0.3: + resolution: {integrity: sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==} + dependencies: + layout-base: 1.0.2 + dev: false + + /cose-base@2.2.0: + resolution: {integrity: sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==} + dependencies: + layout-base: 2.0.1 + dev: false + /cosmiconfig@8.3.6(typescript@5.3.3): resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==} engines: {node: '>=14'} @@ -9706,6 +9997,300 @@ packages: strip-bom: 2.0.0 dev: false + /cytoscape-cose-bilkent@4.1.0(cytoscape@3.30.4): + resolution: {integrity: sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==} + peerDependencies: + cytoscape: ^3.2.0 + dependencies: + cose-base: 1.0.3 + cytoscape: 3.30.4 + dev: false + + /cytoscape-fcose@2.2.0(cytoscape@3.30.4): + resolution: {integrity: sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==} + peerDependencies: + cytoscape: ^3.2.0 + dependencies: + cose-base: 2.2.0 + cytoscape: 3.30.4 + dev: false + + /cytoscape@3.30.4: + resolution: {integrity: sha512-OxtlZwQl1WbwMmLiyPSEBuzeTIQnwZhJYYWFzZ2PhEHVFwpeaqNIkUzSiso00D98qk60l8Gwon2RP304d3BJ1A==} + engines: {node: '>=0.10'} + dev: false + + /d3-array@2.12.1: + resolution: {integrity: sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==} + dependencies: + internmap: 1.0.1 + dev: false + + /d3-array@3.2.4: + resolution: {integrity: sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==} + engines: {node: '>=12'} + dependencies: + internmap: 2.0.3 + dev: false + + /d3-axis@3.0.0: + resolution: {integrity: sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==} + engines: {node: '>=12'} + dev: false + + /d3-brush@3.0.0: + resolution: {integrity: sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==} + engines: {node: '>=12'} + dependencies: + d3-dispatch: 3.0.1 + d3-drag: 3.0.0 + d3-interpolate: 3.0.1 + d3-selection: 3.0.0 + d3-transition: 3.0.1(d3-selection@3.0.0) + dev: false + + /d3-chord@3.0.1: + resolution: {integrity: sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==} + engines: {node: '>=12'} + dependencies: + d3-path: 3.1.0 + dev: false + + /d3-color@3.1.0: + resolution: {integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==} + engines: {node: '>=12'} + dev: false + + /d3-contour@4.0.2: + resolution: {integrity: sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==} + engines: {node: '>=12'} + dependencies: + d3-array: 3.2.4 + dev: false + + /d3-delaunay@6.0.4: + resolution: {integrity: sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==} + engines: {node: '>=12'} + dependencies: + delaunator: 5.0.1 + dev: false + + /d3-dispatch@3.0.1: + resolution: {integrity: sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==} + engines: {node: '>=12'} + dev: false + + /d3-drag@3.0.0: + resolution: {integrity: sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==} + engines: {node: '>=12'} + dependencies: + d3-dispatch: 3.0.1 + d3-selection: 3.0.0 + dev: false + + /d3-dsv@3.0.1: + resolution: {integrity: sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==} + engines: {node: '>=12'} + hasBin: true + dependencies: + commander: 7.2.0 + iconv-lite: 0.6.3 + rw: 1.3.3 + dev: false + + /d3-ease@3.0.1: + resolution: {integrity: sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==} + engines: {node: '>=12'} + dev: false + + /d3-fetch@3.0.1: + resolution: {integrity: sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==} + engines: {node: '>=12'} + dependencies: + d3-dsv: 3.0.1 + dev: false + + /d3-force@3.0.0: + resolution: {integrity: sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==} + engines: {node: '>=12'} + dependencies: + d3-dispatch: 3.0.1 + d3-quadtree: 3.0.1 + d3-timer: 3.0.1 + dev: false + + /d3-format@3.1.0: + resolution: {integrity: sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==} + engines: {node: '>=12'} + dev: false + + /d3-geo@3.1.1: + resolution: {integrity: sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==} + engines: {node: '>=12'} + dependencies: + d3-array: 3.2.4 + dev: false + + /d3-hierarchy@3.1.2: + resolution: {integrity: sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==} + engines: {node: '>=12'} + dev: false + + /d3-interpolate@3.0.1: + resolution: {integrity: sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==} + engines: {node: '>=12'} + dependencies: + d3-color: 3.1.0 + dev: false + + /d3-path@1.0.9: + resolution: {integrity: sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==} + dev: false + + /d3-path@3.1.0: + resolution: {integrity: sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==} + engines: {node: '>=12'} + dev: false + + /d3-polygon@3.0.1: + resolution: {integrity: sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==} + engines: {node: '>=12'} + dev: false + + /d3-quadtree@3.0.1: + resolution: {integrity: sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==} + engines: {node: '>=12'} + dev: false + + /d3-random@3.0.1: + resolution: {integrity: sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==} + engines: {node: '>=12'} + dev: false + + /d3-sankey@0.12.3: + resolution: {integrity: sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==} + dependencies: + d3-array: 2.12.1 + d3-shape: 1.3.7 + dev: false + + /d3-scale-chromatic@3.1.0: + resolution: {integrity: sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==} + engines: {node: '>=12'} + dependencies: + d3-color: 3.1.0 + d3-interpolate: 3.0.1 + dev: false + + /d3-scale@4.0.2: + resolution: {integrity: sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==} + engines: {node: '>=12'} + dependencies: + d3-array: 3.2.4 + d3-format: 3.1.0 + d3-interpolate: 3.0.1 + d3-time: 3.1.0 + d3-time-format: 4.1.0 + dev: false + + /d3-selection@3.0.0: + resolution: {integrity: sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==} + engines: {node: '>=12'} + dev: false + + /d3-shape@1.3.7: + resolution: {integrity: sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==} + dependencies: + d3-path: 1.0.9 + dev: false + + /d3-shape@3.2.0: + resolution: {integrity: sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==} + engines: {node: '>=12'} + dependencies: + d3-path: 3.1.0 + dev: false + + /d3-time-format@4.1.0: + resolution: {integrity: sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==} + engines: {node: '>=12'} + dependencies: + d3-time: 3.1.0 + dev: false + + /d3-time@3.1.0: + resolution: {integrity: sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==} + engines: {node: '>=12'} + dependencies: + d3-array: 3.2.4 + dev: false + + /d3-timer@3.0.1: + resolution: {integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==} + engines: {node: '>=12'} + dev: false + + /d3-transition@3.0.1(d3-selection@3.0.0): + resolution: {integrity: sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==} + engines: {node: '>=12'} + peerDependencies: + d3-selection: 2 - 3 + dependencies: + d3-color: 3.1.0 + d3-dispatch: 3.0.1 + d3-ease: 3.0.1 + d3-interpolate: 3.0.1 + d3-selection: 3.0.0 + d3-timer: 3.0.1 + dev: false + + /d3-zoom@3.0.0: + resolution: {integrity: sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==} + engines: {node: '>=12'} + dependencies: + d3-dispatch: 3.0.1 + d3-drag: 3.0.0 + d3-interpolate: 3.0.1 + d3-selection: 3.0.0 + d3-transition: 3.0.1(d3-selection@3.0.0) + dev: false + + /d3@7.9.0: + resolution: {integrity: sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==} + engines: {node: '>=12'} + dependencies: + d3-array: 3.2.4 + d3-axis: 3.0.0 + d3-brush: 3.0.0 + d3-chord: 3.0.1 + d3-color: 3.1.0 + d3-contour: 4.0.2 + d3-delaunay: 6.0.4 + d3-dispatch: 3.0.1 + d3-drag: 3.0.0 + d3-dsv: 3.0.1 + d3-ease: 3.0.1 + d3-fetch: 3.0.1 + d3-force: 3.0.0 + d3-format: 3.1.0 + d3-geo: 3.1.1 + d3-hierarchy: 3.1.2 + d3-interpolate: 3.0.1 + d3-path: 3.1.0 + d3-polygon: 3.0.1 + d3-quadtree: 3.0.1 + d3-random: 3.0.1 + d3-scale: 4.0.2 + d3-scale-chromatic: 3.1.0 + d3-selection: 3.0.0 + d3-shape: 3.2.0 + d3-time: 3.1.0 + d3-time-format: 4.1.0 + d3-timer: 3.0.1 + d3-transition: 3.0.1(d3-selection@3.0.0) + d3-zoom: 3.0.0 + dev: false + /d@1.0.2: resolution: {integrity: sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==} engines: {node: '>=0.12'} @@ -9714,6 +10299,13 @@ packages: type: 2.7.3 dev: false + /dagre-d3-es@7.0.11: + resolution: {integrity: sha512-tvlJLyQf834SylNKax8Wkzco/1ias1OPw8DcUMDE7oUIoSEW25riQVuiu/0OWEFqT0cxHT3Pa9/D82Jr47IONw==} + dependencies: + d3: 7.9.0 + lodash-es: 4.17.21 + dev: false + /data-uri-to-buffer@2.0.2: resolution: {integrity: sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==} dev: false @@ -9774,6 +10366,10 @@ packages: '@babel/runtime': 7.23.9 dev: false + /dayjs@1.11.13: + resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} + dev: false + /debounce-fn@4.0.0: resolution: {integrity: sha512-8pYCQiL9Xdcg0UPSD3d+0KMlOjp+KGU5EPwYddgzQ7DATsg4fuUDjQtsYLmWjnk2obnNHgV3vE2Y4jejSOJVBQ==} engines: {node: '>=10'} @@ -9821,6 +10417,18 @@ packages: ms: 2.1.2 dev: false + /debug@4.3.7: + resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.3 + dev: false + /decamelize@1.2.0: resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} engines: {node: '>=0.10.0'} @@ -9933,6 +10541,12 @@ packages: esprima: 4.0.1 dev: false + /delaunator@5.0.1: + resolution: {integrity: sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==} + dependencies: + robust-predicates: 3.0.2 + dev: false + /delayed-stream@1.0.0: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} @@ -10204,6 +10818,12 @@ packages: resolution: {integrity: sha512-cTOAhc36AalkjtBpfG6O8JimdTMWNXjiePT2xQH/ppBGi/4uIpmj8eKyIkMJErXWARyINV/sB38yf8JCLF5pbQ==} dev: false + /dompurify@3.2.2: + resolution: {integrity: sha512-YMM+erhdZ2nkZ4fTNRTSI94mb7VG7uVF5vj5Zde7tImgnhZE3R6YW/IACGIHb2ux+QkEXMhe591N+5jWOmL4Zw==} + optionalDependencies: + '@types/trusted-types': 2.0.7 + dev: false + /domutils@1.5.1: resolution: {integrity: sha512-gSu5Oi/I+3wDENBsOWBiRK1eoGxcywYSqg3rR960/+EfY0CF4EX1VPkgHOZ3WiS/Jg2DtliF6BhWcHlfpYUcGw==} dependencies: @@ -12558,6 +13178,10 @@ packages: duplexer: 0.1.2 dev: false + /hachure-fill@0.5.2: + resolution: {integrity: sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg==} + dev: false + /handle-thing@2.0.1: resolution: {integrity: sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==} dev: false @@ -13077,6 +13701,15 @@ packages: side-channel: 1.0.6 dev: false + /internmap@1.0.1: + resolution: {integrity: sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==} + dev: false + + /internmap@2.0.3: + resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==} + engines: {node: '>=12'} + dev: false + /interpret@3.1.1: resolution: {integrity: sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==} engines: {node: '>=10.13.0'} @@ -14309,6 +14942,13 @@ packages: engines: {node: '>= 0.4.0'} dev: false + /katex@0.16.11: + resolution: {integrity: sha512-RQrI8rlHY92OLf3rho/Ts8i/XvjgguEjOkO1BEXcU3N8BqPpSzBNwV/G0Ukr+P/l3ivvJUE/Fa/CwbS6HesGNQ==} + hasBin: true + dependencies: + commander: 8.3.0 + dev: false + /keygrip@1.1.0: resolution: {integrity: sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==} engines: {node: '>= 0.6'} @@ -14322,6 +14962,10 @@ packages: json-buffer: 3.0.1 dev: false + /khroma@2.1.0: + resolution: {integrity: sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==} + dev: false + /kind-of@6.0.3: resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} engines: {node: '>=0.10.0'} @@ -14431,10 +15075,25 @@ packages: - supports-color dev: false + /kolorist@1.8.0: + resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} + dev: false + /kuler@2.0.0: resolution: {integrity: sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==} dev: false + /langium@3.0.0: + resolution: {integrity: sha512-+Ez9EoiByeoTu/2BXmEaZ06iPNXM6thWJp02KfBO/raSMyCJ4jw7AkWWa+zBCTm0+Tw1Fj9FOxdqSskyN5nAwg==} + engines: {node: '>=16.0.0'} + dependencies: + chevrotain: 11.0.3 + chevrotain-allstar: 0.3.1(chevrotain@11.0.3) + vscode-languageserver: 9.0.1 + vscode-languageserver-textdocument: 1.0.12 + vscode-uri: 3.0.8 + dev: false + /launch-editor@2.6.1: resolution: {integrity: sha512-eB/uXmFVpY4zezmGp5XtU21kwo7GBbKB+EQ+UZeWtGb9yAM5xt/Evk+lYH3eRNAtId+ej4u7TYPFZ07w4s7rRw==} dependencies: @@ -14442,6 +15101,14 @@ packages: shell-quote: 1.8.1 dev: false + /layout-base@1.0.2: + resolution: {integrity: sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==} + dev: false + + /layout-base@2.0.1: + resolution: {integrity: sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==} + dev: false + /lazy-val@1.0.5: resolution: {integrity: sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==} dev: false @@ -14697,6 +15364,14 @@ packages: json5: 2.2.3 dev: false + /local-pkg@0.5.1: + resolution: {integrity: sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ==} + engines: {node: '>=14'} + dependencies: + mlly: 1.7.3 + pkg-types: 1.2.1 + dev: false + /localforage@1.10.0: resolution: {integrity: sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==} dependencies: @@ -14736,6 +15411,10 @@ packages: p-locate: 6.0.0 dev: false + /lodash-es@4.17.21: + resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} + dev: false + /lodash.assignin@4.2.0: resolution: {integrity: sha512-yX/rx6d/UTVh7sSVWVSIMjfnz95evAgDFdb1ZozC35I9mSFCkmzptOzevxjgbQUsc78NR44LVHWjsoMQXy9FDg==} dev: false @@ -15026,6 +15705,12 @@ packages: uc.micro: 2.0.0 dev: false + /marked@13.0.3: + resolution: {integrity: sha512-rqRix3/TWzE9rIoFGIn8JmsVfhiuC8VIQ8IdX5TfzmeBucdY05/0UlzKaw0eVtpcN/OdVFpBk7CjKGo9iHJ/zA==} + engines: {node: '>= 18'} + hasBin: true + dev: false + /matcher@3.0.0: resolution: {integrity: sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==} engines: {node: '>=10'} @@ -15115,6 +15800,33 @@ packages: engines: {node: '>= 8'} dev: false + /mermaid@11.4.1: + resolution: {integrity: sha512-Mb01JT/x6CKDWaxigwfZYuYmDZ6xtrNwNlidKZwkSrDaY9n90tdrJTV5Umk+wP1fZscGptmKFXHsXMDEVZ+Q6A==} + dependencies: + '@braintree/sanitize-url': 7.1.0 + '@iconify/utils': 2.1.33 + '@mermaid-js/parser': 0.3.0 + '@types/d3': 7.4.3 + cytoscape: 3.30.4 + cytoscape-cose-bilkent: 4.1.0(cytoscape@3.30.4) + cytoscape-fcose: 2.2.0(cytoscape@3.30.4) + d3: 7.9.0 + d3-sankey: 0.12.3 + dagre-d3-es: 7.0.11 + dayjs: 1.11.13 + dompurify: 3.2.2 + katex: 0.16.11 + khroma: 2.1.0 + lodash-es: 4.17.21 + marked: 13.0.3 + roughjs: 4.6.6 + stylis: 4.3.4 + ts-dedent: 2.2.0 + uuid: 9.0.1 + transitivePeerDependencies: + - supports-color + dev: false + /methods@1.1.2: resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} engines: {node: '>= 0.6'} @@ -15381,6 +16093,15 @@ packages: hasBin: true dev: false + /mlly@1.7.3: + resolution: {integrity: sha512-xUsx5n/mN0uQf4V548PKQ+YShA4/IW0KI1dZhrNrPCLG+xizETbHTkOa1f8/xut9JRPp8kQuMnz0oqwkTiLo/A==} + dependencies: + acorn: 8.14.0 + pathe: 1.1.2 + pkg-types: 1.2.1 + ufo: 1.5.4 + dev: false + /module-details-from-path@1.0.3: resolution: {integrity: sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==} dev: false @@ -16247,6 +16968,10 @@ packages: resolution: {integrity: sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==} dev: false + /package-manager-detector@0.2.6: + resolution: {integrity: sha512-9vPH3qooBlYRJdmdYP00nvjZOulm40r5dhtal8st18ctf+6S1k7pi5yIHLvI4w5D70x0Y+xdVD9qITH0QO/A8A==} + dev: false + /pako@1.0.11: resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} dev: false @@ -16381,6 +17106,10 @@ packages: resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} dev: false + /path-data-parser@0.1.0: + resolution: {integrity: sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w==} + dev: false + /path-exists@3.0.0: resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==} engines: {node: '>=4'} @@ -16656,6 +17385,14 @@ packages: find-up: 4.1.0 dev: false + /pkg-types@1.2.1: + resolution: {integrity: sha512-sQoqa8alT3nHjGuTjuKgOnvjo4cljkufdtLMnO2LBP/wRwuDlo1tkaEdMxCRhyGRPacv/ztlZgDPm2b7FAmEvw==} + dependencies: + confbox: 0.1.8 + mlly: 1.7.3 + pathe: 1.1.2 + dev: false + /pkg-up@3.1.0: resolution: {integrity: sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==} engines: {node: '>=8'} @@ -16699,6 +17436,17 @@ packages: engines: {node: '>=4.0.0'} dev: false + /points-on-curve@0.2.0: + resolution: {integrity: sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A==} + dev: false + + /points-on-path@0.2.1: + resolution: {integrity: sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g==} + dependencies: + path-data-parser: 0.1.0 + points-on-curve: 0.2.0 + dev: false + /possible-typed-array-names@1.0.0: resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} engines: {node: '>= 0.4'} @@ -17680,6 +18428,10 @@ packages: dev: false optional: true + /robust-predicates@3.0.2: + resolution: {integrity: sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==} + dev: false + /rollup-plugin-inject@3.0.2: resolution: {integrity: sha512-ptg9PQwzs3orn4jkgXJ74bfs5vYz1NCZlSQMBUA0wKcGp5i5pA1AO3fOUEte8enhGUC+iapTCzEWw2jEFFUO/w==} deprecated: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-inject. @@ -17705,12 +18457,25 @@ packages: resolution: {integrity: sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ==} dev: false + /roughjs@4.6.6: + resolution: {integrity: sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ==} + dependencies: + hachure-fill: 0.5.2 + path-data-parser: 0.1.0 + points-on-curve: 0.2.0 + points-on-path: 0.2.1 + dev: false + /run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} dependencies: queue-microtask: 1.2.3 dev: false + /rw@1.3.3: + resolution: {integrity: sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==} + dev: false + /rxjs@7.8.1: resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} requiresBuild: true @@ -18754,6 +19519,10 @@ packages: webpack: 5.90.3(esbuild@0.20.1)(webpack-cli@5.1.4) dev: false + /stylis@4.3.4: + resolution: {integrity: sha512-osIBl6BGUmSfDkyH2mB7EFvCJntXDrLhKjHTRj/rK6xLH0yuPrHULDRQzKokSOD4VoorhtKpfcfW1GAntu8now==} + dev: false + /sumchecker@3.0.1: resolution: {integrity: sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==} engines: {node: '>= 8.0'} @@ -19232,6 +20001,10 @@ packages: resolution: {integrity: sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==} dev: false + /tinyexec@0.3.1: + resolution: {integrity: sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==} + dev: false + /tippy.js@6.3.7: resolution: {integrity: sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==} dependencies: @@ -19380,6 +20153,11 @@ packages: resolution: {integrity: sha512-+1iDGY6NmOGidq7i7xZGA4cm8DAa6fqdYcvO5Z6yBevH++Bdo9Qt/mN0TzHUgcCcKv1gmh9+W5dHqz8pMWbCbg==} dev: false + /ts-dedent@2.2.0: + resolution: {integrity: sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==} + engines: {node: '>=6.10'} + dev: false + /ts-invariant@0.4.4: resolution: {integrity: sha512-uEtWkFM/sdZvRNNDL3Ehu4WVpwaulhwQszV8mrtcdeE8nN00BV9mAmQ88RkrBhFgl9gMgvjJLAQcZbnPXI9mlA==} dependencies: @@ -20087,6 +20865,37 @@ packages: dev: false optional: true + /vscode-jsonrpc@8.2.0: + resolution: {integrity: sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==} + engines: {node: '>=14.0.0'} + dev: false + + /vscode-languageserver-protocol@3.17.5: + resolution: {integrity: sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==} + dependencies: + vscode-jsonrpc: 8.2.0 + vscode-languageserver-types: 3.17.5 + dev: false + + /vscode-languageserver-textdocument@1.0.12: + resolution: {integrity: sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==} + dev: false + + /vscode-languageserver-types@3.17.5: + resolution: {integrity: sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==} + dev: false + + /vscode-languageserver@9.0.1: + resolution: {integrity: sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==} + hasBin: true + dependencies: + vscode-languageserver-protocol: 3.17.5 + dev: false + + /vscode-uri@3.0.8: + resolution: {integrity: sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==} + dev: false + /w3c-keyname@2.2.8: resolution: {integrity: sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==} dev: false @@ -31590,7 +32399,7 @@ packages: dev: false file:projects/text-editor-resources.tgz(@types/node@20.11.19)(bufferutil@4.0.8)(esbuild@0.20.1)(highlight.js@11.8.0)(postcss-load-config@4.0.2)(postcss@8.4.35)(ts-node@10.9.2)(utf-8-validate@6.0.4): - resolution: {integrity: sha512-yKlrakMY05rwNIM/iOBwM8RgQ52Nc6tBP8iV6yDvaIuwzPUhvE4PFV4XoZV2sGjD0IhQGy1WdrpcWe1tQuRuxw==, tarball: file:projects/text-editor-resources.tgz} + resolution: {integrity: sha512-lkwDEQVO9bTsGXgxCo5/Ap2EtqD5H1pA0WIkkbcK5IiyR6v6lqzFGfzavmJluKX1GQ4rfaGYQoMXqvSOhUq7Pg==, tarball: file:projects/text-editor-resources.tgz} id: file:projects/text-editor-resources.tgz name: '@rush-temp/text-editor-resources' version: 0.0.0 @@ -31632,6 +32441,7 @@ packages: jest: 29.7.0(@types/node@20.11.19)(ts-node@10.9.2) lib0: 0.2.89 lowlight: 3.1.0 + mermaid: 11.4.1 prettier: 3.2.5 prettier-plugin-svelte: 3.2.2(prettier@3.2.5)(svelte@4.2.19) prosemirror-codemark: 0.4.2 diff --git a/packages/theme/styles/prose.scss b/packages/theme/styles/prose.scss index 2955a62328..a358f51a0d 100644 --- a/packages/theme/styles/prose.scss +++ b/packages/theme/styles/prose.scss @@ -41,7 +41,7 @@ table.proseTable { box-sizing: border-box; position: relative; - > * { + >* { margin-bottom: 0; } } @@ -72,15 +72,19 @@ table.proseTable { left: var(--table-selection-border-indent); right: var(--table-selection-border-indent); } + &__border-top::before { border-top-width: var(--table-selection-border-width); } + &__border-bottom::before { border-bottom-width: var(--table-selection-border-width); } + &__border-left::before { border-left-width: var(--table-selection-border-width); } + &__border-right::before { border-right-width: var(--table-selection-border-width); } @@ -276,7 +280,9 @@ table.proseTable { } } - &:hover + .table-insert-marker { opacity: 1; } + &:hover+.table-insert-marker { + opacity: 1; + } } .table-insert-marker { @@ -381,19 +387,94 @@ pre.proseCodeBlock { } // Fixes for MessageViewer -pre.proseCodeBlock > pre.proseCode { +pre.proseCodeBlock>pre.proseCode { padding: 0; background-color: transparent; border: none; border-radius: 0; } -.proseHeading { line-height: 110%; } +.proseHeading { + line-height: 110%; +} // Fixes for cursors .ProseMirror { - h1, h2, h3, p, pre, code { cursor: text; } - p div { cursor: auto; } + + h1, + h2, + h3, + p, + pre, + code { + cursor: text; + } + + p div { + cursor: auto; + } +} + +.proseMermaidDiagram { + --border-color: transparent; + + cursor: auto; + + position: relative; + border: 1px solid var(--border-color); + border-radius: .25rem; + + + &:not(.selected) header { + visibility: hidden; + } + + &:not(.folded) { + --border-color: var(--theme-button-border); + + header { + visibility: visible; + } + } + + &.selected { + --border-color: var(--theme-editbox-focus-border) + } + + header { + user-select: none; + position: absolute; + right: 0.5rem; + top: 0.5rem; + + display: flex; + gap: 0.5rem; + } + + >code { + display: block; + padding: 0.75rem; + user-select: text; + font-family: var(--mono-font); + color: var(--theme-content-color); + + min-height: 3rem; + + background: var(--theme-button-default); + + font-size: 0.875rem; + line-height: 1.5em; + } + + .mermaidPreviewContainer { + padding: 0.5rem; + cursor: default; + } + + &:not(.folded) .mermaidPreviewContainer { + border-top: 1px solid var(--border-color); + min-height: 6rem; + } } .theme-dark { @@ -402,4 +483,4 @@ pre.proseCodeBlock > pre.proseCode { .theme-light { @import './github-light.scss'; -} +} \ No newline at end of file diff --git a/plugins/text-editor-assets/lang/en.json b/plugins/text-editor-assets/lang/en.json index 2c63a5982d..0c5390b770 100644 --- a/plugins/text-editor-assets/lang/en.json +++ b/plugins/text-editor-assets/lang/en.json @@ -39,7 +39,6 @@ "FullDescription": "Full description", "NoFullDescription": "There are no detailed description", "EnableDiffMode": "Diff mode", - "AddColumnBefore": "Add before", "AddColumnAfter": "Add after", "DeleteColumn": "Delete", @@ -48,7 +47,6 @@ "DeleteRow": "Delete", "DeleteTable": "Delete", "Duplicate": "Duplicate", - "CategoryRow": "Rows", "CategoryColumn": "Columns", "Table": "Table", @@ -60,6 +58,7 @@ "Image": "Image", "SeparatorLine": "Separator line", "TodoList": "Action item", - "DrawingBoard": "Drawing board" + "DrawingBoard": "Drawing board", + "MermaidDiargram": "Diagram" } -} +} \ No newline at end of file diff --git a/plugins/text-editor-assets/lang/ru.json b/plugins/text-editor-assets/lang/ru.json index 41aaf9e4c2..5d42871c13 100644 --- a/plugins/text-editor-assets/lang/ru.json +++ b/plugins/text-editor-assets/lang/ru.json @@ -39,7 +39,6 @@ "FullDescription": "Детальное описание", "NoFullDescription": "Нет детального описания", "EnableDiffMode": "Режим сравнения", - "AddColumnBefore": "Добавить до", "AddColumnAfter": "Добавить после", "DeleteColumn": "Удалить", @@ -48,7 +47,6 @@ "DeleteRow": "Удалить", "DeleteTable": "Удалить", "Duplicate": "Дублировать", - "CategoryRow": "Строки", "CategoryColumn": "Колонки", "Table": "Таблица", @@ -60,6 +58,7 @@ "Image": "Изображение", "SeparatorLine": "Разделительная линия", "TodoList": "Действие", - "DrawingBoard": "Доска" + "DrawingBoard": "Доска", + "MermaidDiargram": "Диаграмма" } -} +} \ No newline at end of file diff --git a/plugins/text-editor-resources/package.json b/plugins/text-editor-resources/package.json index b02551f545..df3012c3e2 100644 --- a/plugins/text-editor-resources/package.json +++ b/plugins/text-editor-resources/package.json @@ -83,6 +83,8 @@ "slugify": "^1.6.6", "lib0": "^0.2.88", "y-indexeddb": "^9.0.12", - "lowlight": "^3.1.0" + "lowlight": "^3.1.0", + "mermaid": "~11.4.1", + "@hcengineering/theme": "^0.6.5" } } diff --git a/plugins/text-editor-resources/src/components/CollaborativeTextEditor.svelte b/plugins/text-editor-resources/src/components/CollaborativeTextEditor.svelte index 711a7c4b34..cb43f5641e 100644 --- a/plugins/text-editor-resources/src/components/CollaborativeTextEditor.svelte +++ b/plugins/text-editor-resources/src/components/CollaborativeTextEditor.svelte @@ -83,6 +83,7 @@ import { LeftMenuExtension } from './extension/leftMenu' import { type FileAttachFunction } from './extension/types' import { completionConfig, inlineCommandsConfig } from './extensions' + import { MermaidExtension, mermaidOptions } from './extension/mermaid' export let object: Doc export let attribute: KeyedAttribute @@ -279,7 +280,8 @@ { id: 'code-block', label: textEditor.string.CodeBlock, icon: view.icon.CodeBlock }, { id: 'separator-line', label: textEditor.string.SeparatorLine, icon: view.icon.SeparatorLine }, { id: 'todo-list', label: textEditor.string.TodoList, icon: view.icon.TodoList }, - { id: 'drawing-board', label: textEditor.string.DrawingBoard, icon: IconScribble as any } + { id: 'drawing-board', label: textEditor.string.DrawingBoard, icon: IconScribble as any }, + { id: 'mermaid', label: textEditor.string.MermaidDiargram, icon: view.icon.Model } ], handleSelect: handleLeftMenuClick }) @@ -375,6 +377,9 @@ case 'drawing-board': editor.commands.insertContentAt(pos, { type: 'drawingBoard', attrs: { id: generateId() } }) break + case 'mermaid': + editor.commands.insertContentAt(pos, { type: 'mermaid' }) + break } } @@ -466,6 +471,7 @@ } }), EmojiExtension, + MermaidExtension.configure({ ...mermaidOptions, ydoc, ydocContentField: field }), DrawingBoardExtension.configure({ getSavedBoard }), ...extensions ], diff --git a/plugins/text-editor-resources/src/components/extension/mermaid.ts b/plugins/text-editor-resources/src/components/extension/mermaid.ts new file mode 100644 index 0000000000..b655166e04 --- /dev/null +++ b/plugins/text-editor-resources/src/components/extension/mermaid.ts @@ -0,0 +1,711 @@ +// +// 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 { codeBlockOptions } from '@hcengineering/text' +import { type CodeBlockLowlightOptions, CodeBlockLowlight } from '@tiptap/extension-code-block-lowlight' +import { type Node as ProseMirrorNode } from '@tiptap/pm/model' +import { NodeSelection, Plugin, PluginKey, TextSelection, type Transaction } from '@tiptap/pm/state' +import { Decoration, DecorationSet, type EditorView } from '@tiptap/pm/view' +import { createLowlight } from 'lowlight' +import { isChangeEditable } from './editable' +import type { MermaidConfig } from 'mermaid' +import { getCurrentTheme, isThemeDark, themeStore } from '@hcengineering/theme' + +import { createRelativePositionFromTypeIndex, type RelativePosition, type Doc as YDoc } from 'yjs' +import { mergeAttributes } from '@tiptap/core' + +export interface MermaidOptions extends CodeBlockLowlightOptions { + ydoc?: YDoc + ydocContentField?: string +} + +export const mermaidOptions: CodeBlockLowlightOptions = { + ...codeBlockOptions, + lowlight: createLowlight({ mermaid: mermaidHLJS }), + defaultLanguage: 'mermaid' +} + +const mermaidMetaTxField = 'mermaid-meta-tx' + +interface TxMetaContainer { + nodePatch?: NodePatchSpec + renderResult?: MermaidRenderResult + updateDecorations?: boolean +} + +interface NodeDecorationState { + type: 'mermaid' + + diagramBuilder: (view: EditorView) => MermaidRenderResult | null + + folded: boolean + textContent: string + selected: boolean +} + +function getTxMeta (tx?: Transaction): TxMetaContainer | undefined { + return tx?.getMeta('mermaid-meta-tx') +} +function setTxMeta (tx: Transaction, meta: TxMetaContainer): Transaction { + return tx.setMeta(mermaidMetaTxField, meta).setMeta('addToHistory', false) +} + +interface NodePatchSpec { + pos: number + folded: boolean + selected: boolean +} + +export const MermaidExtension = CodeBlockLowlight.extend({ + name: 'mermaid', + group: 'block', + + draggable: true, + selectable: true, + + parseHTML () { + return [ + { + tag: 'div.mermaid-diagram', + preserveWhitespace: 'full' + } + ] + }, + + addAttributes () { + return { + language: { + default: 'mermaid' + } + } + }, + + renderHTML ({ node, HTMLAttributes }) { + return [ + 'div', + mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, { + class: 'mermaid-diagram' + }), + [ + 'code', + { + class: node.attrs.language !== undefined ? this.options.languageClassPrefix + node.attrs.language : null + }, + 0 + ] + ] + }, + + addCommands () { + return {} + }, + + addInputRules () { + return [] + }, + + addProseMirrorPlugins () { + return [...(this.parent?.() ?? []), MermaidDecorator(this.options)] + }, + + addNodeView () { + return ({ getPos, editor, node, decorations }) => { + const containerNode = document.createElement('pre') + containerNode.className = 'proseMermaidDiagram' + + const headerNode = containerNode.appendChild(document.createElement('header')) + headerNode.contentEditable = 'false' + + const contentNode = containerNode.appendChild(document.createElement('code')) + contentNode.translate = false + contentNode.spellcheck = false + + const previewNode = containerNode.appendChild(document.createElement('div')) + previewNode.className = 'mermaidPreviewContainer' + previewNode.contentEditable = 'false' + + const languageLabelNode = headerNode.appendChild(document.createElement('button')) + + const languageLabelSpanNode = languageLabelNode.appendChild(document.createElement('span')) + languageLabelSpanNode.className = 'overflow-label label disabled mr-2' + languageLabelSpanNode.textContent = 'mermaid' + + const toggleButtonNode = headerNode.appendChild(document.createElement('button')) + + const toggleButtonIconNode = toggleButtonNode.appendChild(document.createElement('div')) + toggleButtonIconNode.className = 'btn-icon' + + let nodeState: NodeDecorationState = { + type: 'mermaid', + folded: false, + selected: false, + diagramBuilder: () => null, + textContent: node.textContent + } + + const toggleFoldState = (newState: boolean, event?: MouseEvent): void => { + event?.preventDefault() + if (typeof getPos !== 'function') return + + const pos = getPos() + const node = editor.view.state.doc.nodeAt(pos) + + if (node?.type.name !== MermaidExtension.name) return + + const nodePatch: NodePatchSpec = { + pos, + folded: !nodeState.folded, + selected: nodeState.selected + } + + const tr = setTxMeta(editor.view.state.tr, { nodePatch }) + + if (nodePatch.folded) { + tr.setSelection(NodeSelection.create(editor.view.state.doc, pos)) + } else { + const selection = TextSelection.findFrom(editor.view.state.doc.resolve(pos + node.nodeSize), -1) + if (selection !== null) tr.setSelection(selection) + } + + editor.view.dispatch(tr) + } + + toggleButtonNode.onmousedown = (e) => { + toggleFoldState(!nodeState.folded, e) + } + previewNode.ondblclick = (e) => { + toggleFoldState(!nodeState.folded, e) + } + + previewNode.onclick = (e) => { + if (typeof getPos !== 'function') return + const pos = getPos() + const selection = NodeSelection.create(editor.view.state.doc, pos) + editor.view.dispatch(editor.view.state.tr.setSelection(selection)) + e.preventDefault() + } + + const syncState = (decorations: readonly Decoration[]): void => { + nodeState = decorations.find((d) => d.spec.type === MermaidExtension.name)?.spec ?? nodeState + + const isEmpty = nodeState.textContent.trim().length === 0 + const diagram = nodeState.diagramBuilder?.(editor.view) ?? null + const error = diagram?.error ?? null + const diagramNode = error === null ? diagram?.domFragments[0] ?? null : null + + const allowFold = !isEmpty && error === null + + if (nodeState.folded) { + containerNode.classList.add('folded') + contentNode.style.display = 'none' + languageLabelNode.style.display = 'none' + toggleButtonIconNode.innerHTML = editIconSvg + toggleButtonNode.className = 'antiButton primary medium sh-no-shape bs-none only-icon' + } else { + containerNode.classList.remove('folded') + contentNode.style.display = '' + languageLabelNode.style.display = '' + toggleButtonIconNode.innerHTML = foldIconSvg + toggleButtonNode.className = 'antiButton link-bordered medium sh-no-shape bs-none only-icon' + } + + toggleButtonNode.style.display = allowFold ? '' : 'none' + previewNode.style.display = diagramNode !== null ? '' : 'none' + + if (nodeState.selected) { + containerNode.classList.add('selected') + } else { + containerNode.classList.remove('selected') + } + + if (!isEmpty && error !== null) { + languageLabelNode.className = + 'antiButton negative medium sh-no-shape bs-none gap-medium iconR pointer-events-none' + } else { + languageLabelNode.className = + 'antiButton link-bordered medium sh-no-shape bs-none gap-medium iconR pointer-events-none' + } + + while (previewNode.firstChild !== null && previewNode.firstChild !== diagramNode) { + previewNode.removeChild(previewNode.firstChild) + } + + if (diagramNode?.parentElement !== previewNode) { + diagramNode?.parentElement?.removeChild(diagramNode) + } + + if (diagramNode !== null && previewNode.firstChild !== diagramNode) { + previewNode.appendChild(diagramNode) + } + + if (!allowFold && nodeState.folded) { + toggleFoldState(false) + } + } + + const toggleSelection = (newState: boolean): void => { + if (nodeState.selected === newState) return + if (typeof getPos !== 'function') return + const pos = getPos() + const tr = setTxMeta(editor.view.state.tr, { + nodePatch: { + pos, + folded: nodeState.folded, + selected: newState + } + }) + editor.view.dispatch(tr) + } + + syncState(decorations) + + return { + dom: containerNode, + contentDOM: contentNode, + + selectNode: () => { + toggleSelection(true) + }, + deselectNode: () => { + toggleSelection(false) + }, + + stopEvent: (event) => { + if (event instanceof DragEvent && !nodeState.folded) { + event.preventDefault() + } + }, + update: (node, decorations) => { + if (node.type.name !== MermaidExtension.name) return false + syncState(decorations) + return true + } + } + } + } +}) + +interface MermaidPluginState { + decorationSet: DecorationSet + decorationCache: Map + + nodeidCache: Map + renderCache: Map + pendingFragments: Set + + throttle: ThrottledCaller +} + +interface MermaidRenderResult { + svg?: string + error?: { + name?: string + message: string + } + input: string + domFragments: HTMLElement[] + theme: MermaidConfig['theme'] +} + +async function renderMermaidDiagram (code: string, theme: MermaidConfig['theme']): Promise { + // Has no practical effect now, but in case the Webpack + // configuration gets changed to split the vendor bundle, it might come in handy + const mermaid = (await import(/* webpackMode: "lazy-once" */ 'mermaid')).default + + mermaid.initialize({ + startOnLoad: false, + securityLevel: 'loose', + fontFamily: 'var(--font-family)', + logLevel: 5, + theme + }) + + const id = `mermaid-diagram-${Math.random().toString(36).substring(2, 9)}` + + const result: MermaidRenderResult = { + input: code, + domFragments: [], + theme + } + + try { + const render = await mermaid.render(id, code) + result.svg = render.svg + } catch (e: any) { + if (typeof e?.message === 'string') { + result.error = { + name: e.name, + message: e.message + } + } else { + result.error = { + name: 'unknown', + message: 'unknown' + } + } + } + + return result +} + +function buildState ( + options: MermaidOptions, + prev: MermaidPluginState, + doc: ProseMirrorNode, + tr?: Transaction +): MermaidPluginState { + const renderCache = new Map(prev.renderCache) + const nodeidCache = new Map() + const decorationCache = new Map() + const pendingFragments = new Set(prev.pendingFragments) + const theme: MermaidConfig['theme'] = isThemeDark(getCurrentTheme()) ? 'dark' : 'default' + + const unusedRenderCache = new Set(renderCache.keys()) + const usedFragments = new Set() + + const newRenderCacheEntry = getTxMeta(tr)?.renderResult + if (newRenderCacheEntry !== undefined) { + renderCache.set(newRenderCacheEntry.input, newRenderCacheEntry) + } + + const buildOrReuseFragment = (renderState: MermaidRenderResult | null): HTMLElement | null => { + if (renderState?.svg === undefined) return null + + const reuse = renderState.domFragments.find((f) => !usedFragments.has(f)) + if (reuse !== undefined) { + usedFragments.add(reuse) + return reuse + } + + const container = document.createElement('div') + container.className = 'mermaidPreview' + container.innerHTML = renderState.svg + + renderState.domFragments.push(container) + usedFragments.add(container) + + return container + } + + const buildDiagram = ( + node: ProseMirrorNode, + nodeid: string | number, + view: EditorView, + theme: MermaidConfig['theme'] + ): MermaidRenderResult => { + const textContent = node.textContent + const nodeRenderState = renderCache.get(textContent) + const nodeTargetRenderState = nodeRenderState ?? + prev.nodeidCache.get(nodeid) ?? { input: textContent, theme, domFragments: [] } + + unusedRenderCache.delete(textContent) + + nodeidCache.set(nodeid, nodeTargetRenderState) + const element = buildOrReuseFragment(nodeTargetRenderState) + + if ((nodeRenderState === undefined && !pendingFragments.has(textContent)) || nodeRenderState?.theme !== theme) { + pendingFragments.add(textContent) + + prev.throttle.call(nodeid, () => { + renderMermaidDiagram(textContent, theme).then( + (renderResult) => { + view.dispatch(setTxMeta(view.state.tr, { renderResult })) + pendingFragments.delete(textContent) + }, + (reject) => { + console.log(reject) + pendingFragments.delete(textContent) + } + ) + }) + } + + return { ...nodeTargetRenderState, domFragments: element !== null ? [element] : [] } + } + + const decorations: Decoration[] = [] + const lastDecorationSet = tr !== undefined ? prev.decorationSet.map(tr.mapping, tr.doc) : prev.decorationSet + + const nodeStatePatch = getTxMeta(tr)?.nodePatch + + let mIndex = 0 + doc.descendants((node, pos, parent, index) => { + if (node.type.name !== MermaidExtension.name) { + return + } + + // See https://github.com/yjs/y-prosemirror/issues/49 + // Ideally, one would hope that decorations would be recovered through the use of + // transaction mapping, but with Yjs this is not possible in many cases. + // So there's a need for dirty hacks to keep the state of the node intact. (See below). + const yjsdoc = options.ydoc?.getXmlFragment(options.ydocContentField ?? 'content') + const yid = + yjsdoc !== undefined ? yRelativePositionToString(createRelativePositionFromTypeIndex(yjsdoc, index)) : undefined + const nodeid = yid ?? index + const oldCache = prev.decorationCache + const oldState = + (lastDecorationSet.find(pos, pos + node.nodeSize).find((d) => d.spec.type === MermaidExtension.name) + ?.spec as NodeDecorationState) ?? + (yid !== undefined ? oldCache.get(nodeid) : undefined) ?? + (oldCache.get(mIndex)?.textContent === node.textContent ? oldCache.get(mIndex) : undefined) + + const newState: NodeDecorationState = { + type: 'mermaid', + diagramBuilder: (view: EditorView) => buildDiagram(node, nodeid, view, theme), + folded: oldState?.folded ?? node.textContent.trim().length > 0, + selected: oldState?.selected ?? false, + textContent: node.textContent + } + + if (nodeStatePatch !== undefined && pos === nodeStatePatch.pos) { + newState.folded = nodeStatePatch.folded + newState.selected = nodeStatePatch.selected + } + + if (yid !== undefined) decorationCache.set(yid, newState) + decorationCache.set(mIndex, newState) + mIndex++ + + decorations.push(Decoration.node(pos, pos + node.nodeSize, {}, newState)) + }) + + const decorationSet = DecorationSet.create(doc, decorations) + + if (unusedRenderCache.size >= 16) { + for (const key of unusedRenderCache) { + renderCache.delete(key) + } + } + + return { + decorationSet, + decorationCache, + renderCache, + nodeidCache, + throttle: prev.throttle, + pendingFragments + } +} + +export function MermaidDecorator (options: MermaidOptions): Plugin { + return new Plugin({ + key: new PluginKey('mermaid-decorator'), + props: { + decorations (state) { + return this.getState(state)?.decorationSet + } + }, + state: { + init (config, state) { + return buildState( + options, + { + decorationSet: DecorationSet.create(state.doc, []), + decorationCache: new Map(), + nodeidCache: new Map(), + renderCache: new Map(), + throttle: new ThrottledCaller(150), + pendingFragments: new Set() + }, + state.doc + ) + }, + apply (tr, prev, oldState, newState) { + if (tr.docChanged || isChangeEditable(tr) || getTxMeta(tr) !== undefined) { + return buildState(options, prev, newState.doc, tr) + } + + return prev + } + }, + view (editorView) { + const unsubscribe = themeStore.subscribe(() => { + editorView.dispatch(setTxMeta(editorView.state.tr, { updateDecorations: true })) + }) + + return { + destroy () { + unsubscribe() + } + } + } + }) +} + +class ThrottledCaller { + timers = new Map() + delay: number + + lookup (key: T): number { + return this.timers.get(key) ?? 0 + } + + update (key: T, increment: number = 0): number { + const ticks = this.lookup(key) + increment + this.timers.set(key, ticks) + if (ticks === 0) this.timers.delete(key) + return ticks + } + + constructor (delay: number = 150) { + this.delay = delay + } + + call (key: T, callback: () => void): void { + const instant = this.lookup(key) === 0 + if (instant) callback() + + this.update(key, 1) + setTimeout(() => { + const ticks = this.update(key, -1) + if (ticks === 0 && !instant) callback() + }, this.delay) + } +} + +function yRelativePositionToString (id: RelativePosition): string | undefined { + if (id.item?.client === undefined) return + return `${id.item.client}_${id.item.clock}` +} + +// There is no public implementation of memraid syntax for higlightjs, while implementations for +// other highlighting tools are either incomplete or outdated (even the one used in the official live editor). +// This is a crude (broken) and incomplete port of the grammar. +function mermaidHLJS (hljs: any): any { + return { + case_insensitive: false, + contains: [ + // Comments + hljs.COMMENT('%%', '%%', {}), + + // Style definitions + { + className: 'style', + begin: /^([ \t]*(?:classDef|linkStyle|style)[ \t]+[\w$-]+[ \t]+)\w.*[^\s;]/m, + keywords: { + name: 'classDef linkStyle style' + }, + contains: [ + { + className: 'property', + begin: /\b\w[\w-]*(?=[ \t]*:)/ + }, + { + className: 'operator', + begin: /:/ + }, + { + className: 'punctuation', + begin: /,/ + } + ] + }, + + // Inter-arrow labels + { + className: 'operator', + begin: + /([^<>ox.=-])(?:-[-.]|==)(?![<>ox.=-])[ \t]*(?:"[^"\r\n]*"|[^\s".=-](?:[^\r\n.=-]*[^\s.=-])?)[ \t]*(?:\.+->?|--+[->]|==+[=>])(?![<>ox.=-])/, + contains: [ + { + className: 'operator', + begin: /(?:\.+->?|--+[->]|==+[=>])$/ + }, + { + className: 'string', + begin: /^([\s\S]{2}[ \t]*)\S(?:[\s\S]*\S)?/ + }, + { + className: 'arrow-head', + begin: /^\S+/ + } + ] + }, + + // Arrow types + { + className: 'operator', + variants: [ + { begin: /(?<=^|[^{}|o.-])[|}][|o](?:--|\.\.)[|o][|{](?![{}|o.-])/ }, + { + begin: + /(?<=^|[^<>ox.=-])(?:[ox]?|(?:==+|--+|-\.*-)[>ox]|===+|---+|-\.+-)(?![<>ox.=-])/ + }, + { begin: /(?<=^|[^<>()x-])(?:--?(?:>>|[x>)])(?![<>()x])|(?:<<|[x<(])--?(?!-))/ }, + { begin: /(?<=^|[^<>|*o.-])(?:[*o]--|--[*o]|<\|?(?:--|\.\.)|(?:--|\.\.)\|?>|--|\.\.)(?![<>|*o.-])/ } + ] + }, + + // Labels + { + className: 'string', + begin: /(^|[^|<])\|(?:[^\r\n"|]|"[^"\r\n]*")+\|/ + }, + + // Text elements + { + className: 'string', + begin: /(?:[([{]+|\b>)(?:[^\r\n"()[\]{}]|"[^"\r\n]*")+(?:[)\]}]+|>)/ + }, + + // Strings + { + className: 'string', + begin: /"[^"\r\n]*"/ + }, + + // Annotations + { + className: 'keyword', + begin: /<<(?:abstract|choice|enumeration|fork|interface|join|service)>>|\[\[(?:choice|fork|join)\]\]/i + }, + + // Keywords + { + className: 'keyword', + variants: [ + { + begin: + /(^[ \t]*)(?:action|callback|class|classDef|classDiagram|click|direction|erDiagram|flowchart|gantt|gitGraph|graph|journey|link|linkStyle|pie|requirementDiagram|sequenceDiagram|stateDiagram|stateDiagram-v2|style|subgraph)(?![\w$-])/m + }, + { + begin: + /(^[ \t]*)(?:activate|alt|and|as|autonumber|deactivate|else|end(?:[ \t]+note)?|loop|opt|par|participant|rect|state|note[ \t]+(?:over|(?:left|right)[ \t]+of))(?![\w$-])/im + } + ] + }, + + // Entities + { + className: 'variable', + begin: /#[a-z0-9]+;/ + }, + + // Operators + { + className: 'operator', + begin: /(\w[ \t]*)&(?=[ \t]*\w)|:::|:/ + } + ] + } +} + +const editIconSvg = ` + +` + +const foldIconSvg = ` + +` diff --git a/plugins/text-editor-resources/src/components/extensions.ts b/plugins/text-editor-resources/src/components/extensions.ts index c69ab8ef56..96bdeb673e 100644 --- a/plugins/text-editor-resources/src/components/extensions.ts +++ b/plugins/text-editor-resources/src/components/extensions.ts @@ -149,7 +149,8 @@ export function inlineCommandsConfig ( { id: 'code-block', label: textEditor.string.CodeBlock, icon: view.icon.CodeBlock }, { id: 'separator-line', label: textEditor.string.SeparatorLine, icon: view.icon.SeparatorLine }, { id: 'todo-list', label: textEditor.string.TodoList, icon: view.icon.TodoList }, - { id: 'drawing-board', label: textEditor.string.DrawingBoard, icon: IconScribble as any } + { id: 'drawing-board', label: textEditor.string.DrawingBoard, icon: IconScribble as any }, + { id: 'mermaid', label: textEditor.string.MermaidDiargram, icon: view.icon.Model } ].filter(({ id }) => !excludedCommands.includes(id as InlineCommandId)) }, command: ({ editor, range, props }: { editor: Editor, range: Range, props: any }) => { diff --git a/plugins/text-editor/src/plugin.ts b/plugins/text-editor/src/plugin.ts index 93e52d3bcf..e59cbc83ed 100644 --- a/plugins/text-editor/src/plugin.ts +++ b/plugins/text-editor/src/plugin.ts @@ -94,7 +94,8 @@ export default plugin(textEditorId, { Image: '' as IntlString, SeparatorLine: '' as IntlString, TodoList: '' as IntlString, - DrawingBoard: '' as IntlString + DrawingBoard: '' as IntlString, + MermaidDiargram: '' as IntlString }, icon: { Header1: '' as Asset, From 066c18cf13a6e5d6639bbabcb94801b3dea1f59b Mon Sep 17 00:00:00 2001 From: Alexander Onnikov Date: Fri, 6 Dec 2024 21:58:42 +0700 Subject: [PATCH 2/3] UBERF-8629 Use ObjectIdentifier for mentions (#7280) Signed-off-by: Alexander Onnikov --- .../src/components/MentionPopup.svelte | 32 ++++++++++++++++--- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/plugins/text-editor-resources/src/components/MentionPopup.svelte b/plugins/text-editor-resources/src/components/MentionPopup.svelte index 26ce8aad39..6b9632b418 100644 --- a/plugins/text-editor-resources/src/components/MentionPopup.svelte +++ b/plugins/text-editor-resources/src/components/MentionPopup.svelte @@ -15,12 +15,23 @@ -->