@memizy/oqse 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.
@@ -5,3 +5,4 @@ export * from './manifestValidation';
5
5
  export * from './progress';
6
6
  export * from './progressValidation';
7
7
  export * from './utils';
8
+ export * from './richTextProcessor';
@@ -9,7 +9,8 @@ export type { FeatureProfile } from './oqse';
9
9
  * - `import` - Data ingestion: parses OQSE data into an internal system.
10
10
  * - `export` - Data generation: serializes internal data into OQSE format.
11
11
  */
12
- export type OfficialAction = 'render' | 'edit' | 'validate' | 'import' | 'export';
12
+ export declare const OFFICIAL_ACTIONS: readonly ["render", "edit", "validate", "import", "export"];
13
+ export type OfficialAction = typeof OFFICIAL_ACTIONS[number];
13
14
  /**
14
15
  * Custom action using the required `x-` prefix (e.g., `"x-preview"`, `"x-sync"`).
15
16
  * Host environments that do not recognize a custom action MUST ignore it.
@@ -47,11 +48,12 @@ export type OQSEQuestionDensity = 'low' | 'medium' | 'high';
47
48
  * `meta.requirements.features` (Study Set) to signal support/requirement.
48
49
  *
49
50
  * Dependency notes:
50
- * - `syntax-highlighting`, `mermaid`, `smiles`, `abc-notation`, `html-safe`
51
+ * - `syntax-highlighting`, `mermaid`, `smiles`, `abc-notation`, `html`
51
52
  * are only meaningful when `markdown` is also declared.
52
53
  * - `latexPackages` (in FeatureProfile) is only meaningful when `math` is declared.
53
54
  */
54
- export type OfficialFeatureKey = 'markdown' | 'html-safe' | 'math' | 'ruby-annotations' | 'rtl' | 'syntax-highlighting' | 'mermaid' | 'smiles' | 'abc-notation' | 'text-to-speech' | 'voice-input' | 'handwriting-recognition';
55
+ export declare const OFFICIAL_FEATURE_KEYS: readonly ["markdown", "math", "rtl", "html", "syntax-highlighting", "mermaid", "smiles", "abc-notation", "text-to-speech", "voice-input", "handwriting-recognition"];
56
+ export type OfficialFeatureKey = typeof OFFICIAL_FEATURE_KEYS[number];
55
57
  /**
56
58
  * A custom feature using the required `x-` prefix (e.g., `"x-memizy-3d-voxel"`).
57
59
  * MUST NOT collide with current or future official registry entries.
@@ -68,7 +70,8 @@ export type FeatureFlag = OfficialFeatureKey | CustomFeatureKey;
68
70
  * Declared in `capabilities.itemProperties` (app support) and
69
71
  * `meta.requirements.itemProperties` (set requirement).
70
72
  */
71
- export type OfficialItemProperty = 'hints' | 'explanation' | 'incorrectFeedback' | 'sources' | 'relatedItems' | 'dependencyItems' | 'timeLimit' | 'lang' | 'topic' | 'pedagogy';
73
+ export declare const OFFICIAL_ITEM_PROPERTIES: readonly ["hints", "explanation", "incorrectFeedback", "sources", "relatedItems", "dependencyItems", "timeLimit", "lang", "topic", "pedagogy"];
74
+ export type OfficialItemProperty = typeof OFFICIAL_ITEM_PROPERTIES[number];
72
75
  /**
73
76
  * A custom item property using the `x-` prefix.
74
77
  */
@@ -83,7 +86,8 @@ export type ItemPropertyKey = OfficialItemProperty | CustomItemProperty;
83
86
  * Declared in `capabilities.metaProperties` (app support) and
84
87
  * `meta.requirements.metaProperties` (set requirement).
85
88
  */
