@vvfx/dsl-ir
v0.0.1-beta.10
Published
Editable DSL and Animation IR bidirectional converter
Keywords
Readme
@vvfx/dsl-ir
Bidirectional conversion and validation for editable DSL and source-neutral Animation IR.
The package owns the DSL boundary only. Importing and exporting Galacean Effects JSONScene, including preservation of
GE-only data, is handled by @vvfx/ge-ir.
Contents
Install
Node.js 22 or later is required.
pnpm add @vvfx/dsl-irInstall @vvfx/ge-ir as well when working with Galacean Effects:
pnpm add @vvfx/dsl-ir @vvfx/ge-irUsage
Convert DSL to Animation IR
A DSL document created from scratch does not need preserved data:
import { convertDSLToIR, type Composition } from '@vvfx/dsl-ir';
const dsl: Composition = {
meta: {
name: 'example',
duration: 2,
fps: 30,
width: 512,
height: 512,
loop: true,
background_color: null,
},
layers: [],
};
const { scene, diagnostics } = convertDSLToIR(dsl);DSL timing is expressed in seconds. Animation IR timing is expressed in frames, using dsl.meta.fps as the frame
rate. Adjacent animation segments may have different end and start values to represent an instantaneous reset.
DSL uses the initial position.z as a sibling stacking value: higher values render above lower values.
Array order does not control stacking. Equal values retain the imported order with preserved data; standalone DSL
uses layer IDs as a deterministic tie-breaker. Imported DSL exposes painter ranks in Z, while the paired sidecar
retains source spatial depth. Changing only Z reorders whole sibling subtrees without moving them toward the camera.
Standalone DSL positions are placed on the IR 2D plane (z = 0). Animated position uses its first segment's start Z
as a fixed rank. Editing XY on a layer with varying source depth retains depth at matching keyframe times;
changing that position's timing or replacing it with a static position is unsupported.
Convert Animation IR to DSL
convertIRToDSL always returns the editable DSL, diagnostics, and an IRToDSLPreservedData sidecar:
import { convertIRToDSL } from '@vvfx/dsl-ir';
const { dsl, preservedData, diagnostics } = convertIRToDSL(scene);The sidecar retains IR data and write-back relationships that DSL cannot represent completely. It is adapter-owned
data rather than business data. It can be persisted with JSON.stringify and JSON.parse, but applications should not
modify or depend on its internal structure.
Write edited DSL back to its source IR
Pass the DSL and sidecar produced by the same conversion back to convertDSLToIR:
const converted = convertIRToDSL(scene);
const editedDSL = structuredClone(converted.dsl);
editedDSL.layers[0].opacity = { a: false, value: 0.5 };
const { scene: updatedScene, diagnostics } = convertDSLToIR(editedDSL, {
preservedData: converted.preservedData,
onChange: change => console.info(change),
onWarning: warning => console.warn(warning),
});When preservedData is supplied, the converter applies DSL-representable changes to the retained IR snapshot while
keeping information outside the DSL contract. strict: true promotes conversion warnings and unsupported edits to
errors.
Combine with @vvfx/ge-ir
The application coordinates the adapters and keeps their sidecars paired.
import { convertGEToIR, convertIRToGE, updateGEToIRPreservedData } from '@vvfx/ge-ir';
import { convertIRToDSL, convertDSLToIR } from '@vvfx/dsl-ir';
const ge = convertGEToIR(geScene, { frameRate: 30 });
const dsl = convertIRToDSL(ge.scene);
const edited = structuredClone(dsl.dsl);
edited.meta.duration = 4;
const updated = convertDSLToIR(edited, { preservedData: dsl.preservedData });
const preservedData = updateGEToIRPreservedData(ge.scene, updated.scene, ge.preservedData);
const restored = convertIRToGE(updated.scene, { preservedData });Particle layers
Composition and Layer define the DSL for all layer types. Particle layers use type: 'particle' and the same
transform semantics as other layers. All layers may omit time_range, rotation, scale, anchor, and
opacity. Preserved write-back leaves omitted channels unchanged; fresh conversion uses composition timing and
identity transforms. Input DSL objects are not completed or mutated. convertIRToDSL produces complete layers;
validateDSL and convertDSLToIR validate and convert them through the common pipeline. parseParticleShape parses optional,
read-only emitter geometry supplied by a source adapter.
Applications compose source effects, target layout, model requests and GE resource restoration through public adapter APIs.
Data and editing boundaries
@vvfx/animation-iris the single source of truth for Animation IR types and validation.- DSL is an editing-oriented subset, not a mirror of any source format schema.
convertIRToDSLexpands precompositions and stores the write-back relationships inIRToDSLPreservedData.- Fidelity-preserving write-back supports field edits, deletion, and reordering of existing layers under the same parent. Unsafe edits are reported through diagnostics or warnings.
- Both conversion directions validate their IR boundary. Every successfully returned
scenesatisfies the Animation IR contract. - External images entering Animation IR must use absolute URLs or Data URLs. DSL font families become system font
assets.
Inline SVG assets use their SVG content when
urlis omitted or empty. - Particle Layers use the same
convertIRToDSLandconvertDSLToIRworkflow as other supported Layers. Editableoptionsandemissionvalues are represented in DSL. Source adapters may also expose an optional read-onlyshapeblock for model context; renderer, resources, and other GE-only fields remain in the GE adapter sidecar. - Burst
cyclesdefaults to one; zero means unbounded repetition until the Layer ends. Repeated bursts require a positiveintervalin seconds. - Particle lifetime and emission values use the DSL subset of GE
NumberExpression: constant tag0and random-range tag4. IR curves are projected with diagnostics and retained in the DSL sidecar until the corresponding field is edited. A projectedshapeblock is not written into Animation IR; the source adapter remains responsible for restoring the original emitter geometry.
Further documentation:
- DSL format
- DSL and IR guide
- DSL and IR editing capabilities
- DSL, IR, and GE package boundaries
- Animation IR particle contract
API
Runtime exports
| Export | Purpose |
| --- | --- |
| convertDSLToIR | Convert a new DSL document to IR, or write DSL values back to retained IR |
| convertIRToDSL | Convert IR to editable DSL and return the sidecar needed for write-back |
| validateDSL | Validate an unknown value against the DSL contract |
| DSLValidationError | Structured error thrown when conversion cannot continue |
Core signatures:
function convertDSLToIR(composition: Composition, options?: ConvertDSLToIROptions): DSLToIRResult;
function convertIRToDSL(scene: IRScene): IRToDSLResult;
function validateDSL(dsl: unknown, options?: ValidateDSLOptions): DSLValidationResult;Type exports
All public types are imported from the package root:
- DSL schema:
AnimationCurve,AnimatedProperty,Asset,Composition,CompositionMeta,Description,Layer,LLMSVGAsset,NumberExpression, theParticle*types,TextProperties,UserAsset, andValueType. - Validation:
DSLValidationIssue,DSLValidationResult, andValidateDSLOptions. - DSL to IR:
ConvertDSLToIROptions,DSLToIRChange,DSLToIRResult, andDSLToIRWarning. - IR to DSL:
IRToDSLPreservedDataandIRToDSLResult.
Important result and option types:
interface IRToDSLResult {
dsl: Composition;
preservedData: IRToDSLPreservedData;
diagnostics: ConversionDiagnostic[];
}
interface DSLToIRResult {
scene: IRScene;
diagnostics: ConversionDiagnostic[];
}
interface ConvertDSLToIROptions {
preservedData?: IRToDSLPreservedData;
strict?: boolean;
onWarning?: (warning: DSLToIRWarning) => void;
onChange?: (change: DSLToIRChange) => void;
}Project structure
src/
dsl/ DSL schema and validation
dsl2ir/ DSL to Animation IR
recombine/ Preserved-data write-back into retained IR
ir2dsl/ Animation IR to DSL and precomposition expansion
common/ Value mappings shared by both directionsContributing
Use repository issues for questions and bug reports. Pull requests are welcome. Run the package checks after changing public behavior:
pnpm --filter @vvfx/dsl-ir test
pnpm --filter @vvfx/dsl-ir buildLicense
MIT © 2019-present Ant Group Co., Ltd.
