Skip to content

Commit 70b4a24

Browse files
committed
revert #98, fix #99, add sanity tests
1 parent 80c5d1d commit 70b4a24

File tree

6 files changed

+252
-53
lines changed

6 files changed

+252
-53
lines changed

lib/less-parser.js

+5
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,11 @@ export default class LessParser extends Parser {
316316
}
317317
}
318318

319+
// we don't want to add params for pseudo-selectors that utilize parens (#56)
320+
// if ((extend || !colon) && (brackets.length > 0 || type === 'brackets' || params[0])) {
321+
// params.push(token);
322+
// }
323+
319324
// we don't want to add params for pseudo-selectors that utilize parens (#56) or bracket selectors (#96)
320325
if ((extend || !colon) && (brackets.length > 0 || type === 'brackets' || params[0]) && brackets[0] !== ']') {
321326
params.push(token);

lib/tokenizer/tokenize-at-rule.js

-5
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,10 @@ export default function tokenizeAtRule (state) {
3535
else {
3636
atEndPattern.lastIndex = state.pos + 1;
3737
atEndPattern.test(state.css);
38-
const spaceColonPos = state.css.indexOf(' :', state.pos);
3938

4039
if (atEndPattern.lastIndex === 0) {
4140
state.nextPos = state.css.length - 1;
4241
}
43-
// for cases where there is extra whitespace between a variable name and ":" (#92)
44-
else if (spaceColonPos > state.pos && state.css.slice(state.pos, state.pos + 5) !== "@page") {
45-
state.nextPos = spaceColonPos + 1;
46-
}
4742
else {
4843
state.nextPos = atEndPattern.lastIndex - 2;
4944
}
+179
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
@import '../../widgets/common/ext.cx.common.less';
2+
@import 'mediawiki.mixins';
3+
4+
.cx-dashboard {
5+
color: @colorGray2;
6+
max-width: @max-dashboard-width;
7+
margin: 0 auto;
8+
padding: 10px 40px 20px;
9+
10+
@media only screen and ( max-width: ( @narrow - 1px ) ) {
11+
padding: 10px 24px 20px;
12+
}
13+
14+
@media only screen and ( max-width: ( @very-narrow - 1px ) ) {
15+
padding: 10px 12px 20px;
16+
}
17+
18+
/* Clearfix */
19+
&:after {
20+
// Non empty content value avoids an Opera bug that creates space around
21+
// clearfixed elements if the contenteditable attribute is also present
22+
// somewhere in the HTML.
23+
content: ' ';
24+
visibility: hidden;
25+
display: block;
26+
height: 0;
27+
clear: both;
28+
}
29+
}
30+
31+
.cx-dashboard-sidebar {
32+
// Separation between sidebar (which is at the bottom on smaller screen sizes)
33+
// and bottom of the document should be 48px.
34+
// Dashboard has 20px bottom padding, and with adding 28px for bottom margin, we get desired 48px
35+
margin-bottom: 28px;
36+
line-height: 1;
37+
38+
@media only screen and ( min-width: @wide ) {
39+
.mw-ui-one-third;
40+
padding: 0 0 0 30px;
41+
42+
position: -webkit-sticky;
43+
position: sticky;
44+
top: 10px;
45+
}
46+
47+
ul {
48+
margin: 0;
49+
50+
li {
51+
list-style: none;
52+
margin: 0;
53+
54+
// Following styles should support possible additions to help card
55+
&:not( :last-child ) {
56+
margin-bottom: 16px;
57+
}
58+
59+
&:first-child {
60+
padding-top: 4px;
61+
}
62+
63+
&:last-child {
64+
padding-bottom: 4px;
65+
}
66+
}
67+
}
68+
69+
&__link,
70+
&__link:visited {
71+
background-position: center left;
72+
background-repeat: no-repeat;
73+
background-size: 16px;
74+
color: @colorProgressive;
75+
padding-left: 24px;
76+
}
77+
78+
&__link {
79+
&--information {
80+
.background-image-svg('../images/cx-information.svg', '../images/cx-information.png');
81+
}
82+
83+
&--stats {
84+
.background-image-svg('../images/cx-stats.svg', '../images/cx-stats.png');
85+
}
86+
87+
&--feedback {
88+
.background-image-svg('../images/cx-discuss.svg', '../images/cx-discuss.png');
89+
}
90+
}
91+
92+
&__help {
93+
background-color: #fff;
94+
.box-sizing( border-box );
95+
border-radius: @borderRadius;
96+
padding: 16px;
97+
.box-shadow-card;
98+
font-size: 16px;
99+
100+
.cx-translator--visible ~ & {
101+
@media only screen and ( min-width: @narrow ) and ( max-width: ( @wide - 1px ) ) {
102+
display: inline-block;
103+
width: 47.5%;
104+
margin-left: 5%;
105+
vertical-align: top;
106+
}
107+
}
108+
109+
&-title {
110+
color: @colorGray5;
111+
margin-bottom: 16px;
112+
font-weight: bold;
113+
}
114+
}
115+
}
116+
117+
.cx-translationlist-container {
118+
background-color: @colorGray14;
119+
margin-bottom: 48px;
120+
padding: 0;
121+
122+
@media only screen and ( min-width: @wide ) {
123+
.mw-ui-two-thirds;
124+
padding: 0;
125+
// This is needed so sidebar doesn't wiggle
126+
width: 66.667%;
127+
}
128+
}
129+
130+
.translation-filter {
131+
background-color: @colorGray14;
132+
padding: 10px 5px 20px 5px;
133+
margin: -10px -5px 0 -5px;
134+
position: -webkit-sticky;
135+
position: sticky;
136+
top: 0;
137+
z-index: 1;
138+
139+
.flex-center-justify;
140+
141+
> .oo-ui-buttonWidget > .oo-ui-buttonElement-button {
142+
height: 2.34375em;
143+
padding-right: 0.46875em;
144+
145+
@media only screen and ( min-width: 380px ) {
146+
height: auto;
147+
padding-right: 0.9375em;
148+
}
149+
150+
> .oo-ui-labelElement-label {
151+
// Hide text and show only '+' icon on "New translation" button for screen sizes below 380px
152+
display: none;
153+
154+
@media only screen and ( min-width: 380px ) {
155+
display: inline;
156+
}
157+
}
158+
}
159+
}
160+
161+
.oo-ui-popupWidget {
162+
// We need popup widgets to stay above .translation-filter
163+
z-index: 2;
164+
}
165+
166+
.cx-header-infobar {
167+
float: none;
168+
max-width: @max-dashboard-width;
169+
margin: 0 auto;
170+
padding: 0 40px;
171+
172+
@media only screen and ( max-width: ( @narrow - 1px ) ) {
173+
padding: 0 24px;
174+
}
175+
176+
@media only screen and ( max-width: ( @very-narrow - 1px ) ) {
177+
padding: 0 12px;
178+
}
179+
}

test/parser/params.spec.js

+8-1
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,20 @@ describe('Parser', () => {
1515
expect(root.first.params).to.be.undefined;
1616
});
1717

18+
// sanity check from issue #99
19+
it('should not assign parameters for bracket selectors', () => {
20+
const code = '@media only screen and ( max-width: ( @narrow - 1px ) ) {\n padding: 10px 24px 20px;\n}';
21+
const root = parse(code);
22+
23+
expect(root.first.type).to.eql('atrule');
24+
});
25+
1826
it('should not assign parameters for bracket selectors', () => {
1927
const code = '.test1,.test2[test=test] {}';
2028
const root = parse(code);
2129

2230
expect(root.first.selector).to.eql('.test1,.test2[test=test]');
2331
expect(root.first.params).to.be.undefined;
2432
});
25-
2633
});
2734
});

