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
|
@@ -1,233 +0,0 @@
|
|
|
1
|
-
{%- comment -%}
|
|
2
|
-
Popular Posts Widget Component
|
|
3
|
-
Displays trending and most popular content
|
|
4
|
-
|
|
5
|
-
Parameters:
|
|
6
|
-
- max_posts: Maximum posts to display (default: 5)
|
|
7
|
-
- sort_by: Sorting method (recent, comments, trending) (default: recent)
|
|
8
|
-
- show_stats: Show reading stats (default: true)
|
|
9
|
-
- show_thumbnail: Show post thumbnail (default: true)
|
|
10
|
-
- layout: Display layout (list, grid, compact) (default: list)
|
|
11
|
-
- heading: Custom heading (default: "Popular Posts")
|
|
12
|
-
{%- endcomment -%}
|
|
13
|
-
|
|
14
|
-
{%- assign max_posts = include.max_posts | default: 5 -%}
|
|
15
|
-
{%- assign sort_by = include.sort_by | default: "recent" -%}
|
|
16
|
-
{%- assign show_stats = include.show_stats | default: true -%}
|
|
17
|
-
{%- assign show_thumbnail = include.show_thumbnail | default: true -%}
|
|
18
|
-
{%- assign layout = include.layout | default: "list" -%}
|
|
19
|
-
{%- assign heading = include.heading | default: "Popular Posts" -%}
|
|
20
|
-
|
|
21
|
-
{%- comment -%} Get posts and apply basic filtering {%- endcomment -%}
|
|
22
|
-
{%- assign all_posts = site.posts -%}
|
|
23
|
-
|
|
24
|
-
{%- comment -%} Simulate popularity scoring (in real app, use analytics data) {%- endcomment -%}
|
|
25
|
-
{%- assign scored_posts = "" | split: "" -%}
|
|
26
|
-
|
|
27
|
-
{%- for post in all_posts limit: 20 -%}
|
|
28
|
-
{%- assign score = 0 -%}
|
|
29
|
-
|
|
30
|
-
{%- comment -%} Recency score (prefer recent content) {%- endcomment -%}
|
|
31
|
-
{%- assign days_old = "now" | date: "%s" | minus: post.date | date: "%s" | divided_by: 86400 -%}
|
|
32
|
-
{%- if days_old < 7 -%}
|
|
33
|
-
{%- assign score = score | plus: 50 -%}
|
|
34
|
-
{%- elsif days_old < 30 -%}
|
|
35
|
-
{%- assign score = score | plus: 30 -%}
|
|
36
|
-
{%- elsif days_old < 90 -%}
|
|
37
|
-
{%- assign score = score | plus: 10 -%}
|
|
38
|
-
{%- endif -%}
|
|
39
|
-
|
|
40
|
-
{%- comment -%} Tag count (more tags = more discoverable) {%- endcomment -%}
|
|
41
|
-
{%- assign tag_score = post.tags.size | times: 5 -%}
|
|
42
|
-
{%- assign score = score | plus: tag_score -%}
|
|
43
|
-
|
|
44
|
-
{%- comment -%} Featured posts bonus {%- endcomment -%}
|
|
45
|
-
{%- if post.featured -%}
|
|
46
|
-
{%- assign score = score | plus: 25 -%}
|
|
47
|
-
{%- endif -%}
|
|
48
|
-
|
|
49
|
-
{%- comment -%} Difficulty-based scoring (beginner posts might be more popular) {%- endcomment -%}
|
|
50
|
-
{%- if post.difficulty == "beginner" -%}
|
|
51
|
-
{%- assign score = score | plus: 15 -%}
|
|
52
|
-
{%- endif -%}
|
|
53
|
-
|
|
54
|
-
{%- comment -%} Add randomness for variety (simulates view counts) {%- endcomment -%}
|
|
55
|
-
{%- assign random_bonus = post.title | size | modulo: 30 -%}
|
|
56
|
-
{%- assign score = score | plus: random_bonus -%}
|
|
57
|
-
|
|
58
|
-
{%- comment -%} Store post with score {%- endcomment -%}
|
|
59
|
-
{%- assign post_with_score = post.url | append: "||" | append: score -%}
|
|
60
|
-
{%- assign scored_posts = scored_posts | push: post_with_score -%}
|
|
61
|
-
{%- endfor -%}
|
|
62
|
-
|
|
63
|
-
{%- comment -%} Simple bubble sort by score {%- endcomment -%}
|
|
64
|
-
{%- assign sorted_posts = scored_posts -%}
|
|
65
|
-
{%- for i in (1..scored_posts.size) -%}
|
|
66
|
-
{%- for j in (1..scored_posts.size) -%}
|
|
67
|
-
{%- assign current = sorted_posts[j] | split: "||" -%}
|
|
68
|
-
{%- assign prev = sorted_posts[j-1] | split: "||" -%}
|
|
69
|
-
{%- if current[1] and prev[1] -%}
|
|
70
|
-
{%- assign current_score = current[1] | plus: 0 -%}
|
|
71
|
-
{%- assign prev_score = prev[1] | plus: 0 -%}
|
|
72
|
-
{%- if current_score > prev_score -%}
|
|
73
|
-
{%- assign temp = sorted_posts[j] -%}
|
|
74
|
-
{%- assign sorted_posts[j] = sorted_posts[j-1] -%}
|
|
75
|
-
{%- assign sorted_posts[j-1] = temp -%}
|
|
76
|
-
{%- endif -%}
|
|
77
|
-
{%- endif -%}
|
|
78
|
-
{%- endfor -%}
|
|
79
|
-
{%- endfor -%}
|
|
80
|
-
|
|
81
|
-
{%- comment -%} Build popular posts array {%- endcomment -%}
|
|
82
|
-
{%- assign popular_posts = "" | split: "" -%}
|
|
83
|
-
{%- for item in sorted_posts limit: max_posts -%}
|
|
84
|
-
{%- assign item_parts = item | split: "||" -%}
|
|
85
|
-
{%- assign post_url = item_parts[0] -%}
|
|
86
|
-
|
|
87
|
-
{%- for post in site.posts -%}
|
|
88
|
-
{%- if post.url == post_url -%}
|
|
89
|
-
{%- assign popular_posts = popular_posts | push: post -%}
|
|
90
|
-
{%- break -%}
|
|
91
|
-
{%- endif -%}
|
|
92
|
-
{%- endfor -%}
|
|
93
|
-
{%- endfor -%}
|
|
94
|
-
|
|
95
|
-
<aside class="popular-posts popular-posts--{{ layout }}"
|
|
96
|
-
data-popular-posts
|
|
97
|
-
aria-label="{{ heading }}">
|
|
98
|
-
|
|
99
|
-
<div class="popular-posts__header">
|
|
100
|
-
<h3 class="popular-posts__title">
|
|
101
|
-
<svg xmlns="http://www.w3.org/2000/svg"
|
|
102
|
-
width="20"
|
|
103
|
-
height="20"
|
|
104
|
-
viewBox="0 0 24 24"
|
|
105
|
-
fill="none"
|
|
106
|
-
stroke="currentColor"
|
|
107
|
-
stroke-width="2"
|
|
108
|
-
stroke-linecap="round"
|
|
109
|
-
stroke-linejoin="round"
|
|
110
|
-
aria-hidden="true">
|
|
111
|
-
<polyline points="23 6 13.5 15.5 8.5 10.5 1 18"></polyline>
|
|
112
|
-
<polyline points="17 6 23 6 23 12"></polyline>
|
|
113
|
-
</svg>
|
|
114
|
-
{{ heading }}
|
|
115
|
-
</h3>
|
|
116
|
-
|
|
117
|
-
{%- if show_stats -%}
|
|
118
|
-
<span class="popular-posts__subtitle">
|
|
119
|
-
Trending this month
|
|
120
|
-
</span>
|
|
121
|
-
{%- endif -%}
|
|
122
|
-
</div>
|
|
123
|
-
|
|
124
|
-
<div class="popular-posts__list">
|
|
125
|
-
{%- for post in popular_posts -%}
|
|
126
|
-
{%- assign loop_index = forloop.index -%}
|
|
127
|
-
|
|
128
|
-
<article class="popular-post"
|
|
129
|
-
itemscope
|
|
130
|
-
itemtype="https://schema.org/BlogPosting">
|
|
131
|
-
|
|
132
|
-
<div class="popular-post__rank" aria-label="Rank {{ loop_index }}">
|
|
133
|
-
{{ loop_index }}
|
|
134
|
-
</div>
|
|
135
|
-
|
|
136
|
-
{%- if show_thumbnail and post.featured_image or post.image -%}
|
|
137
|
-
<div class="popular-post__thumbnail">
|
|
138
|
-
<a href="{{ post.url | relative_url }}"
|
|
139
|
-
tabindex="-1"
|
|
140
|
-
aria-hidden="true">
|
|
141
|
-
<img src="{{ post.featured_image | default: post.image | relative_url }}"
|
|
142
|
-
alt=""
|
|
143
|
-
loading="lazy"
|
|
144
|
-
itemprop="image">
|
|
145
|
-
</a>
|
|
146
|
-
</div>
|
|
147
|
-
{%- endif -%}
|
|
148
|
-
|
|
149
|
-
<div class="popular-post__content">
|
|
150
|
-
<h4 class="popular-post__title" itemprop="headline">
|
|
151
|
-
<a href="{{ post.url | relative_url }}"
|
|
152
|
-
class="popular-post__link">
|
|
153
|
-
{{ post.title }}
|
|
154
|
-
</a>
|
|
155
|
-
</h4>
|
|
156
|
-
|
|
157
|
-
{%- if show_stats -%}
|
|
158
|
-
<div class="popular-post__meta">
|
|
159
|
-
{%- if post.date -%}
|
|
160
|
-
<time class="popular-post__date"
|
|
161
|
-
datetime="{{ post.date | date_to_xmlschema }}"
|
|
162
|
-
itemprop="datePublished">
|
|
163
|
-
{{ post.date | date: "%b %d, %Y" }}
|
|
164
|
-
</time>
|
|
165
|
-
{%- endif -%}
|
|
166
|
-
|
|
167
|
-
<span class="popular-post__separator" aria-hidden="true">•</span>
|
|
168
|
-
|
|
169
|
-
{%- comment -%} Reading time {%- endcomment -%}
|
|
170
|
-
{% include components/reading-time.html
|
|
171
|
-
content=post.content
|
|
172
|
-
variant="inline"
|
|
173
|
-
show_icon=false %}
|
|
174
|
-
|
|
175
|
-
{%- comment -%} View count removed — was simulated. Re-enable with real analytics data. {%- endcomment -%}
|
|
176
|
-
</div>
|
|
177
|
-
{%- endif -%}
|
|
178
|
-
|
|
179
|
-
{%- if post.excerpt and layout != "compact" -%}
|
|
180
|
-
<p class="popular-post__excerpt" itemprop="description">
|
|
181
|
-
{{ post.excerpt | strip_html | truncatewords: 15 }}
|
|
182
|
-
</p>
|
|
183
|
-
{%- endif -%}
|
|
184
|
-
|
|
185
|
-
{%- if post.tags.size > 0 and layout == "grid" -%}
|
|
186
|
-
<div class="popular-post__tags">
|
|
187
|
-
{%- for tag in post.tags limit: 2 -%}
|
|
188
|
-
<span class="popular-post__tag">{{ tag }}</span>
|
|
189
|
-
{%- endfor -%}
|
|
190
|
-
</div>
|
|
191
|
-
{%- endif -%}
|
|
192
|
-
</div>
|
|
193
|
-
|
|
194
|
-
{%- comment -%} Trending indicator for top 3 {%- endcomment -%}
|
|
195
|
-
{%- if loop_index <= 3 -%}
|
|
196
|
-
<div class="popular-post__badge" aria-label="Trending">
|
|
197
|
-
<svg xmlns="http://www.w3.org/2000/svg"
|
|
198
|
-
width="16"
|
|
199
|
-
height="16"
|
|
200
|
-
viewBox="0 0 24 24"
|
|
201
|
-
fill="none"
|
|
202
|
-
stroke="currentColor"
|
|
203
|
-
stroke-width="2"
|
|
204
|
-
aria-hidden="true">
|
|
205
|
-
<polyline points="23 6 13.5 15.5 8.5 10.5 1 18"></polyline>
|
|
206
|
-
<polyline points="17 6 23 6 23 12"></polyline>
|
|
207
|
-
</svg>
|
|
208
|
-
</div>
|
|
209
|
-
{%- endif -%}
|
|
210
|
-
</article>
|
|
211
|
-
{%- endfor -%}
|
|
212
|
-
</div>
|
|
213
|
-
|
|
214
|
-
{%- if site.phase4_features.popular_posts.show_view_all -%}
|
|
215
|
-
<div class="popular-posts__footer">
|
|
216
|
-
<a href="{{ '/archive/' | relative_url }}"
|
|
217
|
-
class="popular-posts__view-all">
|
|
218
|
-
View all posts
|
|
219
|
-
<svg xmlns="http://www.w3.org/2000/svg"
|
|
220
|
-
width="16"
|
|
221
|
-
height="16"
|
|
222
|
-
viewBox="0 0 24 24"
|
|
223
|
-
fill="none"
|
|
224
|
-
stroke="currentColor"
|
|
225
|
-
stroke-width="2"
|
|
226
|
-
aria-hidden="true">
|
|
227
|
-
<line x1="5" y1="12" x2="19" y2="12"></line>
|
|
228
|
-
<polyline points="12 5 19 12 12 19"></polyline>
|
|
229
|
-
</svg>
|
|
230
|
-
</a>
|
|
231
|
-
</div>
|
|
232
|
-
{%- endif -%}
|
|
233
|
-
</aside>
|
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
{%- comment -%}
|
|
2
|
-
Reading Progress Tracker
|
|
3
|
-
Displays a visual indicator of reading progress with time estimate
|
|
4
|
-
|
|
5
|
-
Parameters:
|
|
6
|
-
- position: Position on page (top, bottom, sticky)
|
|
7
|
-
- show_time: Show time remaining estimate (default: true)
|
|
8
|
-
- show_percentage: Show percentage complete (default: true)
|
|
9
|
-
{%- endcomment -%}
|
|
10
|
-
|
|
11
|
-
{%- assign position = include.position | default: "top" -%}
|
|
12
|
-
{%- assign show_time = include.show_time | default: true -%}
|
|
13
|
-
{%- assign show_percentage = include.show_percentage | default: true -%}
|
|
14
|
-
|
|
15
|
-
<div class="reading-progress reading-progress--{{ position }}" data-reading-progress aria-label="Reading progress">
|
|
16
|
-
{%- comment -%} Progress bar {%- endcomment -%}
|
|
17
|
-
<div class="reading-progress__bar">
|
|
18
|
-
<div class="reading-progress__fill"
|
|
19
|
-
data-progress-fill
|
|
20
|
-
role="progressbar"
|
|
21
|
-
aria-valuenow="0"
|
|
22
|
-
aria-valuemin="0"
|
|
23
|
-
aria-valuemax="100"
|
|
24
|
-
aria-label="Reading progress percentage">
|
|
25
|
-
</div>
|
|
26
|
-
</div>
|
|
27
|
-
|
|
28
|
-
{%- comment -%} Progress stats {%- endcomment -%}
|
|
29
|
-
<div class="reading-progress__stats">
|
|
30
|
-
{%- if show_percentage -%}
|
|
31
|
-
<span class="reading-progress__percentage" data-progress-percentage aria-live="polite">
|
|
32
|
-
<span data-percentage-value>0</span>% complete
|
|
33
|
-
</span>
|
|
34
|
-
{%- endif -%}
|
|
35
|
-
|
|
36
|
-
{%- if show_time -%}
|
|
37
|
-
<span class="reading-progress__time" data-progress-time aria-live="polite">
|
|
38
|
-
<svg class="reading-progress__icon" xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
39
|
-
<circle cx="12" cy="12" r="10"></circle>
|
|
40
|
-
<polyline points="12 6 12 12 16 14"></polyline>
|
|
41
|
-
</svg>
|
|
42
|
-
<span data-time-value>...</span> remaining
|
|
43
|
-
</span>
|
|
44
|
-
{%- endif -%}
|
|
45
|
-
</div>
|
|
46
|
-
</div>
|
|
47
|
-
|
|
48
|
-
<script>
|
|
49
|
-
(function() {
|
|
50
|
-
'use strict';
|
|
51
|
-
|
|
52
|
-
document.addEventListener('DOMContentLoaded', function() {
|
|
53
|
-
const progressContainer = document.querySelector('[data-reading-progress]');
|
|
54
|
-
if (!progressContainer) return;
|
|
55
|
-
|
|
56
|
-
const progressFill = progressContainer.querySelector('[data-progress-fill]');
|
|
57
|
-
const percentageValue = progressContainer.querySelector('[data-percentage-value]');
|
|
58
|
-
const timeValue = progressContainer.querySelector('[data-time-value]');
|
|
59
|
-
|
|
60
|
-
// Get article content for calculation
|
|
61
|
-
const articleContent = document.querySelector('.post-content, .article-content, article, main');
|
|
62
|
-
if (!articleContent) return;
|
|
63
|
-
|
|
64
|
-
// Calculate reading time (words per minute)
|
|
65
|
-
const wordsPerMinute = 200;
|
|
66
|
-
const text = articleContent.textContent || articleContent.innerText;
|
|
67
|
-
const wordCount = text.trim().split(/\s+/).length;
|
|
68
|
-
const totalReadingTime = Math.ceil(wordCount / wordsPerMinute);
|
|
69
|
-
|
|
70
|
-
// Track scroll position
|
|
71
|
-
let ticking = false;
|
|
72
|
-
|
|
73
|
-
function updateProgress() {
|
|
74
|
-
// Get scroll position
|
|
75
|
-
const windowHeight = window.innerHeight;
|
|
76
|
-
const documentHeight = document.documentElement.scrollHeight;
|
|
77
|
-
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
|
|
78
|
-
|
|
79
|
-
// Calculate progress percentage
|
|
80
|
-
const scrollableDistance = documentHeight - windowHeight;
|
|
81
|
-
const scrollPercentage = scrollableDistance > 0
|
|
82
|
-
? Math.min(Math.max((scrollTop / scrollableDistance) * 100, 0), 100)
|
|
83
|
-
: 0;
|
|
84
|
-
|
|
85
|
-
// Update progress bar
|
|
86
|
-
if (progressFill) {
|
|
87
|
-
progressFill.style.width = scrollPercentage + '%';
|
|
88
|
-
progressFill.setAttribute('aria-valuenow', Math.round(scrollPercentage));
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// Update percentage text
|
|
92
|
-
if (percentageValue) {
|
|
93
|
-
percentageValue.textContent = Math.round(scrollPercentage);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// Update time remaining
|
|
97
|
-
if (timeValue) {
|
|
98
|
-
const timeRemaining = Math.max(
|
|
99
|
-
Math.ceil(totalReadingTime * (1 - scrollPercentage / 100)),
|
|
100
|
-
0
|
|
101
|
-
);
|
|
102
|
-
|
|
103
|
-
if (timeRemaining === 0) {
|
|
104
|
-
timeValue.textContent = 'Complete!';
|
|
105
|
-
} else if (timeRemaining === 1) {
|
|
106
|
-
timeValue.textContent = '1 min';
|
|
107
|
-
} else {
|
|
108
|
-
timeValue.textContent = timeRemaining + ' min';
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
ticking = false;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
function requestTick() {
|
|
116
|
-
if (!ticking) {
|
|
117
|
-
window.requestAnimationFrame(updateProgress);
|
|
118
|
-
ticking = true;
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// Listen to scroll events
|
|
123
|
-
window.addEventListener('scroll', requestTick, { passive: true });
|
|
124
|
-
window.addEventListener('resize', requestTick, { passive: true });
|
|
125
|
-
|
|
126
|
-
// Initial update
|
|
127
|
-
updateProgress();
|
|
128
|
-
|
|
129
|
-
// Update when images load
|
|
130
|
-
window.addEventListener('load', updateProgress);
|
|
131
|
-
});
|
|
132
|
-
})();
|
|
133
|
-
</script>
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
{%- comment -%}
|
|
2
|
-
Reading Time Estimate Component
|
|
3
|
-
Calculates and displays estimated reading time with metadata
|
|
4
|
-
|
|
5
|
-
Parameters:
|
|
6
|
-
- content: Content to analyze (default: page.content)
|
|
7
|
-
- words_per_minute: Reading speed (default: 200)
|
|
8
|
-
- show_word_count: Show word count (default: false)
|
|
9
|
-
- show_icon: Show clock icon (default: true)
|
|
10
|
-
- variant: Display variant (inline, badge, detailed) (default: inline)
|
|
11
|
-
{%- endcomment -%}
|
|
12
|
-
|
|
13
|
-
{%- assign content_to_analyze = include.content | default: page.content -%}
|
|
14
|
-
{%- assign words_per_minute = include.words_per_minute | default: 200 -%}
|
|
15
|
-
{%- assign show_word_count = include.show_word_count | default: false -%}
|
|
16
|
-
{%- assign show_icon = include.show_icon | default: true -%}
|
|
17
|
-
{%- assign variant = include.variant | default: "inline" -%}
|
|
18
|
-
|
|
19
|
-
{%- comment -%} Calculate word count {%- endcomment -%}
|
|
20
|
-
{%- assign words = content_to_analyze | strip_html | number_of_words -%}
|
|
21
|
-
|
|
22
|
-
{%- comment -%} Calculate reading time in minutes {%- endcomment -%}
|
|
23
|
-
{%- assign reading_time_float = words | divided_by: words_per_minute | plus: 0.0 -%}
|
|
24
|
-
{%- assign reading_time = reading_time_float | ceil -%}
|
|
25
|
-
|
|
26
|
-
{%- comment -%} Handle edge cases {%- endcomment -%}
|
|
27
|
-
{%- if reading_time < 1 -%}
|
|
28
|
-
{%- assign reading_time = 1 -%}
|
|
29
|
-
{%- endif -%}
|
|
30
|
-
|
|
31
|
-
{%- comment -%} Format reading time display {%- endcomment -%}
|
|
32
|
-
{%- if reading_time == 1 -%}
|
|
33
|
-
{%- assign time_label = "1 min read" -%}
|
|
34
|
-
{%- else -%}
|
|
35
|
-
{%- assign time_label = reading_time | append: " min read" -%}
|
|
36
|
-
{%- endif -%}
|
|
37
|
-
|
|
38
|
-
{%- comment -%} Calculate additional metrics for detailed variant {%- endcomment -%}
|
|
39
|
-
{%- if variant == "detailed" -%}
|
|
40
|
-
{%- assign hours = reading_time | divided_by: 60 -%}
|
|
41
|
-
{%- assign remaining_minutes = reading_time | modulo: 60 -%}
|
|
42
|
-
|
|
43
|
-
{%- comment -%} Estimate based on different reading speeds {%- endcomment -%}
|
|
44
|
-
{%- assign slow_reading_time = words | divided_by: 150 | ceil -%}
|
|
45
|
-
{%- assign fast_reading_time = words | divided_by: 250 | ceil -%}
|
|
46
|
-
{%- endif -%}
|
|
47
|
-
|
|
48
|
-
<span class="reading-time reading-time--{{ variant }}"
|
|
49
|
-
data-reading-time
|
|
50
|
-
data-words="{{ words }}"
|
|
51
|
-
data-minutes="{{ reading_time }}"
|
|
52
|
-
itemscope
|
|
53
|
-
itemtype="https://schema.org/Article">
|
|
54
|
-
|
|
55
|
-
{%- if show_icon -%}
|
|
56
|
-
<svg class="reading-time__icon"
|
|
57
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
58
|
-
width="16"
|
|
59
|
-
height="16"
|
|
60
|
-
viewBox="0 0 24 24"
|
|
61
|
-
fill="none"
|
|
62
|
-
stroke="currentColor"
|
|
63
|
-
stroke-width="2"
|
|
64
|
-
stroke-linecap="round"
|
|
65
|
-
stroke-linejoin="round"
|
|
66
|
-
aria-hidden="true">
|
|
67
|
-
<circle cx="12" cy="12" r="10"></circle>
|
|
68
|
-
<polyline points="12 6 12 12 16 14"></polyline>
|
|
69
|
-
</svg>
|
|
70
|
-
{%- endif -%}
|
|
71
|
-
|
|
72
|
-
{%- if variant == "detailed" -%}
|
|
73
|
-
<span class="reading-time__details">
|
|
74
|
-
<span class="reading-time__primary">
|
|
75
|
-
<strong class="reading-time__time" itemprop="timeRequired" content="PT{{ reading_time }}M">
|
|
76
|
-
{{ time_label }}
|
|
77
|
-
</strong>
|
|
78
|
-
</span>
|
|
79
|
-
|
|
80
|
-
<span class="reading-time__secondary">
|
|
81
|
-
<span class="reading-time__word-count">
|
|
82
|
-
{{ words }} words
|
|
83
|
-
</span>
|
|
84
|
-
|
|
85
|
-
{%- if hours >= 1 -%}
|
|
86
|
-
<span class="reading-time__alternative">
|
|
87
|
-
({{ hours }}h {{ remaining_minutes }}m)
|
|
88
|
-
</span>
|
|
89
|
-
{%- endif -%}
|
|
90
|
-
</span>
|
|
91
|
-
|
|
92
|
-
<span class="reading-time__range">
|
|
93
|
-
<small>{{ fast_reading_time }}-{{ slow_reading_time }} min depending on speed</small>
|
|
94
|
-
</span>
|
|
95
|
-
</span>
|
|
96
|
-
|
|
97
|
-
{%- elsif variant == "badge" -%}
|
|
98
|
-
<span class="reading-time__badge">
|
|
99
|
-
<span class="reading-time__time" itemprop="timeRequired" content="PT{{ reading_time }}M">
|
|
100
|
-
{{ time_label }}
|
|
101
|
-
</span>
|
|
102
|
-
{%- if show_word_count -%}
|
|
103
|
-
<span class="reading-time__word-count">
|
|
104
|
-
{{ words }} words
|
|
105
|
-
</span>
|
|
106
|
-
{%- endif -%}
|
|
107
|
-
</span>
|
|
108
|
-
|
|
109
|
-
{%- else -%}
|
|
110
|
-
{%- comment -%} Inline variant (default) {%- endcomment -%}
|
|
111
|
-
<span class="reading-time__time" itemprop="timeRequired" content="PT{{ reading_time }}M">
|
|
112
|
-
{{ time_label }}
|
|
113
|
-
</span>
|
|
114
|
-
{%- if show_word_count -%}
|
|
115
|
-
<span class="reading-time__separator" aria-hidden="true">•</span>
|
|
116
|
-
<span class="reading-time__word-count">
|
|
117
|
-
{{ words }} words
|
|
118
|
-
</span>
|
|
119
|
-
{%- endif -%}
|
|
120
|
-
{%- endif -%}
|
|
121
|
-
</span>
|
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
{%- comment -%}
|
|
2
|
-
Series/Collection Navigation Component
|
|
3
|
-
Displays navigation for multi-part content series
|
|
4
|
-
|
|
5
|
-
Parameters:
|
|
6
|
-
- series: Series name/ID
|
|
7
|
-
- show_progress: Show progress indicator (default: true)
|
|
8
|
-
- compact: Compact layout (default: false)
|
|
9
|
-
{%- endcomment -%}
|
|
10
|
-
|
|
11
|
-
{%- assign series_name = include.series | default: page.series -%}
|
|
12
|
-
{%- assign show_progress = include.show_progress | default: true -%}
|
|
13
|
-
{%- assign compact = include.compact | default: false -%}
|
|
14
|
-
|
|
15
|
-
{%- if series_name -%}
|
|
16
|
-
{%- comment -%} Get all posts in this series {%- endcomment -%}
|
|
17
|
-
{%- assign series_posts = site.posts | where: "series", series_name | sort: "series_order" -%}
|
|
18
|
-
{%- assign series_count = series_posts | size -%}
|
|
19
|
-
|
|
20
|
-
{%- if series_count > 0 -%}
|
|
21
|
-
{%- comment -%} Find current post position {%- endcomment -%}
|
|
22
|
-
{%- assign current_index = 0 -%}
|
|
23
|
-
{%- for post in series_posts -%}
|
|
24
|
-
{%- if post.url == page.url -%}
|
|
25
|
-
{%- assign current_index = forloop.index -%}
|
|
26
|
-
{%- endif -%}
|
|
27
|
-
{%- endfor -%}
|
|
28
|
-
|
|
29
|
-
<nav class="series-nav{% if compact %} series-nav--compact{% endif %}"
|
|
30
|
-
aria-label="Series navigation: {{ series_name }}">
|
|
31
|
-
<div class="series-nav__header">
|
|
32
|
-
<svg class="series-nav__icon" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
33
|
-
<path d="M12 2v20M2 12h20"></path>
|
|
34
|
-
<path d="M16 8l4 4-4 4M8 16l-4-4 4-4"></path>
|
|
35
|
-
</svg>
|
|
36
|
-
<h3 class="series-nav__title">
|
|
37
|
-
<span class="series-nav__label">Series:</span>
|
|
38
|
-
{{ series_name }}
|
|
39
|
-
</h3>
|
|
40
|
-
</div>
|
|
41
|
-
|
|
42
|
-
{%- if show_progress -%}
|
|
43
|
-
<div class="series-nav__progress" aria-label="Series progress">
|
|
44
|
-
<div class="series-nav__progress-bar">
|
|
45
|
-
<div class="series-nav__progress-fill"
|
|
46
|
-
style="width: {{ current_index | times: 100 | divided_by: series_count }}%"
|
|
47
|
-
role="progressbar"
|
|
48
|
-
aria-valuenow="{{ current_index }}"
|
|
49
|
-
aria-valuemin="0"
|
|
50
|
-
aria-valuemax="{{ series_count }}"
|
|
51
|
-
aria-label="Part {{ current_index }} of {{ series_count }}">
|
|
52
|
-
</div>
|
|
53
|
-
</div>
|
|
54
|
-
<span class="series-nav__progress-text">
|
|
55
|
-
Part {{ current_index }} of {{ series_count }}
|
|
56
|
-
</span>
|
|
57
|
-
</div>
|
|
58
|
-
{%- endif -%}
|
|
59
|
-
|
|
60
|
-
<ol class="series-nav__list">
|
|
61
|
-
{%- for post in series_posts -%}
|
|
62
|
-
{%- assign is_current = false -%}
|
|
63
|
-
{%- if post.url == page.url -%}
|
|
64
|
-
{%- assign is_current = true -%}
|
|
65
|
-
{%- endif -%}
|
|
66
|
-
|
|
67
|
-
<li class="series-nav__item{% if is_current %} series-nav__item--current{% endif %}">
|
|
68
|
-
<div class="series-nav__number">{{ forloop.index }}</div>
|
|
69
|
-
{%- if is_current -%}
|
|
70
|
-
<div class="series-nav__content">
|
|
71
|
-
<strong class="series-nav__post-title">{{ post.title }}</strong>
|
|
72
|
-
<span class="series-nav__badge">Current</span>
|
|
73
|
-
</div>
|
|
74
|
-
{%- else -%}
|
|
75
|
-
<a href="{{ post.url | relative_url }}" class="series-nav__content">
|
|
76
|
-
<span class="series-nav__post-title">{{ post.title }}</span>
|
|
77
|
-
{%- if post.excerpt -%}
|
|
78
|
-
<span class="series-nav__excerpt">{{ post.excerpt | strip_html | truncate: 80 }}</span>
|
|
79
|
-
{%- endif -%}
|
|
80
|
-
</a>
|
|
81
|
-
{%- endif -%}
|
|
82
|
-
</li>
|
|
83
|
-
{%- endfor -%}
|
|
84
|
-
</ol>
|
|
85
|
-
|
|
86
|
-
{%- comment -%} Previous/Next navigation {%- endcomment -%}
|
|
87
|
-
<div class="series-nav__controls">
|
|
88
|
-
{%- if current_index > 1 -%}
|
|
89
|
-
{%- assign prev_post = series_posts[current_index | minus: 2] -%}
|
|
90
|
-
<a href="{{ prev_post.url | relative_url }}" class="series-nav__button series-nav__button--prev">
|
|
91
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
92
|
-
<polyline points="15 18 9 12 15 6"></polyline>
|
|
93
|
-
</svg>
|
|
94
|
-
Previous
|
|
95
|
-
</a>
|
|
96
|
-
{%- else -%}
|
|
97
|
-
<div class="series-nav__button series-nav__button--disabled">
|
|
98
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
99
|
-
<polyline points="15 18 9 12 15 6"></polyline>
|
|
100
|
-
</svg>
|
|
101
|
-
Previous
|
|
102
|
-
</div>
|
|
103
|
-
{%- endif -%}
|
|
104
|
-
|
|
105
|
-
{%- if current_index < series_count -%}
|
|
106
|
-
{%- assign next_post = series_posts[current_index] -%}
|
|
107
|
-
<a href="{{ next_post.url | relative_url }}" class="series-nav__button series-nav__button--next">
|
|
108
|
-
Next
|
|
109
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
110
|
-
<polyline points="9 18 15 12 9 6"></polyline>
|
|
111
|
-
</svg>
|
|
112
|
-
</a>
|
|
113
|
-
{%- else -%}
|
|
114
|
-
<div class="series-nav__button series-nav__button--disabled">
|
|
115
|
-
Next
|
|
116
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
117
|
-
<polyline points="9 18 15 12 9 6"></polyline>
|
|
118
|
-
</svg>
|
|
119
|
-
</div>
|
|
120
|
-
{%- endif -%}
|
|
121
|
-
</div>
|
|
122
|
-
</nav>
|
|
123
|
-
{%- endif -%}
|
|
124
|
-
{%- endif -%}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
{%- comment -%}
|
|
2
|
-
Social Proof Indicators Component
|
|
3
|
-
|
|
4
|
-
This component requires REAL metrics passed via include parameters.
|
|
5
|
-
It does NOT generate simulated/fabricated data.
|
|
6
|
-
|
|
7
|
-
Usage (only when real analytics data is available):
|
|
8
|
-
{% include components/social-proof.html views=page_views %}
|
|
9
|
-
|
|
10
|
-
To enable real data, configure GA4 analytics and use the analytics
|
|
11
|
-
dashboard plugin to fetch actual page view counts.
|
|
12
|
-
|
|
13
|
-
See: https://github.com/DiogoRibeiro7/analytics-blog-jekyll/issues/23
|
|
14
|
-
{%- endcomment -%}
|
|
15
|
-
|
|
16
|
-
{%- if include.views or include.readers -%}
|
|
17
|
-
<div class="social-proof{% if include.compact %} social-proof--compact{% endif %}"
|
|
18
|
-
data-social-proof>
|
|
19
|
-
<div class="social-proof__metrics">
|
|
20
|
-
{%- if include.views -%}
|
|
21
|
-
<div class="social-proof__metric" data-metric="views">
|
|
22
|
-
<span class="social-proof__value">{{ include.views }}</span>
|
|
23
|
-
<span class="social-proof__label">views</span>
|
|
24
|
-
</div>
|
|
25
|
-
{%- endif -%}
|
|
26
|
-
{%- if include.readers -%}
|
|
27
|
-
<div class="social-proof__metric" data-metric="readers">
|
|
28
|
-
<span class="social-proof__value">{{ include.readers }}</span>
|
|
29
|
-
<span class="social-proof__label">reading now</span>
|
|
30
|
-
</div>
|
|
31
|
-
{%- endif -%}
|
|
32
|
-
</div>
|
|
33
|
-
</div>
|
|
34
|
-
{%- endif -%}
|