@shuji-bonji/experiential-manual-model
v0.1.0
Published
Data model for experiential operation manuals (screens with hotspots, screen flows, procedures, troubleshooting): TypeScript types, JSON Schema, validator and a converter from the 2021 experience_based_operation_explanation JSON. Independent of S1000D.
Maintainers
Readme
@shuji-bonji/experiential-manual-model
English | 日本語
A common data model for "experiential operation manuals", which let you learn how to operate a screen or a device by trying it out. The authoring tool and the viewer read and write data in this form; conversion to S1000D® data modules is done by a separate package (s1000d-writer-mcp). This package itself does not depend on S1000D and does not use S1000D terminology.
What is included
| Content | Location |
|---|---|
| TypeScript types (Manual / Topic / Step / Screen / Hotspot / Transition / Asset / Scope / Admonition / Term) | src/types.ts |
| JSON Schema (draft 2020-12) | schema/manual.schema.json (also readable as @shuji-bonji/experiential-manual-model/schema/manual.schema.json) |
| Validation validateManual(json) — returns shape errors, broken references and duplicate ids in errors, and unreachable screens and unused assets in warnings. It has no runtime dependencies | src/validate.ts |
| fromLegacyJson(json), which reads the JSON.json of the 2021 work experience_based_operation_explanation | src/legacy.ts |
| numberSteps(steps), which builds procedure numbers (1, 1.1, …) | src/number.ts |
| Ticket machine example | examples/kenbaiki.manual.json |
Model
classDiagram
class Manual { id; title; version; language; scopes; topics; assets; glossary }
class Topic { id; kind; title; summary; blocks; steps; screens; startScreenRef }
class Step { id; text; targetRef; expected; admonitions; assetRefs; scopeRefs; next; question; answers; children }
class Screen { id; caption; assetRef; description; admonitions; hotspots }
class Hotspot { id; label; shape; coords; action; transition }
class Transition { to; condition; when; label }
class Asset { id; kind; source; display; alt }
class Scope { id; property; values; displayText }
Manual --> Topic
Manual --> Asset
Manual --> Scope
Topic --> Step
Topic --> Screen
Screen --> Hotspot
Hotspot --> Transition
Step --> TransitionTopic.kindhas 4 values:description(explanatory text),procedure(a procedure),screenFlow(screens and transitions) andtroubleshooting(proceeds by question and answer).Hotspot.coordsuses the same notation as the HTML<area>element (rectis[x1, y1, x2, y2],circleis[cx, cy, r],polyis[x1, y1, x2, y2, …]).Scopeis a range of applicability such as "this model" or "outdoor installation".Topic/Step/Block/Screenrefer to it throughscopeRefs.Asset.sourceis the original, andAsset.displayis the derived form used for display (for example, an original JT 3D model and a glTF for display).- Procedure numbers are not stored.
numberStepsbuilds them at display time.
Usage
import { readFileSync } from 'node:fs';
import { validateManual, fromLegacyJson, numberSteps, type Manual } from '@shuji-bonji/experiential-manual-model';
const manual = JSON.parse(readFileSync('kenbaiki.manual.json', 'utf8')) as Manual;
const result = validateManual(manual);
if (!result.ok) console.error(result.errors); // [{ path: '/topics/1/screens/0/hotspots/0/transition/to', message: '…' }]
console.log(result.warnings); // unreachable screens, unused assets and scopes
// Read the 2021 JSON.json
const { manual: converted, warnings } = fromLegacyJson(JSON.parse(readFileSync('JSON.json', 'utf8')));
// Procedure numbers
for (const { number, step } of numberSteps(manual.topics[2].steps!)) console.log(number, step.text);Mapping from the 2021 JSON
| 2021 JSON.json | This model |
|---|---|
| purchaseTypes[] (displayAreas[] in its README) | Topic (kind: "screenFlow") |
| titleID / title / description | Topic.id / title / summary |
| screenID (or screenId) / caption / description / imageUrl in screens[] | Screen.id (made unique by prefixing the topic id) / caption / description / assetRef |
| supplementaryExplanation | Screen.admonitions[{ level: "note" }] |
| name / shape / coords / destination (or screenTransitionDestination) in buttons[] | Hotspot.label / shape / coords / transition.to |
There are 2 buttons whose rect coords carry a fifth value. fromLegacyJson drops it and records it in warnings.
Development
npm install
npm test # validation, conversion, JSON Schema (ajv is a dev-only dependency)
npm run buildLicense
MIT
