-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathutils.js
More file actions
57 lines (51 loc) · 2.24 KB
/
utils.js
File metadata and controls
57 lines (51 loc) · 2.24 KB
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
let svgCache = {}
/**
* @name fetchFromCache
* @returns {Promise} a shared promise across requests for this resource.
* @description HTML `fetch` only goes so far to cache responses.
* This utility prevents fetch requests on the same page session
* (and especially those requested in close proximity)
* from pinging the server multiple times by storing
* a cache dictionary in the module scope.
* Also runs response.text() before returning.
*/
export const fetchFromCache = (url) => {
if (!svgCache[url]) {
svgCache[url] = fetch(url).then((data) => data.text())
}
return svgCache[url]
}
export const scopeIDs = (data) => {
/** match IDs and convert to array */
const regex = /id=["'](\S+)["']/gi
const IDs = [...data.matchAll(regex)].map((match) => match[1])
/** replace each id and its references */
IDs.forEach((id) => {
/** add a uuid to the id */
const newID = `${id}-${crypto.randomUUID()}`
/**
* referring to https://www.w3.org/TR/wai-aria/#typemapping,
* there are a few attributes that can contain an "ID reference list"
*/
const idReferenceAttributes = ["id", "aria-activedescendant", "aria-errormessage", "for"]
idReferenceAttributes.forEach((attribute) => {
const regex = new RegExp(`${attribute}=["']${id}["']`, "g")
data = data.replaceAll(regex, `${attribute}="${newID}"`)
})
const idReferenceListAttributes = ["aria-controls", "aria-describedby", "aria-details", "aria-flowto", "aria-labeledby", "aria-owns"]
idReferenceListAttributes.forEach((attribute) => {
/**
* in id reference list (space-separated (\S+) blocks), only replace the current `id` with `newID` and leave the rest of the id reference list alone.
* assume that the current `id` may appear anywhere in the space-separated list of IDs.
* example: `aria-describedby="xxxx yyyy"` becomes `aria-describedby="xxxx-234234 yyyy-234234"`
*/
const regex = new RegExp(`${attribute}=(?:'([^']*)'|"([^"]*)")`, "g")
data = data.replaceAll(regex, (match) => {
match.split(" ").map((singleID) => (singleID === id) ? newID : match)
})
})
/** replace url-based ID references */
data = data.replaceAll(`url(#${id})`, `url(#${newID})`)
})
return data
}