r95266 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r95265‎ | r95266 | r95267 >
Date:22:29, 22 August 2011
Author:neilk
Status:reverted (Comments)
Tags:
Comment:
mediawiki.uri.js (needed for uploadwizard)
Modified paths:
  • /branches/wmf/1.17wmf1/resources/Resources.php (modified) (history)
  • /branches/wmf/1.17wmf1/resources/mediawiki/mediawiki.uri.js (added) (history)

Diff [purge]

Index: branches/wmf/1.17wmf1/resources/Resources.php
@@ -342,6 +342,9 @@
343343 'dependencies' => array( 'jquery.checkboxShiftClick', 'jquery.client', 'jquery.placeholder' ),
344344 'debugScripts' => 'resources/mediawiki.util/mediawiki.util.test.js',
345345 ),
 346+ 'mediawiki.Uri' => array(
 347+ 'scripts' => 'resources/mediawiki/mediawiki.uri.js',
 348+ ),
346349 'mediawiki.action.history' => array(
347350 'scripts' => 'resources/mediawiki.action/mediawiki.action.history.js',
348351 'dependencies' => 'mediawiki.legacy.history',
Index: branches/wmf/1.17wmf1/resources/mediawiki/mediawiki.uri.js
@@ -0,0 +1,260 @@
 2+/**
 3+ * Library for simple URI parsing and manipulation. Requires jQuery.
 4+ *
 5+ * Do not expect full RFC 3986 compliance. Intended to be minimal, but featureful.
 6+ * The use cases we have in mind are constructing 'next page' or 'previous page' URLs,
 7+ * detecting whether we need to use cross-domain proxies for an API, constructing
 8+ * simple URL-based API calls, etc.
 9+ *
 10+ * Intended to compress very well if you use a JS-parsing minifier.
 11+ *
 12+ * Dependencies: mw, jQuery
 13+ *
 14+ * Example:
 15+ *
 16+ * var uri = new mw.Uri( 'http://foo.com/mysite/mypage.php?quux=2' );
 17+ *
 18+ * if ( uri.host == 'foo.com' ) {
 19+ * uri.host = 'www.foo.com';
 20+ * uri.extend( { bar: 1 } );
 21+ *
 22+ * $( 'a#id1' ).attr( 'href', uri );
 23+ * // anchor with id 'id1' now links to http://foo.com/mysite/mypage.php?bar=1&quux=2
 24+ *
 25+ * $( 'a#id2' ).attr( 'href', uri.clone().extend( { bar: 3, pif: 'paf' } ) );
 26+ * // anchor with id 'id2' now links to http://foo.com/mysite/mypage.php?bar=3&quux=2&pif=paf
 27+ * }
 28+ *
 29+ * Parsing here is regex based, so may not work on all URIs, but is good enough for most.
 30+ *
 31+ * Given a URI like
 32+ * 'http://usr:pwd@www.test.com:81/dir/dir.2/index.htm?q1=0&&test1&test2=&test3=value+%28escaped%29&r=1&r=2#top':
 33+ * The returned object will have the following properties:
 34+ *
 35+ * protocol 'http'
 36+ * user 'usr'
 37+ * password 'pwd'
 38+ * host 'www.test.com'
 39+ * port '81'
 40+ * path '/dir/dir.2/index.htm'
 41+ * query {
 42+ * q1: 0,
 43+ * test1: null,
 44+ * test2: '',
 45+ * test3: 'value (escaped)'
 46+ * r: [1, 2]
 47+ * }
 48+ * fragment 'top'
 49+ *
 50+ * n.b. 'password' is not technically allowed for HTTP URIs, but it is possible with other
 51+ * sorts of URIs.
 52+ * You can modify the properties directly. Then use the toString() method to extract the
 53+ * full URI string again.
 54+ *
 55+ * Parsing based on parseUri 1.2.2 (c) Steven Levithan <stevenlevithan.com> MIT License
 56+ * http://stevenlevithan.com/demo/parseuri/js/
 57+ *
 58+ */
 59+
 60+( function( $ ) {
 61+
 62+ /**
 63+ * Function that's useful when constructing the URI string -- we frequently encounter the pattern of
 64+ * having to add something to the URI as we go, but only if it's present, and to include a character before or after if so.
 65+ * @param {String} to prepend, if value not empty
 66+ * @param {String} value to include, if not empty
 67+ * @param {String} to append, if value not empty
 68+ * @param {Boolean} raw -- if true, do not URI encode
 69+ * @return {String}
 70+ */
 71+ function cat( pre, val, post, raw ) {
 72+ if ( val === undefined || val === null || val === '' ) {
 73+ return '';
 74+ } else {
 75+ return pre + ( raw ? val : mw.Uri.encode( val ) ) + post;
 76+ }
 77+ }
 78+
 79+ // Regular expressions to parse many common URIs.
 80+ var parser = {
 81+ strict: /^(?:([^:\/?#]+):)?(?:\/\/(?:(?:([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)?((?:[^?#\/]*\/)*[^?#]*)(?:\?([^#]*))?(?:#(.*))?/,
 82+ loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?(?:(?:([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?((?:\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?[^?#\/]*)(?:\?([^#]*))?(?:#(.*))?/
 83+ },
 84+
 85+ // The order here matches the order of captured matches in the above parser regexes.
 86+ properties = [
 87+ 'protocol', // http
 88+ 'user', // usr
 89+ 'password', // pwd
 90+ 'host', // www.test.com
 91+ 'port', // 81
 92+ 'path', // /dir/dir.2/index.htm
 93+ 'query', // q1=0&&test1&test2=value (will become { q1: 0, test1: '', test2: 'value' } )
 94+ 'fragment' // top
 95+ ];
 96+
 97+ /**
 98+ * Constructs URI object. Throws error if arguments are illegal/impossible, or otherwise don't parse.
 99+ * @constructor
 100+ * @param {!Object|String} URI string, or an Object with appropriate properties (especially another URI object to clone). Object must have non-blank 'protocol', 'host', and 'path' properties.
 101+ * @param {Boolean} strict mode (when parsing a string)
 102+ */
 103+ mw.Uri = function( uri, strictMode ) {
 104+ strictMode = !!strictMode;
 105+ if ( uri !== undefined && uri !== null || uri !== '' ) {
 106+ if ( typeof uri === 'string' ) {
 107+ this._parse( uri, strictMode );
 108+ } else if ( typeof uri === 'object' ) {
 109+ var _this = this;
 110+ $.each( properties, function( i, property ) {
 111+ _this[property] = uri[property];
 112+ } );
 113+ if ( this.query === undefined ) {
 114+ this.query = {};
 115+ }
 116+ }
 117+ }
 118+ if ( !( this.protocol && this.host && this.path ) ) {
 119+ throw new Error( 'Bad constructor arguments' );
 120+ }
 121+ };
 122+
 123+ /**
 124+ * Standard encodeURIComponent, with extra stuff to make all browsers work similarly and more compliant with RFC 3986
 125+ * Similar to rawurlencode from PHP and our JS library mw.util.rawurlencode, but we also replace space with a +
 126+ * @param {String} string
 127+ * @return {String} encoded for URI
 128+ */
 129+ mw.Uri.encode = function( s ) {
 130+ return encodeURIComponent( s )
 131+ .replace( /!/g, '%21').replace( /'/g, '%27').replace( /\(/g, '%28')
 132+ .replace( /\)/g, '%29').replace( /\*/g, '%2A')
 133+ .replace( /%20/g, '+' );
 134+ };
 135+
 136+ /**
 137+ * Standard decodeURIComponent, with '+' to space
 138+ * @param {String} string encoded for URI
 139+ * @return {String} decoded string
 140+ */
 141+ mw.Uri.decode = function( s ) {
 142+ return decodeURIComponent( s ).replace( /\+/g, ' ' );
 143+ };
 144+
 145+ mw.Uri.prototype = {
 146+
 147+ /**
 148+ * Parse a string and set our properties accordingly.
 149+ * @param {String} URI
 150+ * @param {Boolean} strictness
 151+ * @return {Boolean} success
 152+ */
 153+ _parse: function( str, strictMode ) {
 154+ var matches = parser[ strictMode ? 'strict' : 'loose' ].exec( str );
 155+ var uri = this;
 156+ $.each( properties, function( i, property ) {
 157+ uri[ property ] = matches[ i+1 ];
 158+ } );
 159+
 160+ // uri.query starts out as the query string; we will parse it into key-val pairs then make
 161+ // that object the "query" property.
 162+ // we overwrite query in uri way to make cloning easier, it can use the same list of properties.
 163+ var q = {};
 164+ // using replace to iterate over a string
 165+ if ( uri.query ) {
 166+ uri.query.replace( /(?:^|&)([^&=]*)(?:(=)([^&]*))?/g, function ($0, $1, $2, $3) {
 167+ if ( $1 ) {
 168+ var k = mw.Uri.decode( $1 );
 169+ var v = ( $2 === '' || $2 === undefined ) ? null : mw.Uri.decode( $3 );
 170+ if ( typeof q[ k ] === 'string' ) {
 171+ q[ k ] = [ q[ k ] ];
 172+ }
 173+ if ( typeof q[ k ] === 'object' ) {
 174+ q[ k ].push( v );
 175+ } else {
 176+ q[ k ] = v;
 177+ }
 178+ }
 179+ } );
 180+ }
 181+ this.query = q;
 182+ },
 183+
 184+ /**
 185+ * Returns user and password portion of a URI.
 186+ * @return {String}
 187+ */
 188+ getUserInfo: function() {
 189+ return cat( '', this.user, cat( ':', this.password, '' ) );
 190+ },
 191+
 192+ /**
 193+ * Gets host and port portion of a URI.
 194+ * @return {String}
 195+ */
 196+ getHostPort: function() {
 197+ return this.host + cat( ':', this.port, '' );
 198+ },
 199+
 200+ /**
 201+ * Returns the userInfo and host and port portion of the URI.
 202+ * In most real-world URLs, this is simply the hostname, but it is more general.
 203+ * @return {String}
 204+ */
 205+ getAuthority: function() {
 206+ return cat( '', this.getUserInfo(), '@' ) + this.getHostPort();
 207+ },
 208+
 209+ /**
 210+ * Returns the query arguments of the URL, encoded into a string
 211+ * Does not preserve the order of arguments passed into the URI. Does handle escaping.
 212+ * @return {String}
 213+ */
 214+ getQueryString: function() {
 215+ var args = [];
 216+ $.each( this.query, function( key, val ) {
 217+ var k = mw.Uri.encode( key );
 218+ var vals = val === null ? [ null ] : $.makeArray( val );
 219+ $.each( vals, function( i, v ) {
 220+ args.push( k + ( v === null ? '' : '=' + mw.Uri.encode( v ) ) );
 221+ } );
 222+ } );
 223+ return args.join( '&' );
 224+ },
 225+
 226+ /**
 227+ * Returns everything after the authority section of the URI
 228+ * @return {String}
 229+ */
 230+ getRelativePath: function() {
 231+ return this.path + cat( '?', this.getQueryString(), '', true ) + cat( '#', this.fragment, '' );
 232+ },
 233+
 234+ /**
 235+ * Gets the entire URI string. May not be precisely the same as input due to order of query arguments.
 236+ * @return {String} the URI string
 237+ */
 238+ toString: function() {
 239+ return this.protocol + '://' + this.getAuthority() + this.getRelativePath();
 240+ },
 241+
 242+ /**
 243+ * Clone this URI
 244+ * @return {Object} new URI object with same properties
 245+ */
 246+ clone: function() {
 247+ return new mw.Uri( this );
 248+ },
 249+
 250+ /**
 251+ * Extend the query -- supply query parameters to override or add to ours
 252+ * @param {Object} query parameters in key-val form to override or add
 253+ * @return {Object} this URI object
 254+ */
 255+ extend: function( parameters ) {
 256+ $.extend( this.query, parameters );
 257+ return this;
 258+ }
 259+ };
 260+
 261+} )( jQuery );
Property changes on: branches/wmf/1.17wmf1/resources/mediawiki/mediawiki.uri.js
___________________________________________________________________
Added: svn:eol-style
1262 + native

Follow-up revisions

RevisionCommit summaryAuthorDate
r95285reverting hacks to get UploadWizard deploy to work (r95273, r95267, r95266)neilk23:54, 22 August 2011

Comments

#Comment by He7d3r (talk | contribs)   01:22, 23 August 2011
+	'mediawiki.Uri' => array(

Shouldn't this module name be in lower case as the other mediawiki.***?

#Comment by Johnduhart (talk | contribs)   01:24, 23 August 2011

Nope, doesn't matter. (Title is uppercase in trunk)

#Comment by NeilK (talk | contribs)   01:32, 23 August 2011

Krinkle and I went back and forth about this over email. We definitely have a convention for libraries to be all lowercase. Krinkle believes that a constructor should be uppercase. I am not really convinced that there is any benefit to having the package name be different from the filename.

Status & tagging log