Skip to content

Commit fb05308

Browse files
committed
Merge branch 'feature/refine-for-examples' into develop
2 parents 2de8944 + d081f6d commit fb05308

20 files changed

+624
-93
lines changed

cli/cli.ts

+29-17
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
#!/usr/bin/env node
22
import * as program from "commander";
3-
import { ComposeFile, ComposeDirectory, InspectDirectory, InspectFile } from "./literator";
3+
import { ComposeFile, ComposeDirectory, InspectDirectory, InspectFile, CrossoutDirectory } from "./literator";
44
import { resolve, join } from "path";
55
import { lstatSync } from "fs";
66
import { readJsonSync, readJSONSync } from "fs-extra";
7-
import { config } from "./config.js";
7+
import { config } from "./config";
88

99
const package_json = readJSONSync(resolve(__dirname, "../../package.json"));
1010
program.version(package_json.version)
1111
program.option("-w, --watch", "compose file or files in directory in watch mode");
12+
program.option("-clean, --clean", "remove generated files");
1213
program.parse(process.argv);
1314

1415
const args = program.args;
@@ -19,29 +20,40 @@ if (args.length === 0)
1920
}
2021
else
2122
{
22-
const working_directory = process.cwd();
2323
const [target] = args;
24+
2425
if (target)
2526
{
26-
27-
//
28-
const project_package = readJsonSync(join(working_directory, "package.json"), { throws: false }) || { devDependencies: {} };
29-
30-
const dsl_names = Object.keys(project_package.devDependencies).filter(key => key.startsWith("draft-dsl"));
31-
const dsls = dsl_names.map(name => require(`${join(working_directory, "node_modules", name)}`)?.MakeDSL());
32-
config.dsls = dsls;
33-
34-
//
35-
const path = resolve(working_directory, target);
36-
if (lstatSync(path).isDirectory())
27+
if (program.clean)
3728
{
38-
program.watch ? InspectDirectory(path) : ComposeDirectory(path);
29+
CrossoutDirectory(target);
3930
}
40-
else
31+
else
4132
{
42-
program.watch ? InspectFile(path) : ComposeFile(path);
33+
Transcribe(target);
4334
}
4435
}
4536
}
4637

38+
function Transcribe(target: string)
39+
{
40+
//
41+
const working_directory = process.cwd();
42+
const project_package = readJsonSync(join(working_directory, "package.json"), { throws: false }) || { devDependencies: {} };
43+
44+
//
45+
const dsl_names = Object.keys(project_package.devDependencies).filter(key => key.startsWith("draft-dsl"));
46+
const dsls = dsl_names.map(name => require(`${join(working_directory, "node_modules", name)}`)?.MakeDSL());
47+
config.dsls = dsls;
4748

49+
//
50+
const path = resolve(working_directory, target);
51+
if (lstatSync(path).isDirectory())
52+
{
53+
program.watch ? InspectDirectory(path) : ComposeDirectory(path);
54+
}
55+
else
56+
{
57+
program.watch ? InspectFile(path) : ComposeFile(path);
58+
}
59+
}

cli/literator.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ export function CrossoutDirectory(path: string)
8282
{
8383
if (absolute.endsWith(".tsx"))
8484
{
85-
removeSync(absolute.replace(".tsx", ".svelte"));
85+
removeSync(absolute.replace(".tsx", ""));
8686
}
8787
})
8888
}

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "svelte-draft",
3-
"version": "0.0.5",
3+
"version": "0.1.0",
44
"description": "Develop svelte app in typedraft",
55
"author": "mistlog",
66
"license": "MIT",

source-view/generator/closing-element-visitor.md

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ function HandleClosingElement(tag_name: string, e: NodePath<JSXClosingElement>,
2424
"use match";
2525
(tag_name: "if" | "each" | "await") => Append(`{/${tag_name}}`);
2626
(tag_name: "else") => Append("");
27+
(tag_name: "debug") => Append("}");
2728
() => Append(ToString(e.node));
2829
}
2930
```

source-view/generator/jsx-expression-container-visitor.md

+21-3
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,25 @@ function HandleContainer(tag_name: string) {
2727
(tag_name: "await") => {
2828
<HandleAwait />;
2929
};
30+
(tag_name: "debug") => {
31+
<HandleDebug />;
32+
};
3033
() => {
3134
<HandleDefault />;
3235
};
3336
}
3437
```
3538

