Compare commits

...
Author SHA1 Message Date
Steph ff88a247f2 update tests 2023-11-07 06:58:57 -08:00
Steph 269c4e4deb fix docs paths 2023-10-29 21:35:29 -07:00
Sidharth Vinod 02adac1adf Merge pull request #1307 from mermaid-js/release-promotion
Release live editor
2023-10-06 11:04:33 +05:30
Sidharth Vinod 414c5bb59b Update mermaid 2023-10-06 11:02:43 +05:30
Sidharth Vinod 9ef8105ab1 Merge pull request #1311 from mermaid-js/browserslist-update
build: update Browserslist db
2023-10-06 10:55:03 +05:30
Sidharth Vinod 18ed1c9695 Merge pull request #1303 from Yokozuna59/feat/support-sankey-highlighting
feat: support `sankey` diagram highlighting
2023-10-06 10:54:42 +05:30
GitHub Action 173c7260c1 build: update Browserslist db 2023-10-01 02:20:39 +00:00
Sidharth Vinod 83382901cd Merge pull request #1304 from mermaid-js/renovate/patch-all-minor-patch
chore(deps): update all non-major dependencies (patch)
2023-09-21 14:42:35 +00:00
renovate[bot] 580e6657e1 chore(deps): update all non-major dependencies 2023-09-20 22:29:28 +00:00
Reda Al Sulais d0dcbf37e1 feat: support sankey diagram highlighting 2023-09-16 15:02:06 +03:00
Sidharth Vinod 675ecccbf6 Merge pull request #1301 from mermaid-js/release-promotion
Release live editor
2023-09-15 13:32:54 +05:30
Sidharth Vinod e504f25680 Mermaid 10.4.0 2023-09-15 13:31:44 +05:30
Sidharth Vinod 2cf66be68f Merge pull request #1297 from mermaid-js/release-promotion
Release live editor
2023-09-15 10:17:02 +05:30
Sidharth Vinod 75ad46bdb6 Merge pull request #1298 from mermaid-js/browserslist-update
build: update Browserslist db
2023-09-15 09:02:43 +05:30
GitHub Action bde9b1b7c7 build: update Browserslist db 2023-09-15 02:15:23 +00:00
Sidharth Vinod d4ebb23232 Merge pull request #1280 from mermaid-js/renovate/all-minor-patch
chore(deps): update all non-major dependencies (minor)
2023-09-14 20:29:22 +00:00
Sidharth Vinod b0b13c2d1e Fix tests 2023-09-15 01:53:46 +05:30
Sidharth Vinod 3a6abf5128 Merge pull request #1278 from mermaid-js/release-promotion
Release live editor
2023-09-15 01:40:08 +05:30
Sidharth Vinod 67ceb7ad77 fix cypress 2023-09-15 01:35:54 +05:30
Sidharth Vinod 8bba1ade92 Merge branch 'master' into release-promotion 2023-09-15 01:26:36 +05:30
renovate[bot] 6e09fa34fe chore(deps): update all non-major dependencies 2023-09-14 19:56:17 +00:00
Sidharth Vinod cf58bb1bb5 Merge pull request #1296 from mermaid-js/renovate/patch-all-minor-patch
chore(deps): update all non-major dependencies (patch)
2023-09-14 19:55:28 +00:00
renovate[bot] aa660c838b chore(deps): update all non-major dependencies 2023-09-14 16:48:03 +00:00
Sidharth Vinod d34706f1c8 Group mermaid release separately 2023-09-14 13:26:19 +05:30
Sidharth Vinod 39eba2673f Merge pull request #1283 from mermaid-js/renovate/patch-all-minor-patch
chore(deps): update all non-major dependencies (patch)
2023-09-06 06:58:29 +00:00
Sidharth Vinod ca4afee296 Merge pull request #1293 from mermaid-js/dependabot/npm_and_yarn/adobe/css-tools-4.3.1
Bump @adobe/css-tools from 4.3.0 to 4.3.1
2023-09-06 06:58:16 +00:00
renovate[bot] 60273f59a1 chore(deps): update all non-major dependencies 2023-09-05 15:13:03 +00:00
Sidharth Vinod 62d81d33b2 Merge pull request #1285 from mermaid-js/browserslist-update
build: update Browserslist db
2023-09-05 13:12:41 +00:00
Sidharth Vinod 7261334c85 Merge pull request #1292 from Yokozuna59/fix/add-missing-keywords-to-pie
fix: add missing and remove duplicate keywords in `pie`
2023-09-05 13:12:25 +00:00
GitHub Action 6b46fe4a2b build: update Browserslist db 2023-09-01 02:17:51 +00:00
GitHub Action 1698f2f5c0 build: update Browserslist db 2023-09-01 02:17:07 +00:00
dependabot[bot] 8362b3e265 Bump @adobe/css-tools from 4.3.0 to 4.3.1
Bumps [@adobe/css-tools](https://github.com/adobe/css-tools) from 4.3.0 to 4.3.1.
- [Changelog](https://github.com/adobe/css-tools/blob/main/History.md)
- [Commits](https://github.com/adobe/css-tools/commits)

---
updated-dependencies:
- dependency-name: "@adobe/css-tools"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-30 09:02:04 +00:00
Reda Al Sulais 557e54e82b fix: add missing and remove duplicate keywords in pie 2023-08-28 13:57:37 +03:00
Sidharth Vinod 1c8201a204 Add --platform linux/amd64 to run command 2023-08-17 04:31:15 +00:00
Sidharth Vinod 3e2d35a5ae Merge pull request #1279 from mermaid-js/renovate/patch-all-minor-patch
chore(deps): update all non-major dependencies (patch)
2023-08-12 14:15:58 +00:00
renovate[bot] c73f22c947 chore(deps): update all non-major dependencies 2023-08-11 17:28:03 +00:00
Sidharth Vinod f23b8b00fa Merge pull request #1274 from mermaid-js/renovate/patch-all-minor-patch
chore(deps): update all non-major dependencies (patch)
2023-08-02 18:49:31 +00:00
renovate[bot] 98d9045555 chore(deps): update all non-major dependencies 2023-08-02 18:48:10 +00:00
Sidharth Vinod ca874162fc Merge pull request #1275 from mermaid-js/renovate/all-minor-patch
chore(deps): update all non-major dependencies (minor)
2023-08-02 18:47:10 +00:00
Sidharth Vinod 18d20550fd Merge pull request #1277 from mermaid-js/browserslist-update
build: update Browserslist db
2023-08-02 18:47:02 +00:00
renovate[bot] 0bc4e098b5 chore(deps): update all non-major dependencies 2023-08-01 16:03:11 +00:00
GitHub Action f607ab4564 build: update Browserslist db 2023-08-01 02:32:24 +00:00
Sidharth Vinod 8194a3ff86 Merge pull request #1272 from mermaid-js/release-promotion
Release live editor
2023-07-28 16:59:23 +05:30
Sidharth Vinod 281af4a242 Merge pull request #1264 from mermaid-js/dependabot/npm_and_yarn/semver-5.7.2
Bump semver from 5.7.1 to 5.7.2
2023-07-27 09:29:46 +00:00
Sidharth Vinod ad86f4b678 Merge pull request #1263 from mermaid-js/release-promotion
Release live editor
2023-07-27 14:57:28 +05:30
dependabot[bot] 9e5323c9a1 Bump semver from 5.7.1 to 5.7.2
Bumps [semver](https://github.com/npm/node-semver) from 5.7.1 to 5.7.2.
- [Release notes](https://github.com/npm/node-semver/releases)
- [Changelog](https://github.com/npm/node-semver/blob/v5.7.2/CHANGELOG.md)
- [Commits](https://github.com/npm/node-semver/compare/v5.7.1...v5.7.2)

---
updated-dependencies:
- dependency-name: semver
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-27 09:22:17 +00:00
Sidharth Vinod 6829b98854 Merge pull request #1267 from mermaid-js/renovate/all-minor-patch
chore(deps): update all non-major dependencies (minor)
2023-07-27 09:20:25 +00:00
Sidharth Vinod 62a5012efd Fix node version 2023-07-27 14:46:13 +05:30
renovate[bot] 49bf28b1a2 chore(deps): update all non-major dependencies 2023-07-26 10:02:11 +00:00
Sidharth Vinod 047ba5228b Merge pull request #1269 from mermaid-js/renovate/patch-all-minor-patch
chore(deps): update all non-major dependencies (patch)
2023-07-25 13:16:44 +00:00
renovate[bot] 4bd3c35bc0 chore(deps): update all non-major dependencies 2023-07-24 22:22:29 +00:00
Sidharth Vinod b789053031 Merge pull request #1268 from mermaid-js/dependabot/npm_and_yarn/word-wrap-1.2.4
Bump word-wrap from 1.2.3 to 1.2.4
2023-07-19 07:05:02 +00:00
dependabot[bot] 9478ef0184 Bump word-wrap from 1.2.3 to 1.2.4
Bumps [word-wrap](https://github.com/jonschlinkert/word-wrap) from 1.2.3 to 1.2.4.
- [Release notes](https://github.com/jonschlinkert/word-wrap/releases)
- [Commits](https://github.com/jonschlinkert/word-wrap/compare/1.2.3...1.2.4)

---
updated-dependencies:
- dependency-name: word-wrap
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-19 02:45:04 +00:00
Sidharth Vinod e3b7a31a6b Merge pull request #1265 from mermaid-js/browserslist-update
build: update Browserslist db
2023-07-18 16:41:09 +00:00
Sidharth Vinod 157c82ba81 Merge pull request #1266 from mermaid-js/renovate/patch-all-minor-patch
chore(deps): update all non-major dependencies (patch)
2023-07-17 09:05:40 +00:00
renovate[bot] 3510ed3e63 chore(deps): update all non-major dependencies 2023-07-17 00:24:27 +00:00
GitHub Action e8d970102b build: update Browserslist db 2023-07-15 02:56:04 +00:00
Sidharth Vinod 0e5030e95d Merge pull request #1262 from mermaid-js/renovate/all-minor-patch
chore(deps): update all non-major dependencies (minor)
2023-07-10 18:21:55 +00:00
renovate[bot] 88be72cee5 chore(deps): update all non-major dependencies 2023-07-10 01:46:31 +00:00
Sidharth Vinod 0e5c4c4f5d Merge pull request #1257 from mermaid-js/release-promotion
Release live editor
2023-07-07 16:15:59 +05:30
Sidharth Vinod 1a7cbab88f Merge pull request #1256 from nirname/fix-docker-ports
Fixed docker ports for local development
2023-07-07 07:00:42 +00:00
Sidharth Vinod 30817c53f1 Merge pull request #1259 from mermaid-js/renovate/patch-all-minor-patch
chore(deps): update all non-major dependencies (patch)
2023-07-07 06:59:54 +00:00
renovate[bot] 90f1dbf176 chore(deps): update all non-major dependencies 2023-07-06 12:03:30 +00:00
Sidharth Vinod d24a9e7fda Merge pull request #1255 from mermaid-js/renovate/all-minor-patch
chore(deps): update all non-major dependencies (minor)
2023-07-02 06:14:12 +00:00
Sidharth Vinod 257dab1407 Merge pull request #1258 from mermaid-js/browserslist-update
build: update Browserslist db
2023-07-02 06:13:49 +00:00
renovate[bot] 5ebb0d2883 chore(deps): update all non-major dependencies 2023-07-01 03:53:47 +00:00
GitHub Action b8015c3a23 build: update Browserslist db 2023-07-01 03:01:01 +00:00
Sidharth Vinod 336422bd48 Merge pull request #1254 from mermaid-js/renovate/patch-all-minor-patch
chore(deps): update all non-major dependencies (patch)
2023-06-28 15:12:17 +05:30
Sidharth Vinod bc03fa4ef8 Merge pull request #1253 from mermaid-js/browserslist-update
build: update Browserslist db
2023-06-28 15:12:05 +05:30
renovate[bot] abcbd6a698 chore(deps): update all non-major dependencies 2023-06-28 07:49:02 +00:00
Nikolay Rozhkov ea0669a62b Fixed docker ports for local development 2023-06-20 03:57:09 +03:00
GitHub Action d2adcd1429 build: update Browserslist db 2023-06-15 02:35:39 +00:00
Sidharth Vinod a3c4c79788 Revert "Outbound link tracking"
This reverts commit 094f451a82.
2023-06-14 23:02:26 +05:30
Sidharth Vinod ac569f8eca Merge pull request #1252 from mermaid-js/release-promotion
Release live editor
2023-06-14 22:56:33 +05:30
Sidharth Vinod 6a1d24f2e7 Merge pull request #1251 from mermaid-js/sidv/save
Outbound link tracking
2023-06-14 22:56:02 +05:30
Sidharth Vinod f63c416a3d Update links 2023-06-14 22:55:23 +05:30
Sidharth Vinod 094f451a82 Outbound link tracking 2023-06-14 22:50:08 +05:30
Knut Sveidqvist c68ffa8cb1 Merge pull request #1250 from mermaid-js/release-promotion
Release live editor
2023-06-14 18:20:43 +02:00
Knut Sveidqvist 8e15941c35 Merge branch 'master' into release-promotion 2023-06-14 18:12:59 +02:00
Knut Sveidqvist 3444b895b1 Merge pull request #1249 from mermaid-js/sidv/save
Add save to mermaidchart button
2023-06-14 15:59:34 +00:00
Sidharth Vinod a95d02427f Add save to mermaidchart button 2023-06-14 16:25:57 +05:30
Sidharth Vinod 59f76003b3 Merge pull request #1248 from mermaid-js/release-promotion
Release live editor
2023-06-13 10:16:59 +05:30
Sidharth Vinod 68e2aa4437 Fix error alignment 2023-06-13 10:05:07 +05:30
Sidharth Vinod 471c0504c6 Merge pull request #1247 from mermaid-js/renovate/all-minor-patch
chore(deps): update all non-major dependencies (minor)
2023-06-12 11:27:39 +05:30
Sidharth Vinod 6930f3e4cc Merge pull request #1246 from mermaid-js/renovate/patch-all-minor-patch
chore(deps): update all non-major dependencies (patch)
2023-06-12 11:27:19 +05:30
renovate[bot] 9344ad88dd chore(deps): update all non-major dependencies 2023-06-12 01:14:09 +00:00
renovate[bot] 0ce87fab09 chore(deps): update all non-major dependencies 2023-06-12 01:13:57 +00:00
Sidharth Vinod aa2a2a2dd1 Merge pull request #1245 from mermaid-js/release-promotion
Release live editor
2023-06-10 23:51:21 +05:30
Sidharth Vinod 925a0acd82 Merge branch 'master' into release-promotion 2023-06-10 23:46:02 +05:30
Sidharth Vinod 2e784599b1 chore: mermaid@10.2.3 2023-06-10 23:45:19 +05:30
Sidharth Vinod a5383887ee Merge pull request #1241 from mermaid-js/release-promotion
Release live editor
2023-06-10 02:38:28 +05:30
Sidharth Vinod 6f123d6026 Add analytics comment. 2023-06-10 01:51:11 +05:30
Sidharth Vinod 78fec6411c Merge branch 'master' into develop
* master:
  Add lengthBucket
  Add QuardantChart and Mindmap to diagram types
  Update plausible
  Update license
2023-06-10 01:50:27 +05:30
Sidharth Vinod dc735e2d08 Add lengthBucket 2023-06-09 23:29:06 +05:30
Sidharth Vinod ca5610ab79 Add QuardantChart and Mindmap to diagram types 2023-06-09 23:18:52 +05:30
Sidharth Vinod 7db475acb2 Update plausible 2023-06-09 18:42:30 +05:30
Sidharth Vinod 8c9bf1ace3 Merge pull request #1242 from mermaid-js/renovate/patch-all-minor-patch
chore(deps): update all non-major dependencies (patch)
2023-06-07 17:54:55 +00:00
renovate[bot] fb54fabd1e chore(deps): update all non-major dependencies 2023-06-06 19:45:45 +00:00
Sidharth Vinod 0c690fcd0e Merge pull request #1232 from ztec/bug/1230updateDockerPort
Fix #1230 Docker: use 8080 port instead of 80 to reduce privilege requirements
2023-06-04 11:56:56 +05:30
Sidharth Vinod bb98ba3456 Merge pull request #1240 from mermaid-js/release-promotion
Release live editor
2023-06-03 15:59:18 +05:30
Sidharth Vinod fce17b96cc Merge branch 'master' into release-promotion 2023-06-03 15:52:38 +05:30
Sidharth Vinod d64f6c1a1b Merge pull request #1228 from mermaid-js/renovate/all-minor-patch
chore(deps): update all non-major dependencies (minor)
2023-06-03 10:21:43 +00:00
renovate[bot] 51fe584fb3 chore(deps): update all non-major dependencies 2023-06-03 02:10:07 +00:00
Sidharth Vinod 01b79503c9 Merge pull request #1234 from mermaid-js/renovate/patch-all-minor-patch
chore(deps): update all non-major dependencies (patch)
2023-06-03 00:21:24 +05:30
Sidharth Vinod 38ca72ce84 Merge pull request #1233 from mermaid-js/release-promotion
Release live editor
2023-06-02 18:38:14 +05:30
renovate[bot] c1542619e9 chore(deps): update all non-major dependencies 2023-06-02 13:07:45 +00:00
Sidharth Vinod 082c9f725b Merge branch 'master' into release-promotion 2023-06-02 18:37:39 +05:30
Sidharth Vinod fdbd25ca65 Merge pull request #1231 from mermaid-js/release/10.2.0
Release 10.2.0
2023-06-02 18:37:04 +05:30
Sidharth Vinod a355922f25 Merge branch 'develop' into release/10.2.0
* develop:
  build: update Browserslist db
2023-06-02 18:23:07 +05:30
Sidharth Vinod 5d6e2c71b0 Merge pull request #1239 from mermaid-js/browserslist-update
build: update Browserslist db
2023-06-02 18:22:50 +05:30
Sidharth Vinod cbafaf6cc4 Upgrade mermaid 10.2.2 2023-06-02 18:22:22 +05:30
Sidharth Vinod 28272e985d Merge branch 'develop' into release/10.2.0
* develop:
  Added quadrantChart in the live editor with sample
  chore(deps): update all non-major dependencies
2023-06-02 12:38:54 +05:30
Sidharth Vinod 87ad2d68c6 Upgrade mermaid 10.2.1 2023-06-02 12:36:46 +05:30
GitHub Action 8b1a2899cc build: update Browserslist db 2023-06-01 03:06:04 +00:00
Sidharth Vinod b1538f6bad Merge pull request #1237 from amsubhash/add-quadrantchart-to-mermaid-live-editor
Added quadrantChart in the live editor with sample
2023-05-31 08:58:45 +05:30
Subhash Halder b2b284c118 Added quadrantChart in the live editor with sample 2023-05-30 21:42:17 +05:30
Sidharth Vinod 8e2f8b6804 Merge pull request #1227 from mermaid-js/renovate/patch-all-minor-patch
chore(deps): update all non-major dependencies (patch)
2023-05-26 12:17:07 +00:00
ztec c3b711c5cd Fix #1230 Docker: use 8080 port instead of 80 to reduce privilege requirements 2023-05-26 11:01:45 +02:00
renovate[bot] e1926f0e83 chore(deps): update all non-major dependencies 2023-05-26 08:48:04 +00:00
Sidharth Vinod d2d2f4bc43 Release 10.2.0 2023-05-26 12:15:55 +05:30
Sidharth Vinod 9a46b199cf Merge pull request #1218 from mermaid-js/release-promotion
Release live editor
2023-05-17 00:43:30 +05:30
Sidharth Vinod 16ac30da7c Update license 2023-05-16 23:52:33 +05:30
Sidharth Vinod b06fd02dcb Merge pull request #1222 from mermaid-js/renovate/all-minor-patch
chore(deps): update all non-major dependencies (minor)
2023-05-16 18:15:51 +00:00
renovate[bot] 84c7f4e837 chore(deps): update all non-major dependencies 2023-05-16 17:37:06 +00:00
Sidharth Vinod bf0700853e Merge pull request #1221 from mermaid-js/renovate/patch-all-minor-patch
chore(deps): update all non-major dependencies (patch)
2023-05-16 17:36:22 +00:00
Sidharth Vinod bf90c3c0e3 Merge pull request #1224 from mermaid-js/browserslist-update
build: update Browserslist db
2023-05-16 17:36:09 +00:00
renovate[bot] d19fbd1b5b chore(deps): update all non-major dependencies 2023-05-16 07:49:38 +00:00
GitHub Action d9bc26cd59 build: update Browserslist db 2023-05-15 02:29:41 +00:00
Sidharth Vinod b1bcc5a20f Merge pull request #1220 from enchant97-forks/develop
Use nginx-unprivileged
2023-05-09 06:18:36 +00:00
Leo Spratt a8c0fb111c Use nginx-unprivileged
This allows the Docker image to run as an unprivileged user, due to
changes in Docker; the port remains as 80.
2023-05-07 18:03:19 +01:00
Sidharth Vinod 635345ea66 Merge pull request #1213 from mermaid-js/renovate/patch-all-minor-patch
chore(deps): update all non-major dependencies (patch)
2023-05-02 07:59:22 +00:00
renovate[bot] 5c4cc9a3f9 chore(deps): update all non-major dependencies 2023-05-02 05:32:20 +00:00
Sidharth Vinod dd58ac8146 Merge pull request #1217 from mermaid-js/renovate/node-20.x
chore(deps): update node.js to v20
2023-05-02 05:30:59 +00:00
renovate[bot] f3beacfae1 chore(deps): update node.js to v20 2023-05-01 06:32:50 +00:00
Sidharth Vinod ea13b2a54f Merge pull request #1216 from mermaid-js/release-promotion
Release live editor
2023-05-01 12:01:23 +05:30
Sidharth Vinod 448b47a8e3 Fix title 2023-05-01 12:00:53 +05:30
Sidharth Vinod 90407fe0d1 Change branch 2023-05-01 11:59:52 +05:30
Sidharth Vinod 85c3ddd365 change release branch name 2023-05-01 11:57:59 +05:30
Sidharth Vinod 6655a2c320 Update release-pr 2023-05-01 11:56:47 +05:30
Sidharth Vinod 52523ca6c2 Change branch 2023-05-01 11:54:30 +05:30
Sidharth Vinod 68496371f9 Merge branch 'develop' of https://github.com/mermaid-js/mermaid-live-editor into develop
* 'develop' of https://github.com/mermaid-js/mermaid-live-editor:
  build: update Browserslist db
2023-05-01 11:53:10 +05:30
Sidharth Vinod 4994bba729 Release PR 2023-05-01 11:53:05 +05:30
Sidharth Vinod d8581aca56 Merge pull request #1214 from mermaid-js/browserslist-update
build: update Browserslist db
2023-05-01 06:16:02 +00:00
GitHub Action 2d5aa85b36 build: update Browserslist db 2023-05-01 02:27:53 +00:00
Sidharth Vinod 94f8f5087f Merge pull request #1208 from mermaid-js/develop
Remove suggestions in editor
2023-04-30 22:13:52 +05:30
Sidharth Vinod 37085cce55 Merge pull request #1206 from mermaid-js/renovate/patch-all-minor-patch
Update all non-major dependencies (patch)
2023-04-29 17:24:35 +00:00
Sidharth Vinod e81a6a4eab Merge pull request #1207 from mermaid-js/renovate/all-minor-patch
Update all non-major dependencies (minor)
2023-04-29 17:24:26 +00:00
renovate[bot] f7380ab331 Update all non-major dependencies 2023-04-28 15:53:18 +00:00
renovate[bot] 72dfdf7a9a Update all non-major dependencies 2023-04-27 07:26:41 +00:00
Sidharth Vinod f209011795 Remove unnecessary completions 2023-04-27 11:31:54 +05:30
Sidharth Vinod ebbd7f252c Merge branch 'master' into develop
* master:
2023-04-25 13:42:48 +05:30
Sidharth Vinod 5f99efa611 Remove suggestions 2023-04-25 13:42:27 +05:30
Sidharth Vinod 677a00f69f Update vite 2023-04-21 23:53:45 +05:30
Sidharth Vinod 0192b86128 Merge pull request #1204 from mermaid-js/develop
Release
2023-04-20 13:01:38 +05:30
Sidharth Vinod 8e02db8e19 update sk 2023-04-20 12:55:27 +05:30
Sidharth Vinod 1d8b1221a1 Merge pull request #1205 from mermaid-js/fix/monaco
Fix/monaco
2023-04-20 07:23:36 +00:00
Sidharth Vinod 5a5ec855a9 fix Test 2023-04-20 12:47:48 +05:30
Sidharth Vinod d63e1a0356 Merge branch 'develop' into fix/monaco
* develop:
  Revert "Fix editor"
  Add loading test
  Revert "Fix/monaco (#865)"
  Fix editor
  Fix/monaco (#865)
  Fix editor broken moving between code and config
2023-04-20 12:21:49 +05:30
Sidharth Vinod 79fe5a79cd Properly load monaco workers 2023-04-20 12:20:46 +05:30
Sidharth Vinod ab0bdf1780 Properly load monaco workers 2023-04-20 12:20:31 +05:30
Sidharth Vinod b798a62d97 Merge branch 'master' into develop 2023-04-19 20:55:27 +05:30
Sidharth Vinod eea17f31dd Merge branch 'develop' of https://github.com/mermaid-js/mermaid-live-editor into develop
* 'develop' of https://github.com/mermaid-js/mermaid-live-editor:
  Revert "Fix/monaco (#865)"
2023-04-19 20:54:04 +05:30
Sidharth Vinod 7887854068 Revert "Fix editor"
This reverts commit 6448cbf19d.
2023-04-19 20:54:00 +05:30
Sidharth Vinod adb82e7da0 Add loading test 2023-04-19 20:53:32 +05:30
Sidharth Vinod 1efb5aa62e Revert "Fix/monaco (#865)"
This reverts commit 6e9453da0e.
2023-04-19 20:41:34 +05:30
Sidharth Vinod 5348de04b9 Merge pull request #1203 from mermaid-js/develop
Release
2023-04-19 19:49:57 +05:30
Sidharth Vinod 6448cbf19d Fix editor 2023-04-19 19:42:57 +05:30
Sidharth Vinod a928f99165 Merge branch 'master' into develop
* master:
  Fix/monaco (#865)
2023-04-19 19:05:57 +05:30
Sidharth Vinod 943b45849d Merge pull request #1200 from dlitsman/develop
Fix editor broken moving between code and config
2023-04-19 13:16:53 +00:00
Sidharth VinodGitHub Actionrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>github-merge-queue[bot] <118344674+github-merge-queue[bot]@users.noreply.github.com>
6e9453da0e Fix/monaco (#865)
* Fix monaco import

* Cleanup monaco

* Test fix

* Test fix

* build: update Browserslist db

* chore(deps): update all non-major dependencies

* Fix editor

---------

Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: github-merge-queue[bot] <118344674+github-merge-queue[bot]@users.noreply.github.com>
2023-04-19 18:46:20 +05:30
Sidharth Vinod b8fe37f782 Fix editor 2023-04-19 18:38:32 +05:30
Sidharth Vinod 38975c9a32 Merge branch 'develop' into fix/monaco
* develop: (356 commits)
  chore(deps): update all non-major dependencies
  build: update Browserslist db
  fix Test
  chore(deps): update all non-major dependencies
  chore(deps): update node.js to v19
  chore(deps): update dependency jsdom to v21
  chore(deps): update actions/stale action to v8
  chore(deps): update all non-major dependencies
  Bump d3-color from 3.0.1 to 3.1.0
  Did it really work??
  Reduce timeouts
  Splitup tests
  cacheBust loadSite
  Reduce timeout & retries
  Update typeInEditor
  Fix commenting test
  Fix commenting test
  Fix loadSite ?
  Fix commenting test
  Fix branch test
  ...
2023-04-19 18:33:09 +05:30
github-merge-queue[bot] fd189c2dfe Merge pull request #1199 from mermaid-js/browserslist-update
build: update Browserslist db
2023-04-19 06:51:01 +00:00
github-merge-queue[bot] 335c19d04e Merge pull request #1201 from mermaid-js/renovate/patch-all-minor-patch
chore(deps): update all non-major dependencies (patch)
2023-04-19 06:48:43 +00:00
renovate[bot] ae0e1059dd chore(deps): update all non-major dependencies 2023-04-18 13:29:28 +00:00
Dmitry Litsman a0ccc8f94a Fix editor broken moving between code and config 2023-04-16 15:07:33 +01:00
GitHub Action 12cbbd3567 build: update Browserslist db 2023-04-15 02:25:15 +00:00
Sidharth Vinod d3f2b81639 Merge pull request #1197 from mermaid-js/develop
Deps
2023-04-13 17:57:14 +05:30
Sidharth Vinod b770dd46d5 fix Test 2023-04-13 17:51:47 +05:30
Sidharth Vinod b5ae544932 Merge pull request #1155 from mermaid-js/renovate/all-minor-patch
chore(deps): update all non-major dependencies (minor)
2023-04-13 12:05:57 +00:00
Sidharth Vinod 222d1f2f01 Merge branch 'master' into develop 2023-04-13 17:35:33 +05:30
renovate[bot] c74d604bac chore(deps): update all non-major dependencies 2023-04-13 12:03:30 +00:00
Sidharth Vinod d688544fc5 Merge pull request #1196 from mermaid-js/renovate/node-19.x
chore(deps): update node.js to v19
2023-04-13 12:02:27 +00:00
Sidharth Vinod aeff048783 Merge pull request #1195 from mermaid-js/renovate/jsdom-21.x
chore(deps): update dependency jsdom to v21
2023-04-13 12:02:20 +00:00
Sidharth Vinod 4b2b36bbae Merge pull request #1194 from mermaid-js/renovate/actions-stale-8.x
chore(deps): update actions/stale action to v8
2023-04-13 12:02:13 +00:00
renovate[bot] 6282001d9b chore(deps): update node.js to v19 2023-04-13 12:02:06 +00:00
Sidharth Vinod 6ad555fbd8 Merge pull request #1170 from mermaid-js/dependabot/npm_and_yarn/d3-color-3.1.0
Bump d3-color from 3.0.1 to 3.1.0
2023-04-13 12:02:03 +00:00
renovate[bot] 506ead98fc chore(deps): update dependency jsdom to v21 2023-04-13 12:02:02 +00:00
Sidharth Vinod 23dba5aaac Merge pull request #1169 from mermaid-js/dependabot/npm_and_yarn/braintree/sanitize-url-6.0.2
Bump @braintree/sanitize-url from 6.0.0 to 6.0.2
2023-04-13 12:01:49 +00:00
renovate[bot] 00ebee9438 chore(deps): update actions/stale action to v8 2023-04-13 12:01:46 +00:00
Sidharth Vinod 07d312c84c Merge pull request #1154 from mermaid-js/renovate/patch-all-minor-patch
chore(deps): update all non-major dependencies (patch)
2023-04-13 12:00:51 +00:00
Sidharth Vinod db5506077a Merge pull request #1193 from mermaid-js/develop
10.1.0
2023-04-13 17:30:01 +05:30
renovate[bot] 172a9950b4 chore(deps): update all non-major dependencies 2023-04-13 11:54:14 +00:00
dependabot[bot] 7e112c76c7 Bump d3-color from 3.0.1 to 3.1.0
Bumps [d3-color](https://github.com/d3/d3-color) from 3.0.1 to 3.1.0.
- [Release notes](https://github.com/d3/d3-color/releases)
- [Commits](https://github.com/d3/d3-color/compare/v3.0.1...v3.1.0)

---
updated-dependencies:
- dependency-name: d3-color
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-13 11:53:47 +00:00
Sidharth Vinod a12efbc4e7 Merge pull request #1192 from mermaid-js/release/10.1.0
"mermaid": "10.1.0"
2023-04-13 11:51:27 +00:00
Sidharth Vinod 3febc39331 Did it really work?? 2023-04-13 17:16:31 +05:30
Sidharth Vinod 1daca60eab Reduce timeouts 2023-04-13 17:10:52 +05:30
Sidharth Vinod c43c691070 Splitup tests 2023-04-13 17:09:37 +05:30
Sidharth Vinod 0301aa1a06 cacheBust loadSite 2023-04-13 17:01:57 +05:30
Sidharth Vinod 97472ca368 Reduce timeout & retries 2023-04-13 16:50:47 +05:30
Sidharth Vinod e789adf5f8 Update typeInEditor 2023-04-13 16:44:07 +05:30
Sidharth Vinod c821848b74 Fix commenting test 2023-04-13 16:42:12 +05:30
Sidharth Vinod 6fc44e06ed Fix commenting test 2023-04-13 16:38:32 +05:30
Sidharth Vinod 28452a8b7d Fix loadSite ? 2023-04-13 16:35:31 +05:30
Sidharth Vinod e5a4e7b997 Fix commenting test 2023-04-13 16:31:02 +05:30
Sidharth Vinod d364cdfd83 Fix branch test 2023-04-13 13:00:46 +05:30
Sidharth Vinod 982ef0377f Fix tests 2023-04-13 12:40:09 +05:30
Sidharth Vinod 8a13644b9a Merge branch 'develop' into release/10.1.0
* develop:
  build: update Browserslist db
2023-04-13 12:13:29 +05:30
Sidharth Vinod 5c19c117cf Update other deps 2023-04-13 12:08:01 +05:30
Sidharth Vinod 46907e5fa3 Merge pull request #1182 from mermaid-js/browserslist-update
build: update Browserslist db
2023-04-13 06:29:29 +00:00
dependabot[bot] 61fb92ea68 Bump @braintree/sanitize-url from 6.0.0 to 6.0.2
Bumps [@braintree/sanitize-url](https://github.com/braintree/sanitize-url) from 6.0.0 to 6.0.2.
- [Release notes](https://github.com/braintree/sanitize-url/releases)
- [Changelog](https://github.com/braintree/sanitize-url/blob/main/CHANGELOG.md)
- [Commits](https://github.com/braintree/sanitize-url/compare/v6.0.0...v6.0.2)

---
updated-dependencies:
- dependency-name: "@braintree/sanitize-url"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-13 06:28:47 +00:00
Sidharth Vinod e5afb85239 "mermaid": "10.1.0" 2023-04-13 11:58:34 +05:30
Sidharth Vinod 8edce6a3c1 Revert ""mermaid": "10.1.0""
This reverts commit d4fadaff24.
2023-04-13 11:57:49 +05:30
Sidharth Vinod d4fadaff24 "mermaid": "10.1.0" 2023-04-13 00:00:40 +05:30
GitHub Action 19d7be1058 build: update Browserslist db 2023-04-01 02:25:11 +00:00
Sidharth Vinod bf6c54c00e Merge branch 'master' into develop
* master:
  feat: Add mermaidchart logo
2023-03-16 00:41:56 +05:30
Sidharth Vinod f6344341ef feat: Add mermaidchart logo 2023-03-16 00:39:36 +05:30
Sidharth Vinod 3874aa48fc Merge pull request #1177 from mermaid-js/browserslist-update
build: update Browserslist db
2023-03-15 11:31:54 +00:00
GitHub Action cb43694063 build: update Browserslist db 2023-03-15 02:33:54 +00:00
Sidharth Vinod 8215f56eba Merge pull request #1168 from mermaid-js/browserslist-update
build: update Browserslist db
2023-03-03 08:49:58 +00:00
GitHub Action 395e0a558b build: update Browserslist db 2023-03-01 02:54:27 +00:00
Sidharth Vinod 1605536f13 Merge pull request #1164 from mermaid-js/develop
Release v10
2023-02-24 10:51:07 +05:30
Sidharth Vinod 7dc59f1396 Merge pull request #1160 from mermaid-js/release/10.0.0
Release/10.0.0
2023-02-24 10:50:07 +05:30
Sidharth Vinod 59168d2437 fix: re enable uncompressed URL test 2023-02-24 10:37:29 +05:30
Sidharth Vinod 5a6dccb263 fix: Comment test caret location 2023-02-24 10:36:20 +05:30
Sidharth Vinod 6c16fa76ff fix: Adjust image size 2023-02-24 10:32:10 +05:30
Sidharth Vinod ccbb45a09c fix: E2e Tests 2023-02-24 10:10:52 +05:30
Sidharth Vinod 052665ef09 Actions, default closed 2023-02-22 10:01:16 +05:30
Sidharth Vinod ee1652e9f2 v10 2023-02-21 17:46:00 +05:30
Sidharth Vinod bbd6378065 v10 changes 2023-02-19 20:09:42 +05:30
Sidharth Vinod e93641e41f Release v10 2023-02-19 19:49:50 +05:30
Sidharth Vinod 5925448ca4 Replace moment with dayjs 2023-02-19 00:14:57 +05:30
Sidharth Vinod 5e930d19e7 Merge remote-tracking branch 'origin/develop' into release/9.4
* origin/develop:
  Fix browserlist base branch
  build: update Browserslist db
  Move browserlist update to cron
  Update Browserslist
  Update snapshots
  Fix Preset
  Update Browserslist
  chore(deps): update all non-major dependencies
  chore(deps): update all non-major dependencies
  chore: Cleanup with eslint-unicorn
  Fix tests
  Fix tests
  Update loadSite.spec.ts
  Update snapshots.js
  Also changed 'graph' to 'flowchart' on state.ts
  Replacing "chart" with "flowchart"
2023-02-16 21:04:47 +05:30
Sidharth Vinod 131dd06cde Merge pull request #1158 from mermaid-js/develop
Release 9.4
2023-02-16 21:02:05 +05:30
Sidharth Vinod e96225dc69 Merge branch 'master' into develop 2023-02-16 18:02:16 +05:30
Sidharth Vinod 3a42afd102 Merge pull request #1156 from mermaid-js/browserslist-update
build: update Browserslist db
2023-02-16 17:34:26 +05:30
Sidharth Vinod 5394074ac5 Fix browserlist base branch 2023-02-16 17:33:42 +05:30
Sidharth Vinod 20358bc254 Remove mindmap 2023-02-16 15:56:30 +05:30
Sidharth Vinod 6ece0a8a94 comment out consoles 2023-02-16 15:55:07 +05:30
Sidharth Vinod 71f4097fa0 Log SVG code 2023-02-16 15:51:53 +05:30
Sidharth Vinod 308aec1580 Merge branch 'release/9.4' of https://github.com/mermaid-js/mermaid-live-editor into release/9.4
* 'release/9.4' of https://github.com/mermaid-js/mermaid-live-editor:
  Update Browserslist
2023-02-16 15:48:06 +05:30
Sidharth Vinod 8c07649b10 Remove mindmap 2023-02-16 15:48:02 +05:30
sidharthv96 3a1b8f87c3 Update Browserslist 2023-02-16 10:02:52 +00:00
Sidharth Vinod af4f60874e 9.4.0 2023-02-16 15:31:31 +05:30
GitHub Action e5f303e6e2 build: update Browserslist db 2023-02-15 02:44:06 +00:00
Sidharth Vinod e461f108f1 Merge pull request #1106 from mermaid-js/sidv/eslint-unicorn
Cleanup with eslint-unicorn
2023-02-10 19:25:54 +00:00
Sidharth Vinod 64519ba8a1 Merge pull request #1153 from mermaid-js/sidv/browserlist
Move browserlist update to cron
2023-02-10 19:09:03 +00:00
Sidharth Vinod ec5937b4fb Move browserlist update to cron 2023-02-11 00:32:39 +05:30
sidharthv96 10a11cfc32 Update Browserslist 2023-02-10 18:53:40 +00:00
Sidharth Vinod 9ebbd3b36c Merge remote-tracking branch 'origin/develop' into sidv/eslint-unicorn
* origin/develop: (51 commits)
  Update snapshots
  Fix Preset
  Update Browserslist
  chore(deps): update all non-major dependencies
  chore(deps): update all non-major dependencies
  chore(deps): update dependency eslint to v8.33.0
  chore(deps): update all non-major dependencies
  chore(deps): update all non-major dependencies
  chore(deps): update all non-major dependencies
  chore(deps): update all non-major dependencies
  chore(deps): update dependency eslint to v8.30.0
  Fix links
  chore(deps): update all non-major dependencies
  SvelteKit 1.0!
  Update sveltekit
  Skip updatebrowserslit on renovate
  v9.3.0
  mermaid 9.3.0-rc.7
  Fix vite.config.js typing
  mermaid 9.3.0-rc.6
  ...
2023-02-11 00:22:23 +05:30
Sidharth Vinod 9e25c2d2c4 Merge pull request #654 from victorp13/patch-1
Replacing "graph" with "flowchart"
2023-02-08 12:43:51 +05:30
Sidharth Vinod 9853442201 Update snapshots 2023-02-08 00:16:46 +05:30
Sidharth Vinod ebca0ebe34 Merge pull request #1151 from mermaid-js/renovate/all-minor-patch
chore(deps): update all non-major dependencies (minor)
2023-02-08 00:15:29 +05:30
Sidharth Vinod abb2405436 Merge branch 'patch-1' of https://github.com/victorp13/mermaid-live-editor into pr/victorp13/654
* 'patch-1' of https://github.com/victorp13/mermaid-live-editor:
  Update Browserslist
2023-02-08 00:09:31 +05:30
Sidharth Vinod a6b1254425 Fix Preset 2023-02-08 00:09:26 +05:30
sidharthv96 95bf41d3e6 Update Browserslist 2023-02-07 18:38:28 +00:00
Sidharth Vinod 68f81df59b Merge remote-tracking branch 'origin/develop' into pr/victorp13/654
* origin/develop: (509 commits)
  chore(deps): update all non-major dependencies
  chore(deps): update dependency eslint to v8.33.0
  chore(deps): update all non-major dependencies
  chore(deps): update all non-major dependencies
  chore(deps): update all non-major dependencies
  chore(deps): update all non-major dependencies
  chore(deps): update dependency eslint to v8.30.0
  Fix links
  chore(deps): update all non-major dependencies
  SvelteKit 1.0!
  Update sveltekit
  Skip updatebrowserslit on renovate
  v9.3.0
  mermaid 9.3.0-rc.7
  Fix vite.config.js typing
  mermaid 9.3.0-rc.6
  rc.5
  fix: Adjust image size
  Update to rc.4
  Update to rc.3
  ...
2023-02-08 00:05:14 +05:30
renovate[bot] d3b25e5cb8 chore(deps): update all non-major dependencies 2023-02-07 18:30:45 +00:00
Sidharth Vinod 65c1ea844c Merge pull request #1145 from mermaid-js/renovate/patch-all-minor-patch
chore(deps): update all non-major dependencies (patch)
2023-02-07 23:59:00 +05:30
renovate[bot] 864988e24a chore(deps): update all non-major dependencies 2023-02-07 09:28:56 +00:00
sidharthv96 2fc032f58a Update Browserslist 2023-01-31 16:36:15 +00:00
Sidharth Vinod 2033e9002f 9.4.0-rc.1 2023-01-31 22:04:56 +05:30
Sidharth Vinod 651a5cb7ef Merge pull request #1146 from mermaid-js/renovate/all-minor-patch
chore(deps): update dependency eslint to v8.33.0
2023-01-30 09:20:01 +05:30
renovate[bot] a7454aa8cb chore(deps): update dependency eslint to v8.33.0 2023-01-30 02:01:16 +00:00
Sidharth Vinod 43ff34178e Merge pull request #1142 from mermaid-js/renovate/all-minor-patch
chore(deps): update all non-major dependencies (minor)
2023-01-29 01:19:45 +05:30
renovate[bot] 703744ebf3 chore(deps): update all non-major dependencies 2023-01-27 20:34:14 +00:00
Sidharth Vinod 15eaee6e9b Merge pull request #1120 from mermaid-js/renovate/patch-all-minor-patch
chore(deps): update all non-major dependencies (patch)
2023-01-21 22:47:07 +05:30
renovate[bot] fa9b0344f4 chore(deps): update all non-major dependencies 2023-01-21 14:29:26 +00:00
Sidharth Vinod 965b39c2f2 Merge pull request #1138 from mermaid-js/renovate/all-minor-patch
chore(deps): update all non-major dependencies (minor)
2023-01-17 21:38:40 +05:30
renovate[bot] 26908080cb chore(deps): update all non-major dependencies 2023-01-16 18:05:56 +00:00
Sidharth Vinod 7c64a65497 Merge pull request #1128 from mermaid-js/renovate/all-minor-patch
chore(deps): update all non-major dependencies (minor)
2022-12-27 13:06:37 +05:30
renovate[bot] be75d950bd chore(deps): update all non-major dependencies 2022-12-26 21:02:04 +00:00
Sidharth Vinod 4022d8d872 Merge pull request #1127 from mermaid-js/renovate/all-minor-patch
chore(deps): update dependency eslint to v8.30.0
2022-12-19 10:24:48 +05:30
renovate[bot] ccb294e5df chore(deps): update dependency eslint to v8.30.0 2022-12-19 02:44:15 +00:00
Sidharth Vinod 8d1f3f08f8 Merge branch 'develop' of https://github.com/mermaid-js/mermaid-live-editor into develop
* 'develop' of https://github.com/mermaid-js/mermaid-live-editor:
  chore(deps): update all non-major dependencies
2022-12-17 00:17:50 +05:30
Sidharth Vinod a12e9a3e6d Fix links 2022-12-17 00:17:44 +05:30
Sidharth Vinod c138e1dc94 Merge pull request #1121 from mermaid-js/renovate/all-minor-patch
chore(deps): update all non-major dependencies (minor)
2022-12-17 00:15:30 +05:30
renovate[bot] 74431cdc08 chore(deps): update all non-major dependencies 2022-12-15 15:09:41 +00:00
Sidharth Vinod 0812b84487 Merge pull request #1124 from mermaid-js/develop
Svelte Kit 1.0 🥳 🍾
2022-12-15 17:50:45 +05:30
Sidharth Vinod cfc5567980 SvelteKit 1.0! 2022-12-15 17:42:40 +05:30
Sidharth Vinod 096f005938 Merge branch 'develop' of https://github.com/mermaid-js/mermaid-live-editor into develop
* 'develop' of https://github.com/mermaid-js/mermaid-live-editor:
  v9.3.0
  mermaid 9.3.0-rc.7
  Fix vite.config.js typing
  mermaid 9.3.0-rc.6
  rc.5
  fix: Adjust image size
  Update to rc.4
  Update to rc.3
  Remove card snapshot
  Update snapshot
  Update to rc.2
  Update Browserslist
  9.3.0-rc.1
2022-12-15 17:31:41 +05:30
Sidharth Vinod 37d96f9a87 Merge pull request #1123 from mermaid-js/develop
Release 9.3.0
2022-12-15 17:31:14 +05:30
Sidharth Vinod 8c4b7d52d1 Update sveltekit 2022-12-15 17:30:58 +05:30
Sidharth Vinod cc7411fef8 Merge pull request #1119 from mermaid-js/release/9.3
9.3.0
2022-12-15 17:23:26 +05:30
Sidharth Vinod 1382504456 Skip updatebrowserslit on renovate 2022-12-15 17:20:39 +05:30
Sidharth Vinod 860039a924 v9.3.0 2022-12-15 17:18:24 +05:30
Sidharth Vinod 33a4cbbf78 mermaid 9.3.0-rc.7 2022-12-15 09:15:35 +05:30
Sidharth Vinod 7be86b5fa7 Fix vite.config.js typing 2022-12-14 10:18:21 +05:30
Sidharth Vinod b835e0448d mermaid 9.3.0-rc.6 2022-12-14 09:46:51 +05:30
Sidharth Vinod 7c5f9f1661 rc.5 2022-12-13 13:46:35 +05:30
Sidharth Vinod 0a34cbe9c7 fix: Adjust image size 2022-12-13 12:19:02 +05:30
Sidharth Vinod a2146da8e1 Update to rc.4 2022-12-13 00:40:18 +05:30
Sidharth Vinod d23de5f9e0 Update to rc.3 2022-12-13 00:24:54 +05:30
Sidharth Vinod 7d18fa6b95 Remove card snapshot 2022-12-13 00:11:03 +05:30
Sidharth Vinod 8dbb011b98 Update snapshot 2022-12-13 00:08:20 +05:30
Sidharth Vinod 4c398ed8dd Merge branch 'release/9.3' of https://github.com/mermaid-js/mermaid-live-editor into release/9.3
* 'release/9.3' of https://github.com/mermaid-js/mermaid-live-editor:
  Update Browserslist
2022-12-12 23:58:04 +05:30
Sidharth Vinod 532e7a6537 Update to rc.2 2022-12-12 23:57:59 +05:30
Sidharth Vinod 049635cf3a Update docs button title 2022-12-12 22:34:09 +05:30
sidharthv96 c06511f11f Update Browserslist 2022-12-09 07:14:05 +00:00
Sidharth Vinod e6adff074a 9.3.0-rc.1 2022-12-09 12:42:48 +05:30
Sidharth Vinod 55988eb750 Merge pull request #1115 from mermaid-js/renovate/patch-all-minor-patch
chore(deps): update all non-major dependencies (patch)
2022-12-06 23:05:09 +05:30
Sidharth Vinod e368a20b8d Merge pull request #1116 from mermaid-js/renovate/all-minor-patch
chore(deps): update all non-major dependencies (minor)
2022-12-06 23:04:45 +05:30
Sidharth Vinod 3cc56a0348 Merge pull request #1117 from aswinthaikkat/updatereadme
docs: Improve installation steps
2022-12-06 22:34:29 +05:30
aswin 36b7aba2f4 docs: Add dependency install step 2022-12-06 22:33:16 +05:30
aswin 54485ac068 docs: Improve installation steps 2022-12-06 22:22:41 +05:30
renovate[bot] fc6cf1f014 Update Browserslist 2022-12-05 01:28:05 +00:00
renovate[bot] 048f280b8e Update Browserslist 2022-12-05 01:27:32 +00:00
renovate[bot] 19f26ce4b9 chore(deps): update all non-major dependencies 2022-12-05 01:26:57 +00:00
renovate[bot] 6f115d4ac2 chore(deps): update all non-major dependencies 2022-12-05 01:26:30 +00:00
Sidharth Vinod 347d669c9c Merge pull request #1109 from mermaid-js/develop
Release
2022-11-30 14:25:43 +05:30
Sidharth Vinod df7da711a9 Merge branch 'master' into develop 2022-11-30 14:19:16 +05:30
Sidharth Vinod 282dfcc701 Merge pull request #1114 from lagraham337/develop
Nav: Fixed broken tutorial link
2022-11-30 14:18:24 +05:30
Lauren Graham 998c5f7fd9 Nav: Fixed broken tutorial link 2022-11-29 20:54:26 -08:00
Sidharth Vinod 6c907c48c7 Merge pull request #1113 from mermaid-js/renovate/patch-all-minor-patch
chore(deps): update all non-major dependencies (patch)
2022-11-28 10:33:29 +05:30
renovate[bot] fe981b7646 chore(deps): update all non-major dependencies 2022-11-28 01:03:14 +00:00
Sidharth Vinod e36b1d42e4 chore: Skip uncompressed URL test 2022-11-25 16:15:01 +05:30
Sidharth Vinod a62a65ea05 Try something 2022-11-25 14:33:49 +05:30
Sidharth Vinod d9cdab3528 test: Change test order 2022-11-25 14:28:45 +05:30
Sidharth Vinod 5b3b0a499e Merge pull request #1108 from mermaid-js/develop
Release
2022-11-25 14:19:21 +05:30
Sidharth Vinod 1b6a1910ce Merge pull request #1107 from mermaid-js/sidv/betterErrors
Show properly formatted error messages.
2022-11-25 13:32:58 +05:30
Sidharth Vinod f794fa9e0e chore: cleanup 2022-11-25 13:25:20 +05:30
Sidharth Vinod 17ca5f29d0 fix: Error type 2022-11-25 13:23:42 +05:30
Sidharth Vinod b7aae5f94f chore: Bump node 2022-11-25 13:19:12 +05:30
Sidharth Vinod 6888765e37 Merge branch 'master' into sidv/eslint-unicorn
* master:
2022-11-25 13:06:08 +05:30
Sidharth Vinod 25e186158d chore: Cleanup with eslint-unicorn 2022-11-25 13:05:57 +05:30
Sidharth Vinod ffd68c7551 Show good error messages. 2022-11-25 12:11:11 +05:30
Sidharth Vinod 909b95ba7b Merge pull request #1105 from mermaid-js/renovate/patch-all-minor-patch
chore(deps): update all non-major dependencies (patch)
2022-11-25 11:27:44 +05:30
Sidharth Vinod f4dd01c4fe chore: fix trailing slash 2022-11-25 11:17:30 +05:30
renovate[bot] 7508a555d4 chore(deps): update all non-major dependencies 2022-11-24 22:05:13 +00:00
Sidharth Vinod 4453a04a05 Merge pull request #1104 from mermaid-js/develop
Release
2022-11-24 22:14:04 +05:30
Sidharth Vinod 9d3a33e593 Block only tests 2022-11-24 22:07:14 +05:30
Sidharth Vinod 0378cd4ba6 Merge branch 'sidv/fixEditorHang' into develop
* sidv/fixEditorHang:
  Remove it.only
2022-11-24 22:05:27 +05:30
Sidharth Vinod c518217ba7 Merge branch 'develop' of https://github.com/mermaid-js/mermaid-live-editor into develop
* 'develop' of https://github.com/mermaid-js/mermaid-live-editor:
  fix #1103
  fix: Remove AsyncQueue
  Update Browserslist
2022-11-24 22:04:52 +05:30
Sidharth Vinod c9a2e6bf09 snapshot 2022-11-24 22:04:48 +05:30
Sidharth Vinod f136f7bd58 Remove it.only 2022-11-24 22:04:15 +05:30
Sidharth Vinod 03d2be91e6 Merge pull request #1099 from mermaid-js/sidv/fixEditorHang
Remove AsyncQueue
2022-11-24 22:03:50 +05:30
Sidharth Vinod 3e6c28f15a fix #1103 2022-11-24 21:56:20 +05:30
Sidharth Vinod 2b800e960d Merge branch 'develop' into sidv/fixEditorHang
* develop:
  chore(deps): update all non-major dependencies
  Update Browserslist
  chore: Update deps
2022-11-24 21:26:47 +05:30
Sidharth Vinod 06bd4cf176 Merge pull request #1101 from mermaid-js/renovate/all-minor-patch
chore(deps): update all non-major dependencies (minor)
2022-11-24 21:16:10 +05:30
renovate[bot] 42a55e10a6 chore(deps): update all non-major dependencies 2022-11-24 14:57:03 +00:00
Sidharth Vinod 996db3b198 Merge pull request #1100 from mermaid-js/sidv/updateDeps
chore: Update deps
2022-11-24 20:24:51 +05:30
sidharthv96 7a598f408c Update Browserslist 2022-11-24 10:56:27 +00:00
Sidharth Vinod 924d10aac3 chore: Update deps 2022-11-24 16:25:12 +05:30
Sidharth Vinod 22df217b44 Merge branch 'sidv/fixEditorHang' of https://github.com/mermaid-js/mermaid-live-editor into sidv/fixEditorHang
* 'sidv/fixEditorHang' of https://github.com/mermaid-js/mermaid-live-editor:
  Update Browserslist
2022-11-24 16:20:08 +05:30
Sidharth Vinod 7c4c2a02f9 fix: Remove AsyncQueue 2022-11-24 16:20:01 +05:30
sidharthv96 20c6e9146c Update Browserslist 2022-11-24 10:30:12 +00:00
Sidharth Vinod afeb649833 Merge pull request #1095 from mermaid-js/develop
Release: Fix editor hang
2022-11-17 13:20:15 +05:30
Sidharth Vinod fcf53c98c2 Merge pull request #1094 from mermaid-js/sidv/fixEditorHang
Fix #1089: Update monaco-mermaid
2022-11-17 13:19:04 +05:30
Sidharth Vinod 749968e0f5 Fix #1089: Update monaco-mermaid 2022-11-17 11:21:21 +05:30
Sidharth Vinod ba56f08370 Merge pull request #1091 from mermaid-js/develop
Release
2022-11-15 20:43:45 +05:30
Sidharth Vinod d92bf85009 Merge pull request #1092 from mermaid-js/renovate/all-minor-patch
chore(deps): update all non-major dependencies (minor)
2022-11-15 20:33:03 +05:30
renovate[bot] 6936dc5755 chore(deps): update all non-major dependencies 2022-11-15 14:50:54 +00:00
Sidharth Vinod b41ff80d9d Merge pull request #1090 from mermaid-js/sidv/capitalizeSvelteComponents
chore: Capitalize components to be inline with svelte standards
2022-11-15 20:15:21 +05:30
Sidharth Vinod 68ab43ac5d fix lint 2022-11-15 19:59:13 +05:30
Sidharth Vinod 68b589a33a chore: Cleanup, fix theme 2022-11-15 19:51:00 +05:30
Sidharth Vinod 9eb39f31a0 fix: Snapshot, env types 2022-11-15 19:00:46 +05:30
Sidharth Vinod 08eaf725b9 chore: Cleanup potentially problematic code. 2022-11-15 18:57:33 +05:30
Sidharth Vinod 85ad89b915 chore: Cleanup potentially
problematic code.
2022-11-15 18:48:16 +05:30
Sidharth Vinod 60c352a849 Fix casing 2022-11-15 17:05:14 +05:30
Sidharth Vinod b0aa0a9cb2 fix: Type errors 2022-11-15 17:03:25 +05:30
Sidharth Vinod 34dafa13c9 test commit 2022-11-15 16:29:49 +05:30
Sidharth Vinod 684bd708de test commit 2022-11-15 16:29:05 +05:30
Sidharth Vinod d5ee6d4c02 Fix card.test.ts 2022-11-15 16:14:41 +05:30
Sidharth Vinod 233f1822d1 chore: Rename components 2022-11-15 16:04:36 +05:30
Sidharth Vinod 6167503246 Merge branch 'develop' into fix/monaco
* develop: (23 commits)
  Fix test
  Fix test
  Fix test
  Fix security formatting.
  Fix cypress
  Pin versions; Fix svelte kit
  Cypress
  Remove mocha
  Add dom testing
  Add vitest
  Add check before typing
  Split vite config
  Update kit
  Update Browserslist
  Add license
  chore(deps): bump mermaid from 9.1.2 to 9.1.3 (#877)
  chore(deps-dev): bump lint-staged from 13.0.2 to 13.0.3 (#872)
  Update Browserslist
  chore(deps-dev): bump cypress from 10.2.0 to 10.3.0 (#873)
  chore(deps-dev): bump @sveltejs/kit (#871)
  ...
2022-07-07 11:59:58 +05:30
Sidharth Vinod f7544d0d9a Test fix 2022-06-28 17:59:23 +05:30
Sidharth Vinod 705f257cc1 Test fix 2022-06-28 16:30:22 +05:30
Sidharth Vinod d2b0ae012f Cleanup monaco 2022-06-28 15:51:05 +05:30
Sidharth Vinod 44c6e2848e Fix monaco import 2022-06-28 15:13:08 +05:30
Sidharth Vinod bf06bdf71a Fix tests 2022-02-22 23:05:18 +05:30
Sidharth Vinod 68a0d29320 Fix tests 2022-02-22 22:28:32 +05:30
Victor Pikula 14ac5f23a5 Update loadSite.spec.ts 2022-02-22 15:17:57 +01:00
Victor Pikula e7676cf4a8 Update snapshots.js 2022-02-22 15:17:19 +01:00
Victor Pikula 0f34a76ded Also changed 'graph' to 'flowchart' on state.ts 2022-02-21 15:51:32 +01:00
Victor Pikula ee934c60b4 Replacing "chart" with "flowchart"
Since the documentation mentions "flowchart" in the example pages, it makes more sense to also show a flowchart as the first example loaded in the editor. It looks to me like "graph" was deprecated? Not 100% sure.
2022-02-16 09:36:26 +01:00
67 changed files with 4714 additions and 3154 deletions
+53 -3
View File
@@ -5,9 +5,19 @@ module.exports = {
'eslint:recommended', 'eslint:recommended',
'plugin:@typescript-eslint/recommended', 'plugin:@typescript-eslint/recommended',
// 'plugin:@typescript-eslint/recommended-requiring-type-checking', // 'plugin:@typescript-eslint/recommended-requiring-type-checking',
'plugin:@typescript-eslint/strict',
'plugin:unicorn/recommended',
'prettier' 'prettier'
], ],
plugins: ['svelte3', 'tailwindcss', '@typescript-eslint', 'es', 'vitest'], plugins: [
'svelte3',
'tailwindcss',
'@typescript-eslint',
'es',
'vitest',
'no-only-tests',
'unicorn'
],
ignorePatterns: [ ignorePatterns: [
'docs/*', 'docs/*',
'*.cjs', '*.cjs',
@@ -19,7 +29,19 @@ module.exports = {
'package.json', 'package.json',
'tsconfig.json' 'tsconfig.json'
], ],
overrides: [{ files: ['*.svelte'], processor: 'svelte3/svelte3' }], overrides: [
{ files: ['*.svelte'], processor: 'svelte3/svelte3' },
{
files: ['*.ts'],
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:@typescript-eslint/recommended-requiring-type-checking',
'plugin:@typescript-eslint/strict',
'prettier'
]
}
],
settings: { settings: {
'svelte3/typescript': () => require('typescript') 'svelte3/typescript': () => require('typescript')
}, },
@@ -45,6 +67,34 @@ module.exports = {
'@typescript-eslint/no-unsafe-member-access': 'off', '@typescript-eslint/no-unsafe-member-access': 'off',
'@typescript-eslint/no-unsafe-assignment': 'off', '@typescript-eslint/no-unsafe-assignment': 'off',
'es/no-regexp-lookbehind-assertions': 'error', 'es/no-regexp-lookbehind-assertions': 'error',
curly: ['error', 'all'] curly: ['error', 'all'],
'no-only-tests/no-only-tests': 'error',
'unicorn/no-null': 'off',
'unicorn/filename-case': [
'error',
{
case: 'camelCase'
}
],
'unicorn/prevent-abbreviations': [
'error',
{
allowList: {
ctx: true,
db: true,
doc: true,
env: true,
fn: true,
i: true,
param: true,
req: true,
res: true,
str: true,
searchParams: true,
temp: true,
ImportMetaEnv: true
}
}
]
} }
}; };
+1 -1
View File
@@ -16,7 +16,7 @@ jobs:
- uses: actions/setup-node@v3 - uses: actions/setup-node@v3
with: with:
node-version: '16' node-version: 18
cache: yarn cache: yarn
- name: Build & Deploy - name: Build & Deploy
+21
View File
@@ -0,0 +1,21 @@
name: Create release pull request
on:
push:
branches:
- develop
jobs:
productionPromotion:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
ref: master
- name: Reset promotion branch
run: |
git fetch origin develop:develop
git reset --hard develop
- name: Create Pull Request
uses: peter-evans/create-pull-request@v5
with:
branch: release-promotion
title: Release live editor
+1 -1
View File
@@ -8,7 +8,7 @@ jobs:
stale: stale:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/stale@v6 - uses: actions/stale@v8
with: with:
repo-token: ${{ secrets.GITHUB_TOKEN }} repo-token: ${{ secrets.GITHUB_TOKEN }}
exempt-issue-labels: 'retained' exempt-issue-labels: 'retained'
+1 -1
View File
@@ -32,7 +32,7 @@ jobs:
- uses: actions/setup-node@v3 - uses: actions/setup-node@v3
with: with:
node-version: 16 node-version: 18
cache: 'yarn' cache: 'yarn'
# Install NPM dependencies, cache them correctly # Install NPM dependencies, cache them correctly
+1 -1
View File
@@ -26,7 +26,7 @@ jobs:
- uses: actions/setup-node@v3 - uses: actions/setup-node@v3
with: with:
node-version: 16 node-version: 18
cache: 'yarn' cache: 'yarn'
- name: Lint & Test - name: Lint & Test
+27 -13
View File
@@ -1,18 +1,32 @@
name: Update Browserslist name: Update Browserslist database
on: on:
push: schedule:
branches-ignore: - cron: '0 2 1,15 * *'
- 'develop'
- 'master' permissions:
contents: write
pull-requests: write
jobs: jobs:
build: update-browserslist-database:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - name: Checkout repository
- run: npx browserslist@latest --update-db uses: actions/checkout@v3
- name: Commit changes
uses: EndBug/add-and-commit@v9
with: with:
author_name: ${{ github.actor }} fetch-depth: 0
author_email: ${{ github.actor }}@users.noreply.github.com - name: Configure git
message: 'Update Browserslist' run: |
git config --global user.email "action@github.com"
git config --global user.name "GitHub Action"
- name: Update Browserslist database and create PR if applies
uses: c2corg/browserslist-update-action@v2
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
branch: browserslist-update
base_branch: develop
commit_message: 'build: update Browserslist db'
title: 'build: update Browserslist db'
body: Auto-generated by [browserslist-update-action](https://github.com/c2corg/browserslist-update-action/)
labels: 'chores, github action'
@@ -1,25 +0,0 @@
name: Update Monaco-editor
on:
workflow_dispatch:
push:
branches:
- 'dependabot/npm_and_yarn/develop/monaco-editor-**'
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 18
- name: Update monaco version
run: |
yarn install
node ./bin/update-monaco.js
- name: Commit changes
uses: EndBug/add-and-commit@v9
with:
author_name: ${{ github.actor }}
author_email: ${{ github.actor }}@users.noreply.github.com
message: 'Update Monaco-editor'
+19 -1
View File
@@ -1,6 +1,24 @@
{ {
"editor.formatOnSave": true, "editor.formatOnSave": true,
"cSpell.words": ["asyncable", "mindmap", "pako", "Serde", "serdes"], "cSpell.blockCheckingWhenLineLengthGreaterThan": 150,
"cSpell.words": [
"asyncable",
"Browserslist",
"ckppp",
"corg",
"cssnano",
"daisyui",
"esserializer",
"KROKI",
"localstorage",
"mermaidchart",
"mindmap",
"pako",
"Serde",
"serdes",
"tailwindcss",
"uparrow"
],
"vitest.commandLine": "yarn test:unit", "vitest.commandLine": "yarn test:unit",
"vitest.enable": true, "vitest.enable": true,
"testing.autoRun.mode": "rerun", "testing.autoRun.mode": "rerun",
+3 -3
View File
@@ -1,17 +1,17 @@
# Two-stage docker container for mermaid-js/mermaid-live-editor # Two-stage docker container for mermaid-js/mermaid-live-editor
# Build : docker build -t mermaid-js/mermaid-live-editor . # Build : docker build -t mermaid-js/mermaid-live-editor .
# Run : docker run --name mermaid-live-editor --publish 8080:80 mermaid-js/mermaid-live-editor # Run : docker run --name mermaid-live-editor --publish 8080:8080 mermaid-js/mermaid-live-editor
# Start : docker start mermaid-live-editor # Start : docker start mermaid-live-editor
# Use webbrowser : http://localhost:8080 # Use webbrowser : http://localhost:8080
# Stop : press ctrl + c # Stop : press ctrl + c
# or # or
# docker stop mermaid-live-editor # docker stop mermaid-live-editor
FROM node:18.12.0 as mermaid-live-editor-builder FROM node:18.17.1 as mermaid-live-editor-builder
COPY --chown=node:node . /home COPY --chown=node:node . /home
WORKDIR /home WORKDIR /home
RUN yarn install RUN yarn install
RUN yarn build RUN yarn build
FROM nginx:alpine as mermaid-live-editor-runner FROM nginxinc/nginx-unprivileged:alpine as mermaid-live-editor-runner
COPY ./nginx.conf /etc/nginx/conf.d/default.conf COPY ./nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=mermaid-live-editor-builder --chown=nginx:nginx /home/docs /usr/share/nginx/html COPY --from=mermaid-live-editor-builder --chown=nginx:nginx /home/docs /usr/share/nginx/html
+1 -1
View File
@@ -1,4 +1,4 @@
FROM node:18 FROM node:18.17.1
WORKDIR /app WORKDIR /app
COPY package.json . COPY package.json .
COPY yarn.lock . COPY yarn.lock .
+1 -1
View File
@@ -1,6 +1,6 @@
MIT License MIT License
Copyright (c) 2020 - 2021 Knut Sveidqvist Copyright (c) 2020 - 2023 Knut Sveidqvist
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
+11 -8
View File
@@ -24,7 +24,7 @@ You can try out a live version [here](https://mermaid.live/).
### Run published image ### Run published image
```bash ```bash
docker run --publish 8000:80 ghcr.io/mermaid-js/mermaid-live-editor docker run --platform linux/amd64 --publish 8000:8080 ghcr.io/mermaid-js/mermaid-live-editor
``` ```
### To configure renderer URL ### To configure renderer URL
@@ -43,21 +43,24 @@ Default is `https://kroki.io`
docker compose up --build docker compose up --build
``` ```
Then open http://localhost:8000 Then open http://localhost:3000
## Setup ## Setup
[Volta](https://volta.sh) is used for managing node and yarn versions. Below link will help you making a copy of the repository in your local system.
This project is set up using [Yarn](https://classic.yarnpkg.com/en/docs/getting-started): https://docs.github.com/en/get-started/quickstart/fork-a-repo
``` ## Requirements
yarn install
``` - [volta](https://volta.sh/) to manage node versions.
- [Node.js](https://nodejs.org/en/). `volta install node`
- [yarn](https://yarnpkg.com/) package manager. `volta install yarn`
## Development ## Development
``` ```sh
yarn install
yarn dev -- --open yarn dev -- --open
``` ```
+3 -3
View File
@@ -6,10 +6,10 @@ export default defineConfig({
viewportWidth: 1440, viewportWidth: 1440,
viewportHeight: 768, viewportHeight: 768,
snapshotFileName: './cypress/snapshots.js', snapshotFileName: './cypress/snapshots.js',
defaultCommandTimeout: 16000, defaultCommandTimeout: 5000,
requestTimeout: 16000, requestTimeout: 5000,
retries: { retries: {
runMode: 4, runMode: 2,
openMode: 0 openMode: 0
}, },
e2e: { e2e: {
+8 -7
View File
@@ -1,15 +1,16 @@
import { verifyFileSize } from './util'; import { typeInEditor, verifyFileSizeGreaterThan } from './util';
describe('Check actions', () => { describe('Check actions', () => {
beforeEach(() => { beforeEach(() => {
cy.clearLocalStorage(); cy.clearLocalStorage();
cy.visit('/edit'); cy.visit('/edit');
cy.contains('Actions').click();
}); });
it('should update markdown code', () => { it('should update markdown code', () => {
cy.get('#markdown') cy.get('#markdown')
.invoke('val') .invoke('val')
.then((oldText) => { .then((oldText) => {
cy.get('#editor').click('bottom').type('{enter}C --> HistoryTest'); typeInEditor('C --> HistoryTest', { bottom: true, newline: true });
cy.get('#markdown') cy.get('#markdown')
.invoke('val') .invoke('val')
.then((newText) => { .then((newText) => {
@@ -18,7 +19,7 @@ describe('Check actions', () => {
}); });
}); });
it('should load gists from URL', () => { it.skip('should load gists from URL', () => {
cy.get('#gist').type('https://gist.github.com/sidharthv96/6268a23e673a533dcb198f241fd7012a'); cy.get('#gist').type('https://gist.github.com/sidharthv96/6268a23e673a533dcb198f241fd7012a');
cy.contains('Load Gist').click(); cy.contains('Load Gist').click();
cy.contains('Go shopping!!'); cy.contains('Go shopping!!');
@@ -28,20 +29,20 @@ describe('Check actions', () => {
cy.clock(new Date(2022, 0, 1).getTime()); cy.clock(new Date(2022, 0, 1).getTime());
cy.get(`#downloadPNG`).click(); cy.get(`#downloadPNG`).click();
verifyFileSize('diagram', 'png', 21_000); verifyFileSizeGreaterThan('diagram', 'png', 34_000);
cy.get(`#downloadSVG`).click(); cy.get(`#downloadSVG`).click();
verifyFileSize('diagram', 'svg', 10_000); verifyFileSizeGreaterThan('diagram', 'svg', 10_000);
// Verify downloaded file is different for different diagrams // Verify downloaded file is different for different diagrams
cy.contains('Sample Diagrams').click(); cy.contains('Sample Diagrams').click();
cy.contains('ER').click(); cy.contains('ER').click();
cy.get(`#downloadPNG`).click(); cy.get(`#downloadPNG`).click();
verifyFileSize('diagram', 'png', 46_000); verifyFileSizeGreaterThan('diagram', 'png', 40_000);
cy.get(`#downloadSVG`).click(); cy.get(`#downloadSVG`).click();
verifyFileSize('diagram', 'svg', 12_000); verifyFileSizeGreaterThan('diagram', 'svg', 11_000);
cy.clock().invoke('restore'); cy.clock().invoke('restore');
}); });
+20 -9
View File
@@ -1,16 +1,18 @@
import { getEditor, cmd } from './util'; import { typeInEditor, cmd } from './util';
describe('Auto sync tests', () => { describe('Auto sync tests', () => {
beforeEach(() => { beforeEach(() => {
cy.clearLocalStorage(); cy.clearLocalStorage();
cy.visit('/'); cy.visit('/');
cy.url().should('contain', '/edit#pako');
cy.window().should('have.property', 'editorLoaded', true);
}); });
it('should dim diagram when code is edited', () => { it('should dim diagram when code is edited', () => {
cy.contains('Auto sync').click(); cy.contains('Auto sync').click();
cy.get('#view').should('not.have.class', 'outOfSync'); cy.get('#view').should('not.have.class', 'outOfSync');
cy.get('#errorContainer').should('not.exist'); cy.get('#errorContainer').should('not.exist');
getEditor({ bottom: true, newline: true }).type(' C --> Test'); typeInEditor(' C --> Test', { bottom: true });
cy.get('#view').should('have.class', 'outOfSync'); cy.get('#view').should('have.class', 'outOfSync');
cy.get('#errorContainer').should('contain.text', 'Diagram out of sync.'); cy.get('#errorContainer').should('contain.text', 'Diagram out of sync.');
cy.getLocalStorage('codeStore').snapshot(); cy.getLocalStorage('codeStore').snapshot();
@@ -19,10 +21,10 @@ describe('Auto sync tests', () => {
it('should update diagram when shortcut is used', () => { it('should update diagram when shortcut is used', () => {
cy.contains('Auto sync').click(); cy.contains('Auto sync').click();
cy.get('#view').should('not.have.class', 'outOfSync'); cy.get('#view').should('not.have.class', 'outOfSync');
getEditor().type(' C --> Test'); typeInEditor(' C --> Test');
cy.get('#view').should('have.class', 'outOfSync'); cy.get('#view').should('have.class', 'outOfSync');
cy.get('#errorContainer').should('contain.text', 'Diagram out of sync.'); cy.get('#errorContainer').should('contain.text', 'Diagram out of sync.');
getEditor().type(`${cmd}{enter}`); typeInEditor(`${cmd}{enter}`);
cy.get('#errorContainer').should('not.exist'); cy.get('#errorContainer').should('not.exist');
cy.get('#view').should('not.have.class', 'outOfSync'); cy.get('#view').should('not.have.class', 'outOfSync');
}); });
@@ -38,21 +40,22 @@ describe('Auto sync tests', () => {
it('should not dim diagram when code is in sync', () => { it('should not dim diagram when code is in sync', () => {
cy.contains('Auto sync').click(); cy.contains('Auto sync').click();
cy.get('#view').should('not.have.class', 'outOfSync'); cy.get('#view').should('not.have.class', 'outOfSync');
getEditor().type(' C --> Test'); typeInEditor(' C --> Test');
cy.get('#view').should('have.class', 'outOfSync'); cy.get('#view').should('have.class', 'outOfSync');
cy.get('[data-cy=sync]').click(); cy.get('[data-cy=sync]').click();
cy.get('#view').should('not.have.class', 'outOfSync'); cy.get('#view').should('not.have.class', 'outOfSync');
cy.get('#autoSync').check(); cy.get('#autoSync').check();
getEditor().type('ing'); typeInEditor('ing');
cy.get('#view').should('not.have.class', 'outOfSync'); cy.get('#view').should('not.have.class', 'outOfSync');
cy.getLocalStorage('codeStore').snapshot(); cy.getLocalStorage('codeStore').snapshot();
}); });
it('supports commenting code out/in', () => { it('supports commenting code out/in', () => {
getEditor().type(`{uparrow}${cmd}/`); cy.get('#editor').contains('Car').click();
cy.get('#editor').get('textarea').type(`${cmd}/`, { force: true });
cy.get('#view').contains('Car').should('not.exist'); cy.get('#view').contains('Car').should('not.exist');
getEditor().type(`{uparrow}${cmd}/`); typeInEditor(`{uparrow}${cmd}/`);
cy.get('#view').contains('Car').should('exist'); cy.get('#view').contains('Car').should('exist');
}); });
@@ -61,7 +64,7 @@ describe('Auto sync tests', () => {
'/edit#pako:eNpljjEKwzAMRa8SNOcEnlt6gK5eVFvYJsgOqkwpIXevg9smEE1PnyfxF3DFExgISW-CczQ2D21cYU7a-SGYXRwyvTp9jUhuKlVP-eHy7zA-leQsMEmg_QOM0BLG5FujZVMsaCQmC6ahR5ks2Lw2r84ela4-aREwKpVGwKrl_s7ut3fnkjAIcg_XDzuaUhs' '/edit#pako:eNpljjEKwzAMRa8SNOcEnlt6gK5eVFvYJsgOqkwpIXevg9smEE1PnyfxF3DFExgISW-CczQ2D21cYU7a-SGYXRwyvTp9jUhuKlVP-eHy7zA-leQsMEmg_QOM0BLG5FujZVMsaCQmC6ahR5ks2Lw2r84ela4-aREwKpVGwKrl_s7ut3fnkjAIcg_XDzuaUhs'
); );
cy.get('#errorContainer').should('not.exist'); cy.get('#errorContainer').should('not.exist');
getEditor({ newline: true }).type(`branch test`); typeInEditor(`branch test`, { bottom: true, newline: true });
cy.get('#editor').contains('branch test').should('exist'); cy.get('#editor').contains('branch test').should('exist');
cy.get('#errorContainer') cy.get('#errorContainer')
.contains( .contains(
@@ -69,6 +72,14 @@ describe('Auto sync tests', () => {
) )
.should('exist'); .should('exist');
}); });
it('should update diagram after entire text is removed', () => {
// https://github.com/mermaid-js/mermaid-live-editor/issues/1102
typeInEditor(`${cmd} a {backspace}`);
typeInEditor('graph LR');
typeInEditor(' {enter} A-->Car');
cy.get('#view').contains('Car').should('exist');
});
}); });
describe('Pan and Zoom', () => { describe('Pan and Zoom', () => {
+6 -6
View File
@@ -14,23 +14,23 @@ describe('Editor docs tests', () => {
it('Test to see if the correct URL loads when changing from one diagram to other', () => { it('Test to see if the correct URL loads when changing from one diagram to other', () => {
cy.contains('Flow').click(); cy.contains('Flow').click();
cy.get(`[data-cy=docs][href$="/#/flowchart"]`).should('exist'); cy.get(`[data-cy=docs][href$="/syntax/flowchart"]`).should('exist');
cy.contains('Config').click(); cy.contains('Config').click();
cy.get(`[data-cy=docs][href$="/#/flowchart?id=configuration"]`).should('exist'); cy.get(`[data-cy=docs][href$="/syntax/flowchart?id=configuration"]`).should('exist');
cy.contains('Sequence').click(); cy.contains('Sequence').click();
cy.get(`[data-cy=docs][href$="/#/sequenceDiagram?id=configuration"]`).should('exist'); cy.get(`[data-cy=docs][href$="/syntax/sequenceDiagram?id=configuration"]`).should('exist');
cy.contains('Code').click(); cy.contains('Code').click();
cy.get(`[data-cy=docs][href$="/#/sequenceDiagram"]`).should('exist'); cy.get(`[data-cy=docs][href$="/syntax/sequenceDiagram"]`).should('exist');
}); });
it("Test to check URLs for a case where config URL doesn't exist", () => { it("Test to check URLs for a case where config URL doesn't exist", () => {
cy.contains('State').click(); cy.contains('State').click();
cy.get(`[data-cy=docs][href$="/#/stateDiagram"]`).should('exist'); cy.get(`[data-cy=docs][href$="/syntax/stateDiagram"]`).should('exist');
cy.contains('Config').click(); cy.contains('Config').click();
cy.get(`[data-cy=docs][href$="/#/stateDiagram"]`).should('exist'); cy.get(`[data-cy=docs][href$="/syntax/stateDiagram"]`).should('exist');
}); });
}); });
+8 -10
View File
@@ -1,4 +1,4 @@
import { getEditor, verifyFileSnapshot } from './util'; import { typeInEditor, verifyFileSnapshot } from './util';
describe('Save History', () => { describe('Save History', () => {
beforeEach(() => { beforeEach(() => {
@@ -6,7 +6,6 @@ describe('Save History', () => {
cy.clearLocalStorage(); cy.clearLocalStorage();
cy.visit('/edit'); cy.visit('/edit');
cy.contains('Actions').click();
cy.contains('History').click(); cy.contains('History').click();
}); });
@@ -24,7 +23,6 @@ describe('Save History', () => {
'[{"state":{"code":"graph TD\\n A[New Year] -->|Get money| B(Go shopping)","mermaid":"{\\n \\"theme\\": \\"dark\\"\\n}","autoSync":true,"updateDiagram":false},"time":0,"type":"auto","id":"69ea820e-522b-4a44-86cf-fd58acde09df","name":"barking-dog"},{"state":{"code":"graph TD\\n A[Christmas] -->|Get money| B(Go shopping)","mermaid":"{\\n \\"theme\\": \\"dark\\"\\n}","autoSync":true,"updateDiagram":true},"time":0,"type":"manual","id":"x749ffc6-21dd-418a-b984-7c1ffc3146b3","name":"needy-mosquito"}]' '[{"state":{"code":"graph TD\\n A[New Year] -->|Get money| B(Go shopping)","mermaid":"{\\n \\"theme\\": \\"dark\\"\\n}","autoSync":true,"updateDiagram":false},"time":0,"type":"auto","id":"69ea820e-522b-4a44-86cf-fd58acde09df","name":"barking-dog"},{"state":{"code":"graph TD\\n A[Christmas] -->|Get money| B(Go shopping)","mermaid":"{\\n \\"theme\\": \\"dark\\"\\n}","autoSync":true,"updateDiagram":true},"time":0,"type":"manual","id":"x749ffc6-21dd-418a-b984-7c1ffc3146b3","name":"needy-mosquito"}]'
); );
cy.reload(); cy.reload();
cy.contains('Actions').click();
cy.contains('History').click(); cy.contains('History').click();
cy.get('#historyList').find('li').should('have.length', 2); cy.get('#historyList').find('li').should('have.length', 2);
cy.get('#historyList').find('No items in History').should('not.exist'); cy.get('#historyList').find('No items in History').should('not.exist');
@@ -53,14 +51,14 @@ describe('Save History', () => {
expect(str).to.equal('State already saved.'); expect(str).to.equal('State already saved.');
}); });
cy.on('window:confirm', () => true); cy.on('window:confirm', () => true);
getEditor().type(' C --> HistoryTest'); typeInEditor(' C --> HistoryTest');
cy.get('#saveHistory').click(); cy.get('#saveHistory').click();
cy.get('#historyList').find('li').should('have.length', 2); cy.get('#historyList').find('li').should('have.length', 2);
}); });
it('should be able to restore and delete', () => { it('should be able to restore and delete', () => {
cy.get('#saveHistory').click(); cy.get('#saveHistory').click();
getEditor().type(' C --> HistoryTest'); typeInEditor(' C --> HistoryTest');
cy.get('#historyList').find('No items in History').should('not.exist'); cy.get('#historyList').find('No items in History').should('not.exist');
cy.get('#historyList').find('li').should('have.length', 1); cy.get('#historyList').find('li').should('have.length', 1);
cy.contains('HistoryTest'); cy.contains('HistoryTest');
@@ -70,7 +68,7 @@ describe('Save History', () => {
cy.get('#historyList').find('li').should('have.length', 0); cy.get('#historyList').find('li').should('have.length', 0);
cy.get('#historyList').contains('No items in History'); cy.get('#historyList').contains('No items in History');
cy.get('#saveHistory').click(); cy.get('#saveHistory').click();
getEditor().type(' C --> HistoryTest'); typeInEditor(' C --> HistoryTest');
cy.get('#saveHistory').click(); cy.get('#saveHistory').click();
cy.get('#editor').type('ing'); cy.get('#editor').type('ing');
cy.get('#clearHistory').click(); cy.get('#clearHistory').click();
@@ -83,16 +81,16 @@ describe('Save History', () => {
// TODO: Fix #639 // TODO: Fix #639
xit('should auto save history', () => { xit('should auto save history', () => {
getEditor().type(' C --> HistoryTest'); typeInEditor(' C --> HistoryTest');
cy.tick(70000); cy.tick(70_000);
cy.contains('Timeline').click(); cy.contains('Timeline').click();
cy.get('#historyList').find('li').should('have.length', 1); cy.get('#historyList').find('li').should('have.length', 1);
cy.get('#editor').type('ing'); cy.get('#editor').type('ing');
cy.tick(70000); cy.tick(70_000);
cy.get('#historyList').find('li').should('have.length', 2); cy.get('#historyList').find('li').should('have.length', 2);
for (let i = 0; i < 31; i++) { for (let i = 0; i < 31; i++) {
cy.get('#editor').type('.'); cy.get('#editor').type('.');
cy.tick(70000); cy.tick(70_000);
} }
cy.get('#historyList').find('li').should('have.length', 30); cy.get('#historyList').find('li').should('have.length', 30);
}); });
+29 -15
View File
@@ -4,6 +4,7 @@ describe('Site Loads', () => {
beforeEach(() => { beforeEach(() => {
cy.clearLocalStorage(); cy.clearLocalStorage();
cy.visit('/'); cy.visit('/');
cy.url().should('include', '/edit#pako');
}); });
it('Check Home page load', () => { it('Check Home page load', () => {
@@ -12,6 +13,12 @@ describe('Site Loads', () => {
cy.getLocalStorage('codeStore').snapshot(); cy.getLocalStorage('codeStore').snapshot();
}); });
it('should keep code after reload', () => {
cy.get('#editor').contains('Car');
cy.reload();
cy.get('#editor').contains('Car');
});
it('Check Redirect from old URL', () => { it('Check Redirect from old URL', () => {
cy.visit( cy.visit(
'/#/edit/eyJjb2RlIjoiZ3JhcGggVERcbiAgICBBW0NocmlzdG1hc10gLS0-fEdldCBtb25leXwgQihHbyBzaG9wcGluZylcbiAgICBCIC0tPiBDe0xldCBtZSB0aGlua31cbiAgICBDIC0tPnxPbmV8IERbTGFwdG9wXVxuICAgIEMgLS0-fFR3b3wgRVtpUGhvbmVdXG4gICAgQyAtLT58VGhyZWV8IEZbZmE6ZmEtY2FyIENhcl0iLCJtZXJtYWlkIjp7InRoZW1lIjoiZGVmYXVsdCJ9LCJ1cGRhdGVFZGl0b3IiOmZhbHNlfQ' '/#/edit/eyJjb2RlIjoiZ3JhcGggVERcbiAgICBBW0NocmlzdG1hc10gLS0-fEdldCBtb25leXwgQihHbyBzaG9wcGluZylcbiAgICBCIC0tPiBDe0xldCBtZSB0aGlua31cbiAgICBDIC0tPnxPbmV8IERbTGFwdG9wXVxuICAgIEMgLS0-fFR3b3wgRVtpUGhvbmVdXG4gICAgQyAtLT58VGhyZWV8IEZbZmE6ZmEtY2FyIENhcl0iLCJtZXJtYWlkIjp7InRoZW1lIjoiZGVmYXVsdCJ9LCJ1cGRhdGVFZGl0b3IiOmZhbHNlfQ'
@@ -93,22 +100,9 @@ describe('Site Loads', () => {
cy.reload(true); cy.reload(true);
cy.contains('Please Click here to Raise an issue in github.'); cy.contains('Please Click here to Raise an issue in github.');
}); });
});
it('should load uncompressed URL', () => { describe('Verify types of URLs', () => {
cy.visit(
'/edit/#eyJjb2RlIjoiZ3JhcGggVERcbiAgICBBW05ldyBZZWFyXSAtLT58R2V0IG1vbmV5fCBCKEdvIHNob3BwaW5nKVxuICAgIEIgLS0-IEN7TGV0IG1lIHRoaW5rfVxuICAgIEMgLS0-fE9uZXwgRFtMYXB0b3BdXG4gICAgQyAtLT58VHdvfCBFW2lQaG9uZV1cbiAgICBDIC0tPnxUaHJlZXwgRltmYTpmYS1jYXIgQ2FyXSIsIm1lcm1haWQiOiJ7XG4gIFwidGhlbWVcIjogXCJkZWZhdWx0XCJcbn0iLCJ1cGRhdGVFZGl0b3IiOmZhbHNlLCJhdXRvU3luYyI6dHJ1ZSwidXBkYXRlRGlhZ3JhbSI6ZmFsc2V9'
);
cy.contains('New Year');
cy.visit(
'/edit#eyJjb2RlIjoiY2xhc3NEaWFncmFtXG4gICAgQW5pbWFsIDx8LS0gRHVja1xuICAgIEFuaW1hbCA8fC0tIEZpc2hcbiAgICBBbmltYWwgPHwtLSBaZWJyYVxuICAgIEFuaW1hbCA6ICtpbnQgYWdlXG4gICAgQW5pbWFsIDogK1N0cmluZyBnZW5kZXJcbiAgICBBbmltYWw6ICtpc01hbW1hbCgpXG4gICAgQW5pbWFsOiArbWF0ZSgpXG4gICAgY2xhc3MgRHVja3tcbiAgICAgICtTdHJpbmcgYmVha0NvbG9yXG4gICAgICArc3dpbSgpXG4gICAgICArcXVhY2soKVxuICAgIH1cbiAgICBjbGFzcyBGaXNoe1xuICAgICAgLWludCBzaXplSW5GZWV0XG4gICAgICAtY2FuRWF0KClcbiAgICB9XG4gICAgY2xhc3MgWmVicmF7XG4gICAgICArYm9vbCBpc193aWxkXG4gICAgICArcnVuKClcbiAgICB9XG4gICAgICAgICAgICAiLCJtZXJtYWlkIjoie1xuICBcInRoZW1lXCI6IFwiZGFya1wiXG59IiwidXBkYXRlRWRpdG9yIjpmYWxzZSwiYXV0b1N5bmMiOnRydWUsInVwZGF0ZURpYWdyYW0iOmZhbHNlfQ'
);
cy.contains('Animal');
cy.visit(
'/edit/#base64:eyJjb2RlIjoiZ3JhcGggVERcbiAgICBBW05ldyBZZWFyXSAtLT58R2V0IG1vbmV5fCBCKEdvIHNob3BwaW5nKVxuICAgIEIgLS0-IEN7TGV0IG1lIHRoaW5rfVxuICAgIEMgLS0-fE9uZXwgRFtMYXB0b3BdXG4gICAgQyAtLT58VHdvfCBFW2lQaG9uZV1cbiAgICBDIC0tPnxUaHJlZXwgRltmYTpmYS1jYXIgQ2FyXSIsIm1lcm1haWQiOiJ7XG4gIFwidGhlbWVcIjogXCJkZWZhdWx0XCJcbn0iLCJ1cGRhdGVFZGl0b3IiOmZhbHNlLCJhdXRvU3luYyI6dHJ1ZSwidXBkYXRlRGlhZ3JhbSI6ZmFsc2V9'
);
cy.contains('New Year');
});
it('should load compressed URL', () => { it('should load compressed URL', () => {
cy.visit( cy.visit(
'/edit#pako:eNpVkM2KwkAQhF-l6dMK5gVyEDRxvYi7sF6WjIcm0zqDzg_jBJEk725Hd2G3Tw31VVFUj23QjCWeEkUD-1p5kFs2O77BN1M6QFEshg1ncMHzfYDV2ybA1YQYrT_NXvhqgqDqtxPGkI315_ElVU__h-cB6mZLMYd4-Kvsb2GAdWM_jcT_V0xicb03RyqPVLSUoJI-OEfHyZHV0rqfDAqzYccKS3k1pbNC5Ufhuqgp81rbHBJKxuXKc6Quh6-7b7HMqeNfqLYkC7gfanwAlW1ZvQ' '/edit#pako:eNpVkM2KwkAQhF-l6dMK5gVyEDRxvYi7sF6WjIcm0zqDzg_jBJEk725Hd2G3Tw31VVFUj23QjCWeEkUD-1p5kFs2O77BN1M6QFEshg1ncMHzfYDV2ybA1YQYrT_NXvhqgqDqtxPGkI315_ElVU__h-cB6mZLMYd4-Kvsb2GAdWM_jcT_V0xicb03RyqPVLSUoJI-OEfHyZHV0rqfDAqzYccKS3k1pbNC5Ufhuqgp81rbHBJKxuXKc6Quh6-7b7HMqeNfqLYkC7gfanwAlW1ZvQ'
@@ -119,4 +113,24 @@ describe('Site Loads', () => {
); );
cy.contains('Animal'); cy.contains('Animal');
}); });
describe('Uncompressed URLs', () => {
it('should load URL without specifier', () => {
cy.visit(
'/edit/#eyJjb2RlIjoiZ3JhcGhcbiAgICBUZXN0TGFiZWwiLCJtZXJtYWlkIjoie1xuICBcInRoZW1lXCI6IFwiZGVmYXVsdFwiXG59IiwidXBkYXRlRWRpdG9yIjpmYWxzZSwiYXV0b1N5bmMiOnRydWUsInVwZGF0ZURpYWdyYW0iOmZhbHNlfQ'
);
cy.contains('TestLabel');
cy.visit(
'/edit#eyJjb2RlIjoiY2xhc3NEaWFncmFtXG4gICAgQW5pbWFsIDx8LS0gRHVja1xuICAgIEFuaW1hbCA8fC0tIEZpc2hcbiAgICBBbmltYWwgPHwtLSBaZWJyYVxuICAgIEFuaW1hbCA6ICtpbnQgYWdlXG4gICAgQW5pbWFsIDogK1N0cmluZyBnZW5kZXJcbiAgICBBbmltYWw6ICtpc01hbW1hbCgpXG4gICAgQW5pbWFsOiArbWF0ZSgpXG4gICAgY2xhc3MgRHVja3tcbiAgICAgICtTdHJpbmcgYmVha0NvbG9yXG4gICAgICArc3dpbSgpXG4gICAgICArcXVhY2soKVxuICAgIH1cbiAgICBjbGFzcyBGaXNoe1xuICAgICAgLWludCBzaXplSW5GZWV0XG4gICAgICAtY2FuRWF0KClcbiAgICB9XG4gICAgY2xhc3MgWmVicmF7XG4gICAgICArYm9vbCBpc193aWxkXG4gICAgICArcnVuKClcbiAgICB9XG4gICAgICAgICAgICAiLCJtZXJtYWlkIjoie1xuICBcInRoZW1lXCI6IFwiZGFya1wiXG59IiwidXBkYXRlRWRpdG9yIjpmYWxzZSwiYXV0b1N5bmMiOnRydWUsInVwZGF0ZURpYWdyYW0iOmZhbHNlfQ'
);
cy.contains('Animal');
});
it('should load URL with "base64" specifier', () => {
cy.visit(
'/edit/#base64:eyJjb2RlIjoiZ3JhcGhcbiAgICBUZXN0TGFiZWwiLCJtZXJtYWlkIjoie1xuICBcInRoZW1lXCI6IFwiZGVmYXVsdFwiXG59IiwidXBkYXRlRWRpdG9yIjpmYWxzZSwiYXV0b1N5bmMiOnRydWUsInVwZGF0ZURpYWdyYW0iOmZhbHNlfQ'
);
cy.contains('TestLabel');
});
});
}); });
+2 -2
View File
@@ -12,7 +12,7 @@ describe('Test themes', () => {
}); });
} }
}); });
cy.contains('Change Theme').click(); cy.contains('Theme').click();
}); });
it('should set light theme as default', () => { it('should set light theme as default', () => {
@@ -44,7 +44,7 @@ describe('Test themes', () => {
}); });
} }
}); });
cy.contains('Change Theme').click(); cy.contains('Theme').click();
}); });
it('should set dark theme as default', () => { it('should set dark theme as default', () => {
+30 -11
View File
@@ -1,26 +1,44 @@
export const cmd = `{${Cypress.platform === 'darwin' ? 'meta' : 'ctrl'}}`; export const cmd = `{${Cypress.platform === 'darwin' ? 'meta' : 'ctrl'}}`;
export const getEditor = ({ bottom = true, newline = false } = {}) => interface EditorOptions {
cy bottom?: boolean;
.get('#editor textarea:first') newline?: boolean;
.click() }
.focused()
.type(`${bottom ? '{pageDown}' : cmd}`) export const typeInEditor = (
.type(`${newline ? '{enter}' : cmd}`); text: string,
{ bottom = true, newline = false }: EditorOptions = {}
) => {
cy.window().should('have.property', 'editorLoaded', true);
cy.get('#editor').click();
cy.get('#editor').within(($editor) => {
if (bottom) {
cy.get('textarea').type('{pageDown}', { force: true });
}
if (newline) {
cy.get('textarea').type('{enter}', { force: true });
}
cy.get('textarea').type(text, { force: true });
});
};
const downloadsFolder = Cypress.config('downloadsFolder'); const downloadsFolder = Cypress.config('downloadsFolder');
export const verifyFileSize = ( export const verifyFileSizeGreaterThan = (
fileType: 'history' | 'diagram', fileType: 'history' | 'diagram',
extension: string, extension: string,
size: number size: number
) => { ) => {
const fileName = `mermaid-${fileType}-2022-01-01-000000.${extension}`; const fileName = `mermaid-${fileType}-2022-01-01-000000.${extension}`;
const filePath = `${downloadsFolder}/${fileName}`; const filePath = `${downloadsFolder}/${fileName}`;
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
cy.verifyDownload(fileName); cy.verifyDownload(fileName);
cy.readFile(filePath, null, { cy.readFile(filePath, null, {
log: false log: false
}).then((buffer) => expect((buffer as ArrayBuffer).byteLength).to.be.gt(size)); }).then((buffer: ArrayBuffer) => {
expect(buffer.byteLength).to.be.gt(size);
expect(buffer.byteLength).to.be.lt(size * 1.3);
});
cy.task('deleteFile', filePath); cy.task('deleteFile', filePath);
}; };
@@ -31,11 +49,12 @@ export const verifyFileSnapshot = (
) => { ) => {
const fileName = `mermaid-${fileType}-2022-01-01-000000.${extension}`; const fileName = `mermaid-${fileType}-2022-01-01-000000.${extension}`;
const filePath = `${downloadsFolder}/${fileName}`; const filePath = `${downloadsFolder}/${fileName}`;
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
cy.verifyDownload(fileName); cy.verifyDownload(fileName);
cy.readFile(filePath, null, { cy.readFile(filePath, null, {
log: false log: false
}).then((buffer) => }).then((buffer: ArrayBuffer) =>
expect(new TextDecoder('utf-8').decode(buffer as ArrayBuffer)).to.contain(content) expect(new TextDecoder('utf8').decode(buffer)).to.contain(content)
); );
cy.task('deleteFile', filePath); cy.task('deleteFile', filePath);
}; };
+4 -4
View File
@@ -1,7 +1,7 @@
module.exports = { module.exports = {
"Site Loads": { "Site Loads": {
"Check Home page load": { "Check Home page load": {
"1": "{\"code\":\"graph TD\\n A[Christmas] -->|Get money| B(Go shopping)\\n B --> C{Let me think}\\n C -->|One| D[Laptop]\\n C -->|Two| E[iPhone]\\n C -->|Three| F[fa:fa-car Car]\\n \",\"mermaid\":\"{\\n \\\"theme\\\": \\\"default\\\"\\n}\",\"autoSync\":true,\"updateDiagram\":true}" "1": "{\"code\":\"flowchart TD\\n A[Christmas] -->|Get money| B(Go shopping)\\n B --> C{Let me think}\\n C -->|One| D[Laptop]\\n C -->|Two| E[iPhone]\\n C -->|Three| F[fa:fa-car Car]\\n \",\"mermaid\":\"{\\n \\\"theme\\\": \\\"default\\\"\\n}\",\"autoSync\":true,\"updateDiagram\":true}"
}, },
"Check Redirect from old URL": { "Check Redirect from old URL": {
"1": "{\"code\":\"graph TD\\n A[Christmas] -->|Get money| B(Go shopping)\\n B --> C{Let me think}\\n C -->|One| D[Laptop]\\n C -->|Two| E[iPhone]\\n C -->|Three| F[fa:fa-car Car]\",\"mermaid\":\"{\\n \\\"theme\\\": \\\"default\\\"\\n}\",\"autoSync\":true,\"updateDiagram\":true}" "1": "{\"code\":\"graph TD\\n A[Christmas] -->|Get money| B(Go shopping)\\n B --> C{Let me think}\\n C -->|One| D[Laptop]\\n C -->|Two| E[iPhone]\\n C -->|Three| F[fa:fa-car Car]\",\"mermaid\":\"{\\n \\\"theme\\\": \\\"default\\\"\\n}\",\"autoSync\":true,\"updateDiagram\":true}"
@@ -16,13 +16,13 @@ module.exports = {
"1": "{\"code\":\"graph TD\\n A[Party] -->|Get money| B(Go shopping!!)\\n \",\"mermaid\":\"{\\n \\\"theme\\\": \\\"forest\\\",\\n \\\"test\\\": \\\"hello world\\\"\\n}\",\"autoSync\":true,\"updateDiagram\":true,\"loader\":{\"type\":\"files\",\"config\":{\"codeURL\":\"https://gist.githubusercontent.com/sidharthv96/6268a23e673a533dcb198f241fd7012a/raw/4eb03887e6a41397e80bdcdbf94017c498f8f1e2/code.mmd\",\"configURL\":\"https://gist.githubusercontent.com/sidharthv96/6268a23e673a533dcb198f241fd7012a/raw/4eb03887e6a41397e80bdcdbf94017c498f8f1e2/config.json\"}}}" "1": "{\"code\":\"graph TD\\n A[Party] -->|Get money| B(Go shopping!!)\\n \",\"mermaid\":\"{\\n \\\"theme\\\": \\\"forest\\\",\\n \\\"test\\\": \\\"hello world\\\"\\n}\",\"autoSync\":true,\"updateDiagram\":true,\"loader\":{\"type\":\"files\",\"config\":{\"codeURL\":\"https://gist.githubusercontent.com/sidharthv96/6268a23e673a533dcb198f241fd7012a/raw/4eb03887e6a41397e80bdcdbf94017c498f8f1e2/code.mmd\",\"configURL\":\"https://gist.githubusercontent.com/sidharthv96/6268a23e673a533dcb198f241fd7012a/raw/4eb03887e6a41397e80bdcdbf94017c498f8f1e2/config.json\"}}}"
} }
}, },
"__version": "10.10.0", "__version": "12.17.4",
"Auto sync tests": { "Auto sync tests": {
"should dim diagram when code is edited": { "should dim diagram when code is edited": {
"1": "{\"code\":\"graph TD\\n A[Christmas] -->|Get money| B(Go shopping)\\n B --> C{Let me think}\\n C -->|One| D[Laptop]\\n C -->|Two| E[iPhone]\\n C -->|Three| F[fa:fa-car Car]\\n C --> Test\",\"mermaid\":\"{\\n \\\"theme\\\": \\\"default\\\"\\n}\",\"autoSync\":false,\"updateDiagram\":false}" "1": "{\"code\":\"flowchart TD\\n A[Christmas] -->|Get money| B(Go shopping)\\n B --> C{Let me think}\\n C -->|One| D[Laptop]\\n C -->|Two| E[iPhone]\\n C -->|Three| F[fa:fa-car Car]\\n C --> Test\",\"mermaid\":\"{\\n \\\"theme\\\": \\\"default\\\"\\n}\",\"autoSync\":false,\"updateDiagram\":false}"
}, },
"should not dim diagram when code is in sync": { "should not dim diagram when code is in sync": {
"1": "{\"code\":\"graph TD\\n A[Christmas] -->|Get money| B(Go shopping)\\n B --> C{Let me think}\\n C -->|One| D[Laptop]\\n C -->|Two| E[iPhone]\\n C -->|Three| F[fa:fa-car Car]\\n C --> Testing\",\"mermaid\":\"{\\n \\\"theme\\\": \\\"default\\\"\\n}\",\"autoSync\":true,\"updateDiagram\":false}" "1": "{\"code\":\"flowchart TD\\n A[Christmas] -->|Get money| B(Go shopping)\\n B --> C{Let me think}\\n C -->|One| D[Laptop]\\n C -->|Two| E[iPhone]\\n C -->|Three| F[fa:fa-car Car]\\n C --> Testing\",\"mermaid\":\"{\\n \\\"theme\\\": \\\"default\\\"\\n}\",\"autoSync\":true,\"updateDiagram\":false}"
} }
}, },
"Test themes": { "Test themes": {
+1 -1
View File
@@ -1,7 +1,7 @@
{ {
"compilerOptions": { "compilerOptions": {
"allowJs": true, "allowJs": true,
"types": ["cypress", "cypress-localstorage-commands", "cy-verify-downloads"] "types": ["cypress", "cypress-localstorage-commands", "cy-verify-downloads", "node"]
}, },
"include": ["**/*.ts"] "include": ["**/*.ts"]
} }
+1 -1
View File
@@ -7,5 +7,5 @@ services:
volumes: volumes:
- ./src:/app/src - ./src:/app/src
ports: ports:
- 8080:8080 - 3000:3000
- 24678:24678 - 24678:24678
+1 -1
View File
@@ -1,5 +1,5 @@
server { server {
listen 80; listen 8080;
server_name mermaid; server_name mermaid;
location / { location / {
root /usr/share/nginx/html; root /usr/share/nginx/html;
+46 -45
View File
@@ -23,61 +23,62 @@
}, },
"devDependencies": { "devDependencies": {
"@cypress/snapshot": "2.1.7", "@cypress/snapshot": "2.1.7",
"@sveltejs/adapter-static": "1.0.0-next.46", "@sveltejs/adapter-static": "2.0.3",
"@sveltejs/kit": "1.0.0-next.522", "@sveltejs/kit": "1.25.0",
"@testing-library/jest-dom": "5.16.5", "@testing-library/jest-dom": "5.17.0",
"@testing-library/svelte": "3.2.2", "@testing-library/svelte": "3.2.2",
"@types/pako": "2.0.0", "@types/pako": "2.0.0",
"@types/uuid": "8.3.4", "@types/uuid": "9.0.4",
"@typescript-eslint/eslint-plugin": "5.42.0", "@typescript-eslint/eslint-plugin": "5.62.0",
"@typescript-eslint/parser": "5.42.0", "@typescript-eslint/parser": "5.62.0",
"@vitest/ui": "0.25.1", "@vitest/ui": "^0.34.0",
"autoprefixer": "10.4.12", "autoprefixer": "^10.4.14",
"c8": "7.12.0", "c8": "7.14.0",
"chai": "4.3.6", "chai": "^4.3.7",
"cssnano": "5.1.13", "cssnano": "^6.0.0",
"cy-verify-downloads": "0.1.11", "cy-verify-downloads": "0.2.0",
"cypress": "11.0.1", "cypress": "12.17.4",
"cypress-localstorage-commands": "2.2.1", "cypress-localstorage-commands": "2.2.4",
"eslint": "8.27.0", "eslint": "8.49.0",
"eslint-config-prettier": "8.5.0", "eslint-config-prettier": "8.10.0",
"eslint-plugin-cypress": "2.12.1", "eslint-plugin-cypress": "2.14.0",
"eslint-plugin-es": "4.1.0", "eslint-plugin-es": "4.1.0",
"eslint-plugin-no-only-tests": "^3.1.0",
"eslint-plugin-postcss-modules": "2.0.0", "eslint-plugin-postcss-modules": "2.0.0",
"eslint-plugin-svelte3": "4.0.0", "eslint-plugin-svelte3": "4.0.0",
"eslint-plugin-tailwindcss": "3.6.2", "eslint-plugin-tailwindcss": "3.13.0",
"eslint-plugin-vitest": "0.0.11", "eslint-plugin-unicorn": "^46.0.0",
"esserializer": "1.3.2", "eslint-plugin-vitest": "^0.3.0",
"husky": "8.0.1", "esserializer": "1.3.11",
"jsdom": "20.0.1", "font-awesome": "^4.7.0",
"lint-staged": "13.0.3", "husky": "^8.0.3",
"node-html-parser": "6.1.1", "jsdom": "21.1.2",
"postcss": "8.4.18", "lint-staged": "13.3.0",
"node-html-parser": "^6.1.5",
"postcss": "^8.4.21",
"postcss-load-config": "4.0.1", "postcss-load-config": "4.0.1",
"prettier": "2.7.1", "prettier": "2.8.8",
"prettier-plugin-svelte": "2.8.0", "prettier-plugin-svelte": "^2.10.0",
"svelte": "3.53.1", "svelte": "3.59.2",
"svelte-preprocess": "4.10.7", "svelte-preprocess": "5.0.4",
"tailwindcss": "3.2.1", "tailwindcss": "^3.3.1",
"tslib": "2.4.0", "tslib": "^2.5.0",
"typescript": "4.8.4", "typescript": "5.2.2",
"vite": "3.2.2", "vite": "^4.3.9",
"vitest": "0.25.1" "vitest": "^0.34.0"
}, },
"dependencies": { "dependencies": {
"@mermaid-js/mermaid-mindmap": "9.2.2", "analytics": "0.8.9",
"analytics": "0.8.1",
"analytics-plugin-plausible": "0.0.6", "analytics-plugin-plausible": "0.0.6",
"daisyui": "2.39.1", "daisyui": "2.52.0",
"js-base64": "3.7.2", "dayjs": "^1.11.7",
"mermaid": "9.2.2", "js-base64": "3.7.5",
"moment": "2.29.4", "mermaid": "10.5.0",
"monaco-editor": "0.34.1", "monaco-editor": "0.43.0",
"monaco-mermaid": "1.0.6",
"pako": "2.1.0", "pako": "2.1.0",
"random-word-slugs": "0.1.6", "random-word-slugs": "0.1.7",
"svg-pan-zoom": "3.6.1", "svg-pan-zoom": "3.6.1",
"uuid": "9.0.0" "uuid": "9.0.1"
}, },
"lint-staged": { "lint-staged": {
"*.{ts,svelte,js,css,md,json}": [ "*.{ts,svelte,js,css,md,json}": [
@@ -86,7 +87,7 @@
] ]
}, },
"volta": { "volta": {
"node": "18.12.0", "node": "18.17.1",
"yarn": "1.22.19" "yarn": "1.22.19"
}, },
"engines": { "engines": {
+4
View File
@@ -11,6 +11,10 @@
":automergePatch" ":automergePatch"
], ],
"packageRules": [ "packageRules": [
{
"matchPackagePatterns": ["^mermaid"],
"groupName": "Mermaid packages"
},
{ {
"matchUpdateTypes": ["minor", "patch", "pin", "digest"], "matchUpdateTypes": ["minor", "patch", "pin", "digest"],
"automerge": true "automerge": true
+2 -30
View File
@@ -17,38 +17,10 @@
<link rel="manifest" href="%sveltekit.assets%/manifest.json" /> <link rel="manifest" href="%sveltekit.assets%/manifest.json" />
<link <link
rel="stylesheet" rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css"
integrity="sha512-xh6O/CkQoPOWDdYTDqeRdPCVd1SpvCA9XXcUnZS2FmJNp1coAFzvtCN9BmamE+4aHK8yyUHUSCcJHgXloTyT2A==" integrity="sha512-z3gLpd7yknf1YoNbCzqRKc4qyor8gaKU1qmn+CShxbuBusANI9QpRohGBreCFkKxLhei6S9CQXFEbbKuqLg0DA=="
crossorigin="anonymous" crossorigin="anonymous"
referrerpolicy="no-referrer" /> referrerpolicy="no-referrer" />
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.34.1/min/vs/editor/editor.main.min.css"
integrity="sha512-GzcoZD7y5zvBofYtImXPZaPVhoY7xLPt+ysmbPb/vU+quSKFkcngxaSrxuwprDZL4MALUqGFmnqCxQZqMozv1Q=="
crossorigin="anonymous"
referrerpolicy="no-referrer" />
<script>
var require = {
paths: {
vs: 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.34.0/min/vs'
}
};
</script>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.34.1/min/vs/loader.min.js"
integrity="sha512-6bIYsGqvLpAiEBXPdRQeFf5cueeBECtAKJjIHer3BhBZNTV3WLcLA8Tm3pDfxUwTMIS+kAZwTUvJ1IrMdX8C5w=="
crossorigin="anonymous"
referrerpolicy="no-referrer"></script>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.34.1/min/vs/editor/editor.main.nls.min.js"
integrity="sha512-CCv+DKWw+yZhxf4Z+ExT6HC5G+3S45TeMTYcJyYbdrv4BpK2vyALJ4FoVR/KGWDIPu7w4tNCOC9MJQIkYPR5FA=="
crossorigin="anonymous"
referrerpolicy="no-referrer"></script>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.34.1/min/vs/editor/editor.main.js"
integrity="sha512-BtSZPhzoyN8kq1axY6cgOFPSgLJgFwvAZ3WxeDGxEFXeFcFuK2s7Hr+zF75npVHASUY1dxudAfIVzwmgdR89Bw=="
crossorigin="anonymous"
referrerpolicy="no-referrer"></script>
%sveltekit.head% %sveltekit.head%
</head> </head>
<body> <body>
+5 -5
View File
@@ -1,11 +1,11 @@
/// <reference types="vite/client" /> /// <reference types="vite/client" />
interface ImportMetaEnv { interface ImportMetaEnv {
readonly MERMAID_RENDERER_URL: string; readonly MERMAID_RENDERER_URL?: string;
readonly MERMAID_KROKI_RENDERER_URL: string; readonly MERMAID_KROKI_RENDERER_URL?: string;
readonly MERMAID_CDN_URL: string; readonly MERMAID_CDN_URL?: string;
readonly MERMAID_BASE_URL: string; readonly MERMAID_BASE_URL?: string;
readonly MERMAID_LOCAL: boolean; readonly MERMAID_LOCAL?: boolean;
// more env variables... // more env variables...
} }
+2 -1
View File
@@ -9,7 +9,8 @@ declare global {
namespace jest { namespace jest {
interface Matchers<R = void> interface Matchers<R = void>
// eslint-disable-next-line @typescript-eslint/ban-ts-comment // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore // @ts-expect-error
// eslint-disable-next-line no-undef
extends TestingLibraryMatchers<typeof expect.stringContaining, R> {} extends TestingLibraryMatchers<typeof expect.stringContaining, R> {}
} }
} }
@@ -1,22 +1,22 @@
<script lang="ts"> <script lang="ts">
import { browser } from '$app/environment'; import { browser } from '$app/environment';
import Card from '$lib/components/card/card.svelte'; import Card from '$lib/components/Card/Card.svelte';
import { env } from '$lib/util/env'; import { env } from '$lib/util/env';
import { pakoSerde } from '$lib/util/serde'; import { pakoSerde } from '$lib/util/serde';
import { stateStore } from '$lib/util/state'; import { stateStore } from '$lib/util/state';
import { logEvent } from '$lib/util/stats'; import { logEvent } from '$lib/util/stats';
import { toBase64 } from 'js-base64'; import { toBase64 } from 'js-base64';
import moment from 'moment'; import dayjs from 'dayjs';
const { krokiRendererUrl, rendererUrl } = env; const { krokiRendererUrl, rendererUrl } = env;
type Exporter = (context: CanvasRenderingContext2D, image: HTMLImageElement) => () => void; type Exporter = (context: CanvasRenderingContext2D, image: HTMLImageElement) => () => void;
const getFileName = (ext: string) => const getFileName = (ext: string) =>
`mermaid-diagram-${moment().format('YYYY-MM-DD-HHmmss')}.${ext}`; `mermaid-diagram-${dayjs().format('YYYY-MM-DD-HHmmss')}.${ext}`;
const getBase64SVG = (svg?: HTMLElement, width?: number, height?: number): string => { const getBase64SVG = (svg?: HTMLElement, width?: number, height?: number): string => {
svg?.setAttribute('height', `${height}px`); height && svg?.setAttribute('height', `${height}px`);
svg?.setAttribute('width', `${width}px`); // Workaround https://stackoverflow.com/questions/28690643/firefox-error-rendering-an-svg-image-to-html5-canvas-with-drawimage width && svg?.setAttribute('width', `${width}px`); // Workaround https://stackoverflow.com/questions/28690643/firefox-error-rendering-an-svg-image-to-html5-canvas-with-drawimage
if (!svg) { if (!svg) {
svg = getSvgEl(); svg = getSvgEl();
} }
@@ -28,7 +28,10 @@
const exportImage = (event: Event, exporter: Exporter) => { const exportImage = (event: Event, exporter: Exporter) => {
const canvas: HTMLCanvasElement = document.createElement('canvas'); const canvas: HTMLCanvasElement = document.createElement('canvas');
const svg: HTMLElement = document.querySelector('#container svg'); const svg: HTMLElement | null = document.querySelector('#container svg');
if (!svg) {
throw new Error('svg not found');
}
const box: DOMRect = svg.getBoundingClientRect(); const box: DOMRect = svg.getBoundingClientRect();
canvas.width = box.width; canvas.width = box.width;
canvas.height = box.height; canvas.height = box.height;
@@ -43,6 +46,9 @@
} }
const context = canvas.getContext('2d'); const context = canvas.getContext('2d');
if (!context) {
throw new Error('context not found');
}
context.fillStyle = 'white'; context.fillStyle = 'white';
context.fillRect(0, 0, canvas.width, canvas.height); context.fillRect(0, 0, canvas.width, canvas.height);
@@ -56,12 +62,12 @@
const getSvgEl = () => { const getSvgEl = () => {
const svgEl: HTMLElement = document const svgEl: HTMLElement = document
.querySelector('#container svg') .querySelector('#container svg')!
.cloneNode(true) as HTMLElement; .cloneNode(true) as HTMLElement;
svgEl.setAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink'); svgEl.setAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink');
const fontAwesomeCdnUrl = Array.from(document.head.getElementsByTagName('link')) const fontAwesomeCdnUrl = Array.from(document.head.getElementsByTagName('link'))
.map((l) => l.href) .map((l) => l.href)
.find((h) => h && h.includes('font-awesome')); .find((h) => h.includes('font-awesome'));
if (fontAwesomeCdnUrl == null) { if (fontAwesomeCdnUrl == null) {
return svgEl; return svgEl;
} }
@@ -99,10 +105,10 @@
context.drawImage(image, 0, 0, canvas.width, canvas.height); context.drawImage(image, 0, 0, canvas.width, canvas.height);
canvas.toBlob((blob) => { canvas.toBlob((blob) => {
try { try {
// @ts-ignore: https://github.com/microsoft/TypeScript-DOM-lib-generator/pull/1004/files if (!blob) {
throw new Error('blob is empty');
}
void navigator.clipboard.write([ void navigator.clipboard.write([
/* eslint-disable no-undef */
// @ts-ignore: https://github.com/microsoft/TypeScript/issues/43821
new ClipboardItem({ new ClipboardItem({
[blob.type]: blob [blob.type]: blob
}) })
@@ -142,7 +148,7 @@
let gistURL = ''; let gistURL = '';
stateStore.subscribe(({ loader }) => { stateStore.subscribe(({ loader }) => {
if (loader?.type === 'gist') { if (loader?.type === 'gist') {
// @ts-ignore Gist will have url // @ts-expect-error Gist will have url
gistURL = loader.config.url; gistURL = loader.config.url;
} }
}); });
@@ -166,8 +172,7 @@
if (browser && ['mermaid.live', 'netlify'].some((path) => window.location.host.includes(path))) { if (browser && ['mermaid.live', 'netlify'].some((path) => window.location.host.includes(path))) {
isNetlify = true; isNetlify = true;
} }
stateStore.subscribe(async (state) => { stateStore.subscribe(({ code, serialized }) => {
const { code, serialized } = await state;
iUrl = `${rendererUrl}/img/${serialized}?type=png`; iUrl = `${rendererUrl}/img/${serialized}?type=png`;
svgUrl = `${rendererUrl}/svg/${serialized}`; svgUrl = `${rendererUrl}/svg/${serialized}`;
krokiUrl = `${krokiRendererUrl}/mermaid/svg/${pakoSerde.serialize(code)}`; krokiUrl = `${krokiRendererUrl}/mermaid/svg/${pakoSerde.serialize(code)}`;
@@ -175,7 +180,7 @@
}); });
</script> </script>
<Card title="Actions" isOpen={true}> <Card title="Actions" isOpen={false}>
<div class="flex flex-wrap gap-2 m-2"> <div class="flex flex-wrap gap-2 m-2">
{#if isClipboardAvailable()} {#if isClipboardAvailable()}
<button class="action-btn w-full" on:click={onCopyClipboard} <button class="action-btn w-full" on:click={onCopyClipboard}
@@ -1,11 +1,11 @@
<script lang="ts"> <script lang="ts">
import type { Tab } from '$lib/types'; import type { Tab } from '$lib/types';
import { slide } from 'svelte/transition'; import { slide } from 'svelte/transition';
import Tabs from './tabs.svelte'; import Tabs from './Tabs.svelte';
export let isCloseable = true; export let isCloseable = true;
export let isOpen = true; export let isOpen = true;
export let tabs: Tab[] = []; export let tabs: Tab[] = [];
export let activeTabID: string = ''; export let activeTabID = '';
export let title: string; export let title: string;
$: isOpen = isCloseable ? isOpen : true; $: isOpen = isCloseable ? isOpen : true;
$: isTabsShown = isOpen && tabs.length > 0; $: isTabsShown = isOpen && tabs.length > 0;
@@ -1,6 +1,6 @@
import { cleanup, render } from '@testing-library/svelte'; import { cleanup, render } from '@testing-library/svelte';
import { describe, expect, it, afterEach } from 'vitest'; import { describe, expect, it, afterEach } from 'vitest';
import Card from './card.svelte'; import Card from './Card.svelte';
describe('card.svelte', () => { describe('card.svelte', () => {
// TODO: @testing-library/svelte claims to add this automatically but it doesn't work without explicit afterEach // TODO: @testing-library/svelte claims to add this automatically but it doesn't work without explicit afterEach
@@ -10,8 +10,8 @@ describe('card.svelte', () => {
const { container } = render(Card, { const { container } = render(Card, {
title: 'TabTest', title: 'TabTest',
tabs: [ tabs: [
{ id: 't1', title: 'title1' }, { id: 't1', title: 'title1', icon: 'fab fa-git-alt' },
{ id: 't2', title: 'title2' } { id: 't2', title: 'title2', icon: 'far fa-bookmark' }
] ]
}); });
expect(container).toBeTruthy(); expect(container).toBeTruthy();
@@ -19,6 +19,5 @@ describe('card.svelte', () => {
expect(container).toHaveTextContent('title1'); expect(container).toHaveTextContent('title1');
expect(container).toHaveTextContent('title2'); expect(container).toHaveTextContent('title2');
expect(container).not.toHaveTextContent('title3'); expect(container).not.toHaveTextContent('title3');
expect(container.innerHTML).toMatchSnapshot();
}); });
}); });
+128
View File
@@ -0,0 +1,128 @@
<script lang="ts">
import type { EditorMode } from '$lib/types';
import { stateStore, updateCode, updateConfig } from '$lib/util/state';
import { themeStore } from '$lib/util/theme';
import { errorDebug, syncDiagram } from '$lib/util/util';
import * as monaco from 'monaco-editor';
import monacoJsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker';
import monacoEditorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker';
import { onMount } from 'svelte';
import { initEditor } from '$lib/util/monacoExtra';
import { logEvent } from '$lib/util/stats';
let divEl: HTMLDivElement | undefined = undefined;
let editor: monaco.editor.IStandaloneCodeEditor | undefined;
let editorOptions: monaco.editor.IStandaloneEditorConstructionOptions = {
minimap: {
enabled: false
},
theme: 'mermaid',
overviewRulerLanes: 0
};
let text = '';
stateStore.subscribe(({ errorMarkers, editorMode, code, mermaid }) => {
// console.log('editor store subscription', { code, mermaid });
if (!editor) {
return;
}
// Update editor text if it's different
const newText = editorMode === 'code' ? code : mermaid;
if (newText !== text) {
// console.log('updating editor text', newText);
editor.setScrollTop(0);
editor.setValue(newText);
text = newText;
}
// Update editor mode if it's different
const language = editorMode === 'code' ? 'mermaid' : 'json';
const model = editor.getModel();
if (!model) {
console.error("editor model doesn't exist");
return;
}
if (model.getLanguageId() !== language) {
monaco.editor.setModelLanguage(model, language);
}
// Display/clear errors
monaco.editor.setModelMarkers(model, 'mermaid', errorMarkers);
});
themeStore.subscribe(({ isDark }) => {
editor && monaco.editor.setTheme(isDark ? 'mermaid-dark' : 'mermaid');
});
const handleUpdate = (text: string, mode: EditorMode) => {
// console.log('editor HandleUpdate', { text, mode });
if (mode === 'code') {
updateCode(text);
} else {
updateConfig(text);
}
};
onMount(async () => {
self.MonacoEnvironment = {
getWorker(_, label) {
if (label === 'json') {
return new monacoJsonWorker();
}
return new monacoEditorWorker();
}
};
if (!divEl) {
throw new Error('divEl is undefined');
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
initEditor(monaco);
errorDebug(100);
editor = monaco.editor.create(divEl, editorOptions);
editor.onDidChangeModelContent(({ isFlush, changes }) => {
const newText = editor?.getValue();
// console.log('editor onDidChangeModelContent', { text, newText, isFlush, changes });
if (!newText || text === newText || isFlush) {
return;
}
text = newText;
handleUpdate(text, $stateStore.editorMode);
});
editor.addAction({
id: 'mermaid-render-diagram',
label: 'Render Diagram',
keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter],
run: function () {
syncDiagram();
logEvent('renderDiagram', {
method: 'keyboardShortcut'
});
}
});
monaco.editor.setTheme($themeStore.isDark ? 'mermaid-dark' : 'mermaid');
const resizeObserver = new ResizeObserver((entries) => {
editor?.layout({
height: entries[0].contentRect.height,
width: entries[0].contentRect.width
});
});
if (divEl.parentElement) {
resizeObserver.observe(divEl.parentElement);
}
// @ts-ignore
if (window.Cypress) {
// @ts-ignore
window.editorLoaded = true;
}
return () => {
// console.log(`editor disposed`);
editor?.dispose();
};
});
</script>
<div bind:this={divEl} id="editor" class="overflow-hidden" />
@@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import Card from '$lib/components/card/card.svelte'; import Card from '$lib/components/Card/Card.svelte';
import { inputStateStore, getStateString } from '$lib/util/state'; import { inputStateStore, getStateString } from '$lib/util/state';
import { import {
addHistoryEntry, addHistoryEntry,
@@ -13,10 +13,13 @@
import { notify, prompt } from '$lib/util/notify'; import { notify, prompt } from '$lib/util/notify';
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import { get } from 'svelte/store'; import { get } from 'svelte/store';
import moment from 'moment'; import dayjs from 'dayjs';
import type { HistoryType, State, Tab } from '$lib/types'; import dayjsRelativeTime from 'dayjs/plugin/relativeTime';
import type { HistoryEntry, HistoryType, State, Tab } from '$lib/types';
import { logEvent } from '$lib/util/stats'; import { logEvent } from '$lib/util/stats';
dayjs.extend(dayjsRelativeTime);
const HISTORY_SAVE_INTERVAL = 60000; const HISTORY_SAVE_INTERVAL = 60000;
const tabSelectHandler = (message: CustomEvent<Tab>) => { const tabSelectHandler = (message: CustomEvent<Tab>) => {
@@ -41,7 +44,7 @@
const url = URL.createObjectURL(blob); const url = URL.createObjectURL(blob);
const a = document.createElement('a'); const a = document.createElement('a');
a.href = url; a.href = url;
a.download = `mermaid-history-${moment().format('YYYY-MM-DD-HHmmss')}.json`; a.download = `mermaid-history-${dayjs().format('YYYY-MM-DD-HHmmss')}.json`;
a.click(); a.click();
URL.revokeObjectURL(url); URL.revokeObjectURL(url);
logEvent('history', { logEvent('history', {
@@ -60,7 +63,7 @@
} }
const reader = new FileReader(); const reader = new FileReader();
reader.onload = (e) => { reader.onload = (e) => {
const data = JSON.parse(e.target.result as string); const data: HistoryEntry[] = JSON.parse(e.target.result as string);
restoreHistory(data); restoreHistory(data);
}; };
reader.readAsText(file); reader.readAsText(file);
@@ -95,7 +98,7 @@
const relativeTime = (time: number) => { const relativeTime = (time: number) => {
const t = new Date(time); const t = new Date(time);
return `${new Date(t).toLocaleString()} (${moment(t).fromNow()})`; return `${new Date(t).toLocaleString()} (${dayjs(t).fromNow()})`;
}; };
onMount(() => { onMount(() => {
@@ -161,7 +164,6 @@
<a <a
href={url} href={url}
target="_blank" target="_blank"
rel="noreferrer"
title="Open revision in new tab" title="Open revision in new tab"
class="hover:underline text-blue-500">{name}</a> class="hover:underline text-blue-500">{name}</a>
{:else} {:else}
@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-unnecessary-condition */
import type { HistoryEntry } from '$lib/types'; import type { HistoryEntry } from '$lib/types';
import { describe, it, expect } from 'vitest'; import { describe, it, expect } from 'vitest';
import { import {
@@ -7,7 +8,7 @@ import {
historyModeStore, historyModeStore,
historyStore historyStore
} from './history'; } from './history';
import { defaultState } from '../../util/state'; import { defaultState } from '$lib/util/state';
import { get } from 'svelte/store'; import { get } from 'svelte/store';
describe('history', () => { describe('history', () => {
@@ -17,28 +18,30 @@ describe('history', () => {
addHistoryEntry({ addHistoryEntry({
state: defaultState, state: defaultState,
time: 12345, time: 12_345,
type: 'manual' type: 'manual'
}); });
const [manualEntry]: HistoryEntry[] = JSON.parse( const [manualEntry] = JSON.parse(
window.localStorage.getItem('manualHistoryStore') window.localStorage.getItem('manualHistoryStore') ?? '[]'
); ) as HistoryEntry[];
expect(manualEntry.time).toBe(12345); expect(manualEntry.time).toBe(12_345);
expect(manualEntry.type).toBe('manual'); expect(manualEntry.type).toBe('manual');
expect(manualEntry.name).not.toBeNull(); expect(manualEntry.name).not.toBeNull();
expect(manualEntry.state).not.toBeNull(); expect(manualEntry.state).not.toBeNull();
addHistoryEntry({ addHistoryEntry({
state: defaultState, state: defaultState,
time: 54321, time: 54_321,
type: 'auto' type: 'auto'
}); });
const [autoEntry]: HistoryEntry[] = JSON.parse(window.localStorage.getItem('autoHistoryStore')); const [autoEntry] = JSON.parse(
window.localStorage.getItem('autoHistoryStore') ?? '[]'
) as HistoryEntry[];
expect(autoEntry.time).toBe(54321); expect(autoEntry.time).toBe(54_321);
expect(autoEntry.type).toBe('auto'); expect(autoEntry.type).toBe('auto');
expect(autoEntry.name).not.toBeNull(); expect(autoEntry.name).not.toBeNull();
expect(autoEntry.state).not.toBeNull(); expect(autoEntry.state).not.toBeNull();
@@ -54,12 +57,12 @@ describe('history', () => {
it('should clear history entries', () => { it('should clear history entries', () => {
addHistoryEntry({ addHistoryEntry({
state: defaultState, state: defaultState,
time: 12345, time: 12_345,
type: 'manual' type: 'manual'
}); });
addHistoryEntry({ addHistoryEntry({
state: { ...defaultState, code: 'graph TD\\n A[Christmas] -->|Get money| B(Go shopping)' }, state: { ...defaultState, code: 'graph TD\\n A[Christmas] -->|Get money| B(Go shopping)' },
time: 123456, time: 123_456,
type: 'manual' type: 'manual'
}); });
@@ -74,12 +77,12 @@ describe('history', () => {
historyModeStore.set('auto'); historyModeStore.set('auto');
addHistoryEntry({ addHistoryEntry({
state: defaultState, state: defaultState,
time: 54321, time: 54_321,
type: 'auto' type: 'auto'
}); });
addHistoryEntry({ addHistoryEntry({
state: { ...defaultState, code: 'graph TD\\n A[Christmas] -->|Get money| B(Go shopping)' }, state: { ...defaultState, code: 'graph TD\\n A[Christmas] -->|Get money| B(Go shopping)' },
time: 654321, time: 654_321,
type: 'auto' type: 'auto'
}); });
expect(get(historyStore).length).toBe(2); expect(get(historyStore).length).toBe(2);
@@ -101,19 +104,23 @@ describe('history migration', () => {
'autoHistoryStore', 'autoHistoryStore',
'[{"state":{"code":"graph TD\\n A[New Year] -->|Get money| B(Go shopping)","mermaid":"{\\n \\"theme\\": \\"dark\\"\\n}","autoSync":true,"updateDiagram":false},"time":0,"type":"auto","name":"barking-dog"},{"state":{"code":"graph TD\\n A[Christmas] -->|Get money| B(Go shopping)","mermaid":"{\\n \\"theme\\": \\"dark\\"\\n}","autoSync":true,"updateDiagram":true},"time":0,"type":"manual","name":"needy-mosquito"}]' '[{"state":{"code":"graph TD\\n A[New Year] -->|Get money| B(Go shopping)","mermaid":"{\\n \\"theme\\": \\"dark\\"\\n}","autoSync":true,"updateDiagram":false},"time":0,"type":"auto","name":"barking-dog"},{"state":{"code":"graph TD\\n A[Christmas] -->|Get money| B(Go shopping)","mermaid":"{\\n \\"theme\\": \\"dark\\"\\n}","autoSync":true,"updateDiagram":true},"time":0,"type":"manual","name":"needy-mosquito"}]'
); );
let manualHistoryStore: HistoryEntry[] = JSON.parse( let manualHistoryStore = JSON.parse(
window.localStorage.getItem('manualHistoryStore') window.localStorage.getItem('manualHistoryStore') ?? '[]'
); ) as HistoryEntry[];
let autoHistoryStore: HistoryEntry[] = JSON.parse( let autoHistoryStore = JSON.parse(
window.localStorage.getItem('autoHistoryStore') window.localStorage.getItem('autoHistoryStore') ?? '[]'
); ) as HistoryEntry[];
expect(manualHistoryStore.every(({ id }) => id !== undefined)).toBe(false); expect(manualHistoryStore.every(({ id }) => id !== undefined)).toBe(false);
expect(autoHistoryStore.every(({ id }) => id !== undefined)).toBe(false); expect(autoHistoryStore.every(({ id }) => id !== undefined)).toBe(false);
injectHistoryIDs(); injectHistoryIDs();
manualHistoryStore = JSON.parse(window.localStorage.getItem('manualHistoryStore')); manualHistoryStore = JSON.parse(
autoHistoryStore = JSON.parse(window.localStorage.getItem('autoHistoryStore')); window.localStorage.getItem('manualHistoryStore') ?? '[]'
) as HistoryEntry[];
autoHistoryStore = JSON.parse(
window.localStorage.getItem('autoHistoryStore') ?? '[]'
) as HistoryEntry[];
expect(manualHistoryStore.every(({ id }) => id !== undefined)).toBe(true); expect(manualHistoryStore.every(({ id }) => id !== undefined)).toBe(true);
expect(autoHistoryStore.every(({ id }) => id !== undefined)).toBe(true); expect(autoHistoryStore.every(({ id }) => id !== undefined)).toBe(true);
}); });
@@ -26,19 +26,27 @@ const manualHistoryStore: Writable<HistoryEntry[]> = persist(
'manualHistoryStore' 'manualHistoryStore'
); );
export const loaderHistoryStore: Writable<HistoryEntry[]> = writable([] as HistoryEntry[]); export const loaderHistoryStore: Writable<HistoryEntry[]> = writable([]);
export const historyStore: Readable<HistoryEntry[]> = derived( export const historyStore: Readable<HistoryEntry[]> = derived(
[historyModeStore, autoHistoryStore, manualHistoryStore, loaderHistoryStore], [historyModeStore, autoHistoryStore, manualHistoryStore, loaderHistoryStore],
([historyMode, autoHistories, manualHistories, loadedHistories], set) => { ([historyMode, autoHistories, manualHistories, loadedHistories], set) => {
if (historyMode === 'auto') { switch (historyMode) {
set(autoHistories); case 'auto': {
} else if (historyMode === 'manual') { set(autoHistories);
set(manualHistories); break;
} else if (historyMode === 'loader') { }
set(loadedHistories); case 'manual': {
} else { set(manualHistories);
set(autoHistories); break;
}
case 'loader': {
set(loadedHistories);
break;
}
default: {
set(autoHistories);
}
} }
} }
); );
@@ -65,10 +73,10 @@ export const addHistoryEntry = (entryToAdd: Optional<HistoryEntry, 'id'>): void
} }
return [entry, ...entries]; return [entry, ...entries];
}); });
} else if (entry.type === 'manual') {
manualHistoryStore.update((entries) => [entry, ...entries]);
logEvent('history', { action: 'save' });
} }
manualHistoryStore.update((entries) => [entry, ...entries]);
logEvent('history', { action: 'save' });
}; };
export const clearHistoryData = (idToClear?: string): void => { export const clearHistoryData = (idToClear?: string): void => {
@@ -90,7 +98,7 @@ export const getPreviousState = (auto: boolean): string => {
}; };
export const restoreHistory = (data: HistoryEntry[]) => { export const restoreHistory = (data: HistoryEntry[]) => {
const entries = data.filter(validateEntry); const entries = data.filter((element) => validateEntry(element));
const invalidEntryCount = data.length - entries.length; const invalidEntryCount = data.length - entries.length;
if (invalidEntryCount > 0) { if (invalidEntryCount > 0) {
console.error(`${invalidEntryCount} invalid history entries were removed.`); console.error(`${invalidEntryCount} invalid history entries were removed.`);
@@ -122,20 +130,23 @@ export const restoreHistory = (data: HistoryEntry[]) => {
alert('No valid entries found.'); alert('No valid entries found.');
} }
}; };
const setIDs = (entries: HistoryEntry[]) => {
for (const entry of entries) {
if (!entry.id) {
entry.id = uuidV4();
}
}
return entries;
};
export const injectHistoryIDs = (): void => { export const injectHistoryIDs = (): void => {
const setIDs = (entries: HistoryEntry[]) => {
for (const entry of entries) {
if (!entry.id) {
entry.id = uuidV4();
}
}
return entries;
};
autoHistoryStore.update(setIDs); autoHistoryStore.update(setIDs);
manualHistoryStore.update(setIDs); manualHistoryStore.update(setIDs);
}; };
const validateEntry = (entry: HistoryEntry): boolean => { const validateEntry = (entry: HistoryEntry): boolean => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
return entry.type && entry.state && entry.time && true; return entry.type && entry.state && entry.time && true;
}; };
@@ -1,27 +1,28 @@
<script context="module"> <script context="module" lang="ts">
import { version } from 'mermaid/package.json'; import { version } from 'mermaid/package.json';
import { analytics } from '$lib/util/stats'; import { analytics } from '$lib/util/stats';
analytics?.track('version', { void analytics?.track('version', {
mermaidVersion: version mermaidVersion: version
}); });
</script> </script>
<script lang="ts"> <script lang="ts">
import Theme from './theme.svelte'; import Theme from './Theme.svelte';
interface Link { interface Link {
title: string;
href: string; href: string;
title?: string;
icon?: string; icon?: string;
img?: string;
} }
const links: Link[] = [ const links: Link[] = [
{ {
title: 'Documentation', title: 'Documentation',
href: 'https://mermaid-js.github.io/mermaid/#/n00b-gettingStarted' href: 'https://mermaid.js.org/intro/n00b-gettingStarted.html'
}, },
{ {
title: 'Tutorial', title: 'Tutorial',
href: 'https://github.com/mermaid-js/mermaid/blob/develop/docs/Tutorials.md' href: 'https://mermaid.js.org/config/Tutorials.html'
}, },
{ {
title: 'Mermaid', title: 'Mermaid',
@@ -32,9 +33,12 @@
href: 'https://github.com/mermaid-js/mermaid-cli' href: 'https://github.com/mermaid-js/mermaid-cli'
}, },
{ {
title: '',
href: 'https://github.com/mermaid-js/mermaid-live-editor', href: 'https://github.com/mermaid-js/mermaid-live-editor',
icon: 'fab fa-github fa-lg' icon: 'fab fa-github fa-lg'
},
{
href: 'https://mermaidchart.com',
img: '/mermaidchart-logo.svg'
} }
]; ];
</script> </script>
@@ -47,7 +51,7 @@
</div> </div>
<label for="menu-toggle" class="pointer-cursor lg:hidden block" <label for="menu-toggle" class="pointer-cursor lg:hidden block"
><svg ><svg
class="fill-current " class="fill-current"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
width="20" width="20"
height="20" height="20"
@@ -59,13 +63,18 @@
<Theme /> <Theme />
<div class="hidden lg:flex lg:items-center lg:w-auto w-full" id="menu"> <div class="hidden lg:flex lg:items-center lg:w-auto w-full" id="menu">
<ul class="lg:flex items-center justify-between text-base pt-4 lg:pt-0"> <ul class="lg:flex items-center justify-between text-base pt-4 lg:pt-0">
{#each links as { title, href, icon }} {#each links as { title, href, icon, img }}
<li> <li>
<a class="btn btn-ghost" target="_blank" rel="noreferrer" {href}> <a class="btn btn-ghost" target="_blank" {href}>
{#if icon} {#if icon}
<i class={icon} /> <i class={icon} />
{:else if img}
<img src={img} alt={title} />
{/if} {/if}
{title}</a> {#if title}
{title}
{/if}
</a>
</li> </li>
{/each} {/each}
</ul> </ul>
@@ -79,4 +88,9 @@
.navbar { .navbar {
z-index: 10000; z-index: 10000;
} }
img {
width: 1.5rem;
height: 1.5rem;
}
</style> </style>
@@ -1,10 +1,10 @@
<script lang="ts"> <script lang="ts">
import { updateCode } from '$lib/util/state'; import { updateCode } from '$lib/util/state';
import Card from '$lib/components/card/card.svelte'; import Card from '$lib/components/Card/Card.svelte';
import { logEvent } from '$lib/util/stats'; import { logEvent } from '$lib/util/stats';
const samples = { const samples = {
Flow: `graph TD Flow: `flowchart TD
A[Christmas] -->|Get money| B(Go shopping) A[Christmas] -->|Get money| B(Go shopping)
B --> C{Let me think} B --> C{Let me think}
C -->|One| D[Laptop] C -->|One| D[Laptop]
@@ -101,10 +101,25 @@
Argument mapping Argument mapping
Tools Tools
Pen and paper Pen and paper
Mermaid` Mermaid`,
QuadrantChart: `quadrantChart
title Reach and engagement of campaigns
x-axis Low Reach --> High Reach
y-axis Low Engagement --> High Engagement
quadrant-1 We should expand
quadrant-2 Need to promote
quadrant-3 Re-evaluate
quadrant-4 May be improved
Campaign A: [0.3, 0.6]
Campaign B: [0.45, 0.23]
Campaign C: [0.57, 0.69]
Campaign D: [0.78, 0.34]
Campaign E: [0.40, 0.34]
Campaign F: [0.35, 0.78]`
}; };
const loadSampleDiagram = (diagramType: string): void => { type SampleTypes = keyof typeof samples;
const loadSampleDiagram = (diagramType: SampleTypes): void => {
updateCode(samples[diagramType], { updateCode(samples[diagramType], {
updateDiagram: true, updateDiagram: true,
resetPanZoom: true resetPanZoom: true
@@ -113,8 +128,8 @@
}; };
// Adding in this array will add an icon to the preset menu // Adding in this array will add an icon to the preset menu
const newDiagrams: Array<keyof typeof samples> = ['Mindmap']; const newDiagrams: SampleTypes[] = ['Mindmap', 'QuadrantChart'];
const diagramOrder: Array<keyof typeof samples> = [ const diagramOrder: SampleTypes[] = [
'Sequence', 'Sequence',
'Flow', 'Flow',
'Class', 'Class',
@@ -124,7 +139,8 @@
'User Journey', 'User Journey',
'Git', 'Git',
'Pie', 'Pie',
'Mindmap' 'Mindmap',
'QuadrantChart'
]; ];
</script> </script>
@@ -1,4 +1,4 @@
<script> <script lang="ts">
import { setTheme, themeStore } from '$lib/util/theme'; import { setTheme, themeStore } from '$lib/util/theme';
const themes = [ const themes = [
@@ -28,7 +28,7 @@
<div class="hidden lg:block dropdown"> <div class="hidden lg:block dropdown">
<!-- svelte-ignore a11y-no-noninteractive-tabindex --> <!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<div tabindex="0" class="btn btn-ghost "> <div tabindex="0" class="btn btn-ghost">
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
fill="none" fill="none"
@@ -39,7 +39,7 @@
stroke-linejoin="round" stroke-linejoin="round"
stroke-width="2" stroke-width="2"
d="M7 21a4 4 0 01-4-4V5a2 2 0 012-2h4a2 2 0 012 2v12a4 4 0 01-4 4zm0 0h12a2 2 0 002-2v-4a2 2 0 00-2-2h-2.343M11 7.343l1.657-1.657a2 2 0 012.828 0l2.829 2.829a2 2 0 010 2.828l-8.486 8.485M7 17h.01" /></svg> d="M7 21a4 4 0 01-4-4V5a2 2 0 012-2h4a2 2 0 012 2v12a4 4 0 01-4 4zm0 0h12a2 2 0 002-2v-4a2 2 0 00-2-2h-2.343M11 7.343l1.657-1.657a2 2 0 012.828 0l2.829 2.829a2 2 0 010 2.828l-8.486 8.485M7 17h.01" /></svg>
<span class="hidden md:inline"> Change Theme </span> <span class="hidden md:inline">Theme</span>
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 1792 1792" viewBox="0 0 1792 1792"
@@ -52,7 +52,7 @@
<!-- svelte-ignore a11y-no-noninteractive-tabindex --> <!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<ul tabindex="0" class="p-4 menu compact"> <ul tabindex="0" class="p-4 menu compact">
{#each themes as theme} {#each themes as theme}
<li class={theme.includes($themeStore.theme) ? 'bordered' : ''}> <li class:bordered={$themeStore.theme !== undefined && theme.includes($themeStore.theme)}>
<span <span
class="btn btn-ghost justify-start" class="btn btn-ghost justify-start"
on:click={() => setTheme(theme)} on:click={() => setTheme(theme)}
@@ -4,8 +4,9 @@
import panzoom from 'svg-pan-zoom'; import panzoom from 'svg-pan-zoom';
import type { State, ValidatedState } from '$lib/types'; import type { State, ValidatedState } from '$lib/types';
import { logEvent } from '$lib/util/stats'; import { logEvent } from '$lib/util/stats';
import { AsyncQueue, cmdKey } from '$lib/util/util'; import { cmdKey } from '$lib/util/util';
import { render as renderDiagram } from '$lib/util/mermaid'; import { render as renderDiagram } from '$lib/util/mermaid';
import type { MermaidConfig } from 'mermaid';
let code = ''; let code = '';
let config = ''; let config = '';
@@ -16,9 +17,12 @@
let hide = false; let hide = false;
let manualUpdate = true; let manualUpdate = true;
let panZoomEnabled = $stateStore.panZoom; let panZoomEnabled = $stateStore.panZoom;
let pzoom: SvgPanZoom.Instance; let pzoom: typeof panzoom | undefined;
const handlePanZoomChange = () => { const handlePanZoomChange = () => {
if (!pzoom) {
return;
}
const pan = pzoom.getPan(); const pan = pzoom.getPan();
const zoom = pzoom.getZoom(); const zoom = pzoom.getZoom();
updateCodeStore({ pan, zoom }); updateCodeStore({ pan, zoom });
@@ -32,8 +36,11 @@
hide = true; hide = true;
pzoom?.destroy(); pzoom?.destroy();
pzoom = undefined; pzoom = undefined;
Promise.resolve().then(() => { void Promise.resolve().then(() => {
const graphDiv = document.getElementById('graph-div'); const graphDiv = document.getElementById('graph-div');
if (!graphDiv) {
return;
}
pzoom = panzoom(graphDiv, { pzoom = panzoom(graphDiv, {
onPan: handlePanZoomChange, onPan: handlePanZoomChange,
onZoom: handlePanZoomChange, onZoom: handlePanZoomChange,
@@ -70,27 +77,30 @@
code = state.code; code = state.code;
config = state.mermaid; config = state.mermaid;
panZoomEnabled = state.panZoom; panZoomEnabled = state.panZoom;
const scroll = view.parentElement.scrollTop; const scroll = view.parentElement!.scrollTop;
delete container.dataset.processed; delete container.dataset.processed;
await renderDiagram( const { svg, bindFunctions } = await renderDiagram(
Object.assign({}, JSON.parse(state.mermaid)), Object.assign({}, JSON.parse(state.mermaid)) as MermaidConfig,
code, code,
'graph-div', 'graph-div'
(svgCode, bindFunctions) => {
if (svgCode.length > 0) {
handlePanZoom(state);
container.innerHTML = svgCode;
// console.log(container.innerHTML);
const graphDiv = document.getElementById('graph-div');
graphDiv.setAttribute('height', '100%');
graphDiv.style.maxWidth = '100%';
if (bindFunctions) {
bindFunctions(graphDiv);
}
}
}
); );
view.parentElement.scrollTop = scroll;
if (svg.length > 0) {
handlePanZoom(state);
container.innerHTML = svg;
console.log({ svg });
const graphDiv = document.getElementById('graph-div');
if (!graphDiv) {
throw new Error('graph-div not found');
}
graphDiv.setAttribute('height', '100%');
graphDiv.style.maxWidth = '100%';
if (bindFunctions) {
bindFunctions(graphDiv);
}
}
view.parentElement!.scrollTop = scroll;
error = false; error = false;
} else if (manualUpdate) { } else if (manualUpdate) {
manualUpdate = false; manualUpdate = false;
@@ -103,29 +113,26 @@
} }
}; };
const q = new AsyncQueue(handleStateChange);
onMount(() => { onMount(() => {
stateStore.subscribe(async (state) => { stateStore.subscribe((state) => {
await q.process(state); void handleStateChange(state);
}); });
window.addEventListener('resize', () => { window.addEventListener('resize', () => {
if ($stateStore.panZoom && pzoom) { if ($stateStore.panZoom && pzoom) {
pzoom.resize(); pzoom.resize();
} }
}); });
console.log('View mounted');
}); });
</script> </script>
{#if (error && $stateStore.error instanceof Error) || outOfSync} {#if (error && $stateStore.error instanceof Error) || outOfSync}
<div <div
class="absolute w-full p-2 z-10 {error class="absolute w-full p-2 z-10 font-mono {error
? 'text-red-600' ? 'text-red-600'
: 'text-yellow-600'} bg-base-100 bg-opacity-80 text-center" : 'text-yellow-600'} bg-base-100 bg-opacity-80 text-left"
id="errorContainer"> id="errorContainer">
{#if error} {#if error}
{$stateStore.error} {@html $stateStore.error?.toString().replace(/\n/g, '<br />')}
{:else} {:else}
Diagram out of sync. <br /> Diagram out of sync. <br />
Press <i class="fas fa-sync" /> (Sync button) or <kbd>{cmdKey} + Enter</kbd> to sync. Press <i class="fas fa-sync" /> (Sync button) or <kbd>{cmdKey} + Enter</kbd> to sync.
@@ -1,3 +0,0 @@
// Vitest Snapshot v1
exports[`card.svelte > mounts 1`] = `"<div><div class=\\"card rounded overflow-hidden m-2 flex-grow flex flex-col shadow-2xl\\"><div class=\\"bg-primary p-2 pb-0 flex-none cursor-pointer\\"><div class=\\"flex justify-between\\"><div class=\\"flex cursor-default s-_wx1E_JHsCoF\\"><span class=\\"mr-2 font-semibold s-_wx1E_JHsCoF\\"><i class=\\"fas fa-chevron-right icon s-_wx1E_JHsCoF isOpen\\"></i> TabTest</span> <ul class=\\"tabs s-_wx1E_JHsCoF\\"><div class=\\"tab tab-lifted tab-active s-_wx1E_JHsCoF\\"><i class=\\"mr-1 undefined s-_wx1E_JHsCoF\\"></i> title1 </div><div class=\\"tab tab-lifted text-primary-content s-_wx1E_JHsCoF\\"><i class=\\"mr-1 undefined s-_wx1E_JHsCoF\\"></i> title2 </div></ul></div><!--<Tabs>--> <div class=\\"flex gap-x-4 items-center -mt-2\\"></div></div></div> <div class=\\"card-body p-0 flex-grow overflow-auto text-base-content\\"></div></div><!--<Card>--></div>"`;
-115
View File
@@ -1,115 +0,0 @@
<script lang="ts">
import type { EditorMode } from '$lib/types';
import { stateStore, updateCode, updateConfig } from '$lib/util/state';
import { themeStore } from '$lib/util/theme';
import { errorDebug, syncDiagram } from '$lib/util/util';
import type monaco from 'monaco-editor';
import { onMount } from 'svelte';
import initEditor from 'monaco-mermaid';
import { logEvent } from '$lib/util/stats';
let divEl: HTMLDivElement = null;
let editor: monaco.editor.IStandaloneCodeEditor;
let Monaco: typeof monaco;
let editorOptions: monaco.editor.IStandaloneEditorConstructionOptions = {
minimap: {
enabled: false
},
theme: 'mermaid',
overviewRulerLanes: 0
};
let text = '';
stateStore.subscribe(({ errorMarkers, editorMode, code, mermaid }) => {
console.log('editor store subscription', { code, mermaid });
if (!editor) return;
// Update editor text if it's different
const newText = editorMode === 'code' ? code : mermaid;
if (newText !== text) {
console.log('updating editor text', newText);
editor.setValue(newText);
text = newText;
}
// Update editor mode if it's different
const language = editorMode === 'code' ? 'mermaid' : 'json';
if (editor.getModel().getLanguageId() !== language) {
Monaco?.editor.setModelLanguage(editor.getModel(), language);
}
// Display/clear errors
Monaco?.editor.setModelMarkers(editor.getModel(), 'mermaid', errorMarkers);
});
themeStore.subscribe(({ isDark }) => {
editor && Monaco?.editor.setTheme(isDark ? 'mermaid-dark' : 'mermaid');
});
const handleUpdate = (text: string, mode: EditorMode) => {
console.log('editor HandleUpdate', { text, mode });
if (mode === 'code') {
updateCode(text);
} else {
updateConfig(text);
}
};
const loadMonaco = async () => {
console.log('Loading Monaco...');
// errorDebug();
let i = 0;
while (i++ < 500) {
// @ts-ignore : This is a hack to handle a svelte-kit error when importing monaco.
Monaco = window.monaco;
if (Monaco !== undefined) {
return;
}
await new Promise((r) => setTimeout(r, 100));
}
alert('Loading Monaco Editor failed. Please try refreshing the page.');
};
onMount(async () => {
await loadMonaco(); // Fix https://github.com/mermaid-js/mermaid-live-editor/issues/175
initEditor(Monaco);
errorDebug(100);
editor = Monaco.editor.create(divEl, editorOptions);
editor.onDidChangeModelContent(({ isFlush, changes }) => {
const newText = editor.getValue();
console.log('editor onDidChangeModelContent', { text, newText, isFlush, changes });
if (text === newText || isFlush) {
return;
}
text = newText;
handleUpdate(text, $stateStore.editorMode);
});
editor.addAction({
id: 'mermaid-render-diagram',
label: 'Render Diagram',
keybindings: [Monaco.KeyMod.CtrlCmd | Monaco.KeyCode.Enter],
run: function () {
syncDiagram();
logEvent('renderDiagram', {
method: 'keyboadShortcut'
});
}
});
Monaco?.editor.setTheme($themeStore.isDark ? 'mermaid-dark' : 'mermaid');
const resizeObserver = new ResizeObserver((entries) => {
editor.layout({
height: entries[0].contentRect.height,
width: entries[0].contentRect.width
});
});
resizeObserver.observe(divEl.parentElement);
console.log(`editor mounted`);
return () => {
console.log(`editor disposed`);
editor.dispose();
};
});
</script>
<div bind:this={divEl} id="editor" class="overflow-hidden" />
+15 -13
View File
@@ -1,11 +1,3 @@
/**
* Can be made globally available by placing this
* inside `global.d.ts` and removing `export` keyword
*/
export interface Locals {
userid: string;
}
export interface MarkerData { export interface MarkerData {
severity: number; severity: number;
message: string; message: string;
@@ -40,7 +32,7 @@ export interface State {
export interface ValidatedState extends State { export interface ValidatedState extends State {
editorMode: EditorMode; editorMode: EditorMode;
error: unknown; error?: Error;
errorMarkers: MarkerData[]; errorMarkers: MarkerData[];
serialized: string; serialized: string;
} }
@@ -73,14 +65,24 @@ export type HistoryEntry = { id: string; state: State; time: number; url?: strin
} }
); );
export interface DocConfig { export type DocumentationConfig = Record<
[key: string]: { string,
{
code: string; code: string;
config?: string; config?: string;
}; }
} >;
export type EditorMode = 'code' | 'config'; export type EditorMode = 'code' | 'config';
export type Loader = (url: string) => Promise<State>; export type Loader = (url: string) => Promise<State>;
export type Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>; export type Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>;
export interface ErrorHash {
loc: {
first_line: number;
last_line: number;
first_column: number;
last_column: number;
};
}
+61 -41
View File
@@ -3,19 +3,26 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access */ /* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-explicit-any */
import type { State } from '$lib/types'; import type { State } from '$lib/types';
import { defaultState } from '../state'; import { defaultState } from '$lib/util/state';
import { addHistoryEntry } from '../../components/history/history'; import { addHistoryEntry } from '$lib/components/History/history';
import { fetchJSON, fetchText } from '$lib/util/util';
const codeFileName = 'code.mmd'; const codeFileName = 'code.mmd';
const configFileName = 'config.json'; const configFileName = 'config.json';
interface GithubFile {
truncated: boolean;
raw_url: string;
content: string;
}
const isValidGist = (files: any): boolean => { const isValidGist = (files: any): boolean => {
return codeFileName in files; return codeFileName in files;
}; };
const getFileContent = async (file: any): Promise<string> => { const getFileContent = async (file: GithubFile): Promise<string> => {
if (file.truncated) { if (file.truncated) {
return await (await fetch(file.raw_url)).text(); return await fetchText(file.raw_url);
} }
return file.content; return file.content;
}; };
@@ -29,16 +36,26 @@ interface GistData {
url: string; url: string;
} }
interface GistResponse {
files: Record<string, GithubFile>;
html_url: string;
history: { url: string; committed_at: string; version: string; user: { login: string } }[];
}
const getGistData = async (gistURL: string): Promise<GistData> => { const getGistData = async (gistURL: string): Promise<GistData> => {
const path = gistURL.split('github.com').pop();
if (!path) {
throw new Error('Invalid GitHub URL' + gistURL);
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
const [_, __, gistID, revisionID] = gistURL.split('github.com').pop().split('/'); const [_, __, gistID, revisionID] = path.split('/');
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const { html_url, files, history } = await ( const { html_url, files, history }: GistResponse = await fetchJSON(
await fetch(`https://api.github.com/gists/${gistID}${revisionID ? '/' + revisionID : ''}`) `https://api.github.com/gists/${gistID}${revisionID ? '/' + revisionID : ''}`
).json(); );
if (isValidGist(files)) { if (isValidGist(files)) {
const code = await getFileContent(files[codeFileName]); const code = await getFileContent(files[codeFileName]);
let config: string; let config = '{}';
if (configFileName in files) { if (configFileName in files) {
config = await getFileContent(files[configFileName]); config = await getFileContent(files[configFileName]);
} }
@@ -50,10 +67,10 @@ const getGistData = async (gistURL: string): Promise<GistData> => {
config, config,
author: currentItem.user.login, author: currentItem.user.login,
time: new Date(currentItem.committed_at).getTime(), time: new Date(currentItem.committed_at).getTime(),
version: (currentItem.version as string).slice(-7) version: currentItem.version.slice(-7)
}; };
} else { } else {
throw 'Invalid gist provided'; throw new Error('Invalid gist provided');
} }
}; };
@@ -73,35 +90,38 @@ const getStateFromGist = (gist: GistData, gistURL: string = gist.url): State =>
}; };
export const loadGistData = async (gistURL: string): Promise<State> => { export const loadGistData = async (gistURL: string): Promise<State> => {
try { const path = gistURL.split('github.com').pop();
// eslint-disable-next-line @typescript-eslint/no-unused-vars if (!path) {
const [_, __, gistID, revisionID] = gistURL.split('github.com').pop().split('/'); throw new Error('Invalid GitHub URL' + gistURL);
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const { history } = await (
await fetch(`https://api.github.com/gists/${gistID}${revisionID ? '/' + revisionID : ''}`)
).json();
const gistHistory: GistData[] = [];
for (const entry of history) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const data: GistData = await getGistData(entry.url).catch(() => undefined);
data && gistHistory.push(data);
}
if (gistHistory.length === 0) {
throw 'Invalid gist provided';
}
gistHistory.reverse();
const state = getStateFromGist(gistHistory.slice(-1).pop(), gistURL);
for (const gist of gistHistory) {
addHistoryEntry({
state: getStateFromGist(gist),
time: gist.time,
type: 'loader',
url: gist.url,
name: `${gist.author} v${gist.version}`
});
}
return state;
} catch (err) {
console.error(err);
} }
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [_, __, gistID, revisionID] = path.split('/');
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const { history }: GistResponse = await fetchJSON(
`https://api.github.com/gists/${gistID}${revisionID ? '/' + revisionID : ''}`
);
const gistHistory: GistData[] = [];
for (const entry of history) {
const data: GistData | undefined = await getGistData(entry.url).catch();
data && gistHistory.push(data);
}
if (gistHistory.length === 0) {
throw new Error('Invalid gist provided');
}
gistHistory.reverse();
const entry = gistHistory.slice(-1).pop();
if (!entry) {
throw new Error('Invalid gist provided');
}
const state = getStateFromGist(entry, gistURL);
for (const gist of gistHistory) {
addHistoryEntry({
state: getStateFromGist(gist),
time: gist.time,
type: 'loader',
url: gist.url,
name: `${gist.author} v${gist.version}`
});
}
return state;
}; };
+24 -25
View File
@@ -1,6 +1,8 @@
import { loadGistData } from './gist'; import { loadGistData } from './gist';
import { updateCodeStore, defaultState } from '../state'; import { updateCodeStore, defaultState } from '$lib/util/state';
import { fetchText } from '$lib/util/util';
import type { Loader, State } from '$lib/types'; import type { Loader, State } from '$lib/types';
const loaders: Record<string, Loader> = { const loaders: Record<string, Loader> = {
gist: loadGistData gist: loadGistData
}; };
@@ -8,36 +10,21 @@ const loaders: Record<string, Loader> = {
export const loadDataFromUrl = async (): Promise<void> => { export const loadDataFromUrl = async (): Promise<void> => {
const searchParams = new URLSearchParams(window.location.search); const searchParams = new URLSearchParams(window.location.search);
let state: Partial<State> = defaultState; let state: Partial<State> = defaultState;
let code: string, config: string;
let loaded = false; let loaded = false;
const codeURL: string = searchParams.get('code'); const codeURL: string | undefined = searchParams.get('code') ?? undefined;
const configURL: string = searchParams.get('config'); const configURL: string | undefined = searchParams.get('config') ?? undefined;
let code: string | undefined;
const config = configURL ? await fetchText(configURL) : defaultState.mermaid;
if (codeURL) { if (codeURL) {
code = await (await fetch(codeURL)).text(); code = await fetchText(codeURL);
loaded = true; loaded = true;
} }
if (configURL) { if (code) {
config = await (await fetch(configURL)).text(); if (!codeURL) {
} else { throw new Error('Code URL is not defined');
config = defaultState.mermaid;
}
if (!code) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
for (const [key, value] of searchParams.entries()) {
if (key in loaders) {
try {
state = await loaders[key](value);
loaded = true;
break;
} catch (err) {
console.error(err);
}
}
} }
} else {
state = { state = {
code, code,
mermaid: config, mermaid: config,
@@ -49,6 +36,18 @@ export const loadDataFromUrl = async (): Promise<void> => {
} }
} }
}; };
} else {
for (const [key, value] of searchParams.entries()) {
if (key in loaders) {
try {
state = await loaders[key](value);
loaded = true;
break;
} catch (error) {
console.error(error);
}
}
}
} }
loaded && loaded &&
updateCodeStore({ updateCodeStore({
+7 -18
View File
@@ -1,27 +1,16 @@
import mermaid, { type MermaidConfig } from 'mermaid'; import mermaid from 'mermaid';
import mindmap from '@mermaid-js/mermaid-mindmap'; import type { MermaidConfig, RenderResult } from 'mermaid';
const initialize = mermaid.registerExternalDiagrams([mindmap]);
export const init = async () => {
await initialize;
};
export const render = async ( export const render = async (
config: MermaidConfig, config: MermaidConfig,
code: string, code: string,
id: string, id: string
callback: Parameters<typeof mermaid.render>[2] ): Promise<RenderResult> => {
): Promise<void> => {
// Should be able to call this multiple times without any issues. // Should be able to call this multiple times without any issues.
mermaid.initialize(config); mermaid.initialize(config);
// console.log('Rendering', code); return await mermaid.render(id, code);
// mermaid.mermaidAPI.render(id, code, callback);
await init();
await mermaid.mermaidAPI.renderAsync(id, code, callback);
}; };
export const parse = async (code: string): Promise<boolean> => { export const parse = async (code: string): Promise<unknown> => {
await init(); return await mermaid.parse(code);
return (await mermaid.parseAsync(code)) as boolean;
}; };
+10 -6
View File
@@ -16,18 +16,22 @@ describe('migrations', () => {
it('should migrate from v0 to v1', async () => { it('should migrate from v0 to v1', async () => {
const { applyMigrations } = await import('./migrations'); const { applyMigrations } = await import('./migrations');
let manualHistoryStore: HistoryEntry[] = JSON.parse( let manualHistoryStore: HistoryEntry[] = JSON.parse(
window.localStorage.getItem('manualHistoryStore') window.localStorage.getItem('manualHistoryStore') ?? '[]'
); ) as HistoryEntry[];
let autoHistoryStore: HistoryEntry[] = JSON.parse( let autoHistoryStore: HistoryEntry[] = JSON.parse(
window.localStorage.getItem('autoHistoryStore') window.localStorage.getItem('autoHistoryStore') ?? '[]'
); ) as HistoryEntry[];
expect(manualHistoryStore.every(({ id }) => id !== undefined)).toBe(false); expect(manualHistoryStore.every(({ id }) => id !== undefined)).toBe(false);
expect(autoHistoryStore.every(({ id }) => id !== undefined)).toBe(false); expect(autoHistoryStore.every(({ id }) => id !== undefined)).toBe(false);
applyMigrations(); applyMigrations();
manualHistoryStore = JSON.parse(window.localStorage.getItem('manualHistoryStore')); manualHistoryStore = JSON.parse(
autoHistoryStore = JSON.parse(window.localStorage.getItem('autoHistoryStore')); window.localStorage.getItem('manualHistoryStore') ?? '[]'
) as HistoryEntry[];
autoHistoryStore = JSON.parse(
window.localStorage.getItem('autoHistoryStore') ?? '[]'
) as HistoryEntry[];
expect(manualHistoryStore.every(({ id }) => id !== undefined)).toBe(true); expect(manualHistoryStore.every(({ id }) => id !== undefined)).toBe(true);
expect(autoHistoryStore.every(({ id }) => id !== undefined)).toBe(true); expect(autoHistoryStore.every(({ id }) => id !== undefined)).toBe(true);
}); });
+2 -2
View File
@@ -1,13 +1,13 @@
import { writable, get, type Writable } from 'svelte/store'; import { writable, get, type Writable } from 'svelte/store';
import { persist, localStorage } from '$lib/util/persist'; import { persist, localStorage } from '$lib/util/persist';
import { injectHistoryIDs } from '$lib/components/history/history'; import { injectHistoryIDs } from '$lib/components/History/history';
import { logEvent } from './stats'; import { logEvent } from './stats';
interface MigrationState { interface MigrationState {
version: number; version: number;
} }
const migrations: { [key: string]: () => void } = { const migrations: Record<string, () => void> = {
injectHistoryIDs injectHistoryIDs
}; };
+621
View File
@@ -0,0 +1,621 @@
// Modified from https://github.com/Yash-Singh1/monaco-mermaid/blob/main/index.ts
import type * as Monaco from 'monaco-editor';
export const initEditor = (monacoEditor: typeof Monaco): void => {
monacoEditor.languages.register({ id: 'mermaid' });
const requirementDiagrams = [
'requirement',
'functionalRequirement',
'interfaceRequirement',
'performanceRequirement',
'physicalRequirement',
'designConstraint'
];
const keywords: Record<
string,
{
typeKeywords: string[];
blockKeywords: string[];
keywords: string[];
}
> = {
flowchart: {
typeKeywords: ['flowchart', 'flowchart-v2', 'graph'],
blockKeywords: ['subgraph', 'end'],
keywords: [
'TB',
'TD',
'BT',
'RL',
'LR',
'click',
'call',
'href',
'_self',
'_blank',
'_parent',
'_top',
'linkStyle',
'style',
'classDef',
'class',
'direction',
'interpolate'
]
},
sequenceDiagram: {
typeKeywords: ['sequenceDiagram'],
blockKeywords: ['alt', 'par', 'and', 'loop', 'else', 'end', 'rect', 'opt', 'alt', 'rect'],
keywords: [
'participant',
'as',
'Note',
'note',
'right of',
'left of',
'over',
'activate',
'deactivate',
'autonumber',
'title',
'actor',
'accDescription',
'link',
'links'
]
},
classDiagram: {
typeKeywords: ['classDiagram', 'classDiagram-v2'],
blockKeywords: ['class'],
keywords: [
'link',
'click',
'callback',
'call',
'href',
'cssClass',
'direction',
'TB',
'BT',
'RL',
'LR',
'title',
'accDescription',
'order'
]
},
stateDiagram: {
typeKeywords: ['stateDiagram', 'stateDiagram-v2'],
blockKeywords: ['state', 'note', 'end'],
keywords: ['state', 'as', 'hide empty description', 'direction', 'TB', 'BT', 'RL', 'LR']
},
erDiagram: {
typeKeywords: ['erDiagram'],
blockKeywords: [],
keywords: ['title', 'accDescription']
},
journey: {
typeKeywords: ['journey'],
blockKeywords: ['section'],
keywords: ['title']
},
info: {
typeKeywords: ['info'],
blockKeywords: [],
keywords: ['showInfo']
},
gantt: {
typeKeywords: ['gantt'],
blockKeywords: [],
keywords: [
'title',
'dateFormat',
'axisFormat',
'todayMarker',
'section',
'excludes',
'inclusiveEndDates'
]
},
requirementDiagram: {
typeKeywords: ['requirement', 'requirementDiagram'],
blockKeywords: [...requirementDiagrams, 'element'],
keywords: []
},
gitGraph: {
typeKeywords: ['gitGraph'],
blockKeywords: [],
keywords: [
'accTitle',
'accDescr',
'commit',
'cherry-pick',
'branch',
'merge',
'reset',
'checkout',
'LR',
'BT',
'id',
'msg',
'type',
'tag',
'NORMAL',
'REVERSE',
'HIGHLIGHT'
]
},
pie: {
typeKeywords: ['pie'],
blockKeywords: [],
keywords: ['showData', 'title', 'accDescr', 'accTitle']
},
c4Diagram: {
typeKeywords: ['C4Context', 'C4Container', 'C4Component', 'C4Dynamic', 'C4Deployment'],
blockKeywords: [
'Boundary',
'Enterprise_Boundary',
'System_Boundary',
'Container_Boundary',
'Node',
'Node_L',
'Node_R'
],
keywords: [
'title',
'accDescription',
'direction',
'TB',
'BT',
'RL',
'LR',
'Person_Ext',
'Person',
'SystemQueue_Ext',
'SystemDb_Ext',
'System_Ext',
'SystemQueue',
'SystemDb',
'System',
'ContainerQueue_Ext',
'ContainerDb_Ext',
'Container_Ext',
'ContainerQueue',
'ContainerDb',
'Container',
'ComponentQueue_Ext',
'ComponentDb_Ext',
'Component_Ext',
'ComponentQueue',
'ComponentDb',
'Component',
'Deployment_Node',
'Rel',
'BiRel',
'Rel_Up',
'Rel_U',
'Rel_Down',
'Rel_D',
'Rel_Left',
'Rel_L',
'Rel_Right',
'Rel_R',
'Rel_Back',
'RelIndex'
]
},
sankey: {
typeKeywords: ['sankey-beta'],
blockKeywords: [],
keywords: []
}
};
const configDirectiveHandler = [
/^\s*%%(?={)/,
{
token: 'string',
next: '@configDirective',
nextEmbedded: 'javascript'
}
] as Monaco.languages.IShortMonarchLanguageRule1;
// Register a tokens provider for the mermaid language
monacoEditor.languages.setMonarchTokensProvider('mermaid', {
...Object.entries(keywords)
.map((entry) =>
Object.fromEntries(
Object.entries(entry[1]).map((deepEntry) => [
entry[0] + deepEntry[0][0].toUpperCase() + deepEntry[0].slice(1),
deepEntry[1]
])
)
)
// eslint-disable-next-line unicorn/no-array-reduce
.reduce(
(overallKeywords, nextKeyword) => ({
...overallKeywords,
...nextKeyword
}),
{}
),
tokenizer: {
root: [
[/^\s*gitGraph/m, 'typeKeyword', 'gitGraph'],
[/^\s*info/m, 'typeKeyword', 'info'],
[/^\s*pie/m, 'typeKeyword', 'pie'],
[/^\s*(flowchart|flowchart-v2|graph)/m, 'typeKeyword', 'flowchart'],
[/^\s*sequenceDiagram/, 'typeKeyword', 'sequenceDiagram'],
[/^\s*classDiagram(-v2)?/, 'typeKeyword', 'classDiagram'],
[/^\s*journey/, 'typeKeyword', 'journey'],
[/^\s*gantt/, 'typeKeyword', 'gantt'],
[/^\s*stateDiagram(-v2)?/, 'typeKeyword', 'stateDiagram'],
[/^\s*er(Diagram)?/, 'typeKeyword', 'erDiagram'],
[/^\s*requirement(Diagram)?/, 'typeKeyword', 'requirementDiagram'],
[/^\s*sankey-beta/m, 'typeKeyword', 'sankey'],
[
/^\s*(C4Context|C4Container|C4Component|C4Dynamic|C4Deployment)/m,
'typeKeyword',
'c4Diagram'
],
configDirectiveHandler,
[/%%[^${].*$/, 'comment']
],
configDirective: [[/%%$/, { token: 'string', next: '@pop', nextEmbedded: '@pop' }]],
gitGraph: [
configDirectiveHandler,
[/option(?=s)/, { token: 'typeKeyword', next: 'optionsGitGraph' }],
[/(accTitle|accDescr)(\s*:)(\s*[^\n\r]+$)/, ['keyword', 'delimiter.bracket', 'string']],
[
/(^\s*branch)(.*?)(\s+order)(:\s*)(\d+\s*$)/,
['keyword', 'variable', 'keyword', 'delimiter.bracket', 'number']
],
[/".*?"/, 'string'],
[
/(^\s*)(branch|reset|merge|checkout)(\s*\S+)/m,
['delimiter.bracket', 'keyword', 'variable']
],
[
/[A-Za-z][\w$]*/,
{
cases: {
'@gitGraphBlockKeywords': 'typeKeyword',
'@gitGraphKeywords': 'keyword'
}
}
],
[/%%[^$]([^%]*(?!%%$)%?)*$/, 'comment'],
[/\^/, 'delimiter.bracket']
],
optionsGitGraph: [
[
/s$/,
{
token: 'typeKeyword',
nextEmbedded: 'json'
}
],
['end', { token: 'typeKeyword', next: '@pop', nextEmbedded: '@pop' }]
],
info: [
[
/[A-Za-z][\w$]*/,
{
cases: {
'@infoBlockKeywords': 'typeKeyword',
'@infoKeywords': 'keyword'
}
}
]
],
pie: [
configDirectiveHandler,
[/(title|accDescription)(.*$)/, ['keyword', 'string']],
[
/[A-Za-z][\w$]*/,
{
cases: {
'@pieBlockKeywords': 'typeKeyword',
'@pieKeywords': 'keyword'
}
}
],
[/".*?"/, 'string'],
[/\s*\d+/, 'number'],
[/:/, 'delimiter.bracket'],
[/%%[^$]([^%]*(?!%%$)%?)*$/, 'comment']
],
flowchart: [
configDirectiveHandler,
[/[ox]?(--+|==+)[ox]/, 'transition'],
[
/[A-Za-z][\w$]*/,
{
cases: {
'@flowchartBlockKeywords': 'typeKeyword',
'@flowchartKeywords': 'keyword',
'@default': 'variable'
}
}
],
[/\|+.+?\|+/, 'string'],
[/\[+(\\.+?[/\\]|\/.+?[/\\])]+/, 'string'],
[/[>[]+[^[\]|]+?]+/, 'string'],
[/{+.+?}+/, 'string'],
[/\(+.+?\)+/, 'string'],
[/-\.+->?/, 'transition'],
[/(-[.-])([^>-][^-]+?)(-{3,}|-{2,}>|\.-+>)/, ['transition', 'string', 'transition']],
[/(==+)([^=]+?)(={3,}|={2,}>)/, ['transition', 'string', 'transition']],
[/<?(--+|==+)>|===+|---+/, 'transition'],
[/:::/, 'transition'],
[/[&;]/, 'delimiter.bracket'],
[/".*?"/, 'string'],
[/%%[^$]([^%]*(?!%%$)%?)*$/, 'comment']
],
sequenceDiagram: [
configDirectiveHandler,
[/(title:?|accDescription)([^\n\r;]*$)/, ['keyword', 'string']],
[/(autonumber)([^\S\n\r]+off[^\S\n\r]*$)/, ['keyword', 'keyword']],
[/(autonumber)((?:[^\S\n\r]+\d+){2}[^\S\n\r]*$)/, ['keyword', 'number']],
[/(autonumber)([^\S\n\r]+\d+[^\S\n\r]*$)/, ['keyword', 'number']],
[
/(link\s+)(.*?)(:)(\s*.*?)(\s*@)(\s*[^\n\r;]+)/,
['keyword', 'variable', 'delimiter.bracket', 'string', 'delimiter.bracket', 'string']
],
[
/((?:links|properties)\s+)([^\n\r:]*?)(:\s+)/,
[
{ token: 'keyword' },
{ token: 'variable' },
{
token: 'delimiter.bracket',
nextEmbedded: 'javascript',
next: '@sequenceDiagramLinksProps'
}
]
],
[
/[A-Za-z][\w$]*/,
{
cases: {
'@sequenceDiagramBlockKeywords': 'typeKeyword',
'@sequenceDiagramKeywords': 'keyword',
'@default': 'variable'
}
}
],
[/(--?>?>|--?[)x])[+-]?/, 'transition'],
[/(:)([^\n:]*?$)/, ['delimiter.bracket', 'string']],
[/%%[^$]([^%]*(?!%%$)%?)*$/, 'comment']
],
sequenceDiagramLinksProps: [
// [/^:/, { token: 'delimiter.bracket', nextEmbedded: 'json' }],
[/$|;/, { nextEmbedded: '@pop', next: '@pop', token: 'delimiter.bracket' }]
],
classDiagram: [
configDirectiveHandler,
[/(^\s*(?:title|accDescription))(\s+.*$)/, ['keyword', 'string']],
[
/(\*|<\|?|o|)(--|\.\.)(\*|\|?>|o|)([\t ]*[A-Za-z]+[\t ]*)(:)(.*?$)/,
['transition', 'transition', 'transition', 'variable', 'delimiter.bracket', 'string']
],
[/(?!class\s)([A-Za-z]+)(\s+[A-Za-z]+)/, ['type', 'variable']],
[/(\*|<\|?|o)?(--|\.\.)(\*|\|?>|o)?/, 'transition'],
[/^\s*class\s(?!.*{)/, 'keyword'],
[
/[A-Za-z][\w$]*/,
{
cases: {
'@classDiagramBlockKeywords': 'typeKeyword',
'@classDiagramKeywords': 'keyword',
'@default': 'variable'
}
}
],
[/%%[^$]([^%]*(?!%%$)%?)*$/, 'comment'],
[/(<<)(.+?)(>>)/, ['delimiter.bracket', 'annotation', 'delimiter.bracket']],
[/".*?"/, 'string'],
[/:::/, 'transition'],
[/:|\+|-|#|~|\*\s*$|\$\s*$|\(|\)|{|}/, 'delimiter.bracket']
],
journey: [
configDirectiveHandler,
[/(title)(.*)/, ['keyword', 'string']],
[/(section)(.*)/, ['typeKeyword', 'string']],
[
/[A-Za-z][\w$]*/,
{
cases: {
'@journeyBlockKeywords': 'typeKeyword',
'@journeyKeywords': 'keyword',
'@default': 'variable'
}
}
],
[
/(^\s*.+?)(:)(.*?)(:)(.*?)([$,])/,
[
'string',
'delimiter.bracket',
'number',
'delimiter.bracket',
'variable',
'delimiter.bracket'
]
],
[/,/, 'delimiter.bracket'],
[/(^\s*.+?)(:)([^:]*?)$/, ['string', 'delimiter.bracket', 'variable']],
[/%%[^$]([^%]*(?!%%$)%?)*$/, 'comment']
],
gantt: [
configDirectiveHandler,
[/(title)(.*)/, ['keyword', 'string']],
[/(section)(.*)/, ['typeKeyword', 'string']],
[/^\s*([^\n:]*?)(:)/, ['string', 'delimiter.bracket']],
[
/[A-Za-z][\w$]*/,
{
cases: {
'@ganttBlockKeywords': 'typeKeyword',
'@ganttKeywords': 'keyword'
}
}
],
[/%%[^$]([^%]*(?!%%$)%?)*$/, 'comment'],
[/:/, 'delimiter.bracket']
],
stateDiagram: [
configDirectiveHandler,
[/note[^:]*$/, { token: 'typeKeyword', next: 'stateDiagramNote' }],
['hide empty description', 'keyword'],
[/^\s*state\s(?!.*{)/, 'keyword'],
[/(<<)(fork|join|choice)(>>)/, 'annotation'],
[/(\[\[)(fork|join|choice)(]])/, ['delimiter.bracket', 'annotation', 'delimiter.bracket']],
[
/[A-Za-z][\w$]*/,
{
cases: {
'@stateDiagramBlockKeywords': 'typeKeyword',
'@stateDiagramKeywords': 'keyword',
'@default': 'variable'
}
}
],
[/".*?"/, 'string'],
[/(:)([^\n:]*?$)/, ['delimiter.bracket', 'string']],
[/{|}/, 'delimiter.bracket'],
[/%%[^$]([^%]*(?!%%$)%?)*$/, 'comment'],
[/-->/, 'transition'],
[/\[.*?]/, 'string']
],
stateDiagramNote: [
[/^\s*end note$/, { token: 'typeKeyword', next: '@pop' }],
[/.*/, 'string']
],
erDiagram: [
configDirectiveHandler,
[/(title|accDescription)(.*$)/, ['keyword', 'string']],
[/[|}][o|](--|\.\.)[o|][{|]/, 'transition'],
[/".*?"/, 'string'],
[/(:)(.*?$)/, ['delimiter.bracket', 'string']],
[/[:{}]/, 'delimiter.bracket'],
[/([A-Za-z]+)(\s+[A-Za-z]+)/, ['type', 'variable']],
[/%%[^$]([^%]*(?!%%$)%?)*$/, 'comment'],
[/[A-Z_a-z-][\w$]*/, 'variable']
],
requirementDiagram: [
configDirectiveHandler,
[/->|<-|-/, 'transition'],
[/(\d+\.)*\d+/, 'number'],
[
/[A-Z_a-z-][\w$]*/,
{
cases: {
'@requirementDiagramBlockKeywords': 'typeKeyword',
'@default': 'variable'
}
}
],
[/[/:{}]/, 'delimiter.bracket'],
[/%%[^$]([^%]*(?!%%$)%?)*$/, 'comment'],
[/".*?"/, 'string']
],
c4Diagram: [
configDirectiveHandler,
[/(title|accDescription)(.*$)/, ['keyword', 'string']],
[/\(/, { token: 'delimiter.bracket', next: 'c4DiagramParenthesis' }],
[
/[A-Z_a-z-][\w$]*/,
{
cases: {
'@c4DiagramBlockKeywords': 'typeKeyword',
'@c4DiagramKeywords': 'keyword',
'@default': 'variable'
}
}
],
[/%%[^$]([^%]*(?!%%$)%?)*$/, 'comment']
],
c4DiagramParenthesis: [
[/,/, 'delimiter.bracket'],
[/\)/, { next: '@pop', token: 'delimiter.bracket' }],
[/[^),]/, 'string']
],
sankey: [
configDirectiveHandler,
[/(title)(.*)/, ['keyword', 'string']],
[/(accTitle|accDescr)(\s*:)(\s*[^\n\r]+$)/, ['keyword', 'delimiter.bracket', 'string']],
[/".*?"/, 'string'],
[/[A-Za-z]+/, 'string'],
[/\s*\d+/, 'number'],
[/,/, 'delimiter.bracket'],
[/%%[^$]([^%]*(?!%%$)%?)*$/, 'comment']
]
}
});
monacoEditor.editor.defineTheme('mermaid-dark', {
base: 'vs-dark',
inherit: true,
colors: {},
rules: [
{ token: 'typeKeyword', foreground: '9650c8', fontStyle: 'bold' },
{ token: 'transition', foreground: '008800', fontStyle: 'bold' },
{ token: 'identifier', foreground: '9cdcfe' }
]
});
monacoEditor.editor.defineTheme('mermaid', {
base: 'vs',
inherit: true,
colors: {},
rules: [
{ token: 'typeKeyword', foreground: '9650c8', fontStyle: 'bold' },
{ token: 'keyword', foreground: '649696' },
{ token: 'custom-error', foreground: 'ff0000', fontStyle: 'bold' },
{ token: 'string', foreground: 'AA8500' },
{ token: 'transition', foreground: '008800', fontStyle: 'bold' },
{ token: 'delimiter.bracket', foreground: '000000', fontStyle: 'bold' },
{ token: 'annotation', foreground: '4b4b96' },
{ token: 'number', foreground: '4b4b96' },
{ token: 'comment', foreground: '888c89' },
{ token: 'variable', foreground: 'A22889' },
{ token: 'type', foreground: '2BDEA8' },
{ token: 'identifier', foreground: '9cdcfe' }
]
});
monacoEditor.languages.registerCompletionItemProvider('mermaid', {
provideCompletionItems: () => {
return {
suggestions: []
};
}
});
monacoEditor.languages.setLanguageConfiguration('mermaid', {
autoClosingPairs: [
{
open: '(',
close: ')'
},
{
open: '{',
close: '}'
},
{
open: '[',
close: ']'
}
],
brackets: [
['(', ')'],
['{', '}'],
['[', ']']
],
comments: {
lineComment: '%%'
}
});
};
+21 -29
View File
@@ -39,16 +39,16 @@ let noWarnings = false;
/** /**
* List of storages where the warning have already been displayed. * List of storages where the warning have already been displayed.
*/ */
const alreadyWarnFor: Array<string> = []; const alreadyWarnFor: string[] = [];
/** /**
* Add a log to indicate that the requested Storage have not been found. * Add a log to indicate that the requested Storage have not been found.
* @param {string} storageName * @param {string} storageName
*/ */
const warnStorageNotFound = (storageName) => { const warnStorageNotFound = (storageName: string) => {
const isProduction = typeof process !== 'undefined' && process.env?.NODE_ENV === 'production'; const isProduction = typeof process !== 'undefined' && process.env.NODE_ENV === 'production';
if (!noWarnings && alreadyWarnFor.indexOf(storageName) === -1 && !isProduction) { if (!noWarnings && !alreadyWarnFor.includes(storageName) && !isProduction) {
let message = `Unable to find the ${storageName}. No data will be persisted.`; let message = `Unable to find the ${storageName}. No data will be persisted.`;
if (typeof window === 'undefined') { if (typeof window === 'undefined') {
message += message +=
@@ -60,17 +60,8 @@ const warnStorageNotFound = (storageName) => {
} }
}; };
const allowedClasses = [];
/**
* Add a class to the allowed list of classes to be serialized
* @param classDef The class to add to the list
*/
export const addSerializableClass = (classDef: () => unknown): void => {
allowedClasses.push(classDef);
};
const serialize = (value: unknown): string => ESSerializer.serialize(value); const serialize = (value: unknown): string => ESSerializer.serialize(value);
const deserialize = (value: string): unknown => { const deserialize = (value?: string | null): unknown => {
// @TODO: to remove in the next major // @TODO: to remove in the next major
if (value === 'undefined') { if (value === 'undefined') {
return undefined; return undefined;
@@ -78,14 +69,14 @@ const deserialize = (value: string): unknown => {
if (value !== null && value !== undefined) { if (value !== null && value !== undefined) {
try { try {
return ESSerializer.deserialize(value, allowedClasses); return ESSerializer.deserialize(value);
} catch (e) { } catch {
// Do nothing // Do nothing
// use the value "as is" // use the value "as is"
} }
try { try {
return JSON.parse(value); return JSON.parse(value);
} catch (e) { } catch {
// Do nothing // Do nothing
// use the value "as is" // use the value "as is"
} }
@@ -162,7 +153,7 @@ export function persist<T>(
store.set(initialValue); store.set(initialValue);
} }
if ((storage as SelfUpdateStorageInterface<T>).addListener) { if ('addListener' in storage) {
(storage as SelfUpdateStorageInterface<T>).addListener(key, (newValue) => { (storage as SelfUpdateStorageInterface<T>).addListener(key, (newValue) => {
store.set(newValue); store.set(newValue);
}); });
@@ -184,24 +175,24 @@ function getBrowserStorage(
browserStorage: Storage, browserStorage: Storage,
listenExternalChanges = false listenExternalChanges = false
): SelfUpdateStorageInterface<any> { ): SelfUpdateStorageInterface<any> {
const listeners: Array<{ key: string; listener: (newValue: any) => void }> = []; const listeners: { key: string; listener: (newValue: any) => void }[] = [];
const listenerFunction = (event: StorageEvent) => { const listenerFunction = (event: StorageEvent) => {
const eventKey = event.key; const eventKey = event.key;
if (event.storageArea === browserStorage) { if (event.storageArea === browserStorage) {
listeners for (const { listener } of listeners.filter(({ key }) => key === eventKey)) {
.filter(({ key }) => key === eventKey) listener(deserialize(event.newValue));
.forEach(({ listener }) => { }
listener(deserialize(event.newValue));
});
} }
}; };
const connect = () => { const connect = () => {
if (listenExternalChanges && typeof window !== 'undefined' && window?.addEventListener) { // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (listenExternalChanges && typeof window !== 'undefined' && window.addEventListener) {
window.addEventListener('storage', listenerFunction); window.addEventListener('storage', listenerFunction);
} }
}; };
const disconnect = () => { const disconnect = () => {
if (listenExternalChanges && typeof window !== 'undefined' && window?.removeEventListener) { // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (listenExternalChanges && typeof window !== 'undefined' && window.removeEventListener) {
window.removeEventListener('storage', listenerFunction); window.removeEventListener('storage', listenerFunction);
} }
}; };
@@ -237,10 +228,11 @@ function getBrowserStorage(
/** /**
* Storage implementation that use the browser local storage * Storage implementation that use the browser local storage
* @param {boolean} listenExternalChanges - Update the store if the localStorage is updated from another page * @param listenExternalChanges - Update the store if the localStorage is updated from another page
*/ */
export function localStorage<T>(listenExternalChanges = false): StorageInterface<T> { export function localStorage<T>(listenExternalChanges = false): StorageInterface<T> {
if (typeof window !== 'undefined' && window?.localStorage) { // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (typeof window !== 'undefined' && window.localStorage) {
return getBrowserStorage(window.localStorage, listenExternalChanges); return getBrowserStorage(window.localStorage, listenExternalChanges);
} }
warnStorageNotFound('window.localStorage'); warnStorageNotFound('window.localStorage');
@@ -250,7 +242,7 @@ export function localStorage<T>(listenExternalChanges = false): StorageInterface
/** /**
* Storage implementation that do nothing * Storage implementation that do nothing
*/ */
export function noopStorage(): StorageInterface<any> { export function noopStorage<T>(): StorageInterface<T> {
return { return {
getValue(): null { getValue(): null {
return null; return null;
+10 -10
View File
@@ -3,29 +3,29 @@ import { serializeState, deserializeState, type SerdeType } from './serde';
import { defaultState } from './state'; import { defaultState } from './state';
import type { State } from '$lib/types'; import type { State } from '$lib/types';
describe('Serde tests', () => { const verifySerde = (state: State, serde?: SerdeType): string => {
const verifySerde = (state: State, serde?: SerdeType): string => { const serialized = serializeState(state, serde);
const serialized = serializeState(state, serde); const deserialized = deserializeState(serialized);
const deserialized = deserializeState(serialized); expect(deserialized).to.deep.equal(state);
expect(deserialized).to.deep.equal(state); return serialized;
return serialized; };
};
describe('Serde tests', () => {
it('should serialize and deserialize with default serde', () => { it('should serialize and deserialize with default serde', () => {
expect(verifySerde(defaultState)).toMatchInlineSnapshot( expect(verifySerde(defaultState)).toMatchInlineSnapshot(
'"pako:eNpVj81qw0AMhF9F6NRC_AI-BGK7zSXQQHLz5iBsObuk-8Naphjb7551fEl1EjPfiNGEjW8Zc7xHChqulXKQ5lCXOppeLPU3yLL9fGQB6x2PMxQfRw-99iEYd__c-GKFoJxOK8Yg2rjHslnlK__jeIaqPlEQH27vzvXPz_BVm7NO5_87OnJKfdcd5R1lDUUoKb4Q3KHlaMm0qfq0KgpFs2WFeVpb7mj4FYXKLQmlQfxldA3mEgfe4RBaEq4MpaftJi5PNtJU8w"' '"pako:eNpVjk2Lg0AMhv9KyGkL9Q94WGh1t5fCFurN6SFo7AztfDBGpKj_fcd62c0pvM_zhkzY-JYxx-7px0ZTFKhK5SDNoS50NL1Y6m-QZZ_ziQWsd_ya4fhx8tBrH4Jx993mH1cJium8agyijXssGyre_R_HM5T1mYL4cPtLqtHP8FWbi07n_xMdObW-647yjrKGIhQU3wru0XK0ZNr0_rQmCkWzZYV5WlvuaHiKQuWWpNIg_vpyDeYSB97jEFoSLg3dI9ktXH4B_cJWqw"'
); );
}); });
it('should serialize and deserialize with base64 serde', () => { it('should serialize and deserialize with base64 serde', () => {
expect(verifySerde(defaultState, 'base64')).toMatchInlineSnapshot( expect(verifySerde(defaultState, 'base64')).toMatchInlineSnapshot(
'"base64:eyJjb2RlIjoiZ3JhcGggVERcbiAgICBBW0NocmlzdG1hc10gLS0-fEdldCBtb25leXwgQihHbyBzaG9wcGluZylcbiAgICBCIC0tPiBDe0xldCBtZSB0aGlua31cbiAgICBDIC0tPnxPbmV8IERbTGFwdG9wXVxuICAgIEMgLS0-fFR3b3wgRVtpUGhvbmVdXG4gICAgQyAtLT58VGhyZWV8IEZbZmE6ZmEtY2FyIENhcl1cbiAgIiwibWVybWFpZCI6IntcbiAgXCJ0aGVtZVwiOiBcImRlZmF1bHRcIlxufSIsImF1dG9TeW5jIjp0cnVlLCJ1cGRhdGVEaWFncmFtIjp0cnVlfQ"' '"base64:eyJjb2RlIjoiZmxvd2NoYXJ0IFREXG4gICAgQVtDaHJpc3RtYXNdIC0tPnxHZXQgbW9uZXl8IEIoR28gc2hvcHBpbmcpXG4gICAgQiAtLT4gQ3tMZXQgbWUgdGhpbmt9XG4gICAgQyAtLT58T25lfCBEW0xhcHRvcF1cbiAgICBDIC0tPnxUd298IEVbaVBob25lXVxuICAgIEMgLS0-fFRocmVlfCBGW2ZhOmZhLWNhciBDYXJdXG4gICIsIm1lcm1haWQiOiJ7XG4gIFwidGhlbWVcIjogXCJkZWZhdWx0XCJcbn0iLCJhdXRvU3luYyI6dHJ1ZSwidXBkYXRlRGlhZ3JhbSI6dHJ1ZX0"'
); );
}); });
it('should serialize and deserialize with pako serde', () => { it('should serialize and deserialize with pako serde', () => {
expect(verifySerde(defaultState, 'pako')).toMatchInlineSnapshot( expect(verifySerde(defaultState, 'pako')).toMatchInlineSnapshot(
'"pako:eNpVj81qw0AMhF9F6NRC_AI-BGK7zSXQQHLz5iBsObuk-8Naphjb7551fEl1EjPfiNGEjW8Zc7xHChqulXKQ5lCXOppeLPU3yLL9fGQB6x2PMxQfRw-99iEYd__c-GKFoJxOK8Yg2rjHslnlK__jeIaqPlEQH27vzvXPz_BVm7NO5_87OnJKfdcd5R1lDUUoKb4Q3KHlaMm0qfq0KgpFs2WFeVpb7mj4FYXKLQmlQfxldA3mEgfe4RBaEq4MpaftJi5PNtJU8w"' '"pako:eNpVjk2Lg0AMhv9KyGkL9Q94WGh1t5fCFurN6SFo7AztfDBGpKj_fcd62c0pvM_zhkzY-JYxx-7px0ZTFKhK5SDNoS50NL1Y6m-QZZ_ziQWsd_ya4fhx8tBrH4Jx993mH1cJium8agyijXssGyre_R_HM5T1mYL4cPtLqtHP8FWbi07n_xMdObW-647yjrKGIhQU3wru0XK0ZNr0_rQmCkWzZYV5WlvuaHiKQuWWpNIg_vpyDeYSB97jEFoSLg3dI9ktXH4B_cJWqw"'
); );
}); });
+1 -1
View File
@@ -36,7 +36,7 @@ const serdes: { [key in SerdeType]: Serde } = {
}; };
export const serializeState = (state: State, serde: SerdeType = 'pako'): string => { export const serializeState = (state: State, serde: SerdeType = 'pako'): string => {
if (serdes[serde] === undefined) { if (!(serde in serdes)) {
throw new Error(`Unknown serde type: ${serde}`); throw new Error(`Unknown serde type: ${serde}`);
} }
const json = JSON.stringify(state); const json = JSON.stringify(state);
+38 -42
View File
@@ -2,30 +2,28 @@ import { writable, get, type Readable, derived } from 'svelte/store';
import { persist, localStorage } from './persist'; import { persist, localStorage } from './persist';
import { saveStatistics, countLines } from './stats'; import { saveStatistics, countLines } from './stats';
import { serializeState, deserializeState } from './serde'; import { serializeState, deserializeState } from './serde';
import { cmdKey, errorDebug, AsyncQueue } from './util'; import { cmdKey, errorDebug, formatJSON } from './util';
import { parse } from './mermaid'; import { parse } from './mermaid';
import type { MarkerData, State, ValidatedState } from '$lib/types'; import type { ErrorHash, MarkerData, State, ValidatedState } from '$lib/types';
import type { MermaidConfig } from 'mermaid';
export const defaultState: State = { export const defaultState: State = {
code: `graph TD code: `flowchart TD
A[Christmas] -->|Get money| B(Go shopping) A[Christmas] -->|Get money| B(Go shopping)
B --> C{Let me think} B --> C{Let me think}
C -->|One| D[Laptop] C -->|One| D[Laptop]
C -->|Two| E[iPhone] C -->|Two| E[iPhone]
C -->|Three| F[fa:fa-car Car] C -->|Three| F[fa:fa-car Car]
`, `,
mermaid: JSON.stringify( mermaid: formatJSON({
{ theme: 'default'
theme: 'default' }),
},
null,
2
),
autoSync: true, autoSync: true,
updateDiagram: true updateDiagram: true
}; };
const urlParseFailedState = `graph TD const urlParseFailedState = `flowchart TD
A[Loading URL failed. We can try to figure out why.] -->|Decode JSON| B(Please check the console to see the JSON and error details.) A[Loading URL failed. We can try to figure out why.] -->|Decode JSON| B(Please check the console to see the JSON and error details.)
B --> C{Is the JSON correct?} B --> C{Is the JSON correct?}
C -->|Yes| D(Please Click here to Raise an issue in github.<br/>Including the broken link in the issue <br/> will speed up the fix.) C -->|Yes| D(Please Click here to Raise an issue in github.<br/>Including the broken link in the issue <br/> will speed up the fix.)
@@ -50,8 +48,6 @@ export const currentState: ValidatedState = (() => {
}; };
})(); })();
let q: AsyncQueue<State>;
const processState = async (state: State) => { const processState = async (state: State) => {
const processed: ValidatedState = { const processed: ValidatedState = {
...state, ...state,
@@ -65,23 +61,28 @@ const processState = async (state: State) => {
processed.serialized = serializeState(state); processed.serialized = serializeState(state);
await parse(state.code); await parse(state.code);
JSON.parse(state.mermaid); JSON.parse(state.mermaid);
} catch (e) { } catch (error) {
processed.error = e; processed.error = error as Error;
errorDebug(); errorDebug();
console.error(e); console.error(error);
if (e.hash) { if ('hash' in error) {
try { try {
const {
loc: { first_line, last_line, first_column, last_column }
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
} = error.hash as ErrorHash;
const marker: MarkerData = { const marker: MarkerData = {
severity: 8, // Error severity: 8, // Error
startLineNumber: e.hash.loc.first_line, startLineNumber: first_line,
startColumn: e.hash.loc.first_column, startColumn: first_column,
endLineNumber: e.hash.loc.last_line, endLineNumber: last_line,
endColumn: (e.hash.loc.last_column as number) + 1, endColumn: last_column + 1,
message: e.str // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment
message: error.str
}; };
processed.errorMarkers = [marker]; processed.errorMarkers = [marker];
} catch (err) { } catch (error) {
console.error('Error without line helper', err); console.error('Error without line helper', error);
} }
} }
} }
@@ -92,14 +93,7 @@ const processState = async (state: State) => {
export const stateStore: Readable<ValidatedState> = derived( export const stateStore: Readable<ValidatedState> = derived(
[inputStateStore], [inputStateStore],
([state], set) => { ([state], set) => {
if (!q) { void processState(state).then(set);
// Initialize the queue for first time.
q = new AsyncQueue(async (state: State) => {
const newState = await processState(state);
set(newState);
});
}
q.process(state);
}, },
currentState currentState
); );
@@ -109,8 +103,10 @@ export const loadState = (data: string): void => {
console.log(`Loading '${data}'`); console.log(`Loading '${data}'`);
try { try {
state = deserializeState(data); state = deserializeState(data);
const mermaidConfig: { [key: string]: string } = const mermaidConfig: MermaidConfig =
typeof state.mermaid === 'string' ? JSON.parse(state.mermaid) : state.mermaid; typeof state.mermaid === 'string'
? (JSON.parse(state.mermaid) as MermaidConfig)
: state.mermaid;
if ( if (
mermaidConfig.securityLevel && mermaidConfig.securityLevel &&
mermaidConfig.securityLevel !== 'strict' && mermaidConfig.securityLevel !== 'strict' &&
@@ -120,11 +116,11 @@ export const loadState = (data: string): void => {
) { ) {
delete mermaidConfig.securityLevel; // Prevent setting overriding securityLevel when loading state to mitigate possible XSS attack delete mermaidConfig.securityLevel; // Prevent setting overriding securityLevel when loading state to mitigate possible XSS attack
} }
state.mermaid = JSON.stringify(mermaidConfig, null, 2); state.mermaid = formatJSON(mermaidConfig);
} catch (e) { } catch (error) {
state = get(inputStateStore); state = get(inputStateStore);
if (data) { if (data) {
console.error('Init error', e); console.error('Init error', error);
state.code = urlParseFailedState; state.code = urlParseFailedState;
state.mermaid = defaultState.mermaid; state.mermaid = defaultState.mermaid;
} }
@@ -146,7 +142,7 @@ export const updateCode = (
resetPanZoom = false resetPanZoom = false
}: { updateDiagram?: boolean; resetPanZoom?: boolean } = {} }: { updateDiagram?: boolean; resetPanZoom?: boolean } = {}
): void => { ): void => {
console.log('updateCode', code); // console.log('updateCode', code);
const lines = countLines(code); const lines = countLines(code);
saveStatistics(code); saveStatistics(code);
errorDebug(); errorDebug();
@@ -172,7 +168,7 @@ export const updateCode = (
}; };
export const updateConfig = (config: string): void => { export const updateConfig = (config: string): void => {
console.log('updateConfig', config); // console.log('updateConfig', config);
inputStateStore.update((state) => { inputStateStore.update((state) => {
return { ...state, mermaid: config }; return { ...state, mermaid: config };
}); });
@@ -180,12 +176,12 @@ export const updateConfig = (config: string): void => {
export const toggleDarkTheme = (dark: boolean): void => { export const toggleDarkTheme = (dark: boolean): void => {
inputStateStore.update((state) => { inputStateStore.update((state) => {
const config = JSON.parse(state.mermaid); const config = JSON.parse(state.mermaid) as MermaidConfig;
if (!config.theme || ['dark', 'default'].includes(config.theme)) { if (!config.theme || ['dark', 'default'].includes(config.theme)) {
config.theme = dark ? 'dark' : 'default'; config.theme = dark ? 'dark' : 'default';
} }
return { ...state, mermaid: JSON.stringify(config, null, 2) }; return { ...state, mermaid: formatJSON(config) };
}); });
}; };
@@ -194,7 +190,7 @@ export const initURLSubscription = (): void => {
stateStore.subscribe(({ serialized }) => { stateStore.subscribe(({ serialized }) => {
clearTimeout(urlDebounce); clearTimeout(urlDebounce);
urlDebounce = window.setTimeout(() => { urlDebounce = window.setTimeout(() => {
history.replaceState(undefined, undefined, `#${serialized}`); history.replaceState(undefined, '', `#${serialized}`);
}, 250); }, 250);
}); });
}; };
+39 -16
View File
@@ -1,6 +1,6 @@
import { browser } from '$app/environment'; import { browser } from '$app/environment';
import type { AnalyticsInstance } from 'analytics'; import type { AnalyticsInstance } from 'analytics';
export let analytics: AnalyticsInstance; export let analytics: AnalyticsInstance | undefined;
export const initAnalytics = async (): Promise<void> => { export const initAnalytics = async (): Promise<void> => {
if (browser && !analytics) { if (browser && !analytics) {
@@ -15,19 +15,19 @@ export const initAnalytics = async (): Promise<void> => {
plausible({ plausible({
domain: 'mermaid.live', domain: 'mermaid.live',
hashMode: false, hashMode: false,
trackLocalhost: false, // By default 'false' // All tracked stats are public and available at https://p.mermaid.live/mermaid.live
apiHost: 'https://plausible.io' apiHost: 'https://p.mermaid.live'
}) })
] ]
}); });
} catch (e) { } catch (error) {
console.log(e); console.log(error);
console.info('Analytics blocked ;)'); console.info('Analytics blocked ;)');
} }
} }
}; };
export const detectType = (text: string): string => { export const detectType = (text: string): string | undefined => {
const possibleDiagramTypes = [ const possibleDiagramTypes = [
'classDiagram', 'classDiagram',
'erDiagram', 'erDiagram',
@@ -37,7 +37,9 @@ export const detectType = (text: string): string => {
'graph', 'graph',
'journey', 'journey',
'pie', 'pie',
'stateDiagram' 'stateDiagram',
'quadrantChart',
'mindmap'
]; ];
const firstLine = text const firstLine = text
.replace(/^\s*%%.*\n/g, '\n') .replace(/^\s*%%.*\n/g, '\n')
@@ -49,7 +51,7 @@ export const detectType = (text: string): string => {
}; };
export const countLines = (code: string): number => { export const countLines = (code: string): number => {
return (code.match(/\n/g) || '').length + 1; return (code.match(/\n/g)?.length ?? 0) + 1;
}; };
export const saveStatistics = (graph: string): void => { export const saveStatistics = (graph: string): void => {
@@ -58,7 +60,27 @@ export const saveStatistics = (graph: string): void => {
return; return;
} }
const length = countLines(graph); const length = countLines(graph);
logEvent('render', { graphType, length }); const lengthBucket =
length < 10
? '0-10'
: length < 25
? '10-25'
: length < 50
? '25-50'
: length < 100
? '50-100'
: length < 200
? '100-200'
: length < 500
? '200-500'
: length < 700
? '500-700'
: length < 1000
? '700-1000'
: length < 1500
? '1000-1500'
: '1500+';
logEvent('render', { graphType, length, lengthBucket });
}; };
const minutesToMilliSeconds = (minutes: number): number => { const minutesToMilliSeconds = (minutes: number): number => {
@@ -80,19 +102,20 @@ const delaysPerEvent = {
themeChange: defaultDelay themeChange: defaultDelay
}; };
export type AnalyticsEvent = keyof typeof delaysPerEvent; export type AnalyticsEvent = keyof typeof delaysPerEvent;
const timeouts: Record<string, number> = {}; const timeouts: Map<string, number> = new Map<string, number>();
// manual debounce to reduce the number of events sent to analytics // manual debounce to reduce the number of events sent to analytics
export const logEvent = (name: AnalyticsEvent, data?: unknown): void => { export const logEvent = (name: AnalyticsEvent, data?: unknown): void => {
if (!analytics) { if (!analytics) {
return; return;
} }
const key = data ? JSON.stringify({ name, data }) : name; const key = data ? JSON.stringify({ name, data }) : name;
if (timeouts[key] === undefined) { if (timeouts.has(key)) {
void analytics.track(name, data); clearTimeout(timeouts.get(key));
} else { } else {
clearTimeout(timeouts[key]); void analytics.track(name, data);
} }
timeouts[key] = window.setTimeout(() => { timeouts.set(
delete timeouts[key]; key,
}, delaysPerEvent[name]); window.setTimeout(() => timeouts.delete(key), delaysPerEvent[name])
);
}; };
+3 -3
View File
@@ -16,7 +16,7 @@ export const themeStore: Writable<ThemeConfig> = persist(
'themeStore' 'themeStore'
); );
const darkThemes = [ const darkThemes = new Set([
'dark', 'dark',
'synthwave', 'synthwave',
'halloween', 'halloween',
@@ -25,13 +25,13 @@ const darkThemes = [
'luxury', 'luxury',
'black', 'black',
'dracula' 'dracula'
]; ]);
export const setTheme = (theme: string): void => { export const setTheme = (theme: string): void => {
if (theme.includes(' ')) { if (theme.includes(' ')) {
theme = theme.split(' ')[1].trim(); theme = theme.split(' ')[1].trim();
} }
const isDark = darkThemes.includes(theme); const isDark = darkThemes.has(theme);
console.log('Setting theme', theme); console.log('Setting theme', theme);
themeStore.set({ theme, isDark }); themeStore.set({ theme, isDark });
logEvent('themeChange', { theme, isDark }); logEvent('themeChange', { theme, isDark });
+11 -24
View File
@@ -3,7 +3,6 @@ import { analytics, initAnalytics } from './stats';
import { loadDataFromUrl } from './fileLoaders/loader'; import { loadDataFromUrl } from './fileLoaders/loader';
import { initLoading } from './loading'; import { initLoading } from './loading';
import { applyMigrations } from './migrations'; import { applyMigrations } from './migrations';
import { init } from './mermaid';
export const loadStateFromURL = (): void => { export const loadStateFromURL = (): void => {
loadState(window.location.hash.slice(1)); loadState(window.location.hash.slice(1));
@@ -17,16 +16,15 @@ export const syncDiagram = (): void => {
export const initHandler = async (): Promise<void> => { export const initHandler = async (): Promise<void> => {
applyMigrations(); applyMigrations();
await initLoading('Loading Mermaid...', init());
loadStateFromURL(); loadStateFromURL();
await initLoading('Loading Gist...', loadDataFromUrl().catch(console.error)); await initLoading('Loading Gist...', loadDataFromUrl().catch(console.error));
syncDiagram(); syncDiagram();
initURLSubscription(); initURLSubscription();
await initAnalytics(); await initAnalytics();
analytics?.page(); await analytics?.page();
}; };
export const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0; export const isMac = navigator.platform.toUpperCase().includes('MAC');
export const cmdKey = isMac ? 'Cmd' : 'Ctrl'; export const cmdKey = isMac ? 'Cmd' : 'Ctrl';
let count = 0; let count = 0;
@@ -39,23 +37,12 @@ export const errorDebug = (limit = 100) => {
} }
}; };
// To queue async tasks so they are executed one after the other, not concurrently. export const formatJSON = (data: unknown): string => JSON.stringify(data, undefined, 2);
export class AsyncQueue<T> { export const fetchJSON = async <T>(url: string): Promise<T> => {
private readonly queue: T[] = []; const res = await fetch(url);
private running = false; return res.json() as T;
constructor(private processor: (item: T) => Promise<void>) {} };
public async process(item: T): Promise<void> { export const fetchText = async (url: string): Promise<string> => {
this.queue.push(item); const res = await fetch(url);
if (this.running) { return res.text();
return; };
}
this.running = true;
while (this.queue.length > 0) {
const item = this.queue.shift();
if (item) {
await this.processor(item);
}
}
this.running = false;
}
}
+1
View File
@@ -1,3 +1,4 @@
export const prerender = true; export const prerender = true;
export const csr = true; export const csr = true;
export const ssr = false; export const ssr = false;
export const trailingSlash = 'ignore';
+2 -2
View File
@@ -10,8 +10,8 @@
// This can be removed once https://github.com/sveltejs/kit/issues/1612 is fixed. // This can be removed once https://github.com/sveltejs/kit/issues/1612 is fixed.
// Then move it into src and vite will bundle it automatically. // Then move it into src and vite will bundle it automatically.
onMount(() => { onMount(() => {
window.addEventListener('hashchange', async (ev) => { window.addEventListener('hashchange', () => {
await initHandler(); void initHandler();
}); });
if ('serviceWorker' in navigator) { if ('serviceWorker' in navigator) {
navigator.serviceWorker navigator.serviceWorker
+69 -48
View File
@@ -1,64 +1,74 @@
<script lang="ts"> <script lang="ts">
import Editor from '$lib/components/editor.svelte'; import Editor from '$lib/components/Editor.svelte';
import Navbar from '$lib/components/navbar.svelte'; import Navbar from '$lib/components/Navbar.svelte';
import Preset from '$lib/components/preset.svelte'; import Preset from '$lib/components/Preset.svelte';
import Actions from '$lib/components/actions.svelte'; import Actions from '$lib/components/Actions.svelte';
import View from '$lib/components/view.svelte'; import View from '$lib/components/View.svelte';
import Card from '$lib/components/card/card.svelte'; import Card from '$lib/components/Card/Card.svelte';
import History from '$lib/components/history/history.svelte'; import History from '$lib/components/History/History.svelte';
import { inputStateStore, stateStore, updateCodeStore } from '$lib/util/state'; import { inputStateStore, stateStore, updateCodeStore } from '$lib/util/state';
import { cmdKey, initHandler, syncDiagram } from '$lib/util/util'; import { cmdKey, initHandler, syncDiagram } from '$lib/util/util';
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import type { Tab, DocConfig, EditorMode, ValidatedState } from '$lib/types';
import { base } from '$app/paths'; import { base } from '$app/paths';
import { dev } from '$app/environment';
import type { Tab, DocumentationConfig, EditorMode, ValidatedState } from '$lib/types';
const MCBaseURL = dev ? 'http://localhost:5174' : 'https://mermaidchart.com';
const docURLBase = 'https://mermaid-js.github.io/mermaid'; const docURLBase = 'https://mermaid-js.github.io/mermaid';
const docMap: DocConfig = { const docMap: DocumentationConfig = {
graph: {
code: '/#/flowchart',
config: '/#/flowchart?id=configuration'
},
flowchart: {
code: '/#/flowchart',
config: '/#/flowchart?id=configuration'
},
sequenceDiagram: {
code: '/#/sequenceDiagram',
config: '/#/sequenceDiagram?id=configuration'
},
classDiagram: { classDiagram: {
code: '/#/classDiagram', code: '/syntax/classDiagram',
config: '/#/classDiagram?id=configuration' config: '/syntax/classDiagram#configuration'
},
'stateDiagram-v2': {
code: '/#/stateDiagram'
},
gantt: {
code: '/#/gantt',
config: '/#/gantt?id=configuration'
},
pie: {
code: '/#/pie'
}, },
erDiagram: { erDiagram: {
code: '/#/entityRelationshipDiagram', code: '/syntax/entityRelationshipDiagram'
config: '/#/entityRelationshipDiagram?id=styling'
}, },
journey: { flowchart: {
code: '/#/user-journey' code: '/syntax/flowchart',
config: '/syntax/flowchart#configuration'
},
gantt: {
code: '/syntax/gantt',
config: '/syntax/gantt#configuration'
}, },
gitGraph: { gitGraph: {
code: '/#/gitgraph', code: '/syntax/gitgraph',
config: '/#/gitgraph?id=gitgraph-specific-configuration-options' config: '/syntax/gitgraph#gitgraph-specific-configuration-options'
},
graph: {
code: '/syntax/flowchart',
config: '/syntax/flowchart#configuration'
},
journey: {
code: '/syntax/userJourney'
},
mindmap: {
code: '/syntax/mindmap'
},
pie: {
code: '/syntax/pie',
config: '/syntax/pie#configuration'
},
quadrantChart: {
code: '/syntax/quadrantChart',
config: '/syntax/quadrantChart#chart-configurations'
},
sequenceDiagram: {
code: '/syntax/sequenceDiagram',
config: '/syntax/sequenceDiagram#configuration'
},
'stateDiagram-v2': {
code: '/syntax/stateDiagram'
} }
}; };
let docURL = docURLBase; let docURL = docURLBase;
let activeTabID = 'code'; let activeTabID = 'code';
let docKey = '';
stateStore.subscribe(({ code, editorMode }: ValidatedState) => { stateStore.subscribe(({ code, editorMode }: ValidatedState) => {
activeTabID = editorMode; activeTabID = editorMode;
const codeTypeMatch = /([\S]+)[\s\n]/.exec(code); const codeTypeMatch = /([\S]+)[\s\n]/.exec(code);
if (codeTypeMatch && codeTypeMatch.length > 1) { if (codeTypeMatch && codeTypeMatch.length > 1) {
const docKey = codeTypeMatch[1]; docKey = codeTypeMatch[1];
const docConfig = docMap[docKey] ?? { code: '' }; const docConfig = docMap[docKey] ?? { code: '' };
docURL = docURLBase + (docConfig[editorMode] ?? docConfig.code ?? ''); docURL = docURLBase + (docConfig[editorMode] ?? docConfig.code ?? '');
} }
@@ -86,6 +96,10 @@
await initHandler(); await initHandler();
const resizer = document.getElementById('resizeHandler'); const resizer = document.getElementById('resizeHandler');
const element = document.getElementById('editorPane'); const element = document.getElementById('editorPane');
if (!resizer || !element) {
console.debug('Failed to find resize handler or editor pane', { resizer, element });
return;
}
const resize = (e: { pageX: number }) => { const resize = (e: { pageX: number }) => {
const newWidth = e.pageX - element.getBoundingClientRect().left; const newWidth = e.pageX - element.getBoundingClientRect().left;
if (newWidth > 50) { if (newWidth > 50) {
@@ -129,8 +143,10 @@
on:click={syncDiagram}><i class="fas fa-sync" /></button> on:click={syncDiagram}><i class="fas fa-sync" /></button>
{/if} {/if}
<button class="btn btn-secondary btn-xs" title="View documentation"> <button
<a target="_blank" rel="noreferrer" href={docURL} data-cy="docs"> class="btn btn-secondary btn-xs"
title="View documentation for {docKey.replace('Diagram', '')} diagram">
<a target="_blank" href={docURL} data-cy="docs">
<i class="fas fa-book mr-1" />Docs <i class="fas fa-book mr-1" />Docs
</a> </a>
</button> </button>
@@ -148,22 +164,27 @@
<div id="resizeHandler" class="hidden md:block" /> <div id="resizeHandler" class="hidden md:block" />
<div class="flex-1 flex flex-col overflow-hidden"> <div class="flex-1 flex flex-col overflow-hidden">
<Card title="Diagram" isCloseable={false}> <Card title="Diagram" isCloseable={false}>
<div slot="actions" class="flex flex-row items-center"> <div slot="actions" class="flex flex-row items-center gap-2">
<label class="cursor-pointer label py-0" for="panZoom"> <label class="cursor-pointer label py-0" for="panZoom">
<span>Pan & Zoom</span> <span>Pan & Zoom</span>
<input <input
type="checkbox" type="checkbox"
class="toggle {$stateStore.panZoom ? 'btn-secondary' : 'toggle-primary'} ml-1" class="toggle {$stateStore.panZoom ? 'btn-secondary' : 'toggle-primary'}"
id="panZoom" id="panZoom"
bind:checked={$inputStateStore.panZoom} /> bind:checked={$inputStateStore.panZoom} />
</label> </label>
<a <a
href={`${base}/view#${$stateStore.serialized}`} href={`${base}/view#${$stateStore.serialized}`}
target="_blank" target="_blank"
rel="noreferrer" class="btn btn-secondary btn-xs gap-1"
class="btn btn-secondary btn-xs" title="View diagram in new page"><i class="fas fa-external-link-alt" />Full screen</a>
title="View diagram in new page" <a
><i class="fas fa-external-link-alt mr-1" />Full screen</a> href={`${MCBaseURL}/app/plugin/save?state=${$stateStore.serialized}`}
target="_blank"
class="btn btn-secondary btn-xs gap-1 bg-[#FF3570]"
title="Save diagram in Mermaid Chart"
><img src="/mermaidchart-logo.svg" class="w-5 h-5" alt="Mermaid chart logo" />Save to
Mermaid Chart</a>
</div> </div>
<div class="flex-1 overflow-auto"> <div class="flex-1 overflow-auto">
+1 -1
View File
@@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import View from '$lib/components/view.svelte'; import View from '$lib/components/View.svelte';
import { initHandler } from '$lib/util/util'; import { initHandler } from '$lib/util/util';
import { onMount } from 'svelte'; import { onMount } from 'svelte';
onMount(initHandler); onMount(initHandler);
+1
View File
@@ -0,0 +1 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 490.16 490.16"><defs><style>.cls-1{fill:#ff3670;}.cls-2{fill:#fff;}</style></defs><rect class="cls-1" width="490.16" height="490.16" rx="84.61"/><path class="cls-2" d="M407.48,111.18A165.2,165.2,0,0,0,245.08,220,165.2,165.2,0,0,0,82.68,111.18a165.5,165.5,0,0,0,72.06,143.64,88.81,88.81,0,0,1,38.53,73.45v50.86H296.9V328.27a88.8,88.8,0,0,1,38.52-73.45,165.41,165.41,0,0,0,72.06-143.64Z"/><path class="cls-2" d="M160.63,328.27a56.09,56.09,0,0,0-24.27-46.49,198.74,198.74,0,0,1-28.54-23.66A196.87,196.87,0,0,1,82.53,227V379.13h78.1Z"/><path class="cls-2" d="M329.53,328.27a56.09,56.09,0,0,1,24.27-46.49,198.74,198.74,0,0,0,28.54-23.66A196.87,196.87,0,0,0,407.63,227V379.13h-78.1Z"/></svg>

After

Width:  |  Height:  |  Size: 772 B

+1 -2
View File
@@ -18,8 +18,7 @@ const config = {
? { ? {
base: `/mermaid-live-editor` base: `/mermaid-live-editor`
} }
: {}, : {}
trailingSlash: 'ignore'
} }
}; };
+1
View File
@@ -12,6 +12,7 @@
"compilerOptions": { "compilerOptions": {
"resolveJsonModule": true, "resolveJsonModule": true,
"allowSyntheticDefaultImports": true, "allowSyntheticDefaultImports": true,
"strictNullChecks": true,
"types": ["vitest/importMeta"] "types": ["vitest/importMeta"]
}, },
"extends": "./.svelte-kit/tsconfig.json" "extends": "./.svelte-kit/tsconfig.json"
+4 -4
View File
@@ -1,6 +1,7 @@
import { sveltekit } from '@sveltejs/kit/vite'; import { sveltekit } from '@sveltejs/kit/vite';
/** @type {import('vite').UserConfig} */ import { defineConfig } from 'vitest/config';
const config = {
export default defineConfig({
plugins: [sveltekit()], plugins: [sveltekit()],
envPrefix: 'MERMAID_', envPrefix: 'MERMAID_',
optimizeDeps: { include: ['mermaid'] }, optimizeDeps: { include: ['mermaid'] },
@@ -22,5 +23,4 @@ const config = {
reporter: ['text', 'json', 'html', 'lcov'] reporter: ['text', 'json', 'html', 'lcov']
} }
} }
}; });
export default config;
+3148 -2417
View File
File diff suppressed because it is too large Load Diff