- /**
- * (We put this method definition here, and not in prototype, to make sure it's not overwritten by any magic.)
- * Walk entire node structure, applying replacements and template functions when appropriate
- *
- * @param {Mixed} node Abstract syntax tree (top node or subnode)
- * @param {Array} replacements for $1, $2, ... $n
- * @return {Mixed} single-string node or array of nodes suitable for jQuery appending
- */
- this.emit = function ( node, replacements ) {
- var ret, subnodes, operation,
- jmsg = this;
- switch ( typeof node ) {
- case 'string':
- case 'number':
- ret = node;
- break;
- // typeof returns object for arrays
- case 'object':
- // node is an array of nodes
- // eslint-disable-next-line no-jquery/no-map-util
- subnodes = $.map( node.slice( 1 ), function ( n ) {
- return jmsg.emit( n, replacements );
- } );
- operation = node[ 0 ].toLowerCase();
- if ( typeof jmsg[ operation ] === 'function' ) {
- ret = jmsg[ operation ]( subnodes, replacements );
- } else {
- throw new Error( 'Unknown operation "' + operation + '"' );
- }
- break;
- case 'undefined':
- // Parsing the empty string (as an entire expression, or as a paramExpression in a template) results in undefined
- // Perhaps a more clever parser can detect this, and return the empty string? Or is that useful information?
- // The logical thing is probably to return the empty string here when we encounter undefined.
- ret = '';
- break;
- default:
- throw new Error( 'Unexpected type in AST: ' + typeof node );
- }
- return ret;
- };
- };
-
- // For everything in input that follows double-open-curly braces, there should be an equivalent parser
- // function. For instance {{PLURAL ... }} will be processed by 'plural'.
- // If you have 'magic words' then configure the parser to have them upon creation.
- //
- // An emitter method takes the parent node, the array of subnodes and the array of replacements (the values that $1, $2... should translate to).
- // Note: all such functions must be pure, with the exception of referring to other pure functions via this.language (convertPlural and so on)
- mw.jqueryMsg.HtmlEmitter.prototype = {
- /**
- * Parsing has been applied depth-first we can assume that all nodes here are single nodes
- * Must return a single node to parents -- a jQuery with synthetic span
- * However, unwrap any other synthetic spans in our children and pass them upwards
- *
- * @param {Mixed[]} nodes Some single nodes, some arrays of nodes
- * @return {jQuery}
- */
- concat: function ( nodes ) {
- var $span = $( '<span>' ).addClass( 'mediaWiki_htmlEmitter' );
- // eslint-disable-next-line no-jquery/no-each-util
- $.each( nodes, function ( i, node ) {
- // Let jQuery append nodes, arrays of nodes and jQuery objects
- // other things (strings, numbers, ..) are appended as text nodes (not as HTML strings)
- appendWithoutParsing( $span, node );
- } );
- return $span;
- },
+ /**
+ * Return escaped replacement of correct index, or string if unavailable.
+ * Note that we expect the parsed parameter to be zero-based. i.e. $1 should have become [ 0 ].
+ * if the specified parameter is not found return the same string
+ * (e.g. "$99" -> parameter 98 -> not found -> return "$99" )
+ *
+ * TODO: Throw error if nodes.length > 1 ?
+ *
+ * @param {Array} nodes List of one element, integer, n >= 0
+ * @param {Array} replacements List of at least n strings
+ * @return {string|jQuery} replacement
+ */
+ replace: function ( nodes, replacements ) {
+ var index = parseInt( nodes[ 0 ], 10 );