Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: windows compatibility #1996

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 53 additions & 51 deletions packages/cli/src/api/catalog/getCatalogDependentFiles.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { FormatterWrapper } from "../formats"
import mockFs from "mock-fs"
import * as process from "process"
import os from "os"
const skipOnWindows = os.platform() === "win32" ? it.skip : it
import path from "node:path"

describe("getCatalogDependentFiles", () => {
let format: FormatterWrapper
Expand Down Expand Up @@ -156,58 +156,60 @@ describe("getCatalogDependentFiles", () => {
})

// https://github.com/lingui/js-lingui/issues/1705
skipOnWindows(
"Should return absolute path when relative catalog path is specified",
async () => {
const oldCwd = process.cwd()

process.chdir("/")

mockFs({
"/src/locales": {
// "messages.pot": "bla",
"en.po": "bla",
"pl.po": "bla",
"es.po": "bla",
"pt-PT.po": "bla",
"pt-BR.po": "bla",
},
})

const config = makeConfig(
{
locales: ["en", "pl", "es", "pt-PT", "pt-BR"],
sourceLocale: "en",
fallbackLocales: {
"pt-PT": "pt-BR",
default: "en",
},
},
{ skipValidation: true }
)

const catalog = new Catalog(
{
name: null,
path: "./src/locales/{locale}",
include: ["src/"],
exclude: [],
format,
},
config
)
it("Should return absolute path when relative catalog path is specified", async () => {
const oldCwd = process.cwd()

const actual = await getCatalogDependentFiles(catalog, "pt-PT")
mockFs.restore()
process.chdir("/")

expect(actual).toMatchInlineSnapshot(`
[
/src/locales/pt-BR.po,
/src/locales/en.po,
]
`)
mockFs({
"/src/locales": {
// "messages.pot": "bla",
"en.po": "bla",
"pl.po": "bla",
"es.po": "bla",
"pt-PT.po": "bla",
"pt-BR.po": "bla",
},
})

process.chdir(oldCwd)
const config = makeConfig(
{
locales: ["en", "pl", "es", "pt-PT", "pt-BR"],
sourceLocale: "en",
fallbackLocales: {
"pt-PT": "pt-BR",
default: "en",
},
},
{ skipValidation: true }
)

const catalog = new Catalog(
{
name: null,
path: "./src/locales/{locale}",
include: ["src/"],
exclude: [],
format,
},
config
)

const actual = await getCatalogDependentFiles(catalog, "pt-PT")
mockFs.restore()
process.chdir(oldCwd)

if (os.platform() === "win32") {
const root = path.parse(oldCwd).root
expect(actual).toStrictEqual([
`${root}src\\locales\\pt-BR.po`,
`${root}src\\locales\\en.po`,
])
} else {
expect(actual).toStrictEqual([
"/src/locales/pt-BR.po",
"/src/locales/en.po",
])
}
)
})
})
30 changes: 21 additions & 9 deletions packages/cli/src/api/catalog/getCatalogs.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,15 +102,17 @@ describe("getCatalogs", () => {
],
})

const catalogs = await getCatalogs(config)
const catalogs = (await getCatalogs(config)).sort((a, b) =>
a.path.localeCompare(b.path)
)

