@bitstillery/mithril 3.9.1 → 3.9.2
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/api/router.ts +5 -5
- package/package.json +1 -1
- package/pathname/compileTemplate.ts +3 -2
- package/querystring/parse.ts +6 -5
- package/render/hyperscript.ts +7 -5
- package/render/render.ts +12 -10
- package/render/ssrState.ts +2 -2
- package/server/logger.ts +1 -1
- package/server/session.ts +1 -1
- package/store.ts +3 -3
- package/util/ssr.ts +1 -1
package/api/router.ts
CHANGED
|
@@ -167,7 +167,7 @@ export default function router($window: any, mountRedraw: MountRedraw) {
|
|
|
167
167
|
function getRedirectPath(redirectObj: RedirectObject): string {
|
|
168
168
|
// First try our REDIRECT symbol
|
|
169
169
|
if (REDIRECT in redirectObj) {
|
|
170
|
-
return redirectObj[REDIRECT]
|
|
170
|
+
return redirectObj[REDIRECT]!
|
|
171
171
|
}
|
|
172
172
|
// Otherwise, check all symbol keys
|
|
173
173
|
const symbolKeys = Object.getOwnPropertySymbols(redirectObj)
|
|
@@ -215,9 +215,9 @@ export default function router($window: any, mountRedraw: MountRedraw) {
|
|
|
215
215
|
function loop(i: number) {
|
|
216
216
|
if (!compiled) return
|
|
217
217
|
for (; i < compiled.length; i++) {
|
|
218
|
-
if (compiled[i]
|
|
219
|
-
let payload = compiled[i]
|
|
220
|
-
const matchedRoute = compiled[i]
|
|
218
|
+
if (compiled[i]!.check(data)) {
|
|
219
|
+
let payload = compiled[i]!.component
|
|
220
|
+
const matchedRoute = compiled[i]!.route
|
|
221
221
|
const localComp = payload
|
|
222
222
|
// Store the RouteResolver if payload has both onmatch and render
|
|
223
223
|
// This allows us to preserve the resolver even after onmatch returns a component
|
|
@@ -237,7 +237,7 @@ export default function router($window: any, mountRedraw: MountRedraw) {
|
|
|
237
237
|
// Handle redirect objects: explicit redirect signal
|
|
238
238
|
if (isRedirect(comp)) {
|
|
239
239
|
// Extract redirect target path
|
|
240
|
-
const redirectPath = comp
|
|
240
|
+
const redirectPath = getRedirectPath(comp)
|
|
241
241
|
const resolve = routeSetResolve
|
|
242
242
|
routeSetResolve = null
|
|
243
243
|
// Trigger navigation to redirect target; resolve original Promise when redirect completes
|
package/package.json
CHANGED
|
@@ -38,14 +38,15 @@ export default function compileTemplate(template: string): CompiledTemplate {
|
|
|
38
38
|
// First, check the params. Usually, there isn't any, and it's just
|
|
39
39
|
// checking a static set.
|
|
40
40
|
for (let i = 0; i < templateKeys.length; i++) {
|
|
41
|
-
if (templateData.params[templateKeys[i]] !== data.params[templateKeys[i]]) return false
|
|
41
|
+
if (templateData.params[templateKeys[i]!] !== data.params[templateKeys[i]!]) return false
|
|
42
42
|
}
|
|
43
43
|
// If no interpolations exist, let's skip all the ceremony
|
|
44
44
|
if (!keys.length) return regexp.test(data.path)
|
|
45
45
|
const values = regexp.exec(data.path)
|
|
46
46
|
if (values == null) return false
|
|
47
47
|
for (let i = 0; i < keys.length; i++) {
|
|
48
|
-
|
|
48
|
+
// Every key is a non-optional capture group, so a match fills all of them.
|
|
49
|
+
data.params[keys[i]!.k] = keys[i]!.r ? values[i + 1] : decodeURIComponent(values[i + 1]!)
|
|
49
50
|
}
|
|
50
51
|
return true
|
|
51
52
|
}
|
package/querystring/parse.ts
CHANGED
|
@@ -8,9 +8,9 @@ export default function parseQueryString(string: string | null | undefined): Rec
|
|
|
8
8
|
const counters: Record<string, number> = {}
|
|
9
9
|
const data: Record<string, any> = {}
|
|
10
10
|
for (let i = 0; i < entries.length; i++) {
|
|
11
|
-
const entry = entries[i]
|
|
12
|
-
const key = decodeURIComponentSafe(entry[0])
|
|
13
|
-
let value: any = entry.length === 2 ? decodeURIComponentSafe(entry[1]) : ''
|
|
11
|
+
const entry = entries[i]!.split('=')
|
|
12
|
+
const key = decodeURIComponentSafe(entry[0]!)
|
|
13
|
+
let value: any = entry.length === 2 ? decodeURIComponentSafe(entry[1]!) : ''
|
|
14
14
|
|
|
15
15
|
if (value === 'true') value = true
|
|
16
16
|
else if (value === 'false') value = false
|
|
@@ -19,9 +19,10 @@ export default function parseQueryString(string: string | null | undefined): Rec
|
|
|
19
19
|
let cursor: any = data
|
|
20
20
|
if (key.indexOf('[') > -1) levels.pop()
|
|
21
21
|
for (let j = 0; j < levels.length; j++) {
|
|
22
|
-
const level = levels[j]
|
|
22
|
+
const level = levels[j]!
|
|
23
23
|
const nextLevel = levels[j + 1]
|
|
24
|
-
|
|
24
|
+
// Past the last level nextLevel is undefined, which parseInt reads as NaN.
|
|
25
|
+
const isNumber = nextLevel == '' || !isNaN(parseInt(nextLevel as string, 10))
|
|
25
26
|
let finalLevel: string | number
|
|
26
27
|
if (level === '') {
|
|
27
28
|
const key = levels.slice(0, j).join()
|
package/render/hyperscript.ts
CHANGED
|
@@ -31,25 +31,27 @@ function isFormAttributeKey(key: string): boolean {
|
|
|
31
31
|
return key === 'value' || key === 'checked' || key === 'selectedIndex' || key === 'selected'
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
// A match fills groups 1-2 (tag/#id/.class) or groups 3-4 ([attr]), never both; group 6
|
|
35
|
+
// is absent for a bare `[attr]`, so a bare `[class]` joins in as an empty class.
|
|
34
36
|
function compileSelector(selector: string): {tag: string; attrs: Record<string, any>; is?: string} {
|
|
35
37
|
let match: RegExpExecArray | null
|
|
36
38
|
let tag = 'div'
|
|
37
|
-
const classes: string[] = []
|
|
39
|
+
const classes: (string | undefined)[] = []
|
|
38
40
|
let attrs: Record<string, any> = {}
|
|
39
41
|
let isStatic = true
|
|
40
42
|
while ((match = selectorParser.exec(selector)) !== null) {
|
|
41
43
|
const type = match[1]
|
|
42
44
|
const value = match[2]
|
|
43
|
-
if (type === '' && value !== '') tag = value
|
|
45
|
+
if (type === '' && value !== '') tag = value!
|
|
44
46
|
else if (type === '#') attrs.id = value
|
|
45
47
|
else if (type === '.') classes.push(value)
|
|
46
|
-
else if (match[3][0] === '[') {
|
|
48
|
+
else if (match[3]![0] === '[') {
|
|
47
49
|
let attrValue = match[6]
|
|
48
50
|
if (attrValue) attrValue = attrValue.replace(/\\(["'])/g, '$1').replace(/\\\\/g, '\\')
|
|
49
51
|
if (match[4] === 'class') classes.push(attrValue)
|
|
50
52
|
else {
|
|
51
|
-
attrs[match[4]] = attrValue === '' ? attrValue : attrValue || true
|
|
52
|
-
if (isFormAttributeKey(match[4])) isStatic = false
|
|
53
|
+
attrs[match[4]!] = attrValue === '' ? attrValue : attrValue || true
|
|
54
|
+
if (isFormAttributeKey(match[4]!)) isStatic = false
|
|
53
55
|
}
|
|
54
56
|
}
|
|
55
57
|
}
|
package/render/render.ts
CHANGED
|
@@ -895,16 +895,18 @@ export default function renderFactory() {
|
|
|
895
895
|
// of the items that are part of the longest increasing
|
|
896
896
|
// subsequence
|
|
897
897
|
const lisTemp: number[] = []
|
|
898
|
+
// Every index read below is in range: i < a.length, `result` is never empty and holds
|
|
899
|
+
// indices into `a`, and `lisTemp` mirrors `a`'s length.
|
|
898
900
|
function makeLisIndices(a: number[]): number[] {
|
|
899
901
|
const result = [0]
|
|
900
902
|
let u = 0,
|
|
901
903
|
v = 0
|
|
902
904
|
const il = (lisTemp.length = a.length)
|
|
903
|
-
for (let i = 0; i < il; i++) lisTemp[i] = a[i]
|
|
905
|
+
for (let i = 0; i < il; i++) lisTemp[i] = a[i]!
|
|
904
906
|
for (let i = 0; i < il; ++i) {
|
|
905
907
|
if (a[i] === -1) continue
|
|
906
|
-
const j = result[result.length - 1]
|
|
907
|
-
if (a[j] < a[i]) {
|
|
908
|
+
const j = result[result.length - 1]!
|
|
909
|
+
if (a[j]! < a[i]!) {
|
|
908
910
|
lisTemp[i] = j
|
|
909
911
|
result.push(i)
|
|
910
912
|
continue
|
|
@@ -915,22 +917,22 @@ export default function renderFactory() {
|
|
|
915
917
|
// Fast integer average without overflow.
|
|
916
918
|
|
|
917
919
|
const c = (u >>> 1) + (v >>> 1) + (u & v & 1)
|
|
918
|
-
if (a[result[c]] < a[i]) {
|
|
920
|
+
if (a[result[c]!]! < a[i]!) {
|
|
919
921
|
u = c + 1
|
|
920
922
|
} else {
|
|
921
923
|
v = c
|
|
922
924
|
}
|
|
923
925
|
}
|
|
924
|
-
if (a[i] < a[result[u]]) {
|
|
925
|
-
if (u > 0) lisTemp[i] = result[u - 1]
|
|
926
|
+
if (a[i]! < a[result[u]!]!) {
|
|
927
|
+
if (u > 0) lisTemp[i] = result[u - 1]!
|
|
926
928
|
result[u] = i
|
|
927
929
|
}
|
|
928
930
|
}
|
|
929
931
|
u = result.length
|
|
930
|
-
v = result[u - 1]
|
|
932
|
+
v = result[u - 1]!
|
|
931
933
|
while (u-- > 0) {
|
|
932
934
|
result[u] = v
|
|
933
|
-
v = lisTemp[v]
|
|
935
|
+
v = lisTemp[v]!
|
|
934
936
|
}
|
|
935
937
|
lisTemp.length = 0
|
|
936
938
|
return result
|
|
@@ -1453,14 +1455,14 @@ export default function renderFactory() {
|
|
|
1453
1455
|
false,
|
|
1454
1456
|
)
|
|
1455
1457
|
// Execute hooks from override render
|
|
1456
|
-
for (let i = 0; i < overrideHooks.length; i++) overrideHooks[i]()
|
|
1458
|
+
for (let i = 0; i < overrideHooks.length; i++) overrideHooks[i]!()
|
|
1457
1459
|
}
|
|
1458
1460
|
|
|
1459
1461
|
;(dom as any).vnodes = normalized
|
|
1460
1462
|
// `document.activeElement` can return null: https://html.spec.whatwg.org/multipage/interaction.html#dom-document-activeelement
|
|
1461
1463
|
if (active != null && activeElement(dom) !== active && typeof (active as any).focus === 'function')
|
|
1462
1464
|
(active as any).focus()
|
|
1463
|
-
for (let i = 0; i < hooks.length; i++) hooks[i]()
|
|
1465
|
+
for (let i = 0; i < hooks.length; i++) hooks[i]!()
|
|
1464
1466
|
} finally {
|
|
1465
1467
|
currentRedraw = prevRedraw
|
|
1466
1468
|
currentDOM = prevDOM
|
package/render/ssrState.ts
CHANGED
|
@@ -306,11 +306,11 @@ function restoreComputedProperties(state: State<any>, initial: any): void {
|
|
|
306
306
|
const keys = prefix ? prefix.split('.').filter((k) => k) : []
|
|
307
307
|
let targetState = target
|
|
308
308
|
for (let i = 0; i < keys.length; i++) {
|
|
309
|
-
if (!targetState[keys[i]]) {
|
|
309
|
+
if (!targetState[keys[i]!]) {
|
|
310
310
|
// Nested state doesn't exist yet, skip
|
|
311
311
|
return
|
|
312
312
|
}
|
|
313
|
-
targetState = targetState[keys[i]]
|
|
313
|
+
targetState = targetState[keys[i]!]
|
|
314
314
|
}
|
|
315
315
|
// Clear any existing signal in signalMap so function is re-initialized as ComputedSignal
|
|
316
316
|
if (targetState && typeof targetState === 'object' && (targetState as any).__isState) {
|
package/server/logger.ts
CHANGED
|
@@ -96,7 +96,7 @@ function getColorByHash(text: string): string {
|
|
|
96
96
|
colors.cyan,
|
|
97
97
|
]
|
|
98
98
|
const hash = hashString(text)
|
|
99
|
-
return colorOptions[hash % colorOptions.length]
|
|
99
|
+
return colorOptions[hash % colorOptions.length]!
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
const textEncoder = typeof TextEncoder !== 'undefined' ? new TextEncoder() : null
|
package/server/session.ts
CHANGED
|
@@ -83,5 +83,5 @@ export class MemorySessionStore implements SessionStore {
|
|
|
83
83
|
export function extractSessionId(req: Request): string | null {
|
|
84
84
|
const cookies = req.headers.get('cookie') || ''
|
|
85
85
|
const sessionIdMatch = cookies.match(/sessionId=([^;]+)/)
|
|
86
|
-
return sessionIdMatch ? sessionIdMatch[1] : null
|
|
86
|
+
return sessionIdMatch ? sessionIdMatch[1]! : null
|
|
87
87
|
}
|
package/store.ts
CHANGED
|
@@ -21,11 +21,11 @@ function restoreComputedProperties(state: State<any>, initial: any): void {
|
|
|
21
21
|
const keys = prefix ? prefix.split('.').filter((k) => k) : []
|
|
22
22
|
let targetState = target
|
|
23
23
|
for (let i = 0; i < keys.length; i++) {
|
|
24
|
-
if (!targetState || !targetState[keys[i]]) {
|
|
24
|
+
if (!targetState || !targetState[keys[i]!]) {
|
|
25
25
|
// Nested state doesn't exist yet, skip
|
|
26
26
|
return
|
|
27
27
|
}
|
|
28
|
-
targetState = targetState[keys[i]]
|
|
28
|
+
targetState = targetState[keys[i]!]
|
|
29
29
|
}
|
|
30
30
|
if (targetState) {
|
|
31
31
|
// Clear any existing signal in signalMap so function is re-initialized as ComputedSignal
|
|
@@ -536,7 +536,7 @@ export class Store<T extends Record<string, any> = Record<string, any>> {
|
|
|
536
536
|
try {
|
|
537
537
|
const match = document.cookie.match(new RegExp(`(?:^|;\\s*)${key}=([^;]*)`))
|
|
538
538
|
if (!match) return {}
|
|
539
|
-
const parsed = JSON.parse(decodeURIComponent(match[1]))
|
|
539
|
+
const parsed = JSON.parse(decodeURIComponent(match[1]!))
|
|
540
540
|
return parsed && typeof parsed === 'object' ? parsed : {}
|
|
541
541
|
} catch {
|
|
542
542
|
return {}
|
package/util/ssr.ts
CHANGED
|
@@ -198,7 +198,7 @@ function formatCombinedStructure(parent: Element | Node | null, vnode: any, maxP
|
|
|
198
198
|
|
|
199
199
|
// Closing tags for DOM parents (in reverse order)
|
|
200
200
|
for (let i = domElements.length - 1; i >= 0; i--) {
|
|
201
|
-
lines.push(' '.repeat(i) + domElements[i]
|
|
201
|
+
lines.push(' '.repeat(i) + domElements[i]!.closeTag)
|
|
202
202
|
}
|
|
203
203
|
|
|
204
204
|
return lines.join('\n')
|