refactor lint report stuff, use $element
This commit is contained in:
parent
ec01914f17
commit
85a5702fe0
|
@ -154,7 +154,7 @@ function setCleanSection(section) {
|
||||||
const cm = section.CodeMirror;
|
const cm = section.CodeMirror;
|
||||||
if (cm) {
|
if (cm) {
|
||||||
section.savedValue = cm.changeGeneration();
|
section.savedValue = cm.changeGeneration();
|
||||||
indicateCodeChange(cm);
|
updateTitle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1570,6 +1570,7 @@ function fromMozillaFormat() {
|
||||||
// parserlib contained in CSSLint-worker.js
|
// parserlib contained in CSSLint-worker.js
|
||||||
onDOMscripted(['vendor-overwrites/csslint/csslint-worker.js']).then(() => {
|
onDOMscripted(['vendor-overwrites/csslint/csslint-worker.js']).then(() => {
|
||||||
doImportWhenReady(event.target);
|
doImportWhenReady(event.target);
|
||||||
|
editors.forEach(cm => updateLintReportIfEnabled(cm, 1));
|
||||||
editors.last.state.renderLintReportNow = true;
|
editors.last.state.renderLintReportNow = true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
136
edit/lint.js
136
edit/lint.js
|
@ -152,9 +152,9 @@ function updateLinter({immediately} = {}) {
|
||||||
if (guttersOption) {
|
if (guttersOption) {
|
||||||
cm.setOption('guttersOption', guttersOption);
|
cm.setOption('guttersOption', guttersOption);
|
||||||
updateGutters(cm, guttersOption);
|
updateGutters(cm, guttersOption);
|
||||||
}
|
|
||||||
cm.refresh();
|
cm.refresh();
|
||||||
updateLintReport(cm);
|
}
|
||||||
|
setTimeout(updateLintReport, 0, cm);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,6 +188,9 @@ function updateLinter({immediately} = {}) {
|
||||||
updateEditors();
|
updateEditors();
|
||||||
});
|
});
|
||||||
$('#linter-settings').style.display = !linter ? 'none' : 'inline-block';
|
$('#linter-settings').style.display = !linter ? 'none' : 'inline-block';
|
||||||
|
if (!linter) {
|
||||||
|
$('#lint > div').textContent = '';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateLintReport(cm, delay) {
|
function updateLintReport(cm, delay) {
|
||||||
|
@ -203,7 +206,7 @@ function updateLintReport(cm, delay) {
|
||||||
if (delay === 0) {
|
if (delay === 0) {
|
||||||
// immediately show pending csslint/stylelint messages in onbeforeunload and save
|
// immediately show pending csslint/stylelint messages in onbeforeunload and save
|
||||||
clearTimeout(state.lintTimeout);
|
clearTimeout(state.lintTimeout);
|
||||||
update(cm);
|
updateLintReportInternal(cm);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (delay > 0) {
|
if (delay > 0) {
|
||||||
|
@ -211,75 +214,81 @@ function updateLintReport(cm, delay) {
|
||||||
state.lintTimeout = setTimeout(cm => {
|
state.lintTimeout = setTimeout(cm => {
|
||||||
if (cm.performLint) {
|
if (cm.performLint) {
|
||||||
cm.performLint();
|
cm.performLint();
|
||||||
update(cm);
|
updateLintReportInternal(cm);
|
||||||
}
|
}
|
||||||
}, delay, cm);
|
}, delay, cm);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// user is editing right now: postpone updating the report for the new issues (default: 500ms lint + 4500ms)
|
if (state.options) {
|
||||||
// or update it as soon as possible (default: 500ms lint + 100ms) in case an existing issue was just fixed
|
|
||||||
clearTimeout(state.reportTimeout);
|
clearTimeout(state.reportTimeout);
|
||||||
state.reportTimeout = setTimeout(update, (state.options || {}).delay + 100, cm);
|
const delay = cm && cm.state.renderLintReportNow ? 0 : state.options.delay + 100;
|
||||||
state.postponeNewIssues = delay === undefined || delay === null;
|
state.reportTimeout = setTimeout(updateLintReportInternal, delay, cm, {
|
||||||
|
postponeNewIssues: delay === undefined || delay === null
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function update(cm) {
|
function updateLintReportInternal(scope, {postponeNewIssues} = {}) {
|
||||||
const scope = cm ? [cm] : editors;
|
scope = scope ? [scope] : editors;
|
||||||
let changed = false;
|
let changed = false;
|
||||||
let fixedOldIssues = false;
|
let fixedOldIssues = false;
|
||||||
|
const clipString = (str, limit) =>
|
||||||
|
str.length <= limit ? str : str.substr(0, limit) + '...';
|
||||||
scope.forEach(cm => {
|
scope.forEach(cm => {
|
||||||
const scopedState = cm.state.lint || {};
|
const lintState = cm.state.lint || {};
|
||||||
const oldMarkers = scopedState.markedLast || {};
|
const oldMarkers = lintState.markedLast || new Map();
|
||||||
const newMarkers = {};
|
const newMarkers = lintState.markedLast = new Map();
|
||||||
const html = !scopedState.marked || scopedState.marked.length === 0 ? '' : '<tbody>' +
|
const marked = lintState.marked || {};
|
||||||
scopedState.marked.map(mark => {
|
const activeLine = cm.getCursor().line;
|
||||||
|
if (marked.length) {
|
||||||
|
const body = $element({tag: 'tbody',
|
||||||
|
appendChild: marked.map(mark => {
|
||||||
const info = mark.__annotation;
|
const info = mark.__annotation;
|
||||||
const isActiveLine = info.from.line === cm.getCursor().line;
|
const {line, ch} = info.from;
|
||||||
const pos = isActiveLine ? 'cursor' : (info.from.line + ',' + info.from.ch);
|
const isActiveLine = line === activeLine;
|
||||||
// rule name added in parentheses at the end; extract it out for the info popup
|
const pos = isActiveLine ? 'cursor' : (line + ',' + ch);
|
||||||
const text = info.message;
|
const title = clipString(info.message, 1000) + `\n(${info.rule})`;
|
||||||
const title = escapeHtml(text + `\n(${info.rule})`, {limit: 1000});
|
const message = clipString(info.message, 100);
|
||||||
const message = escapeHtml(text, {limit: 100});
|
|
||||||
if (isActiveLine || oldMarkers[pos] === message) {
|
if (isActiveLine || oldMarkers[pos] === message) {
|
||||||
delete oldMarkers[pos];
|
oldMarkers.delete(pos);
|
||||||
}
|
}
|
||||||
newMarkers[pos] = message;
|
newMarkers.set(pos, message);
|
||||||
return `<tr class="${info.severity}">
|
return $element({tag: 'tr',
|
||||||
<td role="severity" data-rule="${info.rule}">
|
className: info.severity,
|
||||||
<div class="CodeMirror-lint-marker-${info.severity}">${info.severity}</div>
|
appendChild: [
|
||||||
</td>
|
$element({tag: 'td',
|
||||||
<td role="line">${info.from.line + 1}</td>
|
attributes: {role: 'severity'},
|
||||||
<td role="sep">:</td>
|
dataset: {rule: info.rule},
|
||||||
<td role="col">${info.from.ch + 1}</td>
|
appendChild: $element({
|
||||||
<td role="message" title="${title}">${message}</td>
|
className: 'CodeMirror-lint-marker-' + info.severity,
|
||||||
</tr>`;
|
textContent: info.severity,
|
||||||
}).join('') + '</tbody>';
|
}),
|
||||||
scopedState.markedLast = newMarkers;
|
}),
|
||||||
fixedOldIssues |= scopedState.reportDisplayed && Object.keys(oldMarkers).length > 0;
|
$element({tag: 'td', attributes: {role: 'line'}, textContent: line + 1}),
|
||||||
if ((scopedState.html || '') !== html) {
|
$element({tag: 'td', attributes: {role: 'sep'}, textContent: ':'}),
|
||||||
scopedState.html = html;
|
$element({tag: 'td', attributes: {role: 'col'}, textContent: ch + 1}),
|
||||||
|
$element({tag: 'td', attributes: {role: 'message'}, textContent: message, title}),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
})
|
||||||
|
});
|
||||||
|
const text = body.textContentCached = body.textContent;
|
||||||
|
if (text !== ((lintState.body || {}).textContentCached || '')) {
|
||||||
|
lintState.body = body;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
fixedOldIssues |= lintState.reportDisplayed && oldMarkers.size;
|
||||||
});
|
});
|
||||||
if (changed) {
|
if (changed) {
|
||||||
clearTimeout(state ? state.renderTimeout : undefined);
|
if (!postponeNewIssues || fixedOldIssues || editors.last.state.renderLintReportNow) {
|
||||||
if (!state || !state.postponeNewIssues || fixedOldIssues || editors.last.state.renderLintReportNow) {
|
|
||||||
editors.last.state.renderLintReportNow = false;
|
editors.last.state.renderLintReportNow = false;
|
||||||
renderLintReport(true);
|
renderLintReport(true);
|
||||||
} else {
|
} else {
|
||||||
state.renderTimeout = setTimeout(renderLintReport, CodeMirror.defaults.lintReportDelay, true);
|
debounce(renderLintReport, CodeMirror.defaults.lintReportDelay, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function escapeHtml(html, {limit} = {}) {
|
|
||||||
const chars = {'&': '&', '<': '<', '>': '>', '"': '"', "'": ''', '/': '/'};
|
|
||||||
let ellipsis = '';
|
|
||||||
if (limit && html.length > limit) {
|
|
||||||
html = html.substr(0, limit);
|
|
||||||
ellipsis = '...';
|
|
||||||
}
|
|
||||||
return html.replace(/[&<>"'/]/g, char => chars[char]) + ellipsis;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderLintReport(someBlockChanged) {
|
function renderLintReport(someBlockChanged) {
|
||||||
const container = $('#lint');
|
const container = $('#lint');
|
||||||
|
@ -288,18 +297,29 @@ function renderLintReport(someBlockChanged) {
|
||||||
const newContent = content.cloneNode(false);
|
const newContent = content.cloneNode(false);
|
||||||
let issueCount = 0;
|
let issueCount = 0;
|
||||||
editors.forEach((cm, index) => {
|
editors.forEach((cm, index) => {
|
||||||
if (cm.state.lint && cm.state.lint.html) {
|
const lintState = cm.state.lint || {};
|
||||||
const html = '<caption>' + label + ' ' + (index + 1) + '</caption>' + cm.state.lint.html;
|
const body = lintState.body;
|
||||||
const newBlock = newContent.appendChild(tHTML(html, 'table'));
|
if (!body) {
|
||||||
|
return;
|
||||||
newBlock.cm = cm;
|
}
|
||||||
|
const newBlock = $element({
|
||||||
|
tag: 'table',
|
||||||
|
appendChild: [
|
||||||
|
$element({tag: 'caption', textContent: label + ' ' + (index + 1)}),
|
||||||
|
body,
|
||||||
|
],
|
||||||
|
cm,
|
||||||
|
});
|
||||||
|
newContent.appendChild(newBlock);
|
||||||
issueCount += newBlock.rows.length;
|
issueCount += newBlock.rows.length;
|
||||||
|
|
||||||
const block = content.children[newContent.children.length - 1];
|
const block = content.children[newContent.children.length - 1];
|
||||||
const blockChanged = !block || cm !== block.cm || html !== block.innerHTML;
|
const blockChanged =
|
||||||
|
!block ||
|
||||||
|
block.cm !== cm ||
|
||||||
|
body.textContentCached !== block.textContentCached;
|
||||||
someBlockChanged |= blockChanged;
|
someBlockChanged |= blockChanged;
|
||||||
cm.state.lint.reportDisplayed = blockChanged;
|
lintState.reportDisplayed = blockChanged;
|
||||||
}
|
|
||||||
});
|
});
|
||||||
if (someBlockChanged || newContent.children.length !== content.children.length) {
|
if (someBlockChanged || newContent.children.length !== content.children.length) {
|
||||||
$('#issue-count').textContent = issueCount;
|
$('#issue-count').textContent = issueCount;
|
||||||
|
|
|
@ -244,6 +244,12 @@ function $element(opt) {
|
||||||
Object.assign(element.dataset, opt.dataset);
|
Object.assign(element.dataset, opt.dataset);
|
||||||
delete opt.dataset;
|
delete opt.dataset;
|
||||||
}
|
}
|
||||||
|
if (opt.attributes) {
|
||||||
|
for (const attr in opt.attributes) {
|
||||||
|
element.setAttribute(attr, opt.attributes[attr]);
|
||||||
|
}
|
||||||
|
delete opt.attributes;
|
||||||
|
}
|
||||||
if (ns) {
|
if (ns) {
|
||||||
for (const attr in opt) {
|
for (const attr in opt) {
|
||||||
element.setAttributeNS(null, attr, opt[attr]);
|
element.setAttributeNS(null, attr, opt[attr]);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user