|
| 1 | +# Bundle Documentation |
| 2 | +Documentation for Source bundles is generated using the [`typedoc`](https://typedoc.org) tool. There are two types: HTML and JSON documentation. |
| 3 | + |
| 4 | +By reading comments and type annotations, `typedoc` is able to generate both human readable documentation and documentation in the form of JSON. |
| 5 | + |
| 6 | +> [!WARNING] |
| 7 | +> By default, `typedoc` does type checking for code, similar to `tsc`. This functionality has been turned off as more often then not, `tsc` will be run before `typedoc`, making the type checking performed by `typedoc` extraneous. |
| 8 | +> |
| 9 | +> This does mean that if the documentation is built without running `tsc`, there is a possibility that type errors will cause `typedoc` to crash. |
| 10 | +
|
| 11 | +## Writing Documentation |
| 12 | +`typedoc` reads both Typescript type annotations, as well as [TSDOC](https://tsdoc.org) style comments. It will build documentation for all functions and constants exported by the particular module. |
| 13 | + |
| 14 | +Let us look at an example from the `curve` module. |
| 15 | +```ts |
| 16 | +// functions.ts |
| 17 | +/** |
| 18 | + * Makes a Point with given x and y coordinates. |
| 19 | + * |
| 20 | + * @param x x-coordinate of new point |
| 21 | + * @param y y-coordinate of new point |
| 22 | + * @returns with x and y as coordinates |
| 23 | + * @example |
| 24 | + * ``` |
| 25 | + * const point = make_point(0.5, 0.5); |
| 26 | + * ``` |
| 27 | + */ |
| 28 | +export function make_point(x: number, y: number): Point { |
| 29 | + return new Point(x, y, 0, [0, 0, 0, 1]); |
| 30 | +} |
| 31 | +``` |
| 32 | + |
| 33 | +```ts |
| 34 | +// index.ts |
| 35 | +export { make_point } from './functions.ts'; |
| 36 | +``` |
| 37 | +Since the `curve` bundle exports the `make_point` function, `typedoc` will generate documentation for it. |
| 38 | + |
| 39 | +The following sections are conventions for writing documentation. |
| 40 | + |
| 41 | +### Entry Point |
| 42 | +At the entry point for each bundle, there should be a block comment that provides general information about the bundle. |
| 43 | + |
| 44 | +This example is taken from the `repeat` bundle: |
| 45 | +```ts |
| 46 | +// repeat/src/index.ts |
| 47 | +/** |
| 48 | + * Test bundle for Source Academy modules repository |
| 49 | + * @author Loh Xian Ze, Bryan |
| 50 | + * @author Tang Xin Kye, Marcus |
| 51 | + * @module repeat |
| 52 | + */ |
| 53 | + |
| 54 | +export { repeat, twice, thrice } from './functions'; |
| 55 | +``` |
| 56 | +It is important that you provide an `@module` tag in this description. Otherwise, the build tools may not be able to detect your bundle's |
| 57 | +documentation properly. |
| 58 | + |
| 59 | +### Use of `@hidden` |
| 60 | +If there are exports you want hidden from the output of the documentation, you must use the either `@hidden` tag. |
| 61 | + |
| 62 | +The example below is taken from the `rune` bundle: |
| 63 | +```ts |
| 64 | +// rune/src/type_map.ts |
| 65 | +import createTypeMap from '@sourceacademy/modules-lib/type_map'; |
| 66 | + |
| 67 | +const typeMapCreator = createTypeMap(); |
| 68 | + |
| 69 | +export const { functionDeclaration, variableDeclaration, classDeclaration } = typeMapCreator; |
| 70 | + |
| 71 | +/** @hidden */ |
| 72 | +export const type_map = typeMapCreator.type_map; |
| 73 | +``` |
| 74 | + |
| 75 | +This causes `type_map` to be removed from the documentation, even if it is exported from `rune/src/index.ts`. |
| 76 | + |
| 77 | +> [!WARNING] |
| 78 | +> Bundle `type_map`s are supposed to be internal implementation details hidden from users. If you forget to apply a `@hidden` tag to |
| 79 | +> your bundle's type map export, the build tools will show a warning. |
| 80 | +
|
| 81 | +### Use of `@function` |
| 82 | +Following v0.28, Typedoc only documents function-like types as functions if they are explicitly typed as functions (see the issue [here](https://github.com/TypeStrong/typedoc/issues/2881)). |
| 83 | +This means that if you have code that looks like this: |
| 84 | +```ts |
| 85 | +// curve/functions.ts |
| 86 | +function createDrawFunction( |
| 87 | + scaleMode: ScaleMode, |
| 88 | + drawMode: DrawMode, |
| 89 | + space: CurveSpace, |
| 90 | + isFullView: boolean |
| 91 | +): (numPoints: number) => RenderFunction { |
| 92 | + return (numPoints: number) => { |
| 93 | + // implementation details |
| 94 | + }; |
| 95 | +} |
| 96 | + |
| 97 | +export const draw_connected = createDrawFunction('none', 'lines', '2D', false); |
| 98 | +``` |
| 99 | +and `RenderFunction` has the following type: |
| 100 | +```ts |
| 101 | +// curve/types.ts |
| 102 | +/** |
| 103 | + * A function that specifies additional rendering information when taking in |
| 104 | + * a CurveFunction and returns a ShapeDrawn based on its specifications. |
| 105 | + */ |
| 106 | +export type RenderFunction = { |
| 107 | + (func: Curve): CurveDrawn |
| 108 | + is3D: boolean |
| 109 | +}; |
| 110 | +``` |
| 111 | +Typedoc won't consider `draw_connected` to be a function. Instead it will consider it to be a variable: |
| 112 | + |
| 113 | + |
| 114 | +This is because `drawConnected` is of type `RenderFunction` and `RenderFunction` is only _function-like_. |
| 115 | + |
| 116 | +To remedy this, include the `@function` tag in your documentation: |
| 117 | +```ts {6} |
| 118 | +/** |
| 119 | + * Returns a function that turns a given Curve into a Drawing, by sampling the |
| 120 | + * Curve at `num` sample points and connecting each pair with a line. |
| 121 | + * The parts between (0,0) and (1,1) of the resulting Drawing are shown in the window. |
| 122 | + * |
| 123 | + * @function |
| 124 | + * @param num determines the number of points, lower than 65535, to be sampled. |
| 125 | + * Including 0 and 1, there are `num + 1` evenly spaced sample points |
| 126 | + * @return function of type Curve → Drawing |
| 127 | + * @example |
| 128 | + * ``` |
| 129 | + * draw_connected(100)(t => make_point(t, t)); |
| 130 | + * ``` |
| 131 | + */ |
| 132 | +export const draw_connected = createDrawFunction('none', 'lines', '2D', false); |
| 133 | +``` |
| 134 | + |
| 135 | +The export will now be correctly recognized as a function: |
| 136 | + |
| 137 | + |
| 138 | +There is no automatic way to make this distinction, so it is up to the bundle authors to make sure that this convention is adhered to. |
| 139 | + |
| 140 | +## HTML Documentation |
| 141 | +The human readable documentation resides in the `build/documentation` folder. You can view its output [here](https://source-academy.github.io/modules/documentation). This is what the output for `make_point` looks like: |
| 142 | + |
| 143 | + |
| 144 | + |
| 145 | +The description block supports formatting using Markdown. The markdown is translated into HTML during building. |
| 146 | + |
| 147 | +## JSON Documentation |
| 148 | + |
| 149 | +To provide the frontend with documentation that can be directly displayed to the user, each module has its own json file in the `jsons` folder containing the formatted descriptions of exported variables. |
| 150 | +Using the example code above, here is what the JSON documentation looks like for the actual `curve` bundle: |
| 151 | +```jsonc |
| 152 | +{ |
| 153 | + "make_point": { |
| 154 | + "kind": "function", |
| 155 | + "name": "make_point", |
| 156 | + "description": "<p>Makes a Point with given x and y coordinates.</p>", |
| 157 | + "params": [ |
| 158 | + [ |
| 159 | + "x", |
| 160 | + "number" |
| 161 | + ], |
| 162 | + [ |
| 163 | + "y", |
| 164 | + "number" |
| 165 | + ] |
| 166 | + ], |
| 167 | + "retType": "Point" |
| 168 | + }, |
| 169 | + // ...other functions and constants |
| 170 | +} |
| 171 | +``` |
| 172 | +This is then displayed by the frontend: |
| 173 | + |
| 174 | + |
| 175 | + |
| 176 | + |
| 177 | +When building the json documentation for a bundle, the following steps are taken: |
| 178 | +1. From `typedoc`'s output, extract the [project](https://typedoc.org/api/classes/ProjectReflection.html) corresponding to the bundle. |
| 179 | +1. For each exported variable, run it through a converter to convert the `typedoc` project into a single string: |
| 180 | + - For constants, their names and types are extracted |
| 181 | + - For functions, their name, the names and types of each parameter, and return types are extracted.\ |
| 182 | + The descriptions of both functions are constants are also included, but first they are passed through a Markdown to HTML converter called [drawdown](https://github.com/adamvleggett/drawdown), included in this project as `drawdown.ts` |
| 183 | +3. The code then converts it to the HTML format expected by the frontend |
| 184 | +3. All the processed strings then get written to a json file in the jsons folder. |
| 185 | + |
| 186 | +If no documentation could be found, or there was an error parsing the documented code, the system will still output jsons, just with warnings. |
0 commit comments