Skip to content

✨ Added ability to put a share button on posts#26866

Merged
troyciesco merged 28 commits intomainfrom
FEA-480/portal-native-share
Apr 8, 2026
Merged

✨ Added ability to put a share button on posts#26866
troyciesco merged 28 commits intomainfrom
FEA-480/portal-native-share

Conversation

@peterzimon
Copy link
Copy Markdown
Contributor

@peterzimon peterzimon commented Mar 18, 2026

ref https://linear.app/ghost/issue/FEA-480/native-share-buttons-with-link-based-referral-param-for-attribution

This PR adds a new small modal component to Portal that allows a reader to more easily share a post. It fires by adding #/share on any post link. The modal lets visitors copy the link to the post and share to top social platforms.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 18, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

This pull request introduces a new Share modal feature to the Portal application. The implementation includes a new ShareModal component that extracts metadata from the host document (canonical URL, Open Graph tags, Twitter tags, favicon, site name, and author) and generates social share links for Twitter, Facebook, LinkedIn, Threads, Bluesky, and email. The component provides copy-to-clipboard functionality with visual feedback and a collapsible menu for additional sharing options. The copy-to-clipboard utility was enhanced to use the Clipboard API with a fallback to document.execCommand. Route handling was updated to support the "share" path, corresponding styles were integrated, and comprehensive tests were added. Internationalization keys for the new feature were added across all supported language locales with placeholder empty translations.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The PR title clearly summarizes the main change: adding a share button feature to posts via Portal. It is concise, specific, and directly reflects the primary purpose of the changeset.
Description check ✅ Passed The PR description clearly describes the feature being added: a new Portal modal component for sharing posts with copy-to-clipboard and social platform integration.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch FEA-480/portal-native-share

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

🧹 Nitpick comments (4)
ghost/i18n/locales/zh-Hant/portal.json (1)

58-59: Prefer real zh-Hant strings for new share actions (instead of empty placeholders).

At Line 58, Line 59, Line 88, Line 127, Line 176, Line 214, and Line 244, these are user-facing modal actions. Using empty strings can produce mixed-language/blank labels in localized UI. Consider filling these now.

Suggested translation patch
-    "Copied": "",
-    "Copy link": "",
+    "Copied": "已複製",
+    "Copy link": "複製連結",
@@
-    "Facebook": "",
+    "Facebook": "Facebook",
@@
-    "LinkedIn": "",
+    "LinkedIn": "LinkedIn",
@@
-    "Share": "",
+    "Share": "分享",
@@
-    "Threads": "",
+    "Threads": "Threads",
@@
-    "X (Twitter)": "",
+    "X (Twitter)": "X(Twitter)",

Also applies to: 88-88, 127-127, 176-176, 214-214, 244-244

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/zh-Hant/portal.json` around lines 58 - 59, Replace the
empty strings for the user-facing share/action keys (e.g., "Copied", "Copy link"
and the other modal action keys referenced in the review) with proper
Traditional Chinese (zh-Hant) translations so the localized UI doesn't show
blank or English labels; update the values for the keys "Copied" and "Copy link"
(and the other empty action keys at the locations noted) with suitable zh-Hant
strings that match the tone of the portal UI.
ghost/i18n/locales/ca/portal.json (1)

58-59: Populate the new share labels in Catalan before shipping broadly.

These new share-related keys are currently empty. Even with fallback behavior, this creates an inconsistent localized experience in the new modal.

Suggested translation patch
-    "Copied": "",
-    "Copy link": "",
+    "Copied": "Copiat",
+    "Copy link": "Copia l'enllaç",
@@
-    "Facebook": "",
+    "Facebook": "Facebook",
@@
-    "LinkedIn": "",
+    "LinkedIn": "LinkedIn",
@@
-    "Share": "",
+    "Share": "Comparteix",
@@
-    "Threads": "",
+    "Threads": "Threads",
@@
-    "X (Twitter)": "",
+    "X (Twitter)": "X (Twitter)",

Also applies to: 88-88, 127-127, 176-176, 214-214, 244-244

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/ca/portal.json` around lines 58 - 59, The new
share-related keys in the Catalan locale ("Copied" and "Copy link" and the other
empty share labels present in portal.json) are empty and must be populated;
update the translation strings for the keys "Copied", "Copy link" (and any other
blank share-related keys referenced in the file) with correct Catalan
equivalents so the share modal displays localized text instead of falling back
to the default language, keeping the key names unchanged.
ghost/i18n/locales/he/portal.json (1)

58-59: Prefer non-empty defaults for new share-related locale keys.

Lines 58, 59, 88, 127, 176, 214, and 244 add new keys with empty values. This can produce inconsistent UX for Hebrew users (fallback language mix, or blank labels if fallback doesn’t trigger on empty strings). Consider setting explicit values now.

Proposed patch
-    "Copied": "",
-    "Copy link": "",
+    "Copied": "הועתק",
+    "Copy link": "העתק קישור",
@@
-    "Facebook": "",
+    "Facebook": "Facebook",
@@
-    "LinkedIn": "",
+    "LinkedIn": "LinkedIn",
@@
-    "Share": "",
+    "Share": "שיתוף",
@@
-    "Threads": "",
+    "Threads": "Threads",
@@
-    "X (Twitter)": "",
+    "X (Twitter)": "X (Twitter)",

Also applies to: 88-88, 127-127, 176-176, 214-214, 244-244

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/he/portal.json` around lines 58 - 59, Several new
share-related locale keys (e.g., "Copied" and "Copy link") were added with empty
values; replace those empty strings with explicit non-empty Hebrew defaults (or
clear English placeholders if Hebrew translations are not ready) for "Copied",
"Copy link" and the other newly added share-related locale keys in this locale
file so the UI never falls back to a blank label; keep the same quoting/JSON
style as surrounding entries and follow existing translation conventions when
providing the values.
ghost/i18n/locales/context.json (1)

70-71: Add translator context text for the new share labels.

These entries are currently blank, which removes guidance for translators and can cause inconsistent wording across locales.

💡 Suggested context text
-    "Copied": "",
-    "Copy link": "",
+    "Copied": "Toast text shown after a share URL is copied",
+    "Copy link": "Button label to copy the current page URL in the share modal",
...
-    "Facebook": "",
+    "Facebook": "Share target label for Facebook",
...
-    "LinkedIn": "",
+    "LinkedIn": "Share target label for LinkedIn",
...
-    "Share": "",
+    "Share": "Title/label for the share modal and share actions",
...
-    "Threads": "",
+    "Threads": "Share target label for Threads",
...
-    "X (Twitter)": "",
+    "X (Twitter)": "Share target label for X (formerly Twitter)"

Also applies to: 109-109, 164-164, 245-245, 310-310, 354-354

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/context.json` around lines 70 - 71, The i18n context
entries for the share labels are blank; add concise translator context strings
for the keys "Copied" and "Copy link" (and the other identical keys elsewhere)
so translators understand intent and tone — e.g., indicate whether "Copied" is a
confirmation message shown after copying a link and whether "Copy link" is a
button/action label; update the context.json entries for the "Copied" and "Copy
link" keys (and matching keys found in the same file) with those brief
explanatory notes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/portal/README.md`:
- Line 25: The README entry describing how to open the share modal is
inconsistent: update the route fragment documented alongside data-portal="share"
to match the PR objective by replacing `#/portal/share` with `#/share` (so the
docs show Share modal can be opened with `data-portal="share"` (or `#/share`));
ensure both the inline fragment text and any other references in the same file
that mention `#/portal/share` are changed to `#/share`.

