@eslint/css-tree 3.3.4 → 3.5.0

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.
package/dist/version.cjs CHANGED
@@ -1 +1 @@
1
- module.exports = "3.3.4";
1
+ module.exports = "3.5.0";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const version = "3.3.4";
1
+ export const version = "3.5.0";
@@ -1,4 +1,5 @@
1
- import { tokenize, Delim, WhiteSpace } from '../tokenizer/index.js';
1
+ import { Delim, WhiteSpace } from '../tokenizer/index.js';
2
+ import { getTokenizer } from '../utils/get-tokenizer.js';
2
3
  import { generateSourceMap } from './sourceMap.js';
3
4
  import * as tokenBefore from './token-before.js';
4
5
 
@@ -23,12 +24,6 @@ function processChildren(node, delimeter) {
23
24
  node.children.forEach(this.node, this);
24
25
  }
25
26
 
26
- function processChunk(chunk) {
27
- tokenize(chunk, (type, start, end) => {
28
- this.token(type, chunk.slice(start, end));
29
- });
30
- }
31
-
32
27
  export function createGenerator(config) {
33
28
  const types = new Map();
34
29
 
@@ -87,7 +82,13 @@ export function createGenerator(config) {
87
82
  node: (node) => handlers.node(node),
88
83
  children: processChildren,
89
84
  token: (type, value) => handlers.token(type, value),
90
- tokenize: processChunk
85
+ tokenize: function (chunk) {
86
+ const tokenize = getTokenizer(config);
87
+
88
+ return tokenize(chunk, (type, start, end) => {
89
+ this.token(type, chunk.slice(start, end));
90
+ });
91
+ }
91
92
  };
92
93
 
93
94
  handlers.node(node);
package/lib/index.d.ts CHANGED
@@ -2693,19 +2693,21 @@ type ParserContext = TokenStream
2693
2693
  [key: string]: unknown;
2694
2694
  };
2695
2695
 
