|
1 | 1 | "use strict"; |
2 | 2 |
|
3 | | -const path = require("path"); |
| 3 | +const pathUtils = require("path"); |
| 4 | +const fs = require("fs"); |
4 | 5 |
|
5 | 6 | function normalize(src) { |
6 | | - return src.replace(/\//, path.sep); |
| 7 | + return src.replace(/\//, pathUtils.sep); |
7 | 8 | } |
8 | 9 |
|
9 | 10 | module.exports = function (api) { |
@@ -125,6 +126,8 @@ module.exports = function (api) { |
125 | 126 | convertESM ? "@babel/proposal-export-namespace-from" : null, |
126 | 127 | convertESM ? "@babel/transform-modules-commonjs" : null, |
127 | 128 |
|
| 129 | + pluginPackageJsonMacro, |
| 130 | + |
128 | 131 | process.env.STRIP_BABEL_8_FLAG && [ |
129 | 132 | pluginToggleBabel8Breaking, |
130 | 133 | { breaking: bool(process.env.BABEL_8_BREAKING) }, |
@@ -319,3 +322,49 @@ function pluginToggleBabel8Breaking({ types: t }, { breaking }) { |
319 | 322 | }, |
320 | 323 | }; |
321 | 324 | } |
| 325 | + |
| 326 | +function pluginPackageJsonMacro({ types: t }) { |
| 327 | + const fnName = "PACKAGE_JSON"; |
| 328 | + |
| 329 | + return { |
| 330 | + visitor: { |
| 331 | + ReferencedIdentifier(path) { |
| 332 | + if (path.isIdentifier({ name: fnName })) { |
| 333 | + throw path.buildCodeFrameError( |
| 334 | + `"${fnName}" is only supported in member expressions.` |
| 335 | + ); |
| 336 | + } |
| 337 | + }, |
| 338 | + MemberExpression(path) { |
| 339 | + if (!path.get("object").isIdentifier({ name: fnName })) return; |
| 340 | + |
| 341 | + if (path.node.computed) { |
| 342 | + throw path.buildCodeFrameError( |
| 343 | + `"${fnName}" does not support computed properties.` |
| 344 | + ); |
| 345 | + } |
| 346 | + const field = path.node.property.name; |
| 347 | + |
| 348 | + // TODO: When dropping old Node.js versions, use require.resolve |
| 349 | + // instead of looping through the folders hierarchy |
| 350 | + |
| 351 | + let pkg; |
| 352 | + for (let dir = pathUtils.dirname(this.filename); ; ) { |
| 353 | + try { |
| 354 | + pkg = fs.readFileSync(pathUtils.join(dir, "package.json"), "utf8"); |
| 355 | + break; |
| 356 | + } catch (_) {} |
| 357 | + |
| 358 | + const prev = dir; |
| 359 | + dir = pathUtils.resolve(dir, ".."); |
| 360 | + |
| 361 | + // We are in the root and didn't find a package.json file |
| 362 | + if (dir === prev) return; |
| 363 | + } |
| 364 | + |
| 365 | + const value = JSON.parse(pkg)[field]; |
| 366 | + path.replaceWith(t.valueToNode(value)); |
| 367 | + }, |
| 368 | + }, |
| 369 | + }; |
| 370 | +} |
0 commit comments