From 394520643189ad0dda296c09fb0f2dff73ce8165 Mon Sep 17 00:00:00 2001
From: JesmoDev <26099018+JesmoDev@users.noreply.github.com>
Date: Mon, 9 Sep 2024 20:43:50 +0200
Subject: [PATCH 001/241] install tiptap
---
package-lock.json | 521 +++++++++++++++++++++++++++++++++++++++++++++-
package.json | 3 +
2 files changed, 514 insertions(+), 10 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 826baef473..cbc477b3b5 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -40,6 +40,9 @@
"./src/packages/webhook"
],
"dependencies": {
+ "@tiptap/core": "^2.6.6",
+ "@tiptap/pm": "^2.6.6",
+ "@tiptap/starter-kit": "^2.6.6",
"@types/diff": "^5.2.1",
"@types/dompurify": "^3.0.5",
"@types/uuid": "^10.0.0",
@@ -4640,6 +4643,11 @@
"@babel/runtime": "^7.13.10"
}
},
+ "node_modules/@remirror/core-constants": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@remirror/core-constants/-/core-constants-2.0.2.tgz",
+ "integrity": "sha512-dyHY+sMF0ihPus3O27ODd4+agdHMEmuRdyiZJ2CCWjPV5UFmn17ZbElvk6WOGVE4rdCJKZQCrPV2BcikOMLUGQ=="
+ },
"node_modules/@rollup/plugin-commonjs": {
"version": "26.0.1",
"resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-26.0.1.tgz",
@@ -6481,6 +6489,299 @@
"url": "https://opencollective.com/storybook"
}
},
+ "node_modules/@tiptap/core": {
+ "version": "2.6.6",
+ "resolved": "https://registry.npmjs.org/@tiptap/core/-/core-2.6.6.tgz",
+ "integrity": "sha512-VO5qTsjt6rwworkuo0s5AqYMfDA0ZwiTiH6FHKFSu2G/6sS7HKcc/LjPq+5Legzps4QYdBDl3W28wGsGuS1GdQ==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/pm": "^2.6.6"
+ }
+ },
+ "node_modules/@tiptap/extension-blockquote": {
+ "version": "2.6.6",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-blockquote/-/extension-blockquote-2.6.6.tgz",
+ "integrity": "sha512-hAdsNlMfzzxld154hJqPqtWqO5i4/7HoDfuxmyqBxdMJ+e2UMaIGBGwoLRXG0V9UoRwJusjqlpyD7pIorxNlgA==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "^2.6.6"
+ }
+ },
+ "node_modules/@tiptap/extension-bold": {
+ "version": "2.6.6",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-bold/-/extension-bold-2.6.6.tgz",
+ "integrity": "sha512-CD6gBhdQtCoqYSmx8oAV8gvKtVOGZSyyvuNYo7by9eZ56DqLYnd7kbUj0RH7o9Ymf/iJTOUJ6XcvrsWwo4lubg==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "^2.6.6"
+ }
+ },
+ "node_modules/@tiptap/extension-bullet-list": {
+ "version": "2.6.6",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-bullet-list/-/extension-bullet-list-2.6.6.tgz",
+ "integrity": "sha512-WEKxbVSYuvmX2wkHWP8HXk5nzA7stYwtdaubwWH/R17kGI3IGScJuMQ9sEN82uzJU8bfgL9yCbH2bY8Fj/Q4Ow==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "^2.6.6"
+ }
+ },
+ "node_modules/@tiptap/extension-code": {
+ "version": "2.6.6",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-code/-/extension-code-2.6.6.tgz",
+ "integrity": "sha512-JrEFKsZiLvfvOFhOnnrpA0TzCuJjDeysfbMeuKUZNV4+DhYOL28d39H1++rEtJAX0LcbBU60oC5/PrlU9SpvRQ==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "^2.6.6"
+ }
+ },
+ "node_modules/@tiptap/extension-code-block": {
+ "version": "2.6.6",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-code-block/-/extension-code-block-2.6.6.tgz",
+ "integrity": "sha512-1YLp/zHMHSkE2xzht8nPR6T4sQJJ3ket798czxWuQEbetFv/l0U/mpiPpYSLObj6oTAoqYZ0kWXZj5eQSpPB8Q==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "^2.6.6",
+ "@tiptap/pm": "^2.6.6"
+ }
+ },
+ "node_modules/@tiptap/extension-document": {
+ "version": "2.6.6",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-document/-/extension-document-2.6.6.tgz",
+ "integrity": "sha512-6qlH5VWzLHHRVeeciRC6C4ZHpMsAGPNG16EF53z0GeMSaaFD/zU3B239QlmqXmLsAl8bpf8Bn93N0t2ABUvScw==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "^2.6.6"
+ }
+ },
+ "node_modules/@tiptap/extension-dropcursor": {
+ "version": "2.6.6",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-dropcursor/-/extension-dropcursor-2.6.6.tgz",
+ "integrity": "sha512-O6CeKriA9uyHsg7Ui4z5ZjEWXQxrIL+1zDekffW0wenGC3G4LUsCzAiFS4LSrR9a3u7tnwqGApW10rdkmCGF4w==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "^2.6.6",
+ "@tiptap/pm": "^2.6.6"
+ }
+ },
+ "node_modules/@tiptap/extension-gapcursor": {
+ "version": "2.6.6",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-gapcursor/-/extension-gapcursor-2.6.6.tgz",
+ "integrity": "sha512-O2lQ2t0X0Vsbn3yLWxFFHrXY6C2N9Y6ZF/M7LWzpcDTUZeWuhoNkFE/1yOM0h6ZX1DO2A9hNIrKpi5Ny8yx+QA==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "^2.6.6",
+ "@tiptap/pm": "^2.6.6"
+ }
+ },
+ "node_modules/@tiptap/extension-hard-break": {
+ "version": "2.6.6",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-hard-break/-/extension-hard-break-2.6.6.tgz",
+ "integrity": "sha512-bsUuyYBrMDEiudx1dOQSr9MzKv13m0xHWrOK+DYxuIDYJb5g+c9un5cK7Js+et/HEYYSPOoH/iTW6h+4I5YeUg==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "^2.6.6"
+ }
+ },
+ "node_modules/@tiptap/extension-heading": {
+ "version": "2.6.6",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-heading/-/extension-heading-2.6.6.tgz",
+ "integrity": "sha512-bgx9vptVFi5yFkIw1OI53J7+xJ71Or3SOe/Q8eSpZv53DlaKpL/TzKw8Z54t1PrI2rJ6H9vrLtkvixJvBZH1Ug==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "^2.6.6"
+ }
+ },
+ "node_modules/@tiptap/extension-history": {
+ "version": "2.6.6",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-history/-/extension-history-2.6.6.tgz",
+ "integrity": "sha512-tPTzAmPGqMX5Bd5H8lzRpmsaMvB9DvI5Dy2za/VQuFtxgXmDiFVgHRkRXIuluSkPTuANu84XBOQ0cBijqY8x4w==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "^2.6.6",
+ "@tiptap/pm": "^2.6.6"
+ }
+ },
+ "node_modules/@tiptap/extension-horizontal-rule": {
+ "version": "2.6.6",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-2.6.6.tgz",
+ "integrity": "sha512-cFEfv7euDpuLSe8exY8buwxkreKBAZY9Hn3EetKhPcLQo+ut5Y24chZTxFyf9b+Y0wz3UhOhLTZSz7fTobLqBA==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "^2.6.6",
+ "@tiptap/pm": "^2.6.6"
+ }
+ },
+ "node_modules/@tiptap/extension-italic": {
+ "version": "2.6.6",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-italic/-/extension-italic-2.6.6.tgz",
+ "integrity": "sha512-t7ZPsXqa8nJZZ/6D0rQyZ/KsvzLaSihC6hBTjUQ77CeDGV9PhDWjIcBW4OrvwraJDBd12ETBeQ2CkULJOgH+lQ==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "^2.6.6"
+ }
+ },
+ "node_modules/@tiptap/extension-list-item": {
+ "version": "2.6.6",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-list-item/-/extension-list-item-2.6.6.tgz",
+ "integrity": "sha512-k+oEzZu2cgVKqPqOP1HzASOKLpTEV9m7mRVPAbuaaX8mSyvIgD6f+JUx9PvgYv//D918wk98LMoRBFX53tDJ4w==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "^2.6.6"
+ }
+ },
+ "node_modules/@tiptap/extension-ordered-list": {
+ "version": "2.6.6",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-ordered-list/-/extension-ordered-list-2.6.6.tgz",
+ "integrity": "sha512-AJwyfLXIi7iUGnK5twJbwdVVpQyh7fU6OK75h1AwDztzsOcoPcxtffDlZvUOd4ZtwuyhkzYqVkeI0f+abTWZTw==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "^2.6.6"
+ }
+ },
+ "node_modules/@tiptap/extension-paragraph": {
+ "version": "2.6.6",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-paragraph/-/extension-paragraph-2.6.6.tgz",
+ "integrity": "sha512-fD/onCr16UQWx+/xEmuFC2MccZZ7J5u4YaENh8LMnAnBXf78iwU7CAcmuc9rfAEO3qiLoYGXgLKiHlh2ZfD4wA==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "^2.6.6"
+ }
+ },
+ "node_modules/@tiptap/extension-strike": {
+ "version": "2.6.6",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-strike/-/extension-strike-2.6.6.tgz",
+ "integrity": "sha512-Ze8KhGk+wzSJSJRl5fbhTI6AvPu2LmcHYeO3pMEH8u4gV5WTXfmKJVStEIAzkoqvwEQVWzXvy8nDgsFQHiojPg==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "^2.6.6"
+ }
+ },
+ "node_modules/@tiptap/extension-text": {
+ "version": "2.6.6",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-text/-/extension-text-2.6.6.tgz",
+ "integrity": "sha512-e84uILnRzNzcwK1DVQNpXVmBG1Cq3BJipTOIDl1LHifOok7MBjhI/X+/NR0bd3N2t6gmDTWi63+4GuJ5EeDmsg==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "^2.6.6"
+ }
+ },
+ "node_modules/@tiptap/pm": {
+ "version": "2.6.6",
+ "resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-2.6.6.tgz",
+ "integrity": "sha512-56FGLPn3fwwUlIbLs+BO21bYfyqP9fKyZQbQyY0zWwA/AG2kOwoXaRn7FOVbjP6CylyWpFJnpRRmgn694QKHEg==",
+ "dependencies": {
+ "prosemirror-changeset": "^2.2.1",
+ "prosemirror-collab": "^1.3.1",
+ "prosemirror-commands": "^1.5.2",
+ "prosemirror-dropcursor": "^1.8.1",
+ "prosemirror-gapcursor": "^1.3.2",
+ "prosemirror-history": "^1.4.1",
+ "prosemirror-inputrules": "^1.4.0",
+ "prosemirror-keymap": "^1.2.2",
+ "prosemirror-markdown": "^1.13.0",
+ "prosemirror-menu": "^1.2.4",
+ "prosemirror-model": "^1.22.2",
+ "prosemirror-schema-basic": "^1.2.3",
+ "prosemirror-schema-list": "^1.4.1",
+ "prosemirror-state": "^1.4.3",
+ "prosemirror-tables": "^1.4.0",
+ "prosemirror-trailing-node": "^2.0.9",
+ "prosemirror-transform": "^1.9.0",
+ "prosemirror-view": "^1.33.9"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ }
+ },
+ "node_modules/@tiptap/starter-kit": {
+ "version": "2.6.6",
+ "resolved": "https://registry.npmjs.org/@tiptap/starter-kit/-/starter-kit-2.6.6.tgz",
+ "integrity": "sha512-zb9xIg3WjG9AsJoyWrfqx5SL9WH7/HTdkB79jFpWtOF/Kaigo7fHFmhs2FsXtJMJlcdMTO2xeRuCYHt5ozXlhg==",
+ "dependencies": {
+ "@tiptap/core": "^2.6.6",
+ "@tiptap/extension-blockquote": "^2.6.6",
+ "@tiptap/extension-bold": "^2.6.6",
+ "@tiptap/extension-bullet-list": "^2.6.6",
+ "@tiptap/extension-code": "^2.6.6",
+ "@tiptap/extension-code-block": "^2.6.6",
+ "@tiptap/extension-document": "^2.6.6",
+ "@tiptap/extension-dropcursor": "^2.6.6",
+ "@tiptap/extension-gapcursor": "^2.6.6",
+ "@tiptap/extension-hard-break": "^2.6.6",
+ "@tiptap/extension-heading": "^2.6.6",
+ "@tiptap/extension-history": "^2.6.6",
+ "@tiptap/extension-horizontal-rule": "^2.6.6",
+ "@tiptap/extension-italic": "^2.6.6",
+ "@tiptap/extension-list-item": "^2.6.6",
+ "@tiptap/extension-ordered-list": "^2.6.6",
+ "@tiptap/extension-paragraph": "^2.6.6",
+ "@tiptap/extension-strike": "^2.6.6",
+ "@tiptap/extension-text": "^2.6.6",
+ "@tiptap/pm": "^2.6.6"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ }
+ },
"node_modules/@tootallnate/quickjs-emscripten": {
"version": "0.23.0",
"resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz",
@@ -9863,8 +10164,7 @@
"node_modules/argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
- "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
- "dev": true
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
},
"node_modules/aria-hidden": {
"version": "1.2.4",
@@ -11439,6 +11739,11 @@
"integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
"dev": true
},
+ "node_modules/crelt": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz",
+ "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g=="
+ },
"node_modules/cross-spawn": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
@@ -12201,7 +12506,6 @@
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
- "dev": true,
"engines": {
"node": ">=0.12"
},
@@ -16009,7 +16313,6 @@
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz",
"integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==",
- "dev": true,
"dependencies": {
"uc.micro": "^2.0.0"
}
@@ -16387,7 +16690,6 @@
"version": "14.1.0",
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz",
"integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==",
- "dev": true,
"dependencies": {
"argparse": "^2.0.1",
"entities": "^4.4.0",
@@ -16663,8 +16965,7 @@
"node_modules/mdurl": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz",
- "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==",
- "dev": true
+ "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w=="
},
"node_modules/media-typer": {
"version": "0.3.0",
@@ -18249,6 +18550,11 @@
"node": ">=8"
}
},
+ "node_modules/orderedmap": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/orderedmap/-/orderedmap-2.1.1.tgz",
+ "integrity": "sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g=="
+ },
"node_modules/os-tmpdir": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
@@ -18980,6 +19286,193 @@
"node": ">= 6"
}
},
+ "node_modules/prosemirror-changeset": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/prosemirror-changeset/-/prosemirror-changeset-2.2.1.tgz",
+ "integrity": "sha512-J7msc6wbxB4ekDFj+n9gTW/jav/p53kdlivvuppHsrZXCaQdVgRghoZbSS3kwrRyAstRVQ4/+u5k7YfLgkkQvQ==",
+ "dependencies": {
+ "prosemirror-transform": "^1.0.0"
+ }
+ },
+ "node_modules/prosemirror-collab": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/prosemirror-collab/-/prosemirror-collab-1.3.1.tgz",
+ "integrity": "sha512-4SnynYR9TTYaQVXd/ieUvsVV4PDMBzrq2xPUWutHivDuOshZXqQ5rGbZM84HEaXKbLdItse7weMGOUdDVcLKEQ==",
+ "dependencies": {
+ "prosemirror-state": "^1.0.0"
+ }
+ },
+ "node_modules/prosemirror-commands": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/prosemirror-commands/-/prosemirror-commands-1.6.0.tgz",
+ "integrity": "sha512-xn1U/g36OqXn2tn5nGmvnnimAj/g1pUx2ypJJIe8WkVX83WyJVC5LTARaxZa2AtQRwntu9Jc5zXs9gL9svp/mg==",
+ "dependencies": {
+ "prosemirror-model": "^1.0.0",
+ "prosemirror-state": "^1.0.0",
+ "prosemirror-transform": "^1.0.0"
+ }
+ },
+ "node_modules/prosemirror-dropcursor": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/prosemirror-dropcursor/-/prosemirror-dropcursor-1.8.1.tgz",
+ "integrity": "sha512-M30WJdJZLyXHi3N8vxN6Zh5O8ZBbQCz0gURTfPmTIBNQ5pxrdU7A58QkNqfa98YEjSAL1HUyyU34f6Pm5xBSGw==",
+ "dependencies": {
+ "prosemirror-state": "^1.0.0",
+ "prosemirror-transform": "^1.1.0",
+ "prosemirror-view": "^1.1.0"
+ }
+ },
+ "node_modules/prosemirror-gapcursor": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/prosemirror-gapcursor/-/prosemirror-gapcursor-1.3.2.tgz",
+ "integrity": "sha512-wtjswVBd2vaQRrnYZaBCbyDqr232Ed4p2QPtRIUK5FuqHYKGWkEwl08oQM4Tw7DOR0FsasARV5uJFvMZWxdNxQ==",
+ "dependencies": {
+ "prosemirror-keymap": "^1.0.0",
+ "prosemirror-model": "^1.0.0",
+ "prosemirror-state": "^1.0.0",
+ "prosemirror-view": "^1.0.0"
+ }
+ },
+ "node_modules/prosemirror-history": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/prosemirror-history/-/prosemirror-history-1.4.1.tgz",
+ "integrity": "sha512-2JZD8z2JviJrboD9cPuX/Sv/1ChFng+xh2tChQ2X4bB2HeK+rra/bmJ3xGntCcjhOqIzSDG6Id7e8RJ9QPXLEQ==",
+ "dependencies": {
+ "prosemirror-state": "^1.2.2",
+ "prosemirror-transform": "^1.0.0",
+ "prosemirror-view": "^1.31.0",
+ "rope-sequence": "^1.3.0"
+ }
+ },
+ "node_modules/prosemirror-inputrules": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/prosemirror-inputrules/-/prosemirror-inputrules-1.4.0.tgz",
+ "integrity": "sha512-6ygpPRuTJ2lcOXs9JkefieMst63wVJBgHZGl5QOytN7oSZs3Co/BYbc3Yx9zm9H37Bxw8kVzCnDsihsVsL4yEg==",
+ "dependencies": {
+ "prosemirror-state": "^1.0.0",
+ "prosemirror-transform": "^1.0.0"
+ }
+ },
+ "node_modules/prosemirror-keymap": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/prosemirror-keymap/-/prosemirror-keymap-1.2.2.tgz",
+ "integrity": "sha512-EAlXoksqC6Vbocqc0GtzCruZEzYgrn+iiGnNjsJsH4mrnIGex4qbLdWWNza3AW5W36ZRrlBID0eM6bdKH4OStQ==",
+ "dependencies": {
+ "prosemirror-state": "^1.0.0",
+ "w3c-keyname": "^2.2.0"
+ }
+ },
+ "node_modules/prosemirror-markdown": {
+ "version": "1.13.0",
+ "resolved": "https://registry.npmjs.org/prosemirror-markdown/-/prosemirror-markdown-1.13.0.tgz",
+ "integrity": "sha512-UziddX3ZYSYibgx8042hfGKmukq5Aljp2qoBiJRejD/8MH70siQNz5RB1TrdTPheqLMy4aCe4GYNF10/3lQS5g==",
+ "dependencies": {
+ "markdown-it": "^14.0.0",
+ "prosemirror-model": "^1.20.0"
+ }
+ },
+ "node_modules/prosemirror-menu": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/prosemirror-menu/-/prosemirror-menu-1.2.4.tgz",
+ "integrity": "sha512-S/bXlc0ODQup6aiBbWVsX/eM+xJgCTAfMq/nLqaO5ID/am4wS0tTCIkzwytmao7ypEtjj39i7YbJjAgO20mIqA==",
+ "dependencies": {
+ "crelt": "^1.0.0",
+ "prosemirror-commands": "^1.0.0",
+ "prosemirror-history": "^1.0.0",
+ "prosemirror-state": "^1.0.0"
+ }
+ },
+ "node_modules/prosemirror-model": {
+ "version": "1.22.3",
+ "resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.22.3.tgz",
+ "integrity": "sha512-V4XCysitErI+i0rKFILGt/xClnFJaohe/wrrlT2NSZ+zk8ggQfDH4x2wNK7Gm0Hp4CIoWizvXFP7L9KMaCuI0Q==",
+ "dependencies": {
+ "orderedmap": "^2.0.0"
+ }
+ },
+ "node_modules/prosemirror-schema-basic": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/prosemirror-schema-basic/-/prosemirror-schema-basic-1.2.3.tgz",
+ "integrity": "sha512-h+H0OQwZVqMon1PNn0AG9cTfx513zgIG2DY00eJ00Yvgb3UD+GQ/VlWW5rcaxacpCGT1Yx8nuhwXk4+QbXUfJA==",
+ "dependencies": {
+ "prosemirror-model": "^1.19.0"
+ }
+ },
+ "node_modules/prosemirror-schema-list": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/prosemirror-schema-list/-/prosemirror-schema-list-1.4.1.tgz",
+ "integrity": "sha512-jbDyaP/6AFfDfu70VzySsD75Om2t3sXTOdl5+31Wlxlg62td1haUpty/ybajSfJ1pkGadlOfwQq9kgW5IMo1Rg==",
+ "dependencies": {
+ "prosemirror-model": "^1.0.0",
+ "prosemirror-state": "^1.0.0",
+ "prosemirror-transform": "^1.7.3"
+ }
+ },
+ "node_modules/prosemirror-state": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/prosemirror-state/-/prosemirror-state-1.4.3.tgz",
+ "integrity": "sha512-goFKORVbvPuAQaXhpbemJFRKJ2aixr+AZMGiquiqKxaucC6hlpHNZHWgz5R7dS4roHiwq9vDctE//CZ++o0W1Q==",
+ "dependencies": {
+ "prosemirror-model": "^1.0.0",
+ "prosemirror-transform": "^1.0.0",
+ "prosemirror-view": "^1.27.0"
+ }
+ },
+ "node_modules/prosemirror-tables": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/prosemirror-tables/-/prosemirror-tables-1.5.0.tgz",
+ "integrity": "sha512-VMx4zlYWm7aBlZ5xtfJHpqa3Xgu3b7srV54fXYnXgsAcIGRqKSrhiK3f89omzzgaAgAtDOV4ImXnLKhVfheVNQ==",
+ "dependencies": {
+ "prosemirror-keymap": "^1.1.2",
+ "prosemirror-model": "^1.8.1",
+ "prosemirror-state": "^1.3.1",
+ "prosemirror-transform": "^1.2.1",
+ "prosemirror-view": "^1.13.3"
+ }
+ },
+ "node_modules/prosemirror-trailing-node": {
+ "version": "2.0.9",
+ "resolved": "https://registry.npmjs.org/prosemirror-trailing-node/-/prosemirror-trailing-node-2.0.9.tgz",
+ "integrity": "sha512-YvyIn3/UaLFlFKrlJB6cObvUhmwFNZVhy1Q8OpW/avoTbD/Y7H5EcjK4AZFKhmuS6/N6WkGgt7gWtBWDnmFvHg==",
+ "dependencies": {
+ "@remirror/core-constants": "^2.0.2",
+ "escape-string-regexp": "^4.0.0"
+ },
+ "peerDependencies": {
+ "prosemirror-model": "^1.22.1",
+ "prosemirror-state": "^1.4.2",
+ "prosemirror-view": "^1.33.8"
+ }
+ },
+ "node_modules/prosemirror-trailing-node/node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/prosemirror-transform": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/prosemirror-transform/-/prosemirror-transform-1.10.0.tgz",
+ "integrity": "sha512-9UOgFSgN6Gj2ekQH5CTDJ8Rp/fnKR2IkYfGdzzp5zQMFsS4zDllLVx/+jGcX86YlACpG7UR5fwAXiWzxqWtBTg==",
+ "dependencies": {
+ "prosemirror-model": "^1.21.0"
+ }
+ },
+ "node_modules/prosemirror-view": {
+ "version": "1.34.2",
+ "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.34.2.tgz",
+ "integrity": "sha512-tPX/V2Xd70vrAGQ/V9CppJtPKnQyQMypJGlLylvdI94k6JaG+4P6fVmXPR1zc1eVTW0gq3c6zsfqwJKCRLaG9Q==",
+ "dependencies": {
+ "prosemirror-model": "^1.20.0",
+ "prosemirror-state": "^1.0.0",
+ "prosemirror-transform": "^1.1.0"
+ }
+ },
"node_modules/proxy-addr": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
@@ -19071,7 +19564,6 @@
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz",
"integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==",
- "dev": true,
"engines": {
"node": ">=6"
}
@@ -19938,6 +20430,11 @@
"rollup": "^1.9.2 || ^2.0.0"
}
},
+ "node_modules/rope-sequence": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/rope-sequence/-/rope-sequence-1.3.4.tgz",
+ "integrity": "sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ=="
+ },
"node_modules/run-async": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz",
@@ -21621,8 +22118,7 @@
"node_modules/uc.micro": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz",
- "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==",
- "dev": true
+ "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A=="
},
"node_modules/ufo": {
"version": "1.5.4",
@@ -22615,6 +23111,11 @@
"@esbuild/win32-x64": "0.21.5"
}
},
+ "node_modules/w3c-keyname": {
+ "version": "2.2.8",
+ "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz",
+ "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ=="
+ },
"node_modules/walkdir": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/walkdir/-/walkdir-0.4.1.tgz",
diff --git a/package.json b/package.json
index 0d7af660b1..911ef8621f 100644
--- a/package.json
+++ b/package.json
@@ -212,6 +212,9 @@
"npm": ">=10.1 < 11"
},
"dependencies": {
+ "@tiptap/core": "^2.6.6",
+ "@tiptap/pm": "^2.6.6",
+ "@tiptap/starter-kit": "^2.6.6",
"@types/diff": "^5.2.1",
"@types/dompurify": "^3.0.5",
"@types/uuid": "^10.0.0",
From 507ab979bd642ad783ecfac4e68362209589b4f1 Mon Sep 17 00:00:00 2001
From: JesmoDev <26099018+JesmoDev@users.noreply.github.com>
Date: Mon, 9 Sep 2024 21:00:45 +0200
Subject: [PATCH 002/241] init tiptap
---
src/apps/backoffice/backoffice.element.ts | 1 +
src/external/tiptap/index.ts | 2 +
src/packages/tiptap/components/index.ts | 1 +
.../tiptap/components/input-tiptap/index.ts | 1 +
.../input-tiptap/input-tiptap.element.ts | 112 ++++++++
.../input-tiptap/tiptap-fixed-menu.element.ts | 266 ++++++++++++++++++
src/packages/tiptap/manifests.ts | 4 +
.../tiptap/property-editors/manifests.ts | 4 +
.../property-editors/tiptap/manifests.ts | 16 ++
.../property-editor-ui-tiptap.element.ts | 49 ++++
src/packages/tiptap/umbraco-package.ts | 9 +
src/packages/tiptap/vite.config.ts | 12 +
tsconfig.json | 1 +
13 files changed, 478 insertions(+)
create mode 100644 src/external/tiptap/index.ts
create mode 100644 src/packages/tiptap/components/index.ts
create mode 100644 src/packages/tiptap/components/input-tiptap/index.ts
create mode 100644 src/packages/tiptap/components/input-tiptap/input-tiptap.element.ts
create mode 100644 src/packages/tiptap/components/input-tiptap/tiptap-fixed-menu.element.ts
create mode 100644 src/packages/tiptap/manifests.ts
create mode 100644 src/packages/tiptap/property-editors/manifests.ts
create mode 100644 src/packages/tiptap/property-editors/tiptap/manifests.ts
create mode 100644 src/packages/tiptap/property-editors/tiptap/property-editor-ui-tiptap.element.ts
create mode 100644 src/packages/tiptap/umbraco-package.ts
create mode 100644 src/packages/tiptap/vite.config.ts
diff --git a/src/apps/backoffice/backoffice.element.ts b/src/apps/backoffice/backoffice.element.ts
index d59e98126c..42c5f423d6 100644
--- a/src/apps/backoffice/backoffice.element.ts
+++ b/src/apps/backoffice/backoffice.element.ts
@@ -37,6 +37,7 @@ const CORE_PACKAGES = [
import('../../packages/telemetry/umbraco-package.js'),
import('../../packages/templating/umbraco-package.js'),
import('../../packages/tiny-mce/umbraco-package.js'),
+ import('../../packages/tiptap/umbraco-package.js'),
import('../../packages/ufm/umbraco-package.js'),
import('../../packages/umbraco-news/umbraco-package.js'),
import('../../packages/user/umbraco-package.js'),
diff --git a/src/external/tiptap/index.ts b/src/external/tiptap/index.ts
new file mode 100644
index 0000000000..1d5fb7fe1e
--- /dev/null
+++ b/src/external/tiptap/index.ts
@@ -0,0 +1,2 @@
+export * from '@tiptap/core';
+export * from '@tiptap/starter-kit';
diff --git a/src/packages/tiptap/components/index.ts b/src/packages/tiptap/components/index.ts
new file mode 100644
index 0000000000..d7e1544b7d
--- /dev/null
+++ b/src/packages/tiptap/components/index.ts
@@ -0,0 +1 @@
+export * from './input-tiptap/index.js';
diff --git a/src/packages/tiptap/components/input-tiptap/index.ts b/src/packages/tiptap/components/input-tiptap/index.ts
new file mode 100644
index 0000000000..f11b53c7d9
--- /dev/null
+++ b/src/packages/tiptap/components/input-tiptap/index.ts
@@ -0,0 +1 @@
+export * from './input-tiptap.element.js';
diff --git a/src/packages/tiptap/components/input-tiptap/input-tiptap.element.ts b/src/packages/tiptap/components/input-tiptap/input-tiptap.element.ts
new file mode 100644
index 0000000000..1932b8d77e
--- /dev/null
+++ b/src/packages/tiptap/components/input-tiptap/input-tiptap.element.ts
@@ -0,0 +1,112 @@
+import type { PropertyValueMap } from '@umbraco-cms/backoffice/external/lit';
+import { css, customElement, html, property, state } from '@umbraco-cms/backoffice/external/lit';
+import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
+import { UUIFormControlMixin } from '@umbraco-cms/backoffice/external/uui';
+import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor';
+
+import './tiptap-fixed-menu.element.js';
+import { Editor, StarterKit } from '@umbraco-cms/backoffice/external/tiptap';
+
+@customElement('umb-input-tiptap')
+export class UmbInputTiptapElement extends UUIFormControlMixin(UmbLitElement, '') {
+ @property({ attribute: false })
+ configuration?: UmbPropertyEditorConfigCollection;
+
+ @state()
+ _editor!: Editor;
+
+ protected override firstUpdated(_changedProperties: PropertyValueMap | Map): void {
+ super.firstUpdated(_changedProperties);
+
+ const editor = this.shadowRoot?.querySelector('#editor');
+
+ if (!editor) return;
+
+ const json =
+ this.value && typeof this.value === 'string'
+ ? JSON.parse(this.value)
+ : {
+ type: 'doc',
+ content: [
+ {
+ type: 'paragraph',
+ content: [
+ {
+ type: 'text',
+ text: 'Hello Umbraco',
+ },
+ ],
+ },
+ ],
+ };
+
+ // TODO: Try Disable css inject to remove prosemirror css
+ this._editor = new Editor({
+ element: editor,
+ extensions: [StarterKit],
+ content: json,
+ onUpdate: ({ editor }) => {
+ const json = editor.getJSON();
+ this.value = JSON.stringify(json);
+ console.log('json', json);
+ },
+ });
+ }
+
+ protected getFormElement() {
+ return null;
+ }
+
+ override render() {
+ return html`
+
+
+ `;
+ }
+
+ static override styles = [
+ css`
+ #editor {
+ border-radius: var(--uui-border-radius);
+ border: 1px solid var(--uui-color-border);
+ margin: 0 auto;
+ box-sizing: border-box;
+ height: 100%;
+ width: 100%;
+ padding: 1rem;
+ overflow: clip;
+ min-height: 400px;
+ display: grid; /* Don't ask me why this is needed, but it is. */
+ }
+
+ #editor code {
+ font-family: 'Roboto Mono', monospace;
+ background: none;
+ color: inherit;
+ font-size: 0.8rem;
+ padding: 0;
+ }
+ .ProseMirror {
+ height: 100%;
+ width: 100%;
+ outline: none;
+ white-space: pre-wrap;
+ }
+ .ProseMirror p,
+ .ProseMirror h1,
+ .ProseMirror h2,
+ .ProseMirror h3 {
+ margin-top: 0;
+ margin-bottom: 0.1rem;
+ }
+ `,
+ ];
+}
+
+export default UmbInputTiptapElement;
+
+declare global {
+ interface HTMLElementTagNameMap {
+ 'umb-input-tiptap': UmbInputTiptapElement;
+ }
+}
diff --git a/src/packages/tiptap/components/input-tiptap/tiptap-fixed-menu.element.ts b/src/packages/tiptap/components/input-tiptap/tiptap-fixed-menu.element.ts
new file mode 100644
index 0000000000..28a3a2185f
--- /dev/null
+++ b/src/packages/tiptap/components/input-tiptap/tiptap-fixed-menu.element.ts
@@ -0,0 +1,266 @@
+import { LitElement, css, customElement, html, property, state } from '@umbraco-cms/backoffice/external/lit';
+import type { Editor } from '@umbraco-cms/backoffice/external/tiptap';
+
+@customElement('umb-tiptap-fixed-menu')
+export class UmbTiptapFixedMenuElement extends LitElement {
+ @state()
+ actions = [
+ {
+ name: 'paragraph',
+ icon: html``,
+ command: () => this.editor?.chain().focus().setParagraph().run(),
+ },
+ {
+ name: 'bold',
+ icon: html``,
+ command: () => this.editor?.chain().focus().toggleBold().run(),
+ },
+ {
+ name: 'italic',
+ icon: html``,
+ command: () => this.editor?.chain().focus().toggleItalic().run(),
+ },
+ {
+ name: 'underline',
+ icon: html``,
+ // command: () => this.editor?.chain().focus().toggleUnderline().run(),
+ },
+ {
+ name: 'strikethrough',
+ icon: html``,
+ command: () => this.editor?.chain().focus().toggleStrike().run(),
+ },
+ {
+ name: 'heading-1',
+ icon: html``,
+ command: () => this.editor?.chain().focus().toggleHeading({ level: 1 }).run(),
+ },
+ {
+ name: 'heading-2',
+ icon: html``,
+ command: () => this.editor?.chain().focus().toggleHeading({ level: 2 }).run(),
+ },
+ {
+ name: 'heading-3',
+ icon: html``,
+ command: () => this.editor?.chain().focus().toggleHeading({ level: 3 }).run(),
+ },
+ {
+ name: 'heading-4',
+ icon: html``,
+ command: () => this.editor?.chain().focus().toggleHeading({ level: 4 }).run(),
+ },
+ {
+ name: 'heading-5',
+ icon: html``,
+ command: () => this.editor?.chain().focus().toggleHeading({ level: 5 }).run(),
+ },
+ {
+ name: 'blockquote',
+ icon: html``,
+ command: () => this.editor?.chain().focus().toggleBlockquote().run(),
+ },
+ {
+ name: 'code',
+ icon: html``,
+ command: () => this.editor?.chain().focus().toggleCodeBlock().run(),
+ },
+ {
+ name: 'bullet-list',
+ icon: html``,
+ command: () => this.editor?.chain().focus().toggleBulletList().run(),
+ },
+ {
+ name: 'ordered-list',
+ icon: html``,
+ command: () => this.editor?.chain().focus().toggleOrderedList().run(),
+ },
+ {
+ name: 'horizontal-rule',
+ icon: html``,
+ command: () => this.editor?.chain().focus().setHorizontalRule().run(),
+ },
+ {
+ name: 'align-left',
+ icon: html``,
+ // command: () => this.editor?.chain().focus().setTextAlign('left').run(),
+ },
+ {
+ name: 'align-center',
+ icon: html``,
+ // command: () => this.editor?.chain().focus().setTextAlign('center').run(),
+ },
+ {
+ name: 'align-right',
+ icon: html``,
+ // command: () => this.editor?.chain().focus().setTextAlign('right').run(),
+ },
+ {
+ name: 'align-justify',
+ icon: html``,
+ // command: () => this.editor?.chain().focus().setTextAlign('justify').run(),
+ },
+ {
+ name: 'image',
+ icon: html``,
+ command: () => {
+ const url = prompt('Enter the image URL');
+ if (url) {
+ // this.editor?.chain().focus().setImage({ src: url }).run();
+ }
+ },
+ },
+ {
+ name: 'add',
+ icon: html``,
+ command: () => {
+ const tag = prompt('Enter the tag');
+ if (tag) {
+ // this.editor?.chain().focus().addCustomNode(tag).run();
+ }
+ },
+ },
+ ];
+
+ @property({ attribute: false })
+ editor?: Editor;
+
+ override render() {
+ return html`
+ ${this.actions.map(
+ (action) => html` `,
+ )}
+ `;
+ }
+
+ static override styles = css`
+ :host {
+ border-radius: var(--uui-border-radius);
+ border: 1px solid var(--uui-color-border);
+ background-color: var(--uui-color-surface);
+ color: var(--color-text);
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(32px, 1fr));
+ position: sticky;
+ top: -18px;
+ left: 0px;
+ right: 0px;
+ height: 32px;
+ padding: 8px;
+ border-bottom: none;
+ }
+
+ button {
+ color: var(--color-text);
+ border: none;
+ background: none;
+ cursor: pointer;
+ padding: 4px;
+ margin: 0;
+ border-radius: 4px;
+ box-sizing: border-box;
+ }
+
+ button img {
+ width: 100%;
+ height: 100%;
+ }
+
+ button:hover {
+ color: var(--color-primary);
+ }
+ `;
+}
+
+declare global {
+ interface HTMLElementTagNameMap {
+ 'umb-tiptap-fixed-menu': UmbTiptapFixedMenuElement;
+ }
+}
diff --git a/src/packages/tiptap/manifests.ts b/src/packages/tiptap/manifests.ts
new file mode 100644
index 0000000000..1dcd948374
--- /dev/null
+++ b/src/packages/tiptap/manifests.ts
@@ -0,0 +1,4 @@
+import { manifests as propertyEditors } from './property-editors/manifests.js';
+import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry';
+
+export const manifests: Array = [...propertyEditors];
diff --git a/src/packages/tiptap/property-editors/manifests.ts b/src/packages/tiptap/property-editors/manifests.ts
new file mode 100644
index 0000000000..1a38fe7fe9
--- /dev/null
+++ b/src/packages/tiptap/property-editors/manifests.ts
@@ -0,0 +1,4 @@
+import { manifests as tiptapManifests } from './tiptap/manifests.js';
+import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry';
+
+export const manifests: Array = [...tiptapManifests];
diff --git a/src/packages/tiptap/property-editors/tiptap/manifests.ts b/src/packages/tiptap/property-editors/tiptap/manifests.ts
new file mode 100644
index 0000000000..ba824b19d6
--- /dev/null
+++ b/src/packages/tiptap/property-editors/tiptap/manifests.ts
@@ -0,0 +1,16 @@
+import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry';
+
+export const manifests: Array = [
+ {
+ type: 'propertyEditorUi',
+ alias: 'Umb.PropertyEditorUi.Tiptap',
+ name: 'Tiptap Property Editor UI',
+ element: () => import('./property-editor-ui-tiptap.element.js'),
+ meta: {
+ label: 'Tiptap Editor',
+ propertyEditorSchemaAlias: 'Umbraco.Tiptap',
+ icon: 'icon-document',
+ group: 'richText',
+ },
+ },
+];
diff --git a/src/packages/tiptap/property-editors/tiptap/property-editor-ui-tiptap.element.ts b/src/packages/tiptap/property-editors/tiptap/property-editor-ui-tiptap.element.ts
new file mode 100644
index 0000000000..27390b2a0d
--- /dev/null
+++ b/src/packages/tiptap/property-editors/tiptap/property-editor-ui-tiptap.element.ts
@@ -0,0 +1,49 @@
+import { customElement, html, property, state } from '@umbraco-cms/backoffice/external/lit';
+import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
+import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor';
+import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry';
+
+import '../../components/input-tiptap/input-tiptap.element.js';
+
+// Look at Tiny for correct types
+export interface UmbRichTextEditorValueType {
+ markup?: string;
+ blocks?: any;
+}
+
+/**
+ * @element umb-property-editor-ui-tiptap
+ */
+@customElement('umb-property-editor-ui-tiptap')
+export class UmbPropertyEditorUITiptapElement extends UmbLitElement implements UmbPropertyEditorUiElement {
+ //
+ public set config(config: UmbPropertyEditorConfigCollection | undefined) {
+ this._config = config;
+ }
+
+ @property({ attribute: false })
+ public set value(value: UmbRichTextEditorValueType) {
+ this._value = value;
+ }
+ public get value(): UmbRichTextEditorValueType {
+ return this._value;
+ }
+
+ @state()
+ _config?: UmbPropertyEditorConfigCollection;
+
+ @state()
+ private _value: UmbRichTextEditorValueType = {};
+
+ override render() {
+ return html``;
+ }
+}
+
+export default UmbPropertyEditorUITiptapElement;
+
+declare global {
+ interface HTMLElementTagNameMap {
+ 'umb-property-editor-ui-tiptap': UmbPropertyEditorUITiptapElement;
+ }
+}
diff --git a/src/packages/tiptap/umbraco-package.ts b/src/packages/tiptap/umbraco-package.ts
new file mode 100644
index 0000000000..79a0937305
--- /dev/null
+++ b/src/packages/tiptap/umbraco-package.ts
@@ -0,0 +1,9 @@
+export const name = 'Umbraco.Core.TipTap';
+export const extensions = [
+ {
+ name: 'TipTap Bundle',
+ alias: 'Umb.Bundle.TipTap',
+ type: 'bundle',
+ js: () => import('./manifests.js'),
+ },
+];
diff --git a/src/packages/tiptap/vite.config.ts b/src/packages/tiptap/vite.config.ts
new file mode 100644
index 0000000000..7e6c0e3f77
--- /dev/null
+++ b/src/packages/tiptap/vite.config.ts
@@ -0,0 +1,12 @@
+import { defineConfig } from 'vite';
+import { rmSync } from 'fs';
+import { getDefaultConfig } from '../../vite-config-base';
+
+const dist = '../../../dist-cms/packages/tiptap';
+
+// delete the unbundled dist folder
+rmSync(dist, { recursive: true, force: true });
+
+export default defineConfig({
+ ...getDefaultConfig({ dist }),
+});
diff --git a/tsconfig.json b/tsconfig.json
index 13058d558f..23ba90be60 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -135,6 +135,7 @@ DON'T EDIT THIS FILE DIRECTLY. It is generated by /devops/tsconfig/index.js
"@umbraco-cms/backoffice/external/router-slot": ["./src/external/router-slot/index.ts"],
"@umbraco-cms/backoffice/external/rxjs": ["./src/external/rxjs/index.ts"],
"@umbraco-cms/backoffice/external/tinymce": ["./src/external/tinymce/index.ts"],
+ "@umbraco-cms/backoffice/external/tiptap": ["./src/external/tiptap/index.ts"],
"@umbraco-cms/backoffice/external/uui": ["./src/external/uui/index.ts"],
"@umbraco-cms/backoffice/external/uuid": ["./src/external/uuid/index.ts"]
}
From 0cf07db73f06d004e6e15b07eb2f1f0d89df0aac Mon Sep 17 00:00:00 2001
From: JesmoDev <26099018+JesmoDev@users.noreply.github.com>
Date: Mon, 9 Sep 2024 21:15:26 +0200
Subject: [PATCH 003/241] package json
---
src/packages/tiptap/package.json | 8 ++++++++
1 file changed, 8 insertions(+)
create mode 100644 src/packages/tiptap/package.json
diff --git a/src/packages/tiptap/package.json b/src/packages/tiptap/package.json
new file mode 100644
index 0000000000..00d278e4d9
--- /dev/null
+++ b/src/packages/tiptap/package.json
@@ -0,0 +1,8 @@
+{
+ "name": "@umbraco-backoffice/tiptap",
+ "private": true,
+ "type": "module",
+ "scripts": {
+ "build": "vite build"
+ }
+}
From 3f480945e5bb15736d7de24ea031fa4bcacee56b Mon Sep 17 00:00:00 2001
From: JesmoDev <26099018+JesmoDev@users.noreply.github.com>
Date: Mon, 9 Sep 2024 21:33:09 +0200
Subject: [PATCH 004/241] add editor schema
---
.../tiptap/property-editors/Umbraco.Tiptap.ts | 13 +++++++++++++
1 file changed, 13 insertions(+)
create mode 100644 src/packages/tiptap/property-editors/Umbraco.Tiptap.ts
diff --git a/src/packages/tiptap/property-editors/Umbraco.Tiptap.ts b/src/packages/tiptap/property-editors/Umbraco.Tiptap.ts
new file mode 100644
index 0000000000..7837aea024
--- /dev/null
+++ b/src/packages/tiptap/property-editors/Umbraco.Tiptap.ts
@@ -0,0 +1,13 @@
+import type { ManifestPropertyEditorSchema } from '@umbraco-cms/backoffice/extension-registry';
+
+export const manifest: ManifestPropertyEditorSchema = {
+ type: 'propertyEditorSchema',
+ name: 'Rich Text Tiptap',
+ alias: 'Umbraco.Tiptap',
+ meta: {
+ defaultPropertyEditorUiAlias: 'Umb.PropertyEditorUi.Tiptap',
+ settings: {
+ properties: [],
+ },
+ },
+};
From f6a788289ef1d120949d5f5e3a40ee4903e86d5d Mon Sep 17 00:00:00 2001
From: JesmoDev <26099018+JesmoDev@users.noreply.github.com>
Date: Tue, 10 Sep 2024 13:36:54 +0200
Subject: [PATCH 005/241] use json schema
---
.../tiptap/property-editors/Umbraco.Tiptap.ts | 13 -------------
.../tiptap/property-editors/tiptap/manifests.ts | 2 +-
2 files changed, 1 insertion(+), 14 deletions(-)
delete mode 100644 src/packages/tiptap/property-editors/Umbraco.Tiptap.ts
diff --git a/src/packages/tiptap/property-editors/Umbraco.Tiptap.ts b/src/packages/tiptap/property-editors/Umbraco.Tiptap.ts
deleted file mode 100644
index 7837aea024..0000000000
--- a/src/packages/tiptap/property-editors/Umbraco.Tiptap.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import type { ManifestPropertyEditorSchema } from '@umbraco-cms/backoffice/extension-registry';
-
-export const manifest: ManifestPropertyEditorSchema = {
- type: 'propertyEditorSchema',
- name: 'Rich Text Tiptap',
- alias: 'Umbraco.Tiptap',
- meta: {
- defaultPropertyEditorUiAlias: 'Umb.PropertyEditorUi.Tiptap',
- settings: {
- properties: [],
- },
- },
-};
diff --git a/src/packages/tiptap/property-editors/tiptap/manifests.ts b/src/packages/tiptap/property-editors/tiptap/manifests.ts
index ba824b19d6..140d8e4b96 100644
--- a/src/packages/tiptap/property-editors/tiptap/manifests.ts
+++ b/src/packages/tiptap/property-editors/tiptap/manifests.ts
@@ -8,7 +8,7 @@ export const manifests: Array = [
element: () => import('./property-editor-ui-tiptap.element.js'),
meta: {
label: 'Tiptap Editor',
- propertyEditorSchemaAlias: 'Umbraco.Tiptap',
+ propertyEditorSchemaAlias: 'Umbraco.Plain.Json',
icon: 'icon-document',
group: 'richText',
},
From 8876590fc7fc622c355df5988b967ab69b27ac0e Mon Sep 17 00:00:00 2001
From: JesmoDev <26099018+JesmoDev@users.noreply.github.com>
Date: Tue, 10 Sep 2024 14:12:05 +0200
Subject: [PATCH 006/241] read an write value
---
.../input-tiptap/input-tiptap.element.ts | 21 +++-------------
.../property-editor-ui-tiptap.element.ts | 25 +++++++++++++------
2 files changed, 21 insertions(+), 25 deletions(-)
diff --git a/src/packages/tiptap/components/input-tiptap/input-tiptap.element.ts b/src/packages/tiptap/components/input-tiptap/input-tiptap.element.ts
index 1932b8d77e..2c6bfc01bc 100644
--- a/src/packages/tiptap/components/input-tiptap/input-tiptap.element.ts
+++ b/src/packages/tiptap/components/input-tiptap/input-tiptap.element.ts
@@ -6,6 +6,7 @@ import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/
import './tiptap-fixed-menu.element.js';
import { Editor, StarterKit } from '@umbraco-cms/backoffice/external/tiptap';
+import { UmbChangeEvent } from '@umbraco-cms/backoffice/event';
@customElement('umb-input-tiptap')
export class UmbInputTiptapElement extends UUIFormControlMixin(UmbLitElement, '') {
@@ -22,23 +23,7 @@ export class UmbInputTiptapElement extends UUIFormControlMixin(UmbLitElement, ''
if (!editor) return;
- const json =
- this.value && typeof this.value === 'string'
- ? JSON.parse(this.value)
- : {
- type: 'doc',
- content: [
- {
- type: 'paragraph',
- content: [
- {
- type: 'text',
- text: 'Hello Umbraco',
- },
- ],
- },
- ],
- };
+ const json = this.value && typeof this.value === 'string' ? JSON.parse(this.value) : this.value;
// TODO: Try Disable css inject to remove prosemirror css
this._editor = new Editor({
@@ -48,7 +33,7 @@ export class UmbInputTiptapElement extends UUIFormControlMixin(UmbLitElement, ''
onUpdate: ({ editor }) => {
const json = editor.getJSON();
this.value = JSON.stringify(json);
- console.log('json', json);
+ this.dispatchEvent(new UmbChangeEvent());
},
});
}
diff --git a/src/packages/tiptap/property-editors/tiptap/property-editor-ui-tiptap.element.ts b/src/packages/tiptap/property-editors/tiptap/property-editor-ui-tiptap.element.ts
index 27390b2a0d..c1683214d7 100644
--- a/src/packages/tiptap/property-editors/tiptap/property-editor-ui-tiptap.element.ts
+++ b/src/packages/tiptap/property-editors/tiptap/property-editor-ui-tiptap.element.ts
@@ -1,10 +1,12 @@
+import type UmbInputTiptapElement from '../../components/input-tiptap/input-tiptap.element.js';
import { customElement, html, property, state } from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
-import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor';
+import {
+ UmbPropertyValueChangeEvent,
+ type UmbPropertyEditorConfigCollection,
+} from '@umbraco-cms/backoffice/property-editor';
import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry';
-import '../../components/input-tiptap/input-tiptap.element.js';
-
// Look at Tiny for correct types
export interface UmbRichTextEditorValueType {
markup?: string;
@@ -22,10 +24,10 @@ export class UmbPropertyEditorUITiptapElement extends UmbLitElement implements U
}
@property({ attribute: false })
- public set value(value: UmbRichTextEditorValueType) {
+ public set value(value: string) {
this._value = value;
}
- public get value(): UmbRichTextEditorValueType {
+ public get value(): string {
return this._value;
}
@@ -33,10 +35,19 @@ export class UmbPropertyEditorUITiptapElement extends UmbLitElement implements U
_config?: UmbPropertyEditorConfigCollection;
@state()
- private _value: UmbRichTextEditorValueType = {};
+ private _value: string = '';
+
+ #onChange(event: CustomEvent & { target: UmbInputTiptapElement }) {
+ const value = event.target.value as string;
+ this._value = value;
+ this.dispatchEvent(new UmbPropertyValueChangeEvent());
+ }
override render() {
- return html``;
+ return html``;
}
}
From fe7b941dd26132d42d7efd5fa8900185ac6d8372 Mon Sep 17 00:00:00 2001
From: JesmoDev <26099018+JesmoDev@users.noreply.github.com>
Date: Tue, 10 Sep 2024 14:16:14 +0200
Subject: [PATCH 007/241] fix import
---
.../tiptap/property-editor-ui-tiptap.element.ts | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/packages/tiptap/property-editors/tiptap/property-editor-ui-tiptap.element.ts b/src/packages/tiptap/property-editors/tiptap/property-editor-ui-tiptap.element.ts
index c1683214d7..23fd1fbfb1 100644
--- a/src/packages/tiptap/property-editors/tiptap/property-editor-ui-tiptap.element.ts
+++ b/src/packages/tiptap/property-editors/tiptap/property-editor-ui-tiptap.element.ts
@@ -7,6 +7,8 @@ import {
} from '@umbraco-cms/backoffice/property-editor';
import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry';
+import '../../components/input-tiptap/input-tiptap.element.js';
+
// Look at Tiny for correct types
export interface UmbRichTextEditorValueType {
markup?: string;
From e20a7d3c28bac3ec99e9005d54c71fbd13194cbc Mon Sep 17 00:00:00 2001
From: JesmoDev <26099018+JesmoDev@users.noreply.github.com>
Date: Tue, 10 Sep 2024 15:28:51 +0200
Subject: [PATCH 008/241] install more tiptap extensions
---
package-lock.json | 26 ++++++++++++++++++++++++++
package.json | 2 ++
2 files changed, 28 insertions(+)
diff --git a/package-lock.json b/package-lock.json
index cbc477b3b5..2707efe191 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -41,6 +41,8 @@
],
"dependencies": {
"@tiptap/core": "^2.6.6",
+ "@tiptap/extension-text-align": "^2.6.6",
+ "@tiptap/extension-underline": "^2.6.6",
"@tiptap/pm": "^2.6.6",
"@tiptap/starter-kit": "^2.6.6",
"@types/diff": "^5.2.1",
@@ -6722,6 +6724,30 @@
"@tiptap/core": "^2.6.6"
}
},
+ "node_modules/@tiptap/extension-text-align": {
+ "version": "2.6.6",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-text-align/-/extension-text-align-2.6.6.tgz",
+ "integrity": "sha512-WdyxULEEHfI3hRDHAFOUoeP84h9myabadfjtZrub7/zO2PKKPAZLBN2vWat5PowH8E8GYX8vqKr9vaX+slfh5g==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "^2.6.6"
+ }
+ },
+ "node_modules/@tiptap/extension-underline": {
+ "version": "2.6.6",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-underline/-/extension-underline-2.6.6.tgz",
+ "integrity": "sha512-3A4HqsDM/AFb2VaeWACpGexjgI257kz0yU4jNV8uyydDR2KhqeinuEnoSoOmx9T3pL006TWfPg4vaQYPO3qvrQ==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "^2.6.6"
+ }
+ },
"node_modules/@tiptap/pm": {
"version": "2.6.6",
"resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-2.6.6.tgz",
diff --git a/package.json b/package.json
index 911ef8621f..b63b9a48a1 100644
--- a/package.json
+++ b/package.json
@@ -213,6 +213,8 @@
},
"dependencies": {
"@tiptap/core": "^2.6.6",
+ "@tiptap/extension-text-align": "^2.6.6",
+ "@tiptap/extension-underline": "^2.6.6",
"@tiptap/pm": "^2.6.6",
"@tiptap/starter-kit": "^2.6.6",
"@types/diff": "^5.2.1",
From 4188b13db12bfe08a1718fdd6681a59fd6eaad69 Mon Sep 17 00:00:00 2001
From: JesmoDev <26099018+JesmoDev@users.noreply.github.com>
Date: Tue, 10 Sep 2024 15:29:02 +0200
Subject: [PATCH 009/241] styling and icons
---
src/external/tiptap/index.ts | 2 +
.../tiptap/components/input-tiptap/icons.ts | 252 ++++++++++++++++++
.../input-tiptap/input-tiptap.element.ts | 37 ++-
.../input-tiptap/tiptap-fixed-menu.element.ts | 214 +++++----------
4 files changed, 343 insertions(+), 162 deletions(-)
create mode 100644 src/packages/tiptap/components/input-tiptap/icons.ts
diff --git a/src/external/tiptap/index.ts b/src/external/tiptap/index.ts
index 1d5fb7fe1e..42ab4c52b1 100644
--- a/src/external/tiptap/index.ts
+++ b/src/external/tiptap/index.ts
@@ -1,2 +1,4 @@
export * from '@tiptap/core';
export * from '@tiptap/starter-kit';
+export * from '@tiptap/extension-underline';
+export * from '@tiptap/extension-text-align';
diff --git a/src/packages/tiptap/components/input-tiptap/icons.ts b/src/packages/tiptap/components/input-tiptap/icons.ts
new file mode 100644
index 0000000000..1d6e9544aa
--- /dev/null
+++ b/src/packages/tiptap/components/input-tiptap/icons.ts
@@ -0,0 +1,252 @@
+import { html } from '@umbraco-cms/backoffice/external/lit';
+
+export const bold = html``;
+
+export const italic = html``;
+
+export const underline = html``;
+
+export const strikethrough = html``;
+export const heading1 = html``;
+export const heading2 = html``;
+export const heading3 = html``;
+export const blockquote = html``;
+export const code = html``;
+export const bulletList = html``;
+export const orderedList = html``;
+export const horizontalRule = html``;
+export const alignLeft = html``;
+export const alignCenter = html``;
+export const alignRight = html``;
+export const alignJustify = html``;
diff --git a/src/packages/tiptap/components/input-tiptap/input-tiptap.element.ts b/src/packages/tiptap/components/input-tiptap/input-tiptap.element.ts
index 2c6bfc01bc..60e01af1c8 100644
--- a/src/packages/tiptap/components/input-tiptap/input-tiptap.element.ts
+++ b/src/packages/tiptap/components/input-tiptap/input-tiptap.element.ts
@@ -5,7 +5,7 @@ import { UUIFormControlMixin } from '@umbraco-cms/backoffice/external/uui';
import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor';
import './tiptap-fixed-menu.element.js';
-import { Editor, StarterKit } from '@umbraco-cms/backoffice/external/tiptap';
+import { Editor, StarterKit, TextAlign, Underline } from '@umbraco-cms/backoffice/external/tiptap';
import { UmbChangeEvent } from '@umbraco-cms/backoffice/event';
@customElement('umb-input-tiptap')
@@ -28,7 +28,13 @@ export class UmbInputTiptapElement extends UUIFormControlMixin(UmbLitElement, ''
// TODO: Try Disable css inject to remove prosemirror css
this._editor = new Editor({
element: editor,
- extensions: [StarterKit],
+ extensions: [
+ StarterKit,
+ TextAlign.configure({
+ types: ['heading', 'paragraph', 'blockquote', 'ordered_list', 'bullet_list'],
+ }),
+ Underline,
+ ],
content: json,
onUpdate: ({ editor }) => {
const json = editor.getJSON();
@@ -44,7 +50,7 @@ export class UmbInputTiptapElement extends UUIFormControlMixin(UmbLitElement, ''
override render() {
return html`
-
+
`;
}
@@ -54,6 +60,9 @@ export class UmbInputTiptapElement extends UUIFormControlMixin(UmbLitElement, ''
#editor {
border-radius: var(--uui-border-radius);
border: 1px solid var(--uui-color-border);
+ border-top-left-radius: 0;
+ border-top-right-radius: 0;
+ border-top: 0;
margin: 0 auto;
box-sizing: border-box;
height: 100%;
@@ -64,6 +73,18 @@ export class UmbInputTiptapElement extends UUIFormControlMixin(UmbLitElement, ''
display: grid; /* Don't ask me why this is needed, but it is. */
}
+ #editor pre {
+ background-color: var(--uui-color-surface-alt);
+ padding: var(--uui-size-space-2) var(--uui-size-space-4);
+ border-radius: calc(var(--uui-border-radius) * 2);
+ }
+
+ #editor code:not(pre > code) {
+ background-color: var(--uui-color-surface-alt);
+ padding: var(--uui-size-space-1) var(--uui-size-space-2);
+ border-radius: calc(var(--uui-border-radius) * 2);
+ }
+
#editor code {
font-family: 'Roboto Mono', monospace;
background: none;
@@ -77,12 +98,12 @@ export class UmbInputTiptapElement extends UUIFormControlMixin(UmbLitElement, ''
outline: none;
white-space: pre-wrap;
}
- .ProseMirror p,
- .ProseMirror h1,
- .ProseMirror h2,
- .ProseMirror h3 {
+ #editor p,
+ #editor h1,
+ #editor h2,
+ #editor h3 {
margin-top: 0;
- margin-bottom: 0.1rem;
+ margin-bottom: 0.5em;
}
`,
];
diff --git a/src/packages/tiptap/components/input-tiptap/tiptap-fixed-menu.element.ts b/src/packages/tiptap/components/input-tiptap/tiptap-fixed-menu.element.ts
index 28a3a2185f..8dd8d78f6a 100644
--- a/src/packages/tiptap/components/input-tiptap/tiptap-fixed-menu.element.ts
+++ b/src/packages/tiptap/components/input-tiptap/tiptap-fixed-menu.element.ts
@@ -1,3 +1,21 @@
+import {
+ alignCenter,
+ alignJustify,
+ alignLeft,
+ alignRight,
+ blockquote,
+ bold,
+ bulletList,
+ code,
+ heading1,
+ heading2,
+ heading3,
+ horizontalRule,
+ italic,
+ orderedList,
+ strikethrough,
+ underline,
+} from './icons.js';
import { LitElement, css, customElement, html, property, state } from '@umbraco-cms/backoffice/external/lit';
import type { Editor } from '@umbraco-cms/backoffice/external/tiptap';
@@ -5,207 +23,94 @@ import type { Editor } from '@umbraco-cms/backoffice/external/tiptap';
export class UmbTiptapFixedMenuElement extends LitElement {
@state()
actions = [
- {
- name: 'paragraph',
- icon: html``,
- command: () => this.editor?.chain().focus().setParagraph().run(),
- },
+ // TODO: I don't think we need a paragraph button. It's the default state.
+ // {
+ // name: 'paragraph',
+ // icon: html``,
+ // command: () => this.editor?.chain().focus().setParagraph().run(),
+ // },
{
name: 'bold',
- icon: html``,
+ icon: bold,
command: () => this.editor?.chain().focus().toggleBold().run(),
},
{
name: 'italic',
- icon: html``,
+ icon: italic,
command: () => this.editor?.chain().focus().toggleItalic().run(),
},
{
name: 'underline',
- icon: html``,
- // command: () => this.editor?.chain().focus().toggleUnderline().run(),
+ icon: underline,
+ command: () => this.editor?.chain().focus().toggleUnderline().run(),
},
{
name: 'strikethrough',
- icon: html``,
+ icon: strikethrough,
command: () => this.editor?.chain().focus().toggleStrike().run(),
},
{
- name: 'heading-1',
- icon: html``,
+ name: 'h1',
+ icon: heading1,
command: () => this.editor?.chain().focus().toggleHeading({ level: 1 }).run(),
},
{
- name: 'heading-2',
- icon: html``,
+ name: 'h2',
+ icon: heading2,
command: () => this.editor?.chain().focus().toggleHeading({ level: 2 }).run(),
},
{
- name: 'heading-3',
- icon: html``,
+ name: 'h3',
+ icon: heading3,
command: () => this.editor?.chain().focus().toggleHeading({ level: 3 }).run(),
},
- {
- name: 'heading-4',
- icon: html``,
- command: () => this.editor?.chain().focus().toggleHeading({ level: 4 }).run(),
- },
- {
- name: 'heading-5',
- icon: html``,
- command: () => this.editor?.chain().focus().toggleHeading({ level: 5 }).run(),
- },
{
name: 'blockquote',
- icon: html``,
+ icon: blockquote,
command: () => this.editor?.chain().focus().toggleBlockquote().run(),
},
{
name: 'code',
- icon: html``,
+ icon: code,
command: () => this.editor?.chain().focus().toggleCodeBlock().run(),
},
{
name: 'bullet-list',
- icon: html``,
+ icon: bulletList,
command: () => this.editor?.chain().focus().toggleBulletList().run(),
},
{
name: 'ordered-list',
- icon: html``,
+ icon: orderedList,
command: () => this.editor?.chain().focus().toggleOrderedList().run(),
},
{
name: 'horizontal-rule',
- icon: html``,
+ icon: horizontalRule,
command: () => this.editor?.chain().focus().setHorizontalRule().run(),
},
{
name: 'align-left',
- icon: html``,
- // command: () => this.editor?.chain().focus().setTextAlign('left').run(),
+ icon: alignLeft,
+ command: () => this.editor?.chain().focus().setTextAlign('left').run(),
},
{
name: 'align-center',
- icon: html``,
- // command: () => this.editor?.chain().focus().setTextAlign('center').run(),
+ icon: alignCenter,
+ command: () => this.editor?.chain().focus().setTextAlign('center').run(),
},
{
name: 'align-right',
- icon: html``,
- // command: () => this.editor?.chain().focus().setTextAlign('right').run(),
+ icon: alignRight,
+ command: () => this.editor?.chain().focus().setTextAlign('right').run(),
},
{
name: 'align-justify',
- icon: html``,
- // command: () => this.editor?.chain().focus().setTextAlign('justify').run(),
- },
- {
- name: 'image',
- icon: html``,
- command: () => {
- const url = prompt('Enter the image URL');
- if (url) {
- // this.editor?.chain().focus().setImage({ src: url }).run();
- }
- },
- },
- {
- name: 'add',
- icon: html``,
- command: () => {
- const tag = prompt('Enter the tag');
- if (tag) {
- // this.editor?.chain().focus().addCustomNode(tag).run();
- }
- },
+ icon: alignJustify,
+ command: () => this.editor?.chain().focus().setTextAlign('justify').run(),
},
];
@@ -227,22 +132,22 @@ export class UmbTiptapFixedMenuElement extends LitElement {
background-color: var(--uui-color-surface);
color: var(--color-text);
display: grid;
- grid-template-columns: repeat(auto-fill, minmax(32px, 1fr));
+ grid-template-columns: repeat(auto-fill, minmax(24px, 1fr));
position: sticky;
- top: -18px;
+ top: -25px;
left: 0px;
right: 0px;
- height: 32px;
- padding: 8px;
- border-bottom: none;
+ padding: 4px;
}
button {
- color: var(--color-text);
+ color: var(--uui-color-interactive);
+ width: 24px;
+ height: 24px;
+ padding: 4px;
border: none;
background: none;
cursor: pointer;
- padding: 4px;
margin: 0;
border-radius: 4px;
box-sizing: border-box;
@@ -254,7 +159,8 @@ export class UmbTiptapFixedMenuElement extends LitElement {
}
button:hover {
- color: var(--color-primary);
+ color: var(--uui-color-interactive-emphasis);
+ background-color: var(--uui-color-surface-alt);
}
`;
}
From f2102c9e34717e59e668fdbe504cbddaa6fdf141 Mon Sep 17 00:00:00 2001
From: JesmoDev <26099018+JesmoDev@users.noreply.github.com>
Date: Wed, 11 Sep 2024 10:03:35 +0200
Subject: [PATCH 010/241] install tiptap link
---
package-lock.json | 22 ++++++++++++++++++++++
package.json | 1 +
2 files changed, 23 insertions(+)
diff --git a/package-lock.json b/package-lock.json
index 2707efe191..1f042effe8 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -41,6 +41,7 @@
],
"dependencies": {
"@tiptap/core": "^2.6.6",
+ "@tiptap/extension-link": "^2.6.6",
"@tiptap/extension-text-align": "^2.6.6",
"@tiptap/extension-underline": "^2.6.6",
"@tiptap/pm": "^2.6.6",
@@ -6664,6 +6665,22 @@
"@tiptap/core": "^2.6.6"
}
},
+ "node_modules/@tiptap/extension-link": {
+ "version": "2.6.6",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-link/-/extension-link-2.6.6.tgz",
+ "integrity": "sha512-NJSR5Yf/dI3do0+Mr6e6nkbxRQcqbL7NOPxo5Xw8VaKs2Oe8PX+c7hyqN3GZgn6uEbZdbVi1xjAniUokouwpFg==",
+ "dependencies": {
+ "linkifyjs": "^4.1.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "^2.6.6",
+ "@tiptap/pm": "^2.6.6"
+ }
+ },
"node_modules/@tiptap/extension-list-item": {
"version": "2.6.6",
"resolved": "https://registry.npmjs.org/@tiptap/extension-list-item/-/extension-list-item-2.6.6.tgz",
@@ -16343,6 +16360,11 @@
"uc.micro": "^2.0.0"
}
},
+ "node_modules/linkifyjs": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/linkifyjs/-/linkifyjs-4.1.3.tgz",
+ "integrity": "sha512-auMesunaJ8yfkHvK4gfg1K0SaKX/6Wn9g2Aac/NwX+l5VdmFZzo/hdPGxEOETj+ryRa4/fiOPjeeKURSAJx1sg=="
+ },
"node_modules/lit": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/lit/-/lit-3.2.0.tgz",
diff --git a/package.json b/package.json
index b63b9a48a1..321787d1bd 100644
--- a/package.json
+++ b/package.json
@@ -213,6 +213,7 @@
},
"dependencies": {
"@tiptap/core": "^2.6.6",
+ "@tiptap/extension-link": "^2.6.6",
"@tiptap/extension-text-align": "^2.6.6",
"@tiptap/extension-underline": "^2.6.6",
"@tiptap/pm": "^2.6.6",
From 6323004492f153969eafad66b0f4a6f88b85b624 Mon Sep 17 00:00:00 2001
From: JesmoDev <26099018+JesmoDev@users.noreply.github.com>
Date: Wed, 11 Sep 2024 10:03:43 +0200
Subject: [PATCH 011/241] styling
---
src/external/tiptap/index.ts | 1 +
.../tiptap/components/input-tiptap/icons.ts | 80 +++++++++++--------
.../input-tiptap/input-tiptap.element.ts | 25 +++++-
.../input-tiptap/tiptap-fixed-menu.element.ts | 59 ++++++++++++--
4 files changed, 123 insertions(+), 42 deletions(-)
diff --git a/src/external/tiptap/index.ts b/src/external/tiptap/index.ts
index 42ab4c52b1..9eae18bcdd 100644
--- a/src/external/tiptap/index.ts
+++ b/src/external/tiptap/index.ts
@@ -2,3 +2,4 @@ export * from '@tiptap/core';
export * from '@tiptap/starter-kit';
export * from '@tiptap/extension-underline';
export * from '@tiptap/extension-text-align';
+export * from '@tiptap/extension-link';
diff --git a/src/packages/tiptap/components/input-tiptap/icons.ts b/src/packages/tiptap/components/input-tiptap/icons.ts
index 1d6e9544aa..2676404411 100644
--- a/src/packages/tiptap/components/input-tiptap/icons.ts
+++ b/src/packages/tiptap/components/input-tiptap/icons.ts
@@ -1,9 +1,10 @@
import { html } from '@umbraco-cms/backoffice/external/lit';
+const iconSize = '16px';
export const bold = html`
-
+
End of test content
`,
@@ -860,6 +860,9 @@ export const data: Array = [
Some value for the RTE with an external link and an internal link foo foo
Macro alias: TestMacro
+
+
+
End of test content
`,
},
From 81c79088537672995c59d04bc81f14a37643561e Mon Sep 17 00:00:00 2001
From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Date: Fri, 13 Sep 2024 14:55:40 +0200
Subject: [PATCH 019/241] chore: use already defined function for same purpose
---
.../tiny-mce/property-editor-ui-tiny-mce.element.ts | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/packages/tiny-mce/property-editors/tiny-mce/property-editor-ui-tiny-mce.element.ts b/src/packages/tiny-mce/property-editors/tiny-mce/property-editor-ui-tiny-mce.element.ts
index d40071b228..8cb80938c6 100644
--- a/src/packages/tiny-mce/property-editors/tiny-mce/property-editor-ui-tiny-mce.element.ts
+++ b/src/packages/tiny-mce/property-editors/tiny-mce/property-editor-ui-tiny-mce.element.ts
@@ -149,7 +149,8 @@ export class UmbPropertyEditorUITinyMceElement extends UmbLitElement implements
...this._value,
markup: markup,
};
- this.dispatchEvent(new UmbPropertyValueChangeEvent());
+
+ this.#fireChangeEvent();
}
override render() {
From c5d33e403a10877fcb1fee3804b378fe6d9d2a4b Mon Sep 17 00:00:00 2001
From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Date: Fri, 13 Sep 2024 14:56:00 +0200
Subject: [PATCH 020/241] feat: make tiptap use the predefined format of
Umbraco.RichText
---
.../input-tiptap/input-tiptap.element.ts | 11 +-
.../property-editor-ui-tiptap.element.ts | 113 ++++++++++++++++--
2 files changed, 106 insertions(+), 18 deletions(-)
diff --git a/src/packages/rte/tiptap/components/input-tiptap/input-tiptap.element.ts b/src/packages/rte/tiptap/components/input-tiptap/input-tiptap.element.ts
index 1615081f67..10d3ee9432 100644
--- a/src/packages/rte/tiptap/components/input-tiptap/input-tiptap.element.ts
+++ b/src/packages/rte/tiptap/components/input-tiptap/input-tiptap.element.ts
@@ -19,15 +19,11 @@ export class UmbInputTiptapElement extends UUIFormControlMixin(UmbLitElement, ''
@state()
_editor!: Editor;
- protected override firstUpdated(_changedProperties: PropertyValueMap | Map): void {
- super.firstUpdated(_changedProperties);
-
+ protected override firstUpdated(): void {
const editor = this.shadowRoot?.querySelector('#editor');
if (!editor) return;
- const json = this.value && typeof this.value === 'string' ? JSON.parse(this.value) : this.value;
-
this._editor = new Editor({
element: editor,
extensions: [
@@ -38,10 +34,9 @@ export class UmbInputTiptapElement extends UUIFormControlMixin(UmbLitElement, ''
Link.configure({ openOnClick: false }),
Underline,
],
- content: json,
+ content: this.value.toString(),
onUpdate: ({ editor }) => {
- const json = editor.getJSON();
- this.value = JSON.stringify(json);
+ this.value = editor.getHTML();
this.dispatchEvent(new UmbChangeEvent());
},
});
diff --git a/src/packages/rte/tiptap/property-editors/tiptap/property-editor-ui-tiptap.element.ts b/src/packages/rte/tiptap/property-editors/tiptap/property-editor-ui-tiptap.element.ts
index 23fd1fbfb1..7ab482cb77 100644
--- a/src/packages/rte/tiptap/property-editors/tiptap/property-editor-ui-tiptap.element.ts
+++ b/src/packages/rte/tiptap/property-editors/tiptap/property-editor-ui-tiptap.element.ts
@@ -8,13 +8,21 @@ import {
import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry';
import '../../components/input-tiptap/input-tiptap.element.js';
+import {
+ UmbBlockRteEntriesContext,
+ UmbBlockRteManagerContext,
+ type UmbBlockRteLayoutModel,
+} from '@umbraco-cms/backoffice/block-rte';
+import type { UmbBlockValueType } from '@umbraco-cms/backoffice/block';
// Look at Tiny for correct types
export interface UmbRichTextEditorValueType {
- markup?: string;
- blocks?: any;
+ markup: string;
+ blocks: UmbBlockValueType;
}
+const UMB_BLOCK_RTE_BLOCK_LAYOUT_ALIAS = 'Umbraco.RichText';
+
/**
* @element umb-property-editor-ui-tiptap
*/
@@ -26,30 +34,115 @@ export class UmbPropertyEditorUITiptapElement extends UmbLitElement implements U
}
@property({ attribute: false })
- public set value(value: string) {
- this._value = value;
+ public set value(value: UmbRichTextEditorValueType | undefined) {
+ const buildUpValue: Partial = value ? { ...value } : {};
+ buildUpValue.markup ??= '';
+ buildUpValue.blocks ??= { layout: {}, contentData: [], settingsData: [] };
+ buildUpValue.blocks.layout ??= {};
+ buildUpValue.blocks.contentData ??= [];
+ buildUpValue.blocks.settingsData ??= [];
+ this._value = buildUpValue as UmbRichTextEditorValueType;
+
+ if (this._latestMarkup !== this._value.markup) {
+ this._markup = this._value.markup;
+ }
+
+ this.#managerContext.setLayouts(buildUpValue.blocks.layout[UMB_BLOCK_RTE_BLOCK_LAYOUT_ALIAS] ?? []);
+ this.#managerContext.setContents(buildUpValue.blocks.contentData);
+ this.#managerContext.setSettings(buildUpValue.blocks.settingsData);
}
- public get value(): string {
+ public get value(): UmbRichTextEditorValueType {
return this._value;
}
+ /**
+ * Sets the input to readonly mode, meaning value cannot be changed but still able to read and select its content.
+ * @attr
+ * @default false
+ */
+ @property({ type: Boolean, reflect: true })
+ readonly = false;
+
@state()
_config?: UmbPropertyEditorConfigCollection;
@state()
- private _value: string = '';
+ private _value: UmbRichTextEditorValueType = {
+ markup: '',
+ blocks: { layout: {}, contentData: [], settingsData: [] },
+ };
+
+ // Separate state for markup, to avoid re-rendering/re-setting the value of the Tiptap editor when the value does not really change.
+ @state()
+ private _markup = '';
+ private _latestMarkup = ''; // The latest value gotten from the Tiptap editor.
+
+ #managerContext = new UmbBlockRteManagerContext(this);
+ #entriesContext = new UmbBlockRteEntriesContext(this);
+
+ constructor() {
+ super();
+
+ this.observe(this.#entriesContext.layoutEntries, (layouts) => {
+ // Update manager:
+ this.#managerContext.setLayouts(layouts);
+ });
+
+ this.observe(this.#managerContext.layouts, (layouts) => {
+ this._value = {
+ ...this._value,
+ blocks: { ...this._value.blocks, layout: { [UMB_BLOCK_RTE_BLOCK_LAYOUT_ALIAS]: layouts } },
+ };
+ this.#fireChangeEvent();
+ });
+ this.observe(this.#managerContext.contents, (contents) => {
+ this._value = { ...this._value, blocks: { ...this._value.blocks, contentData: contents } };
+ this.#fireChangeEvent();
+ });
+ this.observe(this.#managerContext.settings, (settings) => {
+ this._value = { ...this._value, blocks: { ...this._value.blocks, settingsData: settings } };
+ this.#fireChangeEvent();
+ });
+ }
+
+ #fireChangeEvent() {
+ this.dispatchEvent(new UmbPropertyValueChangeEvent());
+ }
#onChange(event: CustomEvent & { target: UmbInputTiptapElement }) {
const value = event.target.value as string;
- this._value = value;
- this.dispatchEvent(new UmbPropertyValueChangeEvent());
+ this._latestMarkup = value;
+
+ // TODO: Validate blocks
+ // Loop through used, to remove the classes on these.
+ /*const blockEls = div.querySelectorAll(`umb-rte-block, umb-rte-block-inline`);
+ blockEls.forEach((blockEl) => {
+ blockEl.removeAttribute('contenteditable');
+ blockEl.removeAttribute('class');
+ });
+
+ // Remove unused Blocks of Blocks Layout. Leaving only the Blocks that are present in Markup.
+ //const blockElements = editor.dom.select(`umb-rte-block, umb-rte-block-inline`);
+ const usedContentUdis = Array.from(blockEls).map((blockElement) => blockElement.getAttribute('data-content-udi'));
+ const unusedBlocks = this.#managerContext.getLayouts().filter((x) => usedContentUdis.indexOf(x.contentUdi) === -1);
+ unusedBlocks.forEach((blockLayout) => {
+ this.#managerContext.removeOneLayout(blockLayout.contentUdi);
+ });*/
+
+ this._value = {
+ ...this._value,
+ markup: this._latestMarkup,
+ };
+
+ this.#fireChangeEvent();
}
override render() {
return html``;
+ .configuration=${this._config}
+ ?readonly=${this.readonly}>`;
}
}
From ffaa17ab44377bc14e36303870a3cdfe28759fec Mon Sep 17 00:00:00 2001
From: leekelleher
Date: Mon, 16 Sep 2024 15:22:36 +0100
Subject: [PATCH 021/241] Adds `tiptapExtension` manifest type
---
.../core/extension-registry/models/index.ts | 3 +++
.../models/tiptap-extension.model.ts | 6 +++++
src/packages/rte/manifests.ts | 3 ++-
.../tiptap/components/input-tiptap/index.ts | 1 +
.../input-tiptap/tiptap-extension.ts | 22 +++++++++++++++++++
src/packages/rte/tiptap/index.ts | 1 +
6 files changed, 35 insertions(+), 1 deletion(-)
create mode 100644 src/packages/core/extension-registry/models/tiptap-extension.model.ts
create mode 100644 src/packages/rte/tiptap/components/input-tiptap/tiptap-extension.ts
create mode 100644 src/packages/rte/tiptap/index.ts
diff --git a/src/packages/core/extension-registry/models/index.ts b/src/packages/core/extension-registry/models/index.ts
index 00fec52d8f..d79b3f9e4a 100644
--- a/src/packages/core/extension-registry/models/index.ts
+++ b/src/packages/core/extension-registry/models/index.ts
@@ -42,6 +42,7 @@ import type { ManifestSectionView } from './section-view.model.js';
import type { ManifestStore, ManifestTreeStore, ManifestItemStore } from './store.model.js';
import type { ManifestTheme } from './theme.model.js';
import type { ManifestTinyMcePlugin } from './tinymce-plugin.model.js';
+import type { ManifestTiptapExtension } from './tiptap-extension.model.js';
import type { ManifestTree } from './tree.model.js';
import type { ManifestTreeItem } from './tree-item.model.js';
import type { ManifestUfmComponent } from './ufm-component.model.js';
@@ -113,6 +114,7 @@ export type * from './section.model.js';
export type * from './store.model.js';
export type * from './theme.model.js';
export type * from './tinymce-plugin.model.js';
+export type * from './tiptap-extension.model.js';
export type * from './tree-item.model.js';
export type * from './tree.model.js';
export type * from './ufm-component.model.js';
@@ -206,6 +208,7 @@ export type ManifestTypes =
| ManifestStore
| ManifestTheme
| ManifestTinyMcePlugin
+ | ManifestTiptapExtension
| ManifestTree
| ManifestTreeItem
| ManifestTreeStore
diff --git a/src/packages/core/extension-registry/models/tiptap-extension.model.ts b/src/packages/core/extension-registry/models/tiptap-extension.model.ts
new file mode 100644
index 0000000000..5d9ff73dfa
--- /dev/null
+++ b/src/packages/core/extension-registry/models/tiptap-extension.model.ts
@@ -0,0 +1,6 @@
+import type { UmbTiptapExtensionBase } from '@umbraco-cms/backoffice/tiptap';
+import type { ManifestApi } from '@umbraco-cms/backoffice/extension-api';
+
+export interface ManifestTiptapExtension extends ManifestApi {
+ type: 'tiptapExtension';
+}
diff --git a/src/packages/rte/manifests.ts b/src/packages/rte/manifests.ts
index f4d7d8f1ff..1a38fe7fe9 100644
--- a/src/packages/rte/manifests.ts
+++ b/src/packages/rte/manifests.ts
@@ -1,3 +1,4 @@
import { manifests as tiptapManifests } from './tiptap/manifests.js';
+import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry';
-export const manifests = [...tiptapManifests];
+export const manifests: Array = [...tiptapManifests];
diff --git a/src/packages/rte/tiptap/components/input-tiptap/index.ts b/src/packages/rte/tiptap/components/input-tiptap/index.ts
index f11b53c7d9..0d9456b123 100644
--- a/src/packages/rte/tiptap/components/input-tiptap/index.ts
+++ b/src/packages/rte/tiptap/components/input-tiptap/index.ts
@@ -1 +1,2 @@
export * from './input-tiptap.element.js';
+export * from './tiptap-extension.js';
diff --git a/src/packages/rte/tiptap/components/input-tiptap/tiptap-extension.ts b/src/packages/rte/tiptap/components/input-tiptap/tiptap-extension.ts
new file mode 100644
index 0000000000..aa01ea3420
--- /dev/null
+++ b/src/packages/rte/tiptap/components/input-tiptap/tiptap-extension.ts
@@ -0,0 +1,22 @@
+import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
+import type { Editor, Extension, Mark, Node } from '@umbraco-cms/backoffice/external/tiptap';
+import type { TemplateResult } from '@umbraco-cms/backoffice/external/lit';
+import type { UmbApi } from '@umbraco-cms/backoffice/extension-api';
+import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
+
+export abstract class UmbTiptapExtensionBase extends UmbControllerBase implements UmbApi {
+ constructor(host: UmbControllerHost) {
+ super(host);
+ }
+
+ abstract getExtensions(): Array;
+
+ abstract getToolbarButtons(): Array;
+}
+
+export interface UmbTiptapToolbarButton {
+ name: string;
+ icon: string | TemplateResult;
+ isActive: (editor?: Editor) => boolean | undefined;
+ command: (editor?: Editor) => boolean | undefined | void | Promise | Promise | Promise;
+}
diff --git a/src/packages/rte/tiptap/index.ts b/src/packages/rte/tiptap/index.ts
new file mode 100644
index 0000000000..8a8c2711ca
--- /dev/null
+++ b/src/packages/rte/tiptap/index.ts
@@ -0,0 +1 @@
+export * from './components/index.js';
From 1dc79920811840d0f7d0d3122b41227d5a1ab0d2 Mon Sep 17 00:00:00 2001
From: leekelleher
Date: Mon, 16 Sep 2024 15:24:41 +0100
Subject: [PATCH 022/241] [WIP] Placeholder media picker extension for Tiptap
RTE
---
.../rte/tiptap/extensions/manifests.ts | 10 +++
.../tiptap-mediapicker.extension.ts | 68 +++++++++++++++++++
src/packages/rte/tiptap/manifests.ts | 3 +-
3 files changed, 80 insertions(+), 1 deletion(-)
create mode 100644 src/packages/rte/tiptap/extensions/manifests.ts
create mode 100644 src/packages/rte/tiptap/extensions/tiptap-mediapicker.extension.ts
diff --git a/src/packages/rte/tiptap/extensions/manifests.ts b/src/packages/rte/tiptap/extensions/manifests.ts
new file mode 100644
index 0000000000..6780ce1c09
--- /dev/null
+++ b/src/packages/rte/tiptap/extensions/manifests.ts
@@ -0,0 +1,10 @@
+import type { ManifestTiptapExtension } from '@umbraco-cms/backoffice/extension-registry';
+
+export const manifests: Array = [
+ {
+ type: 'tiptapExtension',
+ alias: 'Umb.Tiptap.MediaPicker',
+ name: 'Media Picker Tiptap Extension',
+ api: () => import('./tiptap-mediapicker.extension.js'),
+ },
+];
diff --git a/src/packages/rte/tiptap/extensions/tiptap-mediapicker.extension.ts b/src/packages/rte/tiptap/extensions/tiptap-mediapicker.extension.ts
new file mode 100644
index 0000000000..be14701cef
--- /dev/null
+++ b/src/packages/rte/tiptap/extensions/tiptap-mediapicker.extension.ts
@@ -0,0 +1,68 @@
+import { UmbTiptapExtensionBase } from '../components/input-tiptap/tiptap-extension.js';
+import { mergeAttributes, Node } from '@umbraco-cms/backoffice/external/tiptap';
+import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal';
+import type { Editor } from '@umbraco-cms/backoffice/external/tiptap';
+import { UMB_MEDIA_PICKER_MODAL } from '@umbraco-cms/backoffice/media';
+
+export default class UmbTiptapMediaPickerPlugin extends UmbTiptapExtensionBase {
+ getExtensions() {
+ return [
+ Node.create({
+ name: 'umbMediaPicker',
+ group: 'block',
+ marks: '',
+ draggable: true,
+ addNodeView() {
+ return () => {
+ //console.log('umb-media.addNodeView');
+ const dom = document.createElement('umb-debug');
+ dom.attributes.setNamedItem(document.createAttribute('visible'));
+ dom.attributes.setNamedItem(document.createAttribute('dialog'));
+ return { dom };
+ };
+ },
+ parseHTML() {
+ //console.log('umb-media.parseHTML');
+ return [{ tag: 'umb-media' }];
+ },
+ renderHTML({ HTMLAttributes }) {
+ //console.log('umb-media.renderHTML');
+ return ['umb-media', mergeAttributes(HTMLAttributes)];
+ },
+ }),
+ ];
+ }
+
+ getToolbarButtons() {
+ return [
+ {
+ name: 'umb-media',
+ icon: 'icon-picture',
+ isActive: (editor?: Editor) => editor?.isActive('umbMediaPicker'),
+ command: async (editor?: Editor) => {
+ //console.log('umb-media.command', editor);
+
+ const selection = await this.#openMediaPicker();
+ if (!selection || !selection.length) return;
+
+ editor?.chain().focus().insertContent(`${selection}`).run();
+ },
+ },
+ ];
+ }
+
+ async #openMediaPicker() {
+ const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT);
+ const modalHandler = modalManager?.open(this, UMB_MEDIA_PICKER_MODAL, {
+ data: { multiple: false },
+ value: { selection: [] },
+ });
+
+ if (!modalHandler) return;
+
+ const { selection } = await modalHandler.onSubmit().catch(() => ({ selection: undefined }));
+
+ //console.log('umb-media.selection', selection);
+ return selection;
+ }
+}
diff --git a/src/packages/rte/tiptap/manifests.ts b/src/packages/rte/tiptap/manifests.ts
index 1dcd948374..8e6836b5cc 100644
--- a/src/packages/rte/tiptap/manifests.ts
+++ b/src/packages/rte/tiptap/manifests.ts
@@ -1,4 +1,5 @@
+import { manifests as extensions } from './extensions/manifests.js';
import { manifests as propertyEditors } from './property-editors/manifests.js';
import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry';
-export const manifests: Array = [...propertyEditors];
+export const manifests: Array = [...extensions, ...propertyEditors];
From e7ccf77f7705321fbddcafa59cda5e2dcda40c24 Mon Sep 17 00:00:00 2001
From: leekelleher
Date: Mon, 16 Sep 2024 15:26:18 +0100
Subject: [PATCH 023/241] Refactored `umb-input-tiptap` to await loading
extensions
before initializing the Tiptap editor.
---
.../input-tiptap/input-tiptap.element.ts | 63 +++++++++++++------
1 file changed, 45 insertions(+), 18 deletions(-)
diff --git a/src/packages/rte/tiptap/components/input-tiptap/input-tiptap.element.ts b/src/packages/rte/tiptap/components/input-tiptap/input-tiptap.element.ts
index 10d3ee9432..87e7b4e387 100644
--- a/src/packages/rte/tiptap/components/input-tiptap/input-tiptap.element.ts
+++ b/src/packages/rte/tiptap/components/input-tiptap/input-tiptap.element.ts
@@ -1,31 +1,60 @@
-import type { UmbTiptapFixedMenuElement } from './tiptap-fixed-menu.element.js';
-import type { PropertyValueMap } from '@umbraco-cms/backoffice/external/lit';
-import { css, customElement, html, property, query, state } from '@umbraco-cms/backoffice/external/lit';
+import type { UmbTiptapExtensionBase } from './tiptap-extension.js';
+import { css, customElement, html, property, state } from '@umbraco-cms/backoffice/external/lit';
+import { loadManifestApi } from '@umbraco-cms/backoffice/extension-api';
+import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
+import { Editor, Link, StarterKit, TextAlign, Underline } from '@umbraco-cms/backoffice/external/tiptap';
+import { UmbChangeEvent } from '@umbraco-cms/backoffice/event';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
-import { UUIFormControlMixin } from '@umbraco-cms/backoffice/external/uui';
+import { UmbFormControlMixin } from '@umbraco-cms/backoffice/validation';
import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor';
import './tiptap-fixed-menu.element.js';
import './tiptap-hover-menu.element.js';
-import { Editor, Link, StarterKit, TextAlign, Underline } from '@umbraco-cms/backoffice/external/tiptap';
-import { UmbChangeEvent } from '@umbraco-cms/backoffice/event';
@customElement('umb-input-tiptap')
-export class UmbInputTiptapElement extends UUIFormControlMixin(UmbLitElement, '') {
- @query('umb-tiptap-fixed-menu') _fixedMenuElement!: UmbTiptapFixedMenuElement;
+export class UmbInputTiptapElement extends UmbFormControlMixin(UmbLitElement, '') {
+ @state()
+ private _extensions: Array = [];
+
@property({ attribute: false })
configuration?: UmbPropertyEditorConfigCollection;
@state()
- _editor!: Editor;
+ private _editor!: Editor;
+
+ protected override async firstUpdated() {
+ await Promise.all([await this.#loadExtensions(), await this.#loadEditor()]);
+ }
- protected override firstUpdated(): void {
- const editor = this.shadowRoot?.querySelector('#editor');
+ async #loadExtensions() {
+ await new Promise((resolve) => {
+ this.observe(umbExtensionsRegistry.byType('tiptapExtension'), async (manifests) => {
+ this._extensions = [];
- if (!editor) return;
+ for (const manifest of manifests) {
+ if (manifest.api) {
+ const extension = await loadManifestApi(manifest.api);
+ if (extension) {
+ this._extensions.push(new extension(this));
+ }
+ }
+ }
+
+ this.requestUpdate('_extensions');
+
+ resolve();
+ });
+ });
+ }
+
+ async #loadEditor() {
+ const element = this.shadowRoot?.querySelector('#editor');
+ if (!element) return;
+
+ const extensions = this._extensions.map((ext) => ext.getExtensions()).flat();
this._editor = new Editor({
- element: editor,
+ element: element,
extensions: [
StarterKit,
TextAlign.configure({
@@ -33,6 +62,7 @@ export class UmbInputTiptapElement extends UUIFormControlMixin(UmbLitElement, ''
}),
Link.configure({ openOnClick: false }),
Underline,
+ ...extensions,
],
content: this.value.toString(),
onUpdate: ({ editor }) => {
@@ -42,14 +72,11 @@ export class UmbInputTiptapElement extends UUIFormControlMixin(UmbLitElement, ''
});
}
- protected getFormElement() {
- return null;
- }
-
override render() {
+ if (!this._extensions?.length) return html``;
return html`
-
+
`;
}
From 35f30170cd5919e375ed11940241f0fb2fcf4dec Mon Sep 17 00:00:00 2001
From: leekelleher
Date: Mon, 16 Sep 2024 15:26:52 +0100
Subject: [PATCH 024/241] Refactored `umb-tiptap-fixed-menu` to load in the
toolbar button extensions
---
.../input-tiptap/tiptap-fixed-menu.element.ts | 154 +++++++++---------
1 file changed, 77 insertions(+), 77 deletions(-)
diff --git a/src/packages/rte/tiptap/components/input-tiptap/tiptap-fixed-menu.element.ts b/src/packages/rte/tiptap/components/input-tiptap/tiptap-fixed-menu.element.ts
index 598b787211..ab47a21d1a 100644
--- a/src/packages/rte/tiptap/components/input-tiptap/tiptap-fixed-menu.element.ts
+++ b/src/packages/rte/tiptap/components/input-tiptap/tiptap-fixed-menu.element.ts
@@ -1,29 +1,13 @@
-import {
- alignCenter,
- alignJustify,
- alignLeft,
- alignRight,
- blockquote,
- bold,
- bulletList,
- code,
- heading1,
- heading2,
- heading3,
- horizontalRule,
- italic,
- link,
- orderedList,
- strikethrough,
- underline,
-} from './icons.js';
-import { LitElement, css, customElement, html, property, state } from '@umbraco-cms/backoffice/external/lit';
+import * as icons from './icons.js';
+import type { UmbTiptapExtensionBase, UmbTiptapToolbarButton } from './tiptap-extension.js';
+import { css, customElement, html, property, state, when } from '@umbraco-cms/backoffice/external/lit';
+import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import type { Editor } from '@umbraco-cms/backoffice/external/tiptap';
@customElement('umb-tiptap-fixed-menu')
-export class UmbTiptapFixedMenuElement extends LitElement {
+export class UmbTiptapFixedMenuElement extends UmbLitElement {
@state()
- actions = [
+ actions: Array = [
// TODO: I don't think we need a paragraph button. It's the default state.
// {
// name: 'paragraph',
@@ -31,107 +15,108 @@ export class UmbTiptapFixedMenuElement extends LitElement {
//
//
// `,
- // command: () => this.editor?.chain().focus().setParagraph().run(),
+ // command: (editor) => editor?.chain().focus().setParagraph().run(),
// },
{
name: 'bold',
- icon: bold,
- isActive: () => this.editor?.isActive('bold'),
- command: () => this.editor?.chain().focus().toggleBold().run(),
+ icon: icons.bold,
+ isActive: (editor) => editor?.isActive('bold'),
+ command: (editor) => editor?.chain().focus().toggleBold().run(),
},
{
name: 'italic',
- icon: italic,
- isActive: () => this.editor?.isActive('italic'),
- command: () => this.editor?.chain().focus().toggleItalic().run(),
+ icon: icons.italic,
+ isActive: (editor) => editor?.isActive('italic'),
+ command: (editor) => editor?.chain().focus().toggleItalic().run(),
},
{
name: 'underline',
- icon: underline,
- isActive: () => this.editor?.isActive('underline'),
- command: () => this.editor?.chain().focus().toggleUnderline().run(),
+ icon: icons.underline,
+ isActive: (editor) => editor?.isActive('underline'),
+ command: (editor) => editor?.chain().focus().toggleUnderline().run(),
},
{
name: 'strikethrough',
- icon: strikethrough,
- isActive: () => this.editor?.isActive('strike'),
- command: () => this.editor?.chain().focus().toggleStrike().run(),
+ icon: icons.strikethrough,
+ isActive: (editor) => editor?.isActive('strike'),
+ command: (editor) => editor?.chain().focus().toggleStrike().run(),
},
{
name: 'h1',
- icon: heading1,
- isActive: () => this.editor?.isActive('heading', { level: 1 }),
- command: () => this.editor?.chain().focus().toggleHeading({ level: 1 }).run(),
+ icon: icons.heading1,
+ isActive: (editor) => editor?.isActive('heading', { level: 1 }),
+ command: (editor) => editor?.chain().focus().toggleHeading({ level: 1 }).run(),
},
{
name: 'h2',
- icon: heading2,
- isActive: () => this.editor?.isActive('heading', { level: 2 }),
- command: () => this.editor?.chain().focus().toggleHeading({ level: 2 }).run(),
+ icon: icons.heading2,
+ isActive: (editor) => editor?.isActive('heading', { level: 2 }),
+ command: (editor) => editor?.chain().focus().toggleHeading({ level: 2 }).run(),
},
{
name: 'h3',
- icon: heading3,
- isActive: () => this.editor?.isActive('heading', { level: 3 }),
- command: () => this.editor?.chain().focus().toggleHeading({ level: 3 }).run(),
+ icon: icons.heading3,
+ isActive: (editor) => editor?.isActive('heading', { level: 3 }),
+ command: (editor) => editor?.chain().focus().toggleHeading({ level: 3 }).run(),
},
{
name: 'blockquote',
- icon: blockquote,
- isActive: () => this.editor?.isActive('blockquote'),
- command: () => this.editor?.chain().focus().toggleBlockquote().run(),
+ icon: icons.blockquote,
+ isActive: (editor) => editor?.isActive('blockquote'),
+ command: (editor) => editor?.chain().focus().toggleBlockquote().run(),
},
{
name: 'code',
- icon: code,
- isActive: () => this.editor?.isActive('codeBlock'),
- command: () => this.editor?.chain().focus().toggleCodeBlock().run(),
+ icon: icons.code,
+ isActive: (editor) => editor?.isActive('codeBlock'),
+ command: (editor) => editor?.chain().focus().toggleCodeBlock().run(),
},
{
name: 'bullet-list',
- icon: bulletList,
- isActive: () => this.editor?.isActive('bulletList'),
- command: () => this.editor?.chain().focus().toggleBulletList().run(),
+ icon: icons.bulletList,
+ isActive: (editor) => editor?.isActive('bulletList'),
+ command: (editor) => editor?.chain().focus().toggleBulletList().run(),
},
{
name: 'ordered-list',
- icon: orderedList,
- isActive: () => this.editor?.isActive('orderedList'),
- command: () => this.editor?.chain().focus().toggleOrderedList().run(),
+ icon: icons.orderedList,
+ isActive: (editor) => editor?.isActive('orderedList'),
+ command: (editor) => editor?.chain().focus().toggleOrderedList().run(),
},
{
name: 'horizontal-rule',
- icon: horizontalRule,
- isActive: () => this.editor?.isActive('horizontalRule'),
- command: () => this.editor?.chain().focus().setHorizontalRule().run(),
+ icon: icons.horizontalRule,
+ isActive: (editor) => editor?.isActive('horizontalRule'),
+ command: (editor) => editor?.chain().focus().setHorizontalRule().run(),
},
{
name: 'align-left',
- icon: alignLeft,
- isActive: () => this.editor?.isActive({ textAlign: 'left' }),
- command: () => this.editor?.chain().focus().setTextAlign('left').run(),
+ icon: icons.alignLeft,
+ isActive: (editor) => editor?.isActive({ textAlign: 'left' }),
+ command: (editor) => editor?.chain().focus().setTextAlign('left').run(),
},
{
name: 'align-center',
- icon: alignCenter,
- isActive: () => this.editor?.isActive({ textAlign: 'center' }),
- command: () => this.editor?.chain().focus().setTextAlign('center').run(),
+ icon: icons.alignCenter,
+ isActive: (editor) => editor?.isActive({ textAlign: 'center' }),
+ command: (editor) => editor?.chain().focus().setTextAlign('center').run(),
},
{
name: 'align-right',
- icon: alignRight,
- isActive: () => this.editor?.isActive({ textAlign: 'right' }),
- command: () => this.editor?.chain().focus().setTextAlign('right').run(),
+ icon: icons.alignRight,
+ isActive: (editor) => editor?.isActive({ textAlign: 'right' }),
+ command: (editor) => editor?.chain().focus().setTextAlign('right').run(),
},
{
name: 'align-justify',
- icon: alignJustify,
- isActive: () => this.editor?.isActive({ textAlign: 'justify' }),
- command: () => this.editor?.chain().focus().setTextAlign('justify').run(),
+ icon: icons.alignJustify,
+ isActive: (editor) => editor?.isActive({ textAlign: 'justify' }),
+ command: (editor) => editor?.chain().focus().setTextAlign('justify').run(),
},
{
name: 'link',
- icon: link,
+ icon: icons.link,
+ isActive: (editor) => editor?.isActive('link'),
command: () => {
const text = prompt('Enter the text');
const url = prompt('Enter the URL');
@@ -151,9 +136,6 @@ export class UmbTiptapFixedMenuElement extends LitElement {
];
@property({ attribute: false })
- get editor() {
- return this.#editor;
- }
set editor(value) {
const oldValue = this.#editor;
if (value === oldValue) {
@@ -163,18 +145,36 @@ export class UmbTiptapFixedMenuElement extends LitElement {
this.#editor?.on('selectionUpdate', this.#onUpdate);
this.#editor?.on('update', this.#onUpdate);
}
+ get editor() {
+ return this.#editor;
+ }
#editor?: Editor;
+ @property({ attribute: false })
+ extensions: Array = [];
+
#onUpdate = () => {
this.requestUpdate();
};
+ protected override firstUpdated() {
+ const buttons = this.extensions.flatMap((ext) => ext.getToolbarButtons());
+ this.actions.push(...buttons);
+ }
+
override render() {
return html`
${this.actions.map(
(action) => html`
-