@automattic/social-previews 3.2.4 → 3.2.5

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
@@ -5,12 +5,19 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [3.2.5] - 2026-06-15
9
+ ### Changed
10
+ - Update package dependencies. [#49273]
11
+
12
+ ### Fixed
13
+ - Render editor hyperlinks as clickable links in Bluesky and Tumblr previews [#49483]
14
+
8
15
  ## [3.2.4] - 2026-06-08
9
16
  ### Changed
10
17
  - Update dependencies. [#49354]
11
18
 
12
19
  ### Fixed
13
- - Fix Mastodon share preview showing the post URL twice when the custom message already includes it. [#49338]
20
+ - Avoid having the Mastodon share preview show post URL twice when the custom message already includes it. [#49338]
14
21
 
15
22
  ## [3.2.3] - 2026-05-25
16
23
  ### Changed
@@ -200,6 +207,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
200
207
 
201
208
  - Initial release after extracting from Calypso.
202
209
 
210
+ [3.2.5]: https://github.com/Automattic/social-previews/compare/v3.2.4...v3.2.5
203
211
  [3.2.4]: https://github.com/Automattic/social-previews/compare/v3.2.3...v3.2.4
204
212
  [3.2.3]: https://github.com/Automattic/social-previews/compare/v3.2.2...v3.2.3
205
213
  [3.2.2]: https://github.com/Automattic/social-previews/compare/v3.2.1...v3.2.2
package/dist/index.d.mts CHANGED
@@ -1,5 +1,28 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
 
3
+ /**
4
+ * An editor hyperlink: the visible anchor text and the URL it points to.
5
+ */
6
+ type Hyperlink = {
7
+ text: string;
8
+ href: string;
9
+ /**
10
+ * Zero-based index of this anchor among identical occurrences of `text` in
11
+ * the content, so repeated texts link the right duplicate. Defaults to 0.
12
+ */
13
+ occurrence?: number;
14
+ };
15
+ /**
16
+ * Extracts `(text, href)` pairs from `<a href="…">text</a>` in HTML, skipping
17
+ * autolinks (text already equals the URL) and non-http(s) hrefs. Mirrors the
18
+ * backend `ExtractorUtils::get_anchor_links_from_html` so the preview links the
19
+ * same anchors the published share will.
20
+ *
21
+ * @param html - Raw post content HTML.
22
+ * @return The editor hyperlinks found, in document order.
23
+ */
24
+ declare function parseHyperlinks(html: string): Hyperlink[];
25
+
3
26
  declare const HEADING_LEVELS: readonly [2, 3, 4, 5, 6];
4
27
  type SectionHeadingProps = {
5
28
  className?: string;
@@ -12,6 +35,11 @@ interface SocialPreviewBaseProps {
12
35
  * The URL of the post/page to preview.
13
36
  */
14
37
  url: string;
38
+ /**
39
+ * Editor hyperlinks rendered over the matching body text on the networks
40
+ * that support inline links (Bluesky, Tumblr). Other networks ignore this.
41
+ */
42
+ hyperlinks?: Hyperlink[];
15
43
  /**
16
44
  * The title of the post/page to preview.
17
45
  */
@@ -275,4 +303,4 @@ declare function InstagramPostPreview({ image, media, name, profileImage, captio
275
303
 
276
304
  declare const InstagramPreviews: React.FC<InstagramPreviewsProps>;
277
305
 
278
- export { AUTO_SHARED_LINK_PREVIEW, AUTO_SHARED_SOCIAL_POST_PREVIEW, BlueskyLinkPreview, BlueskyPostPreview, BlueskyPreviews, type BlueskyPreviewsProps, DEFAULT_LINK_PREVIEW, FacebookLinkPreview, type FacebookLinkPreviewProps, FacebookPostPreview, FacebookPreviews, type FacebookPreviewsProps, GoogleSearchPreview, type GoogleSearchPreviewProps, InstagramPostPreview, InstagramPreviews, LANDSCAPE_MODE, LinkedInLinkPreview, type LinkedInLinkPreviewProps, LinkedInPostPreview, LinkedInPreviews, MastodonLinkPreview, MastodonPostPreview, MastodonPreviews, type MastodonPreviewsProps, type MediaItem, NextdoorLinkPreview, type NextdoorLinkPreviewProps, NextdoorPostPreview, NextdoorPreviews, PORTRAIT_MODE, type SocialPreviewBaseProps, type SocialPreviewsBaseProps, TYPE_ARTICLE, TYPE_WEBSITE, ThreadsLinkPreview, ThreadsPostPreview, ThreadsPreviews, TumblrLinkPreview, TumblrPostPreview, TumblrPreviews, type TumblrPreviewsProps, TwitterLinkPreview, TwitterPostPreview, TwitterPreviews };
306
+ export { AUTO_SHARED_LINK_PREVIEW, AUTO_SHARED_SOCIAL_POST_PREVIEW, BlueskyLinkPreview, BlueskyPostPreview, BlueskyPreviews, type BlueskyPreviewsProps, DEFAULT_LINK_PREVIEW, FacebookLinkPreview, type FacebookLinkPreviewProps, FacebookPostPreview, FacebookPreviews, type FacebookPreviewsProps, GoogleSearchPreview, type GoogleSearchPreviewProps, type Hyperlink, InstagramPostPreview, InstagramPreviews, LANDSCAPE_MODE, LinkedInLinkPreview, type LinkedInLinkPreviewProps, LinkedInPostPreview, LinkedInPreviews, MastodonLinkPreview, MastodonPostPreview, MastodonPreviews, type MastodonPreviewsProps, type MediaItem, NextdoorLinkPreview, type NextdoorLinkPreviewProps, NextdoorPostPreview, NextdoorPreviews, PORTRAIT_MODE, type SocialPreviewBaseProps, type SocialPreviewsBaseProps, TYPE_ARTICLE, TYPE_WEBSITE, ThreadsLinkPreview, ThreadsPostPreview, ThreadsPreviews, TumblrLinkPreview, TumblrPostPreview, TumblrPreviews, type TumblrPreviewsProps, TwitterLinkPreview, TwitterPostPreview, TwitterPreviews, parseHyperlinks };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,28 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
 
3
+ /**
4
+ * An editor hyperlink: the visible anchor text and the URL it points to.
5
+ */
6
+ type Hyperlink = {
7
+ text: string;
8
+ href: string;
9
+ /**
10
+ * Zero-based index of this anchor among identical occurrences of `text` in
11
+ * the content, so repeated texts link the right duplicate. Defaults to 0.
12
+ */
13
+ occurrence?: number;
14
+ };
15
+ /**
16
+ * Extracts `(text, href)` pairs from `<a href="…">text</a>` in HTML, skipping
17
+ * autolinks (text already equals the URL) and non-http(s) hrefs. Mirrors the
18
+ * backend `ExtractorUtils::get_anchor_links_from_html` so the preview links the
19
+ * same anchors the published share will.
20
+ *
21
+ * @param html - Raw post content HTML.
22
+ * @return The editor hyperlinks found, in document order.
23
+ */
24
+ declare function parseHyperlinks(html: string): Hyperlink[];
25
+
3
26
  declare const HEADING_LEVELS: readonly [2, 3, 4, 5, 6];
4
27
  type SectionHeadingProps = {
5
28
  className?: string;
@@ -12,6 +35,11 @@ interface SocialPreviewBaseProps {
12
35
  * The URL of the post/page to preview.
13
36
  */
14
37
  url: string;
38
+ /**
39
+ * Editor hyperlinks rendered over the matching body text on the networks
40
+ * that support inline links (Bluesky, Tumblr). Other networks ignore this.
41
+ */
42
+ hyperlinks?: Hyperlink[];
15
43
  /**
16
44
  * The title of the post/page to preview.
17
45
  */
@@ -275,4 +303,4 @@ declare function InstagramPostPreview({ image, media, name, profileImage, captio
275
303
 
276
304
  declare const InstagramPreviews: React.FC<InstagramPreviewsProps>;
277
305
 
278
- export { AUTO_SHARED_LINK_PREVIEW, AUTO_SHARED_SOCIAL_POST_PREVIEW, BlueskyLinkPreview, BlueskyPostPreview, BlueskyPreviews, type BlueskyPreviewsProps, DEFAULT_LINK_PREVIEW, FacebookLinkPreview, type FacebookLinkPreviewProps, FacebookPostPreview, FacebookPreviews, type FacebookPreviewsProps, GoogleSearchPreview, type GoogleSearchPreviewProps, InstagramPostPreview, InstagramPreviews, LANDSCAPE_MODE, LinkedInLinkPreview, type LinkedInLinkPreviewProps, LinkedInPostPreview, LinkedInPreviews, MastodonLinkPreview, MastodonPostPreview, MastodonPreviews, type MastodonPreviewsProps, type MediaItem, NextdoorLinkPreview, type NextdoorLinkPreviewProps, NextdoorPostPreview, NextdoorPreviews, PORTRAIT_MODE, type SocialPreviewBaseProps, type SocialPreviewsBaseProps, TYPE_ARTICLE, TYPE_WEBSITE, ThreadsLinkPreview, ThreadsPostPreview, ThreadsPreviews, TumblrLinkPreview, TumblrPostPreview, TumblrPreviews, type TumblrPreviewsProps, TwitterLinkPreview, TwitterPostPreview, TwitterPreviews };
306
+ export { AUTO_SHARED_LINK_PREVIEW, AUTO_SHARED_SOCIAL_POST_PREVIEW, BlueskyLinkPreview, BlueskyPostPreview, BlueskyPreviews, type BlueskyPreviewsProps, DEFAULT_LINK_PREVIEW, FacebookLinkPreview, type FacebookLinkPreviewProps, FacebookPostPreview, FacebookPreviews, type FacebookPreviewsProps, GoogleSearchPreview, type GoogleSearchPreviewProps, type Hyperlink, InstagramPostPreview, InstagramPreviews, LANDSCAPE_MODE, LinkedInLinkPreview, type LinkedInLinkPreviewProps, LinkedInPostPreview, LinkedInPreviews, MastodonLinkPreview, MastodonPostPreview, MastodonPreviews, type MastodonPreviewsProps, type MediaItem, NextdoorLinkPreview, type NextdoorLinkPreviewProps, NextdoorPostPreview, NextdoorPreviews, PORTRAIT_MODE, type SocialPreviewBaseProps, type SocialPreviewsBaseProps, TYPE_ARTICLE, TYPE_WEBSITE, ThreadsLinkPreview, ThreadsPostPreview, ThreadsPreviews, TumblrLinkPreview, TumblrPostPreview, TumblrPreviews, type TumblrPreviewsProps, TwitterLinkPreview, TwitterPostPreview, TwitterPreviews, parseHyperlinks };
package/dist/index.js CHANGED
@@ -50,6 +50,43 @@ var formatMastodonDate = new Intl.DateTimeFormat("en-US", {
50
50
  day: "numeric",
51
51
  year: "numeric"
52
52
  }).format;
53
+ var collapseWhitespace = (text) => text.replace(/\s+/g, " ").trim();
54
+ var countOccurrences = (haystack, needle) => {
55
+ let count = 0;
56
+ for (let pos = haystack.indexOf(needle); pos !== -1; pos = haystack.indexOf(needle, pos + 1)) {
57
+ count++;
58
+ }
59
+ return count;
60
+ };
61
+ var nthIndexOf = (haystack, needle, n) => {
62
+ let pos = haystack.indexOf(needle);
63
+ while (pos !== -1 && n > 0) {
64
+ n--;
65
+ pos = haystack.indexOf(needle, pos + 1);
66
+ }
67
+ return pos;
68
+ };
69
+ function parseHyperlinks(html) {
70
+ if (!html) {
71
+ return [];
72
+ }
73
+ const doc = document.implementation.createHTMLDocument("");
74
+ doc.body.innerHTML = html;
75
+ const links = [];
76
+ for (const anchor of Array.from(doc.body.querySelectorAll("a[href]"))) {
77
+ const href = _nullishCoalesce(anchor.getAttribute("href"), () => ( ""));
78
+ const text = collapseWhitespace(_nullishCoalesce(anchor.textContent, () => ( "")));
79
+ if (!/^https?:\/\//i.test(href) || "" === text || text === href) {
80
+ continue;
81
+ }
82
+ const range = doc.createRange();
83
+ range.selectNodeContents(doc.body);
84
+ range.setEndBefore(anchor);
85
+ const occurrence = countOccurrences(collapseWhitespace(range.toString()), text);
86
+ links.push({ text, href, occurrence });
87
+ }
88
+ return links;
89
+ }
53
90
  var hashtagUrlMap = {
54
91
  twitter: "https://twitter.com/hashtag/%1$s",
55
92
  facebook: "https://www.facebook.com/hashtag/%1$s",
@@ -68,7 +105,8 @@ function preparePreviewText(text, options) {
68
105
  maxLines,
69
106
  hyperlinkHashtags = true,
70
107
  // Instagram doesn't support hyperlink URLs at the moment.
71
- hyperlinkUrls = "instagram" !== platform
108
+ hyperlinkUrls = "instagram" !== platform,
109
+ hyperlinks
72
110
  } = options;
73
111
  let result = stripHtmlTags(text);
74
112
  result = result.replaceAll(/(?:\s*[\n\r]){2,}/g, "\n\n");
@@ -98,6 +136,31 @@ function preparePreviewText(text, options) {
98
136
  result = result.replace(fullMatch, `${whitespace}<Hashtag${index} />`);
99
137
  });
100
138
  }
139
+ if (_optionalChain([hyperlinks, 'optionalAccess', _4 => _4.length])) {
140
+ const matches = [];
141
+ hyperlinks.forEach(({ text: anchorText, href, occurrence = 0 }, index) => {
142
+ if (!anchorText) {
143
+ return;
144
+ }
145
+ const pos = nthIndexOf(result, anchorText, occurrence);
146
+ if (pos === -1) {
147
+ return;
148
+ }
149
+ const overlaps = matches.some(
150
+ (match) => pos < match.pos + match.text.length && match.pos < pos + anchorText.length
151
+ );
152
+ if (!overlaps) {
153
+ matches.push({ pos, text: anchorText, href, index });
154
+ }
155
+ });
156
+ matches.sort((a, b) => b.pos - a.pos);
157
+ for (const { pos, text: anchorText, href, index } of matches) {
158
+ const token = `Hyperlink${index}`;
159
+ componentMap[token] = /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "a", { href, rel: "noopener noreferrer", target: "_blank" });
160
+ const wrapped = `<${token}>${anchorText}</${token}>`;
161
+ result = result.slice(0, pos) + wrapped + result.slice(pos + anchorText.length);
162
+ }
163
+ }
101
164
  result = result.replace(/\n/g, "<br />");
102
165
  componentMap.br = /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "br", {});
103
166
  return _element.createInterpolateElement.call(void 0, result, componentMap);
@@ -387,7 +450,7 @@ var TwitterPostPreview = ({
387
450
  cardType,
388
451
  url
389
452
  }) => {
390
- const hasMedia = !!_optionalChain([media, 'optionalAccess', _4 => _4.length]);
453
+ const hasMedia = !!_optionalChain([media, 'optionalAccess', _5 => _5.length]);
391
454
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "twitter-preview__wrapper", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "twitter-preview__container", children: [
392
455
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Sidebar, { profileImage, showThreadConnector }),
393
456
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "twitter-preview__main", children: [
@@ -449,7 +512,7 @@ var TwitterPreviews = ({
449
512
  hidePostPreview,
450
513
  tweets
451
514
  }) => {
452
- if (!_optionalChain([tweets, 'optionalAccess', _5 => _5.length])) {
515
+ if (!_optionalChain([tweets, 'optionalAccess', _6 => _6.length])) {
453
516
  return null;
454
517
  }
455
518
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "social-preview twitter-preview", children: [
@@ -547,7 +610,7 @@ function LinkedInPostPreview({
547
610
  title,
548
611
  url
549
612
  }) {
550
- const hasMedia = !!_optionalChain([media, 'optionalAccess', _6 => _6.length]);
613
+ const hasMedia = !!_optionalChain([media, 'optionalAccess', _7 => _7.length]);
551
614
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "linkedin-preview__wrapper", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "section", { className: `linkedin-preview__container ${hasMedia ? "has-media" : ""}`, children: [
552
615
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "linkedin-preview__header", children: [
553
616
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "linkedin-preview__header--avatar", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AvatarWithFallback, { src: profileImage }) }),
@@ -784,7 +847,7 @@ var actions_default = TumblrPostActions;
784
847
 
785
848
 
786
849
  var TumblrPostHeader = ({ user }) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "tumblr-preview__post-header", children: [
787
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "tumblr-preview__post-header-username", children: _optionalChain([user, 'optionalAccess', _7 => _7.displayName]) || // translators: username of a fictional Tumblr User
850
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "tumblr-preview__post-header-username", children: _optionalChain([user, 'optionalAccess', _8 => _8.displayName]) || // translators: username of a fictional Tumblr User
788
851
  _i18n.__.call(void 0, "anonymous-user", "social-previews") }),
789
852
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, icons_default, { name: "ellipsis" })
790
853
  ] });
@@ -799,7 +862,7 @@ var TumblrLinkPreview = ({
799
862
  user,
800
863
  url
801
864
  }) => {
802
- const avatarUrl = _optionalChain([user, 'optionalAccess', _8 => _8.avatarUrl]);
865
+ const avatarUrl = _optionalChain([user, 'optionalAccess', _9 => _9.avatarUrl]);
803
866
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "tumblr-preview__post", children: [
804
867
  avatarUrl && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "img", { className: "tumblr-preview__avatar", src: avatarUrl, alt: "" }),
805
868
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "tumblr-preview__card", children: [
@@ -836,10 +899,11 @@ var TumblrPostPreview = ({
836
899
  image,
837
900
  user,
838
901
  url,
839
- media
902
+ media,
903
+ hyperlinks
840
904
  }) => {
841
- const avatarUrl = _optionalChain([user, 'optionalAccess', _9 => _9.avatarUrl]);
842
- const mediaItem = _optionalChain([media, 'optionalAccess', _10 => _10[0]]);
905
+ const avatarUrl = _optionalChain([user, 'optionalAccess', _10 => _10.avatarUrl]);
906
+ const mediaItem = _optionalChain([media, 'optionalAccess', _11 => _11[0]]);
843
907
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "tumblr-preview__post", children: [
844
908
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AvatarWithFallback, { className: "tumblr-preview__avatar", src: avatarUrl }),
845
909
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "tumblr-preview__card", children: [
@@ -847,7 +911,8 @@ var TumblrPostPreview = ({
847
911
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "tumblr-preview__body", children: [
848
912
  title ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "tumblr-preview__title", children: tumblrTitle(title) }) : null,
849
913
  description && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "tumblr-preview__description", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ExpandableText, { text: description, children: (visibleText) => preparePreviewText(tumblrDescription(visibleText), {
850
- platform: "tumblr"
914
+ platform: "tumblr",
915
+ hyperlinks
851
916
  }) }) }),
852
917
  mediaItem ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "tumblr-preview__media-item", children: mediaItem.type.startsWith("video/") ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "video", { controls: true, className: "tumblr-preview__media--video", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "source", { src: mediaItem.url, type: mediaItem.type }) }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "img", { className: "tumblr-preview__image", src: mediaItem.url, alt: "" }) }) : image && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
853
918
  "img",
@@ -873,7 +938,7 @@ var TumblrPreviews = ({
873
938
  hidePostPreview,
874
939
  ...props
875
940
  }) => {
876
- const hasMedia = !!_optionalChain([props, 'access', _11 => _11.media, 'optionalAccess', _12 => _12.length]);
941
+ const hasMedia = !!_optionalChain([props, 'access', _12 => _12.media, 'optionalAccess', _13 => _13.length]);
877
942
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "social-preview tumblr-preview", children: [
878
943
  !hidePostPreview && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "section", { className: "social-preview__section tumblr-preview__section", children: [
879
944
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SectionHeading, {
@@ -1025,11 +1090,11 @@ var FacebookPostHeader = ({ user, timeElapsed, hideOptions }) => {
1025
1090
  AvatarWithFallback,
1026
1091
  {
1027
1092
  className: "facebook-preview__post-header-avatar",
1028
- src: _optionalChain([user, 'optionalAccess', _13 => _13.avatarUrl])
1093
+ src: _optionalChain([user, 'optionalAccess', _14 => _14.avatarUrl])
1029
1094
  }
1030
1095
  ),
1031
1096
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { children: [
1032
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "facebook-preview__post-header-name", children: _optionalChain([user, 'optionalAccess', _14 => _14.displayName]) || // translators: name of a fictional Facebook User
1097
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "facebook-preview__post-header-name", children: _optionalChain([user, 'optionalAccess', _15 => _15.displayName]) || // translators: name of a fictional Facebook User
1033
1098
  _i18n.__.call(void 0, "Anonymous User", "social-previews") }),
1034
1099
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "facebook-preview__post-header-share", children: [
1035
1100
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "facebook-preview__post-header-time", children: timeElapsed ? _i18n.__.call(void 0,
@@ -1173,7 +1238,7 @@ var FacebookPreviews = ({
1173
1238
  hidePostPreview,
1174
1239
  ...props
1175
1240
  }) => {
1176
- const hasMedia = !!_optionalChain([props, 'access', _15 => _15.media, 'optionalAccess', _16 => _16.length]);
1241
+ const hasMedia = !!_optionalChain([props, 'access', _16 => _16.media, 'optionalAccess', _17 => _17.length]);
1177
1242
  const hasCustomImage = !!props.customImage;
1178
1243
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "social-preview facebook-preview", children: [
1179
1244
  !hidePostPreview && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "section", { className: "social-preview__section facebook-preview__section", children: [
@@ -1291,8 +1356,8 @@ var mastodonBody = (text, options) => {
1291
1356
  var getMastodonAddressDetails = (address) => {
1292
1357
  const matches = address.match(ADDRESS_PATTERN);
1293
1358
  return {
1294
- username: _optionalChain([matches, 'optionalAccess', _17 => _17[1]]) || "",
1295
- instance: _optionalChain([matches, 'optionalAccess', _18 => _18[2]]) || DEFAULT_MASTODON_INSTANCE
1359
+ username: _optionalChain([matches, 'optionalAccess', _18 => _18[1]]) || "",
1360
+ instance: _optionalChain([matches, 'optionalAccess', _19 => _19[2]]) || DEFAULT_MASTODON_INSTANCE
1296
1361
  };
1297
1362
  };
1298
1363
 
@@ -1362,7 +1427,7 @@ var MastodonPostHeader = ({ user }) => {
1362
1427
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { children: [
1363
1428
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "mastodon-preview__post-header-displayname", children: displayName || // translators: username of a fictional Mastodon User
1364
1429
  _i18n.__.call(void 0, "anonymous-user", "social-previews") }),
1365
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "mastodon-preview__post-header-username", children: _optionalChain([address, 'optionalAccess', _19 => _19.replace, 'call', _20 => _20(`@${DEFAULT_MASTODON_INSTANCE}`, "")]) || "@username" })
1430
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "mastodon-preview__post-header-username", children: _optionalChain([address, 'optionalAccess', _20 => _20.replace, 'call', _21 => _21(`@${DEFAULT_MASTODON_INSTANCE}`, "")]) || "@username" })
1366
1431
  ] })
1367
1432
  ] }),
1368
1433
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "mastodon-preview__post-header-audience", children: [
@@ -1391,7 +1456,7 @@ var MastodonLinkPreview = (props) => {
1391
1456
 
1392
1457
  var MastonPostBody = (props) => {
1393
1458
  const { title, description, customText, user, children } = props;
1394
- const instance = _optionalChain([user, 'optionalAccess', _21 => _21.address]) ? getMastodonAddressDetails(user.address).instance : "";
1459
+ const instance = _optionalChain([user, 'optionalAccess', _22 => _22.address]) ? getMastodonAddressDetails(user.address).instance : "";
1395
1460
  const options = {
1396
1461
  instance,
1397
1462
  offset: 0
@@ -1426,7 +1491,7 @@ var MastodonPostPreview = (props) => {
1426
1491
  const { user, media } = props;
1427
1492
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "mastodon-preview__post", children: [
1428
1493
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, header_default3, { user }),
1429
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, body_default, { ...props, children: _optionalChain([media, 'optionalAccess', _22 => _22.length]) ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: _clsx2.default.call(void 0, "mastodon-preview__media", { "as-grid": media.length > 1 }), children: media.map((mediaItem, index) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1494
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, body_default, { ...props, children: _optionalChain([media, 'optionalAccess', _23 => _23.length]) ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: _clsx2.default.call(void 0, "mastodon-preview__media", { "as-grid": media.length > 1 }), children: media.map((mediaItem, index) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1430
1495
  "div",
1431
1496
  {
1432
1497
  className: "mastodon-preview__media-item",
@@ -1434,7 +1499,7 @@ var MastodonPostPreview = (props) => {
1434
1499
  },
1435
1500
  `mastodon-preview__media-item-${index}`
1436
1501
  )) }) : null }),
1437
- !_optionalChain([media, 'optionalAccess', _23 => _23.length]) ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, card_default, { ...props }) : null,
1502
+ !_optionalChain([media, 'optionalAccess', _24 => _24.length]) ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, card_default, { ...props }) : null,
1438
1503
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, actions_default3, {})
1439
1504
  ] });
1440
1505
  };
@@ -1615,7 +1680,7 @@ function NextdoorPostPreview({
1615
1680
  title,
1616
1681
  url
1617
1682
  }) {
1618
- const hasMedia = !!_optionalChain([media, 'optionalAccess', _24 => _24.length]);
1683
+ const hasMedia = !!_optionalChain([media, 'optionalAccess', _25 => _25.length]);
1619
1684
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "nextdoor-preview__wrapper", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "section", { className: `nextdoor-preview__container ${hasMedia ? "has-media" : ""}`, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "nextdoor-preview__content", children: [
1620
1685
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "nextdoor-preview__header", children: [
1621
1686
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "nextdoor-preview__header--avatar", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AvatarWithFallback, { src: profileImage }) }),
@@ -1647,7 +1712,7 @@ function NextdoorPostPreview({
1647
1712
  "div",
1648
1713
  {
1649
1714
  className: "nextdoor-preview__media-item",
1650
- children: _optionalChain([mediaItem, 'optionalAccess', _25 => _25.type, 'optionalAccess', _26 => _26.startsWith, 'call', _27 => _27("video/")]) ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "video", { controls: true, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "source", { src: mediaItem.url, type: mediaItem.type }) }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "img", { alt: mediaItem.alt || "", src: mediaItem.url })
1715
+ children: _optionalChain([mediaItem, 'optionalAccess', _26 => _26.type, 'optionalAccess', _27 => _27.startsWith, 'call', _28 => _28("video/")]) ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "video", { controls: true, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "source", { src: mediaItem.url, type: mediaItem.type }) }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "img", { alt: mediaItem.alt || "", src: mediaItem.url })
1651
1716
  },
1652
1717
  `nextdoor-preview__media-item-${index}`
1653
1718
  );
@@ -1820,21 +1885,28 @@ var blueskyTitle = (text) => firstValid(
1820
1885
  hardTruncation(TITLE_LENGTH5)
1821
1886
  )(stripHtmlTags(text)) || "";
1822
1887
  var blueskyBody = (text, options = {}) => {
1823
- const { offset = 0, reserveUrlSpace = true } = options;
1888
+ const { offset = 0, reserveUrlSpace = true, hyperlinks } = options;
1824
1889
  return preparePreviewText(text, {
1825
1890
  platform: "bluesky",
1826
- maxChars: BODY_LENGTH2 - (reserveUrlSpace ? URL_LENGTH2 : 0) - offset
1891
+ maxChars: BODY_LENGTH2 - (reserveUrlSpace ? URL_LENGTH2 : 0) - offset,
1892
+ hyperlinks
1827
1893
  });
1828
1894
  };
1829
1895
  var blueskyUrl = (text) => firstValid(shortEnough(URL_LENGTH2), hardTruncation(URL_LENGTH2))(stripHtmlTags(text)) || "";
1830
1896
 
1831
1897
  // src/bluesky-preview/post/body/index.tsx
1832
1898
 
1833
- var BlueskyPostBody = ({ customText, url, children, appendUrl }) => {
1834
- const showUrl = appendUrl && !!url && !_optionalChain([customText, 'optionalAccess', _28 => _28.includes, 'call', _29 => _29(url)]);
1899
+ var BlueskyPostBody = ({
1900
+ customText,
1901
+ url,
1902
+ children,
1903
+ appendUrl,
1904
+ hyperlinks
1905
+ }) => {
1906
+ const showUrl = appendUrl && !!url && !_optionalChain([customText, 'optionalAccess', _29 => _29.includes, 'call', _30 => _30(url)]);
1835
1907
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "bluesky-preview__body", children: [
1836
1908
  customText ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
1837
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { children: blueskyBody(customText, { reserveUrlSpace: showUrl }) }),
1909
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { children: blueskyBody(customText, { reserveUrlSpace: showUrl, hyperlinks }) }),
1838
1910
  showUrl ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
1839
1911
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "br", {}),
1840
1912
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "a", { href: url, target: "_blank", rel: "noreferrer noopener", children: blueskyUrl(url.replace(/^https?:\/\//, "")) })
@@ -1898,7 +1970,7 @@ var BlueskyPostPreview = (props) => {
1898
1970
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, BlueskyPostSidebar, { user }),
1899
1971
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { children: [
1900
1972
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, header_default4, { user }),
1901
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, body_default2, { ...props, appendUrl: _nullishCoalesce(appendUrl, () => ( Boolean(_optionalChain([media, 'optionalAccess', _30 => _30.length])))), children: _optionalChain([media, 'optionalAccess', _31 => _31.length]) ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: _clsx2.default.call(void 0, "bluesky-preview__media", { "as-grid": media.length > 1 }), children: media.map((mediaItem, index) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1973
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, body_default2, { ...props, appendUrl: _nullishCoalesce(appendUrl, () => ( Boolean(_optionalChain([media, 'optionalAccess', _31 => _31.length])))), children: _optionalChain([media, 'optionalAccess', _32 => _32.length]) ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: _clsx2.default.call(void 0, "bluesky-preview__media", { "as-grid": media.length > 1 }), children: media.map((mediaItem, index) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1902
1974
  "div",
1903
1975
  {
1904
1976
  className: "bluesky-preview__media-item",
@@ -1906,7 +1978,7 @@ var BlueskyPostPreview = (props) => {
1906
1978
  },
1907
1979
  `bluesky-preview__media-item-${index}`
1908
1980
  )) }) : null }),
1909
- !_optionalChain([media, 'optionalAccess', _32 => _32.length]) ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, card_default2, { ...props }) : null,
1981
+ !_optionalChain([media, 'optionalAccess', _33 => _33.length]) ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, card_default2, { ...props }) : null,
1910
1982
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, actions_default4, {})
1911
1983
  ] })
1912
1984
  ] });
@@ -2095,7 +2167,7 @@ var ThreadsPostPreview = ({
2095
2167
  title,
2096
2168
  url
2097
2169
  }) => {
2098
- const hasMedia = !!_optionalChain([media, 'optionalAccess', _33 => _33.length]);
2170
+ const hasMedia = !!_optionalChain([media, 'optionalAccess', _34 => _34.length]);
2099
2171
  const displayAsCard = url && image && !hasMedia;
2100
2172
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "threads-preview__wrapper", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "threads-preview__container", children: [
2101
2173
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Sidebar2, { profileImage, showThreadConnector }),
@@ -2142,7 +2214,7 @@ var ThreadsPreviews = ({
2142
2214
  hidePostPreview,
2143
2215
  posts
2144
2216
  }) => {
2145
- if (!_optionalChain([posts, 'optionalAccess', _34 => _34.length])) {
2217
+ if (!_optionalChain([posts, 'optionalAccess', _35 => _35.length])) {
2146
2218
  return null;
2147
2219
  }
2148
2220
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "social-preview threads-preview", children: [
@@ -2347,7 +2419,7 @@ function InstagramPostPreview({
2347
2419
  url
2348
2420
  }) {
2349
2421
  const username = name || "username";
2350
- const mediaItem = _optionalChain([media, 'optionalAccess', _35 => _35[0]]);
2422
+ const mediaItem = _optionalChain([media, 'optionalAccess', _36 => _36[0]]);
2351
2423
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "instagram-preview__wrapper", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "section", { className: "instagram-preview__container", children: [
2352
2424
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "instagram-preview__header", children: [
2353
2425
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "instagram-preview__header--avatar", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AvatarWithFallback, { src: profileImage }) }),
@@ -2442,5 +2514,6 @@ var InstagramPreviews = ({
2442
2514
 
2443
2515
 
2444
2516
 
2445
- exports.AUTO_SHARED_LINK_PREVIEW = AUTO_SHARED_LINK_PREVIEW; exports.AUTO_SHARED_SOCIAL_POST_PREVIEW = AUTO_SHARED_SOCIAL_POST_PREVIEW; exports.BlueskyLinkPreview = BlueskyLinkPreview; exports.BlueskyPostPreview = BlueskyPostPreview; exports.BlueskyPreviews = BlueskyPreviews; exports.DEFAULT_LINK_PREVIEW = DEFAULT_LINK_PREVIEW; exports.FacebookLinkPreview = FacebookLinkPreview; exports.FacebookPostPreview = FacebookPostPreview; exports.FacebookPreviews = FacebookPreviews; exports.GoogleSearchPreview = GoogleSearchPreview; exports.InstagramPostPreview = InstagramPostPreview; exports.InstagramPreviews = InstagramPreviews; exports.LANDSCAPE_MODE = LANDSCAPE_MODE; exports.LinkedInLinkPreview = LinkedInLinkPreview; exports.LinkedInPostPreview = LinkedInPostPreview; exports.LinkedInPreviews = LinkedInPreviews; exports.MastodonLinkPreview = MastodonLinkPreview; exports.MastodonPostPreview = MastodonPostPreview; exports.MastodonPreviews = MastodonPreviews; exports.NextdoorLinkPreview = NextdoorLinkPreview; exports.NextdoorPostPreview = NextdoorPostPreview; exports.NextdoorPreviews = NextdoorPreviews; exports.PORTRAIT_MODE = PORTRAIT_MODE; exports.TYPE_ARTICLE = TYPE_ARTICLE; exports.TYPE_WEBSITE = TYPE_WEBSITE; exports.ThreadsLinkPreview = ThreadsLinkPreview; exports.ThreadsPostPreview = ThreadsPostPreview; exports.ThreadsPreviews = ThreadsPreviews; exports.TumblrLinkPreview = TumblrLinkPreview; exports.TumblrPostPreview = TumblrPostPreview; exports.TumblrPreviews = TumblrPreviews; exports.TwitterLinkPreview = TwitterLinkPreview; exports.TwitterPostPreview = TwitterPostPreview; exports.TwitterPreviews = TwitterPreviews;
2517
+
2518
+ exports.AUTO_SHARED_LINK_PREVIEW = AUTO_SHARED_LINK_PREVIEW; exports.AUTO_SHARED_SOCIAL_POST_PREVIEW = AUTO_SHARED_SOCIAL_POST_PREVIEW; exports.BlueskyLinkPreview = BlueskyLinkPreview; exports.BlueskyPostPreview = BlueskyPostPreview; exports.BlueskyPreviews = BlueskyPreviews; exports.DEFAULT_LINK_PREVIEW = DEFAULT_LINK_PREVIEW; exports.FacebookLinkPreview = FacebookLinkPreview; exports.FacebookPostPreview = FacebookPostPreview; exports.FacebookPreviews = FacebookPreviews; exports.GoogleSearchPreview = GoogleSearchPreview; exports.InstagramPostPreview = InstagramPostPreview; exports.InstagramPreviews = InstagramPreviews; exports.LANDSCAPE_MODE = LANDSCAPE_MODE; exports.LinkedInLinkPreview = LinkedInLinkPreview; exports.LinkedInPostPreview = LinkedInPostPreview; exports.LinkedInPreviews = LinkedInPreviews; exports.MastodonLinkPreview = MastodonLinkPreview; exports.MastodonPostPreview = MastodonPostPreview; exports.MastodonPreviews = MastodonPreviews; exports.NextdoorLinkPreview = NextdoorLinkPreview; exports.NextdoorPostPreview = NextdoorPostPreview; exports.NextdoorPreviews = NextdoorPreviews; exports.PORTRAIT_MODE = PORTRAIT_MODE; exports.TYPE_ARTICLE = TYPE_ARTICLE; exports.TYPE_WEBSITE = TYPE_WEBSITE; exports.ThreadsLinkPreview = ThreadsLinkPreview; exports.ThreadsPostPreview = ThreadsPostPreview; exports.ThreadsPreviews = ThreadsPreviews; exports.TumblrLinkPreview = TumblrLinkPreview; exports.TumblrPostPreview = TumblrPostPreview; exports.TumblrPreviews = TumblrPreviews; exports.TwitterLinkPreview = TwitterLinkPreview; exports.TwitterPostPreview = TwitterPostPreview; exports.TwitterPreviews = TwitterPreviews; exports.parseHyperlinks = parseHyperlinks;
2446
2519
  //# sourceMappingURL=index.js.map