mirror of
https://github.com/outline/outline.git
synced 2026-06-13 19:35:02 +03:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| baf7c1a6cd | |||
| f254ce0b84 |
@@ -88,7 +88,7 @@ export default class PasteHandler extends Extension {
|
||||
|
||||
// If the users selection is currently in a code block then paste
|
||||
// as plain text, ignore all formatting and HTML content.
|
||||
if (isInCode(state)) {
|
||||
if (isInCode(state, { inclusive: true })) {
|
||||
event.preventDefault();
|
||||
view.dispatch(state.tr.insertText(text));
|
||||
return true;
|
||||
|
||||
@@ -7,6 +7,8 @@ type Options = {
|
||||
onlyBlock?: boolean;
|
||||
/** Only check if the selection is inside a code mark. */
|
||||
onlyMark?: boolean;
|
||||
/** If true then code must contain entire selection */
|
||||
inclusive?: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -20,17 +22,29 @@ export function isInCode(state: EditorState, options?: Options): boolean {
|
||||
const { nodes, marks } = state.schema;
|
||||
|
||||
if (!options?.onlyMark) {
|
||||
if (nodes.code_block && isNodeActive(nodes.code_block)(state)) {
|
||||
if (
|
||||
nodes.code_block &&
|
||||
isNodeActive(nodes.code_block, undefined, {
|
||||
inclusive: options?.inclusive,
|
||||
})(state)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
if (nodes.code_fence && isNodeActive(nodes.code_fence)(state)) {
|
||||
if (
|
||||
nodes.code_fence &&
|
||||
isNodeActive(nodes.code_fence, undefined, {
|
||||
inclusive: options?.inclusive,
|
||||
})(state)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!options?.onlyBlock) {
|
||||
if (marks.code_inline) {
|
||||
return isMarkActive(marks.code_inline)(state);
|
||||
return isMarkActive(marks.code_inline, undefined, {
|
||||
inclusive: options?.inclusive,
|
||||
})(state);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@ import { getMarksBetween } from "./getMarksBetween";
|
||||
type Options = {
|
||||
/** Only return match if the range and attrs is exact */
|
||||
exact?: boolean;
|
||||
/** If true then mark must contain entire selection */
|
||||
inclusive?: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -40,7 +42,8 @@ export const isMarkActive =
|
||||
Object.keys(attrs).every(
|
||||
(key) => mark.attrs[key] === attrs[key]
|
||||
)) &&
|
||||
(!options?.exact || (start === from && end === to))
|
||||
(!options?.exact || (start === from && end === to)) &&
|
||||
(!options?.inclusive || (start <= from && end >= to))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,31 +3,55 @@ import { EditorState } from "prosemirror-state";
|
||||
import { Primitive } from "utility-types";
|
||||
import { findParentNode } from "./findParentNode";
|
||||
|
||||
type Options = {
|
||||
/** Only return match if the range and attrs is exact */
|
||||
exact?: boolean;
|
||||
/** If true then node must contain entire selection */
|
||||
inclusive?: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if a node is active in the current selection or not.
|
||||
*
|
||||
* @param type The node type to check.
|
||||
* @param attrs The attributes to check.
|
||||
* @param options The options to use.
|
||||
* @returns A function that checks if a node is active in the current selection or not.
|
||||
*/
|
||||
export const isNodeActive =
|
||||
(type: NodeType, attrs: Record<string, Primitive> = {}) =>
|
||||
(state: EditorState) => {
|
||||
(type: NodeType, attrs?: Record<string, Primitive>, options?: Options) =>
|
||||
(state: EditorState): boolean => {
|
||||
if (!type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const nodeAfter = state.selection.$from.nodeAfter;
|
||||
let node = nodeAfter?.type === type ? nodeAfter : undefined;
|
||||
const { from, to } = state.selection;
|
||||
const nodeWithPos = findParentNode(
|
||||
(node) =>
|
||||
node.type === type &&
|
||||
(!attrs ||
|
||||
Object.keys(attrs).every((key) => node.attrs[key] === attrs[key]))
|
||||
)(state.selection);
|
||||
|
||||
if (!node) {
|
||||
const parent = findParentNode((n) => n.type === type)(state.selection);
|
||||
node = parent?.node;
|
||||
if (!nodeWithPos) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Object.keys(attrs).length || !node) {
|
||||
return !!node;
|
||||
if (options?.inclusive) {
|
||||
// Check if the node's position contains the entire selection
|
||||
return (
|
||||
nodeWithPos.pos <= from &&
|
||||
nodeWithPos.pos + nodeWithPos.node.nodeSize >= to
|
||||
);
|
||||
}
|
||||
|
||||
return node.hasMarkup(type, { ...node.attrs, ...attrs });
|
||||
if (options?.exact) {
|
||||
// Check if node's range exactly matches selection
|
||||
return (
|
||||
nodeWithPos.pos === from &&
|
||||
nodeWithPos.pos + nodeWithPos.node.nodeSize === to
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user