17 match, result; |
17 match, result; |
18 |
18 |
19 re.lastIndex = index || 0; |
19 re.lastIndex = index || 0; |
20 match = re.exec( text ); |
20 match = re.exec( text ); |
21 |
21 |
22 if ( ! match ) |
22 if ( ! match ) { |
23 return; |
23 return; |
|
24 } |
24 |
25 |
25 // If we matched an escaped shortcode, try again. |
26 // If we matched an escaped shortcode, try again. |
26 if ( match[1] === '[' && match[7] === ']' ) |
27 if ( '[' === match[1] && ']' === match[7] ) { |
27 return wp.shortcode.next( tag, text, re.lastIndex ); |
28 return wp.shortcode.next( tag, text, re.lastIndex ); |
|
29 } |
28 |
30 |
29 result = { |
31 result = { |
30 index: match.index, |
32 index: match.index, |
31 content: match[0], |
33 content: match[0], |
32 shortcode: wp.shortcode.fromMatch( match ) |
34 shortcode: wp.shortcode.fromMatch( match ) |
33 }; |
35 }; |
34 |
36 |
35 // If we matched a leading `[`, strip it from the match |
37 // If we matched a leading `[`, strip it from the match |
36 // and increment the index accordingly. |
38 // and increment the index accordingly. |
37 if ( match[1] ) { |
39 if ( match[1] ) { |
38 result.match = result.match.slice( 1 ); |
40 result.content = result.content.slice( 1 ); |
39 result.index++; |
41 result.index++; |
40 } |
42 } |
41 |
43 |
42 // If we matched a trailing `]`, strip it from the match. |
44 // If we matched a trailing `]`, strip it from the match. |
43 if ( match[7] ) |
45 if ( match[7] ) { |
44 result.match = result.match.slice( 0, -1 ); |
46 result.content = result.content.slice( 0, -1 ); |
|
47 } |
45 |
48 |
46 return result; |
49 return result; |
47 }, |
50 }, |
48 |
51 |
49 // ### Replace matching shortcodes in a block of text |
52 // ### Replace matching shortcodes in a block of text |
54 // |
57 // |
55 // Shortcode matches are objects that contain the shortcode `tag`, |
58 // Shortcode matches are objects that contain the shortcode `tag`, |
56 // a shortcode `attrs` object, the `content` between shortcode tags, |
59 // a shortcode `attrs` object, the `content` between shortcode tags, |
57 // and a boolean flag to indicate if the match was a `single` tag. |
60 // and a boolean flag to indicate if the match was a `single` tag. |
58 replace: function( tag, text, callback ) { |
61 replace: function( tag, text, callback ) { |
59 return text.replace( wp.shortcode.regexp( tag ), function( match, left, tag, attrs, slash, content, closing, right, offset ) { |
62 return text.replace( wp.shortcode.regexp( tag ), function( match, left, tag, attrs, slash, content, closing, right ) { |
60 // If both extra brackets exist, the shortcode has been |
63 // If both extra brackets exist, the shortcode has been |
61 // properly escaped. |
64 // properly escaped. |
62 if ( left === '[' && right === ']' ) |
65 if ( left === '[' && right === ']' ) { |
63 return match; |
66 return match; |
|
67 } |
64 |
68 |
65 // Create the match object and pass it through the callback. |
69 // Create the match object and pass it through the callback. |
66 var result = callback( wp.shortcode.fromMatch( arguments ) ); |
70 var result = callback( wp.shortcode.fromMatch( arguments ) ); |
67 |
71 |
68 // Make sure to return any of the extra brackets if they |
72 // Make sure to return any of the extra brackets if they |
162 // generated by `wp.shortcode.regexp()`. `match` can also be set to the |
166 // generated by `wp.shortcode.regexp()`. `match` can also be set to the |
163 // `arguments` from a callback passed to `regexp.replace()`. |
167 // `arguments` from a callback passed to `regexp.replace()`. |
164 fromMatch: function( match ) { |
168 fromMatch: function( match ) { |
165 var type; |
169 var type; |
166 |
170 |
167 if ( match[4] ) |
171 if ( match[4] ) { |
168 type = 'self-closing'; |
172 type = 'self-closing'; |
169 else if ( match[6] ) |
173 } else if ( match[6] ) { |
170 type = 'closed'; |
174 type = 'closed'; |
171 else |
175 } else { |
172 type = 'single'; |
176 type = 'single'; |
|
177 } |
173 |
178 |
174 return new wp.shortcode({ |
179 return new wp.shortcode({ |
175 tag: match[2], |
180 tag: match[2], |
176 attrs: match[3], |
181 attrs: match[3], |
177 type: type, |
182 type: type, |
242 // ### Transform the shortcode match into a string |
248 // ### Transform the shortcode match into a string |
243 string: function() { |
249 string: function() { |
244 var text = '[' + this.tag; |
250 var text = '[' + this.tag; |
245 |
251 |
246 _.each( this.attrs.numeric, function( value ) { |
252 _.each( this.attrs.numeric, function( value ) { |
247 if ( /\s/.test( value ) ) |
253 if ( /\s/.test( value ) ) { |
248 text += ' "' + value + '"'; |
254 text += ' "' + value + '"'; |
249 else |
255 } else { |
250 text += ' ' + value; |
256 text += ' ' + value; |
|
257 } |
251 }); |
258 }); |
252 |
259 |
253 _.each( this.attrs.named, function( value, name ) { |
260 _.each( this.attrs.named, function( value, name ) { |
254 text += ' ' + name + '="' + value + '"'; |
261 text += ' ' + name + '="' + value + '"'; |
255 }); |
262 }); |
256 |
263 |
257 // If the tag is marked as `single` or `self-closing`, close the |
264 // If the tag is marked as `single` or `self-closing`, close the |
258 // tag and ignore any additional content. |
265 // tag and ignore any additional content. |
259 if ( 'single' === this.type ) |
266 if ( 'single' === this.type ) { |
260 return text + ']'; |
267 return text + ']'; |
261 else if ( 'self-closing' === this.type ) |
268 } else if ( 'self-closing' === this.type ) { |
262 return text + ' /]'; |
269 return text + ' /]'; |
|
270 } |
263 |
271 |
264 // Complete the opening tag. |
272 // Complete the opening tag. |
265 text += ']'; |
273 text += ']'; |
266 |
274 |
267 if ( this.content ) |
275 if ( this.content ) { |
268 text += this.content; |
276 text += this.content; |
|
277 } |
269 |
278 |
270 // Add the closing tag. |
279 // Add the closing tag. |
271 return text + '[/' + this.tag + ']'; |
280 return text + '[/' + this.tag + ']'; |
272 } |
281 } |
273 }); |
282 }); |
289 // with no value). |
298 // with no value). |
290 attrs: function( content ) { |
299 attrs: function( content ) { |
291 var result, attrs; |
300 var result, attrs; |
292 |
301 |
293 // If `content` ends in a slash, strip it. |
302 // If `content` ends in a slash, strip it. |
294 if ( '/' === content[ content.length - 1 ] ) |
303 if ( '/' === content[ content.length - 1 ] ) { |
295 content = content.slice( 0, -1 ); |
304 content = content.slice( 0, -1 ); |
|
305 } |
296 |
306 |
297 result = wp.shortcode.attrs( content ); |
307 result = wp.shortcode.attrs( content ); |
298 attrs = result.named; |
308 attrs = result.named; |
299 |
309 |
300 _.each( result.numeric, function( key ) { |
310 _.each( result.numeric, function( key ) { |
301 if ( /\s/.test( key ) ) |
311 if ( /\s/.test( key ) ) { |
302 return; |
312 return; |
|
313 } |
303 |
314 |
304 attrs[ key ] = ''; |
315 attrs[ key ] = ''; |
305 }); |
316 }); |
306 |
317 |
307 return attrs; |
318 return attrs; |
314 |
325 |
315 _.each( options.attrs, function( value, attr ) { |
326 _.each( options.attrs, function( value, attr ) { |
316 text += ' ' + attr; |
327 text += ' ' + attr; |
317 |
328 |
318 // Use empty attribute notation where possible. |
329 // Use empty attribute notation where possible. |
319 if ( '' === value ) |
330 if ( '' === value ) { |
320 return; |
331 return; |
|
332 } |
321 |
333 |
322 // Convert boolean values to strings. |
334 // Convert boolean values to strings. |
323 if ( _.isBoolean( value ) ) |
335 if ( _.isBoolean( value ) ) { |
324 value = value ? 'true' : 'false'; |
336 value = value ? 'true' : 'false'; |
|
337 } |
325 |
338 |
326 text += '="' + value + '"'; |
339 text += '="' + value + '"'; |
327 }); |
340 }); |
328 |
341 |
329 // Return the result if it is a self-closing tag. |
342 // Return the result if it is a self-closing tag. |
330 if ( options.single ) |
343 if ( options.single ) { |
331 return text + ' />'; |
344 return text + ' />'; |
|
345 } |
332 |
346 |
333 // Complete the opening tag. |
347 // Complete the opening tag. |
334 text += '>'; |
348 text += '>'; |
335 |
349 |
336 // If `content` is an object, recursively call this function. |
350 // If `content` is an object, recursively call this function. |