Nature's Particle Manager

    TypeScript icon, indicating that this package has built-in type declarations

    0.0.11 • Public • Published

    prosemirror-dev-toolkit version package minified size package size

    This is a rewrite of prosemirror-dev-tools which I'm a big fan of, yet have felt could use some improvements. Since it didn't seem that actively maintained anymore and also because I wanted to remove the hard dependency to React, use TypeScript and make the whole thing smaller, I took it to my own hands to rewrite it in Svelte.

    Unlike React, Svelte compiles directly to JS without having to bundle a runtime which should make the library smaller to use in projects that don't use React. I also pruned some of the extra dependencies by using out-of-the-box Svelte features and have experimented making the library injectable as a stand-alone script.


    npm i prosemirror-dev-toolkit

    And use it eg:

    import { applyDevTools } from 'prosemirror-dev-toolkit'
    import { EditorState } from 'prosemirror-state'
    import { EditorView } from 'prosemirror-view'
    import { schema } from 'prosemirror-schema-basic'
    import { exampleSetup } from 'prosemirror-example-setup'
    const view = new EditorView(document.querySelector('#editor') as HTMLElement, {
      state: EditorState.create({
        doc: schema.nodes.doc.createAndFill(),
        plugins: exampleSetup({ schema })

    Code sandbox


    type ButtonPosition = 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left'
    interface DevToolsOpts {
      devToolsExpanded?: boolean
      buttonPosition?: ButtonPosition
    declare function applyDevTools(view: EditorView, opts?: DevToolsOpts): void
    declare function removeDevTools(): void
    declare global {
      interface Window {
        applyDevTools: typeof applyDevTools;
        editorView?: EditorView;
        _node?: { node: PMNode, pos: number };
        _doc?: {
          [key: string]: any;
        _trs?: Transaction[];
        _plugin?: [Plugin | undefined, unknown];
    export { applyDevTools, removeDevTools, ButtonPosition, DevToolsOpts }

    I am adding properties to the global Window interface which may or may not that convenient. From my perspective I don't have to ts-ignore those assignments but if you use those properties in your repos you'll have to obey the types or receive rather weird errors (that may take a moment to figure out).


    As was in the old tools, prosemirror-dev-toolkit consists of 6 tabs which interact with the PM editor in various ways. Basically what happens is dev-toolkit injects itself into the DOM, visible as the rounded button in the bottom right corner, and then sets the dispatchTransaction prop of the EditorView to be able to track transactions.

    In addition it can persist snapshots and hydrate them which I enhanced by adding export/import from JSON as well as ensuring the functionality doesn't break with Yjs. In the old dev-tools there was a node picker to inspect PM nodes that I have not had time to remake.

    For quick live editor instance debugging I have added a script to inject the dev-toolkit directly from CDN: inject.js Not 100% bulletproof but works in most cases. Improvements welcome. Might use it to turn this into a Chrome extension.


    State tab

    Shows the current toJSON'd state.doc as well as the selection, augmented by a few additional properties, active marks and a simple summary of the document. These tree views were implemented in the original with react-json-tree library which although ported to Svelte (svelte-json-tree) felt a little complex and difficult to customize. Instead, I wrote a simple recursive component and then rolled it out as a separate Svelte library:


    History tab

    History tab shows the last dispatched transaction with a diff of the changed content, diff of the changed selection, toDOM'd document slice between the selection start and end and the actual transaction at the bottom.

    Copying the old diffing logic was perhaps the most annoying feature to implement as it required me to wrap my head around the jsondiffpatch's delta format and figure out how to rewrite it in Svelte. Somewhat interesting topic, certainly, but quite tedious. I changed the original colors to a perhaps more distinct palette and added the transaction to the history entry as well. I've found it quite useful.

    I added some new features to the trees such as 'log' and 'copy' buttons which log the node to window (eg into _node variable) or add it to your clipboard.

    You can hydrate the doc from a transaction by double-clicking it. I have thought of adding import/export of transaction history to allow replaying them but haven't had time for it.


    Plugins tab

    Shows the current plugins and their states. This is mostly the same as in the old tools but I added some convenience buttons to for example log the plugin to a _plugin object that you can manipulate from the console. Handy for inspecting the plugin editor props which are not visible from the plugin state.

    As a side-note, I'm sure I have not covered all possible object types in svelte-tree-view beyond the common Objects/Arrays/Maps/Sets. Make an issue or PR if something's weird.


    Schema tab

    Shows the current schema's nodes and marks. Same as in the old tools but I added circular node detection to make the recursion a little lighter. Not strictly needed as all the nodes are uncollapsed and can't be auto-expanded but hey, it's there.


    Structure tab

    A bit more complicated tab it shows the document in a neat block view with a side panel to inspect the node contents. Auto-expands the content whenever it's within reasonable size (less than 50 children). You can double click nodes to scroll into them. Thought about allowing selecting and deleting nodes directly from the DocView.


    Snapshots tab

    Shows the stored snapshots (toJSON'd topNode eg "doc") in localStorage. The changes I've made are switching to date strings instead of unix timestamps for default names. Then, you can double-click the snapshot to edit its name. 'Show' button replaces the current doc with the snapshot doc, allowing you to revert it with 'Hide'. 'Restore' does a one-way replacement of the doc with the snapshot. And well I say one-way but since I don't erase the actual PM history you can Ctrl-z your way out of it.

    'Export' toJSONs and downloads the snapshot. You have to now double-click 'Delete' to prevent occasional misclicks. There's also a new 'Import snapshot' button above the main panel to replace the doc with exported snapshot.

    How to run locally

    1. yarn
    2. yarn start

    Should open a React app at http://localhost:3300/prosemirror-dev-toolkit/


    To run the end-to-end tests you must launch the example app (yarn start) and then run yarn test:e2e in the core directory. I kinda skipped the unit tests since Jest was just too much trouble to work with although Cypress has its rough edges too. I hope I have covered at least most of the basic cases to avoid sudden regressions.


    npm i prosemirror-dev-toolkit

    DownloadsWeekly Downloads






    Unpacked Size

    2.36 MB

    Total Files


    Last publish


    • tekk