expect([cleanCatalog(catalogs[0]), cleanCatalog(catalogs[1])]).toEqual([
cleanCatalog(
new Catalog(
{
name: "componentB",
path: "componentB/locales/{locale}",
include: ["componentB/"],
name: "componentA",
path: "componentA/locales/{locale}",
include: ["componentA/"],
exclude: [],
format,
},
Expand All @@ -120,9 +122,9 @@ describe("getCatalogs", () => {
cleanCatalog(
new Catalog(
{
name: "componentA",
path: "componentA/locales/{locale}",
include: ["componentA/"],
name: "componentB",
path: "componentB/locales/{locale}",
include: ["componentB/"],
exclude: [],
format,
},
Expand All @@ -147,7 +149,12 @@ describe("getCatalogs", () => {
},
],
})
expect(cleanCatalog((await getCatalogs(config))[0])).toEqual(

const catalogs = (await getCatalogs(config)).sort((a, b) =>
a.path.localeCompare(b.path)
)

expect(cleanCatalog(catalogs[0])).toEqual(
cleanCatalog(
new Catalog(
{
Expand Down Expand Up @@ -182,7 +189,12 @@ describe("getCatalogs", () => {
},
],
})
expect(cleanCatalog((await getCatalogs(config))[0])).toEqual(

const catalogs = (await getCatalogs(config)).sort((a, b) =>
a.path.localeCompare(b.path)
)

expect(cleanCatalog(catalogs[0])).toEqual(
cleanCatalog(
new Catalog(
{
Expand Down
7 changes: 4 additions & 3 deletions packages/cli/src/api/extractors/babel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,10 @@ async function createSourceMapper(code: string, sourceMaps?: any) {
} else if (code.search(inlineSourceMapsRE) != -1) {
const { SourceMapConsumer } = await import("source-map")
const { fromSource } = await import("convert-source-map")
sourceMapsConsumer = await new SourceMapConsumer(
fromSource(code).toObject()
)

const t = fromSource(code).toObject()

sourceMapsConsumer = await new SourceMapConsumer(t)
}

return {
Expand Down
17 changes: 5 additions & 12 deletions packages/cli/src/api/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import fs from "fs"
import path from "path"
import normalize from "normalize-path"
import normalizePath from "normalize-path"

export const PATHSEP = "/" // force posix everywhere

Expand Down Expand Up @@ -88,13 +88,6 @@ export function makeInstall(packageName: string, dev: boolean = false) {
: `npm install ${dev ? "--save-dev" : "--save"} ${packageName}`
}

/**
* Normalize Windows backslashes in path so they look always as posix
*/
export function normalizeSlashes(path: string) {
return path.replace("\\", "/")
}

/**
* Remove ./ at the beginning: ./relative => relative
* relative => relative
Expand All @@ -104,14 +97,14 @@ export function normalizeSlashes(path: string) {
export function normalizeRelativePath(sourcePath: string): string {
if (path.isAbsolute(sourcePath)) {
// absolute path
return normalize(sourcePath, false)
return normalizePath(sourcePath, false)
}

// https://github.com/lingui/js-lingui/issues/809
const isDir = isDirectory(sourcePath)

return normalizeSlashes(
normalize(path.relative(process.cwd(), sourcePath), false) +
(isDir ? "/" : "")
return (
normalizePath(path.relative(process.cwd(), sourcePath), false) +
(isDir ? "/" : "")
)
}
1 change: 0 additions & 1 deletion packages/cli/src/extract-experimental/bundleSource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ export async function bundleSource(
sourceRoot: outDir,
sourcesContent: false,
packages: "external",
outbase: rootDir,
metafile: true,

plugins: [
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
import { resolveTemplatePath } from "./resolveTemplatePath"
import os from "os"
import normalizePath from "normalize-path"

const skipOnWindows = os.platform().startsWith("win") ? describe.skip : describe

skipOnWindows("resolveTemplateName", () => {
describe("resolveTemplateName", () => {
const rootDir = "/Users/lingui-app"

test("Should use `messages` suffix when {entryName} defined in output", () => {
const entrypoint = `${rootDir}/pages/about/index.ts`
const output = `${rootDir}/locales/{entryDir}/{entryName}.{locale}`

const actual = resolveTemplatePath(entrypoint, output, rootDir, ".pot")
expect(actual).toMatchInlineSnapshot(
expect(normalizePath(actual)).toMatchInlineSnapshot(
`/Users/lingui-app/locales/pages/about/index.messages.pot`
)
})
Expand All @@ -21,7 +19,7 @@ skipOnWindows("resolveTemplateName", () => {
const output = `${rootDir}/locales/{entryDir}/{locale}`

const actual = resolveTemplatePath(entrypoint, output, rootDir, ".json")
expect(actual).toMatchInlineSnapshot(
expect(normalizePath(actual)).toMatchInlineSnapshot(
`/Users/lingui-app/locales/pages/about/index.json`
)
})
Expand All @@ -31,7 +29,7 @@ skipOnWindows("resolveTemplateName", () => {
const output = `${rootDir}/{entryDir}/locales/{locale}`

const actual = resolveTemplatePath(entrypoint, output, rootDir, ".pot")
expect(actual).toMatchInlineSnapshot(
expect(normalizePath(actual)).toMatchInlineSnapshot(
`/Users/lingui-app/pages/trip/day/locales/[day].page.pot`
)
})
Expand Down
7 changes: 4 additions & 3 deletions packages/cli/src/lingui-compile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
import { getCatalogs, getFormat } from "./api"
import { TranslationMissingEvent } from "./api/catalog/getTranslationsForCatalog"
import { getCatalogForMerge } from "./api/catalog/getCatalogs"
import { normalizeSlashes } from "./api/utils"
import normalizePath from "normalize-path"

import nodepath from "path"

export type CliCompileOptions = {
Expand Down Expand Up @@ -89,7 +90,7 @@
namespace
)

compiledPath = normalizeSlashes(
compiledPath = normalizePath(
nodepath.relative(config.rootDir, compiledPath)
)

Expand All @@ -113,7 +114,7 @@
namespace
)

compiledPath = normalizeSlashes(
compiledPath = normalizePath(

Check warning on line 117 in packages/cli/src/lingui-compile.ts

View check run for this annotation

Codecov / codecov/patch

packages/cli/src/lingui-compile.ts#L117

Added line #L117 was not covered by tests
nodepath.relative(config.rootDir, compiledPath)
)

Expand Down
20 changes: 12 additions & 8 deletions packages/cli/src/lingui-extract-experimental.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import { program } from "commander"

import { getConfig, LinguiConfigNormalized } from "@lingui/conf"
import nodepath from "path"
import os from "os"
import { getFormat } from "./api/formats"
import fs from "fs/promises"
import { extractFromFiles } from "./api/catalog/extractFromFiles"
import { normalizeSlashes } from "./api/utils"
import normalizePath from "normalize-path"

import { bundleSource } from "./extract-experimental/bundleSource"
import {
writeCatalogs,
Expand Down Expand Up @@ -53,9 +53,15 @@ export default async function command(
)
)

const tempDir = await fs.mkdtemp(
nodepath.join(os.tmpdir(), "js-lingui-extract-")
)
// unfortunately we can't use os.tmpdir() in this case
// on windows it might create a folder on a different disk then source code is stored
// (tmpdir would be always on C: but code could be stored on D:)
// and then relative path in sourcemaps produced by esbuild will be broken.
// sourcemaps itself doesn't allow to have absolute windows path, because they are not URL compatible.
// that's why we store esbuild bundles in .lingui folder
const tmpPrefix = ".lingui/"
await fs.mkdir(tmpPrefix, { recursive: true })
const tempDir = await fs.mkdtemp(tmpPrefix)
await fs.rm(tempDir, { recursive: true, force: true })

const bundleResult = await bundleSource(
Expand Down Expand Up @@ -136,9 +142,7 @@ export default async function command(
}

stats.push({
entry: normalizeSlashes(
nodepath.relative(linguiConfig.rootDir, entryPoint)
),
entry: normalizePath(nodepath.relative(linguiConfig.rootDir, entryPoint)),
content: output,
})
}
Expand Down
6 changes: 2 additions & 4 deletions packages/cli/src/lingui-extract-template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { getConfig, LinguiConfigNormalized } from "@lingui/conf"

import { getCatalogs } from "./api"
import nodepath from "path"
import { normalizeSlashes } from "./api/utils"
import normalizePath from "normalize-path"

export type CliExtractTemplateOptions = {
verbose: boolean
Expand All @@ -31,9 +31,7 @@ export default async function command(

if (result) {
catalogStats[
normalizeSlashes(
nodepath.relative(config.rootDir, catalog.templateFile)
)
normalizePath(nodepath.relative(config.rootDir, catalog.templateFile))
] = Object.keys(result).length
}
commandSuccess &&= Boolean(result)
Expand Down
4 changes: 2 additions & 2 deletions packages/cli/src/lingui-extract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { getCatalogs, AllCatalogsType } from "./api"
import { printStats } from "./api/stats"
import { helpRun } from "./api/help"
import ora from "ora"
import { normalizeSlashes } from "./api/utils"
import normalizePath from "normalize-path"

export type CliExtractOptions = {
verbose: boolean
Expand Down Expand Up @@ -40,7 +40,7 @@ export default async function command(
})

catalogStats[
normalizeSlashes(nodepath.relative(config.rootDir, catalog.path))
normalizePath(nodepath.relative(config.rootDir, catalog.path))
] = result || {}

commandSuccess &&= Boolean(result)
Expand Down
Loading
Loading