Index: trunk/extensions/UploadWizard/test/jasmine/makeLanguageSpec.php |
— | — | @@ -1,114 +0,0 @@ |
2 | | -<?php |
3 | | - |
4 | | -/** |
5 | | - * This PHP script defines the spec that the Javascript message parser should conform to. |
6 | | - * |
7 | | - * It does this by looking up the results of various string kinds of string parsing, with various languages, |
8 | | - * in the current installation of MediaWiki. It then outputs a static specification, mapping expected inputs to outputs, |
9 | | - * which can be used with the JasmineBDD framework. This specification can then be used by simply including it into |
10 | | - * the SpecRunner.html file. |
11 | | - * |
12 | | - * This is similar to Michael Dale (mdale@mediawiki.org)'s parser tests, except that it doesn't look up the |
13 | | - * API results while doing the test, so the Jasmine run is much faster(at the cost of being out of date in rare |
14 | | - * circumstances. But mostly the parsing that we are doing in Javascript doesn't change much.) |
15 | | - * |
16 | | - */ |
17 | | - |
18 | | -$maintenanceDir = dirname( dirname( dirname( dirname( dirname( __FILE__ ) ) ) ) ) . '/maintenance'; |
19 | | - |
20 | | -require( "$maintenanceDir/Maintenance.php" ); |
21 | | - |
22 | | -class MakeLanguageSpec extends Maintenance { |
23 | | - |
24 | | - static $keyToTestArgs = array( |
25 | | - 'undelete_short' => array( |
26 | | - array( 0 ), |
27 | | - array( 1 ), |
28 | | - array( 2 ), |
29 | | - array( 5 ), |
30 | | - array( 21 ), |
31 | | - array( 101 ) |
32 | | - ), |
33 | | - 'category-subcat-count' => array( |
34 | | - array( 0, 10 ), |
35 | | - array( 1, 1 ), |
36 | | - array( 1, 2 ), |
37 | | - array( 3, 30 ) |
38 | | - ) |
39 | | - ); |
40 | | - |
41 | | - public function __construct() { |
42 | | - parent::__construct(); |
43 | | - $this->mDescription = "Create a JasmineBDD-compatible specification for message parsing"; |
44 | | - // add any other options here |
45 | | - } |
46 | | - |
47 | | - public function execute() { |
48 | | - list( $messages, $tests ) = $this->getMessagesAndTests(); |
49 | | - $this->writeJavascriptFile( $messages, $tests, "spec/mediawiki.language.parser.spec.data.js" ); |
50 | | - } |
51 | | - |
52 | | - private function getMessagesAndTests() { |
53 | | - $messages = array(); |
54 | | - $tests = array(); |
55 | | - $wfMsgExtOptions = array( 'parsemag' ); |
56 | | - foreach ( array( 'en', 'fr', 'ar', 'jp', 'zh' ) as $languageCode ) { |
57 | | - $wfMsgExtOptions['language'] = $languageCode; |
58 | | - foreach ( self::$keyToTestArgs as $key => $testArgs ) { |
59 | | - foreach ($testArgs as $args) { |
60 | | - // get the raw template, without any transformations |
61 | | - $template = wfMsgGetKey( $key, /* useDb */ true, $languageCode, /* transform */ false ); |
62 | | - |
63 | | - // get the magic-parsed version with args |
64 | | - $wfMsgExtArgs = array_merge( array( $key, $wfMsgExtOptions ), $args ); |
65 | | - $result = call_user_func_array( 'wfMsgExt', $wfMsgExtArgs ); |
66 | | - |
67 | | - // record the template, args, language, and expected result |
68 | | - // fake multiple languages by flattening them together |
69 | | - $langKey = $languageCode . '_' . $key; |
70 | | - $messages[ $langKey ] = $template; |
71 | | - $tests[] = array( |
72 | | - 'name' => $languageCode . " " . $key . " " . join( ",", $args ), |
73 | | - 'key' => $langKey, |
74 | | - 'args' => $args, |
75 | | - 'result' => $result, |
76 | | - 'lang' => $languageCode |
77 | | - ); |
78 | | - } |
79 | | - } |
80 | | - } |
81 | | - return array( $messages, $tests ); |
82 | | - } |
83 | | - |
84 | | - private function writeJavascriptFile( $messages, $tests, $dataSpecFile ) { |
85 | | - global $argv; |
86 | | - $arguments = count($argv) ? $argv : $_SERVER[ 'argv' ]; |
87 | | - |
88 | | - $json = new Services_JSON; |
89 | | - $json->pretty = true; |
90 | | - $javascriptPrologue = "// This file stores the results from the PHP parser for certain messages and arguments,\n" |
91 | | - . "// so we can test the equivalent Javascript libraries.\n" |
92 | | - . '// Last generated with ' . join(' ', $arguments) . ' at ' . gmdate('c') . "\n\n"; |
93 | | - $javascriptMessages = "mediaWiki.messages.set( " . $json->encode( $messages, true ) . " );\n"; |
94 | | - $javascriptTests = 'var jasmineMsgSpec = ' . $json->encode( $tests, true ) . ";\n"; |
95 | | - |
96 | | - $fp = fopen( $dataSpecFile, 'w' ); |
97 | | - if ( !$fp ) { |
98 | | - die( "couldn't open $dataSpecFile for writing" ); |
99 | | - } |
100 | | - $success = fwrite( $fp, $javascriptPrologue . $javascriptMessages . $javascriptTests ); |
101 | | - if ( !$success ) { |
102 | | - die( "couldn't write to $dataSpecFile" ); |
103 | | - } |
104 | | - $success = fclose( $fp ); |
105 | | - if ( !$success ) { |
106 | | - die( "couldn't close $dataSpecFile" ); |
107 | | - } |
108 | | - } |
109 | | -} |
110 | | - |
111 | | -$maintClass = "MakeLanguageSpec"; |
112 | | -require_once( "$maintenanceDir/doMaintenance.php" ); |
113 | | - |
114 | | - |
115 | | - |
Index: trunk/extensions/UploadWizard/test/jasmine/SpecRunner.html |
— | — | @@ -12,10 +12,6 @@ |
13 | 13 | |
14 | 14 | <script type="text/javascript" src="../../../../resources/mediawiki/mediawiki.js"></script> |
15 | 15 | <script type="text/javascript" src="../../../../resources/mediawiki.language/mediawiki.language.js"></script> |
16 | | - <script type="text/javascript" src="../../../../resources/mediawiki/mediawiki.Uri.js"></script> |
17 | | - <script type="text/javascript" src="../../resources/mediawiki.language.parser.js"></script> |
18 | | - <script type="text/javascript" src="../../../../resources/mediawiki/mediawiki.api.js"></script> |
19 | | - <script type="text/javascript" src="../../../../resources/mediawiki/mediawiki.api.edit.js"></script> |
20 | 16 | <script type="text/javascript" src="../../../../resources/mediawiki/mediawiki.Title.js"></script> |
21 | 17 | <script type="text/javascript" src="../../resources/mw.units.js"></script> |
22 | 18 | <script type="text/javascript" src="../../resources/jquery/jquery.pubsub.js"></script> |
— | — | @@ -24,11 +20,7 @@ |
25 | 21 | |
26 | 22 | |
27 | 23 | <!-- include spec files here... --> |
28 | | - <script type="text/javascript" src="spec/mw.Api.spec.js"></script> |
29 | | - <script type="text/javascript" src="spec/mw.Api.edit.spec.js"></script> |
30 | 24 | |
31 | | - <script type="text/javascript" src="spec/mediawiki.language.parser.spec.js"></script> |
32 | | - |
33 | 25 | <script type="text/javascript" src="spec/mw.Title.spec.js"></script> |
34 | 26 | <script type="text/javascript" src="spec/mw.units.spec.js"></script> |
35 | 27 | <script type="text/javascript" src="spec/mw.pubsub.spec.js"></script> |
Index: trunk/extensions/UploadWizard/test/jasmine/spec/mediawiki.language.parser.spec.js |
— | — | @@ -1,350 +0,0 @@ |
2 | | -/* spec for language & message behaviour in MediaWiki */ |
3 | | - |
4 | | - |
5 | | -mediaWiki.messages.set( { |
6 | | - "en_empty": "", |
7 | | - "en_simple": "Simple message", |
8 | | - "en_replace": "Simple $1 replacement", |
9 | | - "en_replace2": "Simple $1 $2 replacements", |
10 | | - "en_link": "Simple [http://example.com link to example].", |
11 | | - "en_link_replace": "Complex [$1 $2] behaviour.", |
12 | | - "en_simple_magic": "Simple {{ALOHOMORA}} message", |
13 | | - "en_undelete_short": "Undelete {{PLURAL:$1|one edit|$1 edits}}", |
14 | | - "en_undelete_empty_param": "Undelete{{PLURAL:$1|| multiple edits}}", |
15 | | - "en_category-subcat-count": "{{PLURAL:$2|This category has only the following subcategory.|This category has the following {{PLURAL:$1|subcategory|$1 subcategories}}, out of $2 total.}}", |
16 | | - "en_escape0": "Escape \\to fantasy island", |
17 | | - "en_escape1": "I had \\$2.50 in my pocket", |
18 | | - "en_escape2": "I had {{PLURAL:$1|the absolute \\|$1\\| which came out to \\$3.00 in my C:\\\\drive| some stuff}}", |
19 | | - "en_fail": "This should fail to {{parse", |
20 | | - "en_fail_magic": "There is no such magic word as {{SIETNAME}}" |
21 | | -} ); |
22 | | - |
23 | | -/** |
24 | | - * Tests |
25 | | - */ |
26 | | -( function( $j ) { |
27 | | - describe( "mediaWiki.language.parser", function() { |
28 | | - |
29 | | - describe( "basic message functionality", function() { |
30 | | - |
31 | | - it( "should return identity for empty string", function() { |
32 | | - var parser = new mediaWiki.language.parser(); |
33 | | - expect( parser.parse( 'en_empty' ).html() ).toEqual( '' ); |
34 | | - } ); |
35 | | - |
36 | | - |
37 | | - it( "should return identity for simple string", function() { |
38 | | - var parser = new mediaWiki.language.parser(); |
39 | | - expect( parser.parse( 'en_simple' ).html() ).toEqual( 'Simple message' ); |
40 | | - } ); |
41 | | - |
42 | | - } ); |
43 | | - |
44 | | - describe( "escaping", function() { |
45 | | - |
46 | | - it ( "should handle simple escaping", function() { |
47 | | - var parser = new mediaWiki.language.parser(); |
48 | | - expect( parser.parse( 'en_escape0' ).html() ).toEqual( 'Escape to fantasy island' ); |
49 | | - } ); |
50 | | - |
51 | | - it ( "should escape dollar signs found in ordinary text when backslashed", function() { |
52 | | - var parser = new mediaWiki.language.parser(); |
53 | | - expect( parser.parse( 'en_escape1' ).html() ).toEqual( 'I had $2.50 in my pocket' ); |
54 | | - } ); |
55 | | - |
56 | | - it ( "should handle a complicated escaping case, including escaped pipe chars in template args", function() { |
57 | | - var parser = new mediaWiki.language.parser(); |
58 | | - expect( parser.parse( 'en_escape2', [ 1 ] ).html() ).toEqual( 'I had the absolute |1| which came out to $3.00 in my C:\\drive' ); |
59 | | - } ); |
60 | | - |
61 | | - } ); |
62 | | - |
63 | | - describe( "replacing", function() { |
64 | | - |
65 | | - it ( "should handle simple replacing", function() { |
66 | | - var parser = new mediaWiki.language.parser(); |
67 | | - expect( parser.parse( 'en_replace', [ 'foo' ] ).html() ).toEqual( 'Simple foo replacement' ); |
68 | | - } ); |
69 | | - |
70 | | - it ( "should return $n if replacement not there", function() { |
71 | | - var parser = new mediaWiki.language.parser(); |
72 | | - expect( parser.parse( 'en_replace', [] ).html() ).toEqual( 'Simple $1 replacement' ); |
73 | | - expect( parser.parse( 'en_replace2', [ 'bar' ] ).html() ).toEqual( 'Simple bar $2 replacements' ); |
74 | | - } ); |
75 | | - |
76 | | - } ); |
77 | | - |
78 | | - describe( "linking", function() { |
79 | | - |
80 | | - it ( "should handle a simple link", function() { |
81 | | - var parser = new mediaWiki.language.parser(); |
82 | | - var parsed = parser.parse( 'en_link' ); |
83 | | - var contents = parsed.contents(); |
84 | | - expect( contents.length ).toEqual( 3 ); |
85 | | - expect( contents[0].nodeName ).toEqual( '#text' ); |
86 | | - expect( contents[0].nodeValue ).toEqual( 'Simple ' ); |
87 | | - expect( contents[1].nodeName ).toEqual( 'A' ); |
88 | | - expect( contents[1].getAttribute( 'href' ) ).toEqual( 'http://example.com' ); |
89 | | - expect( contents[1].childNodes[0].nodeValue ).toEqual( 'link to example' ); |
90 | | - expect( contents[2].nodeName ).toEqual( '#text' ); |
91 | | - expect( contents[2].nodeValue ).toEqual( '.' ); |
92 | | - } ); |
93 | | - |
94 | | - it ( "should replace a URL into a link", function() { |
95 | | - var parser = new mediaWiki.language.parser(); |
96 | | - var parsed = parser.parse( 'en_link_replace', [ 'http://example.com/foo', 'linking' ] ); |
97 | | - var contents = parsed.contents(); |
98 | | - expect( contents.length ).toEqual( 3 ); |
99 | | - expect( contents[0].nodeName ).toEqual( '#text' ); |
100 | | - expect( contents[0].nodeValue ).toEqual( 'Complex ' ); |
101 | | - expect( contents[1].nodeName ).toEqual( 'A' ); |
102 | | - expect( contents[1].getAttribute( 'href' ) ).toEqual( 'http://example.com/foo' ); |
103 | | - expect( contents[1].childNodes[0].nodeValue ).toEqual( 'linking' ); |
104 | | - expect( contents[2].nodeName ).toEqual( '#text' ); |
105 | | - expect( contents[2].nodeValue ).toEqual( ' behaviour.' ); |
106 | | - } ); |
107 | | - |
108 | | - it ( "should bind a click handler into a link", function() { |
109 | | - var parser = new mediaWiki.language.parser(); |
110 | | - var clicked = false; |
111 | | - var click = function() { clicked = true; }; |
112 | | - var parsed = parser.parse( 'en_link_replace', [ click, 'linking' ] ); |
113 | | - var contents = parsed.contents(); |
114 | | - expect( contents.length ).toEqual( 3 ); |
115 | | - expect( contents[0].nodeName ).toEqual( '#text' ); |
116 | | - expect( contents[0].nodeValue ).toEqual( 'Complex ' ); |
117 | | - expect( contents[1].nodeName ).toEqual( 'A' ); |
118 | | - expect( contents[1].getAttribute( 'href' ) ).toEqual( '#' ); |
119 | | - expect( contents[1].childNodes[0].nodeValue ).toEqual( 'linking' ); |
120 | | - expect( contents[2].nodeName ).toEqual( '#text' ); |
121 | | - expect( contents[2].nodeValue ).toEqual( ' behaviour.' ); |
122 | | - // determining bindings is hard in IE |
123 | | - var anchor = parsed.find( 'a' ); |
124 | | - if ( ( $j.browser.mozilla || $j.browser.webkit ) && anchor.click ) { |
125 | | - expect( clicked ).toEqual( false ); |
126 | | - anchor.click(); |
127 | | - expect( clicked ).toEqual( true ); |
128 | | - } |
129 | | - } ); |
130 | | - |
131 | | - it ( "should wrap a jquery arg around link contents -- even another element", function() { |
132 | | - var parser = new mediaWiki.language.parser(); |
133 | | - var clicked = false; |
134 | | - var click = function() { clicked = true; }; |
135 | | - var button = $j( '<button>' ).click( click ); |
136 | | - var parsed = parser.parse( 'en_link_replace', [ button, 'buttoning' ] ); |
137 | | - var contents = parsed.contents(); |
138 | | - expect( contents.length ).toEqual( 3 ); |
139 | | - expect( contents[0].nodeName ).toEqual( '#text' ); |
140 | | - expect( contents[0].nodeValue ).toEqual( 'Complex ' ); |
141 | | - expect( contents[1].nodeName ).toEqual( 'BUTTON' ); |
142 | | - expect( contents[1].childNodes[0].nodeValue ).toEqual( 'buttoning' ); |
143 | | - expect( contents[2].nodeName ).toEqual( '#text' ); |
144 | | - expect( contents[2].nodeValue ).toEqual( ' behaviour.' ); |
145 | | - // determining bindings is hard in IE |
146 | | - if ( ( $j.browser.mozilla || $j.browser.webkit ) && button.click ) { |
147 | | - expect( clicked ).toEqual( false ); |
148 | | - parsed.find( 'button' ).click(); |
149 | | - expect( clicked ).toEqual( true ); |
150 | | - } |
151 | | - } ); |
152 | | - |
153 | | - |
154 | | - } ); |
155 | | - |
156 | | - |
157 | | - describe( "magic keywords", function() { |
158 | | - it( "should substitute magic keywords", function() { |
159 | | - var options = { |
160 | | - magic: { |
161 | | - 'alohomora' : 'open' |
162 | | - } |
163 | | - }; |
164 | | - var parser = new mediaWiki.language.parser( options ); |
165 | | - expect( parser.parse( 'en_simple_magic' ).html() ).toEqual( 'Simple open message' ); |
166 | | - } ); |
167 | | - } ); |
168 | | - |
169 | | - describe( "error conditions", function() { |
170 | | - it( "should return non-existent key in square brackets", function() { |
171 | | - var parser = new mediaWiki.language.parser(); |
172 | | - expect( parser.parse( 'en_does_not_exist' ).html() ).toEqual( '[en_does_not_exist]' ); |
173 | | - } ); |
174 | | - |
175 | | - |
176 | | - it( "should fail to parse", function() { |
177 | | - var parser = new mediaWiki.language.parser(); |
178 | | - expect( function() { parser.parse( 'en_fail' ); } ).toThrow( |
179 | | - 'Parse error at position 20 in input: This should fail to {{parse' |
180 | | - ); |
181 | | - } ); |
182 | | - } ); |
183 | | - |
184 | | - describe( "empty parameters", function() { |
185 | | - it( "should deal with empty parameters", function() { |
186 | | - var parser = new mediaWiki.language.parser(); |
187 | | - var ast = parser.getAst( 'en_undelete_empty_param' ); |
188 | | - expect( parser.parse( 'en_undelete_empty_param', [ 1 ] ).html() ).toEqual( 'Undelete' ); |
189 | | - expect( parser.parse( 'en_undelete_empty_param', [ 3 ] ).html() ).toEqual( 'Undelete multiple edits' ); |
190 | | - |
191 | | - } ); |
192 | | - } ); |
193 | | - |
194 | | - describe( "easy message interface functions", function() { |
195 | | - it( "should allow a global that returns strings", function() { |
196 | | - var gM = mediaWiki.language.getMessageFunction(); |
197 | | - // passing this through jQuery and back to string, because browsers may have subtle differences, like the case of tag names. |
198 | | - // a surrounding <SPAN> is needed for html() to work right |
199 | | - var expectedHtml = $j( '<span>Complex <a href="http://example.com/foo">linking</a> behaviour.</span>' ).html(); |
200 | | - var result = gM( 'en_link_replace', 'http://example.com/foo', 'linking' ); |
201 | | - expect( typeof result ).toEqual( 'string' ); |
202 | | - expect( result ).toEqual( expectedHtml ); |
203 | | - } ); |
204 | | - |
205 | | - it( "should allow a jQuery plugin that appends to nodes", function() { |
206 | | - $j.fn.msg = mediaWiki.language.getJqueryMessagePlugin(); |
207 | | - var $div = $j( '<div>' ).append( $j( '<p>' ).addClass( 'foo' ) ); |
208 | | - var clicked = false; |
209 | | - var $button = $j( '<button>' ).click( function() { clicked = true; } ); |
210 | | - $div.find( '.foo' ).msg( 'en_link_replace', $button, 'buttoning' ); |
211 | | - // passing this through jQuery and back to string, because browsers may have subtle differences, like the case of tag names. |
212 | | - // a surrounding <SPAN> is needed for html() to work right |
213 | | - var expectedHtml = $j( '<span>Complex <button>buttoning</button> behaviour.</span>' ).html(); |
214 | | - var createdHtml = $div.find( '.foo' ).html(); |
215 | | - // it is hard to test for clicks with IE; also it inserts or removes spaces around nodes when creating HTML tags, depending on their type. |
216 | | - // so need to check the strings stripped of spaces. |
217 | | - if ( ( $j.browser.mozilla || $j.browser.webkit ) && $button.click ) { |
218 | | - expect( createdHtml ).toEqual( expectedHtml ); |
219 | | - $div.find( 'button ').click(); |
220 | | - expect( clicked ).toEqual( true ); |
221 | | - } else if ( $j.browser.ie ) { |
222 | | - expect( createdHtml.replace( /\s/, '' ) ).toEqual( expectedHtml.replace( /\s/, '' ) ); |
223 | | - } |
224 | | - delete $j.fn.msg; |
225 | | - } ); |
226 | | - |
227 | | - } ); |
228 | | - |
229 | | - // The parser functions can throw errors, but let's not actually blow up for the user -- instead dump the error into the interface so we have |
230 | | - // a chance at fixing this |
231 | | - describe( "easy message interface functions with graceful failures", function() { |
232 | | - it( "should allow a global that returns strings, with graceful failure", function() { |
233 | | - var gM = mediaWiki.language.getMessageFunction(); |
234 | | - // passing this through jQuery and back to string, because browsers may have subtle differences, like the case of tag names. |
235 | | - // a surrounding <SPAN> is needed for html() to work right |
236 | | - var expectedHtml = $j( '<span>en_fail: Parse error at position 20 in input: This should fail to {{parse</span>' ).html(); |
237 | | - var result = gM( 'en_fail' ); |
238 | | - expect( typeof result ).toEqual( 'string' ); |
239 | | - expect( result ).toEqual( expectedHtml ); |
240 | | - } ); |
241 | | - |
242 | | - it( "should allow a global that returns strings, with graceful failure on missing magic words", function() { |
243 | | - var gM = mediaWiki.language.getMessageFunction(); |
244 | | - // passing this through jQuery and back to string, because browsers may have subtle differences, like the case of tag names. |
245 | | - // a surrounding <SPAN> is needed for html() to work right |
246 | | - var expectedHtml = $j( '<span>en_fail_magic: unknown operation "sietname"</span>' ).html(); |
247 | | - var result = gM( 'en_fail_magic' ); |
248 | | - expect( typeof result ).toEqual( 'string' ); |
249 | | - expect( result ).toEqual( expectedHtml ); |
250 | | - } ); |
251 | | - |
252 | | - |
253 | | - it( "should allow a jQuery plugin, with graceful failure", function() { |
254 | | - $j.fn.msg = mediaWiki.language.getJqueryMessagePlugin(); |
255 | | - var $div = $j( '<div>' ).append( $j( '<p>' ).addClass( 'foo' ) ); |
256 | | - $div.find( '.foo' ).msg( 'en_fail' ); |
257 | | - // passing this through jQuery and back to string, because browsers may have subtle differences, like the case of tag names. |
258 | | - // a surrounding <SPAN> is needed for html() to work right |
259 | | - var expectedHtml = $j( '<span>en_fail: Parse error at position 20 in input: This should fail to {{parse</span>' ).html(); |
260 | | - var createdHtml = $div.find( '.foo' ).html(); |
261 | | - expect( createdHtml ).toEqual( expectedHtml ); |
262 | | - delete $j.fn.msg; |
263 | | - } ); |
264 | | - |
265 | | - } ); |
266 | | - |
267 | | - |
268 | | - |
269 | | - |
270 | | - describe( "test plurals and other language-specific functions", function() { |
271 | | - /* copying some language definitions in here -- it's hard to make this test fast and reliable |
272 | | - otherwise, and we don't want to have to know the mediawiki URL from this kind of test either. |
273 | | - We also can't preload the langs for the test since they clobber the same namespace. |
274 | | - In principle Roan said it was okay to change how languages worked so that didn't happen... maybe |
275 | | - someday. We'd have to the same kind of importing of the default rules for most rules, or maybe |
276 | | - come up with some kind of subclassing scheme for languages */ |
277 | | - var languageClasses = { |
278 | | - ar: { |
279 | | - /** |
280 | | - * Arabic (العربية) language functions |
281 | | - */ |
282 | | - |
283 | | - convertPlural: function( count, forms ) { |
284 | | - forms = mediaWiki.language.preConvertPlural( forms, 6 ); |
285 | | - if ( count === 0 ) { |
286 | | - return forms[0]; |
287 | | - } |
288 | | - if ( count == 1 ) { |
289 | | - return forms[1]; |
290 | | - } |
291 | | - if ( count == 2 ) { |
292 | | - return forms[2]; |
293 | | - } |
294 | | - if ( count % 100 >= 3 && count % 100 <= 10 ) { |
295 | | - return forms[3]; |
296 | | - } |
297 | | - if ( count % 100 >= 11 && count % 100 <= 99 ) { |
298 | | - return forms[4]; |
299 | | - } |
300 | | - return forms[5]; |
301 | | - }, |
302 | | - |
303 | | - digitTransformTable: { |
304 | | - '0': '٠', // ٠ |
305 | | - '1': '١', // ١ |
306 | | - '2': '٢', // ٢ |
307 | | - '3': '٣', // ٣ |
308 | | - '4': '٤', // ٤ |
309 | | - '5': '٥', // ٥ |
310 | | - '6': '٦', // ٦ |
311 | | - '7': '٧', // ٧ |
312 | | - '8': '٨', // ٨ |
313 | | - '9': '٩', // ٩ |
314 | | - '.': '٫', // ٫ wrong table ? |
315 | | - ',': '٬' // ٬ |
316 | | - } |
317 | | - |
318 | | - }, |
319 | | - en: { }, |
320 | | - fr: { |
321 | | - convertPlural: function( count, forms ) { |
322 | | - forms = mediaWiki.language.preConvertPlural( forms, 2 ); |
323 | | - return ( count <= 1 ) ? forms[0] : forms[1]; |
324 | | - } |
325 | | - }, |
326 | | - jp: { }, |
327 | | - zh: { } |
328 | | - }; |
329 | | - |
330 | | - /* simulate how the language classes override, or don't, the standard functions in mediaWiki.language */ |
331 | | - $j.each( languageClasses, function( langCode, rules ) { |
332 | | - $j.each( [ 'convertPlural', 'convertNumber' ], function( i, propertyName ) { |
333 | | - if ( typeof rules[ propertyName ] === 'undefined' ) { |
334 | | - rules[ propertyName ] = mediaWiki.language[ propertyName ]; |
335 | | - } |
336 | | - } ); |
337 | | - } ); |
338 | | - |
339 | | - $j.each( jasmineMsgSpec, function( i, test ) { |
340 | | - it( "should parse " + test.name, function() { |
341 | | - // using language override so we don't have to muck with global namespace |
342 | | - var parser = new mediaWiki.language.parser( { language: languageClasses[ test.lang ] } ); |
343 | | - var parsedHtml = parser.parse( test.key, test.args ).html(); |
344 | | - expect( parsedHtml ).toEqual( test.result ); |
345 | | - } ); |
346 | | - } ); |
347 | | - |
348 | | - } ); |
349 | | - |
350 | | - } ); |
351 | | -} )( jQuery ); |
Index: trunk/extensions/UploadWizard/test/jasmine/spec/mediawiki.language.parser.spec.data.js |
— | — | @@ -1,488 +0,0 @@ |
2 | | -// This file stores the results from the PHP parser for certain messages and arguments, |
3 | | -// so we can test the equivalent Javascript libraries. |
4 | | -// Last generated with makeLanguageSpec.php at 2011-01-28T02:04:09+00:00 |
5 | | - |
6 | | -mediaWiki.messages.set( { |
7 | | - "en_undelete_short": "Undelete {{PLURAL:$1|one edit|$1 edits}}", |
8 | | - "en_category-subcat-count": "{{PLURAL:$2|This category has only the following subcategory.|This category has the following {{PLURAL:$1|subcategory|$1 subcategories}}, out of $2 total.}}", |
9 | | - "fr_undelete_short": "Restaurer $1 modification{{PLURAL:$1||s}}", |
10 | | - "fr_category-subcat-count": "Cette cat\u00e9gorie comprend {{PLURAL:$2|la sous-cat\u00e9gorie|$2 sous-cat\u00e9gories, dont {{PLURAL:$1|celle|les $1}}}} ci-dessous.", |
11 | | - "ar_undelete_short": "\u0627\u0633\u062a\u0631\u062c\u0627\u0639 {{PLURAL:$1|\u062a\u0639\u062f\u064a\u0644 \u0648\u0627\u062d\u062f|\u062a\u0639\u062f\u064a\u0644\u064a\u0646|$1 \u062a\u0639\u062f\u064a\u0644\u0627\u062a|$1 \u062a\u0639\u062f\u064a\u0644|$1 \u062a\u0639\u062f\u064a\u0644\u0627}}", |
12 | | - "ar_category-subcat-count": "{{PLURAL:$2|\u0644\u0627 \u062a\u0635\u0627\u0646\u064a\u0641 \u0641\u0631\u0639\u064a\u0629 \u0641\u064a \u0647\u0630\u0627 \u0627\u0644\u062a\u0635\u0646\u064a\u0641|\u0647\u0630\u0627 \u0627\u0644\u062a\u0635\u0646\u064a\u0641 \u0641\u064a\u0647 \u0627\u0644\u062a\u0635\u0646\u064a\u0641 \u0627\u0644\u0641\u0631\u0639\u064a \u0627\u0644\u062a\u0627\u0644\u064a \u0641\u0642\u0637.|\u0647\u0630\u0627 \u0627\u0644\u062a\u0635\u0646\u064a\u0641 \u0641\u064a\u0647 {{PLURAL:$1||\u0647\u0630\u0627 \u0627\u0644\u062a\u0635\u0646\u064a\u0641 \u0627\u0644\u0641\u0631\u0639\u064a|\u0647\u0630\u064a\u0646 \u0627\u0644\u062a\u0635\u0646\u064a\u0641\u064a\u0646 \u0627\u0644\u0641\u0631\u0639\u064a\u064a\u0646|\u0647\u0630\u0647 \u0627\u0644$1 \u062a\u0635\u0627\u0646\u064a\u0641 \u0627\u0644\u0641\u0631\u0639\u064a\u0629|\u0647\u0630\u0647 \u0627\u0644$1 \u062a\u0635\u0646\u064a\u0641\u0627 \u0641\u0631\u0639\u064a\u0627|\u0647\u0630\u0647 \u0627\u0644$1 \u062a\u0635\u0646\u064a\u0641 \u0641\u0631\u0639\u064a}}\u060c \u0645\u0646 \u0625\u062c\u0645\u0627\u0644\u064a $2.}}", |
13 | | - "jp_undelete_short": "Undelete {{PLURAL:$1|one edit|$1 edits}}", |
14 | | - "jp_category-subcat-count": "{{PLURAL:$2|This category has only the following subcategory.|This category has the following {{PLURAL:$1|subcategory|$1 subcategories}}, out of $2 total.}}", |
15 | | - "zh_undelete_short": "\u6062\u590d\u88ab\u5220\u9664\u7684$1\u9879\u4fee\u8ba2", |
16 | | - "zh_category-subcat-count": "{{PLURAL:$2|\u672c\u5206\u7c7b\u53ea\u6709\u4e0b\u5217\u4e00\u4e2a\u5b50\u5206\u7c7b\u3002|\u672c\u5206\u7c7b\u5305\u542b\u4e0b\u5217$1\u4e2a\u5b50\u5206\u7c7b\uff0c\u5171\u6709$2\u4e2a\u5b50\u5206\u7c7b\u3002}}" |
17 | | -} ); |
18 | | -var jasmineMsgSpec = [ |
19 | | - { |
20 | | - "name": "en undelete_short 0", |
21 | | - "key": "en_undelete_short", |
22 | | - "args": [ |
23 | | - 0 |
24 | | - ], |
25 | | - "result": "Undelete 0 edits", |
26 | | - "lang": "en" |
27 | | - }, |
28 | | - { |
29 | | - "name": "en undelete_short 1", |
30 | | - "key": "en_undelete_short", |
31 | | - "args": [ |
32 | | - 1 |
33 | | - ], |
34 | | - "result": "Undelete one edit", |
35 | | - "lang": "en" |
36 | | - }, |
37 | | - { |
38 | | - "name": "en undelete_short 2", |
39 | | - "key": "en_undelete_short", |
40 | | - "args": [ |
41 | | - 2 |
42 | | - ], |
43 | | - "result": "Undelete 2 edits", |
44 | | - "lang": "en" |
45 | | - }, |
46 | | - { |
47 | | - "name": "en undelete_short 5", |
48 | | - "key": "en_undelete_short", |
49 | | - "args": [ |
50 | | - 5 |
51 | | - ], |
52 | | - "result": "Undelete 5 edits", |
53 | | - "lang": "en" |
54 | | - }, |
55 | | - { |
56 | | - "name": "en undelete_short 21", |
57 | | - "key": "en_undelete_short", |
58 | | - "args": [ |
59 | | - 21 |
60 | | - ], |
61 | | - "result": "Undelete 21 edits", |
62 | | - "lang": "en" |
63 | | - }, |
64 | | - { |
65 | | - "name": "en undelete_short 101", |
66 | | - "key": "en_undelete_short", |
67 | | - "args": [ |
68 | | - 101 |
69 | | - ], |
70 | | - "result": "Undelete 101 edits", |
71 | | - "lang": "en" |
72 | | - }, |
73 | | - { |
74 | | - "name": "en category-subcat-count 0,10", |
75 | | - "key": "en_category-subcat-count", |
76 | | - "args": [ |
77 | | - 0, |
78 | | - 10 |
79 | | - ], |
80 | | - "result": "This category has the following 0 subcategories, out of 10 total.", |
81 | | - "lang": "en" |
82 | | - }, |
83 | | - { |
84 | | - "name": "en category-subcat-count 1,1", |
85 | | - "key": "en_category-subcat-count", |
86 | | - "args": [ |
87 | | - 1, |
88 | | - 1 |
89 | | - ], |
90 | | - "result": "This category has only the following subcategory.", |
91 | | - "lang": "en" |
92 | | - }, |
93 | | - { |
94 | | - "name": "en category-subcat-count 1,2", |
95 | | - "key": "en_category-subcat-count", |
96 | | - "args": [ |
97 | | - 1, |
98 | | - 2 |
99 | | - ], |
100 | | - "result": "This category has the following subcategory, out of 2 total.", |
101 | | - "lang": "en" |
102 | | - }, |
103 | | - { |
104 | | - "name": "en category-subcat-count 3,30", |
105 | | - "key": "en_category-subcat-count", |
106 | | - "args": [ |
107 | | - 3, |
108 | | - 30 |
109 | | - ], |
110 | | - "result": "This category has the following 3 subcategories, out of 30 total.", |
111 | | - "lang": "en" |
112 | | - }, |
113 | | - { |
114 | | - "name": "fr undelete_short 0", |
115 | | - "key": "fr_undelete_short", |
116 | | - "args": [ |
117 | | - 0 |
118 | | - ], |
119 | | - "result": "Restaurer 0 modification", |
120 | | - "lang": "fr" |
121 | | - }, |
122 | | - { |
123 | | - "name": "fr undelete_short 1", |
124 | | - "key": "fr_undelete_short", |
125 | | - "args": [ |
126 | | - 1 |
127 | | - ], |
128 | | - "result": "Restaurer 1 modification", |
129 | | - "lang": "fr" |
130 | | - }, |
131 | | - { |
132 | | - "name": "fr undelete_short 2", |
133 | | - "key": "fr_undelete_short", |
134 | | - "args": [ |
135 | | - 2 |
136 | | - ], |
137 | | - "result": "Restaurer 2 modifications", |
138 | | - "lang": "fr" |
139 | | - }, |
140 | | - { |
141 | | - "name": "fr undelete_short 5", |
142 | | - "key": "fr_undelete_short", |
143 | | - "args": [ |
144 | | - 5 |
145 | | - ], |
146 | | - "result": "Restaurer 5 modifications", |
147 | | - "lang": "fr" |
148 | | - }, |
149 | | - { |
150 | | - "name": "fr undelete_short 21", |
151 | | - "key": "fr_undelete_short", |
152 | | - "args": [ |
153 | | - 21 |
154 | | - ], |
155 | | - "result": "Restaurer 21 modifications", |
156 | | - "lang": "fr" |
157 | | - }, |
158 | | - { |
159 | | - "name": "fr undelete_short 101", |
160 | | - "key": "fr_undelete_short", |
161 | | - "args": [ |
162 | | - 101 |
163 | | - ], |
164 | | - "result": "Restaurer 101 modifications", |
165 | | - "lang": "fr" |
166 | | - }, |
167 | | - { |
168 | | - "name": "fr category-subcat-count 0,10", |
169 | | - "key": "fr_category-subcat-count", |
170 | | - "args": [ |
171 | | - 0, |
172 | | - 10 |
173 | | - ], |
174 | | - "result": "Cette cat\u00e9gorie comprend 10 sous-cat\u00e9gories, dont celle ci-dessous.", |
175 | | - "lang": "fr" |
176 | | - }, |
177 | | - { |
178 | | - "name": "fr category-subcat-count 1,1", |
179 | | - "key": "fr_category-subcat-count", |
180 | | - "args": [ |
181 | | - 1, |
182 | | - 1 |
183 | | - ], |
184 | | - "result": "Cette cat\u00e9gorie comprend la sous-cat\u00e9gorie ci-dessous.", |
185 | | - "lang": "fr" |
186 | | - }, |
187 | | - { |
188 | | - "name": "fr category-subcat-count 1,2", |
189 | | - "key": "fr_category-subcat-count", |
190 | | - "args": [ |
191 | | - 1, |
192 | | - 2 |
193 | | - ], |
194 | | - "result": "Cette cat\u00e9gorie comprend 2 sous-cat\u00e9gories, dont celle ci-dessous.", |
195 | | - "lang": "fr" |
196 | | - }, |
197 | | - { |
198 | | - "name": "fr category-subcat-count 3,30", |
199 | | - "key": "fr_category-subcat-count", |
200 | | - "args": [ |
201 | | - 3, |
202 | | - 30 |
203 | | - ], |
204 | | - "result": "Cette cat\u00e9gorie comprend 30 sous-cat\u00e9gories, dont les 3 ci-dessous.", |
205 | | - "lang": "fr" |
206 | | - }, |
207 | | - { |
208 | | - "name": "ar undelete_short 0", |
209 | | - "key": "ar_undelete_short", |
210 | | - "args": [ |
211 | | - 0 |
212 | | - ], |
213 | | - "result": "\u0627\u0633\u062a\u0631\u062c\u0627\u0639 \u062a\u0639\u062f\u064a\u0644 \u0648\u0627\u062d\u062f", |
214 | | - "lang": "ar" |
215 | | - }, |
216 | | - { |
217 | | - "name": "ar undelete_short 1", |
218 | | - "key": "ar_undelete_short", |
219 | | - "args": [ |
220 | | - 1 |
221 | | - ], |
222 | | - "result": "\u0627\u0633\u062a\u0631\u062c\u0627\u0639 \u062a\u0639\u062f\u064a\u0644\u064a\u0646", |
223 | | - "lang": "ar" |
224 | | - }, |
225 | | - { |
226 | | - "name": "ar undelete_short 2", |
227 | | - "key": "ar_undelete_short", |
228 | | - "args": [ |
229 | | - 2 |
230 | | - ], |
231 | | - "result": "\u0627\u0633\u062a\u0631\u062c\u0627\u0639 2 \u062a\u0639\u062f\u064a\u0644\u0627\u062a", |
232 | | - "lang": "ar" |
233 | | - }, |
234 | | - { |
235 | | - "name": "ar undelete_short 5", |
236 | | - "key": "ar_undelete_short", |
237 | | - "args": [ |
238 | | - 5 |
239 | | - ], |
240 | | - "result": "\u0627\u0633\u062a\u0631\u062c\u0627\u0639 5 \u062a\u0639\u062f\u064a\u0644", |
241 | | - "lang": "ar" |
242 | | - }, |
243 | | - { |
244 | | - "name": "ar undelete_short 21", |
245 | | - "key": "ar_undelete_short", |
246 | | - "args": [ |
247 | | - 21 |
248 | | - ], |
249 | | - "result": "\u0627\u0633\u062a\u0631\u062c\u0627\u0639 21 \u062a\u0639\u062f\u064a\u0644\u0627", |
250 | | - "lang": "ar" |
251 | | - }, |
252 | | - { |
253 | | - "name": "ar undelete_short 101", |
254 | | - "key": "ar_undelete_short", |
255 | | - "args": [ |
256 | | - 101 |
257 | | - ], |
258 | | - "result": "\u0627\u0633\u062a\u0631\u062c\u0627\u0639 101 \u062a\u0639\u062f\u064a\u0644\u0627", |
259 | | - "lang": "ar" |
260 | | - }, |
261 | | - { |
262 | | - "name": "ar category-subcat-count 0,10", |
263 | | - "key": "ar_category-subcat-count", |
264 | | - "args": [ |
265 | | - 0, |
266 | | - 10 |
267 | | - ], |
268 | | - "result": "\u0647\u0630\u0627 \u0627\u0644\u062a\u0635\u0646\u064a\u0641 \u0641\u064a\u0647 \u060c \u0645\u0646 \u0625\u062c\u0645\u0627\u0644\u064a 10.", |
269 | | - "lang": "ar" |
270 | | - }, |
271 | | - { |
272 | | - "name": "ar category-subcat-count 1,1", |
273 | | - "key": "ar_category-subcat-count", |
274 | | - "args": [ |
275 | | - 1, |
276 | | - 1 |
277 | | - ], |
278 | | - "result": "\u0647\u0630\u0627 \u0627\u0644\u062a\u0635\u0646\u064a\u0641 \u0641\u064a\u0647 \u0627\u0644\u062a\u0635\u0646\u064a\u0641 \u0627\u0644\u0641\u0631\u0639\u064a \u0627\u0644\u062a\u0627\u0644\u064a \u0641\u0642\u0637.", |
279 | | - "lang": "ar" |
280 | | - }, |
281 | | - { |
282 | | - "name": "ar category-subcat-count 1,2", |
283 | | - "key": "ar_category-subcat-count", |
284 | | - "args": [ |
285 | | - 1, |
286 | | - 2 |
287 | | - ], |
288 | | - "result": "\u0647\u0630\u0627 \u0627\u0644\u062a\u0635\u0646\u064a\u0641 \u0641\u064a\u0647 \u0647\u0630\u0627 \u0627\u0644\u062a\u0635\u0646\u064a\u0641 \u0627\u0644\u0641\u0631\u0639\u064a\u060c \u0645\u0646 \u0625\u062c\u0645\u0627\u0644\u064a 2.", |
289 | | - "lang": "ar" |
290 | | - }, |
291 | | - { |
292 | | - "name": "ar category-subcat-count 3,30", |
293 | | - "key": "ar_category-subcat-count", |
294 | | - "args": [ |
295 | | - 3, |
296 | | - 30 |
297 | | - ], |
298 | | - "result": "\u0647\u0630\u0627 \u0627\u0644\u062a\u0635\u0646\u064a\u0641 \u0641\u064a\u0647 \u0647\u0630\u0647 \u0627\u06443 \u062a\u0635\u0627\u0646\u064a\u0641 \u0627\u0644\u0641\u0631\u0639\u064a\u0629\u060c \u0645\u0646 \u0625\u062c\u0645\u0627\u0644\u064a 30.", |
299 | | - "lang": "ar" |
300 | | - }, |
301 | | - { |
302 | | - "name": "jp undelete_short 0", |
303 | | - "key": "jp_undelete_short", |
304 | | - "args": [ |
305 | | - 0 |
306 | | - ], |
307 | | - "result": "Undelete 0 edits", |
308 | | - "lang": "jp" |
309 | | - }, |
310 | | - { |
311 | | - "name": "jp undelete_short 1", |
312 | | - "key": "jp_undelete_short", |
313 | | - "args": [ |
314 | | - 1 |
315 | | - ], |
316 | | - "result": "Undelete one edit", |
317 | | - "lang": "jp" |
318 | | - }, |
319 | | - { |
320 | | - "name": "jp undelete_short 2", |
321 | | - "key": "jp_undelete_short", |
322 | | - "args": [ |
323 | | - 2 |
324 | | - ], |
325 | | - "result": "Undelete 2 edits", |
326 | | - "lang": "jp" |
327 | | - }, |
328 | | - { |
329 | | - "name": "jp undelete_short 5", |
330 | | - "key": "jp_undelete_short", |
331 | | - "args": [ |
332 | | - 5 |
333 | | - ], |
334 | | - "result": "Undelete 5 edits", |
335 | | - "lang": "jp" |
336 | | - }, |
337 | | - { |
338 | | - "name": "jp undelete_short 21", |
339 | | - "key": "jp_undelete_short", |
340 | | - "args": [ |
341 | | - 21 |
342 | | - ], |
343 | | - "result": "Undelete 21 edits", |
344 | | - "lang": "jp" |
345 | | - }, |
346 | | - { |
347 | | - "name": "jp undelete_short 101", |
348 | | - "key": "jp_undelete_short", |
349 | | - "args": [ |
350 | | - 101 |
351 | | - ], |
352 | | - "result": "Undelete 101 edits", |
353 | | - "lang": "jp" |
354 | | - }, |
355 | | - { |
356 | | - "name": "jp category-subcat-count 0,10", |
357 | | - "key": "jp_category-subcat-count", |
358 | | - "args": [ |
359 | | - 0, |
360 | | - 10 |
361 | | - ], |
362 | | - "result": "This category has the following 0 subcategories, out of 10 total.", |
363 | | - "lang": "jp" |
364 | | - }, |
365 | | - { |
366 | | - "name": "jp category-subcat-count 1,1", |
367 | | - "key": "jp_category-subcat-count", |
368 | | - "args": [ |
369 | | - 1, |
370 | | - 1 |
371 | | - ], |
372 | | - "result": "This category has only the following subcategory.", |
373 | | - "lang": "jp" |
374 | | - }, |
375 | | - { |
376 | | - "name": "jp category-subcat-count 1,2", |
377 | | - "key": "jp_category-subcat-count", |
378 | | - "args": [ |
379 | | - 1, |
380 | | - 2 |
381 | | - ], |
382 | | - "result": "This category has the following subcategory, out of 2 total.", |
383 | | - "lang": "jp" |
384 | | - }, |
385 | | - { |
386 | | - "name": "jp category-subcat-count 3,30", |
387 | | - "key": "jp_category-subcat-count", |
388 | | - "args": [ |
389 | | - 3, |
390 | | - 30 |
391 | | - ], |
392 | | - "result": "This category has the following 3 subcategories, out of 30 total.", |
393 | | - "lang": "jp" |
394 | | - }, |
395 | | - { |
396 | | - "name": "zh undelete_short 0", |
397 | | - "key": "zh_undelete_short", |
398 | | - "args": [ |
399 | | - 0 |
400 | | - ], |
401 | | - "result": "\u6062\u590d\u88ab\u5220\u9664\u76840\u9879\u4fee\u8ba2", |
402 | | - "lang": "zh" |
403 | | - }, |
404 | | - { |
405 | | - "name": "zh undelete_short 1", |
406 | | - "key": "zh_undelete_short", |
407 | | - "args": [ |
408 | | - 1 |
409 | | - ], |
410 | | - "result": "\u6062\u590d\u88ab\u5220\u9664\u76841\u9879\u4fee\u8ba2", |
411 | | - "lang": "zh" |
412 | | - }, |
413 | | - { |
414 | | - "name": "zh undelete_short 2", |
415 | | - "key": "zh_undelete_short", |
416 | | - "args": [ |
417 | | - 2 |
418 | | - ], |
419 | | - "result": "\u6062\u590d\u88ab\u5220\u9664\u76842\u9879\u4fee\u8ba2", |
420 | | - "lang": "zh" |
421 | | - }, |
422 | | - { |
423 | | - "name": "zh undelete_short 5", |
424 | | - "key": "zh_undelete_short", |
425 | | - "args": [ |
426 | | - 5 |
427 | | - ], |
428 | | - "result": "\u6062\u590d\u88ab\u5220\u9664\u76845\u9879\u4fee\u8ba2", |
429 | | - "lang": "zh" |
430 | | - }, |
431 | | - { |
432 | | - "name": "zh undelete_short 21", |
433 | | - "key": "zh_undelete_short", |
434 | | - "args": [ |
435 | | - 21 |
436 | | - ], |
437 | | - "result": "\u6062\u590d\u88ab\u5220\u9664\u768421\u9879\u4fee\u8ba2", |
438 | | - "lang": "zh" |
439 | | - }, |
440 | | - { |
441 | | - "name": "zh undelete_short 101", |
442 | | - "key": "zh_undelete_short", |
443 | | - "args": [ |
444 | | - 101 |
445 | | - ], |
446 | | - "result": "\u6062\u590d\u88ab\u5220\u9664\u7684101\u9879\u4fee\u8ba2", |
447 | | - "lang": "zh" |
448 | | - }, |
449 | | - { |
450 | | - "name": "zh category-subcat-count 0,10", |
451 | | - "key": "zh_category-subcat-count", |
452 | | - "args": [ |
453 | | - 0, |
454 | | - 10 |
455 | | - ], |
456 | | - "result": "\u672c\u5206\u7c7b\u5305\u542b\u4e0b\u52170\u4e2a\u5b50\u5206\u7c7b\uff0c\u5171\u670910\u4e2a\u5b50\u5206\u7c7b\u3002", |
457 | | - "lang": "zh" |
458 | | - }, |
459 | | - { |
460 | | - "name": "zh category-subcat-count 1,1", |
461 | | - "key": "zh_category-subcat-count", |
462 | | - "args": [ |
463 | | - 1, |
464 | | - 1 |
465 | | - ], |
466 | | - "result": "\u672c\u5206\u7c7b\u53ea\u6709\u4e0b\u5217\u4e00\u4e2a\u5b50\u5206\u7c7b\u3002", |
467 | | - "lang": "zh" |
468 | | - }, |
469 | | - { |
470 | | - "name": "zh category-subcat-count 1,2", |
471 | | - "key": "zh_category-subcat-count", |
472 | | - "args": [ |
473 | | - 1, |
474 | | - 2 |
475 | | - ], |
476 | | - "result": "\u672c\u5206\u7c7b\u5305\u542b\u4e0b\u52171\u4e2a\u5b50\u5206\u7c7b\uff0c\u5171\u67092\u4e2a\u5b50\u5206\u7c7b\u3002", |
477 | | - "lang": "zh" |
478 | | - }, |
479 | | - { |
480 | | - "name": "zh category-subcat-count 3,30", |
481 | | - "key": "zh_category-subcat-count", |
482 | | - "args": [ |
483 | | - 3, |
484 | | - 30 |
485 | | - ], |
486 | | - "result": "\u672c\u5206\u7c7b\u5305\u542b\u4e0b\u52173\u4e2a\u5b50\u5206\u7c7b\uff0c\u5171\u670930\u4e2a\u5b50\u5206\u7c7b\u3002", |
487 | | - "lang": "zh" |
488 | | - } |
489 | | -]; |
Index: trunk/extensions/UploadWizard/UploadWizardHooks.php |
— | — | @@ -10,10 +10,6 @@ |
11 | 11 | public static $modules = array( |
12 | 12 | // n.b. we tend not to use mediawiki.language functions, they are better implemented in mediawiki.language.parser. |
13 | 13 | // however, loading mediawiki.language will a) create the namespace b) load the language files with convertPlural for the current language and all. |
14 | | - 'ext.uploadwizard.mediawiki.language.parser' => array( |
15 | | - 'dependencies' => array( 'mediawiki.language', 'mediawiki.util' ), |
16 | | - 'scripts' => 'resources/mediawiki.language.parser.js' |
17 | | - ), |
18 | 14 | 'ext.uploadWizard' => array( |
19 | 15 | 'dependencies' => array( |
20 | 16 | 'jquery.autoEllipsis', |
— | — | @@ -27,7 +23,7 @@ |
28 | 24 | 'mediawiki.Uri', |
29 | 25 | 'mediawiki.util', |
30 | 26 | 'mediawiki.libs.jpegmeta', |
31 | | - 'ext.uploadwizard.mediawiki.language.parser', |
| 27 | + 'mediawiki.jqueryMsg', |
32 | 28 | 'mediawiki.api', |
33 | 29 | 'mediawiki.api.edit', |
34 | 30 | 'mediawiki.api.category', |
Index: trunk/extensions/UploadWizard/resources/mediawiki.language.parser.peg |
— | — | @@ -1,76 +0,0 @@ |
2 | | -/* PEG grammar for a subset of wikitext, useful in the MediaWiki frontend */ |
3 | | - |
4 | | -start |
5 | | - = e:expression* { return e.length > 1 ? [ "CONCAT" ].concat(e) : e[0]; } |
6 | | - |
7 | | -expression |
8 | | - = template |
9 | | - / link |
10 | | - / extlink |
11 | | - / replacement |
12 | | - / literal |
13 | | - |
14 | | -paramExpression |
15 | | - = template |
16 | | - / link |
17 | | - / extlink |
18 | | - / replacement |
19 | | - / literalWithoutBar |
20 | | - |
21 | | -template |
22 | | - = "{{" t:templateContents "}}" { return t; } |
23 | | - |
24 | | -templateContents |
25 | | - = twr:templateWithReplacement p:templateParam* { return twr.concat(p) } |
26 | | - / t:templateName p:templateParam* { return p.length ? [ t, p ] : [ t ] } |
27 | | - |
28 | | -templateWithReplacement |
29 | | - = t:templateName ":" r:replacement { return [ t, r ] } |
30 | | - |
31 | | -templateParam |
32 | | - = "|" e:paramExpression* { return e.length > 1 ? [ "CONCAT" ].concat(e) : e[0]; } |
33 | | - |
34 | | -templateName |
35 | | - = tn:[A-Za-z_]+ { return tn.join('').toUpperCase() } |
36 | | - |
37 | | -link |
38 | | - = "[[" w:expression "]]" { return [ 'WLINK', w ]; } |
39 | | - |
40 | | -extlink |
41 | | - = "[" url:url whitespace text:expression "]" { return [ 'LINK', url, text ] } |
42 | | - |
43 | | -url |
44 | | - = url:[^ ]+ { return url.join(''); } |
45 | | - |
46 | | -whitespace |
47 | | - = [ ]+ |
48 | | - |
49 | | -replacement |
50 | | - = '$' digits:digits { return [ 'REPLACE', parseInt( digits, 10 ) - 1 ] } |
51 | | - |
52 | | -digits |
53 | | - = [0-9]+ |
54 | | - |
55 | | -literal |
56 | | - = lit:escapedOrRegularLiteral+ { return lit.join(''); } |
57 | | - |
58 | | -literalWithoutBar |
59 | | - = lit:escapedOrLiteralWithoutBar+ { return lit.join(''); } |
60 | | - |
61 | | -escapedOrRegularLiteral |
62 | | - = escapedLiteral |
63 | | - / regularLiteral |
64 | | - |
65 | | -escapedOrLiteralWithoutBar |
66 | | - = escapedLiteral |
67 | | - / regularLiteralWithoutBar |
68 | | - |
69 | | -escapedLiteral |
70 | | - = "\\" escaped:. { return escaped; } |
71 | | - |
72 | | -regularLiteral |
73 | | - = [^{}\[\]$\\] |
74 | | - |
75 | | -regularLiteralWithoutBar |
76 | | - = [^{}\[\]$\\|] |
77 | | - |
Index: trunk/extensions/UploadWizard/resources/mediawiki.language.parser.js |
— | — | @@ -1,637 +0,0 @@ |
2 | | -/** |
3 | | - * Experimental advanced wikitext parser-emitter. |
4 | | - * See: http://www.mediawiki.org/wiki/Extension:UploadWizard/MessageParser for docs |
5 | | - * |
6 | | - * @author neilk@wikimedia.org |
7 | | - */ |
8 | | - |
9 | | -( function( mw, $j ) { |
10 | | - |
11 | | - /** |
12 | | - * Given parser options, return a function that parses a key and replacements, returning jQuery object |
13 | | - * @param {Object} parser options |
14 | | - * @return {Function} accepting ( String message key, String replacement1, String replacement2 ... ) and returning {jQuery} |
15 | | - */ |
16 | | - function getFailableParserFn( options ) { |
17 | | - var parser = new mw.language.parser( options ); |
18 | | - /** |
19 | | - * Try to parse a key and optional replacements, returning a jQuery object that may be a tree of jQuery nodes. |
20 | | - * If there was an error parsing, return the key and the error message (wrapped in jQuery). This should put the error right into |
21 | | - * the interface, without causing the page to halt script execution, and it hopefully should be clearer how to fix it. |
22 | | - * |
23 | | - * @param {Array} first element is the key, replacements may be in array in 2nd element, or remaining elements. |
24 | | - * @return {jQuery} |
25 | | - */ |
26 | | - return function( args ) { |
27 | | - var key = args[0]; |
28 | | - var replacements = $j.isArray( args[1] ) ? args[1] : $j.makeArray( args ).slice( 1 ); |
29 | | - try { |
30 | | - return parser.parse( key, replacements ); |
31 | | - } catch ( e ) { |
32 | | - return $j( '<span></span>' ).append( key + ': ' + e.message ); |
33 | | - } |
34 | | - }; |
35 | | - } |
36 | | - |
37 | | - /** |
38 | | - * Class method. |
39 | | - * Returns a function suitable for use as a global, to construct strings from the message key (and optional replacements). |
40 | | - * e.g. |
41 | | - * window.gM = mediaWiki.parser.getMessageFunction( options ); |
42 | | - * $j( 'p#headline' ).html( gM( 'hello-user', username ) ); |
43 | | - * |
44 | | - * Like the old gM() function this returns only strings, so it destroys any bindings. If you want to preserve bindings use the |
45 | | - * jQuery plugin version instead. This is only included for backwards compatibility with gM(). |
46 | | - * |
47 | | - * @param {Array} parser options |
48 | | - * @return {Function} function suitable for assigning to window.gM |
49 | | - */ |
50 | | - mw.language.getMessageFunction = function( options ) { |
51 | | - var failableParserFn = getFailableParserFn( options ); |
52 | | - /** |
53 | | - * N.B. replacements are variadic arguments or an array in second parameter. In other words: |
54 | | - * somefunction(a, b, c, d) |
55 | | - * is equivalent to |
56 | | - * somefunction(a, [b, c, d]) |
57 | | - * |
58 | | - * @param {String} message key |
59 | | - * @param {Array} optional replacements (can also specify variadically) |
60 | | - * @return {String} rendered HTML as string |
61 | | - */ |
62 | | - return function( /* key, replacements */ ) { |
63 | | - return failableParserFn( arguments ).html(); |
64 | | - }; |
65 | | - }; |
66 | | - |
67 | | - /** |
68 | | - * Class method. |
69 | | - * Returns a jQuery plugin which parses the message in the message key, doing replacements optionally, and appends the nodes to |
70 | | - * the current selector. Bindings to passed-in jquery elements are preserved. Functions become click handlers for [$1 linktext] links. |
71 | | - * e.g. |
72 | | - * $j.fn.msg = mediaWiki.parser.getJqueryPlugin( options ); |
73 | | - * var userlink = $j( '<a>' ).click( function() { alert( "hello!!") } ); |
74 | | - * $j( 'p#headline' ).msg( 'hello-user', userlink ); |
75 | | - * |
76 | | - * @param {Array} parser options |
77 | | - * @return {Function} function suitable for assigning to jQuery plugin, such as $j.fn.msg |
78 | | - */ |
79 | | - mw.language.getJqueryMessagePlugin = function( options ) { |
80 | | - var failableParserFn = getFailableParserFn( options ); |
81 | | - /** |
82 | | - * N.B. replacements are variadic arguments or an array in second parameter. In other words: |
83 | | - * somefunction(a, b, c, d) |
84 | | - * is equivalent to |
85 | | - * somefunction(a, [b, c, d]) |
86 | | - * |
87 | | - * We append to 'this', which in a jQuery plugin context will be the selected elements. |
88 | | - * @param {String} message key |
89 | | - * @param {Array} optional replacements (can also specify variadically) |
90 | | - * @return {jQuery} this |
91 | | - */ |
92 | | - return function( /* key, replacements */ ) { |
93 | | - var $target = this.empty(); |
94 | | - $j.each( failableParserFn( arguments ).contents(), function( i, node ) { |
95 | | - $target.append( node ); |
96 | | - } ); |
97 | | - return $target; |
98 | | - }; |
99 | | - }; |
100 | | - |
101 | | - var parserDefaults = { |
102 | | - 'magic' : {}, |
103 | | - 'messages' : mw.messages, |
104 | | - 'language' : mw.language |
105 | | - }; |
106 | | - |
107 | | - /** |
108 | | - * The parser itself. |
109 | | - * Describes an object, whose primary duty is to .parse() message keys. |
110 | | - * @param {Array} options |
111 | | - */ |
112 | | - mw.language.parser = function( options ) { |
113 | | - this.settings = $j.extend( {}, parserDefaults, options ); |
114 | | - this.emitter = new mw.language.htmlEmitter( this.settings.language, this.settings.magic ); |
115 | | - }; |
116 | | - |
117 | | - mw.language.parser.prototype = { |
118 | | - |
119 | | - // cache, map of mediaWiki message key to the AST of the message. In most cases, the message is a string so this is identical. |
120 | | - // (This is why we would like to move this functionality server-side). |
121 | | - astCache: {}, |
122 | | - |
123 | | - /** |
124 | | - * Where the magic happens. |
125 | | - * Parses a message from the key, and swaps in replacements as necessary, wraps in jQuery |
126 | | - * If an error is thrown, returns original key, and logs the error |
127 | | - * @param {String} message key |
128 | | - * @param {Array} replacements for $1, $2... $n |
129 | | - * @return {jQuery} |
130 | | - */ |
131 | | - parse: function( key, replacements ) { |
132 | | - return this.emitter.emit( this.getAst( key ), replacements ); |
133 | | - }, |
134 | | - |
135 | | - /** |
136 | | - * Fetch the message string associated with a key, return parsed structure. Memoized. |
137 | | - * Note that we pass '[' + key + ']' back for a missing message here. |
138 | | - * @param {String} key |
139 | | - * @return {String|Array} string of '[key]' if message missing, simple string if possible, array of arrays if needs parsing |
140 | | - */ |
141 | | - getAst: function( key ) { |
142 | | - if ( typeof this.astCache[ key ] === 'undefined' ) { |
143 | | - var wikiText = this.settings.messages.get( key ); |
144 | | - if ( typeof wikiText !== 'string' ) { |
145 | | - wikiText = "\\[" + key + "\\]"; |
146 | | - } |
147 | | - this.astCache[ key ] = this.wikiTextToAst( wikiText ); |
148 | | - } |
149 | | - return this.astCache[ key ]; |
150 | | - }, |
151 | | - |
152 | | - /* |
153 | | - * Parses the input wikiText into an abstract syntax tree, essentially an s-expression. |
154 | | - * |
155 | | - * CAVEAT: This does not parse all wikitext. It could be more efficient, but it's pretty good already. |
156 | | - * n.b. We want to move this functionality to the server. Nothing here is required to be on the client. |
157 | | - * |
158 | | - * @param {String} message string wikitext |
159 | | - * @throws Error |
160 | | - * @return {Mixed} abstract syntax tree |
161 | | - */ |
162 | | - wikiTextToAst: function( input ) { |
163 | | - |
164 | | - // Indicates current position in input as we parse through it. |
165 | | - // Shared among all parsing functions below. |
166 | | - var pos = 0; |
167 | | - |
168 | | - // ========================================================= |
169 | | - // parsing combinators - could be a library on its own |
170 | | - // ========================================================= |
171 | | - |
172 | | - |
173 | | - // Try parsers until one works, if none work return null |
174 | | - function choice( ps ) { |
175 | | - return function() { |
176 | | - for ( var i = 0; i < ps.length; i++ ) { |
177 | | - var result = ps[i](); |
178 | | - if ( result !== null ) { |
179 | | - return result; |
180 | | - } |
181 | | - } |
182 | | - return null; |
183 | | - }; |
184 | | - } |
185 | | - |
186 | | - // try several ps in a row, all must succeed or return null |
187 | | - // this is the only eager one |
188 | | - function sequence( ps ) { |
189 | | - var originalPos = pos; |
190 | | - var result = []; |
191 | | - for ( var i = 0; i < ps.length; i++ ) { |
192 | | - var res = ps[i](); |
193 | | - if ( res === null ) { |
194 | | - pos = originalPos; |
195 | | - return null; |
196 | | - } |
197 | | - result.push( res ); |
198 | | - } |
199 | | - return result; |
200 | | - } |
201 | | - |
202 | | - // run the same parser over and over until it fails. |
203 | | - // must succeed a minimum of n times or return null |
204 | | - function nOrMore( n, p ) { |
205 | | - return function() { |
206 | | - var originalPos = pos; |
207 | | - var result = []; |
208 | | - var parsed = p(); |
209 | | - while ( parsed !== null ) { |
210 | | - result.push( parsed ); |
211 | | - parsed = p(); |
212 | | - } |
213 | | - if ( result.length < n ) { |
214 | | - pos = originalPos; |
215 | | - return null; |
216 | | - } |
217 | | - return result; |
218 | | - }; |
219 | | - } |
220 | | - |
221 | | - // There is a general pattern -- parse a thing, if that worked, apply transform, otherwise return null. |
222 | | - // But using this as a combinator seems to cause problems when combined with nOrMore(). |
223 | | - // May be some scoping issue |
224 | | - function transform( p, fn ) { |
225 | | - return function() { |
226 | | - var result = p(); |
227 | | - return result === null ? null : fn( result ); |
228 | | - }; |
229 | | - } |
230 | | - |
231 | | - // Helpers -- just make ps out of simpler JS builtin types |
232 | | - |
233 | | - function makeStringParser( s ) { |
234 | | - var len = s.length; |
235 | | - return function() { |
236 | | - var result = null; |
237 | | - if ( input.substr( pos, len ) === s ) { |
238 | | - result = s; |
239 | | - pos += len; |
240 | | - } |
241 | | - return result; |
242 | | - }; |
243 | | - } |
244 | | - |
245 | | - function makeRegexParser( regex ) { |
246 | | - return function() { |
247 | | - var matches = input.substr( pos ).match( regex ); |
248 | | - if ( matches === null ) { |
249 | | - return null; |
250 | | - } |
251 | | - pos += matches[0].length; |
252 | | - return matches[0]; |
253 | | - }; |
254 | | - } |
255 | | - |
256 | | - |
257 | | - /** |
258 | | - * =================================================================== |
259 | | - * General patterns above this line -- wikitext specific parsers below |
260 | | - * =================================================================== |
261 | | - */ |
262 | | - |
263 | | - // Parsing functions follow. All parsing functions work like this: |
264 | | - // They don't accept any arguments. |
265 | | - // Instead, they just operate non destructively on the string 'input' |
266 | | - // As they can consume parts of the string, they advance the shared variable pos, |
267 | | - // and return tokens (or whatever else they want to return). |
268 | | - |
269 | | - // some things are defined as closures and other things as ordinary functions |
270 | | - // converting everything to a closure makes it a lot harder to debug... errors pop up |
271 | | - // but some debuggers can't tell you exactly where they come from. Also the mutually |
272 | | - // recursive functions seem not to work in all browsers then. (Tested IE6-7, Opera, Safari, FF) |
273 | | - // This may be because, to save code, memoization was removed |
274 | | - |
275 | | - |
276 | | - var regularLiteral = makeRegexParser( /^[^{}[\]$\\]/ ); |
277 | | - var regularLiteralWithoutBar = makeRegexParser(/^[^{}[\]$\\|]/); |
278 | | - var regularLiteralWithoutSpace = makeRegexParser(/^[^{}[\]$\s]/); |
279 | | - |
280 | | - var backslash = makeStringParser( "\\" ); |
281 | | - var anyCharacter = makeRegexParser( /^./ ); |
282 | | - |
283 | | - function escapedLiteral() { |
284 | | - var result = sequence( [ |
285 | | - backslash, |
286 | | - anyCharacter |
287 | | - ] ); |
288 | | - return result === null ? null : result[1]; |
289 | | - } |
290 | | - |
291 | | - var escapedOrLiteralWithoutSpace = choice( [ |
292 | | - escapedLiteral, |
293 | | - regularLiteralWithoutSpace |
294 | | - ] ); |
295 | | - |
296 | | - var escapedOrLiteralWithoutBar = choice( [ |
297 | | - escapedLiteral, |
298 | | - regularLiteralWithoutBar |
299 | | - ] ); |
300 | | - |
301 | | - var escapedOrRegularLiteral = choice( [ |
302 | | - escapedLiteral, |
303 | | - regularLiteral |
304 | | - ] ); |
305 | | - |
306 | | - // Used to define "literals" without spaces, in space-delimited situations |
307 | | - function literalWithoutSpace() { |
308 | | - var result = nOrMore( 1, escapedOrLiteralWithoutSpace )(); |
309 | | - return result === null ? null : result.join(''); |
310 | | - } |
311 | | - |
312 | | - // Used to define "literals" within template parameters. The pipe character is the parameter delimeter, so by default |
313 | | - // it is not a literal in the parameter |
314 | | - function literalWithoutBar() { |
315 | | - var result = nOrMore( 1, escapedOrLiteralWithoutBar )(); |
316 | | - return result === null ? null : result.join(''); |
317 | | - } |
318 | | - |
319 | | - function literal() { |
320 | | - var result = nOrMore( 1, escapedOrRegularLiteral )(); |
321 | | - return result === null ? null : result.join(''); |
322 | | - } |
323 | | - |
324 | | - var whitespace = makeRegexParser( /^\s+/ ); |
325 | | - var dollar = makeStringParser( '$' ); |
326 | | - var digits = makeRegexParser( /^\d+/ ); |
327 | | - |
328 | | - function replacement() { |
329 | | - var result = sequence( [ |
330 | | - dollar, |
331 | | - digits |
332 | | - ] ); |
333 | | - if ( result === null ) { |
334 | | - return null; |
335 | | - } |
336 | | - return [ 'REPLACE', parseInt( result[1], 10 ) - 1 ]; |
337 | | - } |
338 | | - |
339 | | - |
340 | | - var openExtlink = makeStringParser( '[' ); |
341 | | - var closeExtlink = makeStringParser( ']' ); |
342 | | - |
343 | | - // this extlink MUST have inner text, e.g. [foo] not allowed; [foo bar] is allowed |
344 | | - function extlink() { |
345 | | - var result = null; |
346 | | - var parsedResult = sequence( [ |
347 | | - openExtlink, |
348 | | - nonWhitespaceExpression, |
349 | | - whitespace, |
350 | | - expression, |
351 | | - closeExtlink |
352 | | - ] ); |
353 | | - if ( parsedResult !== null ) { |
354 | | - result = [ 'LINK', parsedResult[1], parsedResult[3] ]; |
355 | | - } |
356 | | - return result; |
357 | | - } |
358 | | - |
359 | | - var openLink = makeStringParser( '[[' ); |
360 | | - var closeLink = makeStringParser( ']]' ); |
361 | | - |
362 | | - function link() { |
363 | | - var result = null; |
364 | | - var parsedResult = sequence( [ |
365 | | - openLink, |
366 | | - expression, |
367 | | - closeLink |
368 | | - ] ); |
369 | | - if ( parsedResult !== null ) { |
370 | | - result = [ 'WLINK', parsedResult[1] ]; |
371 | | - } |
372 | | - return result; |
373 | | - } |
374 | | - |
375 | | - var templateName = transform( |
376 | | - // see $wgLegalTitleChars |
377 | | - // not allowing : due to the need to catch "PLURAL:$1" |
378 | | - makeRegexParser( /^[ !"$&'()*,.\/0-9;=?@A-Z\^_`a-z~\x80-\xFF+-]+/ ), |
379 | | - function( result ) { return result.toString(); } |
380 | | - ); |
381 | | - |
382 | | - function templateParam() { |
383 | | - var result = sequence( [ |
384 | | - pipe, |
385 | | - nOrMore( 0, paramExpression ) |
386 | | - ] ); |
387 | | - if ( result === null ) { |
388 | | - return null; |
389 | | - } |
390 | | - var expr = result[1]; |
391 | | - // use a "CONCAT" operator if there are multiple nodes, otherwise return the first node, raw. |
392 | | - return expr.length > 1 ? [ "CONCAT" ].concat( expr ) : expr[0]; |
393 | | - } |
394 | | - |
395 | | - var pipe = makeStringParser( '|' ); |
396 | | - |
397 | | - function templateWithReplacement() { |
398 | | - var result = sequence( [ |
399 | | - templateName, |
400 | | - colon, |
401 | | - replacement |
402 | | - ] ); |
403 | | - return result === null ? null : [ result[0], result[2] ]; |
404 | | - } |
405 | | - |
406 | | - var colon = makeStringParser(':'); |
407 | | - |
408 | | - var templateContents = choice( [ |
409 | | - function() { |
410 | | - var res = sequence( [ |
411 | | - templateWithReplacement, |
412 | | - nOrMore( 0, templateParam ) |
413 | | - ] ); |
414 | | - return res === null ? null : res[0].concat( res[1] ); |
415 | | - }, |
416 | | - function() { |
417 | | - var res = sequence( [ |
418 | | - templateName, |
419 | | - nOrMore( 0, templateParam ) |
420 | | - ] ); |
421 | | - if ( res === null ) { |
422 | | - return null; |
423 | | - } |
424 | | - return [ res[0] ].concat( res[1] ); |
425 | | - } |
426 | | - ] ); |
427 | | - |
428 | | - var openTemplate = makeStringParser('{{'); |
429 | | - var closeTemplate = makeStringParser('}}'); |
430 | | - |
431 | | - function template() { |
432 | | - var result = sequence( [ |
433 | | - openTemplate, |
434 | | - templateContents, |
435 | | - closeTemplate |
436 | | - ] ); |
437 | | - return result === null ? null : result[1]; |
438 | | - } |
439 | | - |
440 | | - var nonWhitespaceExpression = choice( [ |
441 | | - template, |
442 | | - link, |
443 | | - extlink, |
444 | | - replacement, |
445 | | - literalWithoutSpace |
446 | | - ] ); |
447 | | - |
448 | | - var paramExpression = choice( [ |
449 | | - template, |
450 | | - link, |
451 | | - extlink, |
452 | | - replacement, |
453 | | - literalWithoutBar |
454 | | - ] ); |
455 | | - |
456 | | - var expression = choice( [ |
457 | | - template, |
458 | | - link, |
459 | | - extlink, |
460 | | - replacement, |
461 | | - literal |
462 | | - ] ); |
463 | | - |
464 | | - function start() { |
465 | | - var result = nOrMore( 0, expression )(); |
466 | | - if ( result === null ) { |
467 | | - return null; |
468 | | - } |
469 | | - return [ "CONCAT" ].concat( result ); |
470 | | - } |
471 | | - |
472 | | - // everything above this point is supposed to be stateless/static, but |
473 | | - // I am deferring the work of turning it into prototypes & objects. It's quite fast enough |
474 | | - |
475 | | - // finally let's do some actual work... |
476 | | - |
477 | | - var result = start(); |
478 | | - |
479 | | - /* |
480 | | - * For success, the p must have gotten to the end of the input |
481 | | - * and returned a non-null. |
482 | | - * n.b. This is part of language infrastructure, so we do not throw an internationalizable message. |
483 | | - */ |
484 | | - if (result === null || pos !== input.length) { |
485 | | - throw new Error( "Parse error at position " + pos.toString() + " in input: " + input ); |
486 | | - } |
487 | | - return result; |
488 | | - } |
489 | | - |
490 | | - }; |
491 | | - |
492 | | - /** |
493 | | - * htmlEmitter - object which primarily exists to emit HTML from parser ASTs |
494 | | - */ |
495 | | - mw.language.htmlEmitter = function( language, magic ) { |
496 | | - this.language = language; |
497 | | - var _this = this; |
498 | | - |
499 | | - $j.each( magic, function( key, val ) { |
500 | | - _this[ key.toLowerCase() ] = function() { return val; }; |
501 | | - } ); |
502 | | - |
503 | | - /** |
504 | | - * (We put this method definition here, and not in prototype, to make sure it's not overwritten by any magic.) |
505 | | - * Walk entire node structure, applying replacements and template functions when appropriate |
506 | | - * @param {Mixed} abstract syntax tree (top node or subnode) |
507 | | - * @param {Array} replacements for $1, $2, ... $n |
508 | | - * @return {Mixed} single-string node or array of nodes suitable for jQuery appending |
509 | | - */ |
510 | | - this.emit = function( node, replacements ) { |
511 | | - var ret = null; |
512 | | - var _this = this; |
513 | | - switch( typeof node ) { |
514 | | - case 'string': |
515 | | - case 'number': |
516 | | - ret = node; |
517 | | - break; |
518 | | - case 'object': // node is an array of nodes |
519 | | - var subnodes = $j.map( node.slice( 1 ), function( n ) { |
520 | | - return _this.emit( n, replacements ); |
521 | | - } ); |
522 | | - var operation = node[0].toLowerCase(); |
523 | | - if ( typeof _this[operation] === 'function' ) { |
524 | | - ret = _this[ operation ]( subnodes, replacements ); |
525 | | - } else { |
526 | | - throw new Error( 'unknown operation "' + operation + '"' ); |
527 | | - } |
528 | | - break; |
529 | | - case 'undefined': |
530 | | - // Parsing the empty string (as an entire expression, or as a paramExpression in a template) results in undefined |
531 | | - // Perhaps a more clever parser can detect this, and return the empty string? Or is that useful information? |
532 | | - // The logical thing is probably to return the empty string here when we encounter undefined. |
533 | | - ret = ''; |
534 | | - break; |
535 | | - default: |
536 | | - throw new Error( 'unexpected type in AST: ' + typeof node ); |
537 | | - } |
538 | | - return ret; |
539 | | - }; |
540 | | - |
541 | | - }; |
542 | | - |
543 | | - // For everything in input that follows double-open-curly braces, there should be an equivalent parser |
544 | | - // function. For instance {{PLURAL ... }} will be processed by 'plural'. |
545 | | - // If you have 'magic words' then configure the parser to have them upon creation. |
546 | | - // |
547 | | - // An emitter method takes the parent node, the array of subnodes and the array of replacements (the values that $1, $2... should translate to). |
548 | | - // Note: all such functions must be pure, with the exception of referring to other pure functions via this.language (convertPlural and so on) |
549 | | - mw.language.htmlEmitter.prototype = { |
550 | | - |
551 | | - /** |
552 | | - * Parsing has been applied depth-first we can assume that all nodes here are single nodes |
553 | | - * Must return a single node to parents -- a jQuery with synthetic span |
554 | | - * However, unwrap any other synthetic spans in our children and pass them upwards |
555 | | - * @param {Array} nodes - mixed, some single nodes, some arrays of nodes |
556 | | - * @return {jQuery} |
557 | | - */ |
558 | | - concat: function( nodes ) { |
559 | | - var span = $j( '<span>' ).addClass( 'mediaWiki_htmlEmitter' ); |
560 | | - $j.each( nodes, function( i, node ) { |
561 | | - if ( node instanceof jQuery && node.hasClass( 'mediaWiki_htmlEmitter' ) ) { |
562 | | - $j.each( node.contents(), function( j, childNode ) { |
563 | | - span.append( childNode ); |
564 | | - } ); |
565 | | - } else { |
566 | | - // strings, integers, anything else |
567 | | - span.append( node ); |
568 | | - } |
569 | | - } ); |
570 | | - return span; |
571 | | - }, |
572 | | - |
573 | | - /** |
574 | | - * Return replacement of correct index, or string if unavailable. |
575 | | - * Note that we expect the parsed parameter to be zero-based. i.e. $1 should have become [ 0 ]. |
576 | | - * if the specified parameter is not found return the same string |
577 | | - * (e.g. "$99" -> parameter 98 -> not found -> return "$99" ) |
578 | | - * TODO throw error if nodes.length > 1 ? |
579 | | - * @param {Array} of one element, integer, n >= 0 |
580 | | - * @return {String} replacement |
581 | | - */ |
582 | | - replace: function( nodes, replacements ) { |
583 | | - var index = parseInt( nodes[0], 10 ); |
584 | | - return index < replacements.length ? replacements[index] : '$' + ( index + 1 ); |
585 | | - }, |
586 | | - |
587 | | - /** |
588 | | - * Transform wiki-link |
589 | | - * TODO unimplemented |
590 | | - */ |
591 | | - wlink: function( nodes ) { |
592 | | - return "unimplemented"; |
593 | | - }, |
594 | | - |
595 | | - /** |
596 | | - * Transform parsed structure into external link |
597 | | - * If the href is a jQuery object, treat it as "enclosing" the link text. |
598 | | - * ... function, treat it as the click handler |
599 | | - * ... string, treat it as a URI |
600 | | - * TODO: throw an error if nodes.length > 2 ? |
601 | | - * @param {Array} of two elements, {jQuery|Function|String} and {String} |
602 | | - * @return {jQuery} |
603 | | - */ |
604 | | - link: function( nodes ) { |
605 | | - var arg = nodes[0]; |
606 | | - var contents = nodes[1]; |
607 | | - var $el; |
608 | | - if ( arg instanceof jQuery ) { |
609 | | - $el = arg; |
610 | | - } else { |
611 | | - $el = $j( '<a>' ); |
612 | | - if ( typeof arg === 'function' ) { |
613 | | - $el.click( arg ).attr( 'href', '#' ); |
614 | | - } else { |
615 | | - $el.attr( 'href', arg.toString() ); |
616 | | - } |
617 | | - } |
618 | | - $el.append( contents ); |
619 | | - return $el; |
620 | | - }, |
621 | | - |
622 | | - /** |
623 | | - * Transform parsed structure into pluralization |
624 | | - * n.b. The first node may be a non-integer (for instance, a string representing an Arabic number). |
625 | | - * So convert it back with the current language's convertNumber. |
626 | | - * @param {Array} of nodes, [ {String|Number}, {String}, {String} ... ] |
627 | | - * @return {String} selected pluralized form according to current language |
628 | | - */ |
629 | | - plural: function( nodes ) { |
630 | | - var count = parseInt( this.language.convertNumber( nodes[0], true ), 10 ); |
631 | | - var forms = nodes.slice(1); |
632 | | - return forms.length ? this.language.convertPlural( count, forms ) : ''; |
633 | | - } |
634 | | - |
635 | | - }; |
636 | | - |
637 | | - |
638 | | -} )( mediaWiki, jQuery ); |
Index: trunk/extensions/UploadWizard/UploadWizardPage.js |
— | — | @@ -20,12 +20,5 @@ |
21 | 21 | }; |
22 | 22 | |
23 | 23 | jQuery( document ).ready( function() { |
24 | | - // add "magic" to Language template parser for keywords |
25 | | - var options = { magic: { 'SITENAME' : wgSiteName } }; |
26 | | - |
27 | | - window.gM = mediaWiki.language.getMessageFunction( options ); |
28 | | - $j.fn.msg = mediaWiki.language.getJqueryMessagePlugin( options ); |
29 | | - |
30 | | - // show page. |
31 | 24 | mw.UploadWizardPage(); |
32 | 25 | } ); |