|
| 1 | +A few notes on coding conventions used in this project. |
| 2 | + |
| 3 | +# Tooling |
| 4 | + |
| 5 | +Run these commands to perform type and style checks and automatically reformat code based on conventions: |
| 6 | + |
| 7 | +```bash |
| 8 | +make check # Type check + lint frontend and backend |
| 9 | +make fmt # Format all code |
| 10 | +``` |
| 11 | + |
| 12 | +# Code Style Guidelines |
| 13 | + |
| 14 | +## TypeScript (client and plugs) |
| 15 | + |
| 16 | +### Import Organization |
| 17 | + |
| 18 | +```typescript |
| 19 | +// Use relative imports by default (include .ts extension) |
| 20 | +import { Space } from "./space.ts"; |
| 21 | +// Use `type` for type-only imports (part of the lint rules) |
| 22 | +import type { Command } from "./types/command.ts"; |
| 23 | + |
| 24 | +// Use package-prefixed absolute when available (defined in deno.json) |
| 25 | +import { sleep } from "@silverbulletmd/silverbullet/lib/async"; |
| 26 | +``` |
| 27 | + |
| 28 | +### TypeScript Conventions |
| 29 | +* Use `type` over `interface` for object shapes |
| 30 | +* Use `type` for unions and complex types |
| 31 | +* Always type function parameters explicitly |
| 32 | +* Type return values for public APIs |
| 33 | +* Let TypeScript infer obvious variable types |
| 34 | +* Use `any` for error objects in catch blocks |
| 35 | + |
| 36 | + |
| 37 | +### Naming Conventions |
| 38 | +- **Variables & functions:** `camelCase` |
| 39 | +- **Classes:** `PascalCase` |
| 40 | +- **Files:** `snake_case.ts` (e.g., `http_space_primitives.ts`) |
| 41 | +- **Test files:** `*.test.ts` alongside source files |
| 42 | +- **Types:** `PascalCase` (e.g., `PageMeta`, `SpacePrimitives`) |
| 43 | +- **Constants:** `camelCase` |
| 44 | + |
| 45 | + |
| 46 | +### Testing Patterns |
| 47 | +TypeScript tests run with Deno. |
| 48 | + |
| 49 | +**Test structure:** |
| 50 | +```typescript |
| 51 | +Deno.test("Test description in plain English", async () => { |
| 52 | + // Setup |
| 53 | + const kv = new MemoryKvPrimitives(); |
| 54 | + const space = new Space(new DataStoreSpacePrimitives(kv), eventHook); |
| 55 | + |
| 56 | + // Execute |
| 57 | + await space.writePage("test", testPage); |
| 58 | + |
| 59 | + // Assert |
| 60 | + assertEquals(await space.readPage("test"), testPage); |
| 61 | +}); |
| 62 | +``` |
| 63 | + |
| 64 | +**Assertions:** |
| 65 | +```typescript |
| 66 | +import { assertEquals, assertNotEquals } from "@std/assert"; |
| 67 | + |
| 68 | +assertEquals(actual, expected); |
| 69 | +assertNotEquals(actual, notExpected); |
| 70 | +``` |
| 71 | + |
| 72 | +**Test configuration:** |
| 73 | +```typescript |
| 74 | +Deno.test("Test with options", { |
| 75 | + sanitizeResources: false, |
| 76 | + sanitizeOps: false, |
| 77 | +}, async () => { |
| 78 | + // test code |
| 79 | +}); |
| 80 | +``` |
| 81 | + |
| 82 | +### Comments & Documentation |
| 83 | + |
| 84 | +Use JSDoc for public APIs: |
| 85 | +```typescript |
| 86 | +/** |
| 87 | + * Lists all pages (files ending in .md) in the space. |
| 88 | + * @param unfiltered - Whether to include filtered pages |
| 89 | + * @returns A list of all pages represented as PageMeta objects |
| 90 | + */ |
| 91 | +export function listPages(unfiltered?: boolean): Promise<PageMeta[]> { |
| 92 | + return syscall("space.listPages", unfiltered); |
| 93 | +} |
| 94 | +``` |
| 95 | + |
| 96 | +Inline comments: |
| 97 | +* In case of doubt: add comments around the _why_ of the code (not what) |
| 98 | +* Add TODO comments for known issues |
| 99 | + |
| 100 | +```typescript |
| 101 | +// Note: these events are dispatched asynchronously (not waiting for results) |
| 102 | +this.eventHook.dispatchEvent(...); |
| 103 | + |
| 104 | +// TODO: Clean this up, this has become a god class |
| 105 | +export class Client { |
| 106 | +``` |
| 107 | +
|
| 108 | +### Code Patterns |
| 109 | +
|
| 110 | +**Definite assignment for late initialization:** |
| 111 | +```typescript |
| 112 | +class Client { |
| 113 | + space!: Space; // Initialized in init() |
| 114 | + editorView!: EditorView; |
| 115 | +} |
| 116 | +``` |
| 117 | +
|
| 118 | +**Destructuring:** |
| 119 | +```typescript |
| 120 | +const { name, def } = command; |
| 121 | +const { text, meta } = await this.space.readPage(name); |
| 122 | +``` |
| 123 | +
|
| 124 | +## Go (server) |
| 125 | +Follow common Go conventions. `make fmt` also reformats Go code. |
| 126 | +
|
| 127 | +## Lua (libraries) |
| 128 | +See `website/Space Lua/Conventions` |
0 commit comments