/
preprocess.es6
112 lines (101 loc) · 3.53 KB
/
preprocess.es6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
function indentError(input, l, p) {
throw input.error('Mixed tabs and spaces are not allowed', l, p + 1);
}
export default function preprocess(input, lines) {
let indentType;
let prevNumber = 0;
let parts = lines.map(line => {
let lastComma = false;
let comment = false;
let number = prevNumber + 1;
let atrule = false;
let indent = '';
let tokens = [];
let colon = false;
if ( line.length > 0 ) {
if ( line[0][0] === 'space' ) {
indent = line[0][1];
tokens = line.slice(1);
} else {
indent = '';
tokens = line;
}
if ( !indentType && indent.length ) {
indentType = indent[0] === ' ' ? 'space' : 'tab';
}
if ( indentType === 'space' ) {
if ( indent.indexOf('\t') !== -1 ) {
indentError(input, number, indent.indexOf('\t'));
}
} else if ( indentType === 'tab' ) {
if ( indent.indexOf(' ') !== -1 ) {
indentError(input, number, indent.indexOf(' '));
}
}
if ( tokens.length ) {
for ( let i = tokens.length - 1; i >= 0; i-- ) {
let type = tokens[i][0];
if ( type === ',' ) {
lastComma = true;
break;
} else if ( type === 'space' ) {
continue;
} else if ( type === 'comment' ) {
continue;
} else if ( type === 'newline' ) {
continue;
} else {
break;
}
}
comment = tokens[0][0] === 'comment';
atrule = tokens[0][0] === 'at-word';
let brackets = 0;
for ( let i = 0; i < tokens.length - 1; i++ ) {
let type = tokens[i][0];
let next = tokens[i + 1][0];
if ( type === '(' ) {
brackets += 1;
} else if ( type === ')' ) {
brackets -= 1;
} else if ( type === ':' && brackets === 0 &&
(next === 'space' || next === 'newline') ) {
colon = true;
}
}
}
let last = tokens[tokens.length - 1];
if ( last && last[0] === 'newline' ) prevNumber = last[2];
}
return {
number,
indent,
colon,
tokens,
atrule,
comment,
lastComma,
before: ''
};
});
parts = parts.reduceRight( (all, i) => {
if ( !i.tokens.length || i.tokens.every(j => j[0] === 'newline') ) {
let prev = all[0];
let before = i.indent + i.tokens.map( j => j[1] ).join('');
prev.before = before + prev.before;
} else {
all.unshift(i);
}
return all;
}, [{ end: true, before: '' }]);
parts.forEach( (part, i) => {
if ( i === 0 ) return;
let prev = parts[i - 1];
let last = prev.tokens[prev.tokens.length - 1];
if ( last && last[0] === 'newline' ) {
part.before = last[1] + part.before;
prev.tokens.pop();
}
});
return parts;
}