Request for Comment (RFC) and a proposal for adopting JSDoc within the three.js project. The proposal intends to mitigate or solve two longstanding problems:
- Unofficial type definitions: Increasingly, many web projects and IDEs rely on type definitions in libraries, which three.js does not natively provide. The community maintains type definitions in a separate repository, with some overhead in cost and potential for mistakes or delays.
- Cost of maintaining localized documentation: API documentation for each class is maintained in hand-written HTML files, one file for each {class, language} pair. Maintainers contribute to the English-language documentation, while volunteers are largely responsible for identifying where English translations have changed and updating the localized versions.
Required if RFC is accepted.
JavaScript source files will be annotated with comments in JSDoc format, describing only those type definitions required for public-facing APIs. Human-readable API descriptions are not present at this milestone. From the JSDoc comments, release builds will generate TypeScript type definitions published to npm within the library.
Example: `src/core/Object.js`
/**
* @property {true} isObject3D
* @property {string} uuid
* @property {number} id
* @property {string} name
* @property {string} type
* @property {Object3D|null} parent
* @property {Object3D[]} children
* @property {Vector3} up
* @property {Vector3} position
* @property {Euler} rotation
* @property {Vector3} scale
* ...
*/
class Object3D extends EventDispatcher {
constructor() { ... }
/**
* @param {WebGLRenderer} renderer
* @param {Scene} scene
* @param {Camera} camera
* @param {BufferGeometry} geometry
* @param {Material} material
* @param {any} group
*/
onBeforeRender() { ... }
/**
* @param {WebGLRenderer} renderer
* @param {Scene} scene
* @param {Camera} camera
* @param {BufferGeometry} geometry
* @param {Material} material
* @param {any} group
*/
onAfterRender() { ... }
/**
* @param {Matrix4} matrix
*/
applyMatrix4(matrix) { ... }
...
}
We'll add typescript
to package.json#devDependencies
, and create a tsconfig.json
file with checkJS
and allowJS
options enabled. Editors like VSCode should then automatically provide hints when types are invalid. The code will run as expected in a browser, regardless of whether types are updated or compiled. At build time, TypeScript compiles the JSDoc comments to build/three.d.ts
, including API definitions for the entire library — including three
and three/addons/*
. See dts-buddy
for details on how this should work.
Optional, and depends on Milestone 1.
In addition to type annotations, JSDoc comments will now include human-readable descriptions, in English, for each public-facing API item. In a build step, tooling will process the JSDoc comments or the d.ts
files, and generate corresponding HTML pages identical to our current pages.
What about inline examples?
If desired, examples may be specified in one of two ways:
/**
* Description of Mesh class here.
*
* @example link_to_example.html
*
* @example
* Inline example below:
* ```javascript
* import { Mesh } from 'three';
* const mesh = new Mesh( geometry, material );
* ```
*/
class Mesh {
}
The former requires external files, and the latter is more verbose. Either will require some work on the HTML generator, which I believe is manageable. For simplicity, it may be preferable to leave these examples out of the API documentation and link to other examples or the manual instead.
Optional, and depends on Milestones 2–3.
JSDoc or type definitions are processed in a build step, assigning a unique key to each English-language comment (e.g. Mesh#geometry
). For each target output language, a human readable file (likely .csv or .yaml) is generated with content equivalent to:
Example: lang_it.csv
key | enUpdated | itUpdated | en | it |
---|---|---|---|---|
Mesh#geometry | 2021-05-04 | 2021-10-15 | An instance of BufferGeometry... | Un'istanza di BufferGeometry... |
Mesh#material | 2021-05-04 | 2021-10-15 | An instance of Material... | Un'istanza di Material... |
The lastUpdated
column will be maintained by the generator, allowing translators to more easily find sections where the English comments have changed since the last translation. Optionally, translations may be modified in external software like Microsoft Excel or Google Sheets.
In a final build step, these translation files are processed, and translated HTML pages for API documentation are generated alongside the English-language versions.
- By generating API documentation automatically, the process for maintaining API docs diverges from the process for maintaining the manual and other written resources on the website.
- JSDoc type annotations are admittedly verbose, and less ergonomic to write than TypeScript annotations. This problem could be mitigated if proposals for JavaScript Type Annotations are approved and implemented.
-
Rewrite three.js in TypeScript. None of the primary maintainers of three.js are currently interested in a change toward writing and maintaining TypeScript code.
-
Maintain
d.ts
type definitions manually. Manually updatingd.ts
files was attempted as a trial for several three.js releases. Cost of maintenance was prohibitive, and inability to validate hand-writtend.ts
files against source files created unacceptable problems.
- TypeScript cannot parse
@property
or@member
directives in JSDoc, breaking use ofObject.defineProperty
. See list of supported tags.- microsoft/TypeScript#7237
- microsoft/TypeScript#28730
- microsoft/TypeScript#15715
- dsherret/ts-morph#1427 (possible workaround without the TypeScript compiler)
Throwing spaghetti around... for Milestone 3, maybe there's a translation API that
en
updates could be feed into? AI's getting much better at this these days.Liking efforts being made in this area. Sending best wishes 👍