@psrt/sdk 0.1.0 → 0.1.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # @psrt/sdk
2
2
 
3
- Stateless PSRT SDK powered by WebAssembly (Go core).
3
+ TypeScript library for parsing, editing, and compiling PSRT documents.
4
4
 
5
5
  ## Install
6
6
 
@@ -10,28 +10,67 @@ npm install @psrt/sdk
10
10
 
11
11
  ## Usage
12
12
 
13
+ Call `initPsrt()` once at startup, then use the API:
14
+
13
15
  ```typescript
14
- import { initPsrt, parse, compileToHtml, adaptEntriesForWeb } from '@psrt/sdk'
16
+ import { readFileSync } from 'node:fs'
17
+ import { initPsrt, parse, compileToHtml, compileToSvg } from '@psrt/sdk'
15
18
 
16
- await initPsrt('/path/to/psrt.wasm')
19
+ await initPsrt()
17
20
 
21
+ const psrtString = readFileSync('document.psrt', 'utf8')
18
22
  const doc = parse(psrtString)
23
+
19
24
  const html = compileToHtml(doc)
20
- const styles = adaptEntriesForWeb(JSON.stringify(entries), 800, 600, 1)
25
+ const svg = compileToSvg(doc, doc.pages[0]!.name)
21
26
  ```
22
27
 
23
- ## Browser (Vite)
28
+ `initPsrt()` is idempotent — safe to call more than once, but one call at app entry is enough.
24
29
 
25
- Copy `wasm/psrt.wasm` and `wasm/wasm_exec.js` to your `public/` folder, then:
30
+ ## Editor (fluent API)
26
31
 
27
32
  ```typescript
28
- await initPsrt(`${import.meta.env.BASE_URL}wasm/psrt.wasm`)
33
+ import { initPsrt, parse, stringify, transform } from '@psrt/sdk'
34
+
35
+ await initPsrt()
36
+
37
+ const doc = parse(psrtString)
38
+ const pageName = doc.pages[0]!.name
39
+
40
+ const updated = transform(doc)
41
+ .addText(pageName, {
42
+ x: 10,
43
+ y: 20,
44
+ width: 100,
45
+ textSize: 2,
46
+ index: 1,
47
+ content: 'Hello',
48
+ style: {},
49
+ })
50
+ .build()
51
+
52
+ const out = stringify(updated)
53
+ ```
54
+
55
+ ## Live preview styles
56
+
57
+ ```typescript
58
+ import { initPsrt, adaptEntriesForWeb } from '@psrt/sdk'
59
+
60
+ await initPsrt()
61
+
62
+ const styles = adaptEntriesForWeb(entriesJSON, canvasWidth, canvasHeight, zoom)
29
63
  ```
30
64
 
31
65
  ## Exports
32
66
 
33
- - **I/O:** `parse`, `stringify`, `formatDocument`, `resolveDocument`
67
+ - **Init:** `initPsrt`
68
+ - **I/O:** `parse`, `stringify`, `formatDocument`, `resolveDocument`, `resolveDocumentStrict`
34
69
  - **Compile:** `compileToHtml`, `compileToSvg`
35
- - **Preview:** `adaptEntriesForWeb`
70
+ - **Preview:** `adaptEntriesForWeb`, `formatPageDocumentJSON`, `mergePageDocumentPSRT`
36
71
  - **Editor:** `addText`, `setTextContent`, `transform`, …
37
72
  - **Types:** `PsrtDocument`, `Document`, `Page`, `TextBlock`, …
