@slidejs/dsl 0.0.1
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/README.md +193 -0
- package/dist/ast.d.ts +117 -0
- package/dist/ast.d.ts.map +1 -0
- package/dist/compiler.d.ts +15 -0
- package/dist/compiler.d.ts.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +203 -0
- package/dist/index.js.map +1 -0
- package/dist/parser-KEWKxNFb.js +616 -0
- package/dist/parser-KEWKxNFb.js.map +1 -0
- package/dist/parser.d.ts +49 -0
- package/dist/parser.d.ts.map +1 -0
- package/package.json +47 -0
- package/src/generated/parser.js +2992 -0
package/README.md
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
# @slidejs/dsl
|
|
2
|
+
|
|
3
|
+
Slide DSL 语法解析器和编译器。
|
|
4
|
+
|
|
5
|
+
## 特性
|
|
6
|
+
|
|
7
|
+
- 基于 [Peggy](https://peggyjs.org/) 的语法解析器
|
|
8
|
+
- 类型安全的 AST 定义
|
|
9
|
+
- 支持表达式计算和 for 循环
|
|
10
|
+
- 完整的错误处理
|
|
11
|
+
|
|
12
|
+
## 使用示例
|
|
13
|
+
|
|
14
|
+
### 解析 DSL
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
import { parseSlideDSL } from '@slidejs/dsl';
|
|
18
|
+
|
|
19
|
+
const source = `
|
|
20
|
+
present quiz "my-quiz" {
|
|
21
|
+
rules {
|
|
22
|
+
rule start "intro" {
|
|
23
|
+
slide {
|
|
24
|
+
content text {
|
|
25
|
+
"Welcome to the quiz!"
|
|
26
|
+
}
|
|
27
|
+
behavior {
|
|
28
|
+
transition zoom {
|
|
29
|
+
duration 500
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
rule content "questions" {
|
|
36
|
+
for section in quiz.sections {
|
|
37
|
+
for question in section.questions {
|
|
38
|
+
slide {
|
|
39
|
+
content dynamic {
|
|
40
|
+
name: "wsx-quiz-question"
|
|
41
|
+
attrs {
|
|
42
|
+
title: section.title
|
|
43
|
+
question: question.text
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
rule end "thanks" {
|
|
52
|
+
slide {
|
|
53
|
+
content text {
|
|
54
|
+
"Thank you!"
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
`;
|
|
61
|
+
|
|
62
|
+
const ast = await parseSlideDSL(source);
|
|
63
|
+
console.log(ast);
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### 编译为可执行的 SlideDSL
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
import { compile } from '@slidejs/dsl';
|
|
70
|
+
import { SlideEngine } from '@slidejs/core';
|
|
71
|
+
import { quizToSlideContext } from '@slidejs/dsl';
|
|
72
|
+
|
|
73
|
+
// 解析 DSL
|
|
74
|
+
const ast = await parseSlideDSL(source);
|
|
75
|
+
|
|
76
|
+
// 编译为 SlideDSL 对象
|
|
77
|
+
const slideDSL = compile(ast);
|
|
78
|
+
|
|
79
|
+
// 创建 Context
|
|
80
|
+
const context = quizToSlideContext(quizDSL);
|
|
81
|
+
|
|
82
|
+
// 生成 Slides
|
|
83
|
+
const engine = new SlideEngine(slideDSL);
|
|
84
|
+
const slides = engine.generate(context);
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## 语法参考
|
|
88
|
+
|
|
89
|
+
### Presentation
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
present <type> "<name>" {
|
|
93
|
+
rules {
|
|
94
|
+
// 规则定义
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Rules
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
rule start "<name>" {
|
|
103
|
+
// slides
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
rule content "<name>" {
|
|
107
|
+
// for 循环或 slides
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
rule end "<name>" {
|
|
111
|
+
// slides
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Slide
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
slide {
|
|
119
|
+
content <type> {
|
|
120
|
+
// 内容
|
|
121
|
+
}
|
|
122
|
+
behavior {
|
|
123
|
+
// 行为
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Content
|
|
129
|
+
|
|
130
|
+
```
|
|
131
|
+
// 动态内容(组件)
|
|
132
|
+
content dynamic {
|
|
133
|
+
name: "<component-name>"
|
|
134
|
+
attrs {
|
|
135
|
+
key: value
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// 静态文本
|
|
140
|
+
content text {
|
|
141
|
+
"line 1"
|
|
142
|
+
"line 2"
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Behavior
|
|
147
|
+
|
|
148
|
+
```
|
|
149
|
+
behavior {
|
|
150
|
+
transition <type> {
|
|
151
|
+
option: value
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### For Loop
|
|
157
|
+
|
|
158
|
+
```
|
|
159
|
+
for item in collection {
|
|
160
|
+
// slides
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// 嵌套 for 循环
|
|
164
|
+
for outer in collection1 {
|
|
165
|
+
for inner in outer.collection2 {
|
|
166
|
+
// slides
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## 开发
|
|
172
|
+
|
|
173
|
+
### 生成 Parser
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
pnpm generate:parser
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### 构建
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
pnpm build
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### 测试
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
pnpm test
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## License
|
|
192
|
+
|
|
193
|
+
MIT
|
package/dist/ast.d.ts
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @slidejs/dsl - AST 类型定义
|
|
3
|
+
*
|
|
4
|
+
* Peggy 解析器生成的抽象语法树(AST)类型
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* AST 节点基类
|
|
8
|
+
*/
|
|
9
|
+
export interface ASTNode {
|
|
10
|
+
type: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Presentation 节点(根节点)
|
|
14
|
+
*/
|
|
15
|
+
export interface PresentationNode {
|
|
16
|
+
version: string;
|
|
17
|
+
sourceType: string;
|
|
18
|
+
sourceId: string;
|
|
19
|
+
rules: RuleNode[];
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Rule 节点
|
|
23
|
+
*/
|
|
24
|
+
export interface RuleNode extends ASTNode {
|
|
25
|
+
type: 'rule';
|
|
26
|
+
ruleType: 'start' | 'content' | 'end';
|
|
27
|
+
name: string;
|
|
28
|
+
slides?: SlideNode[];
|
|
29
|
+
body?: ForLoopNode | SlideNode[];
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* For Loop 节点
|
|
33
|
+
*/
|
|
34
|
+
export interface ForLoopNode extends ASTNode {
|
|
35
|
+
type: 'for';
|
|
36
|
+
variable: string;
|
|
37
|
+
collection: MemberExpressionNode | string;
|
|
38
|
+
body: ForLoopNode | SlideNode[];
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Slide 节点
|
|
42
|
+
*/
|
|
43
|
+
export interface SlideNode extends ASTNode {
|
|
44
|
+
type: 'slide';
|
|
45
|
+
content: ContentNode;
|
|
46
|
+
behavior?: BehaviorNode;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Content 节点
|
|
50
|
+
*/
|
|
51
|
+
export type ContentNode = DynamicContentNode | TextContentNode;
|
|
52
|
+
/**
|
|
53
|
+
* Dynamic Content 节点
|
|
54
|
+
*/
|
|
55
|
+
export interface DynamicContentNode extends ASTNode {
|
|
56
|
+
type: 'dynamic';
|
|
57
|
+
component: string;
|
|
58
|
+
props: Record<string, ExpressionValue>;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Text Content 节点
|
|
62
|
+
*/
|
|
63
|
+
export interface TextContentNode extends ASTNode {
|
|
64
|
+
type: 'text';
|
|
65
|
+
lines: ExpressionValue[];
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Behavior 节点
|
|
69
|
+
*/
|
|
70
|
+
export interface BehaviorNode extends ASTNode {
|
|
71
|
+
type: 'behavior';
|
|
72
|
+
transition: TransitionNode;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Transition 节点
|
|
76
|
+
*/
|
|
77
|
+
export interface TransitionNode extends ASTNode {
|
|
78
|
+
type: 'transition';
|
|
79
|
+
transType: string;
|
|
80
|
+
options: Record<string, ExpressionValue>;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Member Expression 节点
|
|
84
|
+
*/
|
|
85
|
+
export interface MemberExpressionNode extends ASTNode {
|
|
86
|
+
type: 'member';
|
|
87
|
+
object: string;
|
|
88
|
+
properties: string[];
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Binary Expression 节点
|
|
92
|
+
*/
|
|
93
|
+
export interface BinaryExpressionNode extends ASTNode {
|
|
94
|
+
type: 'binary';
|
|
95
|
+
operator: '+' | '-' | '*' | '/';
|
|
96
|
+
left: ExpressionValue;
|
|
97
|
+
right: ExpressionValue;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Number Literal 节点
|
|
101
|
+
*/
|
|
102
|
+
export interface NumberLiteralNode extends ASTNode {
|
|
103
|
+
type: 'number';
|
|
104
|
+
value: number;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Boolean Literal 节点
|
|
108
|
+
*/
|
|
109
|
+
export interface BooleanLiteralNode extends ASTNode {
|
|
110
|
+
type: 'boolean';
|
|
111
|
+
value: boolean;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Expression 值类型
|
|
115
|
+
*/
|
|
116
|
+
export type ExpressionValue = string | NumberLiteralNode | BooleanLiteralNode | MemberExpressionNode | BinaryExpressionNode;
|
|
117
|
+
//# sourceMappingURL=ast.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ast.d.ts","sourceRoot":"","sources":["../src/ast.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,QAAQ,EAAE,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,QAAS,SAAQ,OAAO;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,GAAG,SAAS,GAAG,KAAK,CAAC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC;IACrB,IAAI,CAAC,EAAE,WAAW,GAAG,SAAS,EAAE,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,WAAY,SAAQ,OAAO;IAC1C,IAAI,EAAE,KAAK,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,oBAAoB,GAAG,MAAM,CAAC;IAC1C,IAAI,EAAE,WAAW,GAAG,SAAS,EAAE,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,SAAU,SAAQ,OAAO;IACxC,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,WAAW,CAAC;IACrB,QAAQ,CAAC,EAAE,YAAY,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,kBAAkB,GAAG,eAAe,CAAC;AAE/D;;GAEG;AACH,MAAM,WAAW,kBAAmB,SAAQ,OAAO;IACjD,IAAI,EAAE,SAAS,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;CACxC;AAED;;GAEG;AACH,MAAM,WAAW,eAAgB,SAAQ,OAAO;IAC9C,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,eAAe,EAAE,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,YAAa,SAAQ,OAAO;IAC3C,IAAI,EAAE,UAAU,CAAC;IACjB,UAAU,EAAE,cAAc,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,cAAe,SAAQ,OAAO;IAC7C,IAAI,EAAE,YAAY,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;CAC1C;AAED;;GAEG;AACH,MAAM,WAAW,oBAAqB,SAAQ,OAAO;IACnD,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAqB,SAAQ,OAAO;IACnD,IAAI,EAAE,QAAQ,CAAC;IACf,QAAQ,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;IAChC,IAAI,EAAE,eAAe,CAAC;IACtB,KAAK,EAAE,eAAe,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAkB,SAAQ,OAAO;IAChD,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,kBAAmB,SAAQ,OAAO;IACjD,IAAI,EAAE,SAAS,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,MAAM,eAAe,GACvB,MAAM,GACN,iBAAiB,GACjB,kBAAkB,GAClB,oBAAoB,GACpB,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { SlideContext } from '@slidejs/context';
|
|
2
|
+
import { SlideDSL } from '@slidejs/core';
|
|
3
|
+
import { PresentationNode } from './ast';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Compiler 错误
|
|
7
|
+
*/
|
|
8
|
+
export declare class CompileError extends Error {
|
|
9
|
+
constructor(message: string);
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* 编译 AST 为 SlideDSL
|
|
13
|
+
*/
|
|
14
|
+
export declare function compile<TContext extends SlideContext = SlideContext>(ast: PresentationNode): SlideDSL<TContext>;
|
|
15
|
+
//# sourceMappingURL=compiler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compiler.d.ts","sourceRoot":"","sources":["../src/compiler.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,EAAE,QAAQ,EAA8B,MAAM,eAAe,CAAC;AAC1E,OAAO,KAAK,EACV,gBAAgB,EAWjB,MAAM,OAAO,CAAC;AAEf;;GAEG;AACH,qBAAa,YAAa,SAAQ,KAAK;gBACzB,OAAO,EAAE,MAAM;CAI5B;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,QAAQ,SAAS,YAAY,GAAG,YAAY,EAClE,GAAG,EAAE,gBAAgB,GACpB,QAAQ,CAAC,QAAQ,CAAC,CA0BpB"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @slidejs/dsl
|
|
3
|
+
*
|
|
4
|
+
* Slide DSL 语法解析器和编译器
|
|
5
|
+
*/
|
|
6
|
+
export type { PresentationNode, RuleNode, SlideNode, ForLoopNode, ContentNode, DynamicContentNode, TextContentNode, BehaviorNode, TransitionNode, MemberExpressionNode, BinaryExpressionNode, NumberLiteralNode, BooleanLiteralNode, ExpressionValue, } from './ast';
|
|
7
|
+
export { ParseError, createParser, parseSlideDSL } from './parser';
|
|
8
|
+
export type { Parser } from './parser';
|
|
9
|
+
export { compile, CompileError } from './compiler';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,YAAY,EACV,gBAAgB,EAChB,QAAQ,EACR,SAAS,EACT,WAAW,EACX,WAAW,EACX,kBAAkB,EAClB,eAAe,EACf,YAAY,EACZ,cAAc,EACd,oBAAoB,EACpB,oBAAoB,EACpB,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,GAChB,MAAM,OAAO,CAAC;AAEf,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACnE,YAAY,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAEvC,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
class s extends Error {
|
|
2
|
+
constructor(r, t) {
|
|
3
|
+
super(r), this.location = t, this.name = "ParseError";
|
|
4
|
+
}
|
|
5
|
+
}
|
|
6
|
+
async function y() {
|
|
7
|
+
const { parse: e } = await import("./parser-KEWKxNFb.js");
|
|
8
|
+
return {
|
|
9
|
+
parse(r) {
|
|
10
|
+
try {
|
|
11
|
+
return e(r);
|
|
12
|
+
} catch (t) {
|
|
13
|
+
if (t && typeof t == "object" && "location" in t) {
|
|
14
|
+
const i = "message" in t && typeof t.message == "string" ? t.message : String(t);
|
|
15
|
+
throw new s(i, t.location);
|
|
16
|
+
}
|
|
17
|
+
const o = t && typeof t == "object" && "message" in t && typeof t.message == "string" ? t.message : String(t);
|
|
18
|
+
throw new s(o);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
async function v(e) {
|
|
24
|
+
if (e == null)
|
|
25
|
+
throw new s("DSL source cannot be null or undefined");
|
|
26
|
+
if (typeof e != "string")
|
|
27
|
+
throw new s(`DSL source must be a string, got: ${typeof e}`);
|
|
28
|
+
if (e.trim().length === 0)
|
|
29
|
+
throw new s("DSL source cannot be empty");
|
|
30
|
+
return (await y()).parse(e);
|
|
31
|
+
}
|
|
32
|
+
class n extends Error {
|
|
33
|
+
constructor(r) {
|
|
34
|
+
super(r), this.name = "CompileError";
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function $(e) {
|
|
38
|
+
if (!e)
|
|
39
|
+
throw new n("AST is null or undefined");
|
|
40
|
+
if (!e.rules || !Array.isArray(e.rules))
|
|
41
|
+
throw new n("AST rules must be an array");
|
|
42
|
+
if (!e.sourceType || typeof e.sourceType != "string")
|
|
43
|
+
throw new n("AST sourceType must be a non-empty string");
|
|
44
|
+
if (!e.sourceId || typeof e.sourceId != "string")
|
|
45
|
+
throw new n("AST sourceId must be a non-empty string");
|
|
46
|
+
const r = e.rules.map((t) => m(t));
|
|
47
|
+
return {
|
|
48
|
+
version: e.version,
|
|
49
|
+
sourceType: e.sourceType,
|
|
50
|
+
sourceId: e.sourceId,
|
|
51
|
+
rules: r
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function m(e) {
|
|
55
|
+
return {
|
|
56
|
+
type: e.ruleType,
|
|
57
|
+
name: e.name,
|
|
58
|
+
generate: (r) => e.slides ? e.slides.map((t) => u(t, r)) : e.body ? b(e.body, r) : []
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
function b(e, r) {
|
|
62
|
+
return Array.isArray(e) ? e.map((t) => u(t, r)) : c(e, r);
|
|
63
|
+
}
|
|
64
|
+
function c(e, r) {
|
|
65
|
+
const t = [];
|
|
66
|
+
if (!e.variable || typeof e.variable != "string")
|
|
67
|
+
throw new n("For loop variable must be a non-empty string");
|
|
68
|
+
const o = a(e.collection, r);
|
|
69
|
+
if (o == null)
|
|
70
|
+
throw new n(
|
|
71
|
+
`For loop collection "${e.collection}" evaluates to ${o === null ? "null" : "undefined"}`
|
|
72
|
+
);
|
|
73
|
+
if (!Array.isArray(o))
|
|
74
|
+
throw new n(
|
|
75
|
+
`For loop collection "${e.collection}" must be an array, got: ${typeof o}`
|
|
76
|
+
);
|
|
77
|
+
for (const i of o) {
|
|
78
|
+
const l = {
|
|
79
|
+
...r,
|
|
80
|
+
[e.variable]: i
|
|
81
|
+
};
|
|
82
|
+
Array.isArray(e.body) ? t.push(...e.body.map((f) => u(f, l))) : t.push(...c(e.body, l));
|
|
83
|
+
}
|
|
84
|
+
return t;
|
|
85
|
+
}
|
|
86
|
+
function u(e, r) {
|
|
87
|
+
return {
|
|
88
|
+
content: w(e.content, r),
|
|
89
|
+
behavior: e.behavior ? h(e.behavior, r) : void 0
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
function w(e, r) {
|
|
93
|
+
return e.type === "dynamic" ? {
|
|
94
|
+
type: "dynamic",
|
|
95
|
+
component: e.component,
|
|
96
|
+
props: p(e.props, r)
|
|
97
|
+
} : {
|
|
98
|
+
type: "text",
|
|
99
|
+
lines: e.lines.map((t) => String(a(t, r)))
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
function h(e, r) {
|
|
103
|
+
return {
|
|
104
|
+
transition: {
|
|
105
|
+
type: e.transition.transType,
|
|
106
|
+
...p(e.transition.options, r)
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
function p(e, r) {
|
|
111
|
+
const t = {};
|
|
112
|
+
for (const [o, i] of Object.entries(e))
|
|
113
|
+
t[o] = a(i, r);
|
|
114
|
+
return t;
|
|
115
|
+
}
|
|
116
|
+
function a(e, r) {
|
|
117
|
+
if (typeof e == "string")
|
|
118
|
+
return e;
|
|
119
|
+
if (typeof e == "object" && e !== null && "type" in e)
|
|
120
|
+
switch (e.type) {
|
|
121
|
+
case "number":
|
|
122
|
+
return e.value;
|
|
123
|
+
case "boolean":
|
|
124
|
+
return e.value;
|
|
125
|
+
case "member":
|
|
126
|
+
return g(e, r);
|
|
127
|
+
case "binary":
|
|
128
|
+
return d(e, r);
|
|
129
|
+
default:
|
|
130
|
+
throw new n(`Unknown expression type: ${e.type}`);
|
|
131
|
+
}
|
|
132
|
+
throw new n(`Invalid expression: ${JSON.stringify(e)}`);
|
|
133
|
+
}
|
|
134
|
+
function g(e, r) {
|
|
135
|
+
let t = r[e.object];
|
|
136
|
+
if (e.properties.length === 0) {
|
|
137
|
+
if (t === void 0)
|
|
138
|
+
throw new n(
|
|
139
|
+
`Variable "${e.object}" is not defined in context`
|
|
140
|
+
);
|
|
141
|
+
return t;
|
|
142
|
+
}
|
|
143
|
+
const o = [e.object];
|
|
144
|
+
for (const i of e.properties) {
|
|
145
|
+
if (o.push(i), t == null)
|
|
146
|
+
throw new n(
|
|
147
|
+
`Cannot access property "${i}" of "${o.slice(0, -1).join(".")}" because it is ${t === null ? "null" : "undefined"}`
|
|
148
|
+
);
|
|
149
|
+
if (typeof t != "object")
|
|
150
|
+
throw new n(
|
|
151
|
+
`Cannot access property "${i}" of "${o.slice(0, -1).join(".")}" because it is not an object (got ${typeof t})`
|
|
152
|
+
);
|
|
153
|
+
if (!(i in t))
|
|
154
|
+
throw new n(
|
|
155
|
+
`Property "${i}" does not exist on "${o.slice(0, -1).join(".")}"`
|
|
156
|
+
);
|
|
157
|
+
t = t[i];
|
|
158
|
+
}
|
|
159
|
+
return t;
|
|
160
|
+
}
|
|
161
|
+
function d(e, r) {
|
|
162
|
+
const t = a(e.left, r), o = a(e.right, r);
|
|
163
|
+
switch (e.operator) {
|
|
164
|
+
case "+":
|
|
165
|
+
if (typeof t == "string" || typeof o == "string")
|
|
166
|
+
return String(t) + String(o);
|
|
167
|
+
if (typeof t != "number" || typeof o != "number")
|
|
168
|
+
throw new n(
|
|
169
|
+
`Cannot add ${typeof t} and ${typeof o}. Both operands must be numbers or at least one must be a string.`
|
|
170
|
+
);
|
|
171
|
+
return t + o;
|
|
172
|
+
case "-":
|
|
173
|
+
if (typeof t != "number" || typeof o != "number")
|
|
174
|
+
throw new n(
|
|
175
|
+
`Cannot subtract ${typeof o} from ${typeof t}. Both operands must be numbers.`
|
|
176
|
+
);
|
|
177
|
+
return t - o;
|
|
178
|
+
case "*":
|
|
179
|
+
if (typeof t != "number" || typeof o != "number")
|
|
180
|
+
throw new n(
|
|
181
|
+
`Cannot multiply ${typeof t} and ${typeof o}. Both operands must be numbers.`
|
|
182
|
+
);
|
|
183
|
+
return t * o;
|
|
184
|
+
case "/":
|
|
185
|
+
if (typeof t != "number" || typeof o != "number")
|
|
186
|
+
throw new n(
|
|
187
|
+
`Cannot divide ${typeof t} by ${typeof o}. Both operands must be numbers.`
|
|
188
|
+
);
|
|
189
|
+
if (o === 0)
|
|
190
|
+
throw new n("Division by zero is not allowed");
|
|
191
|
+
return t / o;
|
|
192
|
+
default:
|
|
193
|
+
throw new n(`Unknown operator: ${e.operator}`);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
export {
|
|
197
|
+
n as CompileError,
|
|
198
|
+
s as ParseError,
|
|
199
|
+
$ as compile,
|
|
200
|
+
y as createParser,
|
|
201
|
+
v as parseSlideDSL
|
|
202
|
+
};
|
|
203
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/parser.ts","../src/compiler.ts"],"sourcesContent":["/**\n * @slidejs/dsl - Parser 接口\n *\n * 使用 Peggy 生成的 parser 解析 Slide DSL 语法\n */\n\nimport type { PresentationNode } from './ast';\n\n/**\n * Parser 错误\n */\nexport class ParseError extends Error {\n constructor(\n message: string,\n public location?: {\n start: { line: number; column: number; offset: number };\n end: { line: number; column: number; offset: number };\n }\n ) {\n super(message);\n this.name = 'ParseError';\n }\n}\n\n/**\n * Parser 接口\n */\nexport interface Parser {\n /**\n * 解析 Slide DSL 源代码\n */\n parse(source: string): PresentationNode;\n}\n\n/**\n * 创建 Parser 实例\n */\nexport async function createParser(): Promise<Parser> {\n // 动态导入生成的 parser\n const { parse } = await import('./generated/parser.js');\n\n return {\n parse(source: string): PresentationNode {\n try {\n return parse(source) as PresentationNode;\n } catch (error) {\n if (error && typeof error === 'object' && 'location' in error) {\n const errorMessage =\n 'message' in error && typeof error.message === 'string'\n ? error.message\n : String(error);\n throw new ParseError(errorMessage, error.location as ParseError['location']);\n }\n const errorMessage =\n error && typeof error === 'object' && 'message' in error && typeof error.message === 'string'\n ? error.message\n : String(error);\n throw new ParseError(errorMessage);\n }\n },\n };\n}\n\n/**\n * 便捷函数:直接解析 DSL 源代码\n */\nexport async function parseSlideDSL(source: string): Promise<PresentationNode> {\n // 输入验证\n if (source === null || source === undefined) {\n throw new ParseError('DSL source cannot be null or undefined');\n }\n\n if (typeof source !== 'string') {\n throw new ParseError(`DSL source must be a string, got: ${typeof source}`);\n }\n\n if (source.trim().length === 0) {\n throw new ParseError('DSL source cannot be empty');\n }\n\n const parser = await createParser();\n return parser.parse(source);\n}\n","/**\n * @slidejs/dsl - Compiler\n *\n * 将 AST 编译为可执行的 SlideDSL 对象\n */\n\nimport type { SlideContext } from '@slidejs/context';\nimport type { SlideDSL, SlideRule, SlideDefinition } from '@slidejs/core';\nimport type {\n PresentationNode,\n RuleNode,\n SlideNode,\n ForLoopNode,\n ContentNode,\n BehaviorNode,\n ExpressionValue,\n MemberExpressionNode,\n BinaryExpressionNode,\n NumberLiteralNode,\n BooleanLiteralNode,\n} from './ast';\n\n/**\n * Compiler 错误\n */\nexport class CompileError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'CompileError';\n }\n}\n\n/**\n * 编译 AST 为 SlideDSL\n */\nexport function compile<TContext extends SlideContext = SlideContext>(\n ast: PresentationNode\n): SlideDSL<TContext> {\n // 输入验证\n if (!ast) {\n throw new CompileError('AST is null or undefined');\n }\n\n if (!ast.rules || !Array.isArray(ast.rules)) {\n throw new CompileError('AST rules must be an array');\n }\n\n if (!ast.sourceType || typeof ast.sourceType !== 'string') {\n throw new CompileError('AST sourceType must be a non-empty string');\n }\n\n if (!ast.sourceId || typeof ast.sourceId !== 'string') {\n throw new CompileError('AST sourceId must be a non-empty string');\n }\n\n const rules: SlideRule<TContext>[] = ast.rules.map(ruleNode => compileRule(ruleNode));\n\n return {\n version: ast.version,\n sourceType: ast.sourceType,\n sourceId: ast.sourceId,\n rules,\n };\n}\n\n/**\n * 编译 Rule 节点\n */\nfunction compileRule<TContext extends SlideContext = SlideContext>(\n node: RuleNode\n): SlideRule<TContext> {\n return {\n type: node.ruleType,\n name: node.name,\n generate: (context: TContext) => {\n if (node.slides) {\n // 简单规则:直接生成 slides\n return node.slides.map(slideNode => compileSlide(slideNode, context));\n } else if (node.body) {\n // Content 规则:可能包含 for 循环\n return compileRuleBody(node.body, context);\n }\n return [];\n },\n };\n}\n\n/**\n * 编译 Rule Body(可能包含 for 循环)\n */\nfunction compileRuleBody<TContext extends SlideContext = SlideContext>(\n body: ForLoopNode | SlideNode[],\n context: TContext\n): SlideDefinition[] {\n if (Array.isArray(body)) {\n // 直接是 slides 数组\n return body.map(slideNode => compileSlide(slideNode, context));\n } else {\n // For 循环\n return compileForLoop(body, context);\n }\n}\n\n/**\n * 编译 For 循环\n */\nfunction compileForLoop<TContext extends SlideContext = SlideContext>(\n node: ForLoopNode,\n context: TContext\n): SlideDefinition[] {\n const slides: SlideDefinition[] = [];\n\n // 输入验证\n if (!node.variable || typeof node.variable !== 'string') {\n throw new CompileError('For loop variable must be a non-empty string');\n }\n\n // 解析集合表达式\n const collection = evaluateExpression(node.collection, context);\n\n if (collection === null || collection === undefined) {\n throw new CompileError(\n `For loop collection \"${node.collection}\" evaluates to ${collection === null ? 'null' : 'undefined'}`\n );\n }\n\n if (!Array.isArray(collection)) {\n throw new CompileError(\n `For loop collection \"${node.collection}\" must be an array, got: ${typeof collection}`\n );\n }\n\n // 遍历集合,为每个元素生成 slides\n for (const item of collection) {\n // 创建新的上下文,添加循环变量\n const loopContext = {\n ...context,\n [node.variable]: item,\n } as TContext;\n\n if (Array.isArray(node.body)) {\n // Body 是 slides 数组\n slides.push(...node.body.map(slideNode => compileSlide(slideNode, loopContext)));\n } else {\n // Body 是嵌套的 for 循环\n slides.push(...compileForLoop(node.body, loopContext));\n }\n }\n\n return slides;\n}\n\n/**\n * 编译 Slide 节点\n */\nfunction compileSlide<TContext extends SlideContext = SlideContext>(\n node: SlideNode,\n context: TContext\n): SlideDefinition {\n return {\n content: compileContent(node.content, context),\n behavior: node.behavior ? compileBehavior(node.behavior, context) : undefined,\n };\n}\n\n/**\n * 编译 Content 节点\n */\nfunction compileContent<TContext extends SlideContext = SlideContext>(\n node: ContentNode,\n context: TContext\n): SlideDefinition['content'] {\n if (node.type === 'dynamic') {\n // 动态内容(组件)\n return {\n type: 'dynamic',\n component: node.component,\n props: evaluateProps(node.props, context),\n };\n } else {\n // 静态文本\n return {\n type: 'text',\n lines: node.lines.map(line => String(evaluateExpression(line, context))),\n };\n }\n}\n\n/**\n * 编译 Behavior 节点\n */\nfunction compileBehavior<TContext extends SlideContext = SlideContext>(\n node: BehaviorNode,\n context: TContext\n): SlideDefinition['behavior'] {\n return {\n transition: {\n type: (node.transition as unknown as { transType: string }).transType as 'slide' | 'zoom' | 'fade' | 'cube' | 'flip' | 'none',\n ...evaluateProps(node.transition.options, context),\n },\n };\n}\n\n/**\n * 计算属性对象\n */\nfunction evaluateProps<TContext extends SlideContext = SlideContext>(\n props: Record<string, ExpressionValue>,\n context: TContext\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(props)) {\n result[key] = evaluateExpression(value, context);\n }\n\n return result;\n}\n\n/**\n * 计算表达式\n */\nfunction evaluateExpression<TContext extends SlideContext = SlideContext>(\n expr: ExpressionValue,\n context: TContext\n): unknown {\n // 字符串字面量\n if (typeof expr === 'string') {\n return expr;\n }\n\n // 对象类型(AST 节点)\n if (typeof expr === 'object' && expr !== null && 'type' in expr) {\n switch (expr.type) {\n case 'number':\n return (expr as NumberLiteralNode).value;\n\n case 'boolean':\n return (expr as BooleanLiteralNode).value;\n\n case 'member':\n return evaluateMemberExpression(expr as MemberExpressionNode, context);\n\n case 'binary':\n return evaluateBinaryExpression(expr as BinaryExpressionNode, context);\n\n default:\n throw new CompileError(`Unknown expression type: ${(expr as { type: string }).type}`);\n }\n }\n\n throw new CompileError(`Invalid expression: ${JSON.stringify(expr)}`);\n}\n\n/**\n * 计算成员表达式(如 quiz.title, section.questions)\n * 也处理单个变量引用(properties 为空数组)\n */\nfunction evaluateMemberExpression<TContext extends SlideContext = SlideContext>(\n expr: MemberExpressionNode,\n context: TContext\n): unknown {\n // 从 context 中获取对象\n let value: unknown = context[expr.object as keyof TContext];\n\n // 如果没有属性,直接返回变量值(单个标识符的情况)\n if (expr.properties.length === 0) {\n if (value === undefined) {\n throw new CompileError(\n `Variable \"${expr.object}\" is not defined in context`\n );\n }\n return value;\n }\n\n // 构建属性路径用于错误信息\n const pathParts: string[] = [expr.object];\n\n // 遍历属性链\n for (const prop of expr.properties) {\n pathParts.push(prop);\n const currentPath = pathParts.join('.');\n\n // 检查 value 是否为 null 或 undefined\n if (value === null || value === undefined) {\n throw new CompileError(\n `Cannot access property \"${prop}\" of \"${pathParts.slice(0, -1).join('.')}\" because it is ${value === null ? 'null' : 'undefined'}`\n );\n }\n\n // 检查 value 是否为对象\n if (typeof value !== 'object') {\n throw new CompileError(\n `Cannot access property \"${prop}\" of \"${pathParts.slice(0, -1).join('.')}\" because it is not an object (got ${typeof value})`\n );\n }\n\n // 检查属性是否存在\n if (!(prop in value)) {\n throw new CompileError(\n `Property \"${prop}\" does not exist on \"${pathParts.slice(0, -1).join('.')}\"`\n );\n }\n\n value = (value as Record<string, unknown>)[prop];\n }\n\n return value;\n}\n\n/**\n * 计算二元表达式\n */\nfunction evaluateBinaryExpression<TContext extends SlideContext = SlideContext>(\n expr: BinaryExpressionNode,\n context: TContext\n): unknown {\n const left = evaluateExpression(expr.left, context);\n const right = evaluateExpression(expr.right, context);\n\n switch (expr.operator) {\n case '+':\n // 字符串拼接或数字相加\n if (typeof left === 'string' || typeof right === 'string') {\n return String(left) + String(right);\n }\n // 确保是数字类型\n if (typeof left !== 'number' || typeof right !== 'number') {\n throw new CompileError(\n `Cannot add ${typeof left} and ${typeof right}. Both operands must be numbers or at least one must be a string.`\n );\n }\n return left + right;\n\n case '-':\n if (typeof left !== 'number' || typeof right !== 'number') {\n throw new CompileError(\n `Cannot subtract ${typeof right} from ${typeof left}. Both operands must be numbers.`\n );\n }\n return left - right;\n\n case '*':\n if (typeof left !== 'number' || typeof right !== 'number') {\n throw new CompileError(\n `Cannot multiply ${typeof left} and ${typeof right}. Both operands must be numbers.`\n );\n }\n return left * right;\n\n case '/':\n if (typeof left !== 'number' || typeof right !== 'number') {\n throw new CompileError(\n `Cannot divide ${typeof left} by ${typeof right}. Both operands must be numbers.`\n );\n }\n if (right === 0) {\n throw new CompileError('Division by zero is not allowed');\n }\n return left / right;\n\n default:\n throw new CompileError(`Unknown operator: ${expr.operator}`);\n }\n}\n"],"names":["ParseError","message","location","createParser","parse","source","error","errorMessage","parseSlideDSL","CompileError","compile","ast","rules","ruleNode","compileRule","node","context","compileSlide","slideNode","compileRuleBody","body","compileForLoop","slides","collection","evaluateExpression","item","loopContext","compileContent","compileBehavior","evaluateProps","line","props","result","key","value","expr","evaluateMemberExpression","evaluateBinaryExpression","pathParts","prop","left","right"],"mappings":"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"}
|