wp/wp-includes/js/shortcode.js
changeset 5 5e2f62d02dcd
parent 0 d970ebf37754
child 7 cf61fcea0001
equal deleted inserted replaced
4:346c88efed21 5:5e2f62d02dcd
     1 // Utility functions for parsing and handling shortcodes in Javascript.
     1 // Utility functions for parsing and handling shortcodes in JavaScript.
     2 
     2 
     3 // Ensure the global `wp` object exists.
     3 // Ensure the global `wp` object exists.
     4 window.wp = window.wp || {};
     4 window.wp = window.wp || {};
     5 
     5 
     6 (function(){
     6 (function(){
    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,
   200 		this.attrs = {
   205 		this.attrs = {
   201 			named:   {},
   206 			named:   {},
   202 			numeric: []
   207 			numeric: []
   203 		};
   208 		};
   204 
   209 
   205 		if ( ! attrs )
   210 		if ( ! attrs ) {
   206 			return;
   211 			return;
       
   212 		}
   207 
   213 
   208 		// Parse a string of attributes.
   214 		// Parse a string of attributes.
   209 		if ( _.isString( attrs ) ) {
   215 		if ( _.isString( attrs ) ) {
   210 			this.attrs = wp.shortcode.attrs( attrs );
   216 			this.attrs = wp.shortcode.attrs( attrs );
   211 
   217 
   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.