This repository has been archived by the owner on Jun 7, 2024. It is now read-only.
forked from speced/respec
-
Notifications
You must be signed in to change notification settings - Fork 0
/
data-cite.js
123 lines (118 loc) · 3.69 KB
/
data-cite.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/**
* Module core/data-cite
*
* Allows citing other specifications using
* anchor elements. Simply add "data-cite"
* and key of specification.
*
* This module simply adds the found key
* to either conf.normativeReferences
* or to conf.informativeReferences depending on
* if it starts with a ! or not.
*
* Usage:
* https://github.com/w3c/respec/wiki/data--cite
*/
import "deps/regenerator";
import { pub } from "core/pubsubhub";
import { resolveRef } from "core/biblio";
export const name = "core/data-cite";
function requestLookup(conf) {
const toCiteDetails = citeDetailsConverter(conf);
return async function(elem) {
const originalKey = elem.dataset.cite;
let { key, frag } = toCiteDetails(elem);
let href = "";
// This is just referring to this document
if (key === conf.shortName) {
href = document.location.href;
} else {
// Let's go look it up in spec ref...
const entry = await resolveRef(key);
cleanElement(elem);
if (!entry) {
var msg = `Couldn't find a match for 'data-cite=${originalKey}'.`;
console.warn(msg, elem);
msg += " Please check developer console for offending element.";
pub("warn", msg);
return;
}
href = entry.href;
}
if (frag) {
href = new URL(frag, href).href;
}
switch (elem.localName) {
case "a": {
elem.href = href;
break;
}
case "dfn": {
const a = elem.ownerDocument.createElement("a");
a.href = href;
while (elem.firstChild) {
a.appendChild(elem.firstChild);
}
elem.appendChild(a, elem);
break;
}
}
};
}
function cleanElement(elem) {
["data-cite", "data-cite-frag"]
.filter(attrName => elem.hasAttribute(attrName))
.forEach(attrName => elem.removeAttribute(attrName));
}
function citeDetailsConverter(conf) {
return function toCiteDetails(elem) {
const { dataset } = elem;
let { cite: key, citeFrag: frag } = dataset;
const isNormative = key.startsWith("!");
const fragPosition = key.search("#");
// The key is a fragment, resolve using the shortName as key
if (key.startsWith("#") && !frag) {
// Closes data-cite not starting with "#"
const closest = elem.parentElement.closest(
`[data-cite]:not([data-cite^="#"])`
);
const { key: parentKey, isNormative: closestIsNormative } = closest
? toCiteDetails(closest)
: { key: conf.shortName || "", isNormative: false };
elem.dataset.cite = closestIsNormative ? `!${parentKey}` : parentKey;
elem.dataset.citeFrag = key; // the key is acting as fragment
return toCiteDetails(elem);
}
if (fragPosition !== -1) {
frag = !frag ? key.substr(fragPosition) : frag;
key = key.substring(0, fragPosition);
}
if (isNormative) {
key = key.substr(1);
}
if (frag && !frag.startsWith("#")) {
frag = "#" + frag;
}
return { key, isNormative, frag };
};
}
export async function run(conf) {
const toCiteDetails = citeDetailsConverter(conf);
Array.from(document.querySelectorAll(["dfn[data-cite], a[data-cite]"]))
.filter(el => el.dataset.cite)
.map(toCiteDetails)
.reduce((conf, { isNormative, key }) => {
if (isNormative) {
conf.normativeReferences.add(key);
} else {
conf.informativeReferences.add(key);
}
return conf;
}, conf);
}
export async function linkInlineCitations(doc) {
const toLookupRequest = requestLookup(doc.defaultView.respecConfig);
const citedSpecs = doc.querySelectorAll("dfn[data-cite], a[data-cite]");
const lookupRequests = Array.from(citedSpecs).map(toLookupRequest);
return await Promise.all(lookupRequests);
}