Description
The only reference to precedence I could find in the spec is this:
If there are multiple matching reference link definitions, the one that comes first in the document is used. (It is desirable in such cases to emit a warning.)
The issue is that when you define a LRD (link reference definition) in a Setext heading (or a probable Setext heading*), this link will populate the refmap
before any paragraph LRDs are parsed, which occurs at the document finalization step.
*A paragraph interrupted by a setext heading underline that only contains links, thus creating an empty <p>
, which is immediately unlinked from the AST.
Example inputs:
[x]: fizz
[x]: buzz
===
[x]
has an href=buzz
,
Whereas
[x]: fizz
[x]: buzz
[x]
has an href=fizz
.
My interpretation of the spec is that both should result in href=fizz
as that is the first LRD.
Assuming this is a bug, my idea of a fix would be to use a modified Parser.refmap
where it has an Map<number, Array<LRD>>
and the key would be the line number of the containing paragraph (sourcepos[0][0]
), as the exact lines don't matter as long as the array is populated in-order.
So if this was the input
[line1]: a
[line2]: b
rest of paragraph
[line5]: e
===
would have the map
{
5: [e],
1: [a, b]
}
(where a, b, e
are objects of typedef LRD {destination: string, title: string, label: string}
with map def
Map<number, Array<LRD>>
)
Then setext headings' block start and document finalization can occur in the order they do, but could add another step after document finalization. E.g.
/**
* @param {Map<number, Array<{destination: string, title: string, label: string}>>} unorderedRefmap
*/
function getFinalRefmap(unorderedRefmap) {
const sortedKeys = [...unorderedRefmap.keys()].sort((a, b) => a - b);
const finalRefmap = {};
for (const k of sortedKeys) {
const values = unorderedRefmap.get(k);
for (const v of values) {
if (!finalRefmap[v.label]) {
finalRefmap[v.label] = {destination: v.destination, title: v.title};
}
}
}
return finalRefmap ;
}
Something like that should work, its just a matter of adding to the placeholder refmap correctly, which is a bit trickier since inline.js needs a reference to it and mutates it.