In `@apps/portal/src/app.js`:
- Around line 953-956: The share route mapping returning {page: 'share'} is
never reached because fetchLinkData's linkRegex only matches hashes like
/portal/..., so hashes like "#/share" bypass it; update fetchLinkData to
recognize the "#/share" fragment (either by expanding linkRegex to include
^#\/share(?:\/|$) or adding an explicit check for hash.startsWith('#/share')) so
that when the hash is "#/share" it returns the same path === 'share' result and
triggers the modal; refer to fetchLinkData and linkRegex as the places to change
and ensure the code path that builds {page: 'share'} is returned for "#/share".

In `@apps/portal/test/unit/components/pages/share-modal.test.js`:
- Around line 95-100: The test assertions in the ShareModal unit test check
button order incorrectly; update the expectations that read the actions array
(from container.querySelector('.gh-portal-share-actions').children) so they
assert the actual DOM order: actions[0] = 'copy', actions[1] = 'email',
actions[2] = 'twitter', actions[3] = 'facebook', actions[4] =
'gh-portal-share-more' (adjust the expect(...).toHaveClass calls accordingly in
the share-modal.test.js test that references the actions array).

In `@ghost/i18n/locales/de-CH/portal.json`:
- Around line 58-59: The de-CH locale file has empty translations for the new
share-modal keys (e.g., "Copied" and "Copy link" in portal.json and the other
empty entries noted); populate each empty string with the correct Swiss German
translations (or explicit passthrough if they are brand names) so the UI doesn’t
fallback to source strings—update the keys "Copied", "Copy link" and the other
empty keys mentioned (lines referenced in the review) with appropriate localized
text, preserving the JSON key names and punctuation.

In `@ghost/i18n/locales/en/portal.json`:
- Line 33: Add the missing translation keys "Bluesky" and "More options" to
every locale's portal.json and to the shared context.json metadata so
translations and fallback behavior remain consistent; for each locale file add
the same key names (use the English strings or empty "" placeholders as
appropriate) and in context.json add corresponding entries for "Bluesky" and
"More options" so tools that read context/metadata can detect them.

In `@ghost/i18n/locales/hu/portal.json`:
- Around line 58-59: Add Hungarian translations for the actionable UI strings in
the portal.json locale: set "Copied" to "Másolva", "Copy link" to "Link
másolása", and "Share" to "Megosztás"; ensure you update both occurrences
referenced in the file (the keys "Copied", "Copy link", and "Share") so the
user-facing copy is consistently localized across the portal.

In `@ghost/i18n/locales/nn/portal.json`:
- Around line 58-59: The nn locale file has empty values for several UI strings
causing fallback to keys; update portal.json by supplying Norwegian Nynorsk
translations for the keys "Copied", "Copy link", "Facebook", "LinkedIn",
"Share", "Threads", and "X (Twitter)" (the exact entries shown in the diff) so
they are not empty, or explicitly mark/annotate them as intentional placeholders
before merging; ensure you edit the nn/portal.json entries for those keys to
contain the correct Nynorsk strings.

In `@ghost/i18n/locales/sl/portal.json`:
- Around line 58-59: Add the missing "Bluesky" translation key to the Slovenian
portal locale so t('Bluesky') used by ShareModal resolves; update the JSON in
sl/portal.json to include the entry "Bluesky": "" alongside the existing social
platform keys (e.g., "Facebook", "LinkedIn", "Threads", "X (Twitter)") so the
ShareModal component in apps/portal/src/components/pages/share-modal.js finds
the key.

In `@ghost/i18n/locales/sr-Cyrl/portal.json`:
- Around line 58-59: Fill in Serbian Cyrillic translations for the empty generic
UI action keys in ghost/i18n/locales/sr-Cyrl/portal.json — specifically provide
proper SR-Cyrl values for "Copied" and "Copy link" and for the other empty
entries referenced (the empty generic action keys around the same modal at the
other noted locations). Update those JSON values with concise Serbian-Cyrillic
strings (keeping brand names unchanged if present) so the new Share modal does
not display mixed-language UI.

---

Nitpick comments:
In `@ghost/i18n/locales/ca/portal.json`:
- Around line 58-59: The new share-related keys in the Catalan locale ("Copied"
and "Copy link" and the other empty share labels present in portal.json) are
empty and must be populated; update the translation strings for the keys
"Copied", "Copy link" (and any other blank share-related keys referenced in the
file) with correct Catalan equivalents so the share modal displays localized
text instead of falling back to the default language, keeping the key names
unchanged.

In `@ghost/i18n/locales/context.json`:
- Around line 70-71: The i18n context entries for the share labels are blank;
add concise translator context strings for the keys "Copied" and "Copy link"
(and the other identical keys elsewhere) so translators understand intent and
tone — e.g., indicate whether "Copied" is a confirmation message shown after
copying a link and whether "Copy link" is a button/action label; update the
context.json entries for the "Copied" and "Copy link" keys (and matching keys
found in the same file) with those brief explanatory notes.

In `@ghost/i18n/locales/he/portal.json`:
- Around line 58-59: Several new share-related locale keys (e.g., "Copied" and
"Copy link") were added with empty values; replace those empty strings with
explicit non-empty Hebrew defaults (or clear English placeholders if Hebrew
translations are not ready) for "Copied", "Copy link" and the other newly added
share-related locale keys in this locale file so the UI never falls back to a
blank label; keep the same quoting/JSON style as surrounding entries and follow
existing translation conventions when providing the values.

In `@ghost/i18n/locales/zh-Hant/portal.json`:
- Around line 58-59: Replace the empty strings for the user-facing share/action
keys (e.g., "Copied", "Copy link" and the other modal action keys referenced in
the review) with proper Traditional Chinese (zh-Hant) translations so the
localized UI doesn't show blank or English labels; update the values for the
keys "Copied" and "Copy link" (and the other empty action keys at the locations
noted) with suitable zh-Hant strings that match the tone of the portal UI.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: bb5a4a8c-a7d1-4784-9b27-0f9eaa9d4db3

📥 Commits

Reviewing files that changed from the base of the PR and between 29dc800 and 8e3422c.

⛔ Files ignored due to path filters (8)
  • apps/portal/src/images/icons/ellipsis.svg is excluded by !**/*.svg
  • apps/portal/src/images/icons/envelope.svg is excluded by !**/*.svg
  • apps/portal/src/images/icons/share-bluesky.svg is excluded by !**/*.svg
  • apps/portal/src/images/icons/share-facebook.svg is excluded by !**/*.svg
  • apps/portal/src/images/icons/share-link.svg is excluded by !**/*.svg
  • apps/portal/src/images/icons/share-linkedin.svg is excluded by !**/*.svg
  • apps/portal/src/images/icons/share-threads.svg is excluded by !**/*.svg
  • apps/portal/src/images/icons/share-x.svg is excluded by !**/*.svg
📒 Files selected for processing (73)
  • apps/portal/README.md
  • apps/portal/src/app.js
  • apps/portal/src/components/frame.styles.js
  • apps/portal/src/components/pages/share-modal.js
  • apps/portal/src/pages.js
  • apps/portal/src/utils/copy-to-clipboard.js
  • apps/portal/test/data-attributes.test.js
  • apps/portal/test/portal-links.test.js
  • apps/portal/test/unit/components/pages/share-modal.test.js
  • apps/portal/test/utils/copy-to-clipboard.test.js
  • ghost/i18n/locales/af/portal.json
  • ghost/i18n/locales/ar/portal.json
  • ghost/i18n/locales/bg/portal.json
  • ghost/i18n/locales/bn/portal.json
  • ghost/i18n/locales/bs/portal.json
  • ghost/i18n/locales/ca/portal.json
  • ghost/i18n/locales/context.json
  • ghost/i18n/locales/cs/portal.json
  • ghost/i18n/locales/da/portal.json
  • ghost/i18n/locales/de-CH/portal.json
  • ghost/i18n/locales/de/portal.json
  • ghost/i18n/locales/el/portal.json
  • ghost/i18n/locales/en/portal.json
  • ghost/i18n/locales/eo/portal.json
  • ghost/i18n/locales/es/portal.json
  • ghost/i18n/locales/et/portal.json
  • ghost/i18n/locales/eu/portal.json
  • ghost/i18n/locales/fa/portal.json
  • ghost/i18n/locales/fi/portal.json
  • ghost/i18n/locales/fr/portal.json
  • ghost/i18n/locales/gd/portal.json
  • ghost/i18n/locales/he/portal.json
  • ghost/i18n/locales/hi/portal.json
  • ghost/i18n/locales/hr/portal.json
  • ghost/i18n/locales/hu/portal.json
  • ghost/i18n/locales/id/portal.json
  • ghost/i18n/locales/is/portal.json
  • ghost/i18n/locales/it/portal.json
  • ghost/i18n/locales/ja/portal.json
  • ghost/i18n/locales/ko/portal.json
  • ghost/i18n/locales/kz/portal.json
  • ghost/i18n/locales/lt/portal.json
  • ghost/i18n/locales/lv/portal.json
  • ghost/i18n/locales/mk/portal.json
  • ghost/i18n/locales/mn/portal.json
  • ghost/i18n/locales/ms/portal.json
  • ghost/i18n/locales/nb/portal.json
  • ghost/i18n/locales/ne/portal.json
  • ghost/i18n/locales/nl/portal.json
  • ghost/i18n/locales/nn/portal.json
  • ghost/i18n/locales/pa/portal.json
  • ghost/i18n/locales/pl/portal.json
  • ghost/i18n/locales/pt-BR/portal.json
  • ghost/i18n/locales/pt/portal.json
  • ghost/i18n/locales/ro/portal.json
  • ghost/i18n/locales/ru/portal.json
  • ghost/i18n/locales/si/portal.json
  • ghost/i18n/locales/sk/portal.json
  • ghost/i18n/locales/sl/portal.json
  • ghost/i18n/locales/sq/portal.json
  • ghost/i18n/locales/sr-Cyrl/portal.json
  • ghost/i18n/locales/sr/portal.json
  • ghost/i18n/locales/sv/portal.json
  • ghost/i18n/locales/sw/portal.json
  • ghost/i18n/locales/ta/portal.json
  • ghost/i18n/locales/th/portal.json
  • ghost/i18n/locales/tr/portal.json
  • ghost/i18n/locales/uk/portal.json
  • ghost/i18n/locales/ur/portal.json
  • ghost/i18n/locales/uz/portal.json
  • ghost/i18n/locales/vi/portal.json
  • ghost/i18n/locales/zh-Hant/portal.json
  • ghost/i18n/locales/zh/portal.json

Comment thread apps/portal/README.md Outdated
Comment thread apps/portal/src/app.js
Comment thread apps/portal/test/unit/components/pages/share-modal.test.js
Comment thread ghost/i18n/locales/de-CH/portal.json
Comment thread ghost/i18n/locales/en/portal.json
Comment thread ghost/i18n/locales/hu/portal.json
Comment thread ghost/i18n/locales/nn/portal.json
Comment thread ghost/i18n/locales/sl/portal.json
Comment thread ghost/i18n/locales/sr-Cyrl/portal.json
peterzimon added a commit that referenced this pull request Mar 18, 2026
ref #26866

Bumped @tryghost/portal version, aligned share action order with spec, and regenerated portal locale keys required by i18n checks.
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 15

♻️ Duplicate comments (2)
ghost/i18n/locales/hu/portal.json (1)

59-60: ⚠️ Potential issue | 🟡 Minor

Fill the Hungarian action labels for the share UI.

Line 59, Line 60, Line 137, and Line 178 are empty for user-facing actions, so users will see fallback English in a Hungarian locale.

Suggested patch
-    "Copied": "",
-    "Copy link": "",
+    "Copied": "Másolva",
+    "Copy link": "Link másolása",
...
-    "More options": "",
+    "More options": "További lehetőségek",
...
-    "Share": "",
+    "Share": "Megosztás",

Also applies to: 137-137, 178-178

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/hu/portal.json` around lines 59 - 60, The Hungarian locale
file is missing translations for several user-facing action labels; update the
portal.json entries for the keys "Copied" and "Copy link" (and the other empty
action-label keys noted at the same file positions) by providing appropriate
Hungarian strings (e.g., "Másolva" for "Copied", "Link másolása" for "Copy
link") so users see localized UI text instead of falling back to English; edit
the existing keys in portal.json and ensure the values are properly quoted JSON
strings.
ghost/i18n/locales/nn/portal.json (1)

59-60: ⚠️ Potential issue | 🟡 Minor

Provide Nynorsk values for share action labels.

Line 59, Line 60, Line 137, and Line 178 are still empty. These are user-visible actions and should not rely on fallback/source text in the nn locale.

Also applies to: 137-137, 178-178

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/nn/portal.json` around lines 59 - 60, The nn locale file
has empty values for the share action keys—fill in Nynorsk translations for the
JSON keys "Copied" and "Copy link" (and the other two empty keys shown at lines
137 and 178) so these user-visible actions do not fall back to the source
locale; update the corresponding string values in
ghost/i18n/locales/nn/portal.json with accurate Nynorsk phrases while keeping
the JSON keys unchanged.
🧹 Nitpick comments (4)
ghost/i18n/locales/el/portal.json (1)

33-33: Fill the new share labels in Greek to avoid English fallback UI

Because these values are empty, users in el locale will see source keys (English) for the Share modal labels (e.g., “Copy link”, “Share”), creating mixed-language UX.

Proposed localization patch
-    "Bluesky": "",
+    "Bluesky": "Bluesky",
...
-    "Copied": "",
-    "Copy link": "",
+    "Copied": "Αντιγράφηκε",
+    "Copy link": "Αντιγραφή συνδέσμου",
...
-    "Facebook": "",
+    "Facebook": "Facebook",
...
-    "LinkedIn": "",
+    "LinkedIn": "LinkedIn",
...
-    "More options": "",
+    "More options": "Περισσότερες επιλογές",
...
-    "Share": "",
+    "Share": "Κοινοποίηση",
...
-    "Threads": "",
+    "Threads": "Threads",
...
-    "X (Twitter)": "",
+    "X (Twitter)": "X (Twitter)",

Also applies to: 59-60, 89-89, 128-128, 137-137, 178-178, 216-216, 246-246

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/el/portal.json` at line 33, Several share-label JSON keys
(e.g., "Bluesky", and the other empty keys noted at positions 59-60, 89, 128,
137, 178, 216, 246) are empty, causing English fallback; open the portal.json
locale object and provide Greek translations for each empty share-related key
(for example fill "Bluesky" with the Greek equivalent), ensuring every empty
string is replaced with an appropriate Greek label so the Share modal displays
fully localized text for the el locale.
ghost/i18n/locales/ro/portal.json (1)

33-33: Translate the new Share modal labels in Romanian.

These new user-facing strings are currently empty. Adding Romanian values now will avoid mixed-language UX in the new share flow.

🌐 Suggested locale patch
-    "Bluesky": "",
+    "Bluesky": "Bluesky",
-    "Copied": "",
+    "Copied": "Copiat",
-    "Copy link": "",
+    "Copy link": "Copiază linkul",
-    "Facebook": "",
+    "Facebook": "Facebook",
-    "LinkedIn": "",
+    "LinkedIn": "LinkedIn",
-    "More options": "",
+    "More options": "Mai multe opțiuni",
-    "Share": "",
+    "Share": "Distribuie",
-    "Threads": "",
+    "Threads": "Threads",
-    "X (Twitter)": "",
+    "X (Twitter)": "X (Twitter)",

Also applies to: 59-60, 89-89, 128-128, 137-137, 178-178, 216-216, 246-246

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/ro/portal.json` at line 33, Fill in Romanian translations
for the new Share modal keys in portal.json — notably the "Bluesky" key (and the
other empty share-modal keys referenced in the review) by replacing the empty
strings with proper Romanian text, keeping the JSON keys unchanged; ensure you
preserve existing formatting/commas and escape any special characters, validate
the JSON after editing, and run the locale lint/CI to confirm there are no
missing translations or syntax errors.
ghost/i18n/locales/hi/portal.json (1)

33-33: Fill new Hindi share strings to avoid untranslated UI in Share Modal

These new keys are currently empty, so Hindi users will likely see fallback English for core share actions. Please localize them before release.

Proposed patch (please validate with a native Hindi reviewer)
-    "Bluesky": "",
+    "Bluesky": "ब्लूस्काई",
...
-    "Copied": "",
+    "Copied": "कॉपी किया गया",
-    "Copy link": "",
+    "Copy link": "लिंक कॉपी करें",
...
-    "Facebook": "",
+    "Facebook": "फ़ेसबुक",
...
-    "LinkedIn": "",
+    "LinkedIn": "लिंक्डइन",
...
-    "More options": "",
+    "More options": "और विकल्प",
...
-    "Share": "",
+    "Share": "साझा करें",
...
-    "Threads": "",
+    "Threads": "थ्रेड्स",
...
-    "X (Twitter)": "",
+    "X (Twitter)": "एक्स (ट्विटर)",

Also applies to: 59-60, 89-89, 128-128, 137-137, 178-178, 216-216, 246-246

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/hi/portal.json` at line 33, The listed share-string keys
in portal.json (e.g., "Bluesky" and the other empty keys at the mentioned
locations) are empty and must be replaced with Hindi translations; open
ghost/i18n/locales/hi/portal.json, locate the keys "Bluesky" (and the other
empty entries referenced) and replace each "" with an appropriate Hindi
translation that matches the share-modal context (short, UI-friendly labels),
preserve JSON string escaping and punctuation, run a JSON/l10n validation or
build to ensure no syntax errors, and optionally add a comment or note for a
native reviewer if unsure about nuance.
ghost/i18n/locales/context.json (1)

33-33: Add context descriptions for new share keys.

In context.json, these keys are translator metadata; leaving them blank makes future localization harder and less consistent.

💡 Suggested patch
-    "Bluesky": "",
+    "Bluesky": "Social network label in Share modal",
@@
-    "Copied": "",
-    "Copy link": "",
+    "Copied": "Toast text shown after copying the post URL",
+    "Copy link": "Button label to copy the post URL",
@@
-    "Facebook": "",
+    "Facebook": "Social network label in Share modal",
@@
-    "LinkedIn": "",
+    "LinkedIn": "Social network label in Share modal",
@@
-    "More options": "",
+    "More options": "Button label to open native share dialog",
@@
-    "Share": "",
+    "Share": "Share modal title",
@@
-    "Threads": "",
+    "Threads": "Social network label in Share modal",
@@
-    "X (Twitter)": "",
+    "X (Twitter)": "Social network label in Share modal",

Also applies to: 71-72, 110-110, 165-165, 179-179, 247-247, 312-312, 356-356

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/context.json` at line 33, The context.json entries for new
share keys (e.g., "Bluesky" and the other newly added share keys) are currently
empty; add concise translator metadata for each key in context.json describing
where and how the string is used (e.g., "Label for sharing via Bluesky social
network", whether it's a button/tooltip, and any
placeholder/noun/gender/pluralization notes) so translators know context and
constraints; update the entries for all new share keys (the same set referenced
in the review) with short, clear descriptions that include intended UI location
(button/label/menu), any variable placeholders, and preferred tone/register.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/portal/src/components/pages/share-modal.js`:
- Around line 383-385: getShareUrl currently falls back to window.location.href
which may include hash fragments like "#/share" and leak modal routing state;
update getShareUrl so when getCanonicalUrl() is falsy it returns the current
location without any hash fragment (i.e., strip everything from the first '#' in
window.location.href or use the URL API to construct a href that omits
location.hash) before returning the fallback; keep references to getShareUrl and
getCanonicalUrl so the change is applied in that function.
- Around line 324-326: The metadata helpers in ShareModal (e.g.,
getCanonicalUrl) are querying the iframe's empty document; change them to read
from the host page by using window.parent for DOM and location access (e.g.,
replace document.querySelector(...) with
window.parent.document.querySelector(...) and window.location.href fallback with
window.parent.location.href) and update all metadata getter functions and their
usages (the functions around getCanonicalUrl and where their results are used
around lines 446-453) to use window.parent so the canonical URL, title,
description and image come from the parent page.

In `@ghost/i18n/locales/cs/portal.json`:
- Line 33: The JSON entries for new share labels are left empty (e.g., the
"Bluesky" key in portal.json) so Czech users get fallback source strings; open
ghost/i18n/locales/cs/portal.json and fill each empty string value (including
"Bluesky" and the other empty share-label keys reported) with proper Czech
translations, preserving the exact JSON keys and punctuation, escaping any
special characters, and keeping trailing commas/format consistent; after
updating, run the project's i18n/JSON linter or formatter to ensure valid JSON
and that keys remain unchanged.

In `@ghost/i18n/locales/es/portal.json`:
- Around line 59-60: The Spanish locale file is missing translations for share
action keys causing English fallbacks: add appropriate Spanish strings for the
keys "Copied" and "Copy link" (present at the shown lines) and for the other
empty keys at lines 137 and 178 (the other share/action strings in portal.json)
by updating ghost/i18n/locales/es/portal.json so each empty value is replaced
with the correct Spanish translation, preserving the exact JSON key names and
surrounding punctuation.

In `@ghost/i18n/locales/fa/portal.json`:
- Around line 59-60: The Persian locale file is missing translations for UI
action labels; update the JSON entries for the keys "Copied" and "Copy link"
(and the other empty keys referenced at the same locations) with proper Persian
strings so they don't fall back to the default locale; edit the values for
"Copied", "Copy link" (and the empty keys at the other referenced positions) to
use correct Persian translations, preserve surrounding punctuation/quote
structure and valid JSON formatting, and run a quick lint/parse to ensure no
trailing commas or syntax errors.

In `@ghost/i18n/locales/fr/portal.json`:
- Line 33: Populate the missing French translations for the newly added Share
modal labels by replacing the empty string values for the listed keys (e.g.
"Bluesky" and the other empty entries at the same locations) with appropriate
French text; edit the fr/portal.json entries for "Bluesky" and the other empty
share-related keys referenced in the comment so they contain proper French
labels (ensure wording matches existing portal terminology and pluralization/
casing used elsewhere), then run a quick UI check to confirm there are no
fallback English strings in the Share modal.

In `@ghost/i18n/locales/gd/portal.json`:
- Around line 59-60: The Gaelic (gd) locale file has empty UI strings for the
share actions — fill the empty values for the keys "Copied" and "Copy link" (and
the other empty keys at the indicated spots around lines 137 and 178) with
proper Gaelic translations, or if translation is not available, explicitly
annotate those keys as pending (e.g., add a clear "TODO: translate" comment or
placeholder value) so the missing translations are tracked; update the values
for the keys "Copied", "Copy link" and the other empty keys referenced to either
their correct Gaelic strings or a standardized pending-locale marker.

In `@ghost/i18n/locales/is/portal.json`:
- Around line 59-60: Translate the empty user-facing action labels in the
Icelandic locale by providing Icelandic strings for the keys shown (e.g.,
"Copied" and "Copy link") and for the other empty entries referenced at lines
137 and 178; update the JSON values for those keys in portal.json (use
appropriate Icelandic phrases such as “Afritað” for "Copied" and “Afrita tengil”
for "Copy link") so the locale no longer falls back to the default language.

In `@ghost/i18n/locales/it/portal.json`:
- Around line 59-60: Fill the empty Italian translation values for the share
action labels: set "Copied" to "Copiato" and "Copy link" to "Copia link", and
also complete the other two empty entries mentioned (the keys at the empty lines
around 137 and 178) with appropriate Italian strings; ensure you preserve the
JSON key names exactly, use proper capitalization/punctuation consistent with
existing locale entries, escape any special characters, and run the repo's
i18n/json linter to validate the file.

In `@ghost/i18n/locales/ko/portal.json`:
- Line 33: Fill the empty Korean translations for the new Share modal keys
(e.g., the "Bluesky" key and the other empty share-label keys added for the
Share modal) so the UI isn’t mixed-language; locate the empty entries (the
"Bluesky" key and the other newly added share keys indicated in the review) and
replace each empty string with the proper Korean translation, keeping the JSON
key names intact and ensuring punctuation/quoting stays valid.

In `@ghost/i18n/locales/pt-BR/portal.json`:
- Line 33: Several share-modal keys in pt-BR locale (for example the "Bluesky"
key and other empty share strings in portal.json) are left as empty strings
causing fallback to source text; open ghost/i18n/locales/pt-BR/portal.json,
locate the empty share-related keys (e.g., "Bluesky" and the other empty entries
mentioned) and replace each "" value with the correct Brazilian Portuguese
translation that matches the source intent (preserve punctuation/capitalization
and any placeholders), then save and run a quick smoke check of the portal share
modal to confirm translations appear.

In `@ghost/i18n/locales/ru/portal.json`:
- Line 33: Several new RU locale keys in portal.json are left empty (e.g.,
"Bluesky" plus the other new share-related keys added at the same commits),
which causes English fallbacks; populate each newly added string value with the
correct Russian translation for the corresponding share modal labels/buttons
(find and update the empty keys such as "Bluesky" and the other newly added
empty keys in the same JSON object) so the Russian UI shows translated text
instead of English fallbacks.

In `@ghost/i18n/locales/si/portal.json`:
- Line 33: The new Sinhala locale has empty values for share-label keys (e.g.,
"Bluesky", and the generic labels "Copied", "Copy link", "More options",
"Share") so the UI falls back to English; open ghost/i18n/locales/si/portal.json
and provide Sinhala translations for those keys (and the other empty keys
mentioned at positions corresponding to lines 59-60, 89, 128, 137, 178, 216,
246), ensuring brand names like "Bluesky" remain unchanged (passthrough) while
all generic labels receive proper Sinhala text.

In `@ghost/i18n/locales/th/portal.json`:
- Line 33: Several share modal translation keys in
ghost/i18n/locales/th/portal.json (e.g., "Bluesky" plus the other empty keys at
lines mentioned) are empty; provide Thai translations for each of the new
share-related keys so the UI renders Thai text. Open portal.json and replace the
empty string values for the keys "Bluesky" and the other blank share modal keys
(the entries referenced at lines 59-60, 89, 128, 137, 178, 216, 246) with
appropriate Thai translations that match the English source text, keeping the
JSON key names unchanged and preserving punctuation and any interpolation
placeholders.

In `@ghost/i18n/locales/zh-Hant/portal.json`:
- Around line 59-60: The file has empty Traditional Chinese values for the
share-related keys "Copied" and "Copy link" (and two other empty string keys
later in the file at the noted positions); fill them with proper zh-Hant
translations (e.g., "已複製" for "Copied" and "複製連結" for "Copy link") and likewise
provide appropriate Traditional Chinese strings for the other empty keys found
at the two later positions so all portal share/action labels are fully
localized; update the values for the keys "Copied" and "Copy link" (and the
other empty keys at the indicated locations) in
ghost/i18n/locales/zh-Hant/portal.json.

---

Duplicate comments:
In `@ghost/i18n/locales/hu/portal.json`:
- Around line 59-60: The Hungarian locale file is missing translations for
several user-facing action labels; update the portal.json entries for the keys
"Copied" and "Copy link" (and the other empty action-label keys noted at the
same file positions) by providing appropriate Hungarian strings (e.g., "Másolva"
for "Copied", "Link másolása" for "Copy link") so users see localized UI text
instead of falling back to English; edit the existing keys in portal.json and
ensure the values are properly quoted JSON strings.

In `@ghost/i18n/locales/nn/portal.json`:
- Around line 59-60: The nn locale file has empty values for the share action
keys—fill in Nynorsk translations for the JSON keys "Copied" and "Copy link"
(and the other two empty keys shown at lines 137 and 178) so these user-visible
actions do not fall back to the source locale; update the corresponding string
values in ghost/i18n/locales/nn/portal.json with accurate Nynorsk phrases while
keeping the JSON keys unchanged.

---

Nitpick comments:
In `@ghost/i18n/locales/context.json`:
- Line 33: The context.json entries for new share keys (e.g., "Bluesky" and the
other newly added share keys) are currently empty; add concise translator
metadata for each key in context.json describing where and how the string is
used (e.g., "Label for sharing via Bluesky social network", whether it's a
button/tooltip, and any placeholder/noun/gender/pluralization notes) so
translators know context and constraints; update the entries for all new share
keys (the same set referenced in the review) with short, clear descriptions that
include intended UI location (button/label/menu), any variable placeholders, and
preferred tone/register.

In `@ghost/i18n/locales/el/portal.json`:
- Line 33: Several share-label JSON keys (e.g., "Bluesky", and the other empty
keys noted at positions 59-60, 89, 128, 137, 178, 216, 246) are empty, causing
English fallback; open the portal.json locale object and provide Greek
translations for each empty share-related key (for example fill "Bluesky" with
the Greek equivalent), ensuring every empty string is replaced with an
appropriate Greek label so the Share modal displays fully localized text for the
el locale.

In `@ghost/i18n/locales/hi/portal.json`:
- Line 33: The listed share-string keys in portal.json (e.g., "Bluesky" and the
other empty keys at the mentioned locations) are empty and must be replaced with
Hindi translations; open ghost/i18n/locales/hi/portal.json, locate the keys
"Bluesky" (and the other empty entries referenced) and replace each "" with an
appropriate Hindi translation that matches the share-modal context (short,
UI-friendly labels), preserve JSON string escaping and punctuation, run a
JSON/l10n validation or build to ensure no syntax errors, and optionally add a
comment or note for a native reviewer if unsure about nuance.

In `@ghost/i18n/locales/ro/portal.json`:
- Line 33: Fill in Romanian translations for the new Share modal keys in
portal.json — notably the "Bluesky" key (and the other empty share-modal keys
referenced in the review) by replacing the empty strings with proper Romanian
text, keeping the JSON keys unchanged; ensure you preserve existing
formatting/commas and escape any special characters, validate the JSON after
editing, and run the locale lint/CI to confirm there are no missing translations
or syntax errors.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 349e32cb-cf08-4616-bb37-82b9c84ef450

📥 Commits

Reviewing files that changed from the base of the PR and between 8e3422c and 1a510f5.

📒 Files selected for processing (64)
  • apps/portal/package.json
  • apps/portal/src/components/pages/share-modal.js
  • ghost/i18n/locales/af/portal.json
  • ghost/i18n/locales/ar/portal.json
  • ghost/i18n/locales/bg/portal.json
  • ghost/i18n/locales/bn/portal.json
  • ghost/i18n/locales/bs/portal.json
  • ghost/i18n/locales/ca/portal.json
  • ghost/i18n/locales/context.json
  • ghost/i18n/locales/cs/portal.json
  • ghost/i18n/locales/da/portal.json
  • ghost/i18n/locales/de-CH/portal.json
  • ghost/i18n/locales/de/portal.json
  • ghost/i18n/locales/el/portal.json
  • ghost/i18n/locales/eo/portal.json
  • ghost/i18n/locales/es/portal.json
  • ghost/i18n/locales/et/portal.json
  • ghost/i18n/locales/eu/portal.json
  • ghost/i18n/locales/fa/portal.json
  • ghost/i18n/locales/fi/portal.json
  • ghost/i18n/locales/fr/portal.json
  • ghost/i18n/locales/gd/portal.json
  • ghost/i18n/locales/he/portal.json
  • ghost/i18n/locales/hi/portal.json
  • ghost/i18n/locales/hr/portal.json
  • ghost/i18n/locales/hu/portal.json
  • ghost/i18n/locales/id/portal.json
  • ghost/i18n/locales/is/portal.json
  • ghost/i18n/locales/it/portal.json
  • ghost/i18n/locales/ja/portal.json
  • ghost/i18n/locales/ko/portal.json
  • ghost/i18n/locales/kz/portal.json
  • ghost/i18n/locales/lt/portal.json
  • ghost/i18n/locales/lv/portal.json
  • ghost/i18n/locales/mk/portal.json
  • ghost/i18n/locales/mn/portal.json
  • ghost/i18n/locales/ms/portal.json
  • ghost/i18n/locales/nb/portal.json
  • ghost/i18n/locales/ne/portal.json
  • ghost/i18n/locales/nl/portal.json
  • ghost/i18n/locales/nn/portal.json
  • ghost/i18n/locales/pa/portal.json
  • ghost/i18n/locales/pl/portal.json
  • ghost/i18n/locales/pt-BR/portal.json
  • ghost/i18n/locales/pt/portal.json
  • ghost/i18n/locales/ro/portal.json
  • ghost/i18n/locales/ru/portal.json
  • ghost/i18n/locales/si/portal.json
  • ghost/i18n/locales/sk/portal.json
  • ghost/i18n/locales/sl/portal.json
  • ghost/i18n/locales/sq/portal.json
  • ghost/i18n/locales/sr-Cyrl/portal.json
  • ghost/i18n/locales/sr/portal.json
  • ghost/i18n/locales/sv/portal.json
  • ghost/i18n/locales/sw/portal.json
  • ghost/i18n/locales/ta/portal.json
  • ghost/i18n/locales/th/portal.json
  • ghost/i18n/locales/tr/portal.json
  • ghost/i18n/locales/uk/portal.json
  • ghost/i18n/locales/ur/portal.json
  • ghost/i18n/locales/uz/portal.json
  • ghost/i18n/locales/vi/portal.json
  • ghost/i18n/locales/zh-Hant/portal.json
  • ghost/i18n/locales/zh/portal.json
✅ Files skipped from review due to trivial changes (1)
  • apps/portal/package.json
🚧 Files skipped from review as they are similar to previous changes (24)
  • ghost/i18n/locales/sr/portal.json
  • ghost/i18n/locales/pl/portal.json
  • ghost/i18n/locales/ms/portal.json
  • ghost/i18n/locales/fi/portal.json
  • ghost/i18n/locales/vi/portal.json
  • ghost/i18n/locales/eo/portal.json
  • ghost/i18n/locales/tr/portal.json
  • ghost/i18n/locales/kz/portal.json
  • ghost/i18n/locales/zh/portal.json
  • ghost/i18n/locales/id/portal.json
  • ghost/i18n/locales/mn/portal.json
  • ghost/i18n/locales/ca/portal.json
  • ghost/i18n/locales/nb/portal.json
  • ghost/i18n/locales/mk/portal.json
  • ghost/i18n/locales/ja/portal.json
  • ghost/i18n/locales/ne/portal.json
  • ghost/i18n/locales/sv/portal.json
  • ghost/i18n/locales/uk/portal.json
  • ghost/i18n/locales/bg/portal.json
  • ghost/i18n/locales/pt/portal.json
  • ghost/i18n/locales/sr-Cyrl/portal.json
  • ghost/i18n/locales/lv/portal.json
  • ghost/i18n/locales/nl/portal.json
  • ghost/i18n/locales/hr/portal.json

Comment thread apps/portal/src/components/pages/share-modal.js Outdated
Comment thread apps/portal/src/components/pages/share-modal.js Outdated
Comment thread ghost/i18n/locales/cs/portal.json
Comment thread ghost/i18n/locales/es/portal.json
Comment thread ghost/i18n/locales/fa/portal.json
Comment thread ghost/i18n/locales/pt-BR/portal.json
Comment thread ghost/i18n/locales/ru/portal.json
Comment thread ghost/i18n/locales/si/portal.json
Comment thread ghost/i18n/locales/th/portal.json
Comment thread ghost/i18n/locales/zh-Hant/portal.json
peterzimon added a commit that referenced this pull request Mar 18, 2026
ref #26866

Portal runs in an iframe so share metadata must be read from the host page context.
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
apps/portal/src/components/pages/share-modal.js (1)

401-403: ⚠️ Potential issue | 🟡 Minor

Strip hash from fallback share URL to avoid sharing modal route fragments.

Line 402 still falls back to location.href, which may include #/portal/share when canonical metadata is missing. That leaks UI routing state into shared links.

💡 Proposed fix
 const getShareUrl = () => {
-    return getCanonicalUrl() || getHostWindow().location.href;
+    const canonical = getCanonicalUrl();
+    if (canonical) {
+        return canonical;
+    }
+
+    const {origin, pathname, search} = getHostWindow().location;
+    return `${origin}${pathname}${search}`;
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/portal/src/components/pages/share-modal.js` around lines 401 - 403,
getShareUrl currently returns getCanonicalUrl() or getHostWindow().location.href
which can include hash fragments like "#/portal/share"; update getShareUrl so
that when falling back to getHostWindow().location.href it strips the hash
fragment (i.e. use location.href.split('#')[0] or construct from
getHostWindow().location.origin + pathname + search) and return that cleaned
URL; keep getCanonicalUrl() path unchanged and only modify the fallback branch
in the getShareUrl function.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@apps/portal/src/components/pages/share-modal.js`:
- Around line 401-403: getShareUrl currently returns getCanonicalUrl() or
getHostWindow().location.href which can include hash fragments like
"#/portal/share"; update getShareUrl so that when falling back to
getHostWindow().location.href it strips the hash fragment (i.e. use
location.href.split('#')[0] or construct from getHostWindow().location.origin +
pathname + search) and return that cleaned URL; keep getCanonicalUrl() path
unchanged and only modify the fallback branch in the getShareUrl function.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b325200e-91bb-4588-9b6d-e421d22f4789

📥 Commits

Reviewing files that changed from the base of the PR and between 1a510f5 and c65bc21.

📒 Files selected for processing (1)
  • apps/portal/src/components/pages/share-modal.js

peterzimon added a commit that referenced this pull request Mar 18, 2026
ref #26866

LinkedIn is now a primary action and uses the shareArticle URL to improve preview unfurl reliability.
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
apps/portal/src/components/pages/share-modal.js (1)

401-403: ⚠️ Potential issue | 🟡 Minor

Strip hash fragments from fallback share URL.

When canonical metadata is absent, the fallback can include route fragments (for example #/portal/share) in shared links. Build the fallback from origin + pathname + search instead of full href. This is the root cause; related unit assertions should be updated accordingly.

💡 Proposed fix
 const getShareUrl = () => {
-    return getCanonicalUrl() || getHostWindow().location.href;
+    const canonical = getCanonicalUrl();
+    if (canonical) {
+        return canonical;
+    }
+
+    const {origin, pathname, search} = getHostWindow().location;
+    return `${origin}${pathname}${search}`;
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/portal/src/components/pages/share-modal.js` around lines 401 - 403,
getShareUrl currently falls back to getHostWindow().location.href which can
include hash fragments; change the fallback to build the URL from
getHostWindow().location.origin + getHostWindow().location.pathname +
getHostWindow().location.search to strip any hash. Update the getShareUrl
implementation to use getHostWindow().location (origin/pathname/search) when
getCanonicalUrl() is falsy, and adjust related unit tests that asserted the old
href behavior to expect the hash-free URL instead.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@apps/portal/src/components/pages/share-modal.js`:
- Around line 401-403: getShareUrl currently falls back to
getHostWindow().location.href which can include hash fragments; change the
fallback to build the URL from getHostWindow().location.origin +
getHostWindow().location.pathname + getHostWindow().location.search to strip any
hash. Update the getShareUrl implementation to use getHostWindow().location
(origin/pathname/search) when getCanonicalUrl() is falsy, and adjust related
unit tests that asserted the old href behavior to expect the hash-free URL
instead.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 89f623d7-1e85-4028-8619-73676f18bb88

📥 Commits

Reviewing files that changed from the base of the PR and between c65bc21 and 1e6fcac.

📒 Files selected for processing (2)
  • apps/portal/src/components/pages/share-modal.js
  • apps/portal/test/unit/components/pages/share-modal.test.js

peterzimon added a commit that referenced this pull request Mar 19, 2026
ref #26866

This switches share routing to #/share and keeps the old hash path disabled for the requested breaking change.
@peterzimon peterzimon force-pushed the FEA-480/portal-native-share branch from 658bbdc to 9c8ebe8 Compare March 19, 2026 13:36
peterzimon added a commit that referenced this pull request Mar 19, 2026
ref #26866

Bumped @tryghost/portal version, aligned share action order with spec, and regenerated portal locale keys required by i18n checks.
peterzimon added a commit that referenced this pull request Mar 19, 2026
ref #26866

Portal runs in an iframe so share metadata must be read from the host page context.
peterzimon added a commit that referenced this pull request Mar 19, 2026
ref #26866

LinkedIn is now a primary action and uses the shareArticle URL to improve preview unfurl reliability.
peterzimon added a commit that referenced this pull request Mar 19, 2026
ref #26866

This switches share routing to #/share and keeps the old hash path disabled for the requested breaking change.
@peterzimon peterzimon force-pushed the FEA-480/portal-native-share branch from a7b24b9 to 24e684e Compare March 19, 2026 15:32
troyciesco pushed a commit that referenced this pull request Mar 26, 2026
ref #26866

Bumped @tryghost/portal version, aligned share action order with spec, and regenerated portal locale keys required by i18n checks.
troyciesco pushed a commit that referenced this pull request Mar 26, 2026
ref #26866

Portal runs in an iframe so share metadata must be read from the host page context.
troyciesco pushed a commit that referenced this pull request Mar 26, 2026
ref #26866

LinkedIn is now a primary action and uses the shareArticle URL to improve preview unfurl reliability.
troyciesco pushed a commit that referenced this pull request Mar 26, 2026
ref #26866

This switches share routing to #/share and keeps the old hash path disabled for the requested breaking change.
@troyciesco troyciesco force-pushed the FEA-480/portal-native-share branch from 8803292 to 936c768 Compare March 26, 2026 18:02
troyciesco pushed a commit that referenced this pull request Mar 30, 2026
ref #26866

Bumped @tryghost/portal version, aligned share action order with spec, and regenerated portal locale keys required by i18n checks.
troyciesco pushed a commit that referenced this pull request Mar 30, 2026
ref #26866

Portal runs in an iframe so share metadata must be read from the host page context.
troyciesco pushed a commit that referenced this pull request Mar 30, 2026
ref #26866

LinkedIn is now a primary action and uses the shareArticle URL to improve preview unfurl reliability.
troyciesco pushed a commit that referenced this pull request Mar 30, 2026
ref #26866

This switches share routing to #/share and keeps the old hash path disabled for the requested breaking change.
@troyciesco troyciesco force-pushed the FEA-480/portal-native-share branch from 32f34ea to d5ae90f Compare March 30, 2026 00:06
Copy link
Copy Markdown
Member

@cathysarisky cathysarisky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Friendly reminder to please update context.json when you add new strings. Thanks!!

troyciesco pushed a commit that referenced this pull request Apr 6, 2026
ref #26866

Bumped @tryghost/portal version, aligned share action order with spec, and regenerated portal locale keys required by i18n checks.
troyciesco pushed a commit that referenced this pull request Apr 6, 2026
ref #26866

Portal runs in an iframe so share metadata must be read from the host page context.
troyciesco pushed a commit that referenced this pull request Apr 6, 2026
ref #26866

LinkedIn is now a primary action and uses the shareArticle URL to improve preview unfurl reliability.
peterzimon and others added 23 commits April 8, 2026 04:55
ref https://linear.app/ghost/issue/FEA-480

Simplified share metadata to DOM-only and refined modal actions/footer UX
ref https://github.com/TryGhost/Team/issues/FEA-480

Improved share UX with overflow menu, upward animation, excerpt clamp, and corrected mailto encoding.
ref #26866

Bumped @tryghost/portal version, aligned share action order with spec, and regenerated portal locale keys required by i18n checks.
ref #26866

Portal runs in an iframe so share metadata must be read from the host page context.
ref #26866

LinkedIn is now a primary action and uses the shareArticle URL to improve preview unfurl reliability.
ref #26866

This switches share routing to #/share and keeps the old hash path disabled for the requested breaking change.
Refactors a bit of the share modal setup:
- moves into 3 separate files for component, styles, hook
- gathers all the data in one function and simplifies the logic a bit
Changelog for v2.67.1 -> 2.68.0:
  - Updated i18n translations
@troyciesco troyciesco force-pushed the FEA-480/portal-native-share branch from f9d7e57 to e5e8375 Compare April 8, 2026 09:03
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud bot commented Apr 8, 2026

@troyciesco troyciesco changed the title Native Share Buttons – Portal Modal ✨ Added ability to put share buttons on posts Apr 8, 2026
@troyciesco troyciesco changed the title ✨ Added ability to put share buttons on posts ✨ Added ability to put a share button on posts Apr 8, 2026
@troyciesco troyciesco merged commit 0919c1d into main Apr 8, 2026
39 checks passed
@troyciesco troyciesco deleted the FEA-480/portal-native-share branch April 8, 2026 09:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants