@godot-scene-web/tscn-parser 0.1.0
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/LICENSE +21 -0
- package/dist/index.d.ts +116 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +604 -0
- package/dist/index.js.map +1 -0
- package/package.json +41 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Tomás Fox
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
//#region ../core/dist/index.d.ts
|
|
2
|
+
//#region src/index.d.ts
|
|
3
|
+
type GodotDocumentKind = "scene" | "resource";
|
|
4
|
+
/** Renderer-neutral 3×3 linear RGB transform. */
|
|
5
|
+
interface GodotParseDiagnostic {
|
|
6
|
+
severity: "warning" | "error";
|
|
7
|
+
code: string;
|
|
8
|
+
message: string;
|
|
9
|
+
line?: number;
|
|
10
|
+
column?: number;
|
|
11
|
+
}
|
|
12
|
+
interface GodotResource {
|
|
13
|
+
type?: string;
|
|
14
|
+
header: GodotSectionHeader | null;
|
|
15
|
+
extResources: GodotExtResource[];
|
|
16
|
+
subResources: GodotSubResource[];
|
|
17
|
+
properties: Record<string, GodotVariant>;
|
|
18
|
+
diagnostics: GodotParseDiagnostic[];
|
|
19
|
+
}
|
|
20
|
+
interface GodotSceneState {
|
|
21
|
+
kind: "scene";
|
|
22
|
+
nodes: GodotSceneStateNode[];
|
|
23
|
+
connections: GodotSceneStateConnection[];
|
|
24
|
+
extResources: GodotExtResource[];
|
|
25
|
+
subResources: GodotSubResource[];
|
|
26
|
+
editableInstances: string[];
|
|
27
|
+
basePath?: string;
|
|
28
|
+
diagnostics: GodotParseDiagnostic[];
|
|
29
|
+
}
|
|
30
|
+
interface GodotSceneStateNode {
|
|
31
|
+
index: number;
|
|
32
|
+
siblingIndex?: number;
|
|
33
|
+
name: string;
|
|
34
|
+
type?: string;
|
|
35
|
+
parent?: string;
|
|
36
|
+
owner?: string;
|
|
37
|
+
instance?: GodotResourceRefValue;
|
|
38
|
+
instancePlaceholder?: string;
|
|
39
|
+
groups: string[];
|
|
40
|
+
properties: GodotOrderedProperty[];
|
|
41
|
+
}
|
|
42
|
+
interface GodotOrderedProperty {
|
|
43
|
+
name: string;
|
|
44
|
+
value: GodotVariant;
|
|
45
|
+
}
|
|
46
|
+
interface GodotSceneStateConnection {
|
|
47
|
+
signal?: string;
|
|
48
|
+
from?: string;
|
|
49
|
+
to?: string;
|
|
50
|
+
method?: string;
|
|
51
|
+
flags?: number;
|
|
52
|
+
binds?: GodotVariant[];
|
|
53
|
+
unbinds?: number;
|
|
54
|
+
}
|
|
55
|
+
interface GodotSectionHeader {
|
|
56
|
+
section: string;
|
|
57
|
+
attributes: Record<string, GodotVariant>;
|
|
58
|
+
}
|
|
59
|
+
interface GodotExtResource {
|
|
60
|
+
id: string;
|
|
61
|
+
type?: string;
|
|
62
|
+
path?: string;
|
|
63
|
+
uid?: string;
|
|
64
|
+
attributes: Record<string, GodotVariant>;
|
|
65
|
+
properties: Record<string, GodotVariant>;
|
|
66
|
+
}
|
|
67
|
+
interface GodotSubResource {
|
|
68
|
+
id: string;
|
|
69
|
+
type?: string;
|
|
70
|
+
attributes: Record<string, GodotVariant>;
|
|
71
|
+
properties: Record<string, GodotVariant>;
|
|
72
|
+
}
|
|
73
|
+
type GodotVariant = null | boolean | number | string | GodotStringNameVariant | GodotVectorVariant | GodotColorVariant | GodotRectVariant | GodotNodePathVariant | GodotResourceRefValue | GodotCallVariant | GodotVariant[] | {
|
|
74
|
+
[key: string]: GodotVariant;
|
|
75
|
+
};
|
|
76
|
+
interface GodotVectorVariant {
|
|
77
|
+
type: "Vector2" | "Vector2i" | "Vector3" | "Vector3i" | "Vector4" | "Vector4i";
|
|
78
|
+
args: number[];
|
|
79
|
+
}
|
|
80
|
+
interface GodotColorVariant {
|
|
81
|
+
type: "Color";
|
|
82
|
+
args: number[];
|
|
83
|
+
}
|
|
84
|
+
interface GodotStringNameVariant {
|
|
85
|
+
type: "StringName";
|
|
86
|
+
args: string[];
|
|
87
|
+
}
|
|
88
|
+
interface GodotRectVariant {
|
|
89
|
+
type: "Rect2" | "Rect2i";
|
|
90
|
+
args: number[];
|
|
91
|
+
}
|
|
92
|
+
interface GodotNodePathVariant {
|
|
93
|
+
type: "NodePath";
|
|
94
|
+
args: string[];
|
|
95
|
+
}
|
|
96
|
+
interface GodotResourceRefValue {
|
|
97
|
+
type: "ExtResource" | "SubResource";
|
|
98
|
+
id?: string;
|
|
99
|
+
path?: string;
|
|
100
|
+
}
|
|
101
|
+
interface GodotCallVariant {
|
|
102
|
+
type: string;
|
|
103
|
+
args: GodotVariant[];
|
|
104
|
+
}
|
|
105
|
+
//#endregion
|
|
106
|
+
//#region src/index.d.ts
|
|
107
|
+
interface ParseGodotTextOptions {
|
|
108
|
+
path?: string;
|
|
109
|
+
kind?: GodotDocumentKind;
|
|
110
|
+
}
|
|
111
|
+
declare function parseGodotTextScene(text: string, options?: ParseGodotTextOptions): GodotSceneState;
|
|
112
|
+
declare function parseGodotResource(text: string, options?: ParseGodotTextOptions): GodotResource;
|
|
113
|
+
declare function parseGodotValue(source: string, diagnostics?: GodotParseDiagnostic[], line?: number): GodotVariant;
|
|
114
|
+
//#endregion
|
|
115
|
+
export { ParseGodotTextOptions, parseGodotResource, parseGodotTextScene, parseGodotValue };
|
|
116
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":["GodotDocumentKind","ColorMatrix","rows","GodotParseDiagnostic","severity","code","message","line","column","GodotResource","GodotSectionHeader","GodotExtResource","GodotSubResource","GodotVariant","Record","type","header","extResources","subResources","properties","diagnostics","GodotSceneState","GodotSceneStateNode","GodotSceneStateConnection","kind","nodes","connections","editableInstances","basePath","GodotResourceRefValue","GodotOrderedProperty","index","siblingIndex","name","parent","owner","instance","instancePlaceholder","groups","value","signal","from","to","method","flags","binds","unbinds","section","attributes","id","path","uid","GodotNode","propertyEntries","GodotConnection","GodotEditable","GodotStringNameVariant","GodotVectorVariant","GodotColorVariant","GodotRectVariant","GodotNodePathVariant","GodotCallVariant","key","args","GodotRect","x","y","width","height","isColorValue","isRectValue","asNumber","asBoolean","asString","asVector2","asRect2","asResourceRef","decodeFromNativeValue","isGodotSceneState","godotNodePath","node","godotParentPath"],"sources":["../../core/dist/index.d.ts","../src/index.ts"],"mappings":";;KACKA,iBAAAA;;UAKKG,oBAAAA;EACRC,QAAAA;EACAC,IAAAA;EACAC,OAAAA;EACAC,IAAAA;EACAC,MAAAA;AAAAA;AAAAA,UAEQC,aAAAA;EACRM,IAAAA;EACAC,MAAAA,EAAQN,kBAAAA;EACRO,YAAAA,EAAcN,gBAAAA;EACdO,YAAAA,EAAcN,gBAAAA;EACdO,UAAAA,EAAYL,MAAAA,SAAeD,YAAAA;EAC3BO,WAAAA,EAAajB,oBAAAA;AAAAA;AAAAA,UAELkB,eAAAA;EACRG,IAAAA;EACAC,KAAAA,EAAOH,mBAAAA;EACPI,WAAAA,EAAaH,yBAAAA;EACbN,YAAAA,EAAcN,gBAAAA;EACdO,YAAAA,EAAcN,gBAAAA;EACde,iBAAAA;EACAC,QAAAA;EACAR,WAAAA,EAAajB,oBAAAA;AAAAA;AAAAA,UAELmB,mBAAAA;EACRS,KAAAA;EACAC,YAAAA;EACAC,IAAAA;EACAlB,IAAAA;EACAmB,MAAAA;EACAC,KAAAA;EACAC,QAAAA,GAAWP,qBAAAA;EACXQ,mBAAAA;EACAC,MAAAA;EACAnB,UAAAA,EAAYW,oBAAoB;AAAA;AAAA,UAExBA,oBAAAA;EACRG,IAAAA;EACAM,KAAAA,EAAO1B,YAAY;AAAA;AAAA,UAEXU,yBAAAA;EACRiB,MAAAA;EACAC,IAAAA;EACAC,EAAAA;EACAC,MAAAA;EACAC,KAAAA;EACAC,KAAAA,GAAQhC,YAAY;EACpBiC,OAAAA;AAAAA;AAAAA,UAEQpC,kBAAAA;EACRqC,OAAAA;EACAC,UAAAA,EAAYlC,MAAM,SAASD,YAAAA;AAAAA;AAAAA,UAEnBF,gBAAAA;EACRsC,EAAAA;EACAlC,IAAAA;EACAmC,IAAAA;EACAC,GAAAA;EACAH,UAAAA,EAAYlC,MAAAA,SAAeD,YAAAA;EAC3BM,UAAAA,EAAYL,MAAAA,SAAeD,YAAAA;AAAAA;AAAAA,UAEnBD,gBAAAA;EACRqC,EAAAA;EACAlC,IAAAA;EACAiC,UAAAA,EAAYlC,MAAAA,SAAeD,YAAAA;EAC3BM,UAAAA,EAAYL,MAAAA,SAAeD,YAAAA;AAAAA;AAAAA,KAsBxBA,YAAAA,sCAAkD2C,sBAAAA,GAAyBC,kBAAAA,GAAqBC,iBAAAA,GAAoBC,gBAAAA,GAAmBC,oBAAAA,GAAuB/B,qBAAAA,GAAwBgC,gBAAAA,GAAmBhD,YAAAA;EAAAA,CAC3MiD,GAAAA,WAAcjD,YAAAA;AAAAA;AAAAA,UAEP4C,kBAAAA;EACR1C,IAAAA;EACAgD,IAAI;AAAA;AAAA,UAEIL,iBAAAA;EACR3C,IAAAA;EACAgD,IAAI;AAAA;AAAA,UAEIP,sBAAAA;EACRzC,IAAAA;EACAgD,IAAI;AAAA;AAAA,UAEIJ,gBAAAA;EACR5C,IAAAA;EACAgD,IAAI;AAAA;AAAA,UAEIH,oBAAAA;EACR7C,IAAAA;EACAgD,IAAI;AAAA;AAAA,UAEIlC,qBAAAA;EACRd,IAAAA;EACAkC,EAAAA;EACAC,IAAAA;AAAAA;AAAAA,UAEQW,gBAAAA;EACR9C,IAAAA;EACAgD,IAAAA,EAAMlD,YAAY;AAAA;;;UCrFH,qBAAA;EACf,IAAA;EACA,IAAA,GAAO,iBAAiB;AAAA;AAAA,iBAGV,mBAAA,CACd,IAAA,UACA,OAAA,GAAS,qBAAA,GACR,eAAe;AAAA,iBAMF,kBAAA,CACd,IAAA,UACA,OAAA,GAAS,qBAAA,GACR,aAAa;AAAA,iBA4DA,eAAA,CACd,MAAA,UACA,WAAA,GAAa,oBAAA,IACb,IAAA,YACC,YAAY"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,604 @@
|
|
|
1
|
+
//#region src/index.ts
|
|
2
|
+
function parseGodotTextScene(text, options = {}) {
|
|
3
|
+
return godotSceneStateFromDocument(parseDocument(text, {
|
|
4
|
+
...options,
|
|
5
|
+
kind: "scene"
|
|
6
|
+
}));
|
|
7
|
+
}
|
|
8
|
+
function parseGodotResource(text, options = {}) {
|
|
9
|
+
return godotResourceFromDocument(parseDocument(text, {
|
|
10
|
+
...options,
|
|
11
|
+
kind: "resource"
|
|
12
|
+
}));
|
|
13
|
+
}
|
|
14
|
+
function parseDocument(text, options = {}) {
|
|
15
|
+
const kind = options.kind ?? "resource";
|
|
16
|
+
const diagnostics = [];
|
|
17
|
+
const document = {
|
|
18
|
+
kind,
|
|
19
|
+
header: null,
|
|
20
|
+
extResources: [],
|
|
21
|
+
subResources: [],
|
|
22
|
+
nodes: [],
|
|
23
|
+
connections: [],
|
|
24
|
+
editables: [],
|
|
25
|
+
properties: {},
|
|
26
|
+
diagnostics
|
|
27
|
+
};
|
|
28
|
+
let current = { kind: "document" };
|
|
29
|
+
const lines = text.replace(/^\uFEFF/, "").split(/\r?\n/);
|
|
30
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
31
|
+
const lineNumber = index + 1;
|
|
32
|
+
const logical = collectLogicalLine(lines, index);
|
|
33
|
+
index = logical.endIndex;
|
|
34
|
+
const line = stripLineComment(logical.raw).trim();
|
|
35
|
+
if (line.length === 0) continue;
|
|
36
|
+
if (line.startsWith("[") && line.endsWith("]")) {
|
|
37
|
+
current = parseSectionHeader(line.slice(1, -1), lineNumber, diagnostics, document);
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
const assignment = splitAssignment(line);
|
|
41
|
+
if (!assignment) {
|
|
42
|
+
diagnostics.push({
|
|
43
|
+
severity: "warning",
|
|
44
|
+
code: "godot_parser_unsupported_line",
|
|
45
|
+
message: "Unsupported Godot text line.",
|
|
46
|
+
line: lineNumber
|
|
47
|
+
});
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
const value = parseGodotValue(assignment.value, diagnostics, lineNumber);
|
|
51
|
+
assignProperty(document, current, assignment.key, value);
|
|
52
|
+
}
|
|
53
|
+
return document;
|
|
54
|
+
}
|
|
55
|
+
function parseGodotValue(source, diagnostics = [], line) {
|
|
56
|
+
const parser = new ValueParser(source, diagnostics, line);
|
|
57
|
+
const value = parser.parseValue();
|
|
58
|
+
parser.skipTrivia();
|
|
59
|
+
if (!parser.done()) diagnostics.push({
|
|
60
|
+
severity: "warning",
|
|
61
|
+
code: "godot_parser_trailing_value_text",
|
|
62
|
+
message: `Trailing text after Godot value: ${source.slice(parser.position)}`,
|
|
63
|
+
line
|
|
64
|
+
});
|
|
65
|
+
return value;
|
|
66
|
+
}
|
|
67
|
+
function parseSectionHeader(source, line, diagnostics, document) {
|
|
68
|
+
const [section = "", ...attributeParts] = splitHeaderParts(source);
|
|
69
|
+
const attributes = parseHeaderAttributes(attributeParts.join(" "), diagnostics, line);
|
|
70
|
+
switch (section) {
|
|
71
|
+
case "gd_scene":
|
|
72
|
+
case "gd_resource": {
|
|
73
|
+
const header = {
|
|
74
|
+
section,
|
|
75
|
+
attributes
|
|
76
|
+
};
|
|
77
|
+
document.header = header;
|
|
78
|
+
document.kind = section === "gd_scene" ? "scene" : "resource";
|
|
79
|
+
return {
|
|
80
|
+
kind: "header",
|
|
81
|
+
header
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
case "ext_resource": {
|
|
85
|
+
const resource = {
|
|
86
|
+
id: stringAttribute(attributes.id) ?? "",
|
|
87
|
+
type: stringAttribute(attributes.type),
|
|
88
|
+
path: stringAttribute(attributes.path),
|
|
89
|
+
uid: stringAttribute(attributes.uid),
|
|
90
|
+
attributes,
|
|
91
|
+
properties: {}
|
|
92
|
+
};
|
|
93
|
+
document.extResources.push(resource);
|
|
94
|
+
return {
|
|
95
|
+
kind: "ext_resource",
|
|
96
|
+
resource
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
case "sub_resource": {
|
|
100
|
+
const resource = {
|
|
101
|
+
id: stringAttribute(attributes.id) ?? "",
|
|
102
|
+
type: stringAttribute(attributes.type),
|
|
103
|
+
attributes,
|
|
104
|
+
properties: {}
|
|
105
|
+
};
|
|
106
|
+
document.subResources.push(resource);
|
|
107
|
+
return {
|
|
108
|
+
kind: "sub_resource",
|
|
109
|
+
resource
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
case "node": {
|
|
113
|
+
const node = {
|
|
114
|
+
name: stringAttribute(attributes.name) ?? "",
|
|
115
|
+
type: stringAttribute(attributes.type),
|
|
116
|
+
parent: stringAttribute(attributes.parent),
|
|
117
|
+
instance: resourceRefAttribute(attributes.instance),
|
|
118
|
+
attributes,
|
|
119
|
+
properties: {}
|
|
120
|
+
};
|
|
121
|
+
document.nodes.push(node);
|
|
122
|
+
return {
|
|
123
|
+
kind: "node",
|
|
124
|
+
node
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
case "connection": {
|
|
128
|
+
const connection = {
|
|
129
|
+
signal: stringAttribute(attributes.signal),
|
|
130
|
+
from: stringAttribute(attributes.from),
|
|
131
|
+
to: stringAttribute(attributes.to),
|
|
132
|
+
method: stringAttribute(attributes.method),
|
|
133
|
+
attributes
|
|
134
|
+
};
|
|
135
|
+
document.connections.push(connection);
|
|
136
|
+
return {
|
|
137
|
+
kind: "connection",
|
|
138
|
+
connection
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
case "editable": {
|
|
142
|
+
const editable = {
|
|
143
|
+
path: stringAttribute(attributes.path),
|
|
144
|
+
attributes
|
|
145
|
+
};
|
|
146
|
+
document.editables.push(editable);
|
|
147
|
+
return {
|
|
148
|
+
kind: "editable",
|
|
149
|
+
editable
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
case "resource": return { kind: "resource" };
|
|
153
|
+
default:
|
|
154
|
+
diagnostics.push({
|
|
155
|
+
severity: "warning",
|
|
156
|
+
code: "godot_parser_unknown_section",
|
|
157
|
+
message: `Unknown Godot text section: ${section}`,
|
|
158
|
+
line
|
|
159
|
+
});
|
|
160
|
+
return { kind: "document" };
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
function assignProperty(document, current, key, value) {
|
|
164
|
+
switch (current.kind) {
|
|
165
|
+
case "ext_resource":
|
|
166
|
+
current.resource.properties[key] = value;
|
|
167
|
+
break;
|
|
168
|
+
case "sub_resource":
|
|
169
|
+
current.resource.properties[key] = value;
|
|
170
|
+
break;
|
|
171
|
+
case "node":
|
|
172
|
+
current.node.properties[key] = value;
|
|
173
|
+
current.node.propertyEntries ??= [];
|
|
174
|
+
current.node.propertyEntries.push({
|
|
175
|
+
name: key,
|
|
176
|
+
value
|
|
177
|
+
});
|
|
178
|
+
break;
|
|
179
|
+
case "header":
|
|
180
|
+
current.header.attributes[key] = value;
|
|
181
|
+
break;
|
|
182
|
+
case "connection":
|
|
183
|
+
current.connection.attributes[key] = value;
|
|
184
|
+
break;
|
|
185
|
+
case "editable":
|
|
186
|
+
current.editable.attributes[key] = value;
|
|
187
|
+
break;
|
|
188
|
+
case "resource":
|
|
189
|
+
document.properties[key] = value;
|
|
190
|
+
break;
|
|
191
|
+
case "document":
|
|
192
|
+
document.properties[key] = value;
|
|
193
|
+
break;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
function godotSceneStateFromDocument(document) {
|
|
197
|
+
const basePath = stringAttribute(document.header?.attributes.path);
|
|
198
|
+
return {
|
|
199
|
+
kind: "scene",
|
|
200
|
+
nodes: document.nodes.map(godotSceneStateNodeFromDocumentNode),
|
|
201
|
+
connections: document.connections.map(godotSceneStateConnectionFromDocumentConnection),
|
|
202
|
+
extResources: document.extResources,
|
|
203
|
+
subResources: document.subResources,
|
|
204
|
+
editableInstances: document.editables.map((editable) => editable.path).filter((path) => typeof path === "string"),
|
|
205
|
+
...basePath ? { basePath } : {},
|
|
206
|
+
diagnostics: document.diagnostics
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
function godotResourceFromDocument(document) {
|
|
210
|
+
return {
|
|
211
|
+
type: stringAttribute(document.header?.attributes.type),
|
|
212
|
+
header: document.header,
|
|
213
|
+
extResources: document.extResources,
|
|
214
|
+
subResources: document.subResources,
|
|
215
|
+
properties: document.properties,
|
|
216
|
+
diagnostics: document.diagnostics
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
function godotSceneStateNodeFromDocumentNode(node, index) {
|
|
220
|
+
const owner = stringAttribute(node.attributes.owner);
|
|
221
|
+
const instancePlaceholder = stringAttribute(node.attributes.instance_placeholder) ?? stringAttribute(node.attributes.instancePlaceholder);
|
|
222
|
+
const siblingIndex = nodeIndexAttribute(node.attributes.index);
|
|
223
|
+
return {
|
|
224
|
+
index,
|
|
225
|
+
...siblingIndex !== void 0 ? { siblingIndex } : {},
|
|
226
|
+
name: node.name,
|
|
227
|
+
...node.type !== void 0 ? { type: node.type } : {},
|
|
228
|
+
parent: node.parent ?? ".",
|
|
229
|
+
...owner !== void 0 ? { owner } : {},
|
|
230
|
+
...node.instance !== void 0 ? { instance: node.instance } : {},
|
|
231
|
+
...instancePlaceholder !== void 0 ? { instancePlaceholder } : {},
|
|
232
|
+
groups: stringArrayAttribute(node.attributes.groups),
|
|
233
|
+
properties: node.propertyEntries?.map((property) => ({ ...property })) ?? Object.entries(node.properties).map(([name, value]) => ({
|
|
234
|
+
name,
|
|
235
|
+
value
|
|
236
|
+
}))
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
function godotSceneStateConnectionFromDocumentConnection(connection) {
|
|
240
|
+
const flags = numberAttribute(connection.attributes.flags);
|
|
241
|
+
const binds = godotValueArrayAttribute(connection.attributes.binds);
|
|
242
|
+
const unbinds = numberAttribute(connection.attributes.unbinds);
|
|
243
|
+
return {
|
|
244
|
+
...connection.signal !== void 0 ? { signal: connection.signal } : {},
|
|
245
|
+
...connection.from !== void 0 ? { from: connection.from } : {},
|
|
246
|
+
...connection.to !== void 0 ? { to: connection.to } : {},
|
|
247
|
+
...connection.method !== void 0 ? { method: connection.method } : {},
|
|
248
|
+
...flags !== void 0 ? { flags } : {},
|
|
249
|
+
...binds !== void 0 ? { binds } : {},
|
|
250
|
+
...unbinds !== void 0 ? { unbinds } : {}
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
function collectLogicalLine(lines, startIndex) {
|
|
254
|
+
const state = newOpenValueState();
|
|
255
|
+
const parts = [lines[startIndex] ?? ""];
|
|
256
|
+
scanOpenValue(parts[0], state);
|
|
257
|
+
let endIndex = startIndex;
|
|
258
|
+
while (isOpenValue(state) && endIndex + 1 < lines.length) {
|
|
259
|
+
endIndex += 1;
|
|
260
|
+
const line = lines[endIndex] ?? "";
|
|
261
|
+
parts.push(line);
|
|
262
|
+
scanOpenValue(`\n${line}`, state);
|
|
263
|
+
}
|
|
264
|
+
return {
|
|
265
|
+
raw: parts.join("\n"),
|
|
266
|
+
endIndex
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
function newOpenValueState() {
|
|
270
|
+
return {
|
|
271
|
+
quote: null,
|
|
272
|
+
escaped: false,
|
|
273
|
+
inComment: false,
|
|
274
|
+
squareDepth: 0,
|
|
275
|
+
curlyDepth: 0,
|
|
276
|
+
parenDepth: 0
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
function isOpenValue(state) {
|
|
280
|
+
return state.quote !== null || state.squareDepth > 0 || state.curlyDepth > 0 || state.parenDepth > 0;
|
|
281
|
+
}
|
|
282
|
+
function scanOpenValue(source, state) {
|
|
283
|
+
for (let index = 0; index < source.length; index += 1) {
|
|
284
|
+
const char = source[index];
|
|
285
|
+
if (state.inComment) {
|
|
286
|
+
if (char === "\n") state.inComment = false;
|
|
287
|
+
continue;
|
|
288
|
+
}
|
|
289
|
+
if (state.quote) {
|
|
290
|
+
if (state.escaped) state.escaped = false;
|
|
291
|
+
else if (char === "\\") state.escaped = true;
|
|
292
|
+
else if (char === state.quote) state.quote = null;
|
|
293
|
+
continue;
|
|
294
|
+
}
|
|
295
|
+
if (char === "\"" || char === "'") state.quote = char;
|
|
296
|
+
else if (char === ";") state.inComment = true;
|
|
297
|
+
else if (char === "[") state.squareDepth += 1;
|
|
298
|
+
else if (char === "]") state.squareDepth = Math.max(0, state.squareDepth - 1);
|
|
299
|
+
else if (char === "{") state.curlyDepth += 1;
|
|
300
|
+
else if (char === "}") state.curlyDepth = Math.max(0, state.curlyDepth - 1);
|
|
301
|
+
else if (char === "(") state.parenDepth += 1;
|
|
302
|
+
else if (char === ")") state.parenDepth = Math.max(0, state.parenDepth - 1);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
function stripLineComment(line) {
|
|
306
|
+
let quote = null;
|
|
307
|
+
let escaped = false;
|
|
308
|
+
for (let index = 0; index < line.length; index += 1) {
|
|
309
|
+
const char = line[index];
|
|
310
|
+
if (quote) {
|
|
311
|
+
if (escaped) escaped = false;
|
|
312
|
+
else if (char === "\\") escaped = true;
|
|
313
|
+
else if (char === quote) quote = null;
|
|
314
|
+
continue;
|
|
315
|
+
}
|
|
316
|
+
if (char === "\"" || char === "'") quote = char;
|
|
317
|
+
else if (char === ";") return line.slice(0, index);
|
|
318
|
+
}
|
|
319
|
+
return line;
|
|
320
|
+
}
|
|
321
|
+
function splitAssignment(line) {
|
|
322
|
+
const index = line.indexOf("=");
|
|
323
|
+
if (index < 0) return null;
|
|
324
|
+
return {
|
|
325
|
+
key: line.slice(0, index).trim(),
|
|
326
|
+
value: line.slice(index + 1).trim()
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
function splitHeaderParts(source) {
|
|
330
|
+
const parts = [];
|
|
331
|
+
let quote = null;
|
|
332
|
+
let escaped = false;
|
|
333
|
+
let start = 0;
|
|
334
|
+
for (let index = 0; index < source.length; index += 1) {
|
|
335
|
+
const char = source[index];
|
|
336
|
+
if (quote) {
|
|
337
|
+
if (escaped) escaped = false;
|
|
338
|
+
else if (char === "\\") escaped = true;
|
|
339
|
+
else if (char === quote) quote = null;
|
|
340
|
+
continue;
|
|
341
|
+
}
|
|
342
|
+
if (char === "\"" || char === "'") quote = char;
|
|
343
|
+
else if (/\s/.test(char)) {
|
|
344
|
+
if (index > start) parts.push(source.slice(start, index));
|
|
345
|
+
start = index + 1;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
if (start < source.length) parts.push(source.slice(start));
|
|
349
|
+
return parts;
|
|
350
|
+
}
|
|
351
|
+
function parseHeaderAttributes(source, diagnostics, line) {
|
|
352
|
+
const attributes = {};
|
|
353
|
+
const matches = [...source.matchAll(/([A-Za-z0-9_./-]+)=/g)];
|
|
354
|
+
for (let index = 0; index < matches.length; index += 1) {
|
|
355
|
+
const match = matches[index];
|
|
356
|
+
if (match.index === void 0) continue;
|
|
357
|
+
const key = match[1] ?? "";
|
|
358
|
+
const valueStart = match.index + match[0].length;
|
|
359
|
+
const valueEnd = matches[index + 1]?.index ?? source.length;
|
|
360
|
+
attributes[key] = parseGodotValue(source.slice(valueStart, valueEnd).trim(), diagnostics, line);
|
|
361
|
+
}
|
|
362
|
+
return attributes;
|
|
363
|
+
}
|
|
364
|
+
function stringAttribute(value) {
|
|
365
|
+
return typeof value === "string" ? value : void 0;
|
|
366
|
+
}
|
|
367
|
+
function numberAttribute(value) {
|
|
368
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
369
|
+
}
|
|
370
|
+
function nodeIndexAttribute(value) {
|
|
371
|
+
if (typeof value === "number" && Number.isInteger(value)) return value;
|
|
372
|
+
if (typeof value === "string" && /^-?\d+$/.test(value)) return Number(value);
|
|
373
|
+
}
|
|
374
|
+
function stringArrayAttribute(value) {
|
|
375
|
+
return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
|
|
376
|
+
}
|
|
377
|
+
function godotValueArrayAttribute(value) {
|
|
378
|
+
return Array.isArray(value) ? value : void 0;
|
|
379
|
+
}
|
|
380
|
+
function resourceRefAttribute(value) {
|
|
381
|
+
if (typeof value === "object" && value !== null && "type" in value && (value.type === "ExtResource" || value.type === "SubResource") && "id" in value && typeof value.id === "string") return {
|
|
382
|
+
type: value.type,
|
|
383
|
+
id: value.id
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
var ValueParser = class {
|
|
387
|
+
source;
|
|
388
|
+
diagnostics;
|
|
389
|
+
line;
|
|
390
|
+
position = 0;
|
|
391
|
+
constructor(source, diagnostics, line) {
|
|
392
|
+
this.source = source;
|
|
393
|
+
this.diagnostics = diagnostics;
|
|
394
|
+
this.line = line;
|
|
395
|
+
}
|
|
396
|
+
parseValue() {
|
|
397
|
+
this.skipTrivia();
|
|
398
|
+
const char = this.peek();
|
|
399
|
+
if (char === "\"" || char === "'") return this.parseString();
|
|
400
|
+
if (char === "[") return this.parseArray();
|
|
401
|
+
if (char === "{") return this.parseDictionary();
|
|
402
|
+
if (char === "&") return this.parseStringName();
|
|
403
|
+
if (char === "-" || char === "+" || char === "." || isDigit(char)) return this.parseNumber();
|
|
404
|
+
const ident = this.parseIdentifier();
|
|
405
|
+
if (ident.length === 0) {
|
|
406
|
+
this.warn("godot_parser_empty_value", "Expected a Godot value.");
|
|
407
|
+
return null;
|
|
408
|
+
}
|
|
409
|
+
if (ident === "true") return true;
|
|
410
|
+
if (ident === "false") return false;
|
|
411
|
+
if (ident === "null" || ident === "nil") return null;
|
|
412
|
+
this.skipTrivia();
|
|
413
|
+
if (this.peek() === "(") return this.parseCall(ident);
|
|
414
|
+
return ident;
|
|
415
|
+
}
|
|
416
|
+
skipTrivia() {
|
|
417
|
+
while (!this.done() && /\s/.test(this.peek())) this.position += 1;
|
|
418
|
+
}
|
|
419
|
+
done() {
|
|
420
|
+
return this.position >= this.source.length;
|
|
421
|
+
}
|
|
422
|
+
peek() {
|
|
423
|
+
return this.source[this.position] ?? "";
|
|
424
|
+
}
|
|
425
|
+
parseString() {
|
|
426
|
+
const quote = this.peek();
|
|
427
|
+
this.position += 1;
|
|
428
|
+
let result = "";
|
|
429
|
+
let escaped = false;
|
|
430
|
+
while (!this.done()) {
|
|
431
|
+
const char = this.peek();
|
|
432
|
+
this.position += 1;
|
|
433
|
+
if (escaped) {
|
|
434
|
+
result += decodeEscape(char);
|
|
435
|
+
escaped = false;
|
|
436
|
+
} else if (char === "\\") escaped = true;
|
|
437
|
+
else if (char === quote) return result;
|
|
438
|
+
else result += char;
|
|
439
|
+
}
|
|
440
|
+
this.warn("godot_parser_unterminated_string", "Unterminated Godot string.");
|
|
441
|
+
return result;
|
|
442
|
+
}
|
|
443
|
+
parseArray() {
|
|
444
|
+
this.position += 1;
|
|
445
|
+
const values = [];
|
|
446
|
+
while (!this.done()) {
|
|
447
|
+
this.skipTrivia();
|
|
448
|
+
if (this.peek() === "]") {
|
|
449
|
+
this.position += 1;
|
|
450
|
+
return values;
|
|
451
|
+
}
|
|
452
|
+
values.push(this.parseValue());
|
|
453
|
+
this.skipTrivia();
|
|
454
|
+
if (this.peek() === ",") this.position += 1;
|
|
455
|
+
}
|
|
456
|
+
this.warn("godot_parser_unterminated_array", "Unterminated Godot array.");
|
|
457
|
+
return values;
|
|
458
|
+
}
|
|
459
|
+
parseDictionary() {
|
|
460
|
+
this.position += 1;
|
|
461
|
+
const result = {};
|
|
462
|
+
while (!this.done()) {
|
|
463
|
+
this.skipTrivia();
|
|
464
|
+
if (this.peek() === "}") {
|
|
465
|
+
this.position += 1;
|
|
466
|
+
return result;
|
|
467
|
+
}
|
|
468
|
+
const keyValue = this.parseValue();
|
|
469
|
+
this.skipTrivia();
|
|
470
|
+
if (this.peek() !== ":") {
|
|
471
|
+
this.warn("godot_parser_dictionary_colon_missing", "Expected ':' in Godot dictionary.");
|
|
472
|
+
return result;
|
|
473
|
+
}
|
|
474
|
+
this.position += 1;
|
|
475
|
+
const value = this.parseValue();
|
|
476
|
+
result[dictionaryKey(keyValue)] = value;
|
|
477
|
+
this.skipTrivia();
|
|
478
|
+
if (this.peek() === ",") this.position += 1;
|
|
479
|
+
}
|
|
480
|
+
this.warn("godot_parser_unterminated_dictionary", "Unterminated Godot dictionary.");
|
|
481
|
+
return result;
|
|
482
|
+
}
|
|
483
|
+
parseNumber() {
|
|
484
|
+
const start = this.position;
|
|
485
|
+
if (this.peek() === "+" || this.peek() === "-") this.position += 1;
|
|
486
|
+
while (isDigit(this.peek())) this.position += 1;
|
|
487
|
+
if (this.peek() === ".") {
|
|
488
|
+
this.position += 1;
|
|
489
|
+
while (isDigit(this.peek())) this.position += 1;
|
|
490
|
+
}
|
|
491
|
+
if (this.peek().toLowerCase() === "e") {
|
|
492
|
+
this.position += 1;
|
|
493
|
+
if (this.peek() === "+" || this.peek() === "-") this.position += 1;
|
|
494
|
+
while (isDigit(this.peek())) this.position += 1;
|
|
495
|
+
}
|
|
496
|
+
return Number(this.source.slice(start, this.position));
|
|
497
|
+
}
|
|
498
|
+
parseIdentifier() {
|
|
499
|
+
const start = this.position;
|
|
500
|
+
while (!this.done() && /[A-Za-z0-9_./:-]/.test(this.peek())) this.position += 1;
|
|
501
|
+
if (this.peek() === "[") {
|
|
502
|
+
this.position += 1;
|
|
503
|
+
while (!this.done() && this.peek() !== "]") {
|
|
504
|
+
if (!/[A-Za-z0-9_./:-]/.test(this.peek())) break;
|
|
505
|
+
this.position += 1;
|
|
506
|
+
}
|
|
507
|
+
if (this.peek() === "]") this.position += 1;
|
|
508
|
+
}
|
|
509
|
+
return this.source.slice(start, this.position);
|
|
510
|
+
}
|
|
511
|
+
parseStringName() {
|
|
512
|
+
this.position += 1;
|
|
513
|
+
if (this.peek() === "\"" || this.peek() === "'") return {
|
|
514
|
+
type: "StringName",
|
|
515
|
+
args: [this.parseString()]
|
|
516
|
+
};
|
|
517
|
+
this.warn("godot_parser_string_name_expected_string", "Expected quoted string after '&' StringName marker.");
|
|
518
|
+
return {
|
|
519
|
+
type: "StringName",
|
|
520
|
+
args: [""]
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
parseCall(name) {
|
|
524
|
+
this.position += 1;
|
|
525
|
+
const args = [];
|
|
526
|
+
while (!this.done()) {
|
|
527
|
+
this.skipTrivia();
|
|
528
|
+
if (this.peek() === ")") {
|
|
529
|
+
this.position += 1;
|
|
530
|
+
return callValue(name, args);
|
|
531
|
+
}
|
|
532
|
+
args.push(this.parseValue());
|
|
533
|
+
this.skipTrivia();
|
|
534
|
+
if (this.peek() === ",") this.position += 1;
|
|
535
|
+
}
|
|
536
|
+
this.warn("godot_parser_unterminated_call", `Unterminated Godot call ${name}(...).`);
|
|
537
|
+
return callValue(name, args);
|
|
538
|
+
}
|
|
539
|
+
warn(code, message) {
|
|
540
|
+
this.diagnostics.push({
|
|
541
|
+
severity: "warning",
|
|
542
|
+
code,
|
|
543
|
+
message,
|
|
544
|
+
line: this.line,
|
|
545
|
+
column: this.position + 1
|
|
546
|
+
});
|
|
547
|
+
}
|
|
548
|
+
};
|
|
549
|
+
function callValue(name, args) {
|
|
550
|
+
const numericArgs = args.map((arg) => typeof arg === "number" ? arg : NaN);
|
|
551
|
+
switch (name) {
|
|
552
|
+
case "Vector2":
|
|
553
|
+
case "Vector2i":
|
|
554
|
+
case "Vector3":
|
|
555
|
+
case "Vector3i":
|
|
556
|
+
case "Vector4":
|
|
557
|
+
case "Vector4i": return {
|
|
558
|
+
type: name,
|
|
559
|
+
args: numericArgs
|
|
560
|
+
};
|
|
561
|
+
case "Color": return {
|
|
562
|
+
type: "Color",
|
|
563
|
+
args: numericArgs
|
|
564
|
+
};
|
|
565
|
+
case "Rect2":
|
|
566
|
+
case "Rect2i": return {
|
|
567
|
+
type: name,
|
|
568
|
+
args: numericArgs
|
|
569
|
+
};
|
|
570
|
+
case "NodePath": return {
|
|
571
|
+
type: "NodePath",
|
|
572
|
+
args: [typeof args[0] === "string" ? args[0] : ""]
|
|
573
|
+
};
|
|
574
|
+
case "ExtResource":
|
|
575
|
+
case "SubResource": return {
|
|
576
|
+
type: name,
|
|
577
|
+
id: String(args[0] ?? "")
|
|
578
|
+
};
|
|
579
|
+
default: return {
|
|
580
|
+
type: name,
|
|
581
|
+
args
|
|
582
|
+
};
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
function decodeEscape(char) {
|
|
586
|
+
switch (char) {
|
|
587
|
+
case "n": return "\n";
|
|
588
|
+
case "r": return "\r";
|
|
589
|
+
case "t": return " ";
|
|
590
|
+
default: return char;
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
function dictionaryKey(value) {
|
|
594
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") return String(value);
|
|
595
|
+
if (value && typeof value === "object" && !Array.isArray(value) && "type" in value && value.type === "StringName" && "args" in value && Array.isArray(value.args) && typeof value.args[0] === "string") return value.args[0];
|
|
596
|
+
return JSON.stringify(value);
|
|
597
|
+
}
|
|
598
|
+
function isDigit(value) {
|
|
599
|
+
return value >= "0" && value <= "9";
|
|
600
|
+
}
|
|
601
|
+
//#endregion
|
|
602
|
+
export { parseGodotResource, parseGodotTextScene, parseGodotValue };
|
|
603
|
+
|
|
604
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import type {\n GodotConnection,\n GodotDocumentKind,\n GodotEditable,\n GodotExtResource,\n GodotNode,\n GodotParseDiagnostic,\n GodotResource,\n GodotResourceRefValue,\n GodotSceneState,\n GodotSceneStateConnection,\n GodotSceneStateNode,\n GodotSectionHeader,\n GodotSubResource,\n GodotVariant,\n} from \"@godot-scene-web/core\";\n\ninterface ParsedDocument {\n kind: GodotDocumentKind;\n header: GodotSectionHeader | null;\n extResources: GodotExtResource[];\n subResources: GodotSubResource[];\n nodes: GodotNode[];\n connections: GodotConnection[];\n editables: GodotEditable[];\n properties: Record<string, GodotVariant>;\n diagnostics: GodotParseDiagnostic[];\n}\n\ntype CurrentSection =\n | { kind: \"header\"; header: GodotSectionHeader }\n | { kind: \"ext_resource\"; resource: GodotExtResource }\n | { kind: \"sub_resource\"; resource: GodotSubResource }\n | { kind: \"node\"; node: GodotNode }\n | { kind: \"connection\"; connection: GodotConnection }\n | { kind: \"editable\"; editable: GodotEditable }\n | { kind: \"resource\" }\n | { kind: \"document\" };\n\nexport interface ParseGodotTextOptions {\n path?: string;\n kind?: GodotDocumentKind;\n}\n\nexport function parseGodotTextScene(\n text: string,\n options: ParseGodotTextOptions = {},\n): GodotSceneState {\n return godotSceneStateFromDocument(\n parseDocument(text, { ...options, kind: \"scene\" }),\n );\n}\n\nexport function parseGodotResource(\n text: string,\n options: ParseGodotTextOptions = {},\n): GodotResource {\n return godotResourceFromDocument(\n parseDocument(text, { ...options, kind: \"resource\" }),\n );\n}\n\nfunction parseDocument(\n text: string,\n options: ParseGodotTextOptions = {},\n): ParsedDocument {\n const kind = options.kind ?? \"resource\";\n const diagnostics: GodotParseDiagnostic[] = [];\n const document: ParsedDocument = {\n kind,\n header: null,\n extResources: [],\n subResources: [],\n nodes: [],\n connections: [],\n editables: [],\n properties: {},\n diagnostics,\n };\n let current: CurrentSection = { kind: \"document\" };\n const lines = text.replace(/^\\uFEFF/, \"\").split(/\\r?\\n/);\n\n for (let index = 0; index < lines.length; index += 1) {\n const lineNumber = index + 1;\n const logical = collectLogicalLine(lines, index);\n index = logical.endIndex;\n const line = stripLineComment(logical.raw).trim();\n if (line.length === 0) {\n continue;\n }\n if (line.startsWith(\"[\") && line.endsWith(\"]\")) {\n current = parseSectionHeader(\n line.slice(1, -1),\n lineNumber,\n diagnostics,\n document,\n );\n continue;\n }\n const assignment = splitAssignment(line);\n if (!assignment) {\n diagnostics.push({\n severity: \"warning\",\n code: \"godot_parser_unsupported_line\",\n message: \"Unsupported Godot text line.\",\n line: lineNumber,\n });\n continue;\n }\n const value = parseGodotValue(assignment.value, diagnostics, lineNumber);\n assignProperty(document, current, assignment.key, value);\n }\n\n return document;\n}\n\nexport function parseGodotValue(\n source: string,\n diagnostics: GodotParseDiagnostic[] = [],\n line?: number,\n): GodotVariant {\n const parser = new ValueParser(source, diagnostics, line);\n const value = parser.parseValue();\n parser.skipTrivia();\n if (!parser.done()) {\n diagnostics.push({\n severity: \"warning\",\n code: \"godot_parser_trailing_value_text\",\n message: `Trailing text after Godot value: ${source.slice(parser.position)}`,\n line,\n });\n }\n return value;\n}\n\nfunction parseSectionHeader(\n source: string,\n line: number,\n diagnostics: GodotParseDiagnostic[],\n document: ParsedDocument,\n): CurrentSection {\n const [section = \"\", ...attributeParts] = splitHeaderParts(source);\n const attributes = parseHeaderAttributes(\n attributeParts.join(\" \"),\n diagnostics,\n line,\n );\n switch (section) {\n case \"gd_scene\":\n case \"gd_resource\": {\n const header = { section, attributes };\n document.header = header;\n document.kind = section === \"gd_scene\" ? \"scene\" : \"resource\";\n return { kind: \"header\", header };\n }\n case \"ext_resource\": {\n const id = stringAttribute(attributes.id) ?? \"\";\n const resource: GodotExtResource = {\n id,\n type: stringAttribute(attributes.type),\n path: stringAttribute(attributes.path),\n uid: stringAttribute(attributes.uid),\n attributes,\n properties: {},\n };\n document.extResources.push(resource);\n return { kind: \"ext_resource\", resource };\n }\n case \"sub_resource\": {\n const id = stringAttribute(attributes.id) ?? \"\";\n const resource: GodotSubResource = {\n id,\n type: stringAttribute(attributes.type),\n attributes,\n properties: {},\n };\n document.subResources.push(resource);\n return { kind: \"sub_resource\", resource };\n }\n case \"node\": {\n const node: GodotNode = {\n name: stringAttribute(attributes.name) ?? \"\",\n type: stringAttribute(attributes.type),\n parent: stringAttribute(attributes.parent),\n instance: resourceRefAttribute(attributes.instance),\n attributes,\n properties: {},\n };\n document.nodes.push(node);\n return { kind: \"node\", node };\n }\n case \"connection\": {\n const connection: GodotConnection = {\n signal: stringAttribute(attributes.signal),\n from: stringAttribute(attributes.from),\n to: stringAttribute(attributes.to),\n method: stringAttribute(attributes.method),\n attributes,\n };\n document.connections.push(connection);\n return { kind: \"connection\", connection };\n }\n case \"editable\": {\n const editable: GodotEditable = {\n path: stringAttribute(attributes.path),\n attributes,\n };\n document.editables.push(editable);\n return { kind: \"editable\", editable };\n }\n case \"resource\":\n return { kind: \"resource\" };\n default:\n diagnostics.push({\n severity: \"warning\",\n code: \"godot_parser_unknown_section\",\n message: `Unknown Godot text section: ${section}`,\n line,\n });\n return { kind: \"document\" };\n }\n}\n\nfunction assignProperty(\n document: ParsedDocument,\n current: CurrentSection,\n key: string,\n value: GodotVariant,\n): void {\n switch (current.kind) {\n case \"ext_resource\":\n current.resource.properties[key] = value;\n break;\n case \"sub_resource\":\n current.resource.properties[key] = value;\n break;\n case \"node\":\n current.node.properties[key] = value;\n current.node.propertyEntries ??= [];\n current.node.propertyEntries.push({ name: key, value });\n break;\n case \"header\":\n current.header.attributes[key] = value;\n break;\n case \"connection\":\n current.connection.attributes[key] = value;\n break;\n case \"editable\":\n current.editable.attributes[key] = value;\n break;\n case \"resource\":\n document.properties[key] = value;\n break;\n case \"document\":\n document.properties[key] = value;\n break;\n }\n}\n\nfunction godotSceneStateFromDocument(\n document: ParsedDocument,\n): GodotSceneState {\n const basePath = stringAttribute(document.header?.attributes.path);\n return {\n kind: \"scene\",\n nodes: document.nodes.map(godotSceneStateNodeFromDocumentNode),\n connections: document.connections.map(\n godotSceneStateConnectionFromDocumentConnection,\n ),\n extResources: document.extResources,\n subResources: document.subResources,\n editableInstances: document.editables\n .map((editable) => editable.path)\n .filter((path): path is string => typeof path === \"string\"),\n ...(basePath ? { basePath } : {}),\n diagnostics: document.diagnostics,\n };\n}\n\nfunction godotResourceFromDocument(document: ParsedDocument): GodotResource {\n return {\n type: stringAttribute(document.header?.attributes.type),\n header: document.header,\n extResources: document.extResources,\n subResources: document.subResources,\n properties: document.properties,\n diagnostics: document.diagnostics,\n };\n}\n\nfunction godotSceneStateNodeFromDocumentNode(\n node: GodotNode,\n index: number,\n): GodotSceneStateNode {\n const owner = stringAttribute(node.attributes.owner);\n const instancePlaceholder =\n stringAttribute(node.attributes.instance_placeholder) ??\n stringAttribute(node.attributes.instancePlaceholder);\n const siblingIndex = nodeIndexAttribute(node.attributes.index);\n return {\n index,\n ...(siblingIndex !== undefined ? { siblingIndex } : {}),\n name: node.name,\n ...(node.type !== undefined ? { type: node.type } : {}),\n parent: node.parent ?? \".\",\n ...(owner !== undefined ? { owner } : {}),\n ...(node.instance !== undefined ? { instance: node.instance } : {}),\n ...(instancePlaceholder !== undefined ? { instancePlaceholder } : {}),\n groups: stringArrayAttribute(node.attributes.groups),\n properties:\n node.propertyEntries?.map((property) => ({ ...property })) ??\n Object.entries(node.properties).map(([name, value]) => ({ name, value })),\n };\n}\n\nfunction godotSceneStateConnectionFromDocumentConnection(\n connection: GodotConnection,\n): GodotSceneStateConnection {\n const flags = numberAttribute(connection.attributes.flags);\n const binds = godotValueArrayAttribute(connection.attributes.binds);\n const unbinds = numberAttribute(connection.attributes.unbinds);\n return {\n ...(connection.signal !== undefined ? { signal: connection.signal } : {}),\n ...(connection.from !== undefined ? { from: connection.from } : {}),\n ...(connection.to !== undefined ? { to: connection.to } : {}),\n ...(connection.method !== undefined ? { method: connection.method } : {}),\n ...(flags !== undefined ? { flags } : {}),\n ...(binds !== undefined ? { binds } : {}),\n ...(unbinds !== undefined ? { unbinds } : {}),\n };\n}\n\nfunction collectLogicalLine(\n lines: string[],\n startIndex: number,\n): { raw: string; endIndex: number } {\n // Scan incrementally, carrying the open-value state across appended lines —\n // re-scanning the accumulated string per appended line is quadratic, which\n // dominated whole-document parse time on multi-line values (packed arrays,\n // animation tracks, shader code in .tres).\n const state = newOpenValueState();\n const parts = [lines[startIndex] ?? \"\"];\n scanOpenValue(parts[0], state);\n let endIndex = startIndex;\n while (isOpenValue(state) && endIndex + 1 < lines.length) {\n endIndex += 1;\n const line = lines[endIndex] ?? \"\";\n parts.push(line);\n scanOpenValue(`\\n${line}`, state);\n }\n return { raw: parts.join(\"\\n\"), endIndex };\n}\n\ninterface OpenValueState {\n quote: string | null;\n escaped: boolean;\n inComment: boolean;\n squareDepth: number;\n curlyDepth: number;\n parenDepth: number;\n}\n\nfunction newOpenValueState(): OpenValueState {\n return {\n quote: null,\n escaped: false,\n inComment: false,\n squareDepth: 0,\n curlyDepth: 0,\n parenDepth: 0,\n };\n}\n\nfunction isOpenValue(state: OpenValueState): boolean {\n return (\n state.quote !== null ||\n state.squareDepth > 0 ||\n state.curlyDepth > 0 ||\n state.parenDepth > 0\n );\n}\n\nfunction scanOpenValue(source: string, state: OpenValueState): void {\n for (let index = 0; index < source.length; index += 1) {\n const char = source[index];\n if (state.inComment) {\n if (char === \"\\n\") {\n state.inComment = false;\n }\n continue;\n }\n if (state.quote) {\n if (state.escaped) {\n state.escaped = false;\n } else if (char === \"\\\\\") {\n state.escaped = true;\n } else if (char === state.quote) {\n state.quote = null;\n }\n continue;\n }\n if (char === '\"' || char === \"'\") {\n state.quote = char;\n } else if (char === \";\") {\n state.inComment = true;\n } else if (char === \"[\") {\n state.squareDepth += 1;\n } else if (char === \"]\") {\n state.squareDepth = Math.max(0, state.squareDepth - 1);\n } else if (char === \"{\") {\n state.curlyDepth += 1;\n } else if (char === \"}\") {\n state.curlyDepth = Math.max(0, state.curlyDepth - 1);\n } else if (char === \"(\") {\n state.parenDepth += 1;\n } else if (char === \")\") {\n state.parenDepth = Math.max(0, state.parenDepth - 1);\n }\n }\n}\n\nfunction stripLineComment(line: string): string {\n let quote: string | null = null;\n let escaped = false;\n for (let index = 0; index < line.length; index += 1) {\n const char = line[index];\n if (quote) {\n if (escaped) {\n escaped = false;\n } else if (char === \"\\\\\") {\n escaped = true;\n } else if (char === quote) {\n quote = null;\n }\n continue;\n }\n if (char === '\"' || char === \"'\") {\n quote = char;\n } else if (char === \";\") {\n return line.slice(0, index);\n }\n }\n return line;\n}\n\nfunction splitAssignment(line: string): { key: string; value: string } | null {\n const index = line.indexOf(\"=\");\n if (index < 0) {\n return null;\n }\n return {\n key: line.slice(0, index).trim(),\n value: line.slice(index + 1).trim(),\n };\n}\n\nfunction splitHeaderParts(source: string): string[] {\n const parts: string[] = [];\n let quote: string | null = null;\n let escaped = false;\n let start = 0;\n for (let index = 0; index < source.length; index += 1) {\n const char = source[index];\n if (quote) {\n if (escaped) {\n escaped = false;\n } else if (char === \"\\\\\") {\n escaped = true;\n } else if (char === quote) {\n quote = null;\n }\n continue;\n }\n if (char === '\"' || char === \"'\") {\n quote = char;\n } else if (/\\s/.test(char)) {\n if (index > start) {\n parts.push(source.slice(start, index));\n }\n start = index + 1;\n }\n }\n if (start < source.length) {\n parts.push(source.slice(start));\n }\n return parts;\n}\n\nfunction parseHeaderAttributes(\n source: string,\n diagnostics: GodotParseDiagnostic[],\n line: number,\n): Record<string, GodotVariant> {\n const attributes: Record<string, GodotVariant> = {};\n const attrPattern = /([A-Za-z0-9_./-]+)=/g;\n const matches = [...source.matchAll(attrPattern)];\n for (let index = 0; index < matches.length; index += 1) {\n const match = matches[index];\n if (match.index === undefined) {\n continue;\n }\n const key = match[1] ?? \"\";\n const valueStart = match.index + match[0].length;\n const valueEnd = matches[index + 1]?.index ?? source.length;\n attributes[key] = parseGodotValue(\n source.slice(valueStart, valueEnd).trim(),\n diagnostics,\n line,\n );\n }\n return attributes;\n}\n\nfunction stringAttribute(value: GodotVariant | undefined): string | undefined {\n return typeof value === \"string\" ? value : undefined;\n}\n\nfunction numberAttribute(value: GodotVariant | undefined): number | undefined {\n return typeof value === \"number\" && Number.isFinite(value)\n ? value\n : undefined;\n}\n\n// Godot serializes the node header `index` as a quoted string (e.g. `index=\"3\"`),\n// so accept a numeric string as well as a bare number.\nfunction nodeIndexAttribute(\n value: GodotVariant | undefined,\n): number | undefined {\n if (typeof value === \"number\" && Number.isInteger(value)) {\n return value;\n }\n if (typeof value === \"string\" && /^-?\\d+$/.test(value)) {\n return Number(value);\n }\n return undefined;\n}\n\nfunction stringArrayAttribute(value: GodotVariant | undefined): string[] {\n return Array.isArray(value)\n ? value.filter((item): item is string => typeof item === \"string\")\n : [];\n}\n\nfunction godotValueArrayAttribute(\n value: GodotVariant | undefined,\n): GodotVariant[] | undefined {\n return Array.isArray(value) ? value : undefined;\n}\n\nfunction resourceRefAttribute(\n value: GodotVariant | undefined,\n): GodotResourceRefValue | undefined {\n if (\n typeof value === \"object\" &&\n value !== null &&\n \"type\" in value &&\n (value.type === \"ExtResource\" || value.type === \"SubResource\") &&\n \"id\" in value &&\n typeof value.id === \"string\"\n ) {\n const type = value.type;\n return { type, id: value.id };\n }\n return undefined;\n}\n\nclass ValueParser {\n position = 0;\n\n constructor(\n private readonly source: string,\n private readonly diagnostics: GodotParseDiagnostic[],\n private readonly line?: number,\n ) {}\n\n parseValue(): GodotVariant {\n this.skipTrivia();\n const char = this.peek();\n if (char === '\"' || char === \"'\") {\n return this.parseString();\n }\n if (char === \"[\") {\n return this.parseArray();\n }\n if (char === \"{\") {\n return this.parseDictionary();\n }\n if (char === \"&\") {\n return this.parseStringName();\n }\n if (char === \"-\" || char === \"+\" || char === \".\" || isDigit(char)) {\n return this.parseNumber();\n }\n const ident = this.parseIdentifier();\n if (ident.length === 0) {\n this.warn(\"godot_parser_empty_value\", \"Expected a Godot value.\");\n return null;\n }\n if (ident === \"true\") {\n return true;\n }\n if (ident === \"false\") {\n return false;\n }\n if (ident === \"null\" || ident === \"nil\") {\n return null;\n }\n this.skipTrivia();\n if (this.peek() === \"(\") {\n return this.parseCall(ident);\n }\n return ident;\n }\n\n skipTrivia(): void {\n while (!this.done() && /\\s/.test(this.peek())) {\n this.position += 1;\n }\n }\n\n done(): boolean {\n return this.position >= this.source.length;\n }\n\n peek(): string {\n return this.source[this.position] ?? \"\";\n }\n\n private parseString(): string {\n const quote = this.peek();\n this.position += 1;\n let result = \"\";\n let escaped = false;\n while (!this.done()) {\n const char = this.peek();\n this.position += 1;\n if (escaped) {\n result += decodeEscape(char);\n escaped = false;\n } else if (char === \"\\\\\") {\n escaped = true;\n } else if (char === quote) {\n return result;\n } else {\n result += char;\n }\n }\n this.warn(\"godot_parser_unterminated_string\", \"Unterminated Godot string.\");\n return result;\n }\n\n private parseArray(): GodotVariant[] {\n this.position += 1;\n const values: GodotVariant[] = [];\n while (!this.done()) {\n this.skipTrivia();\n if (this.peek() === \"]\") {\n this.position += 1;\n return values;\n }\n values.push(this.parseValue());\n this.skipTrivia();\n if (this.peek() === \",\") {\n this.position += 1;\n }\n }\n this.warn(\"godot_parser_unterminated_array\", \"Unterminated Godot array.\");\n return values;\n }\n\n private parseDictionary(): Record<string, GodotVariant> {\n this.position += 1;\n const result: Record<string, GodotVariant> = {};\n while (!this.done()) {\n this.skipTrivia();\n if (this.peek() === \"}\") {\n this.position += 1;\n return result;\n }\n const keyValue = this.parseValue();\n this.skipTrivia();\n if (this.peek() !== \":\") {\n this.warn(\n \"godot_parser_dictionary_colon_missing\",\n \"Expected ':' in Godot dictionary.\",\n );\n return result;\n }\n this.position += 1;\n const value = this.parseValue();\n result[dictionaryKey(keyValue)] = value;\n this.skipTrivia();\n if (this.peek() === \",\") {\n this.position += 1;\n }\n }\n this.warn(\n \"godot_parser_unterminated_dictionary\",\n \"Unterminated Godot dictionary.\",\n );\n return result;\n }\n\n private parseNumber(): number {\n const start = this.position;\n if (this.peek() === \"+\" || this.peek() === \"-\") {\n this.position += 1;\n }\n while (isDigit(this.peek())) {\n this.position += 1;\n }\n if (this.peek() === \".\") {\n this.position += 1;\n while (isDigit(this.peek())) {\n this.position += 1;\n }\n }\n if (this.peek().toLowerCase() === \"e\") {\n this.position += 1;\n if (this.peek() === \"+\" || this.peek() === \"-\") {\n this.position += 1;\n }\n while (isDigit(this.peek())) {\n this.position += 1;\n }\n }\n return Number(this.source.slice(start, this.position));\n }\n\n private parseIdentifier(): string {\n const start = this.position;\n while (!this.done() && /[A-Za-z0-9_./:-]/.test(this.peek())) {\n this.position += 1;\n }\n if (this.peek() === \"[\") {\n this.position += 1;\n while (!this.done() && this.peek() !== \"]\") {\n if (!/[A-Za-z0-9_./:-]/.test(this.peek())) {\n break;\n }\n this.position += 1;\n }\n if (this.peek() === \"]\") {\n this.position += 1;\n }\n }\n return this.source.slice(start, this.position);\n }\n\n private parseStringName(): GodotVariant {\n this.position += 1;\n if (this.peek() === '\"' || this.peek() === \"'\") {\n return { type: \"StringName\", args: [this.parseString()] };\n }\n this.warn(\n \"godot_parser_string_name_expected_string\",\n \"Expected quoted string after '&' StringName marker.\",\n );\n return { type: \"StringName\", args: [\"\"] };\n }\n\n private parseCall(name: string): GodotVariant {\n this.position += 1;\n const args: GodotVariant[] = [];\n while (!this.done()) {\n this.skipTrivia();\n if (this.peek() === \")\") {\n this.position += 1;\n return callValue(name, args);\n }\n args.push(this.parseValue());\n this.skipTrivia();\n if (this.peek() === \",\") {\n this.position += 1;\n }\n }\n this.warn(\n \"godot_parser_unterminated_call\",\n `Unterminated Godot call ${name}(...).`,\n );\n return callValue(name, args);\n }\n\n private warn(code: string, message: string): void {\n this.diagnostics.push({\n severity: \"warning\",\n code,\n message,\n line: this.line,\n column: this.position + 1,\n });\n }\n}\n\nfunction callValue(name: string, args: GodotVariant[]): GodotVariant {\n const numericArgs = args.map((arg) =>\n typeof arg === \"number\" ? arg : Number.NaN,\n );\n switch (name) {\n case \"Vector2\":\n case \"Vector2i\":\n case \"Vector3\":\n case \"Vector3i\":\n case \"Vector4\":\n case \"Vector4i\":\n return { type: name, args: numericArgs };\n case \"Color\":\n return { type: \"Color\", args: numericArgs };\n case \"Rect2\":\n case \"Rect2i\":\n return { type: name, args: numericArgs };\n case \"NodePath\":\n return {\n type: \"NodePath\",\n args: [typeof args[0] === \"string\" ? args[0] : \"\"],\n };\n case \"ExtResource\":\n case \"SubResource\":\n return { type: name, id: String(args[0] ?? \"\") };\n default:\n // Any other constructor (PackedVector2Array, Transform2D, …): keep the\n // engine-native `{ type, args }` shape with the constructor name as type.\n return { type: name, args };\n }\n}\n\nfunction decodeEscape(char: string): string {\n switch (char) {\n case \"n\":\n return \"\\n\";\n case \"r\":\n return \"\\r\";\n case \"t\":\n return \"\\t\";\n default:\n return char;\n }\n}\n\nfunction dictionaryKey(value: GodotVariant): string {\n if (\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\"\n ) {\n return String(value);\n }\n if (\n value &&\n typeof value === \"object\" &&\n !Array.isArray(value) &&\n \"type\" in value &&\n value.type === \"StringName\" &&\n \"args\" in value &&\n Array.isArray(value.args) &&\n typeof value.args[0] === \"string\"\n ) {\n return value.args[0];\n }\n return JSON.stringify(value);\n}\n\nfunction isDigit(value: string): boolean {\n return value >= \"0\" && value <= \"9\";\n}\n"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@godot-scene-web/tscn-parser",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"description": "Parser for Godot .tscn and .tres text resources.",
|
|
7
|
+
"publishConfig": {
|
|
8
|
+
"access": "public",
|
|
9
|
+
"registry": "https://registry.npmjs.org/"
|
|
10
|
+
},
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "git+https://github.com/tfoxy/godot-scene-web.git"
|
|
14
|
+
},
|
|
15
|
+
"homepage": "https://github.com/tfoxy/godot-scene-web#readme",
|
|
16
|
+
"bugs": {
|
|
17
|
+
"url": "https://github.com/tfoxy/godot-scene-web/issues"
|
|
18
|
+
},
|
|
19
|
+
"sideEffects": false,
|
|
20
|
+
"exports": {
|
|
21
|
+
".": {
|
|
22
|
+
"development": "./src/index.ts",
|
|
23
|
+
"types": "./dist/index.d.ts",
|
|
24
|
+
"import": "./dist/index.js"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"main": "./dist/index.js",
|
|
28
|
+
"types": "./dist/index.d.ts",
|
|
29
|
+
"files": [
|
|
30
|
+
"dist",
|
|
31
|
+
"LICENSE"
|
|
32
|
+
],
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@godot-scene-web/core": "0.1.0"
|
|
35
|
+
},
|
|
36
|
+
"scripts": {
|
|
37
|
+
"build": "tsdown",
|
|
38
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
39
|
+
"test": "vitest run --root ../.. --config ../../vitest.config.ts packages/tscn-parser/test"
|
|
40
|
+
}
|
|
41
|
+
}
|