( function ( mw, $ ) {
'use strict';
+ var util;
+
/**
- * Utility library
- * @class mw.util
- * @singleton
+ * Encode the string like PHP's rawurlencode
+ * @ignore
+ *
+ * @param {string} str String to be encoded.
+ * @return {string} Encoded string
*/
- var util = {
+ function rawurlencode( str ) {
+ str = String( str );
+ return encodeURIComponent( str )
+ .replace( /!/g, '%21' ).replace( /'/g, '%27' ).replace( /\(/g, '%28' )
+ .replace( /\)/g, '%29' ).replace( /\*/g, '%2A' ).replace( /~/g, '%7E' );
+ }
- /**
- * Initialisation
- * (don't call before document ready)
- */
- init: function () {
- util.$content = ( function () {
- var i, l, $node, selectors;
-
- selectors = [
- // The preferred standard is class "mw-body".
- // You may also use class "mw-body mw-body-primary" if you use
- // mw-body in multiple locations. Or class "mw-body-primary" if
- // you use mw-body deeper in the DOM.
- '.mw-body-primary',
- '.mw-body',
-
- // If the skin has no such class, fall back to the parser output
- '#mw-content-text',
-
- // Should never happen... well, it could if someone is not finished writing a
- // skin and has not yet inserted bodytext yet.
- 'body'
- ];
-
- for ( i = 0, l = selectors.length; i < l; i++ ) {
- $node = $( selectors[ i ] );
- if ( $node.length ) {
- return $node.first();
- }
+ /**
+ * Private helper function used by util.escapeId*()
+ * @ignore
+ *
+ * @param {string} str String to be encoded
+ * @param {string} mode Encoding mode, see documentation for $wgFragmentMode
+ * in DefaultSettings.php
+ * @return {string} Encoded string
+ */
+ function escapeIdInternal( str, mode ) {
+ str = String( str );
+
+ switch ( mode ) {
+ case 'html5':
+ return str.replace( / /g, '_' );
+ case 'html5-legacy':
+ str = str.replace( /[ \t\n\r\f_'"&#%]+/g, '_' )
+ .replace( /^_+|_+$/, '' );
+ if ( str === '' ) {
+ str = '_';
}
+ return str;
+ case 'legacy':
+ return rawurlencode( str.replace( / /g, '_' ) )
+ .replace( /%3A/g, ':' )
+ .replace( /%/g, '.' );
+ default:
+ throw new Error( 'Unrecognized ID escaping mode ' + mode );
+ }
+ }
- // Preserve existing customized value in case it was preset
- return util.$content;
- }() );
- },
+ /**
+ * Utility library
+ * @class mw.util
+ * @singleton
+ */
+ util = {
/* Main body */
* @param {string} str String to be encoded.
* @return {string} Encoded string
*/
- rawurlencode: function ( str ) {
- str = String( str );
- return encodeURIComponent( str )
- .replace( /!/g, '%21' ).replace( /'/g, '%27' ).replace( /\(/g, '%28' )
- .replace( /\)/g, '%29' ).replace( /\*/g, '%2A' ).replace( /~/g, '%7E' );
- },
+ rawurlencode: rawurlencode,
/**
- * Encode the string like Sanitizer::escapeId in PHP
+ * Encode the string like Sanitizer::escapeId() in PHP
+ * @deprecated since 1.30 use escapeIdForAttribute() or escapeIdForLink()
*
* @param {string} str String to be encoded.
* @return {string} Encoded string
*/
escapeId: function ( str ) {
- str = String( str );
- return util.rawurlencode( str.replace( / /g, '_' ) )
- .replace( /%3A/g, ':' )
- .replace( /%/g, '.' );
+ return escapeIdInternal( str, 'legacy' );
+ },
+
+ /**
+ * Encode string into HTML id compatible form suitable for use in HTML
+ * Analog to PHP Sanitizer::escapeIdForAttribute()
+ *
+ * @since 1.30
+ *
+ * @param {string} str String to encode
+ * @return {string} Encoded string
+ */
+ escapeIdForAttribute: function ( str ) {
+ var mode = mw.config.get( 'wgFragmentMode' )[ 0 ];
+
+ return escapeIdInternal( str, mode );
+ },
+
+ /**
+ * Encode string into HTML id compatible form suitable for use in links
+ * Analog to PHP Sanitizer::escapeIdForLink()
+ *
+ * @since 1.30
+ *
+ * @param {string} str String to encode
+ * @return {string} Encoded string
+ */
+ escapeIdForLink: function ( str ) {
+ var mode = mw.config.get( 'wgFragmentMode' )[ 0 ],
+ id = escapeIdInternal( str, mode );
+
+ if ( mode === 'html5' ) {
+ id = encodeURIComponent( id ).replace( /%3A/g, ':' );
+ }
+
+ return id;
},
/**
// Append the encoded fragment
if ( fragment.length ) {
- url += '#' + util.escapeId( fragment );
+ url += '#' + util.escapeIdForLink( fragment );
}
return url;
/**
* The content wrapper of the skin (e.g. `.mw-body`).
*
- * Populated on document ready by #init. To use this property,
+ * Populated on document ready. To use this property,
* wait for `$.ready` and be sure to have a module dependency on
- * `mediawiki.util` and `mediawiki.page.startup` which will ensure
- * your document ready handler fires after #init.
+ * `mediawiki.util` which will ensure
+ * your document ready handler fires after initialization.
*
* Because of the lazy-initialised nature of this property,
* you're discouraged from using it.
return true;
}, 'Use mw.notify instead.' );
+ /**
+ * Initialisation of mw.util.$content
+ */
+ function init() {
+ util.$content = ( function () {
+ var i, l, $node, selectors;
+
+ selectors = [
+ // The preferred standard is class "mw-body".
+ // You may also use class "mw-body mw-body-primary" if you use
+ // mw-body in multiple locations. Or class "mw-body-primary" if
+ // you use mw-body deeper in the DOM.
+ '.mw-body-primary',
+ '.mw-body',
+
+ // If the skin has no such class, fall back to the parser output
+ '#mw-content-text'
+ ];
+
+ for ( i = 0, l = selectors.length; i < l; i++ ) {
+ $node = $( selectors[ i ] );
+ if ( $node.length ) {
+ return $node.first();
+ }
+ }
+
+ // Should never happen... well, it could if someone is not finished writing a
+ // skin and has not yet inserted bodytext yet.
+ return $( 'body' );
+ }() );
+ }
+
+ /**
+ * Former public initialisation. Now a no-op function.
+ *
+ * @method util_init
+ * @deprecated since 1.30
+ */
+ mw.log.deprecate( util, 'init', $.noop, 'Remove the call of mw.util.init().', 'mw.util.init' );
+
+ $( init );
+
mw.util = util;
module.exports = util;