lint: contentcollector

This commit is contained in:
John McLear 2021-01-14 11:24:59 +00:00
parent 183b765df0
commit 638bd9942e

View file

@ -31,45 +31,31 @@ const Changeset = require('./Changeset');
const hooks = require('./pluginfw/hooks'); const hooks = require('./pluginfw/hooks');
const _ = require('./underscore'); const _ = require('./underscore');
function sanitizeUnicode(s) { const sanitizeUnicode = (s) => UNorm.nfc(s);
return UNorm.nfc(s);
}
function makeContentCollector(collectStyles, abrowser, apool, domInterface, className2Author) {
abrowser = abrowser || {};
// I don't like the above.
const makeContentCollector = function (
collectStyles, abrowser, apool, domInterface, className2Author) {
const dom = domInterface || { const dom = domInterface || {
isNodeText(n) { isNodeText: (n) => (n.nodeType === 3),
return (n.nodeType == 3); nodeTagName: (n) => n.tagName,
}, nodeValue: (n) => n.nodeValue,
nodeTagName(n) { nodeNumChildren: (n) => {
return n.tagName;
},
nodeValue(n) {
return n.nodeValue;
},
nodeNumChildren(n) {
if (n.childNodes == null) return 0; if (n.childNodes == null) return 0;
return n.childNodes.length; return n.childNodes.length;
}, },
nodeChild(n, i) { nodeChild: (n, i) => {
if (n.childNodes.item == null) { if (n.childNodes.item == null) {
return n.childNodes[i]; return n.childNodes[i];
} }
return n.childNodes.item(i); return n.childNodes.item(i);
}, },
nodeProp(n, p) { nodeProp: (n, p) => n[p],
return n[p]; nodeAttr: (n, a) => {
},
nodeAttr(n, a) {
if (n.getAttribute != null) return n.getAttribute(a); if (n.getAttribute != null) return n.getAttribute(a);
if (n.attribs != null) return n.attribs[a]; if (n.attribs != null) return n.attribs[a];
return null; return null;
}, },
optNodeInnerHTML(n) { optNodeInnerHTML: (n) => n.innerHTML,
return n.innerHTML;
},
}; };
const _blockElems = { const _blockElems = {
@ -84,54 +70,41 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
_blockElems[element] = 1; _blockElems[element] = 1;
}); });
function isBlockElement(n) { const isBlockElement = (n) => !!_blockElems[(dom.nodeTagName(n) || '').toLowerCase()];
return !!_blockElems[(dom.nodeTagName(n) || '').toLowerCase()];
}
function textify(str) { const textify = (str) => sanitizeUnicode(
return sanitizeUnicode( str.replace(/(\n | \n)/g, ' ')
str.replace(/(\n | \n)/g, ' ').replace(/[\n\r ]/g, ' ').replace(/\xa0/g, ' ').replace(/\t/g, ' ')); .replace(/[\n\r ]/g, ' ')
} .replace(/\xa0/g, ' ')
.replace(/\t/g, ' '));
function getAssoc(node, name) { const getAssoc = (node, name) => dom.nodeProp(node, `_magicdom_${name}`);
return dom.nodeProp(node, `_magicdom_${name}`);
}
const lines = (function () { const lines = (() => {
const textArray = []; const textArray = [];
const attribsArray = []; const attribsArray = [];
let attribsBuilder = null; let attribsBuilder = null;
const op = Changeset.newOp('+'); const op = Changeset.newOp('+');
var self = { const self = {
length() { length: () => textArray.length,
return textArray.length; atColumnZero: () => textArray[textArray.length - 1] === '',
}, startNew: () => {
atColumnZero() {
return textArray[textArray.length - 1] === '';
},
startNew() {
textArray.push(''); textArray.push('');
self.flush(true); self.flush(true);
attribsBuilder = Changeset.smartOpAssembler(); attribsBuilder = Changeset.smartOpAssembler();
}, },
textOfLine(i) { textOfLine: (i) => textArray[i],
return textArray[i]; appendText: (txt, attrString) => {
},
appendText(txt, attrString) {
textArray[textArray.length - 1] += txt; textArray[textArray.length - 1] += txt;
// dmesg(txt+" / "+attrString); // dmesg(txt+" / "+attrString);
op.attribs = attrString; op.attribs = attrString;
op.chars = txt.length; op.chars = txt.length;
attribsBuilder.append(op); attribsBuilder.append(op);
}, },
textLines() { textLines: () => textArray.slice(),
return textArray.slice(); attribLines: () => attribsArray,
},
attribLines() {
return attribsArray;
},
// call flush only when you're done // call flush only when you're done
flush(withNewline) { flush: (withNewline) => {
if (attribsBuilder) { if (attribsBuilder) {
attribsArray.push(attribsBuilder.toString()); attribsArray.push(attribsBuilder.toString());
attribsBuilder = null; attribsBuilder = null;
@ -140,21 +113,24 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
}; };
self.startNew(); self.startNew();
return self; return self;
}()); })();
const cc = {}; const cc = {};
function _ensureColumnZero(state) { const _ensureColumnZero = (state) => {
if (!lines.atColumnZero()) { if (!lines.atColumnZero()) {
cc.startNewLine(state); cc.startNewLine(state);
} }
} };
let selection, startPoint, endPoint; let selection, startPoint, endPoint;
let selStart = [-1, -1]; let selStart = [-1, -1];
let selEnd = [-1, -1]; let selEnd = [-1, -1];
function _isEmpty(node, state) { const _isEmpty = (node, state) => {
// consider clean blank lines pasted in IE to be empty // consider clean blank lines pasted in IE to be empty
if (dom.nodeNumChildren(node) == 0) return true; if (dom.nodeNumChildren(node) === 0) return true;
if (dom.nodeNumChildren(node) == 1 && getAssoc(node, 'shouldBeEmpty') && dom.optNodeInnerHTML(node) == ' ' && !getAssoc(node, 'unpasted')) { if (dom.nodeNumChildren(node) === 1 &&
getAssoc(node, 'shouldBeEmpty') &&
dom.optNodeInnerHTML(node) === ' ' &&
!getAssoc(node, 'unpasted')) {
if (state) { if (state) {
const child = dom.nodeChild(node, 0); const child = dom.nodeChild(node, 0);
_reachPoint(child, 0, state); _reachPoint(child, 0, state);
@ -163,37 +139,37 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
return true; return true;
} }
return false; return false;
} };
function _pointHere(charsAfter, state) { const _pointHere = (charsAfter, state) => {
const ln = lines.length() - 1; const ln = lines.length() - 1;
let chr = lines.textOfLine(ln).length; let chr = lines.textOfLine(ln).length;
if (chr == 0 && !_.isEmpty(state.lineAttributes)) { if (chr === 0 && !_.isEmpty(state.lineAttributes)) {
chr += 1; // listMarker chr += 1; // listMarker
} }
chr += charsAfter; chr += charsAfter;
return [ln, chr]; return [ln, chr];
} };
function _reachBlockPoint(nd, idx, state) { const _reachBlockPoint = (nd, idx, state) => {
if (!dom.isNodeText(nd)) _reachPoint(nd, idx, state); if (!dom.isNodeText(nd)) _reachPoint(nd, idx, state);
} };
function _reachPoint(nd, idx, state) { const _reachPoint = (nd, idx, state) => {
if (startPoint && nd == startPoint.node && startPoint.index == idx) { if (startPoint && nd === startPoint.node && startPoint.index === idx) {
selStart = _pointHere(0, state); selStart = _pointHere(0, state);
} }
if (endPoint && nd == endPoint.node && endPoint.index == idx) { if (endPoint && nd === endPoint.node && endPoint.index === idx) {
selEnd = _pointHere(0, state); selEnd = _pointHere(0, state);
} }
} };
cc.incrementFlag = function (state, flagName) { cc.incrementFlag = (state, flagName) => {
state.flags[flagName] = (state.flags[flagName] || 0) + 1; state.flags[flagName] = (state.flags[flagName] || 0) + 1;
}; };
cc.decrementFlag = function (state, flagName) { cc.decrementFlag = (state, flagName) => {
state.flags[flagName]--; state.flags[flagName]--;
}; };
cc.incrementAttrib = function (state, attribName) { cc.incrementAttrib = (state, attribName) => {
if (!state.attribs[attribName]) { if (!state.attribs[attribName]) {
state.attribs[attribName] = 1; state.attribs[attribName] = 1;
} else { } else {
@ -201,15 +177,15 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
} }
_recalcAttribString(state); _recalcAttribString(state);
}; };
cc.decrementAttrib = function (state, attribName) { cc.decrementAttrib = (state, attribName) => {
state.attribs[attribName]--; state.attribs[attribName]--;
_recalcAttribString(state); _recalcAttribString(state);
}; };
function _enterList(state, listType) { const _enterList = (state, listType) => {
if (!listType) return; if (!listType) return;
const oldListType = state.lineAttributes.list; const oldListType = state.lineAttributes.list;
if (listType != 'none') { if (listType !== 'none') {
state.listNesting = (state.listNesting || 0) + 1; state.listNesting = (state.listNesting || 0) + 1;
// reminder that listType can be "number2", "number3" etc. // reminder that listType can be "number2", "number3" etc.
if (listType.indexOf('number') !== -1) { if (listType.indexOf('number') !== -1) {
@ -224,36 +200,36 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
} }
_recalcAttribString(state); _recalcAttribString(state);
return oldListType; return oldListType;
} };
function _exitList(state, oldListType) { const _exitList = (state, oldListType) => {
if (state.lineAttributes.list) { if (state.lineAttributes.list) {
state.listNesting--; state.listNesting--;
} }
if (oldListType && oldListType != 'none') { if (oldListType && oldListType !== 'none') {
state.lineAttributes.list = oldListType; state.lineAttributes.list = oldListType;
} else { } else {
delete state.lineAttributes.list; delete state.lineAttributes.list;
delete state.lineAttributes.start; delete state.lineAttributes.start;
} }
_recalcAttribString(state); _recalcAttribString(state);
} };
function _enterAuthor(state, author) { const _enterAuthor = (state, author) => {
const oldAuthor = state.author; const oldAuthor = state.author;
state.authorLevel = (state.authorLevel || 0) + 1; state.authorLevel = (state.authorLevel || 0) + 1;
state.author = author; state.author = author;
_recalcAttribString(state); _recalcAttribString(state);
return oldAuthor; return oldAuthor;
} };
function _exitAuthor(state, oldAuthor) { const _exitAuthor = (state, oldAuthor) => {
state.authorLevel--; state.authorLevel--;
state.author = oldAuthor; state.author = oldAuthor;
_recalcAttribString(state); _recalcAttribString(state);
} };
function _recalcAttribString(state) { const _recalcAttribString = (state) => {
const lst = []; const lst = [];
for (const a in state.attribs) { for (const a in state.attribs) {
if (state.attribs[a]) { if (state.attribs[a]) {
@ -285,9 +261,9 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
} }
} }
state.attribString = Changeset.makeAttribsString('+', lst, apool); state.attribString = Changeset.makeAttribsString('+', lst, apool);
} };
function _produceLineAttributesMarker(state) { const _produceLineAttributesMarker = (state) => {
// TODO: This has to go to AttributeManager. // TODO: This has to go to AttributeManager.
const attributes = [ const attributes = [
['lmkr', '1'], ['lmkr', '1'],
@ -296,24 +272,24 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
_.map(state.lineAttributes, (value, key) => [key, value]) _.map(state.lineAttributes, (value, key) => [key, value])
); );
lines.appendText('*', Changeset.makeAttribsString('+', attributes, apool)); lines.appendText('*', Changeset.makeAttribsString('+', attributes, apool));
} };
cc.startNewLine = function (state) { cc.startNewLine = (state) => {
if (state) { if (state) {
const atBeginningOfLine = lines.textOfLine(lines.length() - 1).length == 0; const atBeginningOfLine = lines.textOfLine(lines.length() - 1).length === 0;
if (atBeginningOfLine && !_.isEmpty(state.lineAttributes)) { if (atBeginningOfLine && !_.isEmpty(state.lineAttributes)) {
_produceLineAttributesMarker(state); _produceLineAttributesMarker(state);
} }
} }
lines.startNew(); lines.startNew();
}; };
cc.notifySelection = function (sel) { cc.notifySelection = (sel) => {
if (sel) { if (sel) {
selection = sel; selection = sel;
startPoint = selection.startPoint; startPoint = selection.startPoint;
endPoint = selection.endPoint; endPoint = selection.endPoint;
} }
}; };
cc.doAttrib = function (state, na) { cc.doAttrib = (state, na) => {
state.localAttribs = (state.localAttribs || []); state.localAttribs = (state.localAttribs || []);
state.localAttribs.push(na); state.localAttribs.push(na);
cc.incrementAttrib(state, na); cc.incrementAttrib(state, na);
@ -343,9 +319,10 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
if (isBlock) _ensureColumnZero(state); if (isBlock) _ensureColumnZero(state);
const startLine = lines.length() - 1; const startLine = lines.length() - 1;
_reachBlockPoint(node, 0, state); _reachBlockPoint(node, 0, state);
if (dom.isNodeText(node)) { if (dom.isNodeText(node)) {
let txt = dom.nodeValue(node); let txt = dom.nodeValue(node);
var tname = dom.nodeAttr(node.parentNode, 'name'); const tname = dom.nodeAttr(node.parentNode, 'name');
const txtFromHook = hooks.callAll('collectContentLineText', { const txtFromHook = hooks.callAll('collectContentLineText', {
cc: this, cc: this,
@ -365,11 +342,11 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
let rest = ''; let rest = '';
let x = 0; // offset into original text let x = 0; // offset into original text
if (txt.length == 0) { if (txt.length === 0) {
if (startPoint && node == startPoint.node) { if (startPoint && node === startPoint.node) {
selStart = _pointHere(0, state); selStart = _pointHere(0, state);
} }
if (endPoint && node == endPoint.node) { if (endPoint && node === endPoint.node) {
selEnd = _pointHere(0, state); selEnd = _pointHere(0, state);
} }
} }
@ -382,10 +359,10 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
txt = firstLine; txt = firstLine;
} else { /* will only run this loop body once */ } else { /* will only run this loop body once */
} }
if (startPoint && node == startPoint.node && startPoint.index - x <= txt.length) { if (startPoint && node === startPoint.node && startPoint.index - x <= txt.length) {
selStart = _pointHere(startPoint.index - x, state); selStart = _pointHere(startPoint.index - x, state);
} }
if (endPoint && node == endPoint.node && endPoint.index - x <= txt.length) { if (endPoint && node === endPoint.node && endPoint.index - x <= txt.length) {
selEnd = _pointHere(endPoint.index - x, state); selEnd = _pointHere(endPoint.index - x, state);
} }
let txt2 = txt; let txt2 = txt;
@ -396,7 +373,7 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
// removing "\n" from pasted HTML will collapse words together. // removing "\n" from pasted HTML will collapse words together.
txt2 = ''; txt2 = '';
} }
const atBeginningOfLine = lines.textOfLine(lines.length() - 1).length == 0; const atBeginningOfLine = lines.textOfLine(lines.length() - 1).length === 0;
if (atBeginningOfLine) { if (atBeginningOfLine) {
// newlines in the source mustn't become spaces at beginning of line box // newlines in the source mustn't become spaces at beginning of line box
txt2 = txt2.replace(/^\n*/, ''); txt2 = txt2.replace(/^\n*/, '');
@ -412,10 +389,13 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
} }
} }
} else { } else {
var tname = (dom.nodeTagName(node) || '').toLowerCase(); // Not a text node..
const tname = (dom.nodeTagName(node) || '').toLowerCase();
const styl = dom.nodeAttr(node, 'style');
const cls = dom.nodeAttr(node, 'class');
if (tname == 'img') { if (tname === 'img') {
const collectContentImage = hooks.callAll('collectContentImage', { hooks.callAll('collectContentImage', {
cc, cc,
state, state,
tname, tname,
@ -425,8 +405,7 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
}); });
// cc.doAttrib(state, 'image:foo.png'); // cc.doAttrib(state, 'image:foo.png');
state.lineAttributes.img = 'foo.png'; state.lineAttributes.img = 'foo.png';
} else if (tname === 'br') {
} else if (tname == 'br') {
this.breakLine = true; this.breakLine = true;
const tvalue = dom.nodeAttr(node, 'value'); const tvalue = dom.nodeAttr(node, 'value');
const induceLineBreak = hooks.callAll('collectContentLineBreak', { const induceLineBreak = hooks.callAll('collectContentLineBreak', {
@ -437,16 +416,18 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
styl: null, styl: null,
cls: null, cls: null,
}); });
const startNewLine = (typeof (induceLineBreak) === 'object' && induceLineBreak.length == 0) ? true : induceLineBreak[0]; const startNewLine = (
typeof (induceLineBreak) === 'object' &&
induceLineBreak.length === 0) ? true : induceLineBreak[0];
if (startNewLine) { if (startNewLine) {
cc.startNewLine(state); cc.startNewLine(state);
} }
} else if (tname == 'script' || tname == 'style') { } else if (tname === 'script' || tname === 'style') {
// ignore // ignore
} else if (!isEmpty) { } else if (!isEmpty) {
var styl = dom.nodeAttr(node, 'style'); let styl = dom.nodeAttr(node, 'style');
var cls = dom.nodeAttr(node, 'class'); let cls = dom.nodeAttr(node, 'class');
let isPre = (tname == 'pre'); let isPre = (tname === 'pre');
if ((!isPre) && abrowser.safari) { if ((!isPre) && abrowser.safari) {
isPre = (styl && /\bwhite-space:\s*pre\b/i.exec(styl)); isPre = (styl && /\bwhite-space:\s*pre\b/i.exec(styl));
} }
@ -459,7 +440,8 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
styl = null; styl = null;
cls = null; cls = null;
// We have to return here but this could break things in the future, for now it shows how to fix the problem // We have to return here but this could break things in the future,
// for now it shows how to fix the problem
return; return;
} }
@ -471,29 +453,39 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
styl, styl,
cls, cls,
}); });
if (tname == 'b' || (styl && /\bfont-weight:\s*bold\b/i.exec(styl)) || tname == 'strong') { if (tname === 'b' ||
(styl && /\bfont-weight:\s*bold\b/i.exec(styl)) ||
tname === 'strong') {
cc.doAttrib(state, 'bold'); cc.doAttrib(state, 'bold');
} }
if (tname == 'i' || (styl && /\bfont-style:\s*italic\b/i.exec(styl)) || tname == 'em') { if (tname === 'i' ||
(styl && /\bfont-style:\s*italic\b/i.exec(styl)) ||
tname === 'em') {
cc.doAttrib(state, 'italic'); cc.doAttrib(state, 'italic');
} }
if (tname == 'u' || (styl && /\btext-decoration:\s*underline\b/i.exec(styl)) || tname == 'ins') { if (tname === 'u' ||
(styl && /\btext-decoration:\s*underline\b/i.exec(styl)) ||
tname === 'ins') {
cc.doAttrib(state, 'underline'); cc.doAttrib(state, 'underline');
} }
if (tname == 's' || (styl && /\btext-decoration:\s*line-through\b/i.exec(styl)) || tname == 'del') { if (tname === 's' ||
(styl && /\btext-decoration:\s*line-through\b/i.exec(styl)) ||
tname === 'del') {
cc.doAttrib(state, 'strikethrough'); cc.doAttrib(state, 'strikethrough');
} }
if (tname == 'ul' || tname == 'ol') { let type;
if (tname === 'ul' || tname === 'ol') {
if (node.attribs) { if (node.attribs) {
var type = node.attribs.class; type = node.attribs.class;
} else { } else {
var type = null; type = null;
} }
const rr = cls && /(?:^| )list-([a-z]+[0-9]+)\b/.exec(cls); const rr = cls && /(?:^| )list-([a-z]+[0-9]+)\b/.exec(cls);
// lists do not need to have a type, so before we make a wrong guess, check if we find a better hint within the node's children // lists do not need to have a type, so before we make a wrong guess
// check if we find a better hint within the node's children
if (!rr && !type) { if (!rr && !type) {
for (var i in node.children) { for (const i in node.children) {
if (node.children[i] && node.children[i].name == 'ul') { if (node.children[i] && node.children[i].name === 'ul') {
type = node.children[i].attribs.class; type = node.children[i].attribs.class;
if (type) { if (type) {
break; break;
@ -504,8 +496,14 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
if (rr && rr[1]) { if (rr && rr[1]) {
type = rr[1]; type = rr[1];
} else { } else {
if (tname == 'ul') { if (tname === 'ul') {
if ((type && type.match('indent')) || (node.attribs && node.attribs.class && node.attribs.class.match('indent'))) { if ((type && type.match('indent')) ||
(
node.attribs &&
node.attribs.class &&
node.attribs.class.match('indent')
)
) {
type = 'indent'; type = 'indent';
} else { } else {
type = 'bullet'; type = 'bullet';
@ -516,7 +514,7 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
type += String(Math.min(_MAX_LIST_LEVEL, (state.listNesting || 0) + 1)); type += String(Math.min(_MAX_LIST_LEVEL, (state.listNesting || 0) + 1));
} }
oldListTypeOrNull = (_enterList(state, type) || 'none'); oldListTypeOrNull = (_enterList(state, type) || 'none');
} else if ((tname == 'div' || tname == 'p') && cls && cls.match(/(?:^| )ace-line\b/)) { } else if ((tname === 'div' || tname === 'p') && cls && cls.match(/(?:^| )ace-line\b/)) {
// This has undesirable behavior in Chrome but is right in other browsers. // This has undesirable behavior in Chrome but is right in other browsers.
// See https://github.com/ether/etherpad-lite/issues/2412 for reasoning // See https://github.com/ether/etherpad-lite/issues/2412 for reasoning
if (!abrowser.chrome) oldListTypeOrNull = (_enterList(state, type) || 'none'); if (!abrowser.chrome) oldListTypeOrNull = (_enterList(state, type) || 'none');
@ -564,8 +562,8 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
if (className2Author && cls) { if (className2Author && cls) {
const classes = cls.match(/\S+/g); const classes = cls.match(/\S+/g);
if (classes && classes.length > 0) { if (classes && classes.length > 0) {
for (var i = 0; i < classes.length; i++) { for (let i = 0; i < classes.length; i++) {
var c = classes[i]; const c = classes[i];
const a = className2Author(c); const a = className2Author(c);
if (a) { if (a) {
oldAuthorOrNull = (_enterAuthor(state, a) || 'none'); oldAuthorOrNull = (_enterAuthor(state, a) || 'none');
@ -577,8 +575,8 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
} }
const nc = dom.nodeNumChildren(node); const nc = dom.nodeNumChildren(node);
for (var i = 0; i < nc; i++) { for (let i = 0; i < nc; i++) {
var c = dom.nodeChild(node, i); const c = dom.nodeChild(node, i);
cc.collectContent(c, state); cc.collectContent(c, state);
} }
@ -594,7 +592,7 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
if (isPre) cc.decrementFlag(state, 'preMode'); if (isPre) cc.decrementFlag(state, 'preMode');
if (state.localAttribs) { if (state.localAttribs) {
for (var i = 0; i < state.localAttribs.length; i++) { for (let i = 0; i < state.localAttribs.length; i++) {
cc.decrementAttrib(state, state.localAttribs[i]); cc.decrementAttrib(state, state.localAttribs[i]);
} }
} }
@ -608,7 +606,7 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
} }
_reachBlockPoint(node, 1, state); _reachBlockPoint(node, 1, state);
if (isBlock) { if (isBlock) {
if (lines.length() - 1 == startLine) { if (lines.length() - 1 === startLine) {
// added additional check to resolve https://github.com/JohnMcLear/ep_copy_paste_images/issues/20 // added additional check to resolve https://github.com/JohnMcLear/ep_copy_paste_images/issues/20
// this does mean that images etc can't be pasted on lists but imho that's fine // this does mean that images etc can't be pasted on lists but imho that's fine
@ -625,7 +623,7 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
state.localAttribs = localAttribs; state.localAttribs = localAttribs;
}; };
// can pass a falsy value for end of doc // can pass a falsy value for end of doc
cc.notifyNextNode = function (node) { cc.notifyNextNode = (node) => {
// an "empty block" won't end a line; this addresses an issue in IE with // an "empty block" won't end a line; this addresses an issue in IE with
// typing into a blank line at the end of the document. typed text // typing into a blank line at the end of the document. typed text
// goes into the body, and the empty line div still looks clean. // goes into the body, and the empty line div still looks clean.
@ -636,21 +634,15 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
} }
}; };
// each returns [line, char] or [-1,-1] // each returns [line, char] or [-1,-1]
const getSelectionStart = function () { const getSelectionStart = () => selStart;
return selStart; const getSelectionEnd = () => selEnd;
};
const getSelectionEnd = function () {
return selEnd;
};
// returns array of strings for lines found, last entry will be "" if // returns array of strings for lines found, last entry will be "" if
// last line is complete (i.e. if a following span should be on a new line). // last line is complete (i.e. if a following span should be on a new line).
// can be called at any point // can be called at any point
cc.getLines = function () { cc.getLines = () => lines.textLines();
return lines.textLines();
};
cc.finish = function () { cc.finish = () => {
lines.flush(); lines.flush();
const lineAttribs = lines.attribLines(); const lineAttribs = lines.attribLines();
const lineStrings = cc.getLines(); const lineStrings = cc.getLines();
@ -661,17 +653,17 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
const ss = getSelectionStart(); const ss = getSelectionStart();
const se = getSelectionEnd(); const se = getSelectionEnd();
function fixLongLines() { const fixLongLines = () => {
// design mode does not deal with with really long lines! // design mode does not deal with with really long lines!
const lineLimit = 2000; // chars const lineLimit = 2000; // chars
const buffer = 10; // chars allowed over before wrapping const buffer = 10; // chars allowed over before wrapping
let linesWrapped = 0; let linesWrapped = 0;
let numLinesAfter = 0; let numLinesAfter = 0;
for (var i = lineStrings.length - 1; i >= 0; i--) { for (let i = lineStrings.length - 1; i >= 0; i--) {
let oldString = lineStrings[i]; let oldString = lineStrings[i];
let oldAttribString = lineAttribs[i]; let oldAttribString = lineAttribs[i];
if (oldString.length > lineLimit + buffer) { if (oldString.length > lineLimit + buffer) {
var newStrings = []; const newStrings = [];
const newAttribStrings = []; const newAttribStrings = [];
while (oldString.length > lineLimit) { while (oldString.length > lineLimit) {
// var semiloc = oldString.lastIndexOf(';', lineLimit-1); // var semiloc = oldString.lastIndexOf(';', lineLimit-1);
@ -687,13 +679,13 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
newAttribStrings.push(oldAttribString); newAttribStrings.push(oldAttribString);
} }
function fixLineNumber(lineChar) { const fixLineNumber = (lineChar) => {
if (lineChar[0] < 0) return; if (lineChar[0] < 0) return;
let n = lineChar[0]; let n = lineChar[0];
let c = lineChar[1]; let c = lineChar[1];
if (n > i) { if (n > i) {
n += (newStrings.length - 1); n += (newStrings.length - 1);
} else if (n == i) { } else if (n === i) {
let a = 0; let a = 0;
while (c > newStrings[a].length) { while (c > newStrings[a].length) {
c -= newStrings[a].length; c -= newStrings[a].length;
@ -703,13 +695,14 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
} }
lineChar[0] = n; lineChar[0] = n;
lineChar[1] = c; lineChar[1] = c;
} };
fixLineNumber(ss); fixLineNumber(ss);
fixLineNumber(se); fixLineNumber(se);
linesWrapped++; linesWrapped++;
numLinesAfter += newStrings.length; numLinesAfter += newStrings.length;
newStrings.unshift(i, 1); newStrings.unshift(i, 1);
// Still to fix linting issue below.
lineStrings.splice.apply(lineStrings, newStrings); lineStrings.splice.apply(lineStrings, newStrings);
newAttribStrings.unshift(i, 1); newAttribStrings.unshift(i, 1);
lineAttribs.splice.apply(lineAttribs, newAttribStrings); lineAttribs.splice.apply(lineAttribs, newAttribStrings);
@ -719,7 +712,7 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
linesWrapped, linesWrapped,
numLinesAfter, numLinesAfter,
}; };
} };
const wrapData = fixLongLines(); const wrapData = fixLongLines();
return { return {
@ -733,7 +726,7 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
}; };
return cc; return cc;
} };
exports.sanitizeUnicode = sanitizeUnicode; exports.sanitizeUnicode = sanitizeUnicode;
exports.makeContentCollector = makeContentCollector; exports.makeContentCollector = makeContentCollector;