@love-sqjm/magic 2026.4.15

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 (56) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +93 -0
  3. package/app.js +51 -0
  4. package/doc/api/examples.md +563 -0
  5. package/doc/api/index.md +563 -0
  6. package/doc/architecture.md +322 -0
  7. package/doc/config-reference.md +646 -0
  8. package/doc/data-model.md +622 -0
  9. package/doc/development-guide.md +582 -0
  10. package/doc/magic-file/index.md +610 -0
  11. package/doc/user-guide/index.md +485 -0
  12. package/doc/workflow.md +548 -0
  13. package/index.js +157 -0
  14. package/magic.bat +2 -0
  15. package/magic.ps1 +5 -0
  16. package/package.json +44 -0
  17. package/script/build-project.js +16 -0
  18. package/script/config.js +23 -0
  19. package/script/create-project.js +73 -0
  20. package/script/global/printf.js +13 -0
  21. package/script/global/project-build-config.js +161 -0
  22. package/script/global/support-platform.js +5 -0
  23. package/script/module/compiler/global.js +43 -0
  24. package/script/module/compiler/id-generate.js +18 -0
  25. package/script/module/compiler/index-dom.js +78 -0
  26. package/script/module/compiler/macro-replace.js +22 -0
  27. package/script/module/compiler/macro.js +6 -0
  28. package/script/module/compiler/start.js +10 -0
  29. package/script/module/compiler/step/1.js +253 -0
  30. package/script/module/compiler/step/2.js +79 -0
  31. package/script/module/compiler/step/3.js +37 -0
  32. package/script/module/compiler/step/4.js +20 -0
  33. package/script/module/compiler/step/5.js +634 -0
  34. package/script/module/compiler/step/6.js +304 -0
  35. package/script/module/compiler/step/end.js +124 -0
  36. package/script/run-project.js +249 -0
  37. package/script/util/bun-fs.js +40 -0
  38. package/script/util/copy-dir.js +21 -0
  39. package/script/util/create-simple-dom-element.js +23 -0
  40. package/script/util/file-util.js +95 -0
  41. package/script/util/filtration-file.js +20 -0
  42. package/script/util/get-dir-all-file.js +28 -0
  43. package/script/util/get-first-object-key.js +9 -0
  44. package/script/util/is-empty-object.js +8 -0
  45. package/script/util/is-string-over-size.js +4 -0
  46. package/script/util/is.js +18 -0
  47. package/script/util/logging.js +142 -0
  48. package/script/util/task.js +16 -0
  49. package/script/util/traversal.js +28 -0
  50. package/template/platform-config/node-webkit +23 -0
  51. package/template/platform-config/web +1 -0
  52. package/template/project-base/app.xml +5 -0
  53. package/template/project-base/build.module.toml +37 -0
  54. package/template/project-base/build.toml +43 -0
  55. package/template/runtime/runtime.css +3 -0
  56. package/template/runtime/runtime.js +895 -0
