Started playing with prosemirror

- Got base setup together with WYSIWYG/Markdown switching, where HTML is
  the base content format.
- Added some testing routes/views for initial development.
- Added some dev npm tasks to support editor-specific actions.
This commit is contained in:
Dan Brown 2021-11-26 15:05:06 +00:00
parent c3f7b39a0f
commit 27f9e8e4bd
No known key found for this signature in database
GPG Key ID: 46D9F943C24A2EF9
6 changed files with 551 additions and 0 deletions

422
package-lock.json generated
View File

@ -10,6 +10,13 @@
"dropzone": "^5.9.3", "dropzone": "^5.9.3",
"markdown-it": "^12.2.0", "markdown-it": "^12.2.0",
"markdown-it-task-lists": "^2.1.1", "markdown-it-task-lists": "^2.1.1",
"prosemirror-example-setup": "^1.1.2",
"prosemirror-markdown": "^1.6.0",
"prosemirror-model": "^1.15.0",
"prosemirror-schema-basic": "^1.1.2",
"prosemirror-schema-list": "^1.1.6",
"prosemirror-state": "^1.3.4",
"prosemirror-view": "^1.23.2",
"sortablejs": "^1.14.0" "sortablejs": "^1.14.0"
}, },
"devDependencies": { "devDependencies": {
@ -219,6 +226,11 @@
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
"dev": true "dev": true
}, },
"node_modules/crelt": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.5.tgz",
"integrity": "sha512-+BO9wPPi+DWTDcNYhr/W90myha8ptzftZT+LwcmUbbok0rcP/fequmFYCw8NMoH7pkAZQzU78b3kYrlua5a9eA=="
},
"node_modules/cross-spawn": { "node_modules/cross-spawn": {
"version": "6.0.5", "version": "6.0.5",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
@ -1227,6 +1239,11 @@
"integrity": "sha512-k41FwbcLnlgnFh69f4qdUfvDQ+5vaSDnVPFI/y5XuhKRq97EnVVneO9F1ESVCdiVu4fCS2L8usX3mU331hB7pg==", "integrity": "sha512-k41FwbcLnlgnFh69f4qdUfvDQ+5vaSDnVPFI/y5XuhKRq97EnVVneO9F1ESVCdiVu4fCS2L8usX3mU331hB7pg==",
"dev": true "dev": true
}, },
"node_modules/orderedmap": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/orderedmap/-/orderedmap-1.1.1.tgz",
"integrity": "sha512-3Ux8um0zXbVacKUkcytc0u3HgC0b0bBLT+I60r2J/En72cI0nZffqrA7Xtf2Hqs27j1g82llR5Mhbd0Z1XW4AQ=="
},
"node_modules/p-limit": { "node_modules/p-limit": {
"version": "2.3.0", "version": "2.3.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
@ -1345,6 +1362,189 @@
"node": ">=4" "node": ">=4"
} }
}, },
"node_modules/prosemirror-commands": {
"version": "1.1.12",
"resolved": "https://registry.npmjs.org/prosemirror-commands/-/prosemirror-commands-1.1.12.tgz",
"integrity": "sha512-+CrMs3w/ZVPSkR+REg8KL/clyFLv/1+SgY/OMN+CB22Z24j9TZDje72vL36lOZ/E4NeRXuiCcmENcW/vAcG67A==",
"dependencies": {
"prosemirror-model": "^1.0.0",
"prosemirror-state": "^1.0.0",
"prosemirror-transform": "^1.0.0"
}
},
"node_modules/prosemirror-dropcursor": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/prosemirror-dropcursor/-/prosemirror-dropcursor-1.4.0.tgz",
"integrity": "sha512-6+YwTjmqDwlA/Dm+5wK67ezgqgjA/MhSDgaNxKUzH97SmeuWFXyLeDRxxOPZeSo7yTxcDGUCWTEjmQZsVBuMrQ==",
"dependencies": {
"prosemirror-state": "^1.0.0",
"prosemirror-transform": "^1.1.0",
"prosemirror-view": "^1.1.0"
}
},
"node_modules/prosemirror-example-setup": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/prosemirror-example-setup/-/prosemirror-example-setup-1.1.2.tgz",
"integrity": "sha512-MTpIMyqk08jFnzxeRMCinCEMtVSTUtxKgQBGxfCbVe9C6zIOqp9qZZJz5Ojaad1GETySyuj8+OIHHvQsIaaaGQ==",
"dependencies": {
"prosemirror-commands": "^1.0.0",
"prosemirror-dropcursor": "^1.0.0",
"prosemirror-gapcursor": "^1.0.0",
"prosemirror-history": "^1.0.0",
"prosemirror-inputrules": "^1.0.0",
"prosemirror-keymap": "^1.0.0",
"prosemirror-menu": "^1.0.0",
"prosemirror-schema-list": "^1.0.0",
"prosemirror-state": "^1.0.0"
}
},
"node_modules/prosemirror-gapcursor": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/prosemirror-gapcursor/-/prosemirror-gapcursor-1.2.0.tgz",
"integrity": "sha512-yCLy5+0rVqLir/KcHFathQj4Rf8aRHi80FmEfKtM0JmyzvwdomslLzDZ/pX4oFhFKDgjl/WBBBFNqDyNifWg7g==",
"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.2.0",
"resolved": "https://registry.npmjs.org/prosemirror-history/-/prosemirror-history-1.2.0.tgz",
"integrity": "sha512-B9v9xtf4fYbKxQwIr+3wtTDNLDZcmMMmGiI3TAPShnUzvo+Rmv1GiUrsQChY1meetHl7rhML2cppF3FTs7f7UQ==",
"dependencies": {
"prosemirror-state": "^1.2.2",
"prosemirror-transform": "^1.0.0",
"rope-sequence": "^1.3.0"
}
},
"node_modules/prosemirror-inputrules": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/prosemirror-inputrules/-/prosemirror-inputrules-1.1.3.tgz",
"integrity": "sha512-ZaHCLyBtvbyIHv0f5p6boQTIJjlD6o2NPZiEaZWT2DA+j591zS29QQEMT4lBqwcLW3qRSf7ZvoKNbf05YrsStw==",
"dependencies": {
"prosemirror-state": "^1.0.0",
"prosemirror-transform": "^1.0.0"
}
},
"node_modules/prosemirror-keymap": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/prosemirror-keymap/-/prosemirror-keymap-1.1.5.tgz",
"integrity": "sha512-8SZgPH3K+GLsHL2wKuwBD9rxhsbnVBTwpHCO4VUO5GmqUQlxd/2GtBVWTsyLq4Dp3N9nGgPd3+lZFKUDuVp+Vw==",
"dependencies": {
"prosemirror-state": "^1.0.0",
"w3c-keyname": "^2.2.0"
}
},
"node_modules/prosemirror-markdown": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/prosemirror-markdown/-/prosemirror-markdown-1.6.0.tgz",
"integrity": "sha512-y/gRpJIIrNArtkyMax7ypYafb+ZMjddbVHI+AwlcUfCLCCXK57cOmfBMKYVq9kdEKJYVdYHdoyWsVNn1nWLHUg==",
"dependencies": {
"markdown-it": "^10.0.0",
"prosemirror-model": "^1.0.0"
}
},
"node_modules/prosemirror-markdown/node_modules/argparse": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
"dependencies": {
"sprintf-js": "~1.0.2"
}
},
"node_modules/prosemirror-markdown/node_modules/entities": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz",
"integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ=="
},
"node_modules/prosemirror-markdown/node_modules/linkify-it": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz",
"integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==",
"dependencies": {
"uc.micro": "^1.0.1"
}
},
"node_modules/prosemirror-markdown/node_modules/markdown-it": {
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz",
"integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==",
"dependencies": {
"argparse": "^1.0.7",
"entities": "~2.0.0",
"linkify-it": "^2.0.0",
"mdurl": "^1.0.1",
"uc.micro": "^1.0.5"
},
"bin": {
"markdown-it": "bin/markdown-it.js"
}
},
"node_modules/prosemirror-menu": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/prosemirror-menu/-/prosemirror-menu-1.1.4.tgz",
"integrity": "sha512-2ROsji/X9ciDnVSRvSTqFygI34GEdHfQSsK4zBKjPxSEroeiHHcdRMS1ofNIf2zM0Vpp5/YqfpxynElymQkqzg==",
"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.15.0",
"resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.15.0.tgz",
"integrity": "sha512-hQJv7SnIhlAy9ga3lhPPgaufhvCbQB9tHwscJ9E1H1pPHmN8w5V/lURueoYv9Kc3/bpNWoyHa8r3g//m7N0ChQ==",
"dependencies": {
"orderedmap": "^1.1.0"
}
},
"node_modules/prosemirror-schema-basic": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/prosemirror-schema-basic/-/prosemirror-schema-basic-1.1.2.tgz",
"integrity": "sha512-G4q8WflNsR1Q33QAV4MQO0xWrHLOJ+BQcKswGXMy626wlQj6c/1n1v4eC9ns+h2y1r/fJHZEgSZnsNhm9lbrDw==",
"dependencies": {
"prosemirror-model": "^1.2.0"
}
},
"node_modules/prosemirror-schema-list": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/prosemirror-schema-list/-/prosemirror-schema-list-1.1.6.tgz",
"integrity": "sha512-aFGEdaCWmJzouZ8DwedmvSsL50JpRkqhQ6tcpThwJONVVmCgI36LJHtoQ4VGZbusMavaBhXXr33zyD2IVsTlkw==",
"dependencies": {
"prosemirror-model": "^1.0.0",
"prosemirror-transform": "^1.0.0"
}
},
"node_modules/prosemirror-state": {
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/prosemirror-state/-/prosemirror-state-1.3.4.tgz",
"integrity": "sha512-Xkkrpd1y/TQ6HKzN3agsQIGRcLckUMA9u3j207L04mt8ToRgpGeyhbVv0HI7omDORIBHjR29b7AwlATFFf2GLA==",
"dependencies": {
"prosemirror-model": "^1.0.0",
"prosemirror-transform": "^1.0.0"
}
},
"node_modules/prosemirror-transform": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/prosemirror-transform/-/prosemirror-transform-1.3.3.tgz",
"integrity": "sha512-9NLVXy1Sfa2G6qPqhWMkEvwQQMTw7OyTqOZbJaGQWsCeH3hH5Cw+c5eNaLM1Uu75EyKLsEZhJ93XpHJBa6RX8A==",
"dependencies": {
"prosemirror-model": "^1.0.0"
}
},
"node_modules/prosemirror-view": {
"version": "1.23.2",
"resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.23.2.tgz",
"integrity": "sha512-iPgRw6tpcN+KH1yKmSnRmDKsJBVkWLFP6laHcz9rh/n0Ndz7YKKCDldtw6FhHBYoWmZeubbhV/rrQW0VCDG9iw==",
"dependencies": {
"prosemirror-model": "^1.14.3",
"prosemirror-state": "^1.0.0",
"prosemirror-transform": "^1.1.0"
}
},
"node_modules/punycode": { "node_modules/punycode": {
"version": "2.1.1", "version": "2.1.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
@ -1408,6 +1608,11 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/rope-sequence": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/rope-sequence/-/rope-sequence-1.3.2.tgz",
"integrity": "sha512-ku6MFrwEVSVmXLvy3dYph3LAMNS0890K7fabn+0YIRQ2T96T9F4gkFf0vf0WW0JUraNWwGRtInEpH7yO4tbQZg=="
},
"node_modules/sass": { "node_modules/sass": {
"version": "1.43.4", "version": "1.43.4",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.43.4.tgz", "resolved": "https://registry.npmjs.org/sass/-/sass-1.43.4.tgz",
@ -1521,6 +1726,11 @@
"integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==", "integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==",
"dev": true "dev": true
}, },
"node_modules/sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
},
"node_modules/string-width": { "node_modules/string-width": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
@ -1658,6 +1868,11 @@
"spdx-expression-parse": "^3.0.0" "spdx-expression-parse": "^3.0.0"
} }
}, },
"node_modules/w3c-keyname": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.4.tgz",
"integrity": "sha512-tOhfEwEzFLJzf6d1ZPkYfGj+FWhIpBux9ppoP3rlclw3Z0BZv3N7b7030Z1kYth+6rDuAsXUFr+d0VE6Ed1ikw=="
},
"node_modules/which": { "node_modules/which": {
"version": "1.3.1", "version": "1.3.1",
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
@ -1926,6 +2141,11 @@
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
"dev": true "dev": true
}, },
"crelt": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.5.tgz",
"integrity": "sha512-+BO9wPPi+DWTDcNYhr/W90myha8ptzftZT+LwcmUbbok0rcP/fequmFYCw8NMoH7pkAZQzU78b3kYrlua5a9eA=="
},
"cross-spawn": { "cross-spawn": {
"version": "6.0.5", "version": "6.0.5",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
@ -2630,6 +2850,11 @@
"integrity": "sha512-k41FwbcLnlgnFh69f4qdUfvDQ+5vaSDnVPFI/y5XuhKRq97EnVVneO9F1ESVCdiVu4fCS2L8usX3mU331hB7pg==", "integrity": "sha512-k41FwbcLnlgnFh69f4qdUfvDQ+5vaSDnVPFI/y5XuhKRq97EnVVneO9F1ESVCdiVu4fCS2L8usX3mU331hB7pg==",
"dev": true "dev": true
}, },
"orderedmap": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/orderedmap/-/orderedmap-1.1.1.tgz",
"integrity": "sha512-3Ux8um0zXbVacKUkcytc0u3HgC0b0bBLT+I60r2J/En72cI0nZffqrA7Xtf2Hqs27j1g82llR5Mhbd0Z1XW4AQ=="
},
"p-limit": { "p-limit": {
"version": "2.3.0", "version": "2.3.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
@ -2709,6 +2934,188 @@
"integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
"dev": true "dev": true
}, },
"prosemirror-commands": {
"version": "1.1.12",
"resolved": "https://registry.npmjs.org/prosemirror-commands/-/prosemirror-commands-1.1.12.tgz",
"integrity": "sha512-+CrMs3w/ZVPSkR+REg8KL/clyFLv/1+SgY/OMN+CB22Z24j9TZDje72vL36lOZ/E4NeRXuiCcmENcW/vAcG67A==",
"requires": {
"prosemirror-model": "^1.0.0",
"prosemirror-state": "^1.0.0",
"prosemirror-transform": "^1.0.0"
}
},
"prosemirror-dropcursor": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/prosemirror-dropcursor/-/prosemirror-dropcursor-1.4.0.tgz",
"integrity": "sha512-6+YwTjmqDwlA/Dm+5wK67ezgqgjA/MhSDgaNxKUzH97SmeuWFXyLeDRxxOPZeSo7yTxcDGUCWTEjmQZsVBuMrQ==",
"requires": {
"prosemirror-state": "^1.0.0",
"prosemirror-transform": "^1.1.0",
"prosemirror-view": "^1.1.0"
}
},
"prosemirror-example-setup": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/prosemirror-example-setup/-/prosemirror-example-setup-1.1.2.tgz",
"integrity": "sha512-MTpIMyqk08jFnzxeRMCinCEMtVSTUtxKgQBGxfCbVe9C6zIOqp9qZZJz5Ojaad1GETySyuj8+OIHHvQsIaaaGQ==",
"requires": {
"prosemirror-commands": "^1.0.0",
"prosemirror-dropcursor": "^1.0.0",
"prosemirror-gapcursor": "^1.0.0",
"prosemirror-history": "^1.0.0",
"prosemirror-inputrules": "^1.0.0",
"prosemirror-keymap": "^1.0.0",
"prosemirror-menu": "^1.0.0",
"prosemirror-schema-list": "^1.0.0",
"prosemirror-state": "^1.0.0"
}
},
"prosemirror-gapcursor": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/prosemirror-gapcursor/-/prosemirror-gapcursor-1.2.0.tgz",
"integrity": "sha512-yCLy5+0rVqLir/KcHFathQj4Rf8aRHi80FmEfKtM0JmyzvwdomslLzDZ/pX4oFhFKDgjl/WBBBFNqDyNifWg7g==",
"requires": {
"prosemirror-keymap": "^1.0.0",
"prosemirror-model": "^1.0.0",
"prosemirror-state": "^1.0.0",
"prosemirror-view": "^1.0.0"
}
},
"prosemirror-history": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/prosemirror-history/-/prosemirror-history-1.2.0.tgz",
"integrity": "sha512-B9v9xtf4fYbKxQwIr+3wtTDNLDZcmMMmGiI3TAPShnUzvo+Rmv1GiUrsQChY1meetHl7rhML2cppF3FTs7f7UQ==",
"requires": {
"prosemirror-state": "^1.2.2",
"prosemirror-transform": "^1.0.0",
"rope-sequence": "^1.3.0"
}
},
"prosemirror-inputrules": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/prosemirror-inputrules/-/prosemirror-inputrules-1.1.3.tgz",
"integrity": "sha512-ZaHCLyBtvbyIHv0f5p6boQTIJjlD6o2NPZiEaZWT2DA+j591zS29QQEMT4lBqwcLW3qRSf7ZvoKNbf05YrsStw==",
"requires": {
"prosemirror-state": "^1.0.0",
"prosemirror-transform": "^1.0.0"
}
},
"prosemirror-keymap": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/prosemirror-keymap/-/prosemirror-keymap-1.1.5.tgz",
"integrity": "sha512-8SZgPH3K+GLsHL2wKuwBD9rxhsbnVBTwpHCO4VUO5GmqUQlxd/2GtBVWTsyLq4Dp3N9nGgPd3+lZFKUDuVp+Vw==",
"requires": {
"prosemirror-state": "^1.0.0",
"w3c-keyname": "^2.2.0"
}
},
"prosemirror-markdown": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/prosemirror-markdown/-/prosemirror-markdown-1.6.0.tgz",
"integrity": "sha512-y/gRpJIIrNArtkyMax7ypYafb+ZMjddbVHI+AwlcUfCLCCXK57cOmfBMKYVq9kdEKJYVdYHdoyWsVNn1nWLHUg==",
"requires": {
"markdown-it": "^10.0.0",
"prosemirror-model": "^1.0.0"
},
"dependencies": {
"argparse": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
"requires": {
"sprintf-js": "~1.0.2"
}
},
"entities": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz",
"integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ=="
},
"linkify-it": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz",
"integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==",
"requires": {
"uc.micro": "^1.0.1"
}
},
"markdown-it": {
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz",
"integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==",
"requires": {
"argparse": "^1.0.7",
"entities": "~2.0.0",
"linkify-it": "^2.0.0",
"mdurl": "^1.0.1",
"uc.micro": "^1.0.5"
}
}
}
},
"prosemirror-menu": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/prosemirror-menu/-/prosemirror-menu-1.1.4.tgz",
"integrity": "sha512-2ROsji/X9ciDnVSRvSTqFygI34GEdHfQSsK4zBKjPxSEroeiHHcdRMS1ofNIf2zM0Vpp5/YqfpxynElymQkqzg==",
"requires": {
"crelt": "^1.0.0",
"prosemirror-commands": "^1.0.0",
"prosemirror-history": "^1.0.0",
"prosemirror-state": "^1.0.0"
}
},
"prosemirror-model": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.15.0.tgz",
"integrity": "sha512-hQJv7SnIhlAy9ga3lhPPgaufhvCbQB9tHwscJ9E1H1pPHmN8w5V/lURueoYv9Kc3/bpNWoyHa8r3g//m7N0ChQ==",
"requires": {
"orderedmap": "^1.1.0"
}
},
"prosemirror-schema-basic": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/prosemirror-schema-basic/-/prosemirror-schema-basic-1.1.2.tgz",
"integrity": "sha512-G4q8WflNsR1Q33QAV4MQO0xWrHLOJ+BQcKswGXMy626wlQj6c/1n1v4eC9ns+h2y1r/fJHZEgSZnsNhm9lbrDw==",
"requires": {
"prosemirror-model": "^1.2.0"
}
},
"prosemirror-schema-list": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/prosemirror-schema-list/-/prosemirror-schema-list-1.1.6.tgz",
"integrity": "sha512-aFGEdaCWmJzouZ8DwedmvSsL50JpRkqhQ6tcpThwJONVVmCgI36LJHtoQ4VGZbusMavaBhXXr33zyD2IVsTlkw==",
"requires": {
"prosemirror-model": "^1.0.0",
"prosemirror-transform": "^1.0.0"
}
},
"prosemirror-state": {
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/prosemirror-state/-/prosemirror-state-1.3.4.tgz",
"integrity": "sha512-Xkkrpd1y/TQ6HKzN3agsQIGRcLckUMA9u3j207L04mt8ToRgpGeyhbVv0HI7omDORIBHjR29b7AwlATFFf2GLA==",
"requires": {
"prosemirror-model": "^1.0.0",
"prosemirror-transform": "^1.0.0"
}
},
"prosemirror-transform": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/prosemirror-transform/-/prosemirror-transform-1.3.3.tgz",
"integrity": "sha512-9NLVXy1Sfa2G6qPqhWMkEvwQQMTw7OyTqOZbJaGQWsCeH3hH5Cw+c5eNaLM1Uu75EyKLsEZhJ93XpHJBa6RX8A==",
"requires": {
"prosemirror-model": "^1.0.0"
}
},
"prosemirror-view": {
"version": "1.23.2",
"resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.23.2.tgz",
"integrity": "sha512-iPgRw6tpcN+KH1yKmSnRmDKsJBVkWLFP6laHcz9rh/n0Ndz7YKKCDldtw6FhHBYoWmZeubbhV/rrQW0VCDG9iw==",
"requires": {
"prosemirror-model": "^1.14.3",
"prosemirror-state": "^1.0.0",
"prosemirror-transform": "^1.1.0"
}
},
"punycode": { "punycode": {
"version": "2.1.1", "version": "2.1.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
@ -2757,6 +3164,11 @@
"path-parse": "^1.0.6" "path-parse": "^1.0.6"
} }
}, },
"rope-sequence": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/rope-sequence/-/rope-sequence-1.3.2.tgz",
"integrity": "sha512-ku6MFrwEVSVmXLvy3dYph3LAMNS0890K7fabn+0YIRQ2T96T9F4gkFf0vf0WW0JUraNWwGRtInEpH7yO4tbQZg=="
},
"sass": { "sass": {
"version": "1.43.4", "version": "1.43.4",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.43.4.tgz", "resolved": "https://registry.npmjs.org/sass/-/sass-1.43.4.tgz",
@ -2852,6 +3264,11 @@
"integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==", "integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==",
"dev": true "dev": true
}, },
"sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
},
"string-width": { "string-width": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
@ -2959,6 +3376,11 @@
"spdx-expression-parse": "^3.0.0" "spdx-expression-parse": "^3.0.0"
} }
}, },
"w3c-keyname": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.4.tgz",
"integrity": "sha512-tOhfEwEzFLJzf6d1ZPkYfGj+FWhIpBux9ppoP3rlclw3Z0BZv3N7b7030Z1kYth+6rDuAsXUFr+d0VE6Ed1ikw=="
},
"which": { "which": {
"version": "1.3.1", "version": "1.3.1",
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",

View File

@ -7,6 +7,8 @@
"build:js:dev": "esbuild --bundle ./resources/js/index.js --outfile=public/dist/app.js --sourcemap --target=es2019 --main-fields=module,main", "build:js:dev": "esbuild --bundle ./resources/js/index.js --outfile=public/dist/app.js --sourcemap --target=es2019 --main-fields=module,main",
"build:js:watch": "chokidar --initial \"./resources/**/*.js\" -c \"npm run build:js:dev\"", "build:js:watch": "chokidar --initial \"./resources/**/*.js\" -c \"npm run build:js:dev\"",
"build:js:production": "NODE_ENV=production esbuild --bundle ./resources/js/index.js --outfile=public/dist/app.js --sourcemap --target=es2019 --main-fields=module,main --minify", "build:js:production": "NODE_ENV=production esbuild --bundle ./resources/js/index.js --outfile=public/dist/app.js --sourcemap --target=es2019 --main-fields=module,main --minify",
"build:js:editor:dev": "esbuild --bundle ./resources/js/editor.js --outfile=public/dist/editor.js --sourcemap --target=es2019 --main-fields=module,main",
"build:js:editor:watch": "chokidar --initial \"./resources/js/editor.js\" \"./resources/js/editor/*.js\" -c \"npm run build:js:editor:dev\"",
"build": "npm-run-all --parallel build:*:dev", "build": "npm-run-all --parallel build:*:dev",
"production": "npm-run-all --parallel build:*:production", "production": "npm-run-all --parallel build:*:production",
"dev": "npm-run-all --parallel watch livereload", "dev": "npm-run-all --parallel watch livereload",
@ -28,6 +30,13 @@
"dropzone": "^5.9.3", "dropzone": "^5.9.3",
"markdown-it": "^12.2.0", "markdown-it": "^12.2.0",
"markdown-it-task-lists": "^2.1.1", "markdown-it-task-lists": "^2.1.1",
"prosemirror-example-setup": "^1.1.2",
"prosemirror-markdown": "^1.6.0",
"prosemirror-model": "^1.15.0",
"prosemirror-schema-basic": "^1.1.2",
"prosemirror-schema-list": "^1.1.6",
"prosemirror-state": "^1.3.4",
"prosemirror-view": "^1.23.2",
"sortablejs": "^1.14.0" "sortablejs": "^1.14.0"
} }
} }

