/
utils.ts
115 lines (99 loc) · 3.38 KB
/
utils.ts
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
import { GlobalMountOptions, RefSelector } from './types'
import { ComponentOptions, ConcreteComponent, FunctionalComponent } from 'vue'
import { config } from './config'
function mergeStubs(target: Record<string, any>, source: GlobalMountOptions) {
if (source.stubs) {
if (Array.isArray(source.stubs)) {
source.stubs.forEach((x) => (target[x] = true))
} else {
for (const [k, v] of Object.entries(source.stubs)) {
target[k] = v
}
}
}
}
export function mergeGlobalProperties(
mountGlobal: GlobalMountOptions = {}
): Required<GlobalMountOptions> {
const stubs: Record<string, any> = {}
const configGlobal: GlobalMountOptions = config?.global ?? {}
mergeStubs(stubs, configGlobal)
mergeStubs(stubs, mountGlobal)
const renderStubDefaultSlot =
mountGlobal.renderStubDefaultSlot ??
config?.renderStubDefaultSlot ??
configGlobal?.renderStubDefaultSlot
return {
mixins: [...(configGlobal.mixins || []), ...(mountGlobal.mixins || [])],
plugins: [...(configGlobal.plugins || []), ...(mountGlobal.plugins || [])],
stubs,
components: { ...configGlobal.components, ...mountGlobal.components },
provide: { ...configGlobal.provide, ...mountGlobal.provide },
mocks: { ...configGlobal.mocks, ...mountGlobal.mocks },
config: { ...configGlobal.config, ...mountGlobal.config },
directives: { ...configGlobal.directives, ...mountGlobal.directives },
renderStubDefaultSlot
}
}
export const isObject = (obj: unknown): obj is Record<string, any> =>
!!obj && typeof obj === 'object'
// https://stackoverflow.com/a/48218209
export const mergeDeep = (
target: Record<string, unknown>,
source: Record<string, unknown>
) => {
if (!isObject(target) || !isObject(source)) {
return source
}
Object.keys(source).forEach((key) => {
const targetValue = target[key]
const sourceValue = source[key]
if (Array.isArray(targetValue) && Array.isArray(sourceValue)) {
target[key] = sourceValue
} else if (isObject(targetValue) && isObject(sourceValue)) {
target[key] = mergeDeep(Object.assign({}, targetValue), sourceValue)
} else {
target[key] = sourceValue
}
})
return target
}
export function isClassComponent(component: unknown) {
return typeof component === 'function' && '__vccOpts' in component
}
export function isComponent(
component: unknown
): component is ConcreteComponent {
return Boolean(
component &&
(typeof component === 'object' || typeof component === 'function')
)
}
export function isFunctionalComponent(
component: unknown
): component is FunctionalComponent {
return typeof component === 'function' && !isClassComponent(component)
}
export function isObjectComponent(
component: unknown
): component is ComponentOptions {
return Boolean(component && typeof component === 'object')
}
export function textContent(element: Node): string {
// we check if the element is a comment first
// to return an empty string in that case, instead of the comment content
return element.nodeType !== Node.COMMENT_NODE
? element.textContent?.trim() ?? ''
: ''
}
export function hasOwnProperty<O extends {}, P extends PropertyKey>(
obj: O,
prop: P
): obj is O & Record<P, unknown> {
return obj.hasOwnProperty(prop)
}
export function isRefSelector(
selector: string | RefSelector
): selector is RefSelector {
return typeof selector === 'object' && 'ref' in selector
}