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

@guardian/prosemirror-noting

Package Overview
Dependencies
Maintainers
16
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@guardian/prosemirror-noting - npm Package Compare versions

Comparing version 3.0.0 to 3.0.1

.vs/slnx.sqlite

251

dist/noting.js

@@ -8,3 +8,5 @@ 'use strict';

var prosemirrorState = require('prosemirror-state');
var prosemirrorModel = require('prosemirror-model');
var uuid = _interopDefault(require('uuid/v1'));
var v4 = _interopDefault(require('uuid/v4'));
var prosemirrorView = require('prosemirror-view');

@@ -224,2 +226,152 @@

// which is expected to return a node - either the same one or a modified one -
// which is then added in place of the old node
var updateFragmentNodes = function updateFragmentNodes(updater) {
return function (prevFrag) {
var frag = prosemirrorModel.Fragment.empty;
var appendNodeToFragment = function appendNodeToFragment(node) {
return frag = frag.append(prosemirrorModel.Fragment.from(node));
};
prevFrag.forEach(function (node) {
return appendNodeToFragment(node.copy(updateFragmentNodes(updater)(updater(node).content)));
});
return frag;
};
}; // Changes the attributes on a Mark or MarkType on a node if it exists on that
// node
var updateNodeMarkAttrs = function updateNodeMarkAttrs(node, mark) {
var attrs = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
return mark.isInSet(node.marks) ? node.mark(mark.removeFromSet(node.marks).concat(mark.type.create(Object.assign(mark.attrs, attrs)))) : node;
}; // ensures that there are no notes in the document that have the same note id
// in non-contiguous places, which would result in one large note between the
// extremes of those places on certain edits
// e.g. <note id="1">test</note> some <note id="1">stuff</note>
// results in
// e.g. <note id="1">test</note> some <note id="2">stuff</note>
var sanitizeFragment = function sanitizeFragment(frag, markType) {
var getId = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : v4;
var idMap = {}; // the current id of the node according to the input document
var currentNoteId = null;
var setNewId = function setNewId(prevId) {
var newId = !idMap[prevId] ? prevId : getId();
idMap[prevId] = newId;
currentNoteId = prevId;
return newId;
}; // This will return an updated id for this id depending on whether it's been
// seen before in a previous non-contiguous note range, if it's been seen
// before then a new id will be generated and used for this id while the range
// is contiguous
var getAdjustNoteId = function getAdjustNoteId(id) {
if (id === currentNoteId) {
return idMap[id];
}
return setNewId(id);
};
var closeNote = function closeNote() {
currentNoteId = null;
};
return updateFragmentNodes(function (node) {
var noteMark = markType.isInSet(node.marks);
if (noteMark) {
return updateNodeMarkAttrs(node, noteMark, {
id: getAdjustNoteId(noteMark.attrs.id)
});
} // if we're in a text node and we don't have a noteMark then assume we are
// not in a note and close the range
if (node.isText) {
closeNote();
}
return node;
})(frag);
}; // Similar to sanitizeFragment but allows a node to be passed instead
var sanitizeNode = function sanitizeNode(node, markType, getId) {
return node.copy(sanitizeFragment(node.content, markType, getId));
}; // Return an array of all of the new ranges in a document [[start, end], ...]
var getInsertedRanges = function getInsertedRanges(_ref) {
var mapping = _ref.mapping;
var ranges = [];
mapping.maps.forEach(function (stepMap, i) {
stepMap.forEach(function (oldStart, oldEnd, newStart, newEnd) {
ranges.push([mapping.slice(i + 1).map(newStart), mapping.slice(i + 1).map(newEnd)]);
});
});
return ranges;
};
var charsAdded = function charsAdded(oldState, state) {
return state.doc.textContent.length - oldState.doc.textContent.length;
};
/*
* This takes a doc node and a marktype and hunts for them (assuming the have an id
* on their attrs) and merges their start and ends (for use with the note tracker)
*
* Unlike sanitizeNode, this will not look for contiguosness when finding the
* notes as this helper assumes that the consuming code is not interested in
* sanitizing the code. This should not pose any problems as long as notes
* are getting sanitized on load and on paste.
*/
var notesFromDoc = function notesFromDoc(doc, markType) {
var min = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
var max = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
var notes = {};
var _ref2 = new prosemirrorState.AllSelection(doc),
from = _ref2.from,
to = _ref2.to;
var _min = min === false ? from : min;
var _max = max === false ? to : max;
doc.nodesBetween(_min, _max, function (node, start) {
var end = start + node.nodeSize;
var mark = markType.isInSet(node.marks);
if (mark) {
var _mark$attrs = mark.attrs,
id = _mark$attrs.id,
meta = _mark$attrs.meta;
notes[id] = notes[id] || {
id: id,
meta: meta,
// this should be the same across all notes so just set it here
nodes: [],
start: Infinity,
end: -Infinity
};
notes[id] = Object.assign({}, notes[id], {
start: Math.min(notes[id].start, start),
end: Math.max(notes[id].end, end),
nodes: _toConsumableArray(notes[id].nodes).concat([{
start: start,
end: end
}])
});
}
});
return Object.keys(notes).map(function (id) {
return notes[id];
});
};
var ensureType = function ensureType(meta) {

@@ -419,18 +571,24 @@ if (!meta) {

key: "rebuildRange",
value: function rebuildRange(oldState, state) {
var start = oldState.doc.content.findDiffStart(state.doc.content);
value: function rebuildRange(state) {
var ranges = getInsertedRanges(state);
if (start) {
var end = oldState.doc.content.findDiffEnd(state.doc.content).b;
if (start < end) {
return this.mergeableRange(start, end);
} else if (oldState.doc.nodeSize < state.doc.nodeSize) {
// make sure we're over-zealous with our rebuild size
var diff = state.doc.nodeSize - oldState.doc.nodeSize;
return this.mergeableRange(start, start + diff);
}
if (!ranges.length) {
return false;
}
return false;
var start = ranges.reduce(function (acc, _ref5) {
var _ref6 = _slicedToArray(_ref5, 2),
from = _ref6[0],
to = _ref6[1];
return Math.min(acc, from, to);
}, Infinity);
var end = ranges.reduce(function (acc, _ref7) {
var _ref8 = _slicedToArray(_ref7, 2),
from = _ref8[0],
to = _ref8[1];
return Math.max(acc, from, to);
}, -Infinity);
return start < end ? this.mergeableRange(start, end) : false;
}

@@ -442,54 +600,2 @@ }]);

var charsAdded = function charsAdded(oldState, state) {
return state.doc.textContent.length - oldState.doc.textContent.length;
};
/*
* This takes a doc node and a marktype and hunts for them (assuming the have an id
* on their attrs) and merges their start and ends (for use with the note tracker)
*/
var notesFromDoc = function notesFromDoc(doc, markType) {
var min = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
var max = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
var notes = {};
var _ref = new prosemirrorState.AllSelection(doc),
from = _ref.from,
to = _ref.to;
var _min = min === false ? from : min;
var _max = max === false ? to : max;
doc.nodesBetween(_min, _max, function (node, start) {
var end = start + node.nodeSize;
var mark = markType.isInSet(node.marks);
if (mark) {
var _mark$attrs = mark.attrs,
id = _mark$attrs.id,
meta = _mark$attrs.meta;
notes[id] = notes[id] || {
id: id,
meta: meta,
// this should be the same across all notes so just set it here
nodes: [],
start: Infinity,
end: -Infinity
};
notes[id] = Object.assign({}, notes[id], {
start: Math.min(notes[id].start, start),
end: Math.max(notes[id].end, end),
nodes: _toConsumableArray(notes[id].nodes).concat([{
start: start,
end: end
}])
});
}
});
return Object.keys(notes).map(function (id) {
return notes[id];
});
};
var NoteTransaction =

@@ -534,3 +640,3 @@ /*#__PURE__*/

} else if (tr.getMeta("paste") || tr.getMeta(this.historyPlugin)) {
this.handlePaste(oldState);
this.handlePaste();
} else {

@@ -765,7 +871,7 @@ this.handleInput(oldState);

key: "handlePaste",
value: function handlePaste(oldState) {
value: function handlePaste() {
var noteTracker = this.noteTracker,
tr = this.tr,
markType = this.markType;
var rebuildRange = noteTracker.rebuildRange(oldState, tr);
var rebuildRange = noteTracker.rebuildRange(tr);

@@ -1355,3 +1461,9 @@ if (rebuildRange) {

decorations: noteDecorator,
handleClick: handleClick && clickHandler(noteTracker, handleClick)
handleClick: handleClick && clickHandler(noteTracker, handleClick),
transformPasted: function transformPasted(_ref5) {
var content = _ref5.content,
openStart = _ref5.openStart,
openEnd = _ref5.openEnd;
return new prosemirrorModel.Slice(sanitizeFragment(content, markType), openStart, openEnd);
}
},

@@ -1376,1 +1488,2 @@ filterTransaction: function filterTransaction() {

exports.toggleNote = toggleNote;
exports.sanitizeNode = sanitizeNode;
{
"name": "@guardian/prosemirror-noting",
"version": "3.0.0",
"version": "3.0.1",
"description": "A plugin to allow noting in prosemirror",

@@ -5,0 +5,0 @@ "main": "dist/noting.js",

import { Plugin } from "prosemirror-state";
import { Slice } from "prosemirror-model";
import NoteTracker from "./NoteTracker";

@@ -6,3 +7,7 @@ import NoteTransaction from "./NoteTransaction";

import clickHandler from "./clickHandler";
import { notesFromDoc } from "./utils/StateUtils";
import {
notesFromDoc,
sanitizeNode,
sanitizeFragment
} from "./utils/StateUtils";
import { createNoteMark } from "./utils/SchemaUtils";

@@ -133,3 +138,5 @@ import SharedNoteStateTracker from "./SharedNoteStateTracker";

decorations: noteDecorator,
handleClick: handleClick && clickHandler(noteTracker, handleClick)
handleClick: handleClick && clickHandler(noteTracker, handleClick),
transformPasted: ({ content, openStart, openEnd }) =>
new Slice(sanitizeFragment(content, markType), openStart, openEnd)
},

@@ -148,2 +155,2 @@ filterTransaction: (...args) =>

export { createNoteMark, buildNoter, toggleNote };
export { createNoteMark, buildNoter, toggleNote, sanitizeNode };
import Note from "./Note";
import uuid from "uuid/v1";
import { cloneDeep } from "./utils/helpers";
import { getInsertedRanges } from "./utils/StateUtils";

@@ -157,17 +158,21 @@ const ensureType = meta => {

rebuildRange(oldState, state) {
const start = oldState.doc.content.findDiffStart(state.doc.content);
rebuildRange(state) {
let ranges = getInsertedRanges(state);
if (start) {
const end = oldState.doc.content.findDiffEnd(state.doc.content).b;
if (start < end) {
return this.mergeableRange(start, end);
} else if (oldState.doc.nodeSize < state.doc.nodeSize) {
// make sure we're over-zealous with our rebuild size
const diff = state.doc.nodeSize - oldState.doc.nodeSize;
return this.mergeableRange(start, start + diff);
}
if (!ranges.length) {
return false;
}
return false;
const start = ranges.reduce(
(acc, [from, to]) => Math.min(acc, from, to),
Infinity
);
const end = ranges.reduce(
(acc, [from, to]) => Math.max(acc, from, to),
-Infinity
);
return start < end ? this.mergeableRange(start, end) : false;
}
}

@@ -34,3 +34,3 @@ import { Selection } from "prosemirror-state";

} else if (tr.getMeta("paste") || tr.getMeta(this.historyPlugin)) {
this.handlePaste(oldState);
this.handlePaste();
} else {

@@ -249,5 +249,5 @@ this.handleInput(oldState);

*/
handlePaste(oldState) {
handlePaste() {
const { noteTracker, tr, markType } = this;
const rebuildRange = noteTracker.rebuildRange(oldState, tr);
const rebuildRange = noteTracker.rebuildRange(tr);

@@ -254,0 +254,0 @@ if (rebuildRange) {

import { AllSelection } from "prosemirror-state";
import { Fragment } from "prosemirror-model";
import v4 from "uuid/v4";
// Runs through a Fragment's nodes and runs `updater` on them,
// which is expected to return a node - either the same one or a modified one -
// which is then added in place of the old node
const updateFragmentNodes = updater => prevFrag => {
let frag = Fragment.empty;
const appendNodeToFragment = node =>
(frag = frag.append(Fragment.from(node)));
prevFrag.forEach(node =>
appendNodeToFragment(
node.copy(updateFragmentNodes(updater)(updater(node).content))
)
);
return frag;
};
// Changes the attributes on a Mark or MarkType on a node if it exists on that
// node
const updateNodeMarkAttrs = (node, mark, attrs = {}) =>
mark.isInSet(node.marks)
? node.mark(
mark
.removeFromSet(node.marks)
.concat(mark.type.create(Object.assign(mark.attrs, attrs)))
)
: node;
// ensures that there are no notes in the document that have the same note id
// in non-contiguous places, which would result in one large note between the
// extremes of those places on certain edits
// e.g. <note id="1">test</note> some <note id="1">stuff</note>
// results in
// e.g. <note id="1">test</note> some <note id="2">stuff</note>
export const sanitizeFragment = (frag, markType, getId = v4) => {
let idMap = {};
// the current id of the node according to the input document
let currentNoteId = null;
const setNewId = prevId => {
const newId = !idMap[prevId] ? prevId : getId();
idMap[prevId] = newId;
currentNoteId = prevId;
return newId;
};
// This will return an updated id for this id depending on whether it's been
// seen before in a previous non-contiguous note range, if it's been seen
// before then a new id will be generated and used for this id while the range
// is contiguous
const getAdjustNoteId = id => {
if (id === currentNoteId) {
return idMap[id];
}
return setNewId(id);
};
const closeNote = () => {
currentNoteId = null;
};
return updateFragmentNodes(node => {
const noteMark = markType.isInSet(node.marks);
if (noteMark) {
return updateNodeMarkAttrs(node, noteMark, {
id: getAdjustNoteId(noteMark.attrs.id)
});
}
// if we're in a text node and we don't have a noteMark then assume we are
// not in a note and close the range
if (node.isText) {
closeNote();
}
return node;
})(frag);
};
// Similar to sanitizeFragment but allows a node to be passed instead
export const sanitizeNode = (node, markType, getId) =>
node.copy(sanitizeFragment(node.content, markType, getId));
// Return an array of all of the new ranges in a document [[start, end], ...]
export const getInsertedRanges = ({ mapping }) => {
let ranges = [];
mapping.maps.forEach((stepMap, i) => {
stepMap.forEach((oldStart, oldEnd, newStart, newEnd) => {
ranges.push([
mapping.slice(i + 1).map(newStart),
mapping.slice(i + 1).map(newEnd)
]);
});
});
return ranges;
};
export const charsAdded = (oldState, state) =>

@@ -7,5 +107,10 @@ state.doc.textContent.length - oldState.doc.textContent.length;

/*
* This takes a doc node and a marktype and hunts for them (assuming the have an id
* on their attrs) and merges their start and ends (for use with the note tracker)
*/
* This takes a doc node and a marktype and hunts for them (assuming the have an id
* on their attrs) and merges their start and ends (for use with the note tracker)
*
* Unlike sanitizeNode, this will not look for contiguosness when finding the
* notes as this helper assumes that the consuming code is not interested in
* sanitizing the code. This should not pose any problems as long as notes
* are getting sanitized on load and on paste.
*/
export const notesFromDoc = (doc, markType, min = false, max = false) => {

@@ -12,0 +117,0 @@ const notes = {};

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