Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

prosemirror-paste-rules

Package Overview
Dependencies
Maintainers
1
Versions
212
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

prosemirror-paste-rules - npm Package Compare versions

Comparing version 3.0.0-beta.1 to 3.0.0-beta.2

413

dist/prosemirror-paste-rules.js

@@ -0,1 +1,4 @@

function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
// src/paste-rules-plugin.ts

@@ -7,17 +10,29 @@ import { Fragment, Slice } from "prosemirror-model";

function pasteRules(pasteRules2) {
const sortedPasteRules = sort(pasteRules2, (a, z) => (z.priority ?? ExtensionPriority.Low) - (a.priority ?? ExtensionPriority.Low));
const regexPasteRules2 = [];
const filePasteRules = [];
for (const rule of sortedPasteRules) {
if (isRegexPastRule(rule)) {
regexPasteRules2.push(rule);
} else {
filePasteRules.push(rule);
var sortedPasteRules = sort(pasteRules2, (a, z) => {
var _z$priority, _a$priority;
return ((_z$priority = z.priority) !== null && _z$priority !== void 0 ? _z$priority : ExtensionPriority.Low) - ((_a$priority = a.priority) !== null && _a$priority !== void 0 ? _a$priority : ExtensionPriority.Low);
});
var regexPasteRules2 = [];
var filePasteRules = [];
var _iterator = _createForOfIteratorHelper(sortedPasteRules),
_step;
try {
for (_iterator.s(); !(_step = _iterator.n()).done;) {
var rule = _step.value;
if (isRegexPastRule(rule)) {
regexPasteRules2.push(rule);
} else {
filePasteRules.push(rule);
}
}
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
let view;
var _view;
return new Plugin({
key: pastePluginKey,
view: editorView => {
view = editorView;
_view = editorView;
return {};

@@ -28,47 +43,51 @@ },

transformPasted: slice => {
const $pos = view.state.selection.$from;
const nodeName = $pos.node().type.name;
const markNames = new Set($pos.marks().map(mark => mark.type.name));
for (const rule of regexPasteRules2) {
var $pos = _view.state.selection.$from;
var nodeName = $pos.node().type.name;
var markNames = new Set($pos.marks().map(mark => mark.type.name));
var _loop = function _loop() {
var _rule$ignoredNodes, _rule$ignoredMarks, _slice$content$firstC, _slice$content$firstC2;
var rule = _regexPasteRules[_i];
if (
// The parent node is ignored.
rule.ignoredNodes?.includes(nodeName) ||
// The current position contains ignored marks.
rule.ignoredMarks?.some(ignored => markNames.has(ignored))) {
continue;
(_rule$ignoredNodes = rule.ignoredNodes) !== null && _rule$ignoredNodes !== void 0 && _rule$ignoredNodes.includes(nodeName) || // The current position contains ignored marks.
(_rule$ignoredMarks = rule.ignoredMarks) !== null && _rule$ignoredMarks !== void 0 && _rule$ignoredMarks.some(ignored => markNames.has(ignored))) {
return "continue";
}
const textContent = slice.content.firstChild?.textContent ?? "";
const canBeReplaced = !view.state.selection.empty && slice.content.childCount === 1 && textContent;
const match = findMatches(textContent, rule.regexp)[0];
var textContent = (_slice$content$firstC = (_slice$content$firstC2 = slice.content.firstChild) === null || _slice$content$firstC2 === void 0 ? void 0 : _slice$content$firstC2.textContent) !== null && _slice$content$firstC !== void 0 ? _slice$content$firstC : "";
var canBeReplaced = !_view.state.selection.empty && slice.content.childCount === 1 && textContent;
var match = findMatches(textContent, rule.regexp)[0];
if (canBeReplaced && match && rule.type === "mark" && rule.replaceSelection) {
const {
from,
to
} = view.state.selection;
const textSlice = view.state.doc.slice(from, to);
const textContent2 = textSlice.content.textBetween(0, textSlice.content.size);
var _view$state$selection = _view.state.selection,
from = _view$state$selection.from,
to = _view$state$selection.to;
var textSlice = _view.state.doc.slice(from, to);
var textContent2 = textSlice.content.textBetween(0, textSlice.content.size);
if (typeof rule.replaceSelection !== "boolean" ? rule.replaceSelection(textContent2) : rule.replaceSelection) {
const newTextNodes = [];
const {
getAttributes,
markType
} = rule;
const attributes = isFunction(getAttributes) ? getAttributes(match, true) : getAttributes;
const mark = markType.create(attributes);
var newTextNodes = [];
var getAttributes = rule.getAttributes,
markType = rule.markType;
var attributes = isFunction(getAttributes) ? getAttributes(match, true) : getAttributes;
var mark = markType.create(attributes);
textSlice.content.forEach(textNode => {
if (textNode.isText) {
const marks = mark.addToSet(textNode.marks);
var marks = mark.addToSet(textNode.marks);
newTextNodes.push(textNode.mark(marks));
}
});
return Slice.maxOpen(Fragment.fromArray(newTextNodes));
return {
v: Slice.maxOpen(Fragment.fromArray(newTextNodes))
};
}
}
const {
nodes: transformedNodes,
transformed
} = regexPasteRuleHandler(slice.content, rule, view.state.schema);
var _regexPasteRuleHandle = regexPasteRuleHandler(slice.content, rule, _view.state.schema),
transformedNodes = _regexPasteRuleHandle.nodes,
transformed = _regexPasteRuleHandle.transformed;
if (transformed) {
slice = rule.type === "node" && rule.nodeType.isBlock ? new Slice(Fragment.fromArray(transformedNodes), 0, 0) : new Slice(Fragment.fromArray(transformedNodes), slice.openStart, slice.openEnd);
}
};
for (var _i = 0, _regexPasteRules = regexPasteRules2; _i < _regexPasteRules.length; _i++) {
var _ret = _loop();
if (_ret === "continue") continue;
if (typeof _ret === "object") return _ret.v;
}

@@ -80,26 +99,23 @@ return fixSliceOpening(slice);

paste: (view2, clipboardEvent) => {
const event = clipboardEvent;
if (!view2.props.editable?.(view2.state)) {
var _view2$props$editable, _view2$props;
var event = clipboardEvent;
if (!((_view2$props$editable = (_view2$props = view2.props).editable) !== null && _view2$props$editable !== void 0 && _view2$props$editable.call(_view2$props, view2.state))) {
return false;
}
const {
clipboardData
} = event;
var clipboardData = event.clipboardData;
if (!clipboardData) {
return false;
}
const allFiles = [...clipboardData.items].map(data => data.getAsFile()).filter(file => !!file);
var allFiles = [...clipboardData.items].map(data => data.getAsFile()).filter(file => !!file);
if (allFiles.length === 0) {
return false;
}
const {
selection
} = view2.state;
for (const {
fileHandler,
regexp
} of filePasteRules) {
const files = regexp ? allFiles.filter(file => regexp.test(file.type)) : allFiles;
var selection = view2.state.selection;
var _loop2 = function _loop2() {
var _filePasteRules$_i = _filePasteRules[_i2],
fileHandler = _filePasteRules$_i.fileHandler,
regexp = _filePasteRules$_i.regexp;
var files = regexp ? allFiles.filter(file => regexp.test(file.type)) : allFiles;
if (files.length === 0) {
continue;
return "continue";
}

@@ -114,4 +130,11 @@ if (fileHandler({

event.preventDefault();
return true;
return {
v: true
};
}
};
for (var _i2 = 0, _filePasteRules = filePasteRules; _i2 < _filePasteRules.length; _i2++) {
var _ret2 = _loop2();
if (_ret2 === "continue") continue;
if (typeof _ret2 === "object") return _ret2.v;
}

@@ -122,29 +145,28 @@ return false;

drop: (view2, dragEvent) => {
const event = dragEvent;
if (!view2.props.editable?.(view2.state)) {
var _view2$props$editable2, _view2$props2, _view2$posAtCoords$po, _view2$posAtCoords;
var event = dragEvent;
if (!((_view2$props$editable2 = (_view2$props2 = view2.props).editable) !== null && _view2$props$editable2 !== void 0 && _view2$props$editable2.call(_view2$props2, view2.state))) {
return false;
}
const {
dataTransfer,
clientX,
clientY
} = event;
var dataTransfer = event.dataTransfer,
clientX = event.clientX,
clientY = event.clientY;
if (!dataTransfer) {
return false;
}
const allFiles = getDataTransferFiles(event);
var allFiles = getDataTransferFiles(event);
if (allFiles.length === 0) {
return false;
}
const pos = view2.posAtCoords({
var pos = (_view2$posAtCoords$po = (_view2$posAtCoords = view2.posAtCoords({
left: clientX,
top: clientY
})?.pos ?? view2.state.selection.anchor;
for (const {
fileHandler,
regexp
} of filePasteRules) {
const files = regexp ? allFiles.filter(file => regexp.test(file.type)) : allFiles;
})) === null || _view2$posAtCoords === void 0 ? void 0 : _view2$posAtCoords.pos) !== null && _view2$posAtCoords$po !== void 0 ? _view2$posAtCoords$po : view2.state.selection.anchor;
var _loop3 = function _loop3() {
var _filePasteRules2$_i = _filePasteRules2[_i3],
fileHandler = _filePasteRules2$_i.fileHandler,
regexp = _filePasteRules2$_i.regexp;
var files = regexp ? allFiles.filter(file => regexp.test(file.type)) : allFiles;
if (files.length === 0) {
continue;
return "continue";
}

@@ -159,4 +181,11 @@ if (fileHandler({

event.preventDefault();
return true;
return {
v: true
};
}
};
for (var _i3 = 0, _filePasteRules2 = filePasteRules; _i3 < _filePasteRules2.length; _i3++) {
var _ret3 = _loop3();
if (_ret3 === "continue") continue;
if (typeof _ret3 === "object") return _ret3.v;
}

@@ -172,16 +201,13 @@ return false;

return function handler(props) {
const {
fragment,
rule,
nodes
} = props;
const {
regexp,
ignoreWhitespace,
ignoredMarks,
ignoredNodes
} = rule;
let transformed = false;
var fragment = props.fragment,
rule = props.rule,
nodes = props.nodes;
var regexp = rule.regexp,
ignoreWhitespace = rule.ignoreWhitespace,
ignoredMarks = rule.ignoredMarks,
ignoredNodes = rule.ignoredNodes;
var transformed = false;
fragment.forEach(child => {
if (ignoredNodes?.includes(child.type.name) || isCodeNode(child)) {
var _child$text;
if (ignoredNodes !== null && ignoredNodes !== void 0 && ignoredNodes.includes(child.type.name) || isCodeNode(child)) {
nodes.push(child);

@@ -191,3 +217,3 @@ return;

if (!child.isText) {
const childResult = handler({
var childResult = handler({
fragment: child.content,

@@ -197,4 +223,4 @@ rule,

});
transformed ||= childResult.transformed;
const content = Fragment.fromArray(childResult.nodes);
transformed || (transformed = childResult.transformed);
var content = Fragment.fromArray(childResult.nodes);
if (child.type.validContent(content)) {

@@ -207,41 +233,50 @@ nodes.push(child.copy(content));

}
if (child.marks.some(mark => isCodeMark(mark) || ignoredMarks?.includes(mark.type.name))) {
if (child.marks.some(mark => isCodeMark(mark) || (ignoredMarks === null || ignoredMarks === void 0 ? void 0 : ignoredMarks.includes(mark.type.name)))) {
nodes.push(child);
return;
}
const text = child.text ?? "";
let pos = 0;
for (const match of findMatches(text, regexp)) {
const capturedValue = match[1];
const fullValue = match[0];
if (
// This helps prevent matches which are only whitespace from triggering
// an update.
ignoreWhitespace && capturedValue?.trim() === "" || !fullValue) {
return;
}
const start = match.index;
const end = start + fullValue.length;
if (start > pos) {
nodes.push(child.cut(pos, start));
}
let textNode = child.cut(start, end);
if (fullValue && capturedValue) {
const startSpaces = fullValue.search(/\S/);
const textStart = start + fullValue.indexOf(capturedValue);
const textEnd = textStart + capturedValue.length;
if (startSpaces) {
nodes.push(child.cut(start, start + startSpaces));
var text = (_child$text = child.text) !== null && _child$text !== void 0 ? _child$text : "";
var pos = 0;
var _iterator2 = _createForOfIteratorHelper(findMatches(text, regexp)),
_step2;
try {
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
var match = _step2.value;
var capturedValue = match[1];
var fullValue = match[0];
if (
// This helps prevent matches which are only whitespace from triggering
// an update.
ignoreWhitespace && (capturedValue === null || capturedValue === void 0 ? void 0 : capturedValue.trim()) === "" || !fullValue) {
return;
}
textNode = child.cut(textStart, textEnd);
var start = match.index;
var end = start + fullValue.length;
if (start > pos) {
nodes.push(child.cut(pos, start));
}
var textNode = child.cut(start, end);
if (fullValue && capturedValue) {
var startSpaces = fullValue.search(/\S/);
var textStart = start + fullValue.indexOf(capturedValue);
var textEnd = textStart + capturedValue.length;
if (startSpaces) {
nodes.push(child.cut(start, start + startSpaces));
}
textNode = child.cut(textStart, textEnd);
}
transformer({
nodes,
rule,
textNode,
match,
schema
});
transformed = true;
pos = end;
}
transformer({
nodes,
rule,
textNode,
match,
schema
});
transformed = true;
pos = end;
} catch (err) {
_iterator2.e(err);
} finally {
_iterator2.f();
}

@@ -259,18 +294,15 @@ if (text && pos < text.length) {

function markRuleTransformer(props) {
const {
nodes,
rule,
textNode,
match,
schema
} = props;
const {
transformMatch,
getAttributes,
markType
} = rule;
const attributes = isFunction(getAttributes) ? getAttributes(match, false) : getAttributes;
const text = textNode.text ?? "";
const mark = markType.create(attributes);
const transformedCapturedValue = transformMatch?.(match);
var _textNode$text;
var nodes = props.nodes,
rule = props.rule,
textNode = props.textNode,
match = props.match,
schema = props.schema;
var transformMatch = rule.transformMatch,
getAttributes = rule.getAttributes,
markType = rule.markType;
var attributes = isFunction(getAttributes) ? getAttributes(match, false) : getAttributes;
var text = (_textNode$text = textNode.text) !== null && _textNode$text !== void 0 ? _textNode$text : "";
var mark = markType.create(attributes);
var transformedCapturedValue = transformMatch === null || transformMatch === void 0 ? void 0 : transformMatch(match);
if (transformedCapturedValue === "") {

@@ -283,41 +315,34 @@ return;

}
const marks = mark.addToSet(textNode.marks);
nodes.push(schema.text(transformedCapturedValue ?? text, marks));
var marks = mark.addToSet(textNode.marks);
nodes.push(schema.text(transformedCapturedValue !== null && transformedCapturedValue !== void 0 ? transformedCapturedValue : text, marks));
}
function textRuleTransformer(props) {
const {
nodes,
rule,
textNode,
match,
schema
} = props;
const {
transformMatch
} = rule;
const transformedCapturedValue = transformMatch?.(match);
var _ref;
var nodes = props.nodes,
rule = props.rule,
textNode = props.textNode,
match = props.match,
schema = props.schema;
var transformMatch = rule.transformMatch;
var transformedCapturedValue = transformMatch === null || transformMatch === void 0 ? void 0 : transformMatch(match);
if (transformedCapturedValue === "" || transformedCapturedValue === false) {
return;
}
const text = transformedCapturedValue ?? textNode.text ?? "";
var text = (_ref = transformedCapturedValue !== null && transformedCapturedValue !== void 0 ? transformedCapturedValue : textNode.text) !== null && _ref !== void 0 ? _ref : "";
nodes.push(schema.text(text, textNode.marks));
}
function nodeRuleTransformer(props) {
const {
nodes,
rule,
textNode,
match
} = props;
const {
getAttributes,
nodeType,
getContent
} = rule;
const attributes = isFunction(getAttributes) ? getAttributes(match, false) : getAttributes;
const content = (getContent ? getContent(match) : textNode) || void 0;
var nodes = props.nodes,
rule = props.rule,
textNode = props.textNode,
match = props.match;
var getAttributes = rule.getAttributes,
nodeType = rule.nodeType,
getContent = rule.getContent;
var attributes = isFunction(getAttributes) ? getAttributes(match, false) : getAttributes;
var content = (getContent ? getContent(match) : textNode) || void 0;
nodes.push(nodeType.createChecked(attributes, content));
}
function regexPasteRuleHandler(fragment, rule, schema) {
const nodes = [];
var nodes = [];
switch (rule.type) {

@@ -348,5 +373,6 @@ case "mark":

}
function isInCode(selection, {
contained = true
} = {}) {
function isInCode(selection) {
var _ref2 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
_ref2$contained = _ref2.contained,
contained = _ref2$contained === void 0 ? true : _ref2$contained;
if (selection.empty) {

@@ -361,11 +387,29 @@ return resolvedPosInCode(selection.$head);

function resolvedPosInCode($pos) {
for (const depth of range($pos.depth, 1)) {
if (isCodeNode($pos.node(depth))) {
return true;
var _iterator3 = _createForOfIteratorHelper(range($pos.depth, 1)),
_step3;
try {
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
var depth = _step3.value;
if (isCodeNode($pos.node(depth))) {
return true;
}
}
} catch (err) {
_iterator3.e(err);
} finally {
_iterator3.f();
}
for (const mark of $pos.marks()) {
if (isCodeMark(mark)) {
return true;
var _iterator4 = _createForOfIteratorHelper($pos.marks()),
_step4;
try {
for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
var mark = _step4.value;
if (isCodeMark(mark)) {
return true;
}
}
} catch (err) {
_iterator4.e(err);
} finally {
_iterator4.f();
}

@@ -375,18 +419,19 @@ return false;

function isCodeNode(node) {
return node.type.spec.code || node.type.spec.group?.split(" ").includes("code");
var _node$type$spec$group;
return node.type.spec.code || ((_node$type$spec$group = node.type.spec.group) === null || _node$type$spec$group === void 0 ? void 0 : _node$type$spec$group.split(" ").includes("code"));
}
function isCodeMark(mark) {
return mark.type.name === "code" || mark.type.spec.group?.split(" ").includes("code");
var _mark$type$spec$group;
return mark.type.name === "code" || ((_mark$type$spec$group = mark.type.spec.group) === null || _mark$type$spec$group === void 0 ? void 0 : _mark$type$spec$group.split(" ").includes("code"));
}
function getDataTransferFiles(event) {
const {
dataTransfer
} = event;
var _dataTransfer$files, _dataTransfer$items;
var dataTransfer = event.dataTransfer;
if (!dataTransfer) {
return [];
}
if (dataTransfer.files?.length > 0) {
if (((_dataTransfer$files = dataTransfer.files) === null || _dataTransfer$files === void 0 ? void 0 : _dataTransfer$files.length) > 0) {
return [...dataTransfer.files];
}
if (dataTransfer.items?.length) {
if ((_dataTransfer$items = dataTransfer.items) !== null && _dataTransfer$items !== void 0 && _dataTransfer$items.length) {
return [...dataTransfer.items].map(item => item.getAsFile()).filter(item => !!item);

@@ -397,5 +442,5 @@ }

function fixSliceOpening(slice) {
const max = Slice.maxOpen(slice.content);
var max = Slice.maxOpen(slice.content);
return max.openStart < slice.openStart || max.openEnd < slice.openEnd ? max : slice;
}
export { isInCode, pasteRules };
{
"name": "prosemirror-paste-rules",
"version": "3.0.0-beta.1",
"version": "3.0.0-beta.2",
"description": "Better handling of pasted content in your prosemirror editor.",

@@ -34,4 +34,4 @@ "homepage": "https://github.com/remirror/remirror/tree/HEAD/packages/prosemirror-paste-rules",

"@babel/runtime": "^7.22.3",
"@remirror/core-constants": "3.0.0-beta.0",
"@remirror/core-helpers": "4.0.0-beta.0",
"@remirror/core-constants": "3.0.0-beta.1",
"@remirror/core-helpers": "4.0.0-beta.1",
"escape-string-regexp": "^4.0.0"

@@ -38,0 +38,0 @@ },

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc