datalog-theme 0.9.0 → 0.9.2

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 (77) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +30 -0
  3. data/CITATION.cff +2 -2
  4. data/_data/i18n/en.yml +24 -0
  5. data/_data/i18n/es.yml +24 -0
  6. data/_data/i18n/pt.yml +24 -0
  7. data/_includes/components/academic-dashboard.html +4 -4
  8. data/_includes/components/author-list.html +1 -1
  9. data/_includes/components/breadcrumbs.html +6 -4
  10. data/_includes/components/citation-tools.html +5 -53
  11. data/_includes/components/comments-thread.html +1 -1
  12. data/_includes/components/contact-form.html +1 -1
  13. data/_includes/components/correction-report.html +1 -1
  14. data/_includes/components/hero.html +1 -1
  15. data/_includes/components/moderation-inbox.html +1 -1
  16. data/_includes/components/post-hero.html +2 -2
  17. data/_includes/components/reactions.html +1 -1
  18. data/_includes/components/reading-list.html +3 -0
  19. data/_includes/components/reading-mode-toggle.html +2 -0
  20. data/_includes/components/reading-state-panel.html +0 -9
  21. data/_includes/components/reading-state-resume.html +17 -0
  22. data/_includes/components/subscribe-form.html +1 -1
  23. data/_includes/components/subscription-manage.html +2 -1
  24. data/_includes/components/visualization-card.html +1 -1
  25. data/_includes/components/webmentions.html +1 -1
  26. data/_includes/footer/nav-column.html +1 -1
  27. data/_includes/footer.html +2 -2
  28. data/_includes/head.html +13 -12
  29. data/_includes/header/navigation.html +2 -2
  30. data/_includes/header.html +1 -1
  31. data/_includes/layouts/default/article.html +2 -2
  32. data/_includes/meta/math-config.html +3 -0
  33. data/_includes/meta/person-json.html +7 -7
  34. data/_includes/meta/publisher.html +1 -1
  35. data/_includes/meta/schema.html +32 -30
  36. data/_includes/meta/scholarly.html +4 -3
  37. data/_includes/post/related-posts.html +1 -1
  38. data/_layouts/dataset.html +1 -1
  39. data/_layouts/home.html +2 -2
  40. data/_layouts/notebook.html +1 -1
  41. data/_layouts/package.html +5 -5
  42. data/_layouts/portfolio.html +1 -1
  43. data/_layouts/post.html +12 -7
  44. data/_layouts/project.html +3 -3
  45. data/_layouts/research.html +7 -67
  46. data/_plugins/authors.rb +22 -4
  47. data/_plugins/citation_exports.rb +93 -0
  48. data/_plugins/image_optimizer.rb +24 -16
  49. data/_plugins/licenses.rb +15 -3
  50. data/_plugins/math_preprocessor.rb +65 -3
  51. data/_plugins/references.rb +30 -8
  52. data/_plugins/reproducibility.rb +20 -3
  53. data/_plugins/responsive_content.rb +40 -0
  54. data/_plugins/revisions.rb +1 -0
  55. data/_plugins/scholarly.rb +5 -0
  56. data/_plugins/statements.rb +2 -2
  57. data/_sass/_base.scss +5 -0
  58. data/_sass/_layout.scss +18 -1
  59. data/_sass/_mathematical.scss +11 -1
  60. data/_sass/_print.scss +16 -8
  61. data/_sass/_syntax-highlighting.scss +1 -1
  62. data/assets/js/dist/chunks/chunk-VZ5WKQVA.js +1 -0
  63. data/assets/js/dist/chunks/chunk-WIRUK3OZ.js +1 -0
  64. data/assets/js/dist/comments.js +2 -2
  65. data/assets/js/dist/contact.js +1 -1
  66. data/assets/js/dist/corrections.js +1 -1
  67. data/assets/js/dist/moderation.js +1 -1
  68. data/assets/js/dist/reactions.js +1 -1
  69. data/assets/js/dist/reading-state.js +1 -1
  70. data/assets/js/dist/sources.json +16 -16
  71. data/assets/js/dist/subscriptions.js +1 -1
  72. data/assets/js/dist/visualizations.js +2 -2
  73. data/assets/js/dist/webmentions.js +1 -1
  74. data/lib/datalog/theme/version.rb +1 -1
  75. metadata +7 -4
  76. data/assets/js/dist/chunks/chunk-2DYDWUFX.js +0 -1
  77. data/assets/js/dist/chunks/chunk-V7734B2G.js +0 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c9d97f826b4949b35e04d90f542c85c434775e5416ef8c1137af48467e40564d
4
- data.tar.gz: 4451049cefd607378dae94657aab70fa4d9726b68737c1876956e08cf2b80ebf
3
+ metadata.gz: e78d28d83ac0a0f18ae06135f8d07b0523f4b1669bfe838cf7cb146a77c54307
4
+ data.tar.gz: 2f75e9074b965a7edfd417194145ad50ed44a03aa93d789d86ddde7ae4a7a5ec
5
5
  SHA512:
6
- metadata.gz: e5d718fc6d922cbbbcf19838f5c6fc11804f21dfabc577f007e26bad8208b4b8da6e4fd127eecbf9840ae60c871eeab03c374d10727b26f43c25aa4c2487d293
7
- data.tar.gz: f8e910e513c78ea56d675f9c947af5e684f1be8528e11deec81943ad93a5eed585550b3dfcd9da04f11fe48994d32048eade97cc9383b2b8d1087b8f42eaca0a
6
+ metadata.gz: 00f97bd9e578136be77bffc0aa079ad80d9498a8f7becce2162d7ca948920b32fe8387e0f977f6a404a05d5c7a0960dad84f915fefe07ee2844b9d36fb7a5351
7
+ data.tar.gz: 469a1d9ec77a2e9379979fb392a0bd2d6888516742931599bb8fa3457375a17ec85b7b3d322b8d72018129999b7dda91e7123b6fc906eef5e8fddc4c1d952311
data/CHANGELOG.md CHANGED
@@ -2,6 +2,36 @@
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.9.2] - 2026-09-20
6
+
7
+ ### Fixed
8
+
9
+ - Keep newly posted comments visible when an older thread read finishes, and refresh moderation reads that overlap completed actions without losing their filters or pagination.
10
+ - Retry subscription preference saves with the edited topics, clearing retry handlers left by earlier loading failures.
11
+ - Preserve indented code blocks during math preprocessing, distinguish them from indented prose, and accept longer closing code fences so following math is still detected.
12
+ - Percent-encode generated image paths once in the responsive manifest so filenames containing spaces produce valid image candidates in Markdown and responsive-image includes.
13
+
14
+ ## [0.9.1] - 2026-09-20
15
+
16
+ Planned patch release: **0.9.1**. This release contains bug fixes only.
17
+
18
+ ### Fixed
19
+
20
+ - Keep numbered figure, table and statement references unchanged when posts are embedded in feeds or listings. Parse escaped attribute quotes completely and fail malformed tags with the page and tag name (#298, #299).
21
+ - Keep editorial asides in the article flow, preserve image proportions at narrow widths, contain wide tables and equations, and restore spacing beside Rouge line numbers (#300, #301, #319, #321).
22
+ - Use `TechArticle` structured data, respect layout schema types, preserve comparison operators in titles and descriptions, escape script-sensitive JSON, and include `baseurl` in publisher, author and breadcrumb URLs (#302, #303, #313).
23
+ - Preserve idempotency keys across retries of unchanged submissions and recover contact, correction and subscription forms after temporary capability failures (#304, #305).
24
+ - Retain subscription management retries and distinguish service failures from expired links. Prevent stale reaction and moderation reads from overwriting newer state, respect moderation-specific endpoints, show retry timing and body request IDs, and sort timestamps by instant (#306).
25
+ - Capture correction quotes before pointer interaction clears the selection, and clear them after successful submission (#307).
26
+ - Offer reading resume above the article, preserve the saved position until resumed or dismissed, flush pending progress when leaving, and keep erased data erased. Restore highlights after math and visualization rendering and avoid ambiguous matches in other sections (#308, #309).
27
+ - Correct macOS highlight shortcuts and Escape handling, report storage failures while keeping erase available, merge and sanitize imports, honor disabled reading lists, and keep fallback marks out of table/list whitespace and SVG (#310).
28
+ - Produce complete BibTeX, RIS and EndNote records with format-specific types and escaped BibTeX fields. Share the exporter with research pages, preserve semicolon-separated author names, and support organization authors (#311).
29
+ - Supply missing notebook labels in English, Spanish and Portuguese and validate literal translation keys (#312).
30
+ - Validate author and licence shapes, resolve author names and profile handles, inherit partial licence settings, preserve year ranges, normalize repository and DOI links, prevent image variant collisions, handle encoded image paths, and propagate `updated` to feeds and sitemaps (#313).
31
+ - Preserve visualization fallback tables and live content in print and hide code line-number gutters (#314).
32
+ - Default omitted math loading settings to automatic detection and preserve inline parenthesis and double-dollar TeX through Markdown conversion, and leave empty delimiters literal (#315, #316, #320).
33
+ - Render tag and category links only when their archive page exists, removing broken links without adding archive features (#293).
34
+
5
35
  ## [0.9.0] - 2026-09-18
6
36
 
7
37
  ### Added
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.9.0
20
- date-released: 2026-09-18
19
+ version: 0.9.2
20
+ date-released: 2026-09-20
21
21
  keywords:
22
22
  - data-science
23
23
  - jekyll
data/_data/i18n/en.yml CHANGED
@@ -252,6 +252,7 @@ subscriptions:
252
252
  email_invalid: That does not look like an email address.
253
253
  topics_required: Pick at least one.
254
254
  manage:
255
+ retry: Try again
255
256
  idle: "This page confirms, changes or ends a newsletter subscription. Open it from the link in one of the emails."
256
257
  unavailable: Subscriptions are not set up on this site.
257
258
  confirming: Confirming your subscription…
@@ -364,6 +365,7 @@ dynamic_services:
364
365
  server: The service ran into a problem. Try again later.
365
366
  http: The service refused the request.
366
367
  aborted: The request was cancelled.
368
+ retry_after: "Try again in {{seconds}} seconds."
367
369
  reference: "Reference: {{id}}"
368
370
  references:
369
371
  figure: Figure
@@ -503,6 +505,27 @@ dataset:
503
505
  description: Description
504
506
  type: Type
505
507
  notebook:
508
+ tags_label: Notebook tags
509
+ sidebar_label: Notebook details
510
+ sidebar:
511
+ overview: Overview
512
+ code_cells: code cells
513
+ markdown_cells: Markdown cells
514
+ error_outputs: error outputs
515
+ execution: Execution
516
+ kernel: Kernel
517
+ language: Language
518
+ file: File
519
+ branch: Branch
520
+ runtime: Runtime
521
+ not_specified: Not specified
522
+ na: Not available
523
+ run_online: Run online
524
+ launch_binder: Launch in Binder
525
+ open_colab: Open in Colab
526
+ version_history: Version history
527
+ last_commit: Last commit
528
+ view_latest: View latest version
506
529
  label: Interactive Notebook
507
530
  meta:
508
531
  published: "Published:"
@@ -514,6 +537,7 @@ notebook:
514
537
  runtime: "Runtime:"
515
538
  actions:
516
539
  download: Download .ipynb
540
+ view_source: View source
517
541
  launch_binder: Launch in Binder
518
542
  open_colab: Open in Colab
519
543
  academic_dashboard:
data/_data/i18n/es.yml CHANGED
@@ -252,6 +252,7 @@ subscriptions:
252
252
  email_invalid: Eso no parece una dirección de correo.
253
253
  topics_required: Elige al menos uno.
254
254
  manage:
255
+ retry: Intentar de nuevo
255
256
  idle: "Esta página confirma, cambia o termina una suscripción al boletín. Ábrela desde el enlace de uno de los correos."
256
257
  unavailable: Las suscripciones no están configuradas en este sitio.
257
258
  confirming: Confirmando tu suscripción…
@@ -364,6 +365,7 @@ dynamic_services:
364
365
  server: El servicio tuvo un problema. Inténtalo más tarde.
365
366
  http: El servicio rechazó la solicitud.
366
367
  aborted: La solicitud se canceló.
368
+ retry_after: "Inténtalo de nuevo en {{seconds}} segundos."
367
369
  reference: "Referencia: {{id}}"
368
370
  references:
369
371
  figure: Figura
@@ -503,6 +505,27 @@ dataset:
503
505
  description: Descripción
504
506
  type: Tipo
505
507
  notebook:
508
+ tags_label: Etiquetas del notebook
509
+ sidebar_label: Detalles del notebook
510
+ sidebar:
511
+ overview: Resumen
512
+ code_cells: celdas de código
513
+ markdown_cells: celdas Markdown
514
+ error_outputs: salidas con errores
515
+ execution: Ejecución
516
+ kernel: Kernel
517
+ language: Lenguaje
518
+ file: Archivo
519
+ branch: Rama
520
+ runtime: Duración
521
+ not_specified: No especificado
522
+ na: No disponible
523
+ run_online: Ejecutar en línea
524
+ launch_binder: Abrir en Binder
525
+ open_colab: Abrir en Colab
526
+ version_history: Historial de versiones
527
+ last_commit: Último commit
528
+ view_latest: Ver la última versión
506
529
  label: Notebook interactivo
507
530
  meta:
508
531
  published: "Publicado:"
@@ -514,6 +537,7 @@ notebook:
514
537
  runtime: "Duración:"
515
538
  actions:
516
539
  download: Descargar .ipynb
540
+ view_source: Ver código fuente
517
541
  launch_binder: Abrir en Binder
518
542
  open_colab: Abrir en Colab
519
543
  academic_dashboard:
data/_data/i18n/pt.yml CHANGED
@@ -252,6 +252,7 @@ subscriptions:
252
252
  email_invalid: Isso não parece um endereço de email.
253
253
  topics_required: Escolha pelo menos um.
254
254
  manage:
255
+ retry: Tentar de novo
255
256
  idle: "Esta página confirma, altera ou termina uma subscrição da newsletter. Abra-a a partir da ligação num dos emails."
256
257
  unavailable: As subscrições não estão configuradas neste site.
257
258
  confirming: A confirmar a sua subscrição…
@@ -364,6 +365,7 @@ dynamic_services:
364
365
  server: O serviço encontrou um problema. Tente mais tarde.
365
366
  http: O serviço recusou o pedido.
366
367
  aborted: O pedido foi cancelado.
368
+ retry_after: "Tente novamente em {{seconds}} segundos."
367
369
  reference: "Referência: {{id}}"
368
370
  references:
369
371
  figure: Figura
@@ -503,6 +505,27 @@ dataset:
503
505
  description: Descrição
504
506
  type: Tipo
505
507
  notebook:
508
+ tags_label: Etiquetas do notebook
509
+ sidebar_label: Detalhes do notebook
510
+ sidebar:
511
+ overview: Visão geral
512
+ code_cells: células de código
513
+ markdown_cells: células Markdown
514
+ error_outputs: saídas com erros
515
+ execution: Execução
516
+ kernel: Kernel
517
+ language: Linguagem
518
+ file: Ficheiro
519
+ branch: Ramo
520
+ runtime: Duração
521
+ not_specified: Não especificado
522
+ na: Não disponível
523
+ run_online: Executar online
524
+ launch_binder: Abrir no Binder
525
+ open_colab: Abrir no Colab
526
+ version_history: Histórico de versões
527
+ last_commit: Último commit
528
+ view_latest: Ver a versão mais recente
506
529
  label: Notebook interativo
507
530
  meta:
508
531
  published: "Publicado:"
@@ -514,6 +537,7 @@ notebook:
514
537
  runtime: "Duração:"
515
538
  actions:
516
539
  download: Transferir .ipynb
540
+ view_source: Ver código-fonte
517
541
  launch_binder: Abrir no Binder
518
542
  open_colab: Abrir no Colab
519
543
  academic_dashboard:
@@ -155,7 +155,7 @@
155
155
  <li class="submission-card" data-submission-status="{{ submission.status | slugify }}">
156
156
  <article>
157
157
  <header>
158
- <h3>{{ submission.title }}</h3>
158
+ <h3>{{ submission.title | escape }}</h3>
159
159
  <p class="submission-venue">{{ submission.venue }} · <span class="submission-type">{{ submission.type | capitalize }}</span></p>
160
160
  </header>
161
161
  <dl class="submission-meta">
@@ -182,7 +182,7 @@
182
182
  <ul class="workflow-list">
183
183
  {% for review in academic.workflow.peer_review %}
184
184
  <li>
185
- <strong>{{ review.title }}</strong>
185
+ <strong>{{ review.title | escape }}</strong>
186
186
  <p>{{ review.journal }}</p>
187
187
  <p>{% t 'academic_dashboard.workflow.peer_review.status_label' %} <span class="status-badge">{{ review.status }}</span></p>
188
188
  {% assign assigned_label = review.assigned_date | localize_date: date_format %}
@@ -255,7 +255,7 @@
255
255
  <li>
256
256
  <article>
257
257
  <header>
258
- <h3>{{ grant.title }}</h3>
258
+ <h3>{{ grant.title | escape }}</h3>
259
259
  <p>{{ grant.agency }} · {{ grant.role }}</p>
260
260
  </header>
261
261
  <dl class="funding-meta">
@@ -279,7 +279,7 @@
279
279
  <li>
280
280
  <article>
281
281
  <header>
282
- <h3>{{ opportunity.title }}</h3>
282
+ <h3>{{ opportunity.title | escape }}</h3>
283
283
  {% if opportunity.tags %}<p class="opportunity-tags">{{ opportunity.tags | array_to_sentence_string }}</p>{% endif %}
284
284
  </header>
285
285
  <p>{{ opportunity.description }}</p>
@@ -15,7 +15,7 @@ role and affiliation. `people` comes from `page | page_authors` or
15
15
  {%- assign list_property = include.property | default: 'author' -%}
16
16
  <ul class="author-list">
17
17
  {%- for person in include.people -%}
18
- <li class="author-list__person" itemprop="{{ list_property }}" itemscope itemtype="https://schema.org/Person">
18
+ <li class="author-list__person" itemprop="{{ list_property }}" itemscope itemtype="https://schema.org/{% if person.type == 'Organization' %}Organization{% else %}Person{% endif %}">
19
19
  {%- if person.url -%}
20
20
  {%- assign person_href = person.url -%}
21
21
  {%- unless person_href contains '://' -%}{%- assign person_href = person_href | relative_url -%}{%- endunless -%}
@@ -64,11 +64,13 @@ Parameters:
64
64
  {%- if page.categories and page.categories.size > 0 -%}
65
65
  {%- assign main_category = page.categories | first -%}
66
66
  {%- assign category_slug = main_category | slugify -%}
67
+ {%- assign category_archive_path = site.category_archive.path | default: '/categories/' -%}
68
+ {%- assign category_archive_page = site.pages | where: 'url', category_archive_path | first -%}
67
69
  {%- unless position -%}{%- assign position = 2 -%}{%- endunless -%}
68
70
  <li class="breadcrumbs__item" itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">
69
- <a href="{{ site.category_archive.path | default: '/categories/' | append: '#' | append: category_slug | relative_url }}" class="breadcrumbs__link" itemprop="item">
70
- <span itemprop="name">{{ main_category }}</span>
71
- </a>
71
+ {% if category_archive_page %}<a href="{{ category_archive_path | append: '#' | append: category_slug | relative_url }}" class="breadcrumbs__link" itemprop="item">{% endif %}
72
+ <span itemprop="name">{{ main_category | escape }}</span>
73
+ {% if category_archive_page %}</a>{% endif %}
72
74
  <meta itemprop="position" content="{{ position }}" />
73
75
  <span class="breadcrumbs__separator" aria-hidden="true">{{ separator }}</span>
74
76
  </li>
@@ -80,7 +82,7 @@ Parameters:
80
82
  {%- unless position -%}{%- assign position = 2 -%}{%- endunless -%}
81
83
  <li class="breadcrumbs__item breadcrumbs__item--current" itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem" aria-current="page">
82
84
  <span class="breadcrumbs__current" itemprop="item">
83
- <span itemprop="name">{{ page.title | truncate: 50 }}</span>
85
+ <span itemprop="name">{{ page.title | truncate: 50 | escape }}</span>
84
86
  </span>
85
87
  <meta itemprop="position" content="{{ position }}" />
86
88
  </li>
@@ -13,62 +13,14 @@
13
13
  {% assign doi = include.doi | default: page.doi %}
14
14
  {% assign citation_type = include.citation_type | default: include.type | default: 'article' %}
15
15
  {% assign citation_key = include.citation_key | default: page.citation_key | default: page.slug | default: citation_title | slugify %}
16
- {%- comment -%}
17
- The author loops trim their whitespace: with several authors, the indentation
18
- ended up inside the BibTeX author field and between the RIS author lines.
19
- {%- endcomment -%}
20
- {%- capture author_line -%}
21
- {%- for author in authors_array -%}
22
- {{- author.name | default: author | strip | escape -}}{%- unless forloop.last %} and {% endunless -%}
23
- {%- endfor -%}
24
- {%- endcapture -%}
25
- {%- capture ris_authors -%}
26
- {%- for author in authors_array %}
27
- AU - {{ author.name | default: author | strip | escape }}
28
- {%- endfor -%}
29
- {%- endcapture -%}
30
- {%- capture endnote_authors -%}
31
- {%- for author in authors_array %}
32
- %A {{ author.name | default: author | strip | escape }}
33
- {%- endfor -%}
34
- {%- endcapture -%}
35
- {% capture bibtex_entry %}@{{ citation_type }}{ {{ citation_key }},
36
- title = { {{ citation_title | strip }} },
37
- author = { {{ author_line | strip }} },
38
- {% if citation_year %}year = { {{ citation_year }} },{% endif %}
39
- {% if publisher %}publisher = { {{ publisher | strip }} },{% endif %}
40
- {% if doi %}doi = { {{ doi }} },{% endif %}
41
- url = { {{ citation_url }} }
42
- }
43
- {% endcapture %}
44
- {% capture ris_entry %}TY - {{ citation_type | upcase }}
45
- TI - {{ citation_title | strip }}
46
- {% if citation_year %}PY - {{ citation_year }}
47
- {% endif %}{{ ris_authors | strip }}
48
- {% if publisher %}PB - {{ publisher | strip }}
49
- {% endif %}
50
- {% if doi %}DO - {{ doi }}
51
- {% endif %}UR - {{ citation_url }}
52
- ER -
53
- {% endcapture %}
54
- {% capture endnote_entry %}%0 {{ citation_type | capitalize }}
55
- %T {{ citation_title | strip }}
56
- {{ endnote_authors | strip }}
57
- {% if citation_year %}%D {{ citation_year }}
58
- {% endif %}
59
- {% if publisher %}%I {{ publisher | strip }}
60
- {% endif %}
61
- {% if doi %}%R {{ doi }}
62
- {% endif %}
63
- %U {{ citation_url }}
64
- {% endcapture %}
16
+ {% assign exports = page | citation_exports: include %}
65
17
  {%- capture authors_plain -%}
66
18
  {%- for author in authors_array -%}
67
19
  {{- author.name | default: author | strip | escape -}}{%- unless forloop.last -%}, {% endunless -%}
68
20
  {%- endfor -%}
69
21
  {%- endcapture -%}
70
22
  {% capture citation_text %}
71
- {{ authors_plain | strip }}{% if citation_year %} ({{ citation_year }}){% endif %}. {{ citation_title | strip }}. {{ publisher | strip }}. {{ citation_url }}.
23
+ {{ authors_plain | strip }}{% if citation_year %} ({{ citation_year }}){% endif %}. {{ citation_title | strip | escape }}. {{ publisher | strip | escape }}. {{ citation_url | escape }}.
72
24
  {% endcapture %}
73
25
  <section class="citation-tools" aria-labelledby="citation-tools-heading-{{ citation_key }}">
74
26
  <div class="citation-tools__header">
@@ -82,21 +34,21 @@ ER -
82
34
  <h3>{% t 'citation_tools.formats.bibtex' %}</h3>
83
35
  <button type="button" class="btn btn--ghost" data-copy-citation data-target="bibtex-{{ citation_key }}">{% t 'citation_tools.copy' %}</button>
84
36
  </header>
85
- <textarea id="bibtex-{{ citation_key }}" readonly aria-label="{% t 'citation_tools.aria.bibtex' %}">{{ bibtex_entry | strip }}</textarea>
37
+ <textarea id="bibtex-{{ citation_key }}" readonly aria-label="{% t 'citation_tools.aria.bibtex' %}">{{ exports.bibtex | escape }}</textarea>
86
38
  </article>
87
39
  <article class="citation-tools__format" data-citation-format="ris">
88
40
  <header>
89
41
  <h3>{% t 'citation_tools.formats.ris' %}</h3>
90
42
  <button type="button" class="btn btn--ghost" data-copy-citation data-target="ris-{{ citation_key }}">{% t 'citation_tools.copy' %}</button>
91
43
  </header>
92
- <textarea id="ris-{{ citation_key }}" readonly aria-label="{% t 'citation_tools.aria.ris' %}">{{ ris_entry | strip }}</textarea>
44
+ <textarea id="ris-{{ citation_key }}" readonly aria-label="{% t 'citation_tools.aria.ris' %}">{{ exports.ris | escape }}</textarea>
93
45
  </article>
94
46
  <article class="citation-tools__format" data-citation-format="endnote">
95
47
  <header>
96
48
  <h3>{% t 'citation_tools.formats.endnote' %}</h3>
97
49
  <button type="button" class="btn btn--ghost" data-copy-citation data-target="endnote-{{ citation_key }}">{% t 'citation_tools.copy' %}</button>
98
50
  </header>
99
- <textarea id="endnote-{{ citation_key }}" readonly aria-label="{% t 'citation_tools.aria.endnote' %}">{{ endnote_entry | strip }}</textarea>
51
+ <textarea id="endnote-{{ citation_key }}" readonly aria-label="{% t 'citation_tools.aria.endnote' %}">{{ exports.endnote | escape }}</textarea>
100
52
  </article>
101
53
  </div>
102
54
  </section>
@@ -27,7 +27,7 @@ Reads `page.datalog_comments` (the plugin's resolved settings: `replies`,
27
27
  "url_invalid": {{ 'comments.url_invalid' | t | jsonify }},
28
28
  "body_short": {{ 'comments.body_short' | t | jsonify }},
29
29
  "errors": {
30
- {%- assign kinds = "disabled,unsupported,version,timeout,network,malformed,unauthorized,forbidden,not_found,conflict,invalid,rate_limited,server,http,aborted,reference" | split: "," -%}
30
+ {%- assign kinds = "disabled,unsupported,version,timeout,network,malformed,unauthorized,forbidden,not_found,conflict,invalid,rate_limited,server,http,aborted,retry_after,reference" | split: "," -%}
31
31
  {%- for kind in kinds -%}
32
32
  {%- assign kind_key = "dynamic_services.errors." | append: kind -%}
33
33
  {{ kind | jsonify }}: {{ kind_key | t | jsonify }}{% unless forloop.last %},{% endunless %}
@@ -31,7 +31,7 @@ overrides a prompt.
31
31
  "subject_required": {{ 'contact.subject_required' | t | jsonify }},
32
32
  "message_short": {{ 'contact.message_short' | t | jsonify }},
33
33
  "errors": {
34
- {%- assign kinds = "disabled,unsupported,version,timeout,network,malformed,unauthorized,forbidden,not_found,conflict,invalid,rate_limited,server,http,aborted,reference" | split: "," -%}
34
+ {%- assign kinds = "disabled,unsupported,version,timeout,network,malformed,unauthorized,forbidden,not_found,conflict,invalid,rate_limited,server,http,aborted,retry_after,reference" | split: "," -%}
35
35
  {%- for kind in kinds -%}
36
36
  {%- assign kind_key = "dynamic_services.errors." | append: kind -%}
37
37
  {{ kind | jsonify }}: {{ kind_key | t | jsonify }}{% unless forloop.last %},{% endunless %}
@@ -24,7 +24,7 @@ their labels from `corrections.categories.*` in _data/i18n.
24
24
  "message_short": {{ 'corrections.message_short' | t | jsonify }},
25
25
  "email_invalid": {{ 'corrections.email_invalid' | t | jsonify }},
26
26
  "errors": {
27
- {%- assign kinds = "disabled,unsupported,version,timeout,network,malformed,unauthorized,forbidden,not_found,conflict,invalid,rate_limited,server,http,aborted,reference" | split: "," -%}
27
+ {%- assign kinds = "disabled,unsupported,version,timeout,network,malformed,unauthorized,forbidden,not_found,conflict,invalid,rate_limited,server,http,aborted,retry_after,reference" | split: "," -%}
28
28
  {%- for kind in kinds -%}
29
29
  {%- assign kind_key = "dynamic_services.errors." | append: kind -%}
30
30
  {{ kind | jsonify }}: {{ kind_key | t | jsonify }}{% unless forloop.last %},{% endunless %}
@@ -23,7 +23,7 @@
23
23
  <section class="hero">
24
24
  <div class="hero-overlay"></div>
25
25
  <div class="container hero-content">
26
- <h1>{{ page.hero_title | default: site.title }}</h1>
26
+ <h1>{{ page.hero_title | default: site.title | escape }}</h1>
27
27
  <p class="hero-tagline">{{ page.hero_tagline | default: site.hero_tagline }}</p>
28
28
  {% if page.hero_cta_url %}
29
29
  {% capture hero_cta_fallback %}{% t 'home.read_more' %}{% endcapture %}
@@ -62,7 +62,7 @@ a fetch credentials mode, a sign-in link) are public.
62
62
  {%- endfor -%}
63
63
  },
64
64
  "errors": {
65
- {%- assign kinds = "disabled,unsupported,version,timeout,network,malformed,unauthorized,forbidden,not_found,conflict,invalid,rate_limited,server,http,aborted,reference" | split: "," -%}
65
+ {%- assign kinds = "disabled,unsupported,version,timeout,network,malformed,unauthorized,forbidden,not_found,conflict,invalid,rate_limited,server,http,aborted,retry_after,reference" | split: "," -%}
66
66
  {%- for kind in kinds -%}
67
67
  {%- assign kind_key = "dynamic_services.errors." | append: kind -%}
68
68
  {{ kind | jsonify }}: {{ kind_key | t | jsonify }}{% unless forloop.last %},{% endunless %}
@@ -51,10 +51,10 @@ Policy does not allow inline style attributes.
51
51
  <div id="{{ hero_id }}" class="post-hero post-hero--overlay">
52
52
  <div class="post-hero__inner">
53
53
  {%- if include.page.title -%}
54
- <h1 class="article-title post-hero__title" itemprop="headline">{{ include.page.title }}</h1>
54
+ <h1 class="article-title post-hero__title" itemprop="headline">{{ include.page.title | escape }}</h1>
55
55
  {%- endif -%}
56
56
  {%- if include.page.subtitle -%}
57
- <p class="post-hero__subtitle">{{ include.page.subtitle }}</p>
57
+ <p class="post-hero__subtitle">{{ include.page.subtitle | escape }}</p>
58
58
  {%- endif -%}
59
59
  </div>
60
60
  </div>
@@ -24,7 +24,7 @@ the script from the service's answer, never here.
24
24
  "thanks": {{ 'reactions.thanks' | t | jsonify }},
25
25
  "already": {{ 'reactions.already' | t | jsonify }},
26
26
  "errors": {
27
- {%- assign kinds = "disabled,unsupported,version,timeout,network,malformed,unauthorized,forbidden,not_found,conflict,invalid,rate_limited,server,http,aborted,reference" | split: "," -%}
27
+ {%- assign kinds = "disabled,unsupported,version,timeout,network,malformed,unauthorized,forbidden,not_found,conflict,invalid,rate_limited,server,http,aborted,retry_after,reference" | split: "," -%}
28
28
  {%- for kind in kinds -%}
29
29
  {%- assign kind_key = "dynamic_services.errors." | append: kind -%}
30
30
  {{ kind | jsonify }}: {{ kind_key | t | jsonify }}{% unless forloop.last %},{% endunless %}
@@ -8,6 +8,7 @@ components/reading-list.html %}` on a page, named in
8
8
  theme_options.reading_state.list_url so posts link to it. Filled from this
9
9
  browser's storage; nothing comes from a server.
10
10
  {%- endcomment -%}
11
+ {%- unless site.theme_options.reading_state.enabled == false -%}
11
12
  {%- capture progress_label %}{% t 'post.reading_state.progress' %}{% endcapture -%}
12
13
  {%- capture highlights_label %}{% t 'post.reading_state.highlights_count' %}{% endcapture -%}
13
14
  {%- capture saved_label %}{% t 'post.reading_state.saved' %}{% endcapture -%}
@@ -29,3 +30,5 @@ browser's storage; nothing comes from a server.
29
30
  </div>
30
31
  <p class="reading-data__status" data-reading-status aria-live="polite"></p>
31
32
  </div>
33
+
34
+ {%- endunless -%}
@@ -50,6 +50,8 @@ from one page to the next.
50
50
  apply(!document.body.classList.contains('reading-mode'));
51
51
  });
52
52
  document.addEventListener('keydown', function (event) {
53
+ var target = event.target;
54
+ if (event.defaultPrevented || event.isComposing || (target && target.closest && (target.closest('input, textarea, select, [contenteditable]:not([contenteditable="false"])')))) return;
53
55
  if (event.key === 'Escape' && document.body.classList.contains('reading-mode')) {
54
56
  apply(false);
55
57
  toggle.focus();
@@ -22,15 +22,6 @@ off; without progress or highlights, only the data controls remain.
22
22
  {%- capture erased_article %}{% t 'post.reading_state.erased_article' %}{% endcapture -%}
23
23
  {%- capture erased_all %}{% t 'post.reading_state.erased_all' %}{% endcapture -%}
24
24
  <div class="reading-state" data-reading-state data-article="{{ page.url | relative_url }}" data-title="{{ page.title | escape }}" data-progress="{{ want_progress }}" data-highlights="{{ want_highlights }}">
25
- {%- if want_progress %}
26
- <div class="reading-resume" data-reading-resume data-progress-label="{{ progress_label | strip | escape }}" role="region" aria-labelledby="reading-resume-heading" hidden>
27
- <p class="reading-resume__text"><strong id="reading-resume-heading">{% t 'post.reading_state.resume' %}</strong> <span data-reading-resume-detail></span></p>
28
- <div class="reading-resume__actions">
29
- <button type="button" class="post-tool" data-reading-resume-go>{% t 'post.reading_state.resume_button' %}</button>
30
- <button type="button" class="post-tool" data-reading-resume-dismiss>{% t 'post.reading_state.dismiss' %}</button>
31
- </div>
32
- </div>
33
- {%- endif %}
34
25
  {%- if want_highlights %}
35
26
  <div class="reading-toolbar" data-reading-toolbar role="toolbar" aria-label="{% t 'post.reading_state.highlight' %}" hidden>
36
27
  <button type="button" data-reading-highlight>{% t 'post.reading_state.highlight' %}</button>
@@ -0,0 +1,17 @@
1
+ {%- comment -%}
2
+ ---
3
+ optional: []
4
+ ---
5
+ Resume prompt above the article, sharing the reading-state controller.
6
+ {%- endcomment -%}
7
+ {%- assign reading_state = site.theme_options.reading_state -%}
8
+ {%- unless reading_state.enabled == false or reading_state.progress == false -%}
9
+ {%- capture progress_label %}{% t 'post.reading_state.progress' %}{% endcapture -%}
10
+ <div class="reading-resume" data-reading-resume data-progress-label="{{ progress_label | strip | escape }}" role="region" aria-labelledby="reading-resume-heading" hidden>
11
+ <p class="reading-resume__text"><strong id="reading-resume-heading">{% t 'post.reading_state.resume' %}</strong> <span data-reading-resume-detail></span></p>
12
+ <div class="reading-resume__actions">
13
+ <button type="button" class="post-tool" data-reading-resume-go>{% t 'post.reading_state.resume_button' %}</button>
14
+ <button type="button" class="post-tool" data-reading-resume-dismiss>{% t 'post.reading_state.dismiss' %}</button>
15
+ </div>
16
+ </div>
17
+ {%- endunless -%}
@@ -33,7 +33,7 @@ own, which would make two same-named landmarks on a post.
33
33
  "email_invalid": {{ 'subscriptions.email_invalid' | t | jsonify }},
34
34
  "topics_required": {{ 'subscriptions.topics_required' | t | jsonify }},
35
35
  "errors": {
36
- {%- assign kinds = "disabled,unsupported,version,timeout,network,malformed,unauthorized,forbidden,not_found,conflict,invalid,rate_limited,server,http,aborted,reference" | split: "," -%}
36
+ {%- assign kinds = "disabled,unsupported,version,timeout,network,malformed,unauthorized,forbidden,not_found,conflict,invalid,rate_limited,server,http,aborted,retry_after,reference" | split: "," -%}
37
37
  {%- for kind in kinds -%}
38
38
  {%- assign kind_key = "dynamic_services.errors." | append: kind -%}
39
39
  {{ kind | jsonify }}: {{ kind_key | t | jsonify }}{% unless forloop.last %},{% endunless %}
@@ -23,8 +23,9 @@ may still lead here.
23
23
  "loading": {{ 'subscriptions.manage.loading' | t | jsonify }},
24
24
  "saving": {{ 'subscriptions.manage.saving' | t | jsonify }},
25
25
  "saved": {{ 'subscriptions.manage.saved' | t | jsonify }},
26
+ "retry": {{ 'subscriptions.manage.retry' | t | jsonify }},
26
27
  "errors": {
27
- {%- assign kinds = "disabled,unsupported,version,timeout,network,malformed,unauthorized,forbidden,not_found,conflict,invalid,rate_limited,server,http,aborted,reference" | split: "," -%}
28
+ {%- assign kinds = "disabled,unsupported,version,timeout,network,malformed,unauthorized,forbidden,not_found,conflict,invalid,rate_limited,server,http,aborted,retry_after,reference" | split: "," -%}
28
29
  {%- for kind in kinds -%}
29
30
  {%- assign kind_key = "dynamic_services.errors." | append: kind -%}
30
31
  {{ kind | jsonify }}: {{ kind_key | t | jsonify }}{% unless forloop.last %},{% endunless %}
@@ -4,7 +4,7 @@
4
4
  <span class="post-meta__badge">{{ tech }}</span>
5
5
  {% if visualization.version %}<span>v{{ visualization.version }}</span>{% endif %}
6
6
  </p>
7
- <h3>{{ visualization.title }}</h3>
7
+ <h3>{{ visualization.title | escape }}</h3>
8
8
  <p>{{ visualization.summary }}</p>
9
9
  {% if visualization.tags %}
10
10
  <ul class="post-list-item__tags">
@@ -30,7 +30,7 @@ The receiver itself is advertised by meta/webmention-discovery.html.
30
30
  "like": {{ 'webmentions.types.like' | t | jsonify }}
31
31
  },
32
32
  "errors": {
33
- {%- assign kinds = "disabled,unsupported,version,timeout,network,malformed,unauthorized,forbidden,not_found,conflict,invalid,rate_limited,server,http,aborted,reference" | split: "," -%}
33
+ {%- assign kinds = "disabled,unsupported,version,timeout,network,malformed,unauthorized,forbidden,not_found,conflict,invalid,rate_limited,server,http,aborted,retry_after,reference" | split: "," -%}
34
34
  {%- for kind in kinds -%}
35
35
  {%- assign kind_key = "dynamic_services.errors." | append: kind -%}
36
36
  {{ kind | jsonify }}: {{ kind_key | t | jsonify }}{% unless forloop.last %},{% endunless %}
@@ -13,7 +13,7 @@ Renders a footer navigation column with optional item descriptions.
13
13
  {%- assign column_items = '' | split: '' -%}
14
14
  {%- endif -%}
15
15
  <div>
16
- <h4>{{ include.title | strip }}</h4>
16
+ <h4>{{ include.title | strip | escape }}</h4>
17
17
  <ul>
18
18
  {%- for item in column_items -%}
19
19
  {%- capture item_label -%}{% if item.label %}{{ item.label }}{% elsif item.label_key %}{% t item.label_key %}{% endif %}{%- endcapture -%}
@@ -6,7 +6,7 @@
6
6
  <footer class="site-footer" role="contentinfo">
7
7
  <div class="container footer-container">
8
8
  <section class="footer-about">
9
- <h2>{{ site.name | default: site.title }}</h2>
9
+ <h2>{{ site.name | default: site.title | escape }}</h2>
10
10
  <p class="footer-description">{{ site.description | strip_html | truncate: 160 }}</p>
11
11
  <p class="footer-author">
12
12
  <strong>{{ site.author.name }}</strong>
@@ -28,7 +28,7 @@
28
28
  <h2 id="footer-explore-heading">Explore</h2>
29
29
  <ul class="footer-link-list">
30
30
  {% for item in footer_links %}
31
- <li><a href="{{ item.url | relative_url }}">{{ item.title }}</a></li>
31
+ <li><a href="{{ item.url | relative_url }}">{{ item.title | escape }}</a></li>
32
32
  {% endfor %}
33
33
  </ul>
34
34
  </nav>