diff --git a/.changeset/fix-footnote-long-url-wrapping.md b/.changeset/fix-footnote-long-url-wrapping.md
new file mode 100644
index 00000000000..be56cf2eaeb
--- /dev/null
+++ b/.changeset/fix-footnote-long-url-wrapping.md
@@ -0,0 +1,5 @@
+---
+'@shopify/cli-kit': patch
+---
+
+Render banner/alert footnote URLs on a single contiguous line so long links are no longer broken by hard newlines and remain copy-pasteable when terminal hyperlinks are unsupported
diff --git a/packages/cli-kit/src/private/node/ui/components/Alert.test.tsx b/packages/cli-kit/src/private/node/ui/components/Alert.test.tsx
index d956487745a..56ea8c2ef3e 100644
--- a/packages/cli-kit/src/private/node/ui/components/Alert.test.tsx
+++ b/packages/cli-kit/src/private/node/ui/components/Alert.test.tsx
@@ -165,14 +165,14 @@ describe('Alert', async () => {
})
// The footnote block (rendered after the closing `╰`) must list the
- // URL. Ink wraps the long URL onto its own line when it exceeds terminal
- // width, so we assert the `[1]` anchor and the URL show up *outside* the
- // bordered box rather than as a single contiguous `[1] URL` substring.
+ // URL as a single contiguous `[1] URL` line. The footnote Box is sized to
+ // the line length so Ink never hard-wraps the URL (which would insert
+ // newline characters and break copy-paste/clickability); the terminal
+ // soft-wraps the overflow at display time instead.
const closingBorderIndex = frame.indexOf('╰')
expect(closingBorderIndex).toBeGreaterThanOrEqual(0)
const afterBox = frame.slice(closingBorderIndex)
- expect(afterBox).toContain('[1]')
- expect(afterBox).toContain(longUrl)
+ expect(afterBox).toContain(`[1] ${longUrl}`)
// And the body must reference the footnote.
expect(frame).toContain('docs [1]')
})
diff --git a/packages/cli-kit/src/private/node/ui/components/Banner.tsx b/packages/cli-kit/src/private/node/ui/components/Banner.tsx
index 948306f9648..8411a5538ef 100644
--- a/packages/cli-kit/src/private/node/ui/components/Banner.tsx
+++ b/packages/cli-kit/src/private/node/ui/components/Banner.tsx
@@ -32,9 +32,18 @@ const Footnotes = () => {
return linkIds.length > 0 ? (
- {linkIds.map((id) => (
- {`[${id}] ${links[id]?.url}`}
- ))}
+ {linkIds.map((id) => {
+ const line = `[${id}] ${links[id]?.url}`
+ // Render each footnote on a Box wide enough to fit the whole line so
+ // Ink doesn't hard-wrap long URLs (which inserts newline characters and
+ // breaks copy-paste/clickability). The terminal soft-wraps the overflow
+ // at display time without mutating the underlying text.
+ return (
+
+ {line}
+
+ )
+ })}
) : null
}
diff --git a/packages/cli-kit/src/public/node/plugins/multiple-installation-warning.test.ts b/packages/cli-kit/src/public/node/plugins/multiple-installation-warning.test.ts
index dddda0afc4a..b5170d2085e 100644
--- a/packages/cli-kit/src/public/node/plugins/multiple-installation-warning.test.ts
+++ b/packages/cli-kit/src/public/node/plugins/multiple-installation-warning.test.ts
@@ -26,23 +26,22 @@ describe('showMultipleCLIWarningIfNeeded', () => {
// Then
expect(mockOutput.info()).toMatchInlineSnapshot(`
- "╭─ info ───────────────────────────────────────────────────────────────────────╮
- │ │
- │ Two Shopify CLI installations found – using global installation │
- │ │
- │ A global installation (v${CLI_KIT_VERSION}) and a local dependency (v3.70.0) were │
- │ detected. │
- │ We recommend removing the @shopify/cli and @shopify/app dependencies from │
- │ your package.json, unless you want to use different versions across │
- │ multiple apps. │
- │ │
- │ See Shopify CLI documentation. [1] │
- │ │
- ╰──────────────────────────────────────────────────────────────────────────────╯
- [1] https://shopify.dev/docs/apps/build/cli-for-apps#switch-to-a-global-executab
- le-or-local-dependency
- "
- `)
+ "╭─ info ───────────────────────────────────────────────────────────────────────╮
+ │ │
+ │ Two Shopify CLI installations found – using global installation │
+ │ │
+ │ A global installation (v${CLI_KIT_VERSION}) and a local dependency (v3.70.0) were │
+ │ detected. │
+ │ We recommend removing the @shopify/cli and @shopify/app dependencies from │
+ │ your package.json, unless you want to use different versions across │
+ │ multiple apps. │
+ │ │
+ │ See Shopify CLI documentation. [1] │
+ │ │
+ ╰──────────────────────────────────────────────────────────────────────────────╯
+ [1] https://shopify.dev/docs/apps/build/cli-for-apps#switch-to-a-global-executable-or-local-dependency
+ "
+ `)
mockOutput.clear()
})
@@ -58,23 +57,22 @@ describe('showMultipleCLIWarningIfNeeded', () => {
// Then
expect(mockOutput.info()).toMatchInlineSnapshot(`
- "╭─ info ───────────────────────────────────────────────────────────────────────╮
- │ │
- │ Two Shopify CLI installations found – using local dependency │
- │ │
- │ A global installation (v3.70.0) and a local dependency (v${CLI_KIT_VERSION}) were │
- │ detected. │
- │ We recommend removing the @shopify/cli and @shopify/app dependencies from │
- │ your package.json, unless you want to use different versions across │
- │ multiple apps. │
- │ │
- │ See Shopify CLI documentation. [1] │
- │ │
- ╰──────────────────────────────────────────────────────────────────────────────╯
- [1] https://shopify.dev/docs/apps/build/cli-for-apps#switch-to-a-global-executab
- le-or-local-dependency
- "
- `)
+ "╭─ info ───────────────────────────────────────────────────────────────────────╮
+ │ │
+ │ Two Shopify CLI installations found – using local dependency │
+ │ │
+ │ A global installation (v3.70.0) and a local dependency (v${CLI_KIT_VERSION}) were │
+ │ detected. │
+ │ We recommend removing the @shopify/cli and @shopify/app dependencies from │
+ │ your package.json, unless you want to use different versions across │
+ │ multiple apps. │
+ │ │
+ │ See Shopify CLI documentation. [1] │
+ │ │
+ ╰──────────────────────────────────────────────────────────────────────────────╯
+ [1] https://shopify.dev/docs/apps/build/cli-for-apps#switch-to-a-global-executable-or-local-dependency
+ "
+ `)
mockOutput.clear()
})
@@ -91,23 +89,22 @@ describe('showMultipleCLIWarningIfNeeded', () => {
// Then
expect(mockOutput.info()).toMatchInlineSnapshot(`
- "╭─ info ───────────────────────────────────────────────────────────────────────╮
- │ │
- │ Two Shopify CLI installations found – using global installation │
- │ │
- │ A global installation (v${CLI_KIT_VERSION}) and a local dependency (v3.70.0) were │
- │ detected. │
- │ We recommend removing the @shopify/cli and @shopify/app dependencies from │
- │ your package.json, unless you want to use different versions across │
- │ multiple apps. │
- │ │
- │ See Shopify CLI documentation. [1] │
- │ │
- ╰──────────────────────────────────────────────────────────────────────────────╯
- [1] https://shopify.dev/docs/apps/build/cli-for-apps#switch-to-a-global-executab
- le-or-local-dependency
- "
- `)
+ "╭─ info ───────────────────────────────────────────────────────────────────────╮
+ │ │
+ │ Two Shopify CLI installations found – using global installation │
+ │ │
+ │ A global installation (v${CLI_KIT_VERSION}) and a local dependency (v3.70.0) were │
+ │ detected. │
+ │ We recommend removing the @shopify/cli and @shopify/app dependencies from │
+ │ your package.json, unless you want to use different versions across │
+ │ multiple apps. │
+ │ │
+ │ See Shopify CLI documentation. [1] │
+ │ │
+ ╰──────────────────────────────────────────────────────────────────────────────╯
+ [1] https://shopify.dev/docs/apps/build/cli-for-apps#switch-to-a-global-executable-or-local-dependency
+ "
+ `)
})
test('does not show a warning if there is no local dependency', async () => {
diff --git a/packages/cli-kit/src/public/node/ui.tsx b/packages/cli-kit/src/public/node/ui.tsx
index 4147ee6247d..28e4a1863da 100644
--- a/packages/cli-kit/src/public/node/ui.tsx
+++ b/packages/cli-kit/src/public/node/ui.tsx
@@ -100,10 +100,7 @@ export type RenderAlertOptions = Omit
* │ │
* ╰──────────────────────────────────────────────────────────╯
* [1] https://shopify.dev
- * [2] https://www.google.com/search?q=jh56t9l34kpo35tw8s28hn7s
- * 9s2xvzla01d8cn6j7yq&rlz=1C1GCEU_enUS832US832&oq=jh56t9l34kpo
- * 35tw8s28hn7s9s2xvzla01d8cn6j7yq&aqs=chrome.0.35i39l2j0l4j46j
- * 69i60.2711j0j7&sourceid=chrome&ie=UTF-8
+ * [2] https://www.google.com/search?q=jh56t9l34kpo35tw8s28hn7s9s2xvzla01d8cn6j7yq&rlz=1C1GCEU_enUS832US832&oq=jh56t9l34kpo35tw8s28hn7s9s2xvzla01d8cn6j7yq&aqs=chrome.0.35i39l2j0l4j46j69i60.2711j0j7&sourceid=chrome&ie=UTF-8
* [3] https://shopify.com
*
*/
@@ -134,8 +131,7 @@ export function renderInfo(options: RenderAlertOptions) {
* │ • See your deployment and set it live [1] │
* │ │
* ╰──────────────────────────────────────────────────────────╯
- * [1] https://partners.shopify.com/1797046/apps/4523695/deploy
- * ments
+ * [1] https://partners.shopify.com/1797046/apps/4523695/deployments
*
*/
export function renderSuccess(options: RenderAlertOptions) {