forked from sveltejs/svelte
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathInlineComponent.ts
113 lines (88 loc) · 2.93 KB
/
InlineComponent.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
import { escape, escape_template, stringify } from '../../utils/stringify';
import { quote_name_if_necessary } from '../../../utils/names';
import { snip } from '../../utils/snip';
import Renderer from '../Renderer';
import { stringify_props } from '../../utils/stringify_props';
import { get_slot_scope } from './shared/get_slot_scope';
import { AppendTarget } from '../../../interfaces';
function stringify_attribute(chunk: Node) {
if (chunk.type === 'Text') {
return escape_template(escape(chunk.data));
}
return '${@escape(' + snip(chunk) + ')}';
}
function get_attribute_value(attribute) {
if (attribute.is_true) return `true`;
if (attribute.chunks.length === 0) return `''`;
if (attribute.chunks.length === 1) {
const chunk = attribute.chunks[0];
if (chunk.type === 'Text') {
return stringify(chunk.data);
}
return snip(chunk);
}
return '`' + attribute.chunks.map(stringify_attribute).join('') + '`';
}
export default function(node, renderer: Renderer, options) {
const binding_props = [];
const binding_fns = [];
node.bindings.forEach(binding => {
renderer.has_bindings = true;
// TODO this probably won't work for contextual bindings
const snippet = snip(binding.expression);
binding_props.push(`${binding.name}: ${snippet}`);
binding_fns.push(`${binding.name}: $$value => { ${snippet} = $$value; $$settled = false }`);
});
const uses_spread = node.attributes.find(attr => attr.is_spread);
let props;
if (uses_spread) {
props = `Object.assign(${
node.attributes
.map(attribute => {
if (attribute.is_spread) {
return snip(attribute.expression);
} else {
return `{ ${attribute.name}: ${get_attribute_value(attribute)} }`;
}
})
.concat(binding_props.map(p => `{ ${p} }`))
.join(', ')
})`;
} else {
props = stringify_props(
node.attributes
.map(attribute => `${attribute.name}: ${get_attribute_value(attribute)}`)
.concat(binding_props)
);
}
const bindings = stringify_props(binding_fns);
const expression = (
node.name === 'svelte:self'
? '__svelte:self__' // TODO conflict-proof this
: node.name === 'svelte:component'
? `((${snip(node.expression)}) || @missing_component)`
: node.name
);
const slot_fns = [];
if (node.children.length) {
const target: AppendTarget = {
slots: { default: '' },
slot_stack: ['default']
};
renderer.targets.push(target);
const slot_scopes = new Map();
slot_scopes.set('default', get_slot_scope(node.lets));
renderer.render(node.children, Object.assign({}, options, {
slot_scopes
}));
Object.keys(target.slots).forEach(name => {
const slot_scope = slot_scopes.get(name);
slot_fns.push(
`${quote_name_if_necessary(name)}: (${slot_scope}) => \`${target.slots[name]}\``
);
});
renderer.targets.pop();
}
const slots = stringify_props(slot_fns);
renderer.append(`\${@validate_component(${expression}, '${node.name}').$$render($$result, ${props}, ${bindings}, ${slots})}`);
}