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
|
import counters from './assets/images/counters.svg';
import mapsheets from './assets/images/mapsheets.svg';
async function loadScript(scenario, svg, script) {
return new Promise((resolve, reject) => {
const scriptEl = document.createElementNS("http://www.w3.org/2000/svg", 'script');
scriptEl.onload = () => {
console.log(`${script}.js loaded`);
resolve();
};
scriptEl.onerror = () => {
reject(Error('Script failed to load.'));
};
const dataset = scenario.querySelector('script')?.dataset || {};
if ('cols' in dataset && 'rows' in dataset) {
scriptEl.dataset.rows = dataset.rows;
scriptEl.dataset.cols = dataset.cols;
}
scriptEl.setAttributeNS(null, 'href', `../../${script}.js`);
svg.append(scriptEl);
});
}
export async function requestResource(url) {
return new Promise((resolve, reject) => {
const request = new XMLHttpRequest();
request.open('GET', url, true);
request.responseType = 'document';
request.onload = function() {
if (request.status === 200) {
resolve(request.response);
} else {
reject(Error('Image didn\'t load successfully; error code:' + request.statusText));
}
};
request.onerror = function() {
reject(Error('There was a network error.'));
};
request.send();
});
}
export async function build(svg, request) {
const defs = svg.querySelector('defs');
const gb = svg.querySelector('.gameboard');
const grid = svg.querySelector('.grid');
const scenario = await request;
const startLocs = scenario.querySelector('.start-locations');
const externalResourceEls = Array.from(scenario.querySelectorAll('use[href*=".svg"'));
scenario.querySelectorAll('defs > *').forEach(el => defs.append(svg.ownerDocument.importNode(el, true)));
const refs = externalResourceEls.reduce((acc, el) => {
const href = el.getAttributeNS(null, 'href');
const [filename] = href.match(/.+\.svg/);
const fragmentIdentifier = href.split('.svg').pop();
(acc[filename] ??= new Set()).add(fragmentIdentifier);
el.setAttributeNS(null, 'href', fragmentIdentifier);
return acc;
}, {});
const hashedFilenames = {
'counters.svg': counters,
'mapsheets.svg': mapsheets
}
await Promise.all(
Object.keys(refs).map(filename => requestResource(hashedFilenames[filename]))
).then(result => {
Object.keys(refs).forEach((filename, index) => {
const external = result[index];
refs[filename].forEach(fragmentIdentifier => {
external
.querySelectorAll(`${fragmentIdentifier} use`)
.forEach(el => refs[filename].add(el.getAttributeNS(null, 'href')));
});
const refsQuery = [...refs[filename]].join(', ');
external.querySelectorAll(refsQuery).forEach(node =>
defs.append(svg.ownerDocument.importNode(node, true))
);
});
});
//if (startLocs) grid.before(svg.ownerDocument.importNode(startLocs, true));
const scenarioGrid = scenario.querySelector('.grid');
if (scenarioGrid) {
grid.replaceWith(svg.ownerDocument.importNode(scenarioGrid, true));
}
await loadScript(scenario, svg, 'radial')
return loadScript(scenario, svg, 'map');
}
|