@master/css 2.0.0-rc.61 → 2.0.0-rc.62

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.
Files changed (125) hide show
  1. package/dist/animation-rule.cjs +24 -0
  2. package/dist/animation-rule.d.ts +11 -0
  3. package/dist/animation-rule.mjs +22 -0
  4. package/dist/common.cjs +50 -1
  5. package/dist/common.d.ts +14 -0
  6. package/dist/common.mjs +45 -2
  7. package/dist/config/at.cjs +13 -10
  8. package/dist/config/at.d.ts +4 -1
  9. package/dist/config/at.mjs +13 -10
  10. package/dist/config/index.cjs +3 -0
  11. package/dist/config/index.d.ts +2 -1
  12. package/dist/config/index.mjs +3 -1
  13. package/dist/config/modes.d.ts +4 -2
  14. package/dist/config/rules.cjs +25 -13
  15. package/dist/config/rules.d.ts +4 -2
  16. package/dist/config/rules.mjs +25 -13
  17. package/dist/config/screens.cjs +17 -0
  18. package/dist/config/screens.d.ts +14 -0
  19. package/dist/config/screens.mjs +15 -0
  20. package/dist/config/selectors.cjs +11 -15
  21. package/dist/config/selectors.d.ts +10 -8
  22. package/dist/config/selectors.mjs +11 -15
  23. package/dist/config/utilities.cjs +3 -0
  24. package/dist/config/utilities.d.ts +3 -0
  25. package/dist/config/utilities.mjs +3 -0
  26. package/dist/config/variables.cjs +0 -13
  27. package/dist/config/variables.d.ts +0 -13
  28. package/dist/config/variables.mjs +0 -13
  29. package/dist/core.cjs +438 -476
  30. package/dist/core.d.ts +13 -4
  31. package/dist/core.mjs +438 -476
  32. package/dist/factories/with-syntax-layer.cjs +37 -260
  33. package/dist/factories/with-syntax-layer.mjs +37 -260
  34. package/dist/index.cjs +38 -12
  35. package/dist/index.d.ts +19 -7
  36. package/dist/index.mjs +17 -7
  37. package/dist/layer.cjs +11 -7
  38. package/dist/layer.d.ts +4 -3
  39. package/dist/layer.mjs +11 -7
  40. package/dist/non-layer.cjs +10 -17
  41. package/dist/non-layer.d.ts +1 -1
  42. package/dist/non-layer.mjs +10 -17
  43. package/dist/rule.cjs +4 -6
  44. package/dist/rule.d.ts +3 -10
  45. package/dist/rule.mjs +4 -6
  46. package/dist/syntax-rule-type.cjs +7 -8
  47. package/dist/syntax-rule-type.d.ts +7 -7
  48. package/dist/syntax-rule-type.mjs +7 -8
  49. package/dist/syntax-rule.cjs +116 -328
  50. package/dist/syntax-rule.d.ts +18 -25
  51. package/dist/syntax-rule.mjs +117 -329
  52. package/dist/types/common.d.ts +2 -0
  53. package/dist/types/config.d.ts +12 -7
  54. package/dist/types/syntax.d.ts +5 -24
  55. package/dist/utils/compare-rule-priority.cjs +143 -0
  56. package/dist/utils/compare-rule-priority.d.ts +7 -0
  57. package/dist/utils/compare-rule-priority.mjs +138 -0
  58. package/dist/utils/equal-at-rules.cjs +22 -0
  59. package/dist/utils/equal-at-rules.d.ts +2 -0
  60. package/dist/utils/equal-at-rules.mjs +20 -0
  61. package/dist/utils/equal-declarations.cjs +10 -0
  62. package/dist/utils/equal-declarations.d.ts +2 -0
  63. package/dist/utils/equal-declarations.mjs +8 -0
  64. package/dist/utils/equal-selectors.cjs +70 -0
  65. package/dist/utils/equal-selectors.d.ts +2 -0
  66. package/dist/utils/equal-selectors.mjs +68 -0
  67. package/dist/utils/equal-variants.cjs +10 -0
  68. package/dist/utils/equal-variants.d.ts +2 -0
  69. package/dist/utils/equal-variants.mjs +8 -0
  70. package/dist/utils/extend-config.cjs +0 -1
  71. package/dist/utils/extend-config.mjs +0 -1
  72. package/dist/utils/generate-at.cjs +30 -0
  73. package/dist/utils/generate-at.d.ts +2 -0
  74. package/dist/utils/generate-at.mjs +28 -0
  75. package/dist/utils/generate-selector.cjs +49 -0
  76. package/dist/utils/generate-selector.d.ts +2 -0
  77. package/dist/utils/generate-selector.mjs +47 -0
  78. package/dist/utils/get-single-at-number-rule-node.cjs +9 -0
  79. package/dist/utils/get-single-at-number-rule-node.d.ts +2 -0
  80. package/dist/utils/get-single-at-number-rule-node.mjs +7 -0
  81. package/dist/utils/parse-at.cjs +157 -0
  82. package/dist/utils/parse-at.d.ts +39 -0
  83. package/dist/utils/parse-at.mjs +155 -0
  84. package/dist/utils/parse-pair.cjs +51 -0
  85. package/dist/utils/parse-pair.d.ts +8 -0
  86. package/dist/utils/parse-pair.mjs +49 -0
  87. package/dist/utils/parse-selector.cjs +112 -0
  88. package/dist/utils/parse-selector.d.ts +19 -0
  89. package/dist/utils/parse-selector.mjs +110 -0
  90. package/dist/utils/parse-value.cjs +39 -0
  91. package/dist/utils/parse-value.d.ts +2 -0
  92. package/dist/utils/parse-value.mjs +37 -0
  93. package/dist/utils/replace-char-outside-quotes.cjs +21 -0
  94. package/dist/utils/replace-char-outside-quotes.d.ts +1 -0
  95. package/dist/utils/replace-char-outside-quotes.mjs +19 -0
  96. package/dist/utils/sort-readable-classes.cjs +74 -0
  97. package/dist/utils/{reorder-for-readable-classes.d.ts → sort-readable-classes.d.ts} +1 -1
  98. package/dist/utils/sort-readable-classes.mjs +72 -0
  99. package/dist/utils/split-char-outside-quotes.cjs +29 -0
  100. package/dist/utils/split-char-outside-quotes.d.ts +1 -0
  101. package/dist/utils/split-char-outside-quotes.mjs +27 -0
  102. package/dist/variable-rule.cjs +86 -0
  103. package/dist/variable-rule.d.ts +23 -0
  104. package/dist/variable-rule.mjs +81 -0
  105. package/package.json +1 -1
  106. package/dist/rule-node.cjs +0 -18
  107. package/dist/rule-node.d.ts +0 -14
  108. package/dist/rule-node.mjs +0 -16
  109. package/dist/utils/are-rule-at-equal.cjs +0 -12
  110. package/dist/utils/are-rule-at-equal.d.ts +0 -2
  111. package/dist/utils/are-rule-at-equal.mjs +0 -10
  112. package/dist/utils/are-rule-modes-equal.cjs +0 -7
  113. package/dist/utils/are-rule-modes-equal.d.ts +0 -2
  114. package/dist/utils/are-rule-modes-equal.mjs +0 -5
  115. package/dist/utils/are-rule-selectors-equal.cjs +0 -29
  116. package/dist/utils/are-rule-selectors-equal.d.ts +0 -2
  117. package/dist/utils/are-rule-selectors-equal.mjs +0 -27
  118. package/dist/utils/are-rule-states-equal.cjs +0 -11
  119. package/dist/utils/are-rule-states-equal.d.ts +0 -2
  120. package/dist/utils/are-rule-states-equal.mjs +0 -9
  121. package/dist/utils/are-rules-duplicated.cjs +0 -17
  122. package/dist/utils/are-rules-duplicated.d.ts +0 -2
  123. package/dist/utils/are-rules-duplicated.mjs +0 -15
  124. package/dist/utils/reorder-for-readable-classes.cjs +0 -62
  125. package/dist/utils/reorder-for-readable-classes.mjs +0 -60
