datalog-theme 0.7.0 → 0.9.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 (203) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +188 -0
  3. data/CITATION.cff +2 -2
  4. data/README.md +25 -17
  5. data/_data/cdn-integrity.yml +0 -30
  6. data/_data/i18n/en.yml +297 -0
  7. data/_data/i18n/es.yml +297 -0
  8. data/_data/i18n/pt.yml +297 -0
  9. data/_data/js_manifest.json +16 -0
  10. data/_includes/analytics/dashboard.html +3 -1
  11. data/_includes/components/api-function.html +20 -1
  12. data/_includes/components/author-bio.html +21 -11
  13. data/_includes/components/author-list.html +32 -0
  14. data/_includes/components/citation-tools.html +33 -25
  15. data/_includes/components/comments-thread.html +90 -0
  16. data/_includes/components/contact-form.html +120 -0
  17. data/_includes/components/correction-report.html +82 -0
  18. data/_includes/components/enhanced-code-block.html +1 -1
  19. data/_includes/components/enhanced-toc.html +6 -7
  20. data/_includes/components/license-link.html +13 -0
  21. data/_includes/components/license-notice.html +28 -0
  22. data/_includes/components/moderation-inbox.html +139 -0
  23. data/_includes/components/reactions.html +49 -0
  24. data/_includes/components/reading-list.html +31 -0
  25. data/_includes/components/reading-mode-toggle.html +65 -0
  26. data/_includes/components/reading-state-bookmark.html +27 -0
  27. data/_includes/components/reading-state-panel.html +71 -0
  28. data/_includes/components/reproducibility.html +61 -0
  29. data/_includes/components/responsive-image.html +3 -3
  30. data/_includes/components/revision-history.html +39 -0
  31. data/_includes/components/revision-notice.html +35 -0
  32. data/_includes/components/series-nav.html +64 -0
  33. data/_includes/components/subscribe-form.html +88 -0
  34. data/_includes/components/subscription-manage.html +68 -0
  35. data/_includes/components/webmentions.html +48 -0
  36. data/_includes/csp-meta.html +135 -11
  37. data/_includes/footer.html +22 -20
  38. data/_includes/head.html +111 -63
  39. data/_includes/header/navigation.html +12 -15
  40. data/_includes/header.html +28 -19
  41. data/_includes/layouts/default/article.html +9 -7
  42. data/_includes/meta/dynamic-services-config.html +14 -0
  43. data/_includes/meta/math-config.html +18 -10
  44. data/_includes/meta/person-json.html +27 -0
  45. data/_includes/meta/publisher.html +45 -0
  46. data/_includes/meta/schema.html +67 -30
  47. data/_includes/meta/scholarly.html +121 -0
  48. data/_includes/meta/scripts-loader.html +18 -32
  49. data/_includes/meta/webmention-discovery.html +14 -0
  50. data/_includes/post/related-posts.html +4 -7
  51. data/_includes/scripts.html +57 -0
  52. data/_includes/search/index-data.json +9 -34
  53. data/_layouts/dataset.html +5 -3
  54. data/_layouts/default.html +16 -8
  55. data/_layouts/notebook.html +1 -0
  56. data/_layouts/package.html +4 -2
  57. data/_layouts/page.html +15 -0
  58. data/_layouts/portfolio.html +1 -0
  59. data/_layouts/post.html +102 -23
  60. data/_layouts/project.html +4 -3
  61. data/_layouts/research.html +20 -8
  62. data/_plugins/analytics_dashboard.rb +9 -3
  63. data/_plugins/authors.rb +133 -0
  64. data/_plugins/config_validator.rb +231 -23
  65. data/_plugins/critical_css_check.rb +42 -0
  66. data/_plugins/csp_generator.rb +18 -28
  67. data/_plugins/datalog_bibliography.rb +9 -7
  68. data/_plugins/datalog_comments.rb +8 -5
  69. data/_plugins/datalog_slides.rb +9 -8
  70. data/_plugins/i18n.rb +13 -12
  71. data/_plugins/image_optimizer.rb +241 -178
  72. data/_plugins/licenses.rb +135 -0
  73. data/_plugins/math_preprocessor.rb +59 -7
  74. data/_plugins/notebook_converter.rb +23 -4
  75. data/_plugins/plugin_loader.rb +3 -1
  76. data/_plugins/publications_generator.rb +8 -2
  77. data/_plugins/references.rb +238 -0
  78. data/_plugins/reproducibility.rb +150 -0
  79. data/_plugins/revisions.rb +101 -0
  80. data/_plugins/rouge_highlight_filter.rb +42 -0
  81. data/_plugins/scholarly.rb +50 -0
  82. data/_plugins/search_code_blocks.rb +30 -0
  83. data/_plugins/search_normalizer.rb +15 -53
  84. data/_plugins/search_pages.rb +3 -4
  85. data/_plugins/series.rb +104 -0
  86. data/_plugins/statements.rb +87 -0
  87. data/_sass/_academic-dashboard.scss +262 -0
  88. data/_sass/_base.scss +20 -1
  89. data/_sass/_comments-thread.scss +159 -0
  90. data/_sass/_components.scss +64 -1153
  91. data/_sass/_features.scss +17 -0
  92. data/_sass/_layout.scss +385 -1
  93. data/_sass/_mathematical.scss +27 -0
  94. data/_sass/_moderation.scss +222 -0
  95. data/_sass/_notebooks.scss +322 -0
  96. data/_sass/_open-science-badges.scss +56 -0
  97. data/_sass/{_phase1-enhancements.scss → _post-components.scss} +5 -3
  98. data/_sass/_print.scss +291 -0
  99. data/_sass/_reactions.scss +89 -0
  100. data/_sass/_reading-state.scss +290 -0
  101. data/_sass/_search-page.scss +530 -0
  102. data/_sass/_search.scss +46 -0
  103. data/_sass/_service-forms.scss +204 -0
  104. data/_sass/_subscriptions.scss +140 -0
  105. data/_sass/_syntax-highlighting.scss +212 -97
  106. data/_sass/_theme.scss +40 -19
  107. data/_sass/_typography.scss +130 -0
  108. data/_sass/_utilities.scss +5 -0
  109. data/_sass/_variables.scss +6 -0
  110. data/_sass/_webmentions.scss +125 -0
  111. data/assets/css/main.scss +14 -0
  112. data/assets/js/dist/academic.js +1 -1
  113. data/assets/js/dist/analytics-dashboard.js +1 -1
  114. data/assets/js/dist/chunks/chunk-2DYDWUFX.js +1 -0
  115. data/assets/js/dist/chunks/chunk-PATLC23F.js +1 -0
  116. data/assets/js/dist/chunks/chunk-V7734B2G.js +1 -0
  117. data/assets/js/dist/comments.js +2 -0
  118. data/assets/js/dist/contact.js +1 -0
  119. data/assets/js/dist/core.js +1 -1
  120. data/assets/js/dist/corrections.js +1 -0
  121. data/assets/js/dist/loader.js +1 -1
  122. data/assets/js/dist/math.js +1 -1
  123. data/assets/js/dist/moderation.js +1 -0
  124. data/assets/js/dist/notebook.js +1 -1
  125. data/assets/js/dist/reactions.js +1 -0
  126. data/assets/js/dist/reading-state.js +1 -0
  127. data/assets/js/dist/search.js +1 -1
  128. data/assets/js/dist/sources.json +52 -0
  129. data/assets/js/dist/subscriptions.js +1 -0
  130. data/assets/js/dist/visualizations.js +11 -2
  131. data/assets/js/dist/webmentions.js +1 -0
  132. data/assets/js/loader.js +37 -1
  133. data/datalog-theme.gemspec +35 -23
  134. data/lib/datalog/cli.rb +43 -15
  135. data/lib/datalog/critical_css.rb +168 -0
  136. data/lib/datalog/plugin_system/dependency_resolver.rb +0 -2
  137. data/lib/datalog/plugins/comments.rb +33 -3
  138. data/lib/datalog/theme/installed_files.rb +113 -0
  139. data/lib/datalog/theme/package.rb +57 -0
  140. data/lib/datalog/theme/repository_checkout.rb +94 -0
  141. data/lib/datalog/theme/version.rb +5 -1
  142. data/lib/datalog/warning_filter.rb +5 -11
  143. data/lib/datalog-theme.rb +6 -0
  144. metadata +96 -147
  145. data/_data/academic.yml +0 -217
  146. data/_data/config/author.yml +0 -121
  147. data/_data/datasets.yml +0 -28
  148. data/_data/js_meta.json +0 -371
  149. data/_data/navigation.yml +0 -145
  150. data/_data/projects.yml +0 -41
  151. data/_data/publications.yml +0 -28
  152. data/_data/social.yml +0 -73
  153. data/_data/visualizations.yml +0 -51
  154. data/_includes/components/advanced-search.html +0 -682
  155. data/_includes/components/bookmark-system.html +0 -96
  156. data/_includes/components/comments.html +0 -244
  157. data/_includes/components/content-recommendations.html +0 -228
  158. data/_includes/components/email-preferences.html +0 -200
  159. data/_includes/components/enhanced-metadata.html +0 -228
  160. data/_includes/components/language-switcher.html +0 -396
  161. data/_includes/components/navigation-enhancements.html +0 -454
  162. data/_includes/components/newsletter-signup.html +0 -178
  163. data/_includes/components/popular-posts.html +0 -233
  164. data/_includes/components/reading-progress.html +0 -133
  165. data/_includes/components/reading-time.html +0 -121
  166. data/_includes/components/series-navigation.html +0 -124
  167. data/_includes/components/social-proof.html +0 -34
  168. data/_includes/components/user-preferences.html +0 -566
  169. data/_includes/meta/syntax-config.html +0 -19
  170. data/_layouts/archive.html +0 -282
  171. data/_layouts/post-sidebar.html +0 -183
  172. data/_sass/_phase3-enhancements.scss +0 -874
  173. data/_sass/_phase4-enhancements.scss +0 -1214
  174. data/_sass/_phase5-enhancements.scss +0 -414
  175. data/assets/js/academic.js +0 -262
  176. data/assets/js/analytics-dashboard.js +0 -382
  177. data/assets/js/core/dark-mode.js +0 -79
  178. data/assets/js/core/github-cards.js +0 -123
  179. data/assets/js/core/language-filter.js +0 -69
  180. data/assets/js/core/navigation.js +0 -184
  181. data/assets/js/core/scroll-progress.js +0 -45
  182. data/assets/js/core/search-hotkeys.js +0 -62
  183. data/assets/js/core/skip-links.js +0 -62
  184. data/assets/js/dist/manifest.json +0 -22
  185. data/assets/js/dist/meta.json +0 -371
  186. data/assets/js/main.js +0 -23
  187. data/assets/js/math.js +0 -818
  188. data/assets/js/notebook.js +0 -158
  189. data/assets/js/search/analytics.js +0 -91
  190. data/assets/js/search/app.js +0 -271
  191. data/assets/js/search/autocomplete.js +0 -120
  192. data/assets/js/search/engine.js +0 -260
  193. data/assets/js/search/filters.js +0 -45
  194. data/assets/js/search/render.js +0 -217
  195. data/assets/js/search/utils.js +0 -99
  196. data/assets/js/search.js +0 -354
  197. data/assets/js/visualizations.js +0 -816
  198. data/assets/publications/datalog-publications.bib +0 -8
  199. data/assets/publications/datalog-publications.ris +0 -9
  200. data/assets/publications/publications.bib +0 -30
  201. data/assets/templates/diogo-ribeiro-cv.md +0 -31
  202. data/assets/templates/diogo-ribeiro-cv.tex +0 -32
  203. 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 };