Skip to content

Commit db2651b

Browse files
refactor: remove unnecessary stuff
1 parent 190f9bc commit db2651b

File tree

2 files changed

+76
-63
lines changed

2 files changed

+76
-63
lines changed

src/__tests__/exceptions.js

+28-15
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,40 @@
11
import {throws} from './util/helpers';
22

33
// Unclosed elements
4-
throws('unclosed string', 'a[href="wow]');
5-
throws('unclosed comment', '/* oops');
6-
throws('unclosed pseudo element', 'button::');
7-
throws('unclosed pseudo class', 'a:');
8-
throws('unclosed attribute selector', '[name="james"][href');
4+
throws('unclosed string', 'a[href="wow]', 'Unclosed quote');
5+
throws('unclosed comment', '/* oops', 'Unclosed comment');
6+
throws('unclosed pseudo element', 'button::', 'Expected a pseudo-class or pseudo-element.');
7+
throws('unclosed pseudo class', 'a:', 'Expected a pseudo-class or pseudo-element.');
8+
throws('unclosed attribute selector', '[name', 'Expected a closing square bracket.');
9+
throws('unclosed attribute selector (2)', '[name=', 'Expected a closing square bracket.');
10+
throws('unclosed attribute selector (3)', '[name="james"', 'Expected a closing square bracket.');
11+
throws('unclosed attribute selector (4)', '[name="james"][href', 'Expected a closing square bracket.');
12+
throws('unclosed attribute selector (5)', '[name="james"][href', 'Expected a closing square bracket.');
913

10-
throws('no opening parenthesis', ')');
11-
throws('no opening parenthesis (2)', ':global.foo)');
12-
throws('no opening parenthesis (3)', 'h1:not(h2:not(h3)))');
14+
throws('invalid attribute selector', '[]', 'Expected an attribute.');
15+
throws('invalid attribute selector (2)', '["hello"]', 'Expected an attribute.');
16+
throws('invalid attribute selector (3)', '[="hello"]', 'Expected an attribute, found "=" instead.');
1317

14-
throws('no opening square bracket', ']');
15-
throws('no opening square bracket (2)', ':global.foo]');
16-
throws('no opening square bracket (3)', '[global]]');
18+
throws('no opening parenthesis', ')', 'Expected an opening parenthesis.');
19+
throws('no opening parenthesis (2)', ':global.foo)', 'Expected an opening parenthesis.');
20+
throws('no opening parenthesis (3)', 'h1:not(h2:not(h3)))', 'Expected an opening parenthesis.');
1721

18-
throws('bad pseudo element', 'button::"after"');
19-
throws('missing closing parenthesis in pseudo', ':not([attr="test"]:not([attr="test"])');
22+
throws('no opening square bracket', ']', 'Expected an opening square bracket.');
23+
throws('no opening square bracket (2)', ':global.foo]', 'Expected an opening square bracket.');
24+
throws('no opening square bracket (3)', '[global]]', 'Expected an opening square bracket.');
2025

21-
throws('bad syntax', '-moz-osx-font-smoothing: grayscale');
22-
throws('bad syntax (2)', '! .body');
26+
throws('bad pseudo element', 'button::"after"', 'Expected a pseudo-class or pseudo-element.');
27+
throws('missing closing parenthesis in pseudo', ':not([attr="test"]:not([attr="test"])', 'Expected a closing parenthesis.');
28+
29+
throws('bad syntax', '-moz-osx-font-smoothing: grayscale', 'Expected a pseudo-class or pseudo-element.');
30+
throws('bad syntax (2)', '! .body', 'Unexpected \'!\'. Escaping special characters with \\ may help.');
2331

2432
throws('missing backslash for semicolon', '.;');
2533
throws('missing backslash for semicolon (2)', '.\;');
2634
throws('unexpected / foo', '-Option\/root', "Unexpected '/'. Escaping special characters with \\ may help.");
2735
throws('bang in selector', '.foo !optional', "Unexpected '!'. Escaping special characters with \\ may help.");
36+
37+
throws('misplaced parenthesis', ':not(', 'Expected a closing parenthesis.');
38+
throws('misplaced parenthesis (2)', ':not)', 'Expected an opening parenthesis.');
39+
throws('misplaced parenthesis (3)', ':not((', 'Expected a closing parenthesis.');
40+
throws('misplaced parenthesis (4)', ':not))', 'Expected an opening parenthesis.');

src/parser.js

