codigo0/scorm/generator/manifest-generator.ts

101 lines
4.1 KiB
TypeScript

/**
* Generar imsmanifest.xml para paquetes SCORM 1.2
*/
import { writeFile } from 'fs/promises';
import { join } from 'path';
import { Guide } from '../../src/data/guides-index.js';
/**
* Generar imsmanifest.xml para una guía
*/
export async function generateManifest(
guide: Guide,
outputPath: string
): Promise<void> {
const manifest = `<?xml version="1.0" encoding="UTF-8"?>
<manifest identifier="EMERGES_TES_${guide.id.toUpperCase()}"
version="1.0"
xmlns="http://www.imsproject.org/xsd/imscp_rootv1p1p2"
xmlns:adlcp="http://www.adlnet.org/xsd/adlcp_rootv1p2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.imsproject.org/xsd/imscp_rootv1p1p2 imscp_rootv1p1p2.xsd
http://www.imsglobal.org/xsd/imsmd_rootv1p2p1 imsmd_rootv1p2p1.xsd
http://www.adlnet.org/xsd/adlcp_rootv1p2 adlcp_rootv1p2.xsd">
<metadata>
<schema>ADL SCORM</schema>
<schemaversion>1.2</schemaversion>
<lom xmlns="http://www.imsglobal.org/xsd/imsmd_rootv1p2p1">
<general>
<identifier>
<catalog>URI</catalog>
<entry>urn:uuid:${guide.id}</entry>
</identifier>
<title>
<langstring xml:lang="es">${escapeXml(guide.titulo)} - Guía de Refuerzo</langstring>
</title>
<description>
<langstring xml:lang="es">${escapeXml(guide.descripcion)}</langstring>
</description>
<language>es</language>
</general>
<lifecycle>
<version>
<langstring xml:lang="es">1.0</langstring>
</version>
</lifecycle>
<educational>
<learningresourcetype>
<source>
<langstring xml:lang="es">LOMv1.0</langstring>
</source>
<value>
<langstring xml:lang="es">Guía de Refuerzo</langstring>
</value>
</learningresourcetype>
</educational>
</lom>
</metadata>
<organizations default="EMERGES_TES_${guide.id.toUpperCase()}_ORG">
<organization identifier="EMERGES_TES_${guide.id.toUpperCase()}_ORG">
<title>${escapeXml(guide.titulo)}</title>
<item identifier="ITEM_${guide.id.toUpperCase()}_ROOT" identifierref="RES_${guide.id.toUpperCase()}_ROOT">
<title>${escapeXml(guide.titulo)}</title>
${guide.secciones.map((section, index) => `
<item identifier="ITEM_${guide.id.toUpperCase()}_SEC${String(section.numero).padStart(2, '0')}" identifierref="RES_${guide.id.toUpperCase()}_SEC${String(section.numero).padStart(2, '0')}">
<title>${escapeXml(section.titulo)}</title>
</item>`).join('')}
</item>
</organization>
</organizations>
<resources>
<resource identifier="RES_${guide.id.toUpperCase()}_ROOT" type="webcontent" adlcp:scormtype="sco" href="index.html">
<file href="index.html"/>
<file href="assets/scorm-api.js"/>
<file href="assets/navigation.js"/>
<file href="assets/styles.css"/>
</resource>
${guide.secciones.map((section) => `
<resource identifier="RES_${guide.id.toUpperCase()}_SEC${String(section.numero).padStart(2, '0')}" type="webcontent" adlcp:scormtype="sco" href="sections/section-${String(section.numero).padStart(2, '0')}.html">
<file href="sections/section-${String(section.numero).padStart(2, '0')}.html"/>
<dependency identifierref="RES_${guide.id.toUpperCase()}_ROOT"/>
</resource>`).join('')}
</resources>
</manifest>`;
await writeFile(outputPath, manifest, 'utf-8');
}
/**
* Escapar caracteres XML especiales
*/
function escapeXml(text: string): string {
return text
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&apos;');
}