74
resources/js/editor.js Normal file
View File

@ -0,0 +1,74 @@
import {EditorState} from "prosemirror-state";
import {EditorView} from "prosemirror-view";
import {exampleSetup} from "prosemirror-example-setup";
import {defaultMarkdownParser,
defaultMarkdownSerializer} from "prosemirror-markdown";
import {DOMParser, DOMSerializer} from "prosemirror-model";
import {schema} from "./editor/schema";
class MarkdownView {
constructor(target, content) {
// Build DOM from content
const renderDoc = document.implementation.createHTMLDocument();
renderDoc.body.innerHTML = content;
const htmlDoc = DOMParser.fromSchema(schema).parse(renderDoc.body);
const markdown = defaultMarkdownSerializer.serialize(htmlDoc);
this.textarea = target.appendChild(document.createElement("textarea"))
this.textarea.value = markdown;
}
get content() {
const markdown = this.textarea.value;
const doc = defaultMarkdownParser.parse(markdown);
const fragment = DOMSerializer.fromSchema(schema).serializeFragment(doc.content);
const renderDoc = document.implementation.createHTMLDocument();
renderDoc.body.appendChild(fragment);
return renderDoc.body.innerHTML;
}
focus() { this.textarea.focus() }
destroy() { this.textarea.remove() }
}
class ProseMirrorView {
constructor(target, content) {
// Build DOM from content
const renderDoc = document.implementation.createHTMLDocument();
renderDoc.body.innerHTML = content;
this.view = new EditorView(target, {
state: EditorState.create({
doc: DOMParser.fromSchema(schema).parse(renderDoc.body),
plugins: exampleSetup({schema})
})
});
}
get content() {
const fragment = DOMSerializer.fromSchema(schema).serializeFragment(this.view.state.doc.content);
const renderDoc = document.implementation.createHTMLDocument();
renderDoc.body.appendChild(fragment);
return renderDoc.body.innerHTML;
}
focus() { this.view.focus() }
destroy() { this.view.destroy() }
}
const place = document.querySelector("#editor");
let view = new ProseMirrorView(place, document.getElementById('content').innerHTML);
const markdownToggle = document.getElementById('markdown-toggle');
markdownToggle.addEventListener('change', event => {
const View = markdownToggle.checked ? MarkdownView : ProseMirrorView;
if (view instanceof View) return
const content = view.content
console.log(content);
view.destroy()
view = new View(place, content)
view.focus()
});

