datalog-theme 0.7.0 → 0.8.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +125 -0
- data/CITATION.cff +2 -2
- data/README.md +23 -17
- data/_data/cdn-integrity.yml +0 -30
- data/_includes/analytics/dashboard.html +3 -1
- data/_includes/components/api-function.html +20 -1
- data/_includes/components/enhanced-code-block.html +1 -1
- data/_includes/csp-meta.html +115 -11
- data/_includes/footer.html +19 -20
- data/_includes/head.html +60 -23
- data/_includes/header/navigation.html +12 -15
- data/_includes/header.html +28 -19
- data/_includes/layouts/default/article.html +5 -1
- data/_includes/meta/math-config.html +9 -5
- data/_includes/meta/schema.html +5 -2
- data/_includes/meta/scripts-loader.html +16 -32
- data/_includes/post/related-posts.html +4 -7
- data/_includes/search/index-data.json +9 -34
- data/_layouts/dataset.html +1 -0
- data/_layouts/default.html +16 -8
- data/_layouts/notebook.html +1 -0
- data/_layouts/package.html +1 -0
- data/_layouts/portfolio.html +1 -0
- data/_layouts/post.html +20 -5
- data/_layouts/project.html +2 -1
- data/_plugins/analytics_dashboard.rb +9 -3
- data/_plugins/config_validator.rb +12 -7
- data/_plugins/csp_generator.rb +18 -28
- data/_plugins/datalog_bibliography.rb +9 -7
- data/_plugins/datalog_comments.rb +8 -5
- data/_plugins/datalog_slides.rb +9 -8
- data/_plugins/i18n.rb +7 -8
- data/_plugins/image_optimizer.rb +17 -6
- data/_plugins/math_preprocessor.rb +33 -3
- data/_plugins/notebook_converter.rb +23 -4
- data/_plugins/plugin_loader.rb +3 -1
- data/_plugins/publications_generator.rb +8 -2
- data/_plugins/rouge_highlight_filter.rb +42 -0
- data/_plugins/search_code_blocks.rb +30 -0
- data/_plugins/search_normalizer.rb +15 -53
- data/_plugins/search_pages.rb +3 -4
- data/_sass/_academic-dashboard.scss +262 -0
- data/_sass/_base.scss +12 -0
- data/_sass/_components.scss +64 -1153
- data/_sass/_features.scss +17 -0
- data/_sass/_layout.scss +1 -1
- data/_sass/_notebooks.scss +322 -0
- data/_sass/_open-science-badges.scss +56 -0
- data/_sass/{_phase1-enhancements.scss → _post-components.scss} +1 -1
- data/_sass/_search-page.scss +530 -0
- data/_sass/_search.scss +46 -0
- data/_sass/_syntax-highlighting.scss +212 -97
- data/_sass/_theme.scss +29 -19
- data/_sass/_typography.scss +14 -0
- data/assets/css/main.scss +14 -0
- data/assets/js/dist/academic.js +1 -1
- data/assets/js/dist/analytics-dashboard.js +1 -1
- data/assets/js/dist/chunks/chunk-225H5YXE.js +1 -0
- data/assets/js/dist/core.js +1 -1
- data/assets/js/dist/loader.js +1 -1
- data/assets/js/dist/notebook.js +1 -1
- data/assets/js/dist/search.js +1 -1
- data/assets/js/dist/visualizations.js +11 -2
- data/assets/js/loader.js +3 -1
- data/datalog-theme.gemspec +36 -23
- data/lib/datalog/cli.rb +34 -14
- data/lib/datalog/plugin_system/dependency_resolver.rb +0 -2
- data/lib/datalog/theme/package.rb +57 -0
- data/lib/datalog/theme/repository_checkout.rb +90 -0
- data/lib/datalog/theme/version.rb +1 -1
- data/lib/datalog/warning_filter.rb +5 -11
- data/lib/datalog-theme.rb +5 -0
- metadata +48 -133
- data/_data/academic.yml +0 -217
- data/_data/config/author.yml +0 -121
- data/_data/datasets.yml +0 -28
- data/_data/js_meta.json +0 -371
- data/_data/navigation.yml +0 -145
- data/_data/projects.yml +0 -41
- data/_data/publications.yml +0 -28
- data/_data/social.yml +0 -73
- data/_data/visualizations.yml +0 -51
- data/_includes/components/advanced-search.html +0 -682
- data/_includes/components/bookmark-system.html +0 -96
- data/_includes/components/comments.html +0 -244
- data/_includes/components/content-recommendations.html +0 -228
- data/_includes/components/email-preferences.html +0 -200
- data/_includes/components/enhanced-metadata.html +0 -228
- data/_includes/components/language-switcher.html +0 -396
- data/_includes/components/navigation-enhancements.html +0 -454
- data/_includes/components/newsletter-signup.html +0 -178
- data/_includes/components/popular-posts.html +0 -233
- data/_includes/components/reading-progress.html +0 -133
- data/_includes/components/reading-time.html +0 -121
- data/_includes/components/series-navigation.html +0 -124
- data/_includes/components/social-proof.html +0 -34
- data/_includes/components/user-preferences.html +0 -566
- data/_includes/meta/syntax-config.html +0 -19
- data/_layouts/archive.html +0 -282
- data/_layouts/post-sidebar.html +0 -183
- data/_sass/_phase3-enhancements.scss +0 -874
- data/_sass/_phase4-enhancements.scss +0 -1214
- data/_sass/_phase5-enhancements.scss +0 -414
- data/assets/js/academic.js +0 -262
- data/assets/js/analytics-dashboard.js +0 -382
- data/assets/js/core/dark-mode.js +0 -79
- data/assets/js/core/github-cards.js +0 -123
- data/assets/js/core/language-filter.js +0 -69
- data/assets/js/core/navigation.js +0 -184
- data/assets/js/core/scroll-progress.js +0 -45
- data/assets/js/core/search-hotkeys.js +0 -62
- data/assets/js/core/skip-links.js +0 -62
- data/assets/js/dist/manifest.json +0 -22
- data/assets/js/dist/meta.json +0 -371
- data/assets/js/main.js +0 -23
- data/assets/js/math.js +0 -818
- data/assets/js/notebook.js +0 -158
- data/assets/js/search/analytics.js +0 -91
- data/assets/js/search/app.js +0 -271
- data/assets/js/search/autocomplete.js +0 -120
- data/assets/js/search/engine.js +0 -260
- data/assets/js/search/filters.js +0 -45
- data/assets/js/search/render.js +0 -217
- data/assets/js/search/utils.js +0 -99
- data/assets/js/search.js +0 -354
- data/assets/js/visualizations.js +0 -816
- data/assets/publications/datalog-publications.bib +0 -8
- data/assets/publications/datalog-publications.ris +0 -9
- data/assets/publications/publications.bib +0 -30
- data/assets/templates/diogo-ribeiro-cv.md +0 -31
- data/assets/templates/diogo-ribeiro-cv.tex +0 -32
- data/lib/datalog/theme/theme.rb +0 -18
data/assets/js/dist/search.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var j="datalog-search-analytics";function K({panel:e,list:n,empty:t,onSelect:o}){if(!e||!n||!t)return{record(){},render(){}};let r=g(),f="";function g(){let v=Object.create(null);try{let s=window.localStorage.getItem(j);if(s){let i=JSON.parse(s);i&&typeof i=="object"&&Object.entries(i).forEach(([d,u])=>{typeof u=="number"&&Number.isFinite(u)&&(v[d]=u)})}}catch(s){}return v}function w(){try{window.localStorage.setItem(j,JSON.stringify(r))}catch(v){}}function c(v){let s=(v||"").trim();!s||s===f||(f=s,r[s]=(r[s]||0)+1,w(),h())}function h(){let v=Object.entries(r).filter(([i])=>i&&i.trim().length>1).sort((i,d)=>d[1]-i[1]).slice(0,5);if(n.replaceChildren(),v.length===0){t.hidden=!1;return}t.hidden=!0;let s=document.createDocumentFragment();v.forEach(([i,d])=>{let u=document.createElement("li"),p=document.createElement("button");p.type="button",p.className="search-analytics__query",p.textContent=`${i} (${d})`,p.addEventListener("click",()=>{typeof o=="function"&&o(i)}),u.appendChild(p),s.appendChild(u)}),n.appendChild(s)}return{record:c,render:h}}function z(e=""){let n=e==null?"":String(e);try{return n.toLowerCase().normalize("NFKD").replace(new RegExp("\\p{Diacritic}","gu"),"")}catch(t){return n.toLowerCase()}}function F(e=""){return z(e).replace(/\s+/g,"")}function P(e=""){return z(e).split(/[^a-z0-9\\._]+/).filter(Boolean)}function H(e=""){return/\\|\^|_|\{|\}|\$/.test(e)}function B(e=""){return/`|::|->|=>|\(|\)|\{|\}|\[|\]|=|\bdef\b|\bfunction\b|\bclass\b/.test(e)}function X(e,n){if(!e||!n)return!1;let t=0;for(let o=0;o<e.length&&t<n.length;o+=1)e[o]===n[t]&&(t+=1);return t===n.length}function oe(e){if(!e)return"";let n=document.createElement("div");return n.innerHTML=e,n.textContent||n.innerText||""}function O(e,n,t){if(!e)return"";let o=oe(e),r=Math.max(0,n-80),f=Math.min(o.length,n+t+80);return`${o.slice(r,f)}${f<o.length?"\u2026":""}`}function se(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function _(e,n){if(!e||!n)return e;let t=Array.from(new Set(P(n))).sort((r,f)=>f.length-r.length),o=e;return t.forEach(r=>{if(!r)return;let f=new RegExp(`(${se(r)})`,"gi");o=o.replace(f,"<mark>$1</mark>")}),o}function M(e){return(e||"").toString().split(/[-_\s]+/).map(n=>n.charAt(0).toUpperCase()+n.slice(1)).join(" ")}function J(e){switch(e){case"post":return"Tutorial & Blog";case"project":return"Project";case"research":return"Research";case"dataset":return"Dataset";default:return M(e||"Page")}}function Y({panel:e,limit:n=8,onSelect:t}){if(!e)return{setSuggestions(){},update(){},close(){},handleNavigation(){}};let o=[],r=-1;function f(s){o=Array.isArray(s)?[...s]:[]}function g(s){r=-1;let i=(s||"").trim().toLowerCase();if(!i){h();return}let d=o.filter(p=>p&&p.toLowerCase().includes(i)).slice(0,n);if(d.length===0){h();return}let u=document.createDocumentFragment();d.forEach((p,E)=>{let y=document.createElement("button");y.type="button",y.className="search-autocomplete__option",y.setAttribute("role","option"),y.dataset.autocompleteOption="",y.dataset.value=p,y.setAttribute("aria-selected",E===r?"true":"false"),y.replaceChildren(),y.insertAdjacentHTML("beforeend",_(p,i)),u.appendChild(y)}),e.replaceChildren(),e.appendChild(u),e.hidden=!1}function w(s,i){if(e.hidden)return;let d=Array.from(e.querySelectorAll("[data-autocomplete-option]"));if(d.length!==0){if(s.key==="ArrowDown")s.preventDefault(),r=(r+1)%d.length,c(d);else if(s.key==="ArrowUp")s.preventDefault(),r=(r-1+d.length)%d.length,c(d);else if(s.key==="Enter"&&r>=0){s.preventDefault();let u=d[r],p=u?u.dataset.value:"";p&&i&&(i.value=p),typeof t=="function"&&t(p),v()}}}function c(s){s.forEach((i,d)=>{let u=d===r;i.setAttribute("aria-selected",u?"true":"false"),i.classList.toggle("is-active",u)})}function h(){e.replaceChildren(),e.hidden=!0,r=-1}function v(){h()}return e.addEventListener("click",s=>{let i=s.target.closest("[data-autocomplete-option]");if(!i)return;let d=i.dataset.value||"";d&&typeof t=="function"&&t(d),v()}),{setSuggestions:f,update:g,close:v,handleNavigation:w}}function V(e=[]){let n=Array.isArray(e)?[...e]:[];function t(g){n=Array.isArray(g)?[...g]:[]}function o(g,w={}){let c=(g||"").trim();if(!c)return[];let h=z(c),v=P(c),s=H(c),i=B(c),{type:d="",language:u="",difficulty:p="",tags:E=new Set}=w;return n.map(y=>le(y,{rawQuery:c,normalizedQuery:h,queryTokens:v,mathQuery:s,codeQuery:i,typeFilter:d,languageFilter:u,difficultyFilter:p,selectedTags:E})).filter(y=>y&&y.score>0).sort((y,C)=>C.score-y.score||y.title.localeCompare(C.title))}function r(g=150){return ce(n,g)}function f(){return[...n]}return{setDocuments:t,search:o,suggestions:r,getDocuments:f}}function ce(e=[],n=150){let t=new Set;return e.forEach(o=>{o.title&&t.add(o.title),Array.isArray(o.languages)&&o.languages.forEach(r=>t.add(r)),Array.isArray(o.tags)&&o.tags.forEach(r=>t.add(`#${r}`)),Array.isArray(o.math)&&o.math.slice(0,3).forEach(r=>t.add(r))}),Array.from(t).slice(0,n)}function le(e,n){let{rawQuery:t,normalizedQuery:o,queryTokens:r,mathQuery:f,codeQuery:g,typeFilter:w,languageFilter:c,difficultyFilter:h,selectedTags:v}=n;if(w&&e.type!==w)return null;let s=Array.isArray(e.languages)?e.languages:[];if(c&&!s.includes(c))return null;if(h){let a=String(e.difficulty||"").toLowerCase();if(!a||a!==h)return null}if(v&&v.size>0){let a=ue(e,"tags");for(let S of v)if(!a.has(S))return null}if(!t)return null;let i=e.normalized||{},d=i.content||z(e.content||""),u=i.summary||z(e.summary||""),p=i.title||z(e.title||""),E=G(i.tags,e.tags),y=G(i.languages,e.languages),C=i.difficulty||z(e.difficulty||""),T=Array.isArray(e.code)?e.code:[],k=Array.isArray(e.math)?e.math:[],m=0,q="",x=null,L=null;if(p.includes(o)&&(m+=40),r.forEach(a=>{a&&(p.includes(a)&&(m+=12),u.includes(a)&&(m+=8),d.includes(a)&&(m+=6),E.forEach(S=>{S.includes(a)&&(m+=4)}),y.forEach(S=>{S.includes(a)&&(m+=4)}),C.includes(a)&&(m+=2))}),T.length>0){let a=F(t);for(let S of T){let b=String(S.language||"").toLowerCase(),I=S.code||"",N=F(I);if(N.includes(a)){m+=30,x={language:b,code:I};break}if(g&&X(N,a)){m+=18,x={language:b,code:I};break}}!x&&T[0]&&(x={language:String(T[0].language||"").toLowerCase(),code:T[0].code||""})}if(k.length>0){let a=o.replace(/\\/g,"");for(let S of k)if(z(String(S)).includes(a)){m+=26,L=S;break}f&&!L&&k[0]&&(L=k[0],m+=10)}if(d.includes(o)){let a=d.indexOf(o);q=O(e.content||"",a,t.length),m+=10}else if(u.includes(o)){let a=u.indexOf(o);q=O(e.summary||"",a,t.length),m+=6}return m===0?null:{id:`${e.url}`,title:e.title,url:e.url,summary:e.summary,snippet:q,codeSnippet:x,mathSnippet:L,tags:e.tags||[],languages:e.languages||[],difficulty:e.difficulty||"",type:e.type||"page",date:e.date,readingTime:e.reading_time,score:m}}function G(e,n){return Array.isArray(e)&&e.length>0?e:Array.isArray(n)?n.map(t=>z(t)):[]}function ue(e,n){let o=(e.normalized||{})[n];if(Array.isArray(o)&&o.length>0)return new Set(o);let r=Array.isArray(e[n])?e[n]:[];return new Set(r.map(f=>z(f)))}function W(e,n,t){if(!e)return;let o=new Set;n.forEach(g=>{(g.tags||g.topics||[]).forEach(c=>{if(!c)return;let h=String(c).trim().toLowerCase();h&&o.add(h)})});let r=Array.from(o).sort();if(r.length===0){let g=document.createElement("p");g.className="search-filter__empty",g.textContent="No tags available yet.",e.replaceChildren(g);return}let f=document.createDocumentFragment();r.forEach(g=>{let w=document.createElement("button");w.type="button",w.className="search-filter__tag",w.textContent=g,w.dataset.filterTag=g,w.setAttribute("aria-pressed",t.has(g)?"true":"false"),f.appendChild(w)}),e.replaceChildren(),e.appendChild(f)}function Z(e,n,t){let{resultsList:o,resultsMeta:r,emptyState:f,template:g}=t;if(!o||!r||!f||!g)return;if(o.replaceChildren(),!n){r.textContent="Enter a query to begin.",f.hidden=!0;return}if(e.length===0){r.textContent=`No matches for \u201C${n}\u201D.`,f.hidden=!1;return}f.hidden=!0,r.textContent=`${e.length} result${e.length===1?"":"s"} for \u201C${n}\u201D.`;let w=document.createDocumentFragment();e.forEach(c=>{let h=g.content.cloneNode(!0),v=h.querySelector("[data-result-type]"),s=h.querySelector("[data-result-difficulty]"),i=h.querySelector("[data-result-languages]"),d=h.querySelector("[data-result-link]"),u=h.querySelector("[data-result-summary]"),p=h.querySelector("[data-result-code]"),E=p?p.querySelector("code"):null,y=h.querySelector("[data-result-math]"),C=h.querySelector("[data-result-math-preview]"),T=h.querySelector("[data-result-math-code]"),k=h.querySelector("[data-result-math-copy]"),m=h.querySelector("[data-result-excerpt]"),q=h.querySelector("[data-result-tags]"),x=h.querySelector("[data-result-date]");if(v&&(v.textContent=J(c.type)),s&&(c.difficulty?(s.textContent=`Difficulty: ${M(c.difficulty)}`,s.hidden=!1):s.hidden=!0),i&&(c.languages&&c.languages.length>0?(i.textContent=`Languages: ${c.languages.map(L=>M(L)).join(", ")}`,i.hidden=!1):i.hidden=!0),d&&(d.textContent=c.title||c.url,d.setAttribute("href",c.url)),u&&(u.replaceChildren(),u.insertAdjacentHTML("beforeend",_(c.summary||"",n))),y&&T&&(c.mathSnippet?(y.hidden=!1,T.textContent=c.mathSnippet,C&&(window.DatalogMath&&typeof window.DatalogMath.renderLatex=="function"?window.DatalogMath.renderLatex(C,c.mathSnippet,{display:!1,enhance:!1}):window.MathJax&&typeof window.MathJax.typesetPromise=="function"?(C.innerHTML=`\\(${c.mathSnippet}\\)`,window.MathJax.typesetPromise([C]).catch(()=>{C.textContent=c.mathSnippet})):C.textContent=c.mathSnippet),k&&k.addEventListener("click",()=>de(c.mathSnippet,y))):y.hidden=!0),m&&(c.snippet?(m.replaceChildren(),m.insertAdjacentHTML("beforeend",_(c.snippet,n)),m.hidden=!1):m.hidden=!0),p&&E)if(c.codeSnippet&&c.codeSnippet.code){let L=c.codeSnippet.language||"text";p.classList.remove("language-none"),p.classList.add(`language-${L}`),E.className=`language-${L}`;let a=c.codeSnippet.code;if(window.Prism&&window.Prism.languages){let S=window.Prism.languages[L]||window.Prism.languages.markup;E.innerHTML=window.Prism.highlight(a,S,L)}else E.textContent=a;p.hidden=!1}else p.hidden=!0;if(q&&(q.replaceChildren(),(c.tags||[]).forEach(L=>{let a=document.createElement("li");a.textContent=`#${L}`,q.appendChild(a)})),x)if(c.date){let L=new Date(c.date);Number.isNaN(L.getTime())?x.hidden=!0:(x.textContent=L.toLocaleDateString(void 0,{year:"numeric",month:"short",day:"numeric"}),x.hidden=!1)}else x.hidden=!0;w.appendChild(h)}),o.appendChild(w)}function de(e,n){if(!e)return;let t=()=>{if(!n)return;let r=n.querySelector("[data-result-math-copy]"),f=r?r.querySelector(".visually-hidden"):null;if(r&&f){let g=r.getAttribute("data-sr-original")||f.textContent;r.getAttribute("data-sr-original")||r.setAttribute("data-sr-original",g||"Copy LaTeX"),f.textContent="Copied LaTeX",r.classList.add("is-copied"),window.setTimeout(()=>{f.textContent=r.getAttribute("data-sr-original")||"Copy LaTeX",r.classList.remove("is-copied")},2e3)}},o=()=>{let r=document.createElement("textarea");r.value=e,r.setAttribute("aria-hidden","true"),r.style.position="fixed",r.style.opacity="0",document.body.appendChild(r),r.select();try{document.execCommand("copy"),t()}catch(f){}document.body.removeChild(r)};navigator.clipboard&&navigator.clipboard.writeText?navigator.clipboard.writeText(e).then(()=>t()).catch(()=>o()):o()}var fe=8;function ee(){let e=document.querySelector("[data-search-app]");if(!e)return;let n=e.querySelector("[data-search-form]"),t=e.querySelector("[data-search-input]"),o=e.querySelector("[data-search-results]"),r=e.querySelector("[data-search-meta]"),f=e.querySelector("[data-search-empty]"),g=e.querySelector("[data-search-autocomplete]"),w=e.querySelector("[data-search-analytics]"),c=w?w.querySelector(".search-app__analytics-list"):null,h=w?w.querySelector(".search-app__analytics-empty"):null,v=document.getElementById("search-result-template"),s=e.querySelector("[data-filter-type]"),i=e.querySelector("[data-filter-language]"),d=e.querySelector("[data-filter-difficulty]"),u=e.querySelector("[data-filter-tags]"),p=e.getAttribute("data-search-index")||"/search.json",E=new Set,y=V(),C=K({panel:w,list:c,empty:h,onSelect:a=>{t&&(t.value=a,x())}}),T=Y({panel:g,limit:fe,onSelect:a=>{a&&t&&(t.value=a,t.focus(),x())}}),k=!1,m=new URLSearchParams(window.location.search);t&&m.has("q")&&(t.value=m.get("q")||""),s&&m.has("type")&&(s.value=m.get("type")),i&&m.has("language")&&(i.value=m.get("language")),d&&m.has("difficulty")&&(d.value=m.get("difficulty")),m.has("tags")&&m.get("tags").split(",").map(a=>a.trim().toLowerCase()).filter(Boolean).forEach(a=>E.add(a)),he(t,()=>{T.close(),x()}),ge(p).then(a=>{let S=a.documents||[];y.setDocuments(S),T.setSuggestions(y.suggestions()),W(u,S,E),k=!0,q()}).catch(a=>{r&&(r.textContent="Unable to load the search index. Please try again later.")}),n&&n.addEventListener("submit",a=>{a.preventDefault(),x()}),t&&(t.addEventListener("input",()=>{T.update(t.value)}),t.addEventListener("keydown",a=>{T.handleNavigation(a,t)}),t.addEventListener("focus",()=>{T.update(t.value)})),s&&s.addEventListener("change",x),i&&i.addEventListener("change",x),d&&d.addEventListener("change",x),e.addEventListener("click",a=>{let S=a.target;if(S.matches("[data-filter-tag]")){let b=S.getAttribute("data-filter-tag");b&&(E.has(b)?(E.delete(b),S.setAttribute("aria-pressed","false")):(E.add(b),S.setAttribute("aria-pressed","true")),x())}}),document.addEventListener("click",a=>{!g||g.hidden||e.contains(a.target)||T.close()}),document.addEventListener("keydown",a=>{let S=document.activeElement?document.activeElement.tagName:"";["INPUT","TEXTAREA"].includes(S)||(a.key==="/"&&!a.ctrlKey&&!a.metaKey&&!a.altKey||(a.key==="k"||a.key==="K")&&(a.ctrlKey||a.metaKey))&&(a.preventDefault(),t&&(t.focus(),t.select()))}),C.render();function q(){t&&t.value.trim()?x():L()}function x(){if(!t)return;if(!k){r&&(r.textContent="Loading technical index\u2026");return}let a=t.value.trim(),S={type:s?s.value:"",language:i?i.value:"",difficulty:d?d.value:"",tags:E},b=y.search(a,S);Z(b,a,{resultsList:o,resultsMeta:r,emptyState:f,template:v}),L(a),C.record(a)}function L(a){let S=new URL(window.location.href),b=S.searchParams;a?b.set("q",a):b.delete("q"),s&&s.value?b.set("type",s.value):b.delete("type"),i&&i.value?b.set("language",i.value):b.delete("language"),d&&d.value?b.set("difficulty",d.value):b.delete("difficulty"),E.size>0?b.set("tags",Array.from(E).join(",")):b.delete("tags");let I=b.toString(),N=I?`${S.pathname}?${I}`:S.pathname;window.history.replaceState({},"",N)}}function ge(e){return fetch(e,{credentials:"same-origin"}).then(n=>{if(!n.ok)throw new Error(`HTTP ${n.status}`);return n.json()})}function he(e,n){e&&e.addEventListener("keydown",t=>{t.key==="Escape"&&(e.value="",typeof n=="function"&&n())})}var pe=300,me="search-result-",U=500;function ye(e,n=pe){let t,o=(...r)=>{t&&window.clearTimeout(t),t=window.setTimeout(()=>{t=void 0,e.apply(null,r)},n)};return o.cancel=()=>{t&&(window.clearTimeout(t),t=void 0)},o}function $(e,n){if(!e)return;let t=String(n||"");e.textContent===t?e.textContent=`${t}\xA0`:e.textContent=t,t.trim()?e.removeAttribute("hidden"):e.setAttribute("hidden","")}function Se(){let e=document.querySelector("[data-search-app]");if(!e)return;let n=e.querySelector("[data-search-form]"),t=e.querySelector("[data-search-input]"),o=e.querySelector("[data-search-results]"),r=e.querySelector("[data-search-empty]"),f=e.querySelector("[data-search-loading]"),g=e.querySelector("[data-search-region]"),w=e.querySelector('[data-search-live="count"]'),c=e.querySelector('[data-search-live="selection"]'),h=e.querySelector('[data-search-live="status"]'),v=e.querySelector("[data-search-filters]"),s=e.querySelector("[data-filter-tags]");if(!t||!o)return;let i=-1,d=0,u=[],p=!1,E=[],y=0,C=null,T=ye(()=>{n&&(p=!0,Q(),$(h,"Loading results\u2026"),n.dispatchEvent(new Event("submit",{cancelable:!0})))});new MutationObserver(()=>{I()}).observe(o,{childList:!0}),I(),q(),s&&new MutationObserver(()=>{q()}).observe(s,{childList:!0}),t.addEventListener("input",()=>{S(!1),T()}),t.addEventListener("keydown",l=>{if(!x(l)&&l.key==="Tab"&&E.length>0){l.preventDefault();let A=l.shiftKey?E.length-1:0;E[A].focus()}});function m(l){if(l.key!=="Tab"||E.length===0)return;l.preventDefault();let A=E.indexOf(l.currentTarget);if(A===-1)return;let D=l.shiftKey?-1:1,R=(A+D+E.length)%E.length;E[R].focus()}function q(){if(!v)return;let l=Array.from(v.querySelectorAll("select")),A=s?Array.from(s.querySelectorAll("[data-filter-tag]")):[];E=[...l,...A],E.forEach(D=>{D.removeEventListener("keydown",m),D.addEventListener("keydown",m)})}function x(l){if(!u.length&&["ArrowDown","ArrowUp","Enter"].includes(l.key))return!1;switch(l.key){case"ArrowDown":return l.preventDefault(),L(1),!0;case"ArrowUp":return l.preventDefault(),L(-1),!0;case"Enter":return i>=0?(l.preventDefault(),re(),!0):!1;case"Escape":return l.preventDefault(),ae(),!0;default:return!1}}function L(l){if(!u.length)return;let A=i===-1?l>0?0:u.length-1:(i+l+u.length)%u.length;a(A)}function a(l){if(!(l<-1||l>=u.length)&&i!==l)if(i>=0&&u[i]&&u[i].classList.remove("is-active"),i=l,i>=0){let A=u[i];if(!A)return;A.classList.add("is-active");let D=b(A);t.setAttribute("aria-activedescendant",D);let R=ie(A);$(c,`Result ${i+1} of ${u.length}: ${R}`),A.scrollIntoView({block:"nearest"})}else t.removeAttribute("aria-activedescendant"),$(c,"Search results selection cleared.")}function S(l=!0){i>=0&&u[i]&&u[i].classList.remove("is-active"),i=-1,t.removeAttribute("aria-activedescendant"),l&&$(c,"Search results selection cleared.")}function b(l){if(l.id)return l.id;d+=1;let A=`${me}${d}`;return l.id=A,A}function I(){u=Array.from(o.querySelectorAll(".search-result")),u.forEach(l=>{b(l),l.setAttribute("role","option"),l.setAttribute("tabindex","-1")}),i>=u.length&&S(!1),p&&(p=!1,$(h,"Results updated.")),ne(),N()}function N(){if(!w)return;let l=t.value.trim();if(!l){$(w,"Enter a query to begin.");return}if(r&&!r.hidden&&u.length===0){$(w,`No results found for \u201C${l}\u201D.`);return}$(w,`${u.length} result${u.length===1?"":"s"} found for \u201C${l}\u201D.`)}function Q(){g&&g.setAttribute("aria-busy","true"),f&&(C&&(window.clearTimeout(C),C=null),y=Date.now(),f.hidden=!1,f.removeAttribute("hidden"))}function ne(){if(g&&g.setAttribute("aria-busy","false"),f){let l=()=>{f.hidden=!0,f.setAttribute("hidden",""),C=null,y=0},A=y?Date.now()-y:U;if(A<U){let D=U-A;C&&window.clearTimeout(C),C=window.setTimeout(l,D)}else l()}}function re(){let l=i>=0?u[i]:null;if(!l)return;let A=l.querySelector("[data-result-link]");A&&A.href&&window.location.assign(A.href)}function ae(){T.cancel(),t.value="",S(),$(h,"Search cleared."),n&&(p=!0,Q(),n.dispatchEvent(new Event("submit",{cancelable:!0})))}function ie(l){let A=l.querySelector("[data-result-link]");if(A&&A.textContent)return A.textContent.trim();let D=l.querySelector(".search-result__title");return D&&D.textContent?D.textContent.trim():"Result"}}var we=typeof process!="undefined"&&process.env&&process.env.VITEST==="true";function te(){ee(),Se()}we||(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",te):te());export{ye as debounce,Se as setupSearchEnhancements,$ as updateLiveRegion};
|
|
1
|
+
import"./chunks/chunk-225H5YXE.js";var Q="datalog-search-analytics";function j({panel:e,list:n,empty:t,onSelect:i}){if(!e||!n||!t)return{record(){},render(){}};let r=d(),f="";function d(){let u=Object.create(null);try{let c=window.localStorage.getItem(Q);if(c){let a=JSON.parse(c);a&&typeof a=="object"&&Object.entries(a).forEach(([l,S])=>{typeof S=="number"&&Number.isFinite(S)&&(u[l]=S)})}}catch(c){}return u}function m(){try{window.localStorage.setItem(Q,JSON.stringify(r))}catch(u){}}function s(u){let c=(u||"").trim();!c||c===f||(f=c,r[c]=(r[c]||0)+1,m(),p())}function p(){let u=Object.entries(r).filter(([a])=>a&&a.trim().length>1).sort((a,l)=>l[1]-a[1]).slice(0,5);if(n.replaceChildren(),u.length===0){t.hidden=!1;return}t.hidden=!0;let c=document.createDocumentFragment();u.forEach(([a,l])=>{let S=document.createElement("li"),g=document.createElement("button");g.type="button",g.className="search-analytics__query",g.textContent=`${a} (${l})`,g.addEventListener("click",()=>{typeof i=="function"&&i(a)}),S.appendChild(g),c.appendChild(S)}),n.appendChild(c)}return{record:s,render:p}}function k(e=""){let n=e==null?"":String(e);try{return n.toLowerCase().normalize("NFKD").replace(new RegExp("\\p{Diacritic}","gu"),"")}catch(t){return n.toLowerCase()}}function F(e=""){return k(e).replace(/\s+/g,"")}function P(e=""){return k(e).split(/[^\p{L}\p{N}\\._]+/u).filter(Boolean)}function H(e=""){return/\\|\^|_|\{|\}|\$/.test(e)}function B(e=""){return/`|::|->|=>|\(|\)|\{|\}|\[|\]|=|\bdef\b|\bfunction\b|\bclass\b/.test(e)}function K(e,n){if(!e||!n)return!1;let t=0;for(let i=0;i<e.length&&t<n.length;i+=1)e[i]===n[t]&&(t+=1);return t===n.length}function ae(e){return e&&new DOMParser().parseFromString(String(e),"text/html").body.textContent||""}function O(e,n,t){if(!e)return"";let i=ae(e),r=Math.max(0,n-80),f=Math.min(i.length,n+t+80);return`${i.slice(r,f)}${f<i.length?"\u2026":""}`}function ie(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var oe={"&":"&","<":"<",">":">",'"':""","'":"'"};function _(e){return String(e).replace(/[&<>"']/g,n=>oe[n])}function N(e,n){if(!e)return"";let t=String(e),i=Array.from(new Set(P(n||""))).sort((s,p)=>p.length-s.length);if(!i.length)return _(t);let r=new RegExp(i.map(ie).join("|"),"giu"),f="",d=0,m;for(;(m=r.exec(t))!==null;)f+=`${_(t.slice(d,m.index))}<mark>${_(m[0])}</mark>`,d=m.index+m[0].length;return f+_(t.slice(d))}function M(e){return(e||"").toString().split(/[-_\s]+/).map(n=>n.charAt(0).toUpperCase()+n.slice(1)).join(" ")}function X(e){switch(e){case"post":return"Tutorial & Blog";case"project":return"Project";case"research":return"Research";case"dataset":return"Dataset";default:return M(e||"Page")}}function J({panel:e,limit:n=8,onSelect:t}){if(!e)return{setSuggestions(){},update(){},close(){},handleNavigation(){}};let i=[],r=-1;function f(c){i=Array.isArray(c)?[...c]:[]}function d(c){r=-1;let a=(c||"").trim().toLowerCase();if(!a){p();return}let l=i.filter(g=>g&&g.toLowerCase().includes(a)).slice(0,n);if(l.length===0){p();return}let S=document.createDocumentFragment();l.forEach((g,C)=>{let E=document.createElement("button");E.type="button",E.className="search-autocomplete__option",E.setAttribute("role","option"),E.dataset.autocompleteOption="",E.dataset.value=g,E.setAttribute("aria-selected",C===r?"true":"false"),E.replaceChildren(),E.insertAdjacentHTML("beforeend",N(g,a)),S.appendChild(E)}),e.replaceChildren(),e.appendChild(S),e.hidden=!1}function m(c,a){if(e.hidden)return;let l=Array.from(e.querySelectorAll("[data-autocomplete-option]"));if(l.length!==0){if(c.key==="ArrowDown")c.preventDefault(),r=(r+1)%l.length,s(l);else if(c.key==="ArrowUp")c.preventDefault(),r=(r-1+l.length)%l.length,s(l);else if(c.key==="Enter"&&r>=0){c.preventDefault();let S=l[r],g=S?S.dataset.value:"";g&&a&&(a.value=g),typeof t=="function"&&t(g),u()}}}function s(c){c.forEach((a,l)=>{let S=l===r;a.setAttribute("aria-selected",S?"true":"false"),a.classList.toggle("is-active",S)})}function p(){e.replaceChildren(),e.hidden=!0,r=-1}function u(){p()}return e.addEventListener("click",c=>{let a=c.target.closest("[data-autocomplete-option]");if(!a)return;let l=a.dataset.value||"";l&&typeof t=="function"&&t(l),u()}),{setSuggestions:f,update:d,close:u,handleNavigation:m}}function W(e=[]){let n=Array.isArray(e)?[...e]:[];function t(d){n=Array.isArray(d)?[...d]:[]}function i(d,m={}){let s=(d||"").trim();if(!s)return[];let p=k(s),u=P(s),c=H(s),a=B(s),{type:l="",language:S="",difficulty:g="",tags:C=new Set}=m;return n.map(E=>ce(E,{rawQuery:s,normalizedQuery:p,queryTokens:u,mathQuery:c,codeQuery:a,typeFilter:l,languageFilter:S,difficultyFilter:g,selectedTags:C})).filter(E=>E&&E.score>0).sort((E,T)=>T.score-E.score||E.title.localeCompare(T.title))}function r(d=150){return se(n,d)}function f(){return[...n]}return{setDocuments:t,search:i,suggestions:r,getDocuments:f}}function se(e=[],n=150){let t=new Set;return e.forEach(i=>{i.title&&t.add(i.title),Array.isArray(i.languages)&&i.languages.forEach(r=>t.add(r)),Array.isArray(i.tags)&&i.tags.forEach(r=>t.add(`#${r}`)),Array.isArray(i.math)&&i.math.slice(0,3).forEach(r=>t.add(r))}),Array.from(t).slice(0,n)}function ce(e,n){let{rawQuery:t,normalizedQuery:i,queryTokens:r,mathQuery:f,codeQuery:d,typeFilter:m,languageFilter:s,difficultyFilter:p,selectedTags:u}=n;if(m&&e.type!==m)return null;let c=Array.isArray(e.languages)?e.languages:[];if(s&&!c.includes(s))return null;if(p){let y=String(e.difficulty||"").toLowerCase();if(!y||y!==p)return null}if(u&&u.size>0){let y=new Set(G(e).tags);for(let o of u)if(!y.has(o))return null}if(!t)return null;let{title:a,summary:l,content:S,tags:g,languages:C,difficulty:E}=G(e),T=Array.isArray(e.code)?e.code:[],q=Array.isArray(e.math)?e.math:[],x=0,w="",D=null,A=null;if(a.includes(i)&&(x+=40),r.forEach(y=>{y&&(a.includes(y)&&(x+=12),l.includes(y)&&(x+=8),S.includes(y)&&(x+=6),g.forEach(o=>{o.includes(y)&&(x+=4)}),C.forEach(o=>{o.includes(y)&&(x+=4)}),E.includes(y)&&(x+=2))}),T.length>0){let y=F(t);for(let o of T){let b=String(o.language||"").toLowerCase(),v=o.code||"",z=F(v);if(z.includes(y)){x+=30,D={language:b,code:v};break}if(d&&K(z,y)){x+=18,D={language:b,code:v};break}}!D&&T[0]&&(D={language:String(T[0].language||"").toLowerCase(),code:T[0].code||""})}if(q.length>0){let y=i.replace(/\\/g,"");for(let o of q)if(k(String(o)).includes(y)){x+=26,A=o;break}f&&!A&&q[0]&&(A=q[0],x+=10)}if(S.includes(i)){let y=S.indexOf(i);w=O(e.content||"",y,t.length),x+=10}else if(l.includes(i)){let y=l.indexOf(i);w=O(e.summary||"",y,t.length),x+=6}return x===0?null:{id:`${e.url}`,title:e.title,url:e.url,summary:e.summary,snippet:w,codeSnippet:D,mathSnippet:A,tags:e.tags||[],languages:e.languages||[],difficulty:e.difficulty||"",type:e.type||"page",date:e.date,readingTime:e.reading_time,score:x}}var Y=new WeakMap;function G(e){let n=Y.get(e);if(n)return n;let t=e.normalized||{},i={title:t.title||k(e.title||""),summary:t.summary||k(e.summary||""),content:t.content||k(e.content||""),tags:V(t.tags,e.tags),languages:V(t.languages,e.languages),difficulty:t.difficulty||k(e.difficulty||"")};return Y.set(e,i),i}function V(e,n){return Array.isArray(e)&&e.length>0?e:Array.isArray(n)?n.map(t=>k(t)):[]}function Z(e,n,t){if(!e)return;let i=new Set;n.forEach(d=>{(d.tags||d.topics||[]).forEach(s=>{if(!s)return;let p=String(s).trim().toLowerCase();p&&i.add(p)})});let r=Array.from(i).sort();if(r.length===0){let d=document.createElement("p");d.className="search-filter__empty",d.textContent="No tags available yet.",e.replaceChildren(d);return}let f=document.createDocumentFragment();r.forEach(d=>{let m=document.createElement("button");m.type="button",m.className="search-filter__tag",m.textContent=d,m.dataset.filterTag=d,m.setAttribute("aria-pressed",t.has(d)?"true":"false"),f.appendChild(m)}),e.replaceChildren(),e.appendChild(f)}function ee(e,n,t){let{resultsList:i,resultsMeta:r,emptyState:f,template:d}=t;if(!i||!r||!f||!d)return;if(i.replaceChildren(),!n){r.textContent="Enter a query to begin.",f.hidden=!0;return}if(e.length===0){r.textContent=`No matches for \u201C${n}\u201D.`,f.hidden=!1;return}f.hidden=!0,r.textContent=`${e.length} result${e.length===1?"":"s"} for \u201C${n}\u201D.`;let m=document.createDocumentFragment();e.forEach(s=>{let p=d.content.cloneNode(!0),u=p.querySelector("[data-result-type]"),c=p.querySelector("[data-result-difficulty]"),a=p.querySelector("[data-result-languages]"),l=p.querySelector("[data-result-link]"),S=p.querySelector("[data-result-summary]"),g=p.querySelector("[data-result-code]"),C=g?g.querySelector("code"):null,E=p.querySelector("[data-result-math]"),T=p.querySelector("[data-result-math-preview]"),q=p.querySelector("[data-result-math-code]"),x=p.querySelector("[data-result-math-copy]"),w=p.querySelector("[data-result-excerpt]"),D=p.querySelector("[data-result-tags]"),A=p.querySelector("[data-result-date]");if(u&&(u.textContent=X(s.type)),c&&(s.difficulty?(c.textContent=`Difficulty: ${M(s.difficulty)}`,c.hidden=!1):c.hidden=!0),a&&(s.languages&&s.languages.length>0?(a.textContent=`Languages: ${s.languages.map(y=>M(y)).join(", ")}`,a.hidden=!1):a.hidden=!0),l&&(l.textContent=s.title||s.url,l.setAttribute("href",s.url)),S&&(S.replaceChildren(),S.insertAdjacentHTML("beforeend",N(s.summary||"",n))),E&&q&&(s.mathSnippet?(E.hidden=!1,q.textContent=s.mathSnippet,T&&(window.DatalogMath&&typeof window.DatalogMath.renderLatex=="function"?window.DatalogMath.renderLatex(T,s.mathSnippet,{display:!1,enhance:!1}):window.MathJax&&typeof window.MathJax.typesetPromise=="function"?(T.textContent=`\\(${s.mathSnippet}\\)`,window.MathJax.typesetPromise([T]).catch(()=>{T.textContent=s.mathSnippet})):T.textContent=s.mathSnippet),x&&x.addEventListener("click",()=>le(s.mathSnippet,E))):E.hidden=!0),w&&(s.snippet?(w.replaceChildren(),w.insertAdjacentHTML("beforeend",N(s.snippet,n)),w.hidden=!1):w.hidden=!0),g&&C)if(s.codeSnippet&&s.codeSnippet.code){let y=s.codeSnippet.language||"text";g.classList.remove("language-none"),g.classList.add(`language-${y}`),C.className=`language-${y}`,C.textContent=s.codeSnippet.code,g.hidden=!1}else g.hidden=!0;if(D&&(D.replaceChildren(),(s.tags||[]).forEach(y=>{let o=document.createElement("li");o.textContent=`#${y}`,D.appendChild(o)})),A)if(s.date){let y=new Date(s.date);Number.isNaN(y.getTime())?A.hidden=!0:(A.textContent=y.toLocaleDateString(void 0,{year:"numeric",month:"short",day:"numeric"}),A.hidden=!1)}else A.hidden=!0;m.appendChild(p)}),i.appendChild(m)}function le(e,n){if(!e)return;let t=()=>{if(!n)return;let r=n.querySelector("[data-result-math-copy]"),f=r?r.querySelector(".visually-hidden"):null;if(r&&f){let d=r.getAttribute("data-sr-original")||f.textContent;r.getAttribute("data-sr-original")||r.setAttribute("data-sr-original",d||"Copy LaTeX"),f.textContent="Copied LaTeX",r.classList.add("is-copied"),window.setTimeout(()=>{f.textContent=r.getAttribute("data-sr-original")||"Copy LaTeX",r.classList.remove("is-copied")},2e3)}},i=()=>{let r=document.createElement("textarea");r.value=e,r.setAttribute("aria-hidden","true"),r.style.position="fixed",r.style.opacity="0",document.body.appendChild(r),r.select();try{document.execCommand("copy"),t()}catch(f){}document.body.removeChild(r)};navigator.clipboard&&navigator.clipboard.writeText?navigator.clipboard.writeText(e).then(()=>t()).catch(()=>i()):i()}var ue=8;function te(){let e=document.querySelector("[data-search-app]");if(!e)return;let n=e.querySelector("[data-search-form]"),t=e.querySelector("[data-search-input]"),i=e.querySelector("[data-search-results]"),r=e.querySelector("[data-search-meta]"),f=e.querySelector("[data-search-empty]"),d=e.querySelector("[data-search-autocomplete]"),m=e.querySelector("[data-search-analytics]"),s=m?m.querySelector(".search-app__analytics-list"):null,p=m?m.querySelector(".search-app__analytics-empty"):null,u=document.getElementById("search-result-template"),c=e.querySelector("[data-filter-type]"),a=e.querySelector("[data-filter-language]"),l=e.querySelector("[data-filter-difficulty]"),S=e.querySelector("[data-filter-tags]"),g=e.getAttribute("data-search-index")||"/search.json",C=new Set,E=W(),T=j({panel:m,list:s,empty:p,onSelect:o=>{t&&(t.value=o,A())}}),q=J({panel:d,limit:ue,onSelect:o=>{o&&t&&(t.value=o,t.focus(),A())}}),x=!1,w=new URLSearchParams(window.location.search);t&&w.has("q")&&(t.value=w.get("q")||""),c&&w.has("type")&&(c.value=w.get("type")),a&&w.has("language")&&(a.value=w.get("language")),l&&w.has("difficulty")&&(l.value=w.get("difficulty")),w.has("tags")&&w.get("tags").split(",").map(o=>o.trim().toLowerCase()).filter(Boolean).forEach(o=>C.add(o)),fe(t,()=>{q.close(),A()}),de(g).then(o=>{let b=o.documents||[];E.setDocuments(b),q.setSuggestions(E.suggestions()),Z(S,b,C),x=!0,D()}).catch(o=>{r&&(r.textContent="Unable to load the search index. Please try again later.")}),n&&n.addEventListener("submit",o=>{o.preventDefault(),A()}),t&&(t.addEventListener("input",()=>{q.update(t.value)}),t.addEventListener("keydown",o=>{q.handleNavigation(o,t)}),t.addEventListener("focus",()=>{q.update(t.value)})),c&&c.addEventListener("change",A),a&&a.addEventListener("change",A),l&&l.addEventListener("change",A),e.addEventListener("click",o=>{let b=o.target;if(b.matches("[data-filter-tag]")){let v=b.getAttribute("data-filter-tag");v&&(C.has(v)?(C.delete(v),b.setAttribute("aria-pressed","false")):(C.add(v),b.setAttribute("aria-pressed","true")),A())}}),document.addEventListener("click",o=>{!d||d.hidden||e.contains(o.target)||q.close()}),document.addEventListener("keydown",o=>{let b=document.activeElement?document.activeElement.tagName:"";["INPUT","TEXTAREA"].includes(b)||(o.key==="/"&&!o.ctrlKey&&!o.metaKey&&!o.altKey||(o.key==="k"||o.key==="K")&&(o.ctrlKey||o.metaKey))&&(o.preventDefault(),t&&(t.focus(),t.select()))}),T.render();function D(){t&&t.value.trim()?A():y()}function A(){if(!t)return;if(!x){r&&(r.textContent="Loading technical index\u2026");return}let o=t.value.trim(),b={type:c?c.value:"",language:a?a.value:"",difficulty:l?l.value:"",tags:C},v=E.search(o,b);ee(v,o,{resultsList:i,resultsMeta:r,emptyState:f,template:u}),y(o),T.record(o)}function y(o){let b=new URL(window.location.href),v=b.searchParams;o?v.set("q",o):v.delete("q"),c&&c.value?v.set("type",c.value):v.delete("type"),a&&a.value?v.set("language",a.value):v.delete("language"),l&&l.value?v.set("difficulty",l.value):v.delete("difficulty"),C.size>0?v.set("tags",Array.from(C).join(",")):v.delete("tags");let z=v.toString(),R=z?`${b.pathname}?${z}`:b.pathname;window.history.replaceState({},"",R)}}function de(e){return fetch(e,{credentials:"same-origin"}).then(n=>{if(!n.ok)throw new Error(`HTTP ${n.status}`);return n.json()})}function fe(e,n){e&&e.addEventListener("keydown",t=>{t.key==="Escape"&&(e.value="",typeof n=="function"&&n())})}var pe=300,ge="search-result-",U=500;function he(e,n=pe){let t,i=(...r)=>{t&&window.clearTimeout(t),t=window.setTimeout(()=>{t=void 0,e.apply(null,r)},n)};return i.cancel=()=>{t&&(window.clearTimeout(t),t=void 0)},i}function $(e,n){if(!e)return;let t=String(n||"");e.textContent===t?e.textContent=`${t}\xA0`:e.textContent=t,t.trim()?e.removeAttribute("hidden"):e.setAttribute("hidden","")}function me(){let e=document.querySelector("[data-search-app]");if(!e)return;let n=e.querySelector("[data-search-form]"),t=e.querySelector("[data-search-input]"),i=e.querySelector("[data-search-results]"),r=e.querySelector("[data-search-empty]"),f=e.querySelector("[data-search-loading]"),d=e.querySelector("[data-search-region]"),m=e.querySelector('[data-search-live="count"]'),s=e.querySelector('[data-search-live="selection"]'),p=e.querySelector('[data-search-live="status"]');if(!t||!i)return;let u=-1,c=0,a=[],l=!1,S=0,g=null,C=he(()=>{n&&(l=!0,o(),$(p,"Loading results\u2026"),n.dispatchEvent(new Event("submit",{cancelable:!0})))});new MutationObserver(()=>{A()}).observe(i,{childList:!0}),A(),t.addEventListener("input",()=>{w(!1),C()}),t.addEventListener("keydown",T);function T(h){if(!a.length&&["ArrowDown","ArrowUp","Enter"].includes(h.key))return!1;switch(h.key){case"ArrowDown":return h.preventDefault(),q(1),!0;case"ArrowUp":return h.preventDefault(),q(-1),!0;case"Enter":return u>=0?(h.preventDefault(),v(),!0):!1;case"Escape":return h.preventDefault(),z(),!0;default:return!1}}function q(h){if(!a.length)return;let L=u===-1?h>0?0:a.length-1:(u+h+a.length)%a.length;x(L)}function x(h){if(!(h<-1||h>=a.length)&&u!==h)if(u>=0&&a[u]&&a[u].classList.remove("is-active"),u=h,u>=0){let L=a[u];if(!L)return;L.classList.add("is-active");let I=D(L);t.setAttribute("aria-activedescendant",I);let re=R(L);$(s,`Result ${u+1} of ${a.length}: ${re}`),L.scrollIntoView({block:"nearest"})}else t.removeAttribute("aria-activedescendant"),$(s,"Search results selection cleared.")}function w(h=!0){u>=0&&a[u]&&a[u].classList.remove("is-active"),u=-1,t.removeAttribute("aria-activedescendant"),h&&$(s,"Search results selection cleared.")}function D(h){if(h.id)return h.id;c+=1;let L=`${ge}${c}`;return h.id=L,L}function A(){a=Array.from(i.querySelectorAll(".search-result")),a.forEach(h=>{D(h),h.setAttribute("role","option"),h.setAttribute("tabindex","-1")}),u>=a.length&&w(!1),l&&(l=!1,$(p,"Results updated.")),b(),y()}function y(){if(!m)return;let h=t.value.trim();if(!h){$(m,"Enter a query to begin.");return}if(r&&!r.hidden&&a.length===0){$(m,`No results found for \u201C${h}\u201D.`);return}$(m,`${a.length} result${a.length===1?"":"s"} found for \u201C${h}\u201D.`)}function o(){d&&d.setAttribute("aria-busy","true"),f&&(g&&(window.clearTimeout(g),g=null),S=Date.now(),f.hidden=!1,f.removeAttribute("hidden"))}function b(){if(d&&d.setAttribute("aria-busy","false"),f){let h=()=>{f.hidden=!0,f.setAttribute("hidden",""),g=null,S=0},L=S?Date.now()-S:U;if(L<U){let I=U-L;g&&window.clearTimeout(g),g=window.setTimeout(h,I)}else h()}}function v(){let h=u>=0?a[u]:null;if(!h)return;let L=h.querySelector("[data-result-link]");L&&L.href&&window.location.assign(L.href)}function z(){C.cancel(),t.value="",w(),$(p,"Search cleared."),n&&(l=!0,o(),n.dispatchEvent(new Event("submit",{cancelable:!0})))}function R(h){let L=h.querySelector("[data-result-link]");if(L&&L.textContent)return L.textContent.trim();let I=h.querySelector(".search-result__title");return I&&I.textContent?I.textContent.trim():"Result"}}var ye=typeof process!="undefined"&&process.env&&process.env.VITEST==="true";function ne(){te(),me()}ye||(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",ne):ne());export{he as debounce,me as setupSearchEnhancements,$ as updateLiveRegion};
|
|
@@ -1,2 +1,11 @@
|
|
|
1
|
-
(function(){let
|
|
2
|
-
|
|
1
|
+
(function(){let Z=typeof process!="undefined"&&process.env&&process.env.VITEST==="true",_="[data-viz-type]",I='script[type="application/json"]',F='script[type="application/vnd.jupyter.widget-state+json"]',K='script[type="application/vnd.jupyter.widget-view+json"]',q=new Map,L=new Set,k="viz-table-fallback-template",z=(t,e={})=>{if(!t)return Promise.reject(new Error("Missing script source"));if(q.has(t))return q.get(t);let r=new Promise((n,s)=>{let o=document.createElement("script");o.src=t,o.async=e.async!==!1,e.integrity&&(o.integrity=e.integrity,o.crossOrigin=e.crossOrigin||"anonymous"),o.onload=()=>n(o),o.onerror=a=>s(a),document.head.appendChild(o)});return q.set(t,r),r},Q=t=>!t||L.has(t)?Promise.resolve():new Promise((e,r)=>{let n=document.createElement("link");n.rel="stylesheet",n.href=t,n.onload=()=>{L.add(t),e(n)},n.onerror=s=>r(s),document.head.appendChild(n)}),b=t=>Object.prototype.toString.call(t)==="[object Object]",y=t=>t===null||typeof t=="undefined"?"":t instanceof Date?t.toISOString():Array.isArray(t)?t.map(e=>y(e)).join(", "):b(t)?Object.entries(t).map(([e,r])=>`${e}: ${y(r)}`).join("; "):typeof t=="boolean"?t?"Yes":"No":typeof t=="number"?Number.isFinite(t)?`${t}`:"":String(t),T=(t,e=[])=>b(t)?Object.entries(t).reduce((r,[n,s])=>{let o=e.concat([n]);return b(s)?Object.assign(r,T(s,o)):Array.isArray(s)?r[o.join(" \u203A ")]=s.map(a=>y(a)).join(", "):r[o.join(" \u203A ")]=s,r},{}):{[e.join(" \u203A ")||"Value"]:t},m=t=>{if(!t)return[];if(Array.isArray(t)){if(!t.length)return[];if(t.every(e=>b(e)))return t.map(e=>T(e));if(Array.isArray(t[0])){let e=t[0],r=e.every(o=>typeof o=="string"||typeof o=="number"),n=e.map((o,a)=>r?y(o):`Column ${a+1}`),s=r?1:0;return t.slice(s).map((o,a)=>{let c={};return Array.isArray(o)?(n.forEach((i,l)=>{c[i]=o[l]}),n.length||o.forEach((i,l)=>{c[`Column ${l+1}`]=i})):c[`Row ${a+1}`]=o,c})}return t.map((e,r)=>({Index:r+1,Value:e}))}return b(t)?Array.isArray(t.data)?m(t.data):Array.isArray(t.values)?m(t.values):Array.isArray(t.rows)?m(t.rows):[T(t)]:[{Value:t}]},tt=t=>{let e=["Series","Trace","Group","Category","Index","X","Y","Z","Value","Text"],r=[];return e.forEach(n=>{t.includes(n)&&r.push(n)}),t.filter(n=>!e.includes(n)).sort().forEach(n=>r.push(n)),r},et=t=>{let e=t.getAttribute("data-viz-title");if(e)return e;let r=t.querySelector(".viz-title");return r&&r.textContent?r.textContent.trim():t.getAttribute("data-viz-slug")||"Visualization data"},rt=()=>{let t=document.getElementById(k);if(t)return t;t=document.createElement("template"),t.id=k;let e=document.createElement("div");return e.insertAdjacentHTML("afterbegin",'<div class="viz-table-container" data-viz-table-container><button type="button" class="viz-table-toggle" data-viz-table-toggle aria-expanded="false">Show data table</button><div class="viz-table-wrapper" data-viz-table-wrapper hidden><table class="viz-table" data-viz-table><caption data-viz-table-caption></caption><thead data-viz-table-head></thead><tbody data-viz-table-body></tbody></table></div></div>'),t.content.appendChild(e.firstElementChild),document.body.appendChild(t),t},E=(t,e={})=>{let{caption:r,rows:n}=e,s=m(n);if(!s.length)return;let o=Array.from(s.reduce((p,f)=>(Object.keys(f).forEach(O=>p.add(O)),p),new Set));if(!o.length)return;let a=tt(o),i=rt().content.firstElementChild.cloneNode(!0),l=i.querySelector("[data-viz-table-toggle]"),u=i.querySelector("[data-viz-table-wrapper]"),H=i.querySelector("[data-viz-table]"),w=i.querySelector("[data-viz-table-caption]"),h=i.querySelector("[data-viz-table-head]"),S=i.querySelector("[data-viz-table-body]"),A=`${t.getAttribute("data-viz-slug")||t.id||"viz"}-table`;H.id=A,l.setAttribute("aria-controls",A),w.textContent=r||et(t);let x=document.createElement("tr");a.forEach(p=>{let f=document.createElement("th");f.scope="col",f.textContent=p,x.appendChild(f)}),h.appendChild(x),s.forEach(p=>{let f=document.createElement("tr");a.forEach((O,yt)=>{let X=y(p[O]);if(yt===0){let v=document.createElement("th");v.scope="row",v.textContent=X,f.appendChild(v)}else{let v=document.createElement("td");v.textContent=X,f.appendChild(v)}}),S.appendChild(f)}),l.addEventListener("click",()=>{let p=l.getAttribute("aria-expanded")==="true";l.setAttribute("aria-expanded",String(!p)),l.textContent=p?"Show data table":"Hide data table",p?u.setAttribute("hidden",""):u.removeAttribute("hidden")});let Y=t.querySelector("[data-viz-table-container]");Y&&Y.remove(),t.appendChild(i),(t.querySelector("[data-viz-canvas]")||t).setAttribute("aria-describedby",A)},N=(t=[])=>{let e=[];return t.forEach((r,n)=>{let s=r.name||`Series ${n+1}`,o=Array.isArray(r.x)?r.x:[],a=Array.isArray(r.y)?r.y:[],c=Array.isArray(r.text)?r.text:[],i=r.z;if(Array.isArray(i)&&i.length&&Array.isArray(i[0])){let u=o.length?o:i[0].map((w,h)=>h+1);(a.length?a:i.map((w,h)=>h+1)).forEach((w,h)=>{let S=i[h]||[];u.forEach((A,x)=>{e.push({Series:s,Y:w,X:A,Value:Array.isArray(S)?S[x]:S,Text:c[h]?y(c[h]):""})})});return}let l=Math.max(o.length,a.length,c.length);for(let u=0;u<l;u+=1)e.push({Series:s,X:o[u],Y:a[u],Text:c[u]})}),e.length?e:null},M=t=>t?Array.isArray(t)?t:b(t)&&Array.isArray(t.data)?t.data:t:null,V=t=>{let e=t.querySelector("script[data-observable-data]");if(!e)return null;try{return JSON.parse(e.textContent||"null")}catch(r){return null}},g=null,j=new Set,C=(t,e)=>{if(typeof window[e]!="undefined")return Promise.resolve(window[e]);let r=()=>z(t).then(()=>window[e]);if(g)return g.then(o=>new Promise((a,c)=>{o([t],i=>a(i||window[e]),c)}),r);let n=r();j.add(n);let s=()=>j.delete(n);return n.then(s,s),n},D=()=>C("https://cdn.jsdelivr.net/npm/plotly.js-dist-min@2.27.0/plotly.min.js","Plotly"),nt=()=>C("https://cdn.jsdelivr.net/npm/d3@7/dist/d3.min.js","d3"),ot=()=>C("https://cdn.jsdelivr.net/npm/@bokeh/bokehjs@3.3.3/build/js/bokeh.min.js","Bokeh").then(t=>t&&t.Plotting?t:z("https://cdn.jsdelivr.net/npm/@bokeh/bokehjs@3.3.3/build/js/bokeh-api.min.js").then(()=>window.Bokeh)),R=()=>(g||(g=Promise.allSettled([...j]).then(()=>typeof window.requirejs!="undefined"?window.requirejs:z("https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js",{async:!1}).then(()=>window.requirejs))),g),st=()=>R().then(t=>{let e=window.__datalogWidgetManagerPromise;if(e)return e;let r=new Promise((n,s)=>{t.config({paths:{"@jupyter-widgets/html-manager":"https://cdn.jsdelivr.net/npm/@jupyter-widgets/html-manager@1.0.8/dist/embed-amd","@jupyter-widgets/base":"https://cdn.jsdelivr.net/npm/@jupyter-widgets/base@6.0.7/dist/index","@jupyter-widgets/controls":"https://cdn.jsdelivr.net/npm/@jupyter-widgets/controls@5.0.7/dist/index","@lumino/coreutils":"https://cdn.jsdelivr.net/npm/@lumino/coreutils@2.1.1/dist/index","@lumino/widgets":"https://cdn.jsdelivr.net/npm/@lumino/widgets@2.3.1/dist/index"}}),t(["@jupyter-widgets/html-manager"],o=>n(o),o=>s(o))});return window.__datalogWidgetManagerPromise=r,r}),at=(t,e)=>{let r=document.createElement("button");return r.type="button",r.className="viz-toolbar__button",r.textContent=t,r.addEventListener("click",n=>{n.preventDefault(),e(n)}),r},d=(t,e,r="info")=>{let n=t.querySelector("[data-viz-status]");n&&(n.textContent=e,n.dataset.tone=r)},$=t=>{let e=t.getAttribute("data-viz-version"),r=t.getAttribute("data-viz-updated"),n=t.querySelector("[data-viz-meta]");if(!n)return;let s=[];e&&s.push(`v${e}`),r&&s.push(`Updated ${r}`),n.textContent=s.join(" \xB7 ")},it=t=>{let e=t.querySelector("[data-viz-canvas]")||t,r=t.querySelector(I);if(!r)return d(t,"Missing Plotly specification","error"),Promise.resolve();let n={};try{n=JSON.parse(r.textContent||"{}")}catch(a){return d(t,"Invalid Plotly specification","error"),Promise.resolve()}let s=Array.isArray(n.data)?n.data:[],o=Object.assign({autosize:!0},n.layout||{});return D().then(a=>a.newPlot(e,s,o,{responsive:!0,displaylogo:!1})).then(()=>{d(t,"Interactive");let a=t.querySelector("[data-viz-export]");a&&(a.replaceChildren(),a.appendChild(at("Download PNG",()=>{D().then(i=>{i.downloadImage(e,{format:"png",filename:t.getAttribute("data-viz-slug")||"visualization"})})})));let c=N(s);c&&E(t,{caption:o&&o.title?y(o.title.text||o.title):void 0,rows:c})}).catch(()=>{d(t,"Plotly failed to load","error")})},B=(t,e,r,n)=>{let s={args:n,done:!1,error:null,result:void 0},o=document.createElement("script"),a=t.nonce||t.getAttribute("nonce");a&&(o.nonce=a),o.datalogRun=s,o.textContent=`(function (run) {
|
|
2
|
+
try {
|
|
3
|
+
run.result = (function (${e.join(", ")}) {
|
|
4
|
+
${r}
|
|
5
|
+
}).apply(null, run.args);
|
|
6
|
+
run.done = true;
|
|
7
|
+
} catch (error) {
|
|
8
|
+
run.error = error;
|
|
9
|
+
}
|
|
10
|
+
})(document.currentScript.datalogRun);`;try{document.head.appendChild(o)}finally{o.remove()}if(s.error)throw s.error;if(!s.done)throw new Error("The Content Security Policy did not allow the visualization script to run");return s.result},ct=t=>{let e=t.querySelector("[data-d3-script]");return e?nt().then(r=>{let n=e.textContent||"",s=t.querySelector("[data-viz-canvas]")||t;s.replaceChildren();let o=[],a=c=>{typeof c!="undefined"&&o.push(c)};try{let c=`${n}
|
|
11
|
+
;try { if (typeof data !== 'undefined') captureData(data); } catch (instrumentationError) {}`,i=B(e,["d3","element","captureData"],c,[r,s,a]);typeof i!="undefined"&&a(i);let l=o.length?o[o.length-1]:null,u=M(l);u&&E(t,{rows:u}),d(t,"Interactive")}catch(c){s.replaceChildren(),d(t,"D3 rendering error","error")}}).catch(()=>d(t,"D3 assets failed to load","error")):(d(t,"Missing D3 rendering instructions","error"),Promise.resolve())},dt=t=>{try{let e=new URL(t,"https://observablehq.com");if(e.origin!=="https://observablehq.com")return null;let r=Array.from(e.searchParams,([n,s])=>`${encodeURIComponent(n)}=${encodeURIComponent(s)}`).join("&");return"https://observablehq.com"+e.pathname+(r?"?"+r:"")}catch(e){return null}},lt=t=>{let e=t.getAttribute("data-observable-src")||t.getAttribute("data-viz-src");if(!e)return d(t,"Missing Observable notebook source","error"),Promise.resolve();let r=dt(e);if(!r)return d(t,"Observable embeds must come from observablehq.com","error"),Promise.resolve();let n=document.createElement("iframe");n.src=r,n.loading="lazy",n.title=t.getAttribute("data-viz-title")||"Observable visualization",n.setAttribute("allowfullscreen",""),n.setAttribute("sandbox","allow-scripts allow-same-origin allow-popups allow-forms"),n.className="viz-embed",(t.querySelector("[data-viz-canvas]")||t).replaceChildren(n),d(t,"Embedded");let o=V(t);return o&&E(t,{rows:o}),Promise.resolve()},ut=t=>{let e=t.querySelector(I),r=t.querySelector("[data-bokeh-script]"),n=t.querySelector("[data-viz-canvas]")||t;return!e&&!r?(d(t,"Missing Bokeh specification","error"),Promise.resolve()):ot().then(s=>{if(e){let o={};try{o=JSON.parse(e.textContent||"{}")}catch(c){d(t,"Invalid Bokeh specification","error");return}let a=n.id||`bokeh-${Math.random().toString(36).slice(2)}`;n.id=a;try{s.embed.embed_item(o,a),d(t,"Interactive")}catch(c){d(t,"Bokeh rendering error","error")}return}if(r){let o=r.textContent||"";n.replaceChildren();try{B(r,["Bokeh","element"],o,[s,n]),d(t,"Interactive")}catch(a){d(t,"Bokeh rendering error","error")}}}).catch(s=>{d(t,"Bokeh assets failed to load","error")})},pt=t=>{let e=t.getAttribute("data-shiny-src");if(!e)return d(t,"Missing Shiny application source","error"),Promise.resolve();let r=document.createElement("iframe");r.src=e,r.loading="lazy",r.title=t.getAttribute("data-viz-title")||"R Shiny application",r.className="viz-embed",r.setAttribute("allow","fullscreen"),r.setAttribute("sandbox","allow-scripts allow-forms allow-same-origin");let n=t.getAttribute("data-shiny-height");return r.style.height=n||"640px",(t.querySelector("[data-viz-canvas]")||t).replaceChildren(r),d(t,"Embedded"),Promise.resolve()},ht=t=>{let e=t.querySelector(F),r=t.querySelector(K);if(!e||!r)return d(t,"Missing widget state payload","error"),Promise.resolve();let n,s;try{n=JSON.parse(e.textContent||"{}"),s=JSON.parse(r.textContent||"{}")}catch(a){return d(t,"Invalid widget payload","error"),Promise.resolve()}let o=t.querySelector("[data-viz-canvas]")||t;return o.replaceChildren(),st().then(a=>{let c=new a.HTMLManager({loader:a.requireLoader});return c.set_state(n).then(()=>c.get_model(s.model_id)).then(i=>c.create_view(i)).then(i=>c.display_view(i,o)).then(()=>d(t,"Interactive")).catch(i=>{d(t,"Widget rendering error","error")})}).catch(a=>{d(t,"Widget assets failed to load","error")})},P=t=>{let e=t.getAttribute("data-viz-type");switch($(t),e){case"plotly":return it(t);case"observable":return lt(t);case"d3":return ct(t);case"bokeh":return ut(t);case"shiny":return pt(t);case"ipywidgets":return ht(t);default:return d(t,"Unsupported visualization type","error"),Promise.resolve()}},W=()=>{if(!("IntersectionObserver"in window)){document.querySelectorAll(_).forEach(e=>{P(e)});return}let t=new IntersectionObserver((e,r)=>{e.filter(n=>n.isIntersecting).forEach(n=>{let s=n.target;r.unobserve(s),P(s)})},{rootMargin:"200px 0px"});document.querySelectorAll(_).forEach(e=>{t.observe(e)})},U=t=>{document.querySelectorAll("[data-viz-card]").forEach(r=>{let n=!t.tech||r.dataset.vizTech===t.tech,s=(r.dataset.vizTags||"").split(",").map(a=>a.trim()).filter(Boolean),o=!t.tag||s.includes(t.tag);r.hidden=!(n&&o)})},G=()=>{let t=document.querySelector("[data-viz-gallery]");if(!t)return;let e=t.querySelector('[data-viz-filter="tech"]'),r=t.querySelector('[data-viz-filter="tag"]'),n=()=>{U({tech:e&&e.value!=="all"?e.value:"",tag:r&&r.value!=="all"?r.value:""})};e&&e.addEventListener("change",n),r&&r.addEventListener("change",n),n()},J=()=>{W(),G()},ft={loadScript:z,loadStyle:Q,loadUmd:C,ensureRequire:R,resetRequireLoading:()=>{g=null,j.clear()},normalizeRecords:m,stringifyValue:y,buildDataTable:E,annotateVersionMetadata:$,buildPlotlyRecords:N,buildD3Records:M,buildObservableRecords:V,filterGallery:U,renderVisualization:P,initializeVisualizations:W,initializeGallery:G};typeof globalThis!="undefined"&&(globalThis.__DATALOG_VIZ_INTERNALS__=ft),Z||(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",J):J())})();
|
data/assets/js/loader.js
CHANGED
|
@@ -61,7 +61,9 @@ async function importModule(url) {
|
|
|
61
61
|
const FEATURE_CONFIG = [
|
|
62
62
|
{
|
|
63
63
|
name: "search",
|
|
64
|
-
|
|
64
|
+
// Only the search page renders the app. The header's search form is a
|
|
65
|
+
// plain form on every page, and matching it loaded the bundle everywhere.
|
|
66
|
+
test: () => document.querySelector("[data-search-app]")
|
|
65
67
|
},
|
|
66
68
|
{
|
|
67
69
|
name: "visualizations",
|
data/datalog-theme.gemspec
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative "lib/datalog/theme/version"
|
|
4
|
+
require_relative "lib/datalog/theme/package"
|
|
4
5
|
|
|
5
6
|
Gem::Specification.new do |spec|
|
|
6
7
|
spec.name = "datalog-theme"
|
|
@@ -23,7 +24,9 @@ Gem::Specification.new do |spec|
|
|
|
23
24
|
spec.metadata["plugin_type"] = "theme"
|
|
24
25
|
spec.metadata["orcid"] = "https://orcid.org/0009-0001-2022-7072"
|
|
25
26
|
|
|
26
|
-
|
|
27
|
+
# The sass-embedded and nokogiri releases the theme is tested with need Ruby
|
|
28
|
+
# 3.2; the gemspec said 3.0.
|
|
29
|
+
spec.required_ruby_version = ">= 3.2"
|
|
27
30
|
spec.require_paths = ["lib"]
|
|
28
31
|
spec.bindir = "bin"
|
|
29
32
|
spec.executables = ["datalog"]
|
|
@@ -31,10 +34,13 @@ Gem::Specification.new do |spec|
|
|
|
31
34
|
# Ship only theme infrastructure — not demo content (_posts, _pages, _portfolio,
|
|
32
35
|
# _datasets, _packages, _notebooks, tests, docs, scripts, CI configs, frontend
|
|
33
36
|
# tooling, Dockerfiles, etc.). Theme consumers get layouts/includes/sass/assets/
|
|
34
|
-
# plugins/data/lib/bin and the licensing/changelog metadata.
|
|
37
|
+
# plugins/data/lib/bin and the licensing/changelog metadata. Within _data and
|
|
38
|
+
# assets, the demo site's own files (its navigation, social profiles, author
|
|
39
|
+
# profile, CV and publication exports) stay out: see Datalog::Theme::Package.
|
|
35
40
|
spec.files = Dir.chdir(__dir__) do
|
|
36
41
|
tracked = `git ls-files -z`.split("\x0").select do |f|
|
|
37
|
-
f.match?(%r{\A(?:_layouts|_includes|_sass|_plugins|_data|assets|lib|bin)/})
|
|
42
|
+
(f.match?(%r{\A(?:_layouts|_includes|_sass|_plugins|_data|assets|lib|bin)/}) &&
|
|
43
|
+
Datalog::Theme::Package.theme_file?(f)) ||
|
|
38
44
|
%w[
|
|
39
45
|
LICENSE
|
|
40
46
|
README.md
|
|
@@ -47,32 +53,39 @@ Gem::Specification.new do |spec|
|
|
|
47
53
|
# The browser bundles are build output, so git does not track them, but
|
|
48
54
|
# _data/js_manifest.json points every page at them: a gem without them
|
|
49
55
|
# gives consumers a site whose scripts all 404. Run `npm run build:js`
|
|
50
|
-
# before packaging; scripts/verify_gem_package.rb checks the result.
|
|
51
|
-
|
|
56
|
+
# before packaging; scripts/verify_gem_package.rb checks the result. The
|
|
57
|
+
# esbuild metafile and the copy of the manifest written next to the bundles
|
|
58
|
+
# are records of the build that no page loads, so they stay out.
|
|
59
|
+
built = Dir.glob("assets/js/dist/**/*").select { |f| File.file?(f) } -
|
|
60
|
+
%w[assets/js/dist/manifest.json assets/js/dist/meta.json]
|
|
52
61
|
|
|
53
62
|
(tracked + built).uniq.sort
|
|
54
63
|
end
|
|
55
64
|
|
|
65
|
+
# Each dependency stops below its next major version, so a breaking release
|
|
66
|
+
# reaches sites through a pull request that updates this file rather than an
|
|
67
|
+
# untested `bundle update`.
|
|
56
68
|
spec.add_runtime_dependency "jekyll", "~> 4.3"
|
|
57
69
|
spec.add_runtime_dependency "jekyll-sass-converter", "~> 3.0"
|
|
58
|
-
spec.add_runtime_dependency "jekyll-feed", "
|
|
59
|
-
spec.add_runtime_dependency "jekyll-seo-tag", "
|
|
60
|
-
spec.add_runtime_dependency "jekyll-sitemap", "
|
|
61
|
-
spec.add_runtime_dependency "sass-embedded", "
|
|
62
|
-
spec.add_runtime_dependency "jekyll-paginate", "
|
|
63
|
-
spec.add_runtime_dependency "jekyll-include-cache", "
|
|
64
|
-
spec.add_runtime_dependency "jekyll-
|
|
65
|
-
spec.add_runtime_dependency "
|
|
66
|
-
spec.add_runtime_dependency "
|
|
67
|
-
spec.add_runtime_dependency "
|
|
68
|
-
spec.add_runtime_dependency "
|
|
69
|
-
spec.add_runtime_dependency "
|
|
70
|
-
spec.add_runtime_dependency "
|
|
71
|
-
spec.add_runtime_dependency "
|
|
72
|
-
spec.add_runtime_dependency "
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
70
|
+
spec.add_runtime_dependency "jekyll-feed", "~> 0.16"
|
|
71
|
+
spec.add_runtime_dependency "jekyll-seo-tag", "~> 2.8"
|
|
72
|
+
spec.add_runtime_dependency "jekyll-sitemap", "~> 1.4"
|
|
73
|
+
spec.add_runtime_dependency "sass-embedded", "~> 1.71"
|
|
74
|
+
spec.add_runtime_dependency "jekyll-paginate", "~> 1.1"
|
|
75
|
+
spec.add_runtime_dependency "jekyll-include-cache", "~> 0.2"
|
|
76
|
+
spec.add_runtime_dependency "jekyll-redirect-from", "~> 0.16"
|
|
77
|
+
spec.add_runtime_dependency "kramdown-parser-gfm", "~> 1.1"
|
|
78
|
+
spec.add_runtime_dependency "webrick", "~> 1.8"
|
|
79
|
+
spec.add_runtime_dependency "fastimage", "~> 2.2"
|
|
80
|
+
spec.add_runtime_dependency "loofah", "~> 2.19"
|
|
81
|
+
spec.add_runtime_dependency "nokogiri", "~> 1.15"
|
|
82
|
+
spec.add_runtime_dependency "mini_magick", ">= 4.12", "< 6"
|
|
83
|
+
spec.add_runtime_dependency "logger", "~> 1.6"
|
|
84
|
+
spec.add_runtime_dependency "thor", "~> 1.3"
|
|
85
|
+
# googleauth, with the Google Cloud gems it brings, is needed only by the
|
|
86
|
+
# analytics dashboard with a GA4 property configured, and such a site adds it
|
|
87
|
+
# to its own Gemfile. jekyll-archives and jekyll-remote-theme were listed here
|
|
88
|
+
# but used by nothing in the theme.
|
|
76
89
|
|
|
77
90
|
spec.add_development_dependency "bundler", ">= 2.4"
|
|
78
91
|
spec.add_development_dependency "rake", ">= 13.0"
|
data/lib/datalog/cli.rb
CHANGED
|
@@ -83,19 +83,27 @@ module Datalog
|
|
|
83
83
|
branch = options[:branch]
|
|
84
84
|
message = options[:message] || "Publish DataLog site on #{Time.now.utc.strftime('%Y-%m-%d %H:%M UTC')}"
|
|
85
85
|
|
|
86
|
-
|
|
87
|
-
|
|
86
|
+
# A deployment is a production build: without JEKYLL_ENV the published
|
|
87
|
+
# site left out the analytics tag and shipped the development CSP logger.
|
|
88
|
+
build_env = { "BUNDLE_GEMFILE" => gemfile_path(root), "JEKYLL_ENV" => "production" }
|
|
89
|
+
say_status :build, "JEKYLL_ENV=production bundle exec jekyll build", :blue
|
|
90
|
+
unless system(build_env, "bundle exec jekyll build", chdir: root)
|
|
88
91
|
say_error "Jekyll build failed. Resolve the error above and try again."
|
|
89
92
|
exit 1
|
|
90
93
|
end
|
|
91
94
|
|
|
95
|
+
published = false
|
|
92
96
|
Dir.mktmpdir("datalog-publish") do |tmp|
|
|
93
97
|
worktree_path = File.join(tmp, "deploy")
|
|
94
98
|
prepare_worktree(root, branch, worktree_path)
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
99
|
+
begin
|
|
100
|
+
copy_site_output(root, worktree_path)
|
|
101
|
+
published = commit_and_push(worktree_path, branch, message)
|
|
102
|
+
ensure
|
|
103
|
+
cleanup_worktree(root, worktree_path)
|
|
104
|
+
end
|
|
98
105
|
end
|
|
106
|
+
exit 1 unless published
|
|
99
107
|
end
|
|
100
108
|
|
|
101
109
|
desc "update", "Update the DataLog theme and related assets to the latest version"
|
|
@@ -182,23 +190,26 @@ module Datalog
|
|
|
182
190
|
exit 1
|
|
183
191
|
end
|
|
184
192
|
|
|
193
|
+
# Values go in as JSON strings, which YAML reads as double-quoted scalars.
|
|
194
|
+
# Interpolated between plain quotes, a title containing a double quote
|
|
195
|
+
# or a tag containing a colon produced front matter that did not parse.
|
|
185
196
|
tags_yaml = if tags.empty?
|
|
186
197
|
"[]"
|
|
187
198
|
else
|
|
188
|
-
"\n" + tags.map { |tag| " - #{tag}" }.join("\n")
|
|
199
|
+
"\n" + tags.map { |tag| " - #{tag.to_json}" }.join("\n")
|
|
189
200
|
end
|
|
190
201
|
front_matter = <<~YAML
|
|
191
202
|
---
|
|
192
203
|
layout: post
|
|
193
|
-
title:
|
|
194
|
-
description:
|
|
195
|
-
author:
|
|
204
|
+
title: #{title.to_json}
|
|
205
|
+
description: #{summary.to_json}
|
|
206
|
+
author: #{author.to_json}
|
|
196
207
|
date: #{date.strftime('%Y-%m-%d')}
|
|
197
208
|
tags:#{tags_yaml}
|
|
198
|
-
difficulty:
|
|
209
|
+
difficulty: #{difficulty.to_json}
|
|
199
210
|
hero:
|
|
200
211
|
image: /assets/images/#{slug}.jpg
|
|
201
|
-
alt: "Hero image for #{title}"
|
|
212
|
+
alt: #{"Hero image for #{title}".to_json}
|
|
202
213
|
callouts:
|
|
203
214
|
- label: Key takeaway
|
|
204
215
|
content: Highlight the most important insight from the post.
|
|
@@ -553,17 +564,26 @@ module Datalog
|
|
|
553
564
|
end
|
|
554
565
|
end
|
|
555
566
|
|
|
567
|
+
# Returns whether the branch now holds the site. The exit status of commit
|
|
568
|
+
# and push used to be ignored, so a rejected push still ended as a publish.
|
|
556
569
|
def commit_and_push(worktree_path, branch, message)
|
|
557
570
|
Dir.chdir(worktree_path) do
|
|
558
571
|
system("git", "add", "--all")
|
|
559
572
|
if system("git", "diff", "--cached", "--quiet")
|
|
560
573
|
say_status :skip, "No changes to publish", :yellow
|
|
561
|
-
return
|
|
574
|
+
return true
|
|
575
|
+
end
|
|
576
|
+
|
|
577
|
+
unless system("git", "commit", "-m", message)
|
|
578
|
+
say_error "git commit failed, so nothing was published."
|
|
579
|
+
return false
|
|
562
580
|
end
|
|
563
581
|
|
|
564
|
-
system("git", "commit", "-m", message)
|
|
565
582
|
say_status :git, "git push origin #{branch}", :blue
|
|
566
|
-
system("git", "push", "origin", branch)
|
|
583
|
+
return true if system("git", "push", "origin", branch)
|
|
584
|
+
|
|
585
|
+
say_error "git push to #{branch} failed, so the site was not published."
|
|
586
|
+
false
|
|
567
587
|
end
|
|
568
588
|
end
|
|
569
589
|
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Datalog
|
|
4
|
+
module Theme
|
|
5
|
+
# The repository is both the theme and the theme's demo site, and the demo
|
|
6
|
+
# keeps some of its files in directories a theme also uses. These lists say
|
|
7
|
+
# which of those files belong to the theme. The gemspec packages only those,
|
|
8
|
+
# and RepositoryCheckout applies the same split to sites that install the
|
|
9
|
+
# theme from a Git checkout or a local path, which see the whole repository.
|
|
10
|
+
module Package
|
|
11
|
+
# The _data files the layouts need in order to render. The rest of _data
|
|
12
|
+
# (navigation, social profiles, publications, the author profile) is the
|
|
13
|
+
# demo site's own; a site using the theme supplies its own versions.
|
|
14
|
+
DATA_FILES = %w[
|
|
15
|
+
_data/i18n
|
|
16
|
+
_data/js_manifest.json
|
|
17
|
+
_data/cdn-integrity.yml
|
|
18
|
+
].freeze
|
|
19
|
+
|
|
20
|
+
# Downloads the demo site links to from assets/: the maintainer's CV
|
|
21
|
+
# templates and publication exports.
|
|
22
|
+
DEMO_ASSETS = %w[
|
|
23
|
+
assets/publications
|
|
24
|
+
assets/templates
|
|
25
|
+
].freeze
|
|
26
|
+
|
|
27
|
+
# Pages load the bundles in assets/js/dist, which scripts/build_js.mjs
|
|
28
|
+
# builds from the sources beside them, and the loader that picks among
|
|
29
|
+
# the bundles. No page loads the sources themselves, and a site copies
|
|
30
|
+
# every theme asset into its output, so the gem leaves them out.
|
|
31
|
+
SCRIPTS_PAGES_LOAD = %w[
|
|
32
|
+
assets/js/dist
|
|
33
|
+
assets/js/loader.js
|
|
34
|
+
].freeze
|
|
35
|
+
|
|
36
|
+
module_function
|
|
37
|
+
|
|
38
|
+
# Whether a repository-relative path is part of the theme rather than
|
|
39
|
+
# demo content that happens to live in a theme directory.
|
|
40
|
+
def theme_file?(path)
|
|
41
|
+
return DATA_FILES.any? { |entry| inside?(path, entry) } if inside?(path, "_data")
|
|
42
|
+
return SCRIPTS_PAGES_LOAD.any? { |entry| inside?(path, entry) } if inside?(path, "assets/js")
|
|
43
|
+
|
|
44
|
+
DEMO_ASSETS.none? { |entry| inside?(path, entry) }
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# The site.data keys the theme's own data files are read into.
|
|
48
|
+
def data_keys
|
|
49
|
+
DATA_FILES.map { |entry| File.basename(entry, ".*") }
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def inside?(path, entry)
|
|
53
|
+
path == entry || path.start_with?("#{entry}/")
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "jekyll"
|
|
4
|
+
require_relative "package"
|
|
5
|
+
|
|
6
|
+
module Datalog
|
|
7
|
+
module Theme
|
|
8
|
+
# A site that installs the theme from a Git checkout or a local path
|
|
9
|
+
# (`gem "datalog-theme", github: ...` or `path: ...`) gets the whole
|
|
10
|
+
# repository as its theme, and the repository is also the demo site. Jekyll
|
|
11
|
+
# merges the demo's _config.yml into the site's configuration, reads the
|
|
12
|
+
# demo's _data as theme data and copies the demo's downloads from assets/.
|
|
13
|
+
# The site then inherits the maintainer's name, contact addresses and social
|
|
14
|
+
# profiles, and jekyll-feed stops the build on a datasets feed for a
|
|
15
|
+
# collection the site does not have. The packaged gem contains none of those
|
|
16
|
+
# files; these hooks give a checkout the same contents.
|
|
17
|
+
module RepositoryCheckout
|
|
18
|
+
module_function
|
|
19
|
+
|
|
20
|
+
# The packaged gem ships no _config.yml, so one at the theme root means
|
|
21
|
+
# the theme is a copy of the repository.
|
|
22
|
+
def applies_to?(site)
|
|
23
|
+
theme = site.theme
|
|
24
|
+
!theme.nil? && theme.name == "datalog-theme" && File.file?(File.join(theme.root, "_config.yml"))
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Jekyll merges the theme configuration before any theme code runs, so it
|
|
28
|
+
# cannot be taken back out here: Jekyll's own `ignore_theme_config` switch
|
|
29
|
+
# is the only way to keep it out. A site that sets the switch to false has
|
|
30
|
+
# chosen to inherit the demo configuration.
|
|
31
|
+
def check_configuration(site)
|
|
32
|
+
return unless applies_to?(site)
|
|
33
|
+
return if site.config.key?("ignore_theme_config")
|
|
34
|
+
|
|
35
|
+
raise Jekyll::Errors::FatalException, <<~MESSAGE
|
|
36
|
+
datalog-theme is installed from a copy of its repository (#{site.theme.root}),
|
|
37
|
+
which is also the theme's demo site. Jekyll merges the demo's _config.yml into
|
|
38
|
+
your configuration, so your site would carry the demo's author, contact
|
|
39
|
+
addresses, social profiles and feeds.
|
|
40
|
+
|
|
41
|
+
Add this line to your _config.yml:
|
|
42
|
+
|
|
43
|
+
ignore_theme_config: true
|
|
44
|
+
|
|
45
|
+
The theme then also leaves out the demo's _data files and downloads. Set it to
|
|
46
|
+
false instead only if you mean to inherit the demo configuration.
|
|
47
|
+
MESSAGE
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def remove_demo_content(site)
|
|
51
|
+
return unless applies_to?(site) && site.config["ignore_theme_config"] == true
|
|
52
|
+
|
|
53
|
+
remove_demo_assets(site)
|
|
54
|
+
remove_demo_data(site)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def remove_demo_assets(site)
|
|
58
|
+
demo_dirs = Package::DEMO_ASSETS.map { |entry| File.join(site.theme.root, entry, "") }
|
|
59
|
+
site.static_files.reject! { |file| demo_dirs.any? { |dir| file.path.start_with?(dir) } }
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# site.data holds the theme's data with the site's merged over it. Each key
|
|
63
|
+
# the demo contributed goes back to the site's own value, or away.
|
|
64
|
+
def remove_demo_data(site)
|
|
65
|
+
theme_data_dir = File.join(site.theme.root, "_data")
|
|
66
|
+
return unless File.directory?(theme_data_dir)
|
|
67
|
+
|
|
68
|
+
demo_keys = Dir.children(theme_data_dir).map { |name| File.basename(name, ".*") } - Package.data_keys
|
|
69
|
+
return if demo_keys.empty?
|
|
70
|
+
|
|
71
|
+
own = Jekyll::DataReader.new(site).read(site.config["data_dir"])
|
|
72
|
+
demo_keys.each do |key|
|
|
73
|
+
if own.key?(key)
|
|
74
|
+
site.data[key] = own[key]
|
|
75
|
+
else
|
|
76
|
+
site.data.delete(key)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
Jekyll::Hooks.register :site, :after_init do |site|
|
|
85
|
+
Datalog::Theme::RepositoryCheckout.check_configuration(site)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
Jekyll::Hooks.register :site, :post_read do |site|
|
|
89
|
+
Datalog::Theme::RepositoryCheckout.remove_demo_content(site)
|
|
90
|
+
end
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Datalog
|
|
4
|
+
# Silences two warnings that every build repeats. Kernel#warn reports through
|
|
5
|
+
# Warning.warn, so prepending here covers both. A Kernel#warn override used to
|
|
6
|
+
# sit alongside it, and it printed keyword arguments such as `uplevel:` and
|
|
7
|
+
# `category:` as a hash after the message instead of honouring them.
|
|
4
8
|
module WarningFilter
|
|
5
9
|
FILTERS = [
|
|
6
10
|
/literal string will be frozen/,
|
|
7
11
|
/already initialized constant Datalog::Theme::VERSION/
|
|
8
12
|
].freeze
|
|
9
13
|
|
|
10
|
-
def warn(message)
|
|
14
|
+
def warn(message, **options)
|
|
11
15
|
return if FILTERS.any? { |pattern| pattern.match?(message) }
|
|
12
16
|
|
|
13
17
|
super
|
|
@@ -16,13 +20,3 @@ module Datalog
|
|
|
16
20
|
end
|
|
17
21
|
|
|
18
22
|
Warning.singleton_class.prepend(Datalog::WarningFilter) if defined?(Warning)
|
|
19
|
-
|
|
20
|
-
module Kernel
|
|
21
|
-
alias __datalog_warn warn
|
|
22
|
-
|
|
23
|
-
def warn(message = nil, *args)
|
|
24
|
-
return if message && Datalog::WarningFilter::FILTERS.any? { |pattern| pattern.match?(message) }
|
|
25
|
-
|
|
26
|
-
__datalog_warn(message, *args)
|
|
27
|
-
end
|
|
28
|
-
end
|
data/lib/datalog-theme.rb
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative "datalog/theme/version"
|
|
4
|
+
# The layouts render their page-independent includes with {% include_cached %},
|
|
5
|
+
# which comes from jekyll-include-cache rather than Jekyll itself.
|
|
6
|
+
require "jekyll-include-cache"
|
|
4
7
|
|
|
5
8
|
module Datalog
|
|
6
9
|
module Theme
|
|
@@ -31,3 +34,5 @@ module Datalog
|
|
|
31
34
|
end
|
|
32
35
|
|
|
33
36
|
Datalog::Theme.load_plugins
|
|
37
|
+
|
|
38
|
+
require_relative "datalog/theme/repository_checkout"
|