mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-04-26 09:16:22 +02:00
250 lines
4.7 KiB
TypeScript
250 lines
4.7 KiB
TypeScript
'use client';
|
|
|
|
import type { AutoformatBlockRule, AutoformatRule } from '@platejs/autoformat';
|
|
import type { SlateEditor } from 'platejs';
|
|
|
|
import {
|
|
autoformatArrow,
|
|
autoformatLegal,
|
|
autoformatLegalHtml,
|
|
autoformatMath,
|
|
AutoformatPlugin,
|
|
autoformatPunctuation,
|
|
autoformatSmartQuotes,
|
|
} from '@platejs/autoformat';
|
|
import { insertEmptyCodeBlock } from '@platejs/code-block';
|
|
import { toggleList, toggleTaskList, unwrapList } from '@platejs/list-classic';
|
|
import { openNextToggles } from '@platejs/toggle/react';
|
|
import { ElementApi, isType, KEYS } from 'platejs';
|
|
|
|
const preFormat: AutoformatBlockRule['preFormat'] = (editor) =>
|
|
unwrapList(editor);
|
|
|
|
const format = (editor: SlateEditor, customFormatting: any) => {
|
|
if (editor.selection) {
|
|
const parentEntry = editor.api.parent(editor.selection);
|
|
|
|
if (!parentEntry) return;
|
|
|
|
const [node] = parentEntry;
|
|
|
|
if (ElementApi.isElement(node) && !isType(editor, node, KEYS.codeBlock)) {
|
|
customFormatting();
|
|
}
|
|
}
|
|
};
|
|
|
|
const formatTaskList = (editor: SlateEditor, defaultChecked = false) => {
|
|
format(editor, () => toggleTaskList(editor, defaultChecked));
|
|
};
|
|
|
|
const formatList = (editor: SlateEditor, elementType: string) => {
|
|
format(editor, () =>
|
|
toggleList(editor, {
|
|
type: elementType,
|
|
})
|
|
);
|
|
};
|
|
|
|
const autoformatMarks: AutoformatRule[] = [
|
|
{
|
|
match: '***',
|
|
mode: 'mark',
|
|
type: [KEYS.bold, KEYS.italic],
|
|
},
|
|
{
|
|
match: '__*',
|
|
mode: 'mark',
|
|
type: [KEYS.underline, KEYS.italic],
|
|
},
|
|
{
|
|
match: '__**',
|
|
mode: 'mark',
|
|
type: [KEYS.underline, KEYS.bold],
|
|
},
|
|
{
|
|
match: '___***',
|
|
mode: 'mark',
|
|
type: [KEYS.underline, KEYS.bold, KEYS.italic],
|
|
},
|
|
{
|
|
match: '**',
|
|
mode: 'mark',
|
|
type: KEYS.bold,
|
|
},
|
|
{
|
|
match: '__',
|
|
mode: 'mark',
|
|
type: KEYS.underline,
|
|
},
|
|
{
|
|
match: '*',
|
|
mode: 'mark',
|
|
type: KEYS.italic,
|
|
},
|
|
{
|
|
match: '_',
|
|
mode: 'mark',
|
|
type: KEYS.italic,
|
|
},
|
|
{
|
|
match: '~~',
|
|
mode: 'mark',
|
|
type: KEYS.strikethrough,
|
|
},
|
|
{
|
|
match: '^',
|
|
mode: 'mark',
|
|
type: KEYS.sup,
|
|
},
|
|
{
|
|
match: '~',
|
|
mode: 'mark',
|
|
type: KEYS.sub,
|
|
},
|
|
{
|
|
match: '==',
|
|
mode: 'mark',
|
|
type: KEYS.highlight,
|
|
},
|
|
{
|
|
match: '≡',
|
|
mode: 'mark',
|
|
type: KEYS.highlight,
|
|
},
|
|
{
|
|
match: '`',
|
|
mode: 'mark',
|
|
type: KEYS.code,
|
|
},
|
|
];
|
|
|
|
const autoformatBlocks: AutoformatRule[] = [
|
|
{
|
|
match: '# ',
|
|
mode: 'block',
|
|
preFormat,
|
|
type: KEYS.h1,
|
|
},
|
|
{
|
|
match: '## ',
|
|
mode: 'block',
|
|
preFormat,
|
|
type: KEYS.h2,
|
|
},
|
|
{
|
|
match: '### ',
|
|
mode: 'block',
|
|
preFormat,
|
|
type: KEYS.h3,
|
|
},
|
|
{
|
|
match: '#### ',
|
|
mode: 'block',
|
|
preFormat,
|
|
type: KEYS.h4,
|
|
},
|
|
{
|
|
match: '##### ',
|
|
mode: 'block',
|
|
preFormat,
|
|
type: KEYS.h5,
|
|
},
|
|
{
|
|
match: '###### ',
|
|
mode: 'block',
|
|
preFormat,
|
|
type: KEYS.h6,
|
|
},
|
|
{
|
|
match: '> ',
|
|
mode: 'block',
|
|
preFormat,
|
|
type: KEYS.blockquote,
|
|
},
|
|
{
|
|
match: '```',
|
|
mode: 'block',
|
|
preFormat,
|
|
type: KEYS.codeBlock,
|
|
format: (editor) => {
|
|
insertEmptyCodeBlock(editor, {
|
|
defaultType: KEYS.p,
|
|
insertNodesOptions: { select: true },
|
|
});
|
|
},
|
|
},
|
|
{
|
|
match: '+ ',
|
|
mode: 'block',
|
|
preFormat: openNextToggles,
|
|
type: KEYS.toggle,
|
|
},
|
|
{
|
|
match: ['---', '—-', '___ '],
|
|
mode: 'block',
|
|
type: KEYS.hr,
|
|
format: (editor) => {
|
|
editor.tf.setNodes({ type: KEYS.hr });
|
|
editor.tf.insertNodes({
|
|
children: [{ text: '' }],
|
|
type: KEYS.p,
|
|
});
|
|
},
|
|
},
|
|
];
|
|
|
|
const autoformatLists: AutoformatRule[] = [
|
|
{
|
|
match: ['* ', '- '],
|
|
mode: 'block',
|
|
preFormat,
|
|
type: KEYS.li,
|
|
format: (editor) => formatList(editor, KEYS.ulClassic),
|
|
},
|
|
{
|
|
match: [String.raw`^\d+\.$ `, String.raw`^\d+\)$ `],
|
|
matchByRegex: true,
|
|
mode: 'block',
|
|
preFormat,
|
|
type: KEYS.li,
|
|
format: (editor) => formatList(editor, KEYS.olClassic),
|
|
},
|
|
{
|
|
match: '[] ',
|
|
mode: 'block',
|
|
type: KEYS.taskList,
|
|
format: (editor) => formatTaskList(editor, false),
|
|
},
|
|
{
|
|
match: '[x] ',
|
|
mode: 'block',
|
|
type: KEYS.taskList,
|
|
format: (editor) => formatTaskList(editor, true),
|
|
},
|
|
];
|
|
|
|
export const AutoformatKit = [
|
|
AutoformatPlugin.configure({
|
|
options: {
|
|
enableUndoOnDelete: true,
|
|
rules: [
|
|
...autoformatBlocks,
|
|
...autoformatMarks,
|
|
...autoformatSmartQuotes,
|
|
...autoformatPunctuation,
|
|
...autoformatLegal,
|
|
...autoformatLegalHtml,
|
|
...autoformatArrow,
|
|
...autoformatMath,
|
|
...autoformatLists,
|
|
].map((rule) => ({
|
|
...rule,
|
|
query: (editor) =>
|
|
!editor.api.some({
|
|
match: { type: editor.getType(KEYS.codeBlock) },
|
|
}),
|
|
})),
|
|
},
|
|
}),
|
|
];
|