@patch-adams/core 1.6.0 → 1.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -601,7 +601,20 @@ interface CourseStructure {
601
601
  /** Lessons in the course */
602
602
  lessons: CourseStructureLesson[];
603
603
  }
604
- /** User-assigned class mappings at course, lesson, and block levels */
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 */
605
618
  interface CourseClassMappings {
606
619
  /** Space-separated class names for the <html> element (course level) */
607
620
  course?: string;
@@ -609,6 +622,8 @@ interface CourseClassMappings {
609
622
  lessons?: Record<string, string>;
610
623
  /** Block ID -> space-separated class names */
611
624
  blocks?: Record<string, string>;
625
+ /** Block groups: adjacent blocks wrapped in container divs at runtime */
626
+ blockGroups?: BlockGroup[];
612
627
  }
613
628
 
614
629
  /**
@@ -747,6 +762,11 @@ declare class HtmlInjector {
747
762
  * Escape a string for use in HTML attributes
748
763
  */
749
764
  private escapeAttr;
765
+ /**
766
+ * Inject a tiny inline script that fetches the asset version BEFORE any loaders.
767
+ * Sets window.__pa_v so CSS Before, JS Before, and all other loaders get ?v= cache bust.
768
+ */
769
+ private injectVersionResolver;
750
770
  /**
751
771
  * Inject CSS Before loader at start of <head>
752
772
  */
@@ -1285,4 +1305,4 @@ declare class PluginRegistry {
1285
1305
  */
1286
1306
  declare const pluginRegistry: PluginRegistry;
1287
1307
 
1288
- export { type AsyncAssetConfig, AsyncAssetConfigSchema, type AuthoringTool, AuthoringToolDetector, type AuthoringToolInfo, 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 };
1308
+ 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
@@ -601,7 +601,20 @@ interface CourseStructure {
601
601
  /** Lessons in the course */
602
602
  lessons: CourseStructureLesson[];
603
603
  }
604
- /** User-assigned class mappings at course, lesson, and block levels */
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 */
605
618
  interface CourseClassMappings {
606
619
  /** Space-separated class names for the <html> element (course level) */
607
620
  course?: string;
@@ -609,6 +622,8 @@ interface CourseClassMappings {
609
622
  lessons?: Record<string, string>;
610
623
  /** Block ID -> space-separated class names */
611
624
  blocks?: Record<string, string>;
625
+ /** Block groups: adjacent blocks wrapped in container divs at runtime */
626
+ blockGroups?: BlockGroup[];
612
627
  }
613
628
 
614
629
  /**
@@ -747,6 +762,11 @@ declare class HtmlInjector {
747
762
  * Escape a string for use in HTML attributes
748
763
  */
749
764
  private escapeAttr;
765
+ /**
766
+ * Inject a tiny inline script that fetches the asset version BEFORE any loaders.
767
+ * Sets window.__pa_v so CSS Before, JS Before, and all other loaders get ?v= cache bust.
768
+ */
769
+ private injectVersionResolver;
750
770
  /**
751
771
  * Inject CSS Before loader at start of <head>
752
772
  */
@@ -1285,4 +1305,4 @@ declare class PluginRegistry {
1285
1305
  */
1286
1306
  declare const pluginRegistry: PluginRegistry;
1287
1307
 
1288
- export { type AsyncAssetConfig, AsyncAssetConfigSchema, type AuthoringTool, AuthoringToolDetector, type AuthoringToolInfo, 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 };
1308
+ 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
@@ -5299,18 +5299,21 @@ window.pa_patcher = window.pa_patcher || {
5299
5299
 
5300
5300
  (function() {
5301
5301
  'use strict';
5302
- // Fetch server-controlled cache version (sync, once)
5303
- var ASSET_VERSION_URL = "${assetVersionUrl || ""}";
5304
- window.__pa_v = '';
5305
- if (ASSET_VERSION_URL) {
5306
- try {
5307
- var xhr = new XMLHttpRequest();
5308
- xhr.open('GET', ASSET_VERSION_URL, false);
5309
- xhr.send();
5310
- if (xhr.status === 200) {
5311
- window.__pa_v = JSON.parse(xhr.responseText).v || '1';
5312
- }
5313
- } catch(e) { window.__pa_v = '1'; }
5302
+ // Cache version \u2014 normally set by version resolver (injected before CSS Before).
5303
+ // Fallback: fetch here if version resolver didn't run (older patched packages).
5304
+ if (typeof window.__pa_v === 'undefined') {
5305
+ var ASSET_VERSION_URL = "${assetVersionUrl || ""}";
5306
+ window.__pa_v = '';
5307
+ if (ASSET_VERSION_URL) {
5308
+ try {
5309
+ var xhr = new XMLHttpRequest();
5310
+ xhr.open('GET', ASSET_VERSION_URL, false);
5311
+ xhr.send();
5312
+ if (xhr.status === 200) {
5313
+ window.__pa_v = JSON.parse(xhr.responseText).v || '1';
5314
+ }
5315
+ } catch(e) { window.__pa_v = '1'; }
5316
+ }
5314
5317
  }
5315
5318
 
5316
5319
  var REMOTE_URL = "${remoteUrl}" + (window.__pa_v ? "?v=" + window.__pa_v : "");
@@ -5693,6 +5696,7 @@ function hasClassMappings(mappings) {
5693
5696
  if (mappings.course?.trim()) return true;
5694
5697
  if (mappings.lessons && Object.values(mappings.lessons).some((v) => v?.trim())) return true;
5695
5698
  if (mappings.blocks && Object.values(mappings.blocks).some((v) => v?.trim())) return true;
5699
+ if (mappings.blockGroups && mappings.blockGroups.length > 0) return true;
5696
5700
  return false;
5697
5701
  }
5698
5702
  function generateClassMappingsScript(mappings) {
@@ -5714,6 +5718,10 @@ function generateClassMappingsScript(mappings) {
5714
5718
  }
5715
5719
  const hasBlocks = Object.keys(blockMap).length > 0;
5716
5720
  const hasLessons = Object.keys(lessonMap).length > 0;
5721
+ const blockGroups = (mappings.blockGroups || []).filter(
5722
+ (g) => g.blockIds.length >= 2 && g.className.trim() && g.lessonId
5723
+ );
5724
+ const hasGroups = blockGroups.length > 0;
5717
5725
  const parts = [];
5718
5726
  parts.push(`// PA-Patcher: Custom Class Mappings`);
5719
5727
  parts.push(`(function() {`);
@@ -5779,33 +5787,117 @@ function generateClassMappingsScript(mappings) {
5779
5787
  parts.push(` }`);
5780
5788
  parts.push(``);
5781
5789
  }
5790
+ if (hasGroups) {
5791
+ const groupData = blockGroups.map((g) => ({
5792
+ id: g.id,
5793
+ lessonId: g.lessonId,
5794
+ blockIds: g.blockIds,
5795
+ className: g.className.trim()
5796
+ }));
5797
+ parts.push(` // Block groups (adjacent blocks wrapped in container divs)`);
5798
+ parts.push(` var groupMap = ${JSON.stringify(groupData)};`);
5799
+ parts.push(``);
5800
+ parts.push(` function applyBlockGroups() {`);
5801
+ parts.push(` var hash = window.location.hash || '';`);
5802
+ parts.push(` var match = hash.match(/#\\/lessons\\/([^/]+)/);`);
5803
+ parts.push(` var currentLesson = match ? match[1] : null;`);
5804
+ parts.push(` for (var g = 0; g < groupMap.length; g++) {`);
5805
+ parts.push(` var group = groupMap[g];`);
5806
+ parts.push(` if (group.lessonId !== currentLesson) continue;`);
5807
+ parts.push(` if (document.querySelector('[data-pa-group-id="' + group.id + '"]')) continue;`);
5808
+ parts.push(` var blocks = [];`);
5809
+ parts.push(` var allPresent = true;`);
5810
+ parts.push(` for (var b = 0; b < group.blockIds.length; b++) {`);
5811
+ parts.push(` var el = document.querySelector('[data-block-id="' + group.blockIds[b] + '"]');`);
5812
+ parts.push(` if (!el) { allPresent = false; break; }`);
5813
+ parts.push(` blocks.push(el);`);
5814
+ parts.push(` }`);
5815
+ parts.push(` if (!allPresent) continue;`);
5816
+ parts.push(` var parent = blocks[0].parentNode;`);
5817
+ parts.push(` var sameParent = true;`);
5818
+ parts.push(` for (var s = 1; s < blocks.length; s++) {`);
5819
+ parts.push(` if (blocks[s].parentNode !== parent) { sameParent = false; break; }`);
5820
+ parts.push(` }`);
5821
+ parts.push(` if (!sameParent) continue;`);
5822
+ parts.push(` var wrapper = document.createElement('div');`);
5823
+ parts.push(` wrapper.setAttribute('data-pa-group-id', group.id);`);
5824
+ parts.push(` var cls = group.className.split(' ');`);
5825
+ parts.push(` for (var c = 0; c < cls.length; c++) {`);
5826
+ parts.push(` if (cls[c]) wrapper.classList.add(cls[c]);`);
5827
+ parts.push(` }`);
5828
+ parts.push(` parent.insertBefore(wrapper, blocks[0]);`);
5829
+ parts.push(` for (var m = 0; m < blocks.length; m++) {`);
5830
+ parts.push(` wrapper.appendChild(blocks[m]);`);
5831
+ parts.push(` }`);
5832
+ parts.push(` }`);
5833
+ parts.push(` }`);
5834
+ parts.push(``);
5835
+ parts.push(` function teardownBlockGroups() {`);
5836
+ parts.push(` var wrappers = document.querySelectorAll('[data-pa-group-id]');`);
5837
+ parts.push(` for (var w = 0; w < wrappers.length; w++) {`);
5838
+ parts.push(` var wr = wrappers[w];`);
5839
+ parts.push(` var par = wr.parentNode;`);
5840
+ parts.push(` while (wr.firstChild) {`);
5841
+ parts.push(` par.insertBefore(wr.firstChild, wr);`);
5842
+ parts.push(` }`);
5843
+ parts.push(` par.removeChild(wr);`);
5844
+ parts.push(` }`);
5845
+ parts.push(` }`);
5846
+ parts.push(``);
5847
+ }
5782
5848
  parts.push(` // Initialization`);
5783
5849
  parts.push(` function init() {`);
5784
5850
  if (hasBlocks) {
5785
5851
  parts.push(` applyBlockClasses();`);
5786
5852
  }
5853
+ if (hasGroups) {
5854
+ parts.push(` applyBlockGroups();`);
5855
+ }
5787
5856
  if (hasLessons) {
5788
5857
  parts.push(` applyLessonClasses();`);
5858
+ }
5859
+ if (hasLessons || hasGroups) {
5789
5860
  parts.push(``);
5790
5861
  parts.push(` // Watch for Rise SPA navigation`);
5791
5862
  parts.push(` window.addEventListener('hashchange', function() {`);
5792
- parts.push(` applyLessonClasses();`);
5863
+ if (hasGroups) {
5864
+ parts.push(` teardownBlockGroups();`);
5865
+ }
5866
+ if (hasLessons) {
5867
+ parts.push(` applyLessonClasses();`);
5868
+ }
5793
5869
  if (hasBlocks) {
5794
5870
  parts.push(` setTimeout(applyBlockClasses, 200);`);
5795
5871
  }
5872
+ if (hasGroups) {
5873
+ parts.push(` setTimeout(applyBlockGroups, 300);`);
5874
+ }
5796
5875
  parts.push(` });`);
5797
5876
  }
5798
- if (hasBlocks) {
5877
+ if (hasBlocks || hasGroups) {
5799
5878
  parts.push(``);
5800
5879
  parts.push(` // MutationObserver for lazily-rendered Rise blocks`);
5801
- parts.push(` var observer = new MutationObserver(function(mutations) {`);
5802
- parts.push(` for (var i = 0; i < mutations.length; i++) {`);
5803
- parts.push(` if (mutations[i].addedNodes.length > 0) {`);
5804
- parts.push(` applyBlockClasses();`);
5805
- parts.push(` return;`);
5806
- parts.push(` }`);
5807
- parts.push(` }`);
5808
- parts.push(` });`);
5880
+ if (hasGroups) {
5881
+ parts.push(` var debounceTimer = null;`);
5882
+ parts.push(` var observer = new MutationObserver(function() {`);
5883
+ parts.push(` if (debounceTimer) clearTimeout(debounceTimer);`);
5884
+ parts.push(` debounceTimer = setTimeout(function() {`);
5885
+ if (hasBlocks) {
5886
+ parts.push(` applyBlockClasses();`);
5887
+ }
5888
+ parts.push(` applyBlockGroups();`);
5889
+ parts.push(` }, 100);`);
5890
+ parts.push(` });`);
5891
+ } else {
5892
+ parts.push(` var observer = new MutationObserver(function(mutations) {`);
5893
+ parts.push(` for (var i = 0; i < mutations.length; i++) {`);
5894
+ parts.push(` if (mutations[i].addedNodes.length > 0) {`);
5895
+ parts.push(` applyBlockClasses();`);
5896
+ parts.push(` return;`);
5897
+ parts.push(` }`);
5898
+ parts.push(` }`);
5899
+ parts.push(` });`);
5900
+ }
5809
5901
  parts.push(` var container = document.querySelector('#app') || document.body;`);
5810
5902
  parts.push(` observer.observe(container, { childList: true, subtree: true });`);
5811
5903
  }
@@ -5871,6 +5963,7 @@ var HtmlInjector = class {
5871
5963
  inject(html) {
5872
5964
  let result = html;
5873
5965
  result = this.addHtmlAttributes(result);
5966
+ result = this.injectVersionResolver(result);
5874
5967
  if (this.config.cssBefore.enabled) {
5875
5968
  result = this.injectCssBefore(result);
5876
5969
  }
@@ -5974,6 +6067,20 @@ ${pluginJs}
5974
6067
  escapeAttr(str) {
5975
6068
  return str.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/'/g, "&#39;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
5976
6069
  }
6070
+ /**
6071
+ * Inject a tiny inline script that fetches the asset version BEFORE any loaders.
6072
+ * Sets window.__pa_v so CSS Before, JS Before, and all other loaders get ?v= cache bust.
6073
+ */
6074
+ injectVersionResolver(html) {
6075
+ const assetVersionUrl = this.config.assetVersionUrl || "";
6076
+ if (!assetVersionUrl) return html;
6077
+ const script = `<!-- === PATCH-ADAMS: VERSION RESOLVER === -->
6078
+ <script data-pa="version-resolver">
6079
+ (function(){try{var x=new XMLHttpRequest();x.open('GET','${assetVersionUrl}',false);x.send();if(x.status===200){window.__pa_v=JSON.parse(x.responseText).v||'1'}}catch(e){window.__pa_v='1'}})();
6080
+ </script>`;
6081
+ return html.replace(/<head([^>]*)>/i, `<head$1>
6082
+ ${script}`);
6083
+ }
5977
6084
  /**
5978
6085
  * Inject CSS Before loader at start of <head>
5979
6086
  */