diff --git a/dist/collect.js b/dist/collect.js new file mode 100644 index 0000000..a579caf --- /dev/null +++ b/dist/collect.js @@ -0,0 +1,65 @@ +const { extractFromFile } = require('./extract'); +const fs = require('fs'); +const path = require('path'); + +const _mergeCatalogs = (a, b) => { + const c = {}; + + [a, b].forEach(catalog => { + Object.entries(catalog).forEach(([str, options]) => { + if (c[str]) { + c[str].origin.push(...options.origin); + } else { + c[str] = { + translation: '', + origin: [...options.origin], + }; + } + }); + }); + + return c; +}; + +const collectFromFiles = (srcPaths, ignore = []) => { + const ignorePattern = ignore.length ? new RegExp(ignore.join("|"), "i") : null + let translatableStrings = {}; + + srcPaths.forEach(srcFilename => { + if ( + !fs.existsSync(srcFilename) || + (ignorePattern && ignorePattern.test(srcFilename)) + ) + return + + if (fs.statSync(srcFilename).isDirectory()) { + const subdirs = fs + .readdirSync(srcFilename) + .map(filename => path.join(srcFilename, filename)) + + translatableStrings = _mergeCatalogs(translatableStrings, collectFromFiles(subdirs, ignore)); + return + } + + if (!srcFilename.endsWith('.ts') && !srcFilename.endsWith('.tsx')) { + return; + } + + extractFromFile(srcFilename).forEach(str => { + if (!translatableStrings[str]) { + translatableStrings[str] = { + translation: "", + origin: [ + [srcFilename, 0], + ], + }; + } else { + translatableStrings[str].origin.push([srcFilename, 0]); + } + }); + }); + + return translatableStrings; +}; + +module.exports = { collectFromFiles }; diff --git a/dist/exceptions.js b/dist/exceptions.js new file mode 100644 index 0000000..41954be --- /dev/null +++ b/dist/exceptions.js @@ -0,0 +1,35 @@ +class ValueArgumentErrorMissing extends Error { + constructor (message) { + super(message); + this.name = "Value argument is missing"; + + // capturing the stack trace keeps the reference to your error class + Error.captureStackTrace(this, this.constructor); + } +} + +class InvalidPluralRule extends Error { + constructor (message) { + super(message) + this.name = message + + // capturing the stack trace keeps the reference to your error class + Error.captureStackTrace(this, this.constructor); + } +} + +class MissingFallbackArgument extends Error { + constructor (message) { + super(message) + this.name = message + + // capturing the stack trace keeps the reference to your error class + Error.captureStackTrace(this, this.constructor); + } +} + +module.exports = { + ValueArgumentErrorMissing, + InvalidPluralRule, + MissingFallbackArgument +} \ No newline at end of file diff --git a/dist/extract.js b/dist/extract.js new file mode 100644 index 0000000..c7c5b55 --- /dev/null +++ b/dist/extract.js @@ -0,0 +1,117 @@ +const swc = require('@swc/core') +const { Visitor } = require('@swc/core/Visitor') +const { omit } = require('lodash'); +const { + parseCallPlurals, + parseTextFromJSXElement, + parseJSXPlurals, + parseTextFromTemplateLiteral, +} = require('./parser'); + +// replace whitespace before/after newline with single space +const nlRe = /\s*(?:\r\n|\r|\n)+\s*/g +// remove whitespace before/after tag +const nlTagRe = /(?:(>)(?:\r\n|\r|\n)+\s+|(?:\r\n|\r|\n)+\s+(?=<))/g + +class ExtractVisitor extends Visitor { + constructor() { + super(); + + this.localTransComponentName = 'Trans'; + this.localSelectOrdinalImportName = 'SelectOrdinal'; + this.localPluralImportName = 'Plural'; + this.translatableStrings = {}; + this.visitedStrings = {}; + } + + visitTaggedTemplateExpression(n) { + const expr = super.visitTaggedTemplateExpression(n); + if (expr.tag.object.type !== 'Identifier' || expr.tag.object.value !== 'i18n') { + return expr; + } + + const str = this.cleanText(parseTextFromTemplateLiteral(expr.template)); + this.translatableStrings[str.trim()] = true; + return expr; + } + + visitTsType(n) { + } + + visitImportDeclaration(node) { + const moduleName = node.source.value + if ("@lingui/react" !== moduleName) return + + const importDeclarations = {} + node.specifiers.forEach((specifier) => { + if(specifier.imported && specifier.imported.value) { + importDeclarations[specifier.imported.value] = + specifier.local.value + } + }) + + this.localTransComponentName = importDeclarations["Trans"] || "Trans"; + this.localSelectOrdinalImportName = importDeclarations["SelectOrdinal"] || "SelectOrdinal"; + this.localPluralImportName = importDeclarations["Plural"] || "Plural"; + } + + visitJSXElement(n) { + const expr = super.visitJSXElement(n); + if(expr.opening.name.value === this.localSelectOrdinalImportName || expr.opening.name.value === this.localPluralImportName) { + const str = this.cleanText(parseJSXPlurals(expr, { index: 0, localTransComponentName: this.localTransComponentName, visitedStrings: this.visitedStrings })); + if(str) { + this.translatableStrings[str] = true; + } + } else if (expr.opening.name.value === this.localTransComponentName) { + const str = this.cleanText(parseTextFromJSXElement(expr, { elementIndex: 0, unknownIndex: 0, localTransComponentName: this.localTransComponentName, visitedStrings: this.visitedStrings })); + if(str) { + this.translatableStrings[str] = true; + } + } + + return expr; + } + + visitCallExpression(n) { + const expr = super.visitCallExpression(n); + if(!expr.callee.object || !expr.callee.property){ + return expr; + } + if(expr.callee.object.type !== 'Identifier' || expr.callee.object.value !== 'i18n' || expr.callee.property.value !== 'plural'){ + return expr; + } + const str = this.cleanText(parseCallPlurals(expr)); + this.translatableStrings[str] = true; + return expr; + } + + getCleanedStrings() { + return Object.keys(omit(this.translatableStrings, Object.keys(this.visitedStrings))); + } + + cleanText(value) { + return value.replace(nlTagRe, "$1").replace(nlRe, " ").trim(); + } +} + +const extractFromFile = (filename) => { + const module = swc + .parseFileSync(filename, { + syntax: "typescript", // "ecmascript" | "typescript" + comments: false, + script: true, + tsx: true, + + // Defaults to es3 + target: "es5", + // Input source code are treated as module by default + isModule: true, + }); + + const visitor = new ExtractVisitor(); + visitor.visitProgram(module); + + return visitor.getCleanedStrings(); +}; + +module.exports = { extractFromFile }; diff --git a/dist/lingui-multi.js b/dist/lingui-multi.js index 96b01a7..9f18f2b 100755 --- a/dist/lingui-multi.js +++ b/dist/lingui-multi.js @@ -11,6 +11,8 @@ const uglifyJS = require("uglify-js") const path = require('path') const fs = require('fs') +const { collectFromFiles } = require('./collect'); + // Set up version command commander.version(require('../package.json').version) @@ -28,6 +30,7 @@ commander extractCatalogs(packageFile, packageObject, localesDir, locales, args) } catch (error) { + throw error; console.error(error.message) process.exit(1) } @@ -71,9 +74,12 @@ const extractCatalogs = (packageFile, packageObject, localesDir, locales, args) if (args.upwardBabelRoot) { options.babelOptions = { "rootMode": "upward" }; } - extract.extract(options.srcPathDirs, targetDir, options) - const rawCatalog = extract.collect(targetDir) + // extract.extract(options.srcPathDirs, targetDir, options) + + // const rawCatalog = extract.collect(targetDir) + const rawCatalog = collectFromFiles(options.srcPathDirs, options.ignore); + // console.log(rawCatalog); // Prepopulate with empty translations const linguiCatalog = Object.keys(rawCatalog).reduce((final, key) => Object.assign(final, { @@ -335,13 +341,14 @@ const filterTranslationOnly = catalog => [translationKey]: filterProperties(catalog[translationKey], ['translation']) }), {}) -const simplifyComplexCatalog = catalog => - Object.keys(catalog) +const simplifyComplexCatalog = catalog => { + return Object.keys(catalog) .reduce((simplifiedCatalog, key) => Object.assign(simplifiedCatalog, { [key]: Object.assign(catalog[key], { origin: catalog[key].origin.map(originArray => originArray.shift()) }) - }), {}) + }), {}); +}; module.exports = { loadLinguiCatalog, diff --git a/dist/parser.js b/dist/parser.js new file mode 100644 index 0000000..8f70a6c --- /dev/null +++ b/dist/parser.js @@ -0,0 +1,201 @@ +const { omit } = require('lodash'); +const {ValueArgumentErrorMissing, InvalidPluralRule, MissingFallbackArgument} = require("./exceptions"); + +const pluralRules = ["zero", "one", "two", "few", "many", "other"]; +const commonProps = ["id", "className", "render"]; + +function parseCallPlurals(element, context = {index: 0}) { + const choicesType = element.callee.property.value.toLowerCase(); + const args = element.arguments[0].expression.properties || []; + const choices = {}; + + for (const attr of args) { + let name; + if (attr.type !== 'KeyValueProperty') { + name = attr.value; + } else { + name = attr.key.type === 'NumericLiteral' ? `=${attr.key.value}` : attr.key.value; + } + + if (attr.type === 'Identifier') { + choices[name] = attr.value; + } else if (attr.type === 'KeyValueProperty') { + choices[name] = parsePluralElement(attr.value, {}, context); + } + } + return createPluralString(choices, choicesType) +} + +function parseJSXPlurals(element, context = { index : 0 }) { + const choicesType = element.opening.name.value.toLowerCase(); + const choices = {}; + let jsxContext = {elementIndex: 0, unknownIndex: 0, localTransComponentName: context.localTransComponentName, visitedStrings: context.visitedStrings}; + + for (const attr of element.opening.attributes) { + const { + name: { value: name } + } = attr + + if (!commonProps.includes(name)) { + const exp = attr.value.type !== 'JSXExpressionContainer' + ? attr.value + : attr.value.expression; + choices[name.replace("_", "=")] = parsePluralElement(exp, jsxContext, context); + } + } + return createPluralString(choices, choicesType); +} + +function createPluralString(choices, choicesType) { + const value = choices["value"]; + const choicesKeys = Object.keys(omit(choices, 'value')); + if (!value) { + throw new ValueArgumentErrorMissing(); + } + + // 'other' choice is required + if (!choicesKeys.length) { + throw new MissingFallbackArgument( + `Missing ${choicesType} choices. At least fallback argument 'other' is required.` + ) + } else if (!choicesKeys.includes("other")) { + throw new MissingFallbackArgument( + `Missing fallback argument 'other'.` + ) + } + + if (choicesType === "plural" || choicesType === "selectordinal") { + choicesKeys.forEach(rule => { + if (!pluralRules.includes(rule) && !/=\d+/.test(rule)) { + throw new InvalidPluralRule(`Invalid plural rule '${rule}'. Must be ${pluralRules.join( + ", " + )} or exact number depending on your source language ('one' and 'other' for English).`); + } + }) + } + + const argument = choicesKeys + .map(form => `${form} {${choices[form]}}`) + .join(" "); + + return `{${value}, ${choicesType}, ${argument}}`; +} + +function parsePluralElement(element, localJSXContext, context) { + if(element.type === "Identifier" || element.type === "StringLiteral" || element.type === 'NumericLiteral') { + return element.value.toString(); + } else if(element.type === "JSXElement") { + return parseTextFromJSXElement(element, localJSXContext, false) + } else if(element.type === "TemplateLiteral") { + return parseTextFromTemplateLiteral(element); + } else { + return `${context.index ++}`; + } +} + +function parseTextFromJSXElement(element, context = { elementIndex: 0, unknownIndex: 0 }, isRoot = true) { + let str = ""; + + if (element.type === 'JSXText') { + str += element.value; + } else if (element.type === 'JSXElement') { + const elementIndex = context.elementIndex; + let shouldAddToVisited = false; + + if (element.opening && !isRoot) { + if(element.opening.name.value === context.localTransComponentName ) { + shouldAddToVisited = true; + } else { + if (!element.closing) { + str += `<${elementIndex}/>`; + } else { + str += `<${elementIndex}>`; + } + context.elementIndex++; + } + } + let localStr = ''; + if (element.children) { + element.children.forEach(child => { + localStr += parseTextFromJSXElement(child, context, false); + }); + } + if(shouldAddToVisited){ + context.visitedStrings[localStr] = true; + } + str += localStr; + + if (element.closing && !isRoot && element.opening.name.value !== context.localTransComponentName) { + str += ``; + if (!element.opening) { + context.elementIndex++; + } + } + } else if (element.type === 'JSXExpressionContainer') { + if (element.expression.type === 'Identifier') { + str += `{${cleanIdentifier(element.expression.value)}}`; + } else if (element.expression.type === 'StringLiteral') { + str += element.expression.value; + } else if (element.expression.type === 'TemplateLiteral') { + str += parseTextFromTemplateLiteral(element.expression); + } else if (element.expression.type === 'JSXElement') { + str += parseTextFromJSXElement(element.expression, context, false); + } else { + str += `{${context.unknownIndex}}`; + context.unknownIndex++; + } + } else { + console.log("OH NEE 2", element); + } + + return str; +} + +function parseTextFromTemplateLiteral(expr) { + const elements = [ + ...expr.expressions || [], + ...expr.quasis || [], + ].sort((a, b) => { + if (a.span.start < b.span.start) { + return -1; + } + + if (a.span.start > b.span.start) { + return 1; + } + + return 0; + }); + + let str = ""; + let unknownParamIndex = 0; + + elements.forEach(element => { + if (element.type === 'Identifier') { + str += `{${cleanIdentifier(element.value)}}`; + } else if (element.type === 'TemplateElement') { + str += element.raw; + } else { + str += `{${unknownParamIndex}}`; + unknownParamIndex++; + } + }); + + return str; +} + +function cleanIdentifier(value) { + // I am not sure of the rules behind this( it seems that applies for some of the strings and for some, it doesn't + // if (value.startsWith('min') || value.startsWith('max')) { + // return `_${value}`; + // } + + return value; +} + +module.exports = { + parseCallPlurals, + parseTextFromJSXElement, + parseJSXPlurals, + parseTextFromTemplateLiteral, +} \ No newline at end of file diff --git a/package.json b/package.json index 4dcde0d..147e999 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "private": false, "dependencies": { "@sector-labs/lingui-cli": "2.7.3-sl.19", + "@swc/core": "^1.3.82", "commander": "^2.15.1", "tmp": "^0.2.1", "uglify-js": "^3.10.0" diff --git a/yarn.lock b/yarn.lock index d36145f..0792021 100644 --- a/yarn.lock +++ b/yarn.lock @@ -200,41 +200,41 @@ lodash "^4.17.13" to-fast-properties "^2.0.0" -"@sector-labs/lingui-babel-plugin-extract-messages@2.7.3-sl.20", "@sector-labs/lingui-babel-plugin-extract-messages@^2.7.3-sl.19": - version "2.7.3-sl.20" - resolved "https://registry.yarnpkg.com/@sector-labs/lingui-babel-plugin-extract-messages/-/lingui-babel-plugin-extract-messages-2.7.3-sl.20.tgz#241cdc8457e2b950d78dae69f424ed224824074e" - integrity sha512-G5IiplBf8cnq3ybYpuV9vhGoIGCGfMptgwQOvUQ4XqszbDIQzOoeEsu4Ml/nSPtLsBK8EA8XHa+b522pc9HoRQ== +"@sector-labs/lingui-babel-plugin-extract-messages@2.7.3-sl.19": + version "2.7.3-sl.19" + resolved "https://registry.yarnpkg.com/@sector-labs/lingui-babel-plugin-extract-messages/-/lingui-babel-plugin-extract-messages-2.7.3-sl.19.tgz#46b271a7956a2ec741de7b42995feea477e665f1" + integrity sha512-BjneBd5a0UDlTvCroBn7HTv+XE6ul43EWaCl5SPyr4ORH53CZyIYrVmhewS5CGMtiO+viotVHzP/pfzUNeFGUA== dependencies: - "@sector-labs/lingui-conf" "2.7.3-sl.20" + "@sector-labs/lingui-conf" "2.7.3-sl.19" babel-generator "^6.26.1" -"@sector-labs/lingui-babel-plugin-transform-js@2.7.3-sl.20": - version "2.7.3-sl.20" - resolved "https://registry.yarnpkg.com/@sector-labs/lingui-babel-plugin-transform-js/-/lingui-babel-plugin-transform-js-2.7.3-sl.20.tgz#475d670e525f2ecc6e3ffba364e87e88df2e120b" - integrity sha512-o0/Gkgj1F3rAEJTIeLqnN6FRXYlo5liaV9CE9h3/WUhFSmUPdJEAorqzyE5NKWqLhFJWZzu4FFXasuq9W1Hklw== - -"@sector-labs/lingui-babel-plugin-transform-react@2.7.3-sl.20": - version "2.7.3-sl.20" - resolved "https://registry.yarnpkg.com/@sector-labs/lingui-babel-plugin-transform-react/-/lingui-babel-plugin-transform-react-2.7.3-sl.20.tgz#152615bfac276435eb89ac0aecba8692cd7407c2" - integrity sha512-NnR+w3rRRWUofvvBYWuD43Rm14OUmUUUv4PLnwfDAvewqGuNsHT6iCS8Nj1fj/rY6QPaaE1NpLXxlvoWl/9xGA== - -"@sector-labs/lingui-babel-preset-react@^2.7.3-sl.19": - version "2.7.3-sl.20" - resolved "https://registry.yarnpkg.com/@sector-labs/lingui-babel-preset-react/-/lingui-babel-preset-react-2.7.3-sl.20.tgz#0e2d0309d88215403f142b28798c525c73b683f2" - integrity sha512-kbmnvVl4DqbMqaIMg8ztOMDYOjjQyekXwk2jbF8PvAYwIW3U3fSvCqmS5A9cC1LEKeSODH0CrI2ZXnc/8O72Vw== - dependencies: - "@sector-labs/lingui-babel-plugin-transform-js" "2.7.3-sl.20" - "@sector-labs/lingui-babel-plugin-transform-react" "2.7.3-sl.20" - -"@sector-labs/lingui-cli@^2.7.3-sl.19": - version "2.7.3-sl.20" - resolved "https://registry.yarnpkg.com/@sector-labs/lingui-cli/-/lingui-cli-2.7.3-sl.20.tgz#3ca6f2d5d201e6f6aa5e3c85bf48559e9281625e" - integrity sha512-Cpu+PrLMwOYyydYG5W3c5UDGX04igUzvfQUnjPyvnXwen77zlDYg5/Drm7yjWEovWNn1KIzuJl/oWj3LI/s4Ww== - dependencies: - "@sector-labs/lingui-babel-plugin-extract-messages" "2.7.3-sl.20" - "@sector-labs/lingui-babel-plugin-transform-js" "2.7.3-sl.20" - "@sector-labs/lingui-babel-plugin-transform-react" "2.7.3-sl.20" - "@sector-labs/lingui-conf" "2.7.3-sl.20" +"@sector-labs/lingui-babel-plugin-transform-js@2.7.3-sl.19": + version "2.7.3-sl.19" + resolved "https://registry.yarnpkg.com/@sector-labs/lingui-babel-plugin-transform-js/-/lingui-babel-plugin-transform-js-2.7.3-sl.19.tgz#6a365e2d4d08821e6e2a8d1ed23d1b92b7ee2aec" + integrity sha512-0Y+EXughPU2WqjWeW9H6Evy7VhFDAfa+1nmulGonlxOpG/JwMS0MnLDscnzHIkYjbZFkZXJ/xaj8PW3N0s6FGA== + +"@sector-labs/lingui-babel-plugin-transform-react@2.7.3-sl.19": + version "2.7.3-sl.19" + resolved "https://registry.yarnpkg.com/@sector-labs/lingui-babel-plugin-transform-react/-/lingui-babel-plugin-transform-react-2.7.3-sl.19.tgz#f57e616e312b699bba663e83c8ac0494b85864da" + integrity sha512-lm9yTL69K4e/lDFOqQYpJyzHCtxzKZbm8XHviDHPQCl/dt4mZQCP7ITndCRBrXIfSuzCkdostquIy3oXABeLtQ== + +"@sector-labs/lingui-babel-preset-react@2.7.3-sl.19": + version "2.7.3-sl.19" + resolved "https://registry.yarnpkg.com/@sector-labs/lingui-babel-preset-react/-/lingui-babel-preset-react-2.7.3-sl.19.tgz#befd2f55e0142e78dce18b05486a2e045cb4529e" + integrity sha512-fKLNK8IVqmTlTlqoG2jvCyOyBTSFIohLskYYVCKCFeq41aF4p39jsttpQ88GjK7MNaABfXDozFLUyGoUt7g/EA== + dependencies: + "@sector-labs/lingui-babel-plugin-transform-js" "2.7.3-sl.19" + "@sector-labs/lingui-babel-plugin-transform-react" "2.7.3-sl.19" + +"@sector-labs/lingui-cli@2.7.3-sl.19": + version "2.7.3-sl.19" + resolved "https://registry.yarnpkg.com/@sector-labs/lingui-cli/-/lingui-cli-2.7.3-sl.19.tgz#9d66c8a0534e86568f797c69f3013bc48756a03e" + integrity sha512-0G6l5iompuzCETpC+jGPsritZqG/wCpkj9grDMJzYfwd2iS1CNFL0MSIl2c8hlqyAefJ+zZECfFpzgHGSGXhxA== + dependencies: + "@sector-labs/lingui-babel-plugin-extract-messages" "2.7.3-sl.19" + "@sector-labs/lingui-babel-plugin-transform-js" "2.7.3-sl.19" + "@sector-labs/lingui-babel-plugin-transform-react" "2.7.3-sl.19" + "@sector-labs/lingui-conf" "2.7.3-sl.19" babel-generator "^6.26.1" babel-plugin-syntax-jsx "^6.18.0" babel-runtime "^6.26.0" @@ -258,10 +258,10 @@ ramda "^0.25.0" typescript "^2.9.2" -"@sector-labs/lingui-conf@2.7.3-sl.20": - version "2.7.3-sl.20" - resolved "https://registry.yarnpkg.com/@sector-labs/lingui-conf/-/lingui-conf-2.7.3-sl.20.tgz#0e4e0eecef385d3876ae54d8a179daa2f24cb08b" - integrity sha512-raEUjnaJcVcwOBvSwyjybuyGnv+c8qAVBbPlr673eUey0eh3Oj3m/2uqU7BUBuJMG6eUDjtyEqLudWp85SQGjQ== +"@sector-labs/lingui-conf@2.7.3-sl.19": + version "2.7.3-sl.19" + resolved "https://registry.yarnpkg.com/@sector-labs/lingui-conf/-/lingui-conf-2.7.3-sl.19.tgz#f6c392306317850b707eb709a08d48e9accd527c" + integrity sha512-8QpZsUffFN5UhZVWa5jda3qEG2erKmdSe9FhZRCQMKLxJum0Ymy5lUtRN+OGOfQgXcuJdjE/87w915tJqzT1Gg== dependencies: chalk "^2.3.0" cosmiconfig "^5.0.6" @@ -269,6 +269,79 @@ jest-validate "^23.5.0" pkg-conf "^2.1.0" +"@swc/core-darwin-arm64@1.3.82": + version "1.3.82" + resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.82.tgz#bbf9874747b51053d8a59ea26c3e235c326f24a3" + integrity sha512-JfsyDW34gVKD3uE0OUpUqYvAD3yseEaicnFP6pB292THtLJb0IKBBnK50vV/RzEJtc1bR3g1kNfxo2PeurZTrA== + +"@swc/core-darwin-x64@1.3.82": + version "1.3.82" + resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.3.82.tgz#145cdde16678e0d793620035783e5b413a16ac43" + integrity sha512-ogQWgNMq7qTpITjcP3dnzkFNj7bh6SwMr859GvtOTrE75H7L7jDWxESfH4f8foB/LGxBKiDNmxKhitCuAsZK4A== + +"@swc/core-linux-arm-gnueabihf@1.3.82": + version "1.3.82" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.82.tgz#0c2f32c5793f2ac8e8ccf416aec84d016c30ef7b" + integrity sha512-7TMXG1lXlNhD0kUiEqs+YlGV4irAdBa2quuy+XI3oJf2fBK6dQfEq4xBy65B3khrorzQS3O0oDGQ+cmdpHExHA== + +"@swc/core-linux-arm64-gnu@1.3.82": + version "1.3.82" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.82.tgz#2313d4901fa0ebdd2a0f189909073e1e8a07f1d6" + integrity sha512-26JkOujbzcItPAmIbD5vHJxQVy5ihcSu3YHTKwope1h28sApZdtE7S3e2G3gsZRTIdsCQkXUtAQeqHxGWWR3pw== + +"@swc/core-linux-arm64-musl@1.3.82": + version "1.3.82" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.82.tgz#6e96cf6e52e647fecf27511d766bea90e96f8a2f" + integrity sha512-8Izj9tuuMpoc3cqiPBRtwqpO1BZ/+sfZVsEhLxrbOFlcSb8LnKyMle1g3JMMUwI4EU75RGVIzZMn8A6GOKdJbA== + +"@swc/core-linux-x64-gnu@1.3.82": + version "1.3.82" + resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.82.tgz#6275c10d7c8c0768550bc7934c9dd8cde4881d92" + integrity sha512-0GSrIBScQwTaPv46T2qB7XnDYxndRCpwH4HMjh6FN+I+lfPUhTSJKW8AonqrqT1TbpFIgvzQs7EnTsD7AnSCow== + +"@swc/core-linux-x64-musl@1.3.82": + version "1.3.82" + resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.82.tgz#edb98c30bd0de42bf1a63469937630d942c71988" + integrity sha512-KJUnaaepDKNzrEbwz4jv0iC3/t9x0NSoe06fnkAlhh2+NFKWKKJhVCOBTrpds8n7eylBDIXUlK34XQafjVMUdg== + +"@swc/core-win32-arm64-msvc@1.3.82": + version "1.3.82" + resolved "https://registry.yarnpkg.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.82.tgz#0a8e9b361aac37d01f684c8a3d3e94e5f8c3b14f" + integrity sha512-TR3MHKhDYIyGyFcyl2d/p1ftceXcubAhX5wRSOdtOyr5+K/v3jbyCCqN7bbqO5o43wQVCwwR/drHleYyDZvg8Q== + +"@swc/core-win32-ia32-msvc@1.3.82": + version "1.3.82" + resolved "https://registry.yarnpkg.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.82.tgz#096854ff764282766271f1354ee1214358a8bf01" + integrity sha512-ZX4HzVVt6hs84YUg70UvyBJnBOIspmQQM0iXSzBvOikk3zRoN7BnDwQH4GScvevCEBuou60+i4I6d5kHLOfh8Q== + +"@swc/core-win32-x64-msvc@1.3.82": + version "1.3.82" + resolved "https://registry.yarnpkg.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.82.tgz#1181070bff4a13a7fcc7f1020eef1571f8c1257a" + integrity sha512-4mJMnex21kbQoaHeAmHnVwQN9/XAfPszJ6n9HI7SVH+aAHnbBIR0M59/b50/CJMjTj5niUGk7EwQ3nhVNOG32g== + +"@swc/core@^1.3.82": + version "1.3.82" + resolved "https://registry.yarnpkg.com/@swc/core/-/core-1.3.82.tgz#8f6c53db3c23a1769b6c5085fbcb3b1df9548a40" + integrity sha512-jpC1a18HMH67018Ij2jh+hT7JBFu7ZKcQVfrZ8K6JuEY+kjXmbea07P9MbQUZbAe0FB+xi3CqEVCP73MebodJQ== + dependencies: + "@swc/types" "^0.1.4" + optionalDependencies: + "@swc/core-darwin-arm64" "1.3.82" + "@swc/core-darwin-x64" "1.3.82" + "@swc/core-linux-arm-gnueabihf" "1.3.82" + "@swc/core-linux-arm64-gnu" "1.3.82" + "@swc/core-linux-arm64-musl" "1.3.82" + "@swc/core-linux-x64-gnu" "1.3.82" + "@swc/core-linux-x64-musl" "1.3.82" + "@swc/core-win32-arm64-msvc" "1.3.82" + "@swc/core-win32-ia32-msvc" "1.3.82" + "@swc/core-win32-x64-msvc" "1.3.82" + +"@swc/types@^0.1.4": + version "0.1.4" + resolved "https://registry.yarnpkg.com/@swc/types/-/types-0.1.4.tgz#8d647e111dc97a8e2881bf71c2ee2d011698ff10" + integrity sha512-z/G02d+59gyyUb7KYhKi9jOhicek6QD2oMaotUyG+lUkybpXoV49dY9bj7Ah5Q+y7knK2jU67UTX9FyfGzaxQg== + "@types/parse-json@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"