@@ -0,0 +1,622 @@
1
+ # Magic 数据模型文档
2
+
3
+ ## 概述
4
+
5
+ 本文档描述 Magic 框架的核心数据模型和内部状态结构。
6
+
7
+ ---
8
+
9
+ ## 1. 编译器数据模型
10
+
11
+ ### 1.1 全局项目状态 (project)
12
+
13
+ 位置: `script/module/compiler/global.js`
14
+
15
+ ```typescript
16
+ const project = {
17
+ // 构建配置
18
+ build_config: {
19
+ config: {
20
+ name: string, // 项目名称
21
+ src: string, // 源码目录
22
+ main: string // 入口文件
23
+ },
24
+ build: {
25
+ out: string, // 输出目录
26
+ model: "debug"|"release", // 构建模式
27
+ platform: {
28
+ target: string, // 目标平台
29
+ config: object // 平台配置
30
+ },
31
+ exclude: {
32
+ dir: string[], // 排除目录
33
+ file: string[] // 排除文件
34
+ },
35
+ optimize: {
36
+ "min-code": {
37
+ js: boolean,
38
+ css: boolean,
39
+ html: boolean
40
+ },
41
+ "out-default-theme": boolean
42
+ }
43
+ }
44
+ },
45
+
46
+ // 应用配置
47
+ app_config: {
48
+ title: string, // 页面标题
49
+ lang: string, // 语言
50
+ icon: string | false, // 图标
51
+ initScript: string | null, // 初始化脚本
52
+ import: importItem[] // 导入列表
53
+ },
54
+
55
+ // 源文件映射
56
+ source_file: {
57
+ [ext: string]: source[], // 按扩展名分组
58
+ "*it": () => source[] // 迭代所有文件
59
+ },
60
+
61
+ // DOM 索引
62
+ index_dom: IndexDom,
63
+
64
+ // 目录路径
65
+ outDir: string, // 输出目录
66
+ outDirMagic: string, // magic 目录
67
+ srcDir: string // 源码目录
68
+ };
69
+ ```
70
+
71
+ ### 1.2 source 类
72
+
73
+ ```typescript
74
+ class source {
75
+ ext: string; // 文件扩展名
76
+
77
+ // 获取构建输出路径
78
+ build(): string;
79
+
80
+ // 获取相对路径
81
+ relative(): string;
82
+
83
+ // 获取绝对路径
84
+ absolute(): string;
85
+ }
86
+ ```
87
+
88
+ ### 1.3 mData 类
89
+
90
+ `.m` 文件编译时的中间数据结构。
91
+
92
+ ```typescript
93
+ class mData {
94
+ data: {
95
+ // 导入
96
+ import: {
97
+ [namespace: string]: {
98
+ [tagName: string]: string // 路径
99
+ }
100
+ },
101
+
102
+ // 模板
103
+ template: {
104
+ var: {
105
+ [varName: string]: {
106
+ type: "element" | "import" | "text",
107
+ tagName?: string,
108
+ attribs?: object,
109
+ event?: object,
110
+ args?: object,
111
+ keyword?: object,
112
+ content?: string
113
+ }
114
+ },
115
+ sh: string[], // DOM 构建语句
116
+ fragment: boolean // 是否为片段
117
+ },
118
+
119
+ // 脚本
120
+ before: { code: string },
121
+ global: { code: string },
122
+ event: {
123
+ code: string,
124
+ list: string[]
125
+ },
126
+ listen: {
127
+ code: string,
128
+ list: string[]
129
+ },
130
+ interface: {
131
+ code: string,
132
+ list: string[]
133
+ },
134
+ once_interface: string[],
135
+
136
+ // 样式
137
+ css: string,
138
+ cssScope: { [key: string]: string },
139
+
140
+ // 事件暴露
141
+ "expose-event": string,
142
+
143
+ // 元素 ID 列表
144
+ "use-element-id-list": string[],
145
+
146
+ // 元数据
147
+ name: string,
148
+ originalFile: string,
149
+ templateArgs: { inline: boolean }
150
+ }
151
+ }
152
+ ```
153
+
154
+ ### 1.4 IndexDom 类
155
+
156
+ ```typescript
157
+ class IndexDom {
158
+ headString: string; // head 内容
159
+ bodyString: string; // body 内容
160
+
161
+ // 添加元素
162
+ add(load: "begin" | "end", element: {
163
+ tag: string,
164
+ attrs: { [key: string]: string }[],
165
+ one?: boolean
166
+ }): void;
167
+
168
+ // 生成 HTML
169
+ generate(): string;
170
+ }
171
+ ```
172
+
173
+ ---
174
+
175
+ ## 2. 构建配置模型
176
+
177
+ ### 2.1 Type 配置类型定义
178
+
179
+ 位置: `script/module/compiler/project-build-config.js`
180
+
181
+ ```typescript
182
+ class Type {
183
+ type: "string" | "number" | "boolean" | "array" | "object";
184
+ key: boolean; // 是否必需
185
+ scope: any[] | false; // 枚举范围
186
+
187
+ getScope(): any[] | false;
188
+ getType(): string;
189
+ isKey(): boolean;
190
+ }
191
+ ```
192
+
193
+ ### 2.2 ProjectBuildConfig
194
+
195
+ ```typescript
196
+ const ProjectBuildConfig = {
197
+ // Web 平台基础配置
198
+ base: {
199
+ config: {
200
+ name: Type("string"), // 项目名
201
+ src: Type("string"), // 源码目录
202
+ main: Type("string") // 入口
203
+ },
204
+ build: {
205
+ out: Type("string"),
206
+ model: Type("string", true, ["debug", "release"]),
207
+ platform: {
208
+ target: Type("string", true, ["web", "node-webkit", "module"]),
209
+ config: Type("object")
210
+ },
211
+ exclude: {
212
+ dir: Type("array", false),
213
+ file: Type("array", false)
214
+ },
215
+ optimize: {
216
+ "out-default-theme": Type("boolean", false, [true, false]),
217
+ "min-code": {
218
+ js: Type("boolean", false, [true, false]),
219
+ css: Type("boolean", false, [true, false]),
220
+ html: Type("boolean", false, [true, false])
221
+ }
222
+ },
223
+ import: {
224
+ module: Type("array", false)
225
+ }
226
+ }
227
+ },
228
+
229
+ // 模块配置
230
+ base_module: { /* ... */ },
231
+
232
+ // Web 平台配置
233
+ web: { /* base + server config */ },
234
+
235
+ // Node-Webkit 配置
236
+ nodeWebkit: { /* base + app */ }
237
+ };
238
+ ```
239
+
240
+ ---
241
+
242
+ ## 3. app.xml 数据模型
243
+
244
+ ### 3.1 AppConfig 结构
245
+
246
+ ```typescript
247
+ interface AppConfig {
248
+ lang: string; // 语言代码
249
+ icon: string | false; // 图标路径
250
+ title: string; // 页面标题
251
+ initScript: string | null; // 初始化脚本
252
+ import: ImportItem[]; // 导入列表
253
+ }
254
+
255
+ interface ImportItem {
256
+ o: {
257
+ element: string; // 生成的 HTML 标签
258
+ load: "begin" | "end" | string;
259
+ }
260
+ }
261
+ ```
262
+
263
+ ### 3.2 Import 解析结构
264
+
265
+ ```typescript
266
+ interface ImportGroup {
267
+ // 命名空间
268
+ namespace?: string;
269
+
270
+ // 根路径
271
+ root?: string;
272
+
273
+ // 子节点
274
+ childNodes: ImportNode[];
275
+ }
276
+
277
+ interface ImportNode {
278
+ // 模块标签名
279
+ rawTagName: string;
280
+
281
+ // 属性
282
+ attrs: { [key: string]: string };
283
+
284
+ // 子节点
285
+ childNodes?: ImportNode[];
286
+ }
287
+
288
+ interface ParsedImport {
289
+ [namespace: string]: {
290
+ [tagName: string]: string // 模块路径
291
+ }
292
+ }
293
+ ```
294
+
295
+ ---
296
+
297
+ ## 4. Runtime 数据模型
298
+
299
+ ### 4.1 Window 全局对象
300
+
301
+ ```typescript
302
+ // 全局版本号
303
+ const magic_version: string;
304
+
305
+ // 全局空值
306
+ const nop: null;
307
+
308
+ // Magic 内部存储
309
+ const __MAGIC__: {
310
+ M: {
311
+ [moduleName: string]: new (...args: any[]) => any
312
+ },
313
+ CREATE_ELEMENT_LIST: Map<any, any>
314
+ };
315
+ ```
316
+
317
+ ### 4.2 magic 对象结构
318
+
319
+ ```typescript
320
+ const magic: {
321
+ // 初始化
322
+ init(main: string): void;
323
+
324
+ // DOM 操作
325
+ dom: {
326
+ element(tag: string): HTMLElement;
327
+ text(content: string): Text;
328
+ append(p: HTMLElement, ...childs: any[]): void;
329
+ attribute(e: HTMLElement, atts: object): void;
330
+ event(e: HTMLElement, eventName: string, _this: any, fnName: string, opt?: object): void;
331
+ };
332
+
333
+ // 模块操作
334
+ importM(name: string, args?: object, listen?: object): ImportedModuleElement;
335
+
336
+ // 作用域调用
337
+ call(scope: any): {
338
+ interface: (name: string, ...args: any[]) => any;
339
+ event: (name: string, ...args: any[]) => any;
340
+ listen: (name: string, ...args: any[]) => any;
341
+ };
342
+
343
+ // 事件发射
344
+ emit: {
345
+ event(listen: object): (name: string, ...args: any[]) => any;
346
+ };
347
+
348
+ // 元素查找
349
+ $id(_$id: Map<string, HTMLElement>): {
350
+ (): Record<string, HTMLElement>;
351
+ (id: string): HTMLElement;
352
+ };
353
+
354
+ // 参数处理
355
+ parserArgs(args: string | object): object;
356
+ createArgs(obj: object): string;
357
+ parserListen(listen?: object): object;
358
+
359
+ // 事件处理
360
+ on_event(event: object, listen: object): any;
361
+ end_event(event: object, listen: object): any;
362
+
363
+ // ID 管理
364
+ mapIdElement(): Map<string, HTMLElement> & {
365
+ s(id: string, e: HTMLElement, s?: string): void;
366
+ };
367
+
368
+ // UI 数据
369
+ createUiData(target: object, source: object): object;
370
+
371
+ // 元素初始化
372
+ importElementInit(...args: any[]): void;
373
+
374
+ // 接口导出
375
+ exportInterface(scope: object, target: object, parcel: object): void;
376
+
377
+ // 获取接口
378
+ GetInterface(ele: HTMLElement): object | null;
379
+
380
+ // 作用域绑定
381
+ BindScope(arr: HTMLElement[], ths: object): HTMLElement[];
382
+
383
+ // 动态绑定
384
+ DynamicValueBind(...elements: HTMLElement[]): void;
385
+
386
+ // ID 生成
387
+ idGenerate(): string;
388
+
389
+ // DOM 查询
390
+ $(id: string, root?: HTMLElement): HTMLElement | null;
391
+ };
392
+ ```
393
+
394
+ ### 4.3 ImportedModuleElement 接口
395
+
396
+ ```typescript
397
+ interface ImportedModuleElement extends HTMLElement {
398
+ // 文件路径
399
+ __file: string;
400
+
401
+ // 模块 ID
402
+ mid: string;
403
+
404
+ // 文档片段
405
+ fragment: DocumentFragment;
406
+
407
+ // 接口对象
408
+ interface: {
409
+ [methodName: string]: (...args: any[]) => any;
410
+ };
411
+
412
+ // 模板参数
413
+ templateArgs: {
414
+ inline: boolean;
415
+ };
416
+
417
+ // 根元素
418
+ __root__element__: HTMLElement;
419
+
420
+ // 暴露的事件
421
+ exposeEvent: object;
422
+ }
423
+ ```
424
+
425
+ ---
426
+
427
+ ## 5. 编译输出模型
428
+
429
+ ### 5.1 生成的模块结构
430
+
431
+ ```javascript
432
+ // 编译后的 .m.js 文件
433
+ window["__MAGIC__"]["M"]["模块名"] = function(__args__, __listen__) {
434
+ const call = magic.call(this);
435
+ this._$id = magic.mapIdElement();
436
+ const $id = magic.$id(this._$id);
437
+ const _args = {_file: "path", _id: magic.idGenerate(), ...magic.parserArgs(__args__)};
438
+ const _listen = magic.parserListen(__listen__);
439
+ const emit_event = magic.emit.event(_listen);
440
+
441
+ // 元素定义
442
+ let $e1, $e2, $t1;
443
+ this.__magic_element_root = document.createDocumentFragment();
444
+
445
+ // before 脚本
446
+ { before_code }
447
+
448
+ // 模板渲染
449
+ this.__magic_template = (() => {
450
+ const { element: e, text: t, ... } = magic.dom;
451
+ return {
452
+ render: () => {
453
+ // 元素创建
454
+ // 属性设置
455
+ // 事件绑定
456
+ // DOM 追加
457
+ },
458
+ bind_event: () => { /* 事件绑定 */ },
459
+ export_element: () => { /* 导出元素 */ }
460
+ };
461
+ })();
462
+
463
+ this.__magic_template.render();
464
+
465
+ // global 脚本
466
+ { global_code }
467
+
468
+ // listen 脚本
469
+ { listen_code }
470
+
471
+ // event 脚本
472
+ { event_code }
473
+
474
+ this.__magic_template.bind_event();
475
+
476
+ // interface 脚本
477
+ { interface_code }
478
+
479
+ // default 脚本
480
+ { script_code }
481
+
482
+ // 返回元素
483
+ return { /* fragment or element */ };
484
+ };
485
+ ```
486
+
487
+ ### 5.2 module.info.json 结构
488
+
489
+ 模块模式构建时生成:
490
+
491
+ ```json
492
+ {
493
+ "name": "module-name",
494
+ "dir": "output-dir",
495
+ "model": "release",
496
+ "files": [
497
+ "default-theme-var.css",
498
+ "module.js",
499
+ "module.css"
500
+ ]
501
+ }
502
+ ```
503
+
504
+ ---
505
+
506
+ ## 6. 宏处理数据流
507
+
508
+ ### 6.1 magic_define_include
509
+
510
+ ```typescript
511
+ // 输入
512
+ magic_define_include("./template.html")
513
+
514
+ // 编译时处理
515
+ const filePath = "./template.html";
516
+ const fileContent = fs.readFileSync(filePath);
517
+
518
+ // 输出
519
+ // 替换为文件内容字符串
520
+ ```
521
+
522
+ ### 6.2 magic_define_ui_data
523
+
524
+ ```typescript
525
+ // 输入
526
+ const UiData = magic_define_ui_data({
527
+ text: "hello",
528
+ count: 0
529
+ });
530
+
531
+ // 编译时处理
532
+ // 转换为 magic.createUiData() 调用
533
+
534
+ // 输出
535
+ const UiData = magic.createUiData({
536
+ text: "hello",
537
+ count: 0
538
+ }, _args);
539
+ ```
540
+
541
+ ### 6.3 magic_dynamic_value_bind
542
+
543
+ ```typescript
544
+ // 输入
545
+ magic_dynamic_value_bind($textElement)
546
+
547
+ // 编译时处理
548
+ // 添加到 uiData 的绑定列表
549
+
550
+ // 输出
551
+ magic.DynamicValueBind($textElement, UiData);
552
+ ```
553
+
554
+ ---
555
+
556
+ ## 7. CSS 变量映射
557
+
558
+ ### 7.1 default-theme-var.css 结构
559
+
560
+ ```css
561
+ :root {
562
+ --组件名-作用域-属性名-序号: 原始值;
563
+ --button-m-css-scope-xxx-background-color: #c6c6c6;
564
+ --button-m-css-scope-xxx-border-radius: 5px;
565
+ }
566
+ ```
567
+
568
+ ### 7.2 CSS 作用域映射
569
+
570
+ ```typescript
571
+ // 输入
572
+ <css scope="#id:button">
573
+ & {
574
+ background-color: #c6c6c6;
575
+ }
576
+ </css>
577
+
578
+ // 编译时生成
579
+ .m-css-scope-{随机6位} {
580
+ background-color: var(--button-m-css-scope-{随机6位}-background-color);
581
+ }
582
+ ```
583
+
584
+ ---
585
+
586
+ ## 8. 事件系统数据流
587
+
588
+ ### 8.1 事件对象结构
589
+
590
+ ```typescript
591
+ interface MagicEvent {
592
+ type: string; // 事件类型
593
+ runState?: "on" | "end"; // 运行状态
594
+ }
595
+ ```
596
+
597
+ ### 8.2 监听器注册
598
+
599
+ ```typescript
600
+ // 模板中定义
601
+ <button @click="handler:arg1,arg2">
602
+
603
+ // 编译后
604
+ magic.dom.event(
605
+ buttonElement,
606
+ "click",
607
+ scope,
608
+ "handler",
609
+ { /* options */ }
610
+ );
611
+ ```
612
+
613
+ ### 8.3 emit_event 调用
614
+
615
+ ```typescript
616
+ // 定义
617
+ emit_event("select", { value: "A" });
618
+
619
+ // 实现
620
+ const emit_event = magic.emit.event(_listen);
621
+ emit_event("select", { value: "A" });
622
+ ```