2696
- interface StructureDescriptor {
2697
- type: string;
2698
- optional?: boolean;
2699
- parse?: (this: ParserContext) => CssNodeCommon;
2700
- generate?: (this: ParserContext, node: CssNodeCommon) => void;
2696
+ type StructureValue = string | Function | null;
2697
+ type StructureDescriptor = StructureValue | Array<StructureValue> | Array<Array<StructureValue>>;
2698
+
2699
+ interface StructureDefinition {
2700
+ children?: Array<string>;
2701
+
2702
+ [key: string]: StructureDescriptor | undefined;
2701
2703
  }
2702
2704
 
2703
2705
  interface NodeSyntaxConfig<T extends CssNodeCommon = CssNodeCommon> {
2704
2706
  name: string;
2705
- structure: Record<string, StructureDescriptor>;
2707
+ structure: StructureDefinition;
2706
2708
  parse(this: ParserContext): T;
2707
2709
  generate(this: ParserContext, node: T): void;
2708
- walkContext: WalkContext;
2710
+ walkContext?: string;
2709
2711
  }
2710
2712
 
2711
2713
  interface AtruleSyntax {
@@ -2736,6 +2738,7 @@ export interface SyntaxConfig<T extends CssNodeCommon = CssNodeCommon> {
2736
2738
  scope: Record<string, Recognizer>;
2737
2739
  features: Record<string, Recognizer>;
2738
2740
  parseContext: ParseContext;
2741
+ tokenize: TokenizeFunction;
2739
2742
  }
2740
2743
 
2741
2744
  interface LexerStructureWarning {
@@ -1,4 +1,4 @@
1
- import { tokenize } from '../tokenizer/index.js';
1
+ import { getTokenizer } from '../utils/get-tokenizer.js';
2
2
 
3
3
  const astToTokens = {
4
4
  decorator(handlers) {
@@ -27,8 +27,9 @@ const astToTokens = {
27
27
  }
28
28
  };
29
29
 
30
- function stringToTokens(str) {
30
+ function stringToTokens(str, syntax) {
31
31
  const tokens = [];
32
+ const tokenize = getTokenizer(syntax);
32
33
 
33
34
  tokenize(str, (type, start, end) =>
34
35
  tokens.push({
@@ -43,7 +44,7 @@ function stringToTokens(str) {
43
44
 
44
45
  export default function(value, syntax) {
45
46
  if (typeof value === 'string') {
46
- return stringToTokens(value);
47
+ return stringToTokens(value, syntax);
47
48
  }
48
49
 
49
50
  return syntax.generate(value, astToTokens);
@@ -1,7 +1,6 @@
1
1
  import { List } from '../utils/List.js';
2
2
  import { SyntaxError } from './SyntaxError.js';
3
3
  import {
4
- tokenize,
5
4
  OffsetToLocation,
6
5
  TokenStream,
7
6
  tokenNames,
@@ -21,6 +20,7 @@ import {
21
20
  Number as NumberToken
22
21
  } from '../tokenizer/index.js';
23
22
  import { readSequence } from './sequence.js';
23
+ import { getTokenizer } from '../utils/get-tokenizer.js';
24
24
 
25
25
  const NOOP = () => {};
26
26
  const EXCLAMATIONMARK = 0x0021; // U+0021 EXCLAMATION MARK (!)
@@ -57,7 +57,8 @@ function processConfig(config) {
57
57
  scope: Object.assign(Object.create(null), config.scope),
58
58
  atrule: fetchParseValues(config.atrule),
59
59
  pseudo: fetchParseValues(config.pseudo),
60
- node: fetchParseValues(config.node)
60
+ node: fetchParseValues(config.node),
61
+ tokenize: getTokenizer(config)
61
62
  };
62
63
 
63
64
  for (const [name, context] of Object.entries(config.parseContext)) {
@@ -327,7 +328,7 @@ export function createParser(config) {
327
328
  source = source_;
328
329
  options = options || {};
329
330
 
330
- parser.setSource(source, tokenize);
331
+ parser.setSource(source, parser.tokenize);
331
332
  locationMap.setSource(
332
333
  source,
333
334
  options.offset,
@@ -115,6 +115,12 @@ export default function mix(dest, src) {
115
115
  case 'node':
116
116
  result[prop] = mergeDicts(dest[prop], value, ['name', 'structure', 'parse', 'generate', 'walkContext']);
117
117
  break;
118
+
119
+ case 'tokenize':
120
+ if (typeof value === 'function') {
121
+ result[prop] = value;
122
+ }
123
+ break;
118
124
  }
119
125
  }
120
126
 
@@ -2,6 +2,7 @@ import * as scope from '../scope/index.js';
2
2
  import atrule from '../atrule/index.js';
3
3
  import pseudo from '../pseudo/index.js';
4
4
  import * as node from '../node/index-parse.js';
5
+ import { tokenize } from '../../tokenizer/index.js';
5
6
 
6
7
  export default {
7
8
  parseContext: {
@@ -41,5 +42,6 @@ export default {
41
42
  scope,
42
43
  atrule,
43
44
  pseudo,
44
- node
45
+ node,
46
+ tokenize
45
47
  };
@@ -1,10 +1,10 @@
1
- import { tokenize } from '../tokenizer/index.js';
2
1
  import { createParser } from '../parser/create.js';
3
2
  import { createGenerator } from '../generator/create.js';
4
3
  import { createConvertor } from '../convertor/create.js';
5
4
  import { createWalker } from '../walker/create.js';
6
5
  import { Lexer } from '../lexer/Lexer.js';
7
6
  import mix from './config/mix.js';
7
+ import { getTokenizer } from '../utils/get-tokenizer.js';
8
8
 
9
9
  function createSyntax(config) {
10
10
  const parse = createParser(config);
@@ -16,7 +16,7 @@ function createSyntax(config) {
16
16
  lexer: null,
17
17
  createLexer: config => new Lexer(config, syntax, syntax.lexer.structure),
18
18
 
19
- tokenize,
19
+ tokenize: getTokenizer(config),
20
20
  parse,
21
21
  generate,
22
22
 
@@ -1,13 +1,25 @@
1
1
  import {
2
2
  WhiteSpace,
3
3
  Comment,
4
+ Delim,
4
5
  Semicolon,
6
+ Hash,
7
+ Colon,
5
8
  AtKeyword,
9
+ LeftSquareBracket,
6
10
  LeftCurlyBracket,
7
11
  RightCurlyBracket
8
12
  } from '../../tokenizer/index.js';
9
13
 
10
14
  const AMPERSAND = 0x0026; // U+0026 AMPERSAND (&)
15
+ const DOT = 0x002E; // U+002E FULL STOP (.)
16
+ const STAR = 0x002A; // U+002A ASTERISK (*);
17
+
18
+ const selectorStarts = new Set([
19
+ AMPERSAND,
20
+ DOT,
21
+ STAR
22
+ ]);
11
23
 
12
24
  function consumeRaw() {
13
25
  return this.Raw(null, true);
@@ -32,6 +44,12 @@ function consumeDeclaration() {
32
44
  return node;
33
45
  }
34
46
 
47
+ function isSelectorStart() {
48
+ return this.tokenType === Delim && selectorStarts.has(this.source.charCodeAt(this.tokenStart)) ||
49
+ this.tokenType === Hash || this.tokenType === LeftSquareBracket ||
50
+ this.tokenType === Colon;
51
+ }
52
+
35
53
  export const name = 'Block';
36
54
  export const walkContext = 'block';
37
55
  export const structure = {
@@ -65,7 +83,7 @@ export function parse(isStyleBlock) {
65
83
  break;
66
84
 
67
85
  default:
68
- if (isStyleBlock && this.isDelim(AMPERSAND)) {
86
+ if (isStyleBlock && isSelectorStart.call(this)) {
69
87
  children.push(consumeRule.call(this));
70
88
  } else {
71
89
  children.push(consumer.call(this));
@@ -1,7 +1,7 @@
1
1
  import { CDC } from '../../tokenizer/index.js';
2
2
 
3
3
  export const name = 'CDC';
4
- export const structure = [];
4
+ export const structure = {};
5
5
 
6
6
  export function parse() {
7
7
  const start = this.tokenStart;
@@ -1,7 +1,7 @@
1
1
  import { CDO } from '../../tokenizer/index.js';
2
2
 
3
3
  export const name = 'CDO';
4
- export const structure = [];
4
+ export const structure = {};
5
5
 
6
6
  export function parse() {
7
7
  const start = this.tokenStart;
@@ -0,0 +1,18 @@
1
+ import { tokenize } from '../tokenizer/index.js';
2
+
3
+ const FUNCTION_TYPE = 'function';
4
+
5
+ /**
6
+ * Gets the tokenizer function from the configuration object or returns the default tokenizer
7
+ *
8
+ * @param config Configuration object
9
+ * @returns Corresponding tokenizer function
10
+ */
11
+ export function getTokenizer(config) {
12
+ if (config && typeof config.tokenize === FUNCTION_TYPE) {
13
+ return config.tokenize;
14
+ }
15
+
16
+ // Fallback to the default tokenizer
17
+ return tokenize;
18
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eslint/css-tree",
3
- "version": "3.3.4",
3
+ "version": "3.5.0",
4
4
  "description": "A tool set for CSS: fast detailed parser (CSS → AST), walker (AST traversal), generator (AST → CSS) and lexer (validation and matching) based on specs and browser implementations",
5
5
  "author": "Roman Dvornov <rdvornov@gmail.com> (https://github.com/lahmatiy)",
6
6
  "license": "MIT",