mirror of https://github.com/fantasticit/think.git
client: tableOfContent markdown support
parent
42e05bec0f
commit
c37182f0a8
|
@ -1,4 +1,6 @@
|
|||
export const safeJSONParse = (str, defaultValue = {}) => {
|
||||
if (typeof str === 'object') return str;
|
||||
|
||||
try {
|
||||
return JSON.parse(str);
|
||||
} catch (e) {
|
||||
|
|
|
@ -195,20 +195,29 @@ export const Paste = Extension.create<IPasteOptions>({
|
|||
return false;
|
||||
},
|
||||
clipboardTextSerializer: (slice) => {
|
||||
const isText = isPureText(slice.content.toJSON());
|
||||
const json = slice.content.toJSON();
|
||||
const isSelectAll = slice.openStart === slice.openEnd && slice.openEnd === 0;
|
||||
|
||||
if (isText) {
|
||||
return slice.content.textBetween(0, slice.content.size, '\n\n');
|
||||
}
|
||||
if (typeof json === 'object' || isSelectAll) {
|
||||
return extensionThis.options.prosemirrorToMarkdown({
|
||||
content: slice.content,
|
||||
});
|
||||
} else {
|
||||
const isText = isPureText(json) && !isSelectAll;
|
||||
|
||||
const doc = slice.content;
|
||||
if (!doc) {
|
||||
return '';
|
||||
if (isText) {
|
||||
return slice.content.textBetween(0, slice.content.size, '\n\n');
|
||||
}
|
||||
|
||||
const doc = slice.content;
|
||||
if (!doc) {
|
||||
return '';
|
||||
}
|
||||
const content = extensionThis.options.prosemirrorToMarkdown({
|
||||
content: doc,
|
||||
});
|
||||
return content;
|
||||
}
|
||||
const content = extensionThis.options.prosemirrorToMarkdown({
|
||||
content: doc,
|
||||
});
|
||||
return content;
|
||||
},
|
||||
},
|
||||
}),
|
||||
|
|
|
@ -51,8 +51,6 @@ export const TableOfContentsWrapper = ({ editor }) => {
|
|||
setItems(headings);
|
||||
}, [editor]);
|
||||
|
||||
useEffect(handleUpdate, [handleUpdate]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!editor) {
|
||||
return null;
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
import { Node } from './node';
|
||||
|
||||
export class TableOfContents extends Node {
|
||||
type = 'tableOfContents';
|
||||
|
||||
matching() {
|
||||
return this.DOMNode.nodeName === 'DIV' && this.DOMNode.classList.contains('tableOfContents');
|
||||
}
|
||||
}
|
|
@ -34,6 +34,7 @@ import { Status } from './nodes/status';
|
|||
import { Table } from './nodes/table';
|
||||
import { TableCell } from './nodes/table-cell';
|
||||
import { TableHeader } from './nodes/table-header';
|
||||
import { TableOfContents } from './nodes/table-of-contents';
|
||||
import { TableRow } from './nodes/table-row';
|
||||
// 列表
|
||||
import { TaskList } from './nodes/task-list';
|
||||
|
@ -82,6 +83,7 @@ export class Renderer {
|
|||
TableHeader,
|
||||
TableRow,
|
||||
TableCell,
|
||||
TableOfContents,
|
||||
|
||||
// 列表
|
||||
TaskList,
|
||||
|
|
|
@ -32,6 +32,7 @@ export const markdownToProsemirror = ({ schema, content, hasTitle }) => {
|
|||
|
||||
const parser = new DOMParser();
|
||||
const { body } = parser.parseFromString(extractImage(html), 'text/html');
|
||||
|
||||
body.append(document.createComment(content));
|
||||
const node = htmlToPromsemirror(body, !hasTitle);
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ const markdownIframe = createMarkdownContainer('iframe');
|
|||
const markdownMention = createMarkdownContainer('mention');
|
||||
const markdownMind = createMarkdownContainer('mind');
|
||||
const markdownFlow = createMarkdownContainer('flow');
|
||||
const markdownTableOfContents = createMarkdownContainer('tableOfContents');
|
||||
|
||||
const markdown = markdownit('commonmark')
|
||||
.enable('strikethrough')
|
||||
|
@ -44,7 +45,8 @@ const markdown = markdownit('commonmark')
|
|||
.use(markdownMind)
|
||||
.use(markdownDocumentReference)
|
||||
.use(markdownDocumentChildren)
|
||||
.use(markdownFlow);
|
||||
.use(markdownFlow)
|
||||
.use(markdownTableOfContents);
|
||||
|
||||
export const markdownToHTML = (rawMarkdown) => {
|
||||
return sanitize(markdown.render(rawMarkdown), {});
|
||||
|
|
|
@ -31,6 +31,7 @@ import { Superscript } from 'tiptap/core/extensions/superscript';
|
|||
import { Table } from 'tiptap/core/extensions/table';
|
||||
import { TableCell } from 'tiptap/core/extensions/table-cell';
|
||||
import { TableHeader } from 'tiptap/core/extensions/table-header';
|
||||
import { TableOfContents } from 'tiptap/core/extensions/table-of-contents';
|
||||
import { TableRow } from 'tiptap/core/extensions/table-row';
|
||||
import { TaskItem } from 'tiptap/core/extensions/task-item';
|
||||
import { TaskList } from 'tiptap/core/extensions/task-list';
|
||||
|
@ -147,6 +148,7 @@ const SerializerConfig = {
|
|||
[Table.name]: renderTable,
|
||||
[TableCell.name]: renderTableCell,
|
||||
[TableHeader.name]: renderTableCell,
|
||||
[TableOfContents.name]: renderCustomContainer('tableOfContents'),
|
||||
[TableRow.name]: renderTableRow,
|
||||
[TaskItem.name]: (state, node) => {
|
||||
state.write(`[${node.attrs.checked ? 'x' : ' '}] `);
|
||||
|
|
|
@ -3,10 +3,10 @@ import { copy } from 'helpers/copy';
|
|||
import { safeJSONStringify } from 'helpers/json';
|
||||
import { Fragment, Node } from 'prosemirror-model';
|
||||
|
||||
export function copyNode(nodeOrNodeName: Node);
|
||||
export function copyNode(nodeOrNodeName: Node | Fragment<any>);
|
||||
export function copyNode(nodeOrNodeName: string, editor: Editor);
|
||||
export function copyNode(nodeOrNodeName: string | Node, editor?: Editor) {
|
||||
let targetNode: null | Node = null;
|
||||
export function copyNode(nodeOrNodeName: string | Node | Fragment<any>, editor?: Editor) {
|
||||
let targetNode = null;
|
||||
|
||||
if (typeof nodeOrNodeName === 'string') {
|
||||
const { state } = editor;
|
||||
|
|
Loading…
Reference in New Issue