diff --git a/.changeset/metal-lemons-reflect.md b/.changeset/metal-lemons-reflect.md new file mode 100644 index 00000000000..c79244d4c33 --- /dev/null +++ b/.changeset/metal-lemons-reflect.md @@ -0,0 +1,10 @@ +--- +'@shopify/theme': patch +--- + +Editor shortcut (e) will now navigate to your most recently viewed template + +Hitting `e` while your server is running (`shopify theme dev`) will now open +the theme editor in the Admin to the most recently rendered template that you +viewed in the browser (e.g. if you have multiple tabs open it will use the +one that was rendered most recently). diff --git a/packages/theme/src/cli/services/dev.ts b/packages/theme/src/cli/services/dev.ts index a4499de7891..89742bf6932 100644 --- a/packages/theme/src/cli/services/dev.ts +++ b/packages/theme/src/cli/services/dev.ts @@ -83,6 +83,7 @@ export async function dev(options: DevOptions) { localThemeExtensionFileSystem, directory: options.directory, type: 'theme', + lastRequestedPath: '', options: { themeEditorSync: options['theme-editor-sync'], host, @@ -132,7 +133,12 @@ export async function dev(options: DevOptions) { openURLSafely(urls.preview, 'theme preview') break case 'e': - openURLSafely(urls.themeEditor, 'theme editor') + openURLSafely( + ctx.lastRequestedPath === '/' + ? urls.themeEditor + : `${urls.themeEditor}&previewPath=${encodeURIComponent(ctx.lastRequestedPath)}`, + 'theme editor', + ) break case 'g': openURLSafely(urls.giftCard, 'gift card preview') diff --git a/packages/theme/src/cli/utilities/theme-environment/hot-reload/server.test.ts b/packages/theme/src/cli/utilities/theme-environment/hot-reload/server.test.ts index ef9c833bf9d..441e46408d6 100644 --- a/packages/theme/src/cli/utilities/theme-environment/hot-reload/server.test.ts +++ b/packages/theme/src/cli/utilities/theme-environment/hot-reload/server.test.ts @@ -542,6 +542,7 @@ function createTestContext(options?: {files?: [string, string][]}) { storeFqdn: 'my-store.myshopify.com', sessionCookies: {}, }, + lastRequestedPath: '', localThemeFileSystem, localThemeExtensionFileSystem, directory: 'tmp', diff --git a/packages/theme/src/cli/utilities/theme-environment/html.test.ts b/packages/theme/src/cli/utilities/theme-environment/html.test.ts index 0d87b712b08..fdfedf958c4 100644 --- a/packages/theme/src/cli/utilities/theme-environment/html.test.ts +++ b/packages/theme/src/cli/utilities/theme-environment/html.test.ts @@ -35,8 +35,30 @@ describe('getHtmlHandler', async () => { options: {}, localThemeExtensionFileSystem: emptyThemeExtFileSystem(), localThemeFileSystem: emptyThemeFileSystem(), + lastRequestedPath: '', } as unknown as DevServerContext + test('sets lastRequestedPath to the rendering URL', async () => { + const handler = getHtmlHandler(theme, ctx) + + expect(ctx.lastRequestedPath).toStrictEqual('') + + const event = createH3Event('GET', '/search?q=foo&options%5Bprefix%5D=last') + + vi.mocked(render).mockResolvedValueOnce( + new Response('', { + status: 200, + headers: { + 'x-request-id': 'test-request-id', + }, + }), + ) + + await handler(event) + + expect(ctx.lastRequestedPath).toStrictEqual('/search?q=foo&options%5Bprefix%5D=last') + }) + test('the development server session recovers when a theme id mismatch occurs', async () => { // Given const handler = getHtmlHandler(theme, ctx) diff --git a/packages/theme/src/cli/utilities/theme-environment/html.ts b/packages/theme/src/cli/utilities/theme-environment/html.ts index 6a543b25b14..7ad05a9a105 100644 --- a/packages/theme/src/cli/utilities/theme-environment/html.ts +++ b/packages/theme/src/cli/utilities/theme-environment/html.ts @@ -23,6 +23,8 @@ export function getHtmlHandler(theme: Theme, ctx: DevServerContext): EventHandle return defineEventHandler((event) => { const [browserPathname = '/', browserSearch = ''] = event.path.split('?') + ctx.lastRequestedPath = event.path + const shouldRenderUploadErrorPage = ctx.options.errorOverlay !== 'silent' && ctx.localThemeFileSystem.uploadErrors.size > 0 diff --git a/packages/theme/src/cli/utilities/theme-environment/theme-environment.test.ts b/packages/theme/src/cli/utilities/theme-environment/theme-environment.test.ts index 85504eb45ae..9cc63555baf 100644 --- a/packages/theme/src/cli/utilities/theme-environment/theme-environment.test.ts +++ b/packages/theme/src/cli/utilities/theme-environment/theme-environment.test.ts @@ -86,6 +86,7 @@ describe('setupDevServer', () => { storeFqdn: 'my-store.myshopify.com', sessionCookies: {}, }, + lastRequestedPath: '', localThemeFileSystem, localThemeExtensionFileSystem, directory: 'tmp', diff --git a/packages/theme/src/cli/utilities/theme-environment/types.ts b/packages/theme/src/cli/utilities/theme-environment/types.ts index 4ca51835def..39d4bdee5e1 100644 --- a/packages/theme/src/cli/utilities/theme-environment/types.ts +++ b/packages/theme/src/cli/utilities/theme-environment/types.ts @@ -85,6 +85,11 @@ export interface DevServerContext { */ type: 'theme' | 'theme-extension' + /** + * Tracks the last requested HTML path for keyboard shortcuts. + */ + lastRequestedPath: string + /** * Additional options for the development server. */ diff --git a/packages/theme/src/cli/utilities/theme-ext-environment/theme-ext-server.ts b/packages/theme/src/cli/utilities/theme-ext-environment/theme-ext-server.ts index e1d018ce7d8..5ed6a0d420f 100644 --- a/packages/theme/src/cli/utilities/theme-ext-environment/theme-ext-server.ts +++ b/packages/theme/src/cli/utilities/theme-ext-environment/theme-ext-server.ts @@ -81,6 +81,7 @@ async function contextDevServerContext( localThemeExtensionFileSystem, directory, type: 'theme-extension', + lastRequestedPath: '', options: { themeEditorSync: false, noDelete: false,