mirror of
https://github.com/docmost/docmost.git
synced 2025-11-26 02:21:08 +10:00
* refactor imports - WIP * Add readstream * WIP * fix attachmentId render * fix attachmentId render * turndown video tag * feat: add stream upload support and improve file handling - Add stream upload functionality to storage drivers\n- Improve ZIP file extraction with better encoding handling\n- Fix attachment ID rendering issues\n- Add AWS S3 upload stream support\n- Update dependencies for better compatibility * WIP * notion formatter * move embed parser to editor-ext package * import embeds * utility files * cleanup * Switch from happy-dom to cheerio * Refine code * WIP * bug fixes and UI * sync * WIP * sync * keep import modal mounted * Show modal during upload * WIP * WIP
75 lines
2.1 KiB
TypeScript
75 lines
2.1 KiB
TypeScript
import { Extension } from '@tiptap/core'
|
|
import { PluginKey, Plugin } from '@tiptap/pm/state';
|
|
|
|
export interface TrailingNodeExtensionOptions {
|
|
node: string,
|
|
notAfter: string[],
|
|
}
|
|
|
|
function nodeEqualsType({ types, node }: { types: any, node: any }) {
|
|
return (Array.isArray(types) && types.includes(node.type)) || node.type === types
|
|
}
|
|
|
|
// @ts-ignore
|
|
/**
|
|
* Extension based on:
|
|
* - https://github.com/ueberdosis/tiptap/blob/v1/packages/tiptap-extensions/src/extensions/TrailingNode.js
|
|
* - https://github.com/remirror/remirror/blob/e0f1bec4a1e8073ce8f5500d62193e52321155b9/packages/prosemirror-trailing-node/src/trailing-node-plugin.ts
|
|
*/
|
|
export const TrailingNode = Extension.create<TrailingNodeExtensionOptions>({
|
|
name: 'trailingNode',
|
|
|
|
addOptions() {
|
|
return {
|
|
node: 'paragraph',
|
|
notAfter: [
|
|
'paragraph',
|
|
],
|
|
};
|
|
},
|
|
|
|
addProseMirrorPlugins() {
|
|
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,
|
|
appendTransaction: (_, __, state) => {
|
|
const { doc, tr, schema } = state;
|
|
const shouldInsertNodeAtEnd = plugin.getState(state);
|
|
const endPosition = doc.content.size;
|
|
const type = schema.nodes[this.options.node]
|
|
|
|
if (!shouldInsertNodeAtEnd) {
|
|
return;
|
|
}
|
|
|
|
return tr.insert(endPosition, type.create());
|
|
},
|
|
state: {
|
|
init: (_, state) => {
|
|
try {
|
|
const lastNode = state.tr.doc.lastChild
|
|
return !nodeEqualsType({ node: lastNode, types: disabledNodes })
|
|
} catch (err){
|
|
console.log(err)
|
|
}
|
|
return true;
|
|
},
|
|
apply: (tr, value) => {
|
|
if (!tr.docChanged) {
|
|
return value
|
|
}
|
|
|
|
const lastNode = tr.doc.lastChild
|
|
return !nodeEqualsType({ node: lastNode, types: disabledNodes })
|
|
},
|
|
},
|
|
}),
|
|
]
|
|
}
|
|
})
|