mockaton 13.11.1 → 13.11.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -8
- package/package.json +1 -1
- package/skills/mockaton/SKILL.md +8 -5
- package/src/client/ApiConstants.js +1 -1
- package/src/client/IndexHtml.js +1 -1
- package/src/client/app-header.css +231 -0
- package/src/client/app-header.js +13 -6
- package/src/client/app-mock-list.css +340 -0
- package/src/client/app-mock-list.js +370 -0
- package/src/client/app-payload-viewer.css +90 -0
- package/src/client/app-payload-viewer.js +4 -4
- package/src/client/app-store.js +1 -0
- package/src/client/app.css +0 -654
- package/src/client/app.js +18 -360
- package/src/client/utils/css.js +7 -0
- package/src/client/utils/watcherDev.js +4 -1
- package/src/server/Api.js +54 -53
- package/src/server/MockDispatcher.js +6 -5
- package/src/server/Mockaton.js +11 -12
- package/src/server/Mockaton.test.js +65 -51
- package/src/server/ProxyRelay.js +3 -2
- package/src/server/UrlParsers.js +1 -1
- package/src/server/UrlParsers.test.js +1 -1
- package/src/server/cli.js +37 -33
- package/src/server/cli.test.js +2 -4
- package/src/server/{Watcher.js → stores/Watcher.js} +18 -9
- package/src/server/{mockBrokersCollection.js → stores/brokers.js} +3 -3
- package/src/server/{config.js → stores/config.js} +28 -14
- package/src/server/utils/HttpServerResponse.test.js +5 -7
- package/src/server/utils/WatcherDevClient.js +1 -1
- package/src/server/utils/openInBrowser.js +15 -10
- package/www/src/assets/openapi.json +1 -1
- /package/src/server/{resolverBypassImportCache.js → ResolverBypassImportCache.js} +0 -0
- /package/src/server/{resolverResolveExtensionless.js → ResolverResolveExtensionless.js} +0 -0
- /package/src/server/{cookie.js → stores/cookies.js} +0 -0
package/src/client/app.js
CHANGED
|
@@ -3,14 +3,12 @@ import { createElement as r, t, restoreFocus, Fragment } from './utils/dom.js'
|
|
|
3
3
|
import { store } from './app-store.js'
|
|
4
4
|
import { API } from './ApiConstants.js'
|
|
5
5
|
import { Header } from './app-header.js'
|
|
6
|
+
import { adoptSheet } from './utils/css.js'
|
|
6
7
|
import { PayloadViewer, previewMock } from './app-payload-viewer.js'
|
|
7
|
-
import {
|
|
8
|
+
import { MockList, initKeyboardNavigation, renderRow } from './app-mock-list.js'
|
|
8
9
|
|
|
9
10
|
import CSS from './app.css' with { type: 'css' }
|
|
10
|
-
|
|
11
|
-
document.adoptedStyleSheets.push(CSS)
|
|
12
|
-
Object.assign(CSS, extractClassNames(CSS))
|
|
13
|
-
|
|
11
|
+
adoptSheet(CSS, './app.css')
|
|
14
12
|
|
|
15
13
|
store.onError = onError
|
|
16
14
|
store.render = render
|
|
@@ -19,22 +17,22 @@ store.renderRow = renderRow
|
|
|
19
17
|
onRealTimeUpdate(store.fetchState)
|
|
20
18
|
initKeyboardNavigation()
|
|
21
19
|
|
|
22
|
-
let mounted = false
|
|
23
20
|
function render() {
|
|
24
21
|
restoreFocus(() => document.body.replaceChildren(App()))
|
|
25
22
|
if (store.hasChosenLink) previewMock()
|
|
26
|
-
if (!mounted) LeftSide.$('a')?.focus()
|
|
27
|
-
mounted = true
|
|
23
|
+
if (!store.mounted) LeftSide.$('a')?.focus()
|
|
24
|
+
store.mounted = true
|
|
28
25
|
}
|
|
29
26
|
|
|
30
27
|
function App() {
|
|
31
|
-
return
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
28
|
+
return (
|
|
29
|
+
Fragment(
|
|
30
|
+
Header(),
|
|
31
|
+
r('main', null,
|
|
32
|
+
LeftSide(),
|
|
33
|
+
r('div', { className: CSS.rightSide },
|
|
34
|
+
Resizer(),
|
|
35
|
+
PayloadViewer()))))
|
|
38
36
|
}
|
|
39
37
|
|
|
40
38
|
function LeftSide() {
|
|
@@ -44,305 +42,20 @@ function LeftSide() {
|
|
|
44
42
|
style: { width: LeftSide.ref.width },
|
|
45
43
|
className: CSS.leftSide
|
|
46
44
|
},
|
|
47
|
-
|
|
48
|
-
GroupByMethod(),
|
|
49
|
-
BulkSelector()),
|
|
50
|
-
r('div', { className: CSS.Table }, MockList())))
|
|
45
|
+
MockList()))
|
|
51
46
|
}
|
|
52
47
|
LeftSide.ref = { width: undefined }
|
|
53
48
|
LeftSide.$ = selector => LeftSide.ref.elem.querySelector(selector)
|
|
54
|
-
LeftSide.$$ = selector => LeftSide.ref.elem.querySelectorAll(selector)
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
function GroupByMethod() {
|
|
58
|
-
return (
|
|
59
|
-
r('label', { className: CSS.GroupByMethod },
|
|
60
|
-
r('input', {
|
|
61
|
-
type: 'checkbox',
|
|
62
|
-
checked: store.groupByMethod,
|
|
63
|
-
onChange: store.toggleGroupByMethod
|
|
64
|
-
}),
|
|
65
|
-
r('span', { className: CSS.checkboxBody }, t`Group by Method`)))
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
function BulkSelector() {
|
|
70
|
-
const { comments } = store
|
|
71
|
-
const firstOption = t`Pick Comment…`
|
|
72
|
-
function onChange() {
|
|
73
|
-
const value = this.value
|
|
74
|
-
this.value = firstOption // hack so it’s always selected
|
|
75
|
-
store.bulkSelectByComment(value)
|
|
76
|
-
}
|
|
77
|
-
const disabled = !comments.length
|
|
78
|
-
return (
|
|
79
|
-
r('label', { className: CSS.BulkSelector },
|
|
80
|
-
r('span', null, t`Bulk Select`),
|
|
81
|
-
r('select', {
|
|
82
|
-
disabled,
|
|
83
|
-
autocomplete: 'off',
|
|
84
|
-
title: disabled
|
|
85
|
-
? t`No mock files have comments which are anything within parentheses on the filename.`
|
|
86
|
-
: undefined,
|
|
87
|
-
onChange
|
|
88
|
-
},
|
|
89
|
-
r('option', { value: firstOption }, firstOption),
|
|
90
|
-
r('hr'),
|
|
91
|
-
comments.map(value => r('option', { value }, value)))))
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
function MockList() {
|
|
96
|
-
if (!Object.keys(store.brokersByMethod).length)
|
|
97
|
-
return r('div', null, t`No mocks found`)
|
|
98
|
-
|
|
99
|
-
if (store.groupByMethod)
|
|
100
|
-
return Object.keys(store.brokersByMethod).map(method => Fragment(
|
|
101
|
-
r('div', {
|
|
102
|
-
className: classNames(CSS.TableHeading, store.canProxy && CSS.canProxy)
|
|
103
|
-
}, method),
|
|
104
|
-
FolderGroups(store.folderGroupsByMethod(method))))
|
|
105
|
-
|
|
106
|
-
return FolderGroups(store.folderGroupsByMethod('*'))
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
function FolderGroups(brokersTree) {
|
|
110
|
-
const res = []
|
|
111
|
-
for (const b of brokersTree) {
|
|
112
|
-
if (!b.children.length)
|
|
113
|
-
res.push(Row(b))
|
|
114
|
-
else
|
|
115
|
-
res.push(FolderGroup(b))
|
|
116
|
-
}
|
|
117
|
-
return res
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
function FolderGroup(broker) {
|
|
121
|
-
const folder = broker.urlMask
|
|
122
|
-
const children = broker.children
|
|
123
|
-
return (
|
|
124
|
-
r('details', {
|
|
125
|
-
className: CSS.FolderGroup,
|
|
126
|
-
open: !store.collapsedFolders.has(folder),
|
|
127
|
-
onToggle() {
|
|
128
|
-
store.setFolderCollapsed(folder, !this.open)
|
|
129
|
-
}
|
|
130
|
-
},
|
|
131
|
-
r('summary', null,
|
|
132
|
-
r('span', { className: CSS.FolderChevron }, ChevronDownIcon()),
|
|
133
|
-
r('span', {
|
|
134
|
-
className: classNames(
|
|
135
|
-
CSS.FolderName,
|
|
136
|
-
store.groupByMethod && CSS.groupedByMethod,
|
|
137
|
-
store.canProxy && CSS.canProxy)
|
|
138
|
-
},
|
|
139
|
-
folder + '…')),
|
|
140
|
-
Row(broker),
|
|
141
|
-
children.map(c => c.children.length
|
|
142
|
-
? FolderGroup(c)
|
|
143
|
-
: Row(c))))
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/** @param {BrokerRowModel} row */
|
|
147
|
-
function Row(row) {
|
|
148
|
-
const { method, urlMask } = row
|
|
149
|
-
return (
|
|
150
|
-
r('div', {
|
|
151
|
-
key: row.key,
|
|
152
|
-
className: classNames(CSS.TableRow, mounted && row.isNew && CSS.animIn)
|
|
153
|
-
},
|
|
154
|
-
|
|
155
|
-
store.canProxy && ClickDragToggler({
|
|
156
|
-
className: CSS.ProxyToggler,
|
|
157
|
-
title: t`Proxy Toggler`,
|
|
158
|
-
body: CloudIcon(),
|
|
159
|
-
checked: row.proxied,
|
|
160
|
-
commit(checked) {
|
|
161
|
-
store.setProxied(method, urlMask, checked)
|
|
162
|
-
}
|
|
163
|
-
}),
|
|
164
|
-
|
|
165
|
-
ClickDragToggler({
|
|
166
|
-
className: CSS.DelayToggler,
|
|
167
|
-
title: t`Delay`,
|
|
168
|
-
body: TimerIcon(),
|
|
169
|
-
checked: row.delayed,
|
|
170
|
-
commit(checked) {
|
|
171
|
-
store.setDelayed(method, urlMask, checked)
|
|
172
|
-
}
|
|
173
|
-
}),
|
|
174
|
-
|
|
175
|
-
ClickDragToggler(
|
|
176
|
-
row.isStatic
|
|
177
|
-
? {
|
|
178
|
-
className: CSS.StatusCodeToggler,
|
|
179
|
-
title: t`Not Found`,
|
|
180
|
-
body: t`404`,
|
|
181
|
-
disabled: row.opts.length === 1 && row.status === 404,
|
|
182
|
-
checked: !row.proxied && row.status === 404,
|
|
183
|
-
commit() { store.toggleStatus(method, urlMask, 404) }
|
|
184
|
-
}
|
|
185
|
-
: {
|
|
186
|
-
className: CSS.StatusCodeToggler,
|
|
187
|
-
title: t`Internal Server Error`,
|
|
188
|
-
body: t`500`,
|
|
189
|
-
disabled: row.opts.length === 1 && row.status === 500,
|
|
190
|
-
checked: !row.proxied && row.status === 500,
|
|
191
|
-
commit() { store.toggleStatus(method, urlMask, 500) }
|
|
192
|
-
}),
|
|
193
|
-
|
|
194
|
-
!store.groupByMethod && r('span', { className: CSS.Method }, method),
|
|
195
|
-
|
|
196
|
-
PreviewLink(method, urlMask, row.urlMaskDittoed),
|
|
197
|
-
|
|
198
|
-
MockSelector(row)))
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
function renderRow(method, urlMask) {
|
|
203
|
-
unChooseOld()
|
|
204
|
-
const row = store.brokerAsRow(method, urlMask)
|
|
205
|
-
const tr = LeftSide.$(`.${CSS.TableRow}[key="${row.key}"]`)
|
|
206
|
-
mergeTableRow(tr, Row(row))
|
|
207
|
-
previewMock()
|
|
208
|
-
|
|
209
|
-
function unChooseOld() {
|
|
210
|
-
return LeftSide.$(`a.${CSS.chosen}`)
|
|
211
|
-
?.classList.remove(CSS.chosen)
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
function mergeTableRow(oldRow, newRow) {
|
|
215
|
-
for (let i = 0; i < newRow.children.length; i++) {
|
|
216
|
-
const oldEl = oldRow.children[i]
|
|
217
|
-
const newEl = newRow.children[i]
|
|
218
|
-
switch (newEl.tagName) {
|
|
219
|
-
case 'LABEL': {
|
|
220
|
-
const oldInput = oldEl.querySelector('[type="checkbox"]')
|
|
221
|
-
const newInput = newEl.querySelector('[type="checkbox"]')
|
|
222
|
-
oldInput.checked = newInput.checked
|
|
223
|
-
oldInput.disabled = newInput.disabled
|
|
224
|
-
break
|
|
225
|
-
}
|
|
226
|
-
case 'A':
|
|
227
|
-
oldEl.className = newEl.className
|
|
228
|
-
break
|
|
229
|
-
case 'SELECT':
|
|
230
|
-
oldEl.replaceChildren(...newEl.cloneNode(true).children)
|
|
231
|
-
oldEl.className = newEl.className
|
|
232
|
-
oldEl.disabled = newEl.disabled
|
|
233
|
-
oldEl.value = newEl.value
|
|
234
|
-
break
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
49
|
|
|
240
50
|
|
|
241
|
-
function
|
|
242
|
-
function onClick(event) {
|
|
243
|
-
event.preventDefault()
|
|
244
|
-
store.previewLink(method, urlMask)
|
|
245
|
-
}
|
|
246
|
-
const isChosen = store.chosenLink.method === method && store.chosenLink.urlMask === urlMask
|
|
247
|
-
const [ditto, tail] = urlMaskDittoed
|
|
248
|
-
return (
|
|
249
|
-
r('a', {
|
|
250
|
-
className: classNames(CSS.PreviewLink, isChosen && CSS.chosen),
|
|
251
|
-
href: urlMask,
|
|
252
|
-
onClick
|
|
253
|
-
}, ditto
|
|
254
|
-
? [r('span', { className: CSS.dittoDir }, ditto), tail]
|
|
255
|
-
: tail))
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
/** @param {BrokerRowModel} row */
|
|
260
|
-
function MockSelector(row) {
|
|
261
|
-
return (
|
|
262
|
-
r('select', {
|
|
263
|
-
onChange() {
|
|
264
|
-
store.selectFile(this.value)
|
|
265
|
-
},
|
|
266
|
-
onKeyDown(event) {
|
|
267
|
-
if (event.key === 'ArrowRight' || event.key === 'ArrowLeft')
|
|
268
|
-
event.preventDefault()
|
|
269
|
-
// Because in Firefox they change the select.option, and
|
|
270
|
-
// we use those keys for spreadsheet-like navigation.
|
|
271
|
-
},
|
|
272
|
-
'aria-label': t`Mock Selector`,
|
|
273
|
-
disabled: row.opts.length < 2,
|
|
274
|
-
className: classNames(
|
|
275
|
-
CSS.MockSelector,
|
|
276
|
-
row.selectedIdx > 0 && CSS.nonDefault,
|
|
277
|
-
row.selectedFileIs4xx && CSS.status4xx)
|
|
278
|
-
}, row.opts.map(([value, label, selected]) =>
|
|
279
|
-
r('option', { value, selected }, label))))
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
function ClickDragToggler({ checked, commit, className, title, body }) {
|
|
284
|
-
function onPointerEnter(event) {
|
|
285
|
-
if (event.buttons === 1)
|
|
286
|
-
onPointerDown.call(this, event)
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
function onPointerDown(event) {
|
|
290
|
-
if (event.altKey) {
|
|
291
|
-
onExclusiveClick.call(this)
|
|
292
|
-
return
|
|
293
|
-
}
|
|
294
|
-
this.checked = !this.checked
|
|
295
|
-
this.focus()
|
|
296
|
-
commit(this.checked)
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
function onExclusiveClick() {
|
|
300
|
-
const selector = selectorForColumnOf(this)
|
|
301
|
-
if (!selector)
|
|
302
|
-
return
|
|
303
|
-
|
|
304
|
-
// Uncheck all other in the column.
|
|
305
|
-
for (const elem of LeftSide.$$(selector))
|
|
306
|
-
if (elem !== this && elem.checked && !elem.disabled) {
|
|
307
|
-
elem.checked = false
|
|
308
|
-
elem.dispatchEvent(new Event('change'))
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
if (!this.checked) {
|
|
312
|
-
this.checked = true
|
|
313
|
-
this.dispatchEvent(new Event('change'))
|
|
314
|
-
}
|
|
315
|
-
this.focus()
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
function onClick(event) {
|
|
319
|
-
if (event.pointerType === 'mouse')
|
|
320
|
-
event.preventDefault()
|
|
321
|
-
}
|
|
322
|
-
function onChange() {
|
|
323
|
-
commit(this.checked)
|
|
324
|
-
}
|
|
325
|
-
return (
|
|
326
|
-
r('label', { className: classNames(CSS.Toggler, className), title },
|
|
327
|
-
r('input', {
|
|
328
|
-
type: 'checkbox',
|
|
329
|
-
checked,
|
|
330
|
-
onPointerEnter,
|
|
331
|
-
onPointerDown,
|
|
332
|
-
onClick,
|
|
333
|
-
onChange
|
|
334
|
-
}),
|
|
335
|
-
r('span', { className: CSS.checkboxBody }, body)))
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
function Resizer(ref) {
|
|
51
|
+
function Resizer() {
|
|
339
52
|
let raf = 0
|
|
340
53
|
let initialX = 0
|
|
341
54
|
let initialWidth = 0
|
|
342
55
|
|
|
343
56
|
function onPointerDown(event) {
|
|
344
57
|
initialX = event.clientX
|
|
345
|
-
initialWidth = ref.elem.clientWidth
|
|
58
|
+
initialWidth = LeftSide.ref.elem.clientWidth
|
|
346
59
|
addEventListener('pointerup', onUp, { once: true })
|
|
347
60
|
addEventListener('pointermove', onMove)
|
|
348
61
|
Object.assign(document.body.style, {
|
|
@@ -355,8 +68,8 @@ function Resizer(ref) {
|
|
|
355
68
|
function onMove(event) {
|
|
356
69
|
const MIN_LEFT_WIDTH = 350
|
|
357
70
|
raf = raf || requestAnimationFrame(() => {
|
|
358
|
-
ref.width = Math.max(initialWidth - (initialX - event.clientX), MIN_LEFT_WIDTH) + 'px'
|
|
359
|
-
ref.elem.style.width = ref.width
|
|
71
|
+
LeftSide.ref.width = Math.max(initialWidth - (initialX - event.clientX), MIN_LEFT_WIDTH) + 'px'
|
|
72
|
+
LeftSide.ref.elem.style.width = LeftSide.ref.width
|
|
360
73
|
raf = 0
|
|
361
74
|
})
|
|
362
75
|
}
|
|
@@ -468,58 +181,3 @@ function onRealTimeUpdate(onUpdate) {
|
|
|
468
181
|
conn = null
|
|
469
182
|
}
|
|
470
183
|
}
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
function selectorForColumnOf(elem) {
|
|
475
|
-
return columnSelectors().find(s => elem?.matches(s))
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
function columnSelectors() {
|
|
479
|
-
return [
|
|
480
|
-
`.${CSS.TableRow} .${CSS.ProxyToggler} input`,
|
|
481
|
-
`.${CSS.TableRow} .${CSS.DelayToggler} input`,
|
|
482
|
-
`.${CSS.TableRow} .${CSS.StatusCodeToggler} input`,
|
|
483
|
-
`.${CSS.TableRow} .${CSS.PreviewLink}`,
|
|
484
|
-
// No .MockSelector because down/up arrows have native behavior on them
|
|
485
|
-
]
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
function initKeyboardNavigation() {
|
|
489
|
-
const rowSelectors = [
|
|
490
|
-
...columnSelectors(),
|
|
491
|
-
`.${CSS.TableRow} .${CSS.MockSelector}:enabled`,
|
|
492
|
-
]
|
|
493
|
-
|
|
494
|
-
addEventListener('keydown', function ({ key }) {
|
|
495
|
-
switch (key) {
|
|
496
|
-
case 'ArrowDown':
|
|
497
|
-
case 'ArrowUp': {
|
|
498
|
-
const pivot = document.activeElement
|
|
499
|
-
const sel = selectorForColumnOf(pivot)
|
|
500
|
-
if (sel) {
|
|
501
|
-
const offset = key === 'ArrowDown' ? +1 : -1
|
|
502
|
-
const siblings = LeftSide.$$(sel)
|
|
503
|
-
circularAdjacent(offset, siblings, pivot).focus()
|
|
504
|
-
}
|
|
505
|
-
break
|
|
506
|
-
}
|
|
507
|
-
case 'ArrowRight':
|
|
508
|
-
case 'ArrowLeft': {
|
|
509
|
-
const pivot = document.activeElement
|
|
510
|
-
const sel = rowSelectors.find(s => pivot?.matches(s))
|
|
511
|
-
if (sel) {
|
|
512
|
-
const offset = key === 'ArrowRight' ? +1 : -1
|
|
513
|
-
const siblings = pivot.closest(`.${CSS.TableRow}`).querySelectorAll(rowSelectors.join(','))
|
|
514
|
-
circularAdjacent(offset, siblings, pivot).focus()
|
|
515
|
-
}
|
|
516
|
-
break
|
|
517
|
-
}
|
|
518
|
-
}
|
|
519
|
-
})
|
|
520
|
-
|
|
521
|
-
function circularAdjacent(step, siblings, pivot) {
|
|
522
|
-
const arr = Array.from(siblings)
|
|
523
|
-
return arr[(arr.indexOf(pivot) + step + arr.length) % arr.length]
|
|
524
|
-
}
|
|
525
|
-
}
|
package/src/client/utils/css.js
CHANGED
|
@@ -3,6 +3,13 @@ export function classNames(...args) {
|
|
|
3
3
|
}
|
|
4
4
|
|
|
5
5
|
|
|
6
|
+
export function adoptSheet(sheet, url) {
|
|
7
|
+
sheet.__url = url.replace(/^\.\//, '')
|
|
8
|
+
document.adoptedStyleSheets.push(sheet)
|
|
9
|
+
Object.assign(sheet, extractClassNames(sheet))
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
|
|
6
13
|
export function extractClassNames({ cssRules }) {
|
|
7
14
|
// Class names must begin with _ or a letter, then it can have numbers and hyphens
|
|
8
15
|
// TODO think about tag.className selectors
|
|
@@ -41,6 +41,9 @@ function init() {
|
|
|
41
41
|
|
|
42
42
|
async function hotReloadCSS(file) {
|
|
43
43
|
const mod = await import(`${document.baseURI}${file}?${Date.now()}`, { with: { type: 'css' } })
|
|
44
|
-
|
|
44
|
+
mod.default.__url = file
|
|
45
|
+
for (let i = 0; i < document.adoptedStyleSheets.length; i++)
|
|
46
|
+
if (document.adoptedStyleSheets[i].__url === file)
|
|
47
|
+
document.adoptedStyleSheets[i] = mod.default
|
|
45
48
|
}
|
|
46
49
|
}
|