spec-up-t 1.2.4 → 1.2.5
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/assets/compiled/body.js +6 -3
- package/assets/compiled/head.css +2 -0
- package/assets/css/add-bootstrap-classes-to-images.css +34 -0
- package/assets/css/image-full-size.css +44 -0
- package/assets/js/add-bootstrap-classes-to-images.js +98 -0
- package/assets/js/create-alphabet-index.js +11 -2
- package/assets/js/create-term-filter.js +12 -0
- package/assets/js/hide-show-utility-container.js +17 -0
- package/assets/js/image-full-size.js +76 -0
- package/assets/js/search.js +12 -0
- package/index.js +2 -2
- package/package.json +1 -1
- package/src/README.md +3 -3
- package/src/asset-map.json +5 -0
- package/src/collect-external-references.js +2 -2
- package/src/config/paths.js +2 -2
- package/src/create-term-index.js +126 -22
- package/src/health-check/tref-term-checker.js +1 -1
- package/src/health-check.js +1 -1
- package/src/init.js +1 -1
- package/src/insert-term-index.js +5 -5
- package/src/install-from-boilerplate/add-scripts-keys.js +3 -1
- package/src/install-from-boilerplate/boilerplate/gitignore +1 -1
- package/src/utils/fetch.js +14 -14
package/assets/compiled/body.js
CHANGED
|
@@ -96,8 +96,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
96
96
|
* @since 2024-06-09
|
|
97
97
|
*/
|
|
98
98
|
function editTermButtons(){const e=((t=specConfig.spec_directory).startsWith("./")?t=t.substring(2):t.startsWith("/")&&(t=t.substring(1)),t.endsWith("/")&&(t=t.slice(0,-1)),t);var t;document.querySelectorAll('dt:has(> span[id^="term:"])').forEach((t=>{const n=function(e){let t=e;for(;t.querySelector('span[id^="term:"]');)t=t.querySelector('span[id^="term:"]');return t}(t),r=n.getAttribute("id").split(":")[1],i=specConfig.source.branch||"main";n.innerHTML+=`<span class="edit-term-buttons">\n <a title="Link to the term file in the Github repo in a new tab" target="_blank" rel="noopener" \n href="https://github.com/${specConfig.source.account}/${specConfig.source.repo}/blob/${i}/${e}/${specConfig.spec_terms_directory}/${r}.md" \n class="p-1 edit-term-button btn">\n <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="currentColor" viewBox="0 0 16 16" style="shape-rendering: geometricPrecision;">\n <path fill-rule="evenodd" d="M12.146.146a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1 0 .708l-10 10a.5.5 0 0 1-.168.11l-5 2a.5.5 0 0 1-.65-.65l2-5a.5.5 0 0 1 .11-.168l10-10zM11.207 2.5 13.5 4.793 14.793 3.5 12.5 1.207 11.207 2.5zm1.586 3L10.5 3.207 4 9.707V10h.5a.5.5 0 0 1 .5.5v.5h.5a.5.5 0 0 1 .5.5v.5h.293l6.5-6.5zm-9.761 5.175-.106.106-1.528 3.821 3.821-1.528.106-.106A.5.5 0 0 1 5 12.5V12h-.5a.5.5 0 0 1-.5-.5V11h-.5a.5.5 0 0 1-.468-.325z"/>\n </svg>\n </a>\n <a title="Link to a GitHub page that shows a history of the edits in a new tab" target="_blank" rel="noopener" \n href="https://github.com/${specConfig.source.account}/${specConfig.source.repo}/commits/${i}/${e}/${specConfig.spec_terms_directory}/${r}.md" \n class="p-1 history-term-button btn">\n <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="currentColor" viewBox="0 0 16 16" style="shape-rendering: geometricPrecision;">\n <path fill-rule="evenodd" d="M8 1a7 7 0 1 0 4.95 11.95l.707.707A8.001 8.001 0 1 1 8 0v1z"/>\n <path fill-rule="evenodd" d="M7.5 3a.5.5 0 0 1 .5.5v5.21l3.248 1.856a.5.5 0 0 1-.496.868l-3.5-2A.5.5 0 0 1 7 9V3.5a.5.5 0 0 1 .5-.5z"/>\n <circle cx="8" cy="8" r="0.3"/>\n </svg>\n </a>\n </span>`}))}document.addEventListener("DOMContentLoaded",(function(){editTermButtons()}));
|
|
99
|
-
function
|
|
100
|
-
function
|
|
99
|
+
function hideShowUtilityContainer(){const t=document.querySelector(".terms-and-definitions-list");0===(t?t.querySelectorAll("dt"):[]).length&&document.getElementById("terminology-section-utility-container")?.remove()}document.addEventListener("DOMContentLoaded",(function(){hideShowUtilityContainer()}));
|
|
100
|
+
function createAlphabetIndex(){const e=document.querySelector(".terms-and-definitions-list"),t=e?e.querySelectorAll("dt"):[];if(0===t.length)return;const n=document.getElementById("terminology-section-utility-container"),o={};t.forEach((e=>{const t=e.querySelector("span");if(t?.id){const e=t.id,n=e.charAt(e.indexOf("term:")+5).toUpperCase();o[n]||(o[n]=t.id)}}));const c=document.createElement("div");c.className="alphabet-index-container";const r=document.createElement("p");r.className="number-of-terms",r.textContent=`– There are ${t.length} terms –`,n.appendChild(r),Object.keys(o).sort(((e,t)=>e.toLowerCase().localeCompare(t.toLowerCase()))).forEach((e=>{const t=document.createElement("a");t.href=`#${o[e]}`,t.textContent=e,c.appendChild(t)})),n.appendChild(c)}document.addEventListener("DOMContentLoaded",(function(){createAlphabetIndex()}));
|
|
101
|
+
function inPageSearch(){const t=document.querySelector(".terms-and-definitions-list");if(0===(t?t.querySelectorAll("dt"):[]).length)return;const e=document.getElementById("terminology-section-utility-container"),n=specConfig.searchHighlightStyle||"ssi",i="search-h7vc6omi2hr2880",o="matches",c=document.querySelector(".terms-and-definitions-list"),r=document.createElement("div");r.setAttribute("id",`container-${i}`),r.classList.add("input-group","mb-1","d-flex","align-items-center"),r.setAttribute("role","search"),e.appendChild(r);const s=document.createElement("input");s.setAttribute("type","text"),s.setAttribute("id",i),s.classList.add("form-control"),s.setAttribute("placeholder","🔍"),s.setAttribute("aria-label","Search terms"),s.setAttribute("autocomplete","off"),r.appendChild(s);const a=document.createElement("div");a.classList.add("input-group-append");const d=document.createElement("button");d.setAttribute("id",`one-match-backward-${i}`),d.classList.add("btn","btn-outline-secondary"),d.setAttribute("type","button"),d.setAttribute("disabled","true"),d.setAttribute("title","Go to previous match (Left Arrow)"),d.setAttribute("aria-label","Go to previous match"),d.innerHTML='<span aria-hidden="true">▲</span>',a.appendChild(d);const l=document.createElement("button");l.setAttribute("id",`one-match-forward-${i}`),l.classList.add("btn","btn-outline-secondary"),l.setAttribute("type","button"),l.setAttribute("disabled","true"),l.setAttribute("title","Go to next match (Right Arrow)"),l.setAttribute("aria-label","Go to next match"),l.innerHTML='<span aria-hidden="true">▼</span>',a.appendChild(l);const u=document.createElement("span");u.setAttribute("id",`total-matches-${i}`),u.classList.add("input-group-text"),u.innerHTML=`0 ${o}`,u.setAttribute("aria-live","polite"),u.setAttribute("role","status"),r.appendChild(u),r.appendChild(a),s.addEventListener("input",(function(){A(s.value)})),document.addEventListener("click",(t=>{t.target.classList.contains("collapse-all-defs-button")&&A(s.value)}));const h="highlight-matches-"+i,m={dif:"highlight-matches-DIF-search-h7vc6omi2hr2880",toip:"highlight-matches-ToIP-search-h7vc6omi2hr2880",btc:"highlight-matches-BTC-search-h7vc6omi2hr2880",keri:"highlight-matches-KERI-search-h7vc6omi2hr2880",ssi:"highlight-matches-SSI-search-h7vc6omi2hr2880",gleif:"highlight-matches-GLEIF-search-h7vc6omi2hr2880"}[n.toLowerCase()];let p=0,b=-1;function g(t){t.scrollIntoView({behavior:"smooth",block:"start"});const e=t.getBoundingClientRect(),n=e.top+window.pageYOffset-(window.innerHeight-e.height)/2;window.scrollTo({top:n,behavior:"smooth"})}function f(){b<=0?document.getElementById("one-match-backward-"+i).setAttribute("disabled","disabled"):document.getElementById("one-match-backward-"+i).removeAttribute("disabled"),b>=p-1?document.getElementById("one-match-forward-"+i).setAttribute("disabled","disabled"):document.getElementById("one-match-forward-"+i).removeAttribute("disabled")}function v(){u.innerHTML=`${p} ${o}`}const A=function(t,e){let n;return function(){const i=this,o=arguments;clearTimeout(n),n=setTimeout((()=>t.apply(i,o)),e)}}((function(t){void document.querySelectorAll("span."+h).forEach((t=>{Array.from(t.childNodes).forEach((e=>{e.nodeType===Node.ELEMENT_NODE&&t.removeChild(e)})),t.classList.contains(h)&&(t.outerHTML=t.innerHTML)})),p=0,b=-1,t.length>=2&&('"'===t[0]&&'"'===t[t.length-1]||"'"===t[0]&&"'"===t[t.length-1])&&(t=t.substring(1,t.length-1));if(""===t)return void v();let e=0;!function n(o){if(3!==o.nodeType||function(t){for(;t;){if(t?.classList?.contains("hidden"))return!0;t=t.parentNode}return!1}(o))1===o.nodeType&&Array.from(o.childNodes).forEach(n);else{const n=function(n){const o=n.nodeValue,c=new RegExp(t,"gi");let r,s=0,a=document.createDocumentFragment();for(;null!==(r=c.exec(o));){a.appendChild(document.createTextNode(o.substring(s,r.index)));const t=document.createElement("span");t.textContent=r[0],t.classList.add(h),t.classList.add(m),t.setAttribute("id",i+"-"+e),a.appendChild(t),p=e+1,e++,s=r.index+r[0].length}return a.appendChild(document.createTextNode(o.substring(s))),a}(o);n.childNodes.length>1&&o.parentNode.replaceChild(n,o)}}(c);let n=document.querySelector("."+m);null!==n&&g(n);v(),f(),b=-1}),600);d.addEventListener("click",(function(){b--;const t=document.querySelector("#"+i+"-"+b);t&&g(t),t.classList.add("active"),setTimeout((()=>{t.classList.remove("active")}),3e3),f()})),l.addEventListener("click",(function(){b++;const t=document.querySelector("#"+i+"-"+b);t&&g(t),t.classList.add("active"),setTimeout((()=>{t.classList.remove("active")}),3e3),f()})),document.addEventListener("keyup",(t=>{switch(t.key){case"ArrowRight":l.click();break;case"ArrowLeft":d.click()}}))}document.addEventListener("DOMContentLoaded",(function(){inPageSearch()}));
|
|
101
102
|
function highlightMenuItems(){let e=null;function t(e){document.querySelectorAll("#toc_list a").forEach((e=>{e.classList.remove("highlight-cfib41dyhcd99sm")}));const t=document.querySelector(`#toc_list a[href="#${e.id}"]`);t&&(t.classList.add("highlight-cfib41dyhcd99sm"),t.scrollIntoView({behavior:"smooth",block:"center"}),document.dispatchEvent(new CustomEvent("highlight-menu-item",{detail:{menuItem:t,headingId:e.id}})))}const n=new IntersectionObserver(((n,o)=>{const i=n.filter((e=>e.isIntersecting)).map((e=>e.target));i.length>0?(e=i[0],t(e)):e&&t(e)}),{root:null,rootMargin:"0px",threshold:.1});document.querySelectorAll("h2, h3, h4, h5, h6").forEach((e=>n.observe(e)))}document.addEventListener("DOMContentLoaded",(function(){highlightMenuItems()}));
|
|
102
103
|
function initCollapsibleMenu(){const e=document.getElementById("toc");if(!e)return void console.warn("TOC container not found");e.querySelectorAll(".collapse-toggle").forEach((e=>e.remove()));e.querySelectorAll("ul li").forEach(((e,t)=>{const l=e.querySelector("ul");if(l){e.classList.add("has-children");const o=document.createElement("button");o.className="collapse-toggle",o.setAttribute("aria-label","Toggle section"),o.setAttribute("type","button"),o.id=`toc-toggle-${t}`;const n=e.querySelector(":scope > a");if(n){const e=n.textContent.trim();o.setAttribute("aria-label",`Toggle ${e} section`),n.parentNode.insertBefore(o,n.nextSibling),l.setAttribute("role","group"),l.setAttribute("aria-labelledby",n.id||`toc-item-${t}`),n.id||(n.id=`toc-item-${t}`)}else e.appendChild(o);o.setAttribute("aria-controls",`toc-children-${t}`),l.id=`toc-children-${t}`,o.addEventListener("click",(t=>{t.preventDefault(),t.stopPropagation();e.classList.contains("collapsed")?(e.classList.remove("collapsed"),o.classList.remove("collapsed"),o.setAttribute("aria-expanded","true")):(e.classList.add("collapsed"),o.classList.add("collapsed"),o.setAttribute("aria-expanded","false"))})),o.addEventListener("keydown",(e=>{"Enter"!==e.key&&" "!==e.key||(e.preventDefault(),o.click())}));e.querySelector("a.highlight-cfib41dyhcd99sm, a.active")?o.setAttribute("aria-expanded","true"):(e.classList.add("collapsed"),o.classList.add("collapsed"),o.setAttribute("aria-expanded","false"))}})),console.log("Collapsible menu initialized with accessibility improvements")}function logTOCStructure(){const e=document.getElementById("toc");if(e){console.log("TOC container found:",e),console.log("TOC container children:",e.children);const t=e.querySelector("ul");if(t){console.log("First UL found:",t),console.log("UL class list:",t.classList);const e=t.querySelectorAll("li");console.log("List items count:",e.length)}else console.warn("No UL found in TOC container")}else console.warn("TOC container not found")}document.addEventListener("DOMContentLoaded",(()=>{initCollapsibleMenu(),logTOCStructure()})),document.addEventListener("highlight-menu-item",initCollapsibleMenu);
|
|
103
104
|
function backToTop(){const n=document.createElement("a");n.id="back-to-top-a1zncgtqfpzsig8",n.href="#content",n.innerHTML="↑",document.body.appendChild(n);const t=function(n,t){let e;return function(){const o=this,c=arguments;clearTimeout(e),e=setTimeout((()=>n.apply(o,c)),t)}}((function(){window.scrollY>300?n.style.display="flex":n.style.display="none"}),600);window.addEventListener("scroll",(function(){t()}))}document.addEventListener("DOMContentLoaded",(function(){backToTop()}));
|
|
@@ -109,7 +110,7 @@ function tokenInput(){document.querySelector(".button-token-input").addEventList
|
|
|
109
110
|
function pdfDownload(){fetch("./index.pdf",{method:"HEAD"}).then((e=>{if(e.ok){let e=document.createElement("a");e.classList.add("button-pdf-download"),e.classList.add("btn","d-block","btn-sm","btn-outline-secondary"),e.target="_blank",e.rel="noopener noreferrer",e.href="./index.pdf",e.title="Download this page as a PDF",e.innerHTML='\n <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.5" class="me-1" viewBox="0 0 16 16">\n <path d="M4 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V4.5L9.5 0H4zm0 1h5v4h4v9a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1zm7 4h-1V2l3 3h-2z"/>\n <path d="M6.5 10.5a.5.5 0 0 1-.5-.5V7.5a.5.5 0 0 1 .5-.5H8a.5.5 0 0 1 .5.5V10a.5.5 0 0 1-.5.5H6.5z"/>\n </svg>\n ',e.style.display="inline-flex",e.style.alignItems="center",e.style.justifyContent="center",document.querySelector(".service-menu").prepend(e)}else console.log("PDF file does not exist. No PDF download button will be added.")})).catch((e=>{console.error("Error checking PDF file:",e)}))}document.addEventListener("DOMContentLoaded",(function(){pdfDownload()}));
|
|
110
111
|
function insertTrefs(e){e?.xtrefs?function(e){const n=[];document.querySelectorAll("dt span.transcluded-xref-term").forEach((e=>{const t=Array.from(e.childNodes).filter((e=>e.nodeType===Node.TEXT_NODE)).map((e=>e.textContent.trim())).join("");n.push({element:e,textContent:t})})),n.forEach((n=>{const t=n.element,r=n.textContent,o=e.xtrefs.find((e=>e.term===r)),s=t.closest("dt");if(s){const e=s.nextElementSibling;if(e?.classList.contains("transcluded-xref-term")&&e.classList.contains("meta-info-content-wrapper"))return}if(o){const e=s.parentNode,n=document.createElement("dd");n.classList.add("transcluded-xref-term","meta-info-content-wrapper","collapsed");const t=`\n| Property | Value |\n| -------- | ----- |\n| Owner | ${o.avatarUrl?``:""} ${o.owner||"Unknown"} |\n| Repo | ${o.repo&&o.repoUrl?`[${o.repo}](${o.repoUrl})`:"Unknown"} |\n| Commit hash | ${o.commitHash||"Unknown"} |\n `;n.innerHTML=md.render(t),e.insertBefore(n,s.nextSibling);let r=o.content.replace(/\[\[def:[^\]]*?\]\]/g,"").split("\n").map((e=>e.replace(/^\s*~\s*/,""))).join("\n").replace(/\[\[ref:/g,"").replace(/\]\]/g,"");const d=document.createElement("div");d.innerHTML=md.render(r);const a=d.querySelectorAll("dd");if(a.length>0){let t=n;Array.from(a).forEach((n=>{const r=n.cloneNode(!0);r.classList.add("transcluded-xref-term","transcluded-xref-term-embedded"),e.insertBefore(r,t.nextSibling),t=r}))}else{const t=document.createElement("dd");t.classList.add("transcluded-xref-term","transcluded-xref-term-embedded"),t.innerHTML=d.innerHTML,e.insertBefore(t,n.nextSibling)}}else{const e=s.parentNode,n=document.createElement("dd");n.classList.add("transcluded-xref-term","meta-info-content-wrapper","collapsed");const t="\n| Property | Value |\n| -------- | ----- |\n| Owner | Unknown |\n| Repo | Unknown |\n| Commit hash | not found |\n ";n.innerHTML=md.render(t),e.insertBefore(n,s.nextSibling);const r=document.createElement("dd");r.classList.add("transcluded-xref-term","transcluded-xref-term-embedded","last-dd"),r.innerHTML="<p>This term was not found in the external repository.</p>",e.insertBefore(r,n.nextSibling)}}))}(e):console.error("allXTrefs is undefined or missing xtrefs property")}document.addEventListener("DOMContentLoaded",(()=>{"undefined"!=typeof allXTrefs?insertTrefs(allXTrefs):console.warn("allXTrefs is not available in the global scope. Transcluded references will not be inserted.")}));
|
|
111
112
|
function collapseDefinitions(){const t=document.querySelectorAll("#content dl.terms-and-definitions-list > dd"),e=document.querySelectorAll("#content dl.terms-and-definitions-list > dt"),n=document.querySelectorAll(".collapse-all-defs-button");e.forEach((t=>{const e=document.createElement("button");e.classList.add("collapse-all-defs-button","d-print-none","btn","p-0","fs-5","d-flex","align-items-center","justify-content-center"),e.innerHTML="▲",e.setAttribute("id","toggleButton"),t.appendChild(e)})),document.addEventListener("click",(e=>{e.target.classList.contains("collapse-all-defs-button")&&(!function(){const e=t[0].classList.contains("hidden");t.forEach((t=>{t.classList.toggle("hidden",!e),t.classList.toggle("visible",e)})),n.forEach((t=>{t.innerHTML=e?"▲":"▼",t.title=e?"Collapse all definitions":"Expand all definitions"})),document.querySelector("html").classList.toggle("defs-hidden")}(),e.target.scrollIntoView({behavior:"smooth",block:"start",inline:"nearest"}),setTimeout((()=>{window.scrollBy({top:-100,behavior:"smooth"})}),500))}))}document.addEventListener("DOMContentLoaded",(function(){collapseDefinitions()}));
|
|
112
|
-
function createTermFilter(){const e=document.getElementById("terminology-section-utility-container"),c=document.createElement("div");c.className="d-flex mt-0";const
|
|
113
|
+
function createTermFilter(){const e=document.querySelector(".terms-and-definitions-list");if(0===(e?e.querySelectorAll("dt"):[]).length)return;const t=document.getElementById("terminology-section-utility-container"),c=document.createElement("div");c.className="d-flex mt-0";const n=document.createElement("div");n.className="form-check me-3",n.innerHTML='\n <input class="form-check-input" type="checkbox" id="showLocalTermsCheckbox" checked>\n <label class="form-check-label" for="showLocalTermsCheckbox">\n Show local terms\n </label>\n ';const l=document.createElement("div");l.className="form-check ms-3",l.innerHTML='\n <input class="form-check-input" type="checkbox" id="showExternalTermsCheckbox" checked>\n <label class="form-check-label" for="showExternalTermsCheckbox">\n Show external terms\n </label>\n ',n.querySelector("#showLocalTermsCheckbox").addEventListener("change",(function(e){e.target.checked?document.querySelector("html").classList.remove("hide-local-terms"):document.querySelector("html").classList.add("hide-local-terms")})),l.querySelector("#showExternalTermsCheckbox").addEventListener("change",(function(e){e.target.checked?document.querySelector("html").classList.remove("hide-external-terms"):document.querySelector("html").classList.add("hide-external-terms")})),c.appendChild(n),c.appendChild(l),t.appendChild(c)}document.addEventListener("DOMContentLoaded",(function(){createTermFilter()}));
|
|
113
114
|
function createToggleButton(e){const t=document.createElement("button");t.classList.add("meta-info-toggle-button","btn"),t.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="currentColor" viewBox="0 0 16 16" style="shape-rendering: geometricPrecision;"><path fill-rule="evenodd" d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z"/><path d="M8.93 6.588l-2.29.287-.082.38.45.083c.294.07.352.176.288.469l-.738 3.468c-.194.897.105 1.319.808 1.319.545 0 1.178-.252 1.465-.598l.088-.416c-.2.176-.492.246-.686.246-.275 0-.375-.193-.304-.533L8.93 6.588z"/><path d="M9 4.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0z"/></svg>',t.title="Meta info",t.addEventListener("click",(function(t){t.preventDefault(),t.stopPropagation();e.classList.contains("collapsed")?(e.classList.remove("collapsed"),e.getBoundingClientRect()):e.classList.add("collapsed")}));let n=e.previousElementSibling;for(;n&&"DT"!==n.tagName;)n=n.previousElementSibling;n?n.appendChild(t):e.insertBefore(t,e.firstChild)}document.addEventListener("DOMContentLoaded",(function(){document.querySelectorAll("dl > dd:has(table)").forEach((function(e){e.classList.add("meta-info-content-wrapper");const t=document.createElement("div");for(t.classList.add("meta-info-inner-wrapper");e.firstChild&&e.firstChild!==e.querySelector(".meta-info-toggle-button");)t.appendChild(e.firstChild);e.querySelector(".meta-info-toggle-button")||createToggleButton(e),e.appendChild(t),e.classList.add("collapsed")}))}));
|
|
114
115
|
function fixLastDd(){document.querySelectorAll("dl.terms-and-definitions-list").forEach((t=>{t.querySelectorAll(":scope > dd").forEach(((t,e)=>{let d=t.nextElementSibling;d&&"DT"!==d.tagName||t.classList.contains("last-dd")||t.classList.add("last-dd")}))}))}document.addEventListener("DOMContentLoaded",(function(){fixLastDd()}));
|
|
115
116
|
/**
|
|
@@ -174,6 +175,8 @@ function closeOffCanvasMenu(){document.querySelectorAll("#sidebarMenu a").forEac
|
|
|
174
175
|
* });
|
|
175
176
|
*/
|
|
176
177
|
const horizontalScrollHint=A=>{if(!document.getElementById("horizontalScrollHintStyles")){const A=document.createElement("style");A.id="horizontalScrollHintStyles",A.textContent="\n @keyframes arrow-tweet-panel-pulse {\n 0%,\n to {\n transform: translateZ(0);\n }\n 50% {\n transform: translate3d(10px, 0, 0);\n }\n }\n\n .scrollHint {\n position: absolute;\n top: 1em;\n right: 1em;\n background: #EEE;\n padding: 0.5em;\n\n /* https://smoothshadows.com/#djEsMSw1LDAuMDgsMjQsMCwwLCMwMzA3MTIsI2YzZjRmNiwjZmZmZmZmLDI%3D */\n box-shadow: 0px 0px 1px rgba(3, 7, 18, 0.02),\n 0px 0px 4px rgba(3, 7, 18, 0.03),\n 0px 0px 9px rgba(3, 7, 18, 0.05),\n 0px 0px 15px rgba(3, 7, 18, 0.06),\n 0px 0px 24px rgba(3, 7, 18, 0.08);\n\n border-radius: 7px;\n opacity: 0;\n transition: opacity 1s ease-in-out;\n }\n ",document.head.appendChild(A)}A||(A=".horizontalScroll");(Array.isArray(A)?A:[A]).forEach((A=>{const J="string"==typeof A?document.querySelectorAll(A):[A];Array.from(J).forEach((A=>{if(A){A.style.position="relative";const E=document.createElement("p");function J(){A.scrollWidth>A.clientWidth?E.style.opacity="1":E.style.opacity="0"}E.classList.add("scrollHint"),E.innerHTML="<img style='width: 40px; vertical-align: middle;' src='data:image/png;base64,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' alt='finger scrolling horizontally' /> Scroll to the right",E.style.animation="arrow-tweet-panel-pulse 0.82s ease-in-out infinite",A.appendChild(E),J(),new ResizeObserver(J).observe(A),A.addEventListener("scroll",(function(){E.style.opacity="0"}))}}))}))};document.addEventListener("DOMContentLoaded",(function(){horizontalScrollHint([".table-responsive"])}));
|
|
178
|
+
function addBootstrapClassesToImages(){document.querySelectorAll("#content img").forEach((e=>{if(e.classList.add("img-fluid"),e.classList.add("rounded"),e.classList.add("shadow-sm"),e.classList.add("my-3"),!e.closest("figure")&&!e.parentElement.classList.contains("image-container")){const t=document.createElement("figure");t.classList.add("figure","text-center");if(e.parentElement.replaceChild(t,e),t.appendChild(e),e.alt&&""!==e.alt.trim()){const s=document.createElement("figcaption");s.classList.add("figure-caption","text-center"),s.textContent=e.alt,t.appendChild(s)}}}))}function initImageBootstrapClasses(){const e=document.querySelector("#content");if(e&&(addBootstrapClassesToImages(),"undefined"!=typeof MutationObserver)){new MutationObserver((e=>{let t=!1;e.forEach((e=>{"childList"===e.type&&e.addedNodes.length>0&&e.addedNodes.forEach((e=>{1===e.nodeType&&("IMG"===e.tagName||e.querySelector&&e.querySelector("img"))&&(t=!0)}))})),t&&addBootstrapClassesToImages()})).observe(e,{childList:!0,subtree:!0})}}document.addEventListener("DOMContentLoaded",(()=>{initImageBootstrapClasses()}));
|
|
179
|
+
const imageFullSize=()=>{const e=document.querySelector("#content");function t(){let e=document.querySelector(".image-container-full-page");e&&document.body.removeChild(e)}e?(console.log("event listener added"),e.addEventListener("click",(e=>{if("IMG"===e.target.tagName){let n=e.target;if(null===document.querySelector(".image-container-full-page")){const e=n.cloneNode(!0),o=document.createElement("div");o.classList.add("image-container"),o.classList.add("image-container-full-page"),o.appendChild(e),document.body.appendChild(o),o.addEventListener("click",(function e(){o.removeEventListener("click",e),t()}))}n.classList.toggle("image-full-page")}})),document.addEventListener("keydown",(e=>{"Escape"===e.key&&t()}))):console.log("Element with class '.markdown' not found.")};document.addEventListener("DOMContentLoaded",(()=>{imageFullSize()}));
|
|
177
180
|
/*!
|
|
178
181
|
* Bootstrap v5.3.3 (https://getbootstrap.com/)
|
|
179
182
|
* Copyright 2011-2024 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
|
package/assets/compiled/head.css
CHANGED
|
@@ -24,4 +24,6 @@ h2,h3,h4,h5,h6{margin-top:1.5em!important}#terminology-section-utility-container
|
|
|
24
24
|
article a[href^="https://"]:not(.btn)::after,article a[href^=http]:not(.btn)::after{content:'';width:12px;height:12px;margin-left:4px;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='currentColor' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' d='M8.636 3.5a.5.5 0 0 0-.5-.5H1.5A1.5 1.5 0 0 0 0 4.5v10A1.5 1.5 0 0 0 1.5 16h10a1.5 1.5 0 0 0 1.5-1.5V7.864a.5.5 0 0 0-1 0V14.5a.5.5 0 0 1-.5.5h-10a.5.5 0 0 1-.5-.5v-10a.5.5 0 0 1 .5-.5h6.636a.5.5 0 0 0 .5-.5z'/%3E%3Cpath fill-rule='evenodd' d='M16 .5a.5.5 0 0 0-.5-.5h-5a.5.5 0 0 0 0 1h3.793L6.146 9.146a.5.5 0 1 0 .708.708L15 1.707V5.5a.5.5 0 0 0 1 0v-5z'/%3E%3C/svg%3E");background-position:center;background-repeat:no-repeat;background-size:contain;display:inline-block}
|
|
25
25
|
#repo_issues>header{background:#eee;border-bottom:1px solid #ddd}#repo_issues>header span:first-of-type{font-weight:700;padding-top:.1em}#repo_issues>header .repo-issue-toggle{margin-left:auto;color:inherit;font-weight:700;text-decoration:none}#repo_issue_list{list-style:none;margin:0;padding:0 1.25em 1.25em;font-size:.85em;overflow:auto;-ms-overflow-style:none;scrollbar-width:none}#repo_issue_list::-webkit-scrollbar{display:none}#repo_issue_list:empty:before{content:"No issues found";display:block;text-align:center;font-size:1.1em;color:#aaa;margin:1em 0 0}.repo-issue detail-box{display:flex;flex-direction:column;padding:1em 0;border-bottom:1px solid #ddd}.repo-issue detail-box>section{order:1}.repo-issue detail-box>section:empty+.repo-issue-title [detail-box-toggle]{display:none}.repo-issue-title{display:flex;align-items:center}.repo-issue-link{flex:1;margin:0 0 0 .5em}.repo-issue-number{height:1em;margin:0 .4em 0 0;padding:.3em .25em 0;border-radius:3px;font-weight:700;background:#eee;border:1px solid #ddd;text-align:center;line-height:1em}.repo-issue-number:before{content:"#";font-weight:400;margin:0 .1em 0 0}.repo-issue [detail-box-toggle]{margin:0 0 0 1em;opacity:.35;transition:opacity .4s}.repo-issue [detail-box-toggle]:hover,.repo-issue detail-box[open] [detail-box-toggle]{opacity:1}
|
|
26
26
|
.adjust-font-size #decreaseBtn{background:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" xmlns:xlink="http://www.w3.org/1999/xlink"><text x="50%" y="50%" font-family="Times New Roman" font-size="50" fill="black" dominant-baseline="middle" text-anchor="middle">A</text></svg>') no-repeat center;background-color:#a9dde0;padding:14px 14px;border-bottom-left-radius:4px;border-bottom-right-radius:0;border-top-left-radius:4px;border-top-right-radius:0}.adjust-font-size #increaseBtn{background:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" xmlns:xlink="http://www.w3.org/1999/xlink"><text x="50%" y="50%" font-family="Times New Roman" font-size="80" fill="black" dominant-baseline="middle" text-anchor="middle">A</text></svg>') no-repeat center;background-color:#a9dde0;padding:14px 14px;border-bottom-left-radius:0;border-bottom-right-radius:4px;border-top-left-radius:0;border-top-right-radius:4px;margin-left:-1px!important}.adjust-font-size.btn-group{display:inline-flex}.adjust-font-size.btn-group .btn{position:relative}
|
|
27
|
+
.image-container-full-page{position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,.9);display:flex;justify-content:center;align-items:center;z-index:10000;padding:20px;box-sizing:border-box;cursor:zoom-out}.image-container-full-page img{max-width:90%;max-height:90%;object-fit:contain;box-shadow:0 0 20px rgba(0,0,0,.5)}.image-container-full-page{animation:fadeIn .3s ease-in-out}@keyframes fadeIn{from{opacity:0}to{opacity:1}}
|
|
28
|
+
#content .figure{width:100%;margin-bottom:1.5rem}#content .figure img{transition:all .3s ease}#content .figure img:hover{transform:scale(1.01);cursor:pointer}#content img.img-fluid{max-width:100%;height:auto}#content .figure-caption{margin-top:.5rem;font-style:italic;color:#6c757d}
|
|
27
29
|
:target{scroll-margin-top:calc(50vh)}body:not([hashscroll]) :target{animation:highlight-target 3.5s .25s ease}body:not([hashscroll]) dt:has(:target){animation:highlight-target-parent-dt 3.5s .25s ease}svg[icon]{width:1.25em;height:1.25em;vertical-align:text-top}@keyframes highlight-target{50%{background-color:#ff0}}@keyframes highlight-target-parent-dt{50%{background-color:#ff0;border:1px solid #00c8ff}}#svg{display:none}main *{overflow-wrap:anywhere;word-break:normal}.table-responsive{overflow-x:auto!important;-webkit-overflow-scrolling:touch;width:100%;max-width:100%}.table-responsive *{overflow-wrap:normal!important;word-break:normal!important;white-space:nowrap!important}dd td img{max-width:30px}.notice{margin:1em 0;padding:.5em .9em .55em .65em;border-left:.5em solid}.notice p{margin:.4em 0 0}.note{background:#e9fbe9;border-color:#52e052}.note .notice-link{display:block;color:#178217}.issue{background:#e9f0fb;border-color:#527fe0}.issue .notice-link:before{display:block;color:#1e4cae}.warning{background:#fbe9e9;border-color:#e05252}.warning .notice-link{display:block;color:#ae1e1e}.example{color:#cebe00;background:#1a1e23;border-left:.5em solid}.example .notice-link{display:block;color:inherit;font-size:1.1em;font-family:Heebo,sans-serif}.example pre[class*=language-]{padding:0;border-radius:0}.todo{background:#fbe4ff;border-color:#9700e2}.todo .notice-link{display:block;color:#6d00a2}.alert-primary{background-color:#f9fcff;border-color:#b2ebf2;color:#00838f}.alert-secondary{background-color:#f5f5f5;border-color:#e0e0e0;color:#616161}.alert-success{background-color:#e8f5e9;border-color:#c8e6c9;color:#388e3c}.alert-danger{background-color:#ffebee;border-color:#ef9a9a;color:#d32f2f}.alert-warning{background-color:#fffde7;border-color:#fff9c4;color:#f9a825}.alert-info{background-color:#e1f5fe;border-color:#b3e5fc;color:#0288d1}.alert-light{background-color:#f9f9f9;border-color:#eee;color:#424242}.alert-dark{background-color:#e0e0e0;border-color:#bdbdbd;color:#212121}.alert a{color:inherit;font-weight:700}.alert-primary a{color:#006064}.alert-success a{color:#2e7d32}.alert-danger a{color:#b71c1c}.alert-warning a{color:#f57f17}.alert-info a{color:#01579b}.alert-dark a{color:#000}[data-bs-theme=dark] .alert-primary{background-color:#004d40;border-color:#00695c;color:#b2dfdb}[data-bs-theme=dark] .alert-secondary{background-color:#424242;border-color:#616161;color:#e0e0e0}[data-bs-theme=dark] .alert-success{background-color:#1b5e20;border-color:#2e7d32;color:#a5d6a7}[data-bs-theme=dark] .alert-danger{background-color:#b71c1c;border-color:#c62828;color:#ef9a9a}[data-bs-theme=dark] .alert-warning{background-color:#f57f17;border-color:#ffb300;color:#ffe082}[data-bs-theme=dark] .alert-info{background-color:#01579b;border-color:#0277bd;color:#81d4fa}[data-bs-theme=dark] .alert-light{background-color:#303030;border-color:#424242;color:#e0e0e0}[data-bs-theme=dark] .alert-dark{background-color:#212121;border-color:#424242;color:#bdbdbd}[data-bs-theme=dark] .alert a{color:inherit;font-weight:700}[data-bs-theme=dark] .alert-primary a{color:#80cbc4}[data-bs-theme=dark] .alert-success a{color:#81c784}[data-bs-theme=dark] .alert-danger a{color:#ef5350}[data-bs-theme=dark] .alert-warning a{color:#ffca28}[data-bs-theme=dark] .alert-info a{color:#4fc3f7}[data-bs-theme=dark] .alert-dark a{color:#9e9e9e}#offcanvasSettings .btn-menu-item{border-radius:unset;width:100%;text-align:left;border:1px solid #dee2e6;background-color:var(--card-bg);color:var(--card-text);padding:10px 15px;margin-bottom:5px;transition:background-color .2s ease}#offcanvasSettings .btn-menu-item:hover{background-color:#e9ecef}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file CSS for Bootstrap-enhanced images
|
|
3
|
+
* @author Kor Dwarshuis
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/* Enhanced styles for Bootstrap images in normal view */
|
|
8
|
+
#content .figure {
|
|
9
|
+
width: 100%;
|
|
10
|
+
margin-bottom: 1.5rem;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
#content .figure img {
|
|
14
|
+
transition: all 0.3s ease;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/* Hover effect for better UX */
|
|
18
|
+
#content .figure img:hover {
|
|
19
|
+
transform: scale(1.01);
|
|
20
|
+
cursor: pointer;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/* Make sure images don't exceed their container width */
|
|
24
|
+
#content img.img-fluid {
|
|
25
|
+
max-width: 100%;
|
|
26
|
+
height: auto;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/* Better caption styling */
|
|
30
|
+
#content .figure-caption {
|
|
31
|
+
margin-top: 0.5rem;
|
|
32
|
+
font-style: italic;
|
|
33
|
+
color: #6c757d;
|
|
34
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file CSS for full-size image display
|
|
3
|
+
* @author Kor Dwarshuis
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/* Container that holds the full-size image */
|
|
8
|
+
.image-container-full-page {
|
|
9
|
+
position: fixed;
|
|
10
|
+
top: 0;
|
|
11
|
+
left: 0;
|
|
12
|
+
width: 100%;
|
|
13
|
+
height: 100%;
|
|
14
|
+
background-color: rgba(0, 0, 0, 0.9);
|
|
15
|
+
display: flex;
|
|
16
|
+
justify-content: center;
|
|
17
|
+
align-items: center;
|
|
18
|
+
z-index: 10000;
|
|
19
|
+
padding: 20px;
|
|
20
|
+
box-sizing: border-box;
|
|
21
|
+
cursor: zoom-out;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/* Style for the image inside the container */
|
|
25
|
+
.image-container-full-page img {
|
|
26
|
+
max-width: 90%;
|
|
27
|
+
max-height: 90%;
|
|
28
|
+
object-fit: contain;
|
|
29
|
+
box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/* Optional animation for better UX */
|
|
33
|
+
.image-container-full-page {
|
|
34
|
+
animation: fadeIn 0.3s ease-in-out;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
@keyframes fadeIn {
|
|
38
|
+
from {
|
|
39
|
+
opacity: 0;
|
|
40
|
+
}
|
|
41
|
+
to {
|
|
42
|
+
opacity: 1;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file This file adds Bootstrap classes to images for better responsiveness and styling.
|
|
3
|
+
* @author Kor Dwarshuis
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Function to add Bootstrap classes to images for better responsiveness
|
|
9
|
+
*/
|
|
10
|
+
function addBootstrapClassesToImages() {
|
|
11
|
+
const images = document.querySelectorAll('#content img');
|
|
12
|
+
images.forEach(image => {
|
|
13
|
+
// Add Bootstrap responsive image class
|
|
14
|
+
image.classList.add('img-fluid');
|
|
15
|
+
|
|
16
|
+
// Optional: Add rounded corners
|
|
17
|
+
image.classList.add('rounded');
|
|
18
|
+
|
|
19
|
+
// Optional: Add subtle shadow for better appearance
|
|
20
|
+
image.classList.add('shadow-sm');
|
|
21
|
+
|
|
22
|
+
// Add appropriate margins
|
|
23
|
+
image.classList.add('my-3');
|
|
24
|
+
|
|
25
|
+
// Create a figure element for images that are not already in one
|
|
26
|
+
if (!image.closest('figure') && !image.parentElement.classList.contains('image-container')) {
|
|
27
|
+
// Check if not already wrapped
|
|
28
|
+
const figure = document.createElement('figure');
|
|
29
|
+
figure.classList.add('figure', 'text-center');
|
|
30
|
+
|
|
31
|
+
// Get the original parent and replace the image with the figure
|
|
32
|
+
const parent = image.parentElement;
|
|
33
|
+
parent.replaceChild(figure, image);
|
|
34
|
+
|
|
35
|
+
// Add the image to the figure
|
|
36
|
+
figure.appendChild(image);
|
|
37
|
+
|
|
38
|
+
// If the image has an alt text, create a caption
|
|
39
|
+
if (image.alt && image.alt.trim() !== '') {
|
|
40
|
+
const figcaption = document.createElement('figcaption');
|
|
41
|
+
figcaption.classList.add('figure-caption', 'text-center');
|
|
42
|
+
figcaption.textContent = image.alt;
|
|
43
|
+
figure.appendChild(figcaption);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Initialize the image enhancement with Bootstrap classes
|
|
51
|
+
*/
|
|
52
|
+
function initImageBootstrapClasses() {
|
|
53
|
+
const markdownElement = document.querySelector('#content');
|
|
54
|
+
|
|
55
|
+
if (markdownElement) {
|
|
56
|
+
// Initialize bootstrap classes for all existing images
|
|
57
|
+
addBootstrapClassesToImages();
|
|
58
|
+
|
|
59
|
+
// Add a mutation observer to detect dynamically added images
|
|
60
|
+
if (typeof MutationObserver !== 'undefined') {
|
|
61
|
+
const observer = new MutationObserver((mutations) => {
|
|
62
|
+
let shouldUpdate = false;
|
|
63
|
+
|
|
64
|
+
mutations.forEach(mutation => {
|
|
65
|
+
// Check if new nodes were added
|
|
66
|
+
if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
|
|
67
|
+
// Look for added images
|
|
68
|
+
mutation.addedNodes.forEach(node => {
|
|
69
|
+
if (node.nodeType === 1) { // Element node
|
|
70
|
+
if (node.tagName === 'IMG') {
|
|
71
|
+
shouldUpdate = true;
|
|
72
|
+
} else if (node.querySelector && node.querySelector('img')) {
|
|
73
|
+
shouldUpdate = true;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
if (shouldUpdate) {
|
|
81
|
+
// Apply Bootstrap classes to newly added images
|
|
82
|
+
addBootstrapClassesToImages();
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// Start observing content changes
|
|
87
|
+
observer.observe(markdownElement, {
|
|
88
|
+
childList: true,
|
|
89
|
+
subtree: true
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Run when the DOM is fully loaded
|
|
96
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
97
|
+
initImageBootstrapClasses();
|
|
98
|
+
});
|
|
@@ -5,9 +5,18 @@
|
|
|
5
5
|
* @since 2024-09-19
|
|
6
6
|
*/
|
|
7
7
|
function createAlphabetIndex() {
|
|
8
|
-
|
|
8
|
+
// Check if the terms and definitions list exists
|
|
9
|
+
// If it doesn't exist, exit the function
|
|
10
|
+
// This prevents errors when the script is run on pages without the terms and definitions list
|
|
11
|
+
// and ensures that the script only runs when necessary
|
|
9
12
|
const termsListElement = document.querySelector(".terms-and-definitions-list");
|
|
10
|
-
const dtElements = termsListElement.querySelectorAll("dt");
|
|
13
|
+
const dtElements = termsListElement ? termsListElement.querySelectorAll("dt") : [];
|
|
14
|
+
|
|
15
|
+
if (dtElements.length === 0) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const terminologySectionUtilityContainer = document.getElementById("terminology-section-utility-container");
|
|
11
20
|
const alphabetIndex = {};
|
|
12
21
|
|
|
13
22
|
dtElements.forEach(dt => {
|
|
@@ -5,6 +5,18 @@
|
|
|
5
5
|
* @since 2024-09-19
|
|
6
6
|
*/
|
|
7
7
|
function createTermFilter() {
|
|
8
|
+
// Check if the terms and definitions list exists
|
|
9
|
+
// If it doesn't exist, exit the function
|
|
10
|
+
// This prevents errors when the script is run on pages without the terms and definitions list
|
|
11
|
+
// and ensures that the script only runs when necessary
|
|
12
|
+
const termsListElement = document.querySelector(".terms-and-definitions-list");
|
|
13
|
+
const dtElements = termsListElement ? termsListElement.querySelectorAll("dt") : [];
|
|
14
|
+
|
|
15
|
+
if (dtElements.length === 0) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
|
|
8
20
|
const terminologySectionUtilityContainer = document.getElementById("terminology-section-utility-container");
|
|
9
21
|
|
|
10
22
|
// Create checkboxes container
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
function hideShowUtilityContainer() {
|
|
2
|
+
// Check if the terms and definitions list exists
|
|
3
|
+
// If it doesn't exist, exit the function
|
|
4
|
+
// This prevents errors when the script is run on pages without the terms and definitions list
|
|
5
|
+
// and ensures that the script only runs when necessary
|
|
6
|
+
const termsListElement = document.querySelector(".terms-and-definitions-list");
|
|
7
|
+
const dtElements = termsListElement ? termsListElement.querySelectorAll("dt") : [];
|
|
8
|
+
|
|
9
|
+
if (dtElements.length === 0) {
|
|
10
|
+
document.getElementById("terminology-section-utility-container")?.remove();
|
|
11
|
+
// document.getElementById("terminology-section-utility-container")?.style.display = "none";
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
document.addEventListener("DOMContentLoaded", function () {
|
|
16
|
+
hideShowUtilityContainer();
|
|
17
|
+
});
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file This file adds functionality to display images in full-size on a web page when clicked. The functionality is implemented via a class added to the image element.
|
|
3
|
+
* @author Kor Dwarshuis
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
const imageFullSize = () => {
|
|
9
|
+
const imageFullSizeClass = 'image-full-page';
|
|
10
|
+
|
|
11
|
+
// All images get a click event listener via event delegation
|
|
12
|
+
const markdownElement = document.querySelector('#content');
|
|
13
|
+
|
|
14
|
+
function removeContainer() {
|
|
15
|
+
let container = document.querySelector('.image-container-full-page');
|
|
16
|
+
if (container) {
|
|
17
|
+
document.body.removeChild(container);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (markdownElement) {
|
|
22
|
+
console.log("event listener added");
|
|
23
|
+
|
|
24
|
+
markdownElement.addEventListener('click', (event) => {
|
|
25
|
+
if (event.target.tagName === 'IMG') {
|
|
26
|
+
|
|
27
|
+
// To be implemented: also account for SVG, path, circle, rect
|
|
28
|
+
// if ((event.target.tagName === 'svg' || event.target.tagName === 'path' || event.target.tagName === 'circle' || event.target.tagName === 'rect') && event.target.closest('.markdown')) {
|
|
29
|
+
|
|
30
|
+
let image = event.target;
|
|
31
|
+
|
|
32
|
+
if (document.querySelector('.image-container-full-page') === null) {
|
|
33
|
+
// Add container if it doesn't exist
|
|
34
|
+
|
|
35
|
+
// Clone the image element
|
|
36
|
+
const clonedImage = image.cloneNode(true);
|
|
37
|
+
|
|
38
|
+
// Create a new div element with the class .full-page-image-container
|
|
39
|
+
const container = document.createElement('div');
|
|
40
|
+
container.classList.add('image-container');
|
|
41
|
+
container.classList.add('image-container-full-page');
|
|
42
|
+
|
|
43
|
+
// Add the cloned image to the new container div
|
|
44
|
+
container.appendChild(clonedImage);
|
|
45
|
+
|
|
46
|
+
// Append the new container div to the body
|
|
47
|
+
document.body.appendChild(container);
|
|
48
|
+
|
|
49
|
+
// Add event listener to the new container
|
|
50
|
+
container.addEventListener('click', function containerClickEvent() {
|
|
51
|
+
container.removeEventListener('click', containerClickEvent); // remove this click listener
|
|
52
|
+
removeContainer();
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Toggle the full size class on the original image
|
|
58
|
+
image.classList.toggle(imageFullSizeClass);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// Add keydown event listener to handle the ESC key
|
|
63
|
+
document.addEventListener('keydown', (event) => {
|
|
64
|
+
if (event.key === "Escape") {
|
|
65
|
+
removeContainer();
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
} else {
|
|
70
|
+
console.log("Element with class '.markdown' not found.");
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
75
|
+
imageFullSize();
|
|
76
|
+
});
|
package/assets/js/search.js
CHANGED
|
@@ -14,6 +14,18 @@
|
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
16
|
function inPageSearch() {
|
|
17
|
+
// Check if the terms and definitions list exists
|
|
18
|
+
// If it doesn't exist, exit the function
|
|
19
|
+
// This prevents errors when the script is run on pages without the terms and definitions list
|
|
20
|
+
// and ensures that the script only runs when necessary
|
|
21
|
+
const termsListElement = document.querySelector(".terms-and-definitions-list");
|
|
22
|
+
const dtElements = termsListElement ? termsListElement.querySelectorAll("dt") : [];
|
|
23
|
+
|
|
24
|
+
if (dtElements.length === 0) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
|
|
17
29
|
/*****************/
|
|
18
30
|
/* CONFIGURATION */
|
|
19
31
|
|
package/index.js
CHANGED
|
@@ -25,7 +25,7 @@ module.exports = async function (options = {}) {
|
|
|
25
25
|
|
|
26
26
|
const findPkgDir = require('find-pkg-dir');
|
|
27
27
|
const modulePath = findPkgDir(__dirname);
|
|
28
|
-
let config = fs.readJsonSync('
|
|
28
|
+
let config = fs.readJsonSync('./.cache/specs-generated.json');
|
|
29
29
|
|
|
30
30
|
const createExternalSpecsList = require('./src/create-external-specs-list.js');
|
|
31
31
|
|
|
@@ -218,7 +218,7 @@ module.exports = async function (options = {}) {
|
|
|
218
218
|
|
|
219
219
|
function createScriptElementWithXTrefDataForEmbeddingInHtml() {
|
|
220
220
|
// Test if xtrefs-data.js exists, else make it an empty string
|
|
221
|
-
const inputPath = path.join('
|
|
221
|
+
const inputPath = path.join('.cache', 'xtrefs-data.js');
|
|
222
222
|
|
|
223
223
|
let xtrefsData = '';
|
|
224
224
|
if (fs.existsSync(inputPath)) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "spec-up-t",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.5",
|
|
4
4
|
"description": "Technical specification drafting tool that generates rich specification documents from markdown. Forked from https://github.com/decentralized-identity/spec-up by Daniel Buchner (https://github.com/csuwildcat)",
|
|
5
5
|
"main": "./index",
|
|
6
6
|
"repository": {
|
package/src/README.md
CHANGED
|
@@ -78,9 +78,9 @@
|
|
|
78
78
|
<ul>
|
|
79
79
|
<li>Creates three output files:
|
|
80
80
|
<ul>
|
|
81
|
-
<li><code
|
|
82
|
-
<li><code
|
|
83
|
-
<li><code
|
|
81
|
+
<li><code>.cache/xtrefs-data.json</code> - JSON data file</li>
|
|
82
|
+
<li><code>.cache/xtrefs-data.js</code> - JavaScript module file</li>
|
|
83
|
+
<li><code>.cache/xtrefs-history/xtrefs-data-[timestamp].js</code> - Historical record</li>
|
|
84
84
|
</ul>
|
|
85
85
|
</li>
|
|
86
86
|
</ul>
|
package/src/asset-map.json
CHANGED
|
@@ -23,6 +23,8 @@
|
|
|
23
23
|
"assets/css/external-links.css",
|
|
24
24
|
"assets/css/repo-issues.css",
|
|
25
25
|
"assets/css/adjust-font-size.css",
|
|
26
|
+
"assets/css/image-full-size.css",
|
|
27
|
+
"assets/css/add-bootstrap-classes-to-images.css",
|
|
26
28
|
"assets/css/index.css"
|
|
27
29
|
],
|
|
28
30
|
"js": [
|
|
@@ -44,6 +46,7 @@
|
|
|
44
46
|
"assets/js/tippy.js",
|
|
45
47
|
"assets/js/diff.min.js",
|
|
46
48
|
"assets/js/edit-term-buttons.js",
|
|
49
|
+
"assets/js/hide-show-utility-container.js",
|
|
47
50
|
"assets/js/create-alphabet-index.js",
|
|
48
51
|
"assets/js/search.js",
|
|
49
52
|
"assets/js/highlightMenuItems.js",
|
|
@@ -66,6 +69,8 @@
|
|
|
66
69
|
"assets/js/close-off-canvas-menu.js",
|
|
67
70
|
"assets/js/index.js",
|
|
68
71
|
"assets/js/horizontal-scroll-hint.js",
|
|
72
|
+
"assets/js/add-bootstrap-classes-to-images.js",
|
|
73
|
+
"assets/js/image-full-size.js",
|
|
69
74
|
"assets/js/bootstrap.bundle.min.js"
|
|
70
75
|
]
|
|
71
76
|
}
|
|
@@ -188,12 +188,12 @@ function processExternalReferences(config, GITHUB_API_TOKEN, options) {
|
|
|
188
188
|
);
|
|
189
189
|
|
|
190
190
|
// Ensure that the 'output' directory exists, creating it if necessary.
|
|
191
|
-
const outputDir = '
|
|
191
|
+
const outputDir = '.cache';
|
|
192
192
|
if (!fs.existsSync(outputDir)) {
|
|
193
193
|
fs.mkdirSync(outputDir);
|
|
194
194
|
}
|
|
195
195
|
|
|
196
|
-
// Ensure that the '
|
|
196
|
+
// Ensure that the 'xtrefs-history' in outputDir exists, creating it if necessary.
|
|
197
197
|
const xtrefsHistoryDir = path.join(outputDir, 'xtrefs-history');
|
|
198
198
|
if (!fs.existsSync(xtrefsHistoryDir)) {
|
|
199
199
|
fs.mkdirSync(xtrefsHistoryDir);
|
package/src/config/paths.js
CHANGED
|
@@ -12,9 +12,9 @@ const paths = {};
|
|
|
12
12
|
// console.log(getAllPaths());
|
|
13
13
|
|
|
14
14
|
// Add paths
|
|
15
|
-
paths['output-local-terms'] = path.resolve('
|
|
15
|
+
paths['output-local-terms'] = path.resolve('.cache', 'local-terms-dir');
|
|
16
16
|
paths['specsjson'] = path.resolve('specs.json');
|
|
17
|
-
paths['githubcache'] = path.resolve('
|
|
17
|
+
paths['githubcache'] = path.resolve('.cache', 'github-cache');
|
|
18
18
|
|
|
19
19
|
module.exports = {
|
|
20
20
|
/**
|
package/src/create-term-index.js
CHANGED
|
@@ -1,41 +1,145 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Steps:
|
|
3
|
-
* 1. Reads the configuration from 'specs.json'.
|
|
4
|
-
* 2. Extracts the directories containing the specifications and terms.
|
|
5
|
-
* 3. Lists all file names in the specified terms directory.
|
|
3
|
+
* 1. Reads the configuration from 'specs.json', with fallbacks for missing or invalid files.
|
|
4
|
+
* 2. Extracts the directories containing the specifications and terms, with defaults for missing values.
|
|
5
|
+
* 3. Lists all file names in the specified terms directory if it exists.
|
|
6
6
|
* 4. Joins each file name with the terms directory path.
|
|
7
|
-
* 5. Creates an '
|
|
7
|
+
* 5. Creates an '.cache' directory in the project root if it does not exist.
|
|
8
8
|
* 6. Writes the list of file paths to 'term-index.json' in the project root.
|
|
9
9
|
*
|
|
10
|
+
* If any errors occur during the process, appropriate warnings are logged, and an empty term index
|
|
11
|
+
* will be created rather than throwing fatal errors.
|
|
12
|
+
*
|
|
10
13
|
* @requires fs-extra - File system operations with extra methods.
|
|
11
14
|
* @requires path - Utilities for working with file and directory paths.
|
|
12
15
|
* @file src/create-term-index.js
|
|
13
16
|
* @author Kor Dwarshuis
|
|
14
|
-
* @version 1.
|
|
17
|
+
* @version 1.1.0
|
|
15
18
|
* @since 2024-09-02
|
|
16
19
|
*/
|
|
17
20
|
|
|
18
21
|
const { shouldProcessFile } = require('./utils/file-filter');
|
|
19
22
|
|
|
20
23
|
function createTermIndex() {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
24
|
+
try {
|
|
25
|
+
const fs = require('fs-extra');
|
|
26
|
+
const path = require('path');
|
|
27
|
+
const configPath = 'specs.json';
|
|
28
|
+
|
|
29
|
+
// Check if specs.json exists
|
|
30
|
+
if (!fs.existsSync(configPath)) {
|
|
31
|
+
console.warn(`Config file '${configPath}' not found. Using default configuration.`);
|
|
32
|
+
var config = { specs: [] };
|
|
33
|
+
} else {
|
|
34
|
+
// Read config with try-catch to handle parsing errors
|
|
35
|
+
try {
|
|
36
|
+
var config = fs.readJsonSync(configPath);
|
|
37
|
+
} catch (readError) {
|
|
38
|
+
console.warn(`Error reading config file: ${readError.message}. Using default configuration.`);
|
|
39
|
+
var config = { specs: [] };
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Provide defaults for missing config
|
|
44
|
+
if (!config) {
|
|
45
|
+
console.warn('Config file is empty or invalid. Using defaults.');
|
|
46
|
+
config = { specs: [] };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (!config.specs) {
|
|
50
|
+
console.warn('No specs array found in config. Creating empty specs array.');
|
|
51
|
+
config.specs = [];
|
|
52
|
+
} else if (!Array.isArray(config.specs)) {
|
|
53
|
+
console.warn('Config specs is not an array. Converting to array.');
|
|
54
|
+
config.specs = [config.specs]; // Convert to array if it's an object
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// If no valid specs, create an empty term index
|
|
58
|
+
if (config.specs.length === 0) {
|
|
59
|
+
console.warn('No specs found in configuration. Creating an empty term index.');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Extract spec directories with fallback to current directory
|
|
63
|
+
const specDirectories = config.specs.map((spec, index) => {
|
|
64
|
+
if (!spec.spec_directory) {
|
|
65
|
+
console.warn(`Warning: spec_directory missing in specs.json entry #${index + 1}. Using current directory.`);
|
|
66
|
+
return '.'; // Default to current directory
|
|
67
|
+
}
|
|
68
|
+
return spec.spec_directory;
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// Extract term directories with fallback to default value
|
|
72
|
+
const specTermDirectoryName = config.specs.map((spec, index) => {
|
|
73
|
+
if (!spec.spec_terms_directory) {
|
|
74
|
+
console.warn(`Warning: spec_terms_directory missing in specs.json entry #${index + 1}. Using default 'terms' directory.`);
|
|
75
|
+
return 'terms'; // Default directory name for terms
|
|
76
|
+
}
|
|
77
|
+
return spec.spec_terms_directory;
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
// Safety check - if we have no valid entries, warn and exit cleanly
|
|
81
|
+
if (specDirectories.length === 0 || specTermDirectoryName.length === 0) {
|
|
82
|
+
console.log('No term directories found in configuration. Creating empty term index.');
|
|
83
|
+
|
|
84
|
+
// Create an empty term index
|
|
85
|
+
const outputPathJSON = path.join('.cache', 'term-index.json');
|
|
86
|
+
if (!fs.existsSync('.cache')) {
|
|
87
|
+
fs.mkdirSync('.cache', { recursive: true });
|
|
88
|
+
}
|
|
89
|
+
fs.writeJsonSync(outputPathJSON, [], { spaces: 2 });
|
|
90
|
+
console.log(`✅ Empty term index created at: ${outputPathJSON}`);
|
|
91
|
+
return; // Exit function early
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Verify that the base spec directory exists
|
|
95
|
+
const baseSpecDir = specDirectories[0];
|
|
96
|
+
if (!baseSpecDir || !fs.existsSync(baseSpecDir)) {
|
|
97
|
+
console.warn(`Spec directory '${baseSpecDir}' does not exist. Creating empty term index.`);
|
|
98
|
+
|
|
99
|
+
// Create an empty term index
|
|
100
|
+
const outputPathJSON = path.join('.cache', 'term-index.json');
|
|
101
|
+
if (!fs.existsSync('.cache')) {
|
|
102
|
+
fs.mkdirSync('.cache', { recursive: true });
|
|
103
|
+
}
|
|
104
|
+
fs.writeJsonSync(outputPathJSON, [], { spaces: 2 });
|
|
105
|
+
console.log(`✅ Empty term index created at: ${outputPathJSON}`);
|
|
106
|
+
return; // Exit function early
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Verify that the terms directory exists
|
|
110
|
+
const termsDir = path.join(baseSpecDir, specTermDirectoryName[0]);
|
|
111
|
+
|
|
112
|
+
let files = [];
|
|
113
|
+
if (!fs.existsSync(termsDir)) {
|
|
114
|
+
console.warn(`Terms directory '${termsDir}' does not exist. Creating an empty term index.`);
|
|
115
|
+
} else {
|
|
116
|
+
// Get list of files and filter them
|
|
117
|
+
files = fs.readdirSync(termsDir).filter(shouldProcessFile);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (files.length === 0) {
|
|
121
|
+
console.log('Warning: No term files found to process.');
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const filePaths = files.map(file => specTermDirectoryName[0] + '/' + file);
|
|
125
|
+
const outputPathJSON = path.join('.cache', 'term-index.json');
|
|
126
|
+
|
|
127
|
+
// Create .cache directory if it doesn't exist
|
|
128
|
+
if (!fs.existsSync('.cache')) {
|
|
129
|
+
fs.mkdirSync('.cache', { recursive: true });
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Write the term index file
|
|
133
|
+
try {
|
|
134
|
+
fs.writeJsonSync(outputPathJSON, filePaths, { spaces: 2 });
|
|
135
|
+
console.log(`✅ Term index created with ${files.length} terms. Output: ${outputPathJSON}`);
|
|
136
|
+
} catch (writeError) {
|
|
137
|
+
throw new Error(`Failed to write term index file: ${writeError.message}`);
|
|
138
|
+
}
|
|
139
|
+
} catch (error) {
|
|
140
|
+
console.error(`❌ Error creating term index: ${error.message}`);
|
|
141
|
+
throw error;
|
|
34
142
|
}
|
|
35
|
-
|
|
36
|
-
fs.writeJsonSync(outputPathJSON, filePaths, { spaces: 2 });
|
|
37
|
-
|
|
38
|
-
console.log(`✅ The new terms were added. All done.`);
|
|
39
143
|
}
|
|
40
144
|
|
|
41
145
|
module.exports = {
|
|
@@ -321,7 +321,7 @@ async function getProjectConfiguration(projectRoot) {
|
|
|
321
321
|
externalSpecs,
|
|
322
322
|
specDirs,
|
|
323
323
|
valid: true,
|
|
324
|
-
githubCacheDir: path.join(projectRoot, '
|
|
324
|
+
githubCacheDir: path.join(projectRoot, '.cache', 'github-cache')
|
|
325
325
|
};
|
|
326
326
|
}
|
|
327
327
|
|
package/src/health-check.js
CHANGED
|
@@ -15,7 +15,7 @@ const outputGitignoreChecker = require('./health-check/output-gitignore-checker'
|
|
|
15
15
|
const trefTermChecker = require('./health-check/tref-term-checker');
|
|
16
16
|
|
|
17
17
|
// Configuration
|
|
18
|
-
const OUTPUT_DIR = path.join(process.cwd(), '
|
|
18
|
+
const OUTPUT_DIR = path.join(process.cwd(), '.cache');
|
|
19
19
|
|
|
20
20
|
// Create output directory if it doesn't exist
|
|
21
21
|
if (!fs.existsSync(OUTPUT_DIR)) {
|
package/src/init.js
CHANGED
package/src/insert-term-index.js
CHANGED
|
@@ -19,8 +19,8 @@ function insertTermIndex() {
|
|
|
19
19
|
const fs = require('fs-extra');
|
|
20
20
|
const path = require('path');
|
|
21
21
|
const config = fs.readJsonSync(path.join('specs.json'));
|
|
22
|
-
const terms = fs.readJsonSync(path.join('
|
|
23
|
-
const outputPathJSON = path.join('
|
|
22
|
+
const terms = fs.readJsonSync(path.join('.cache', 'term-index.json'));
|
|
23
|
+
const outputPathJSON = path.join('.cache', 'specs-generated.json');
|
|
24
24
|
let specGenerated = config;
|
|
25
25
|
let markdownPaths = specGenerated.specs[0].markdown_paths;
|
|
26
26
|
|
|
@@ -36,9 +36,9 @@ function insertTermIndex() {
|
|
|
36
36
|
// Save the updated specGenerated object back to the JSON file
|
|
37
37
|
fs.writeJsonSync(outputPathJSON, specGenerated, { spaces: 2 });
|
|
38
38
|
|
|
39
|
-
// Create directory named
|
|
40
|
-
if (!fs.existsSync('
|
|
41
|
-
fs.mkdirSync('
|
|
39
|
+
// Create directory named “.cache” in the project root if it does not yet exist
|
|
40
|
+
if (!fs.existsSync('.cache')) {
|
|
41
|
+
fs.mkdirSync('.cache');
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
fs.writeJsonSync(outputPathJSON, specGenerated, { spaces: 2 });
|
|
@@ -8,7 +8,9 @@ const path = require('path');
|
|
|
8
8
|
* @param {Object} [overwriteKeys={}] - An object specifying which scripts to overwrite if they already exist.
|
|
9
9
|
*/
|
|
10
10
|
function addScriptsKeys(scriptKeys, overwriteKeys = {}) {
|
|
11
|
-
|
|
11
|
+
// Use process.cwd() to get the current working directory where the command is run
|
|
12
|
+
const packageJsonPath = path.resolve(process.cwd(), 'package.json');
|
|
13
|
+
|
|
12
14
|
|
|
13
15
|
// Read the package.json file
|
|
14
16
|
fs.readFile(packageJsonPath, 'utf8', (err, data) => {
|
package/src/utils/fetch.js
CHANGED
|
@@ -5,13 +5,13 @@ const fs = require('fs');
|
|
|
5
5
|
const path = require('path');
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* Fetches the
|
|
8
|
+
* Fetches the .cache/specs-generated.json file and returns it as a JavaScript object
|
|
9
9
|
* @returns {Object} The parsed contents of specs-generated.json
|
|
10
10
|
*/
|
|
11
11
|
function fetchSpecs() {
|
|
12
12
|
try {
|
|
13
|
-
// Resolve path to
|
|
14
|
-
const specsPath = path.resolve(process.cwd(), '
|
|
13
|
+
// Resolve path to .cache/specs-generated.json from the project root
|
|
14
|
+
const specsPath = path.resolve(process.cwd(), '.cache', 'specs-generated.json');
|
|
15
15
|
|
|
16
16
|
// Read the file synchronously
|
|
17
17
|
const specsContent = fs.readFileSync(specsPath, 'utf8');
|
|
@@ -21,19 +21,19 @@ function fetchSpecs() {
|
|
|
21
21
|
|
|
22
22
|
return specs;
|
|
23
23
|
} catch (error) {
|
|
24
|
-
console.error('Error fetching
|
|
24
|
+
console.error('Error fetching .cache/specs-generated.json:', error.message);
|
|
25
25
|
return null;
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
|
-
* Fetches the
|
|
30
|
+
* Fetches the .cache/xtrefs-data.json file and returns it as a JavaScript object
|
|
31
31
|
* @returns {Object} The parsed contents of xtrefs-data.json
|
|
32
32
|
*/
|
|
33
33
|
function fetchExternalTerms() {
|
|
34
34
|
try {
|
|
35
|
-
// Resolve path to
|
|
36
|
-
const xtrefsPath = path.resolve(process.cwd(), '
|
|
35
|
+
// Resolve path to .cache/xtrefs-data.json from the project root
|
|
36
|
+
const xtrefsPath = path.resolve(process.cwd(), '.cache', 'xtrefs-data.json');
|
|
37
37
|
|
|
38
38
|
// Read the file synchronously
|
|
39
39
|
const xtrefsContent = fs.readFileSync(xtrefsPath, 'utf8');
|
|
@@ -43,7 +43,7 @@ function fetchExternalTerms() {
|
|
|
43
43
|
|
|
44
44
|
return xtrefs;
|
|
45
45
|
} catch (error) {
|
|
46
|
-
console.error('Error fetching
|
|
46
|
+
console.error('Error fetching .cache/xtrefs-data.json:', error.message);
|
|
47
47
|
return null;
|
|
48
48
|
}
|
|
49
49
|
}
|
|
@@ -54,8 +54,8 @@ function fetchExternalTerms() {
|
|
|
54
54
|
*/
|
|
55
55
|
async function fetchSpecsAsync() {
|
|
56
56
|
try {
|
|
57
|
-
// Resolve path to
|
|
58
|
-
const specsPath = path.resolve(process.cwd(), '
|
|
57
|
+
// Resolve path to .cache/specs-generated.json from the project root
|
|
58
|
+
const specsPath = path.resolve(process.cwd(), '.cache', 'specs-generated.json');
|
|
59
59
|
|
|
60
60
|
// Read the file asynchronously
|
|
61
61
|
const specsContent = await fs.promises.readFile(specsPath, 'utf8');
|
|
@@ -65,7 +65,7 @@ async function fetchSpecsAsync() {
|
|
|
65
65
|
|
|
66
66
|
return specs;
|
|
67
67
|
} catch (error) {
|
|
68
|
-
console.error('Error fetching
|
|
68
|
+
console.error('Error fetching .cache/specs-generated.json:', error.message);
|
|
69
69
|
return null;
|
|
70
70
|
}
|
|
71
71
|
}
|
|
@@ -76,8 +76,8 @@ async function fetchSpecsAsync() {
|
|
|
76
76
|
*/
|
|
77
77
|
async function fetchExternalTermsAsync() {
|
|
78
78
|
try {
|
|
79
|
-
// Resolve path to
|
|
80
|
-
const xtrefsPath = path.resolve(process.cwd(), '
|
|
79
|
+
// Resolve path to .cache/xtrefs-data.json from the project root
|
|
80
|
+
const xtrefsPath = path.resolve(process.cwd(), '.cache', 'xtrefs-data.json');
|
|
81
81
|
|
|
82
82
|
// Read the file asynchronously
|
|
83
83
|
const xtrefsContent = await fs.promises.readFile(xtrefsPath, 'utf8');
|
|
@@ -87,7 +87,7 @@ async function fetchExternalTermsAsync() {
|
|
|
87
87
|
|
|
88
88
|
return xtrefs;
|
|
89
89
|
} catch (error) {
|
|
90
|
-
console.error('Error fetching
|
|
90
|
+
console.error('Error fetching .cache/xtrefs-data.json:', error.message);
|
|
91
91
|
return null;
|
|
92
92
|
}
|
|
93
93
|
}
|