Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
get plugins() {
return [
new Plugin({
state: {
init(_, { doc }) {
return getDecorations(doc)
},
apply(tr, set) {
// TODO: find way to cache decorations
// see: https://discuss.prosemirror.net/t/how-to-update-multiple-inline-decorations-on-node-change/1493
if (tr.docChanged) {
return getDecorations(tr.doc)
}
return set.map(tr.mapping, tr.doc)
},
},
props: {
decorations(state) {
return this.getState(state)
get plugins() {
return [
new Plugin({
props: {
transformPastedText(text) {
return text.trim()
},
transformPastedHTML(html) {
html = html
// remove all tags with "space only"
.replace(/<[a-z-]+>[\s]+<\/[a-z-]+>/gim, '')
// remove all iframes
.replace(/(]*)(>)[^>]*\/*>/gim, '')
.replace(/[\n]{3,}/gim, '\n\n')
.replace(/(\r\n|\n\r|\r|\n)/g, '<br>$1')
// replace all p tags with line breaks (and spaces) only by single linebreaks
// limit linebreaks to max 2 (equivalent to html "br" linebreak)
.replace(/(<br>\s*){2,}/gim, '<br>')
get plugins() {
return [
new Plugin({
state: {
init() {
return DecorationSet.empty
},
apply: (tr, old) => {
if (this._updating
|| this.options.searching
|| (tr.docChanged && this.options.alwaysSearch)
) {
return this.createDeco(tr.doc)
}
if (tr.docChanged) {
return old.map(tr.mapping, tr.doc)
}
get plugins() {
return [
new Plugin({
props: {
handleDOMEvents: {
drop(view, event) {
const hasFiles = event.dataTransfer
&& event.dataTransfer.files
&& event.dataTransfer.files.length
if (!hasFiles) {
return
}
const images = Array
.from(event.dataTransfer.files)
.filter(file => (/image/i).test(file.type))
if (images.length === 0) {
get plugins() {
return [
new Plugin({
props: {
decorations: ({ doc, plugins, selection }) => {
const editablePlugin = plugins.find(plugin => plugin.key.startsWith('editable$'))
const editable = editablePlugin.props.editable()
const active = editable || !this.options.showOnlyWhenEditable
const { anchor } = selection
const decorations = []
const isEditorEmpty = doc.textContent.length === 0
if (!active) {
return false
}
doc.descendants((node, pos) => {
const hasAnchor = anchor >= pos && anchor <= (pos + node.nodeSize)
const isNodeEmpty = node.content.size === 0
get plugins() {
if (!this.options.openOnClick) {
return []
}
return [
new Plugin({
props: {
handleClick: (view, pos, event) => {
const { schema } = view.state
const attrs = getMarkAttrs(view.state, schema.marks.link)
if (attrs.href && event.target instanceof HTMLAnchorElement) {
event.stopPropagation()
window.open(attrs.href)
}
},
},
}),
]
}
get plugins() {
const plugin = new PluginKey(this.name)
const disabledNodes = Object.entries(this.editor.schema.nodes)
.map(([, value]) => value)
.filter(node => this.options.notAfter.includes(node.name))
return [
new Plugin({
key: plugin,
view: () => ({
update: view => {
const { state } = view
const insertNodeAtEnd = plugin.getState(state)
if (!insertNodeAtEnd) {
return
}
const { doc, schema, tr } = state
const type = schema.nodes[this.options.node]
const transaction = tr.insert(doc.content.size, type.create())
view.dispatch(transaction)
},
}),
get plugins() {
return [
new Plugin({
props: {
handleClick(view, pos) {
const { schema, doc, tr } = view.state;
const range = getMarkRange(doc.resolve(pos), schema.marks.link);
if (!range) {
return;
}
const $start = doc.resolve(range.from);
const $end = doc.resolve(range.to);
const transaction = tr.setSelection(new TextSelection($start, $end));
view.dispatch(transaction);
}
}
get plugins() {
return [
new Plugin({
state: {
init: (_, { doc }) => this.getDecorations({ doc, selections: [] }),
apply: (transaction, decorationSet) => {
const { mapping, doc } = transaction
const selections = transaction.getMeta('selections')
if (selections) {
return this.getDecorations({ doc, selections })
}
return decorationSet.map(mapping, doc)
},
},
props: {
decorations(state) {
return this.getState(state)