@patch-adams/core 1.5.24 → 1.6.1
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/dist/cli.cjs +229 -0
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +229 -0
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +313 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +103 -1
- package/dist/index.d.ts +103 -1
- package/dist/index.js +311 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -564,6 +564,68 @@ interface CourseMetadata {
|
|
|
564
564
|
*/
|
|
565
565
|
declare function extractCourseMetadata(zip: AdmZip, format: string): CourseMetadata;
|
|
566
566
|
|
|
567
|
+
/**
|
|
568
|
+
* Parsed course structure types for Rise SCORM packages.
|
|
569
|
+
* Used by the parse-structure API and the frontend tree view.
|
|
570
|
+
*/
|
|
571
|
+
/** A single block within a Rise lesson */
|
|
572
|
+
interface CourseStructureBlock {
|
|
573
|
+
/** Rise block ID (e.g. "cmk2wzn2p007q3b7hsiobz031") */
|
|
574
|
+
id: string;
|
|
575
|
+
/** Block type: "text", "image", "interactive", "knowledgeCheck", etc. */
|
|
576
|
+
type: string;
|
|
577
|
+
/** Block family: "text", "media", "interactive", etc. */
|
|
578
|
+
family?: string;
|
|
579
|
+
/** Block variant: "paragraph", "accordion", "hero", etc. */
|
|
580
|
+
variant?: string;
|
|
581
|
+
/** Human-readable title derived from block content or type label */
|
|
582
|
+
title?: string;
|
|
583
|
+
}
|
|
584
|
+
/** A lesson (section) in a Rise course */
|
|
585
|
+
interface CourseStructureLesson {
|
|
586
|
+
/** Rise lesson ID */
|
|
587
|
+
id: string;
|
|
588
|
+
/** Lesson title */
|
|
589
|
+
title: string;
|
|
590
|
+
/** Lesson type (e.g. "blocks") */
|
|
591
|
+
type: string;
|
|
592
|
+
/** Blocks within this lesson */
|
|
593
|
+
blocks: CourseStructureBlock[];
|
|
594
|
+
}
|
|
595
|
+
/** Parsed course structure returned by extractCourseStructure() */
|
|
596
|
+
interface CourseStructure {
|
|
597
|
+
/** Course title */
|
|
598
|
+
courseTitle: string;
|
|
599
|
+
/** Course identifier from manifest */
|
|
600
|
+
courseId?: string;
|
|
601
|
+
/** Lessons in the course */
|
|
602
|
+
lessons: CourseStructureLesson[];
|
|
603
|
+
}
|
|
604
|
+
/** A group of adjacent blocks within a lesson wrapped in a container div */
|
|
605
|
+
interface BlockGroup {
|
|
606
|
+
/** Unique identifier for this group */
|
|
607
|
+
id: string;
|
|
608
|
+
/** Lesson ID this group belongs to */
|
|
609
|
+
lessonId: string;
|
|
610
|
+
/** Ordered list of adjacent block IDs (min 2) */
|
|
611
|
+
blockIds: string[];
|
|
612
|
+
/** Space-separated CSS class names for the wrapper div */
|
|
613
|
+
className: string;
|
|
614
|
+
/** Optional human-readable label for the group */
|
|
615
|
+
label?: string;
|
|
616
|
+
}
|
|
617
|
+
/** User-assigned class mappings at course, lesson, block, and group levels */
|
|
618
|
+
interface CourseClassMappings {
|
|
619
|
+
/** Space-separated class names for the <html> element (course level) */
|
|
620
|
+
course?: string;
|
|
621
|
+
/** Lesson ID -> space-separated class names */
|
|
622
|
+
lessons?: Record<string, string>;
|
|
623
|
+
/** Block ID -> space-separated class names */
|
|
624
|
+
blocks?: Record<string, string>;
|
|
625
|
+
/** Block groups: adjacent blocks wrapped in container divs at runtime */
|
|
626
|
+
blockGroups?: BlockGroup[];
|
|
627
|
+
}
|
|
628
|
+
|
|
567
629
|
/**
|
|
568
630
|
* Base configuration for any plugin
|
|
569
631
|
*/
|
|
@@ -880,6 +942,8 @@ interface PatchOptions {
|
|
|
880
942
|
skin?: string;
|
|
881
943
|
/** Original package filename — baked into LRS bridge for statement searchability */
|
|
882
944
|
packageName?: string;
|
|
945
|
+
/** Custom CSS class mappings for course, lesson, and block levels */
|
|
946
|
+
classMappings?: CourseClassMappings;
|
|
883
947
|
}
|
|
884
948
|
/**
|
|
885
949
|
* Main Patcher class for patching e-learning course packages
|
|
@@ -1113,6 +1177,31 @@ declare function generateJsAfterLoader(options: JsAfterOptions): string;
|
|
|
1113
1177
|
*/
|
|
1114
1178
|
declare function buildJsAfterOptions(config: PatchAdamsConfig): JsAfterOptions;
|
|
1115
1179
|
|
|
1180
|
+
/**
|
|
1181
|
+
* Class Mappings Template
|
|
1182
|
+
*
|
|
1183
|
+
* Generates an inline JavaScript snippet that applies user-defined CSS classes
|
|
1184
|
+
* to course, lesson, and block elements at runtime.
|
|
1185
|
+
*
|
|
1186
|
+
* Timing: This script is injected inline (via plugin assets) so it executes
|
|
1187
|
+
* synchronously BEFORE the pa-loading class is removed. The user never sees
|
|
1188
|
+
* an un-styled flash — classes are applied while content is still hidden.
|
|
1189
|
+
*
|
|
1190
|
+
* - Course classes: added to <html> element immediately
|
|
1191
|
+
* - Block classes: added to [data-block-id] elements via MutationObserver
|
|
1192
|
+
* - Lesson classes: toggled on <html> via hashchange (Rise SPA routing)
|
|
1193
|
+
*/
|
|
1194
|
+
|
|
1195
|
+
/**
|
|
1196
|
+
* Check if class mappings contain any actual assignments
|
|
1197
|
+
*/
|
|
1198
|
+
declare function hasClassMappings(mappings?: CourseClassMappings): boolean;
|
|
1199
|
+
/**
|
|
1200
|
+
* Generate an inline JavaScript snippet that applies class mappings at runtime.
|
|
1201
|
+
* Returns an empty string if there are no mappings to apply.
|
|
1202
|
+
*/
|
|
1203
|
+
declare function generateClassMappingsScript(mappings: CourseClassMappings): string;
|
|
1204
|
+
|
|
1116
1205
|
type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent';
|
|
1117
1206
|
/**
|
|
1118
1207
|
* Simple logger utility for Patch-Adams
|
|
@@ -1129,6 +1218,19 @@ declare class Logger {
|
|
|
1129
1218
|
setLevel(level: LogLevel): void;
|
|
1130
1219
|
}
|
|
1131
1220
|
|
|
1221
|
+
/**
|
|
1222
|
+
* Rise Course Structure Parser
|
|
1223
|
+
*
|
|
1224
|
+
* Extracts the hierarchical course structure (lessons + blocks) from a
|
|
1225
|
+
* Rise SCORM ZIP package by parsing the embedded base64-encoded course JSON.
|
|
1226
|
+
*/
|
|
1227
|
+
|
|
1228
|
+
/**
|
|
1229
|
+
* Extract course structure from a Rise SCORM ZIP buffer.
|
|
1230
|
+
* Returns null if the ZIP is not a Rise package or parsing fails.
|
|
1231
|
+
*/
|
|
1232
|
+
declare function extractCourseStructure(zipBuffer: Buffer): CourseStructure | null;
|
|
1233
|
+
|
|
1132
1234
|
/**
|
|
1133
1235
|
* Plugin Registry for Patch-Adams
|
|
1134
1236
|
*
|
|
@@ -1198,4 +1300,4 @@ declare class PluginRegistry {
|
|
|
1198
1300
|
*/
|
|
1199
1301
|
declare const pluginRegistry: PluginRegistry;
|
|
1200
1302
|
|
|
1201
|
-
export { type AsyncAssetConfig, AsyncAssetConfigSchema, type AuthoringTool, AuthoringToolDetector, type AuthoringToolInfo, type BlockingAssetConfig, BlockingAssetConfigSchema, type CourseFingerprint, type CourseMetadata, type CssAfterOptions, type CssBeforeOptions, DEFAULT_LRS_OPTIONS, FormatDetector, type GeneratedPluginAssets, HtmlInjector, type JsAfterOptions, type JsBeforeOptions, type LocalFoldersConfig, LocalFoldersConfigSchema, type LogLevel, Logger, type LrsBridgeConfig, LrsBridgeConfigSchema, type LrsBridgeOptions, type ManifestPaths, ManifestUpdater, type PackageFormat, type PatchAdamsConfig, PatchAdamsConfigSchema, type PatchAdamsPlugin, type PatchOptions, type PatchResult, Patcher, type PluginAssets, type PluginConfig, PluginRegistry, type PluginsConfig, StorylineHtmlInjector, buildCssAfterOptions, buildCssBeforeOptions, buildJsAfterOptions, buildJsBeforeOptions, defaultConfig, extractCourseFingerprint, extractCourseMetadata, generateConfigTemplate, generateCssAfterLoader, generateCssBeforeLoader, generateJsAfterLoader, generateJsBeforeLoader, generateLrsBridgeCode, loadConfig, mergeWithDefaults, pluginRegistry };
|
|
1303
|
+
export { type AsyncAssetConfig, AsyncAssetConfigSchema, type AuthoringTool, AuthoringToolDetector, type AuthoringToolInfo, type BlockGroup, type BlockingAssetConfig, BlockingAssetConfigSchema, type CourseClassMappings, type CourseFingerprint, type CourseMetadata, type CourseStructure, type CourseStructureBlock, type CourseStructureLesson, type CssAfterOptions, type CssBeforeOptions, DEFAULT_LRS_OPTIONS, FormatDetector, type GeneratedPluginAssets, HtmlInjector, type JsAfterOptions, type JsBeforeOptions, type LocalFoldersConfig, LocalFoldersConfigSchema, type LogLevel, Logger, type LrsBridgeConfig, LrsBridgeConfigSchema, type LrsBridgeOptions, type ManifestPaths, ManifestUpdater, type PackageFormat, type PatchAdamsConfig, PatchAdamsConfigSchema, type PatchAdamsPlugin, type PatchOptions, type PatchResult, Patcher, type PluginAssets, type PluginConfig, PluginRegistry, type PluginsConfig, StorylineHtmlInjector, buildCssAfterOptions, buildCssBeforeOptions, buildJsAfterOptions, buildJsBeforeOptions, defaultConfig, extractCourseFingerprint, extractCourseMetadata, extractCourseStructure, generateClassMappingsScript, generateConfigTemplate, generateCssAfterLoader, generateCssBeforeLoader, generateJsAfterLoader, generateJsBeforeLoader, generateLrsBridgeCode, hasClassMappings, loadConfig, mergeWithDefaults, pluginRegistry };
|
package/dist/index.d.ts
CHANGED
|
@@ -564,6 +564,68 @@ interface CourseMetadata {
|
|
|
564
564
|
*/
|
|
565
565
|
declare function extractCourseMetadata(zip: AdmZip, format: string): CourseMetadata;
|
|
566
566
|
|
|
567
|
+
/**
|
|
568
|
+
* Parsed course structure types for Rise SCORM packages.
|
|
569
|
+
* Used by the parse-structure API and the frontend tree view.
|
|
570
|
+
*/
|
|
571
|
+
/** A single block within a Rise lesson */
|
|
572
|
+
interface CourseStructureBlock {
|
|
573
|
+
/** Rise block ID (e.g. "cmk2wzn2p007q3b7hsiobz031") */
|
|
574
|
+
id: string;
|
|
575
|
+
/** Block type: "text", "image", "interactive", "knowledgeCheck", etc. */
|
|
576
|
+
type: string;
|
|
577
|
+
/** Block family: "text", "media", "interactive", etc. */
|
|
578
|
+
family?: string;
|
|
579
|
+
/** Block variant: "paragraph", "accordion", "hero", etc. */
|
|
580
|
+
variant?: string;
|
|
581
|
+
/** Human-readable title derived from block content or type label */
|
|
582
|
+
title?: string;
|
|
583
|
+
}
|
|
584
|
+
/** A lesson (section) in a Rise course */
|
|
585
|
+
interface CourseStructureLesson {
|
|
586
|
+
/** Rise lesson ID */
|
|
587
|
+
id: string;
|
|
588
|
+
/** Lesson title */
|
|
589
|
+
title: string;
|
|
590
|
+
/** Lesson type (e.g. "blocks") */
|
|
591
|
+
type: string;
|
|
592
|
+
/** Blocks within this lesson */
|
|
593
|
+
blocks: CourseStructureBlock[];
|
|
594
|
+
}
|
|
595
|
+
/** Parsed course structure returned by extractCourseStructure() */
|
|
596
|
+
interface CourseStructure {
|
|
597
|
+
/** Course title */
|
|
598
|
+
courseTitle: string;
|
|
599
|
+
/** Course identifier from manifest */
|
|
600
|
+
courseId?: string;
|
|
601
|
+
/** Lessons in the course */
|
|
602
|
+
lessons: CourseStructureLesson[];
|
|
603
|
+
}
|
|
604
|
+
/** A group of adjacent blocks within a lesson wrapped in a container div */
|
|
605
|
+
interface BlockGroup {
|
|
606
|
+
/** Unique identifier for this group */
|
|
607
|
+
id: string;
|
|
608
|
+
/** Lesson ID this group belongs to */
|
|
609
|
+
lessonId: string;
|
|
610
|
+
/** Ordered list of adjacent block IDs (min 2) */
|
|
611
|
+
blockIds: string[];
|
|
612
|
+
/** Space-separated CSS class names for the wrapper div */
|
|
613
|
+
className: string;
|
|
614
|
+
/** Optional human-readable label for the group */
|
|
615
|
+
label?: string;
|
|
616
|
+
}
|
|
617
|
+
/** User-assigned class mappings at course, lesson, block, and group levels */
|
|
618
|
+
interface CourseClassMappings {
|
|
619
|
+
/** Space-separated class names for the <html> element (course level) */
|
|
620
|
+
course?: string;
|
|
621
|
+
/** Lesson ID -> space-separated class names */
|
|
622
|
+
lessons?: Record<string, string>;
|
|
623
|
+
/** Block ID -> space-separated class names */
|
|
624
|
+
blocks?: Record<string, string>;
|
|
625
|
+
/** Block groups: adjacent blocks wrapped in container divs at runtime */
|
|
626
|
+
blockGroups?: BlockGroup[];
|
|
627
|
+
}
|
|
628
|
+
|
|
567
629
|
/**
|
|
568
630
|
* Base configuration for any plugin
|
|
569
631
|
*/
|
|
@@ -880,6 +942,8 @@ interface PatchOptions {
|
|
|
880
942
|
skin?: string;
|
|
881
943
|
/** Original package filename — baked into LRS bridge for statement searchability */
|
|
882
944
|
packageName?: string;
|
|
945
|
+
/** Custom CSS class mappings for course, lesson, and block levels */
|
|
946
|
+
classMappings?: CourseClassMappings;
|
|
883
947
|
}
|
|
884
948
|
/**
|
|
885
949
|
* Main Patcher class for patching e-learning course packages
|
|
@@ -1113,6 +1177,31 @@ declare function generateJsAfterLoader(options: JsAfterOptions): string;
|
|
|
1113
1177
|
*/
|
|
1114
1178
|
declare function buildJsAfterOptions(config: PatchAdamsConfig): JsAfterOptions;
|
|
1115
1179
|
|
|
1180
|
+
/**
|
|
1181
|
+
* Class Mappings Template
|
|
1182
|
+
*
|
|
1183
|
+
* Generates an inline JavaScript snippet that applies user-defined CSS classes
|
|
1184
|
+
* to course, lesson, and block elements at runtime.
|
|
1185
|
+
*
|
|
1186
|
+
* Timing: This script is injected inline (via plugin assets) so it executes
|
|
1187
|
+
* synchronously BEFORE the pa-loading class is removed. The user never sees
|
|
1188
|
+
* an un-styled flash — classes are applied while content is still hidden.
|
|
1189
|
+
*
|
|
1190
|
+
* - Course classes: added to <html> element immediately
|
|
1191
|
+
* - Block classes: added to [data-block-id] elements via MutationObserver
|
|
1192
|
+
* - Lesson classes: toggled on <html> via hashchange (Rise SPA routing)
|
|
1193
|
+
*/
|
|
1194
|
+
|
|
1195
|
+
/**
|
|
1196
|
+
* Check if class mappings contain any actual assignments
|
|
1197
|
+
*/
|
|
1198
|
+
declare function hasClassMappings(mappings?: CourseClassMappings): boolean;
|
|
1199
|
+
/**
|
|
1200
|
+
* Generate an inline JavaScript snippet that applies class mappings at runtime.
|
|
1201
|
+
* Returns an empty string if there are no mappings to apply.
|
|
1202
|
+
*/
|
|
1203
|
+
declare function generateClassMappingsScript(mappings: CourseClassMappings): string;
|
|
1204
|
+
|
|
1116
1205
|
type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent';
|
|
1117
1206
|
/**
|
|
1118
1207
|
* Simple logger utility for Patch-Adams
|
|
@@ -1129,6 +1218,19 @@ declare class Logger {
|
|
|
1129
1218
|
setLevel(level: LogLevel): void;
|
|
1130
1219
|
}
|
|
1131
1220
|
|
|
1221
|
+
/**
|
|
1222
|
+
* Rise Course Structure Parser
|
|
1223
|
+
*
|
|
1224
|
+
* Extracts the hierarchical course structure (lessons + blocks) from a
|
|
1225
|
+
* Rise SCORM ZIP package by parsing the embedded base64-encoded course JSON.
|
|
1226
|
+
*/
|
|
1227
|
+
|
|
1228
|
+
/**
|
|
1229
|
+
* Extract course structure from a Rise SCORM ZIP buffer.
|
|
1230
|
+
* Returns null if the ZIP is not a Rise package or parsing fails.
|
|
1231
|
+
*/
|
|
1232
|
+
declare function extractCourseStructure(zipBuffer: Buffer): CourseStructure | null;
|
|
1233
|
+
|
|
1132
1234
|
/**
|
|
1133
1235
|
* Plugin Registry for Patch-Adams
|
|
1134
1236
|
*
|
|
@@ -1198,4 +1300,4 @@ declare class PluginRegistry {
|
|
|
1198
1300
|
*/
|
|
1199
1301
|
declare const pluginRegistry: PluginRegistry;
|
|
1200
1302
|
|
|
1201
|
-
export { type AsyncAssetConfig, AsyncAssetConfigSchema, type AuthoringTool, AuthoringToolDetector, type AuthoringToolInfo, type BlockingAssetConfig, BlockingAssetConfigSchema, type CourseFingerprint, type CourseMetadata, type CssAfterOptions, type CssBeforeOptions, DEFAULT_LRS_OPTIONS, FormatDetector, type GeneratedPluginAssets, HtmlInjector, type JsAfterOptions, type JsBeforeOptions, type LocalFoldersConfig, LocalFoldersConfigSchema, type LogLevel, Logger, type LrsBridgeConfig, LrsBridgeConfigSchema, type LrsBridgeOptions, type ManifestPaths, ManifestUpdater, type PackageFormat, type PatchAdamsConfig, PatchAdamsConfigSchema, type PatchAdamsPlugin, type PatchOptions, type PatchResult, Patcher, type PluginAssets, type PluginConfig, PluginRegistry, type PluginsConfig, StorylineHtmlInjector, buildCssAfterOptions, buildCssBeforeOptions, buildJsAfterOptions, buildJsBeforeOptions, defaultConfig, extractCourseFingerprint, extractCourseMetadata, generateConfigTemplate, generateCssAfterLoader, generateCssBeforeLoader, generateJsAfterLoader, generateJsBeforeLoader, generateLrsBridgeCode, loadConfig, mergeWithDefaults, pluginRegistry };
|
|
1303
|
+
export { type AsyncAssetConfig, AsyncAssetConfigSchema, type AuthoringTool, AuthoringToolDetector, type AuthoringToolInfo, type BlockGroup, type BlockingAssetConfig, BlockingAssetConfigSchema, type CourseClassMappings, type CourseFingerprint, type CourseMetadata, type CourseStructure, type CourseStructureBlock, type CourseStructureLesson, type CssAfterOptions, type CssBeforeOptions, DEFAULT_LRS_OPTIONS, FormatDetector, type GeneratedPluginAssets, HtmlInjector, type JsAfterOptions, type JsBeforeOptions, type LocalFoldersConfig, LocalFoldersConfigSchema, type LogLevel, Logger, type LrsBridgeConfig, LrsBridgeConfigSchema, type LrsBridgeOptions, type ManifestPaths, ManifestUpdater, type PackageFormat, type PatchAdamsConfig, PatchAdamsConfigSchema, type PatchAdamsPlugin, type PatchOptions, type PatchResult, Patcher, type PluginAssets, type PluginConfig, PluginRegistry, type PluginsConfig, StorylineHtmlInjector, buildCssAfterOptions, buildCssBeforeOptions, buildJsAfterOptions, buildJsBeforeOptions, defaultConfig, extractCourseFingerprint, extractCourseMetadata, extractCourseStructure, generateClassMappingsScript, generateConfigTemplate, generateCssAfterLoader, generateCssBeforeLoader, generateJsAfterLoader, generateJsBeforeLoader, generateLrsBridgeCode, hasClassMappings, loadConfig, mergeWithDefaults, pluginRegistry };
|
package/dist/index.js
CHANGED
|
@@ -5687,6 +5687,228 @@ function buildSkinJsOptions(config) {
|
|
|
5687
5687
|
};
|
|
5688
5688
|
}
|
|
5689
5689
|
|
|
5690
|
+
// src/templates/class-mappings.ts
|
|
5691
|
+
function hasClassMappings(mappings) {
|
|
5692
|
+
if (!mappings) return false;
|
|
5693
|
+
if (mappings.course?.trim()) return true;
|
|
5694
|
+
if (mappings.lessons && Object.values(mappings.lessons).some((v) => v?.trim())) return true;
|
|
5695
|
+
if (mappings.blocks && Object.values(mappings.blocks).some((v) => v?.trim())) return true;
|
|
5696
|
+
if (mappings.blockGroups && mappings.blockGroups.length > 0) return true;
|
|
5697
|
+
return false;
|
|
5698
|
+
}
|
|
5699
|
+
function generateClassMappingsScript(mappings) {
|
|
5700
|
+
if (!hasClassMappings(mappings)) return "";
|
|
5701
|
+
const courseClasses = (mappings.course || "").trim();
|
|
5702
|
+
const blockMap = {};
|
|
5703
|
+
const lessonMap = {};
|
|
5704
|
+
if (mappings.blocks) {
|
|
5705
|
+
for (const [id, classes] of Object.entries(mappings.blocks)) {
|
|
5706
|
+
const trimmed = classes?.trim();
|
|
5707
|
+
if (trimmed) blockMap[id] = trimmed;
|
|
5708
|
+
}
|
|
5709
|
+
}
|
|
5710
|
+
if (mappings.lessons) {
|
|
5711
|
+
for (const [id, classes] of Object.entries(mappings.lessons)) {
|
|
5712
|
+
const trimmed = classes?.trim();
|
|
5713
|
+
if (trimmed) lessonMap[id] = trimmed;
|
|
5714
|
+
}
|
|
5715
|
+
}
|
|
5716
|
+
const hasBlocks = Object.keys(blockMap).length > 0;
|
|
5717
|
+
const hasLessons = Object.keys(lessonMap).length > 0;
|
|
5718
|
+
const blockGroups = (mappings.blockGroups || []).filter(
|
|
5719
|
+
(g) => g.blockIds.length >= 2 && g.className.trim() && g.lessonId
|
|
5720
|
+
);
|
|
5721
|
+
const hasGroups = blockGroups.length > 0;
|
|
5722
|
+
const parts = [];
|
|
5723
|
+
parts.push(`// PA-Patcher: Custom Class Mappings`);
|
|
5724
|
+
parts.push(`(function() {`);
|
|
5725
|
+
parts.push(` 'use strict';`);
|
|
5726
|
+
parts.push(``);
|
|
5727
|
+
if (courseClasses) {
|
|
5728
|
+
parts.push(` // Course-level classes (applied to <html>)`);
|
|
5729
|
+
parts.push(` var courseClasses = ${JSON.stringify(courseClasses)};`);
|
|
5730
|
+
parts.push(` courseClasses.split(' ').forEach(function(cls) {`);
|
|
5731
|
+
parts.push(` if (cls) document.documentElement.classList.add(cls);`);
|
|
5732
|
+
parts.push(` });`);
|
|
5733
|
+
parts.push(``);
|
|
5734
|
+
}
|
|
5735
|
+
if (hasBlocks) {
|
|
5736
|
+
parts.push(` // Block-level classes (applied to [data-block-id] elements)`);
|
|
5737
|
+
parts.push(` var blockMap = ${JSON.stringify(blockMap)};`);
|
|
5738
|
+
parts.push(``);
|
|
5739
|
+
parts.push(` function applyBlockClasses() {`);
|
|
5740
|
+
parts.push(` var ids = Object.keys(blockMap);`);
|
|
5741
|
+
parts.push(` for (var i = 0; i < ids.length; i++) {`);
|
|
5742
|
+
parts.push(` var el = document.querySelector('[data-block-id="' + ids[i] + '"]');`);
|
|
5743
|
+
parts.push(` if (el) {`);
|
|
5744
|
+
parts.push(` var classes = blockMap[ids[i]].split(' ');`);
|
|
5745
|
+
parts.push(` for (var j = 0; j < classes.length; j++) {`);
|
|
5746
|
+
parts.push(` if (classes[j]) el.classList.add(classes[j]);`);
|
|
5747
|
+
parts.push(` }`);
|
|
5748
|
+
parts.push(` }`);
|
|
5749
|
+
parts.push(` }`);
|
|
5750
|
+
parts.push(` }`);
|
|
5751
|
+
parts.push(``);
|
|
5752
|
+
}
|
|
5753
|
+
if (hasLessons) {
|
|
5754
|
+
parts.push(` // Lesson-level classes (toggled on <html> via hash navigation)`);
|
|
5755
|
+
parts.push(` var lessonMap = ${JSON.stringify(lessonMap)};`);
|
|
5756
|
+
parts.push(` var allLessonClasses = [];`);
|
|
5757
|
+
parts.push(` Object.keys(lessonMap).forEach(function(id) {`);
|
|
5758
|
+
parts.push(` lessonMap[id].split(' ').forEach(function(cls) {`);
|
|
5759
|
+
parts.push(` if (cls && allLessonClasses.indexOf(cls) === -1) allLessonClasses.push(cls);`);
|
|
5760
|
+
parts.push(` });`);
|
|
5761
|
+
parts.push(` });`);
|
|
5762
|
+
parts.push(``);
|
|
5763
|
+
parts.push(` var currentLessonId = null;`);
|
|
5764
|
+
parts.push(``);
|
|
5765
|
+
parts.push(` function detectCurrentLesson() {`);
|
|
5766
|
+
parts.push(` var hash = window.location.hash || '';`);
|
|
5767
|
+
parts.push(` var match = hash.match(/#\\/lessons\\/([^/]+)/);`);
|
|
5768
|
+
parts.push(` return match ? match[1] : null;`);
|
|
5769
|
+
parts.push(` }`);
|
|
5770
|
+
parts.push(``);
|
|
5771
|
+
parts.push(` function applyLessonClasses() {`);
|
|
5772
|
+
parts.push(` var lessonId = detectCurrentLesson();`);
|
|
5773
|
+
parts.push(` if (lessonId === currentLessonId) return;`);
|
|
5774
|
+
parts.push(` currentLessonId = lessonId;`);
|
|
5775
|
+
parts.push(` for (var i = 0; i < allLessonClasses.length; i++) {`);
|
|
5776
|
+
parts.push(` document.documentElement.classList.remove(allLessonClasses[i]);`);
|
|
5777
|
+
parts.push(` }`);
|
|
5778
|
+
parts.push(` if (lessonId && lessonMap[lessonId]) {`);
|
|
5779
|
+
parts.push(` var classes = lessonMap[lessonId].split(' ');`);
|
|
5780
|
+
parts.push(` for (var j = 0; j < classes.length; j++) {`);
|
|
5781
|
+
parts.push(` if (classes[j]) document.documentElement.classList.add(classes[j]);`);
|
|
5782
|
+
parts.push(` }`);
|
|
5783
|
+
parts.push(` }`);
|
|
5784
|
+
parts.push(` }`);
|
|
5785
|
+
parts.push(``);
|
|
5786
|
+
}
|
|
5787
|
+
if (hasGroups) {
|
|
5788
|
+
const groupData = blockGroups.map((g) => ({
|
|
5789
|
+
id: g.id,
|
|
5790
|
+
lessonId: g.lessonId,
|
|
5791
|
+
blockIds: g.blockIds,
|
|
5792
|
+
className: g.className.trim()
|
|
5793
|
+
}));
|
|
5794
|
+
parts.push(` // Block groups (adjacent blocks wrapped in container divs)`);
|
|
5795
|
+
parts.push(` var groupMap = ${JSON.stringify(groupData)};`);
|
|
5796
|
+
parts.push(``);
|
|
5797
|
+
parts.push(` function applyBlockGroups() {`);
|
|
5798
|
+
parts.push(` var hash = window.location.hash || '';`);
|
|
5799
|
+
parts.push(` var match = hash.match(/#\\/lessons\\/([^/]+)/);`);
|
|
5800
|
+
parts.push(` var currentLesson = match ? match[1] : null;`);
|
|
5801
|
+
parts.push(` for (var g = 0; g < groupMap.length; g++) {`);
|
|
5802
|
+
parts.push(` var group = groupMap[g];`);
|
|
5803
|
+
parts.push(` if (group.lessonId !== currentLesson) continue;`);
|
|
5804
|
+
parts.push(` if (document.querySelector('[data-pa-group-id="' + group.id + '"]')) continue;`);
|
|
5805
|
+
parts.push(` var blocks = [];`);
|
|
5806
|
+
parts.push(` var allPresent = true;`);
|
|
5807
|
+
parts.push(` for (var b = 0; b < group.blockIds.length; b++) {`);
|
|
5808
|
+
parts.push(` var el = document.querySelector('[data-block-id="' + group.blockIds[b] + '"]');`);
|
|
5809
|
+
parts.push(` if (!el) { allPresent = false; break; }`);
|
|
5810
|
+
parts.push(` blocks.push(el);`);
|
|
5811
|
+
parts.push(` }`);
|
|
5812
|
+
parts.push(` if (!allPresent) continue;`);
|
|
5813
|
+
parts.push(` var parent = blocks[0].parentNode;`);
|
|
5814
|
+
parts.push(` var sameParent = true;`);
|
|
5815
|
+
parts.push(` for (var s = 1; s < blocks.length; s++) {`);
|
|
5816
|
+
parts.push(` if (blocks[s].parentNode !== parent) { sameParent = false; break; }`);
|
|
5817
|
+
parts.push(` }`);
|
|
5818
|
+
parts.push(` if (!sameParent) continue;`);
|
|
5819
|
+
parts.push(` var wrapper = document.createElement('div');`);
|
|
5820
|
+
parts.push(` wrapper.setAttribute('data-pa-group-id', group.id);`);
|
|
5821
|
+
parts.push(` var cls = group.className.split(' ');`);
|
|
5822
|
+
parts.push(` for (var c = 0; c < cls.length; c++) {`);
|
|
5823
|
+
parts.push(` if (cls[c]) wrapper.classList.add(cls[c]);`);
|
|
5824
|
+
parts.push(` }`);
|
|
5825
|
+
parts.push(` parent.insertBefore(wrapper, blocks[0]);`);
|
|
5826
|
+
parts.push(` for (var m = 0; m < blocks.length; m++) {`);
|
|
5827
|
+
parts.push(` wrapper.appendChild(blocks[m]);`);
|
|
5828
|
+
parts.push(` }`);
|
|
5829
|
+
parts.push(` }`);
|
|
5830
|
+
parts.push(` }`);
|
|
5831
|
+
parts.push(``);
|
|
5832
|
+
parts.push(` function teardownBlockGroups() {`);
|
|
5833
|
+
parts.push(` var wrappers = document.querySelectorAll('[data-pa-group-id]');`);
|
|
5834
|
+
parts.push(` for (var w = 0; w < wrappers.length; w++) {`);
|
|
5835
|
+
parts.push(` var wr = wrappers[w];`);
|
|
5836
|
+
parts.push(` var par = wr.parentNode;`);
|
|
5837
|
+
parts.push(` while (wr.firstChild) {`);
|
|
5838
|
+
parts.push(` par.insertBefore(wr.firstChild, wr);`);
|
|
5839
|
+
parts.push(` }`);
|
|
5840
|
+
parts.push(` par.removeChild(wr);`);
|
|
5841
|
+
parts.push(` }`);
|
|
5842
|
+
parts.push(` }`);
|
|
5843
|
+
parts.push(``);
|
|
5844
|
+
}
|
|
5845
|
+
parts.push(` // Initialization`);
|
|
5846
|
+
parts.push(` function init() {`);
|
|
5847
|
+
if (hasBlocks) {
|
|
5848
|
+
parts.push(` applyBlockClasses();`);
|
|
5849
|
+
}
|
|
5850
|
+
if (hasGroups) {
|
|
5851
|
+
parts.push(` applyBlockGroups();`);
|
|
5852
|
+
}
|
|
5853
|
+
if (hasLessons) {
|
|
5854
|
+
parts.push(` applyLessonClasses();`);
|
|
5855
|
+
}
|
|
5856
|
+
if (hasLessons || hasGroups) {
|
|
5857
|
+
parts.push(``);
|
|
5858
|
+
parts.push(` // Watch for Rise SPA navigation`);
|
|
5859
|
+
parts.push(` window.addEventListener('hashchange', function() {`);
|
|
5860
|
+
if (hasGroups) {
|
|
5861
|
+
parts.push(` teardownBlockGroups();`);
|
|
5862
|
+
}
|
|
5863
|
+
if (hasLessons) {
|
|
5864
|
+
parts.push(` applyLessonClasses();`);
|
|
5865
|
+
}
|
|
5866
|
+
if (hasBlocks) {
|
|
5867
|
+
parts.push(` setTimeout(applyBlockClasses, 200);`);
|
|
5868
|
+
}
|
|
5869
|
+
if (hasGroups) {
|
|
5870
|
+
parts.push(` setTimeout(applyBlockGroups, 300);`);
|
|
5871
|
+
}
|
|
5872
|
+
parts.push(` });`);
|
|
5873
|
+
}
|
|
5874
|
+
if (hasBlocks || hasGroups) {
|
|
5875
|
+
parts.push(``);
|
|
5876
|
+
parts.push(` // MutationObserver for lazily-rendered Rise blocks`);
|
|
5877
|
+
if (hasGroups) {
|
|
5878
|
+
parts.push(` var debounceTimer = null;`);
|
|
5879
|
+
parts.push(` var observer = new MutationObserver(function() {`);
|
|
5880
|
+
parts.push(` if (debounceTimer) clearTimeout(debounceTimer);`);
|
|
5881
|
+
parts.push(` debounceTimer = setTimeout(function() {`);
|
|
5882
|
+
if (hasBlocks) {
|
|
5883
|
+
parts.push(` applyBlockClasses();`);
|
|
5884
|
+
}
|
|
5885
|
+
parts.push(` applyBlockGroups();`);
|
|
5886
|
+
parts.push(` }, 100);`);
|
|
5887
|
+
parts.push(` });`);
|
|
5888
|
+
} else {
|
|
5889
|
+
parts.push(` var observer = new MutationObserver(function(mutations) {`);
|
|
5890
|
+
parts.push(` for (var i = 0; i < mutations.length; i++) {`);
|
|
5891
|
+
parts.push(` if (mutations[i].addedNodes.length > 0) {`);
|
|
5892
|
+
parts.push(` applyBlockClasses();`);
|
|
5893
|
+
parts.push(` return;`);
|
|
5894
|
+
parts.push(` }`);
|
|
5895
|
+
parts.push(` }`);
|
|
5896
|
+
parts.push(` });`);
|
|
5897
|
+
}
|
|
5898
|
+
parts.push(` var container = document.querySelector('#app') || document.body;`);
|
|
5899
|
+
parts.push(` observer.observe(container, { childList: true, subtree: true });`);
|
|
5900
|
+
}
|
|
5901
|
+
parts.push(` }`);
|
|
5902
|
+
parts.push(``);
|
|
5903
|
+
parts.push(` if (document.readyState === 'loading') {`);
|
|
5904
|
+
parts.push(` document.addEventListener('DOMContentLoaded', init);`);
|
|
5905
|
+
parts.push(` } else {`);
|
|
5906
|
+
parts.push(` init();`);
|
|
5907
|
+
parts.push(` }`);
|
|
5908
|
+
parts.push(`})();`);
|
|
5909
|
+
return parts.join("\n");
|
|
5910
|
+
}
|
|
5911
|
+
|
|
5690
5912
|
// src/patcher/html-injector.ts
|
|
5691
5913
|
var HtmlInjector = class {
|
|
5692
5914
|
config;
|
|
@@ -7077,6 +7299,13 @@ var Patcher = class {
|
|
|
7077
7299
|
console.log(`[Patcher] Fetched ${fetchedCount} remote files`);
|
|
7078
7300
|
}
|
|
7079
7301
|
const pluginAssets = this.generatePluginAssets();
|
|
7302
|
+
if (hasClassMappings(options.classMappings)) {
|
|
7303
|
+
const classMappingsJs = generateClassMappingsScript(options.classMappings);
|
|
7304
|
+
if (classMappingsJs) {
|
|
7305
|
+
pluginAssets.jsAfter = classMappingsJs + (pluginAssets.jsAfter ? "\n" + pluginAssets.jsAfter : "");
|
|
7306
|
+
console.log("[Patcher] Class mappings JS will be injected inline into HTML");
|
|
7307
|
+
}
|
|
7308
|
+
}
|
|
7080
7309
|
const hasPluginAssets = pluginAssets.cssBefore || pluginAssets.cssAfter || pluginAssets.jsBefore || pluginAssets.jsAfter;
|
|
7081
7310
|
if (hasPluginAssets) {
|
|
7082
7311
|
htmlInjector.setPluginAssets(pluginAssets);
|
|
@@ -7436,7 +7665,88 @@ var Logger = class {
|
|
|
7436
7665
|
this.level = level;
|
|
7437
7666
|
}
|
|
7438
7667
|
};
|
|
7668
|
+
var DESERIALIZE_REGEX = /deserialize\s*\(\s*["']([A-Za-z0-9+/=]+)["']\s*\)/;
|
|
7669
|
+
var RISE_HTML_PATHS = [
|
|
7670
|
+
"scormcontent/index.html",
|
|
7671
|
+
"index.html"
|
|
7672
|
+
];
|
|
7673
|
+
function extractCourseStructure(zipBuffer) {
|
|
7674
|
+
try {
|
|
7675
|
+
const zip = new AdmZip(zipBuffer);
|
|
7676
|
+
let htmlContent = null;
|
|
7677
|
+
for (const path of RISE_HTML_PATHS) {
|
|
7678
|
+
const entry = zip.getEntry(path);
|
|
7679
|
+
if (entry) {
|
|
7680
|
+
htmlContent = entry.getData().toString("utf-8");
|
|
7681
|
+
if (DESERIALIZE_REGEX.test(htmlContent)) break;
|
|
7682
|
+
htmlContent = null;
|
|
7683
|
+
}
|
|
7684
|
+
}
|
|
7685
|
+
if (!htmlContent) {
|
|
7686
|
+
return null;
|
|
7687
|
+
}
|
|
7688
|
+
const match = htmlContent.match(DESERIALIZE_REGEX);
|
|
7689
|
+
if (!match || !match[1]) {
|
|
7690
|
+
return null;
|
|
7691
|
+
}
|
|
7692
|
+
const jsonStr = Buffer.from(match[1], "base64").toString("utf-8");
|
|
7693
|
+
const data = JSON.parse(jsonStr);
|
|
7694
|
+
const course = data.course;
|
|
7695
|
+
if (!course || !Array.isArray(course.lessons)) {
|
|
7696
|
+
return null;
|
|
7697
|
+
}
|
|
7698
|
+
const lessons = course.lessons.filter((lesson) => !lesson.deleted).sort((a, b) => (a.position ?? 0) - (b.position ?? 0)).map((lesson) => {
|
|
7699
|
+
const blocks = (lesson.items || []).map((block) => {
|
|
7700
|
+
const structBlock = {
|
|
7701
|
+
id: block.id,
|
|
7702
|
+
type: block.type || "unknown"
|
|
7703
|
+
};
|
|
7704
|
+
if (block.family) structBlock.family = block.family;
|
|
7705
|
+
if (block.variant) structBlock.variant = block.variant;
|
|
7706
|
+
const title = deriveBlockTitle(block);
|
|
7707
|
+
if (title) structBlock.title = title;
|
|
7708
|
+
return structBlock;
|
|
7709
|
+
});
|
|
7710
|
+
return {
|
|
7711
|
+
id: lesson.id,
|
|
7712
|
+
title: lesson.title || "Untitled Lesson",
|
|
7713
|
+
type: lesson.type || "blocks",
|
|
7714
|
+
blocks
|
|
7715
|
+
};
|
|
7716
|
+
});
|
|
7717
|
+
return {
|
|
7718
|
+
courseTitle: course.title || course.name || "Untitled Course",
|
|
7719
|
+
courseId: course.id || void 0,
|
|
7720
|
+
lessons
|
|
7721
|
+
};
|
|
7722
|
+
} catch {
|
|
7723
|
+
return null;
|
|
7724
|
+
}
|
|
7725
|
+
}
|
|
7726
|
+
function deriveBlockTitle(block) {
|
|
7727
|
+
if (block.title && typeof block.title === "string") {
|
|
7728
|
+
return stripHtml(block.title).substring(0, 80);
|
|
7729
|
+
}
|
|
7730
|
+
const items = block.items;
|
|
7731
|
+
if (!Array.isArray(items) || items.length === 0) return void 0;
|
|
7732
|
+
const firstItem = items[0];
|
|
7733
|
+
if (!firstItem) return void 0;
|
|
7734
|
+
if (firstItem.heading) {
|
|
7735
|
+
return stripHtml(firstItem.heading).substring(0, 80);
|
|
7736
|
+
}
|
|
7737
|
+
if (firstItem.title && typeof firstItem.title === "string") {
|
|
7738
|
+
return stripHtml(firstItem.title).substring(0, 80);
|
|
7739
|
+
}
|
|
7740
|
+
if (firstItem.paragraph) {
|
|
7741
|
+
const text = stripHtml(firstItem.paragraph).substring(0, 60);
|
|
7742
|
+
if (text) return text + (firstItem.paragraph.length > 60 ? "..." : "");
|
|
7743
|
+
}
|
|
7744
|
+
return void 0;
|
|
7745
|
+
}
|
|
7746
|
+
function stripHtml(html) {
|
|
7747
|
+
return html.replace(/<[^>]*>/g, "").trim();
|
|
7748
|
+
}
|
|
7439
7749
|
|
|
7440
|
-
export { AsyncAssetConfigSchema, AuthoringToolDetector, BlockingAssetConfigSchema, DEFAULT_LRS_OPTIONS, FormatDetector, HtmlInjector, LocalFoldersConfigSchema, Logger, LrsBridgeConfigSchema, ManifestUpdater, PatchAdamsConfigSchema, Patcher, PluginRegistry, StorylineHtmlInjector, buildCssAfterOptions, buildCssBeforeOptions, buildJsAfterOptions, buildJsBeforeOptions, defaultConfig, extractCourseFingerprint, extractCourseMetadata, generateConfigTemplate, generateCssAfterLoader, generateCssBeforeLoader, generateJsAfterLoader, generateJsBeforeLoader, generateLrsBridgeCode, loadConfig, mergeWithDefaults, pluginRegistry };
|
|
7750
|
+
export { AsyncAssetConfigSchema, AuthoringToolDetector, BlockingAssetConfigSchema, DEFAULT_LRS_OPTIONS, FormatDetector, HtmlInjector, LocalFoldersConfigSchema, Logger, LrsBridgeConfigSchema, ManifestUpdater, PatchAdamsConfigSchema, Patcher, PluginRegistry, StorylineHtmlInjector, buildCssAfterOptions, buildCssBeforeOptions, buildJsAfterOptions, buildJsBeforeOptions, defaultConfig, extractCourseFingerprint, extractCourseMetadata, extractCourseStructure, generateClassMappingsScript, generateConfigTemplate, generateCssAfterLoader, generateCssBeforeLoader, generateJsAfterLoader, generateJsBeforeLoader, generateLrsBridgeCode, hasClassMappings, loadConfig, mergeWithDefaults, pluginRegistry };
|
|
7441
7751
|
//# sourceMappingURL=index.js.map
|
|
7442
7752
|
//# sourceMappingURL=index.js.map
|