3639
```typescript
37-
function HandleAwait(container: NodePath<JSXExpressionContainer>, generator: IGenerator) {
40+
function HandleDebug(container: NodePath<JSXExpressionContainer>, generator: IGenerator) {
41+
const to_debug = (container.get("expression") as NodePath<ArrayExpression>).get("elements");
42+
const variable_list = to_debug.map(each => ToString(each.node)).join(", ");
43+
generator.Append(variable_list);
44+
}
45+
```
46+
47+
```typescript
48+
function HandleAwait(container: NodePath<JSXExpressionContainer>) {
3849
//
3950
const info = container.get("expression");
4051
if (!info.isObjectExpression()) return;
@@ -104,7 +115,14 @@ function HandleEach(container: NodePath<JSXExpressionContainer>, generator: IGen
104115
```
105116

106117
```typescript
107-
function HandleDefault(container: NodePath<JSXExpressionContainer>, generator: IGenerator) {
108-
generator.Append(ToString(container.node));
118+
function HandleDefault(container: NodePath<JSXExpressionContainer>, generator: IGenerator) {
119+
const expression = container.get("expression");
120+
121+
// use slot props
122+
if (expression.isArrowFunctionExpression()) {
123+
generator.TraverseTag(expression.get("body") as NodePath<JSXElement>);
124+
} else {
125+
generator.Append(ToString(container.node));
126+
}
109127
}
110128
```

source-view/generator/opening-element-visitor.md

+110-13
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ export class OpeningElementVisitor {}
55
```typescript
66
<OpeningElementVisitor /> +
77
function Visit(e: NodePath<JSXOpeningElement>, generator: IGenerator) {
8+
<HandleSlotProps />;
89
<HandleAttributes />;
910

1011
//
@@ -19,27 +20,90 @@ export class OpeningElementVisitor {}
1920
```
2021

2122
```typescript
22-
const TargetTable = { DoubleClick: "dblclick", InnerHTML: "innerHTML", contentEditable: "contenteditable" };
23+
const TargetTable = { DoubleClick: "dblclick", InnerHTML: "innerHTML", contentEditable: "contenteditable", Ref: "this" };
2324
```
2425

2526
```typescript
2627
const NamespaceList = ["on", "bind"];
2728
```
2829

