Skip to content

Commit

Permalink
feat: add sourceIndex to Selector nodes (#290)
Browse files Browse the repository at this point in the history
  • Loading branch information
romainmenke authored May 22, 2024
1 parent b4c848e commit 6485caf
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 4 deletions.
2 changes: 1 addition & 1 deletion src/__tests__/node.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ test('Node#isAtPosition', (t) => {
let notSelector = pseudoNot.first;
t.deepEqual(notSelector.isAtPosition(1, 1), false);
t.deepEqual(notSelector.isAtPosition(1, 4), false);
t.deepEqual(notSelector.isAtPosition(1, 5), true);
t.deepEqual(notSelector.isAtPosition(1, 6), true);
t.deepEqual(notSelector.isAtPosition(1, 7), true);
t.deepEqual(notSelector.isAtPosition(1, 9), true);
t.deepEqual(notSelector.isAtPosition(1, 10), true);
t.deepEqual(notSelector.isAtPosition(1, 11), false);
Expand Down
67 changes: 67 additions & 0 deletions src/__tests__/sourceIndex.mjs
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import {test} from './util/helpers.mjs';

test('universal selector', '*', (t, tree) => {
t.deepEqual(tree.nodes[0].source.start.column, 1);
t.deepEqual(tree.nodes[0].source.end.column, 1);
t.deepEqual(tree.nodes[0].sourceIndex, 0);
t.deepEqual(tree.nodes[0].nodes[0].source.start.column, 1);
t.deepEqual(tree.nodes[0].nodes[0].source.end.column, 1);
t.deepEqual(tree.nodes[0].nodes[0].sourceIndex, 0);
});

test('lobotomized owl selector', ' * + * ', (t, tree) => {
t.deepEqual(tree.nodes[0].source.start.column, 1);
t.deepEqual(tree.nodes[0].source.end.column, 6);
t.deepEqual(tree.nodes[0].sourceIndex, 0);
t.deepEqual(tree.nodes[0].nodes[0].source.start.column, 2);
t.deepEqual(tree.nodes[0].nodes[0].source.end.column, 2);
t.deepEqual(tree.nodes[0].nodes[0].sourceIndex, 1);
Expand All @@ -19,12 +25,18 @@ test('lobotomized owl selector', ' * + * ', (t, tree) => {
});

test('comment', '/**\n * Hello!\n */', (t, tree) => {
t.deepEqual(tree.nodes[0].source.start.column, 1);
t.deepEqual(tree.nodes[0].source.end.column, 3);
t.deepEqual(tree.nodes[0].sourceIndex, 0);
t.deepEqual(tree.nodes[0].nodes[0].source.start.column, 1);
t.deepEqual(tree.nodes[0].nodes[0].source.end.column, 3);
t.deepEqual(tree.nodes[0].nodes[0].sourceIndex, 0);
});

test('comment & universal selectors', '*/*test*/*', (t, tree) => {
t.deepEqual(tree.nodes[0].source.start.column, 1);
t.deepEqual(tree.nodes[0].source.end.column, 10);
t.deepEqual(tree.nodes[0].sourceIndex, 0);
t.deepEqual(tree.nodes[0].nodes[0].source.start.column, 1);
t.deepEqual(tree.nodes[0].nodes[0].source.end.column, 1);
t.deepEqual(tree.nodes[0].nodes[0].sourceIndex, 0);
Expand All @@ -37,27 +49,42 @@ test('comment & universal selectors', '*/*test*/*', (t, tree) => {
});

test('tag selector', 'h1', (t, tree) => {
t.deepEqual(tree.nodes[0].source.start.column, 1);
t.deepEqual(tree.nodes[0].source.end.column, 2);
t.deepEqual(tree.nodes[0].sourceIndex, 0);
t.deepEqual(tree.nodes[0].nodes[0].source.start.column, 1);
t.deepEqual(tree.nodes[0].nodes[0].source.end.column, 2);
t.deepEqual(tree.nodes[0].nodes[0].sourceIndex, 0);
});

test('id selector', '#id', (t, tree) => {
t.deepEqual(tree.nodes[0].source.start.column, 1);
t.deepEqual(tree.nodes[0].source.end.column, 3);
t.deepEqual(tree.nodes[0].sourceIndex, 0);
t.deepEqual(tree.nodes[0].nodes[0].source.start.column, 1);
t.deepEqual(tree.nodes[0].nodes[0].source.end.column, 3);
t.deepEqual(tree.nodes[0].nodes[0].sourceIndex, 0);
});

test('tag selector followed by id selector', 'h1, #id', (t, tree) => {
t.deepEqual(tree.nodes[0].source.start.column, 1);
t.deepEqual(tree.nodes[0].source.end.column, 2);
t.deepEqual(tree.nodes[0].sourceIndex, 0);
t.deepEqual(tree.nodes[0].nodes[0].source.start.column, 1);
t.deepEqual(tree.nodes[0].nodes[0].source.end.column, 2);
t.deepEqual(tree.nodes[0].nodes[0].sourceIndex, 0);
t.deepEqual(tree.nodes[1].source.start.column, 4);
t.deepEqual(tree.nodes[1].source.end.column, 7);
t.deepEqual(tree.nodes[1].sourceIndex, 3);
t.deepEqual(tree.nodes[1].nodes[0].source.start.column, 5);
t.deepEqual(tree.nodes[1].nodes[0].source.end.column, 7);
t.deepEqual(tree.nodes[1].nodes[0].sourceIndex, 4);
});

test('multiple id selectors', '#one#two', (t, tree) => {
t.deepEqual(tree.nodes[0].source.start.column, 1);
t.deepEqual(tree.nodes[0].source.end.column, 8);
t.deepEqual(tree.nodes[0].sourceIndex, 0);
t.deepEqual(tree.nodes[0].nodes[0].source.start.column, 1);
t.deepEqual(tree.nodes[0].nodes[0].source.end.column, 4);
t.deepEqual(tree.nodes[0].nodes[0].sourceIndex, 0);
Expand All @@ -67,6 +94,9 @@ test('multiple id selectors', '#one#two', (t, tree) => {
});

test('multiple id selectors (2)', '#one#two#three#four', (t, tree) => {
t.deepEqual(tree.nodes[0].source.start.column, 1);
t.deepEqual(tree.nodes[0].source.end.column, 19);
t.deepEqual(tree.nodes[0].sourceIndex, 0);
t.deepEqual(tree.nodes[0].nodes[2].source.start.column, 9);
t.deepEqual(tree.nodes[0].nodes[2].source.end.column, 14);
t.deepEqual(tree.nodes[0].nodes[2].sourceIndex, 8);
Expand All @@ -76,24 +106,39 @@ test('multiple id selectors (2)', '#one#two#three#four', (t, tree) => {
});

test('multiple id selectors (3)', '#one#two,#three#four', (t, tree) => {
t.deepEqual(tree.nodes[0].source.start.column, 1);
t.deepEqual(tree.nodes[0].source.end.column, 8);
t.deepEqual(tree.nodes[0].sourceIndex, 0);
t.deepEqual(tree.nodes[0].nodes[1].source.start.column, 5);
t.deepEqual(tree.nodes[0].nodes[1].source.end.column, 8);
t.deepEqual(tree.nodes[0].nodes[1].sourceIndex, 4);
t.deepEqual(tree.nodes[1].source.start.column, 10);
t.deepEqual(tree.nodes[1].source.end.column, 20);
t.deepEqual(tree.nodes[1].sourceIndex, 9);
t.deepEqual(tree.nodes[1].nodes[1].source.start.column, 16);
t.deepEqual(tree.nodes[1].nodes[1].source.end.column, 20);
t.deepEqual(tree.nodes[1].nodes[1].sourceIndex, 15);
});

test('multiple class selectors', '.one.two,.three.four', (t, tree) => {
t.deepEqual(tree.nodes[0].source.start.column, 1);
t.deepEqual(tree.nodes[0].source.end.column, 8);
t.deepEqual(tree.nodes[0].sourceIndex, 0);
t.deepEqual(tree.nodes[0].nodes[1].source.start.column, 5);
t.deepEqual(tree.nodes[0].nodes[1].source.end.column, 8);
t.deepEqual(tree.nodes[0].nodes[1].sourceIndex, 4);
t.deepEqual(tree.nodes[1].source.start.column, 10);
t.deepEqual(tree.nodes[1].source.end.column, 20);
t.deepEqual(tree.nodes[1].sourceIndex, 9);
t.deepEqual(tree.nodes[1].nodes[1].source.start.column, 16);
t.deepEqual(tree.nodes[1].nodes[1].source.end.column, 20);
t.deepEqual(tree.nodes[1].nodes[1].sourceIndex, 15);
});

test('attribute selector', '[name="james"]', (t, tree) => {
t.deepEqual(tree.nodes[0].source.start.column, 1);
t.deepEqual(tree.nodes[0].source.end.column, 14);
t.deepEqual(tree.nodes[0].sourceIndex, 0);
t.deepEqual(tree.nodes[0].nodes[0].source.start.line, 1);
t.deepEqual(tree.nodes[0].nodes[0].source.start.column, 1);
t.deepEqual(tree.nodes[0].nodes[0].source.end.column, 14);
Expand Down Expand Up @@ -130,11 +175,33 @@ test('pseudo-class', 'h1:first-child', (t, tree) => {
t.deepEqual(tree.nodes[0].nodes[1].sourceIndex, 2);
});

test('pseudo-class without argument', ':not()', (t, tree) => {
t.deepEqual(tree.nodes[0].source.start.column, 1);
t.deepEqual(tree.nodes[0].source.end.column, 6);
t.deepEqual(tree.nodes[0].sourceIndex, 0);
t.deepEqual(tree.nodes[0].nodes[0].source.start.line, 1);
t.deepEqual(tree.nodes[0].nodes[0].source.start.column, 1);
t.deepEqual(tree.nodes[0].nodes[0].source.end.column, 6);
t.deepEqual(tree.nodes[0].nodes[0].sourceIndex, 0);
t.deepEqual(tree.nodes[0].nodes[0].nodes[0].source.start.column, 6);
t.deepEqual(tree.nodes[0].nodes[0].nodes[0].source.end.column, 6);
t.deepEqual(tree.nodes[0].nodes[0].nodes[0].sourceIndex, 5);
});

test('pseudo-class with argument', 'h1:not(.strudel, .food)', (t, tree) => {
t.deepEqual(tree.nodes[0].source.start.column, 1);
t.deepEqual(tree.nodes[0].source.end.column, 23);
t.deepEqual(tree.nodes[0].sourceIndex, 0);
t.deepEqual(tree.nodes[0].nodes[1].source.start.line, 1);
t.deepEqual(tree.nodes[0].nodes[1].source.start.column, 3);
t.deepEqual(tree.nodes[0].nodes[1].source.end.column, 23);
t.deepEqual(tree.nodes[0].nodes[1].sourceIndex, 2);
t.deepEqual(tree.nodes[0].nodes[1].nodes[0].source.start.column, 8);
t.deepEqual(tree.nodes[0].nodes[1].nodes[0].source.end.column, 15);
t.deepEqual(tree.nodes[0].nodes[1].nodes[0].sourceIndex, 7);
t.deepEqual(tree.nodes[0].nodes[1].nodes[1].source.start.column, 17);
t.deepEqual(tree.nodes[0].nodes[1].nodes[1].source.end.column, 23);
t.deepEqual(tree.nodes[0].nodes[1].nodes[1].sourceIndex, 16);
});

test('pseudo-element', 'h1::before', (t, tree) => {
Expand Down
17 changes: 14 additions & 3 deletions src/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,10 @@ export default class Parser {
this.root.errorGenerator = this._errorGenerator();


const selector = new Selector({source: {start: {line: 1, column: 1}}});
const selector = new Selector({
source: {start: {line: 1, column: 1}},
sourceIndex: 0,
});
this.root.append(selector);
this.current = selector;

Expand Down Expand Up @@ -608,7 +611,12 @@ export default class Parser {
return;
}
this.current._inferEndPosition();
const selector = new Selector({source: {start: tokenStart(this.tokens[this.position + 1])}});
const selector = new Selector({
source: {
start: tokenStart(this.tokens[this.position + 1]),
},
sourceIndex: this.tokens[this.position + 1][TOKEN.START_POS],
});
this.current.parent.append(selector);
this.current = selector;
this.position ++;
Expand Down Expand Up @@ -685,7 +693,10 @@ export default class Parser {
let unbalanced = 1;
this.position ++;
if (last && last.type === types.PSEUDO) {
const selector = new Selector({source: {start: tokenStart(this.tokens[this.position - 1])}});
const selector = new Selector({
source: {start: tokenStart(this.tokens[this.position])},
sourceIndex: this.tokens[this.position][TOKEN.START_POS],
});
const cache = this.current;
last.append(selector);
this.current = selector;
Expand Down

0 comments on commit 6485caf

Please sign in to comment.