cdui-js 1.0.9 → 1.0.10

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 (3) hide show
  1. package/build/css.ts +302 -302
  2. package/package.json +1 -1
  3. package/src/reactive.ts +75 -43
package/build/css.ts CHANGED
@@ -1,302 +1,302 @@
1
- import fs from 'fs';
2
-
3
- export interface Rule {
4
- match: string;
5
- build(outputs: string[], selector: string, value: string, before: string[]): void;
6
- }
7
-
8
- export const rules: Rule[] = [
9
- {
10
- match: '.margin',
11
- build: (outputs: string[], selector: string, value: string) => {
12
- outputs.push(`${selector} { margin: ${value} }`);
13
- outputs.push(`${selector.replace('margin', 'margin-t')} { margin-top: ${value}; }`);
14
- outputs.push(`${selector.replace('margin', 'margin-r')} { margin-right: ${value}; }`);
15
- outputs.push(`${selector.replace('margin', 'margin-b')} { margin-bottom: ${value}; }`);
16
- outputs.push(`${selector.replace('margin', 'margin-l')} { margin-left: ${value}; }`);
17
- outputs.push(`${selector.replace('margin', 'margin-x')} { margin-left: ${value}; margin-right: ${value}; }`);
18
- outputs.push(`${selector.replace('margin', 'margin-y')} { margin-top: ${value}; margin-bottom: ${value}; }\n`);
19
-
20
- outputs.push(`${selector.replace('margin', '-margin-t')} { margin-top: -${value}; }`);
21
- outputs.push(`${selector.replace('margin', '-margin-r')} { margin-right: -${value}; }`);
22
- outputs.push(`${selector.replace('margin', '-margin-b')} { margin-bottom: -${value}; }`);
23
- outputs.push(`${selector.replace('margin', '-margin-l')} { margin-left: -${value}; }`);
24
-
25
- outputs.push(`${selector.replace('margin', 'padding-m')} { padding: ${value}; }`);
26
- outputs.push(`${selector.replace('margin', 'padding-m-t')} { padding-top: ${value}; }`);
27
- outputs.push(`${selector.replace('margin', 'padding-m-r')} { padding-right: ${value}; }`);
28
- outputs.push(`${selector.replace('margin', 'padding-m-b')} { padding-bottom: ${value}; }`);
29
- outputs.push(`${selector.replace('margin', 'padding-m-l')} { padding-left: ${value}; }`);
30
- outputs.push(`${selector.replace('margin', 'padding-m-x')} { padding-left: ${value}; padding-right: ${value}; }`);
31
- outputs.push(
32
- `${selector.replace('margin', 'padding-m-y')} { padding-top: ${value}; padding-bottom: ${value}; }\n`,
33
- );
34
- },
35
- },
36
- {
37
- match: '.border-c',
38
- build: (outputs: string[], selector: string, value: string, before: string[]) => {
39
- if (selector === '.border-c') {
40
- before.push(`.border { border-color: ${value} }`);
41
- before.push(`.border-t { border-top-color: ${value} }`);
42
- before.push(`.border-r { border-right-color: ${value} }`);
43
- before.push(`.border-b { border-bottom-color: ${value} }`);
44
- before.push(`.border-l { border-left-color: ${value} }\n`);
45
- }
46
-
47
- outputs.push(`${selector} { border-color: ${value} }`);
48
- outputs.push(`${selector.replace('border-c', 'border-t-c')} { border-top-color: ${value}; }`);
49
- outputs.push(`${selector.replace('border-c', 'border-r-c')} { border-right-color: ${value}; }`);
50
- outputs.push(`${selector.replace('border-c', 'border-b-c')} { border-bottom-color: ${value}; }`);
51
- outputs.push(`${selector.replace('border-c', 'border-l-c')} { border-left-color: ${value}; }`);
52
- outputs.push(
53
- `${selector.replace('border-c', 'border-x-c')} { border-left-color: ${value}; border-right-color: ${value}; }`,
54
- );
55
- outputs.push(
56
- `${selector.replace('border-c', 'border-y-c')} { border-top-color: ${value}; border-bottom-color: ${value}; }`,
57
- );
58
- },
59
- },
60
- {
61
- match: '.border-s',
62
- build: (outputs: string[], selector: string, value: string) => {
63
- outputs.push(`${selector} { border-style: ${value} }`);
64
- outputs.push(`${selector.replace('border-s', 'border-t-s')} { border-top-style: ${value}; }`);
65
- outputs.push(`${selector.replace('border-s', 'border-r-s')} { border-right-style: ${value}; }`);
66
- outputs.push(`${selector.replace('border-s', 'border-b-s')} { border-bottom-style: ${value}; }`);
67
- outputs.push(`${selector.replace('border-s', 'border-l-s')} { border-left-style: ${value}; }`);
68
- outputs.push(
69
- `${selector.replace('border-s', 'border-x-s')} { border-left-style: ${value}; border-right-style: ${value}; }`,
70
- );
71
- outputs.push(
72
- `${selector.replace('border-s', 'border-y-s')} { border-top-style: ${value}; border-bottom-style: ${value}; }`,
73
- );
74
- },
75
- },
76
- {
77
- match: '.border',
78
- build: (outputs: string[], selector: string, value: string) => {
79
- outputs.push(`${selector} { border-width: ${value}; border-style: solid; }`);
80
- outputs.push(
81
- `${selector.replace('border', 'border-t')} { border-top-width: ${value}; border-top-style: solid; }`,
82
- );
83
- outputs.push(
84
- `${selector.replace('border', 'border-r')} { border-right-width: ${value}; border-right-style: solid; }`,
85
- );
86
- outputs.push(
87
- `${selector.replace('border', 'border-b')} { border-bottom-width: ${value}; border-bottom-style: solid; }`,
88
- );
89
- outputs.push(
90
- `${selector.replace('border', 'border-l')} { border-left-width: ${value}; border-left-style: solid; }`,
91
- );
92
- outputs.push(
93
- `${selector.replace('border', 'border-x')} { border-left-width: ${value}; border-right-width: ${value}; border-left-style: solid; border-right-style: solid; }`,
94
- );
95
- outputs.push(
96
- `${selector.replace('border', 'border-y')} { border-top-width: ${value}; border-bottom-width: ${value}; border-top-style: solid; border-bottom-style: solid; }`,
97
- );
98
- },
99
- },
100
- {
101
- match: '.round',
102
- build: (outputs: string[], selector: string, value: string) => {
103
- outputs.push(`${selector} { border-radius: ${value} }`);
104
- },
105
- },
106
- {
107
- match: '.padding',
108
- build: (outputs: string[], selector: string, value: string) => {
109
- outputs.push(`${selector} { padding: ${value} }`);
110
- outputs.push(`${selector.replace('padding', 'padding-t')} { padding-top: ${value}; }`);
111
- outputs.push(`${selector.replace('padding', 'padding-r')} { padding-right: ${value}; }`);
112
- outputs.push(`${selector.replace('padding', 'padding-b')} { padding-bottom: ${value}; }`);
113
- outputs.push(`${selector.replace('padding', 'padding-l')} { padding-left: ${value}; }`);
114
- outputs.push(`${selector.replace('padding', 'padding-x')} { padding-left: ${value}; padding-right: ${value}; }`);
115
- outputs.push(
116
- `${selector.replace('padding', 'padding-y')} { padding-top: ${value}; padding-bottom: ${value}; }\n`,
117
- );
118
- },
119
- },
120
- {
121
- match: '.bg-c',
122
- build: (outputs: string[], selector: string, value: string) => {
123
- outputs.push(`${selector} { background-color: ${value} }`);
124
- },
125
- },
126
- {
127
- match: '.color',
128
- build: (outputs: string[], selector: string, value: string) => {
129
- outputs.push(`${selector} { color: ${value} }`);
130
- },
131
- },
132
- {
133
- match: '.font-s',
134
- build: (outputs: string[], selector: string, value: string) => {
135
- outputs.push(`${selector} { font-size: ${value} }`);
136
- },
137
- },
138
- {
139
- match: '.font',
140
- build: (outputs: string[], selector: string, value: string) => {
141
- outputs.push(`${selector} { font-weight: ${value} }`);
142
- },
143
- },
144
- {
145
- match: '.icon-c',
146
- build: (outputs: string[], selector: string, value: string, before: string[]) => {
147
- if (selector === '.icon-c') {
148
- before.push(`body { stroke: ${value}; fill: ${value}; }\n.icon { stroke: inherit; fill: inherit; }`);
149
- }
150
-
151
- outputs.push(`${selector} { stroke: ${value}; fill: ${value}; }`);
152
- },
153
- },
154
- {
155
- match: '.icon-s',
156
- build: (outputs: string[], selector: string, value: string, before: string[]) => {
157
- if (selector === '.icon-s') {
158
- before.push(`.icon { width: ${value}; height: ${value}; }\n`);
159
- }
160
-
161
- outputs.push(`${selector} .icon { width: ${value}; height: ${value}; }`);
162
- outputs.push(`${selector}.icon { width: ${value}; height: ${value}; }`);
163
- },
164
- },
165
- {
166
- match: '.button',
167
- build: (outputs: string[], selector: string, value: string) => {
168
- outputs.push(`${selector} { ${value} }`);
169
- },
170
- },
171
- {
172
- match: '.link',
173
- build: (outputs: string[], selector: string, value: string) => {
174
- if (selector === '.link') {
175
- outputs.push(`a, .link { ${value} }`);
176
- } else {
177
- outputs.push(`${selector} { ${value} }`);
178
- }
179
- },
180
- },
181
- ];
182
-
183
- const findRule = (name: string) => {
184
- for (let i = 0, l = rules.length; i < l; i++) {
185
- if (name.startsWith(rules[i].match)) {
186
- return rules[i];
187
- }
188
- }
189
- };
190
-
191
- const parse = (
192
- rule: Rule,
193
- outputs: string[],
194
- selectorPrefix: string,
195
- name: string,
196
- value: string,
197
- before: string[],
198
- ) => {
199
- if (name.endsWith('-hover')) {
200
- rule.build(outputs, selectorPrefix + name + ':hover', value, before);
201
- rule.build(outputs, selectorPrefix + '.hover:hover ' + name, value, before);
202
- return;
203
- }
204
-
205
- if (name.endsWith('-active')) {
206
- rule.build(outputs, selectorPrefix + name + ':active', value, before);
207
- rule.build(outputs, selectorPrefix + '.active:active ' + name, value, before);
208
- return;
209
- }
210
-
211
- if (name.endsWith('-focus')) {
212
- rule.build(outputs, selectorPrefix + name + ':focus', value, before);
213
- rule.build(outputs, selectorPrefix + '.focus:focus ' + name, value, before);
214
- return;
215
- }
216
-
217
- if (name.endsWith('-selected')) {
218
- rule.build(outputs, selectorPrefix + name + '.selected', value, before);
219
- rule.build(outputs, selectorPrefix + '.selected ' + name, value, before);
220
- return;
221
- }
222
-
223
- rule.build(outputs, selectorPrefix + name, value, before);
224
- };
225
-
226
- /**
227
- * 解析 CSS 规范生成原子样式
228
- *
229
- * @param cssRuleFile CSS 规范文件路径(markdown规范文档)
230
- * @param cssFile 写 css 文件路径
231
- */
232
- export const buildCSS = (cssRuleFile: string, cssFile?: string) => {
233
- let css = fs.readFileSync(cssRuleFile, 'utf8');
234
- let lines = css.split(/\r?\n\s*/);
235
- let selectorPrefix = '';
236
- let outputs = [];
237
- let before = [];
238
-
239
- for (let i = 0, l = lines.length; i < l; i++) {
240
- let line = lines[i].trim();
241
-
242
- switch (line[0] || '') {
243
- case '.':
244
- let index = line.indexOf('{');
245
- let name, value, rule: Rule;
246
-
247
- // 样式组
248
- if (index > 0 && (name = line.slice(0, index).trim()) && (rule = findRule(name))) {
249
- value = line.slice(index + 1);
250
-
251
- if ((value = value.replace(/}\s*\;*\s*/, '').trim())) {
252
- rule.build(outputs, selectorPrefix + name, value, before);
253
- }
254
-
255
- continue;
256
- }
257
-
258
- // 单样式值
259
- if ((index = line.indexOf(':')) > 0 && (name = line.slice(0, index).trim()) && (rule = findRule(name))) {
260
- value = line
261
- .slice(index + 1)
262
- .replace(/;\s*/g, '')
263
- .trim();
264
-
265
- if (value && value !== '#') {
266
- parse(rule, outputs, selectorPrefix, name, value, before);
267
- }
268
-
269
- continue;
270
- }
271
-
272
- console.error('不合法的格式:' + lines[i]);
273
- break;
274
-
275
- case '+': // 上级选择器
276
- selectorPrefix = line.slice(1).trim() + ' ';
277
- outputs.push('\n');
278
- break;
279
-
280
- case '#': // 新的分组
281
- selectorPrefix = '';
282
- outputs.push('\n');
283
- break;
284
-
285
- case '>':
286
- case '':
287
- break;
288
-
289
- default:
290
- console.error('不合法的格式:' + lines[i]);
291
- }
292
- }
293
-
294
- outputs.unshift(...before);
295
- css = outputs.join('\n');
296
-
297
- if (cssFile) {
298
- fs.writeFileSync(cssFile, css, 'utf8');
299
- }
300
-
301
- return css;
302
- };
1
+ import fs from 'fs';
2
+
3
+ export interface Rule {
4
+ match: string;
5
+ build(outputs: string[], selector: string, value: string, before: string[]): void;
6
+ }
7
+
8
+ export const rules: Rule[] = [
9
+ {
10
+ match: '.margin',
11
+ build: (outputs: string[], selector: string, value: string) => {
12
+ outputs.push(`${selector} { margin: ${value} }`);
13
+ outputs.push(`${selector.replace('margin', 'margin-t')} { margin-top: ${value}; }`);
14
+ outputs.push(`${selector.replace('margin', 'margin-r')} { margin-right: ${value}; }`);
15
+ outputs.push(`${selector.replace('margin', 'margin-b')} { margin-bottom: ${value}; }`);
16
+ outputs.push(`${selector.replace('margin', 'margin-l')} { margin-left: ${value}; }`);
17
+ outputs.push(`${selector.replace('margin', 'margin-x')} { margin-left: ${value}; margin-right: ${value}; }`);
18
+ outputs.push(`${selector.replace('margin', 'margin-y')} { margin-top: ${value}; margin-bottom: ${value}; }\n`);
19
+
20
+ outputs.push(`${selector.replace('margin', '-margin-t')} { margin-top: -${value}; }`);
21
+ outputs.push(`${selector.replace('margin', '-margin-r')} { margin-right: -${value}; }`);
22
+ outputs.push(`${selector.replace('margin', '-margin-b')} { margin-bottom: -${value}; }`);
23
+ outputs.push(`${selector.replace('margin', '-margin-l')} { margin-left: -${value}; }`);
24
+
25
+ outputs.push(`${selector.replace('margin', 'padding-m')} { padding: ${value}; }`);
26
+ outputs.push(`${selector.replace('margin', 'padding-m-t')} { padding-top: ${value}; }`);
27
+ outputs.push(`${selector.replace('margin', 'padding-m-r')} { padding-right: ${value}; }`);
28
+ outputs.push(`${selector.replace('margin', 'padding-m-b')} { padding-bottom: ${value}; }`);
29
+ outputs.push(`${selector.replace('margin', 'padding-m-l')} { padding-left: ${value}; }`);
30
+ outputs.push(`${selector.replace('margin', 'padding-m-x')} { padding-left: ${value}; padding-right: ${value}; }`);
31
+ outputs.push(
32
+ `${selector.replace('margin', 'padding-m-y')} { padding-top: ${value}; padding-bottom: ${value}; }\n`,
33
+ );
34
+ },
35
+ },
36
+ {
37
+ match: '.border-c',
38
+ build: (outputs: string[], selector: string, value: string, before: string[]) => {
39
+ if (selector === '.border-c') {
40
+ before.push(`.border { border-color: ${value} }`);
41
+ before.push(`.border-t { border-top-color: ${value} }`);
42
+ before.push(`.border-r { border-right-color: ${value} }`);
43
+ before.push(`.border-b { border-bottom-color: ${value} }`);
44
+ before.push(`.border-l { border-left-color: ${value} }\n`);
45
+ }
46
+
47
+ outputs.push(`${selector} { border-color: ${value} }`);
48
+ outputs.push(`${selector.replace('border-c', 'border-t-c')} { border-top-color: ${value}; }`);
49
+ outputs.push(`${selector.replace('border-c', 'border-r-c')} { border-right-color: ${value}; }`);
50
+ outputs.push(`${selector.replace('border-c', 'border-b-c')} { border-bottom-color: ${value}; }`);
51
+ outputs.push(`${selector.replace('border-c', 'border-l-c')} { border-left-color: ${value}; }`);
52
+ outputs.push(
53
+ `${selector.replace('border-c', 'border-x-c')} { border-left-color: ${value}; border-right-color: ${value}; }`,
54
+ );
55
+ outputs.push(
56
+ `${selector.replace('border-c', 'border-y-c')} { border-top-color: ${value}; border-bottom-color: ${value}; }`,
57
+ );
58
+ },
59
+ },
60
+ {
61
+ match: '.border-s',
62
+ build: (outputs: string[], selector: string, value: string) => {
63
+ outputs.push(`${selector} { border-style: ${value} }`);
64
+ outputs.push(`${selector.replace('border-s', 'border-t-s')} { border-top-style: ${value}; }`);
65
+ outputs.push(`${selector.replace('border-s', 'border-r-s')} { border-right-style: ${value}; }`);
66
+ outputs.push(`${selector.replace('border-s', 'border-b-s')} { border-bottom-style: ${value}; }`);
67
+ outputs.push(`${selector.replace('border-s', 'border-l-s')} { border-left-style: ${value}; }`);
68
+ outputs.push(
69
+ `${selector.replace('border-s', 'border-x-s')} { border-left-style: ${value}; border-right-style: ${value}; }`,
70
+ );
71
+ outputs.push(
72
+ `${selector.replace('border-s', 'border-y-s')} { border-top-style: ${value}; border-bottom-style: ${value}; }`,
73
+ );
74
+ },
75
+ },
76
+ {
77
+ match: '.border',
78
+ build: (outputs: string[], selector: string, value: string) => {
79
+ outputs.push(`${selector} { border-width: ${value}; border-style: solid; }`);
80
+ outputs.push(
81
+ `${selector.replace('border', 'border-t')} { border-top-width: ${value}; border-top-style: solid; }`,
82
+ );
83
+ outputs.push(
84
+ `${selector.replace('border', 'border-r')} { border-right-width: ${value}; border-right-style: solid; }`,
85
+ );
86
+ outputs.push(
87
+ `${selector.replace('border', 'border-b')} { border-bottom-width: ${value}; border-bottom-style: solid; }`,
88
+ );
89
+ outputs.push(
90
+ `${selector.replace('border', 'border-l')} { border-left-width: ${value}; border-left-style: solid; }`,
91
+ );
92
+ outputs.push(
93
+ `${selector.replace('border', 'border-x')} { border-left-width: ${value}; border-right-width: ${value}; border-left-style: solid; border-right-style: solid; }`,
94
+ );
95
+ outputs.push(
96
+ `${selector.replace('border', 'border-y')} { border-top-width: ${value}; border-bottom-width: ${value}; border-top-style: solid; border-bottom-style: solid; }`,
97
+ );
98
+ },
99
+ },
100
+ {
101
+ match: '.round',
102
+ build: (outputs: string[], selector: string, value: string) => {
103
+ outputs.push(`${selector} { border-radius: ${value} }`);
104
+ },
105
+ },
106
+ {
107
+ match: '.padding',
108
+ build: (outputs: string[], selector: string, value: string) => {
109
+ outputs.push(`${selector} { padding: ${value} }`);
110
+ outputs.push(`${selector.replace('padding', 'padding-t')} { padding-top: ${value}; }`);
111
+ outputs.push(`${selector.replace('padding', 'padding-r')} { padding-right: ${value}; }`);
112
+ outputs.push(`${selector.replace('padding', 'padding-b')} { padding-bottom: ${value}; }`);
113
+ outputs.push(`${selector.replace('padding', 'padding-l')} { padding-left: ${value}; }`);
114
+ outputs.push(`${selector.replace('padding', 'padding-x')} { padding-left: ${value}; padding-right: ${value}; }`);
115
+ outputs.push(
116
+ `${selector.replace('padding', 'padding-y')} { padding-top: ${value}; padding-bottom: ${value}; }\n`,
117
+ );
118
+ },
119
+ },
120
+ {
121
+ match: '.bg-c',
122
+ build: (outputs: string[], selector: string, value: string) => {
123
+ outputs.push(`${selector} { background-color: ${value} }`);
124
+ },
125
+ },
126
+ {
127
+ match: '.color',
128
+ build: (outputs: string[], selector: string, value: string) => {
129
+ outputs.push(`${selector} { color: ${value} }`);
130
+ },
131
+ },
132
+ {
133
+ match: '.font-s',
134
+ build: (outputs: string[], selector: string, value: string) => {
135
+ outputs.push(`${selector} { font-size: ${value} }`);
136
+ },
137
+ },
138
+ {
139
+ match: '.font',
140
+ build: (outputs: string[], selector: string, value: string) => {
141
+ outputs.push(`${selector} { font-weight: ${value} }`);
142
+ },
143
+ },
144
+ {
145
+ match: '.icon-c',
146
+ build: (outputs: string[], selector: string, value: string, before: string[]) => {
147
+ if (selector === '.icon-c') {
148
+ before.push(`body { stroke: ${value}; fill: ${value}; }\n.icon { stroke: inherit; fill: inherit; }`);
149
+ }
150
+
151
+ outputs.push(`${selector} { stroke: ${value}; fill: ${value}; }`);
152
+ },
153
+ },
154
+ {
155
+ match: '.icon-s',
156
+ build: (outputs: string[], selector: string, value: string, before: string[]) => {
157
+ if (selector === '.icon-s') {
158
+ before.push(`.icon { width: ${value}; height: ${value}; }\n`);
159
+ }
160
+
161
+ outputs.push(`${selector} .icon { width: ${value}; height: ${value}; }`);
162
+ outputs.push(`${selector}.icon { width: ${value}; height: ${value}; }`);
163
+ },
164
+ },
165
+ {
166
+ match: '.button',
167
+ build: (outputs: string[], selector: string, value: string) => {
168
+ outputs.push(`${selector} { ${value} }`);
169
+ },
170
+ },
171
+ {
172
+ match: '.link',
173
+ build: (outputs: string[], selector: string, value: string) => {
174
+ if (selector === '.link') {
175
+ outputs.push(`a, .link { ${value} }`);
176
+ } else {
177
+ outputs.push(`${selector} { ${value} }`);
178
+ }
179
+ },
180
+ },
181
+ ];
182
+
183
+ const findRule = (name: string) => {
184
+ for (let i = 0, l = rules.length; i < l; i++) {
185
+ if (name.startsWith(rules[i].match)) {
186
+ return rules[i];
187
+ }
188
+ }
189
+ };
190
+
191
+ const parse = (
192
+ rule: Rule,
193
+ outputs: string[],
194
+ selectorPrefix: string,
195
+ name: string,
196
+ value: string,
197
+ before: string[],
198
+ ) => {
199
+ if (name.endsWith('-hover')) {
200
+ rule.build(outputs, selectorPrefix + name + ':hover', value, before);
201
+ rule.build(outputs, selectorPrefix + '.hover:hover ' + name, value, before);
202
+ return;
203
+ }
204
+
205
+ if (name.endsWith('-active')) {
206
+ rule.build(outputs, selectorPrefix + name + ':active', value, before);
207
+ rule.build(outputs, selectorPrefix + '.active:active ' + name, value, before);
208
+ return;
209
+ }
210
+
211
+ if (name.endsWith('-focus')) {
212
+ rule.build(outputs, selectorPrefix + name + ':focus', value, before);
213
+ rule.build(outputs, selectorPrefix + '.focus:focus ' + name, value, before);
214
+ return;
215
+ }
216
+
217
+ if (name.endsWith('-selected')) {
218
+ rule.build(outputs, selectorPrefix + name + '.selected', value, before);
219
+ rule.build(outputs, selectorPrefix + '.selected ' + name, value, before);
220
+ return;
221
+ }
222
+
223
+ rule.build(outputs, selectorPrefix + name, value, before);
224
+ };
225
+
226
+ /**
227
+ * 解析 CSS 规范生成原子样式
228
+ *
229
+ * @param cssRuleFile CSS 规范文件路径(markdown规范文档)
230
+ * @param cssFile 写 css 文件路径
231
+ */
232
+ export const buildCSS = (cssRuleFile: string, cssFile?: string) => {
233
+ let css = fs.readFileSync(cssRuleFile, 'utf8');
234
+ let lines = css.split(/\r?\n\s*/);
235
+ let selectorPrefix = '';
236
+ let outputs = [];
237
+ let before = [];
238
+
239
+ for (let i = 0, l = lines.length; i < l; i++) {
240
+ let line = lines[i].trim();
241
+
242
+ switch (line[0] || '') {
243
+ case '.':
244
+ let index = line.indexOf('{');
245
+ let name, value, rule: Rule;
246
+
247
+ // 样式组
248
+ if (index > 0 && (name = line.slice(0, index).trim()) && (rule = findRule(name))) {
249
+ value = line.slice(index + 1);
250
+
251
+ if ((value = value.replace(/}\s*\;*\s*/, '').trim())) {
252
+ rule.build(outputs, selectorPrefix + name, value, before);
253
+ }
254
+
255
+ continue;
256
+ }
257
+
258
+ // 单样式值
259
+ if ((index = line.indexOf(':')) > 0 && (name = line.slice(0, index).trim()) && (rule = findRule(name))) {
260
+ value = line
261
+ .slice(index + 1)
262
+ .replace(/;\s*/g, '')
263
+ .trim();
264
+
265
+ if (value && value !== '#') {
266
+ parse(rule, outputs, selectorPrefix, name, value, before);
267
+ }
268
+
269
+ continue;
270
+ }
271
+
272
+ console.error('不合法的格式:' + lines[i]);
273
+ break;
274
+
275
+ case '+': // 上级选择器
276
+ selectorPrefix = line.slice(1).trim() + ' ';
277
+ outputs.push('\n');
278
+ break;
279
+
280
+ case '#': // 新的分组
281
+ selectorPrefix = '';
282
+ outputs.push('\n');
283
+ break;
284
+
285
+ case '>':
286
+ case '':
287
+ break;
288
+
289
+ default:
290
+ console.error('不合法的格式:' + lines[i]);
291
+ }
292
+ }
293
+
294
+ outputs.unshift(...before);
295
+ css = outputs.join('\n');
296
+
297
+ if (cssFile) {
298
+ fs.writeFileSync(cssFile, css, 'utf8');
299
+ }
300
+
301
+ return css;
302
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cdui-js",
3
- "version": "1.0.9",
3
+ "version": "1.0.10",
4
4
  "type": "module",
