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;
white-space: pre-wrap;
}
.error {
background: rgb(255, 0, 0, 0.3);
}
.flex-rows {
display: flex;
flex-direction: column;
@ -64,7 +67,7 @@ textarea {
min-height: 0;
}
.highlight {
background: yellow;
background: rgb(255, 0, 0, 0.8);
}
.inset {
box-sizing: border-box;

View file

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