]> BookStack Code Mirror - bookstack/commitdiff
Started playing with prosemirror
authorDan Brown <redacted>
Fri, 26 Nov 2021 15:05:06 +0000 (15:05 +0000)
committerDan Brown <redacted>
Fri, 7 Jan 2022 13:36:52 +0000 (13:36 +0000)
- 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.

package-lock.json
package.json
resources/js/editor.js [new file with mode: 0644]
resources/js/editor/schema.js [new file with mode: 0644]
resources/views/editor-test.blade.php [new file with mode: 0644]
routes/web.php

index f2013e928114207fda36a9c3d2c23e872451901a..fdafe80c667cebeb54806ab517ce11b6bb4e1388 100644 (file)
         "dropzone": "^5.9.3",
         "markdown-it": "^12.2.0",
         "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"
       },
       "devDependencies": {
       "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
       "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": {
       "version": "6.0.5",
       "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
       "integrity": "sha512-k41FwbcLnlgnFh69f4qdUfvDQ+5vaSDnVPFI/y5XuhKRq97EnVVneO9F1ESVCdiVu4fCS2L8usX3mU331hB7pg==",
       "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": {
       "version": "2.3.0",
       "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
         "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": {
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
         "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": {
       "version": "1.43.4",
       "resolved": "https://registry.npmjs.org/sass/-/sass-1.43.4.tgz",
       "integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==",
       "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": {
       "version": "3.1.0",
       "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
         "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": {
       "version": "1.3.1",
       "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
       "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
       "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": {
       "version": "6.0.5",
       "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
       "integrity": "sha512-k41FwbcLnlgnFh69f4qdUfvDQ+5vaSDnVPFI/y5XuhKRq97EnVVneO9F1ESVCdiVu4fCS2L8usX3mU331hB7pg==",
       "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": {
       "version": "2.3.0",
       "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
       "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
       "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": {
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
         "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": {
       "version": "1.43.4",
       "resolved": "https://registry.npmjs.org/sass/-/sass-1.43.4.tgz",
       "integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==",
       "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": {
       "version": "3.1.0",
       "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
         "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": {
       "version": "1.3.1",
       "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
index fe3837a863e16f2c91df20f200a66e0fc259bfd7..cb72c2e72987f5b3563cf0c8260b905efeca10f6 100644 (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: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: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",
     "production": "npm-run-all --parallel build:*:production",
     "dev": "npm-run-all --parallel watch livereload",
     "dropzone": "^5.9.3",
     "markdown-it": "^12.2.0",
     "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"
   }
 }
diff --git a/resources/js/editor.js b/resources/js/editor.js
new file mode 100644 (file)
index 0000000..6b4aff1
--- /dev/null
@@ -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()
+});
\ No newline at end of file
diff --git a/resources/js/editor/schema.js b/resources/js/editor/schema.js
new file mode 100644 (file)
index 0000000..540db57
--- /dev/null
@@ -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};
\ No newline at end of file
diff --git a/resources/views/editor-test.blade.php b/resources/views/editor-test.blade.php
new file mode 100644 (file)
index 0000000..dd740ab
--- /dev/null
@@ -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
\ No newline at end of file
index 73cc3dc66c20522a160eb470c4020b79de5971c8..32074148b6251f6e07741f05524a94543f190ae9 100644 (file)
@@ -38,6 +38,8 @@ use Illuminate\View\Middleware\ShareErrorsFromSession;
 Route::get('/status', [StatusController::class, 'show']);
 Route::get('/robots.txt', [HomeController::class, 'robots']);
 
+Route::view('/editor-test', 'editor-test');
+
 // Authenticated routes...
 Route::middleware('auth')->group(function () {