@memizy/oqse 0.1.1 → 0.1.3

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
@@ -2,27 +2,44 @@
2
2
 
3
3
  Official TypeScript SDK for the Open Quiz & Study Exchange ecosystem, published as @memizy/oqse.
4
4
 
5
+ 🚀 **[OQSE Web Validator](https://memizy.github.io/oqse-specification/)** - Online tool for easy testing and debugging of OQSE JSON structures in the browser.
6
+
5
7
  This repository contains:
8
+ - The human-readable specifications split into four standalone documents:
9
+ - [OQSE (Study Sets)](./oqse.md)
10
+ - [OQSEM (Application Manifests)](./oqse-manifest.md)
11
+ - [OQSEP (User Progress)](./oqse-progress.md)
12
+ - [OQSEH (Set Headers)](./oqse-header.md)
6
13
  - Runtime validators built with Zod.
7
14
  - Manually authored TypeScript types for developer ergonomics.
8
15
  - Auto-generated JSON Schemas distributed with the package.
9
- - The human-readable specification in SPECIFICATION.md.
10
16
 
11
17
  ## Package
12
18
 
13
19
  - Name: @memizy/oqse
14
- - Purpose: validate, parse, and type OQSE, OQSE Manifest, and OQSEP progress data.
20
+ - Purpose: validate, parse, and type OQSE, OQSEM (Application Manifest), and OQSEP (User Progress) data.
21
+
22
+ ## Schemas
23
+
24
+ The auto-generated JSON Schemas are published with this repository and are available at the following URLs:
25
+
26
+ - Core OQSE Schema: https://cdn.jsdelivr.net/gh/memizy/oqse-specification@main/schemas/oqse-v0.1.json
27
+ - Manifest Schema: https://cdn.jsdelivr.net/gh/memizy/oqse-specification@main/schemas/oqse-manifest-v0.1.json
28
+ - Progress Schema: https://cdn.jsdelivr.net/gh/memizy/oqse-specification@main/schemas/oqse-progress-v0.1.json
29
+ - Header Schema: https://cdn.jsdelivr.net/gh/memizy/oqse-specification@main/schemas/oqse-header-v0.1.json
15
30
 
16
31
  ## Architecture & Single Source of Truth
17
32
 
18
- 1. The specification markdown is for humans.
19
- SPECIFICATION.md is the normative documentation for concepts, rules, and semantics.
33
+ The human-readable Markdown specifications are the **absolute single source of truth** for the OQSE ecosystem.
34
+
35
+ 1. **The Specifications**
36
+ The four Markdown files ([oqse.md](./oqse.md), [oqse-manifest.md](./oqse-manifest.md), [oqse-progress.md](./oqse-progress.md), and [oqse-header.md](./oqse-header.md)) constitute the normative documentation for concepts, rules, and semantics.
20
37
 
21
- 2. Zod schemas (*Validation.ts) are the absolute source of truth for code validation.
22
- Runtime validation behavior is defined in src/oqseValidation.ts, src/manifestValidation.ts, and src/progressValidation.ts.
38
+ 2. **Zod Schemas**
39
+ Runtime validators (`*Validation.ts`) are implementations. They **MUST match** the rules defined in the Markdown specs. They are not the source of truth; if they disagree with the text spec, the code is considered a bug.
23
40
 
24
- 3. TypeScript types (oqse.ts, manifest.ts, progress.ts) manually mirror the Zod schemas for better Developer Experience.
25
- These files are intentionally hand-written to provide clearer interfaces, JSDoc, and IntelliSense quality.
41
+ 3. **TypeScript Types**
42
+ TypeScript types (`oqse.ts`, `manifest.ts`, `progress.ts`) manually mirror the Zod schemas for better Developer Experience. They must also strictly adhere to the Markdown specifications.
26
43
 
27
44
  4. JSON schemas are strictly auto-generated using npm run generate:schemas and contributors MUST NOT edit them manually.
28
45
  If validation behavior changes, update the Zod schemas first, then regenerate.
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require(`zod`);function t(e){return e.type===`note`}function n(e){return e.type===`flashcard`}function r(e){return e.type===`true-false`}function i(e){return e.type===`mcq-single`}function a(e){return e.type===`mcq-multi`}function ee(e){return e.type===`short-answer`}function te(e){return e.type===`fill-in-blanks`}function ne(e){return e.type===`fill-in-select`}function re(e){return e.type===`match-pairs`}function ie(e){return e.type===`match-complex`}function ae(e){return e.type===`sort-items`}function oe(e){return e.type===`slider`}function se(e){return e.type===`pin-on-image`}function ce(e){return e.type===`categorize`}function le(e){return e.type===`timeline`}function ue(e){return e.type===`matrix`}function de(e){return e.type===`math-input`}function fe(e){return e.type===`diagram-label`}function pe(e){return e.type===`open-ended`}function me(e){return e.type===`numeric-input`}function he(e){return e.type===`pin-on-model`}function ge(e){return e.type===`chess-puzzle`}function o(e){return[`note`,`flashcard`,`mcq-single`,`short-answer`].includes(e.type)}function _e(e){return!o(e)}var s=e.z.string().uuid({message:`Neplatn+� form+�t UUID`}),c=e.z.string().min(2,`K+-d jazyka mus+� m+�t alespo+� 2 znaky`).regex(/^[a-z]{2,3}(-[A-Z][a-z]{3})?(-[A-Z]{2})?$/,`Neplatn+� form+�t BCP 47 (nap+�. "cs", "en-US")`),l=e.z.string().min(1,`Identifik+�tor licence nesm+� b+�t pr+�zdn+�`),u=e.z.string().regex(/^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2}(\.\d{3})?(Z|[+-]\d{2}:\d{2})?)?$/,`Neplatn+� form+�t ISO 8601 (nap+�. "2025-11-21T14:30:00Z")`),d=e.z.string().url({message:`Mus+� b+�t platn+� absolutn+� URL adresa`}),f=e.z.string().regex(/^[a-z0-9_-]+$/,`Kl+��� assetu mus+� obsahovat pouze mal+� p+�smena, ��+�sla, poml��ky a podtr+�+�tka`),p=e.z.string().min(1,`Text nesm+� b+�t pr+�zdn+�`),m=e.z.string().min(1,`Obsah nesm+� b+�t pr+�zdn+�`),h=e.z.string().optional(),g=e.z.object({lang:c,value:e.z.string().min(1,`URI titulk+� nesm+� b+�t pr+�zdn+�`),label:e.z.string().optional(),kind:e.z.enum([`captions`,`subtitles`,`descriptions`]).optional()}),ve=e.z.object({type:e.z.enum([`image`,`audio`,`video`,`model`]),value:e.z.string().min(1,`URI m+�dia nesm+� b+�t pr+�zdn+�`),mimeType:e.z.string().optional(),altText:e.z.string().optional(),transcript:m.optional(),caption:m.optional(),width:e.z.number().int().positive().optional(),height:e.z.number().int().positive().optional(),start:e.z.number().nonnegative().optional(),end:e.z.number().positive().optional(),loop:e.z.boolean().optional(),subtitles:e.z.array(g).optional(),license:l.optional(),attribution:e.z.string().optional(),checksums:e.z.record(e.z.string(),e.z.string()).optional()}).refine(e=>e.start!==void 0&&e.end!==void 0?e.start<e.end:!0,{message:`Po��+�te��n+� ��as mus+� b+�t men+�+� ne+� koncov+� ��as`,path:[`end`]}).refine(e=>!(e.type===`image`&&!e.altText),{message:`Obr+�zky mus+� m+�t definovan+� alternativn+� text (altText) pro p+�+�stupnost`,path:[`altText`]}),_=e.z.record(f,ve),v=e.z.object({name:p,role:e.z.string().optional(),email:e.z.string().email(`Neplatn+� form+�t e-mailov+� adresy`).optional(),url:d.optional()}),y=e.z.enum([`url`,`doi`,`isbn`,`pdf`,`textbook`,`video`,`audio`,`image`,`model`,`other`]),b=e.z.object({id:p,type:y,value:p,title:p,description:e.z.string().optional(),authors:e.z.array(p).optional(),publishedDate:u.optional(),retrievedAt:u.optional(),license:l.optional()}).refine(e=>{if([`url`,`pdf`,`video`,`audio`,`image`].includes(e.type))try{return new URL(e.value),!0}catch{return!1}return!0},{message:`Pro typy url, pdf, video, audio a image mus+� b+�t value platn+� URL adresa`,path:[`value`]}),x=e.z.object({id:p,location:e.z.string().optional(),quote:m.optional()}),S=e.z.object({wikidataId:e.z.string().regex(/^Q\d+$/,`Wikidata ID mus+� m+�t form+�t Q n+�sledovan+� ��+�slem`).optional(),description:e.z.string().optional()}),C=e.z.record(e.z.string(),S),w=e.z.object({features:e.z.array(e.z.string().min(1,`Kl+��� funkce nesm+� b+�t pr+�zdn+�`)).optional(),latexPackages:e.z.array(e.z.string().min(1,`N+�zev bal+���ku nesm+� b+�t pr+�zdn+�`)).optional(),itemProperties:e.z.array(e.z.string().min(1,`Kl+��� vlastnosti nesm+� b+�t pr+�zdn+�`)).optional(),metaProperties:e.z.array(e.z.string().min(1,`Kl+��� vlastnosti nesm+� b+�t pr+�zdn+�`)).optional()}),T=e.z.enum([`official`,`experimental`,`proprietary`]),ye=e.z.enum([`math`,`media-image`,`media-audio`,`media-video`,`hotspots`,`complex-pairing`,`open-text`]),E=e.z.object({name:p,type:T,vendor:e.z.string().optional()}).refine(e=>!(e.type===`proprietary`&&!e.vendor),{message:`Propriet+�rn+� funkce mus+� m+�t definovan+� vendor (nap+�. "memizy.com")`,path:[`vendor`]}),D=e.z.object({lang:c,id:s,title:p,downloadUrl:d.optional()}),O=e.z.object({id:s,title:p,downloadUrl:d.optional()}),k=e.z.enum([`remember`,`understand`,`apply`,`analyze`,`evaluate`,`create`]),A=e.z.enum([`low`,`medium`,`high`]),j=e.z.object({bloomLevel:k.optional(),irtDifficulty:e.z.number().optional(),irtDiscrimination:e.z.number().optional(),irtGuessing:e.z.number().min(0).max(1,`IRT guessing mus+� b+�t mezi 0 a 1`).optional(),avgTime:e.z.number().positive().optional(),cognitiveLoad:A.optional(),partialCredit:e.z.boolean().optional(),penaltyPerWrong:e.z.number().min(0).max(1,`Penalizace mus+� b+�t mezi 0 a 1`).optional()}),M=e.z.enum([`katex`,`mathjax`]),N=e.z.object({renderer:M.optional(),packages:e.z.array(e.z.string()).optional()}),P=e.z.object({id:s,language:c,title:p.max(500,`Titulek nesm+� b+�t del+�+� ne+� 500 znak+�`),description:m.max(5e3,`Popis nesm+� b+�t del+�+� ne+� 5000 znak+�`).optional(),thumbnail:f.optional(),assets:_.optional(),ageMin:e.z.number().int().nonnegative().optional(),ageMax:e.z.number().int().nonnegative().optional(),subject:e.z.string().optional(),createdAt:u,updatedAt:u,author:v.optional(),contributors:e.z.array(v).optional(),license:l.optional(),licenseUrl:d.optional(),requirements:w.optional(),requiredFeatures:e.z.array(E).optional(),tags:e.z.array(p).optional(),tagDefinitions:C.optional(),translations:e.z.array(D).optional(),sourceMaterials:e.z.array(b).optional(),estimatedTime:e.z.number().positive().optional(),prerequisites:e.z.array(O).optional(),relatedSets:e.z.array(O).optional(),mathSettings:N.optional(),customData:e.z.record(e.z.string(),e.z.unknown()).optional(),appSpecific:e.z.record(e.z.string(),e.z.unknown()).optional()}).refine(e=>e.ageMin!==void 0&&e.ageMax!==void 0?e.ageMin<=e.ageMax:!0,{message:`Minim+�ln+� v��k (ageMin) mus+� b+�t men+�+� nebo roven maxim+�ln+�mu v��ku (ageMax)`,path:[`ageMax`]}).refine(e=>new Date(e.createdAt)<=new Date(e.updatedAt),{message:`Datum vytvo+�en+� (createdAt) mus+� b+�t p+�ed nebo stejn+� jako datum aktualizace (updatedAt)`,path:[`updatedAt`]}),F=e.z.object({id:s,type:e.z.string(),assets:_.optional(),lang:c.optional(),tags:e.z.array(p).optional(),difficulty:e.z.number().int().min(1,`Obt+�+�nost mus+� b+�t minim+�ln�� 1`).max(5,`Obt+�+�nost mus+� b+�t maxim+�ln�� 5`).optional(),timeLimit:e.z.number().positive(`��asov+� limit mus+� b+�t kladn+� ��+�slo`).optional(),hints:e.z.array(m.max(2e3,`N+�pov��da nesm+� b+�t del+�+� ne+� 2000 znak+�`)).max(20,`Maxim+�ln�� 20 n+�pov��d na polo+�ku`).optional(),explanation:m.max(1e4,`Vysv��tlen+� nesm+� b+�t del+�+� ne+� 10000 znak+�`).optional(),incorrectFeedback:m.optional(),sources:e.z.array(x).optional(),relatedItems:e.z.array(s).optional(),dependencyItems:e.z.array(s).optional(),pedagogy:j.optional(),customData:e.z.record(e.z.string(),e.z.unknown()).optional(),appSpecific:e.z.record(e.z.string(),e.z.unknown()).optional()}),I=e.z.object({options:e.z.array(m).min(1,`Mus+� b+�t alespo+� 1 mo+�nost`),correctIndex:e.z.number().int().nonnegative()}).refine(e=>e.correctIndex<e.options.length,{message:`Index spr+�vn+� odpov��di odkazuje na neexistuj+�c+� mo+�nost`,path:[`correctIndex`]}),L=e.z.object({type:e.z.literal(`rect`),label:e.z.string().optional(),x:e.z.number().min(0).max(100,`X mus+� b+�t v rozmez+� 0-100%`),y:e.z.number().min(0).max(100,`Y mus+� b+�t v rozmez+� 0-100%`),width:e.z.number().min(0).max(100,`+�+�+�ka mus+� b+�t v rozmez+� 0-100%`),height:e.z.number().min(0).max(100,`V+�+�ka mus+� b+�t v rozmez+� 0-100%`)}),R=e.z.object({type:e.z.literal(`circle`),label:e.z.string().optional(),x:e.z.number().min(0).max(100,`X mus+� b+�t v rozmez+� 0-100%`),y:e.z.number().min(0).max(100,`Y mus+� b+�t v rozmez+� 0-100%`),radius:e.z.number().min(0).max(100,`Polom��r mus+� b+�t v rozmez+� 0-100%`)}),z=e.z.object({type:e.z.literal(`polygon`),label:e.z.string().optional(),points:e.z.array(e.z.object({x:e.z.number().min(0).max(100),y:e.z.number().min(0).max(100)})).min(3,`Polygon mus+� m+�t alespo+� 3 body`)}),B=e.z.object({type:e.z.literal(`mesh`),label:e.z.string().optional(),targetName:p}),V=e.z.discriminatedUnion(`type`,[L,R,z,B]),H=e.z.object({x:e.z.number(),y:e.z.number(),z:e.z.number()}),U=e.z.object({position:H.optional(),target:H.optional()}),be=e.z.object({id:p,text:m,correctCategoryIndex:e.z.number().int().nonnegative()}),xe=e.z.enum([`year`,`month`,`day`,`datetime`]),Se=e.z.object({id:p,text:m,date:u,precision:xe.optional()}),Ce=e.z.union([L.extend({correctLabelIndex:e.z.number().int().nonnegative()}),R.extend({correctLabelIndex:e.z.number().int().nonnegative()}),z.extend({correctLabelIndex:e.z.number().int().nonnegative()})]),we=e.z.object({label:p,percentage:e.z.number().min(0,`Procenta mus+� b+�t nez+�porn+�`).max(100,`Procenta nesm+� p+�es+�hnout 100`),description:e.z.string().optional()}),Te=e.z.object({criteria:e.z.array(we).min(1,`Rubrika mus+� m+�t alespo+� 1 krit+�rium`)}).refine(e=>e.criteria.reduce((e,t)=>e+t.percentage,0)>0,{message:`Sou��et procent v+�ech krit+�ri+� mus+� b+�t v��t+�+� ne+� 0`,path:[`criteria`]}),Ee=e.z.object({min:e.z.number(),max:e.z.number()}).refine(e=>e.min<=e.max,{message:`Minim+�ln+� hodnota mus+� b+�t men+�+� nebo rovna maxim+�ln+� hodnot��`,path:[`max`]}),De=F.extend({type:e.z.literal(`note`),title:e.z.string().optional(),content:m.max(1e4,`Obsah nesm+� b+�t del+�+� ne+� 10000 znak+�`)}),Oe=F.extend({type:e.z.literal(`flashcard`),front:m.max(1e4,`P+�edn+� strana nesm+� b+�t del+�+� ne+� 10000 znak+�`),back:m.max(1e4,`Zadn+� strana nesm+� b+�t del+�+� ne+� 10000 znak+�`)}),ke=F.extend({type:e.z.literal(`true-false`),question:m.max(1e4,`Ot+�zka nesm+� b+�t del+�+� ne+� 10000 znak+�`),answer:e.z.boolean()}),Ae=F.extend({type:e.z.literal(`mcq-single`),question:m.max(1e4,`Ot+�zka nesm+� b+�t del+�+� ne+� 10000 znak+�`),options:e.z.array(m.max(2e3,`Mo+�nost nesm+� b+�t del+�+� ne+� 2000 znak+�`)).min(2,`Ot+�zka mus+� m+�t alespo+� 2 mo+�nosti`).max(100,`Maxim+�ln�� 100 mo+�nost+�`),correctIndex:e.z.number().int().nonnegative(),shuffleOptions:e.z.boolean().optional(),optionExplanations:e.z.array(e.z.union([m,e.z.null()])).optional()}).refine(e=>e.correctIndex<e.options.length,{message:`Index spr+�vn+� odpov��di odkazuje na neexistuj+�c+� mo+�nost`,path:[`correctIndex`]}).refine(e=>e.optionExplanations?e.optionExplanations.length===e.options.length:!0,{message:`Po��et vysv��tlen+� mo+�nost+� mus+� b+�t stejn+� jako po��et mo+�nost+�`,path:[`optionExplanations`]}),je=F.extend({type:e.z.literal(`mcq-multi`),question:m.max(1e4,`Ot+�zka nesm+� b+�t del+�+� ne+� 10000 znak+�`),options:e.z.array(m.max(2e3,`Mo+�nost nesm+� b+�t del+�+� ne+� 2000 znak+�`)).min(2,`Ot+�zka mus+� m+�t alespo+� 2 mo+�nosti`).max(100,`Maxim+�ln�� 100 mo+�nost+�`),correctIndices:e.z.array(e.z.number().int().nonnegative()).min(1,`Mus+� b+�t alespo+� 1 spr+�vn+� odpov����`),minSelections:e.z.number().int().positive().optional(),maxSelections:e.z.number().int().positive().optional(),shuffleOptions:e.z.boolean().optional(),optionExplanations:e.z.array(e.z.union([m,e.z.null()])).optional()}).refine(e=>e.correctIndices.every(t=>t<e.options.length),{message:`N��kter+� z index+� spr+�vn+�ch odpov��d+� odkazuje na neexistuj+�c+� mo+�nost`,path:[`correctIndices`]}).refine(e=>new Set(e.correctIndices).size===e.correctIndices.length,{message:`Indexy spr+�vn+�ch odpov��d+� obsahuj+� duplicity`,path:[`correctIndices`]}).refine(e=>e.minSelections&&e.maxSelections?e.minSelections<=e.maxSelections:!0,{message:`Minim+�ln+� po��et v+�b��r+� mus+� b+�t men+�+� nebo roven maxim+�ln+�mu po��tu`,path:[`maxSelections`]}).refine(e=>e.maxSelections?e.maxSelections<=e.options.length:!0,{message:`Maxim+�ln+� po��et v+�b��r+� nesm+� p+�es+�hnout po��et mo+�nost+�`,path:[`maxSelections`]}).refine(e=>e.optionExplanations?e.optionExplanations.length===e.options.length:!0,{message:`Po��et vysv��tlen+� mo+�nost+� mus+� b+�t stejn+� jako po��et mo+�nost+�`,path:[`optionExplanations`]}),W=F.extend({type:e.z.literal(`short-answer`),question:m.max(1e4,`Ot+�zka nesm+� b+�t del+�+� ne+� 10000 znak+�`),answers:e.z.array(p).min(1,`Mus+� b+�t alespo+� 1 spr+�vn+� odpov����`),caseSensitive:e.z.boolean().optional(),trimWhitespace:e.z.boolean().optional(),acceptPartial:e.z.boolean().optional(),ignoreDiacritics:e.z.boolean().optional()}),Me=F.extend({type:e.z.literal(`fill-in-blanks`),question:h,text:m.max(1e4,`Text nesm+� b+�t del+�+� ne+� 10000 znak+�`),blanks:e.z.record(e.z.string(),e.z.array(p).min(1,`Ka+�d+� mezera mus+� m+�t alespo+� 1 spr+�vnou odpov����`)),caseSensitive:e.z.boolean().optional(),trimWhitespace:e.z.boolean().optional()}).refine(e=>Object.keys(e.blanks).length>0,{message:`Text mus+� obsahovat alespo+� 1 mezeru k dopln��n+�`,path:[`blanks`]}).refine(e=>{let t=/<blank:([a-zA-Z0-9_-]{1,64})\s*\/>/g,n=new Set,r;for(;(r=t.exec(e.text))!==null;)r[1]&&n.add(r[1]);let i=new Set(Object.keys(e.blanks));for(let e of n)if(!i.has(e))return!1;for(let e of i)if(!n.has(e))return!1;return!0},{message:`V+�echny tokeny v textu mus+� m+�t definici v blanks a v+�echny definice mus+� b+�t pou+�ity v textu`,path:[`blanks`]}),Ne=F.extend({type:e.z.literal(`fill-in-select`),question:h,text:m.max(1e4,`Text nesm+� b+�t del+�+� ne+� 10000 znak+�`),blanks:e.z.record(e.z.string(),I)}).refine(e=>Object.keys(e.blanks).length>0,{message:`Text mus+� obsahovat alespo+� 1 mezeru k v+�b��ru`,path:[`blanks`]}).refine(e=>{let t=/<blank:([a-zA-Z0-9_-]{1,64})\s*\/>/g,n=new Set,r;for(;(r=t.exec(e.text))!==null;)r[1]&&n.add(r[1]);let i=new Set(Object.keys(e.blanks));for(let e of n)if(!i.has(e))return!1;for(let e of i)if(!n.has(e))return!1;return!0},{message:`V+�echny tokeny v textu mus+� m+�t definici v blanks a v+�echny definice mus+� b+�t pou+�ity v textu`,path:[`blanks`]}),Pe=F.extend({type:e.z.literal(`match-pairs`),question:h,prompts:e.z.array(m).min(2,`Mus+� b+�t alespo+� 2 p+�ry k p+�i+�azen+�`),matches:e.z.array(m).min(2,`Mus+� b+�t alespo+� 2 p+�ry k p+�i+�azen+�`)}).refine(e=>e.prompts.length===e.matches.length,{message:`Po��et ot+�zek (prompts) mus+� b+�t stejn+� jako po��et odpov��d+� (matches)`,path:[`matches`]}),Fe=F.extend({type:e.z.literal(`match-complex`),question:h,leftItems:e.z.array(m).min(1,`Mus+� b+�t alespo+� 1 polo+�ka vlevo`),rightItems:e.z.array(m).min(1,`Mus+� b+�t alespo+� 1 polo+�ka vpravo`),connections:e.z.array(e.z.tuple([e.z.number().int().nonnegative(),e.z.number().int().nonnegative()])).min(1,`Mus+� b+�t alespo+� 1 propojen+�`),minCorrect:e.z.number().int().positive().optional()}).refine(e=>e.connections.every(([t,n])=>t<e.leftItems.length&&n<e.rightItems.length),{message:`N��kter+� propojen+� odkazuje na neexistuj+�c+� polo+�ku`,path:[`connections`]}).refine(e=>new Set(e.connections.map(e=>`${e[0]}-${e[1]}`)).size===e.connections.length,{message:`Propojen+� obsahuj+� duplicity`,path:[`connections`]}).refine(e=>e.minCorrect?e.minCorrect<=e.connections.length:!0,{message:`Minim+�ln+� po��et spr+�vn+�ch odpov��d+� nesm+� p+�es+�hnout celkov+� po��et propojen+�`,path:[`minCorrect`]}),Ie=F.extend({type:e.z.literal(`sort-items`),question:m.max(1e4,`Ot+�zka nesm+� b+�t del+�+� ne+� 10000 znak+�`),items:e.z.array(m).min(2,`Mus+� b+�t alespo+� 2 polo+�ky k se+�azen+�`)}),Le=F.extend({type:e.z.literal(`slider`),question:m.max(1e4,`Ot+�zka nesm+� b+�t del+�+� ne+� 10000 znak+�`),min:e.z.number(),max:e.z.number(),step:e.z.number().positive(`Krok mus+� b+�t kladn+� ��+�slo`),correctAnswer:e.z.number(),tolerance:e.z.number().nonnegative(`Tolerance mus+� b+�t nez+�porn+�`),unit:e.z.string().optional()}).refine(e=>e.min<e.max,{message:`Minim+�ln+� hodnota mus+� b+�t men+�+� ne+� maxim+�ln+� hodnota`,path:[`max`]}).refine(e=>e.correctAnswer>=e.min&&e.correctAnswer<=e.max,{message:`Spr+�vn+� odpov���� mus+� b+�t v rozmez+� min-max`,path:[`correctAnswer`]}).refine(e=>{let t=(e.correctAnswer-e.min)/e.step;return Math.abs(t-Math.round(t))<1e-4},{message:`Spr+�vn+� odpov���� mus+� b+�t dosa+�iteln+� pomoc+� definovan+�ho kroku`,path:[`correctAnswer`]}).refine(e=>e.tolerance<=(e.max-e.min)/2,{message:`Tolerance nesm+� b+�t v��t+�+� ne+� polovina rozsahu hodnot`,path:[`tolerance`]}),Re=F.extend({type:e.z.literal(`pin-on-image`),question:m.max(1e4,`Ot+�zka nesm+� b+�t del+�+� ne+� 10000 znak+�`),targetAsset:f,hotspots:e.z.array(V).min(1,`Mus+� b+�t alespo+� 1 hotspot`),multipleCorrect:e.z.boolean().optional(),minCorrect:e.z.number().int().positive().optional()}).refine(e=>e.minCorrect?e.minCorrect<=e.hotspots.length:!0,{message:`Minim+�ln+� po��et spr+�vn+�ch odpov��d+� nesm+� p+�es+�hnout po��et hotspot+�`,path:[`minCorrect`]}),ze=F.extend({type:e.z.literal(`categorize`),question:m.max(1e4,`Ot+�zka nesm+� b+�t del+�+� ne+� 10000 znak+�`),categories:e.z.array(p).min(2,`Mus+� b+�t alespo+� 2 kategorie`),items:e.z.array(be).min(1,`Mus+� b+�t alespo+� 1 polo+�ka ke kategorizaci`)}).refine(e=>e.items.every(t=>t.correctCategoryIndex<e.categories.length),{message:`N��kter+� polo+�ka odkazuje na neexistuj+�c+� kategorii`,path:[`items`]}),Be=F.extend({type:e.z.literal(`timeline`),question:m.max(1e4,`Ot+�zka nesm+� b+�t del+�+� ne+� 10000 znak+�`),events:e.z.array(Se).min(2,`Mus+� b+�t alespo+� 2 ud+�losti`),randomize:e.z.boolean().optional()}),Ve=F.extend({type:e.z.literal(`matrix`),question:m.max(1e4,`Ot+�zka nesm+� b+�t del+�+� ne+� 10000 znak+�`),rows:e.z.array(p).min(1,`Mus+� b+�t alespo+� 1 +�+�dek`),columns:e.z.array(p).min(1,`Mus+� b+�t alespo+� 1 sloupec`),correctCells:e.z.array(e.z.tuple([e.z.number().int().nonnegative(),e.z.number().int().nonnegative()])).min(1,`Mus+� b+�t alespo+� 1 spr+�vn+� bu+�ka`),multiplePerRow:e.z.boolean().optional()}).refine(e=>e.correctCells.every(([t,n])=>t<e.rows.length&&n<e.columns.length),{message:`N��kter+� sou+�adnice bu+�ky odkazuj+� na neexistuj+�c+� +�+�dek nebo sloupec`,path:[`correctCells`]}).refine(e=>new Set(e.correctCells.map(e=>`${e[0]}-${e[1]}`)).size===e.correctCells.length,{message:`Spr+�vn+� bu+�ky obsahuj+� duplicity`,path:[`correctCells`]}).refine(e=>{if(!e.multiplePerRow){let t=new Map;for(let[n]of e.correctCells)t.set(n,(t.get(n)||0)+1);return Array.from(t.values()).every(e=>e<=1)}return!0},{message:`Pokud multiplePerRow je false, ka+�d+� +�+�dek sm+� m+�t maxim+�ln�� 1 spr+�vnou bu+�ku`,path:[`correctCells`]}),He=F.extend({type:e.z.literal(`math-input`),question:m.max(1e4,`Ot+�zka nesm+� b+�t del+�+� ne+� 10000 znak+�`),correctAnswer:p,alternativeAnswers:e.z.array(p).optional(),tolerance:e.z.number().nonnegative().optional()}),Ue=F.extend({type:e.z.literal(`diagram-label`),question:m.max(1e4,`Ot+�zka nesm+� b+�t del+�+� ne+� 10000 znak+�`),targetAsset:f,labels:e.z.array(m).min(1,`Mus+� b+�t alespo+� 1 +�t+�tek`),caseSensitive:e.z.boolean().optional(),requireTyping:e.z.boolean().optional(),zones:e.z.array(Ce).min(1,`Mus+� b+�t alespo+� 1 z+-na`)}).refine(e=>e.zones.every(t=>t.correctLabelIndex<e.labels.length),{message:`N��kter+� z+-na odkazuje na neexistuj+�c+� +�t+�tek`,path:[`zones`]}),We=F.extend({type:e.z.literal(`open-ended`),question:m.max(1e4,`Ot+�zka nesm+� b+�t del+�+� ne+� 10000 znak+�`),minWords:e.z.number().int().positive().optional(),maxWords:e.z.number().int().positive().optional(),sampleAnswer:m.optional(),rubric:Te.optional()}).refine(e=>e.minWords&&e.maxWords?e.minWords<=e.maxWords:!0,{message:`Minim+�ln+� po��et slov mus+� b+�t men+�+� nebo roven maxim+�ln+�mu po��tu`,path:[`maxWords`]}),Ge=F.extend({type:e.z.literal(`numeric-input`),question:m.max(1e4,`Ot+�zka nesm+� b+�t del+�+� ne+� 10000 znak+�`),value:e.z.number(),tolerance:e.z.number().nonnegative().optional(),range:Ee.optional(),unit:e.z.string().optional()}),Ke=F.extend({type:e.z.literal(`pin-on-model`),question:m.max(1e4,`Ot+�zka nesm+� b+�t del+�+� ne+� 10000 znak+�`),targetAsset:f,hotspots:e.z.array(B).min(1,`Mus+� b+�t alespo+� 1 hotspot`),multipleCorrect:e.z.boolean().optional(),minCorrect:e.z.number().int().positive().optional(),camera:U.optional()}).refine(e=>e.minCorrect?e.minCorrect<=e.hotspots.length:!0,{message:`Minim+�ln+� po��et spr+�vn+�ch odpov��d+� nesm+� p+�es+�hnout po��et hotspot+�`,path:[`minCorrect`]}),qe=F.extend({type:e.z.literal(`chess-puzzle`),question:m.max(1e4,`Ot+�zka nesm+� b+�t del+�+� ne+� 10000 znak+�`),fen:p,answers:e.z.array(e.z.array(p).min(1,`Sekvence tah+� nesm+� b+�t pr+�zdn+�`)).min(1,`Mus+� b+�t alespo+� 1 spr+�vn+� sekvence tah+�`),elo:e.z.number().int().nonnegative(`ELO mus+� b+�t nez+�porn+� cel+� ��+�slo`).optional()}),G=e.z.discriminatedUnion(`type`,[De,Oe,ke,Ae,je,W,Me,Ne,Pe,Fe,Ie,Le,Re,ze,Be,Ve,He,Ue,We,Ge,Ke,qe]),K=e.z.object({$schema:e.z.string().url().optional(),version:e.z.string().regex(/^\d+\.\d+$/,`Verze musi byt ve formatu "X.Y" (napr. "0.1")`),meta:P,items:e.z.array(G).max(1e4,`Maxim+�ln�� 10000 polo+�ek na sadu`)}).refine(e=>{let t=new Set(e.items.map(e=>e.id));for(let n of e.items){if(n.relatedItems){for(let e of n.relatedItems)if(!t.has(e))return!1}if(n.dependencyItems){for(let e of n.dependencyItems)if(!t.has(e))return!1}}return!0},{message:`N��kter+� polo+�ka odkazuje na neexistuj+�c+� relatedItems nebo dependencyItems`,path:[`items`]}).refine(e=>e.meta.thumbnail&&e.meta.assets?e.meta.thumbnail in e.meta.assets:!0,{message:`Thumbnail odkazuje na neexistuj+�c+� asset`,path:[`meta`,`thumbnail`]}).refine(e=>{let t=new Set((e.meta.sourceMaterials||[]).map(e=>e.id));for(let n of e.items)if(n.sources){for(let e of n.sources)if(!t.has(e.id))return!1}return!0},{message:`N��kter+� polo+�ka odkazuje na neexistuj+�c+� source material`,path:[`items`]});function Je(e){return K.parse(e)}function Ye(e){let t=K.safeParse(e);return t.success?{success:!0,data:t.data}:{success:!1,error:t.error}}function Xe(e){return G.parse(e)}function Ze(e){let t=G.safeParse(e);return t.success?{success:!0,data:t.data}:{success:!1,error:t.error}}function Qe(e){return e.issues.map(e=>{let t=e.path.join(` ��� `);return t?`${t}: ${e.message}`:e.message})}function q(e){return/^\d+\.\d+$/.test(e)}function $e(e){return/^\d+\.\d+\.\d+(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$/.test(e)}function J(e,t){let[n=0,r=0]=e.split(`.`).map(Number),[i=0,a=0]=t.split(`.`).map(Number);return n===i?r-a:n-i}function et(e){if(typeof e!=`object`||!e)return!1;let t=e;return typeof t.version==`string`&&typeof t.id==`string`&&typeof t.appName==`string`&&t.appName!==``&&typeof t.capabilities==`object`&&t.capabilities!==null&&Array.isArray(t.capabilities.actions)}function tt(e,t){return!(!q(e)||t.minOqseVersion&&q(t.minOqseVersion)&&J(e,t.minOqseVersion)<0||t.maxOqseVersion&&q(t.maxOqseVersion)&&J(e,t.maxOqseVersion)>0)}var Y=e.z.string().min(1,`Hodnota nesm+� b+�t pr+�zdn+�`).trim(),nt=e.z.string().url(`Mus+� b+�t platn+� absolutn+� URL`).refine(e=>e.startsWith(`http://`)||e.startsWith(`https://`),{message:`URL mus+� pou+�+�vat sch+�ma http nebo https`}),X=e.z.string().regex(/^\d+\.\d+$/,`Verze mus+� b+�t ve form+�tu MAJOR.MINOR (nap+�. "0.1")`),rt=e.z.string().regex(/^\d+\.\d+\.\d+$/,`Verze mus+� b+�t ve form+�tu MAJOR.MINOR.PATCH (nap+�. "1.2.3")`),it=[`render`,`edit`,`validate`,`import`,`export`],at=e.z.string().refine(e=>it.includes(e)||e.startsWith(`x-`),{message:`Akce mus+� b+�t jedna z [render, edit, validate, import, export] nebo m+�t prefix "x-"`}),ot=e.z.enum([`game`,`fun`,`drill`]),st=e.z.enum([`low`,`medium`,`high`]),ct=[`math`,`media`,`media-image`,`media-audio`,`media-video`,`media-model`,`hotspots`,`hotspots-3d`,`complex-pairing`,`open-text`,`chess`],lt=e.z.string().refine(e=>ct.includes(e)||e.startsWith(`x-`),{message:`Funkce mus+� b+�t jedna z ofici+�ln+�ch kl+���+� nebo m+�t prefix "x-"`}),ut=e.z.string().min(1,`Kl+��� vlastnosti polo+�ky nesm+� b+�t pr+�zdn+�`),dt=e.z.string().min(1,`Kl+��� vlastnosti metadat nesm+� b+�t pr+�zdn+�`);function Z(t){return e.z.union([e.z.tuple([e.z.literal(`*`)]),e.z.array(t),e.z.null()])}var ft=e.z.string().refine(e=>e.startsWith(`image/`),{message:`Mus+� b+�t platn+� MIME typ obr+�zku (image/...)`}),pt=e.z.string().refine(e=>e.startsWith(`audio/`),{message:`Mus+� b+�t platn+� MIME typ zvuku (audio/...)`}),mt=e.z.string().refine(e=>e.startsWith(`video/`),{message:`Mus+� b+�t platn+� MIME typ videa (video/...)`}),ht=e.z.string().refine(e=>e.startsWith(`model/`)||e===`application/octet-stream`,{message:`Mus+� b+�t platn+� MIME typ 3D modelu (model/... nebo application/octet-stream)`}),gt=e.z.object({image:Z(ft).optional(),audio:Z(pt).optional(),video:Z(mt).optional(),model:Z(ht).optional()}),_t=w.extend({actions:e.z.array(at).min(1,`Aplikace mus+� podporovat alespo+� jednu akci`),types:Z(Y).optional(),assets:gt.optional()}),Q=e.z.object({$schema:nt.optional(),id:Y.regex(/^[a-z0-9-]+(\.[a-z0-9-]+)*$/,`ID mus+� b+�t ve tvaru reverse-domain (nap+�. "com.acme.app")`),appName:Y.max(100,`N+�zev nesm+� b+�t del+�+� ne+� 100 znak+�`),version:X,pluginVersion:rt.optional(),minOqseVersion:X.optional(),maxOqseVersion:X.optional(),capabilities:_t,author:e.z.string().max(100,`N+�zev autora nesm+� b+�t del+�+� ne+� 100 znak+�`).optional(),authorUrl:nt.optional(),locales:e.z.array(Y).optional(),description:e.z.string().max(500,`Popis nesm+� b+�t del+�+� ne+� 500 znak+�`).optional(),emoji:e.z.string().optional(),tags:e.z.array(Y).optional(),studyMode:ot.optional(),questionDensity:st.optional(),appSpecific:e.z.record(e.z.string(),e.z.unknown()).optional()}).refine(e=>{if(!e.minOqseVersion||!e.maxOqseVersion)return!0;let t=e.minOqseVersion.split(`.`),n=e.maxOqseVersion.split(`.`),r=Number(t[0]),i=Number(t[1]),a=Number(n[0]),ee=Number(n[1]);return r===a?i<=ee:r<a},{message:`minOqseVersion nesm+� b+�t vy+�+�+� ne+� maxOqseVersion`,path:[`minOqseVersion`]});function vt(e){return Q.parse(e)}function yt(e){return Q.safeParse(e)}function bt(e){return e.issues.map(e=>{let t=e.path.map(e=>String(e)).join(`.`);return t?`${t}: ${e.message}`:e.message}).join(`
2
- `)}function xt(e){return Q.safeParse(e).success}var St=e.z.object({attempts:e.z.number().int().nonnegative(),incorrect:e.z.number().int().nonnegative(),streak:e.z.number().int().nonnegative()}).refine(e=>e.incorrect<=e.attempts,{message:`incorrect nesmí být vyšší než attempts`,path:[`incorrect`]}),Ct=e.z.object({isCorrect:e.z.boolean(),confidence:e.z.union([e.z.literal(1),e.z.literal(2),e.z.literal(3),e.z.literal(4)]).optional(),answeredAt:u,timeSpent:e.z.number().int().nonnegative().optional(),hintsUsed:e.z.number().int().nonnegative().optional(),isSkipped:e.z.boolean().optional()}).refine(e=>!e.isSkipped||e.isCorrect===!1,{message:`Pokud je isSkipped=true, isCorrect má být false`,path:[`isCorrect`]}),wt=e.z.object({bucket:e.z.union([e.z.literal(0),e.z.literal(1),e.z.literal(2),e.z.literal(3),e.z.literal(4)]),nextReviewAt:u.optional(),stats:St,lastAnswer:Ct.optional(),appSpecific:e.z.record(e.z.string(),e.z.unknown()).optional()}),Tt=e.z.object({setId:s,exportedAt:u,algorithm:e.z.string().regex(/^[a-z0-9-]+$/,`algorithm musí mít formát lowercase alphanumeric s pomlčkami`).optional()}),$=e.z.object({$schema:e.z.string().url().optional(),version:e.z.string().regex(/^\d+\.\d+$/,`Verze musí být ve formátu MAJOR.MINOR`),meta:Tt,records:e.z.record(s,wt)});function Et(e){return $.parse(e)}function Dt(e){return $.safeParse(e)}var Ot=/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;function kt(e){return Ot.test(e)}function At(){return crypto.randomUUID()}exports.AbsoluteURLSchema=d,exports.AssetDictionarySchema=_,exports.AssetKeySchema=f,exports.AudioMimeTypeSchema=pt,exports.BaseItemSchema=F,exports.BloomLevelSchema=k,exports.CameraSetupSchema=U,exports.CategorizeItemSchema=be,exports.CategorizeItemTypeSchema=ze,exports.ChessPuzzleItemSchema=qe,exports.CircleHotspotSchema=R,exports.CognitiveLoadSchema=A,exports.DiagramLabelItemSchema=Ue,exports.DiagramZoneSchema=Ce,exports.FeatureFlagSchema=lt,exports.FeatureProfileSchema=w,exports.FeatureRequirementSchema=E,exports.FeatureTypeSchema=T,exports.FillInBlanksItemSchema=Me,exports.FillInSelectItemSchema=Ne,exports.FlashcardItemSchema=Oe,exports.HotspotObjectSchema=V,exports.ISO8601DateTimeSchema=u,exports.ImageMimeTypeSchema=ft,exports.ItemPropertyKeySchema=ut,exports.LanguageCodeSchema=c,exports.LastAnswerObjectSchema=Ct,exports.LinkedSetObjectSchema=O,exports.MCQMultiItemSchema=je,exports.MCQSingleItemSchema=Ae,exports.ManifestAssetsSchema=gt,exports.ManifestCapabilitiesSchema=_t,exports.MatchComplexItemSchema=Fe,exports.MatchPairsItemSchema=Pe,exports.MathInputItemSchema=He,exports.MathRendererSchema=M,exports.MathSettingsSchema=N,exports.MatrixItemSchema=Ve,exports.MediaObjectSchema=ve,exports.MeshHotspotSchema=B,exports.MetaPropertyKeySchema=dt,exports.ModelMimeTypeSchema=ht,exports.NoteItemSchema=De,exports.NumericInputItemSchema=Ge,exports.NumericRangeSchema=Ee,exports.OQSEActionSchema=at,exports.OQSEFileSchema=K,exports.OQSEItemSchema=G,exports.OQSEManifestSchema=Q,exports.OQSEMetaSchema=P,exports.OQSEPFileSchema=$,exports.OQSEQuestionDensitySchema=st,exports.OQSEStudyModeSchema=ot,exports.OfficialFeatureNameSchema=ye,exports.OpenEndedItemSchema=We,exports.OptionalRichContentSchema=h,exports.PedagogySchema=j,exports.PersonObjectSchema=v,exports.PinOnImageItemSchema=Re,exports.PinOnModelItemSchema=Ke,exports.PlainTextSchema=p,exports.PolygonHotspotSchema=z,exports.ProgressMetaSchema=Tt,exports.ProgressRecordSchema=wt,exports.RectHotspotSchema=L,exports.RichContentSchema=m,exports.RubricCriterionSchema=we,exports.RubricSchema=Te,exports.SPDXLicenseSchema=l,exports.SelectBlankObjectSchema=I,exports.ShortAnswerItemSchema=W,exports.SliderItemSchema=Le,exports.SortItemsItemSchema=Ie,exports.SourceMaterialSchema=b,exports.SourceMaterialTypeSchema=y,exports.SourceReferenceSchema=x,exports.StatsObjectSchema=St,exports.SubtitleTrackSchema=g,exports.TagDefinitionDictionarySchema=C,exports.TagDefinitionSchema=S,exports.TimelineEventSchema=Se,exports.TimelineItemSchema=Be,exports.TimelinePrecisionSchema=xe,exports.TranslationObjectSchema=D,exports.TrueFalseItemSchema=ke,exports.UUIDSchema=s,exports.Vector3Schema=H,exports.VideoMimeTypeSchema=mt,exports.compareManifestVersions=J,exports.formatManifestErrors=bt,exports.formatValidationErrors=Qe,exports.generateUUID=At,exports.isCategorize=ce,exports.isChessPuzzle=ge,exports.isCoreItem=o,exports.isDiagramLabel=fe,exports.isExtendedItem=_e,exports.isFillInBlanks=te,exports.isFillInSelect=ne,exports.isFlashcard=n,exports.isMCQMulti=a,exports.isMCQSingle=i,exports.isMatchComplex=ie,exports.isMatchPairs=re,exports.isMathInput=de,exports.isMatrix=ue,exports.isNote=t,exports.isNumericInput=me,exports.isOQSEManifest=et,exports.isOpenEnded=pe,exports.isPinOnImage=se,exports.isPinOnModel=he,exports.isShortAnswer=ee,exports.isSlider=oe,exports.isSortItems=ae,exports.isTimeline=le,exports.isTrueFalse=r,exports.isValidManifestVersion=q,exports.isValidOQSEManifest=xt,exports.isValidSemVer=$e,exports.isValidUUID=kt,exports.isVersionCompatible=tt,exports.safeValidateManifest=yt,exports.safeValidateOQSEFile=Ye,exports.safeValidateOQSEItem=Ze,exports.safeValidateOQSEPFile=Dt,exports.validateManifest=vt,exports.validateOQSEFile=Je,exports.validateOQSEItem=Xe,exports.validateOQSEPFile=Et;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require(`zod`);function t(e){return e.type===`note`}function n(e){return e.type===`flashcard`}function r(e){return e.type===`true-false`}function i(e){return e.type===`mcq-single`}function a(e){return e.type===`mcq-multi`}function o(e){return e.type===`short-answer`}function ee(e){return e.type===`fill-in-blanks`}function te(e){return e.type===`fill-in-select`}function ne(e){return e.type===`match-pairs`}function re(e){return e.type===`match-complex`}function ie(e){return e.type===`sort-items`}function ae(e){return e.type===`slider`}function oe(e){return e.type===`pin-on-image`}function se(e){return e.type===`categorize`}function ce(e){return e.type===`timeline`}function le(e){return e.type===`matrix`}function ue(e){return e.type===`math-input`}function de(e){return e.type===`diagram-label`}function fe(e){return e.type===`open-ended`}function pe(e){return e.type===`numeric-input`}function me(e){return e.type===`pin-on-model`}function he(e){return e.type===`chess-puzzle`}function s(e){return[`note`,`flashcard`,`mcq-single`,`short-answer`].includes(e.type)}function ge(e){return!s(e)}var c=[`render`,`edit`,`validate`,`import`,`export`],l=[`markdown`,`math`,`rtl`,`html`,`syntax-highlighting`,`mermaid`,`smiles`,`abc-notation`,`text-to-speech`,`voice-input`,`handwriting-recognition`],u=[`hints`,`explanation`,`incorrectFeedback`,`sources`,`relatedItems`,`dependencyItems`,`timeLimit`,`lang`,`topic`,`pedagogy`],d=[`description`,`thumbnail`,`subject`,`language`,`author`,`contributors`,`license`,`ageRestriction`,`tags`,`tagDefinitions`,`sourceMaterials`,`estimatedTime`,`prerequisites`,`translations`,`relatedSets`];function f(e){return/^\d+\.\d+$/.test(e)}function _e(e){return/^\d+\.\d+\.\d+(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$/.test(e)}function p(e,t){let[n=0,r=0]=e.split(`.`).map(Number),[i=0,a=0]=t.split(`.`).map(Number);return n===i?r-a:n-i}function ve(e){if(typeof e!=`object`||!e)return!1;let t=e,n=t.author;return typeof t.version==`string`&&typeof t.id==`string`&&typeof t.appName==`string`&&t.appName!==``&&(n===void 0||typeof n==`object`&&!!n)&&typeof t.capabilities==`object`&&t.capabilities!==null&&Array.isArray(t.capabilities.actions)}function ye(e,t){return!(!f(e)||t.minOqseVersion&&f(t.minOqseVersion)&&p(e,t.minOqseVersion)<0||t.maxOqseVersion&&f(t.maxOqseVersion)&&p(e,t.maxOqseVersion)>0)}var be=/^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/i;function xe(e){return typeof e==`string`&&be.test(e)}var m=[];for(let e=0;e<256;++e)m.push((e+256).toString(16).slice(1));function Se(e,t=0){return(m[e[t+0]]+m[e[t+1]]+m[e[t+2]]+m[e[t+3]]+`-`+m[e[t+4]]+m[e[t+5]]+`-`+m[e[t+6]]+m[e[t+7]]+`-`+m[e[t+8]]+m[e[t+9]]+`-`+m[e[t+10]]+m[e[t+11]]+m[e[t+12]]+m[e[t+13]]+m[e[t+14]]+m[e[t+15]]).toLowerCase()}var h,Ce=new Uint8Array(16);function we(){if(!h){if(typeof crypto>`u`||!crypto.getRandomValues)throw Error(`crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported`);h=crypto.getRandomValues.bind(crypto)}return h(Ce)}var g={};function Te(e,t,n){let r;if(e)r=De(e.random??e.rng?.()??we(),e.msecs,e.seq,t,n);else{let e=Date.now(),i=we();Ee(g,e,i),r=De(i,g.msecs,g.seq,t,n)}return t??Se(r)}function Ee(e,t,n){return e.msecs??=-1/0,e.seq??=0,t>e.msecs?(e.seq=n[6]<<23|n[7]<<16|n[8]<<8|n[9],e.msecs=t):(e.seq=e.seq+1|0,e.seq===0&&e.msecs++),e}function De(e,t,n,r,i=0){if(e.length<16)throw Error(`Random bytes length must be >= 16`);if(!r)r=new Uint8Array(16),i=0;else if(i<0||i+16>r.length)throw RangeError(`UUID byte range ${i}:${i+15} is out of buffer bounds`);return t??=Date.now(),n??=e[6]*127<<24|e[7]<<16|e[8]<<8|e[9],r[i++]=t/1099511627776&255,r[i++]=t/4294967296&255,r[i++]=t/16777216&255,r[i++]=t/65536&255,r[i++]=t/256&255,r[i++]=t&255,r[i++]=112|n>>>28&15,r[i++]=n>>>20&255,r[i++]=128|n>>>14&63,r[i++]=n>>>6&255,r[i++]=n<<2&255|e[10]&3,r[i++]=e[11],r[i++]=e[12],r[i++]=e[13],r[i++]=e[14],r[i++]=e[15],r}function Oe(e){return xe(e)}function ke(){return Te()}function _(e,t=10,n=0){if(n>t)throw Error(`OQSE Security Error: Maximum nesting depth exceeded limit of ${t} levels.`);if(typeof e==`object`&&e){let r=Array.isArray(e)?e:Object.values(e);for(let e of r)_(e,t,n+1)}}var v=e.z.string().uuid({message:`Invalid UUID format`}),y=e.z.string().min(2,`Language code must have at least 2 characters`).regex(/^[a-z]{2,3}(-[A-Z][a-z]{3})?(-[A-Z]{2})?$/,`Invalid BCP 47 format (e.g. "cs", "en-US")`),b=e.z.string().min(1,`License identifier must not be empty`),x=e.z.string().regex(/^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2}(\.\d{3})?(Z|[+-]\d{2}:\d{2})?)?$/,`Invalid ISO 8601 format (e.g. "2025-11-21T14:30:00Z")`),S=e.z.string().url({message:`Must be a valid absolute URL`}),C=e.z.string().regex(/^[a-z0-9_-]+$/,`Asset key must contain only lowercase letters, numbers, hyphens and underscores`),w=e.z.string().min(1,`Text must not be empty`),T=e.z.string().min(1,`Content must not be empty`),E=e.z.string().max(1e4,`Question must not be longer than 10000 characters`).optional(),D=e.z.string().regex(/^[a-zA-Z0-9_-]{1,64}$/,`Token must be alphanumeric, max 64 chars`),O=e.z.object({lang:y,value:e.z.string().min(1,`Subtitle URI must not be empty`).regex(/\.(vtt|srt)(\?.*)?$/i,`Subtitle URI must end with .vtt or .srt`),label:e.z.string().optional(),kind:e.z.enum([`captions`,`subtitles`,`descriptions`]).optional()}),k=e.z.object({type:e.z.enum([`image`,`audio`,`video`,`model`]),value:e.z.string().min(1,`Media URI must not be empty`),mimeType:e.z.string().optional(),altText:e.z.string().optional(),transcript:T.optional(),caption:T.optional(),width:e.z.number().int().positive().optional(),height:e.z.number().int().positive().optional(),start:e.z.number().nonnegative().optional(),end:e.z.number().positive().optional(),loop:e.z.boolean().optional(),subtitles:e.z.array(O).optional(),license:b.optional(),attribution:e.z.string().optional(),checksums:e.z.record(e.z.string(),e.z.string()).optional()}).refine(e=>e.start!==void 0&&e.end!==void 0?e.start<e.end:!0,{message:`Start time must be less than end time`,path:[`end`]}).refine(e=>!(e.type===`image`&&!e.altText),{message:`Images must have alternative text (altText) defined for accessibility`,path:[`altText`]}),A=e.z.record(C,k),j=e.z.object({name:w,role:e.z.string().optional(),email:e.z.string().email(`Invalid email format`).optional(),url:S.optional()}),M=e.z.enum([`url`,`doi`,`isbn`,`pdf`,`textbook`,`video`,`audio`,`image`,`model`,`other`]),N=e.z.object({id:w,type:M,value:w,title:w,description:e.z.string().optional(),authors:e.z.array(w).optional(),publishedDate:x.optional(),retrievedAt:x.optional(),license:b.optional()}).refine(e=>{if([`url`,`pdf`,`video`,`audio`,`image`].includes(e.type))try{return new URL(e.value),!0}catch{return!1}return!0},{message:`For url, pdf, video, audio and image types, value must be a valid URL`,path:[`value`]}),P=e.z.object({id:w,location:e.z.string().optional(),quote:T.optional()}),Ae=e.z.object({wikidataId:e.z.string().regex(/^Q\d+$/,`Wikidata ID must have format Q followed by number`).optional(),description:e.z.string().optional()}),je=e.z.record(e.z.string(),Ae),F=e.z.object({features:e.z.array(e.z.string().refine(e=>l.includes(e)||e.startsWith(`x-`),{message:`Feature must be an official key or have prefix "x-"`})).optional(),latexPackages:e.z.array(e.z.string().min(1,`Package name must not be empty`)).optional(),itemProperties:e.z.array(e.z.string().refine(e=>u.includes(e)||e.startsWith(`x-`),{message:`Item property must be an official key or have prefix "x-"`})).optional(),metaProperties:e.z.array(e.z.string().refine(e=>d.includes(e)||e.startsWith(`x-`),{message:`Meta property must be an official key or have prefix "x-"`})).optional()}),Me=e.z.object({lang:y,id:v,title:w,downloadUrl:S.optional()}),I=e.z.object({id:v,title:w,downloadUrl:S.optional()}),Ne=e.z.enum([`remember`,`understand`,`apply`,`analyze`,`evaluate`,`create`]),Pe=e.z.enum([`low`,`medium`,`high`]),Fe=e.z.object({bloomLevel:Ne.optional(),irtDifficulty:e.z.number().optional(),irtDiscrimination:e.z.number().optional(),irtGuessing:e.z.number().min(0).max(1,`IRT guessing must be between 0 and 1`).optional(),avgTime:e.z.number().positive().optional(),cognitiveLoad:Pe.optional(),partialCredit:e.z.boolean().optional(),penaltyPerWrong:e.z.number().min(0).max(1,`Penalty must be between 0 and 1`).optional()}),L=e.z.object({id:v,language:y,title:w.max(500,`Title must not be longer than 500 characters`),description:T.max(5e3,`Description must not be longer than 5000 characters`).optional(),thumbnail:C.optional(),assets:A.optional(),ageMin:e.z.number().int().nonnegative().optional(),ageMax:e.z.number().int().nonnegative().optional(),subject:e.z.string().optional(),createdAt:x,updatedAt:x,author:j.optional(),contributors:e.z.array(j).optional(),license:b.optional(),licenseUrl:S.optional(),requirements:F.optional(),tags:e.z.array(w).optional(),tagDefinitions:je.optional(),translations:e.z.array(Me).optional(),sourceMaterials:e.z.array(N).optional(),estimatedTime:e.z.number().positive().optional(),prerequisites:e.z.array(I).optional(),relatedSets:e.z.array(I).optional(),customData:e.z.record(e.z.string(),e.z.unknown()).optional(),appSpecific:e.z.record(e.z.string(),e.z.unknown()).optional()}).refine(e=>e.ageMin!==void 0&&e.ageMax!==void 0?e.ageMin<=e.ageMax:!0,{message:`Minimum age (ageMin) must be less than or equal to maximum age (ageMax)`,path:[`ageMax`]}).refine(e=>new Date(e.createdAt)<=new Date(e.updatedAt),{message:`Creation date (createdAt) must be before or equal to update date (updatedAt)`,path:[`updatedAt`]}),R=e.z.object({id:v,type:e.z.string(),assets:A.optional(),lang:y.optional(),tags:e.z.array(w).optional(),topic:w.optional(),difficulty:e.z.number().int().min(1,`Difficulty must be at least 1`).max(5,`Difficulty must be at most 5`).optional(),timeLimit:e.z.number().positive(`Time limit must be a positive number`).optional(),hints:e.z.array(T.max(2e3,`Hint must not be longer than 2000 characters`)).max(20,`Maximum 20 hints per item`).optional(),explanation:T.max(1e4,`Explanation must not be longer than 10000 characters`).optional(),incorrectFeedback:T.optional(),sources:e.z.array(P).optional(),relatedItems:e.z.array(v).optional(),dependencyItems:e.z.array(v).optional(),pedagogy:Fe.optional(),customData:e.z.record(e.z.string(),e.z.unknown()).optional(),appSpecific:e.z.record(e.z.string(),e.z.unknown()).optional()}),Ie=e.z.object({options:e.z.array(T).min(1,`Must have at least 1 option`),correctIndex:e.z.number().int().nonnegative()}).refine(e=>e.correctIndex<e.options.length,{message:`Correct answer index references non-existent option`,path:[`correctIndex`]}),z=e.z.object({type:e.z.literal(`rect`),label:e.z.string().optional(),x:e.z.number().min(0).max(100,`X must be in range 0-100%`),y:e.z.number().min(0).max(100,`Y must be in range 0-100%`),width:e.z.number().min(0).max(100,`Width must be in range 0-100%`),height:e.z.number().min(0).max(100,`Height must be in range 0-100%`)}),B=e.z.object({type:e.z.literal(`circle`),label:e.z.string().optional(),x:e.z.number().min(0).max(100,`X must be in range 0-100%`),y:e.z.number().min(0).max(100,`Y must be in range 0-100%`),radius:e.z.number().min(0).max(100,`Radius must be in range 0-100%`)}),V=e.z.object({type:e.z.literal(`polygon`),label:e.z.string().optional(),points:e.z.array(e.z.object({x:e.z.number().min(0).max(100),y:e.z.number().min(0).max(100)})).min(3,`Polygon must have at least 3 points`)}),H=e.z.object({type:e.z.literal(`mesh`),label:e.z.string().optional(),targetName:w}),Le=e.z.discriminatedUnion(`type`,[z,B,V,H]),Re=e.z.discriminatedUnion(`type`,[z,B,V]),U=e.z.object({x:e.z.number(),y:e.z.number(),z:e.z.number()}),ze=e.z.object({position:U.optional(),target:U.optional()}),Be=e.z.object({id:w,text:T,correctCategoryIndex:e.z.number().int().nonnegative()}),Ve=e.z.enum([`year`,`month`,`day`,`datetime`]),He=e.z.object({id:w,text:T,date:x,precision:Ve.optional()}),Ue=e.z.union([z.extend({correctLabelIndex:e.z.number().int().nonnegative()}),B.extend({correctLabelIndex:e.z.number().int().nonnegative()}),V.extend({correctLabelIndex:e.z.number().int().nonnegative()})]),W=e.z.object({label:w,percentage:e.z.number().min(0,`Percentage must be non-negative`).max(100,`Percentage must not exceed 100`),description:e.z.string().optional()}),We=e.z.object({criteria:e.z.array(W).min(1,`Rubric must have at least 1 criterion`)}).refine(e=>e.criteria.reduce((e,t)=>e+t.percentage,0)>0,{message:`Sum of percentages of all criteria must be greater than 0`,path:[`criteria`]}),Ge=e.z.object({min:e.z.number(),max:e.z.number()}).refine(e=>e.min<=e.max,{message:`Minimum value must be less than or equal to maximum value`,path:[`max`]}),Ke=R.extend({type:e.z.literal(`note`),title:e.z.string().optional(),content:T.max(1e4,`Content must not be longer than 10000 characters`),hiddenContent:T.max(1e4,`Content must not be longer than 10000 characters`).optional()}),qe=R.extend({type:e.z.literal(`flashcard`),front:T.max(1e4,`Front side must not be longer than 10000 characters`),back:T.max(1e4,`Back side must not be longer than 10000 characters`)}),Je=R.extend({type:e.z.literal(`true-false`),question:T.max(1e4,`Question must not be longer than 10000 characters`),answer:e.z.boolean()}),Ye=R.extend({type:e.z.literal(`mcq-single`),question:T.max(1e4,`Question must not be longer than 10000 characters`),options:e.z.array(T.max(2e3,`Option must not be longer than 2000 characters`)).min(2,`Question must have at least 2 options`).max(100,`Maximum 100 options`),correctIndex:e.z.number().int().nonnegative(),shuffleOptions:e.z.boolean().optional(),optionExplanations:e.z.array(e.z.union([T,e.z.null()])).optional()}).refine(e=>e.correctIndex<e.options.length,{message:`Correct answer index references non-existent option`,path:[`correctIndex`]}).refine(e=>e.optionExplanations?e.optionExplanations.length===e.options.length:!0,{message:`Number of option explanations must match number of options`,path:[`optionExplanations`]}).refine(e=>new Set(e.options.map(e=>e.toLowerCase())).size===e.options.length,{message:`Options must not contain duplicates (case-insensitive)`,path:[`options`]}),Xe=R.extend({type:e.z.literal(`mcq-multi`),question:T.max(1e4,`Question must not be longer than 10000 characters`),options:e.z.array(T.max(2e3,`Option must not be longer than 2000 characters`)).min(2,`Question must have at least 2 options`).max(100,`Maximum 100 options`),correctIndices:e.z.array(e.z.number().int().nonnegative()).min(1,`Must have at least 1 correct answer`),minSelections:e.z.number().int().positive().optional(),maxSelections:e.z.number().int().positive().optional(),shuffleOptions:e.z.boolean().optional(),optionExplanations:e.z.array(e.z.union([T,e.z.null()])).optional()}).refine(e=>e.correctIndices.every(t=>t<e.options.length),{message:`Some of correct answer indices reference non-existent option`,path:[`correctIndices`]}).refine(e=>new Set(e.correctIndices).size===e.correctIndices.length,{message:`Correct answer indices contain duplicates`,path:[`correctIndices`]}).refine(e=>e.minSelections&&e.maxSelections?e.minSelections<=e.maxSelections:!0,{message:`Minimum number of selections must be less than or equal to maximum`,path:[`maxSelections`]}).refine(e=>e.maxSelections?e.maxSelections<=e.options.length:!0,{message:`Maximum number of selections must not exceed number of options`,path:[`maxSelections`]}).refine(e=>e.minSelections?e.minSelections<=e.options.length:!0,{message:`minSelections cannot be greater than the number of options`,path:[`minSelections`]}).refine(e=>e.optionExplanations?e.optionExplanations.length===e.options.length:!0,{message:`Number of option explanations must match number of options`,path:[`optionExplanations`]}).refine(e=>new Set(e.options.map(e=>e.toLowerCase())).size===e.options.length,{message:`Options must not contain duplicates (case-insensitive)`,path:[`options`]}),Ze=R.extend({type:e.z.literal(`short-answer`),question:T.max(1e4,`Question must not be longer than 10000 characters`),answers:e.z.array(w).min(1,`Must have at least 1 correct answer`),caseSensitive:e.z.boolean().optional(),trimWhitespace:e.z.boolean().optional(),acceptPartial:e.z.boolean().optional(),ignoreDiacritics:e.z.boolean().optional()}),Qe=R.extend({type:e.z.literal(`fill-in-blanks`),question:E,text:T.max(1e4,`Text must not be longer than 10000 characters`),blanks:e.z.record(D,e.z.array(w).min(1,`Each blank must have at least 1 correct answer`)),caseSensitive:e.z.boolean().optional(),trimWhitespace:e.z.boolean().optional()}).refine(e=>Object.keys(e.blanks).length>0,{message:`Text must contain at least 1 blank to fill`,path:[`blanks`]}).refine(e=>{let t=/<blank:([a-zA-Z0-9_-]{1,64})\s*\/>/g,n=new Set,r;for(;(r=t.exec(e.text))!==null;)r[1]&&n.add(r[1]);let i=new Set(Object.keys(e.blanks));for(let e of n)if(!i.has(e))return!1;for(let e of i)if(!n.has(e))return!1;return!0},{message:`All tokens in text must have definition in blanks and all definitions must be used in text`,path:[`blanks`]}),$e=R.extend({type:e.z.literal(`fill-in-select`),question:E,text:T.max(1e4,`Text must not be longer than 10000 characters`),blanks:e.z.record(D,Ie)}).refine(e=>Object.keys(e.blanks).length>0,{message:`Text must contain at least 1 blank to select`,path:[`blanks`]}).refine(e=>{let t=/<blank:([a-zA-Z0-9_-]{1,64})\s*\/>/g,n=new Set,r;for(;(r=t.exec(e.text))!==null;)r[1]&&n.add(r[1]);let i=new Set(Object.keys(e.blanks));for(let e of n)if(!i.has(e))return!1;for(let e of i)if(!n.has(e))return!1;return!0},{message:`All tokens in text must have definition in blanks and all definitions must be used in text`,path:[`blanks`]}),et=R.extend({type:e.z.literal(`match-pairs`),question:E,prompts:e.z.array(T).min(2,`Must have at least 2 pairs to match`).max(100,`Maximum 100 pairs`),matches:e.z.array(T).min(2,`Must have at least 2 pairs to match`).max(100,`Maximum 100 pairs`)}).refine(e=>e.prompts.length===e.matches.length,{message:`Number of prompts must match number of matches`,path:[`matches`]}),tt=R.extend({type:e.z.literal(`match-complex`),question:E,leftItems:e.z.array(T).min(1,`Must have at least 1 item on left`),rightItems:e.z.array(T).min(1,`Must have at least 1 item on right`),connections:e.z.array(e.z.tuple([e.z.number().int().nonnegative(),e.z.number().int().nonnegative()])).min(1,`Must have at least 1 connection`),minCorrect:e.z.number().int().positive().optional()}).refine(e=>e.connections.every(([t,n])=>t<e.leftItems.length&&n<e.rightItems.length),{message:`Some connection references non-existent item`,path:[`connections`]}).refine(e=>new Set(e.connections.map(e=>`${e[0]}-${e[1]}`)).size===e.connections.length,{message:`Connections contain duplicates`,path:[`connections`]}).refine(e=>e.minCorrect?e.minCorrect<=e.connections.length:!0,{message:`Minimum correct answers must not exceed total number of connections`,path:[`minCorrect`]}),nt=R.extend({type:e.z.literal(`sort-items`),question:T.max(1e4,`Question must not be longer than 10000 characters`),items:e.z.array(T).min(2,`Must have at least 2 items to sort`)}),rt=R.extend({type:e.z.literal(`slider`),question:T.max(1e4,`Question must not be longer than 10000 characters`),min:e.z.number(),max:e.z.number(),step:e.z.number().positive(`Step must be a positive number`),correctAnswer:e.z.number(),tolerance:e.z.number().nonnegative(`Tolerance must be non-negative`),unit:e.z.string().optional()}).refine(e=>e.min<e.max,{message:`Minimum value must be less than maximum value`,path:[`max`]}).refine(e=>e.correctAnswer>=e.min&&e.correctAnswer<=e.max,{message:`Correct answer must be in range min-max`,path:[`correctAnswer`]}).refine(e=>{let t=(e.correctAnswer-e.min)/e.step;return Math.abs(t-Math.round(t))<1e-4},{message:`Correct answer must be reachable by defined step`,path:[`correctAnswer`]}).refine(e=>e.tolerance<=(e.max-e.min)/2,{message:`Tolerance must not be greater than half of value range`,path:[`tolerance`]}),it=R.extend({type:e.z.literal(`pin-on-image`),question:T.max(1e4,`Question must not be longer than 10000 characters`),targetAsset:C,hotspots:e.z.array(Re).min(1,`Must have at least 1 hotspot`),multipleCorrect:e.z.boolean().optional(),minCorrect:e.z.number().int().positive().optional()}).refine(e=>e.minCorrect?e.minCorrect<=e.hotspots.length:!0,{message:`Minimum correct answers must not exceed number of hotspots`,path:[`minCorrect`]}),at=R.extend({type:e.z.literal(`categorize`),question:T.max(1e4,`Question must not be longer than 10000 characters`),categories:e.z.array(w).min(2,`Must have at least 2 categories`),items:e.z.array(Be).min(1,`Must have at least 1 item to categorize`)}).refine(e=>new Set(e.categories.map(e=>e.toLowerCase())).size===e.categories.length,{message:`Categories must not contain duplicates (case-insensitive)`,path:[`categories`]}).refine(e=>e.items.every(t=>t.correctCategoryIndex<e.categories.length),{message:`Some item references non-existent category`,path:[`items`]}),ot=R.extend({type:e.z.literal(`timeline`),question:T.max(1e4,`Question must not be longer than 10000 characters`),events:e.z.array(He).min(2,`Must have at least 2 events`),randomize:e.z.boolean().optional()}),st=R.extend({type:e.z.literal(`matrix`),question:T.max(1e4,`Question must not be longer than 10000 characters`),rows:e.z.array(w).min(1,`Must have at least 1 row`),columns:e.z.array(w).min(1,`Must have at least 1 column`),correctCells:e.z.array(e.z.tuple([e.z.number().int().nonnegative(),e.z.number().int().nonnegative()])).min(1,`Must have at least 1 correct cell`),multiplePerRow:e.z.boolean().optional()}).refine(e=>e.correctCells.every(([t,n])=>t<e.rows.length&&n<e.columns.length),{message:`Some cell coordinates reference non-existent row or column`,path:[`correctCells`]}).refine(e=>new Set(e.correctCells.map(e=>`${e[0]}-${e[1]}`)).size===e.correctCells.length,{message:`Correct cells contain duplicates`,path:[`correctCells`]}).refine(e=>{if(!e.multiplePerRow){let t=new Map;for(let[n]of e.correctCells)t.set(n,(t.get(n)||0)+1);return Array.from(t.values()).every(e=>e<=1)}return!0},{message:`If multiplePerRow is false, each row may have maximum 1 correct cell`,path:[`correctCells`]}),ct=R.extend({type:e.z.literal(`math-input`),question:T.max(1e4,`Question must not be longer than 10000 characters`),correctAnswer:w,alternativeAnswers:e.z.array(w).optional(),tolerance:e.z.number().nonnegative().optional()}),lt=R.extend({type:e.z.literal(`diagram-label`),question:T.max(1e4,`Question must not be longer than 10000 characters`),targetAsset:C,labels:e.z.array(T).min(1,`Must have at least 1 label`),caseSensitive:e.z.boolean().optional(),requireTyping:e.z.boolean().optional(),zones:e.z.array(Ue).min(1,`Must have at least 1 zone`)}).refine(e=>e.zones.every(t=>t.correctLabelIndex<e.labels.length),{message:`Some zone references non-existent label`,path:[`zones`]}),ut=R.extend({type:e.z.literal(`open-ended`),question:T.max(1e4,`Question must not be longer than 10000 characters`),minWords:e.z.number().int().positive().optional(),maxWords:e.z.number().int().positive().optional(),sampleAnswer:T.optional(),rubric:We.optional()}).refine(e=>e.minWords&&e.maxWords?e.minWords<=e.maxWords:!0,{message:`Minimum word count must be less than or equal to maximum`,path:[`maxWords`]}),dt=R.extend({type:e.z.literal(`numeric-input`),question:T.max(1e4,`Question must not be longer than 10000 characters`),value:e.z.number(),tolerance:e.z.number().nonnegative().optional(),range:Ge.optional(),unit:e.z.string().optional()}),ft=R.extend({type:e.z.literal(`pin-on-model`),question:T.max(1e4,`Question must not be longer than 10000 characters`),targetAsset:C,hotspots:e.z.array(H).min(1,`Must have at least 1 hotspot`),multipleCorrect:e.z.boolean().optional(),minCorrect:e.z.number().int().positive().optional(),camera:ze.optional()}).refine(e=>e.minCorrect?e.minCorrect<=e.hotspots.length:!0,{message:`Minimum correct answers must not exceed number of hotspots`,path:[`minCorrect`]}),pt=R.extend({type:e.z.literal(`chess-puzzle`),question:T.max(1e4,`Question must not be longer than 10000 characters`),fen:w,answers:e.z.array(e.z.array(w).min(1,`Move sequence must not be empty`)).min(1,`Must have at least 1 correct move sequence`),elo:e.z.number().int().nonnegative(`ELO must be non-negative integer`).optional()}),G=e.z.discriminatedUnion(`type`,[Ke,qe,Je,Ye,Xe,Ze,Qe,$e,et,tt,nt,rt,it,at,ot,st,ct,lt,ut,dt,ft,pt]),K=e.z.object({$schema:e.z.string().url().optional(),version:e.z.string().regex(/^\d+\.\d+$/,`Version must be in MAJOR.MINOR format (e.g. "0.1")`),meta:L,items:e.z.array(G).max(1e4,`Maximum 10000 items per set`)}).refine(e=>{let t=new Set(e.items.map(e=>e.id));for(let n of e.items){if(n.relatedItems){for(let e of n.relatedItems)if(!t.has(e)||n.id===e)return!1}if(n.dependencyItems){for(let e of n.dependencyItems)if(!t.has(e)||n.id===e)return!1}}return!0},{message:`Some item references non-existent relatedItems, dependencyItems, or references itself`,path:[`items`]}).refine(e=>e.meta.thumbnail&&e.meta.assets?e.meta.thumbnail in e.meta.assets:!0,{message:`Thumbnail references non-existent asset`,path:[`meta`,`thumbnail`]}).refine(e=>{let t=new Set((e.meta.sourceMaterials||[]).map(e=>e.id));for(let n of e.items)if(n.sources){for(let e of n.sources)if(!t.has(e.id))return!1}return!0},{message:`Some item references non-existent source material`,path:[`items`]});function mt(t){let n=t instanceof Error?t.message:`OQSE Security Error: Maximum nesting depth exceeded limit of 10 levels.`;return new e.z.ZodError([{code:e.z.ZodIssueCode.custom,message:n,path:[]}])}function ht(e){return _(e,10),K.parse(e)}function gt(e){try{_(e,10)}catch(e){return{success:!1,error:mt(e)}}let t=K.safeParse(e);return t.success?{success:!0,data:t.data}:{success:!1,error:t.error}}function _t(e){return _(e,10),G.parse(e)}function vt(e){try{_(e,10)}catch(e){return{success:!1,error:mt(e)}}let t=G.safeParse(e);return t.success?{success:!0,data:t.data}:{success:!1,error:t.error}}function yt(e){return e.issues.map(e=>{let t=``;return e.path.forEach((n,r)=>{if(typeof n==`number`)t+=`[${n}]`;else{let i=r===0||typeof e.path[r-1]==`number`;t+=(i?``:`.`)+String(n)}}),t?`${t}: ${e.message}`:e.message})}var q=e.z.string().min(1,`Value must not be empty`).trim(),bt=e.z.string().regex(/^[a-zA-Z]{2,8}(-[a-zA-Z0-9\-]+)*$/,`Must be a valid BCP 47 locale (e.g., "en", "cs")`),J=e.z.string().url(`Must be a valid absolute URL`).refine(e=>e.startsWith(`http://`)||e.startsWith(`https://`),{message:`URL must use http or https scheme`}),xt=e.z.string().regex(/^urn:uuid:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,`Must be a valid URN UUID (urn:uuid:...)`),Y=e.z.string().regex(/^\d+\.\d+$/,`Version must be in MAJOR.MINOR format (e.g. "0.1")`),St=[`note`,`flashcard`,`true-false`,`mcq-single`,`mcq-multi`,`short-answer`,`fill-in-blanks`,`fill-in-select`,`match-pairs`,`match-complex`,`sort-items`,`slider`,`pin-on-image`,`categorize`,`timeline`,`matrix`,`math-input`,`diagram-label`,`open-ended`,`numeric-input`,`pin-on-model`,`chess-puzzle`],Ct=q.refine(e=>St.includes(e)||e.startsWith(`x-`),{message:`Custom types MUST use the "x-" prefix`}),wt=e.z.string().refine(e=>c.includes(e)||e.startsWith(`x-`),{message:`Action must be one of [render, edit, validate, import, export] or have prefix "x-"`}),Tt=e.z.enum([`game`,`fun`,`drill`]),Et=e.z.enum([`low`,`medium`,`high`]),Dt=e.z.string().refine(e=>l.includes(e)||e.startsWith(`x-`),{message:`Feature must be one of official keys or have prefix "x-"`}),Ot=e.z.string().refine(e=>u.includes(e)||e.startsWith(`x-`),{message:`Item property must be an official key or have prefix "x-"`}),kt=e.z.string().refine(e=>d.includes(e)||e.startsWith(`x-`),{message:`Meta property must be an official key or have prefix "x-"`});function X(t){return e.z.union([e.z.tuple([e.z.literal(`*`)]),e.z.array(t),e.z.null()])}var At=e.z.string().refine(e=>e.startsWith(`image/`),{message:`Must be a valid image MIME type (image/...)`}),jt=e.z.string().refine(e=>e.startsWith(`audio/`),{message:`Must be a valid audio MIME type (audio/...)`}),Mt=e.z.string().refine(e=>e.startsWith(`video/`),{message:`Must be a valid video MIME type (video/...)`}),Nt=e.z.string().refine(e=>e.startsWith(`model/`)||e===`application/octet-stream`,{message:`Must be a valid 3D model MIME type (model/... or application/octet-stream)`}),Pt=e.z.object({image:X(At).optional(),audio:X(jt).optional(),video:X(Mt).optional(),model:X(Nt).optional()}),Ft=F.extend({actions:e.z.array(wt).min(1,`Application must support at least one action`),types:X(Ct).optional(),assets:Pt.optional()}).superRefine((t,n)=>{(t.actions.includes(`render`)||t.actions.includes(`edit`))&&(!Array.isArray(t.types)||t.types.length===0)&&n.addIssue({code:e.z.ZodIssueCode.custom,message:`types array MUST be declared and non-empty when actions include "render" or "edit"`,path:[`types`]})}),Z=e.z.object({$schema:J.optional(),id:e.z.union([J,xt]),appName:q.max(200,`Name must not be longer than 200 characters`),version:Y,pluginVersion:e.z.string().optional(),minOqseVersion:Y.optional(),maxOqseVersion:Y.optional(),capabilities:Ft,author:j.optional(),contributors:e.z.array(j).optional(),license:e.z.string().max(100,`License must not be longer than 100 characters`).optional(),licenseUrl:J.optional(),locales:e.z.array(bt).optional(),description:e.z.string().max(5e3,`Description must not be longer than 5000 characters`).optional(),emoji:e.z.string().optional(),tags:e.z.array(q).optional(),studyMode:Tt.optional(),questionDensity:Et.optional(),appSpecific:e.z.record(e.z.string(),e.z.unknown()).optional()}).refine(e=>{if(!e.minOqseVersion||!e.maxOqseVersion)return!0;let t=e.minOqseVersion.split(`.`),n=e.maxOqseVersion.split(`.`),r=Number(t[0]),i=Number(t[1]),a=Number(n[0]),o=Number(n[1]);return r===a?i<=o:r<a},{message:`minOqseVersion must not be greater than maxOqseVersion`,path:[`minOqseVersion`]});function It(e){return Z.parse(e)}function Lt(e){return Z.safeParse(e)}function Rt(e){return e.issues.map(e=>{let t=e.path.map(e=>String(e)).join(`.`);return t?`${t}: ${e.message}`:e.message}).join(`
2
+ `)}function zt(e){return Z.safeParse(e).success}var Bt=e.z.object({attempts:e.z.number().int().nonnegative(),incorrect:e.z.number().int().nonnegative(),streak:e.z.number().int().nonnegative()}).refine(e=>e.incorrect<=e.attempts,{message:`incorrect cannot be higher than attempts`,path:[`incorrect`]}),Vt=e.z.object({isCorrect:e.z.boolean(),confidence:e.z.union([e.z.literal(1),e.z.literal(2),e.z.literal(3),e.z.literal(4)]).optional(),answeredAt:x,timeSpent:e.z.number().int().nonnegative().optional(),hintsUsed:e.z.number().int().nonnegative().default(0),isSkipped:e.z.boolean().optional()}),Ht=e.z.object({bucket:e.z.union([e.z.literal(0),e.z.literal(1),e.z.literal(2),e.z.literal(3),e.z.literal(4)]),nextReviewAt:x.optional(),stats:Bt,lastAnswer:Vt.optional(),appSpecific:e.z.record(e.z.string(),e.z.unknown()).optional()}),Ut=e.z.object({setId:v,exportedAt:x,algorithm:e.z.string().regex(/^[a-z0-9-]+$/,`algorithm must be lowercase alphanumeric with hyphens format`).optional()}),Q=e.z.object({$schema:e.z.url().optional(),version:e.z.string().regex(/^\d+\.\d+$/,`Version must be in MAJOR.MINOR format`),meta:Ut,records:e.z.record(v,Ht)});function Wt(e){return Q.parse(e)}function Gt(e){return Q.safeParse(e)}var $=e.z.object(L.shape).pick({id:!0,title:!0,language:!0,updatedAt:!0,description:!0,author:!0,subject:!0,tags:!0,createdAt:!0,estimatedTime:!0,requirements:!0}).partial({createdAt:!0}).extend({url:S,$schema:e.z.string().url().optional()});function Kt(e){return $.parse(e)}function qt(e){return $.safeParse(e)}function Jt(e){let t={};return{text:e.replace(/<(asset|blank):([a-zA-Z0-9_-]+)\s*\/>/gi,(e,n,r)=>{let i=`[[__OQSE_TOKEN_${Math.random().toString(36).substring(2,15)}__]]`;return t[i]={type:n.toLowerCase(),key:r.toLowerCase(),originalTag:e},i}),tokens:t}}function Yt(e){let t=e.replace(/`{1,}[^`]*`{1,}/g,``).replace(/~{3,}[\s\S]*?~{3,}/g,``);if(/<[a-zA-Z\/][^>]*>/.test(t))throw Error(`OQSE Security Error: Raw HTML tags are not allowed in Tier 1 (Pure Markdown). If the set requires HTML formatting, it MUST declare the 'html' feature in meta.requirements.`)}function Xt(e,t,n){let r=e;for(let[e,i]of Object.entries(t)){let t=i.originalTag;i.type===`asset`&&n.assetReplacer?t=n.assetReplacer(i.key):i.type===`blank`&&n.blankReplacer&&(t=n.blankReplacer(i.key)),r=r.replace(e,t)}return r}function Zt(e,t,n){if(!e)return``;let r=t?.features?.includes(`html`)??!1,{text:i,tokens:a}=Jt(e);r||Yt(i);let o=n.markdownParser(i);if(r){if(!n.htmlSanitizer)throw Error(`OQSE Security Error: Set requires 'html' (Tier 2), but no htmlSanitizer (like DOMPurify) was provided to the options.`);o=n.htmlSanitizer(o)}return Xt(o,a,n)}exports.AbsoluteURLSchema=S,exports.AssetDictionarySchema=A,exports.AssetKeySchema=C,exports.AudioMimeTypeSchema=jt,exports.BaseItemSchema=R,exports.BlankTokenSchema=D,exports.BloomLevelSchema=Ne,exports.CameraSetupSchema=ze,exports.CategorizeItemObjectSchema=Be,exports.CategorizeItemSchema=at,exports.ChessPuzzleItemSchema=pt,exports.CircleHotspotSchema=B,exports.CognitiveLoadSchema=Pe,exports.DiagramLabelItemSchema=lt,exports.DiagramZoneSchema=Ue,exports.FeatureFlagSchema=Dt,exports.FeatureProfileSchema=F,exports.FillInBlanksItemSchema=Qe,exports.FillInSelectItemSchema=$e,exports.FlashcardItemSchema=qe,exports.Hotspot2DSchema=Re,exports.HotspotObjectSchema=Le,exports.ISO8601DateTimeSchema=x,exports.ImageMimeTypeSchema=At,exports.ItemPropertyKeySchema=Ot,exports.LanguageCodeSchema=y,exports.LastAnswerObjectSchema=Vt,exports.LinkedSetObjectSchema=I,exports.MCQMultiItemSchema=Xe,exports.MCQSingleItemSchema=Ye,exports.ManifestAssetsSchema=Pt,exports.ManifestCapabilitiesSchema=Ft,exports.MatchComplexItemSchema=tt,exports.MatchPairsItemSchema=et,exports.MathInputItemSchema=ct,exports.MatrixItemSchema=st,exports.MediaObjectSchema=k,exports.MeshHotspotSchema=H,exports.MetaPropertyKeySchema=kt,exports.ModelMimeTypeSchema=Nt,exports.NoteItemSchema=Ke,exports.NumericInputItemSchema=dt,exports.NumericRangeSchema=Ge,exports.OFFICIAL_ACTIONS=c,exports.OFFICIAL_FEATURE_KEYS=l,exports.OFFICIAL_ITEM_PROPERTIES=u,exports.OFFICIAL_META_PROPERTIES=d,exports.OQSEActionSchema=wt,exports.OQSEFileSchema=K,exports.OQSEHeaderSchema=$,exports.OQSEItemSchema=G,exports.OQSEManifestSchema=Z,exports.OQSEMetaSchema=L,exports.OQSEPFileSchema=Q,exports.OQSEQuestionDensitySchema=Et,exports.OQSEStudyModeSchema=Tt,exports.OpenEndedItemSchema=ut,exports.OptionalRichContentSchema=E,exports.PedagogySchema=Fe,exports.PersonObjectSchema=j,exports.PinOnImageItemSchema=it,exports.PinOnModelItemSchema=ft,exports.PlainTextSchema=w,exports.PolygonHotspotSchema=V,exports.ProgressMetaSchema=Ut,exports.ProgressRecordSchema=Ht,exports.RectHotspotSchema=z,exports.RichContentSchema=T,exports.RubricCriterionSchema=W,exports.RubricSchema=We,exports.SPDXLicenseSchema=b,exports.SelectBlankObjectSchema=Ie,exports.ShortAnswerItemSchema=Ze,exports.SliderItemSchema=rt,exports.SortItemsItemSchema=nt,exports.SourceMaterialSchema=N,exports.SourceMaterialTypeSchema=M,exports.SourceReferenceSchema=P,exports.StatsObjectSchema=Bt,exports.SubtitleTrackSchema=O,exports.TagDefinitionDictionarySchema=je,exports.TagDefinitionSchema=Ae,exports.TimelineEventSchema=He,exports.TimelineItemSchema=ot,exports.TimelinePrecisionSchema=Ve,exports.TranslationObjectSchema=Me,exports.TrueFalseItemSchema=Je,exports.UUIDSchema=v,exports.Vector3Schema=U,exports.VideoMimeTypeSchema=Mt,exports.compareManifestVersions=p,exports.detokenizeOqseTags=Xt,exports.formatManifestErrors=Rt,exports.formatValidationErrors=yt,exports.generateUUID=ke,exports.isCategorize=se,exports.isChessPuzzle=he,exports.isCoreItem=s,exports.isDiagramLabel=de,exports.isExtendedItem=ge,exports.isFillInBlanks=ee,exports.isFillInSelect=te,exports.isFlashcard=n,exports.isMCQMulti=a,exports.isMCQSingle=i,exports.isMatchComplex=re,exports.isMatchPairs=ne,exports.isMathInput=ue,exports.isMatrix=le,exports.isNote=t,exports.isNumericInput=pe,exports.isOQSEManifest=ve,exports.isOpenEnded=fe,exports.isPinOnImage=oe,exports.isPinOnModel=me,exports.isShortAnswer=o,exports.isSlider=ae,exports.isSortItems=ie,exports.isTimeline=ce,exports.isTrueFalse=r,exports.isValidManifestVersion=f,exports.isValidOQSEManifest=zt,exports.isValidSemVer=_e,exports.isValidUUID=Oe,exports.isVersionCompatible=ye,exports.prepareRichTextForDisplay=Zt,exports.safeValidateManifest=Lt,exports.safeValidateOQSEFile=gt,exports.safeValidateOQSEHeader=qt,exports.safeValidateOQSEItem=vt,exports.safeValidateOQSEPFile=Gt,exports.tokenizeOqseTags=Jt,exports.validateJsonDepth=_,exports.validateManifest=It,exports.validateOQSEFile=ht,exports.validateOQSEHeader=Kt,exports.validateOQSEItem=_t,exports.validateOQSEPFile=Wt,exports.validateTier1Markdown=Yt;
package/dist/index.d.ts CHANGED
@@ -4,4 +4,7 @@ export * from './src/manifest';
4
4
  export * from './src/manifestValidation';
5
5
  export * from './src/progress';
6
6
  export * from './src/progressValidation';
7
+ export * from './src/header';
8
+ export * from './src/headerValidation';
7
9
  export * from './src/utils';
10
+ export * from './src/richTextProcessor';