12ed7123ab
* fix: support markdown preview comments * fix: address markdown preview review feedback * fix: address markdown preview comment scope * fix: address markdown preview follow-up feedback * fix: preserve markdown preview run action in file tabs * fix: ignore svg clicks in markdown preview controls * fix: ignore svg markdown preview selection targets
121 lines
3.9 KiB
TypeScript
121 lines
3.9 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import {
|
|
findLineRangeForSelectedText,
|
|
findNearestSourceElement,
|
|
readSourceLineRange,
|
|
resolveMarkdownDomSelection,
|
|
SOURCE_END_ATTR,
|
|
SOURCE_START_ATTR,
|
|
} from "./source-line-ranges";
|
|
|
|
describe("markdown preview source line ranges", () => {
|
|
it("reads a source line range from markdown preview attributes", () => {
|
|
const element = document.createElement("p");
|
|
element.setAttribute(SOURCE_START_ATTR, "4");
|
|
element.setAttribute(SOURCE_END_ATTR, "6");
|
|
|
|
expect(readSourceLineRange(element)).toEqual({ startLine: 4, endLine: 6 });
|
|
});
|
|
|
|
it("finds the nearest source element for a nested selected text node", () => {
|
|
const root = document.createElement("div");
|
|
const paragraph = document.createElement("p");
|
|
const strong = document.createElement("strong");
|
|
strong.textContent = "selected";
|
|
paragraph.setAttribute(SOURCE_START_ATTR, "8");
|
|
paragraph.setAttribute(SOURCE_END_ATTR, "8");
|
|
paragraph.appendChild(strong);
|
|
root.appendChild(paragraph);
|
|
|
|
expect(findNearestSourceElement(root, strong.firstChild)).toBe(paragraph);
|
|
});
|
|
|
|
it("falls back to raw markdown lookup for rendered text spanning source lines", () => {
|
|
const content = [
|
|
"# Title",
|
|
"",
|
|
"First paragraph",
|
|
"continues here",
|
|
"",
|
|
"Second paragraph",
|
|
].join("\r\n");
|
|
|
|
expect(findLineRangeForSelectedText(content, "First paragraph continues here")).toEqual({
|
|
startLine: 3,
|
|
endLine: 4,
|
|
});
|
|
});
|
|
|
|
it("limits raw markdown fallback lookup to reasonable selection spans", () => {
|
|
const content = Array.from({ length: 35 }, (_, index) => `line ${index + 1}`).join("\n");
|
|
|
|
expect(findLineRangeForSelectedText(content, "line 1 line 2 line 3")).toEqual({
|
|
startLine: 1,
|
|
endLine: 3,
|
|
});
|
|
expect(
|
|
findLineRangeForSelectedText(
|
|
content,
|
|
Array.from({ length: 31 }, (_, index) => `line ${index + 1}`).join(" "),
|
|
),
|
|
).toBeNull();
|
|
});
|
|
|
|
it("resolves a DOM selection to the combined source line range", () => {
|
|
const root = document.createElement("div");
|
|
const first = document.createElement("p");
|
|
first.setAttribute(SOURCE_START_ATTR, "3");
|
|
first.setAttribute(SOURCE_END_ATTR, "3");
|
|
first.textContent = "Alpha paragraph";
|
|
const second = document.createElement("p");
|
|
second.setAttribute(SOURCE_START_ATTR, "5");
|
|
second.setAttribute(SOURCE_END_ATTR, "5");
|
|
second.textContent = "Beta paragraph";
|
|
root.append(first, second);
|
|
document.body.appendChild(root);
|
|
|
|
const range = document.createRange();
|
|
range.setStart(first.firstChild!, 0);
|
|
range.setEnd(second.firstChild!, 4);
|
|
const selection = window.getSelection()!;
|
|
selection.removeAllRanges();
|
|
selection.addRange(range);
|
|
|
|
expect(
|
|
resolveMarkdownDomSelection(root, "# Title\n\nAlpha paragraph\n\nBeta paragraph", selection),
|
|
).toMatchObject({
|
|
selectedText: "Alpha paragraphBeta",
|
|
startLine: 3,
|
|
endLine: 5,
|
|
});
|
|
|
|
root.remove();
|
|
selection.removeAllRanges();
|
|
});
|
|
|
|
it("rejects selections that leave the markdown preview root", () => {
|
|
const root = document.createElement("div");
|
|
const paragraph = document.createElement("p");
|
|
paragraph.setAttribute(SOURCE_START_ATTR, "3");
|
|
paragraph.setAttribute(SOURCE_END_ATTR, "3");
|
|
paragraph.textContent = "Alpha paragraph";
|
|
const outside = document.createElement("span");
|
|
outside.textContent = "outside";
|
|
root.appendChild(paragraph);
|
|
document.body.append(root, outside);
|
|
|
|
const range = document.createRange();
|
|
range.setStart(paragraph.firstChild!, 0);
|
|
range.setEnd(outside.firstChild!, 3);
|
|
const selection = window.getSelection()!;
|
|
selection.removeAllRanges();
|
|
selection.addRange(range);
|
|
|
|
expect(resolveMarkdownDomSelection(root, "Alpha paragraph", selection)).toBeNull();
|
|
|
|
root.remove();
|
|
outside.remove();
|
|
selection.removeAllRanges();
|
|
});
|
|
});
|