@@ -10,6 +10,22 @@ const {match} = require('posthtml/lib/api');
10
10
const merge = require ( 'deepmerge' ) ;
11
11
const findPathFromTagName = require ( './find-path' ) ;
12
12
13
+ // Used for slot without name
14
+ const defaultSlotName = '___default__slot__name___' ;
15
+
16
+ const defaultSlotType = 'replace' ;
17
+
18
+ const slotTypes = {
19
+ append : 'append' ,
20
+ prepend : 'prepend'
21
+ } ;
22
+
23
+ /**
24
+ * Process tree's nodes
25
+ * @param {Object } tree - posthtml tree
26
+ * @param {Object } options - plugin options
27
+ * @param {Object } messages - posthtml tree messages
28
+ */
13
29
function processNodes ( tree , options , messages ) {
14
30
tree = applyPluginsToTree ( tree , options . plugins ) ;
15
31
@@ -71,6 +87,13 @@ function processNodes(tree, options, messages) {
71
87
return tree ;
72
88
}
73
89
90
+ /**
91
+ * Parse locals from attributes, globals and via script
92
+ * @param {Object } tree - posthtml tree
93
+ * @param {Object } options - plugin options
94
+ * @param {Object } html - posthtml tree
95
+ * @return {Object } merged locals and default
96
+ */
74
97
function parseLocals ( options , { attrs} , html ) {
75
98
let attributes = { ...attrs } ;
76
99
@@ -96,6 +119,14 @@ function parseLocals(options, {attrs}, html) {
96
119
return { attributes, defaultLocals} ;
97
120
}
98
121
122
+ /**
123
+ * Merge slots content
124
+ * @param {Object } tree
125
+ * @param {Object } component
126
+ * @param {Boolean } strict
127
+ * @param {String } slotTagName
128
+ * @return {Object } tree
129
+ */
99
130
function mergeSlots ( tree , component , strict , slotTagName ) {
100
131
const slots = getSlots ( slotTagName , tree ) ; // Slot in component.html
101
132
const fillSlots = getSlots ( slotTagName , component . content ) ; // Slot in page.html
@@ -114,9 +145,8 @@ function mergeSlots(tree, component, strict, slotTagName) {
114
145
continue ;
115
146
}
116
147
117
- const slotType = [ 'replace' , 'prepend' , 'append' ] . includes ( ( ( slotNode . attrs && slotNode . attrs . type ) || '' ) . toLowerCase ( ) ) ?
118
- ( ( slotNode . attrs && slotNode . attrs . type ) || '' ) . toLowerCase ( ) :
119
- 'replace' ;
148
+ let slotType = slotTypes [ ( slotNode . attrs . type || defaultSlotType ) . toLowerCase ( ) ] || defaultSlotType ;
149
+ slotType = typeof slotNode . attrs . append === 'undefined' ? ( typeof slotNode . attrs . prepend === 'undefined' ? slotType : slotTypes . prepend ) : slotTypes . append ;
120
150
121
151
const layoutBlockNodeList = slots [ slotName ] ;
122
152
for ( const layoutBlockNode of layoutBlockNodeList ) {
@@ -145,25 +175,48 @@ function mergeSlots(tree, component, strict, slotTagName) {
145
175
return tree ;
146
176
}
147
177
178
+ /**
179
+ * Prepend, append or replace slot content
180
+ * @param {Object } slotContent
181
+ * @param {Object } defaultContent
182
+ * @param {String } slotType
183
+ * @return {Object }
184
+ */
148
185
function mergeContent ( slotContent , defaultContent , slotType ) {
149
186
slotContent = slotContent || [ ] ;
150
187
defaultContent = defaultContent || [ ] ;
151
188
152
- if ( ! [ 'append' , 'prepend' ] . includes ( slotType ) ) {
189
+ // Replace
190
+ if ( ! Object . keys ( slotTypes ) . includes ( slotType ) ) {
153
191
return slotContent ;
154
192
}
155
193
156
- return slotType === 'prepend' ?
194
+ // Prepend or append
195
+ return slotType === slotTypes . prepend ?
157
196
slotContent . concat ( defaultContent ) :
158
197
defaultContent . concat ( slotContent ) ;
159
198
}
160
199
200
+ /**
201
+ * Get all slots from content
202
+ * @param {String } tag
203
+ * @param {Object } content
204
+ * @return {Object }
205
+ */
161
206
function getSlots ( tag , content = [ ] ) {
162
207
const slots = { } ;
163
208
164
209
match . call ( content , { tag} , node => {
165
- if ( ! node . attrs || ! node . attrs . name ) {
166
- throw new Error ( '[components] Missing slot name' ) ;
210
+ if ( ! node . attrs ) {
211
+ node . attrs = { } ;
212
+ }
213
+
214
+ if ( ! node . attrs . name ) {
215
+ node . attrs . name = Object . keys ( { ...node . attrs } ) . find ( name => ! Object . keys ( slotTypes ) . includes ( name ) && name !== 'type' ) ;
216
+ }
217
+
218
+ if ( ! node . attrs . name ) {
219
+ node . attrs . name = defaultSlotName ;
167
220
}
168
221
169
222
const { name} = node . attrs ;
@@ -180,6 +233,12 @@ function getSlots(tag, content = []) {
180
233
return slots ;
181
234
}
182
235
236
+ /**
237
+ * Apply plugins to tree
238
+ * @param {Object } tree
239
+ * @param {Array } plugins
240
+ * @return {Object }
241
+ */
183
242
function applyPluginsToTree ( tree , plugins ) {
184
243
return plugins . reduce ( ( tree , plugin ) => {
185
244
tree = plugin ( tree ) ;
0 commit comments