86
- export type OfficialMetaProperty = 'description' | 'thumbnail' | 'subject' | 'language' | 'author' | 'contributors' | 'license' | 'ageRestriction' | 'tags' | 'tagDefinitions' | 'sourceMaterials' | 'estimatedTime' | 'prerequisites' | 'translations' | 'relatedSets';
89
+ export declare const OFFICIAL_META_PROPERTIES: readonly ["description", "thumbnail", "subject", "language", "author", "contributors", "license", "ageRestriction", "tags", "tagDefinitions", "sourceMaterials", "estimatedTime", "prerequisites", "translations", "relatedSets"];
90
+ export type OfficialMetaProperty = typeof OFFICIAL_META_PROPERTIES[number];
87
91
  /**
88
92
  * A custom meta property using the `x-` prefix.
89
93
  */
@@ -64,10 +64,10 @@ export declare const ManifestCapabilitiesSchema: z.ZodObject<{
64
64
  }, z.core.$strip>>;
65
65
  }, z.core.$strip>;
66
66
  /**
67
- * Full OQSE Application Manifest schema (T�2.1.1).
67
+ * Full OQSE Application Manifest schema (Table 2.1.1).
68
68
  *
69
69
  * Validated constraints beyond syntax:
70
- * - `minOqseVersion` �� `maxOqseVersion` when both are present
70
+ * - `minOqseVersion` <= `maxOqseVersion` when both are present
71
71
  * - `version` adheres to MAJOR.MINOR format
72
72
  * - `capabilities.actions` is non-empty (enforced by inner schema)
73
73
  */
@@ -151,15 +151,16 @@ export declare function safeValidateManifest(data: unknown): ReturnType<typeof O
151
151
  * @example
152
152
  * ```ts
153
153
  * console.error(formatManifestErrors(result.error));
154
- * // ��� "id: ID mus+� b+�t ve tvaru reverse-domain..."
155
- * // ��� "capabilities.actions: Aplikace mus+� podporovat alespo+� jednu akci"
154
+ * // Example output:
155
+ * // "id: ID must be in reverse-domain format (e.g. \"com.acme.app\")"
156
+ * // "capabilities.actions: Application must support at least one action"
156
157
  * ```
157
158
  */
158
159
  export declare function formatManifestErrors(error: z.ZodError): string;
159
160
  /**
160
161
  * Checks whether a plain object looks like an OQSE Manifest (duck-typing).
161
162
  *
162
- * This is a fast pre-check ��� use `validateManifest` for full validation.
163
+ * This is a fast pre-check - use `validateManifest` for full validation.
163
164
  *
164
165
  * @param data - Any value.
165
166
  * @returns `true` if `data` has the minimum required shape.
@@ -203,29 +203,6 @@ export interface FeatureProfile {
203
203
  */
204
204
  metaProperties?: string[];
205
205
  }
206
- /**
207
- * Feature requirement type
208
- * @deprecated Use FeatureProfile instead for spec-compliant requirements.
209
- */
210
- export type FeatureType = 'official' | 'experimental' | 'proprietary';
211
- /**
212
- * Official feature names
213
- */
214
- export type OfficialFeatureName = 'math' | 'media-image' | 'media-audio' | 'media-video' | 'hotspots' | 'complex-pairing' | 'open-text';
215
- /**
216
- * Feature requirement object
217
- */
218
- export interface FeatureRequirement {
219
- /** Feature name */
220
- name: string;
221
- /** Feature type */
222
- type: FeatureType;
223
- /**
224
- * For proprietary features: Domain name of the provider (e.g., "memizy.com").
225
- * MUST be present for type: "proprietary", ignored for other types.
226
- */
227
- vendor?: string;
228
- }
229
206
  /**
230
207
  * Translation object defining reference to translated version of this set
231
208
  */