View File

@ -0,0 +1,10 @@
import {Schema} from "prosemirror-model";
import {schema as basicSchema} from "prosemirror-schema-basic";
import {addListNodes} from "prosemirror-schema-list";
const bookstackSchema = new Schema({
nodes: addListNodes(basicSchema.spec.nodes, "paragraph block*", "block"),
marks: basicSchema.spec.marks
})
export {bookstackSchema as schema};

View File

@ -0,0 +1,34 @@
@extends('layouts.simple')
@section('head')
<link rel=stylesheet href="https://prosemirror.net/css/editor.css">
@endsection
@section('body')
<div class="container">
<div>
<input id="markdown-toggle" type="checkbox">
</div>
<div id=editor style="margin-bottom: 23px"></div>
<div id="content" style="display: none;">
<h2>This is an editable block</h2>
<p>Lorem ipsum dolor sit amet, <strong>consectetur adipisicing</strong> elit. Asperiores?</p>
<p><img src="/user_avatar.png" alt="Logo"></p>
<ul>
<li>Item A</li>
<li>Item B</li>
<li>Item C</li>
</ul>
<p>Lorem ipsum dolor sit amet.</p>
</div>
</div>
@endsection
@section('scripts')
<script src="{{ versioned_asset('dist/editor.js') }}" nonce="{{ $cspNonce }}"></script>
@stop

View File

@ -38,6 +38,8 @@ use Illuminate\View\Middleware\ShareErrorsFromSession;
Route::get('/status', [StatusController::class, 'show']); Route::get('/status', [StatusController::class, 'show']);
Route::get('/robots.txt', [HomeController::class, 'robots']); Route::get('/robots.txt', [HomeController::class, 'robots']);
Route::view('/editor-test', 'editor-test');
// Authenticated routes... // Authenticated routes...
Route::middleware('auth')->group(function () { Route::middleware('auth')->group(function () {