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.
Files changed (133) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +125 -0
  3. data/CITATION.cff +2 -2
  4. data/README.md +23 -17
  5. data/_data/cdn-integrity.yml +0 -30
  6. data/_includes/analytics/dashboard.html +3 -1
  7. data/_includes/components/api-function.html +20 -1
  8. data/_includes/components/enhanced-code-block.html +1 -1
  9. data/_includes/csp-meta.html +115 -11
  10. data/_includes/footer.html +19 -20
  11. data/_includes/head.html +60 -23
  12. data/_includes/header/navigation.html +12 -15
  13. data/_includes/header.html +28 -19
  14. data/_includes/layouts/default/article.html +5 -1
  15. data/_includes/meta/math-config.html +9 -5
  16. data/_includes/meta/schema.html +5 -2
  17. data/_includes/meta/scripts-loader.html +16 -32
  18. data/_includes/post/related-posts.html +4 -7
  19. data/_includes/search/index-data.json +9 -34
  20. data/_layouts/dataset.html +1 -0
  21. data/_layouts/default.html +16 -8
  22. data/_layouts/notebook.html +1 -0
  23. data/_layouts/package.html +1 -0
  24. data/_layouts/portfolio.html +1 -0
  25. data/_layouts/post.html +20 -5
  26. data/_layouts/project.html +2 -1
  27. data/_plugins/analytics_dashboard.rb +9 -3
  28. data/_plugins/config_validator.rb +12 -7
  29. data/_plugins/csp_generator.rb +18 -28
  30. data/_plugins/datalog_bibliography.rb +9 -7
  31. data/_plugins/datalog_comments.rb +8 -5
  32. data/_plugins/datalog_slides.rb +9 -8
  33. data/_plugins/i18n.rb +7 -8
  34. data/_plugins/image_optimizer.rb +17 -6
  35. data/_plugins/math_preprocessor.rb +33 -3
  36. data/_plugins/notebook_converter.rb +23 -4
  37. data/_plugins/plugin_loader.rb +3 -1
  38. data/_plugins/publications_generator.rb +8 -2
  39. data/_plugins/rouge_highlight_filter.rb +42 -0
  40. data/_plugins/search_code_blocks.rb +30 -0
  41. data/_plugins/search_normalizer.rb +15 -53
  42. data/_plugins/search_pages.rb +3 -4
  43. data/_sass/_academic-dashboard.scss +262 -0
  44. data/_sass/_base.scss +12 -0
  45. data/_sass/_components.scss +64 -1153
  46. data/_sass/_features.scss +17 -0
  47. data/_sass/_layout.scss +1 -1
  48. data/_sass/_notebooks.scss +322 -0
  49. data/_sass/_open-science-badges.scss +56 -0
  50. data/_sass/{_phase1-enhancements.scss → _post-components.scss} +1 -1
  51. data/_sass/_search-page.scss +530 -0
  52. data/_sass/_search.scss +46 -0
  53. data/_sass/_syntax-highlighting.scss +212 -97
  54. data/_sass/_theme.scss +29 -19
  55. data/_sass/_typography.scss +14 -0
  56. data/assets/css/main.scss +14 -0
  57. data/assets/js/dist/academic.js +1 -1
  58. data/assets/js/dist/analytics-dashboard.js +1 -1
  59. data/assets/js/dist/chunks/chunk-225H5YXE.js +1 -0
  60. data/assets/js/dist/core.js +1 -1
  61. data/assets/js/dist/loader.js +1 -1
  62. data/assets/js/dist/notebook.js +1 -1
  63. data/assets/js/dist/search.js +1 -1
  64. data/assets/js/dist/visualizations.js +11 -2
  65. data/assets/js/loader.js +3 -1
  66. data/datalog-theme.gemspec +36 -23
  67. data/lib/datalog/cli.rb +34 -14
  68. data/lib/datalog/plugin_system/dependency_resolver.rb +0 -2
  69. data/lib/datalog/theme/package.rb +57 -0
  70. data/lib/datalog/theme/repository_checkout.rb +90 -0
  71. data/lib/datalog/theme/version.rb +1 -1
  72. data/lib/datalog/warning_filter.rb +5 -11
  73. data/lib/datalog-theme.rb +5 -0
  74. metadata +48 -133
  75. data/_data/academic.yml +0 -217
  76. data/_data/config/author.yml +0 -121
  77. data/_data/datasets.yml +0 -28
  78. data/_data/js_meta.json +0 -371
  79. data/_data/navigation.yml +0 -145
  80. data/_data/projects.yml +0 -41
  81. data/_data/publications.yml +0 -28
  82. data/_data/social.yml +0 -73
  83. data/_data/visualizations.yml +0 -51
  84. data/_includes/components/advanced-search.html +0 -682
  85. data/_includes/components/bookmark-system.html +0 -96
  86. data/_includes/components/comments.html +0 -244
  87. data/_includes/components/content-recommendations.html +0 -228
  88. data/_includes/components/email-preferences.html +0 -200
  89. data/_includes/components/enhanced-metadata.html +0 -228
  90. data/_includes/components/language-switcher.html +0 -396
  91. data/_includes/components/navigation-enhancements.html +0 -454
  92. data/_includes/components/newsletter-signup.html +0 -178
  93. data/_includes/components/popular-posts.html +0 -233
  94. data/_includes/components/reading-progress.html +0 -133
  95. data/_includes/components/reading-time.html +0 -121
  96. data/_includes/components/series-navigation.html +0 -124
  97. data/_includes/components/social-proof.html +0 -34
  98. data/_includes/components/user-preferences.html +0 -566
  99. data/_includes/meta/syntax-config.html +0 -19
  100. data/_layouts/archive.html +0 -282
  101. data/_layouts/post-sidebar.html +0 -183
  102. data/_sass/_phase3-enhancements.scss +0 -874
  103. data/_sass/_phase4-enhancements.scss +0 -1214
  104. data/_sass/_phase5-enhancements.scss +0 -414
  105. data/assets/js/academic.js +0 -262
  106. data/assets/js/analytics-dashboard.js +0 -382
  107. data/assets/js/core/dark-mode.js +0 -79
  108. data/assets/js/core/github-cards.js +0 -123
  109. data/assets/js/core/language-filter.js +0 -69
  110. data/assets/js/core/navigation.js +0 -184
  111. data/assets/js/core/scroll-progress.js +0 -45
  112. data/assets/js/core/search-hotkeys.js +0 -62
  113. data/assets/js/core/skip-links.js +0 -62
  114. data/assets/js/dist/manifest.json +0 -22
  115. data/assets/js/dist/meta.json +0 -371
  116. data/assets/js/main.js +0 -23
  117. data/assets/js/math.js +0 -818
  118. data/assets/js/notebook.js +0 -158
  119. data/assets/js/search/analytics.js +0 -91
  120. data/assets/js/search/app.js +0 -271
  121. data/assets/js/search/autocomplete.js +0 -120
  122. data/assets/js/search/engine.js +0 -260
  123. data/assets/js/search/filters.js +0 -45
  124. data/assets/js/search/render.js +0 -217
  125. data/assets/js/search/utils.js +0 -99
  126. data/assets/js/search.js +0 -354
  127. data/assets/js/visualizations.js +0 -816
  128. data/assets/publications/datalog-publications.bib +0 -8
  129. data/assets/publications/datalog-publications.ris +0 -9
  130. data/assets/publications/publications.bib +0 -30
  131. data/assets/templates/diogo-ribeiro-cv.md +0 -31
  132. data/assets/templates/diogo-ribeiro-cv.tex +0 -32
  133. data/lib/datalog/theme/theme.rb +0 -18