test/parser/variables.spec.js

+41-28
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// chai uses expressions for validation
22
/* eslint no-unused-expressions: 0 */
33

4+
import * as fs from 'fs';
5+
import * as path from 'path';
46
import { expect } from 'chai';
57
import parse from '../../lib/less-parse';
68

@@ -13,37 +15,48 @@ describe('Parser', () => {
1315
expect(root.first.value).to.eql('1');
1416
});
1517

16-
it('parses variables with whitespaces between name and ":"', () => {
17-
let root = parse('@onespace : 42;');
18-
19-
expect(root.first.prop).to.eql('@onespace');
20-
expect(root.first.value).to.eql('42');
21-
});
22-
23-
it('parses variables with no whitespace between ":" and value', () => {
24-
const root = parse('@var :42;');
25-
26-
expect(root.first.prop).to.eql('@var');
27-
expect(root.first.value).to.eql('42');
28-
});
29-
30-
it('parses mutliple variables with whitespaces between name and ":"', () => {
31-
const root = parse('@foo : 42; @bar : 35;');
18+
// sanity check from issue #99
19+
it('should not fail wikimedia sanity check', () => {
20+
const code = fs.readFileSync(path.join(__dirname, '../../../test/integration/ext.cx.dashboard.less'), 'utf-8');
21+
const root = parse(code);
3222

33-
expect(root.first.prop).to.eql('@foo');
34-
expect(root.first.value).to.eql('42');
35-
expect(root.nodes[1].prop).to.eql('@bar');
36-
expect(root.nodes[1].value).to.eql('35');
23+
expect(root.first.type).to.eql('import');
3724
});
3825

39-
it('parses multiple variables with no whitespace between ":" and value', () => {
40-
const root = parse('@foo :42; @bar :35');
41-
42-
expect(root.first.prop).to.eql('@foo');
43-
expect(root.first.value).to.eql('42');
44-
expect(root.nodes[1].prop).to.eql('@bar');
45-
expect(root.nodes[1].value).to.eql('35');
46-
});
26+
// #98 was merged to resolve this but broke other scenarios
27+
it('parses variables with whitespaces between name and ":"'); //, () => {
28+
// let root = parse('@onespace : 42;');
29+
//
30+
// expect(root.first.prop).to.eql('@onespace');
31+
// expect(root.first.value).to.eql('42');
32+
// });
33+
34+
// #98 was merged to resolve this but broke other scenarios
35+
// these tests are commented out until that is resolved
36+
it('parses variables with no whitespace between ":" and value'); //, () => {
37+
// const root = parse('@var :42;');
38+
//
39+
// expect(root.first.prop).to.eql('@var');
40+
// expect(root.first.value).to.eql('42');
41+
// });
42+
//
43+
it('parses mutliple variables with whitespaces between name and ":"'); //, () => {
44+
// const root = parse('@foo : 42; @bar : 35;');
45+
//
46+
// expect(root.first.prop).to.eql('@foo');
47+
// expect(root.first.value).to.eql('42');
48+
// expect(root.nodes[1].prop).to.eql('@bar');
49+
// expect(root.nodes[1].value).to.eql('35');
50+
// });
51+
//
52+
it('parses multiple variables with no whitespace between ":" and value'); //, () => {
53+
// const root = parse('@foo :42; @bar :35');
54+
//
55+
// expect(root.first.prop).to.eql('@foo');
56+
// expect(root.first.value).to.eql('42');
57+
// expect(root.nodes[1].prop).to.eql('@bar');
58+
// expect(root.nodes[1].value).to.eql('35');
59+
// });
4760

4861
it('parses string variables', () => {
4962
const root = parse('@var: "test";');

test/tokenize.spec.js

+19-19
Original file line numberDiff line numberDiff line change
@@ -169,24 +169,24 @@ describe('#tokenize()', () => {
169169
[')', ')', 1, 7]
170170
]);
171171
});
172-
173-
it('tokenizes @page with extra whitespace', () => {
174-
testTokens('@page :left { margin: 0; }', [
175-
[ 'at-word', '@page', 1, 1, 1, 5 ],
176-
[ 'space', ' ' ],
177-
[ ':', ':', 1, 9 ],
178-
[ 'word', 'left', 1, 10, 1, 13 ],
179-
[ 'space', ' ' ],
180-
[ '{', '{', 1, 15 ],
181-
[ 'space', ' ' ],
182-
[ 'word', 'margin', 1, 17, 1, 22 ],
183-
[ ':', ':', 1, 23 ],
184-
[ 'space', ' ' ],
185-
[ 'word', '0', 1, 25, 1, 25 ],
186-
[ ';', ';', 1, 26 ],
187-
[ 'space', ' ' ],
188-
[ '}', '}', 1, 28 ]
189-
]);
190-
});
172+
//
173+
// it('tokenizes @page with extra whitespace', () => {
174+
// testTokens('@page :left { margin: 0; }', [
175+
// [ 'at-word', '@page', 1, 1, 1, 5 ],
176+
// [ 'space', ' ' ],
177+
// [ ':', ':', 1, 9 ],
178+
// [ 'word', 'left', 1, 10, 1, 13 ],
179+
// [ 'space', ' ' ],
180+
// [ '{', '{', 1, 15 ],
181+
// [ 'space', ' ' ],
182+
// [ 'word', 'margin', 1, 17, 1, 22 ],
183+
// [ ':', ':', 1, 23 ],
184+
// [ 'space', ' ' ],
185+
// [ 'word', '0', 1, 25, 1, 25 ],
186+
// [ ';', ';', 1, 26 ],
187+
// [ 'space', ' ' ],
188+
// [ '}', '}', 1, 28 ]
189+
// ]);
190+
// });
191191
});
192192
});

0 commit comments

Comments
 (0)