@tbela99/css-parser 0.0.1-alpha3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,329 @@
1
+ interface LiteralToken {
2
+ typ: 'Literal';
3
+ val: string;
4
+ }
5
+ interface IdentToken {
6
+ typ: 'Iden';
7
+ val: string;
8
+ }
9
+ interface CommaToken {
10
+ typ: 'Comma';
11
+ }
12
+ interface ColonToken {
13
+ typ: 'Colon';
14
+ }
15
+ interface SemiColonToken {
16
+ typ: 'Semi-colon';
17
+ }
18
+ interface NumberToken {
19
+ typ: 'Number';
20
+ val: string;
21
+ }
22
+ interface AtRuleToken {
23
+ typ: 'At-rule';
24
+ val: string;
25
+ }
26
+ interface PercentageToken {
27
+ typ: 'Perc';
28
+ val: string;
29
+ }
30
+ interface FunctionToken {
31
+ typ: 'Func';
32
+ val: string;
33
+ chi: Token[];
34
+ }
35
+ interface FunctionURLToken {
36
+ typ: 'UrlFunc';
37
+ val: 'url';
38
+ chi: Array<UrlToken | CommentToken>;
39
+ }
40
+ interface StringToken {
41
+ typ: 'String';
42
+ val: string;
43
+ }
44
+ interface BadStringToken {
45
+ typ: 'Bad-string';
46
+ val: string;
47
+ }
48
+ interface UnclosedStringToken {
49
+ typ: 'Unclosed-string';
50
+ val: string;
51
+ }
52
+ interface DimensionToken {
53
+ typ: 'Dimension';
54
+ val: string;
55
+ unit: string;
56
+ }
57
+ interface LengthToken {
58
+ typ: 'Length';
59
+ val: string;
60
+ unit: string;
61
+ }
62
+ interface AngleToken {
63
+ typ: 'Angle';
64
+ val: string;
65
+ unit: string;
66
+ }
67
+ interface TimeToken {
68
+ typ: 'Time';
69
+ val: string;
70
+ unit: 'ms' | 's';
71
+ }
72
+ interface FrequencyToken {
73
+ typ: 'Frequency';
74
+ val: string;
75
+ unit: 'Hz' | 'Khz';
76
+ }
77
+ interface ResolutionToken {
78
+ typ: 'Resolution';
79
+ val: string;
80
+ unit: 'dpi' | 'dpcm' | 'dppx' | 'x';
81
+ }
82
+ interface HashToken {
83
+ typ: 'Hash';
84
+ val: string;
85
+ }
86
+ interface BlockStartToken {
87
+ typ: 'Block-start';
88
+ }
89
+ interface BlockEndToken {
90
+ typ: 'Block-end';
91
+ }
92
+ interface AttrStartToken {
93
+ typ: 'Attr-start';
94
+ }
95
+ interface AttrEndToken {
96
+ typ: 'Attr-end';
97
+ }
98
+ interface ParensStartToken {
99
+ typ: 'Start-parens';
100
+ }
101
+ interface ParensEndToken {
102
+ typ: 'End-parens';
103
+ }
104
+ interface WhitespaceToken {
105
+ typ: 'Whitespace';
106
+ }
107
+ interface CommentToken {
108
+ typ: 'Comment';
109
+ val: string;
110
+ }
111
+ interface BadCommentToken {
112
+ typ: 'Bad-comment';
113
+ val: string;
114
+ }
115
+ interface CDOCommentToken {
116
+ typ: 'CDOCOMM';
117
+ val: string;
118
+ }
119
+ interface BadCDOCommentToken {
120
+ typ: 'BADCDO';
121
+ val: string;
122
+ }
123
+ interface IncludesToken {
124
+ typ: 'Includes';
125
+ val: '~=';
126
+ }
127
+ interface DashMatchToken {
128
+ typ: 'Dash-match';
129
+ val: '|=';
130
+ }
131
+ interface LessThanToken {
132
+ typ: 'Lt';
133
+ }
134
+ interface GreaterThanToken {
135
+ typ: 'Gt';
136
+ }
137
+ interface PseudoClassToken {
138
+ typ: 'Pseudo-class';
139
+ val: string;
140
+ }
141
+ interface PseudoClassFunctionToken {
142
+ typ: 'Pseudo-class-func';
143
+ val: string;
144
+ chi: Token[];
145
+ }
146
+ interface DelimToken {
147
+ typ: 'Delim';
148
+ val: '=';
149
+ }
150
+ interface BadUrlToken {
151
+ typ: 'Bad-url-token';
152
+ val: string;
153
+ }
154
+ interface UrlToken {
155
+ typ: 'Url-token';
156
+ val: string;
157
+ }
158
+ interface EOFToken {
159
+ typ: 'EOF';
160
+ }
161
+ interface ImportantToken {
162
+ typ: 'Important';
163
+ }
164
+ interface ColorToken {
165
+ typ: 'Color';
166
+ val: string;
167
+ kin: 'lit' | 'hex' | 'rgb' | 'rgba' | 'hsl' | 'hsla' | 'hwb' | 'device-cmyk';
168
+ chi?: Token[];
169
+ }
170
+ interface AttrToken {
171
+ typ: 'Attr';
172
+ chi: Token[];
173
+ }
174
+ declare type Token = LiteralToken | IdentToken | CommaToken | ColonToken | SemiColonToken | NumberToken | AtRuleToken | PercentageToken | FunctionURLToken | FunctionToken | DimensionToken | LengthToken | AngleToken | StringToken | TimeToken | FrequencyToken | ResolutionToken | UnclosedStringToken | HashToken | BadStringToken | BlockStartToken | BlockEndToken | AttrStartToken | AttrEndToken | ParensStartToken | ParensEndToken | CDOCommentToken | BadCDOCommentToken | CommentToken | BadCommentToken | WhitespaceToken | IncludesToken | DashMatchToken | LessThanToken | GreaterThanToken | PseudoClassToken | PseudoClassFunctionToken | DelimToken | BadUrlToken | UrlToken | ImportantToken | ColorToken | AttrToken | EOFToken;
175
+
176
+ interface ErrorDescription {
177
+
178
+ // drop rule or declaration | fix rule or declaration
179
+ action: 'drop';
180
+ message: string;
181
+ location: {
182
+ src: string,
183
+ lin: number,
184
+ col: number;
185
+ };
186
+ error?: Error;
187
+ }
188
+
189
+ interface ParserOptions {
190
+
191
+ src?: string;
192
+ sourcemap?: boolean;
193
+ compress?: boolean;
194
+ removeEmpty?: boolean;
195
+ resolveUrls?: boolean;
196
+ resolveImport?: boolean;
197
+ cwd?: string;
198
+ load?: (url: string, currentUrl: string) => Promise<string>;
199
+ resolve?: (url: string, currentUrl: string, currentWorkingDirectory?: string) => { absolute: string, relative: string };
200
+ nodeEventFilter?: NodeType[]
201
+ }
202
+
203
+ interface RenderOptions {
204
+
205
+ compress?: boolean;
206
+ preserveLicense?: boolean;
207
+ indent?: string;
208
+ newLine?: string;
209
+ removeComments?: boolean;
210
+ colorConvert?: boolean;
211
+ }
212
+
213
+ interface TransformOptions extends ParserOptions, RenderOptions {
214
+
215
+ }
216
+
217
+ interface ParseResult {
218
+ ast: AstRuleStyleSheet;
219
+ errors: ErrorDescription[];
220
+ bytesIn: number;
221
+ }
222
+
223
+ interface RenderResult {
224
+ code: string ;
225
+ }
226
+
227
+ interface TransformResult extends ParseResult, RenderResult {
228
+
229
+ stats: {
230
+ bytesIn: number;
231
+ bytesOut: number;
232
+ parse: string;
233
+ render: string;
234
+ total: string;
235
+ }
236
+ }
237
+
238
+ interface Position {
239
+
240
+ ind: number;
241
+ lin: number;
242
+ col: number;
243
+ }
244
+
245
+ interface Location {
246
+
247
+ sta: Position;
248
+ // end: Position;
249
+ src: string;
250
+ }
251
+
252
+ declare type NodeType = 'StyleSheet' | 'InvalidComment' | 'Comment' | 'Declaration' | 'InvalidAtRule' | 'AtRule' | 'Rule';
253
+
254
+ interface Node {
255
+
256
+ typ: NodeType;
257
+ loc?: Location;
258
+ }
259
+
260
+ interface AstComment extends Node {
261
+
262
+ typ: 'Comment',
263
+ val: string;
264
+ }
265
+ interface AstDeclaration extends Node {
266
+
267
+ nam: string,
268
+ val: Token[];
269
+ typ: 'Declaration'
270
+ }
271
+
272
+ interface AstRule extends Node {
273
+
274
+ typ: 'Rule',
275
+ sel: string,
276
+ chi: Array<AstDeclaration | AstComment | AstRuleList>
277
+ }
278
+
279
+ interface AstAtRule extends Node {
280
+
281
+ nam: string;
282
+ val: string;
283
+ chi?: Array<AstDeclaration | AstComment> | Array<AstRule | AstComment>
284
+ }
285
+
286
+ interface AstRuleList extends Node {
287
+
288
+ chi: Array<Node | AstComment>
289
+ }
290
+
291
+ interface AstRuleStyleSheet extends AstRuleList {
292
+ typ: 'StyleSheet',
293
+ chi: Array<AstRuleList | AstComment>
294
+ }
295
+
296
+ type AstNode =
297
+ AstRuleStyleSheet
298
+ | AstRuleList
299
+ | AstComment
300
+ | AstAtRule
301
+ | AstRule
302
+ | AstDeclaration;
303
+
304
+ declare function deduplicate(ast: AstNode, options?: ParserOptions, recursive?: boolean): AstNode;
305
+ declare function hasDeclaration(node: AstAtRule | AstRule | AstRuleList): boolean;
306
+ declare function deduplicateRule(ast: AstNode, options?: ParserOptions): AstNode;
307
+
308
+ declare function render(data: AstNode, opt?: RenderOptions): RenderResult;
309
+ declare function renderToken(token: Token, options?: RenderOptions): string;
310
+
311
+ declare function walk(node: AstNode): Generator<{
312
+ node: AstNode;
313
+ parent?: AstRuleList;
314
+ root?: AstRuleList;
315
+ }>;
316
+
317
+ declare function load(url: string, currentFile: string): Promise<string>;
318
+
319
+ declare const matchUrl: RegExp;
320
+ declare function dirname(path: string): string;
321
+ declare function resolve(url: string, currentDirectory: string, cwd?: string): {
322
+ absolute: string;
323
+ relative: string;
324
+ };
325
+
326
+ declare function parse(iterator: string, opt?: ParserOptions): Promise<ParseResult>;
327
+ declare function transform(css: string, options?: TransformOptions): Promise<TransformResult>;
328
+
329
+ export { deduplicate, deduplicateRule, dirname, hasDeclaration, load, matchUrl, parse, render, renderToken, resolve, transform, walk };
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ export { parse, transform } from './node/index.js';
2
+ export { deduplicate, deduplicateRule, hasDeclaration } from './lib/parser/deduplicate.js';
3
+ export { render, renderToken } from './lib/renderer/render.js';
4
+ export { walk } from './lib/walker/walk.js';
5
+ export { load } from './node/load.js';
6
+ export { dirname, matchUrl, resolve } from './lib/fs/resolve.js';
@@ -0,0 +1,100 @@
1
+ const matchUrl = /^(https?:)?\/\//;
2
+ function dirname(path) {
3
+ if (path == '/' || path === '') {
4
+ return path;
5
+ }
6
+ let i = 0;
7
+ let parts = [''];
8
+ for (; i < path.length; i++) {
9
+ const chr = path.charAt(i);
10
+ if (chr == '/') {
11
+ parts.push('');
12
+ }
13
+ else if (chr == '?' || chr == '#') {
14
+ break;
15
+ }
16
+ else {
17
+ parts[parts.length - 1] += chr;
18
+ }
19
+ }
20
+ parts.pop();
21
+ return parts.length == 0 ? '/' : parts.join('/');
22
+ }
23
+ function splitPath(result) {
24
+ const parts = [''];
25
+ let i = 0;
26
+ for (; i < result.length; i++) {
27
+ const chr = result.charAt(i);
28
+ if (chr == '/') {
29
+ parts.push('');
30
+ }
31
+ else if (chr == '?' || chr == '#') {
32
+ break;
33
+ }
34
+ else {
35
+ parts[parts.length - 1] += chr;
36
+ }
37
+ }
38
+ let k = parts.length;
39
+ while (k--) {
40
+ if (parts[k] == '.') {
41
+ parts.splice(k, 1);
42
+ }
43
+ else if (parts[k] == '..') {
44
+ parts.splice(k - 1, 2);
45
+ }
46
+ }
47
+ return { parts, i };
48
+ }
49
+ function resolve(url, currentDirectory, cwd) {
50
+ if (matchUrl.test(url)) {
51
+ return {
52
+ absolute: url,
53
+ relative: url
54
+ };
55
+ }
56
+ if (matchUrl.test(currentDirectory)) {
57
+ const path = new URL(url, currentDirectory).href;
58
+ return {
59
+ absolute: path,
60
+ relative: path
61
+ };
62
+ }
63
+ let result;
64
+ if (url.charAt(0) == '/') {
65
+ result = url;
66
+ }
67
+ else if (currentDirectory.charAt(0) == '/') {
68
+ result = dirname(currentDirectory) + '/' + url;
69
+ }
70
+ else if (currentDirectory === '' || dirname(currentDirectory) === '') {
71
+ result = url;
72
+ }
73
+ else {
74
+ result = dirname(currentDirectory) + '/' + url;
75
+ }
76
+ let { parts, i } = splitPath(result);
77
+ if (parts.length == 0) {
78
+ const path = result.charAt(0) == '/' ? '/' : '';
79
+ return {
80
+ absolute: path,
81
+ relative: path
82
+ };
83
+ }
84
+ const absolute = parts.join('/');
85
+ const { parts: dirs } = splitPath(cwd ?? currentDirectory);
86
+ for (const p of dirs) {
87
+ if (parts[0] == p) {
88
+ parts.shift();
89
+ }
90
+ else {
91
+ parts.unshift('..');
92
+ }
93
+ }
94
+ return {
95
+ absolute,
96
+ relative: parts.join('/') + (i < result.length ? result.slice(i) : '')
97
+ };
98
+ }
99
+
100
+ export { dirname, matchUrl, resolve };
@@ -0,0 +1,66 @@
1
+ import { PropertySet } from './set.js';
2
+ import { getConfig } from '../utils/config.js';
3
+ import { PropertyMap } from './map.js';
4
+
5
+ const config = getConfig();
6
+ class PropertyList {
7
+ declarations;
8
+ constructor() {
9
+ this.declarations = new Map;
10
+ }
11
+ add(declaration) {
12
+ if (declaration.typ != 'Declaration') {
13
+ this.declarations.set(Number(Math.random().toString().slice(2)).toString(36), declaration);
14
+ return this;
15
+ }
16
+ const propertyName = declaration.nam;
17
+ if (propertyName in config.properties) {
18
+ // @ts-ignore
19
+ const shorthand = config.properties[propertyName].shorthand;
20
+ if (!this.declarations.has(shorthand)) {
21
+ // @ts-ignore
22
+ this.declarations.set(shorthand, new PropertySet(config.properties[shorthand]));
23
+ }
24
+ this.declarations.get(shorthand).add(declaration);
25
+ return this;
26
+ }
27
+ if (propertyName in config.map) {
28
+ // @ts-ignore
29
+ const shorthand = config.map[propertyName].shorthand;
30
+ if (!this.declarations.has(shorthand)) {
31
+ // @ts-ignore
32
+ this.declarations.set(shorthand, new PropertyMap(config.map[shorthand]));
33
+ }
34
+ this.declarations.get(shorthand).add(declaration);
35
+ return this;
36
+ }
37
+ this.declarations.set(propertyName, declaration);
38
+ return this;
39
+ }
40
+ [Symbol.iterator]() {
41
+ let iterator = this.declarations.values();
42
+ const iterators = [];
43
+ return {
44
+ next() {
45
+ let value = iterator.next();
46
+ while ((value.done && iterators.length > 0) ||
47
+ value.value instanceof PropertySet ||
48
+ value.value instanceof PropertyMap) {
49
+ if (value.value instanceof PropertySet || value.value instanceof PropertyMap) {
50
+ iterators.unshift(iterator);
51
+ // @ts-ignore
52
+ iterator = value.value[Symbol.iterator]();
53
+ value = iterator.next();
54
+ }
55
+ if (value.done && iterators.length > 0) {
56
+ iterator = iterators.shift();
57
+ value = iterator.next();
58
+ }
59
+ }
60
+ return value;
61
+ }
62
+ };
63
+ }
64
+ }
65
+
66
+ export { PropertyList };