30+
```typescript
31+
const DirectiveSet = new Set(["transition", "in", "out", "localTransition", "animate", "use"]);
32+
```
33+
2934
```typescript
3035
function HandleAttributes(e: NodePath<JSXOpeningElement>) {
36+
<PreprocessAttributes />;
3137
e.node.attributes.forEach(attr => {
3238
if (attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier") {
3339
const name = attr.name.name;
34-
NamespaceList.forEach(namespace => {
35-
if (TargetTable[name]) {
36-
attr.name = jsxIdentifier(TargetTable[name]);
37-
} else if (name.startsWith(namespace)) {
38-
const raw_target = name.substr(namespace.length);
39-
const target = TargetTable[raw_target] || raw_target.toLowerCase();
40-
attr.name = jsxNamespacedName(jsxIdentifier(namespace), jsxIdentifier(target));
41-
}
42-
});
40+
if (DirectiveSet.has(name)) {
41+
<HandleDirective />;
42+
} else {
43+
<HandleNamespace />;
44+
}
45+
}
46+
});
47+
}
48+
```
49+
50+
```typescript
51+
function PreprocessAttributes(e: NodePath<JSXOpeningElement>) {
52+
e.node.attributes = e.node.attributes.reduce((container, attr) => {
53+
if (attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier" && (attr.name.name === "on" || attr.name.name === "props")) {
54+
const value = attr.value as JSXExpressionContainer;
55+
const config = value.expression as CallExpression;
56+
const [event_config] = config.arguments as [ObjectExpression];
57+
const properties = event_config.properties as Array<ObjectProperty>;
58+
properties.forEach(each => {
59+
//
60+
const prop: string = (each.key as Identifier).name;
61+
const prop_value: string = ToString(each.value);
62+
63+
//
64+
const prefix = attr.name.name === "on" ? "on" : "";
65+
const name = jsxIdentifier(`${prefix}${prop}`);
66+
const value = stringLiteral(`{${prop_value}}`);
67+
container.push(jsxAttribute(name, value));
68+
});
69+
} else {
70+
container.push(attr);
71+
}
72+
return container;
73+
}, []);
74+
}
75+
```
76+
77+
```typescript
78+
const VerticalBar = "$VERTICAL_BAR$";
79+
```
80+
81+
```typescript
82+
function HandleDirective(attr: JSXAttribute) {
83+
const value = attr.value as JSXExpressionContainer;
84+
const config = value.expression as CallExpression;
85+
86+
// use compact to avoid \n in params after ToString
87+
const args = config.arguments.map(arg => ToString(arg, { compact: true }));
88+
const [transition_function, transition_params] = args;
89+
90+
// use VerticalBar and replace it with | latter because | is invalid in JSX
91+
let namespace = name === "localTransition" ? `transition` : name;
92+
let function_name = name === "localTransition" ? `${transition_function}${VerticalBar}local` : transition_function;
93+
attr.name = jsxNamespacedName(jsxIdentifier(namespace), jsxIdentifier(function_name));
94+
attr.value = transition_params ? stringLiteral(`{${transition_params}}`) : null;
95+
}
96+
```
97+
98+
```typescript
99+
function HandleNamespace(attr: JSXAttribute, name: string) {
100+
NamespaceList.forEach(namespace => {
101+
if (TargetTable[name]) {
102+
attr.name = jsxIdentifier(TargetTable[name]);
103+
} else if (name.startsWith(namespace)) {
104+
const raw_target = name.substr(namespace.length);
105+
const target = TargetTable[raw_target] || raw_target.toLowerCase();
106+
attr.name = jsxNamespacedName(jsxIdentifier(namespace), jsxIdentifier(target));
43107
}
44108
});
45109
}
@@ -48,6 +112,9 @@ function HandleAttributes(e: NodePath<JSXOpeningElement>) {
48112
```typescript
49113
function HandleOpeningElement(tag_name: string) {
50114
"use match";
115+
(tag_name: "debug") => {
116+
<HandleDebug />;
117+
};
51118
(tag_name: "if") => {
52119
<HandleIf />;
53120
};
@@ -67,8 +134,19 @@ function HandleOpeningElement(tag_name: string) {
67134
```
68135

69136
```typescript
70-
function HandleDefault(e: NodePath<JSXOpeningElement>, Append: (value: string) => void) {
71-
Append(ToString(e.node));
137+
function HandleDefault(e: NodePath<JSXOpeningElement>, Append: (value: string) => void) {
138+
//
139+
let element = ToString(e.node);
140+
141+
// handle |
142+
element = element.replace(VerticalBar, "|");
143+
Append(element);
144+
}
145+
```
146+
147+
```typescript
148+
function HandleDebug(Append: (value: string) => void) {
149+
Append(`{@debug `);
72150
}
73151
```
74152

@@ -90,6 +168,25 @@ function HandleElse(e: NodePath<JSXOpeningElement>, Append: (value: string) => v
90168
}
91169
```
92170

171+
```typescript
172+
function HandleSlotProps(e: NodePath<JSXOpeningElement>) {
173+
const slot_props = FindChildJSXExpressionContainer(e)
174+
?.get("expression")
175+
?.get("params")
176+
.find(each => each.isObjectPattern()) as NodePath<ObjectPattern>;
177+
if (slot_props) {
178+
const properties = slot_props.node.properties as Array<ObjectProperty>;
179+
properties.forEach(each => {
180+
const prop: string = (each.key as Identifier).name;
181+
const alias: string = ToString(each.value);
182+
const name = jsxNamespacedName(jsxIdentifier("let"), jsxIdentifier(prop));
183+
const value = jsxExpressionContainer(identifier(alias));
184+
e.node.attributes.push(jsxAttribute(name, value));
185+
});
186+
}
187+
}
188+
```
189+
93190
```typescript
94191
function HandleEach(e: NodePath<JSXOpeningElement>, Append: (value: string) => void) {
95192
const raw_from = FindAttribute("from", e)?.node;
@@ -114,7 +211,7 @@ function HandleEach(e: NodePath<JSXOpeningElement>, Append: (value: string) => v
114211

115212
// if we specify value, key only, key info is stored in index
116213
const item_part = `#each ${data} as ${value || "__invalid value__"}`;
117-
const index_part = index ? (index.is_key ? ` (${index.key_name})}` : `, ${index}`) : "";
214+
const index_part = index ? (index.is_key ? ` (${index.key_name})` : `, ${index}`) : "";
118215
const key_part = key ? ` (${key.key_name})` : "";
119216
const each = `{${item_part}${index_part}${key_part}}`;
120217
Append(each);

source-view/section/import-section.md

+7-6
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@ export function TranslateImport(statements: Array<NodePath<ImportDeclaration>>)
44
statements.forEach(each => {
55
//
66
const node = each.node;
7-
const cloned = cloneDeep(node);
8-
const import_from = cloned.source.value;
7+
const import_from = node.source.value;
98

10-
//
11-
if (import_from.startsWith(".") || import_from.startsWith("..")) {
12-
cloned.source.value = import_from.replace(".tsx", "");
9+
// for functions such as store auto subscription: AutoSubscribe
10+
11+
// remove them, because they are just "type provider"
12+
if (import_from.includes("svelte-types")) {
13+
return;
1314
}
14-
translated.push(cloned);
15+
translated.push(node);
1516
});
1617
return translated.map(each => `${ToString(each, { comments: false })}`).join("\n");
1718
}

source-view/section/script-section.md

+20-16
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,24 @@
11
```typescript
2-
export function TranslateScript(body: NodePath<BlockStatement>) {
3-
const translated: Array<Statement> = [];
4-
body.get("body").forEach(each => {
5-
if (each.isVariableDeclaration() && each.node.declarations.length === 1) {
6-
const [declarator] = each.get("declarations");
7-
const init = declarator.get("init");
8-
if (init.isIdentifier() && init.node.name === "props") {
9-
<HandleProps />;
10-
} else {
11-
translated.push(each.node);
12-
}
13-
} else if (!IsTemplate(each)) {
14-
translated.push(each.node);
15-
}
16-
});
17-
return translated.map(each => `${ToString(each, { comments: false })}`).join("\n");
2+
export function TranslateScript(body: NodePath<BlockStatement>) {
3+
const translated: Array<Statement> = [];
4+
body.get("body").forEach(each => {
5+
if (each.isVariableDeclaration() && each.node.declarations.length === 1) {
6+
const [declarator] = each.get("declarations");
7+
if (ToString(declarator.node).startsWith("$")) {
8+
// ignore variable declaration starts with $
9+
return;
10+
}
11+
const init = declarator.get("init");
12+
if (init.isIdentifier() && init.node.name === "props") {
13+
<HandleProps />;
14+
} else {
15+
translated.push(each.node);
16+
}
17+
} else if (!IsTemplate(each)) {
18+
translated.push(each.node);
19+
}
20+
});
21+
return translated.map(each => `${ToString(each, { comments: false })}`).join("\n");
1822
}
1923
```
2024

src/generator/closing-element-visitor.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ function HandleClosingElement(tag_name: string, e: NodePath<JSXClosingElement>,
2828

2929
(tag_name: "if" | "each" | "await") => Append(`{/${tag_name}}`);
3030
(tag_name: "else") => Append("");
31+
(tag_name: "debug") => Append("}");
3132
() => Append(ToString(e.node));
3233
}
3334

0 commit comments

Comments
 (0)