feat: improve editor

This commit is contained in:
fantasticit 2022-03-23 20:42:47 +08:00
parent 3f981d44b0
commit 612754fe4b
20 changed files with 188 additions and 98 deletions

View File

@ -53,7 +53,6 @@
"@tiptap/extension-underline": "^2.0.0-beta.23", "@tiptap/extension-underline": "^2.0.0-beta.23",
"@tiptap/react": "^2.0.0-beta.107", "@tiptap/react": "^2.0.0-beta.107",
"@tiptap/suggestion": "^2.0.0-beta.90", "@tiptap/suggestion": "^2.0.0-beta.90",
"@traptitech/markdown-it-katex": "^3.5.0",
"axios": "^0.25.0", "axios": "^0.25.0",
"classnames": "^2.3.1", "classnames": "^2.3.1",
"copy-to-clipboard": "^3.3.1", "copy-to-clipboard": "^3.3.1",
@ -66,11 +65,8 @@
"markdown-it-anchor": "^8.4.1", "markdown-it-anchor": "^8.4.1",
"markdown-it-container": "^3.0.0", "markdown-it-container": "^3.0.0",
"markdown-it-emoji": "^2.0.0", "markdown-it-emoji": "^2.0.0",
"markdown-it-footnote": "^3.0.3",
"markdown-it-sub": "^1.0.0", "markdown-it-sub": "^1.0.0",
"markdown-it-sup": "^1.0.0", "markdown-it-sup": "^1.0.0",
"markdown-it-task-lists": "^2.1.1",
"marked": "^4.0.12",
"next": "12.0.10", "next": "12.0.10",
"prosemirror-markdown": "^1.7.0", "prosemirror-markdown": "^1.7.0",
"prosemirror-tables": "^1.1.1", "prosemirror-tables": "^1.1.1",

View File

