datalog-theme 0.7.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +188 -0
- data/CITATION.cff +2 -2
- data/README.md +25 -17
- data/_data/cdn-integrity.yml +0 -30
- data/_data/i18n/en.yml +297 -0
- data/_data/i18n/es.yml +297 -0
- data/_data/i18n/pt.yml +297 -0
- data/_data/js_manifest.json +16 -0
- data/_includes/analytics/dashboard.html +3 -1
- data/_includes/components/api-function.html +20 -1
- data/_includes/components/author-bio.html +21 -11
- data/_includes/components/author-list.html +32 -0
- data/_includes/components/citation-tools.html +33 -25
- data/_includes/components/comments-thread.html +90 -0
- data/_includes/components/contact-form.html +120 -0
- data/_includes/components/correction-report.html +82 -0
- data/_includes/components/enhanced-code-block.html +1 -1
- data/_includes/components/enhanced-toc.html +6 -7
- data/_includes/components/license-link.html +13 -0
- data/_includes/components/license-notice.html +28 -0
- data/_includes/components/moderation-inbox.html +139 -0
- data/_includes/components/reactions.html +49 -0
- data/_includes/components/reading-list.html +31 -0
- data/_includes/components/reading-mode-toggle.html +65 -0
- data/_includes/components/reading-state-bookmark.html +27 -0
- data/_includes/components/reading-state-panel.html +71 -0
- data/_includes/components/reproducibility.html +61 -0
- data/_includes/components/responsive-image.html +3 -3
- data/_includes/components/revision-history.html +39 -0
- data/_includes/components/revision-notice.html +35 -0
- data/_includes/components/series-nav.html +64 -0
- data/_includes/components/subscribe-form.html +88 -0
- data/_includes/components/subscription-manage.html +68 -0
- data/_includes/components/webmentions.html +48 -0
- data/_includes/csp-meta.html +135 -11
- data/_includes/footer.html +22 -20
- data/_includes/head.html +111 -63
- data/_includes/header/navigation.html +12 -15
- data/_includes/header.html +28 -19
- data/_includes/layouts/default/article.html +9 -7
- data/_includes/meta/dynamic-services-config.html +14 -0
- data/_includes/meta/math-config.html +18 -10
- data/_includes/meta/person-json.html +27 -0
- data/_includes/meta/publisher.html +45 -0
- data/_includes/meta/schema.html +67 -30
- data/_includes/meta/scholarly.html +121 -0
- data/_includes/meta/scripts-loader.html +18 -32
- data/_includes/meta/webmention-discovery.html +14 -0
- data/_includes/post/related-posts.html +4 -7
- data/_includes/scripts.html +57 -0
- data/_includes/search/index-data.json +9 -34
- data/_layouts/dataset.html +5 -3
- data/_layouts/default.html +16 -8
- data/_layouts/notebook.html +1 -0
- data/_layouts/package.html +4 -2
- data/_layouts/page.html +15 -0
- data/_layouts/portfolio.html +1 -0
- data/_layouts/post.html +102 -23
- data/_layouts/project.html +4 -3
- data/_layouts/research.html +20 -8
- data/_plugins/analytics_dashboard.rb +9 -3
- data/_plugins/authors.rb +133 -0
- data/_plugins/config_validator.rb +231 -23
- data/_plugins/critical_css_check.rb +42 -0
- 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 +13 -12
- data/_plugins/image_optimizer.rb +241 -178
- data/_plugins/licenses.rb +135 -0
- data/_plugins/math_preprocessor.rb +59 -7
- data/_plugins/notebook_converter.rb +23 -4
- data/_plugins/plugin_loader.rb +3 -1
- data/_plugins/publications_generator.rb +8 -2
- data/_plugins/references.rb +238 -0
- data/_plugins/reproducibility.rb +150 -0
- data/_plugins/revisions.rb +101 -0
- data/_plugins/rouge_highlight_filter.rb +42 -0
- data/_plugins/scholarly.rb +50 -0
- data/_plugins/search_code_blocks.rb +30 -0
- data/_plugins/search_normalizer.rb +15 -53
- data/_plugins/search_pages.rb +3 -4
- data/_plugins/series.rb +104 -0
- data/_plugins/statements.rb +87 -0
- data/_sass/_academic-dashboard.scss +262 -0
- data/_sass/_base.scss +20 -1
- data/_sass/_comments-thread.scss +159 -0
- data/_sass/_components.scss +64 -1153
- data/_sass/_features.scss +17 -0
- data/_sass/_layout.scss +385 -1
- data/_sass/_mathematical.scss +27 -0
- data/_sass/_moderation.scss +222 -0
- data/_sass/_notebooks.scss +322 -0
- data/_sass/_open-science-badges.scss +56 -0
- data/_sass/{_phase1-enhancements.scss → _post-components.scss} +5 -3
- data/_sass/_print.scss +291 -0
- data/_sass/_reactions.scss +89 -0
- data/_sass/_reading-state.scss +290 -0
- data/_sass/_search-page.scss +530 -0
- data/_sass/_search.scss +46 -0
- data/_sass/_service-forms.scss +204 -0
- data/_sass/_subscriptions.scss +140 -0
- data/_sass/_syntax-highlighting.scss +212 -97
- data/_sass/_theme.scss +40 -19
- data/_sass/_typography.scss +130 -0
- data/_sass/_utilities.scss +5 -0
- data/_sass/_variables.scss +6 -0
- data/_sass/_webmentions.scss +125 -0
- data/assets/css/main.scss +14 -0
- data/assets/js/dist/academic.js +1 -1
- data/assets/js/dist/analytics-dashboard.js +1 -1
- data/assets/js/dist/chunks/chunk-2DYDWUFX.js +1 -0
- data/assets/js/dist/chunks/chunk-PATLC23F.js +1 -0
- data/assets/js/dist/chunks/chunk-V7734B2G.js +1 -0
- data/assets/js/dist/comments.js +2 -0
- data/assets/js/dist/contact.js +1 -0
- data/assets/js/dist/core.js +1 -1
- data/assets/js/dist/corrections.js +1 -0
- data/assets/js/dist/loader.js +1 -1
- data/assets/js/dist/math.js +1 -1
- data/assets/js/dist/moderation.js +1 -0
- data/assets/js/dist/notebook.js +1 -1
- data/assets/js/dist/reactions.js +1 -0
- data/assets/js/dist/reading-state.js +1 -0
- data/assets/js/dist/search.js +1 -1
- data/assets/js/dist/sources.json +52 -0
- data/assets/js/dist/subscriptions.js +1 -0
- data/assets/js/dist/visualizations.js +11 -2
- data/assets/js/dist/webmentions.js +1 -0
- data/assets/js/loader.js +37 -1
- data/datalog-theme.gemspec +35 -23
- data/lib/datalog/cli.rb +43 -15
- data/lib/datalog/critical_css.rb +168 -0
- data/lib/datalog/plugin_system/dependency_resolver.rb +0 -2
- data/lib/datalog/plugins/comments.rb +33 -3
- data/lib/datalog/theme/installed_files.rb +113 -0
- data/lib/datalog/theme/package.rb +57 -0
- data/lib/datalog/theme/repository_checkout.rb +94 -0
- data/lib/datalog/theme/version.rb +5 -1
- data/lib/datalog/warning_filter.rb +5 -11
- data/lib/datalog-theme.rb +6 -0
- metadata +96 -147
- data/_data/academic.yml +0 -217
- data/_data/config/author.yml +0 -121
- data/_data/datasets.yml +0 -28
- data/_data/js_meta.json +0 -371
- data/_data/navigation.yml +0 -145
- data/_data/projects.yml +0 -41
- data/_data/publications.yml +0 -28
- data/_data/social.yml +0 -73
- data/_data/visualizations.yml +0 -51
- data/_includes/components/advanced-search.html +0 -682
- data/_includes/components/bookmark-system.html +0 -96
- data/_includes/components/comments.html +0 -244
- data/_includes/components/content-recommendations.html +0 -228
- data/_includes/components/email-preferences.html +0 -200
- data/_includes/components/enhanced-metadata.html +0 -228
- data/_includes/components/language-switcher.html +0 -396
- data/_includes/components/navigation-enhancements.html +0 -454
- data/_includes/components/newsletter-signup.html +0 -178
- data/_includes/components/popular-posts.html +0 -233
- data/_includes/components/reading-progress.html +0 -133
- data/_includes/components/reading-time.html +0 -121
- data/_includes/components/series-navigation.html +0 -124
- data/_includes/components/social-proof.html +0 -34
- data/_includes/components/user-preferences.html +0 -566
- data/_includes/meta/syntax-config.html +0 -19
- data/_layouts/archive.html +0 -282
- data/_layouts/post-sidebar.html +0 -183
- data/_sass/_phase3-enhancements.scss +0 -874
- data/_sass/_phase4-enhancements.scss +0 -1214
- data/_sass/_phase5-enhancements.scss +0 -414
- data/assets/js/academic.js +0 -262
- data/assets/js/analytics-dashboard.js +0 -382
- data/assets/js/core/dark-mode.js +0 -79
- data/assets/js/core/github-cards.js +0 -123
- data/assets/js/core/language-filter.js +0 -69
- data/assets/js/core/navigation.js +0 -184
- data/assets/js/core/scroll-progress.js +0 -45
- data/assets/js/core/search-hotkeys.js +0 -62
- data/assets/js/core/skip-links.js +0 -62
- data/assets/js/dist/manifest.json +0 -22
- data/assets/js/dist/meta.json +0 -371
- data/assets/js/main.js +0 -23
- data/assets/js/math.js +0 -818
- data/assets/js/notebook.js +0 -158
- data/assets/js/search/analytics.js +0 -91
- data/assets/js/search/app.js +0 -271
- data/assets/js/search/autocomplete.js +0 -120
- data/assets/js/search/engine.js +0 -260
- data/assets/js/search/filters.js +0 -45
- data/assets/js/search/render.js +0 -217
- data/assets/js/search/utils.js +0 -99
- data/assets/js/search.js +0 -354
- data/assets/js/visualizations.js +0 -816
- data/assets/publications/datalog-publications.bib +0 -8
- data/assets/publications/datalog-publications.ris +0 -9
- data/assets/publications/publications.bib +0 -30
- data/assets/templates/diogo-ribeiro-cv.md +0 -31
- data/assets/templates/diogo-ribeiro-cv.tex +0 -32
- data/lib/datalog/theme/theme.rb +0 -18
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
{%- comment -%}
|
|
2
|
+
---
|
|
3
|
+
optional: []
|
|
4
|
+
---
|
|
5
|
+
The reading-mode control of a post: a button that hides the site's chrome
|
|
6
|
+
and the panels around the article (`body.reading-mode`, styled in
|
|
7
|
+
_sass/_print.scss) and leaves the article with its metadata, its table of
|
|
8
|
+
contents and the way back. Nothing is duplicated: the same article is shown
|
|
9
|
+
with less around it. Escape leaves the mode. `theme_options.reading_mode.enabled:
|
|
10
|
+
false` removes the control; `remember: true` keeps the choice in localStorage
|
|
11
|
+
from one page to the next.
|
|
12
|
+
{%- endcomment -%}
|
|
13
|
+
{%- assign reading_mode = site.theme_options.reading_mode -%}
|
|
14
|
+
{%- unless reading_mode.enabled == false -%}
|
|
15
|
+
{%- capture reading_enter %}{% t 'post.reading_mode.enter' %}{% endcapture -%}
|
|
16
|
+
{%- capture reading_exit %}{% t 'post.reading_mode.exit' %}{% endcapture -%}
|
|
17
|
+
<div class="reading-mode-bar">
|
|
18
|
+
<button type="button" class="post-tool reading-mode-toggle" data-reading-mode-toggle aria-pressed="false" aria-describedby="reading-mode-hint"
|
|
19
|
+
data-label-enter="{{ reading_enter | strip | escape }}" data-label-exit="{{ reading_exit | strip | escape }}"{% if reading_mode.remember %} data-reading-mode-remember{% endif %}>
|
|
20
|
+
<svg aria-hidden="true" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
21
|
+
<path d="M2 4h6a4 4 0 0 1 4 4v12a3 3 0 0 0-3-3H2z"></path>
|
|
22
|
+
<path d="M22 4h-6a4 4 0 0 0-4 4v12a3 3 0 0 1 3-3h7z"></path>
|
|
23
|
+
</svg>
|
|
24
|
+
<span data-reading-mode-label>{{ reading_enter | strip }}</span>
|
|
25
|
+
</button>
|
|
26
|
+
<span class="visually-hidden" id="reading-mode-hint">{% t 'post.reading_mode.hint' %}</span>
|
|
27
|
+
</div>
|
|
28
|
+
<script nonce="{{ page.csp_nonce }}">
|
|
29
|
+
// Reading mode: a class on the body, the button's state and label, Escape to
|
|
30
|
+
// leave, and the choice remembered only when the site asks for it.
|
|
31
|
+
(function () {
|
|
32
|
+
var toggle = document.querySelector('[data-reading-mode-toggle]');
|
|
33
|
+
if (!toggle) return;
|
|
34
|
+
var label = toggle.querySelector('[data-reading-mode-label]');
|
|
35
|
+
var remember = toggle.hasAttribute('data-reading-mode-remember');
|
|
36
|
+
var key = 'datalog-reading-mode';
|
|
37
|
+
|
|
38
|
+
function apply(on) {
|
|
39
|
+
document.body.classList.toggle('reading-mode', on);
|
|
40
|
+
toggle.setAttribute('aria-pressed', on ? 'true' : 'false');
|
|
41
|
+
label.textContent = toggle.getAttribute(on ? 'data-label-exit' : 'data-label-enter');
|
|
42
|
+
if (!remember) return;
|
|
43
|
+
try {
|
|
44
|
+
if (on) localStorage.setItem(key, 'on');
|
|
45
|
+
else localStorage.removeItem(key);
|
|
46
|
+
} catch (error) {}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
toggle.addEventListener('click', function () {
|
|
50
|
+
apply(!document.body.classList.contains('reading-mode'));
|
|
51
|
+
});
|
|
52
|
+
document.addEventListener('keydown', function (event) {
|
|
53
|
+
if (event.key === 'Escape' && document.body.classList.contains('reading-mode')) {
|
|
54
|
+
apply(false);
|
|
55
|
+
toggle.focus();
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
if (remember) {
|
|
59
|
+
try {
|
|
60
|
+
if (localStorage.getItem(key) === 'on') apply(true);
|
|
61
|
+
} catch (error) {}
|
|
62
|
+
}
|
|
63
|
+
})();
|
|
64
|
+
</script>
|
|
65
|
+
{%- endunless -%}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{%- comment -%}
|
|
2
|
+
---
|
|
3
|
+
optional: []
|
|
4
|
+
---
|
|
5
|
+
The "Save for later" button of a post (assets/js/reading-state/ui.js): a
|
|
6
|
+
bookmark kept in this browser, and a link to the saved articles when the
|
|
7
|
+
site has a page for them (theme_options.reading_state.list_url). Renders
|
|
8
|
+
nothing when reading state or bookmarks are off.
|
|
9
|
+
{%- endcomment -%}
|
|
10
|
+
{%- assign reading_state = site.theme_options.reading_state -%}
|
|
11
|
+
{%- unless reading_state.enabled == false or reading_state.bookmarks == false -%}
|
|
12
|
+
{%- capture label_save %}{% t 'post.reading_state.save' %}{% endcapture -%}
|
|
13
|
+
{%- capture label_saved %}{% t 'post.reading_state.saved' %}{% endcapture -%}
|
|
14
|
+
{%- capture label_unavailable %}{% t 'post.reading_state.unavailable' %}{% endcapture -%}
|
|
15
|
+
<button type="button" class="post-tool bookmark-toggle" data-bookmark-toggle aria-pressed="false"
|
|
16
|
+
data-article="{{ page.url | relative_url }}" data-title="{{ page.title | escape }}"
|
|
17
|
+
data-label-save="{{ label_save | strip | escape }}" data-label-saved="{{ label_saved | strip | escape }}"
|
|
18
|
+
data-unavailable="{{ label_unavailable | strip | escape }}">
|
|
19
|
+
<svg aria-hidden="true" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
20
|
+
<path d="M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z"></path>
|
|
21
|
+
</svg>
|
|
22
|
+
<span data-bookmark-label>{{ label_save | strip }}</span>
|
|
23
|
+
</button>
|
|
24
|
+
{%- if reading_state.list_url %}
|
|
25
|
+
<a class="post-tool post-tool--link" href="{{ reading_state.list_url | relative_url }}">{% t 'post.reading_state.saved_list' %}</a>
|
|
26
|
+
{%- endif %}
|
|
27
|
+
{%- endunless -%}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
{%- comment -%}
|
|
2
|
+
---
|
|
3
|
+
optional: []
|
|
4
|
+
---
|
|
5
|
+
A post's reading state (assets/js/reading-state/ui.js): the "resume where
|
|
6
|
+
you left off" prompt, the toolbar that appears over a selection, the panel
|
|
7
|
+
of private highlights and notes, and the controls to export, import and
|
|
8
|
+
erase the reader's data. Everything stays in this browser. The markup is
|
|
9
|
+
inert until the reading-state bundle runs; a browser without storage sees
|
|
10
|
+
the message and disabled controls. Renders nothing when reading state is
|
|
11
|
+
off; without progress or highlights, only the data controls remain.
|
|
12
|
+
{%- endcomment -%}
|
|
13
|
+
{%- assign reading_state = site.theme_options.reading_state -%}
|
|
14
|
+
{%- unless reading_state.enabled == false -%}
|
|
15
|
+
{%- assign want_progress = true -%}{%- if reading_state.progress == false -%}{%- assign want_progress = false -%}{%- endif -%}
|
|
16
|
+
{%- assign want_highlights = true -%}{%- if reading_state.highlights == false -%}{%- assign want_highlights = false -%}{%- endif -%}
|
|
17
|
+
{%- capture progress_label %}{% t 'post.reading_state.progress' %}{% endcapture -%}
|
|
18
|
+
{%- capture erase_confirm %}{% t 'post.reading_state.erase_confirm' %}{% endcapture -%}
|
|
19
|
+
{%- capture imported %}{% t 'post.reading_state.imported' %}{% endcapture -%}
|
|
20
|
+
{%- capture import_failed %}{% t 'post.reading_state.import_failed' %}{% endcapture -%}
|
|
21
|
+
{%- capture exported %}{% t 'post.reading_state.exported' %}{% endcapture -%}
|
|
22
|
+
{%- capture erased_article %}{% t 'post.reading_state.erased_article' %}{% endcapture -%}
|
|
23
|
+
{%- capture erased_all %}{% t 'post.reading_state.erased_all' %}{% endcapture -%}
|
|
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
|
+
{%- if want_highlights %}
|
|
35
|
+
<div class="reading-toolbar" data-reading-toolbar role="toolbar" aria-label="{% t 'post.reading_state.highlight' %}" hidden>
|
|
36
|
+
<button type="button" data-reading-highlight>{% t 'post.reading_state.highlight' %}</button>
|
|
37
|
+
<button type="button" data-reading-note>{% t 'post.reading_state.note' %}</button>
|
|
38
|
+
</div>
|
|
39
|
+
{%- endif %}
|
|
40
|
+
<section class="reading-notes" aria-labelledby="reading-notes-heading" data-reading-panel>
|
|
41
|
+
<h2 id="reading-notes-heading" class="reading-notes__heading">{% if want_highlights %}{% t 'post.reading_state.highlights_heading' %}{% else %}{% t 'post.reading_state.data_heading' %}{% endif %}</h2>
|
|
42
|
+
<p class="reading-notes__intro">{% t 'post.reading_state.intro' %}{% if want_highlights %} {% t 'post.reading_state.shortcuts' %}{% endif %}</p>
|
|
43
|
+
<p class="reading-notes__unavailable" data-reading-unavailable hidden>{% t 'post.reading_state.unavailable' %}</p>
|
|
44
|
+
{%- if want_highlights %}
|
|
45
|
+
<p class="reading-notes__empty" data-reading-empty>{% t 'post.reading_state.empty' %}</p>
|
|
46
|
+
<ul class="reading-notes__list" data-reading-list-items></ul>
|
|
47
|
+
<template data-reading-item-template>
|
|
48
|
+
<li class="reading-note" data-annotation>
|
|
49
|
+
<blockquote class="reading-note__quote" data-annotation-quote></blockquote>
|
|
50
|
+
<p class="reading-note__meta"><span data-annotation-section></span> <span class="reading-note__lost" data-annotation-lost hidden>{% t 'post.reading_state.lost' %}</span></p>
|
|
51
|
+
<label class="reading-note__label"><span>{% t 'post.reading_state.note_label' %}</span><textarea rows="2" data-annotation-note></textarea></label>
|
|
52
|
+
<div class="reading-note__actions">
|
|
53
|
+
<button type="button" class="post-tool" data-annotation-go>{% t 'post.reading_state.go_to' %}</button>
|
|
54
|
+
<button type="button" class="post-tool" data-annotation-remove>{% t 'post.reading_state.remove' %}</button>
|
|
55
|
+
</div>
|
|
56
|
+
</li>
|
|
57
|
+
</template>
|
|
58
|
+
{%- endif %}
|
|
59
|
+
<details class="reading-data">
|
|
60
|
+
<summary>{% t 'post.reading_state.data_heading' %}</summary>
|
|
61
|
+
<div class="reading-data__actions">
|
|
62
|
+
<button type="button" class="post-tool" data-reading-export data-done="{{ exported | strip | escape }}">{% t 'post.reading_state.export' %}</button>
|
|
63
|
+
<label class="post-tool reading-data__import">{% t 'post.reading_state.import' %}<input type="file" accept="application/json,.json" data-reading-import data-done="{{ imported | strip | escape }}" data-failed="{{ import_failed | strip | escape }}"></label>
|
|
64
|
+
<button type="button" class="post-tool" data-reading-erase-article data-done="{{ erased_article | strip | escape }}">{% t 'post.reading_state.erase_article' %}</button>
|
|
65
|
+
<button type="button" class="post-tool" data-reading-erase-all data-confirm="{{ erase_confirm | strip | escape }}" data-done="{{ erased_all | strip | escape }}">{% t 'post.reading_state.erase_all' %}</button>
|
|
66
|
+
</div>
|
|
67
|
+
<p class="reading-data__status" data-reading-status aria-live="polite"></p>
|
|
68
|
+
</details>
|
|
69
|
+
</section>
|
|
70
|
+
</div>
|
|
71
|
+
{%- endunless -%}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{%- comment -%}
|
|
2
|
+
---
|
|
3
|
+
required:
|
|
4
|
+
- page
|
|
5
|
+
---
|
|
6
|
+
"Reproduce this analysis": the code, data, notebook, environment and results
|
|
7
|
+
behind an article (`reproducibility` in front matter, read by the
|
|
8
|
+
page_reproducibility filter, _plugins/reproducibility.rb). Shows the
|
|
9
|
+
artifacts given, each with its identifiers, and renders nothing without one.
|
|
10
|
+
Site paths already carry the baseurl.
|
|
11
|
+
{%- endcomment -%}
|
|
12
|
+
{%- assign reproduce = include.page | page_reproducibility -%}
|
|
13
|
+
{%- if reproduce -%}
|
|
14
|
+
<section class="reproduce" aria-labelledby="reproduce-heading">
|
|
15
|
+
<h2 id="reproduce-heading" class="reproduce__heading">{% t 'post.reproduce.heading' %}</h2>
|
|
16
|
+
<p class="reproduce__intro">{% t 'post.reproduce.intro' %}</p>
|
|
17
|
+
<dl class="reproduce__list">
|
|
18
|
+
{%- for artifact in reproduce.artifacts %}
|
|
19
|
+
{%- assign kind_key = 'post.reproduce.' | append: artifact.kind %}
|
|
20
|
+
<div class="reproduce__item reproduce__item--{{ artifact.kind }}">
|
|
21
|
+
<dt>{{ kind_key | t }}</dt>
|
|
22
|
+
<dd>
|
|
23
|
+
{%- if artifact.url %}
|
|
24
|
+
<a class="reproduce__link" href="{{ artifact.url | escape }}"{% if artifact.external %} rel="external noopener"{% endif %}>{{ artifact.label | escape }}</a>
|
|
25
|
+
{%- endif %}
|
|
26
|
+
{%- if artifact.ref %}
|
|
27
|
+
{%- capture ref_text -%}
|
|
28
|
+
{%- if artifact.ref_url -%}
|
|
29
|
+
<a href="{{ artifact.ref_url | escape }}" rel="external noopener"><code>{{ artifact.ref | escape }}</code></a>
|
|
30
|
+
{%- else -%}
|
|
31
|
+
<code>{{ artifact.ref | escape }}</code>
|
|
32
|
+
{%- endif -%}
|
|
33
|
+
{%- endcapture %}
|
|
34
|
+
<span class="reproduce__detail">{% t 'post.reproduce.ref' ref: ref_text %}</span>
|
|
35
|
+
{%- endif %}
|
|
36
|
+
{%- if artifact.version %}
|
|
37
|
+
{%- assign version_text = artifact.version | escape %}
|
|
38
|
+
<span class="reproduce__detail">{% t 'post.reproduce.version' version: version_text %}</span>
|
|
39
|
+
{%- endif %}
|
|
40
|
+
{%- if artifact.doi %}
|
|
41
|
+
<span class="reproduce__detail">DOI {{ artifact.doi | escape }}</span>
|
|
42
|
+
{%- endif %}
|
|
43
|
+
{%- if artifact.file %}
|
|
44
|
+
{%- if artifact.file_url %}
|
|
45
|
+
<a class="reproduce__link" href="{{ artifact.file_url | escape }}"{% if artifact.file_url contains '://' %} rel="external noopener"{% endif %}><code>{{ artifact.file | escape }}</code></a>
|
|
46
|
+
{%- else %}
|
|
47
|
+
<code>{{ artifact.file | escape }}</code>
|
|
48
|
+
{%- endif %}
|
|
49
|
+
{%- endif %}
|
|
50
|
+
{%- if artifact.container %}
|
|
51
|
+
<span class="reproduce__detail">{% t 'post.reproduce.container' %} <code>{{ artifact.container | escape }}</code></span>
|
|
52
|
+
{%- endif %}
|
|
53
|
+
{%- if artifact.archive %}
|
|
54
|
+
<a class="reproduce__link" href="{{ artifact.archive | escape }}" rel="external noopener">{% t 'post.reproduce.archive' %}: {{ artifact.archive_label | escape }}</a>
|
|
55
|
+
{%- endif %}
|
|
56
|
+
</dd>
|
|
57
|
+
</div>
|
|
58
|
+
{%- endfor %}
|
|
59
|
+
</dl>
|
|
60
|
+
</section>
|
|
61
|
+
{%- endif -%}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
{% assign alt_text = include.alt | to_s %}
|
|
3
3
|
{% if image_src == '' or alt_text == '' %}
|
|
4
4
|
{% comment %}Missing required parameters{% endcomment %}
|
|
5
|
-
{% assign fallback_loading = include.loading | default: site.
|
|
5
|
+
{% assign fallback_loading = include.loading | default: site.datalog_image_config.lazy_loading | default: 'lazy' %}
|
|
6
6
|
<img src="{{ image_src }}" alt="{{ alt_text }}" loading="{{ fallback_loading }}" decoding="async" />
|
|
7
7
|
{% else %}
|
|
8
8
|
{% assign baseurl = site.baseurl | default: '' %}
|
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
{% assign normalized_src = normalized_src | replace: '//', '/' %}
|
|
23
23
|
{% assign responsive_entry = manifest[normalized_src] %}
|
|
24
24
|
{% endif %}
|
|
25
|
-
{% assign requested_sizes = include.sizes | default: site.
|
|
26
|
-
{% assign loading_mode = include.loading | default: site.
|
|
25
|
+
{% assign requested_sizes = include.sizes | default: site.datalog_image_config.default_sizes | default: '100vw' %}
|
|
26
|
+
{% assign loading_mode = include.loading | default: site.datalog_image_config.lazy_loading | default: 'lazy' %}
|
|
27
27
|
{% if responsive_entry %}
|
|
28
28
|
<picture>
|
|
29
29
|
{% for source in responsive_entry.sources %}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{%- comment -%}
|
|
2
|
+
---
|
|
3
|
+
required:
|
|
4
|
+
- page
|
|
5
|
+
optional:
|
|
6
|
+
- date_format
|
|
7
|
+
---
|
|
8
|
+
The revision history of an article (`revisions`, sorted newest first by
|
|
9
|
+
_plugins/revisions.rb), after its body, ending with the publication date.
|
|
10
|
+
Renders nothing for a page without revisions.
|
|
11
|
+
{%- endcomment -%}
|
|
12
|
+
{%- assign revisions = include.page.revisions -%}
|
|
13
|
+
{%- if revisions and revisions.size > 0 -%}
|
|
14
|
+
<section class="revision-history" id="revision-history" aria-labelledby="revision-history-heading">
|
|
15
|
+
<h2 id="revision-history-heading">{% t 'post.revisions.heading' %}</h2>
|
|
16
|
+
<ul class="revision-history__list">
|
|
17
|
+
{%- for revision in revisions -%}
|
|
18
|
+
{%- assign type_key = 'post.revisions.types.' | append: revision.type -%}
|
|
19
|
+
<li class="revision-history__item revision-history__item--{{ revision.type }}">
|
|
20
|
+
<time class="revision-history__date" datetime="{{ revision.date | date: '%Y-%m-%d' }}">{% include helpers/date-format.html date=revision.date format=include.date_format %}</time>
|
|
21
|
+
<span class="revision-history__type">{{ type_key | t }}</span>
|
|
22
|
+
<span class="revision-history__summary">{{ revision.summary | escape }}
|
|
23
|
+
{%- if revision.details_url -%}
|
|
24
|
+
{%- assign details_url = revision.details_url -%}
|
|
25
|
+
{%- unless details_url contains '://' -%}{%- assign details_url = details_url | relative_url -%}{%- endunless %}
|
|
26
|
+
<a class="revision-history__details" href="{{ details_url | escape }}">{% t 'post.revisions.details' %}</a>
|
|
27
|
+
{%- endif -%}
|
|
28
|
+
</span>
|
|
29
|
+
</li>
|
|
30
|
+
{%- endfor -%}
|
|
31
|
+
{%- if include.page.date -%}
|
|
32
|
+
<li class="revision-history__item revision-history__item--published">
|
|
33
|
+
<time class="revision-history__date" datetime="{{ include.page.date | date: '%Y-%m-%d' }}">{% include helpers/date-format.html date=include.page.date format=include.date_format %}</time>
|
|
34
|
+
<span class="revision-history__type">{% t 'post.revisions.types.published' %}</span>
|
|
35
|
+
</li>
|
|
36
|
+
{%- endif -%}
|
|
37
|
+
</ul>
|
|
38
|
+
</section>
|
|
39
|
+
{%- endif -%}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{%- comment -%}
|
|
2
|
+
---
|
|
3
|
+
required:
|
|
4
|
+
- page
|
|
5
|
+
optional:
|
|
6
|
+
- date_format
|
|
7
|
+
---
|
|
8
|
+
The newest correction or update of an article (`revision_notice`, set from
|
|
9
|
+
`revisions` by _plugins/revisions.rb), announced under the metadata with a
|
|
10
|
+
link to the full history. Renders nothing without one, or with
|
|
11
|
+
`revision_notice: false` in front matter.
|
|
12
|
+
{%- endcomment -%}
|
|
13
|
+
{%- assign revision = include.page.revision_notice -%}
|
|
14
|
+
{%- if revision -%}
|
|
15
|
+
{%- capture revision_date -%}{% include helpers/date-format.html date=revision.date format=include.date_format %}{%- endcapture -%}
|
|
16
|
+
{%- assign revision_date = revision_date | strip -%}
|
|
17
|
+
<aside class="revision-notice revision-notice--{{ revision.type }}" aria-labelledby="revision-notice-lead">
|
|
18
|
+
<p class="revision-notice__text">
|
|
19
|
+
<strong id="revision-notice-lead" class="revision-notice__lead">
|
|
20
|
+
{%- if revision.type == 'correction' -%}
|
|
21
|
+
{% t 'post.revisions.corrected_on' date: revision_date %}
|
|
22
|
+
{%- else -%}
|
|
23
|
+
{% t 'post.revisions.updated_on' date: revision_date %}
|
|
24
|
+
{%- endif -%}
|
|
25
|
+
</strong>
|
|
26
|
+
{{ revision.summary | escape }}
|
|
27
|
+
{%- if revision.details_url -%}
|
|
28
|
+
{%- assign details_url = revision.details_url -%}
|
|
29
|
+
{%- unless details_url contains '://' -%}{%- assign details_url = details_url | relative_url -%}{%- endunless %}
|
|
30
|
+
<a class="revision-notice__details" href="{{ details_url | escape }}">{% t 'post.revisions.details' %}</a>
|
|
31
|
+
{%- endif %}
|
|
32
|
+
<a class="revision-notice__history" href="#revision-history">{% t 'post.revisions.history_link' %}</a>
|
|
33
|
+
</p>
|
|
34
|
+
</aside>
|
|
35
|
+
{%- endif -%}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{%- comment -%}
|
|
2
|
+
---
|
|
3
|
+
required:
|
|
4
|
+
- page
|
|
5
|
+
optional:
|
|
6
|
+
- compact
|
|
7
|
+
---
|
|
8
|
+
Navigation within an article series (`series` in front matter, resolved by
|
|
9
|
+
_plugins/series.rb): the series title, "Part k of n", every part in order
|
|
10
|
+
with the current one marked, and the previous and next parts. With
|
|
11
|
+
`compact: true`, the previous and next parts alone, for the end of the
|
|
12
|
+
article. Renders nothing for a page that is not part of a series.
|
|
13
|
+
{%- endcomment -%}
|
|
14
|
+
{%- assign series = include.page.series -%}
|
|
15
|
+
{%- if series.id -%}
|
|
16
|
+
{%- capture part_of -%}{% t 'post.series.part_of' part: series.position total: series.count %}{%- endcapture -%}
|
|
17
|
+
{%- capture nav_label -%}{% t 'post.series.nav_label' title: series.title %}{%- endcapture -%}
|
|
18
|
+
{%- capture series_links -%}
|
|
19
|
+
{%- if series.previous or series.next %}
|
|
20
|
+
<div class="series-nav__links">
|
|
21
|
+
{%- if series.previous %}
|
|
22
|
+
<a class="series-nav__link series-nav__link--previous" rel="prev" href="{{ series.previous.url | relative_url }}">
|
|
23
|
+
<span class="series-nav__link-label">{% t 'post.series.previous' %}</span>
|
|
24
|
+
<span class="series-nav__link-title">{{ series.previous.title | escape }}</span>
|
|
25
|
+
</a>
|
|
26
|
+
{%- endif %}
|
|
27
|
+
{%- if series.next %}
|
|
28
|
+
<a class="series-nav__link series-nav__link--next" rel="next" href="{{ series.next.url | relative_url }}">
|
|
29
|
+
<span class="series-nav__link-label">{% t 'post.series.next' %}</span>
|
|
30
|
+
<span class="series-nav__link-title">{{ series.next.title | escape }}</span>
|
|
31
|
+
</a>
|
|
32
|
+
{%- endif %}
|
|
33
|
+
</div>
|
|
34
|
+
{%- endif %}
|
|
35
|
+
{%- endcapture -%}
|
|
36
|
+
{%- if include.compact -%}
|
|
37
|
+
{%- if series.previous or series.next -%}
|
|
38
|
+
<nav class="series-nav series-nav--compact" aria-label="{{ nav_label | strip | escape }}">
|
|
39
|
+
<p class="series-nav__context">{{ series.title | escape }} · {{ part_of | strip }}</p>
|
|
40
|
+
{{- series_links }}
|
|
41
|
+
</nav>
|
|
42
|
+
{%- endif -%}
|
|
43
|
+
{%- else -%}
|
|
44
|
+
<nav class="series-nav" aria-labelledby="series-nav-heading">
|
|
45
|
+
<p class="series-nav__heading" id="series-nav-heading">
|
|
46
|
+
<span class="series-nav__label">{% t 'post.series.label' %}</span>
|
|
47
|
+
<span class="series-nav__title">{{ series.title | escape }}</span>
|
|
48
|
+
<span class="series-nav__position">{{ part_of | strip }}</span>
|
|
49
|
+
</p>
|
|
50
|
+
{%- if series.description %}
|
|
51
|
+
<p class="series-nav__description">{{ series.description | escape }}</p>
|
|
52
|
+
{%- endif %}
|
|
53
|
+
<progress class="series-nav__progress" value="{{ series.position }}" max="{{ series.count }}" aria-hidden="true"></progress>
|
|
54
|
+
<ol class="series-nav__list">
|
|
55
|
+
{%- for part in series.parts %}
|
|
56
|
+
<li class="series-nav__part{% if part.current %} series-nav__part--current{% endif %}">
|
|
57
|
+
<a href="{{ part.url | relative_url }}"{% if part.current %} aria-current="page"{% endif %}>{{ part.title | escape }}</a>
|
|
58
|
+
</li>
|
|
59
|
+
{%- endfor %}
|
|
60
|
+
</ol>
|
|
61
|
+
{{- series_links }}
|
|
62
|
+
</nav>
|
|
63
|
+
{%- endif -%}
|
|
64
|
+
{%- endif -%}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
{%- comment -%}
|
|
2
|
+
---
|
|
3
|
+
optional:
|
|
4
|
+
- where
|
|
5
|
+
---
|
|
6
|
+
The newsletter subscribe form (assets/js/subscriptions/form.js): an email
|
|
7
|
+
address and, when `subscriptions.topics` lists any, what to receive, sent
|
|
8
|
+
to the site's dynamic services (docs/dynamic-services.md). Renders only
|
|
9
|
+
when the site has a backend with the subscriptions feature on and
|
|
10
|
+
`subscriptions.enabled` is not false; the footer and the post layout
|
|
11
|
+
include it where `subscriptions.placement` says. `where` ("footer",
|
|
12
|
+
"post" or "page", the default) keeps the ids apart when a page carries
|
|
13
|
+
more than one, and picks the heading level.
|
|
14
|
+
|
|
15
|
+
The footer is an include_cached, rendered once per language and reused on
|
|
16
|
+
every page, so the footer form carries nothing of the page: the script
|
|
17
|
+
reads the page's address from its canonical link and its language from
|
|
18
|
+
<html lang>. For the same reason the block has no accessible name of its
|
|
19
|
+
own, which would make two same-named landmarks on a post.
|
|
20
|
+
{%- endcomment -%}
|
|
21
|
+
{%- assign services = site.dynamic_services -%}
|
|
22
|
+
{%- assign subscriptions = site.subscriptions -%}
|
|
23
|
+
{%- if services.base_url and services.base_url != '' and services.features.subscriptions != false and subscriptions.enabled != false -%}
|
|
24
|
+
{%- assign where = include.where | default: 'page' -%}
|
|
25
|
+
{%- assign topics = subscriptions.topics -%}
|
|
26
|
+
{%- assign privacy_url = subscriptions.privacy_url | default: nil -%}
|
|
27
|
+
{%- capture labels_json -%}
|
|
28
|
+
{
|
|
29
|
+
"sending": {{ 'subscriptions.sending' | t | jsonify }},
|
|
30
|
+
"pending": {{ 'subscriptions.pending' | t | jsonify }},
|
|
31
|
+
"confirmed": {{ 'subscriptions.confirmed' | t | jsonify }},
|
|
32
|
+
"duplicate": {{ 'subscriptions.duplicate' | t | jsonify }},
|
|
33
|
+
"email_invalid": {{ 'subscriptions.email_invalid' | t | jsonify }},
|
|
34
|
+
"topics_required": {{ 'subscriptions.topics_required' | t | jsonify }},
|
|
35
|
+
"errors": {
|
|
36
|
+
{%- assign kinds = "disabled,unsupported,version,timeout,network,malformed,unauthorized,forbidden,not_found,conflict,invalid,rate_limited,server,http,aborted,reference" | split: "," -%}
|
|
37
|
+
{%- for kind in kinds -%}
|
|
38
|
+
{%- assign kind_key = "dynamic_services.errors." | append: kind -%}
|
|
39
|
+
{{ kind | jsonify }}: {{ kind_key | t | jsonify }}{% unless forloop.last %},{% endunless %}
|
|
40
|
+
{%- endfor -%}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
{%- endcapture -%}
|
|
44
|
+
<section class="subscribe subscribe--{{ where }}" data-subscribe{% unless where == 'footer' %} data-subscribe-source="{{ page.url | absolute_url }}" data-subscribe-locale="{{ page.lang | default: site.lang | default: 'en' }}"{% endunless %} data-subscribe-double-opt-in="{% if subscriptions.double_opt_in == false %}false{% else %}true{% endif %}">
|
|
45
|
+
<script type="application/json" data-subscribe-labels>{{ labels_json | strip }}</script>
|
|
46
|
+
{%- if where == 'footer' %}
|
|
47
|
+
<h3 class="subscribe__heading" id="subscribe-heading-{{ where }}">{% t 'footer.subscribe_title' %}</h3>
|
|
48
|
+
{%- else %}
|
|
49
|
+
<h2 class="subscribe__heading" id="subscribe-heading-{{ where }}">{% t 'footer.subscribe_title' %}</h2>
|
|
50
|
+
{%- endif %}
|
|
51
|
+
<p class="subscribe__description">{% t 'footer.subscribe_description' %}</p>
|
|
52
|
+
<form class="service-form subscribe__form" id="subscribe-form-{{ where }}" data-state="idle" aria-busy="false" novalidate>
|
|
53
|
+
<fieldset class="service-form__fields">
|
|
54
|
+
<legend class="visually-hidden">{% t 'footer.subscribe_title' %}</legend>
|
|
55
|
+
<div class="service-form__field">
|
|
56
|
+
<label for="subscribe-email-{{ where }}">{% t 'footer.newsletter_label' %}</label>
|
|
57
|
+
<input id="subscribe-email-{{ where }}" name="email" type="email" required autocomplete="email">
|
|
58
|
+
<p class="service-form__error" data-error-for="email" hidden></p>
|
|
59
|
+
</div>
|
|
60
|
+
{%- if topics and topics.size > 0 %}
|
|
61
|
+
<fieldset class="subscribe__topics">
|
|
62
|
+
<legend>{% t 'subscriptions.topics_legend' %}</legend>
|
|
63
|
+
{%- for topic in topics %}
|
|
64
|
+
{%- assign topic_key = "subscriptions.topics." | append: topic %}
|
|
65
|
+
<label class="subscribe__topic" for="subscribe-topic-{{ where }}-{{ topic | slugify }}">
|
|
66
|
+
<input id="subscribe-topic-{{ where }}-{{ topic | slugify }}" type="checkbox" name="topics" value="{{ topic | escape }}" checked>
|
|
67
|
+
{{ topic_key | t }}
|
|
68
|
+
</label>
|
|
69
|
+
{%- endfor %}
|
|
70
|
+
<p class="service-form__error" data-error-for="topics" hidden></p>
|
|
71
|
+
</fieldset>
|
|
72
|
+
{%- endif %}
|
|
73
|
+
<div class="service-form__trap" aria-hidden="true">
|
|
74
|
+
<label for="subscribe-website-{{ where }}">Website</label>
|
|
75
|
+
<input id="subscribe-website-{{ where }}" name="website" type="text" tabindex="-1" autocomplete="off">
|
|
76
|
+
</div>
|
|
77
|
+
</fieldset>
|
|
78
|
+
<p class="service-form__privacy">
|
|
79
|
+
{%- if subscriptions.double_opt_in == false %}{% t 'subscriptions.consent' %}{% else %}{% t 'subscriptions.consent_double' %}{% endif %}
|
|
80
|
+
{%- if privacy_url %} <a href="{{ privacy_url | relative_url }}">{% t 'subscriptions.privacy_link' %}</a>{% endif -%}
|
|
81
|
+
</p>
|
|
82
|
+
<div class="service-form__actions">
|
|
83
|
+
<button type="submit" class="post-tool">{% t 'footer.newsletter_button' %}</button>
|
|
84
|
+
</div>
|
|
85
|
+
<p class="service-form__status" data-form-status role="status" aria-live="polite" hidden></p>
|
|
86
|
+
</form>
|
|
87
|
+
</section>
|
|
88
|
+
{%- endif -%}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{%- comment -%}
|
|
2
|
+
---
|
|
3
|
+
optional: []
|
|
4
|
+
---
|
|
5
|
+
The page the newsletter's emails link to (assets/js/subscriptions/manage.js):
|
|
6
|
+
`?confirm=<token>` confirms a subscription, `?unsubscribe=<token>` ends one
|
|
7
|
+
after a press of the button, `?manage=<token>` changes its topics. Rendered
|
|
8
|
+
by the page layout when the page says `subscription_manage: true`. Without
|
|
9
|
+
a backend offering the feature it says so, since a link in an old email
|
|
10
|
+
may still lead here.
|
|
11
|
+
{%- endcomment -%}
|
|
12
|
+
{%- assign services = site.dynamic_services -%}
|
|
13
|
+
{%- assign subscriptions = site.subscriptions -%}
|
|
14
|
+
{%- if services.base_url and services.base_url != '' and services.features.subscriptions != false and subscriptions.enabled != false -%}
|
|
15
|
+
{%- assign topics = subscriptions.topics -%}
|
|
16
|
+
{%- capture labels_json -%}
|
|
17
|
+
{
|
|
18
|
+
"confirming": {{ 'subscriptions.manage.confirming' | t | jsonify }},
|
|
19
|
+
"confirmed": {{ 'subscriptions.manage.confirmed' | t | jsonify }},
|
|
20
|
+
"invalid_link": {{ 'subscriptions.manage.invalid_link' | t | jsonify }},
|
|
21
|
+
"unsubscribing": {{ 'subscriptions.manage.unsubscribing' | t | jsonify }},
|
|
22
|
+
"unsubscribed": {{ 'subscriptions.manage.unsubscribed' | t | jsonify }},
|
|
23
|
+
"loading": {{ 'subscriptions.manage.loading' | t | jsonify }},
|
|
24
|
+
"saving": {{ 'subscriptions.manage.saving' | t | jsonify }},
|
|
25
|
+
"saved": {{ 'subscriptions.manage.saved' | t | jsonify }},
|
|
26
|
+
"errors": {
|
|
27
|
+
{%- assign kinds = "disabled,unsupported,version,timeout,network,malformed,unauthorized,forbidden,not_found,conflict,invalid,rate_limited,server,http,aborted,reference" | split: "," -%}
|
|
28
|
+
{%- for kind in kinds -%}
|
|
29
|
+
{%- assign kind_key = "dynamic_services.errors." | append: kind -%}
|
|
30
|
+
{{ kind | jsonify }}: {{ kind_key | t | jsonify }}{% unless forloop.last %},{% endunless %}
|
|
31
|
+
{%- endfor -%}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
{%- endcapture -%}
|
|
35
|
+
<section class="subscription-manage" id="subscription-manage" data-subscription-manage data-state="idle" aria-busy="false">
|
|
36
|
+
<script type="application/json" nonce="{{ page.csp_nonce }}" data-manage-labels>{{ labels_json | strip }}</script>
|
|
37
|
+
<p class="subscription-manage__status" data-manage-status role="status" aria-live="polite" hidden></p>
|
|
38
|
+
<p class="subscription-manage__idle" data-manage-idle>{% t 'subscriptions.manage.idle' %}</p>
|
|
39
|
+
<div class="subscription-manage__panel" data-manage-unsubscribe-panel hidden>
|
|
40
|
+
<p>{% t 'subscriptions.manage.unsubscribe_question' %}</p>
|
|
41
|
+
<button type="button" class="post-tool" data-manage-unsubscribe>{% t 'subscriptions.manage.unsubscribe' %}</button>
|
|
42
|
+
</div>
|
|
43
|
+
<form class="service-form subscription-manage__panel" id="subscription-preferences" data-manage-preferences hidden novalidate>
|
|
44
|
+
{%- if topics and topics.size > 0 %}
|
|
45
|
+
<fieldset class="subscribe__topics">
|
|
46
|
+
<legend>{% t 'subscriptions.manage.preferences' %}</legend>
|
|
47
|
+
{%- for topic in topics %}
|
|
48
|
+
{%- assign topic_key = "subscriptions.topics." | append: topic %}
|
|
49
|
+
<label class="subscribe__topic" for="manage-topic-{{ topic | slugify }}">
|
|
50
|
+
<input id="manage-topic-{{ topic | slugify }}" type="checkbox" name="topics" value="{{ topic | escape }}">
|
|
51
|
+
{{ topic_key | t }}
|
|
52
|
+
</label>
|
|
53
|
+
{%- endfor %}
|
|
54
|
+
</fieldset>
|
|
55
|
+
{%- endif %}
|
|
56
|
+
<div class="service-form__actions">
|
|
57
|
+
{%- if topics and topics.size > 0 %}
|
|
58
|
+
<button type="submit" class="post-tool">{% t 'subscriptions.manage.save' %}</button>
|
|
59
|
+
{%- endif %}
|
|
60
|
+
<button type="button" class="post-tool" data-manage-unsubscribe>{% t 'subscriptions.manage.unsubscribe' %}</button>
|
|
61
|
+
</div>
|
|
62
|
+
</form>
|
|
63
|
+
</section>
|
|
64
|
+
{%- else -%}
|
|
65
|
+
<section class="subscription-manage" id="subscription-manage">
|
|
66
|
+
<p class="subscription-manage__idle">{% t 'subscriptions.manage.unavailable' %}</p>
|
|
67
|
+
</section>
|
|
68
|
+
{%- endif -%}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{%- comment -%}
|
|
2
|
+
---
|
|
3
|
+
optional: []
|
|
4
|
+
---
|
|
5
|
+
"Mentioned elsewhere" (assets/js/webmentions/list.js): the links, replies
|
|
6
|
+
and reposts other websites sent about this article, read through the
|
|
7
|
+
site's dynamic services (docs/dynamic-services.md) from what the
|
|
8
|
+
Webmention receiver verified. Apart from the comments, which are hosted
|
|
9
|
+
here. Renders only when the site has a backend with the webmentions
|
|
10
|
+
feature on, `webmentions.enabled` is not false, and the page does not say
|
|
11
|
+
`webmentions: false`. The kinds shown come from `webmentions.types`.
|
|
12
|
+
The receiver itself is advertised by meta/webmention-discovery.html.
|
|
13
|
+
{%- endcomment -%}
|
|
14
|
+
{%- assign services = site.dynamic_services -%}
|
|
15
|
+
{%- assign webmentions = site.webmentions -%}
|
|
16
|
+
{%- if services.base_url and services.base_url != '' and services.features.webmentions != false and webmentions.enabled != false and page.webmentions != false -%}
|
|
17
|
+
{%- assign types = webmentions.types -%}
|
|
18
|
+
{%- if types == nil or types.size == 0 -%}
|
|
19
|
+
{%- assign types = "mention,reply" | split: "," -%}
|
|
20
|
+
{%- endif -%}
|
|
21
|
+
{%- capture labels_json -%}
|
|
22
|
+
{
|
|
23
|
+
"loading": {{ 'webmentions.loading' | t | jsonify }},
|
|
24
|
+
"empty": {{ 'webmentions.empty' | t | jsonify }},
|
|
25
|
+
"retry": {{ 'webmentions.retry' | t | jsonify }},
|
|
26
|
+
"types": {
|
|
27
|
+
"mention": {{ 'webmentions.types.mention' | t | jsonify }},
|
|
28
|
+
"reply": {{ 'webmentions.types.reply' | t | jsonify }},
|
|
29
|
+
"repost": {{ 'webmentions.types.repost' | t | jsonify }},
|
|
30
|
+
"like": {{ 'webmentions.types.like' | t | jsonify }}
|
|
31
|
+
},
|
|
32
|
+
"errors": {
|
|
33
|
+
{%- assign kinds = "disabled,unsupported,version,timeout,network,malformed,unauthorized,forbidden,not_found,conflict,invalid,rate_limited,server,http,aborted,reference" | split: "," -%}
|
|
34
|
+
{%- for kind in kinds -%}
|
|
35
|
+
{%- assign kind_key = "dynamic_services.errors." | append: kind -%}
|
|
36
|
+
{{ kind | jsonify }}: {{ kind_key | t | jsonify }}{% unless forloop.last %},{% endunless %}
|
|
37
|
+
{%- endfor -%}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
{%- endcapture -%}
|
|
41
|
+
<section class="webmentions" id="webmentions" data-webmentions data-webmentions-target="{{ page.url | absolute_url }}" data-webmentions-types="{{ types | join: ',' }}" data-state="idle" aria-labelledby="webmentions-heading">
|
|
42
|
+
<script type="application/json" nonce="{{ page.csp_nonce }}" data-webmentions-labels>{{ labels_json | strip }}</script>
|
|
43
|
+
<h2 class="webmentions__heading" id="webmentions-heading">{% t 'webmentions.heading' %}</h2>
|
|
44
|
+
<p class="webmentions__intro">{% t 'webmentions.intro' %}</p>
|
|
45
|
+
<p class="webmentions__status" data-webmentions-status role="status" aria-live="polite">{% t 'webmentions.loading' %}</p>
|
|
46
|
+
<ul class="webmentions__list" data-webmentions-list hidden></ul>
|
|
47
|
+
</section>
|
|
48
|
+
{%- endif -%}
|