data/assets/js/search.js DELETED
@@ -1,354 +0,0 @@
1
- import { initializeSearchApp } from "./search/app.js";
2
-
3
- const DEBOUNCE_DELAY = 300;
4
- const RESULT_ID_PREFIX = "search-result-";
5
- const MIN_LOADING_VISIBLE_MS = 500;
6
-
7
- function debounce(callback, delay = DEBOUNCE_DELAY) {
8
- let timerId;
9
- const debounced = (...args) => {
10
- if (timerId) {
11
- window.clearTimeout(timerId);
12
- }
13
- timerId = window.setTimeout(() => {
14
- timerId = undefined;
15
- callback.apply(null, args);
16
- }, delay);
17
- };
18
-
19
- debounced.cancel = () => {
20
- if (timerId) {
21
- window.clearTimeout(timerId);
22
- timerId = undefined;
23
- }
24
- };
25
-
26
- return debounced;
27
- }
28
-
29
- function updateLiveRegion(region, message) {
30
- if (!region) {
31
- return;
32
- }
33
- const text = String(message || "");
34
- if (region.textContent === text) {
35
- region.textContent = `${text}\u00A0`;
36
- } else {
37
- region.textContent = text;
38
- }
39
- if (text.trim()) {
40
- region.removeAttribute("hidden");
41
- } else {
42
- region.setAttribute("hidden", "");
43
- }
44
- }
45
-
46
- function setupSearchEnhancements() {
47
- const app = document.querySelector("[data-search-app]");
48
- if (!app) {
49
- return;
50
- }
51
-
52
- const form = app.querySelector("[data-search-form]");
53
- const input = app.querySelector("[data-search-input]");
54
- const resultsList = app.querySelector("[data-search-results]");
55
- const emptyState = app.querySelector("[data-search-empty]");
56
- const loadingIndicator = app.querySelector("[data-search-loading]");
57
- const resultsRegion = app.querySelector("[data-search-region]");
58
- const liveCount = app.querySelector('[data-search-live="count"]');
59
- const liveSelection = app.querySelector('[data-search-live="selection"]');
60
- const liveStatus = app.querySelector('[data-search-live="status"]');
61
- const filtersContainer = app.querySelector("[data-search-filters]");
62
- const tagContainer = app.querySelector("[data-filter-tags]");
63
-
64
- if (!input || !resultsList) {
65
- return;
66
- }
67
-
68
- let activeIndex = -1;
69
- let resultIdCounter = 0;
70
- let resultItems = [];
71
- let pendingSearch = false;
72
- let filterControls = [];
73
- let loadingStartedAt = 0;
74
- let loadingHideTimer = null;
75
-
76
- const debouncedSubmit = debounce(() => {
77
- if (!form) {
78
- return;
79
- }
80
- pendingSearch = true;
81
- showLoading();
82
- updateLiveRegion(liveStatus, "Loading results…");
83
- form.dispatchEvent(new Event("submit", { cancelable: true }));
84
- });
85
-
86
- const observer = new MutationObserver(() => {
87
- refreshResultItems();
88
- });
89
- observer.observe(resultsList, { childList: true });
90
-
91
- refreshResultItems();
92
- refreshFilterControls();
93
-
94
- if (tagContainer) {
95
- const tagObserver = new MutationObserver(() => {
96
- refreshFilterControls();
97
- });
98
- tagObserver.observe(tagContainer, { childList: true });
99
- }
100
-
101
- input.addEventListener("input", () => {
102
- clearActiveResult(false);
103
- debouncedSubmit();
104
- });
105
-
106
- input.addEventListener("keydown", (event) => {
107
- if (handleInputNavigation(event)) {
108
- return;
109
- }
110
- if (event.key === "Tab" && filterControls.length > 0) {
111
- event.preventDefault();
112
- const nextIndex = event.shiftKey ? filterControls.length - 1 : 0;
113
- filterControls[nextIndex].focus();
114
- }
115
- });
116
-
117
- function handleFilterKeydown(event) {
118
- if (event.key !== "Tab" || filterControls.length === 0) {
119
- return;
120
- }
121
- event.preventDefault();
122
- const currentIndex = filterControls.indexOf(event.currentTarget);
123
- if (currentIndex === -1) {
124
- return;
125
- }
126
- const direction = event.shiftKey ? -1 : 1;
127
- const nextIndex = (currentIndex + direction + filterControls.length) % filterControls.length;
128
- filterControls[nextIndex].focus();
129
- }
130
-
131
- function refreshFilterControls() {
132
- if (!filtersContainer) {
133
- return;
134
- }
135
- const selects = Array.from(filtersContainer.querySelectorAll("select"));
136
- const tags = tagContainer ? Array.from(tagContainer.querySelectorAll("[data-filter-tag]")) : [];
137
- filterControls = [...selects, ...tags];
138
- filterControls.forEach((control) => {
139
- control.removeEventListener("keydown", handleFilterKeydown);
140
- control.addEventListener("keydown", handleFilterKeydown);
141
- });
142
- }
143
-
144
- function handleInputNavigation(event) {
145
- if (!resultItems.length && ["ArrowDown", "ArrowUp", "Enter"].includes(event.key)) {
146
- return false;
147
- }
148
- switch (event.key) {
149
- case "ArrowDown":
150
- event.preventDefault();
151
- moveActive(1);
152
- return true;
153
- case "ArrowUp":
154
- event.preventDefault();
155
- moveActive(-1);
156
- return true;
157
- case "Enter":
158
- if (activeIndex >= 0) {
159
- event.preventDefault();
160
- openActiveResult();
161
- return true;
162
- }
163
- return false;
164
- case "Escape":
165
- event.preventDefault();
166
- clearSearch();
167
- return true;
168
- default:
169
- return false;
170
- }
171
- }
172
-
173
- function moveActive(delta) {
174
- if (!resultItems.length) {
175
- return;
176
- }
177
- const nextIndex = activeIndex === -1 ? (delta > 0 ? 0 : resultItems.length - 1) : (activeIndex + delta + resultItems.length) % resultItems.length;
178
- setActiveResult(nextIndex);
179
- }
180
-
181
- function setActiveResult(index) {
182
- if (index < -1 || index >= resultItems.length) {
183
- return;
184
- }
185
- if (activeIndex === index) {
186
- return;
187
- }
188
- if (activeIndex >= 0 && resultItems[activeIndex]) {
189
- resultItems[activeIndex].classList.remove("is-active");
190
- }
191
- activeIndex = index;
192
- if (activeIndex >= 0) {
193
- const item = resultItems[activeIndex];
194
- if (!item) {
195
- return;
196
- }
197
- item.classList.add("is-active");
198
- const id = ensureResultId(item);
199
- input.setAttribute("aria-activedescendant", id);
200
- const title = getResultTitle(item);
201
- updateLiveRegion(liveSelection, `Result ${activeIndex + 1} of ${resultItems.length}: ${title}`);
202
- item.scrollIntoView({ block: "nearest" });
203
- } else {
204
- input.removeAttribute("aria-activedescendant");
205
- updateLiveRegion(liveSelection, "Search results selection cleared.");
206
- }
207
- }
208
-
209
- function clearActiveResult(announce = true) {
210
- if (activeIndex >= 0 && resultItems[activeIndex]) {
211
- resultItems[activeIndex].classList.remove("is-active");
212
- }
213
- activeIndex = -1;
214
- input.removeAttribute("aria-activedescendant");
215
- if (announce) {
216
- updateLiveRegion(liveSelection, "Search results selection cleared.");
217
- }
218
- }
219
-
220
- function ensureResultId(item) {
221
- if (item.id) {
222
- return item.id;
223
- }
224
- resultIdCounter += 1;
225
- const id = `${RESULT_ID_PREFIX}${resultIdCounter}`;
226
- item.id = id;
227
- return id;
228
- }
229
-
230
- function refreshResultItems() {
231
- resultItems = Array.from(resultsList.querySelectorAll(".search-result"));
232
- resultItems.forEach((item) => {
233
- ensureResultId(item);
234
- item.setAttribute("role", "option");
235
- item.setAttribute("tabindex", "-1");
236
- });
237
- if (activeIndex >= resultItems.length) {
238
- clearActiveResult(false);
239
- }
240
- if (pendingSearch) {
241
- pendingSearch = false;
242
- updateLiveRegion(liveStatus, "Results updated.");
243
- }
244
- hideLoading();
245
- announceCount();
246
- }
247
-
248
- function announceCount() {
249
- if (!liveCount) {
250
- return;
251
- }
252
- const query = input.value.trim();
253
- if (!query) {
254
- updateLiveRegion(liveCount, "Enter a query to begin.");
255
- return;
256
- }
257
- if (emptyState && !emptyState.hidden && resultItems.length === 0) {
258
- updateLiveRegion(liveCount, `No results found for “${query}”.`);
259
- return;
260
- }
261
- updateLiveRegion(liveCount, `${resultItems.length} result${resultItems.length === 1 ? "" : "s"} found for “${query}”.`);
262
- }
263
-
264
- function showLoading() {
265
- if (resultsRegion) {
266
- resultsRegion.setAttribute("aria-busy", "true");
267
- }
268
- if (loadingIndicator) {
269
- if (loadingHideTimer) {
270
- window.clearTimeout(loadingHideTimer);
271
- loadingHideTimer = null;
272
- }
273
- loadingStartedAt = Date.now();
274
- loadingIndicator.hidden = false;
275
- loadingIndicator.removeAttribute("hidden");
276
- }
277
- }
278
-
279
- function hideLoading() {
280
- if (resultsRegion) {
281
- resultsRegion.setAttribute("aria-busy", "false");
282
- }
283
- if (loadingIndicator) {
284
- const finalize = () => {
285
- loadingIndicator.hidden = true;
286
- loadingIndicator.setAttribute("hidden", "");
287
- loadingHideTimer = null;
288
- loadingStartedAt = 0;
289
- };
290
- const elapsed = loadingStartedAt ? Date.now() - loadingStartedAt : MIN_LOADING_VISIBLE_MS;
291
- if (elapsed < MIN_LOADING_VISIBLE_MS) {
292
- const remaining = MIN_LOADING_VISIBLE_MS - elapsed;
293
- if (loadingHideTimer) {
294
- window.clearTimeout(loadingHideTimer);
295
- }
296
- loadingHideTimer = window.setTimeout(finalize, remaining);
297
- } else {
298
- finalize();
299
- }
300
- }
301
- }
302
-
303
- function openActiveResult() {
304
- const item = activeIndex >= 0 ? resultItems[activeIndex] : null;
305
- if (!item) {
306
- return;
307
- }
308
- const link = item.querySelector("[data-result-link]");
309
- if (link && link.href) {
310
- window.location.assign(link.href);
311
- }
312
- }
313
-
314
- function clearSearch() {
315
- debouncedSubmit.cancel();
316
- input.value = "";
317
- clearActiveResult();
318
- updateLiveRegion(liveStatus, "Search cleared.");
319
- if (form) {
320
- pendingSearch = true;
321
- showLoading();
322
- form.dispatchEvent(new Event("submit", { cancelable: true }));
323
- }
324
- }
325
-
326
- function getResultTitle(item) {
327
- const link = item.querySelector("[data-result-link]");
328
- if (link && link.textContent) {
329
- return link.textContent.trim();
330
- }
331
- const heading = item.querySelector(".search-result__title");
332
- return heading && heading.textContent ? heading.textContent.trim() : "Result";
333
- }
334
- }
335
-
336
- const isTestEnvironment =
337
- typeof process !== "undefined" &&
338
- process.env &&
339
- (process.env.NODE_ENV === "test" || process.env.VITEST === "true");
340
-
341
- function onReady() {
342
- initializeSearchApp();
343
- setupSearchEnhancements();
344
- }
345
-
346
- if (!isTestEnvironment) {
347
- if (document.readyState === "loading") {
348
- document.addEventListener("DOMContentLoaded", onReady);
349
- } else {
350
- onReady();
351
- }
352
- }
353
-
354
- export { debounce, updateLiveRegion, setupSearchEnhancements };