Skip to content

Commit fbff24f

Browse files
committed
Merge branch 'main' of github.com:HTTPArchive/almanac.httparchive.org into production
2 parents 2cd85ba + 1061203 commit fbff24f

24 files changed

Lines changed: 230 additions & 32 deletions

src/config/last_updated.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@
2121
},
2222
"/static/css/page.css": {
2323
"date_published": "2020-11-13T00:00:00.000Z",
24-
"date_modified": "2022-10-25T00:00:00.000Z",
25-
"hash": "5f0f74e0a58f1876aa0403a5967ac483"
24+
"date_modified": "2022-12-13T00:00:00.000Z",
25+
"hash": "f00848215660c365c3266948f44017f0"
2626
},
2727
"/static/css/splash.css": {
2828
"date_published": "2020-11-13T00:00:00.000Z",
@@ -31,8 +31,8 @@
3131
},
3232
"/static/js/almanac.js": {
3333
"date_published": "2021-02-24T00:00:00.000Z",
34-
"date_modified": "2022-04-29T00:00:00.000Z",
35-
"hash": "4c4ea41eae805e8a6894a7cf51308dea"
34+
"date_modified": "2022-12-13T00:00:00.000Z",
35+
"hash": "9c395a38708aa33f3c645692687b4245"
3636
},
3737
"/static/js/send-web-vitals.js": {
3838
"date_published": "2021-02-24T00:00:00.000Z",
@@ -46,8 +46,8 @@
4646
},
4747
"/static/js/webmentions.js": {
4848
"date_published": "2021-12-01T00:00:00.000Z",
49-
"date_modified": "2022-10-25T00:00:00.000Z",
50-
"hash": "6d0a0ac4914e62f499c6f4a50541a105"
49+
"date_modified": "2022-12-13T00:00:00.000Z",
50+
"hash": "13be3f76f6902375f7b2aa27ae4255e8"
5151
},
5252
"/static/pdfs/web_almanac_2019_en.pdf": {
5353
"date_published": "2020-05-15T00:00:00.000Z",

src/server/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from .helpers import (
55
get_view_args,
66
chapter_lang_exists,
7+
page_lang_exists,
78
featured_chapters_exists,
89
get_ebook_methodology,
910
add_footnote_links,
@@ -63,6 +64,7 @@ def add_header(response):
6364
# Make these functions available in templates.
6465
app.jinja_env.globals["get_view_args"] = get_view_args
6566
app.jinja_env.globals["chapter_lang_exists"] = chapter_lang_exists
67+
app.jinja_env.globals["page_lang_exists"] = page_lang_exists
6668
app.jinja_env.globals["featured_chapters_exists"] = featured_chapters_exists
6769
app.jinja_env.globals["HTTP_STATUS_CODES"] = HTTP_STATUS_CODES
6870
app.jinja_env.globals["get_ebook_methodology"] = get_ebook_methodology

src/server/helpers.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,15 @@ def chapter_lang_exists(lang, year, chapter):
133133
return False
134134

135135

136+
def page_lang_exists(lang, year, page):
137+
if os.path.isfile(
138+
TEMPLATES_DIR + "/%s/%s/%s.html" % (lang, year, page)
139+
):
140+
return True
141+
else:
142+
return False
143+
144+
136145
def featured_chapters_exists(lang, year):
137146
if os.path.isfile(TEMPLATES_DIR + "/%s/%s/featured_chapters.html" % (lang, year)):
138147
return True

src/server/tests/helpers_test.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
get_versioned_filename,
44
get_ebook_size_in_mb,
55
chapter_lang_exists,
6+
page_lang_exists,
67
featured_chapters_exists,
78
get_chapter_nextprev,
89
get_chapter_config,
@@ -158,6 +159,14 @@ def test_chapter_lang_not_exists():
158159
assert chapter_lang_exists("en", "2019", "random") is False
159160

160161

162+
def test_page_lang_exists():
163+
assert page_lang_exists("en", "2019", "methodology") is True
164+
165+
166+
def test_page_lang_not_exists():
167+
assert page_lang_exists("en", "2019", "random") is False
168+
169+
161170
def test_featured_chapters_exists():
162171
assert featured_chapters_exists("en", "2019") is True
163172

src/static/css/page.css

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,10 @@
230230
margin: -6px 3px;
231231
}
232232

233+
#cta-container.invisible {
234+
opacity: 0;
235+
}
236+
233237
#cta-container {
234238
display: flex;
235239
height: 0;
@@ -239,6 +243,8 @@
239243
bottom: 1.25rem;
240244
z-index: 1;
241245
justify-content: flex-end;
246+
opacity: 1;
247+
transition: opacity 1000ms;
242248
}
243249

