MDF (Mowo Data Format) parser and serializer for JavaScript/TypeScript.
A typed, human-readable data format designed for game engines. First-class support for vec3(), quat(), rgb(), hex(), uuid(), asset references, and bare enums.
This is the official JavaScript/TypeScript implementation of MDF.
npm install @mowogames/mdfimport { parse } from "@mowogames/mdf";
const doc = parse(`
Scene "Forest" {
version: 2
gravity: vec3(0, -9.81, 0)
GameObject "Player" {
active: true
mesh: @"Assets/Models/Character.fbx"
Transform {
position: vec3(0, 1, 0)
rotation: quat(0, 0.707, 0, 0.707)
}
RigidBody {
type: Dynamic
mass: 75.0
}
}
}
`);
const root = doc.root();
console.log(root.type); // "Scene"
console.log(root.name); // "Forest"
const gravity = root.getVec3("gravity");
console.log(gravity); // { x: 0, y: -9.81, z: 0 }
const player = root.findChild("GameObject", "Player");
console.log(player.getBool("active")); // true
console.log(player.getString("mesh")); // "Assets/Models/Character.fbx"
const pos = player.findChild("Transform").getVec3("position");
console.log(pos); // { x: 0, y: 1, z: 0 }import {
MdfDocument, MdfInt, MdfBool, MdfString, MdfVec3Val,
MdfEnum, MdfAssetRef, MdfUUID, stringify
} from "@mowogames/mdf";
const doc = new MdfDocument();
const scene = doc.createRoot("Scene", "MyLevel");
scene.set("version", MdfInt(1));
scene.set("gravity", MdfVec3Val(0, -9.81, 0));
const player = scene.addChild("GameObject", "Player");
player.set("active", MdfBool(true));
player.set("tag", MdfString("Player"));
player.set("id", MdfUUID("550e8400-e29b-41d4-a716-446655440000"));
const transform = player.addChild("Transform");
transform.set("position", MdfVec3Val(0, 1, 0));
const body = player.addChild("RigidBody");
body.set("type", MdfEnum("Dynamic"));
console.log(stringify(doc));Output:
Scene "MyLevel" {
version: 1
gravity: vec3(0.0, -9.81, 0.0)
GameObject "Player" {
active: true
tag: "Player"
id: uuid("550e8400-e29b-41d4-a716-446655440000")
Transform {
position: vec3(0.0, 1.0, 0.0)
}
RigidBody {
type: Dynamic
}
}
}
| Type | MDF Syntax | Constructor |
|---|---|---|
| Null | null |
MdfNull() |
| Bool | true / false |
MdfBool(true) |
| Int | 42 |
MdfInt(42) |
| Float | 3.14 |
MdfFloat(3.14) |
| String | "hello" |
MdfString("hello") |
| Vec2 | vec2(1, 2) |
MdfVec2Val(1, 2) |
| Vec3 | vec3(1, 2, 3) |
MdfVec3Val(1, 2, 3) |
| Vec4 | vec4(1, 2, 3, 4) |
MdfVec4Val(1, 2, 3, 4) |
| Quat | quat(0, 0, 0, 1) |
MdfQuatVal(0, 0, 0, 1) |
| Color | rgb(0.5, 0.2, 0.1) |
Parsed as Vec4 with alpha 1.0 |
| Hex | hex(#FF6600) |
Parsed as normalized Vec4 |
| UUID | uuid("...") |
MdfUUID("...") |
| Asset Ref | @"path" |
MdfAssetRef("path") |
| Enum | Dynamic |
MdfEnum("Dynamic") |
| Array | [1, 2, 3] |
MdfArray([...]) |
Parse MDF text. Throws on syntax errors.
Serialize a document to MDF text format.
doc.createRoot(type, name?) // Create root node
doc.root() // Get first root (throws if empty)
doc.roots // All root nodesnode.type // Node type identifier
node.name // Optional name
node.set(key, value) // Set property (chainable)
node.get(key) // Get raw MdfValue
node.has(key) // Check if property exists
node.properties // Map<string, MdfValue>
// Typed getters (throw on type mismatch)
node.getBool(key) // boolean
node.getInt(key) // number (truncated)
node.getFloat(key) // number
node.getString(key) // string (works for String, UUID, AssetRef, Enum)
node.getVec2(key) // { x, y }
node.getVec3(key) // { x, y, z }
node.getVec4(key) // { x, y, z, w }
node.getArray(key) // MdfValue[]
// Children
node.addChild(type, name?) // Add child node
node.findChild(type, name?) // Find first child by type
node.findChildren(type) // Find all children by type
node.children // All children//line comments and/* */block comments- Trailing commas in arrays
- Scientific notation (
1e-6) - Escape sequences in strings (
\n,\t,\\,\") - Multiple root nodes per document
- Heterogeneous arrays
Fully compatible with the C++ MDF library. Files written by either implementation can be read by the other.
MIT