@@ -340,11 +317,6 @@ export interface OQSEMeta {
340
317
  * @see FeatureProfile
341
318
  */
342
319
  requirements?: FeatureProfile;
343
- /**
344
- * @deprecated Use `requirements` (FeatureProfile) instead.
345
- * This field used a non-spec-compliant structure.
346
- */
347
- requiredFeatures?: FeatureRequirement[];
348
320
  /** Array of text labels (tags) for the entire set */
349
321
  tags?: string[];
350
322
  /** Dictionary of tag definitions */
@@ -181,29 +181,6 @@ export declare const FeatureProfileSchema: z.ZodObject<{
181
181
  itemProperties: z.ZodOptional<z.ZodArray<z.ZodString>>;
182
182
  metaProperties: z.ZodOptional<z.ZodArray<z.ZodString>>;
183
183
  }, z.core.$strip>;
184
- export declare const FeatureTypeSchema: z.ZodEnum<{
185
- official: "official";
186
- experimental: "experimental";
187
- proprietary: "proprietary";
188
- }>;
189
- export declare const OfficialFeatureNameSchema: z.ZodEnum<{
190
- math: "math";
191
- "media-image": "media-image";
192
- "media-audio": "media-audio";
193
- "media-video": "media-video";
194
- hotspots: "hotspots";
195
- "complex-pairing": "complex-pairing";
196
- "open-text": "open-text";
197
- }>;
198
- export declare const FeatureRequirementSchema: z.ZodObject<{
199
- name: z.ZodString;
200
- type: z.ZodEnum<{
201
- official: "official";
202
- experimental: "experimental";
203
- proprietary: "proprietary";
204
- }>;
205
- vendor: z.ZodOptional<z.ZodString>;
206
- }, z.core.$strip>;
207
184
  export declare const TranslationObjectSchema: z.ZodObject<{
208
185
  lang: z.ZodString;
209
186
  id: z.ZodString;
@@ -322,15 +299,6 @@ export declare const OQSEMetaSchema: z.ZodObject<{
322
299
  itemProperties: z.ZodOptional<z.ZodArray<z.ZodString>>;
323
300
  metaProperties: z.ZodOptional<z.ZodArray<z.ZodString>>;
324
301
  }, z.core.$strip>>;
325
- requiredFeatures: z.ZodOptional<z.ZodArray<z.ZodObject<{
326
- name: z.ZodString;
327
- type: z.ZodEnum<{
328
- official: "official";
329
- experimental: "experimental";
330
- proprietary: "proprietary";
331
- }>;
332
- vendor: z.ZodOptional<z.ZodString>;
333
- }, z.core.$strip>>>;
334
302
  tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
335
303
  tagDefinitions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
336
304
  wikidataId: z.ZodOptional<z.ZodString>;
@@ -491,7 +459,7 @@ export declare const PolygonHotspotSchema: z.ZodObject<{
491
459
  }, z.core.$strip>>;
492
460
  }, z.core.$strip>;
493
461
  /**
494
- * Mesh hotspot ��� references a named node/mesh in a 3D glTF scene.
462
+ * Mesh hotspot references a named node/mesh in a 3D glTF scene.
495
463
  * Used exclusively in `pin-on-model` items.
496
464
  */
497
465
  export declare const MeshHotspotSchema: z.ZodObject<{
@@ -550,7 +518,7 @@ export declare const CameraSetupSchema: z.ZodObject<{
550
518
  /**
551
519
  * Categorize item
552
520
  */
553
- export declare const CategorizeItemSchema: z.ZodObject<{
521
+ export declare const CategorizeItemObjectSchema: z.ZodObject<{
554
522
  id: z.ZodString;
555
523
  text: z.ZodString;
556
524
  correctCategoryIndex: z.ZodNumber;
@@ -1683,7 +1651,7 @@ export declare const PinOnImageItemSchema: z.ZodObject<{
1683
1651
  /**
1684
1652
  * Categorize Item
1685
1653
  */
1686
- export declare const CategorizeItemTypeSchema: z.ZodObject<{
1654
+ export declare const CategorizeItemSchema: z.ZodObject<{
1687
1655
  id: z.ZodString;
1688
1656
  assets: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
1689
1657
  type: z.ZodEnum<{
@@ -4280,15 +4248,6 @@ export declare const OQSEFileSchema: z.ZodObject<{
4280
4248
  itemProperties: z.ZodOptional<z.ZodArray<z.ZodString>>;
4281
4249
  metaProperties: z.ZodOptional<z.ZodArray<z.ZodString>>;
4282
4250
  }, z.core.$strip>>;
4283
- requiredFeatures: z.ZodOptional<z.ZodArray<z.ZodObject<{
4284
- name: z.ZodString;
4285
- type: z.ZodEnum<{
4286
- official: "official";
4287
- experimental: "experimental";
4288
- proprietary: "proprietary";
4289
- }>;
4290
- vendor: z.ZodOptional<z.ZodString>;
4291
- }, z.core.$strip>>>;
4292
4251
  tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
4293
4252
  tagDefinitions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
4294
4253
  wikidataId: z.ZodOptional<z.ZodString>;
@@ -0,0 +1,46 @@
1
+ import { FeatureProfile } from './oqse';
2
+ export interface TokenMap {
3
+ [tokenId: string]: {
4
+ type: 'asset' | 'blank';
5
+ key: string;
6
+ originalTag: string;
7
+ };
8
+ }
9
+ export interface RichTextProcessingOptions {
10
+ /** * Function to parse Markdown to HTML (e.g., `marked.parse`).
11
+ * For Tier 1, this should ideally be configured to escape raw HTML.
12
+ */
13
+ markdownParser: (markdown: string) => string;
14
+ /** * Function to sanitize HTML (e.g., `DOMPurify.sanitize`).
15
+ * REQUIRED if the set declares the 'html' feature (Tier 2).
16
+ */
17
+ htmlSanitizer?: (html: string) => string;
18
+ /** Callback to render an <asset:key /> tag into HTML (e.g., <img src="...">) */
19
+ assetReplacer?: (key: string) => string;
20
+ /** Callback to render a <blank:key /> tag into HTML (e.g., <input type="text">) */
21
+ blankReplacer?: (key: string) => string;
22
+ }
23
+ /**
24
+ * Step 1: Tokenization.
25
+ * Temporarily replaces <asset:key /> and <blank:key /> with cryptographically safe
26
+ * text tokens so they survive Markdown parsing and HTML sanitization.
27
+ */
28
+ export declare function tokenizeOqseTags(rawText: string): {
29
+ text: string;
30
+ tokens: TokenMap;
31
+ };
32
+ /**
33
+ * Step 2 (Tier 1): Strict HTML Validation.
34
+ * If 'html' is not allowed, any raw HTML tags written by the user must cause a validation error.
35
+ */
36
+ export declare function validateTier1Markdown(textWithoutOqseTags: string): void;
37
+ /**
38
+ * Step 4: Detokenization.
39
+ * Replaces the safe tokens back with the final interactive HTML elements.
40
+ */
41
+ export declare function detokenizeOqseTags(safeHtml: string, tokens: TokenMap, options: Pick<RichTextProcessingOptions, 'assetReplacer' | 'blankReplacer'>): string;
42
+ /**
43
+ * Main Facade for rendering OQSE Rich Content securely.
44
+ * Executes the complete Tokenization -> Validation -> Parsing -> Sanitization -> Detokenization pipeline.
45
+ */
46
+ export declare function prepareRichTextForDisplay(rawContent: string, requirements: FeatureProfile | undefined, options: RichTextProcessingOptions): string;
@@ -0,0 +1 @@
1
+ export {};
@@ -1,3 +1,12 @@
1
1
  export type UUID = string;
2
+ /**
3
+ * Validates if the given string is a syntactically valid UUID (any version).
4
+ * Uses the robust validator from the 'uuid' package.
5
+ */
2
6
  export declare function isValidUUID(id: string): boolean;
7
+ /**
8
+ * Generates a new UUIDv7.
9
+ * UUIDv7 is required by the OQSE specification for new items
10
+ * because it is time-sortable and optimized for database indexing.
11
+ */
3
12
  export declare function generateUUID(): UUID;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memizy/oqse",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "TypeScript SDK and Zod validators for the OQSE specification.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -17,17 +17,19 @@
17
17
  "dist",
18
18
  "schemas",
19
19
  "README.md",
20
- "SPECIFICATION.md"
20
+ "SPECIFICATION.md",
21
+ "LICENSE"
21
22
  ],
22
23
  "scripts": {
23
24
  "dev": "vite build --watch",
24
25
  "generate:schemas": "tsx scripts/generate-schemas.ts",
25
- "build": "npm run generate:schemas && tsc && vite build",
26
+ "build": "npm run generate:schemas && tsc && vite build && tsx scripts/fix-types-entry.ts",
26
27
  "test": "vitest run",
27
28
  "test:watch": "vitest",
28
29
  "prepublishOnly": "npm run build"
29
30
  },
30
31
  "devDependencies": {
32
+ "@types/uuid": "^10.0.0",
31
33
  "tsx": "^4.21.0",
32
34
  "typescript": "~6.0.2",
33
35
  "vite": "^8.0.4",
@@ -35,6 +37,7 @@
35
37
  "vitest": "^4.1.4"
36
38
  },
37
39
  "dependencies": {
40
+ "uuid": "^13.0.0",
38
41
  "zod": "^4.3.6"
39
42
  }
40
43
  }
@@ -38,8 +38,7 @@
38
38
  "features": {
39
39
  "type": "array",
40
40
  "items": {
41
- "type": "string",
42
- "minLength": 1
41
+ "type": "string"
43
42
  }
44
43
  },
45
44
  "latexPackages": {
@@ -52,15 +51,13 @@
52
51
  "itemProperties": {
53
52
  "type": "array",
54
53
  "items": {
55
- "type": "string",
56
- "minLength": 1
54
+ "type": "string"
57
55
  }
58
56
  },
59
57
  "metaProperties": {
60
58
  "type": "array",
61
59
  "items": {
62
- "type": "string",
63
- "minLength": 1
60
+ "type": "string"
64
61
  }
65
62
  },
66
63
  "actions": {
@@ -239,8 +239,7 @@
239
239
  "features": {
240
240
  "type": "array",
241
241
  "items": {
242
- "type": "string",
243
- "minLength": 1
242
+ "type": "string"
244
243
  }
245
244
  },
246
245
  "latexPackages": {
@@ -253,48 +252,18 @@
253
252
  "itemProperties": {
254
253
  "type": "array",
255
254
  "items": {
256
- "type": "string",
257
- "minLength": 1
255
+ "type": "string"
258
256
  }
259
257
  },
260
258
  "metaProperties": {
261
259
  "type": "array",
262
260
  "items": {
263
- "type": "string",
264
- "minLength": 1
261
+ "type": "string"
265
262
  }
266
263
  }
267
264
  },
268
265
  "additionalProperties": false
269
266
  },
270
- "requiredFeatures": {
271
- "type": "array",
272
- "items": {
273
- "type": "object",
274
- "properties": {
275
- "name": {
276
- "type": "string",
277
- "minLength": 1
278
- },
279
- "type": {
280
- "type": "string",
281
- "enum": [
282
- "official",
283
- "experimental",
284
- "proprietary"
285
- ]
286
- },
287
- "vendor": {
288
- "type": "string"
289
- }
290
- },
291
- "required": [
292
- "name",
293
- "type"
294
- ],
295
- "additionalProperties": false
296
- }
297
- },
298
267
  "tags": {
299
268
  "type": "array",
300
269
  "items": {