mirror of https://github.com/fantasticit/think.git
feat: support selecton in banner
This commit is contained in:
parent
8022d937c2
commit
8b098285f9
|
@ -24,7 +24,7 @@ export const Banner = Node.create({
|
|||
type: {
|
||||
default: 'info',
|
||||
rendered: false,
|
||||
parseHTML: getDatasetAttribute('info'),
|
||||
parseHTML: getDatasetAttribute('type'),
|
||||
renderHTML: (attributes) => {
|
||||
return {
|
||||
'data-type': attributes.type,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { Extension } from '@tiptap/core';
|
||||
import { Plugin, PluginKey, NodeSelection, TextSelection, Selection, AllSelection } from 'prosemirror-state';
|
||||
import { Decoration, DecorationSet } from 'prosemirror-view';
|
||||
import { getCurrentNode, isInCodeBlock } from '../services/node';
|
||||
import { getCurrentNode, isInCodeBlock, isInBanner } from '../services/node';
|
||||
import { EXTENSION_PRIORITY_HIGHEST } from '../constants';
|
||||
|
||||
export const selectionPluginKey = new PluginKey('selection');
|
||||
|
@ -56,13 +56,30 @@ export const SelectionExtension = Extension.create({
|
|||
*/
|
||||
if ((event.ctrlKey || event.metaKey) && (event.keyCode == 65 || event.keyCode == 97)) {
|
||||
const node = getCurrentNode(view.state);
|
||||
const $head = view.state.selection.$head;
|
||||
let startPos = null;
|
||||
let endPos = null;
|
||||
|
||||
// 代码块
|
||||
if (isInCodeBlock(view.state)) {
|
||||
const { pos, parentOffset } = view.state.selection.$head;
|
||||
const { pos, parentOffset } = $head;
|
||||
startPos = pos - parentOffset;
|
||||
endPos = pos - parentOffset + node.nodeSize - 2;
|
||||
}
|
||||
|
||||
// 信息框
|
||||
if (isInBanner(view.state)) {
|
||||
// @ts-ignore
|
||||
const { path = [] } = $head;
|
||||
startPos = path[2];
|
||||
endPos = startPos + path[3].content.size;
|
||||
}
|
||||
|
||||
if (startPos !== null && endPos !== null) {
|
||||
const newState = view.state;
|
||||
const next = new TextSelection(
|
||||
newState.doc.resolve(pos - parentOffset + node.nodeSize - 2), //内容结束点
|
||||
newState.doc.resolve(pos - parentOffset) // 内容起始点
|
||||
newState.doc.resolve(endPos), //内容结束点
|
||||
newState.doc.resolve(startPos) // 内容起始点
|
||||
);
|
||||
view?.dispatch(newState.tr.setSelection(next));
|
||||
return true;
|
||||
|
@ -71,19 +88,6 @@ export const SelectionExtension = Extension.create({
|
|||
|
||||
return false;
|
||||
},
|
||||
handleDoubleClickOn(view, pos, node, nodePos, event) {
|
||||
if (node.type.name === 'codeBlock') {
|
||||
event.preventDefault();
|
||||
const transaction = view.state.tr.setMeta('selectNode', {
|
||||
fromPos: nodePos,
|
||||
toPos: nodePos + node.nodeSize,
|
||||
attrs: { class: 'selected-node' },
|
||||
});
|
||||
view?.dispatch(transaction);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
decorations(state) {
|
||||
return this.getState(state);
|
||||
},
|
||||
|
@ -93,10 +97,6 @@ export const SelectionExtension = Extension.create({
|
|||
return DecorationSet.empty;
|
||||
},
|
||||
apply(ctx) {
|
||||
if (ctx.getMeta('selectNode')) {
|
||||
const { fromPos, toPos, attrs } = ctx.getMeta('selectNode');
|
||||
return DecorationSet.create(ctx.doc, [Decoration.node(fromPos, toPos, attrs)]);
|
||||
}
|
||||
const { doc, selection } = ctx;
|
||||
const decorationSet = getDecorations(doc, selection);
|
||||
return decorationSet;
|
||||
|
|
|
@ -7,6 +7,10 @@ export const isMarkdown = (text: string): boolean => {
|
|||
const tables = text.match(/^\|(\S)*\|/gm);
|
||||
if (tables && tables.length) return true;
|
||||
|
||||
// 自定义 container
|
||||
const conatiner = text.match(/^:::/gm);
|
||||
if (conatiner && conatiner.length > 1) return true;
|
||||
|
||||
// code-ish
|
||||
const fences = text.match(/^```/gm);
|
||||
if (fences && fences.length > 1) return true;
|
||||
|
|
|
@ -21,25 +21,36 @@ export function isListNode(node: Node): boolean {
|
|||
return isBulletListNode(node) || isOrderedListNode(node) || isTodoListNode(node);
|
||||
}
|
||||
|
||||
export function isInTitle(state: EditorState): boolean {
|
||||
export function getCurrentNode(state: EditorState): Node {
|
||||
const $head = state.selection.$head;
|
||||
let node = null;
|
||||
|
||||
for (let d = $head.depth; d > 0; d--) {
|
||||
node = $head.node(d);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
export function isInCustomNode(state: EditorState, nodeName: string): boolean {
|
||||
if (!state.schema.nodes[nodeName]) return false;
|
||||
|
||||
const $head = state.selection.$head;
|
||||
for (let d = $head.depth; d > 0; d--) {
|
||||
if ($head.node(d).type === state.schema.nodes.title) {
|
||||
if ($head.node(d).type === state.schema.nodes[nodeName]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function getCurrentNode(state: EditorState): Node {
|
||||
const $head = state.selection.$head;
|
||||
return $head.node($head.depth);
|
||||
}
|
||||
|
||||
export function isInCodeBlock(state: EditorState): boolean {
|
||||
const $head = state.selection.$head;
|
||||
for (let d = $head.depth; d > 0; d--) {
|
||||
if ($head.node(d).type === state.schema.nodes.codeBlock) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return isInCustomNode(state, 'codeBlock');
|
||||
}
|
||||
|
||||
export function isInTitle(state: EditorState): boolean {
|
||||
return isInCustomNode(state, 'title');
|
||||
}
|
||||
|
||||
export function isInBanner(state: EditorState): boolean {
|
||||
return isInCustomNode(state, 'banner');
|
||||
}
|
||||
|
|
|
@ -141,9 +141,11 @@ export const AttachmentWrapper = ({ editor, node, updateAttributes }) => {
|
|||
|
||||
if (isEditable && !url) {
|
||||
return (
|
||||
<div className={cls(styles.wrap, 'render-wrapper')} onClick={selectFile}>
|
||||
<div className={cls(styles.wrap, 'render-wrapper')}>
|
||||
<Spin spinning={loading}>
|
||||
<Text style={{ cursor: 'pointer' }}>{loading ? '正在上传中' : '请选择文件'}</Text>
|
||||
<Text style={{ cursor: 'pointer' }} onClick={selectFile}>
|
||||
{loading ? '正在上传中' : '请选择文件'}
|
||||
</Text>
|
||||
<input ref={$upload} type="file" hidden onChange={handleFile} />
|
||||
</Spin>
|
||||
</div>
|
||||
|
|
Loading…
Reference in New Issue