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.
Files changed (2) hide show
  1. package/README.md +73 -122
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,24 +1,20 @@
1
1
  # open-board-format
2
2
 
3
- A type-safe toolkit to parse, validate, and create Open Board Format (OBF/OBZ) files for Augmentative and Alternative Communication (AAC) applications.
4
-
5
- ## What is Open Board Format?
3
+ [![npm version](https://img.shields.io/npm/v/open-board-format)](https://www.npmjs.com/package/open-board-format)
4
+ [![license](https://img.shields.io/npm/l/open-board-format)](LICENSE)
6
5
 
7
- [Open Board Format](https://www.openboardformat.org/) is an open standard for representing AAC communication boards grids of labeled buttons that a person taps to communicate. It defines two file types:
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
- - **OBF** (`.obf`) A JSON file describing a single communication board: its buttons, images, sounds, grid layout, and metadata.
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
- The format enables users and practitioners to **move boards between AAC apps** without starting from scratch a common pain point in the AAC community.
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** OBF boards from JSON strings, objects, or `File` handles
17
- - **Create & extract** OBZ packages (ZIP archives with boards, images, and sounds)
18
- - **[Zod](https://zod.dev/) schemas** for every OBF type use them for runtime validation, form building, or API contracts
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
- // Serialize back to a formatted JSON string
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 }: ParsedOBZ = await loadOBZ(file);
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 by ID
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
- // Optional: include image/sound resources
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
- // Safe parsing (returns { success, data, error })
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 reference
130
-
131
- ### OBF functions
132
-
133
- | Signature | Description |
134
- | ---------------------------------------- | -------------------------------------------------------------- |
135
- | `parseOBF(json: string): OBFBoard` | Parse a JSON string into a validated board. Handles UTF-8 BOM. |
136
- | `validateOBF(data: unknown): OBFBoard` | Validate an unknown value against the board schema. |
137
- | `stringifyOBF(board: OBFBoard): string` | Serialize a board to a formatted JSON string. |
138
- | `loadOBF(file: File): Promise<OBFBoard>` | Read and parse a board from a `File` object. |
139
-
140
- ### OBZ functions
141
-
142
- | Signature | Description |
143
- | -------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- |
144
- | `extractOBZ(buffer: ArrayBuffer): Promise<ParsedOBZ>` | Extract boards and files from an OBZ archive buffer. |
145
- | `loadOBZ(file: File): Promise<ParsedOBZ>` | Read and extract an OBZ package from a `File` object. |
146
- | `createOBZ(boards: OBFBoard[], rootBoardId: string, resources?: Map<string, Uint8Array>): Promise<Blob>` | Create an OBZ archive from boards and optional resources. |
147
- | `parseManifest(json: string): OBFManifest` | Parse and validate a `manifest.json` string. |
148
-
149
- ### ZIP utilities
150
-
151
- | Signature | Description |
152
- | -------------------------------------------------------------- | ------------------------------------------------------- |
153
- | `zip(files): Promise<Uint8Array>` | Create a ZIP archive from a map of paths to content. |
154
- | `unzip(buffer: ArrayBuffer): Promise<Map<string, Uint8Array>>` | Extract files from a ZIP archive. |
155
- | `isZip(buffer: ArrayBuffer): boolean` | Check whether a buffer starts with the ZIP magic bytes. |
156
-
157
- ### Schemas & types
158
-
159
- <details>
160
- <summary><strong>All exported schemas & types</strong></summary>
161
-
162
- | Schema | Type | Description |
163
- | --------------------------- | --------------------- | ----------------------------------------------- |
164
- | `OBFBoardSchema` | `OBFBoard` | Root board object |
165
- | `OBFButtonSchema` | `OBFButton` | Button with label, action, colors, positioning |
166
- | `OBFGridSchema` | `OBFGrid` | Grid layout (rows, columns, order) |
167
- | `OBFImageSchema` | `OBFImage` | Image resource with dimensions and symbol info |
168
- | `OBFSoundSchema` | `OBFSound` | Sound resource |
169
- | `OBFMediaSchema` | `OBFMedia` | Common media base (shared by images & sounds) |
170
- | `OBFLicenseSchema` | `OBFLicense` | Licensing and attribution |
171
- | `OBFManifestSchema` | `OBFManifest` | OBZ manifest (`manifest.json`) |
172
- | `OBFLoadBoardSchema` | `OBFLoadBoard` | Reference to another board |
173
- | `OBFButtonActionSchema` | `OBFButtonAction` | Spelling or specialty action |
174
- | `OBFSpellingActionSchema` | `OBFSpellingAction` | Spelling action (`+a`, `+oo`, ) |
175
- | `OBFSpecialtyActionSchema` | `OBFSpecialtyAction` | Specialty action (`:clear`, `:home`, …) |
176
- | `OBFIDSchema` | `OBFID` | Unique identifier (string, coerced from number) |
177
- | `OBFFormatVersionSchema` | `OBFFormatVersion` | Format version string |
178
- | `OBFLocaleCodeSchema` | `OBFLocaleCode` | BCP 47 locale code |
179
- | `OBFLocalizedStringsSchema` | `OBFLocalizedStrings` | Key-value string translations |
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.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",