@@ -0,0 +1,47 @@
1
+ import { SELECTOR_COMBINATORS } from '../common.mjs';
2
+
3
+ const prefixMap = {
4
+ 'class': '.',
5
+ 'pseudo-class': ':',
6
+ 'pseudo-element': '::',
7
+ 'attribute': '',
8
+ 'combinator': ''
9
+ };
10
+ function generateSelector(nodes, body = '') {
11
+ const generate = (node)=>{
12
+ if (node.type === 'attribute') return `[${node.value}]`;
13
+ if (node.type === 'combinator') return node.value;
14
+ const prefix = node.type && prefixMap[node.type] || '';
15
+ const base = node.value ? prefix + node.value : '';
16
+ if ('children' in node && node.children?.length) {
17
+ const childrenText = node.children.map(generate).join('');
18
+ return node.value ? base + `(${childrenText})` : base + childrenText;
19
+ }
20
+ return base;
21
+ };
22
+ let pre = '';
23
+ let current = '';
24
+ const groups = [];
25
+ const flatNodes = nodes.flatMap((node)=>!('value' in node) && 'children' in node && node.children?.length ? node.children : node);
26
+ flatNodes.forEach((node)=>{
27
+ if (node.value === ',') {
28
+ groups.push(current);
29
+ current = '';
30
+ } else if (node.value === 'of' && 'children' in node) {
31
+ pre += node.children.map(generate).join('');
32
+ } else {
33
+ current += generate(node);
34
+ }
35
+ });
36
+ if (current) groups.push(current);
37
+ if (pre) {
38
+ const lastChar = pre.charAt(pre.length - 1);
39
+ if (!SELECTOR_COMBINATORS.includes(lastChar) && lastChar !== ' ') {
40
+ pre += ' ';
41
+ }
42
+ }
43
+ const result = groups.length ? groups.map((text)=>pre + body + text).join(',') : pre + body;
44
+ return result;
45
+ }
46
+
47
+ export { generateSelector as default };
@@ -0,0 +1,9 @@
1
+ 'use strict';
2
+
3
+ function getSingleAtNumberRuleNode(nodes) {
4
+ if (nodes.length !== 1) return;
5
+ let atNumberRuleNode = nodes[0];
6
+ if (atNumberRuleNode.type === 'number') return atNumberRuleNode;
7
+ }
8
+
9
+ module.exports = getSingleAtNumberRuleNode;
@@ -0,0 +1,2 @@
1
+ import { AtRuleNode } from './parse-at';
2
+ export default function getSingleAtNumberRuleNode(nodes: AtRuleNode[]): import("./parse-at").AtRuleNumberNode | undefined;
@@ -0,0 +1,7 @@
1
+ function getSingleAtNumberRuleNode(nodes) {
2
+ if (nodes.length !== 1) return;
3
+ let atNumberRuleNode = nodes[0];
4
+ if (atNumberRuleNode.type === 'number') return atNumberRuleNode;
5
+ }
6
+
7
+ export { getSingleAtNumberRuleNode as default };
@@ -0,0 +1,157 @@
1
+ 'use strict';
2
+
3
+ var common = require('../common.cjs');
4
+ var core = require('../core.cjs');
5
+ var parsePair = require('./parse-pair.cjs');
6
+ var parseValue = require('./parse-value.cjs');
7
+ var replaceCharOutsideQuotes = require('./replace-char-outside-quotes.cjs');
8
+ var splitCharOutsideQuotes = require('./split-char-outside-quotes.cjs');
9
+
10
+ function parseAt(token, css = new core(), isRaw = true) {
11
+ let id;
12
+ let firstToken;
13
+ const resolve = (token)=>{
14
+ const regex = /([a-zA-Z0-9-:%|]+|[&|!|,|>|<|=][=]?)/g;
15
+ const raws = [
16
+ ...token.matchAll(regex)
17
+ ].map((match)=>match[0]);
18
+ let nodes = [];
19
+ const addNode = (node)=>{
20
+ let prev = nodes[nodes.length - 1];
21
+ if (node.type === 'number' && !node.name) {
22
+ if (prev?.type === 'comparison') {
23
+ node.operator = prev.value;
24
+ if (node.raw && prev.raw) {
25
+ node.raw = prev.raw + node.raw;
26
+ }
27
+ nodes.pop();
28
+ prev = nodes[nodes.length - 1];
29
+ if (prev?.type === 'string') {
30
+ node.name = prev.value;
31
+ if (node.raw && prev.raw) {
32
+ node.raw = prev.raw + node.raw;
33
+ }
34
+ nodes.pop();
35
+ } else {
36
+ node.name = 'width';
37
+ }
38
+ } else {
39
+ node.name = 'width';
40
+ node.operator = '>=';
41
+ }
42
+ }
43
+ nodes.push(node);
44
+ };
45
+ raws.forEach((raw)=>{
46
+ if (common.AT_COMPARISON_OPERATORS.includes(raw)) {
47
+ const newNode = {
48
+ type: 'comparison',
49
+ value: raw
50
+ };
51
+ if (isRaw) newNode.raw = raw;
52
+ nodes.push(newNode);
53
+ return;
54
+ } else if (raw in common.AT_LOGICAL_OPERATORS) {
55
+ const newNode = {
56
+ type: 'logical',
57
+ value: common.AT_LOGICAL_OPERATORS[raw]
58
+ };
59
+ if (isRaw) newNode.raw = raw;
60
+ nodes.push(newNode);
61
+ return;
62
+ }
63
+ const definedAtRule = css.atRules.get(raw);
64
+ if (!id && !firstToken) {
65
+ firstToken = raw;
66
+ if (common.AT_IDENTIFIERS.includes(firstToken)) {
67
+ id = firstToken;
68
+ return;
69
+ } else if (definedAtRule) {
70
+ id = definedAtRule.id;
71
+ } else if (common.AT_COMPARABLE_FEATURES.includes(firstToken)) {
72
+ id = 'media';
73
+ } else if (firstToken.charAt(0).match(/[a-zA-Z-]/)) {
74
+ id = 'container';
75
+ } else {
76
+ id = 'media';
77
+ }
78
+ }
79
+ let node = {
80
+ type: 'string'
81
+ };
82
+ if (isRaw) node.raw = raw;
83
+ if (definedAtRule) {
84
+ if (definedAtRule.nodes.length === 1) {
85
+ addNode({
86
+ ...definedAtRule.nodes[0],
87
+ raw
88
+ });
89
+ } else if (definedAtRule.nodes.length) {
90
+ addNode({
91
+ raw,
92
+ children: definedAtRule.nodes
93
+ });
94
+ }
95
+ return;
96
+ } else {
97
+ const [splitedNameOrValue, splitedValue] = splitCharOutsideQuotes(raw, ':');
98
+ if (splitedValue) {
99
+ node.name = splitedNameOrValue;
100
+ node.value = splitedValue;
101
+ } else {
102
+ node.value = splitedNameOrValue;
103
+ }
104
+ if (id === 'container' || id === 'media') {
105
+ const { token, ...newNode } = parseValue(node.value, 'rem', css.config.rootSize);
106
+ Object.assign(node, newNode);
107
+ }
108
+ addNode(node);
109
+ }
110
+ });
111
+ return nodes;
112
+ };
113
+ const pair = (token)=>{
114
+ const pairedAtNodes = [];
115
+ const paired = parsePair(token);
116
+ if (paired) {
117
+ if (paired.pre) {
118
+ pairedAtNodes.push(...pair(paired.pre));
119
+ }
120
+ if (paired.body) {
121
+ if (id === 'supports') {
122
+ pairedAtNodes.push({
123
+ type: 'group',
124
+ children: [
125
+ {
126
+ type: 'string',
127
+ value: replaceCharOutsideQuotes(paired.body, '|', ' ')
128
+ }
129
+ ]
130
+ });
131
+ } else {
132
+ const children = pair(paired.body);
133
+ if (children.length > 1) {
134
+ pairedAtNodes.push({
135
+ type: 'group',
136
+ children: pair(paired.body)
137
+ });
138
+ } else {
139
+ pairedAtNodes.push(...children);
140
+ }
141
+ }
142
+ }
143
+ if (paired.post) {
144
+ pairedAtNodes.push(...pair(paired.post));
145
+ }
146
+ } else {
147
+ pairedAtNodes.push(...resolve(token));
148
+ }
149
+ return pairedAtNodes;
150
+ };
151
+ return {
152
+ nodes: pair(token),
153
+ id: id || 'media' // should be assigned to here
154
+ };
155
+ }
156
+
157
+ module.exports = parseAt;
@@ -0,0 +1,39 @@
1
+ import MasterCSS from '../core';
2
+ import { AtIdentifier } from '../types/config';
3
+ export type AtRule = {
4
+ id: AtIdentifier;
5
+ nodes: AtRuleNode[];
6
+ };
7
+ export declare type AtRuleNumberNode = {
8
+ raw?: string;
9
+ name: string;
10
+ type: 'number';
11
+ value: number;
12
+ unit?: string;
13
+ operator?: string;
14
+ };
15
+ export declare type AtRuleStringNode = {
16
+ raw?: string;
17
+ name: string;
18
+ type: 'string';
19
+ value: string;
20
+ };
21
+ export declare type AtRuleValueNode = AtRuleNumberNode | AtRuleStringNode;
22
+ export interface AtRuleComparisonOperatorNode {
23
+ type: 'comparison';
24
+ raw?: string;
25
+ value: string;
26
+ }
27
+ export interface AtRuleLogicalOperatorNode {
28
+ type: 'logical';
29
+ raw?: string;
30
+ value: string;
31
+ }
32
+ export type AtRuleOperatorNode = AtRuleComparisonOperatorNode | AtRuleLogicalOperatorNode;
33
+ export interface AtRuleGroupNode {
34
+ type?: 'group';
35
+ raw?: string;
36
+ children: AtRuleNode[];
37
+ }
38
+ export type AtRuleNode = AtRuleValueNode | AtRuleComparisonOperatorNode | AtRuleLogicalOperatorNode | AtRuleGroupNode;
39
+ export default function parseAt(token: string, css?: MasterCSS, isRaw?: boolean): AtRule;
@@ -0,0 +1,155 @@
1
+ import { AT_COMPARISON_OPERATORS, AT_LOGICAL_OPERATORS, AT_IDENTIFIERS, AT_COMPARABLE_FEATURES } from '../common.mjs';
2
+ import MasterCSS from '../core.mjs';
3
+ import parsePair from './parse-pair.mjs';
4
+ import parseValue from './parse-value.mjs';
5
+ import replaceCharOutsideQuotes from './replace-char-outside-quotes.mjs';
6
+ import splitCharOutsideQuotes from './split-char-outside-quotes.mjs';
7
+
8
+ function parseAt(token, css = new MasterCSS(), isRaw = true) {
9
+ let id;
10
+ let firstToken;
11
+ const resolve = (token)=>{
12
+ const regex = /([a-zA-Z0-9-:%|]+|[&|!|,|>|<|=][=]?)/g;
13
+ const raws = [
14
+ ...token.matchAll(regex)
15
+ ].map((match)=>match[0]);
16
+ let nodes = [];
17
+ const addNode = (node)=>{
18
+ let prev = nodes[nodes.length - 1];
19
+ if (node.type === 'number' && !node.name) {
20
+ if (prev?.type === 'comparison') {
21
+ node.operator = prev.value;
22
+ if (node.raw && prev.raw) {
23
+ node.raw = prev.raw + node.raw;
24
+ }
25
+ nodes.pop();
26
+ prev = nodes[nodes.length - 1];
27
+ if (prev?.type === 'string') {
28
+ node.name = prev.value;
29
+ if (node.raw && prev.raw) {
30
+ node.raw = prev.raw + node.raw;
31
+ }
32
+ nodes.pop();
33
+ } else {
34
+ node.name = 'width';
35
+ }
36
+ } else {
37
+ node.name = 'width';
38
+ node.operator = '>=';
39
+ }
40
+ }
41
+ nodes.push(node);
42
+ };
43
+ raws.forEach((raw)=>{
44
+ if (AT_COMPARISON_OPERATORS.includes(raw)) {
45
+ const newNode = {
46
+ type: 'comparison',
47
+ value: raw
48
+ };
49
+ if (isRaw) newNode.raw = raw;
50
+ nodes.push(newNode);
51
+ return;
52
+ } else if (raw in AT_LOGICAL_OPERATORS) {
53
+ const newNode = {
54
+ type: 'logical',
55
+ value: AT_LOGICAL_OPERATORS[raw]
56
+ };
57
+ if (isRaw) newNode.raw = raw;
58
+ nodes.push(newNode);
59
+ return;
60
+ }
61
+ const definedAtRule = css.atRules.get(raw);
62
+ if (!id && !firstToken) {
63
+ firstToken = raw;
64
+ if (AT_IDENTIFIERS.includes(firstToken)) {
65
+ id = firstToken;
66
+ return;
67
+ } else if (definedAtRule) {
68
+ id = definedAtRule.id;
69
+ } else if (AT_COMPARABLE_FEATURES.includes(firstToken)) {
70
+ id = 'media';
71
+ } else if (firstToken.charAt(0).match(/[a-zA-Z-]/)) {
72
+ id = 'container';
73
+ } else {
74
+ id = 'media';
75
+ }
76
+ }
77
+ let node = {
78
+ type: 'string'
79
+ };
80
+ if (isRaw) node.raw = raw;
81
+ if (definedAtRule) {
82
+ if (definedAtRule.nodes.length === 1) {
83
+ addNode({
84
+ ...definedAtRule.nodes[0],
85
+ raw
86
+ });
87
+ } else if (definedAtRule.nodes.length) {
88
+ addNode({
89
+ raw,
90
+ children: definedAtRule.nodes
91
+ });
92
+ }
93
+ return;
94
+ } else {
95
+ const [splitedNameOrValue, splitedValue] = splitCharOutsideQuotes(raw, ':');
96
+ if (splitedValue) {
97
+ node.name = splitedNameOrValue;
98
+ node.value = splitedValue;
99
+ } else {
100
+ node.value = splitedNameOrValue;
101
+ }
102
+ if (id === 'container' || id === 'media') {
103
+ const { token, ...newNode } = parseValue(node.value, 'rem', css.config.rootSize);
104
+ Object.assign(node, newNode);
105
+ }
106
+ addNode(node);
107
+ }
108
+ });
109
+ return nodes;
110
+ };
111
+ const pair = (token)=>{
112
+ const pairedAtNodes = [];
113
+ const paired = parsePair(token);
114
+ if (paired) {
115
+ if (paired.pre) {
116
+ pairedAtNodes.push(...pair(paired.pre));
117
+ }
118
+ if (paired.body) {
119
+ if (id === 'supports') {
120
+ pairedAtNodes.push({
121
+ type: 'group',
122
+ children: [
123
+ {
124
+ type: 'string',
125
+ value: replaceCharOutsideQuotes(paired.body, '|', ' ')
126
+ }
127
+ ]
128
+ });
129
+ } else {
130
+ const children = pair(paired.body);
131
+ if (children.length > 1) {
132
+ pairedAtNodes.push({
133
+ type: 'group',
134
+ children: pair(paired.body)
135
+ });
136
+ } else {
137
+ pairedAtNodes.push(...children);
138
+ }
139
+ }
140
+ }
141
+ if (paired.post) {
142
+ pairedAtNodes.push(...pair(paired.post));
143
+ }
144
+ } else {
145
+ pairedAtNodes.push(...resolve(token));
146
+ }
147
+ return pairedAtNodes;
148
+ };
149
+ return {
150
+ nodes: pair(token),
151
+ id: id || 'media' // should be assigned to here
152
+ };
153
+ }
154
+
155
+ export { parseAt as default };
@@ -0,0 +1,51 @@
1
+ 'use strict';
2
+
3
+ function parsePair(str, a = '(', b = ')') {
4
+ const stack = [];
5
+ let result = null;
6
+ let inString = null;
7
+ for(let i = 0; i < str.length; i++){
8
+ const char = str[i];
9
+ const prevChar = str[i - 1];
10
+ // 處理 escape 字元,例如 \"
11
+ if (char === '\\') {
12
+ i++ // skip next character
13
+ ;
14
+ continue;
15
+ }
16
+ // 處理字串區段進入與離開
17
+ if ((char === '"' || char === '\'') && prevChar !== '\\') {
18
+ if (inString === char) {
19
+ inString = null // 離開字串
20
+ ;
21
+ } else if (!inString) {
22
+ inString = char // 進入字串
23
+ ;
24
+ }
25
+ continue;
26
+ }
27
+ if (inString) continue; // 若在字串中就忽略括號處理
28
+ // 開始符號
29
+ if (str.startsWith(a, i)) {
30
+ stack.push({
31
+ start: i
32
+ });
33
+ i += a.length - 1;
34
+ } else if (str.startsWith(b, i)) {
35
+ const last = stack.pop();
36
+ if (last) {
37
+ result = {
38
+ start: last.start,
39
+ end: i,
40
+ pre: str.slice(stack.length > 0 ? stack[stack.length - 1].start + a.length : 0, last.start),
41
+ body: str.slice(last.start + a.length, i),
42
+ post: str.slice(i + b.length)
43
+ };
44
+ }
45
+ i += b.length - 1;
46
+ }
47
+ }
48
+ return result;
49
+ }
50
+
51
+ module.exports = parsePair;
@@ -0,0 +1,8 @@
1
+ export interface ParsedPair {
2
+ start: number;
3
+ end: number;
4
+ pre: string;
5
+ body: string;
6
+ post: string;
7
+ }
8
+ export default function parsePair(str: string, a?: string, b?: string): ParsedPair | null;
@@ -0,0 +1,49 @@
1
+ function parsePair(str, a = '(', b = ')') {
2
+ const stack = [];
3
+ let result = null;
4
+ let inString = null;
5
+ for(let i = 0; i < str.length; i++){
6
+ const char = str[i];
7
+ const prevChar = str[i - 1];
8
+ // 處理 escape 字元,例如 \"
9
+ if (char === '\\') {
10
+ i++ // skip next character
11
+ ;
12
+ continue;
13
+ }
14
+ // 處理字串區段進入與離開
15
+ if ((char === '"' || char === '\'') && prevChar !== '\\') {
16
+ if (inString === char) {
17
+ inString = null // 離開字串
18
+ ;
19
+ } else if (!inString) {
20
+ inString = char // 進入字串
21
+ ;
22
+ }
23
+ continue;
24
+ }
25
+ if (inString) continue; // 若在字串中就忽略括號處理
26
+ // 開始符號
27
+ if (str.startsWith(a, i)) {
28
+ stack.push({
29
+ start: i
30
+ });
31
+ i += a.length - 1;
32
+ } else if (str.startsWith(b, i)) {
33
+ const last = stack.pop();
34
+ if (last) {
35
+ result = {
36
+ start: last.start,
37
+ end: i,
38
+ pre: str.slice(stack.length > 0 ? stack[stack.length - 1].start + a.length : 0, last.start),
39
+ body: str.slice(last.start + a.length, i),
40
+ post: str.slice(i + b.length)
41
+ };
42
+ }
43
+ i += b.length - 1;
44
+ }
45
+ }
46
+ return result;
47
+ }
48
+
49
+ export { parsePair as default };
@@ -0,0 +1,112 @@
1
+ 'use strict';
2
+
3
+ var common = require('../common.cjs');
4
+ var core = require('../core.cjs');
5
+ var parsePair = require('./parse-pair.cjs');
6
+
7
+ const SELECTOR_REGEX = new RegExp(`(?:[a-zA-Z0-9-]+)|([${common.SELECTOR_COMBINATORS.join('')}.:,])|(a-zA-Z0-9-)`, 'g');
8
+ function parseSelector(token, css = new core(), isRaw = true) {
9
+ const resolve = (eachToken)=>{
10
+ const nodes = [];
11
+ let currentPrefix = '';
12
+ let tokenIndex = 0;
13
+ for (const match of eachToken.matchAll(SELECTOR_REGEX)){
14
+ const raw = match[0];
15
+ tokenIndex += raw.length;
16
+ if (raw === ':' || raw === '.') {
17
+ currentPrefix += raw;
18
+ continue;
19
+ }
20
+ let type;
21
+ let value = raw;
22
+ const definedNodes = css.selectors.get(currentPrefix + raw);
23
+ if (definedNodes) {
24
+ const firstNode = definedNodes[definedNodes.length - 1];
25
+ nodes.push(definedNodes.length === 1 && firstNode.type ? {
26
+ ...firstNode,
27
+ raw: currentPrefix + raw
28
+ } : {
29
+ children: definedNodes,
30
+ raw: currentPrefix + raw
31
+ });
32
+ currentPrefix = '';
33
+ continue;
34
+ }
35
+ if (common.SELECTOR_COMBINATORS.includes(raw)) {
36
+ type = 'combinator';
37
+ if (raw === '_') {
38
+ const nextRawValue = eachToken[tokenIndex];
39
+ const prevRawValue = eachToken[tokenIndex - raw.length - 1];
40
+ if (prevRawValue !== '_' && nextRawValue !== '_') {
41
+ value = ' ' // support BEM __
42
+ ;
43
+ }
44
+ }
45
+ } else if (raw === ',') {
46
+ type = 'separator';
47
+ } else if (currentPrefix === ':') {
48
+ type = 'pseudo-class';
49
+ } else if (currentPrefix === '::') {
50
+ type = 'pseudo-element';
51
+ } else if (currentPrefix === '.') {
52
+ type = 'class';
53
+ }
54
+ nodes.push({
55
+ value,
56
+ ...isRaw && {
57
+ raw: currentPrefix + raw
58
+ },
59
+ ...type && {
60
+ type
61
+ }
62
+ });
63
+ currentPrefix = '';
64
+ }
65
+ return nodes;
66
+ };
67
+ const pair = (eachToken, nodes = [])=>{
68
+ const paired = parsePair(eachToken);
69
+ if (paired) {
70
+ let { pre, body, post } = paired;
71
+ let name;
72
+ if (body) {
73
+ const lastColonIndex = pre.lastIndexOf(':');
74
+ if (lastColonIndex !== -1) {
75
+ name = pre.slice(lastColonIndex);
76
+ pre = pre.slice(0, lastColonIndex);
77
+ }
78
+ }
79
+ if (pre) nodes.push(...pair(pre));
80
+ if (body) {
81
+ const children = pair(body);
82
+ if (name) {
83
+ const node = resolve(name)[0];
84
+ if (children.length) node.children = children;
85
+ nodes.push(node);
86
+ } else {
87
+ nodes.push(...children);
88
+ }
89
+ }
90
+ if (post) nodes.push(...pair(post));
91
+ return nodes;
92
+ }
93
+ const attrPaired = parsePair(eachToken, '[', ']');
94
+ if (attrPaired) {
95
+ const { pre, body, post } = attrPaired;
96
+ if (pre) nodes.push(...pair(pre));
97
+ nodes.push({
98
+ value: body,
99
+ type: 'attribute',
100
+ ...isRaw && {
101
+ raw: `[${body}]`
102
+ }
103
+ });
104
+ if (post) nodes.push(...pair(post));
105
+ return nodes;
106
+ }
107
+ return resolve(eachToken);
108
+ };
109
+ return pair(token);
110
+ }
111
+
112
+ module.exports = parseSelector;
@@ -0,0 +1,19 @@
1
+ import MasterCSS from '../core';
2
+ export declare type SelectorLiteralNode = {
3
+ type?: 'attribute' | 'pseudo-class' | 'pseudo-element' | 'class';
4
+ raw?: string;
5
+ value?: string;
6
+ children?: SelectorNode[];
7
+ };
8
+ export declare type SelectorSeparatorNode = {
9
+ type: 'separator';
10
+ raw?: string;
11
+ value: string;
12
+ };
13
+ export declare type SelectorCombinatorNode = {
14
+ type: 'combinator';
15
+ raw?: string;
16
+ value: string;
17
+ };
18
+ export declare type SelectorNode = SelectorLiteralNode | SelectorCombinatorNode | SelectorSeparatorNode;
19
+ export default function parseSelector(token: string, css?: MasterCSS, isRaw?: boolean): SelectorNode[];