73
+
74
+ ## React
75
+
76
+ See [@psrt/react-image](../react-image/README.md). Call `initPsrt()` once in your app entry before rendering.
@@ -0,0 +1,260 @@
1
+ /** Initializes PSRT. Call once at app startup before any other SDK API. */
2
+ declare function initPsrt(): Promise<void>;
3
+
4
+ declare const CompileStep: {
5
+ readonly RESOLVE: "resolve";
6
+ readonly BUILD_ASSETS: "buildAssets";
7
+ readonly ADAPT_STYLE: "adaptStyle";
8
+ readonly RENDER_FONTS: "renderFonts";
9
+ readonly RENDER_HEAD: "renderHead";
10
+ readonly RENDER_PAGE: "renderPage";
11
+ readonly RENDER_TEXT: "renderText";
12
+ readonly RENDER_MASK: "renderMask";
13
+ readonly RENDER_INLINE: "renderInline";
14
+ readonly FINALIZE: "finalize";
15
+ };
16
+ type CompileStep = (typeof CompileStep)[keyof typeof CompileStep];
17
+ type CompileStepContext = {
18
+ step: typeof CompileStep.RESOLVE;
19
+ doc: PsrtDocument;
20
+ } | {
21
+ step: typeof CompileStep.BUILD_ASSETS;
22
+ assetCount: number;
23
+ canvasSizes: Record<string, {
24
+ w: number;
25
+ h: number;
26
+ }>;
27
+ } | {
28
+ step: typeof CompileStep.ADAPT_STYLE;
29
+ pageName: string;
30
+ blockIndex: number;
31
+ kind: 'text' | 'mask';
32
+ } | {
33
+ step: typeof CompileStep.RENDER_FONTS;
34
+ fontCount: number;
35
+ } | {
36
+ step: typeof CompileStep.RENDER_HEAD;
37
+ title: string;
38
+ } | {
39
+ step: typeof CompileStep.RENDER_PAGE;
40
+ pageIndex: number;
41
+ pageName: string;
42
+ canvasW: number;
43
+ canvasH: number;
44
+ } | {
45
+ step: typeof CompileStep.RENDER_TEXT;
46
+ pageName: string;
47
+ textIndex: number;
48
+ contentPreview: string;
49
+ } | {
50
+ step: typeof CompileStep.RENDER_MASK;
51
+ pageName: string;
52
+ maskIndex: number;
53
+ } | {
54
+ step: typeof CompileStep.RENDER_INLINE;
55
+ pageName: string;
56
+ textIndex: number;
57
+ htmlLength: number;
58
+ } | {
59
+ step: typeof CompileStep.FINALIZE;
60
+ htmlLength: number;
61
+ pageCount: number;
62
+ };
63
+ type CompileStepObserver = (ctx: CompileStepContext) => void;
64
+ type CompileStepObservers = Partial<Record<CompileStep, CompileStepObserver[]>>;
65
+ declare function notifyObservers(observers: CompileStepObservers | undefined, ctx: CompileStepContext): void;
66
+
67
+ /** JSON object or compact style string from PSRT. */
68
+ type PsrtStyle = Record<string, unknown> | string;
69
+ /** Canonical PSRT document representation. */
70
+ interface PsrtDocument {
71
+ pages: PsrtPage[];
72
+ fonts: string[];
73
+ consts: Record<string, string>;
74
+ }
75
+ type Document = PsrtDocument;
76
+ interface PsrtPage {
77
+ name: string;
78
+ style: PsrtStyle;
79
+ imageUrl: string;
80
+ texts: PsrtText[];
81
+ masks?: PsrtMask[];
82
+ }
83
+ type Page = PsrtPage;
84
+ interface PsrtText {
85
+ x: number;
86
+ y: number;
87
+ width: number;
88
+ textSize: number;
89
+ style: PsrtStyle;
90
+ index: number;
91
+ content: string;
92
+ imageRef?: string;
93
+ }
94
+ /** PSRT text block (>> header), not editor UI model. */
95
+ type TextBlock = PsrtText;
96
+ interface PsrtMask {
97
+ x: number;
98
+ y: number;
99
+ width: number;
100
+ height: number;
101
+ style: PsrtStyle;
102
+ index: number;
103
+ imageRef?: string;
104
+ }
105
+ interface PositionFields {
106
+ x?: number;
107
+ y?: number;
108
+ width?: number;
109
+ textSize?: number;
110
+ }
111
+ interface MaskPositionFields {
112
+ x?: number;
113
+ y?: number;
114
+ width?: number;
115
+ height?: number;
116
+ }
117
+ interface CompileOptions {
118
+ /** Keep original asset URLs instead of embedding data URIs. */
119
+ linksOnly?: boolean;
120
+ /** Omit the HTML variant switcher script (Ctrl+L). */
121
+ noScript?: boolean;
122
+ }
123
+ interface CompileToHtmlPureOptions extends CompileOptions {
124
+ observers?: CompileStepObservers;
125
+ /** Additional PSRT variants bundled into the same HTML (Ctrl+L to switch). */
126
+ variants?: PsrtVariant[];
127
+ }
128
+ /** One PSRT document bundled as an HTML variant alongside the primary doc. */
129
+ interface PsrtVariant {
130
+ /** Label shown in the variant switcher hint (defaults to variant-N). */
131
+ label?: string;
132
+ doc: PsrtDocument;
133
+ }
134
+
135
+ /** Converts a .psrt string into a typed PsrtDocument. */
136
+ declare function parse(psrtString: string): PsrtDocument;
137
+ /** Converts a PsrtDocument back to normative .psrt text. */
138
+ declare function stringify(doc: PsrtDocument): string;
139
+ /** Formats a document with editor cleanup rules. */
140
+ declare function formatDocument(doc: PsrtDocument): string;
141
+
142
+ /** Expands all @const@ placeholders in styles, content, and URLs. */
143
+ declare function resolveDocumentPure(doc: PsrtDocument): PsrtDocument;
144
+
145
+ /** Compiles the document to a self-contained HTML string (WASM). */
146
+ declare function compileToHtml(doc: PsrtDocument | string, options?: CompileOptions): string;
147
+ /** Compiles PsrtDocument to HTML using pure JavaScript (no WASM, no initPsrt). */
148
+ declare function compileToHtmlPure(doc: PsrtDocument, options?: CompileToHtmlPureOptions): string;
149
+
150
+ /** Compiles one page of the document to SVG. */
151
+ declare function compileToSvg(doc: PsrtDocument | string, pageName: string, options?: CompileOptions): string;
152
+
153
+ /** Fluent builder for chained PSRT document edits. */
154
+ declare class Transformer {
155
+ private _doc;
156
+ constructor(input: PsrtDocument | string);
157
+ /** Read-only view of the current document state. */
158
+ get document(): Readonly<PsrtDocument>;
159
+ addConst(name: string, value: string): this;
160
+ removeConst(name: string): this;
161
+ substituteConstReferences(name: string, value: string): this;
162
+ revertConstReferences(name: string, value: string): this;
163
+ addFont(url: string): this;
164
+ removeFont(url: string): this;
165
+ renamePage(oldName: string, newName: string): this;
166
+ setPagePath(pageName: string, path: string): this;
167
+ setPageStyle(pageName: string, key: string, value: string, partial?: PsrtStyle): this;
168
+ removePageStyleKey(pageName: string, key: string): this;
169
+ movePage(pageName: string, before?: string, after?: string): this;
170
+ addPage(page: PsrtPage, before?: string, after?: string): this;
171
+ removePage(name: string): this;
172
+ setTextStyle(pageName: string, textIndex: number, key: string, value: string, partial?: PsrtStyle): this;
173
+ removeTextStyleKey(pageName: string, textIndex: number, key: string): this;
174
+ setTextContent(pageName: string, index: number, content: string, appendContent?: boolean): this;
175
+ addText(pageName: string, text: PsrtText, opts?: {
176
+ beforeIndex?: number;
177
+ afterIndex?: number;
178
+ }): this;
179
+ removeText(pageName: string, textIndex: number): this;
180
+ reorderTextRelative(pageName: string, textIndex: number, beforeIndex?: number, afterIndex?: number): this;
181
+ reorderTextTo(pageName: string, textIndex: number, to: number): this;
182
+ reorderTextByDelta(pageName: string, textIndex: number, delta: number): this;
183
+ setTextPosition(pageName: string, textIndex: number, pos: PositionFields): this;
184
+ nudgeTextPosition(pageName: string, textIndex: number, delta: PositionFields): this;
185
+ setMaskPosition(pageName: string, maskIndex: number, pos: MaskPositionFields): this;
186
+ addMask(pageName: string, mask: PsrtMask, opts?: {
187
+ beforeIndex?: number;
188
+ afterIndex?: number;
189
+ }): this;
190
+ removeMask(pageName: string, maskIndex: number): this;
191
+ setMaskStyle(pageName: string, maskIndex: number, key: string, value: string, partial?: PsrtStyle): this;
192
+ removeMaskStyleKey(pageName: string, maskIndex: number, key: string): this;
193
+ /** Returns the accumulated document after the edit chain. */
194
+ build(): PsrtDocument;
195
+ /** Shortcut: build() + stringify(). */
196
+ buildPsrt(): string;
197
+ }
198
+ declare function transform(input: PsrtDocument | string): Transformer;
199
+
200
+ interface WebPreviewStyle {
201
+ container: Record<string, string>;
202
+ text: Record<string, string>;
203
+ hasStroke: boolean;
204
+ }
205
+ /** Adapts text/mask entries for live web preview CSS (percent → px, stroke → WebKit, etc.). */
206
+ declare function adaptEntriesForWeb(entriesJSON: string, canvasW: number, canvasH: number, zoom: number): WebPreviewStyle[];
207
+ /** Applies a page PSRT fragment into a full document. */
208
+ declare function mergePageDocumentPSRT(fullDocJSON: string, pageName: string, psrtText: string): PsrtDocument;
209
+ /** Formats one page plus document fonts and constants as PSRT text. */
210
+ declare function formatPageDocumentJSON(docJSON: string, pageName: string): string;
211
+
212
+ declare function addConst(doc: PsrtDocument, name: string, value: string): PsrtDocument;
213
+ declare function removeConst(doc: PsrtDocument, name: string): PsrtDocument;
214
+ declare function substituteConstReferences(doc: PsrtDocument, name: string, value: string): PsrtDocument;
215
+ declare function revertConstReferences(doc: PsrtDocument, name: string, value: string): PsrtDocument;
216
+
217
+ declare function addFont(doc: PsrtDocument, url: string): PsrtDocument;
218
+ declare function removeFont(doc: PsrtDocument, url: string): PsrtDocument;
219
+
220
+ declare function renamePage(doc: PsrtDocument, oldName: string, newName: string): PsrtDocument;
221
+ declare function setPagePath(doc: PsrtDocument, pageName: string, path: string): PsrtDocument;
222
+ declare function setPageStyle(doc: PsrtDocument, pageName: string, key: string, value: string, partial?: PsrtStyle): PsrtDocument;
223
+ declare function removePageStyleKey(doc: PsrtDocument, pageName: string, key: string): PsrtDocument;
224
+ declare function movePage(doc: PsrtDocument, pageName: string, before?: string, after?: string): PsrtDocument;
225
+ declare function addPage(doc: PsrtDocument, page: PsrtPage, before?: string, after?: string): PsrtDocument;
226
+ declare function removePage(doc: PsrtDocument, name: string): PsrtDocument;
227
+
228
+ declare function setTextStyle(doc: PsrtDocument, pageName: string, textIndex: number, key: string, value: string, partial?: PsrtStyle): PsrtDocument;
229
+ declare function removeTextStyleKey(doc: PsrtDocument, pageName: string, textIndex: number, key: string): PsrtDocument;
230
+ declare function setTextContent(doc: PsrtDocument, pageName: string, index: number, newContent: string, appendContent?: boolean): PsrtDocument;
231
+ declare function addText(doc: PsrtDocument, pageName: string, text: PsrtText, beforeIndex?: number, afterIndex?: number): PsrtDocument;
232
+ declare function removeText(doc: PsrtDocument, pageName: string, textIndex: number): PsrtDocument;
233
+ declare function reorderTextRelative(doc: PsrtDocument, pageName: string, textIndex: number, beforeIndex?: number, afterIndex?: number): PsrtDocument;
234
+ declare function reorderTextTo(doc: PsrtDocument, pageName: string, textIndex: number, to: number): PsrtDocument;
235
+ declare function reorderTextByDelta(doc: PsrtDocument, pageName: string, textIndex: number, delta: number): PsrtDocument;
236
+ declare function setTextPosition(doc: PsrtDocument, pageName: string, textIndex: number, pos: PositionFields): PsrtDocument;
237
+ declare function nudgeTextPosition(doc: PsrtDocument, pageName: string, textIndex: number, delta: PositionFields): PsrtDocument;
238
+
239
+ declare function setMaskPosition(doc: PsrtDocument, pageName: string, maskIndex: number, pos: MaskPositionFields): PsrtDocument;
240
+ declare function addMask(doc: PsrtDocument, pageName: string, mask: PsrtMask, beforeIndex?: number, afterIndex?: number): PsrtDocument;
241
+ declare function removeMask(doc: PsrtDocument, pageName: string, maskIndex: number): PsrtDocument;
242
+ declare function setMaskStyle(doc: PsrtDocument, pageName: string, maskIndex: number, key: string, value: string, partial?: PsrtStyle): PsrtDocument;
243
+ declare function removeMaskStyleKey(doc: PsrtDocument, pageName: string, maskIndex: number, key: string): PsrtDocument;
244
+
245
+ declare function setStyleKey(style: PsrtStyle, key: string, value: string): PsrtStyle;
246
+ declare function removeStyleKey(style: PsrtStyle, key: string): PsrtStyle;
247
+ declare function mergeStyle(style: PsrtStyle, partial: PsrtStyle): PsrtStyle;
248
+
249
+ declare function findPage(doc: PsrtDocument, name: string): PsrtPage;
250
+ declare function findPageIndex(doc: PsrtDocument, name: string): number;
251
+ declare function findTextByIndex(doc: PsrtDocument, pageName: string, index: number): PsrtText;
252
+ declare function findMaskByIndex(doc: PsrtDocument, pageName: string, index: number): PsrtMask;
253
+ declare function parseTextIndex(s: string): number;
254
+
255
+ /** Expands all @const@ placeholders in styles, content, and URLs. */
256
+ declare function resolveDocument(doc: PsrtDocument): PsrtDocument;
257
+ /** Like resolveDocument but throws on invalid style JSON after expansion. */
258
+ declare function resolveDocumentStrict(doc: PsrtDocument): PsrtDocument;
259
+
260
+ export { type CompileOptions, CompileStep, type CompileStepContext, type CompileStepObserver, type CompileStepObservers, type CompileToHtmlPureOptions, type Document, type MaskPositionFields, type Page, type PositionFields, type PsrtDocument, type PsrtMask, type PsrtPage, type PsrtStyle, type PsrtText, type PsrtVariant, type TextBlock, Transformer, type WebPreviewStyle, adaptEntriesForWeb, addConst, addFont, addMask, addPage, addText, compileToHtml, compileToHtmlPure, compileToSvg, findMaskByIndex, findPage, findPageIndex, findTextByIndex, formatDocument, formatPageDocumentJSON, initPsrt, mergePageDocumentPSRT, mergeStyle, movePage, notifyObservers, nudgeTextPosition, parse, parseTextIndex, removeConst, removeFont, removeMask, removeMaskStyleKey, removePage, removePageStyleKey, removeStyleKey, removeText, removeTextStyleKey, renamePage, reorderTextByDelta, reorderTextRelative, reorderTextTo, resolveDocument, resolveDocumentPure, resolveDocumentStrict, revertConstReferences, setMaskPosition, setMaskStyle, setPagePath, setPageStyle, setStyleKey, setTextContent, setTextPosition, setTextStyle, stringify, substituteConstReferences, transform };