forked from vuejs/vue-test-utils
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathget-scoped-slots.js
87 lines (81 loc) · 2.2 KB
/
get-scoped-slots.js
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
// @flow
import Vue from 'vue'
import { compileToFunctions } from 'vue-template-compiler'
import { throwError, vueVersion } from 'shared/util'
function isDestructuringSlotScope (slotScope: string): boolean {
return slotScope[0] === '{' && slotScope[slotScope.length - 1] === '}'
}
function getVueTemplateCompilerHelpers (): { [name: string]: Function } {
const vue = new Vue()
const helpers = {}
const names = [
'_c',
'_o',
'_n',
'_s',
'_l',
'_t',
'_q',
'_i',
'_m',
'_f',
'_k',
'_b',
'_v',
'_e',
'_u',
'_g'
]
names.forEach(name => {
helpers[name] = vue._renderProxy[name]
})
return helpers
}
function validateEnvironment (): void {
if (window.navigator.userAgent.match(/PhantomJS/i)) {
throwError(
`the scopedSlots option does not support PhantomJS. ` +
`Please use Puppeteer, or pass a component.`
)
}
if (vueVersion < 2.5) {
throwError(`the scopedSlots option is only supported in ` + `[email protected]+.`)
}
}
function validateTempldate (template: string): void {
if (template.trim().substr(0, 9) === '<template') {
throwError(
`the scopedSlots option does not support a template ` +
`tag as the root element.`
)
}
}
export default function getScopedSlots (
scopedSlotsOption: ?{ [slotName: string]: string }
): { [slotName: string]: (props: Object) => VNode } {
const scopedSlots = {}
if (!scopedSlotsOption) {
return scopedSlots
}
validateEnvironment()
const helpers = getVueTemplateCompilerHelpers()
for (const name in scopedSlotsOption) {
const template = scopedSlotsOption[name]
validateTempldate(template)
const render = compileToFunctions(template).render
const domParser = new window.DOMParser()
const _document = domParser.parseFromString(template, 'text/html')
const slotScope = _document.body.firstChild.getAttribute(
'slot-scope'
)
const isDestructuring = isDestructuringSlotScope(slotScope)
scopedSlots[name] = function (props) {
if (isDestructuring) {
return render.call({ ...helpers, ...props })
} else {
return render.call({ ...helpers, [slotScope]: props })
}
}
}
return scopedSlots
}