fix: order a citation run ascending, and name each page once (#24)
This commit was merged in pull request #24.
This commit is contained in:
@@ -170,6 +170,20 @@ describe("linkCitations", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("orders a run ascending, because a model lists by rank and a reader reads by number", () => {
|
||||
// A real answer sent [2][1] for a sentence resting on both, which drew as
|
||||
// "two, one" and left the reader to work out that it meant the first two sources.
|
||||
expect(linkCitations("Both [3][1] agree.", sources).text).toBe(
|
||||
"Both [¹](https://first.example) [³](https://third.example) agree.",
|
||||
);
|
||||
});
|
||||
|
||||
it("cites one page once, however often a run names it", () => {
|
||||
expect(linkCitations("Both [3][1][3] agree.", sources).text).toBe(
|
||||
"Both [¹](https://first.example) [³](https://third.example) agree.",
|
||||
);
|
||||
});
|
||||
|
||||
it("leaves a marker alone when the destination is not one this window should open", () => {
|
||||
const unsafe = [{ index: 1, title: "Nasty", url: "javascript:alert(1)" }];
|
||||
const result = linkCitations("See [1].", unsafe);
|
||||
|
||||
+13
-3
@@ -198,8 +198,8 @@ function stripDefinitions(text: string, known: Set<number>): string {
|
||||
}
|
||||
|
||||
/**
|
||||
* `[1]`, `[^1]`, `[1, 3]` and `[1][2]` as superscript links, plus the numbers that
|
||||
* became links.
|
||||
* `[1]`, `[^1]`, `[1, 3]` and `[1][2]` as superscript links, ordered ascending and
|
||||
* each page once, plus the numbers that became links.
|
||||
*
|
||||
* One run of prose only: fences are the caller's business, because the caller
|
||||
* already walks the document in segments for the maths pass and there is no
|
||||
@@ -214,7 +214,17 @@ export function linkCitations(text: string, sources: Source[]): CitationResult {
|
||||
|
||||
const linked = mapOutsideCodeSpans(prose, (chunk) =>
|
||||
chunk.replace(CITATION_RUN, (whole: string) => {
|
||||
const wanted = [...whole.matchAll(RUN_NUMBERS)].map((match) => Number(match[0]));
|
||||
/**
|
||||
* Ascending, and each page once.
|
||||
*
|
||||
* A run is a set of sources, and a model lists them in the order it thought of
|
||||
* them rather than by number: a real answer sent `[2][1]` for a sentence resting
|
||||
* on both, which drew as "two, one", and `[8][4]` for another. The numbers
|
||||
* themselves are never renumbered, so `[3]` is still the third source the turn
|
||||
* found and the reader can find it in the list.
|
||||
*/
|
||||
const named = [...whole.matchAll(RUN_NUMBERS)].map((match) => Number(match[0]));
|
||||
const wanted = [...new Set(named)].sort((left, right) => left - right);
|
||||
const links: string[] = [];
|
||||
|
||||
for (const index of wanted) {
|
||||
|
||||
Reference in New Issue
Block a user