5
5
  "main": "src/index.ts",
6
6
  "bin": {
package/src/reactive.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Component, createEffect, createSignal, createUniqueId, lazy, untrack } from 'solid-js';
1
+ import { Component, createEffect, createSignal, createUniqueId, lazy } from 'solid-js';
2
2
 
3
3
  export const defineProperty = Object.defineProperty;
4
4
  export const defineProperties = Object.defineProperties;
@@ -64,7 +64,13 @@ export interface SSRRenderPage {
64
64
  abort?: boolean;
65
65
  }
66
66
 
67
+ /**
68
+ * 信息参数(不对比值变化)
69
+ */
67
70
  const signalOptions: any = { equals: false, internal: true };
71
+ /**
72
+ * 对象与代理对象映射
73
+ */
68
74
  const proxyMap = new WeakMap();
69
75
 
70
76
  const arrayToKeys = (names: string[]) => {
@@ -77,6 +83,9 @@ const arrayToKeys = (names: string[]) => {
77
83
  return result;
78
84
  };
79
85
 
86
+ /**
87
+ * 对数组子项有响应的方法
88
+ */
80
89
  const arrayMutationMethods = arrayToKeys([
81
90
  'push',
82
91
  'pop',
@@ -95,6 +104,7 @@ function arrayProxyGetHandler(target: any, property: any, receiver) {
95
104
 
96
105
  // 拦截索引访问
97
106
  if (index >= 0) {
107
+ // 简单值
98
108
  if (typeof value !== 'object' || !value) {
99
109
  return value;
100
110
  }
@@ -104,7 +114,13 @@ function arrayProxyGetHandler(target: any, property: any, receiver) {
104
114
  return value;
105
115
  }
106
116
 
107
- return proxyMap.get(value) || (isArray(value) ? createArraySignal(value)[0]() : reactiveObject(value));
117
+ return proxyMap.get(value) || (!isArray(value) ? reactiveObject(value) : reactiveArray(value));
118
+ }
119
+
120
+ if (property === 'length') {
121
+ // 收集依赖
122
+ this.signal[0]();
123
+ return value;
108
124
  }
109
125
 
110
126
  if (property === '__raw__') {
@@ -113,14 +129,13 @@ function arrayProxyGetHandler(target: any, property: any, receiver) {
113
129
 
114
130
  if (typeof value === 'function') {
115
131
  if (arrayMutationMethods[property]) {
116
- let handler = this;
117
- let set = handler.fn;
132
+ let set = this.signal[1];
118
133
 
119
134
  return function () {
120
135
  let result = value.apply(target, arguments);
121
136
 
122
137
  // 触发更新
123
- set(receiver);
138
+ set(true);
124
139
  return result !== target ? result : receiver;
125
140
  };
126
141
  }
@@ -132,57 +147,50 @@ function arrayProxyGetHandler(target: any, property: any, receiver) {
132
147
  return value;
133
148
  }
134
149
 
135
- function arrayProxySetHandler(target: any, property: any, value, receiver) {
150
+ function arrayProxySetHandler(target: any, property: any, value) {
136
151
  let index = typeof property === 'string' && +property;
137
152
 
138
153
  // 如果是通过索引设置值
139
154
  if (property >= 0) {
140
- target[index] = value;
155
+ // 值有变化
156
+ if (target[index] !== value) {
157
+ target[index] = value;
158
+ // 触发更新
159
+ this.signal[1](true);
160
+ }
141
161
 
142
- // 触发更新
143
- this.fn(receiver);
144
162
  return true;
145
163
  }
146
164
 
147
165
  // 如果设置的是length属性
148
166
  if (property === 'length') {
167
+ // 长度有变化
149
168
  if (target.length !== value) {
150
169
  target.length = value;
151
-
152
170
  // 触发更新
153
- this.fn(receiver);
171
+ this.signal[1](true);
154
172
  return true;
155
173
  }
156
174
 
157
175
  return true;
158
176
  }
159
177
 
160
- return Reflect.set(target, property, value, receiver);
178
+ return target[property];
161
179
  }
162
180
 
163
- const createArraySignal = (value: any[]) => {
164
- let handler = { get: arrayProxyGetHandler, set: arrayProxySetHandler, fn: null };
165
- let proxy = new Proxy(value, handler);
166
- let signal = createSignal(proxy, signalOptions);
167
-
168
- handler.fn = signal[1];
169
-
170
- return signal;
171
- };
172
-
173
- const initSignal = (signals, property, value) => {
174
- return (signals[property] =
175
- typeof value !== 'object' || !isArray(value) ? createSignal(value) : createArraySignal(value));
176
- };
177
-
178
- const reactiveObject = (object) => {
181
+ const reactiveObject = (object: object) => {
179
182
  const signals = create(null);
180
183
 
181
184
  const proxy = new Proxy(object, {
182
- get(target, property, receiver) {
185
+ get(target, property) {
183
186
  if (property !== '__raw__') {
184
- let value = (signals[property] || initSignal(signals, property, target[property]))[0]();
187
+ let signal = signals[property] || (signals[property] = createSignal(true, signalOptions));
188
+ let value = target[property];
189
+
190
+ // 收集依赖
191
+ signal[0]();
185
192
 
193
+ // 值类型
186
194
  if (typeof value !== 'object' || !value) {
187
195
  return value;
188
196
  }
@@ -192,18 +200,29 @@ const reactiveObject = (object) => {
192
200
  return value;
193
201
  }
194
202
 
195
- return proxyMap.get(value) || (isArray(value) ? createArraySignal(value)[0]() : reactiveObject(value));
203
+ return proxyMap.get(value) || (!isArray(value) ? reactiveObject(value) : reactiveArray(value));
196
204
  }
197
205
 
198
206
  return target;
199
207
  },
200
208
 
201
- set(target, property, value, receiver) {
202
- if (value && typeof value === 'object') {
209
+ set(target, property, value) {
210
+ let sign = signals[property];
211
+
212
+ // 只存储原始数据
213
+ if (typeof value === 'object' && value) {
203
214
  value = value.__raw__ || value;
204
215
  }
205
216
 
206
- (signals[property] || initSignal(signals, property, target[property]))[1]((target[property] = value));
217
+ // 有收集依赖且值有变化
218
+ if (sign && value !== target[property]) {
219
+ target[property] = value;
220
+ // 触发更新
221
+ sign[1](true);
222
+ } else {
223
+ target[property] = value;
224
+ }
225
+
207
226
  return true;
208
227
  },
209
228
 
@@ -217,26 +236,39 @@ const reactiveObject = (object) => {
217
236
  return proxy;
218
237
  };
219
238
 
220
- const throwReactiveError = () => {
221
- throw new Error(`Array cannot directly create reactive object,Please use like: reactive({ items: [] })`);
239
+ const reactiveArray = (array: any[]) => {
240
+ let proxy = new Proxy(array, {
241
+ get: arrayProxyGetHandler,
242
+ set: arrayProxySetHandler,
243
+ signal: createSignal(true, signalOptions),
244
+ } as any);
245
+
246
+ proxyMap.set(array, proxy);
247
+ return proxy;
222
248
  };
223
249
 
250
+ /**
251
+ * 响应式代理类型
252
+ */
253
+ export type ReactiveProxy<T> = T extends object ? (T extends any[] ? { value: T } : T) : { value: T };
254
+
224
255
  /**
225
256
  * 创建响应式对象
226
257
  *
227
- * @param object 要封装为响应的对象
258
+ * @param value 要封装为响应式的数据
228
259
  */
229
- export const reactive = <T extends { [key: string]: any }>(object: T extends any[] ? never : T): T => {
230
- if (object && typeof object === 'object') {
260
+ export const reactive = <T>(value: T): ReactiveProxy<T> => {
261
+ if (typeof value === 'object' && value) {
231
262
  // 已经是代理对象
232
- if (object.__raw__) {
233
- return object;
263
+ // @ts-ignore
264
+ if (value.__raw__) {
265
+ return value as ReactiveProxy<T>;
234
266
  }
235
267
 
236
- return proxyMap.get(object) || (!isArray(object) && reactiveObject(object)) || throwReactiveError();
268
+ return proxyMap.get(value) || reactiveObject(!isArray(value) ? value : { value });
237
269
  }
238
270
 
239
- throw new Error(`${object} can not create reactive object`);
271
+ return reactiveObject({ value }) as ReactiveProxy<T>;
240
272
  };
241
273
 
242
274
  /**