lint: domline

This commit is contained in:
John McLear 2021-01-14 13:20:29 +00:00
parent 5bedfa0ba1
commit f466bcd32f

View file

@ -26,17 +26,17 @@ const Security = require('./security');
const hooks = require('./pluginfw/hooks'); const hooks = require('./pluginfw/hooks');
const _ = require('./underscore'); const _ = require('./underscore');
const lineAttributeMarker = require('./linestylefilter').lineAttributeMarker; const lineAttributeMarker = require('./linestylefilter').lineAttributeMarker;
const noop = function () {}; const noop = () => {};
const domline = {}; const domline = {};
domline.addToLineClass = function (lineClass, cls) { domline.addToLineClass = (lineClass, cls) => {
// an "empty span" at any point can be used to add classes to // an "empty span" at any point can be used to add classes to
// the line, using line:className. otherwise, we ignore // the line, using line:className. otherwise, we ignore
// the span. // the span.
cls.replace(/\S+/g, (c) => { cls.replace(/\S+/g, (c) => {
if (c.indexOf('line:') == 0) { if (c.indexOf('line:') === 0) {
// add class to line // add class to line
lineClass = (lineClass ? `${lineClass} ` : '') + c.substring(5); lineClass = (lineClass ? `${lineClass} ` : '') + c.substring(5);
} }
@ -46,7 +46,7 @@ domline.addToLineClass = function (lineClass, cls) {
// if "document" is falsy we don't create a DOM node, just // if "document" is falsy we don't create a DOM node, just
// an object with innerHTML and className // an object with innerHTML and className
domline.createDomLine = function (nonEmpty, doesWrap, optBrowser, optDocument) { domline.createDomLine = (nonEmpty, doesWrap, optBrowser, optDocument) => {
const result = { const result = {
node: null, node: null,
appendSpan: noop, appendSpan: noop,
@ -73,22 +73,19 @@ domline.createDomLine = function (nonEmpty, doesWrap, optBrowser, optDocument) {
let postHtml = ''; let postHtml = '';
let curHTML = null; let curHTML = null;
function processSpaces(s) { const processSpaces = (s) => domline.processSpaces(s, doesWrap);
return domline.processSpaces(s, doesWrap);
}
const perTextNodeProcess = (doesWrap ? _.identity : processSpaces); const perTextNodeProcess = (doesWrap ? _.identity : processSpaces);
const perHtmlLineProcess = (doesWrap ? processSpaces : _.identity); const perHtmlLineProcess = (doesWrap ? processSpaces : _.identity);
let lineClass = 'ace-line'; let lineClass = 'ace-line';
result.appendSpan = function (txt, cls) { result.appendSpan = (txt, cls) => {
console.log("cls", cls);
// console.log("domline", domline, "txt", txt, "cls", cls) // console.log("domline", domline, "txt", txt, "cls", cls)
let processedMarker = false; let processedMarker = false;
// Handle lineAttributeMarker, if present // Handle lineAttributeMarker, if present
if (cls.indexOf(lineAttributeMarker) >= 0) { if (cls.indexOf(lineAttributeMarker) >= 0) {
let listType = /(?:^| )list:(\S+)/.exec(cls); let listType = /(?:^| )list:(\S+)/.exec(cls);
const start = /(?:^| )start:(\S+)/.exec(cls); const start = /(?:^| )start:(\S+)/.exec(cls);
const img = /(?:^| )img:(\S+)/.exec(cls);
_.map(hooks.callAll('aceDomLinePreProcessLineAttributes', { _.map(hooks.callAll('aceDomLinePreProcessLineAttributes', {
domline, domline,
@ -99,7 +96,9 @@ console.log("cls", cls);
processedMarker |= modifier.processedMarker; processedMarker |= modifier.processedMarker;
}); });
if (img) {
// do some shit with an image... cake
}
if (listType) { if (listType) {
listType = listType[1]; listType = listType[1];
@ -109,12 +108,15 @@ console.log("cls", cls);
postHtml = `</li></ul>${postHtml}`; postHtml = `</li></ul>${postHtml}`;
} else { } else {
if (start) { // is it a start of a list with more than one item in? if (start) { // is it a start of a list with more than one item in?
if (start[1] == 1) { // if its the first one at this level? if (start[1] === 1) { // if its the first one at this level?
lineClass = `${lineClass} ` + `list-start-${listType}`; // Add start class to DIV node // Add start class to DIV node
lineClass = `${lineClass} ` + `list-start-${listType}`;
} }
preHtml += `<ol start=${start[1]} class="list-${Security.escapeHTMLAttribute(listType)}"><li>`; preHtml +=
`<ol start=${start[1]} class="list-${Security.escapeHTMLAttribute(listType)}"><li>`;
} else { } else {
preHtml += `<ol class="list-${Security.escapeHTMLAttribute(listType)}"><li>`; // Handles pasted contents into existing lists // Handles pasted contents into existing lists
preHtml += `<ol class="list-${Security.escapeHTMLAttribute(listType)}"><li>`;
} }
postHtml += '</li></ol>'; postHtml += '</li></ol>';
} }
@ -167,18 +169,20 @@ console.log("cls", cls);
} else if (txt) { } else if (txt) {
if (href) { if (href) {
const urn_schemes = new RegExp('^(about|geo|mailto|tel):'); const urn_schemes = new RegExp('^(about|geo|mailto|tel):');
if (!~href.indexOf('://') && !urn_schemes.test(href)) // if the url doesn't include a protocol prefix, assume http // if the url doesn't include a protocol prefix, assume http
{ if (!~href.indexOf('://') && !urn_schemes.test(href)) {
href = `http://${href}`; href = `http://${href}`;
} }
// Using rel="noreferrer" stops leaking the URL/location of the pad when clicking links in the document. // Using rel="noreferrer" stops leaking the URL/location of the pad when
// clicking links in the document.
// Not all browsers understand this attribute, but it's part of the HTML5 standard. // Not all browsers understand this attribute, but it's part of the HTML5 standard.
// https://html.spec.whatwg.org/multipage/links.html#link-type-noreferrer // https://html.spec.whatwg.org/multipage/links.html#link-type-noreferrer
// Additionally, we do rel="noopener" to ensure a higher level of referrer security. // Additionally, we do rel="noopener" to ensure a higher level of referrer security.
// https://html.spec.whatwg.org/multipage/links.html#link-type-noopener // https://html.spec.whatwg.org/multipage/links.html#link-type-noopener
// https://mathiasbynens.github.io/rel-noopener/ // https://mathiasbynens.github.io/rel-noopener/
// https://github.com/ether/etherpad-lite/pull/3636 // https://github.com/ether/etherpad-lite/pull/3636
extraOpenTags = `${extraOpenTags}<a href="${Security.escapeHTMLAttribute(href)}" rel="noreferrer noopener">`; const escapedHref = Security.escapeHTMLAttribute(href);
extraOpenTags = `${extraOpenTags}<a href="${escapedHref}" rel="noreferrer noopener">`;
extraCloseTags = `</a>${extraCloseTags}`; extraCloseTags = `</a>${extraCloseTags}`;
} }
if (simpleTags) { if (simpleTags) {
@ -187,16 +191,23 @@ console.log("cls", cls);
simpleTags.reverse(); simpleTags.reverse();
extraCloseTags = `</${simpleTags.join('></')}>${extraCloseTags}`; extraCloseTags = `</${simpleTags.join('></')}>${extraCloseTags}`;
} }
html.push('<span class="', Security.escapeHTMLAttribute(cls || ''), '">', extraOpenTags, perTextNodeProcess(Security.escapeHTML(txt)), extraCloseTags, '</span>'); html.push('<span class="', Security.escapeHTMLAttribute(cls || ''),
'">',
extraOpenTags,
perTextNodeProcess(
Security.escapeHTML(txt)
),
extraCloseTags,
'</span>');
} }
}; };
result.clearSpans = function () { result.clearSpans = () => {
html = []; html = [];
lineClass = 'ace-line'; lineClass = 'ace-line';
result.lineMarker = 0; result.lineMarker = 0;
}; };
function writeHTML() { const writeHTML = () => {
let newHTML = perHtmlLineProcess(html.join('')); let newHTML = perHtmlLineProcess(html.join(''));
if (!newHTML) { if (!newHTML) {
if ((!document) || (!optBrowser)) { if ((!document) || (!optBrowser)) {
@ -213,21 +224,19 @@ console.log("cls", cls);
curHTML = newHTML; curHTML = newHTML;
result.node.innerHTML = curHTML; result.node.innerHTML = curHTML;
} }
if (lineClass !== null) result.node.className = lineClass; if (lineClass != null) result.node.className = lineClass;
hooks.callAll('acePostWriteDomLineHTML', { hooks.callAll('acePostWriteDomLineHTML', {
node: result.node, node: result.node,
}); });
} };
result.prepareForAdd = writeHTML; result.prepareForAdd = writeHTML;
result.finishUpdate = writeHTML; result.finishUpdate = writeHTML;
result.getInnerHTML = function () { result.getInnerHTML = () => curHTML || '';
return curHTML || '';
};
return result; return result;
}; };
domline.processSpaces = function (s, doesWrap) { domline.processSpaces = (s, doesWrap) => {
if (s.indexOf('<') < 0 && !doesWrap) { if (s.indexOf('<') < 0 && !doesWrap) {
// short-cut // short-cut
return s.replace(/ /g, '&nbsp;'); return s.replace(/ /g, '&nbsp;');
@ -241,31 +250,31 @@ domline.processSpaces = function (s, doesWrap) {
let beforeSpace = false; let beforeSpace = false;
// last space in a run is normal, others are nbsp, // last space in a run is normal, others are nbsp,
// end of line is nbsp // end of line is nbsp
for (var i = parts.length - 1; i >= 0; i--) { for (let i = parts.length - 1; i >= 0; i--) {
var p = parts[i]; const p = parts[i];
if (p == ' ') { if (p === ' ') {
if (endOfLine || beforeSpace) parts[i] = '&nbsp;'; if (endOfLine || beforeSpace) parts[i] = '&nbsp;';
endOfLine = false; endOfLine = false;
beforeSpace = true; beforeSpace = true;
} else if (p.charAt(0) != '<') { } else if (p.charAt(0) !== '<') {
endOfLine = false; endOfLine = false;
beforeSpace = false; beforeSpace = false;
} }
} }
// beginning of line is nbsp // beginning of line is nbsp
for (var i = 0; i < parts.length; i++) { for (let i = 0; i < parts.length; i++) {
var p = parts[i]; const p = parts[i];
if (p == ' ') { if (p === ' ') {
parts[i] = '&nbsp;'; parts[i] = '&nbsp;';
break; break;
} else if (p.charAt(0) != '<') { } else if (p.charAt(0) !== '<') {
break; break;
} }
} }
} else { } else {
for (var i = 0; i < parts.length; i++) { for (let i = 0; i < parts.length; i++) {
var p = parts[i]; const p = parts[i];
if (p == ' ') { if (p === ' ') {
parts[i] = '&nbsp;'; parts[i] = '&nbsp;';
} }
} }