open-board-format 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +73 -122
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,24 +1,20 @@
|
|
|
1
1
|
# open-board-format
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
## What is Open Board Format?
|
|
3
|
+
[](https://www.npmjs.com/package/open-board-format)
|
|
4
|
+
[](LICENSE)
|
|
6
5
|
|
|
7
|
-
|
|
6
|
+
A type-safe toolkit to parse, validate, and create Open Board Format (OBF/OBZ) files for Augmentative and Alternative Communication (AAC) applications.
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
- **OBZ** (`.obz`) — A ZIP archive containing one or more `.obf` boards along with their images, sounds, and a `manifest.json` that ties everything together.
|
|
8
|
+
[Open Board Format](https://www.openboardformat.org/) is an open standard for representing AAC communication boards. It defines two file types:
|
|
11
9
|
|
|
12
|
-
|
|
10
|
+
- **OBF** (`.obf`) — A JSON file describing a single communication board (buttons, images, sounds, grid layout, metadata).
|
|
11
|
+
- **OBZ** (`.obz`) — A ZIP archive containing one or more `.obf` boards along with their associated media and a `manifest.json`.
|
|
13
12
|
|
|
14
13
|
## Features
|
|
15
14
|
|
|
16
|
-
- **Parse & validate
|
|
17
|
-
- **Create & extract
|
|
18
|
-
- **[Zod](https://zod.dev/)
|
|
19
|
-
- **Full TypeScript types** inferred from schemas — no separate type maintenance
|
|
20
|
-
- **Spec-compliant coercion** — numeric IDs are coerced to strings, empty strings become `undefined`, and UTF-8 BOM is handled automatically
|
|
21
|
-
- **Tree-shakeable** ESM build with no side effects (`"sideEffects": false` in `package.json`)
|
|
15
|
+
- **Parse & Validate:** Parse and validate OBF boards from JSON strings, objects, or `File` handles.
|
|
16
|
+
- **Create & Extract:** Serialize boards to JSON, and create or extract OBZ packages (ZIP archives with boards, images, and sounds).
|
|
17
|
+
- **Zod Schemas:** Every OBF type has a corresponding [Zod](https://zod.dev/) schema for runtime validation or API contracts, with full TypeScript types inferred directly.
|
|
22
18
|
|
|
23
19
|
## Install
|
|
24
20
|
|
|
@@ -26,75 +22,46 @@ The format enables users and practitioners to **move boards between AAC apps** w
|
|
|
26
22
|
npm install open-board-format
|
|
27
23
|
```
|
|
28
24
|
|
|
29
|
-
> Zero peer dependencies. Powered by [zod](https://zod.dev/) for validation and [fflate](https://github.com/101arrowz/fflate) for ZIP — both listed as standard `dependencies` in `package.json`, so your bundler deduplicates them normally.
|
|
30
|
-
|
|
31
25
|
## Quick start
|
|
32
26
|
|
|
33
|
-
All examples below assume the following imports:
|
|
34
|
-
|
|
35
|
-
```ts
|
|
36
|
-
import {
|
|
37
|
-
parseOBF,
|
|
38
|
-
validateOBF,
|
|
39
|
-
stringifyOBF,
|
|
40
|
-
loadOBF,
|
|
41
|
-
extractOBZ,
|
|
42
|
-
loadOBZ,
|
|
43
|
-
createOBZ,
|
|
44
|
-
OBFBoardSchema,
|
|
45
|
-
} from "open-board-format";
|
|
46
|
-
import type { OBFBoard, ParsedOBZ } from "open-board-format";
|
|
47
|
-
```
|
|
48
|
-
|
|
49
27
|
### Parse a single board (OBF)
|
|
50
28
|
|
|
51
29
|
```ts
|
|
30
|
+
import { parseOBF, validateOBF, loadOBF } from "open-board-format";
|
|
31
|
+
|
|
52
32
|
// Parse from a JSON string
|
|
53
33
|
const board = parseOBF(jsonString);
|
|
54
|
-
|
|
55
34
|
console.log(board.name); // "My Board"
|
|
56
|
-
console.log(board.buttons[0]); // { id: "1", label: "hello", image_id: "img1" }
|
|
57
35
|
|
|
58
36
|
// Validate an unknown object (throws on failure)
|
|
59
37
|
const validated = validateOBF(untrustedData);
|
|
60
38
|
|
|
61
|
-
//
|
|
62
|
-
const json = stringifyOBF(board);
|
|
63
|
-
|
|
64
|
-
// Load from a File object (e.g. browser file-input)
|
|
39
|
+
// Load from a browser File object
|
|
65
40
|
const fromFile = await loadOBF(file);
|
|
66
41
|
```
|
|
67
42
|
|
|
68
43
|
### Extract an OBZ package
|
|
69
44
|
|
|
70
45
|
```ts
|
|
46
|
+
import { loadOBZ, extractOBZ } from "open-board-format";
|
|
47
|
+
|
|
71
48
|
// From a File (e.g. drag-and-drop)
|
|
72
|
-
const { manifest, boards, files }
|
|
49
|
+
const { manifest, boards, files } = await loadOBZ(file);
|
|
73
50
|
|
|
74
51
|
// Or from an ArrayBuffer (e.g. fetch response)
|
|
75
52
|
const parsed = await extractOBZ(buffer);
|
|
76
53
|
|
|
77
|
-
// Access boards
|
|
78
|
-
const rootPath = parsed.manifest.root; // "boards/1.obf"
|
|
54
|
+
// Access boards and raw files
|
|
79
55
|
const homeBoard = parsed.boards.get("1");
|
|
80
|
-
|
|
81
|
-
// Access raw files (images, sounds, etc.)
|
|
82
56
|
const imageBytes = parsed.files.get("images/logo.png");
|
|
83
57
|
```
|
|
84
58
|
|
|
85
|
-
`ParsedOBZ` has the following shape:
|
|
86
|
-
|
|
87
|
-
```ts
|
|
88
|
-
interface ParsedOBZ {
|
|
89
|
-
manifest: OBFManifest; // Validated manifest.json
|
|
90
|
-
boards: Map<string, OBFBoard>; // Board ID → parsed board
|
|
91
|
-
files: Map<string, Uint8Array>; // File path → raw bytes
|
|
92
|
-
}
|
|
93
|
-
```
|
|
94
|
-
|
|
95
59
|
### Create an OBZ package
|
|
96
60
|
|
|
97
61
|
```ts
|
|
62
|
+
import { createOBZ } from "open-board-format";
|
|
63
|
+
import type { OBFBoard } from "open-board-format";
|
|
64
|
+
|
|
98
65
|
const boards: OBFBoard[] = [
|
|
99
66
|
{
|
|
100
67
|
format: "open-board-0.1",
|
|
@@ -104,19 +71,16 @@ const boards: OBFBoard[] = [
|
|
|
104
71
|
},
|
|
105
72
|
];
|
|
106
73
|
|
|
107
|
-
|
|
74
|
+
const pngBytes = new Uint8Array(/* ... */);
|
|
108
75
|
const resources = new Map([["images/logo.png", pngBytes]]);
|
|
109
|
-
|
|
110
76
|
const blob = await createOBZ(boards, "board-1", resources);
|
|
111
|
-
// blob is a Blob you can download, upload, or store
|
|
112
77
|
```
|
|
113
78
|
|
|
114
79
|
### Use Zod schemas directly
|
|
115
80
|
|
|
116
|
-
Every OBF type is exported as both a **Zod schema** (for runtime validation) and a **TypeScript type** (for static analysis):
|
|
117
|
-
|
|
118
81
|
```ts
|
|
119
|
-
|
|
82
|
+
import { OBFBoardSchema } from "open-board-format";
|
|
83
|
+
|
|
120
84
|
const result = OBFBoardSchema.safeParse(data);
|
|
121
85
|
|
|
122
86
|
if (result.success) {
|
|
@@ -126,70 +90,57 @@ if (result.success) {
|
|
|
126
90
|
}
|
|
127
91
|
```
|
|
128
92
|
|
|
129
|
-
## API
|
|
130
|
-
|
|
131
|
-
### OBF
|
|
132
|
-
|
|
133
|
-
|
|
|
134
|
-
|
|
|
135
|
-
| `parseOBF(json
|
|
136
|
-
| `validateOBF(data
|
|
137
|
-
| `stringifyOBF(board
|
|
138
|
-
| `loadOBF(file
|
|
139
|
-
|
|
140
|
-
### OBZ
|
|
141
|
-
|
|
142
|
-
|
|
|
143
|
-
|
|
|
144
|
-
| `
|
|
145
|
-
| `
|
|
146
|
-
| `createOBZ(boards
|
|
147
|
-
| `parseManifest(json
|
|
148
|
-
|
|
149
|
-
###
|
|
150
|
-
|
|
151
|
-
|
|
|
152
|
-
|
|
|
153
|
-
| `
|
|
154
|
-
| `
|
|
155
|
-
| `
|
|
156
|
-
|
|
157
|
-
###
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
|
163
|
-
|
|
|
164
|
-
| `
|
|
165
|
-
| `
|
|
166
|
-
| `
|
|
167
|
-
| `
|
|
168
|
-
| `
|
|
169
|
-
| `
|
|
170
|
-
| `
|
|
171
|
-
| `
|
|
172
|
-
| `
|
|
173
|
-
| `
|
|
174
|
-
| `
|
|
175
|
-
| `
|
|
176
|
-
| `
|
|
177
|
-
| `
|
|
178
|
-
| `
|
|
179
|
-
| `
|
|
180
|
-
| `OBFStringsSchema` | `OBFStrings` | Multi-locale string map |
|
|
181
|
-
| `OBFSymbolInfoSchema` | `OBFSymbolInfo` | Proprietary symbol set reference |
|
|
182
|
-
|
|
183
|
-
</details>
|
|
184
|
-
|
|
185
|
-
## Spec notes
|
|
186
|
-
|
|
187
|
-
This library targets the **`open-board-0.1`** format version. Key behaviors:
|
|
188
|
-
|
|
189
|
-
- **ID coercion** — Numeric IDs (common in real-world files) are automatically coerced to strings, per the spec's parsing guidelines.
|
|
190
|
-
- **Media resolution order** — When an image or sound has multiple references, resolve in order: `data` → `path` → `url` → `symbol`.
|
|
191
|
-
- **Grid validation** — The `order` array must have exactly `rows` sub-arrays, each with exactly `columns` entries.
|
|
192
|
-
- **Extensions** — Properties prefixed with `ext_` are passed through. The schemas rely on Zod's default object parsing behavior, which preserves unrecognized keys — so custom `ext_` fields survive parsing and serialization without throwing validation errors.
|
|
93
|
+
## API
|
|
94
|
+
|
|
95
|
+
### OBF (single board)
|
|
96
|
+
|
|
97
|
+
| Function | Description |
|
|
98
|
+
| --------------------- | ------------------------------------------------------------ |
|
|
99
|
+
| `parseOBF(json)` | Parse a JSON string into a validated `OBFBoard` |
|
|
100
|
+
| `validateOBF(data)` | Validate an unknown object as `OBFBoard` (throws on failure) |
|
|
101
|
+
| `stringifyOBF(board)` | Serialize an `OBFBoard` to a JSON string |
|
|
102
|
+
| `loadOBF(file)` | Load an `OBFBoard` from a browser `File` |
|
|
103
|
+
|
|
104
|
+
### OBZ (board package)
|
|
105
|
+
|
|
106
|
+
| Function | Description |
|
|
107
|
+
| --------------------------------------- | ------------------------------------------------------------- |
|
|
108
|
+
| `loadOBZ(file)` | Load an OBZ package from a browser `File` |
|
|
109
|
+
| `extractOBZ(buffer)` | Extract boards, manifest, and files from an `ArrayBuffer` |
|
|
110
|
+
| `createOBZ(boards, rootId, resources?)` | Create an OBZ package as a `Blob` |
|
|
111
|
+
| `parseManifest(json)` | Parse a `manifest.json` string into a validated `OBFManifest` |
|
|
112
|
+
|
|
113
|
+
### Utilities
|
|
114
|
+
|
|
115
|
+
| Function | Description |
|
|
116
|
+
| --------------- | -------------------------------------------------------- |
|
|
117
|
+
| `isZip(buffer)` | Check if an `ArrayBuffer` starts with a ZIP magic number |
|
|
118
|
+
| `zip(files)` | Create a ZIP from a map of paths to buffers |
|
|
119
|
+
| `unzip(buffer)` | Extract a ZIP into a map of paths to `Uint8Array` |
|
|
120
|
+
|
|
121
|
+
### Types
|
|
122
|
+
|
|
123
|
+
| Type | Description |
|
|
124
|
+
| --------------------- | ----------------------------------------------------------------------- |
|
|
125
|
+
| `OBFBoard` | A single communication board |
|
|
126
|
+
| `OBFGrid` | Grid layout (rows, columns, order) |
|
|
127
|
+
| `OBFButton` | A button on the board |
|
|
128
|
+
| `OBFButtonAction` | Button action (spelling or specialty) |
|
|
129
|
+
| `OBFSpellingAction` | Spelling action (e.g., `+s`) |
|
|
130
|
+
| `OBFSpecialtyAction` | Specialty action (e.g., `:clear`) |
|
|
131
|
+
| `OBFLoadBoard` | Reference to load another board |
|
|
132
|
+
| `OBFMedia` | Common media properties (base for `OBFImage` and `OBFSound`) |
|
|
133
|
+
| `OBFImage` | An image resource (extends `OBFMedia`) |
|
|
134
|
+
| `OBFSound` | A sound resource (extends `OBFMedia`) |
|
|
135
|
+
| `OBFSymbolInfo` | Symbol set reference |
|
|
136
|
+
| `OBFManifest` | OBZ package manifest |
|
|
137
|
+
| `ParsedOBZ` | Return type of `extractOBZ` / `loadOBZ` — `{ manifest, boards, files }` |
|
|
138
|
+
| `OBFID` | Unique identifier (string, coerced from number) |
|
|
139
|
+
| `OBFFormatVersion` | Format version string (e.g., `open-board-0.1`) |
|
|
140
|
+
| `OBFLicense` | Licensing information |
|
|
141
|
+
| `OBFLocaleCode` | BCP 47 locale code |
|
|
142
|
+
| `OBFLocalizedStrings` | Key-value string translations |
|
|
143
|
+
| `OBFStrings` | Multi-locale string translations |
|
|
193
144
|
|
|
194
145
|
## Development
|
|
195
146
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "open-board-format",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.2",
|
|
5
5
|
"description": "Parse, validate, and create Open Board Format (OBF/OBZ) files for AAC applications.",
|
|
6
6
|
"author": "Shay Cojocaru <shayc@outlook.com>",
|
|
7
7
|
"license": "MIT",
|