datalog-theme 0.6.1 → 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 +175 -0
- data/CITATION.cff +2 -2
- data/README.md +26 -19
- 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/author-bio.html +2 -2
- data/_includes/components/enhanced-code-block.html +1 -1
- data/_includes/components/hero.html +19 -1
- data/_includes/csp-meta.html +115 -11
- data/_includes/footer.html +19 -20
- data/_includes/head.html +61 -29
- data/_includes/header/navigation.html +12 -15
- data/_includes/header.html +29 -20
- data/_includes/layouts/default/article.html +5 -1
- data/_includes/meta/math-config.html +27 -1
- data/_includes/meta/schema.html +5 -2
- data/_includes/meta/scripts-loader.html +16 -31
- data/_includes/post/related-posts.html +4 -7
- data/_includes/scripts.html +1 -9
- data/_includes/search/index-data.json +131 -0
- data/_includes/search/page.html +136 -0
- data/_layouts/dataset.html +1 -0
- data/_layouts/default.html +16 -8
- data/_layouts/home.html +6 -0
- 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 +36 -3
- data/_plugins/notebook_converter.rb +23 -43
- 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 +72 -0
- data/_sass/_academic-dashboard.scss +262 -0
- data/_sass/_base.scss +19 -1
- data/_sass/_components.scss +77 -1144
- data/_sass/_features.scss +17 -0
- data/_sass/_font-fallbacks.scss +43 -0
- data/_sass/_header.scss +10 -0
- data/_sass/_layout.scss +18 -12
- data/_sass/_mathematical.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} +46 -1
- data/_sass/_search-page.scss +530 -0
- data/_sass/_search.scss +47 -1
- data/_sass/_syntax-highlighting.scss +212 -97
- data/_sass/_theme.scss +42 -18
- data/_sass/_typography.scss +14 -0
- data/_sass/_variables.scss +7 -4
- data/assets/css/main.scss +14 -0
- data/assets/img/hero-detail-640.webp +0 -0
- data/assets/img/hero-detail.webp +0 -0
- data/assets/img/social-card.png +0 -0
- data/assets/js/dist/academic.js +1 -0
- data/assets/js/dist/analytics-dashboard.js +1 -0
- data/assets/js/dist/chunks/chunk-225H5YXE.js +1 -0
- data/assets/js/dist/core.js +1 -0
- data/assets/js/dist/loader.js +1 -0
- data/assets/js/dist/math.js +1 -0
- data/assets/js/dist/notebook.js +1 -0
- data/assets/js/dist/search.js +1 -0
- data/assets/js/dist/visualizations.js +11 -0
- data/assets/js/loader.js +3 -1
- data/datalog-theme.gemspec +43 -22
- data/lib/datalog/cli.rb +53 -15
- 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 +21 -0
- metadata +75 -146
- data/_data/academic.yml +0 -217
- data/_data/config/author.yml +0 -121
- data/_data/config/features.yml +0 -262
- data/_data/config/site.yml +0 -42
- data/_data/config/theme.yml +0 -181
- 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/_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/img/20220607123041_detail.001.png +0 -0
- 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/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 -38
- 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
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 76c51ad2ebacf140c696deb3abdf2b8bff74bd31a9594533ddd65bd9c9a3aba4
|
|
4
|
+
data.tar.gz: 5b9d40c77ee4e740774d09ce6fd5c26a6f16c8c92da17d69a611e0a3d00cc930
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 06a2ac68844fdc67bbed3abb7640d1ac13920964454dda355e5c08fb8d0627cbae16d1585677695b94d92bf6e9a568b427ed59871bf5ec2aa2ad02fcbd2f60b8
|
|
7
|
+
data.tar.gz: 8616c20c4894822cc7b047a83668b5f42d58b4e11799320273b697423e4af3e2aa498824e175f65c03fae05fc29793663ed859435a7f640c0e0ab85b7a6f71d1
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,181 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
4
4
|
|
|
5
|
+
## [0.8.0] - 2026-09-14
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- `tests/test_csp_pages.rb` checks that every nonce in a page matches its policy, that MathJax and Disqus pages get what they load, and that Observable's classic embeds may be framed (#196).
|
|
10
|
+
- `csp.script_src`, `csp.style_src`, `csp.font_src` and `csp.connect_src` in `_config.yml` add sources to the Content Security Policy, as `csp.frame_src` does for iframes (#196).
|
|
11
|
+
- The policy sets `object-src 'none'`, `base-uri 'self'` and `form-action 'self'`. None of them falls back to `default-src`, so all three were open (#196).
|
|
12
|
+
- `tests/test_csp.rb` checks which pages get the looser policy. `tests/integration/csp-charts.spec.js` loads the real Plotly and widget manager, checks that the chart and the widget render, and fails on any script or style violation. Unit tests in `tests/js/visualizations.test.js` cover the order in which chart libraries and require.js load (#195).
|
|
13
|
+
- A `rouge_highlight` Liquid filter highlights code passed to an include as the site builds. The package API examples and the enhanced code block, which printed its code unescaped, use it, and the notebook converter highlights code cells the same way (#197).
|
|
14
|
+
- The head preloads the visualization, notebook and academic bundles on the pages that use them, as it already did for search and math, so they download alongside the core bundle instead of after it (#197).
|
|
15
|
+
- `tests/test_rouge_highlighting.rb` checks that code is highlighted as the site builds and that pages load no Prism. `tests/test_feature_loading.rb` checks the new preloads and which pages inline the academic data, and a Playwright test checks that the copy button labels the language and leaves out line numbers (#197).
|
|
16
|
+
- Ruby Tests jobs on Ruby 3.3 and 3.4 in the Tests workflow run the Ruby suite on the newer releases, next to the existing job on 3.2. `tests/test_gem_package.rb` checks the Ruby requirement, that every runtime dependency has an upper bound, that the unused and optional gems stay out, and which script files the gem ships (#203).
|
|
17
|
+
- `tests/test_site_output.rb` checks that every in-page link on the built site reaches an element on that page (#206).
|
|
18
|
+
- A Docker Images workflow builds `Dockerfile` and `Dockerfile.dev`, without pushing, on pull requests that change what they are built from (#205).
|
|
19
|
+
- `bundle exec rake test` builds the demo site and runs the Minitest suite, the same command as the Tests workflow, and is the default Rake task. `tests/test_site_output.rb` takes over what the `ci:verify` scripts checked and no other suite did: `CITATION.cff` matching the theme version, citation exports and scholar metadata on posts, the math status live region, `noopener` on every link that opens a new tab, and sandboxed app embeds. The browser suite checks that code blocks in a post get a labelled copy button, which the post layout adds when the page loads (#204).
|
|
20
|
+
- A Lint job in the Tests workflow runs ESLint and RuboCop, and the test summary fails when it does. Both linters were configured in the repository but ran in no workflow. RuboCop is now a development dependency, pinned because the repository has no `Gemfile.lock`; the offenses that predate the job are listed in `.rubocop_todo.yml`, so new code has to pass (#204).
|
|
21
|
+
- `tests/test_workflows.rb` checks the release and CI guards described below, and `tests/js/cdn-integrity.test.js` runs the Subresource Integrity check from `tests/test_sri.js`, a script no test command ran (#204).
|
|
22
|
+
- `tests/test_gem_consumer.rb` builds a minimal site against the packaged theme and against a checkout of the repository, and fails if the build breaks or publishes anything that identifies the maintainer.
|
|
23
|
+
- `tests/test_navigation_cache.rb` checks that each section still marks only its own navigation link now that the navigation is cached.
|
|
24
|
+
- The performance tests fail if the stylesheet grows past 25 KB gzipped, as they already did for the core script bundle.
|
|
25
|
+
- `tests/test_related_posts.rb` checks that a post lists the posts it shares a tag with.
|
|
26
|
+
- `csp.frame_src` in `_config.yml` lists the hosts a site embeds iframes from, such as Shiny apps, slide decks or videos, and the Content Security Policy allows them next to Observable.
|
|
27
|
+
- `tests/test_feature_loading.rb` checks which pages load MathJax and the search bundle.
|
|
28
|
+
- `show_title: false` in a page's or a layout's front matter leaves out the title the default layout prints, for pages and layouts that render their own `<h1>`.
|
|
29
|
+
- `tests/test_page_structure.rb` checks that no built page has more than one `<h1>`, the footer's headings and landmark name, the color scheme script at the top of `<body>` and the heights of the academic chart's bars. `tests/js/blocked-storage.test.js` covers dark mode and the core initializers with storage blocked, and the browser suite checks that the saved theme applies before any script bundle loads and that the core bundle still loads when storage is blocked.
|
|
30
|
+
- `tests/test_head_metadata.rb` checks that each head tag appears once, that empty verification tags are left out, that the 404, search and admin pages carry `noindex` and stay out of the sitemap, and that every page's JSON-LD parses without empty values.
|
|
31
|
+
- Tests for the fixes to the config validator, the warning filter, notebook images and languages, the analytics cache, plugin hook registration, `{% t %}` options, `datalog publish` and `datalog new post`, in the existing test files for each.
|
|
32
|
+
|
|
33
|
+
### Changed
|
|
34
|
+
|
|
35
|
+
- Each page's Content Security Policy allows only the jsDelivr packages that page loads: the math engine's directory, and Plotly, D3, BokehJS, Vega or Chart.js where the page uses them. The policy allowed all of jsDelivr, which serves any npm package, on every page. Widget pages still allow all of jsDelivr, and they are the only pages that allow require.js from cdnjs (#196).
|
|
36
|
+
- Google's analytics hosts are in the policy only on a site that sets `google_analytics`. They are the hosts Google documents for GA4, including the regional `*.google-analytics.com` hosts GA4 reports to (#196).
|
|
37
|
+
- The Content Security Policy is looser on pages with a Plotly or ipywidgets block and unchanged on every other page. Plotly pages allow inline styles in place of the style nonce. Widget pages also allow `'unsafe-eval'` and fonts from jsDelivr. A page that loads either library another way can set `csp.unsafe_inline_styles` or `csp.unsafe_eval` in its front matter (#195).
|
|
38
|
+
- Code is highlighted by Rouge alone, when the site builds. Pages with code also loaded Prism from jsDelivr (seven scripts and two stylesheets on a post), which highlighted the blocks again in the browser and turned every language it had no grammar for, such as bash and yaml, into plain text. The theme now styles Rouge's tokens and line numbers in light and dark mode, in greys that meet 4.5:1 contrast (the comment grey Prism used measured 2.33:1 in light mode), and gives every code block tabindex="0", as Prism did, so a wide block can be scrolled from the keyboard. Search results show code snippets as plain text (#197).
|
|
39
|
+
- The academic and publication data is inlined only on pages that render citation metrics, tables or charts, the only pages whose script reads it. On the home page it was nearly a quarter of the HTML (#197).
|
|
40
|
+
- The image optimizer fetches one image per page early: the first image in the post or page content, and none on a page that preloads its hero. It gave the first image anywhere on the page both `loading="lazy"` and `fetchpriority="high"`, which was a post card below the hero on the home page and a related-post thumbnail at the bottom of tutorials (#197).
|
|
41
|
+
- Google Fonts is asked for the eight weights the stylesheet uses instead of eleven, and the font stylesheet link no longer repeats its `media` and `data-async-style` attributes (#197).
|
|
42
|
+
- The gem requires Ruby 3.2, the version the sass-embedded and nokogiri releases it resolves need; it claimed 3.0. Every runtime dependency is bounded below its next major version (`~> 1.15` rather than `>= 1.15`), so a breaking release arrives through a pull request instead of an untested `bundle update` (#203).
|
|
43
|
+
- `googleauth` is no longer a dependency of the theme. Only the analytics dashboard with a GA4 property configured uses it, and every site installed it with its Google Cloud dependencies; a site that uses the dashboard adds `gem "googleauth"` to its Gemfile, and without it the dashboard says so (#203).
|
|
44
|
+
- The Docker images build on `ruby:3.4-slim` and serve from `nginx:1.30-alpine`. `ruby:3.2-slim` is end of life, and 1.27 was an nginx mainline branch that no longer gets releases (#203).
|
|
45
|
+
- The pre-commit hook runs lint-staged only: ESLint and the Vitest tests related to the staged JavaScript. It used to run `npm audit`, which needs the network, and the whole Vitest suite on every commit; both still run on every pull request (#205).
|
|
46
|
+
- Dependabot pull requests are titled `chore(deps)`, `chore(deps-dev)` and `ci(deps)`. The prefixes repeated the scope Dependabot appends, which gave titles like `chore(deps-dev)(deps-dev)` (#205).
|
|
47
|
+
- The accessibility, broken link, dependency review and Lighthouse workflows cancel a pull request's superseded runs, the accessibility workflow installs a pinned `pa11y-ci` and uses the `http-server` devDependency, and `package.json` is marked private so `npm publish` refuses to publish the repository's tooling (#205).
|
|
48
|
+
- `gem-release.yml` publishes only from a `v*` tag, a manual run included, and stops when the tag does not match `lib/datalog/theme/version.rb`. The tag job in `release.yml` builds the script bundles and the gem and runs `scripts/verify_gem_package.rb` before it creates the tag, so a broken package no longer leaves a tag and a GitHub release for a gem that never published (#204).
|
|
49
|
+
- The Python security audit runs `pip-audit` on `requirements.txt`. It used to collect `import` lines from `scripts/`, which name modules rather than packages, and ignore every result (#204).
|
|
50
|
+
- `search.json` no longer stores a normalized copy of each document's title, summary, content, tags and languages. The search engine normalizes them in the browser, once per document, with the function it applies to queries; the copy was 41% of the file, and queries and documents had been normalized by different code. With the code blocks below added, the demo's index goes from 219 KB to 137 KB.
|
|
51
|
+
- The Tests workflow runs the Playwright suite and enforces the coverage thresholds on pull requests. The coverage steps waited for a Node 20 leg the matrix no longer has, and the browser specs only ran in the deploy after a merge, so both kinds of failure surfaced on `develop` instead of on the pull request.
|
|
52
|
+
- MathJax loads only on pages with math, and the search bundle only on the search page. With `render_on_load: auto`, MathJax loaded wherever a dollar sign or an escaped parenthesis appeared in the rendered page, including shell variables, prices and inline scripts, and the demo also turned it on for every post; it now follows the expressions the math preprocessor finds, and on the demo loads on 6 pages instead of 28. The search bundle was preloaded and run on every page because the header's search form matched the loader's check; it now loads on the one page that renders the search app.
|
|
53
|
+
- The release workflow promotes a `release/vX.Y.Z` branch to `main` instead of promoting `develop` itself, so the pull request and the merge commit on `main` name the release rather than reading "from develop". `develop` still receives the version bump.
|
|
54
|
+
- The stylesheet carries the styles of an optional feature only when the site uses it: search (`features.search`), visualizations (`features.visualizations`), notebook pages, the `packages` collection, the academic dashboard (`features.academic_dashboard`) and open science badges (badges in `_data/academic.yml`). `assets/css/main.scss` configures the new `_sass/_features.scss` from the site's settings, and each partial loads those styles at the position they always had, so a site with every feature on gets the same stylesheet byte for byte. With all six off it shrinks from 169 KB to 122 KB, or from 27.6 KB to 20.5 KB gzipped. A site that replaced `main.scss` with a plain `@use "theme"` keeps the complete stylesheet. `_sass/_phase1-enhancements.scss` is now `_sass/_post-components.scss`.
|
|
55
|
+
- The layouts use `jekyll-include-cache`, a dependency the theme already declared but never used. The footer and skip link are rendered once per build (the skip link once per page language) and the header navigation once per distinct current section, where each was rendered on every page before: on the demo site the navigation renders 10 times instead of 53. The CSP meta tag, the script loader and the analytics snippet stay per page because each carries that page's CSP nonce. Requiring the theme now also loads `jekyll-include-cache`.
|
|
56
|
+
- The documentation is organised by task. `docs/README.md` indexes the guides by what a reader wants to do; the phase summaries, the configuration refactoring plan and the 2025 security audit moved to `docs/history/` under a note that they are not maintained; and the Phase 1 features guide became `docs/components.md`, without the `phase1_features` settings the theme never read and with instructions that work for a site using the gem. The installation guide lost its leftover citation markers, and the README and the starter template pin the current `~> 0.7` series.
|
|
57
|
+
- The installation guide covers what a site supplies itself (pages, navigation, social links), installing from a Git checkout, and publishing to GitHub Pages with GitHub Actions. It replaces instructions for the built-in Pages build, which cannot run the theme.
|
|
58
|
+
|
|
59
|
+
### Deprecated
|
|
60
|
+
|
|
61
|
+
- `theme_options.syntax_highlighting` no longer has an effect, and a build that sets it prints a warning (#197).
|
|
62
|
+
|
|
63
|
+
### Removed
|
|
64
|
+
|
|
65
|
+
- The CSP generator's inline script hashes. It computed them after a page had rendered, too late to reach the policy written into its head, and every inline script already carries the nonce (#196).
|
|
66
|
+
- Prism: its scripts and stylesheets, their SRI entries, the `meta/syntax-config.html` include, the `syntax_highlighting` page setting and the `theme_options.syntax_highlighting` block in the demo configuration (#197).
|
|
67
|
+
- `window.DatalogTheme` and `window.DatalogContent`, which every page inlined and no script read (#197).
|
|
68
|
+
- `jekyll-archives` and `jekyll-remote-theme` from the gem's dependencies, which nothing in the theme used, and the 22 unbundled script sources from the gem. Pages load the bundles in `assets/js/dist` and `assets/js/loader.js`; every site copied the sources into its published output as well. A site that installs the theme from a checkout still has them (#203).
|
|
69
|
+
- Settings in the demo `_config.yml` that nothing reads: `features.math_toolkit`, `math_search`, `accessibility_skip_link`, `academic_calendar` and `notebook_support`, `theme_options.math.equation_numbering`, and `integrations.binder` and `integrations.colab`, whose buttons are configured under `notebooks:` (#206).
|
|
70
|
+
- `rake ci:verify` and its twelve scripts in `scripts/`. Most checked that source files contained particular strings, repeated what Minitest, Vitest and Playwright already cover, and passed whether or not the built site worked. The Tests workflow no longer sets up Python, which only one of them needed (#204).
|
|
71
|
+
- `project-sync.yml`, which only printed what it would have done, and `tests/test_critical_css.js`, `tests/test_search_accessibility.js` and `tests/test_viz_accessibility.js`, which no test command ran and which failed against the current sources (#204).
|
|
72
|
+
- `lib/datalog/theme/theme.rb`, a theme registration hook that nothing required.
|
|
73
|
+
- Includes and layouts that no layout, page or plugin used, with the styles written for them: the `archive` and `post-sidebar` layouts, and the user preferences panel, popular posts, back-to-top button and keyboard shortcuts panel (`navigation-enhancements`), social proof, enhanced metadata, reading progress, reading time, content recommendations, comments, language switcher, bookmark, email preferences, advanced search, newsletter signup and series navigation includes. Several read `phase2_features` to `phase5_features` settings that nothing defined. Comments still render through the `datalog-comments` plugin. The rules in those stylesheets that did style rendered pages (the `kbd` element, fieldsets, `.button` and the search result cards) moved to the partials for what they style, and `_sass/_phase3-enhancements.scss`, `_phase4-enhancements.scss` and `_phase5-enhancements.scss` are gone. Together with the feature gating above, the demo's stylesheet goes from 169 KB to 134 KB (27.6 KB to 23 KB gzipped), and a site with every optional feature off gets 85 KB (15.7 KB gzipped).
|
|
74
|
+
|
|
75
|
+
### Fixed
|
|
76
|
+
|
|
77
|
+
- MathJax typesets math again. Its configuration loaded the `\require` extension, which stopped MathJax 3.2 while starting up (`Illegal characters used in \require prefix`), so no page rendered an equation. Every extension the pages use is loaded directly, so authors don't need `\require`.
|
|
78
|
+
- Posts with math no longer throw `Cannot read properties of undefined (reading 'then')`. The post layout read `MathJax.startup.promise` before MathJax had loaded; MathJax now announces typeset math with a `datalog:math-ready` event.
|
|
79
|
+
- Equations are no longer taken out of the tab order. MathJax's explorer gave each one `tabindex="1"`, which axe reports; it is turned off, and the assistive MathML screen readers use stays on.
|
|
80
|
+
- The math preprocessor's wrapper has `role="math"`. It carried an `aria-label` with no role, which ARIA forbids, and axe failed the page once MathJax rendered the expression inside it.
|
|
81
|
+
- Notebook pages run their inline scripts. The pages are created after the CSP generator assigns nonces, and their templates printed an empty `page.csp_nonce`, so the browser refused every inline script in the head. MathJax's inserted stylesheet is allowed on math pages.
|
|
82
|
+
- Bokeh blocks render. The theme loaded BokehJS's core bundle, which has no `Bokeh.Plotting`; it now loads the API bundle too, and logs a failed load instead of ignoring it.
|
|
83
|
+
- Disqus comments load. The policy refused Disqus's script, stylesheet, iframe and the inline style that sizes the iframe.
|
|
84
|
+
- Observable embeds display. An `observablehq.com` embed redirects to `old.observablehq.com`, which the policy refused. The demo's two embeds pointed at notebooks that return 404 and now embed D3's zoomable sunburst and bar chart.
|
|
85
|
+
- The demo post's slide deck loads. It pointed at a host that does not exist; it now embeds the reveal.js demo deck, and `revealjs.com` is in the demo's `csp.frame_src`.
|
|
86
|
+
- KaTeX's fonts load. The policy refused the fonts its stylesheet requests from jsDelivr (#196).
|
|
87
|
+
- Plotly charts render. Plotly inserts its rules into a `<style>` element it creates, which the policy refused, so every Plotly block reported that Plotly failed to load (#195).
|
|
88
|
+
- Jupyter widgets render. The policy refused the widget manager's `<style>` elements, the `new Function` it compiles widget schemas with, and its icon fonts. The theme also called a `WidgetManager` that `@jupyter-widgets/html-manager` does not export, and the error was swallowed; it now uses `HTMLManager` (#195).
|
|
89
|
+
- A page with a widget no longer loses its Plotly, D3 or BokehJS chart depending on which script loads first. require.js, which the widget manager loads, made a bundle that ran after it register as an anonymous module, and require.js threw `Mismatched anonymous define()`. Bundles requested after require.js now load through it (#195).
|
|
90
|
+
- The package API include's "See Also" list treated its comma-separated `see_also` string as a single item, so every list became one link to an anchor that did not exist; on the StatFlow page six of them led nowhere. It now splits the list, and StatFlow only lists functions it documents. The Plotly showcase post's contents linked to a heading written as raw HTML without an id, which now has one (#206).
|
|
91
|
+
- Documentation that contradicted the code: the testing guide and the coverage review process quoted coverage thresholds of 20% and 80% where `vitest.config.js` enforces 88/78/83/88; the testing guide still listed Percy; the configuration guide described a comments configuration the plugin does not read, Binder and Colab settings nothing reads, and the MathJax detection #194 replaced; the user guide sent notebook metadata to an unread `_data/notebooks.yml` and Binder links to an unread `integrations.notebooks`; `_config.yml` pointed at `_data/config` files that do not exist; `_data/config/author.yml` linked to a missing page; and the Minimal Mistakes post linked to a docs page the site does not build (#206).
|
|
92
|
+
- Neither Docker image built. `Dockerfile` copied a `Gemfile.lock` the repository does not have, then built the script bundles without esbuild, a dev dependency it had skipped; `Dockerfile.dev` ran `bundle install` without the gemspec the Gemfile loads. Both copy what the gemspec requires, install the OpenSSL and YAML headers that gems such as `openssl` compile against, drop the Python they installed for a notebook check that is gone, and use Node.js 22 like CI (#205).
|
|
93
|
+
- The config validator stopped a build with "Invalid type for 'author'" for `author: Jane Doe`, and with "Invalid value for 'url'" for `url: ""`, which `jekyll new` writes. Both are accepted (#202).
|
|
94
|
+
- Loading the theme broke `warn` keyword arguments for the whole build: a `Kernel#warn` override printed `uplevel:` and `category:` as a hash after the message. The override is gone; the `Warning` filter beside it still silences the same two messages (#202).
|
|
95
|
+
- Notebook images whose base64 data Jupyter had split over lines or ended with a newline failed the data URI check and lost their `src`. The data is joined without whitespace first (#202).
|
|
96
|
+
- A notebook's language went into a code cell's `class` attribute unescaped; it is now cut down to the characters a class name can hold (#202).
|
|
97
|
+
- The analytics dashboard cached a missing-configuration or error report for a day, so after `GA4_PROPERTY_ID` was set it went on saying analytics wasn't configured. Only successful reports are cached (#202).
|
|
98
|
+
- Every DataLog plugin hook ran twice for each post: the loader registered its hooks for posts as well as documents, and Jekyll fires both for a post (#202).
|
|
99
|
+
- `{% t %}` split its options on every comma, so a quoted value such as `name: "Doe, Jane"` reached the translation as a fragment (#202).
|
|
100
|
+
- `datalog publish` built without `JEKYLL_ENV=production`, so the published site left out the analytics tag and included the development CSP logger, and it ignored the exit status of `git commit` and `git push`, so a rejected push still ended as a publish. It builds for production and exits with an error when either step fails (#202).
|
|
101
|
+
- `datalog new post` wrote the title, summary, author and tags between plain quotes, so a title with a double quote or a tag with a colon produced front matter that didn't parse (#202).
|
|
102
|
+
- The `datalog_slides`, `datalog_comments` and `datalog_bibliography` fallback tags, which stand in when their plugin is disabled, printed "feature coming soon", the slides one with the page's raw configuration, on a page that set the key by hand. They render nothing and log a warning naming the plugin to enable (#202).
|
|
103
|
+
- Search never matched code: every document's code list in `search.json` was empty, because the index template split the content on backticks after Jekyll had already rendered posts to HTML. `_plugins/search_code_blocks.rb` collects fenced code blocks from the source before rendering, and the demo's index now carries 34 of them (#198).
|
|
104
|
+
- The 404, search and admin pages asked search engines to index them, the search and admin pages were listed in `sitemap.xml`, and all three appeared in site search. The robots tag now comes from `robots:` in front matter, and those pages set `noindex`, `sitemap: false` and `exclude_from_search: true` (#198, #199).
|
|
105
|
+
- Every page carried the `keywords`, `format-detection` and jsDelivr `preconnect` tags twice, written by both `head.html` and the default layout, and empty Google, Bing, Yandex and Baidu verification tags when the site set no codes (#199).
|
|
106
|
+
- The JSON-LD had `"dateModified": ""` on 26 pages, `"description": ""` where a page had no description, and `"headline": null` on the home page. Values a page doesn't have are left out, and the headline falls back to the site title (#199).
|
|
107
|
+
- A blocked `localStorage` stopped every script feature on the page. Where storage access throws (Safari with all cookies blocked, sandboxed iframes, some privacy extensions), the dark mode toggle threw while the core bundle loaded, the loader gave up, and search, math, visualizations and the academic features never started. Dark mode now treats blocked storage as no saved choice, and each core initializer runs on its own, so a failure is logged without stopping the others (#201).
|
|
108
|
+
- Readers who chose the dark theme saw each page in the light theme first, because the core bundle applied the theme after the page had been drawn. A small nonced script at the top of `<body>` now applies the saved or system choice before anything paints (#201).
|
|
109
|
+
- GitHub repository cards kept their "—" placeholders when the API request failed, with no sign the numbers weren't coming, and asked again on every page view against the unauthenticated limit of 60 requests an hour. A card whose request failed now shows the translated "N/A" and is marked `data-github-state="error"`, and the failure is remembered for ten minutes (#201).
|
|
110
|
+
- Fourteen demo pages had more than one `<h1>`: the default layout printed the title, and so did the dataset, project, portfolio, notebook and package layouts, the 404 page, the archive, category and tag pages and the CV page. Those layouts and pages now set `show_title: false`. Headings in notebook markdown cells move down a level, since a notebook usually opens with its title, and package API examples render as code rather than Markdown, which had turned every Python comment into a heading (15 `<h1>`s on the StatFlow page) (#200).
|
|
111
|
+
- The footer's column titles were `<h3>` regardless of the page above them, and its navigation was an unnamed landmark next to "Primary navigation". The titles are `<h2>` with the same look, and the navigation takes its name from the "Explore" heading (#200).
|
|
112
|
+
- Screen readers announced "Reading progress: N%" on every scroll event, because the percentage sat in a live region. The live region is gone; the progress bar stays hidden from assistive technology (#200).
|
|
113
|
+
- On narrow screens, Escape moved focus to the menu button even with the menu closed, for example while clearing the search field. It now acts only when the menu is open (#200).
|
|
114
|
+
- The bars of the citations-by-year chart on `/academic/` had no height: each set it in a `style` attribute, which the Content Security Policy drops. The heights now come from a nonced style block (#195).
|
|
115
|
+
- Related posts never appeared: the list of posts was split into single characters before it was filtered, so every post said "No related posts yet".
|
|
116
|
+
- Search dropped every letter outside ASCII from its index, so accented, Greek, Cyrillic and CJK words could not be found, and every build printed "[search_normalizer] unicode_normalize gem not available": `String#unicode_normalize` is part of Ruby, not a gem. The browser also cut queries down to the letters a to z; both now keep letters of any script.
|
|
117
|
+
- The search page trapped keyboard focus: Tab from the input or any filter cycled through the filters, so the results could not be reached.
|
|
118
|
+
- Search results inserted text from the index as HTML, and highlighting several words could put one `<mark>` inside the tags of another ("remark" became `re<<mark>ma</mark>rk>`). Results and suggestions are now escaped and highlighted in one pass, and index content is stripped of markup in an inert document.
|
|
119
|
+
- A `_data/publications.yml` written as a list of entries stopped the build with a `TypeError`. A list is now read as the manual entries.
|
|
120
|
+
- The math preprocessor wrapped dollar signs inside code as math, inserting markup into shell, R and SQL snippets, and read prices such as "$5 a month, or $50 a year" as an expression. Fenced code, highlight tags and inline code are left alone, and inline math follows Pandoc's rule: the opening `$` is followed by a non-space, and the closing `$` follows one and is not followed by a digit.
|
|
121
|
+
- The analytics dashboard never rendered: its script uses `export` but was loaded as a classic script from the unbundled source, which failed to parse. It now loads as a module from the built bundle.
|
|
122
|
+
- The Copy buttons of the citation tools on posts, datasets and projects did nothing: their handler lived in the academic bundle, which those pages never load. The core bundle now handles them.
|
|
123
|
+
- Visualizations were refused by the theme's own Content Security Policy. D3 and scripted Bokeh blocks ran their code with `new Function`, which the policy refuses; the code now runs as a script carrying the page's nonce. Plotly and Bokeh loaded from hosts the policy does not list, and Bokeh also requested a stylesheet BokehJS 3 does not publish; both load from jsDelivr now. Observable blocks ignored `data-viz-src`, the attribute the user guide documents; they now accept it, and take embed addresses only from observablehq.com, so a `javascript:` or `data:` URL in the markup never becomes the frame's source. Iframes from any host but Observable were refused. On the demo, the D3 chart, the Observable embed and the Shiny app now render in Chromium. Plotly and ipywidgets charts still fail, because those libraries insert inline styles or evaluate strings, which the policy forbids, and Bokeh has not been confirmed to render.
|
|
124
|
+
- Sites installing the gem published part of the demo site. The maintainer's CV templates and publication exports were copied into every site, and the demo's social profiles, contact addresses and academic profiles reached the footer and the script data on every page through `_data`. The gem now contains only the `_data` files the layouts need (translations, the script manifest and CDN integrity hashes) and none of the demo's downloads, and `scripts/verify_gem_package.rb` refuses a gem that does.
|
|
125
|
+
- A site installing the theme from a Git checkout or a local path inherited the whole demo site. Jekyll merged the demo's `_config.yml` into the site's configuration, so the build stopped on a `datasets` feed for a collection the site did not have, and a site that declared the collection to get past it carried the maintainer's author details, contact addresses and social profiles. The build now stops with an explanation until the site sets `ignore_theme_config: true`, and with that set the theme also leaves out the demo's `_data` files and downloads.
|
|
126
|
+
- The repository and the gem carried `_data/js_meta.json`, the esbuild metafile, whose committed copy had fallen behind the sources: its byte counts described an older build than the bundles it shipped with, and running `npm run build:js` left it modified. The metafile now stays with the bundles in `assets/js/dist/` and out of the gem. The build also no longer rewrites an unchanged `_data/js_manifest.json`, which Windows checkouts reported as modified because of line endings, and the test and gem release workflows fail if the committed manifest does not match the sources.
|
|
127
|
+
- The README said notebooks publish under `/blog/` and that GitHub Pages builds a site with the `github-pages` gem. Notebooks publish under `/notebooks/`, and the build GitHub Pages runs by itself cannot load the theme's plugins, so the README now points to the GitHub Actions workflow in the installation guide.
|
|
128
|
+
- Without `_data/navigation.yml` the header and footer linked to the demo's sections (Research, Projects, Datasets, Academic Ops), which a site using the theme does not have, and the header and footer showed "DataLog" rather than the site's title. The navigation and the footer's "Explore" and "Connect" columns are now left out when there is nothing to list, and the name falls back to `title`.
|
|
129
|
+
|
|
130
|
+
## [0.7.0] - 2026-09-12
|
|
131
|
+
|
|
132
|
+
### Added
|
|
133
|
+
|
|
134
|
+
- `tests/test_search_pages.rb` covers the generator: both pages when search is on, neither when it is off or unconfigured, and no duplicate when the site provides its own.
|
|
135
|
+
- The README carries a badge showing the version published on RubyGems, linking to the gem page.
|
|
136
|
+
- `scripts/verify_gem_package.rb` checks that a built gem contains every bundle its manifest references; the release workflow builds the bundles and runs it before publishing.
|
|
137
|
+
- `tests/test_gem_package.rb` covers what a site using the gem needs: the bundles are packaged, the plugins' gem dependencies are declared, and requiring the theme registers its Liquid tags.
|
|
138
|
+
- The search index test checks that tags are whole tags rather than only that the field is an array.
|
|
139
|
+
- The integration suite runs axe-core over six pages in both light and dark mode, so contrast, missing accessible names and misplaced ARIA cannot regress unnoticed.
|
|
140
|
+
- A social card image (`assets/img/social-card.png`), so the Open Graph and Twitter image tags no longer point at a missing file.
|
|
141
|
+
- The release workflow now does a release in one run plus one pull request: "Run workflow" with a version bumps `develop` and opens the PR into `main`; merging it tags `main`, publishes the GitHub release and starts the gem publish.
|
|
142
|
+
|
|
143
|
+
### Changed
|
|
144
|
+
|
|
145
|
+
- MathJax is only loaded on pages that contain math (`theme_options.math.render_on_load: auto`, the new default of the demo site) and Prism only on pages with a code block (`theme_options.syntax_highlighting.load: auto`); pages can still opt in or out with `math:` and `syntax_highlighting:` front matter, and a page with `math: false` is also left alone by the math preprocessor. Pages without either skip about 400 KB of CDN scripts and stylesheets.
|
|
146
|
+
- The IBM Plex web fonts fall back to local fonts scaled to Plex's metrics, so the swap once the web font arrives no longer moves the layout, and the Google Fonts stylesheet no longer blocks rendering.
|
|
147
|
+
- The home hero image is preloaded and small screens get a 640 px variant (`hero_image_small` for pages that set their own `hero_image`).
|
|
148
|
+
- The Lighthouse workflow inlines critical CSS before building, as the deploy does, so it measures the published configuration.
|
|
149
|
+
- CI jobs install only what they use: the Jekyll test job no longer installs libvips (the image plugin uses MiniMagick, which the runners already provide) or keeps redundant pip and `_site` caches, and the accessibility, Lighthouse and deploy workflows no longer set up Python, which only the Rake verification task needs.
|
|
150
|
+
- The hero background is served as a 46 KB WebP instead of a 1.27 MB PNG.
|
|
151
|
+
- Footer text and links, and the skip link in dark mode, meet the 4.5:1 contrast ratio; the blog listing uses second-level headings for its cards.
|
|
152
|
+
- The Tests workflow runs for pull requests into `main` as well as `develop`; the duplicate theme-stability workflow is gone.
|
|
153
|
+
- The configuration guide documents where settings actually live (`_config.yml` plus `_data/config/author.yml`).
|
|
154
|
+
- The gem publish can authenticate with RubyGems trusted publishing (OpenID Connect) instead of a stored API key; the `RUBYGEMS_TRUSTED_PUBLISHING` repository variable selects it.
|
|
155
|
+
|
|
156
|
+
### Fixed
|
|
157
|
+
|
|
158
|
+
- Sites installing the gem had the search interface and its JavaScript but no search: the page that renders it and the one that builds its index are pages, which a theme gem cannot ship. Both are generated now for any site with `features.search` enabled, and a site that defines either path keeps its own.
|
|
159
|
+
- The published gem could not be used. Jekyll reads `_plugins/` for a site but not for a theme gem, and `lib/datalog-theme.rb` did not load them, so the tags the layouts use were never registered and every consumer site failed to build with `Unknown tag 't'`. Naming the theme under `plugins:` now loads them.
|
|
160
|
+
- The gem shipped `_data/js_manifest.json`, which points every page at the browser bundles, without the bundles themselves: `assets/js/dist/` is build output that git does not track, and the gemspec selected files with `git ls-files`. Sites using the theme loaded no JavaScript at all.
|
|
161
|
+
- The gemspec did not declare `loofah`, which the notebook plugin requires, so loading the theme raised `cannot load such file -- loofah`.
|
|
162
|
+
- The home layout sorted `site.portfolio`, which is nil unless a site declares that collection, and sorting nil stops the build. The section is skipped when the collection is absent.
|
|
163
|
+
- The search index shipped every tag as a list of single characters, so the tag filter on the search page offered 34 buttons reading `a`, `b`, `[`, `"` and so on instead of the 48 real tags. A `split: ''` in the index template turned each tag array into its string form before splitting it.
|
|
164
|
+
- A tag consisting only of whitespace produced a filter button with no accessible name at all, which fails WCAG 4.1.2.
|
|
165
|
+
- The fallback author avatar carried an `aria-label` on a plain `div`, where ARIA prohibits it, so screen readers announced nothing for it. It is now an image role, matching the photo it stands in for.
|
|
166
|
+
- Text set in the teal accent failed WCAG AA everywhere it appeared, reaching only 3.0:1 to 3.5:1 on post badges, skill tags, search highlights and Prism keywords. Teal text now uses a darker tone; the original teal stays for fills and borders.
|
|
167
|
+
- Dark mode had several unreadable components, none of which any check covered: the citation tools kept light backgrounds under light text, leaving a heading white on white at 1.09:1, and difficulty badges kept their light-mode text colour on a near-black pill at 1.93:1.
|
|
168
|
+
- Buttons marked `btn--ghost` were never styled, so they fell back to the browser's own button chrome and could not follow the theme.
|
|
169
|
+
- The Playwright and coverage reports were copied into the built site and published with it. Both are excluded now, and the Playwright report is also ignored by git.
|
|
170
|
+
- `datalog check` reported every dependency as missing on Windows, including bundler, which it treats as a critical failure. The probe called `command -v`, a POSIX shell builtin with no executable behind it; it now searches `PATH` itself, honouring `PATHEXT`.
|
|
171
|
+
- The build and test scripts run on Windows. `npm run test:integration` spawned the Playwright `.cmd` launcher, which Node refuses with `EINVAL`; `npm run build:critical` spawned `bundle`, which is a `.bat` there and failed with `ENOENT`; `bundle exec rake ci:verify` invoked `python3`, which on Windows is a Microsoft Store stub rather than the interpreter; and the CLI tests ran the binstub through its shebang. Node dependencies now run under the current Node binary instead of their launcher shims, and the remaining launchers go through the command interpreter with arguments quoted, so paths containing spaces survive.
|
|
172
|
+
- The site navigation no longer renders expanded and then animates shut on small screens once the script runs, which moved the whole page by about 340 px and put every page's cumulative layout shift near 0.3.
|
|
173
|
+
|
|
174
|
+
### Removed
|
|
175
|
+
|
|
176
|
+
- Percy and its visual suite (`tests/visual/`): Percy never ran without a token and carried the last open npm advisory and about 150 packages, and the suite failed 34 of its 58 specs on CDN waits and strict locators, locally and in CI. The integration specs under `tests/integration/` remain the browser checks and gate every deploy. `npm audit` is clean.
|
|
177
|
+
- The `jekyll-jupyter-notebook` gem and the Jupyter toolchain. Notebook pages are rendered by the theme; only `nbformat` remains, for the notebook validation script.
|
|
178
|
+
- `_data/config/site.yml`, `theme.yml` and `features.yml`, which nothing read.
|
|
179
|
+
|
|
5
180
|
## [0.6.1] - 2026-09-11
|
|
6
181
|
|
|
7
182
|
### Fixed
|
data/CITATION.cff
CHANGED
|
@@ -16,8 +16,8 @@ abstract: >-
|
|
|
16
16
|
It offers integrated notebook publishing, advanced math rendering, interactive
|
|
17
17
|
visualization workflows, and reproducibility tooling optimised for open science communities.
|
|
18
18
|
license: MIT
|
|
19
|
-
version: 0.
|
|
20
|
-
date-released: 2026-09-
|
|
19
|
+
version: 0.8.0
|
|
20
|
+
date-released: 2026-09-14
|
|
21
21
|
keywords:
|
|
22
22
|
- data-science
|
|
23
23
|
- jekyll
|
data/README.md
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# DataLog — A Data Science Jekyll Theme
|
|
2
2
|
|
|
3
|
+
[](https://rubygems.org/gems/datalog-theme)
|
|
3
4
|
[](https://github.com/DiogoRibeiro7/analytics-blog-jekyll/actions/workflows/test.yml)
|
|
4
5
|
[](https://github.com/DiogoRibeiro7/analytics-blog-jekyll/actions/workflows/deploy.yml)
|
|
5
6
|
[](https://github.com/DiogoRibeiro7/analytics-blog-jekyll/actions/workflows/gem-release.yml)
|
|
@@ -40,7 +41,7 @@ site; the rest is reference content you can copy from.
|
|
|
40
41
|
| Demo content (this site only) | `_posts/`, `_notebooks/`, `_portfolio/`, `_datasets/`, `_packages/`, `_pages/`, `index.md`, `404.html` |
|
|
41
42
|
| Starter scaffold | `template/` — minimal seed for the [GitHub template repository](docs/template-repository.md); excluded from this site's build |
|
|
42
43
|
| Configuration | `_config.yml`, `_data/`, `Gemfile`, `package.json`, `requirements.txt` |
|
|
43
|
-
| Tests & tooling | `tests/`, `scripts/`, `Rakefile`, `vitest.config.js`, `playwright.config.js`, `pa11yci.json`, `lighthouserc.json
|
|
44
|
+
| Tests & tooling | `tests/`, `scripts/`, `Rakefile`, `vitest.config.js`, `playwright.config.js`, `pa11yci.json`, `lighthouserc.json` |
|
|
44
45
|
| Docs | `docs/`, `README.md`, `CHANGELOG.md`, `CONTRIBUTING.md`, `SECURITY.md`, `TESTING.md` |
|
|
45
46
|
|
|
46
47
|
```
|
|
@@ -73,13 +74,15 @@ site; the rest is reference content you can copy from.
|
|
|
73
74
|
|
|
74
75
|
## Documentation
|
|
75
76
|
|
|
77
|
+
- [Documentation Index](docs/README.md) — every guide, grouped by what you want to do.
|
|
76
78
|
- [Documentation Site](docs/site/README.md) — source for the live `datalog-theme.github.io` documentation hub with feature walk-throughs, interactive demos, and migration guides.
|
|
77
79
|
- [User Guide](docs/user-guide.md) — comprehensive documentation covering installation, notebooks, math, visualizations, research workflows, accessibility, performance, and collaboration best practices for DataLog users.
|
|
78
80
|
- [Environment Setup Guide](docs/environment-setup.md) — configure environment variables, secrets, and integrations for analytics, testing, and deployment.
|
|
79
81
|
- [Scripts Reference](docs/scripts-reference.md) — complete reference for all build, test, import/export, and utility scripts.
|
|
80
82
|
- [Changelog](CHANGELOG.md) — release highlights and upgrade guidance for each published version of the DataLog theme.
|
|
81
83
|
- [Template Repository Guide](docs/template-repository.md) — instructions for publishing a GitHub template with starter content, configuration, and automated deployments.
|
|
82
|
-
- [Installation Guide](docs/install.md) —
|
|
84
|
+
- [Installation Guide](docs/install.md) — adding the theme to a site, installing from a Git checkout, publishing with GitHub Actions, and local and Docker setup.
|
|
85
|
+
- [Post Components](docs/components.md) — sharing buttons, breadcrumbs, author cards, the table of contents and difficulty badges.
|
|
83
86
|
- [Migrating from Minimal Mistakes](docs/migrating-from-minimal-mistakes.md) — the front-matter fields DataLog reads natively (hero and teaser images, SEO title and description, `classes: wide`, `redirect_from`) and the settings that keep existing URLs.
|
|
84
87
|
- [Plugin Development Guide](docs/plugin-development.md) — understand the hook system and learn how to package extensions for reuse.
|
|
85
88
|
- [Security Policy](SECURITY.md) — report security vulnerabilities and learn about security best practices.
|
|
@@ -95,7 +98,7 @@ site; the rest is reference content you can copy from.
|
|
|
95
98
|
2. **Configure environment** (optional)
|
|
96
99
|
|
|
97
100
|
Copy [`.env.example`](.env.example) to `.env` and fill in any keys you
|
|
98
|
-
need — GA4 credentials,
|
|
101
|
+
need — GA4 credentials, the Codecov token, Playwright base URL, etc.
|
|
99
102
|
All values are optional; the site runs without them, and features that
|
|
100
103
|
require credentials will skip cleanly. See
|
|
101
104
|
[docs/environment-setup.md](docs/environment-setup.md) for the full reference.
|
|
@@ -149,7 +152,7 @@ Once configured, Chart.js visualizations will highlight top-performing posts, se
|
|
|
149
152
|
|
|
150
153
|
DataLog ships with an opinionated notebook-to-post pipeline tailored for technical storytelling:
|
|
151
154
|
|
|
152
|
-
1. **Drop `.ipynb` files into `_notebooks/`** — the custom generator transforms each notebook into a
|
|
155
|
+
1. **Drop `.ipynb` files into `_notebooks/`** — the custom generator transforms each notebook into a page under `/notebooks/<slug>/` while keeping a downloadable copy at `/notebooks/<slug>.ipynb`.
|
|
153
156
|
2. **Leverage notebook metadata** — optional fields like `title`, `tags`, `keywords`, `difficulty`, and execution metadata will surface in the rendered article header and sidebar.
|
|
154
157
|
3. **Preserve interactivity** — HTML outputs, Plotly figures, and widget placeholders are embedded automatically with responsive styling and dark-mode aware formatting.
|
|
155
158
|
4. **Launch live sessions** — configure `notebooks.repository` and `notebooks.branch` in `_config.yml` to enable Binder and Google Colab links for each notebook, alongside GitHub source references and clone instructions.
|
|
@@ -158,9 +161,8 @@ DataLog ships with an opinionated notebook-to-post pipeline tailored for technic
|
|
|
158
161
|
Matplotlib/Seaborn plots, LaTeX, and code syntax highlighting are optimized for both desktop and mobile viewing, while cell numbering and input/output differentiation mirror the native Jupyter experience.
|
|
159
162
|
|
|
160
163
|
4. **Deploy to GitHub Pages**
|
|
161
|
-
-
|
|
162
|
-
-
|
|
163
|
-
- GitHub Pages will automatically build the site using the `github-pages` gem
|
|
164
|
+
- The build GitHub Pages runs by itself cannot load the theme's plugins, so build and publish with GitHub Actions: see [Publish with GitHub Pages](docs/install.md#23-publish-with-github-pages)
|
|
165
|
+
- `.github/workflows/deploy.yml` publishes this repository's demo site that way
|
|
164
166
|
|
|
165
167
|
## Data Science Workflow Integration
|
|
166
168
|
|
|
@@ -186,7 +188,7 @@ Matplotlib/Seaborn plots, LaTeX, and code syntax highlighting are optimized for
|
|
|
186
188
|
The `_config.yml` file exposes an opinionated set of options crafted for research teams:
|
|
187
189
|
|
|
188
190
|
- `theme_options.math` toggles between **MathJax** and **KaTeX** engines, equation numbering, and accessibility defaults.
|
|
189
|
-
-
|
|
191
|
+
- Code blocks are highlighted by Rouge when the site builds, and the theme styles Rouge's output for light and dark mode, so code needs no settings.
|
|
190
192
|
- `theme_options.visualizations` controls default behaviour for Plotly, D3, Bokeh, Observable, Shiny, and widget embeds.
|
|
191
193
|
- `theme_options.taxonomy`, `content.research_areas`, and `content.methodologies` organize content by research area and methodology for archive navigation.
|
|
192
194
|
- `integrations.github` enables live repository metrics with caching support for portfolio cards, while Binder/Colab/Kaggle toggles control interactive notebook links.
|
|
@@ -206,35 +208,40 @@ Data-driven configuration allows you to publish or reorder projects, datasets, s
|
|
|
206
208
|
Add the theme gem to your Jekyll site:
|
|
207
209
|
|
|
208
210
|
```ruby
|
|
209
|
-
gem "datalog-theme", "~> 0.
|
|
211
|
+
gem "datalog-theme", "~> 0.7"
|
|
210
212
|
```
|
|
211
213
|
|
|
212
|
-
Then enable it in `_config.yml
|
|
214
|
+
Then enable it in `_config.yml`. Naming the theme under `plugins:` registers its Liquid tags, and the build needs an author name:
|
|
213
215
|
|
|
214
216
|
```yml
|
|
215
217
|
theme: datalog-theme
|
|
218
|
+
plugins:
|
|
219
|
+
- datalog-theme
|
|
220
|
+
author:
|
|
221
|
+
name: Your Name
|
|
216
222
|
```
|
|
217
223
|
|
|
218
|
-
|
|
224
|
+
The [installation guide](docs/install.md) covers the files a site supplies itself, installing from a Git checkout, and publishing to GitHub Pages. GitHub Pages cannot build a site that uses this theme by itself, so the guide publishes it with GitHub Actions.
|
|
219
225
|
|
|
220
226
|
## Continuous Integration & Testing
|
|
221
227
|
|
|
222
|
-
The
|
|
228
|
+
The Tests workflow (`.github/workflows/test.yml`) runs on every pull request:
|
|
223
229
|
|
|
224
|
-
-
|
|
225
|
-
-
|
|
226
|
-
-
|
|
227
|
-
-
|
|
230
|
+
- Vitest unit tests for the JavaScript, with coverage thresholds.
|
|
231
|
+
- A Jekyll build of the demo site, then the Minitest suite against the output: plugins, templates, the Content Security Policy, packaging and performance budgets.
|
|
232
|
+
- Playwright browser tests, including axe accessibility checks in both themes.
|
|
233
|
+
- ESLint and RuboCop.
|
|
228
234
|
|
|
229
|
-
Run the
|
|
235
|
+
Separate workflows audit dependencies and run CodeQL, Pa11y and Lighthouse. Run the unit and Ruby suites locally with:
|
|
230
236
|
|
|
231
237
|
```bash
|
|
232
|
-
|
|
238
|
+
npm test
|
|
239
|
+
bundle exec rake test
|
|
233
240
|
```
|
|
234
241
|
|
|
235
242
|
## Demo Site
|
|
236
243
|
|
|
237
|
-
The repository doubles as a demo site and content laboratory. Explore the curated examples locally
|
|
244
|
+
The repository doubles as a demo site and content laboratory, published at <https://diogoribeiro7.github.io/analytics-blog-jekyll/>. Explore the curated examples locally with `bundle exec jekyll serve`.
|
|
238
245
|
|
|
239
246
|
## Citation & Academic Metadata
|
|
240
247
|
|
data/_data/cdn-integrity.yml
CHANGED
|
@@ -13,36 +13,6 @@ https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.js:
|
|
|
13
13
|
https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js:
|
|
14
14
|
crossorigin: anonymous
|
|
15
15
|
integrity: sha384-AHAnt9ZhGeHIrydA1Kp1L7FN+2UosbF7RQg6C+9Is/a7kDpQ1684C2iH2VWil6r4
|
|
16
|
-
https://cdn.jsdelivr.net/npm/prismjs@1.29.0/components/prism-javascript.min.js:
|
|
17
|
-
crossorigin: anonymous
|
|
18
|
-
integrity: sha384-D44bgYYKvaiDh4cOGlj1dbSDpSctn2FSUj118HZGmZEShZcO2v//Q5vvhNy206pp
|
|
19
|
-
https://cdn.jsdelivr.net/npm/prismjs@1.29.0/components/prism-julia.min.js:
|
|
20
|
-
crossorigin: anonymous
|
|
21
|
-
integrity: sha384-joWnGJCIIBw7UmQ231RAVzCNiATJS38xk7yfiIDHRBJeYiBPvacMLMvx9d49VnrH
|
|
22
|
-
https://cdn.jsdelivr.net/npm/prismjs@1.29.0/components/prism-python.min.js:
|
|
23
|
-
crossorigin: anonymous
|
|
24
|
-
integrity: sha384-WJdEkJKrbsqw0evQ4GB6mlsKe5cGTxBOw4KAEIa52ZLB7DDpliGkwdme/HMa5n1m
|
|
25
|
-
https://cdn.jsdelivr.net/npm/prismjs@1.29.0/components/prism-r.min.js:
|
|
26
|
-
crossorigin: anonymous
|
|
27
|
-
integrity: sha384-a0dW6ZXBBtsBzzpPHKLx+AdpKmRJXfTGeCGNpzDA83/BoZoTUknyIAwMDuOTBfkS
|
|
28
|
-
https://cdn.jsdelivr.net/npm/prismjs@1.29.0/components/prism-sql.min.js:
|
|
29
|
-
crossorigin: anonymous
|
|
30
|
-
integrity: sha384-/MKWdycCDliku23mP5sYXbZNuXrzgmQO/jsVxwPFn99dVOaXRyKsqDjarqpueGAp
|
|
31
|
-
https://cdn.jsdelivr.net/npm/prismjs@1.29.0/plugins/line-numbers/prism-line-numbers.min.css:
|
|
32
|
-
crossorigin: anonymous
|
|
33
|
-
integrity: sha384-nUkTNLI8COlMCRJ0FHIdX76If83145OTCLUx4gQyfnO0gGeO/sD9czGEUBxtkcUv
|
|
34
|
-
https://cdn.jsdelivr.net/npm/prismjs@1.29.0/plugins/normalize-whitespace/prism-normalize-whitespace.min.js:
|
|
35
|
-
crossorigin: anonymous
|
|
36
|
-
integrity: sha384-1Q1Kn1ruXt6wc5JfXB25OWRaEVBJ5OQ0gfL/pneNkXoVmWmhkBacvG9Rls1+yB2h
|
|
37
|
-
https://cdn.jsdelivr.net/npm/prismjs@1.29.0/prism.min.js:
|
|
38
|
-
crossorigin: anonymous
|
|
39
|
-
integrity: sha384-BGaNxfftg+9+TtC098wxawPFVEUpKYvaiCgbB0iqAMjK/4jDdmUY+oGxrPNvnXEf
|
|
40
|
-
https://cdn.jsdelivr.net/npm/prismjs@1.29.0/themes/prism-coy.css:
|
|
41
|
-
crossorigin: anonymous
|
|
42
|
-
integrity: sha384-/HnXSmP1Tv+9YA13kJX5sL1eVi3XeI57BUEGl+PiVlv6pPcxsbVrHaiw+OepvnSd
|
|
43
|
-
https://cdn.jsdelivr.net/npm/prismjs@1.29.0/themes/prism-tomorrow.css:
|
|
44
|
-
crossorigin: anonymous
|
|
45
|
-
integrity: sha384-RCpAEDK2BSI4uVvV9kefzLdwlNUNZkCZJdOE2LkEa3jtLRcv2YrEVSbM4vwbCCW2
|
|
46
16
|
https://giscus.app/client.js:
|
|
47
17
|
crossorigin: anonymous
|
|
48
18
|
integrity: sha384-UwLZGbJGvkTzz0719+xEzUm/idqwzs0yZN8aB9Se5vUXHbyRyDWw9yqZTIsOsJ7x
|
|
@@ -145,5 +145,7 @@
|
|
|
145
145
|
window.__DATALOG_ANALYTICS__ = {};
|
|
146
146
|
{% endif %}
|
|
147
147
|
</script>
|
|
148
|
-
|
|
148
|
+
{%- comment -%} The built bundle, as a module: the script uses `export`, which a classic script cannot parse. {%- endcomment %}
|
|
149
|
+
{%- assign dashboard_bundle = site.data.js_manifest.entrypoints['analytics-dashboard'] | default: '/assets/js/dist/analytics-dashboard.js' %}
|
|
150
|
+
<script type="module" src="{{ dashboard_bundle | relative_url }}"></script>
|
|
149
151
|
</div>
|
|
@@ -74,19 +74,38 @@ Parameters:
|
|
|
74
74
|
<div class="api-function__section">
|
|
75
75
|
<h4 class="api-function__section-title">Examples</h4>
|
|
76
76
|
<div class="api-function__examples">
|
|
77
|
+
{%- comment -%}
|
|
78
|
+
Examples are code. Through markdownify, a Python comment such as
|
|
79
|
+
"# Two-sample t-test" became a page heading. Examples written as
|
|
80
|
+
Markdown with fenced code blocks still render as Markdown.
|
|
81
|
+
{%- endcomment -%}
|
|
82
|
+
{% if include.examples contains '```' %}
|
|
77
83
|
{{ include.examples | markdownify }}
|
|
84
|
+
{% else %}
|
|
85
|
+
{% assign example_language = include.language | default: page.language | default: 'text' | downcase %}
|
|
86
|
+
<pre class="highlight" tabindex="0"><code class="language-{{ example_language }}">{{ include.examples | strip | rouge_highlight: example_language }}</code></pre>
|
|
87
|
+
{% endif %}
|
|
78
88
|
</div>
|
|
79
89
|
</div>
|
|
80
90
|
{% endif %}
|
|
81
91
|
|
|
82
92
|
{% if include.see_also %}
|
|
93
|
+
{%- comment -%}
|
|
94
|
+
`see_also` is a comma-separated list of functions documented on the same page, such as
|
|
95
|
+
`see_also="mannwhitneyu, anova"`. The loop used to take the whole string as one item, so two
|
|
96
|
+
names made a single link to an anchor that did not exist.
|
|
97
|
+
{%- endcomment -%}
|
|
98
|
+
{% assign see_also_items = include.see_also | split: "," %}
|
|
83
99
|
<div class="api-function__section">
|
|
84
100
|
<h4 class="api-function__section-title">See Also</h4>
|
|
85
101
|
<ul class="api-function__see-also">
|
|
86
|
-
{% for
|
|
102
|
+
{% for raw_item in see_also_items %}
|
|
103
|
+
{% assign item = raw_item | strip %}
|
|
104
|
+
{% if item != "" %}
|
|
87
105
|
<li>
|
|
88
106
|
<a href="#{{ item | slugify }}"><code>{{ item }}</code></a>
|
|
89
107
|
</li>
|
|
108
|
+
{% endif %}
|
|
90
109
|
{% endfor %}
|
|
91
110
|
</ul>
|
|
92
111
|
</div>
|
|
@@ -34,8 +34,8 @@ Parameters:
|
|
|
34
34
|
{%- else -%}
|
|
35
35
|
{%- comment -%} Fallback avatar with initials {%- endcomment -%}
|
|
36
36
|
{%- assign initials = author_name | split: ' ' | map: 'first' | slice: 0, 2 | join: '' | upcase -%}
|
|
37
|
-
<div class="author-bio__avatar-placeholder" aria-label="{{ author_name }}">
|
|
38
|
-
<span>{{ initials }}</span>
|
|
37
|
+
<div class="author-bio__avatar-placeholder" role="img" aria-label="{{ author_name }}">
|
|
38
|
+
<span aria-hidden="true">{{ initials }}</span>
|
|
39
39
|
</div>
|
|
40
40
|
{%- endif -%}
|
|
41
41
|
</div>
|
|
@@ -104,7 +104,7 @@ Parameters:
|
|
|
104
104
|
</div>
|
|
105
105
|
</div>
|
|
106
106
|
|
|
107
|
-
<pre class="enhanced-code-block__pre{% if show_line_numbers %} enhanced-code-block__pre--numbered{% endif %}"><code id="{{ code_id }}" class="language-{{ language }}" data-code-content>{{ code_content }}</code></pre>
|
|
107
|
+
<pre class="highlight enhanced-code-block__pre{% if show_line_numbers %} enhanced-code-block__pre--numbered{% endif %}" tabindex="0"><code id="{{ code_id }}" class="language-{{ language }}" data-code-content>{{ code_content | rouge_highlight: language }}</code></pre>
|
|
108
108
|
|
|
109
109
|
{%- comment -%} Feedback message {%- endcomment -%}
|
|
110
110
|
<div class="enhanced-code-block__feedback" data-feedback role="status" aria-live="polite"></div>
|
|
@@ -1,6 +1,24 @@
|
|
|
1
|
-
{% assign hero_bg = page.hero_image | default: '/assets/img/
|
|
1
|
+
{% assign hero_bg = page.hero_image | default: '/assets/img/hero-detail.webp' %}
|
|
2
|
+
{% assign hero_bg_small = page.hero_image_small %}
|
|
3
|
+
{% if page.hero_image == nil and hero_bg_small == nil %}
|
|
4
|
+
{% assign hero_bg_small = '/assets/img/hero-detail-640.webp' %}
|
|
5
|
+
{% endif %}
|
|
6
|
+
{%- comment -%}
|
|
7
|
+
The hero is the largest paint on the page. A CSS background is only requested
|
|
8
|
+
once the stylesheet applies, so preload it; small screens get a 640 px
|
|
9
|
+
variant (page.hero_image_small when a page brings its own hero_image).
|
|
10
|
+
{%- endcomment -%}
|
|
11
|
+
{% if hero_bg_small %}
|
|
12
|
+
<link rel="preload" as="image" href="{{ hero_bg_small | relative_url }}" media="(max-width: 640px)" fetchpriority="high" />
|
|
13
|
+
<link rel="preload" as="image" href="{{ hero_bg | relative_url }}" media="(min-width: 641px)" fetchpriority="high" />
|
|
14
|
+
{% else %}
|
|
15
|
+
<link rel="preload" as="image" href="{{ hero_bg | relative_url }}" fetchpriority="high" />
|
|
16
|
+
{% endif %}
|
|
2
17
|
<style nonce="{{ page.csp_nonce }}">
|
|
3
18
|
.hero { --hero-bg: url('{{ hero_bg | relative_url }}'); }
|
|
19
|
+
{% if hero_bg_small %}
|
|
20
|
+
@media (max-width: 640px) { .hero { --hero-bg: url('{{ hero_bg_small | relative_url }}'); } }
|
|
21
|
+
{% endif %}
|
|
4
22
|
</style>
|
|
5
23
|
<section class="hero">
|
|
6
24
|
<div class="hero-overlay"></div>
|