Update demo web page to highlight all error lines and ranges by default, encode single quotes in attributes.

This commit is contained in:
David Anson 2025-08-07 20:50:32 -07:00
parent 7676902b88
commit 10db83f719
2 changed files with 40 additions and 20 deletions

View file

@ -47,6 +47,9 @@ textarea {
font-style: italic; font-style: italic;
white-space: pre-wrap; white-space: pre-wrap;
} }
.error {
background: rgb(255, 0, 0, 0.3);
}
.flex-rows { .flex-rows {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -64,7 +67,7 @@ textarea {
min-height: 0; min-height: 0;
} }
.highlight { .highlight {
background: yellow; background: rgb(255, 0, 0, 0.8);
} }
.inset { .inset {
box-sizing: border-box; box-sizing: border-box;

View file

@ -86,6 +86,22 @@
return `[Unsupported renderer "${renderer}"]`; return `[Unsupported renderer "${renderer}"]`;
} }
// Highlight error ranges
function highlightErrors(results, className) {
for (const result of results) {
const { errorRange, lineNumber } = result;
const line = document.getElementById(`l${lineNumber}`);
line.classList.add(className);
if (errorRange) {
const [ col, len ] = errorRange;
for (let i = 0; i < len; i++) {
var char = document.getElementById(`l${lineNumber}c${col + i}`);
char.classList.add(className);
}
}
}
}
// Handle input // Handle input
function onMarkdownInput() { function onMarkdownInput() {
// Markdown // Markdown
@ -97,11 +113,13 @@
var padding = lines.length.toString().replace(/\d/g, " "); var padding = lines.length.toString().replace(/\d/g, " ");
numbered.innerHTML = lines numbered.innerHTML = lines
.map(function mapNumberedLine(line, index) { .map(function mapNumberedLine(line, index) {
line = sanitize(line);
index++; index++;
var paddedIndex = (padding + index).slice(-padding.length); var paddedIndex = (padding + index).slice(-padding.length);
return "<span id='l" + index + "'><em>" + paddedIndex + "</em>: " + return (
line + "</span>"; `<span><em id='l${index}'>${paddedIndex}</em>: ` +
[ ...line ].map((c, i) => `<span id='l${index}c${i + 1}'>${sanitize(c)}</span>`).join("") +
"</span>"
);
}).join("\n"); }).join("\n");
// Violations // Violations
var options = { var options = {
@ -116,7 +134,8 @@
allLintErrors = markdownlint.lintSync(options).content; allLintErrors = markdownlint.lintSync(options).content;
violations.innerHTML = allLintErrors.map(function mapResult(result) { violations.innerHTML = allLintErrors.map(function mapResult(result) {
var ruleName = result.ruleNames.slice(0, 2).join(" / "); var ruleName = result.ruleNames.slice(0, 2).join(" / ");
return "<em><a href='#line' target='" + result.lineNumber + "'>" + var resultJson = encodeURIComponent(JSON.stringify(result)).replaceAll("'", "%27");
return "<em><a href='#line' target='" + resultJson + "'>" +
result.lineNumber + "</a></em> - <a href='" + result.ruleInformation + result.lineNumber + "</a></em> - <a href='" + result.ruleInformation +
"'>" + ruleName + "</a> " + "'>" + ruleName + "</a> " +
result.ruleDescription + result.ruleDescription +
@ -131,11 +150,13 @@
"\"</span>]" : "\"</span>]" :
"") + "") +
(result.fixInfo ? (result.fixInfo ?
" [<a href='#fix' target=\"" + " [<a href='#fix' target='" +
encodeURIComponent(JSON.stringify(result)) + resultJson +
"\" class='detail'>Fix</a>]" : "' class='detail'>Fix</a>]" :
""); "");
}).join("<br/>"); }).join("<br/>");
// Highlight errors
highlightErrors(allLintErrors, "error");
} }
// Load from a string or File object // Load from a string or File object
@ -178,29 +199,25 @@
// Handle violation navigation // Handle violation navigation
function onViolationClick(e) { function onViolationClick(e) {
const resultJson = JSON.parse(decodeURIComponent(e.target.target));
switch (e.target.hash) { switch (e.target.hash) {
case "#fix": case "#fix":
var errors = e.shiftKey ? var errors = e.shiftKey ?
allLintErrors : allLintErrors :
[ JSON.parse(decodeURIComponent(e.target.target)) ]; [ resultJson ];
var fixed = markdownlint.applyFixes(markdown.value, errors); var fixed = markdownlint.applyFixes(markdown.value, errors);
markdown.value = fixed; markdown.value = fixed;
onMarkdownInput(); onMarkdownInput();
e.preventDefault(); e.preventDefault();
break; break;
case "#line": case "#line":
var line = document.getElementById("l" + e.target.target); // eslint-disable-next-line unicorn/no-useless-spread
if (line) { for (const element of [ ...document.getElementsByClassName("highlight") ]) {
var highlighted = document.getElementsByClassName("highlight"); element.classList.remove("highlight");
Array.prototype.forEach.call(
highlighted,
function forElement(element) {
element.classList.remove("highlight");
}
);
line.classList.add("highlight");
line.scrollIntoView();
} }
highlightErrors([ resultJson ], "highlight");
var line = document.getElementById(`l${resultJson.lineNumber}`);
line.scrollIntoView();
e.preventDefault(); e.preventDefault();
break; break;
default: default: