diff --git a/packages/cli-kit/src/public/node/themes/utils.ts b/packages/cli-kit/src/public/node/themes/utils.ts index bee6ad98ed8..dfd6ba3dc14 100644 --- a/packages/cli-kit/src/public/node/themes/utils.ts +++ b/packages/cli-kit/src/public/node/themes/utils.ts @@ -1,6 +1,7 @@ import {Theme} from './types.js' import {renderTextPrompt} from '../ui.js' import {getRandomName} from '../../common/string.js' +import {platform} from 'os' const GID_REGEXP = /gid:\/\/shopify\/\w*\/(\d+)/ @@ -33,3 +34,13 @@ export function parseGid(gid: string): number { } throw new Error(`Invalid GID: ${gid}`) } + +export function filePathToFileUrl(filePath: string): string { + let normalized = filePath.replace(/\\/g, '/') + + if (platform() === 'win32') { + normalized = `/${normalized}` + } + + return encodeURI(`file://${normalized}`) +} diff --git a/packages/theme/src/cli/services/profile.ts b/packages/theme/src/cli/services/profile.ts index a94cc279a4c..405b5cd3ebe 100644 --- a/packages/theme/src/cli/services/profile.ts +++ b/packages/theme/src/cli/services/profile.ts @@ -8,6 +8,7 @@ import {joinPath} from '@shopify/cli-kit/node/path' import {AdminSession} from '@shopify/cli-kit/node/session' import {writeFile, tempDirectory} from '@shopify/cli-kit/node/fs' import {outputResult, outputDebug} from '@shopify/cli-kit/node/output' +import {filePathToFileUrl} from '@shopify/cli-kit/node/themes/utils' export async function profile( adminSession: AdminSession, @@ -49,8 +50,9 @@ export async function profile( async function openProfile(profileJson: string) { // Adapted from https://github.com/jlfwong/speedscope/blob/146477a8508a6d2da697cb0ea0a426ba81b3e8dc/bin/cli.js#L63 - let urlToOpen = await resolveAssetPath('speedscope', 'index.html') - outputDebug(`[Theme Profile] Resolved URL to open: ${urlToOpen}`) + const speedscopeIndexPath = await resolveAssetPath('speedscope', 'index.html') + const speedscopeIndexUrl = filePathToFileUrl(speedscopeIndexPath) + outputDebug(`[Theme Profile] Resolved URL to open: ${speedscopeIndexUrl}`) const filename = 'liquid-profile' const sourceBase64 = Buffer.from(profileJson).toString('base64') @@ -61,18 +63,18 @@ async function openProfile(profileJson: string) { outputDebug(`[Theme Profile] writing JS file to: ${jsPath}`) await writeFile(jsPath, jsSource) outputDebug(`[Theme Profile] JS file created successfully: ${jsPath}`) - urlToOpen += `#localProfilePath=${jsPath}` + const redirectUrl = `${speedscopeIndexUrl}#localProfilePath=${jsPath}` // For some silly reason, the OS X open command ignores any query parameters or hash parameters // passed as part of the URL. To get around this weird issue, we'll create a local HTML file // that just redirects. const htmlPath = joinPath(tempDirectory(), `${filePrefix}.html`) outputDebug(`[Theme Profile] writing HTML file to: ${htmlPath}`) - await writeFile(htmlPath, ``) + await writeFile(htmlPath, ``) outputDebug(`[Theme Profile] HTML file created successfully: ${htmlPath}`) - urlToOpen = `file://${htmlPath}` - outputDebug(`[Theme Profile] Opening URL: ${urlToOpen}`) - const opened = await openURL(urlToOpen) + const htmlUrl = filePathToFileUrl(htmlPath) + outputDebug(`[Theme Profile] Opening URL: ${htmlUrl}`) + const opened = await openURL(htmlUrl) outputDebug(`[Theme Profile] URL opened successfully: ${opened}`) }