244250
.chapter-cta {
@@ -265,6 +271,15 @@
265271
line-height: 1.5rem;
266272
}
267273

274+
.share-cta {
275+
line-height: 1.6em;
276+
}
277+
278+
.share-cta:hover svg,
279+
.share-cta:focus svg {
280+
fill: white;
281+
}
282+
268283
[data-translation] {
269284
display: none;
270285
}

src/static/js/almanac.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,8 @@ function setDiscussionCount() {
482482
el.removeAttribute('data-translation');
483483
});
484484
}
485-
485+
document.querySelector('#cta-container').classList.remove('invisible');
486+
document.querySelector('.discuss-cta').classList.remove('hidden');
486487
gtag('event', 'discussion-count', { 'event_category': 'user', 'event_label': 'enabled', 'value': 1 });
487488
})
488489
.catch(function (err) {

src/static/js/webmentions.js

Lines changed: 83 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// Code related to parsing and showing webmentions
2+
// And Share button
23

34
// Gets the webmentions json data from current URL
45
async function getWebmentions(targetURL) {
@@ -51,17 +52,23 @@ function setReactionsLabel(length, reactionLabel) {
5152

5253
// Singular
5354
if (plural_rules.select(length) === "one") {
54-
reactionLabel.textContent = reactionLabel.getAttribute("data-singular");
55+
reactionLabel.textContent = reactionLabel.dataset.singular;
5556
return;
5657
}
5758

5859
// Few - alternative plural (Used by "ru" and "uk")
59-
if (reactionLabel.getAttribute("data-plural-alt") !== "" && plural_rules.select(length) === "few") {
60-
reactionLabel.textContent = reactionLabel.getAttribute("data-plural-alt");
61-
return;
60+
if (reactionLabel.dataset.plural_alt !== "" && plural_rules.select(length) === "few") {
61+
reactionLabel.textContent = reactionLabel.dataset.plural_alt;
62+
return;
63+
}
64+
65+
// If a plural exists use that.
66+
if (reactionLabel.dataset.plural) {
67+
reactionLabel.textContent = reactionLabel.dataset.plural;
68+
return;
6269
}
6370

64-
// Everything else sticks with the default plural
71+
// Everything else sticks with the default
6572
return;
6673

6774
}
@@ -174,7 +181,7 @@ function renderReactions(webmentions, reactionType, wmProperty) {
174181
const reactionASource = document.createElement("a");
175182
reactionASource.setAttribute("class", "webmention-source");
176183
reactionASource.setAttribute("href", reaction["url"]);
177-
reactionASource.textContent = document.querySelector(".reactions").getAttribute("data-source");
184+
reactionASource.textContent = document.querySelector(".reactions").dataset.source;
178185

179186
reactionDivMeta.appendChild(reactionTime);
180187
reactionDivMeta.appendChild(reactionSpan);
@@ -212,7 +219,12 @@ function setActiveTab() {
212219

213220
// Parses and renders mentions into likes, reposts, replies and mentions
214221
function renderWebmentions(webmentions) {
222+
if (!document.querySelector('.webmentions-cta')) {
223+
return;
224+
}
225+
215226
if (!webmentions.length) {
227+
document.querySelector('#cta-container').classList.remove('invisible');
216228
return;
217229
}
218230

@@ -221,6 +233,14 @@ function renderWebmentions(webmentions) {
221233
renderReactions(webmentions, "replies", "in-reply-to");
222234
renderReactions(webmentions, "mentions", "mention-of");
223235

236+
// Show count of reactions (except if 0)
237+
if (webmentions.length > 0) {
238+
document.querySelectorAll('.num-reactions').forEach(t => t.innerText = webmentions.length);
239+
document.querySelectorAll('.reactions-label').forEach(t => setReactionsLabel(webmentions.length, t));
240+
document.querySelector('.webmentions-cta').classList.remove('hidden');
241+
}
242+
document.querySelector('#cta-container').classList.remove('invisible');
243+
224244
// Set the first active tab (in case no "likes" so that tab is hidden)
225245
setActiveTab();
226246
}
@@ -301,6 +321,63 @@ function addTabListeners() {
301321
}
302322

303323

324+
// Change tabs for webmentions UI
325+
function handleShareButton() {
326+
// DOM references
327+
const button = document.querySelector('.share-cta');
328+
const appleIcon = button.querySelector('.apple-icon');
329+
const androidIcon = button.querySelector('.android-icon');
330+
const canonical = document.querySelector('link[rel="canonical"]');
331+
332+
// Feature detection to see if the Web Share API is supported.
333+
if (!('share' in navigator)) {
334+
return;
335+
}
336+
337+
// Find out if the user is on a device made by Apple and, if so, switch the icon.
338+
if (/Mac|iPhone/.test(navigator.platform)) {
339+
appleIcon.classList.remove('hidden');
340+
androidIcon.classList.add('hidden');
341+
}
342+
343+
button.addEventListener('click', async () => {
344+
// Title and text are identical, since the title may actually be ignored.
345+
const title = document.title;
346+
const text = document.title;
347+
// Use the canonical URL, if it exists, else, the current location.
348+
const url = canonical?.href || location.href;
349+
350+
gtag('event', 'WebShare', {
351+
'event_category': 'clicks',
352+
'event_label': url,
353+
'transport_type': 'beacon',
354+
'value': 1
355+
})
356+
357+
try {
358+
await navigator.share({
359+
url,
360+
text,
361+
title,
362+
});
363+
return;
364+
} catch (err) {
365+
// If the user cancels, an `AbortError` is thrown.
366+
if (err.name !== "AbortError") {
367+
console.error(err.name, err.message);
368+
gtag('event', 'error', {
369+
'event_category': 'WebShare',
370+
'event_label': err.message,
371+
'transport_type': 'beacon',
372+
'value': 1
373+
})
374+
}
375+
}
376+
});
377+
button.classList.remove('hidden');
378+
}
379+
380+
handleShareButton();
304381
addTabListeners();
305382
const BASE_URL = "https://almanac.httparchive.org";
306383
processWebmentions(BASE_URL + window.location.pathname);

src/templates/base.html

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,16 @@
8585
<symbol id="search-logo" viewBox="0 0 13 13">
8686
<path d="m4.8495 7.8226c0.82666 0 1.5262-0.29146 2.0985-0.87438 0.57232-0.58292 0.86378-1.2877 0.87438-2.1144 0.010599-0.82666-0.28086-1.5262-0.87438-2.0985-0.59352-0.57232-1.293-0.86378-2.0985-0.87438-0.8055-0.010599-1.5103 0.28086-2.1144 0.87438-0.60414 0.59352-0.8956 1.293-0.87438 2.0985 0.021197 0.8055 0.31266 1.5103 0.87438 2.1144 0.56172 0.60414 1.2665 0.8956 2.1144 0.87438zm4.4695 0.2115 3.681 3.6819-1.259 1.284-3.6817-3.7 0.0019784-0.69479-0.090043-0.098846c-0.87973 0.76087-1.92 1.1413-3.1207 1.1413-1.3553 0-2.5025-0.46363-3.4417-1.3909s-1.4088-2.0686-1.4088-3.4239c0-1.3553 0.4696-2.4966 1.4088-3.4239 0.9392-0.92727 2.0864-1.3969 3.4417-1.4088 1.3553-0.011889 2.4906 0.45771 3.406 1.4088 0.9154 0.95107 1.379 2.0924 1.3909 3.4239 0 1.2126-0.38043 2.2588-1.1413 3.1385l0.098834 0.090049z" fill="currentColor"/>
8787
</symbol>
88+
<!-- Share Apple -->
89+
<symbol id="share-apple-logo" viewBox="0 0 24 24">
90+
<path d="M0 0h24v24H0V0z" fill="none"></path>
91+
<path d="M16 5l-1.42 1.42-1.59-1.59V16h-1.98V4.83L9.42 6.42 8 5l4-4 4 4zm4 5v11c0 1.1-.9 2-2 2H6c-1.11 0-2-.9-2-2V10c0-1.11.89-2 2-2h3v2H6v11h12V10h-3V8h3c1.1 0 2 .89 2 2z"></path>
92+
</symbol>
93+
<!-- Share Android -->
94+
<symbol id="share-android-logo" viewBox="0 0 24 24">
95+
<path d="M0 0h24v24H0z" fill="none"></path>
96+
<path d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81 1.66 0 3-1.34 3-3s-1.34-3-3-3-3 1.34-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9c-1.66 0-3 1.34-3 3s1.34 3 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.16c-.05.21-.08.43-.08.65 0 1.61 1.31 2.92 2.92 2.92 1.61 0 2.92-1.31 2.92-2.92s-1.31-2.92-2.92-2.92z"></path>
97+
</symbol>
8898
</svg>
8999
{% block content %}{% endblock %}
90100

src/templates/base/base.html

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,11 @@
337337
</li>
338338
{% else %}
339339
<li class="nav-dropdown-list-chapter">
340+
{% if page_lang_exists(lang, year, 'methodology') %}
340341
<a href="{{ url_for('methodology', year=year, lang=lang) }}">{{ self.methodology_title() }}</a>
342+
{% else %}
343+
<a href="{{ url_for('methodology', year=year, lang='en') }}">{{ self.methodology_title() }} <span class="not-translated">({{ self.translation_not_available() }})</span></a>
344+
{% endif %}
341345
</li>
342346
{% endif %}
343347
{% if request.path.endswith("contributors") %}
@@ -346,7 +350,11 @@
346350
</li>
347351
{% else %}
348352
<li class="nav-dropdown-list-chapter">
353+
{% if page_lang_exists(lang, year, 'contributors') %}
349354
<a href="{{ url_for('contributors', year=year, lang=lang) }}">{{ self.contributors_title() }}</a>
355+
{% else %}
356+
<a href="{{ url_for('contributors', year=year, lang='en') }}">{{ self.contributors_title() }} <span class="not-translated">({{ self.translation_not_available() }})</span></a>
357+
{% endif %}
350358
</li>
351359
{% endif %}
352360

src/templates/base/base_chapter.html

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -424,27 +424,34 @@ <h1 class="title title-lg">
424424
<section class="authors">
425425
{{ render_authors() }}
426426
</section>
427-
{% if metadata.get('discuss') %}
428-
<div id="cta-container">
429-
<a class="alt btn chapter-cta comment-cta" hreflang="en" href="https://discuss.httparchive.org/t/{{ metadata.get('discuss') }}">
427+
<div id="cta-container" class="invisible">
428+
{% if metadata.get('discuss') %}
429+
<a class="alt btn chapter-cta comment-cta discuss-cta hidden" hreflang="en" href="https://discuss.httparchive.org/t/{{ metadata.get('discuss') }}">
430430
<svg width="22" height="22" role="img" aria-labelledby="discuss-this-chapter-cta">
431431
<title id="discuss-this-chapter-cta">{{ self.discuss_this_chapter() }}:</title>
432432
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#comment-logo"></use>
433433
</svg>
434-
<span class="num-comments"><span class="not-mobile">{{ self.comments_fallback() }}</span></span> <span data-translation class="comment-singular visually-hidden-mobile">{{ self.comment() }}</span>
435-
<span data-translation class="comment-plural visually-hidden-mobile">{{ self.comments() }}</span>
434+
<span class="num-comments">{{ self.comments_fallback() }}</span> <span data-translation class="comment-singular">{{ self.comment() }}</span>
435+
<span data-translation class="comment-plural">{{ self.comments() }}</span>
436436
</a>
437-
</div>
438-
{% elif year | int >= 2021 %}
439-
<div id="cta-container">
440-
<a class="alt btn chapter-cta comment-cta" href="#reactions">
437+
{% elif year | int >= 2021 %}
438+
<a class="alt btn chapter-cta comment-cta webmentions-cta hidden" href="#reactions">
441439
<svg width="22" height="22" role="img" aria-hidden="true">
442440
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#comment-logo"></use>
443441
</svg>
444-
{{ self.reactions() }}
442+
<span class="num-reactions"></span> <span class="reactions-label" data-singular="{{ self.reaction() }}" data-plural="{{ self.reactions() }}" data-plural-alt="{{ self.reactionsAlt() }}">{{ self.reactionsDefault() }}</span>
445443
</a>
444+
{% endif %}
445+
<button class="alt btn chapter-cta share-cta hidden">
446+
<svg width="22" height="22" role="img" aria-hidden="true" class="apple-icon hidden">
447+
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#share-apple-logo"></use>
448+
</svg>
449+
<svg width="22" height="22" role="img" aria-hidden="true" class="android-icon">
450+
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#share-android-logo"></use>
451+
</svg>
452+
{{ self.share() }}
453+
</button>
446454
</div>
447-
{% endif %}
448455
<nav aria-label="{{ self.prev_next_title() }}" id="chapter-navigation">
449456
{{ render_prevnext() }}
450457
</nav>

0 commit comments

Comments
 (0)