+48-48
Original file line numberDiff line numberDiff line change
@@ -144,11 +144,18 @@ export default class Parser {
144144
attr.push(this.currToken);
145145
this.position ++;
146146
}
147-
if (this.currToken[TOKEN.TYPE] !== tokens.closeSquare) {
148-
return this.expected('closing square bracket', this.currToken[TOKEN.START_POS]);
147+
148+
if (!this.currToken) {
149+
this.position --;
150+
return this.missingClosingSquareBracket();
149151
}
150152

151153
const len = attr.length;
154+
155+
if (len === 0) {
156+
return this.expected('attribute', this.currToken[TOKEN.START_POS]);
157+
}
158+
152159
const node = {
153160
source: getSource(
154161
startingToken[1],
@@ -465,8 +472,7 @@ export default class Parser {
465472
if (rawSpace === space) {
466473
rawSpace = undefined;
467474
}
468-
let result = {space, rawSpace};
469-
return result;
475+
return {space, rawSpace};
470476
}
471477

472478
isNamedCombinator (position = this.position) {
@@ -475,30 +481,27 @@ export default class Parser {
475481
this.tokens[position + 2] && this.tokens[position + 2][TOKEN.TYPE] === tokens.slash;
476482

477483
}
484+
478485
namedCombinator () {
479-
if (this.isNamedCombinator()) {
480-
let nameRaw = this.content(this.tokens[this.position + 1]);
481-
let name = unesc(nameRaw).toLowerCase();
482-
let raws = {};
483-
if (name !== nameRaw) {
484-
raws.value = `/${nameRaw}/`;
485-
}
486-
let node = new Combinator({
487-
value: `/${name}/`,
488-
source: getSource(
489-
this.currToken[TOKEN.START_LINE],
490-
this.currToken[TOKEN.START_COL],
491-
this.tokens[this.position + 2][TOKEN.END_LINE],
492-
this.tokens[this.position + 2][TOKEN.END_COL],
493-
),
494-
sourceIndex: this.currToken[TOKEN.START_POS],
495-
raws,
496-
});
497-
this.position = this.position + 3;
498-
return node;
499-
} else {
500-
this.unexpected();
486+
let nameRaw = this.content(this.tokens[this.position + 1]);
487+
let name = unesc(nameRaw).toLowerCase();
488+
let raws = {};
489+
if (name !== nameRaw) {
490+
raws.value = `/${nameRaw}/`;
501491
}
492+
let node = new Combinator({
493+
value: `/${name}/`,
494+
source: getSource(
495+
this.currToken[TOKEN.START_LINE],
496+
this.currToken[TOKEN.START_COL],
497+
this.tokens[this.position + 2][TOKEN.END_LINE],
498+
this.tokens[this.position + 2][TOKEN.END_COL],
499+
),
500+
sourceIndex: this.currToken[TOKEN.START_POS],
501+
raws,
502+
});
503+
this.position = this.position + 3;
504+
return node;
502505
}
503506

504507
combinator () {
@@ -620,14 +623,22 @@ export default class Parser {
620623
});
621624
}
622625

623-
missingParenthesis () {
626+
missingOpeningParenthesis () {
624627
return this.expected('opening parenthesis', this.currToken[TOKEN.START_POS]);
625628
}
626629

627-
missingSquareBracket () {
630+
missingClosingParenthesis () {
631+
return this.expected('closing parenthesis', this.currToken[TOKEN.START_POS]);
632+
}
633+
634+
missingOpeningSquareBracket () {
628635
return this.expected('opening square bracket', this.currToken[TOKEN.START_POS]);
629636
}
630637

638+
missingClosingSquareBracket () {
639+
return this.expected('closing square bracket', this.currToken[TOKEN.START_POS]);
640+
}
641+
631642
unexpected () {
632643
return this.error(`Unexpected '${this.content()}'. Escaping special characters with \\ may help.`, this.currToken[TOKEN.START_POS]);
633644
}
@@ -702,6 +713,10 @@ export default class Parser {
702713
parenValue += this.parseParenthesisToken(this.currToken);
703714
this.position ++;
704715
}
716+
if (unbalanced) {
717+
this.position --;
718+
return this.missingClosingParenthesis();
719+
}
705720
if (last) {
706721
last.appendToPropertyAndEscape("value", parenValue, parenValue);
707722
} else {
@@ -718,7 +733,8 @@ export default class Parser {
718733
}
719734
}
720735
if (unbalanced) {
721-
return this.expected('closing parenthesis', this.currToken[TOKEN.START_POS]);
736+
this.position --;
737+
return this.missingClosingParenthesis();
722738
}
723739
}
724740

@@ -733,22 +749,13 @@ export default class Parser {
733749
return this.expected(['pseudo-class', 'pseudo-element'], this.position - 1);
734750
}
735751
if (this.currToken[TOKEN.TYPE] === tokens.word) {
736-
this.splitWord(false, (first, length) => {
752+
this.splitWord(false, (first) => {
737753
pseudoStr += first;
738754
this.newNode(new Pseudo({
739755
value: pseudoStr,
740756
source: getTokenSourceSpan(startingToken, this.currToken),
741757
sourceIndex: startingToken[TOKEN.START_POS],
742758
}));
743-
if (
744-
length > 1 &&
745-
this.nextToken &&
746-
this.nextToken[TOKEN.TYPE] === tokens.openParenthesis
747-
) {
748-
this.error('Misplaced parenthesis.', {
749-
index: this.nextToken[TOKEN.START_POS],
750-
});
751-
}
752759
});
753760
} else {
754761
return this.expected(['pseudo-class', 'pseudo-element'], this.currToken[TOKEN.START_POS]);
@@ -813,13 +820,6 @@ export default class Parser {
813820
this.position ++;
814821
let current = this.content();
815822
word += current;
816-
if (current.lastIndexOf('\\') === current.length - 1) {
817-
let next = this.nextToken;
818-
if (next && next[TOKEN.TYPE] === tokens.space) {
819-
word += this.requiredSpace(this.content(next));
820-
this.position ++;
821-
}
822-
}
823823
nextToken = this.nextToken;
824824
}
825825
const hasClass = indexesOf(word, '.').filter(i => word[i - 1] !== '\\');
@@ -905,7 +905,7 @@ export default class Parser {
905905
break;
906906
case tokens.closeParenthesis:
907907
if (throwOnParenthesis) {
908-
this.missingParenthesis();
908+
this.missingOpeningParenthesis();
909909
}
910910
break;
911911
case tokens.openSquare:
@@ -938,7 +938,7 @@ export default class Parser {
938938
break;
939939
// These cases throw; no break needed.
940940
case tokens.closeSquare:
941-
this.missingSquareBracket();
941+
this.missingOpeningSquareBracket();
942942
case tokens.semicolon:
943943
this.missingBackslash();
944944
default:

0 commit comments

Comments
 (0)