pict-docuserve 1.3.3 → 1.3.4

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.
@@ -6050,7 +6050,12 @@ if(tmpInList){tmpHTML.push(tmpListType==='ul'?'</ul>':'</ol>');tmpInList=false;}
6050
6050
  if(tmpLine.match(/^(-{3,}|\*{3,}|_{3,})\s*$/)){fFlushParagraph();if(tmpInList){tmpHTML.push(tmpListType==='ul'?'</ul>':'</ol>');tmpInList=false;}tmpHTML.push('<hr>');continue;}// Headings
6051
6051
  let tmpHeadingMatch=tmpLine.match(/^(#{1,6})\s+(.+)/);if(tmpHeadingMatch){fFlushParagraph();if(tmpInList){tmpHTML.push(tmpListType==='ul'?'</ul>':'</ol>');tmpInList=false;}let tmpLevel=tmpHeadingMatch[1].length;let tmpText=this.parseInline(tmpHeadingMatch[2],pLinkResolver,pImageResolver,pVocabularyResolver);let tmpID=tmpHeadingMatch[2].toLowerCase().replace(/[^\w\s-]/g,'').replace(/\s+/g,'-');tmpHTML.push('<h'+tmpLevel+' id="'+tmpID+'">'+tmpText+'</h'+tmpLevel+'>');continue;}// Unordered list items
6052
6052
  let tmpULMatch=tmpLine.match(/^(\s*)[-*+]\s+(.*)/);if(tmpULMatch){fFlushParagraph();if(!tmpInList||tmpListType!=='ul'){if(tmpInList){tmpHTML.push(tmpListType==='ul'?'</ul>':'</ol>');}tmpHTML.push('<ul>');tmpInList=true;tmpListType='ul';}tmpHTML.push('<li>'+this.parseInline(tmpULMatch[2],pLinkResolver,pImageResolver,pVocabularyResolver)+'</li>');continue;}// Ordered list items
6053
- let tmpOLMatch=tmpLine.match(/^(\s*)\d+\.\s+(.*)/);if(tmpOLMatch){fFlushParagraph();if(!tmpInList||tmpListType!=='ol'){if(tmpInList){tmpHTML.push(tmpListType==='ul'?'</ul>':'</ol>');}tmpHTML.push('<ol>');tmpInList=true;tmpListType='ol';}tmpHTML.push('<li>'+this.parseInline(tmpOLMatch[2],pLinkResolver,pImageResolver,pVocabularyResolver)+'</li>');continue;}// Close list if we've left list items
6053
+ let tmpOLMatch=tmpLine.match(/^(\s*)\d+\.\s+(.*)/);if(tmpOLMatch){fFlushParagraph();if(!tmpInList||tmpListType!=='ol'){if(tmpInList){tmpHTML.push(tmpListType==='ul'?'</ul>':'</ol>');}tmpHTML.push('<ol>');tmpInList=true;tmpListType='ol';}tmpHTML.push('<li>'+this.parseInline(tmpOLMatch[2],pLinkResolver,pImageResolver,pVocabularyResolver)+'</li>');continue;}// Indented continuation line of a wrapped list item — fold its
6054
+ // content into the last <li> instead of closing the list. Closing
6055
+ // here would split a real <ol>/<ul>, and each fragment restarts
6056
+ // ordered numbering. A non-indented non-marker line still closes
6057
+ // the list (handled below); blank lines never reach this branch.
6058
+ if(tmpInList&&tmpLine.match(/^\s+\S/)&&tmpHTML.length>0&&tmpHTML[tmpHTML.length-1].endsWith('</li>')){let tmpLastIndex=tmpHTML.length-1;let tmpListItemBody=tmpHTML[tmpLastIndex].slice(0,-'</li>'.length);tmpHTML[tmpLastIndex]=tmpListItemBody+' '+this.parseInline(tmpLine.trim(),pLinkResolver,pImageResolver,pVocabularyResolver)+'</li>';continue;}// Close list if we've left list items
6054
6059
  if(tmpInList&&tmpLine.trim()!==''){tmpHTML.push(tmpListType==='ul'?'</ul>':'</ol>');tmpInList=false;}// Empty line — flush any accumulated paragraph
6055
6060
  if(tmpLine.trim()===''){fFlushParagraph();continue;}// Table detection
6056
6061
  if(tmpLine.match(/^\|/)&&i+1<tmpLines.length&&tmpLines[i+1].match(/^\|[\s-:|]+\|/)){fFlushParagraph();// Close any open list
@@ -12634,7 +12639,7 @@ try{if(!global.localStorage)return false;}catch(_){return false;}var val=global.
12634
12639
  // presumably different callback function.
12635
12640
  // This makes sure that own properties are retained, so that
12636
12641
  // decorations and such are not lost along the way.
12637
- module.exports=wrappy;function wrappy(fn,cb){if(fn&&cb)return wrappy(fn)(cb);if(typeof fn!=='function')throw new TypeError('need wrapper function');Object.keys(fn).forEach(function(k){wrapper[k]=fn[k];});return wrapper;function wrapper(){var args=new Array(arguments.length);for(var i=0;i<args.length;i++){args[i]=arguments[i];}var ret=fn.apply(this,args);var cb=args[args.length-1];if(typeof ret==='function'&&ret!==cb){Object.keys(cb).forEach(function(k){ret[k]=cb[k];});}return ret;}}},{}],346:[function(require,module,exports){module.exports=extend;var hasOwnProperty=Object.prototype.hasOwnProperty;function extend(){var target={};for(var i=0;i<arguments.length;i++){var source=arguments[i];for(var key in source){if(hasOwnProperty.call(source,key)){target[key]=source[key];}}}return target;}},{}],347:[function(require,module,exports){module.exports={"name":"pict-docuserve","version":"1.3.3","description":"Pict Documentation Server - A single-page documentation viewer built on Pict","main":"source/Pict-Application-Docuserve.js","bin":{"pict-docuserve":"source/cli/Docuserve-CLI-Run.js"},"files":["source/","dist/","html/"],"scripts":{"start":"node source/cli/Docuserve-CLI-Run.js serve","brand":"node node_modules/pict-section-theme/bin/pict-section-theme-brand.js --manifest ../../../Retold-Modules-Manifest.json --module pict-docuserve","prebuild":"npm run brand","build":"npx quack build && npx quack copy","prebuild-docs":"npm run brand","build-docs":"npx quack build && npx quack copy && node source/cli/Docuserve-CLI-Run.js inject ./docs && node example_applications/build-examples.js stage-docs","serve-docs":"node source/cli/Docuserve-CLI-Run.js serve ./docs","serve-examples":"node example_applications/build-examples.js","test":"npx quack test","tests":"npx quack test -g","coverage":"npx quack coverage","prepublishOnly":"npm run build"},"author":"steven velozo <steven@velozo.com>","license":"MIT","dependencies":{"fable-serviceproviderbase":"^3.0.19","lunr":"^2.3.9","pict":"^1.0.372","pict-application":"^1.0.34","pict-provider":"^1.0.13","pict-section-code":"^1.0.11","pict-section-content":"^1.0.3","pict-section-histogram":"^1.0.1","pict-section-modal":"^1.1.1","pict-section-theme":"^1.0.5","pict-service-commandlineutility":"^1.0.19","pict-view":"^1.0.68"},"devDependencies":{"pict-docuserve":"^1.3.2","quackage":"^1.2.4"},"copyFilesSettings":{"whenFileExists":"overwrite"},"copyFiles":[{"from":"./html/*","to":"./dist/"}],"mocha":{"diff":true,"extension":["js"],"package":"./package.json","reporter":"spec","slow":"75","timeout":"5000","ui":"tdd","watch-files":["source/**/*.js","test/**/*.js"],"watch-ignore":["lib/vendor"]},"retold":{"brand":{"Hash":"pict-docuserve","Name":"Pict Docuserve","Tagline":"A documentation viewer built on Pict","Palette":"default","Icon":"<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 96 96\" width=\"96\" height=\"96\">\n\t\t<defs>\n\t\t\t<clipPath id=\"frame-pict-docuserve-filled-light\">\n\t\t\t\t<path d=\"M 2 48\n\t\t\tC 2 18.0222416, 18.0222416 2, 48 2\n\t\t\tC 77.9777584 2, 94 18.0222416, 94 48\n\t\t\tC 94 77.9777584, 77.9777584 94, 48 94\n\t\t\tC 18.0222416 94, 2 77.9777584, 2 48 Z\"/>\n\t\t\t</clipPath>\n\t\t</defs>\n\t\t<path d=\"M 2 48\n\t\t\tC 2 18.0222416, 18.0222416 2, 48 2\n\t\t\tC 77.9777584 2, 94 18.0222416, 94 48\n\t\t\tC 94 77.9777584, 77.9777584 94, 48 94\n\t\t\tC 18.0222416 94, 2 77.9777584, 2 48 Z\" fill=\"#692bbf\"/>\n\t\t<g clip-path=\"url(#frame-pict-docuserve-filled-light)\"><rect x=\"18\" y=\"30\" width=\"48\" height=\"48\" rx=\"8\" fill=\"#c13ccd\" opacity=\"0.9\"/>\n\t\t\t\t\t<rect x=\"30\" y=\"18\" width=\"48\" height=\"48\" rx=\"8\" fill=\"rgba(255,255,255,0.18)\"/></g>\n\t\t<text x=\"48\" y=\"50\" text-anchor=\"middle\" dominant-baseline=\"central\"\n\t\t\tfont-family=\"-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif\"\n\t\t\tfont-size=\"38\" font-weight=\"600\"\n\t\t\tfill=\"#ffffff\" letter-spacing=\"-1\">PD</text>\n\t</svg>","IconType":"svg","Favicon":"<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 96 96\" width=\"96\" height=\"96\">\n\t\t<defs>\n\t\t\t<clipPath id=\"fav-pict-docuserve-light\">\n\t\t\t\t<path d=\"M 2 48\n\t\t\tC 2 18.0222416, 18.0222416 2, 48 2\n\t\t\tC 77.9777584 2, 94 18.0222416, 94 48\n\t\t\tC 94 77.9777584, 77.9777584 94, 48 94\n\t\t\tC 18.0222416 94, 2 77.9777584, 2 48 Z\"/>\n\t\t\t</clipPath>\n\t\t</defs>\n\t\t<path d=\"M 2 48\n\t\t\tC 2 18.0222416, 18.0222416 2, 48 2\n\t\t\tC 77.9777584 2, 94 18.0222416, 94 48\n\t\t\tC 94 77.9777584, 77.9777584 94, 48 94\n\t\t\tC 18.0222416 94, 2 77.9777584, 2 48 Z\" fill=\"#692bbf\"/>\n\t\t<g clip-path=\"url(#fav-pict-docuserve-light)\"><rect x=\"28\" y=\"16\" width=\"52\" height=\"52\" rx=\"9\" fill=\"rgba(255,255,255,0.22)\"/></g>\n\t\t<text x=\"48\" y=\"50\" text-anchor=\"middle\" dominant-baseline=\"central\"\n\t\t\tfont-family=\"-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif\"\n\t\t\tfont-size=\"60\" font-weight=\"800\"\n\t\t\tfill=\"#ffffff\" letter-spacing=\"-1\">P</text>\n\t</svg>","FaviconDark":"<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 96 96\" width=\"96\" height=\"96\">\n\t\t<defs>\n\t\t\t<clipPath id=\"fav-pict-docuserve-dark\">\n\t\t\t\t<path d=\"M 2 48\n\t\t\tC 2 18.0222416, 18.0222416 2, 48 2\n\t\t\tC 77.9777584 2, 94 18.0222416, 94 48\n\t\t\tC 94 77.9777584, 77.9777584 94, 48 94\n\t\t\tC 18.0222416 94, 2 77.9777584, 2 48 Z\"/>\n\t\t\t</clipPath>\n\t\t</defs>\n\t\t<path d=\"M 2 48\n\t\t\tC 2 18.0222416, 18.0222416 2, 48 2\n\t\t\tC 77.9777584 2, 94 18.0222416, 94 48\n\t\t\tC 94 77.9777584, 77.9777584 94, 48 94\n\t\t\tC 18.0222416 94, 2 77.9777584, 2 48 Z\" fill=\"#9a6fd8\"/>\n\t\t<g clip-path=\"url(#fav-pict-docuserve-dark)\"><rect x=\"28\" y=\"16\" width=\"52\" height=\"52\" rx=\"9\" fill=\"rgba(255,255,255,0.22)\"/></g>\n\t\t<text x=\"48\" y=\"50\" text-anchor=\"middle\" dominant-baseline=\"central\"\n\t\t\tfont-family=\"-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif\"\n\t\t\tfont-size=\"60\" font-weight=\"800\"\n\t\t\tfill=\"#101418\" letter-spacing=\"-1\">P</text>\n\t</svg>","Colors":{"Primary":"#692bbf","Secondary":"#c13ccd","PrimaryLight":"#692bbf","PrimaryDark":"#9a6fd8","SecondaryLight":"#c13ccd","SecondaryDark":"#d48adb"}}}};},{}],348:[function(require,module,exports){/**
12642
+ module.exports=wrappy;function wrappy(fn,cb){if(fn&&cb)return wrappy(fn)(cb);if(typeof fn!=='function')throw new TypeError('need wrapper function');Object.keys(fn).forEach(function(k){wrapper[k]=fn[k];});return wrapper;function wrapper(){var args=new Array(arguments.length);for(var i=0;i<args.length;i++){args[i]=arguments[i];}var ret=fn.apply(this,args);var cb=args[args.length-1];if(typeof ret==='function'&&ret!==cb){Object.keys(cb).forEach(function(k){ret[k]=cb[k];});}return ret;}}},{}],346:[function(require,module,exports){module.exports=extend;var hasOwnProperty=Object.prototype.hasOwnProperty;function extend(){var target={};for(var i=0;i<arguments.length;i++){var source=arguments[i];for(var key in source){if(hasOwnProperty.call(source,key)){target[key]=source[key];}}}return target;}},{}],347:[function(require,module,exports){module.exports={"name":"pict-docuserve","version":"1.3.4","description":"Pict Documentation Server - A single-page documentation viewer built on Pict","main":"source/Pict-Application-Docuserve.js","bin":{"pict-docuserve":"source/cli/Docuserve-CLI-Run.js"},"files":["source/","dist/","html/"],"scripts":{"start":"node source/cli/Docuserve-CLI-Run.js serve","brand":"node node_modules/pict-section-theme/bin/pict-section-theme-brand.js --manifest ../../../Retold-Modules-Manifest.json --module pict-docuserve","prebuild":"npm run brand","build":"npx quack build && npx quack copy","prebuild-docs":"npm run brand","build-docs":"npx quack build && npx quack copy && node source/cli/Docuserve-CLI-Run.js inject ./docs && node example_applications/build-examples.js stage-docs","serve-docs":"node source/cli/Docuserve-CLI-Run.js serve ./docs","serve-examples":"node example_applications/build-examples.js","test":"npx quack test","tests":"npx quack test -g","coverage":"npx quack coverage","prepublishOnly":"npm run build"},"author":"steven velozo <steven@velozo.com>","license":"MIT","dependencies":{"fable-serviceproviderbase":"^3.0.19","lunr":"^2.3.9","pict":"^1.0.372","pict-application":"^1.0.34","pict-provider":"^1.0.13","pict-section-code":"^1.0.11","pict-section-content":"^1.0.4","pict-section-histogram":"^1.0.1","pict-section-modal":"^1.1.1","pict-section-theme":"^1.0.5","pict-service-commandlineutility":"^1.0.19","pict-view":"^1.0.68"},"devDependencies":{"pict-docuserve":"^1.3.3","quackage":"^1.2.4"},"copyFilesSettings":{"whenFileExists":"overwrite"},"copyFiles":[{"from":"./html/*","to":"./dist/"}],"mocha":{"diff":true,"extension":["js"],"package":"./package.json","reporter":"spec","slow":"75","timeout":"5000","ui":"tdd","watch-files":["source/**/*.js","test/**/*.js"],"watch-ignore":["lib/vendor"]},"retold":{"brand":{"Hash":"pict-docuserve","Name":"Pict Docuserve","Tagline":"A documentation viewer built on Pict","Palette":"default","Icon":"<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 96 96\" width=\"96\" height=\"96\">\n\t\t<defs>\n\t\t\t<clipPath id=\"frame-pict-docuserve-filled-light\">\n\t\t\t\t<path d=\"M 2 48\n\t\t\tC 2 18.0222416, 18.0222416 2, 48 2\n\t\t\tC 77.9777584 2, 94 18.0222416, 94 48\n\t\t\tC 94 77.9777584, 77.9777584 94, 48 94\n\t\t\tC 18.0222416 94, 2 77.9777584, 2 48 Z\"/>\n\t\t\t</clipPath>\n\t\t</defs>\n\t\t<path d=\"M 2 48\n\t\t\tC 2 18.0222416, 18.0222416 2, 48 2\n\t\t\tC 77.9777584 2, 94 18.0222416, 94 48\n\t\t\tC 94 77.9777584, 77.9777584 94, 48 94\n\t\t\tC 18.0222416 94, 2 77.9777584, 2 48 Z\" fill=\"#692bbf\"/>\n\t\t<g clip-path=\"url(#frame-pict-docuserve-filled-light)\"><rect x=\"18\" y=\"30\" width=\"48\" height=\"48\" rx=\"8\" fill=\"#c13ccd\" opacity=\"0.9\"/>\n\t\t\t\t\t<rect x=\"30\" y=\"18\" width=\"48\" height=\"48\" rx=\"8\" fill=\"rgba(255,255,255,0.18)\"/></g>\n\t\t<text x=\"48\" y=\"50\" text-anchor=\"middle\" dominant-baseline=\"central\"\n\t\t\tfont-family=\"-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif\"\n\t\t\tfont-size=\"38\" font-weight=\"600\"\n\t\t\tfill=\"#ffffff\" letter-spacing=\"-1\">PD</text>\n\t</svg>","IconType":"svg","Favicon":"<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 96 96\" width=\"96\" height=\"96\">\n\t\t<defs>\n\t\t\t<clipPath id=\"fav-pict-docuserve-light\">\n\t\t\t\t<path d=\"M 2 48\n\t\t\tC 2 18.0222416, 18.0222416 2, 48 2\n\t\t\tC 77.9777584 2, 94 18.0222416, 94 48\n\t\t\tC 94 77.9777584, 77.9777584 94, 48 94\n\t\t\tC 18.0222416 94, 2 77.9777584, 2 48 Z\"/>\n\t\t\t</clipPath>\n\t\t</defs>\n\t\t<path d=\"M 2 48\n\t\t\tC 2 18.0222416, 18.0222416 2, 48 2\n\t\t\tC 77.9777584 2, 94 18.0222416, 94 48\n\t\t\tC 94 77.9777584, 77.9777584 94, 48 94\n\t\t\tC 18.0222416 94, 2 77.9777584, 2 48 Z\" fill=\"#692bbf\"/>\n\t\t<g clip-path=\"url(#fav-pict-docuserve-light)\"><rect x=\"28\" y=\"16\" width=\"52\" height=\"52\" rx=\"9\" fill=\"rgba(255,255,255,0.22)\"/></g>\n\t\t<text x=\"48\" y=\"50\" text-anchor=\"middle\" dominant-baseline=\"central\"\n\t\t\tfont-family=\"-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif\"\n\t\t\tfont-size=\"60\" font-weight=\"800\"\n\t\t\tfill=\"#ffffff\" letter-spacing=\"-1\">P</text>\n\t</svg>","FaviconDark":"<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 96 96\" width=\"96\" height=\"96\">\n\t\t<defs>\n\t\t\t<clipPath id=\"fav-pict-docuserve-dark\">\n\t\t\t\t<path d=\"M 2 48\n\t\t\tC 2 18.0222416, 18.0222416 2, 48 2\n\t\t\tC 77.9777584 2, 94 18.0222416, 94 48\n\t\t\tC 94 77.9777584, 77.9777584 94, 48 94\n\t\t\tC 18.0222416 94, 2 77.9777584, 2 48 Z\"/>\n\t\t\t</clipPath>\n\t\t</defs>\n\t\t<path d=\"M 2 48\n\t\t\tC 2 18.0222416, 18.0222416 2, 48 2\n\t\t\tC 77.9777584 2, 94 18.0222416, 94 48\n\t\t\tC 94 77.9777584, 77.9777584 94, 48 94\n\t\t\tC 18.0222416 94, 2 77.9777584, 2 48 Z\" fill=\"#9a6fd8\"/>\n\t\t<g clip-path=\"url(#fav-pict-docuserve-dark)\"><rect x=\"28\" y=\"16\" width=\"52\" height=\"52\" rx=\"9\" fill=\"rgba(255,255,255,0.22)\"/></g>\n\t\t<text x=\"48\" y=\"50\" text-anchor=\"middle\" dominant-baseline=\"central\"\n\t\t\tfont-family=\"-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif\"\n\t\t\tfont-size=\"60\" font-weight=\"800\"\n\t\t\tfill=\"#101418\" letter-spacing=\"-1\">P</text>\n\t</svg>","Colors":{"Primary":"#692bbf","Secondary":"#c13ccd","PrimaryLight":"#692bbf","PrimaryDark":"#9a6fd8","SecondaryLight":"#c13ccd","SecondaryDark":"#d48adb"}}}};},{}],348:[function(require,module,exports){/**
12638
12643
  * Docuserve-Brand — docuserve's own wordmark, used only as a fallback.
12639
12644
  *
12640
12645
  * Docuserve is a viewer: the docs being served dictate the brand, not
@@ -12814,9 +12819,9 @@ let tmpPath=pDocPath;if(!tmpPath.match(/\.md$/)){tmpPath=tmpPath+'.md';}tmpDocPr
12814
12819
  // <path>/README.md so directory-style links resolve.
12815
12820
  if(pError&&!tmpPath.match(/(^|\/)README\.md$/i)){let tmpReadmePath=tmpPath.replace(/\.md$/i,'')+'/README.md';tmpDocProvider.fetchLocalDocument(tmpReadmePath,(pReadmeError,pReadmeHTML)=>{// Show the README on success, else the original
12816
12821
  // not-found page (it names the path the user asked for).
12817
- tmpContentView.displayContent(pReadmeError?pHTML:pReadmeHTML);});return;}// fetchDocument always provides displayable HTML in pHTML,
12822
+ tmpContentView.displayContent(pReadmeError?pHTML:pReadmeHTML);},'','',tmpReadmePath);return;}// fetchDocument always provides displayable HTML in pHTML,
12818
12823
  // even on error, so we can use it directly.
12819
- tmpContentView.displayContent(pHTML);});}/**
12824
+ tmpContentView.displayContent(pHTML);},'','',tmpPath);}/**
12820
12825
  * Navigate to the search page with an optional query.
12821
12826
  *
12822
12827
  * @param {string} pQuery - The search query (may be empty for blank search page)
@@ -12932,14 +12937,19 @@ this._ContentProvider=this.pict.addProvider('Pict-Content',libPictContentProvide
12932
12937
  * @param {string} [pCurrentModule] - The current module name
12933
12938
  * @param {string} [pCurrentDocPath] - The current document path
12934
12939
  * @returns {Function} A link resolver callback
12935
- */_createLinkResolver(pCurrentGroup,pCurrentModule,pCurrentDocPath){return(pHref,pLinkText)=>{// Built example applications (and other static .html pages) are
12940
+ */_createLinkResolver(pCurrentGroup,pCurrentModule,pCurrentDocPath){return(pHref,pLinkText)=>{let tmpHref=String(pHref||'');let tmpIsModuleMode=this.getDocsMode()==='module';// Built example applications (and other static .html pages) are
12936
12941
  // served as plain files alongside the docs. Link straight to
12937
- // them in a new tab rather than SPA-routing through #/page/.
12938
- // Scoped strictly to the .html extension .md pages, catalog
12939
- // routes and http(s):// links fall through unaffected.
12940
- if(!pHref.match(/^[a-z][a-z0-9+.-]*:/i)&&pHref.match(/\.html($|[?#])/i)){return{href:pHref,target:'_blank',rel:'noopener'};}// Convert internal doc links to hash routes
12941
- if(pHref.match(/^\//)||pHref.match(/^[^:]+\.md/)){let tmpRoute=this.convertDocLink(pHref,pCurrentGroup,pCurrentModule,pCurrentDocPath);return{href:tmpRoute};}// Check if this is a GitHub URL that matches a catalog module
12942
- let tmpCatalogRoute=this.resolveGitHubURLToRoute(pHref);if(tmpCatalogRoute){return{href:tmpCatalogRoute};}// Use default behavior for other links
12942
+ // them in a new tab rather than SPA-routing through #/page/. In
12943
+ // module mode the href is resolved against the current
12944
+ // document's directory, exactly the way a .md link is — so every
12945
+ // relative link in the docs shares one base.
12946
+ if(!tmpHref.match(/^[a-z][a-z0-9+.-]*:/i)&&tmpHref.match(/\.html($|[?#])/i)){let tmpAssetHref=tmpIsModuleMode?this._toModuleAssetHref(tmpHref,pCurrentDocPath):tmpHref;return{href:tmpAssetHref,target:'_blank',rel:'noopener'};}// Convert internal doc links to hash routes
12947
+ if(tmpHref.match(/^\//)||tmpHref.match(/^[^:]+\.md/)){let tmpRoute=this.convertDocLink(tmpHref,pCurrentGroup,pCurrentModule,pCurrentDocPath);return{href:tmpRoute};}// Check if this is a GitHub URL that matches a catalog module
12948
+ let tmpCatalogRoute=this.resolveGitHubURLToRoute(tmpHref);if(tmpCatalogRoute){return{href:tmpCatalogRoute};}// Module mode: a remaining relative link (a directory, a media
12949
+ // file, a .json) is resolved against the current document's
12950
+ // directory too, so it shares the one base every other link uses
12951
+ // rather than silently falling back to the docs root.
12952
+ if(tmpIsModuleMode&&tmpHref&&tmpHref.charAt(0)!=='#'&&tmpHref.indexOf('//')!==0&&!tmpHref.match(/^[a-z][a-z0-9+.-]*:/i)){return{href:this._toModuleAssetHref(tmpHref,pCurrentDocPath)};}// Use default behavior for other links
12943
12953
  return null;};}/**
12944
12954
  * Create an image resolver closure for the content provider.
12945
12955
  *
@@ -12998,7 +13008,9 @@ if(!this.pict.AppData.Docuserve.CoverLoaded){this.pict.AppData.Docuserve.Cover={
12998
13008
  *
12999
13009
  * @param {string} pMarkdown - Raw _cover.md content
13000
13010
  * @returns {Object} Parsed cover data
13001
- */parseCover(pMarkdown){let tmpCover={Title:'',Tagline:'',Description:'',Highlights:[],Actions:[]};let tmpLines=pMarkdown.split('\n');for(let i=0;i<tmpLines.length;i++){let tmpLine=tmpLines[i].trim();if(!tmpLine){continue;}// Heading — the title
13011
+ */parseCover(pMarkdown){let tmpCover={Title:'',Tagline:'',Description:'',Highlights:[],Actions:[],ExamplesMarkdown:''};let tmpLines=pMarkdown.split('\n');let tmpInExamples=false;for(let i=0;i<tmpLines.length;i++){let tmpLine=tmpLines[i].trim();// Generated examples region collected verbatim for the splash's
13012
+ // "Interactive Examples" section, never parsed as cover fields.
13013
+ if(tmpLine==='<!-- docuserve:examples:start -->'){tmpInExamples=true;continue;}if(tmpLine==='<!-- docuserve:examples:end -->'){tmpInExamples=false;continue;}if(tmpInExamples){if(tmpLine){tmpCover.ExamplesMarkdown+=(tmpCover.ExamplesMarkdown?'\n':'')+tmpLine;}continue;}if(!tmpLine){continue;}// Heading — the title
13002
13014
  let tmpHeadingMatch=tmpLine.match(/^#+\s+(.+)/);if(tmpHeadingMatch){tmpCover.Title=tmpHeadingMatch[1].trim();continue;}// Blockquote — the tagline
13003
13015
  let tmpBlockquoteMatch=tmpLine.match(/^>\s*(.*)/);if(tmpBlockquoteMatch){tmpCover.Tagline=tmpBlockquoteMatch[1].trim();continue;}// Bullet list — highlights (e.g. "- **Fable** — Core ecosystem, DI, config")
13004
13016
  let tmpBulletMatch=tmpLine.match(/^[-*+]\s+(.*)/);if(tmpBulletMatch){let tmpBulletContent=tmpBulletMatch[1];// Try to split on bold label: **Label** — rest
@@ -13109,11 +13121,41 @@ let tmpURL;if(pGroup&&pModule&&this._Catalog){tmpURL=this.resolveDocumentURL(pGr
13109
13121
  * @returns {string} 'module' | 'ecosystem' | 'legacy'
13110
13122
  */getDocsMode(){if(this._Catalog&&(this._Catalog.Mode==='module'||this._Catalog.Mode==='ecosystem')){return this._Catalog.Mode;}if(this._KeywordIndexMode==='module'||this._KeywordIndexMode==='ecosystem'){return this._KeywordIndexMode;}return'legacy';}/**
13111
13123
  * Module-mode link resolution: every internal documentation reference is
13112
- * a local page. Normalizes an href to a #/page/ hash route.
13124
+ * a local page. Relative links (./sibling.md, ../other.md, bare names)
13125
+ * resolve against the directory of the document that contains them — the
13126
+ * way the links read on disk — while a /-rooted href resolves against the
13127
+ * docs root. "." and ".." segments are collapsed; ".." is clamped at the
13128
+ * docs root so a link can never escape above it.
13113
13129
  *
13114
13130
  * @param {string} pHref - The raw link href
13131
+ * @param {string} [pCurrentDocPath] - Docs-root-relative path of the
13132
+ * document the link lives in (e.g.
13133
+ * "examples/gradebook/README.md"). Absent for root-level
13134
+ * contexts such as the sidebar.
13115
13135
  * @returns {string} A #/page/ hash route (#/Home for an empty path)
13116
- */_toModulePageRoute(pHref){let tmpPath=String(pHref||'').replace(/^\.\//,'').replace(/^\//,'').replace(/\/+$/,'');if(!tmpPath){return'#/Home';}return'#/page/'+tmpPath.replace(/\.md$/i,'');}/**
13136
+ */_toModulePageRoute(pHref,pCurrentDocPath){let tmpHref=String(pHref||'').trim();// A /-rooted href resolves against the docs root; every other href
13137
+ // resolves against the current document's directory.
13138
+ let tmpBaseDir='';if(tmpHref.charAt(0)==='/'){tmpHref=tmpHref.replace(/^\/+/,'');}else if(pCurrentDocPath){let tmpDirParts=String(pCurrentDocPath).split('/');tmpDirParts.pop();tmpBaseDir=tmpDirParts.join('/');}let tmpPath=this._resolveRelativeDocPath(tmpBaseDir,tmpHref);if(!tmpPath){return'#/Home';}return'#/page/'+tmpPath.replace(/\.md$/i,'');}/**
13139
+ * Resolve a relative href against a base directory, collapsing "." and
13140
+ * ".." segments. ".." is clamped at the docs root — it can never escape
13141
+ * above it. Both arguments are POSIX-style docs-root-relative paths.
13142
+ *
13143
+ * @param {string} pBaseDir - The directory the href is relative to.
13144
+ * @param {string} pHref - The href to resolve.
13145
+ * @returns {string} The resolved docs-root-relative path (no leading slash).
13146
+ */_resolveRelativeDocPath(pBaseDir,pHref){let tmpSegments=[];let tmpCombined=(pBaseDir?pBaseDir+'/':'')+String(pHref||'');let tmpParts=tmpCombined.split('/');for(let i=0;i<tmpParts.length;i++){let tmpPart=tmpParts[i];if(tmpPart===''||tmpPart==='.'){continue;}if(tmpPart==='..'){if(tmpSegments.length>0){tmpSegments.pop();}continue;}tmpSegments.push(tmpPart);}return tmpSegments.join('/');}/**
13147
+ * Module-mode resolution for a non-routed link — a built .html page, a
13148
+ * media file, a directory. Resolves the href against the current
13149
+ * document's directory (a /-rooted href against the docs root), the same
13150
+ * way _toModulePageRoute resolves a .md link, and returns a plain
13151
+ * docs-root-relative href. The browser resolves that href against the
13152
+ * docs-root index.html, so it points at the right file from any page.
13153
+ *
13154
+ * @param {string} pHref - The raw link href
13155
+ * @param {string} [pCurrentDocPath] - Docs-root-relative path of the
13156
+ * document the link lives in.
13157
+ * @returns {string} A docs-root-relative href.
13158
+ */_toModuleAssetHref(pHref,pCurrentDocPath){let tmpHref=String(pHref||'').trim();if(!tmpHref){return tmpHref;}let tmpBaseDir='';if(tmpHref.charAt(0)==='/'){tmpHref=tmpHref.replace(/^\/+/,'');}else if(pCurrentDocPath){let tmpDirParts=String(pCurrentDocPath).split('/');tmpDirParts.pop();tmpBaseDir=tmpDirParts.join('/');}return this._resolveRelativeDocPath(tmpBaseDir,tmpHref);}/**
13117
13159
  * Check whether a group/module pair exists in the loaded catalog.
13118
13160
  *
13119
13161
  * Used by search() to decide whether a result should route to
@@ -13322,8 +13364,9 @@ if(this._ContentCache[pURL]){return tmpCallback(null,this._ContentCache[pURL]);}
13322
13364
  * @param {string} [pCurrentModule] - The current module name (e.g. "fable")
13323
13365
  * @param {string} [pCurrentDocPath] - The current document path within the module (e.g. "services/README.md")
13324
13366
  * @returns {string} The converted hash route
13325
- */convertDocLink(pHref,pCurrentGroup,pCurrentModule,pCurrentDocPath){// Single-module docs site: every internal reference is a local page.
13326
- if(this.getDocsMode()==='module'){return this._toModulePageRoute(pHref);}// Strip leading ./ prefix for relative paths
13367
+ */convertDocLink(pHref,pCurrentGroup,pCurrentModule,pCurrentDocPath){// Single-module docs site: every internal reference is a local page,
13368
+ // resolved relative to the current document's directory.
13369
+ if(this.getDocsMode()==='module'){return this._toModulePageRoute(pHref,pCurrentDocPath);}// Strip leading ./ prefix for relative paths
13327
13370
  let tmpPath=pHref.replace(/^\.\//,'');// Remove leading slash
13328
13371
  tmpPath=tmpPath.replace(/^\//,'');// If it looks like an absolute module path (group/module/...), route directly.
13329
13372
  // Both the group AND the module must exist in the catalog, otherwise treat
@@ -13885,7 +13928,9 @@ let tmpGroupRoute=tmpGroup.Route||'';if(!tmpGroupRoute){for(let k=0;k<tmpGroup.M
13885
13928
  // new section each time the title changes.
13886
13929
  if(tmpSidebar&&tmpSidebar.length>0){let tmpCurrentSection=null;for(let i=0;i<tmpSidebar.length;i++){let tmpEntry=tmpSidebar[i];if(tmpEntry.Children){tmpCurrentSection={TitleSlot:[{Title:tmpEntry.Title}],Items:[]};tmpSections.push(tmpCurrentSection);for(let j=0;j<tmpEntry.Children.length;j++){let tmpChild=tmpEntry.Children[j];if(tmpChild.Path){tmpCurrentSection.Items.push({Title:tmpChild.Title,Route:tmpRoutePrefix+tmpChild.Path,ActiveClass:''});}}}else if(tmpEntry.Path){if(!tmpCurrentSection||tmpCurrentSection.TitleSlot.length>0){tmpCurrentSection={TitleSlot:[],Items:[]};tmpSections.push(tmpCurrentSection);}tmpCurrentSection.Items.push({Title:tmpEntry.Title,Route:tmpRoutePrefix+tmpEntry.Path,ActiveClass:''});}}}// Demos sub-section: titled, with active state mirroring the
13887
13930
  // current demo route.
13888
- if(tmpDemos.length>0){let tmpDemoSection={TitleSlot:[{Title:'Demos'}],Items:[]};for(let i=0;i<tmpDemos.length;i++){let tmpDemo=tmpDemos[i];tmpDemoSection.Items.push({Title:tmpDemo.Name||tmpDemo.Hash,Route:tmpDemoPrefix+tmpDemo.Hash,ActiveClass:tmpDemo.Hash===tmpCurrentDemo?'active':''});}tmpSections.push(tmpDemoSection);}this.pict.AppData.Docuserve.ModuleNavSections=tmpSections;}_refreshSearchResults(pQuery){let tmpDocuserve=this.pict.AppData.Docuserve;if(!pQuery||!pQuery.trim()){tmpDocuserve.SidebarSearchResults=[];tmpDocuserve.SidebarSearchOverflow=[];tmpDocuserve.SidebarSearchEmpty=[];return;}let tmpDocProvider=this.pict.providers['Docuserve-Documentation'];let tmpResults=tmpDocProvider.search(pQuery);if(tmpResults.length===0){tmpDocuserve.SidebarSearchResults=[];tmpDocuserve.SidebarSearchOverflow=[];tmpDocuserve.SidebarSearchEmpty=[{}];return;}let tmpMaxResults=8;let tmpDisplayResults=[];for(let i=0;i<tmpResults.length&&i<tmpMaxResults;i++){let tmpResult=tmpResults[i];let tmpMeta=tmpResult.Group&&tmpResult.Module?tmpResult.Group+' / '+tmpResult.Module:'';tmpDisplayResults.push({Title:tmpResult.Title,Route:tmpResult.Route,MetaSlot:tmpMeta?[{Meta:tmpMeta}]:[]});}tmpDocuserve.SidebarSearchResults=tmpDisplayResults;tmpDocuserve.SidebarSearchEmpty=[];if(tmpResults.length>tmpMaxResults){tmpDocuserve.SidebarSearchOverflow=[{EncodedQuery:encodeURIComponent(pQuery),TotalCount:tmpResults.length}];}else{tmpDocuserve.SidebarSearchOverflow=[];}}}module.exports=DocusserveSidebarView;module.exports.default_configuration=_ViewConfiguration;},{"pict-view":231}],359:[function(require,module,exports){const libPictView=require('pict-view');const _ViewConfiguration={ViewIdentifier:"Docuserve-Splash",DefaultRenderable:"Docuserve-Splash-Content",DefaultDestinationAddress:"#Docuserve-Content-Container",AutoRender:false,CSS:/*css*/"\n\t\t.docuserve-splash {\n\t\t\tdisplay: flex;\n\t\t\tflex-direction: column;\n\t\t\talign-items: center;\n\t\t\tjustify-content: center;\n\t\t\tmin-height: calc(100vh - 56px);\n\t\t\tpadding: 3em 2em;\n\t\t\ttext-align: center;\n\t\t\tbackground: var(--theme-color-background-primary, #FDFBF7);\n\t\t}\n\t\t.docuserve-splash h1 {\n\t\t\tfont-size: 3em;\n\t\t\tfont-weight: 700;\n\t\t\tcolor: var(--theme-color-text-primary, #3D3229);\n\t\t\tmargin: 0 0 0.25em 0;\n\t\t}\n\t\t.docuserve-splash h1 small {\n\t\t\tfont-size: 0.4em;\n\t\t\tfont-weight: 400;\n\t\t\tcolor: var(--theme-color-text-muted, #8A7F72);\n\t\t\tvertical-align: middle;\n\t\t\tmargin-left: 0.15em;\n\t\t}\n\t\t.docuserve-splash-tagline {\n\t\t\tfont-size: 1.25em;\n\t\t\tcolor: var(--theme-color-text-secondary, #5E5549);\n\t\t\tmargin-bottom: 1.5em;\n\t\t\tfont-style: italic;\n\t\t}\n\t\t.docuserve-splash-description {\n\t\t\tfont-size: 1em;\n\t\t\tcolor: var(--theme-color-text-secondary, #5E5549);\n\t\t\tmax-width: 600px;\n\t\t\tline-height: 1.7;\n\t\t\tmargin-bottom: 2em;\n\t\t}\n\t\t.docuserve-splash-highlights {\n\t\t\tdisplay: grid;\n\t\t\tgrid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n\t\t\tgap: 1.25em;\n\t\t\tmax-width: 900px;\n\t\t\twidth: 100%;\n\t\t\tmargin-bottom: 2.5em;\n\t\t}\n\t\t.docuserve-splash-highlight-card {\n\t\t\tbackground: var(--theme-color-background-panel, #FFFFFF);\n\t\t\tborder: 1px solid var(--theme-color-border-default, #DDD6CA);\n\t\t\tborder-radius: 8px;\n\t\t\tpadding: 1.25em;\n\t\t\ttext-align: left;\n\t\t\ttransition: box-shadow 0.2s, border-color 0.2s;\n\t\t}\n\t\t.docuserve-splash-highlight-card:hover {\n\t\t\tbox-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);\n\t\t\tborder-color: var(--theme-color-brand-primary, #2E7D74);\n\t\t}\n\t\t.docuserve-splash-highlight-card h3 {\n\t\t\tmargin: 0 0 0.5em 0;\n\t\t\tcolor: var(--theme-color-text-primary, #3D3229);\n\t\t\tfont-size: 1em;\n\t\t}\n\t\t.docuserve-splash-highlight-card p {\n\t\t\tmargin: 0;\n\t\t\tcolor: var(--theme-color-text-secondary, #5E5549);\n\t\t\tfont-size: 0.85em;\n\t\t\tline-height: 1.5;\n\t\t}\n\t\t.docuserve-splash-actions {\n\t\t\tdisplay: flex;\n\t\t\tgap: 1em;\n\t\t\tflex-wrap: wrap;\n\t\t\tjustify-content: center;\n\t\t}\n\t\t.docuserve-splash-actions a {\n\t\t\tdisplay: inline-block;\n\t\t\tpadding: 0.7em 1.5em;\n\t\t\tborder-radius: 6px;\n\t\t\tfont-size: 0.95em;\n\t\t\tfont-weight: 600;\n\t\t\ttext-decoration: none;\n\t\t\ttransition: background-color 0.15s, color 0.15s;\n\t\t\tcursor: pointer;\n\t\t}\n\t\t.docuserve-splash-actions .primary {\n\t\t\tbackground-color: var(--theme-color-brand-primary, #2E7D74);\n\t\t\t/* text-on-brand falls to a fixed light hex \u2014 never to background-panel,\n\t\t\t which inverts contrast in dark themes (dark text on brand bg). */\n\t\t\tcolor: var(--theme-color-text-on-brand, #fff);\n\t\t}\n\t\t.docuserve-splash-actions .primary:hover {\n\t\t\tbackground-color: var(--theme-color-brand-primary-hover, #236660);\n\t\t}\n\t\t.docuserve-splash-actions .secondary {\n\t\t\tbackground-color: var(--theme-color-background-panel, #FFFFFF);\n\t\t\tcolor: var(--theme-color-text-primary, #3D3229);\n\t\t\tborder: 2px solid var(--theme-color-brand-primary, #2E7D74);\n\t\t}\n\t\t.docuserve-splash-actions .secondary:hover {\n\t\t\tborder-color: var(--theme-color-brand-primary-hover, #236660);\n\t\t\tcolor: var(--theme-color-brand-primary, #2E7D74);\n\t\t}\n\t",Templates:[{Hash:"Docuserve-Splash-Template",Template:/*html*/"\n<div class=\"docuserve-splash\">\n\t<h1 id=\"Docuserve-Splash-Title\"></h1>\n\t<div class=\"docuserve-splash-tagline\" id=\"Docuserve-Splash-Tagline\"></div>\n\t<div class=\"docuserve-splash-description\" id=\"Docuserve-Splash-Description\"></div>\n\t<div class=\"docuserve-splash-highlights\" id=\"Docuserve-Splash-Highlights\"></div>\n\t<div class=\"docuserve-splash-actions\" id=\"Docuserve-Splash-Actions\"></div>\n</div>\n"}],Renderables:[{RenderableHash:"Docuserve-Splash-Content",TemplateHash:"Docuserve-Splash-Template",DestinationAddress:"#Docuserve-Content-Container",RenderMethod:"replace"}]};class DocusserveSplashView extends libPictView{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);}onAfterRender(pRenderable,pRenderDestinationAddress,pRecord,pContent){let tmpDocuserve=this.pict.AppData.Docuserve;if(tmpDocuserve.CoverLoaded&&tmpDocuserve.Cover){this.renderFromCover(tmpDocuserve.Cover);}else{this.renderFromCatalog(tmpDocuserve);}return super.onAfterRender(pRenderable,pRenderDestinationAddress,pRecord,pContent);}/**
13931
+ if(tmpDemos.length>0){let tmpDemoSection={TitleSlot:[{Title:'Demos'}],Items:[]};for(let i=0;i<tmpDemos.length;i++){let tmpDemo=tmpDemos[i];tmpDemoSection.Items.push({Title:tmpDemo.Name||tmpDemo.Hash,Route:tmpDemoPrefix+tmpDemo.Hash,ActiveClass:tmpDemo.Hash===tmpCurrentDemo?'active':''});}tmpSections.push(tmpDemoSection);}this.pict.AppData.Docuserve.ModuleNavSections=tmpSections;}_refreshSearchResults(pQuery){let tmpDocuserve=this.pict.AppData.Docuserve;if(!pQuery||!pQuery.trim()){tmpDocuserve.SidebarSearchResults=[];tmpDocuserve.SidebarSearchOverflow=[];tmpDocuserve.SidebarSearchEmpty=[];return;}let tmpDocProvider=this.pict.providers['Docuserve-Documentation'];let tmpResults=tmpDocProvider.search(pQuery);if(tmpResults.length===0){tmpDocuserve.SidebarSearchResults=[];tmpDocuserve.SidebarSearchOverflow=[];tmpDocuserve.SidebarSearchEmpty=[{}];return;}let tmpMaxResults=8;let tmpDisplayResults=[];for(let i=0;i<tmpResults.length&&i<tmpMaxResults;i++){let tmpResult=tmpResults[i];let tmpMeta=tmpResult.Group&&tmpResult.Module?tmpResult.Group+' / '+tmpResult.Module:'';tmpDisplayResults.push({Title:tmpResult.Title,Route:tmpResult.Route,MetaSlot:tmpMeta?[{Meta:tmpMeta}]:[]});}tmpDocuserve.SidebarSearchResults=tmpDisplayResults;tmpDocuserve.SidebarSearchEmpty=[];if(tmpResults.length>tmpMaxResults){tmpDocuserve.SidebarSearchOverflow=[{EncodedQuery:encodeURIComponent(pQuery),TotalCount:tmpResults.length}];}else{tmpDocuserve.SidebarSearchOverflow=[];}}}module.exports=DocusserveSidebarView;module.exports.default_configuration=_ViewConfiguration;},{"pict-view":231}],359:[function(require,module,exports){const libPictView=require('pict-view');const _ViewConfiguration={ViewIdentifier:"Docuserve-Splash",DefaultRenderable:"Docuserve-Splash-Content",DefaultDestinationAddress:"#Docuserve-Content-Container",AutoRender:false,CSS:/*css*/"\n\t\t.docuserve-splash {\n\t\t\tdisplay: flex;\n\t\t\tflex-direction: column;\n\t\t\talign-items: center;\n\t\t\tjustify-content: center;\n\t\t\tmin-height: calc(100vh - 56px);\n\t\t\tpadding: 3em 2em;\n\t\t\ttext-align: center;\n\t\t\tbackground: var(--theme-color-background-primary, #FDFBF7);\n\t\t}\n\t\t.docuserve-splash h1 {\n\t\t\tfont-size: 3em;\n\t\t\tfont-weight: 700;\n\t\t\tcolor: var(--theme-color-text-primary, #3D3229);\n\t\t\tmargin: 0 0 0.25em 0;\n\t\t}\n\t\t.docuserve-splash h1 small {\n\t\t\tfont-size: 0.4em;\n\t\t\tfont-weight: 400;\n\t\t\tcolor: var(--theme-color-text-muted, #8A7F72);\n\t\t\tvertical-align: middle;\n\t\t\tmargin-left: 0.15em;\n\t\t}\n\t\t.docuserve-splash-tagline {\n\t\t\tfont-size: 1.25em;\n\t\t\tcolor: var(--theme-color-text-secondary, #5E5549);\n\t\t\tmargin-bottom: 1.5em;\n\t\t\tfont-style: italic;\n\t\t}\n\t\t.docuserve-splash-description {\n\t\t\tfont-size: 1em;\n\t\t\tcolor: var(--theme-color-text-secondary, #5E5549);\n\t\t\tmax-width: 600px;\n\t\t\tline-height: 1.7;\n\t\t\tmargin-bottom: 2em;\n\t\t}\n\t\t.docuserve-splash-highlights {\n\t\t\tdisplay: grid;\n\t\t\tgrid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n\t\t\tgap: 1.25em;\n\t\t\tmax-width: 900px;\n\t\t\twidth: 100%;\n\t\t\tmargin-bottom: 2.5em;\n\t\t}\n\t\t.docuserve-splash-highlight-card {\n\t\t\tbackground: var(--theme-color-background-panel, #FFFFFF);\n\t\t\tborder: 1px solid var(--theme-color-border-default, #DDD6CA);\n\t\t\tborder-radius: 8px;\n\t\t\tpadding: 1.25em;\n\t\t\ttext-align: left;\n\t\t\ttransition: box-shadow 0.2s, border-color 0.2s;\n\t\t}\n\t\t.docuserve-splash-highlight-card:hover {\n\t\t\tbox-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);\n\t\t\tborder-color: var(--theme-color-brand-primary, #2E7D74);\n\t\t}\n\t\t.docuserve-splash-highlight-card h3 {\n\t\t\tmargin: 0 0 0.5em 0;\n\t\t\tcolor: var(--theme-color-text-primary, #3D3229);\n\t\t\tfont-size: 1em;\n\t\t}\n\t\t.docuserve-splash-highlight-card p {\n\t\t\tmargin: 0;\n\t\t\tcolor: var(--theme-color-text-secondary, #5E5549);\n\t\t\tfont-size: 0.85em;\n\t\t\tline-height: 1.5;\n\t\t}\n\t\t.docuserve-splash-actions {\n\t\t\tdisplay: flex;\n\t\t\tgap: 1em;\n\t\t\tflex-wrap: wrap;\n\t\t\tjustify-content: center;\n\t\t}\n\t\t.docuserve-splash-actions a {\n\t\t\tdisplay: inline-block;\n\t\t\tpadding: 0.7em 1.5em;\n\t\t\tborder-radius: 6px;\n\t\t\tfont-size: 0.95em;\n\t\t\tfont-weight: 600;\n\t\t\ttext-decoration: none;\n\t\t\ttransition: background-color 0.15s, color 0.15s;\n\t\t\tcursor: pointer;\n\t\t}\n\t\t.docuserve-splash-actions .primary {\n\t\t\tbackground-color: var(--theme-color-brand-primary, #2E7D74);\n\t\t\t/* text-on-brand falls to a fixed light hex \u2014 never to background-panel,\n\t\t\t which inverts contrast in dark themes (dark text on brand bg). */\n\t\t\tcolor: var(--theme-color-text-on-brand, #fff);\n\t\t}\n\t\t.docuserve-splash-actions .primary:hover {\n\t\t\tbackground-color: var(--theme-color-brand-primary-hover, #236660);\n\t\t}\n\t\t.docuserve-splash-actions .secondary {\n\t\t\tbackground-color: var(--theme-color-background-panel, #FFFFFF);\n\t\t\tcolor: var(--theme-color-text-primary, #3D3229);\n\t\t\tborder: 2px solid var(--theme-color-brand-primary, #2E7D74);\n\t\t}\n\t\t.docuserve-splash-actions .secondary:hover {\n\t\t\tborder-color: var(--theme-color-brand-primary-hover, #236660);\n\t\t\tcolor: var(--theme-color-brand-primary, #2E7D74);\n\t\t}\n\t\t.docuserve-splash-examples {\n\t\t\tmax-width: 900px;\n\t\t\twidth: 100%;\n\t\t\tmargin-bottom: 2.5em;\n\t\t}\n\t\t/* No staged examples \u2014 collapse the section entirely. */\n\t\t.docuserve-splash-examples:empty {\n\t\t\tdisplay: none;\n\t\t\tmargin: 0;\n\t\t}\n\t\t.docuserve-splash-examples-heading {\n\t\t\tfont-size: 0.95em;\n\t\t\tfont-weight: 700;\n\t\t\ttext-transform: uppercase;\n\t\t\tletter-spacing: 0.08em;\n\t\t\tcolor: var(--theme-color-text-muted, #8A7F72);\n\t\t\tmargin: 0 0 0.85em 0;\n\t\t}\n\t\t.docuserve-splash-examples table {\n\t\t\twidth: 100%;\n\t\t\tborder-collapse: collapse;\n\t\t\tbackground: var(--theme-color-background-panel, #FFFFFF);\n\t\t\tborder: 1px solid var(--theme-color-border-default, #DDD6CA);\n\t\t\tborder-radius: 8px;\n\t\t\toverflow: hidden;\n\t\t}\n\t\t.docuserve-splash-examples thead th {\n\t\t\ttext-align: left;\n\t\t\tfont-size: 0.72em;\n\t\t\tfont-weight: 700;\n\t\t\ttext-transform: uppercase;\n\t\t\tletter-spacing: 0.06em;\n\t\t\tcolor: var(--theme-color-text-muted, #8A7F72);\n\t\t\tpadding: 0.7em 1.1em;\n\t\t\tbackground: var(--theme-color-background-tertiary, #F4EFE6);\n\t\t}\n\t\t.docuserve-splash-examples tbody td {\n\t\t\tpadding: 0.7em 1.1em;\n\t\t\tborder-top: 1px solid var(--theme-color-border-default, #DDD6CA);\n\t\t\tfont-size: 0.9em;\n\t\t\tcolor: var(--theme-color-text-secondary, #5E5549);\n\t\t\ttext-align: left;\n\t\t}\n\t\t.docuserve-splash-examples tbody tr:hover td {\n\t\t\tbackground: var(--theme-color-background-tertiary, #F4EFE6);\n\t\t}\n\t\t.docuserve-splash-examples a {\n\t\t\tcolor: var(--theme-color-brand-primary, #2E7D74);\n\t\t\tfont-weight: 600;\n\t\t\ttext-decoration: none;\n\t\t}\n\t\t.docuserve-splash-examples a:hover {\n\t\t\ttext-decoration: underline;\n\t\t}\n\t\t/* docs/README.md content rendered beneath the hero. */\n\t\t.docuserve-splash-readme {\n\t\t\tmax-width: 820px;\n\t\t\tmargin: 0 auto;\n\t\t\tpadding: 3.5em 2em 5em 2em;\n\t\t\ttext-align: left;\n\t\t}\n\t\t.docuserve-splash-readme:empty {\n\t\t\tdisplay: none;\n\t\t}\n\t",Templates:[{Hash:"Docuserve-Splash-Template",Template:/*html*/"\n<div class=\"docuserve-splash\">\n\t<h1 id=\"Docuserve-Splash-Title\"></h1>\n\t<div class=\"docuserve-splash-tagline\" id=\"Docuserve-Splash-Tagline\"></div>\n\t<div class=\"docuserve-splash-description\" id=\"Docuserve-Splash-Description\"></div>\n\t<div class=\"docuserve-splash-highlights\" id=\"Docuserve-Splash-Highlights\"></div>\n\t<div class=\"docuserve-splash-examples\" id=\"Docuserve-Splash-Examples\"></div>\n\t<div class=\"docuserve-splash-actions\" id=\"Docuserve-Splash-Actions\"></div>\n</div>\n<div class=\"docuserve-splash-readme\" id=\"Docuserve-Splash-Readme\"></div>\n"}],Renderables:[{RenderableHash:"Docuserve-Splash-Content",TemplateHash:"Docuserve-Splash-Template",DestinationAddress:"#Docuserve-Content-Container",RenderMethod:"replace"}]};class DocusserveSplashView extends libPictView{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);}onAfterRender(pRenderable,pRenderDestinationAddress,pRecord,pContent){let tmpDocuserve=this.pict.AppData.Docuserve;if(tmpDocuserve.CoverLoaded&&tmpDocuserve.Cover){this.renderFromCover(tmpDocuserve.Cover);this.renderExamples(tmpDocuserve.Cover);}else{this.renderFromCatalog(tmpDocuserve);}// Render docs/README.md beneath the hero — the splash fills the
13932
+ // viewport above the fold, the README content follows on scroll.
13933
+ this.renderReadme();return super.onAfterRender(pRenderable,pRenderDestinationAddress,pRecord,pContent);}/**
13889
13934
  * Render the splash screen from parsed _cover.md data.
13890
13935
  *
13891
13936
  * @param {Object} pCover - The parsed cover data { Title, Tagline, Description, Highlights, Actions }
@@ -13903,6 +13948,17 @@ let tmpTitle='Documentation';let tmpTagline='';if(pDocuserve.CatalogLoaded&&pDoc
13903
13948
  let tmpHighlightsHTML='';let tmpGroups=pDocuserve.SidebarGroups||[];for(let i=0;i<tmpGroups.length;i++){let tmpGroup=tmpGroups[i];// Skip groups with no modules (like "Home" or "Getting Started")
13904
13949
  if(!tmpGroup.Modules||tmpGroup.Modules.length<1){continue;}let tmpDescription=tmpGroup.Description||tmpGroup.Modules.length+' modules';tmpHighlightsHTML+='<div class="docuserve-splash-highlight-card">';tmpHighlightsHTML+='<h3>'+this.escapeHTML(tmpGroup.Name)+'</h3>';tmpHighlightsHTML+='<p>'+this.escapeHTML(tmpDescription)+'</p>';tmpHighlightsHTML+='</div>';}this.pict.ContentAssignment.assignContent('#Docuserve-Splash-Highlights',tmpHighlightsHTML);// Default action buttons
13905
13950
  this.pict.ContentAssignment.assignContent('#Docuserve-Splash-Actions','');}/**
13951
+ * Render the "Interactive Examples" section of the splash from the
13952
+ * examples region of _cover.md. When the cover carries no examples the
13953
+ * section is left empty — CSS collapses it — so it appears only when a
13954
+ * module has staged interactive examples.
13955
+ *
13956
+ * @param {Object} pCover - The parsed cover data.
13957
+ */renderExamples(pCover){let tmpExamplesMarkdown=pCover&&pCover.ExamplesMarkdown?pCover.ExamplesMarkdown:'';let tmpDocProvider=this.pict.providers['Docuserve-Documentation'];if(!tmpExamplesMarkdown||!tmpDocProvider||!tmpDocProvider._ContentProvider){this.pict.ContentAssignment.assignContent('#Docuserve-Splash-Examples','');return;}let tmpLinkResolver=tmpDocProvider._createLinkResolver('','','');let tmpExamplesHTML=tmpDocProvider._ContentProvider.parseMarkdown(tmpExamplesMarkdown,tmpLinkResolver);this.pict.ContentAssignment.assignContent('#Docuserve-Splash-Examples','<h2 class="docuserve-splash-examples-heading">Interactive Examples</h2>'+tmpExamplesHTML);}/**
13958
+ * Render docs/README.md beneath the splash hero. The landing page is the
13959
+ * full-viewport splash above the fold and the module's README content on
13960
+ * scroll. A missing or unreadable README simply leaves the section empty.
13961
+ */renderReadme(){let tmpDocProvider=this.pict.providers['Docuserve-Documentation'];let tmpDocsBase=this.pict.AppData.Docuserve.DocsBaseURL||'';fetch(tmpDocsBase+'README.md').then(pResponse=>pResponse.ok?pResponse.text():null).then(pMarkdown=>{if(!pMarkdown||!tmpDocProvider||!tmpDocProvider._ContentProvider){this.pict.ContentAssignment.assignContent('#Docuserve-Splash-Readme','');return;}let tmpLinkResolver=tmpDocProvider._createLinkResolver('','','README.md');let tmpImageResolver=tmpDocProvider._createImageResolver(tmpDocsBase+'README.md');let tmpHTML=tmpDocProvider._ContentProvider.parseMarkdown(pMarkdown,tmpLinkResolver,tmpImageResolver);this.pict.ContentAssignment.assignContent('#Docuserve-Splash-Readme','<div class="pict-content">'+tmpHTML+'</div>');}).catch(()=>{this.pict.ContentAssignment.assignContent('#Docuserve-Splash-Readme','');});}/**
13906
13962
  * Sanitize a title string, preserving only <small> tags.
13907
13963
  * All other HTML is escaped.
13908
13964
  *