Skip to content

Commit d2ed1a5

Browse files
committed
Reformat more Markdown files
1 parent 3e5b9b2 commit d2ed1a5

File tree

15 files changed

+159
-15
lines changed

15 files changed

+159
-15
lines changed

docs/src/modules/1-getting-started/6-troubleshooting.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
## Installation Troubleshooting
44

55
### ESBuild Error
6+
67
If you encounter errors with esbuild dependencies like the following while building:
78

89
```txt
@@ -17,6 +18,7 @@ Especially if you've worked with other Javascript/Typescript projects before, yo
1718
does not seem to work (or work permanently) for you.
1819

1920
Things to check for:
21+
2022
- Remove any errant `package.json` or `.yarnrc.yml` files in places like your home directory or elsewhere.
2123
- Run `npm uninstall -g yarn` if you previously installed Yarn using installed `npm`.
2224
- For people running Windows, `corepack enable` is a command that needs to be run using administrator privileges. If this is not possible for you, there are [workarounds](https://github.com/nodejs/corepack?tab=readme-ov-file#corepack-enable--name).

docs/src/modules/2-bundle/1-overview.md

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22

33
Similar to regular Javascript modules, Source allows developers to export functions and constants to users for importing into their programs.
44

5-
For example, the `binary_tree` module may want to provide an abstraction for Source programs to interact with the Binary Tree data structure. Thus, the `binary_tree` module would expose functions such as `make_tree`, `left_branch` and `right_branch` to be used in Source programs.
5+
For example, the `binary_tree` module may want to provide an abstraction for Source programs to interact with the Binary Tree data structure. Thus, the `binary_tree` module would expose functions such as `make_tree`, `left_branch` and `right_branch` to be used in Source programs.
66

77
## Bundle Directory Structure Overview
88

99
The typical bundle structure for a bundle is shown below. Each section will have its own explanation.
10+
1011
```dirtree
1112
name: bundle_name
1213
children:
@@ -65,12 +66,14 @@ export function createDrawFunction(
6566
// implementation hidden...
6667
}
6768
```
69+
6870
Note that `curve/functions.ts` exports both `createDrawFunction` and `make_point`.
6971

7072
```ts
7173
// curve/index.ts
7274
export { make_point } from './functions';
7375
```
76+
7477
However, only `make_point` is exported at the bundle's entry point however `createDrawFunction` is not, so cadets will not be able to access it, identical to how ES modules behave.
7578

7679
```js
@@ -87,6 +90,7 @@ It is not recommended that you use default exports in your code as default expor
8790
:::
8891

8992
## `package.json`
93+
9094
The `package.json` file follows the same format as your typical `package.json` used with the likes of `npm` or `yarn`. If you use the template creation command, it should already have been created for you.
9195

