MediaWiki  1.23.13
CSSJanusTest.php
Go to the documentation of this file.
1 <?php
14  public function testTransform( $cssA, $cssB = null ) {
15 
16  if ( $cssB ) {
17  $transformedA = CSSJanus::transform( $cssA );
18  $this->assertEquals( $transformedA, $cssB, 'Test A-B transformation' );
19 
20  $transformedB = CSSJanus::transform( $cssB );
21  $this->assertEquals( $transformedB, $cssA, 'Test B-A transformation' );
22  } else {
23  // If no B version is provided, it means
24  // the output should equal the input.
25  $transformedA = CSSJanus::transform( $cssA );
26  $this->assertEquals( $transformedA, $cssA, 'Nothing was flipped' );
27  }
28  }
29 
33  public function testTransformAdvanced( $code, $expectedOutput, $options = array() ) {
34  $swapLtrRtlInURL = isset( $options['swapLtrRtlInURL'] ) ?
35  $options['swapLtrRtlInURL'] : false;
36  $swapLeftRightInURL = isset( $options['swapLeftRightInURL'] ) ?
37  $options['swapLeftRightInURL'] : false;
38 
39  $flipped = CSSJanus::transform( $code, $swapLtrRtlInURL, $swapLeftRightInURL );
40 
41  $this->assertEquals( $expectedOutput, $flipped,
42  'Test flipping, options: url-ltr-rtl=' . ( $swapLtrRtlInURL ? 'true' : 'false' )
43  . ' url-left-right=' . ( $swapLeftRightInURL ? 'true' : 'false' )
44  );
45  }
46 
51  public function testTransformBroken( $code, $expectedOutput ) {
52  $flipped = CSSJanus::transform( $code );
53 
54  $this->assertEquals( $expectedOutput, $flipped, 'Test flipping' );
55  }
56 
61  public static function provideTransformCases() {
62  return array(
63  // Property keys
64  array(
65  '.foo { left: 0; }',
66  '.foo { right: 0; }'
67  ),
68  // Guard against partial keys
69  // (CSS currently doesn't have flippable properties
70  // that contain the direction as part of the key without
71  // dash separation)
72  array(
73  '.foo { alright: 0; }'
74  ),
75  array(
76  '.foo { balleft: 0; }'
77  ),
78 
79  // Dashed property keys
80  array(
81  '.foo { padding-left: 0; }',
82  '.foo { padding-right: 0; }'
83  ),
84  array(
85  '.foo { margin-left: 0; }',
86  '.foo { margin-right: 0; }'
87  ),
88  array(
89  '.foo { border-left: 0; }',
90  '.foo { border-right: 0; }'
91  ),
92 
93  // Double-dashed property keys
94  array(
95  '.foo { border-left-color: red; }',
96  '.foo { border-right-color: red; }'
97  ),
98  array(
99  // Includes unknown properties?
100  '.foo { x-left-y: 0; }',
101  '.foo { x-right-y: 0; }'
102  ),
103 
104  // Multi-value properties
105  array(
106  '.foo { padding: 0; }'
107  ),
108  array(
109  '.foo { padding: 0 1px; }'
110  ),
111  array(
112  '.foo { padding: 0 1px 2px; }'
113  ),
114  array(
115  '.foo { padding: 0 1px 2px 3px; }',
116  '.foo { padding: 0 3px 2px 1px; }'
117  ),
118 
119  // Shorthand / Four notation
120  array(
121  '.foo { padding: .25em 15px 0pt 0ex; }',
122  '.foo { padding: .25em 0ex 0pt 15px; }'
123  ),
124  array(
125  '.foo { margin: 1px -4px 3px 2px; }',
126  '.foo { margin: 1px 2px 3px -4px; }'
127  ),
128  array(
129  '.foo { padding: 0 15px .25em 0; }',
130  '.foo { padding: 0 0 .25em 15px; }'
131  ),
132  array(
133  '.foo { padding: 1px 4.1grad 3px 2%; }',
134  '.foo { padding: 1px 2% 3px 4.1grad; }'
135  ),
136  array(
137  '.foo { padding: 1px 2px 3px auto; }',
138  '.foo { padding: 1px auto 3px 2px; }'
139  ),
140  array(
141  '.foo { padding: 1px inherit 3px auto; }',
142  '.foo { padding: 1px auto 3px inherit; }'
143  ),
144  // border-radius assigns different meanings to the values
145  array(
146  '.foo { border-radius: .25em 15px 0pt 0ex; }',
147  '.foo { border-radius: 15px .25em 0ex 0pt; }'
148  ),
149  array(
150  '.foo { border-radius: 0px 0px 5px 5px; }',
151  ),
152  // Ensure the rule doesn't break other stuff
153  array(
154  '.foo { x-unknown: a b c d; }'
155  ),
156  array(
157  '.foo barpx 0 2% { opacity: 0; }'
158  ),
159  array(
160  '#settings td p strong'
161  ),
162  array(
163  // Color names
164  '.foo { border-color: red green blue white }',
165  '.foo { border-color: red white blue green }',
166  ),
167  array(
168  // Color name, hexdecimal, RGB & RGBA
169  '.foo { border-color: red #f00 rgb(255, 0, 0) rgba(255, 0, 0, 0.5) }',
170  '.foo { border-color: red rgba(255, 0, 0, 0.5) rgb(255, 0, 0) #f00 }',
171  ),
172  array(
173  // Color name, hexdecimal, HSL & HSLA
174  '.foo { border-color: red #f00 hsl(0, 100%, 50%) hsla(0, 100%, 50%, 0.5) }',
175  '.foo { border-color: red hsla(0, 100%, 50%, 0.5) hsl(0, 100%, 50%) #f00 }',
176  ),
177  array(
178  // Do not mangle 5 or more values
179  '.foo { -x-unknown: 1 2 3 4 5; }'
180  ),
181  array(
182  '.foo { -x-unknown: 1 2 3 4 5 6; }'
183  ),
184 
185  // Shorthand / Three notation
186  array(
187  '.foo { margin: 1em 0 .25em; }'
188  ),
189  array(
190  '.foo { margin:-1.5em 0 -.75em; }'
191  ),
192 
193  // Shorthand / Two notation
194  array(
195  '.foo { padding: 1px 2px; }'
196  ),
197 
198  // Shorthand / One notation
199  array(
200  '.foo { padding: 1px; }'
201  ),
202 
203  // text-shadow and box-shadow
204  array(
205  '.foo { box-shadow: -6px 3px 8px 5px rgba(0, 0, 0, 0.25); }',
206  '.foo { box-shadow: 6px 3px 8px 5px rgba(0, 0, 0, 0.25); }',
207  ),
208  array(
209  '.foo { box-shadow: inset -6px 3px 8px 5px rgba(0, 0, 0, 0.25); }',
210  '.foo { box-shadow: inset 6px 3px 8px 5px rgba(0, 0, 0, 0.25); }',
211  ),
212  array(
213  '.foo { text-shadow: orange 2px 0; }',
214  '.foo { text-shadow: orange -2px 0; }',
215  ),
216  array(
217  '.foo { text-shadow: 2px 0 orange; }',
218  '.foo { text-shadow: -2px 0 orange; }',
219  ),
220  array(
221  // Don't mangle zeroes
222  '.foo { text-shadow: orange 0 2px; }'
223  ),
224 
225  // Direction
226  // Note: This differs from the Python implementation,
227  // see also CSSJanus::fixDirection for more info.
228  array(
229  '.foo { direction: ltr; }',
230  '.foo { direction: rtl; }'
231  ),
232  array(
233  '.foo { direction: rtl; }',
234  '.foo { direction: ltr; }'
235  ),
236  array(
237  'input { direction: ltr; }',
238  'input { direction: rtl; }'
239  ),
240  array(
241  'input { direction: rtl; }',
242  'input { direction: ltr; }'
243  ),
244  array(
245  'body { direction: ltr; }',
246  'body { direction: rtl; }'
247  ),
248  array(
249  '.foo, body, input { direction: ltr; }',
250  '.foo, body, input { direction: rtl; }'
251  ),
252  array(
253  'body { padding: 10px; direction: ltr; }',
254  'body { padding: 10px; direction: rtl; }'
255  ),
256  array(
257  'body { direction: ltr } .myClass { direction: ltr }',
258  'body { direction: rtl } .myClass { direction: rtl }'
259  ),
260 
261  // Left/right values
262  array(
263  '.foo { float: left; }',
264  '.foo { float: right; }'
265  ),
266  array(
267  '.foo { text-align: left; }',
268  '.foo { text-align: right; }'
269  ),
270  array(
271  '.foo { -x-unknown: left; }',
272  '.foo { -x-unknown: right; }'
273  ),
274  // Guard against selectors that look flippable
275  array(
276  '.column-left { width: 0; }'
277  ),
278  array(
279  'a.left { width: 0; }'
280  ),
281  array(
282  'a.leftification { width: 0; }'
283  ),
284  array(
285  'a.ltr { width: 0; }'
286  ),
287  array(
288  # <div class="a-ltr png">
289  '.a-ltr.png { width: 0; }'
290  ),
291  array(
292  # <foo-ltr attr="x">
293  'foo-ltr[attr="x"] { width: 0; }'
294  ),
295  array(
296  'div.left > span.right+span.left { width: 0; }'
297  ),
298  array(
299  '.thisclass .left .myclass { width: 0; }'
300  ),
301  array(
302  '.thisclass .left .myclass #myid { width: 0; }'
303  ),
304 
305  // Cursor values (east/west)
306  array(
307  '.foo { cursor: e-resize; }',
308  '.foo { cursor: w-resize; }'
309  ),
310  array(
311  '.foo { cursor: se-resize; }',
312  '.foo { cursor: sw-resize; }'
313  ),
314  array(
315  '.foo { cursor: ne-resize; }',
316  '.foo { cursor: nw-resize; }'
317  ),
318 
319  // Background
320  array(
321  '.foo { background-position: top left; }',
322  '.foo { background-position: top right; }'
323  ),
324  array(
325  '.foo { background: url(/foo/bar.png) top left; }',
326  '.foo { background: url(/foo/bar.png) top right; }'
327  ),
328  array(
329  '.foo { background: url(/foo/bar.png) top left no-repeat; }',
330  '.foo { background: url(/foo/bar.png) top right no-repeat; }'
331  ),
332  array(
333  '.foo { background: url(/foo/bar.png) no-repeat top left; }',
334  '.foo { background: url(/foo/bar.png) no-repeat top right; }'
335  ),
336  array(
337  '.foo { background: #fff url(/foo/bar.png) no-repeat top left; }',
338  '.foo { background: #fff url(/foo/bar.png) no-repeat top right; }'
339  ),
340  array(
341  '.foo { background-position: 100% 40%; }',
342  '.foo { background-position: 0% 40%; }'
343  ),
344  array(
345  '.foo { background-position: 23% 0; }',
346  '.foo { background-position: 77% 0; }'
347  ),
348  array(
349  '.foo { background-position: 23% auto; }',
350  '.foo { background-position: 77% auto; }'
351  ),
352  array(
353  '.foo { background-position-x: 23%; }',
354  '.foo { background-position-x: 77%; }'
355  ),
356  array(
357  '.foo { background-position-y: 23%; }',
358  '.foo { background-position-y: 23%; }'
359  ),
360  array(
361  '.foo { background:url(../foo.png) no-repeat 75% 50%; }',
362  '.foo { background:url(../foo.png) no-repeat 25% 50%; }'
363  ),
364  array(
365  '.foo { background: 10% 20% } .bar { background: 40% 30% }',
366  '.foo { background: 90% 20% } .bar { background: 60% 30% }'
367  ),
368 
369  // Multiple rules
370  array(
371  'body { direction: rtl; float: right; } .foo { direction: ltr; float: right; }',
372  'body { direction: ltr; float: left; } .foo { direction: rtl; float: left; }',
373  ),
374 
375  // Duplicate properties
376  array(
377  '.foo { float: left; float: right; float: left; }',
378  '.foo { float: right; float: left; float: right; }',
379  ),
380 
381  // Preserve comments
382  array(
383  '/* left /* right */left: 10px',
384  '/* left /* right */right: 10px'
385  ),
386  array(
387  '/*left*//*left*/left: 10px',
388  '/*left*//*left*/right: 10px'
389  ),
390  array(
391  '/* Going right is cool */ .foo { width: 0 }',
392  ),
393  array(
394  "/* padding-right 1 2 3 4 */\n#test { width: 0}\n/*right*/"
395  ),
396  array(
397  "/** Two line comment\n * left\n \*/\n#test {width: 0}"
398  ),
399 
400  // @noflip annotation
401  array(
402  // before selector (single)
403  '/* @noflip */ div { float: left; }'
404  ),
405  array(
406  // before selector (multiple)
407  '/* @noflip */ div, .notme { float: left; }'
408  ),
409  array(
410  // inside selector
411  'div, /* @noflip */ .foo { float: left; }'
412  ),
413  array(
414  // after selector
415  'div, .notme /* @noflip */ { float: left; }'
416  ),
417  array(
418  // before multiple rules
419  '/* @noflip */ div { float: left; } .foo { float: left; }',
420  '/* @noflip */ div { float: left; } .foo { float: right; }'
421  ),
422  array(
423  // support parentheses in selector
424  '/* @noflip */ .test:not(:first) { margin-right: -0.25em; margin-left: 0.25em; }',
425  '/* @noflip */ .test:not(:first) { margin-right: -0.25em; margin-left: 0.25em; }'
426  ),
427  array(
428  // after multiple rules
429  '.foo { float: left; } /* @noflip */ div { float: left; }',
430  '.foo { float: right; } /* @noflip */ div { float: left; }'
431  ),
432  array(
433  // before multiple properties
434  'div { /* @noflip */ float: left; text-align: left; }',
435  'div { /* @noflip */ float: left; text-align: right; }'
436  ),
437  array(
438  // after multiple properties
439  'div { float: left; /* @noflip */ text-align: left; }',
440  'div { float: right; /* @noflip */ text-align: left; }'
441  ),
442  array(
443  // before a *= attribute selector with multiple properties
444  '/* @noflip */ div.foo[bar*=baz] { float:left; clear: left; }'
445  ),
446  array(
447  // before a ^= attribute selector with multiple properties
448  '/* @noflip */ div.foo[bar^=baz] { float:left; clear: left; }'
449  ),
450  array(
451  // before a ~= attribute selector with multiple properties
452  '/* @noflip */ div.foo[bar~=baz] { float:left; clear: left; }'
453  ),
454  array(
455  // before a = attribute selector with multiple properties
456  '/* @noflip */ div.foo[bar=baz] { float:left; clear: left; }'
457  ),
458  array(
459  // before a quoted attribute selector with multiple properties
460  '/* @noflip */ div.foo[bar=\'baz{quux\'] { float:left; clear: left; }'
461  ),
462 
463  // Guard against css3 stuff
464  array(
465  'background-image: -moz-linear-gradient(#326cc1, #234e8c);'
466  ),
467  array(
468  'background-image: -webkit-gradient(linear, 100% 0%, 0% 0%, from(#666666), to(#ffffff));'
469  ),
470 
471  // CSS syntax / white-space variations
472  // spaces, no spaces, tabs, new lines, omitting semi-colons
473  array(
474  ".foo { left: 0; }",
475  ".foo { right: 0; }"
476  ),
477  array(
478  ".foo{ left: 0; }",
479  ".foo{ right: 0; }"
480  ),
481  array(
482  ".foo{ left: 0 }",
483  ".foo{ right: 0 }"
484  ),
485  array(
486  ".foo{left:0 }",
487  ".foo{right:0 }"
488  ),
489  array(
490  ".foo{left:0}",
491  ".foo{right:0}"
492  ),
493  array(
494  ".foo { left : 0 ; }",
495  ".foo { right : 0 ; }"
496  ),
497  array(
498  ".foo\n { left : 0 ; }",
499  ".foo\n { right : 0 ; }"
500  ),
501  array(
502  ".foo\n { \nleft : 0 ; }",
503  ".foo\n { \nright : 0 ; }"
504  ),
505  array(
506  ".foo\n { \n left : 0 ; }",
507  ".foo\n { \n right : 0 ; }"
508  ),
509  array(
510  ".foo\n { \n left\n : 0; }",
511  ".foo\n { \n right\n : 0; }"
512  ),
513  array(
514  ".foo \n { \n left\n : 0; }",
515  ".foo \n { \n right\n : 0; }"
516  ),
517  array(
518  ".foo\n{\nleft\n:\n0;}",
519  ".foo\n{\nright\n:\n0;}"
520  ),
521  array(
522  ".foo\n.bar {\n\tleft: 0;\n}",
523  ".foo\n.bar {\n\tright: 0;\n}"
524  ),
525  array(
526  ".foo\t{\tleft\t:\t0;}",
527  ".foo\t{\tright\t:\t0;}"
528  ),
529 
530  // Guard against partial keys
531  array(
532  '.foo { leftxx: 0; }',
533  '.foo { leftxx: 0; }'
534  ),
535  array(
536  '.foo { rightxx: 0; }',
537  '.foo { rightxx: 0; }'
538  ),
539  );
540  }
541 
547  public static function provideTransformAdvancedCases() {
548  $bgPairs = array(
549  # [ - _ . ] <-> [ left right ltr rtl ]
550  'foo.jpg' => 'foo.jpg',
551  'left.jpg' => 'right.jpg',
552  'ltr.jpg' => 'rtl.jpg',
553 
554  'foo-left.png' => 'foo-right.png',
555  'foo_left.png' => 'foo_right.png',
556  'foo.left.png' => 'foo.right.png',
557 
558  'foo-ltr.png' => 'foo-rtl.png',
559  'foo_ltr.png' => 'foo_rtl.png',
560  'foo.ltr.png' => 'foo.rtl.png',
561 
562  'left-foo.png' => 'right-foo.png',
563  'left_foo.png' => 'right_foo.png',
564  'left.foo.png' => 'right.foo.png',
565 
566  'ltr-foo.png' => 'rtl-foo.png',
567  'ltr_foo.png' => 'rtl_foo.png',
568  'ltr.foo.png' => 'rtl.foo.png',
569 
570  'foo-ltr-left.gif' => 'foo-rtl-right.gif',
571  'foo_ltr_left.gif' => 'foo_rtl_right.gif',
572  'foo.ltr.left.gif' => 'foo.rtl.right.gif',
573  'foo-ltr_left.gif' => 'foo-rtl_right.gif',
574  'foo_ltr.left.gif' => 'foo_rtl.right.gif',
575  );
576  $provider = array();
577  foreach ( $bgPairs as $left => $right ) {
578  # By default '-rtl' and '-left' etc. are not touched,
579  # Only when the appropiate parameter is set.
580  $provider[] = array(
581  ".foo { background: url(images/$left); }",
582  ".foo { background: url(images/$left); }"
583  );
584  $provider[] = array(
585  ".foo { background: url(images/$right); }",
586  ".foo { background: url(images/$right); }"
587  );
588  $provider[] = array(
589  ".foo { background: url(images/$left); }",
590  ".foo { background: url(images/$right); }",
591  array(
592  'swapLtrRtlInURL' => true,
593  'swapLeftRightInURL' => true,
594  )
595  );
596  $provider[] = array(
597  ".foo { background: url(images/$right); }",
598  ".foo { background: url(images/$left); }",
599  array(
600  'swapLtrRtlInURL' => true,
601  'swapLeftRightInURL' => true,
602  )
603  );
604  }
605 
606  return $provider;
607  }
608 
613  public static function provideTransformBrokenCases() {
614  return array(
615  // Guard against selectors that look flippable
616  array(
617  # <foo-left-x attr="x">
618  'foo-left-x[attr="x"] { width: 0; }',
619  'foo-left-x[attr="x"] { width: 0; }'
620  ),
621  array(
622  # <div class="foo" data-left="x">
623  '.foo[data-left="x"] { width: 0; }',
624  '.foo[data-left="x"] { width: 0; }'
625  ),
626  );
627  }
628 }
data
and how to run hooks for an and one after Each event has a preferably in CamelCase For ArticleDelete hook A clump of code and data that should be run when an event happens This can be either a function and a chunk of data
Definition: hooks.txt:6
php
skin txt MediaWiki includes four core it has been set as the default in MediaWiki since the replacing Monobook it had been been the default skin since before being replaced by Vector largely rewritten in while keeping its appearance Several legacy skins were removed in the as the burden of supporting them became too heavy to bear Those in etc for skin dependent CSS etc for skin dependent JavaScript These can also be customised on a per user by etc This feature has led to a wide variety of user styles becoming that gallery is a good place to ending in php
Definition: skin.txt:62
CSSJanusTest\testTransform
testTransform( $cssA, $cssB=null)
@dataProvider provideTransformCases
Definition: CSSJanusTest.php:14
$right
return false if a UserGetRights hook might remove the named right $right
Definition: hooks.txt:2803
CSSJanusTest\provideTransformAdvancedCases
static provideTransformAdvancedCases()
These cases are tested in one way only (format: actual, expected, msg).
Definition: CSSJanusTest.php:547
MediaWikiTestCase
Definition: MediaWikiTestCase.php:6
array
the array() calling protocol came about after MediaWiki 1.4rc1.
List of Api Query prop modules.
CSSJanusTest\provideTransformCases
static provideTransformCases()
These transform cases are tested in both directions No need to declare a principle twice in both dire...
Definition: CSSJanusTest.php:61
$options
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped & $options
Definition: hooks.txt:1530
CSSJanusTest
Based on the test suite of the original Python CSSJanus libary: http://code.google....
Definition: CSSJanusTest.php:10
as
This document is intended to provide useful advice for parties seeking to redistribute MediaWiki to end users It s targeted particularly at maintainers for Linux since it s been observed that distribution packages of MediaWiki often break We ve consistently had to recommend that users seeking support use official tarballs instead of their distribution s and this often solves whatever problem the user is having It would be nice if this could such as
Definition: distributors.txt:9
CSSJanus\transform
static transform( $css, $swapLtrRtlInURL=false, $swapLeftRightInURL=false)
Transform an LTR stylesheet to RTL.
Definition: CSSJanus.php:139
CSSJanusTest\testTransformAdvanced
testTransformAdvanced( $code, $expectedOutput, $options=array())
@dataProvider provideTransformAdvancedCases
Definition: CSSJanusTest.php:33
CSSJanusTest\testTransformBroken
testTransformBroken( $code, $expectedOutput)
@dataProvider provideTransformBrokenCases @group Broken
Definition: CSSJanusTest.php:51
CSSJanusTest\provideTransformBrokenCases
static provideTransformBrokenCases()
Cases that are currently failing, but should be looked at in the future as enhancements and/or bug fi...
Definition: CSSJanusTest.php:613