astro-atmosphere-comments 0.4.0 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.4.2 (4 November 2026)
4
+
5
+ - Links open in a new tab: those in the sign-in form, "Reply on Bluesky instead", the credit, and the thread's names, dates, faces and links in comments, so readers don't lose their place (and a half-written comment).
6
+
7
+ ## 0.4.1 (4 November 2026)
8
+
9
+ - Fixed: the sign-in and reply overlays of `AtmosphereReactions` showed at the bottom of the page instead of staying hidden until opened (the shared stylesheet made every `.atmo` element a block, dialogs included).
10
+
3
11
  ## 0.4.0 (4 November 2026)
4
12
 
5
13
  - **`AtmosphereReactions`:** likes and reposts on your other Bluesky posts (a feed of your latest posts, say). Mark each post with `data-atmosphere-post` (and its bsky.app address and counts) and put the component once in your layout: each post gets Reply and Quote (opening it on Bluesky), and Repost and Like with counts. Readers who aren't signed in get the sign-in form in an overlay, and their like or repost is done once they're back. Only posts by `allowedAuthors` can be liked or reposted.
@@ -71,8 +71,9 @@ const messages = messagesFor(lang, {
71
71
  });
72
72
  const t = (key: string, vars?: Record<string, string | number>) => translate(messages, lang, key, vars);
73
73
  const th = (key: string, html: Record<string, string>) => translateHtml(messages, lang, key, html);
74
+ // Links lead off the page, so they open in a new tab.
74
75
  const link = (href: string | undefined, text: string, attributes = "") =>
75
- `<a${href ? ` href="${escapeHtml(href)}"` : ""}${attributes}>${escapeHtml(text)}</a>`;
76
+ `<a${href ? ` href="${escapeHtml(href)}"` : ""} target="_blank" rel="noopener"${attributes}>${escapeHtml(text)}</a>`;
76
77
  // The announcement on bsky.app, when the page is given it (otherwise the
77
78
  // script fills it in once the thread has loaded).
78
79
  const atUri = post.match(/^at:\/\/([^/]+)\/app\.bsky\.feed\.post\/([^/]+)$/);
@@ -254,7 +255,7 @@ const returnTo = `${Astro.url.pathname}#atmosphere-comments`;
254
255
  group.append(make("p", "atmo-reactions__count", t(kind === "like" ? "reactions.likes" : "reactions.reposts", { count })));
255
256
  const faces = make("ul", "atmo-facepile");
256
257
  for (const person of people) {
257
- const link = Object.assign(make("a"), { href: person.url, title: nameOf(person), rel: "ugc nofollow noopener" });
258
+ const link = Object.assign(make("a"), { href: person.url, title: nameOf(person), rel: "ugc nofollow noopener", target: "_blank" });
258
259
  link.setAttribute("aria-label", nameOf(person));
259
260
  link.append(avatarOf(person, "atmo-facepile__avatar"));
260
261
  const item = make("li");
@@ -278,11 +279,12 @@ const returnTo = `${Astro.url.pathname}#atmosphere-comments`;
278
279
  const author = Object.assign(make("a", "atmo-comment__author", nameOf(reply.author)), {
279
280
  href: reply.author.url,
280
281
  rel: "ugc nofollow noopener",
282
+ target: "_blank",
281
283
  });
282
284
  const who = make("div", "atmo-comment__who");
283
285
  who.append(author);
284
286
  if (reply.byAuthor) who.append(make("span", "atmo-comment__badge", authorLabel));
285
- const date = Object.assign(make("a", "atmo-comment__date"), { href: reply.url, rel: "ugc nofollow noopener" });
287
+ const date = Object.assign(make("a", "atmo-comment__date"), { href: reply.url, rel: "ugc nofollow noopener", target: "_blank" });
286
288
  const time = Object.assign(make("time"), { dateTime: reply.createdAt, textContent: reply.createdAt ? dates.format(new Date(reply.createdAt)) : "" });
287
289
  date.append(time, make("span", "", ` · ${t("comment.viewOnBluesky")}`));
288
290
  const names = make("div");
@@ -293,7 +295,7 @@ const returnTo = `${Astro.url.pathname}#atmosphere-comments`;
293
295
  const paragraph = make("p");
294
296
  for (const piece of reply.text) {
295
297
  paragraph.append(
296
- piece.href ? Object.assign(make("a", "", piece.text), { href: piece.href, rel: "ugc nofollow noopener" }) : piece.text,
298
+ piece.href ? Object.assign(make("a", "", piece.text), { href: piece.href, rel: "ugc nofollow noopener", target: "_blank" }) : piece.text,
297
299
  );
298
300
  }
299
301
  body.append(paragraph);
@@ -401,7 +403,7 @@ const returnTo = `${Astro.url.pathname}#atmosphere-comments`;
401
403
  const postedMessage = (where: HTMLElement, data: Posted) =>
402
404
  where.replaceChildren(
403
405
  `${t(data.quote ? "posted.quote" : "posted.comment")} `,
404
- Object.assign(document.createElement("a"), { href: data.url, textContent: t("posted.see") }),
406
+ Object.assign(document.createElement("a"), { href: data.url, textContent: t("posted.see"), target: "_blank", rel: "noopener noreferrer" }),
405
407
  );
406
408
 
407
409
  // The comment box (lib/client/composer.ts): posts as a reply to the
@@ -26,7 +26,9 @@ const { id, returnTo, messages, lang, heading } = Astro.props;
26
26
  const { base } = settings;
27
27
  const t = (key: string) => translate(messages, lang, key);
28
28
  const th = (key: string, html: Record<string, string>) => translateHtml(messages, lang, key, html);
29
- const link = (href: string, text: string) => `<a href="${escapeHtml(href)}">${escapeHtml(text)}</a>`;
29
+ // Links lead off the page, so they open in a new tab.
30
+ const link = (href: string, text: string) =>
31
+ `<a href="${escapeHtml(href)}" target="_blank" rel="noopener noreferrer">${escapeHtml(text)}</a>`;
30
32
  ---
31
33
 
32
34
  <form class="atmo__login" id={`${id}-login`} method="post" action={`${base}/login`} data-login-form>
@@ -6,10 +6,19 @@
6
6
  form has its own styles, in SignInForm.astro. */
7
7
 
8
8
  .atmo {
9
- display: block;
10
9
  color: var(--atmo-text, currentColor);
11
10
  }
12
11
 
12
+ /* The components are blocks; their overlays (dialogs, also .atmo) stay hidden
13
+ until opened. */
14
+ .atmo:not(dialog) {
15
+ display: block;
16
+ }
17
+
18
+ dialog.atmo:not([open]) {
19
+ display: none;
20
+ }
21
+
13
22
  /* Only the component's own parts wait for sign-in to be checked; the
14
23
  site's slot content shows straight away. */
15
24
  .atmo.is-loading > :is([data-view], [data-reactions], [data-replies]) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "astro-atmosphere-comments",
3
- "version": "0.4.0",
3
+ "version": "0.4.2",
4
4
  "description": "Atmosphere Comments for Astro: Bluesky comments, likes, reposts and quote posts for Astro sites; readers sign in with their Atmosphere (AT Protocol) account and respond without leaving the page.",
5
5
  "type": "module",
6
6
  "license": "MIT",