@ -78,8 +78,8 @@ export const DocumentCollaboration: React.FC<IProps> = ({ wikiId, documentId })
CollaborationEventEmitter.on(KEY, ({ states: users }) => { CollaborationEventEmitter.on(KEY, ({ states: users }) => {
const newCollaborationUsers = users const newCollaborationUsers = users
.filter(Boolean) .filter(Boolean)
.map((state) => ({ ...state.user, clientId: state.clientId })) .filter((state) => state.user)
.filter(Boolean); .map((state) => ({ ...state.user, clientId: state.clientId }));
if ( if (
collaborationUsers.length === newCollaborationUsers.length && collaborationUsers.length === newCollaborationUsers.length &&

View File

@ -6,7 +6,6 @@ import { ILoginUser, IAuthority } from '@think/domains';
import { useToggle } from 'hooks/useToggle'; import { useToggle } from 'hooks/useToggle';
import { import {
DEFAULT_EXTENSION, DEFAULT_EXTENSION,
Document,
DocumentWithTitle, DocumentWithTitle,
getCollaborationExtension, getCollaborationExtension,
getCollaborationCursorExtension, getCollaborationCursorExtension,
@ -16,6 +15,8 @@ import {
} from 'components/tiptap'; } from 'components/tiptap';
import { DataRender } from 'components/data-render'; import { DataRender } from 'components/data-render';
import { joinUser } from 'components/document/collaboration'; import { joinUser } from 'components/document/collaboration';
import { debounce } from 'helpers/debounce';
import { changeTitle } from './index';
import styles from './index.module.scss'; import styles from './index.module.scss';
interface IProps { interface IProps {
@ -44,10 +45,6 @@ export const Editor: React.FC<IProps> = ({ user, documentId, authority, classNam
}); });
}, [documentId, user.token]); }, [documentId, user.token]);
const noTitleEditor = useEditor({
extensions: [...DEFAULT_EXTENSION, Document],
});
const editor = useEditor({ const editor = useEditor({
editable: authority && authority.editable, editable: authority && authority.editable,
extensions: [ extensions: [
@ -56,10 +53,12 @@ export const Editor: React.FC<IProps> = ({ user, documentId, authority, classNam
getCollaborationExtension(provider), getCollaborationExtension(provider),
getCollaborationCursorExtension(provider, user), getCollaborationCursorExtension(provider, user),
], ],
editorProps: { onTransaction: debounce(({ transaction }) => {
// @ts-ignore try {
noTitleEditor, const title = transaction.doc.content.firstChild.content.firstChild.textContent;
}, changeTitle(title);
} catch (e) {}
}, 200),
}); });
const [loading, toggleLoading] = useToggle(true); const [loading, toggleLoading] = useToggle(true);
@ -68,8 +67,6 @@ export const Editor: React.FC<IProps> = ({ user, documentId, authority, classNam
toggleLoading(false); toggleLoading(false);
}); });
// provid
provider.on('status', async ({ status }) => { provider.on('status', async ({ status }) => {
console.log('status', status); console.log('status', status);
}); });

View File

@ -9,6 +9,7 @@
z-index: 110; z-index: 110;
background-color: var(--semi-color-nav-bg); background-color: var(--semi-color-nav-bg);
height: 60px; height: 60px;
user-select: none;
> div { > div {
overflow: auto; overflow: auto;
@ -39,6 +40,7 @@
overflow: hidden; overflow: hidden;
background-color: var(--semi-color-nav-bg); background-color: var(--semi-color-nav-bg);
border-bottom: 1px solid var(--semi-color-border); border-bottom: 1px solid var(--semi-color-border);
user-select: none;
&.isStandardWidth { &.isStandardWidth {
justify-content: center; justify-content: center;

View File

@ -1,6 +1,6 @@
import Router from 'next/router'; import Router from 'next/router';
import React, { useCallback, useMemo } from 'react'; import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { Layout, Nav, Skeleton, Typography, Space, Button, Tooltip, Spin, Popover } from '@douyinfe/semi-ui'; import { Nav, Skeleton, Typography, Space, Button, Tooltip, Spin, Popover } from '@douyinfe/semi-ui';
import { IconChevronLeft, IconArticle } from '@douyinfe/semi-icons'; import { IconChevronLeft, IconArticle } from '@douyinfe/semi-icons';
import { useUser } from 'data/user'; import { useUser } from 'data/user';
import { useDocumentDetail } from 'data/document'; import { useDocumentDetail } from 'data/document';
@ -13,12 +13,19 @@ import { DocumentStar } from 'components/document/star';
import { DocumentCollaboration } from 'components/document/collaboration'; import { DocumentCollaboration } from 'components/document/collaboration';
import { DocumentStyle } from 'components/document/style'; import { DocumentStyle } from 'components/document/style';
import { useDocumentStyle } from 'hooks/useDocumentStyle'; import { useDocumentStyle } from 'hooks/useDocumentStyle';
import { EventEmitter } from 'helpers/event-emitter';
import { Editor } from './editor'; import { Editor } from './editor';
import styles from './index.module.scss'; import styles from './index.module.scss';
const { Header, Content } = Layout;
const { Text } = Typography; const { Text } = Typography;
const em = new EventEmitter();
const TITLE_CHANGE_EVENT = 'TITLE_CHANGE_EVENT';
export const changeTitle = (title) => {
em.emit(TITLE_CHANGE_EVENT, title);
};
interface IProps { interface IProps {
documentId: string; documentId: string;
} }
@ -30,7 +37,7 @@ export const DocumentEditor: React.FC<IProps> = ({ documentId }) => {
const editorWrapClassNames = useMemo(() => { const editorWrapClassNames = useMemo(() => {
return width === 'standardWidth' ? styles.isStandardWidth : styles.isFullWidth; return width === 'standardWidth' ? styles.isStandardWidth : styles.isFullWidth;
}, [width]); }, [width]);
const [title, setTitle] = useState('');
const { user } = useUser(); const { user } = useUser();
const { data: documentAndAuth, loading: docAuthLoading, error: docAuthError } = useDocumentDetail(documentId); const { data: documentAndAuth, loading: docAuthLoading, error: docAuthError } = useDocumentDetail(documentId);
const { document, authority } = documentAndAuth || {}; const { document, authority } = documentAndAuth || {};
@ -54,13 +61,21 @@ export const DocumentEditor: React.FC<IProps> = ({ documentId }) => {
} }
normalContent={() => ( normalContent={() => (
<Text ellipsis={{ showTooltip: true }} style={{ width: ~~(windowWith / 4) }}> <Text ellipsis={{ showTooltip: true }} style={{ width: ~~(windowWith / 4) }}>
{document.title} {title}
</Text> </Text>
)} )}
/> />
</> </>
); );
useEffect(() => {
em.on(TITLE_CHANGE_EVENT, setTitle);
return () => {
em.destroy();
};
}, []);
return ( return (
<div className={styles.wrap}> <div className={styles.wrap}>
<header> <header>
@ -91,10 +106,9 @@ export const DocumentEditor: React.FC<IProps> = ({ documentId }) => {
<Spin></Spin> <Spin></Spin>
</div> </div>
} }
error={null} error={docAuthError}
normalContent={() => { normalContent={() => {
return ( return (
// <div style={{ fontSize }}>
<> <>
<Seo title={document.title} /> <Seo title={document.title} />
<Editor <Editor

View File

@ -9,6 +9,7 @@
z-index: 110; z-index: 110;
background-color: var(--semi-color-nav-bg); background-color: var(--semi-color-nav-bg);
height: 60px; height: 60px;
user-select: none;
> div { > div {
overflow: auto; overflow: auto;
@ -39,6 +40,7 @@
overflow: hidden; overflow: hidden;
background-color: var(--semi-color-nav-bg); background-color: var(--semi-color-nav-bg);
border-bottom: 1px solid var(--semi-color-border); border-bottom: 1px solid var(--semi-color-border);
user-select: none;
&.isStandardWidth { &.isStandardWidth {
> div { > div {

View File

@ -1,6 +1,6 @@
.items { .items {
width: 160px; width: 160px;
max-height: 50vh; max-height: 40vh;
overflow: auto; overflow: auto;
padding: 0.2rem; padding: 0.2rem;
position: relative; position: relative;

View File

@ -0,0 +1,5 @@
.wrap {
margin: 8px 0;
display: inline-flex;
justify-content: center;
}

View File

@ -0,0 +1,23 @@
import { NodeViewWrapper, NodeViewContent } from '@tiptap/react';
import { useEffect, useMemo } from 'react';
import { Popover, TextArea, Typography, Space } from '@douyinfe/semi-ui';
import { IconHelpCircle } from '@douyinfe/semi-icons';
import katex from 'katex';
import { Checkbox } from '@douyinfe/semi-ui';
import styles from './index.module.scss';
const { Text } = Typography;
export const TaskItemWrapper = ({ editor, node, updateAttributes }) => {
const isEditable = editor.isEditable;
const { checked } = node.attrs;
console.log(node.attrs);
return (
<NodeViewWrapper as="span" className={styles.wrap} contentEditable={false}>
<Checkbox checked={checked} onChange={(e) => updateAttributes({ checked: e.target.checked })} />
<NodeViewContent></NodeViewContent>
</NodeViewWrapper>
);
};

View File

@ -11,7 +11,7 @@ const attrs = {
bdo: ['dir'], bdo: ['dir'],
}; };
export const HTMLMarks = marks.map(({ name, tag }) => export const HTMLMarks = marks.slice(1).map(({ name, tag }) =>
Mark.create({ Mark.create({
name, name,
tag, tag,

View File

@ -116,7 +116,8 @@ export const Paste = Extension.create({
return false; return false;
}, },
clipboardTextSerializer: (slice) => { clipboardTextSerializer: (slice) => {
const doc = this.editor.schema.topNodeType.createAndFill(undefined, slice.content); const doc = slice.content;
if (!doc) { if (!doc) {
return ''; return '';
} }

View File

@ -40,7 +40,7 @@ export const Table = BuiltInTable.extend({
if (fixedWidth && totalWidth > 0) { if (fixedWidth && totalWidth > 0) {
HTMLAttributes.style = `width: ${totalWidth}px;`; HTMLAttributes.style = `width: ${totalWidth}px;`;
} else if (totalWidth && totalWidth > 0) { } else if (totalWidth && totalWidth > 0) {
HTMLAttributes.style = `min-width: ${totalWidth}px`; HTMLAttributes.style = `min-width: 100%`;
} else { } else {
HTMLAttributes.style = null; HTMLAttributes.style = null;
} }

View File

@ -1,8 +1,10 @@
import { wrappingInputRule, mergeAttributes } from '@tiptap/core'; import { wrappingInputRule } from '@tiptap/core';
import { ReactNodeViewRenderer } from '@tiptap/react';
import { TaskItem as BuiltInTaskItem } from '@tiptap/extension-task-item'; import { TaskItem as BuiltInTaskItem } from '@tiptap/extension-task-item';
import { Plugin } from 'prosemirror-state'; import { Plugin } from 'prosemirror-state';
import { findParentNodeClosestToPos } from 'prosemirror-utils'; import { findParentNodeClosestToPos } from 'prosemirror-utils';
import { PARSE_HTML_PRIORITY_HIGHEST } from '../constants'; import { PARSE_HTML_PRIORITY_HIGHEST } from '../constants';
import { TaskItemWrapper } from '../components/taskItem';
const CustomTaskItem = BuiltInTaskItem.extend({ const CustomTaskItem = BuiltInTaskItem.extend({
parseHTML() { parseHTML() {
@ -27,35 +29,79 @@ const CustomTaskItem = BuiltInTaskItem.extend({
]; ];
}, },
// addProseMirrorPlugins() { // addNodeView() {
// return [ // return ReactNodeViewRenderer(TaskItemWrapper);
// new Plugin({ // },
// props: {
// // @ts-ignore
// handleClick: (view, pos, event) => {
// const state = view.state;
// const schema = state.schema;
// const coordinates = view.posAtCoords({ left: event.clientX, top: event.clientY }); addNodeView() {
// const position = state.doc.resolve(coordinates.pos); return ({ node, HTMLAttributes, getPos, editor }) => {
// const parentList = findParentNodeClosestToPos(position, function (node) { const listItem = document.createElement('li');
// return node.type === schema.nodes.taskItem || node.type === schema.nodes.listItem; const checkboxWrapper = document.createElement('span');
// }); const content = document.createElement('div');
// // @ts-ignore
// const isListClicked = event.target.tagName.toLowerCase() === 'li'; checkboxWrapper.contentEditable = 'false';
// if (!isListClicked || !parentList || parentList.node.type !== schema.nodes.taskItem) {
// return; Object.entries(this.options.HTMLAttributes).forEach(([key, value]) => {
// } listItem.setAttribute(key, value);
// const tr = state.tr; });
// tr.setNodeMarkup(parentList.pos, schema.nodes.taskItem, {
// checked: !parentList.node.attrs.checked, listItem.dataset.checked = node.attrs.checked;
// }); listItem.append(checkboxWrapper, content);
// view.dispatch(tr);
// }, Object.entries(HTMLAttributes).forEach(([key, value]) => {
// }, listItem.setAttribute(key, value);
// }), });
// ];
// }, return {
dom: listItem,
contentDOM: content,
update: (updatedNode) => {
if (updatedNode.type !== this.type) {
return false;
}
listItem.dataset.checked = updatedNode.attrs.checked;
return true;
},
};
};
},
addProseMirrorPlugins() {
return [
new Plugin({
props: {
// @ts-ignore
handleClick: (view, pos, event) => {
const state = view.state;
const schema = state.schema;
const coordinates = view.posAtCoords({ left: event.clientX, top: event.clientY });
const position = state.doc.resolve(coordinates.pos);
const parentList = findParentNodeClosestToPos(position, function (node) {
return node.type === schema.nodes.taskItem || node.type === schema.nodes.listItem;
});
if (!parentList) {
return;
}
const element = view.nodeDOM(parentList.pos) as HTMLLIElement;
if (element.tagName.toLowerCase() !== 'li') return;
const parentElement = element.parentElement;
const type = parentElement && parentElement.getAttribute('data-type');
if (!type || type.toLowerCase() !== 'tasklist') return;
const tr = state.tr;
const nextValue = !(element.getAttribute('data-checked') === 'true');
tr.setNodeMarkup(parentList.pos, schema.nodes.taskItem, {
checked: nextValue,
});
view.dispatch(tr);
},
},
}),
];
},
}); });
export const TaskItem = CustomTaskItem.configure({ nested: true }); export const TaskItem = CustomTaskItem.configure({ nested: true });

View File

@ -11,6 +11,8 @@ import { HorizontalRule } from '../extensions/horizontalRule';
import { Iframe } from '../extensions/iframe'; import { Iframe } from '../extensions/iframe';
import { Mind } from '../extensions/mind'; import { Mind } from '../extensions/mind';
import { Table } from '../extensions/table'; import { Table } from '../extensions/table';
import { TaskList } from '../extensions/taskList';
import { TaskItem } from '../extensions/taskItem';
import { Katex } from '../extensions/katex'; import { Katex } from '../extensions/katex';
import { DocumentReference } from '../extensions/documentReference'; import { DocumentReference } from '../extensions/documentReference';
import { DocumentChildren } from '../extensions/documentChildren'; import { DocumentChildren } from '../extensions/documentChildren';
@ -26,6 +28,8 @@ const OTHER_BUBBLE_MENU_TYPES = [
Iframe.name, Iframe.name,
Mind.name, Mind.name,
Table.name, Table.name,
TaskList.name,
TaskItem.name,
DocumentReference.name, DocumentReference.name,
DocumentChildren.name, DocumentChildren.name,
Katex.name, Katex.name,

View File

@ -10,8 +10,6 @@ export const markdownToProsemirror = ({ schema, content, hasTitle }) => {
if (!html) return null; if (!html) return null;
console.log(html);
const parser = new DOMParser(); const parser = new DOMParser();
const { body } = parser.parseFromString(html, 'text/html'); const { body } = parser.parseFromString(html, 'text/html');
body.append(document.createComment(content)); body.append(document.createComment(content));

View File

@ -10,7 +10,7 @@ import { DocumentReference } from '../../../extensions/documentReference';
import { HardBreak } from '../../../extensions/hardBreak'; import { HardBreak } from '../../../extensions/hardBreak';
import { Heading } from '../../../extensions/heading'; import { Heading } from '../../../extensions/heading';
import { HorizontalRule } from '../../../extensions/horizontalRule'; import { HorizontalRule } from '../../../extensions/horizontalRule';
import { marks, HTMLMarks } from '../../../extensions/htmlMarks'; import { marks } from '../../../extensions/htmlMarks';
import { Iframe } from '../../../extensions/iframe'; import { Iframe } from '../../../extensions/iframe';
import { Image } from '../../../extensions/image'; import { Image } from '../../../extensions/image';
import { Italic } from '../../../extensions/italic'; import { Italic } from '../../../extensions/italic';
@ -29,6 +29,7 @@ import { TableRow } from '../../../extensions/tableRow';
import { Text } from '../../../extensions/text'; import { Text } from '../../../extensions/text';
import { TaskItem } from '../../../extensions/taskItem'; import { TaskItem } from '../../../extensions/taskItem';
import { TaskList } from '../../../extensions/taskList'; import { TaskList } from '../../../extensions/taskList';
import { TextStyle } from '../../../extensions/textStyle';
import { Title } from '../../../extensions/title'; import { Title } from '../../../extensions/title';
import { import {
isPlainURL, isPlainURL,
@ -66,6 +67,8 @@ const SerializerConfig = {
mixable: true, mixable: true,
expelEnclosingWhitespace: true, expelEnclosingWhitespace: true,
}, },
// FIXME: 如何导出 style
[TextStyle.name]: { open: '', close: '', mixable: true, expelEnclosingWhitespace: true },
...marks.reduce( ...marks.reduce(
(acc, { name, tag }) => ({ (acc, { name, tag }) => ({
...acc, ...acc,
@ -151,10 +154,9 @@ const SerializerConfig = {
*/ */
export const prosemirrorToMarkdown = ({ content }) => { export const prosemirrorToMarkdown = ({ content }) => {
const serializer = new ProseMirrorMarkdownSerializer(SerializerConfig.nodes, SerializerConfig.marks); const serializer = new ProseMirrorMarkdownSerializer(SerializerConfig.nodes, SerializerConfig.marks);
const markdown = serializer.serialize(content, {
console.log(content);
return serializer.serialize(content, {
tightLists: true, tightLists: true,
}); });
return markdown;
}; };

View File

@ -178,11 +178,31 @@
li { li {
display: flex; display: flex;
align-items: center; align-items: center;
cursor: pointer;
> label { > span {
flex: 0 0 auto; position: relative;
user-select: none; display: block;
transform: translateY(2px); width: 16px;
height: 16px;
border: 1px solid var(--semi-color-border);
border-radius: 2px;
background-color: #fff;
&::after {
content: ' ';
position: absolute;
left: 4.071429px;
top: -0.357143px;
width: 6.714286px;
height: 12.142857px;
border: 2px solid #fff;
border-top: 0;
border-left: 0;
transition: all 0.1s cubic-bezier(0.71, -0.46, 0.88, 0.6), opacity 0.1s;
transform: rotate(45deg) scale(0);
opacity: 0;
}
} }
> div { > div {
@ -193,6 +213,15 @@
&[data-checked='true'] { &[data-checked='true'] {
color: var(--semi-color-text-2); color: var(--semi-color-text-2);
> span {
background-color: var(--semi-color-primary);
&::after {
opacity: 1;
transform: rotate(45deg) scale(1);
}
}
> div { > div {
text-decoration: line-through; text-decoration: line-through;
} }

View File

@ -10,7 +10,6 @@ export class CreateDocumentDto {
@IsString({ message: '文档名称类型错误正确类型为String' }) @IsString({ message: '文档名称类型错误正确类型为String' })
@IsNotEmpty({ message: '文档名称不能为空' }) @IsNotEmpty({ message: '文档名称不能为空' })
@MinLength(1, { message: '文档名称至少1个字符' }) @MinLength(1, { message: '文档名称至少1个字符' })
@MaxLength(50, { message: '文档名称最多50个字符' })
@IsOptional() @IsOptional()
readonly title?: string; readonly title?: string;

View File

@ -19,7 +19,7 @@ export class DocumentEntity {
@Column({ type: 'varchar', comment: '父文档 Id', default: null }) @Column({ type: 'varchar', comment: '父文档 Id', default: null })
public parentDocumentId: string; public parentDocumentId: string;
@Column({ type: 'varchar', length: 50, comment: '文档标题', default: '' }) @Column({ type: 'varchar', default: '未命名文档', comment: '文档标题' })
public title: string; public title: string;
@Column({ type: 'text', comment: '文档内容' }) @Column({ type: 'text', comment: '文档内容' })

View File

@ -87,7 +87,6 @@ importers:
'@tiptap/extension-underline': ^2.0.0-beta.23 '@tiptap/extension-underline': ^2.0.0-beta.23
'@tiptap/react': ^2.0.0-beta.107 '@tiptap/react': ^2.0.0-beta.107
'@tiptap/suggestion': ^2.0.0-beta.90 '@tiptap/suggestion': ^2.0.0-beta.90
'@traptitech/markdown-it-katex': ^3.5.0
'@types/node': 17.0.13 '@types/node': 17.0.13
'@types/react': 17.0.38 '@types/react': 17.0.38
axios: ^0.25.0 axios: ^0.25.0
@ -102,11 +101,8 @@ importers:
markdown-it-anchor: ^8.4.1 markdown-it-anchor: ^8.4.1
markdown-it-container: ^3.0.0 markdown-it-container: ^3.0.0
markdown-it-emoji: ^2.0.0 markdown-it-emoji: ^2.0.0
markdown-it-footnote: ^3.0.3
markdown-it-sub: ^1.0.0 markdown-it-sub: ^1.0.0
markdown-it-sup: ^1.0.0 markdown-it-sup: ^1.0.0
markdown-it-task-lists: ^2.1.1
marked: ^4.0.12
next: 12.0.10 next: 12.0.10
prosemirror-markdown: ^1.7.0 prosemirror-markdown: ^1.7.0
prosemirror-tables: ^1.1.1 prosemirror-tables: ^1.1.1
@ -166,7 +162,6 @@ importers:
'@tiptap/extension-underline': 2.0.0-beta.23_@tiptap+core@2.0.0-beta.171 '@tiptap/extension-underline': 2.0.0-beta.23_@tiptap+core@2.0.0-beta.171
'@tiptap/react': 2.0.0-beta.107_a3fcdb91535fe17b69dfabaa94f3bb3d '@tiptap/react': 2.0.0-beta.107_a3fcdb91535fe17b69dfabaa94f3bb3d
'@tiptap/suggestion': 2.0.0-beta.90_@tiptap+core@2.0.0-beta.171 '@tiptap/suggestion': 2.0.0-beta.90_@tiptap+core@2.0.0-beta.171
'@traptitech/markdown-it-katex': 3.5.0
axios: 0.25.0 axios: 0.25.0
classnames: 2.3.1 classnames: 2.3.1
copy-to-clipboard: 3.3.1 copy-to-clipboard: 3.3.1
@ -179,11 +174,8 @@ importers:
markdown-it-anchor: 8.4.1_markdown-it@12.3.2 markdown-it-anchor: 8.4.1_markdown-it@12.3.2
markdown-it-container: 3.0.0 markdown-it-container: 3.0.0
markdown-it-emoji: 2.0.0 markdown-it-emoji: 2.0.0
markdown-it-footnote: 3.0.3
markdown-it-sub: 1.0.0 markdown-it-sub: 1.0.0
markdown-it-sup: 1.0.0 markdown-it-sup: 1.0.0
markdown-it-task-lists: 2.1.1
marked: 4.0.12
next: 12.0.10_react-dom@17.0.2+react@17.0.2 next: 12.0.10_react-dom@17.0.2+react@17.0.2
prosemirror-markdown: 1.7.0 prosemirror-markdown: 1.7.0
prosemirror-tables: 1.1.1 prosemirror-tables: 1.1.1
@ -1953,12 +1945,6 @@ packages:
resolution: {integrity: sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==} resolution: {integrity: sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==}
engines: {node: '>= 6'} engines: {node: '>= 6'}
/@traptitech/markdown-it-katex/3.5.0:
resolution: {integrity: sha512-7/GI3ETKJjrZD9+azn7WraDWo0ZQ6grtzR4I36qu7U0vOJMBtC+znX7UghdOScrgGnxqGvgWm07SYnlcCtdCvw==}
dependencies:
katex: 0.15.2
dev: false
/@tsconfig/node10/1.0.8: /@tsconfig/node10/1.0.8:
resolution: {integrity: sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==} resolution: {integrity: sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==}
dev: true dev: true
@ -6008,10 +5994,6 @@ packages:
resolution: {integrity: sha512-39j7/9vP/CPCKbEI44oV8yoPJTpvfeReTn/COgRhSpNrjWF3PfP/JUxxB0hxV6ynOY8KH8Y8aX9NMDdo6z+6YQ==} resolution: {integrity: sha512-39j7/9vP/CPCKbEI44oV8yoPJTpvfeReTn/COgRhSpNrjWF3PfP/JUxxB0hxV6ynOY8KH8Y8aX9NMDdo6z+6YQ==}
dev: false dev: false
/markdown-it-footnote/3.0.3:
resolution: {integrity: sha512-YZMSuCGVZAjzKMn+xqIco9d1cLGxbELHZ9do/TSYVzraooV8ypsppKNmUJ0fVH5ljkCInQAtFpm8Rb3eXSrt5w==}
dev: false
/markdown-it-sub/1.0.0: /markdown-it-sub/1.0.0:
resolution: {integrity: sha1-N1/WAm6ufdywEkl/ZBEZXqHjr+g=} resolution: {integrity: sha1-N1/WAm6ufdywEkl/ZBEZXqHjr+g=}
dev: false dev: false
@ -6020,10 +6002,6 @@ packages:
resolution: {integrity: sha1-y5yf+RpSVawI8/09YyhuFd8KH8M=} resolution: {integrity: sha1-y5yf+RpSVawI8/09YyhuFd8KH8M=}
dev: false dev: false
/markdown-it-task-lists/2.1.1:
resolution: {integrity: sha512-TxFAc76Jnhb2OUu+n3yz9RMu4CwGfaT788br6HhEDlvWfdeJcLUsxk1Hgw2yJio0OXsxv7pyIPmvECY7bMbluA==}
dev: false
/markdown-it/12.3.2: /markdown-it/12.3.2:
resolution: {integrity: sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==} resolution: {integrity: sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==}
hasBin: true hasBin: true
@ -6035,12 +6013,6 @@ packages:
uc.micro: 1.0.6 uc.micro: 1.0.6
dev: false dev: false
/marked/4.0.12:
resolution: {integrity: sha512-hgibXWrEDNBWgGiK18j/4lkS6ihTe9sxtV4Q1OQppb/0zzyPSzoFANBa5MfsG/zgsWklmNnhm0XACZOH/0HBiQ==}
engines: {node: '>= 12'}
hasBin: true
dev: false
/mdurl/1.0.1: /mdurl/1.0.1:
resolution: {integrity: sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=} resolution: {integrity: sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=}
dev: false dev: false