From d4faf9eaf432b4689d149e3e4b61ac1ebf260998 Mon Sep 17 00:00:00 2001 From: Gabriel Wicke Date: Thu, 1 Mar 2012 12:47:05 +0000 Subject: [PATCH] More work on wiki link rendering and general wiki title / namespace functionality. --- modules/parser/ext.core.LinkHandler.js | 43 ++++++++++---- modules/parser/mediawiki.Title.js | 57 +++++++++++++++++++ .../parser/mediawiki.parser.environment.js | 46 ++++++++++++++- 3 files changed, 131 insertions(+), 15 deletions(-) create mode 100644 modules/parser/mediawiki.Title.js diff --git a/modules/parser/ext.core.LinkHandler.js b/modules/parser/ext.core.LinkHandler.js index c564cdfb96..752f7bff9b 100644 --- a/modules/parser/ext.core.LinkHandler.js +++ b/modules/parser/ext.core.LinkHandler.js @@ -27,21 +27,40 @@ function WikiLinkHandler( manager, isInclude ) { WikiLinkHandler.prototype.rank = 1.15; // after AttributeExpander WikiLinkHandler.prototype.onWikiLink = function ( token, manager, cb ) { - // Split off and normalize namespace - // Compare with image/media namespaces - // handle image - // handle - // Check if page exists - // - var obj = new TagTk( 'a', [ this.manager.env.lookupKV( token.attribs, 'href' ) ] ); - obj.attribs.push( new KV('data-mw-type', 'internal') ); - var out = [obj].concat( this.manager.env.lookupKV( token.attribs, 'content' ).v, - new EndTagTk( 'a' ) ); - //console.warn( JSON.stringify( out, null, 2 ) ); - return { tokens: out }; + var env = this.manager.env; + var title = this.manager.env.makeTitleFromPrefixedText( + env.tokensToString( + env.lookupKV( token.attribs, 'href' ).v + ) + ); + + if ( title.ns.isFile() ) { + return this.renderFile( token, manager, cb, title ); + } else if ( title.ns.isCategory() ) { + // TODO: implement + return []; + } else { + // Check if page exists + // + var obj = new TagTk( 'a', [ this.manager.env.lookupKV( token.attribs, 'href' ) ] ); + obj.attribs.push( new KV('data-mw-type', 'internal') ); + var out = [obj].concat( this.manager.env.lookupKV( token.attribs, 'content' ).v, + new EndTagTk( 'a' ) ); + //console.warn( JSON.stringify( out, null, 2 ) ); + return { tokens: out }; + } }; +WikiLinkHandler.prototype.renderFile = function ( token, manager, cb, title ) { + // distinguish media types + // if image: parse options + var a = new TagTk( 'a', [ new KV( 'href', title.makeLink() ) ] ); + a.attribs.push( new KV('data-mw-type', 'internal') ); + var img = new SelfclosingTagTk( 'img', [ new KV( 'src', + title.makeLink() ) ] ); + return { tokens: [ a, img, new EndTagTk( 'a' )] }; +}; if (typeof module == "object") { module.exports.WikiLinkHandler = WikiLinkHandler; diff --git a/modules/parser/mediawiki.Title.js b/modules/parser/mediawiki.Title.js new file mode 100644 index 0000000000..af220d934f --- /dev/null +++ b/modules/parser/mediawiki.Title.js @@ -0,0 +1,57 @@ +function Title ( key, ns, nskey, env ) { + this.key = key; + // Namespace index + this.ns = new Namespace( ns ); + // the original ns string + this.nskey = nskey; + this.env = env; +} + +Title.prototype.makeLink = function () { + if ( this.nskey ) { + return this.env.wgScriptPath + this.nskey + ':' + this.key; + } else { + return this.env.wgScriptPath + [this.ns.getDefaultName(), this.name].join(':'); + } +}; + + +function Namespace ( id ) { + this.id = id; +} + +Namespace.prototype._defaultNamespaceIDs = { + file: -2, + image: -2, + special: -1, + main: 0, + category: 14 +}; + +Namespace.prototype._defaultNamespaceNames = { + '-2': 'File', + '-1': 'Special', + '0': '', + '14': 'Category' +}; + +Namespace.prototype.isFile = function ( ) { + return this.id === this._defaultNamespaceIDs.file; +}; +Namespace.prototype.isCategory = function ( ) { + return this.id === this._defaultNamespaceIDs.category; +}; + +Namespace.prototype.getDefaultName = function ( ) { + if ( this.id == this._defaultNamespaceIDs.main ) { + return ''; + } else { + return this._defaultNamespaceNames[this.id]; + } +}; + + +if (typeof module == "object") { + module.exports.Title = Title; + module.exports.Namespace = Namespace; +} diff --git a/modules/parser/mediawiki.parser.environment.js b/modules/parser/mediawiki.parser.environment.js index 6f778201a1..4815c3c74c 100644 --- a/modules/parser/mediawiki.parser.environment.js +++ b/modules/parser/mediawiki.parser.environment.js @@ -1,3 +1,7 @@ +var title = require('./mediawiki.Title.js'), + Title = title.Title, + Namespace = title.Namespace; + var MWParserEnvironment = function(opts) { var options = { tagHooks: {}, @@ -10,6 +14,7 @@ var MWParserEnvironment = function(opts) { fetchTemplates: false, maxDepth: 40 }; + // XXX: this should be namespaced $.extend(options, opts); $.extend(this, options); }; @@ -65,7 +70,7 @@ MWParserEnvironment.prototype.KVtoHash = function ( kvs ) { } //console.warn( 'KVtoHash: ' + JSON.stringify( res )); return res; -} +}; // Does this need separate UI/content inputs? MWParserEnvironment.prototype.formatNum = function( num ) { @@ -98,10 +103,38 @@ MWParserEnvironment.prototype.getTagHook = function( name ) { } }; + +MWParserEnvironment.prototype.makeTitleFromPrefixedText = function ( text ) { + text = this.normalizeTitle( text ); + var nsText = text.split( ':', 1 )[0]; + if ( nsText && nsText !== text ) { + var _ns = new Namespace(0); + var ns = _ns._defaultNamespaceIDs[ nsText.toLowerCase() ]; + console.warn( JSON.stringify( [ nsText, ns ] ) ); + if ( ns !== undefined ) { + return new Title( text.substr( nsText.length + 1 ), ns, nsText, this ); + } else { + return new Title( text, 0, '', this ); + } + } else { + return new Title( text, 0, this ); + } +}; + + +// XXX: move to Title! MWParserEnvironment.prototype.normalizeTitle = function( name ) { if (typeof name !== 'string') { throw new Error('nooooooooo not a string'); } + var forceNS; + if ( name.substr( 0, 1 ) === ':' ) { + forceNS = ':'; + name = name.substr(1); + } else { + forceNS = ''; + } + name = name.trim().replace(/[\s_]+/g, '_'); // Implement int: as alias for MediaWiki: @@ -115,11 +148,18 @@ MWParserEnvironment.prototype.normalizeTitle = function( name ) { } function upperFirst( s ) { return s.substr(0, 1).toUpperCase() + s.substr(1); } - name = name.split(':').map( upperFirst ).join(':'); + // XXX: Do not uppercase all bits! + var ns = name.split(':', 1)[0]; + if( ns !== '' && ns !== name ) { + name = upperFirst( ns ) + ':' + upperFirst( name.substr( ns.length + 1 ) ); + } else { + name = upperFirst( name ); + } + //name = name.split(':').map( upperFirst ).join(':'); //if (name === '') { // throw new Error('Invalid/empty title'); //} - return name; + return forceNS + name; }; /**