How to add plugin into editor? For ex. tables


#1

Hi, agian me with probably noob question. Well I “configured” my workplace and succesfully somehow added editor with markdown preview but now I stuck trying to add another plugin. My code looks like this

import { EditorView } from 'prosemirror-view';
import { EditorState } from 'prosemirror-state';
import {
  schema,
  defaultMarkdownParser,
  defaultMarkdownSerializer
} from 'prosemirror-markdown';
import { exampleSetup } from 'prosemirror-example-setup';

class MarkdownView {
  constructor(target, content) {
this.textarea = target.appendChild(document.createElement('textarea'));
if (content == undefined) {
  this.textarea.value = '';
} else {
  this.textarea.value = content;
}
  }
  get content() {
return this.textarea.value;
  }
  focus() {
this.textarea.focus();
  }
  destroy() {
this.textarea.remove();
  }
}

class ProseMirrorView {
  constructor(target, content) {
this.view = new EditorView(target, {
  state: EditorState.create({
    doc: defaultMarkdownParser.parse(content),
    plugins: exampleSetup({ schema })
  })
});
  }

  get content() {
return defaultMarkdownSerializer.serialize(this.view.state.doc);
  }
  focus() {
this.view.focus();
  }
  destroy() {
this.view.destroy();
  }
}

let place = document.querySelector('#editor');
let view = new MarkdownView(place, document.querySelector('#content').value);

document.querySelectorAll('input[type=radio]').forEach(button => {
  button.addEventListener('change', () => {
if (!button.checked) return;
let View = button.value == 'markdown' ? MarkdownView : ProseMirrorView;
if (view instanceof View) return;
let content = view.content;
view.destroy();
view = new View(place, content);
view.focus();
  });
});

I tried to add table plugin into “exampleSetup plugins” but got only errors. Didn’t find anything about extending editor to new functionality with those all npm package.


#2

Given that you didn’t tell us how you tried that, it’s hard to say what you did wrong.


#3

I imported tables module at top of “prosemirror-example-setup/index.js” var prosemirrorTables = require('prosemirror-tables'); And at bottom (in function “exampleSetup”) I tried to add options to the plugins that this module gives, like:

function exampleSetup(options) {
  var plugins = [
buildInputRules(options.schema),
prosemirrorKeymap.keymap(buildKeymap(options.schema, options.mapKeys)),
prosemirrorKeymap.keymap(prosemirrorCommands.baseKeymap),
prosemirrorDropcursor.dropCursor(),
prosemirrorGapcursor.gapCursor(),
prosemirrorTables.tableNodes(),
prosemirrorTables.toggleHeaderCell()
// ETC
  ];

And the question is: Is this is a way how to add new plugin/module into editor? I mean by editing the code as I do. Or there is a other way to add a plugin/module? The examples on site didn’t help tho


#4

The usual way to use extra plugins with example-setup would be to concat them to the array returned by that, when calling EditorState.create.


#5

Got it working (there is a “table” bar in menu) with this code

    import { EditorView } from 'prosemirror-view';
import { EditorState } from 'prosemirror-state';
import {
  schema,
  defaultMarkdownParser,
  defaultMarkdownSerializer
} from 'prosemirror-markdown';
import { exampleSetup } from 'prosemirror-example-setup';
import {
  addColumnAfter,
  addColumnBefore,
  deleteColumn,
  addRowAfter,
  addRowBefore,
  deleteRow,
  mergeCells,
  splitCell,
  setCellAttr,
  toggleHeaderRow,
  toggleHeaderColumn,
  toggleHeaderCell,
  deleteTable
} from 'prosemirror-tables';
import { MenuItem, Dropdown } from 'prosemirror-menu';
import { buildMenuItems } from 'prosemirror-example-setup';

let menu = buildMenuItems(schema).fullMenu;
function item(label, cmd) {
  return new MenuItem({ label, active: cmd, run: cmd });
}

let tableMenu = [
  item('Insert column before', addColumnBefore),
  item('Insert column after', addColumnAfter),
  item('Delete column', deleteColumn),
  item('Insert row before', addRowBefore),
  item('Insert row after', addRowAfter),
  item('Delete row', deleteRow),
  item('Delete table', deleteTable),
  item('Merge cells', mergeCells),
  item('Split cell', splitCell),
  item('Toggle header column', toggleHeaderColumn),
  item('Toggle header row', toggleHeaderRow),
  item('Toggle header cells', toggleHeaderCell),
  item('Make cell green', setCellAttr('background', '#dfd')),
  item('Make cell not-green', setCellAttr('background', null))
];
menu.splice(2, 0, [new Dropdown(tableMenu, { label: 'Table' })]);

class MarkdownView {
  constructor(target, content) {
    this.textarea = target.appendChild(document.createElement('textarea'));
    if (content == undefined) {
      this.textarea.value = '';
    } else {
      this.textarea.value = content;
    }
  }
  get content() {
    return this.textarea.value;
  }
  focus() {
    this.textarea.focus();
  }
  destroy() {
    this.textarea.remove();
  }
}

class ProseMirrorView {
  constructor(target, content) {
    this.view = new EditorView(target, {
      state: EditorState.create({
        doc: defaultMarkdownParser.parse(content),
        plugins: exampleSetup({ schema, menuContent: menu })
      })
    });
  }

  get content() {
    return defaultMarkdownSerializer.serialize(this.view.state.doc);
  }
  focus() {
    this.view.focus();
  }
  destroy() {
    this.view.destroy();
  }
}

let place = document.querySelector('#editor');
let view = new MarkdownView(place, document.querySelector('#content').value);

document.querySelectorAll('input[type=radio]').forEach(button => {
  button.addEventListener('change', () => {
    if (!button.checked) return;
    let View = button.value == 'markdown' ? MarkdownView : ProseMirrorView;
    if (view instanceof View) return;
    let content = view.content;
    view.destroy();
    view = new View(place, content);
    view.focus();
  });
});

I got all option to play with tables BUT no option to insert/create table. What I’m doing wrong? Is this a even correct?