Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 2 additions & 0 deletions packages/native-tools/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ export default defineConfig({
> **Note**
> For the best performance, disable multithreading on the Lingui CLI side with `lingui extract --workers 1`. The native extractor processes files in parallel itself.

Other extractors can wrap it, for example to extract from compiled `.vue` files. When a wrapper passes a source map in `ctx.sourceMaps`, message origins point to the original file and line.

`createSwcExtractor()` accepts optional extractor options:

```ts
Expand Down
38 changes: 38 additions & 0 deletions packages/native-tools/__test__/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,4 +191,42 @@ describe('createSwcExtractor', () => {

expect(await extract(extractor, linguiConfig)).toEqual(['From custom package'])
})

describe('source maps', () => {
const linguiConfig = makeConfig({locales: ['en']}, {skipValidation: true})

// Generated line 2 maps to line 10, column 2 (0-based: 9, 2) of App.vue
const sourceMaps = {
version: 3,
sources: ['/project/src/App.vue'],
names: [],
mappings: 'AAAA;AASE',
}

const compiled = `import {t} from '@lingui/core/macro';\nt\`Hello\`;\n`

async function extractOrigins(code: string, sourceMaps?: unknown) {
const messages: ExtractedMessage[] = []
await createSwcExtractor().extract('App.vue.js', code, (msg) => messages.push(msg), {
linguiConfig,
sourceMaps,
})
return messages.map((msg) => msg.origin)
}

test('maps origins through ctx.sourceMaps', async () => {
expect(await extractOrigins(compiled)).toEqual([['App.vue.js', 2, 2]])
expect(await extractOrigins(compiled, sourceMaps)).toEqual([['/project/src/App.vue', 10, 3]])
})

test('ctx.sourceMaps takes precedence over an inline source map', async () => {
const inlineMap = {...sourceMaps, sources: ['/project/src/Other.vue']}
const code =
compiled +
`//# sourceMappingURL=data:application/json;base64,${Buffer.from(JSON.stringify(inlineMap)).toString('base64')}\n`

expect(await extractOrigins(code)).toEqual([['/project/src/Other.vue', 10, 3]])
expect(await extractOrigins(code, sourceMaps)).toEqual([['/project/src/App.vue', 10, 3]])
})
})
})
6 changes: 6 additions & 0 deletions packages/native-tools/src-js/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,12 @@ export function createSwcExtractor(options: ExtractorOptions = {}): ExtractorTyp
},

async extract(filename, code, onMessageExtracted, ctx) {
if (ctx.sourceMaps) {
// The native extractor reads only the last inline source map comment,
// so the appended map takes precedence over one already in the code (as in the Babel extractor)
Comment thread
andrii-bodnar marked this conversation as resolved.
Resolved
code += `\n//# sourceMappingURL=data:application/json;base64,${Buffer.from(JSON.stringify(ctx.sourceMaps)).toString('base64')}`
}

const {messages} = await extractMessages(code, filename, {
...options,
macro: mapOptions(ctx.linguiConfig, options.macro),
Expand Down
Loading