9296
```jsonc
@@ -101,21 +105,27 @@ The `package.json` file follows the same format as your typical `package.json` u
101105
}
102106
}
103107
```
108+
104109
You can find more information about each of the fields and what they mean [here](https://docs.npmjs.com/cli/v11/configuring-npm/package-json#devdependencies).
105110

106111
> [!WARNING] Bundle vs Package Name
107112
> The `name` field in `package.json` is the package name and must follow the format `@sourceacademy/bundle-[your bundle name]`.
108113
> The bundle name is what users will actually use to import your bundle from within Source code:
114+
>
109115
> ```ts
110116
> import { whatever } from 'bundle_name';
111117
> ```
118+
>
112119
> However, people consuming your bundle from regular Javascript and Typescript need to use the full (scoped) package name:
120+
>
113121
> ```ts
114122
> import { whatever } from '@sourceacademy/bundle-bundle_name';
115123
> ```
116124
117125
### `manifest.json`
126+
118127
`manifest.json` contains the information required by `js-slang` to load your bundle.
128+
119129
```jsonc
120130
{
121131
"tabs": ["Curve"], // String array of the names of the tabs that will be loaded alongside your bundle
@@ -133,7 +143,9 @@ Your bundle may rely on features that are only present in later Source Chapters.
133143
> You can use the `buildtools list bundle` command to check that your bundle can be properly detected and has the correct format.
134144
135145
## `tsconfig.json`
146+
136147
This file controls the behaviour of Typescript. By default, it should look like this:
148+
137149
```json
138150
{
139151
"extends": "../tsconfig.json",
@@ -148,10 +160,9 @@ This file controls the behaviour of Typescript. By default, it should look like
148160
}
149161
}
150162
```
163+
151164
In general, there should not be a need for you to modify this file. A full explanation on how to use `tsconfig.json` can be found [here](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html). Note that the `typedocOptions` field is a custom field used by `typedoc` for its configuration. Refer to [here](https://typedoc.org/documents/Options.Configuration.html#compileroptions) for more information.
152165

153166
> [!WARNING]
154167
> You should not remove or modify the `typedocOptions` section from your `tsconfig.json` unless you provide the name of your bundle to Typedoc via its other configuration methods. Generating documentation for your bundle
155168
> requires that the name of your bundle be set correctly.
156-
157-

docs/src/modules/2-bundle/3-editing.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,29 @@
11
# Editing an Existing Bundle
2+
23
This page contains instructions for modifying an existing bundle. If you are creating a new bundle from scratch, refer to [these](./2-creating/2-creating) instructions instead.
34

45
## Installing Dependencies
6+
57
To install **only** the dependencies required by the bundle you are modifying, use the command below:
68

79
```sh
810
yarn workspaces focus @sourceacademy/bundle-[desired bundle]
911
```
1012

1113
## Adding Dependencies
14+
1215
Your bundle may need other Javascript packages. To add a dependency to your bundle, run the command below:
16+
1317
```sh
1418
yarn add [dependency]
1519
```
1620

1721
If the dependency does not need to be present during runtime, then use:
22+
1823
```sh
1924
yarn add --dev [dependency]
2025
```
26+
2127
This adds the dependency to `devDependencies` instead.
2228

2329
> [!WARNING]
@@ -27,18 +33,22 @@ This adds the dependency to `devDependencies` instead.
2733
> [!NOTE]
2834
> There are certain dependencies that are common to all bundles (like `react`). When adding such a dependency, remember to add the exact version
2935
> specified in the root repository `package.json`:
36+
>
3037
> ```sh
3138
> yarn add react@^18.3.1
3239
> ```
40+
>
3341
> You can also use the command `yarn constraints` to check if you have incorrectly specified the version of a dependency.
3442
3543
> [!NOTE]
3644
> When adding dependencies that originate from the repository (e.g `@sourceacademy/modules-lib`), use `workspace:^` as the given version:
45+
>
3746
> ```sh
3847
> yarn add @sourceacademy/modules-lib@workspace:^
3948
> ```
4049
4150
### React Within bundles
51+
4252
Currently, the way bundles are loaded by `js-slang` means that React cannot be externalized for bundles. `js-slang` simply has no way to provide React
4353
from the frontend to the bundle.
4454
@@ -47,12 +57,15 @@ This means that tools like the React DevTools will not be able to work correctly
4757
Refer to the [issue](https://github.com/source-academy/modules/issues/211) tracking this functionality.
4858
4959
## Bundle Conventions
60+
5061
To ensure that bundles conform to the different Source language specifications, there are a few rules that bundles need to abide by.
5162
Refer to [this list](./4-conventions/index) for more information.
5263
5364
## Common Modules Library
65+
5466
There are common functions such as `hexToColor` available in the Common Modules Library. You can make use of these functions
5567
instead of implementing your own versions of them.
5668
5769
## Adding Unit Tests
70+
5871
Where possible, you should add unit tests to your bundle. Refer to [this](/modules/4-advanced/testing) page for instructions.

docs/src/modules/2-bundle/4-conventions/1-basic.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
# Basic Conventions
22

33
## 1. Cadet facing functions should not have default or rest parameters
4+
45
The function signature below takes in two booleans, the second of which is optional. This is not supported for Module functions in Source, but is fine if your function
56
isn't being exposed to cadets.
7+
68
```ts
79
// Don't expose this to cadets!
810
function configure_options(option_1: boolean, option_2: boolean = false) {
@@ -26,22 +28,28 @@ Neither default nor rest parameters are currently supported due to an [issue](ht
2628
:::
2729

2830
## 2. If your bundle requires specific Source features, make sure to indicate it in the manifest
31+
2932
Consider the bundle function below:
33+
3034
```ts
3135
export function sum(args: numbers[]) {
3236
return args.reduce((res, each) => res + each, 0);
3337
}
3438
```
39+
3540
It takes an an input an array of `number`s. However, arrays are only available in Source 3 onward. This means that you should indicate in your bundle's manifest:
41+
3642
```jsonc
3743
{
3844
"requires": 3
3945
}
4046
```
47+
4148
to let `js-slang` know that your bundle can't be loaded with Source 1 and 2.
4249

4350
::: details Which data structure to use?
4451
In the above example, the array can actually be replaced with a Source `List`:
52+
4553
```ts
4654
import { head, tail } from 'js-slang/dist/stdlib/list';
4755

@@ -59,11 +67,13 @@ export function sum(args: List) {
5967
return total;
6068
}
6169
```
70+
6271
Lists are actually introduced in Source 1, which would make the above function compatible with Source 1 instead of requiring Source 3. If your bundle doesn't need
6372
functionality specific to arrays, then consider using Source Lists instead.
6473
:::
6574

6675
## 3. Making use of `js-slang/stdlib`
76+
6777
Bundles, where necessary, should use the implementations of libraries such as `list` or `stream` from the `js-slang` standard library:
6878

6979
```ts
@@ -77,6 +87,7 @@ export function is_sound(obj: unknown): obj is Sound {
7787
);
7888
}
7989
```
90+
8091
These libraries get externalized and are then provided to bundles at runtime, so not only does this make your bundle size smaller, but it also
8192
ensures that you are using the same version of the `stdlib` as the version being used by `js-slang` while running your bundle code.
8293

docs/src/modules/2-bundle/4-conventions/2-abstractions.md

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,15 @@ primitive and non primitive objects (`Wave`s are `(t: number) => number` while `
99
Instead of passing around the type in terms of primitives, you should make it such that cadets interact directly with the abstraction instead. Take the `sound` bundle for example.
1010

1111
`Sound`s are defined as a `pair`, where the head is a `Wave` and the tail is a number representing the duration of that sound:
12+
1213
```ts
1314
import type { Pair } from 'js-slang/dist/stdlib/list';
1415

1516
type Sound = Pair<Wave, number>;
1617
```
1718

1819
Functions from the `sound` bundle interact directly with `Sound`s, rather than the underlying type:
20+
1921
```ts
2022
// Do this!
2123
export function play_in_tab(sound: Sound): void {
@@ -31,12 +33,14 @@ export function play_in_tab(sound: Pair<Wave, number>): void {
3133
Functionally, `Sound` behaves like a primitive type: as far as a cadet using the `sound` bundle is concerned, the bundle allows them to make and manipulate `Sound`s.
3234

3335
## Breaking Abstractions with `display` and `stringify`
36+
3437
`js-slang` provides a built-in function for converting any value into a string: `stringify()`. `display()` behaves like the typical `console.log` and prints the string representation
3538
as returned by `stringify` to the REPL. Under the hood, `stringify` uses the default Javascript `toString` functionality to convert primitive types to their string representations. This does
3639
mean that for "primitives" that are actually objects, `js-slang`'s default implementation will end up exposing implementation details.
3740

3841
Taking an example from the `curve` bundle, `RenderFunction`s are considered a type of primitive. Without any further changes, calling `display` on a `RenderFunction` produces the following
3942
output:
43+
4044
```js
4145
// Partial toString() representation of a RenderFunction
4246
curve => {
@@ -47,11 +51,14 @@ curve => {
4751
return curveDrawn;
4852
}
4953
```
54+
5055
This exposes implementation details to the cadet and "breaks" the `RenderFunction` abstraction. Thus, there is a need for such objects to be able to override the default `toString`
5156
implementation.
5257

5358
## The `ReplResult` interface
59+
5460
To allow objects to provide their own `toString` implementations, objects can implement the `ReplResult` interface:
61+
5562
```ts
5663
interface ReplResult {
5764
toReplString: () => string
@@ -69,22 +76,28 @@ but if your circumstances can't support it you can refer to the second method wh
6976

7077
> [!TIP]
7178
> Source automatically hides the implementation for all functions at the top-level of a bundle. Running the code below
79+
>
7280
> ```ts
7381
> import { show } from 'rune';
7482
> display(show);
7583
> ```
84+
>
7685
> produces the following string output:
86+
>
7787
> ```txt
7888
> function show {
79-
> [Function from rune
89+
> [Function from rune
8090
> Implementation hidden]
8191
> }
8292
> ```
93+
>
8394
> This means that is is unnecessary to implement `ReplResult` for any of your top-level functions. You can still override this automatic functionality by implementing
8495
> `ReplResult`.
8596
8697
### Implementing `ReplResult` directly
98+
8799
The simplest way to implement the interface is to do it in Typescript. For example, the `curve` bundle has a `Point` class, which is an abstraction of a point in 3D space with a color value:
100+
88101
```ts
89102
/** Encapsulates 3D point with RGB values. */
90103
export class Point implements ReplResult {
@@ -105,9 +118,11 @@ would result in the infamous `[object Object]` being printed.
105118
The benefit of implementing the interface this way in Typescript is that it enables type-checking to ensure that the interface is properly implemented.
106119

107120
### Implementing `ReplResult` indirectly
121+
108122
The `ReplResult` type is only just a Typescript interface. So long as `toReplString` property is present on the object/function, `js-slang` will be able to call it.
109123

110124
Referring back to the `curve` bundle's `RenderFunction`s, the type `RenderFunction` is really just a plain Javascript function with some extra properties attached to it:
125+
111126
```ts
112127
type RenderFunction = {
113128
(func: Curve): CurveDrawn
@@ -119,6 +134,7 @@ type RenderFunction = {
119134
```
120135

121136
This type doesn't implement the `ReplResult` interface, but before `RenderFunction`s are returned, they have the `toReplString` property set:
137+
122138
```ts
123139
// curve/src/functions.ts
124140

@@ -156,13 +172,15 @@ function createDrawFunction(
156172
// This has type (points: number) => RenderFunction
157173
export const draw_connected = createDrawFunction('none', 'lines', '2D', false);
158174
```
175+
159176
> [!TIP]
160177
> Notice in this case that they abstraction is being applied to the return type of `draw_connected` and not to the return type of `createDrawFunction`. The latter
161178
> is just a factory function for creating the different `draw_connected` function variants, each of which return `RenderFunction`s.
162179
>
163180
> As mentioned earlier, since `draw_connected` is exported at the top-level of the `curve` bundle, `ReplResult` is automatically implemented for it.
164181
165182
We've seen the result of the default `toString` implementation. By providing `toReplString`, `js-slang` can instead return a user-friendly stringified representation of a `RenderFunction`:
183+
166184
```js
167185
import { draw_connected } from 'curve';
168186
display(draw_connected(200));
@@ -179,23 +197,30 @@ provide compile time validation that the property has been set correctly.
179197
> interface, so there should be no need for this, but this section is here as a "just in case".
180198
181199
## Simple Abstractions
200+
182201
There may be cases where you intend for your abstraction to be "decomposable" by cadets. The `Sound` type is just a wrapper around a `js-slang` pair:
202+
183203
```ts
184204
type Wave = (t: number) => number
185205
type Sound = Pair<Wave, number>
186206
```
207+
187208
For both of these types, the default `toString` behaviour closely follows their definitions:
209+
188210
```ts
189211
const s = make_sound(t => 0, 1000);
190212
display(s);
191213
// Produces the output below
192214
// [t => t >= duration ? 0 : wave(t), 100]
193215
```
216+
194217
Calling `display` on a `Sound` prints out a pair consisting of a function and a number. In this case, then, it becomes unnecessary to apply abstractions and implement the `ReplResult` interface.
195218

196219
## Avoid using raw object literals
220+
197221
Object literals are not supported in Source, but might be required in bundle code. For example, in the case where your bundle might have several configurable options that the cadet can change,
198222
you should have a function for each option rather than a single function that takes all the options:
223+
199224
```ts
200225
// Do this!
201226
export function change_text_color(color: string): void;
@@ -210,6 +235,7 @@ export function change_text_options(options: TextOptions): void
210235
```
211236

212237
Alternatively, you could do something like this:
238+
213239
```ts
214240
interface TextOptions {
215241
color: string
@@ -222,4 +248,5 @@ export function change_text_options(options: TextOptions): void
222248
const options = create_text_options('blue', 20);
223249
change_text_options(options);
224250
```
251+
225252
The idea is that the abstraction of the `TextOptions` type is never broken and that the cadet never interacts with the object directly.

0 commit comments

Comments
 (0)