Giter Club home page Giter Club logo

babel-plugin-codegen's Introduction

babel-plugin-codegen 💥

Generate code at build-time


Build Status Code Coverage version downloads MIT License All Contributors PRs Welcome Code of Conduct Babel Macro

The problem

The applications of this plugin are wide, so it's kinda hard to sum it up, but basically my use case was I needed to add a bunch of named exports to glamorous (one for every DOM node type) and I didn't want to maintain the exports in my source file. So someone created a post-build script to concatenate them to the end of the file. I built this plugin so I could do that without having an ad-hoc post-build script.

Read "Make maintainable workarounds with codegen 💥" for more inspiration

This solution

This plugin allows you to generate code at build-time. Any code that runs synchronously in node can be used to generate a string of code and that string will be inserted in place of where your usage appears.

It works by accepting your code string (or module when using the // @codegen comment directive) and requiring it as a module. Then it takes whatever the export was (which should be a string) and converts that string to an AST node and swaps your usage node with the new AST node.

Table of Contents

Installation

This module is distributed via npm which is bundled with node and should be installed as one of your project's devDependencies:

npm install --save-dev babel-plugin-codegen

Usage

This package works in a very similar way to babel-plugin-preval except in this case instead of any value being replaced in the code, you're actually replacing it with code (giving you a little bit more power in exchange for potentially being a little more confusing).

Important notes:

  1. All code run by codegen is not run in a sandboxed environment
  2. All code must run synchronously.

You may like to watch this YouTube video to get an idea of what codegen is and how it can be used.

Template Tag

Before:

codegen`
  const fs = require('fs')
  module.exports = fs.readFileSync(require.resolve('./some-code.js'), 'utf8')
`

After (assuming some-code.js contains the text: var x = 'Hello world!'):

var x = 'Hello world!'

Here you can see the difference between this plugin and babel-plugin-preval, which would output the content of some-code.js as a string instead:

"var x = 'Hello world!'"

codegen can also handle some simple dynamic values as well:

Before:

const three = 3
const x = codegen`module.exports = '${three}'`

After:

const three = 3
const x = 3

import comment

Before:

import /* codegen */ './assign-one.js'

After (assign-one.js is: module.exports = 'var x = 1'):

var x = 1

You can also provide arguments! In this case, the module you import should export a function which accepts those arguments and returns a string.

Before:

import /* codegen(3) */ './assign-identity'

After (assign-identity.js is: module.exports = input => 'var x = ' + JSON.stringify(input) + ';'):

var x = 3

codegen.require

Before:

codegen.require('./es6-identity', 3)

After (es6-identity.js is: export default input => 'var x = ' + JSON.stringify(input) + ';'):

var x = 3

codegen file comment (// @codegen)

Using the codegen file comment will update a whole file to be evaluated down to an export.

Whereas the above usages (assignment/import/require) will only codegen the scope of the assignment or file being imported.

Here is an example of painless index.js which auto import same depth js files at compile time.

Before:

// @codegen
const fs = require("fs");
const path = require("path");
const regx_JSFiles = /\.(es6|js|es|jsx|mjs|ts)$/;
const name = require("path").basename(__filename);

module.exports = fs.readdirSync(__dirname).reduce((acc, cur) => {
  if (name !== cur && regx_JSFiles.test(cur)) {
    acc += `export * from './${cur.replace(regx_JSFiles, "")}'\n`;
  }
  return acc;
}, "");

After:

export * from './apple';
export * from './orange';
export * from './pear';

Configure with Babel

Via .babelrc (Recommended)

.babelrc

{
  "plugins": ["codegen"]
}

Via CLI

babel --plugins codegen script.js

Via Node API

require('babel-core').transform('code', {
  plugins: ['codegen'],
})

Use with babel-plugin-macros

Once you've configured babel-plugin-macros you can import/require the codegen macro at babel-plugin-codegen/macro. For example:

import codegen from 'babel-plugin-codegen/macro'

codegen`module.exports = ['a', 'b', 'c'].map(l => 'export const ' + l + ' = ' + JSON.stringify(l)).join(';')`

           

export const a = "a";
export const b = "b";
export const c = "c";

APIs not supported by the macro

You could also use codegen.macro if you'd prefer to type less 😀

Caveats

One really important thing to note here is that it doesn't work by simply replacing your code with whatever string you export. Instead it replaces it at the AST level. This means that the resulting code should operate the same, but the format of the code could be entirely different. Most of the time this should not matter, but if it matters to you, please feel free to contribute back if you feel like you could make it work!

Examples

Inspiration

I built this to solve a problem I was experiencing with glamorous. It's heavily based on my work in babel-plugin-preval.

Other Solutions

I'm not aware of any, if you are please make a pull request and add it here!

Issues

Looking to contribute? Look for the Good First Issue label.

🐛 Bugs

Please file an issue for bugs, missing documentation, or unexpected behavior.

See Bugs

💡 Feature Requests

Please file an issue to suggest new features. Vote on feature requests by adding a 👍. This helps maintainers prioritize what to work on.

See Feature Requests

Contributors ✨

Thanks goes to these people (emoji key):


Kent C. Dodds

💻 📖 🚇 ⚠️

Michael Rawlings

💻 📖 ⚠️

Jan Willem Henckel

💻 📖 ⚠️

Karan Thakkar

📖

Justin Dorfman

🔍

Michaël De Boey

💻

Matija Marohnić

📖

Minh Nguyen

💻 ⚠️

Caleb Eby

💻

loynoir

📖 💻

gabalafou

📖

This project follows the all-contributors specification. Contributions of any kind welcome!

LICENSE

MIT

babel-plugin-codegen's People

Contributors

allcontributors[bot] avatar andrewmcodes avatar calebeby avatar djfarly avatar gabalafou avatar jdorfman avatar karanjthakkar avatar kentcdodds avatar loynoir avatar maurobringolf avatar michaeldeboey avatar mlrawlings avatar nminhnguyen avatar sangeethakp avatar silvenon avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

babel-plugin-codegen's Issues

import() is not supported

Problem

It seems to not support import() syntax.

What I did:

// @codegen
module.exports = "export default () => import('./logo.svg');"

What happened:

Syntax error: Unexpected token (1:21)

> 1 | //@codegen
    |                     ^
  2 | module.exports = "export default () => import('./logo.svg')"
  3 |

Reproduceable Example

Currently, I'm using create-react-app + react-app-rewired injecting codegen

create-react-app example
cd example
yarn add -D react-app-rewired babel-plugin-codegen
echo "module.exports = (config) => require('react-app-rewired').injectBabelPlugin('codegen', config)" > config-overrides.js
echo "//@codegen\nmodule.exports = \"export default () => import('./logo.svg')\"" > ./src/test.js
echo "require('./test').default().then(svg => console.log(svg))" >> ./src/index.js
$(npm bin)/react-app-rewired build

Import lots of variables in a single line of code

  • "codegen.macro": "^1.0.0",
  • node -v: v9.11.1
  • yarn -v: 1.3.2

I'm generating variables so that my colleague who doesn't know how to code can write simple code now.

[💖this part has no problem]

// ./memeTemplate/variables.js
const codegen = require('codegen.macro');

// preload formulas variables, and generate more variables, so my colleague can import them easily
codegen`
const fs = require('fs');

const formulasJSON = JSON.parse(fs.readFileSync(require.resolve('../formulas.json'), 'utf8'));
const variableNames = [
  ...Object.keys(formulasJSON),
  ...Object.keys(formulasJSON).map(name => '上期' + name),
  ...Object.keys(formulasJSON).map(name => '上上期' + name),
];

module.exports = variableNames
  .map(
    variableName =>
      'export var ' + variableName.replace(/[()、:()]/g, '') + ' = loader => loader.load("' + variableName + '")'
  )
  .join(';');
`;

[Here are problems]

// ./templates.js
// try to automatiously import variables
codegen`
  'const { ' + Object.keys(require('./memeTemplate/variables')).join(',') + '} = require("./memeTemplate/variables");'
`;


// using the automatiously imported variable
`
偿债能力分析
2017年流动资产合计为${流动资产合计}
`

Now it will show an error ./src/templates.js Module build failed: MacroError: The macro you imported from "undefined" is being executed outside the context of compilation with babel-plugin-macros. This indicates that you don't have the babel plugin "babel-plugin-macros" configured correctly. Please see the documentation for how to configure babel-plugin-macros properly

I had tried console.log( 'const { ' + Object.keys(require('./memeTemplate/variables')).join(',') + '} = require("./memeTemplate/variables");' );, it logs the correct require statement:

const { 净资产收益率,平均净资产, ...hugeAmountOfVariables } = require("./memeTemplate/variables");

And if I just import them statisticly:

import {
  销售利润率,
  流动比率,
  ...lotsToImport,
} from './memeTemplate/variables';

It works correctly.

So I can't use codegen to load code generated by codegen?
Or I can't use codegen to generate import statement?

Doesn't work if config is in "babel.config.js" file

  • babel-plugin-codegen version: 3.0.0
  • nodeversion: 10.13.0
  • npm (or yarn) version: 1.12.3

Plugin doesn't work if your Babel config is in babel.config.js, but all works fine if it is in .babelrc

babel.config.js

module.exports = function() {
  return {
    presets: ['babel-preset-expo'],
    plugins: ['codegen'],
  }
}

.babelrc

{
  "presets": ["babel-preset-expo"],
  "plugins": [
    "codegen"
  ]
}

What you did:

// @codegen

module.exports = '
  module.exports = []
'

What happened:

When I use babel.config.js, I get export from module as string "module.exports = []", like there is no top comment "// @codegen".

When I use .babelrc, I get empty array as export from module, as it should be.

Reproduction repository:

https://github.com/serhiipalash/test-babel-codegen

Latest Expo has babel config in babel.config.js, and I don't want to change it as it is the standard for all future releases.

Dynamic import() does not work

Hey Kent, thanks for this amazing babel plugin!
I think I'm going a bit overboard with codegen right now, but it really helps to solve problems. ;)

This is a duplicate of: #8
The solution proposed in the issue (using System.import() instead of import() does work but does not seem future proof if i read the webpack docs correctly. ;)

The use of System.import in webpack did not fit the proposed spec, so it was deprecated in webpack 2.1.0-beta.28 in favor of import().
https://webpack.js.org/api/module-methods/#import-

  • babel-plugin-codegen version: 1.2.1
  • node version: 8
  • npm (or yarn) version: 1.3.2

Copied from the old issue:


What I did:

// @codegen
module.exports = "export default () => import('./logo.svg');"
What happened:

Syntax error: Unexpected token (1:21)

> 1 | //@codegen
    |                     ^
  2 | module.exports = "export default () => import('./logo.svg')"
  3 |

Reproduceable Example
Currently, I'm using create-react-app + react-app-rewired injecting codegen

create-react-app example
cd example
yarn add -D react-app-rewired babel-plugin-codegen
echo "module.exports = (config) => require('react-app-rewired').injectBabelPlugin('codegen', config)" > config-overrides.js
echo "//@codegen\nmodule.exports = \"export default () => import('./logo.svg')\"" > ./src/test.js
echo "require('./test').default().then(svg => console.log(svg))" >> ./src/index.js
$(npm bin)/react-app-rewired build

Suggested solution:
I don't know what causes the issue exactly... if i knew i'd be happy to help.
I tried moving around "syntax-dynamic-import" (helplessly) in the babel config without any observable changes. ;)

Thanks!

Add link to blog post

I would like to add a link to the blog post. Let's add right below "The problem" paragraph and before "This solution" title:

> Read ["Make maintainable workarounds with codegen 💥"](https://blog.kentcdodds.com/make-maintainable-workarounds-with-codegen-d34163a09c13) for more inspiration

Please see the contributing guidelines, and let me know if you have questions or need help.

This is a first-timers-only issue. So I'll only accept a pull request from someone who's never contributed to open source before.

To "claim" this issue, please comment with: "I'm working on this right now." First one to say that gets the issue, the help, and the merge :)

Good luck!

Property value expected type of string but got null

  • babel-plugin-codegen version: ^3.0.0
  • node version: 10.12.0
  • npm (or yarn) version: 6.4.1

Relevant code or config

// @codegen

const hello = 'hello';

module.exports = `
  export default {};
`;

I was expecting the simple code above to work but it just gives the error mentioned in the title.

screenshot 2018-10-26 at 17 12 46

However, if we remove the line const hello = 'hello', everything works as expected and export default {}; it's correctly generated

BABEL error when configuring with babel.config.js and with typescript preset

  • babel-plugin-codegen version: 4.1.4
  • node version: v12.15.0
  • npm version: 6.14.11

With these files:

index.js

// @codegen
module.exports = `console.log("hello world!")`;

babel.config.js

module.exports = {
  presets: ['@babel/preset-typescript'],
  plugins: ['codegen'],
};

I ran this command:

babel --plugins codegen index.js

and got this result:

Error: [BABEL] unknown: Configuration contains string/RegExp pattern, but no filename was passed to Babel
    at matchPattern (/home/jallan/dev/codegen/node_modules/@babel/core/lib/config/config-chain.js:431:11)
    at /home/jallan/dev/codegen/node_modules/@babel/core/lib/config/config-chain.js:418:35
    at Array.some (<anonymous>)
    at matchesPatterns (/home/jallan/dev/codegen/node_modules/@babel/core/lib/config/config-chain.js:418:19)
    at configFieldIsApplicable (/home/jallan/dev/codegen/node_modules/@babel/core/lib/config/config-chain.js:400:10)
    at configIsApplicable (/home/jallan/dev/codegen/node_modules/@babel/core/lib/config/config-chain.js:395:41)
    at /home/jallan/dev/codegen/node_modules/@babel/core/lib/config/config-chain.js:256:13
    at Array.forEach (<anonymous>)
    at /home/jallan/dev/codegen/node_modules/@babel/core/lib/config/config-chain.js:253:42
    at buildPresetChain (/home/jallan/dev/codegen/node_modules/@babel/core/lib/config/config-chain.js:45:17)

Reproduction repository:

https://github.com/jackgeek/codegen-babel-plugin-problem

Problem description:

When using a babel.config.js file the above error occurs, however works fine if you change it to a .babelrc file. Also when you remove the typescript preset it works fine.

codegen seems to be running before other plugins regardless of order?

In short, I'm having this issue:

// @codegen

import fs from 'fs';

the above throws unexpected token import, if I remove the // @codegen line it works fine. My babel plugins are:

 ['transform-es2015-modules-commonjs', 'transform-flow-comments', 'codegen']

I'd expect that codegen would get code transformed from transform-es2015-modules-commonjs and then execute that, but it doesn't seem to be the case. Thoughts?

Stale imports when running in watch mode

First of all, thanks for an amazing plugin!

  • babel-plugin-codegen version: 4.0.1
  • node version: 12.14.1
  • npm version: 6.13.4

What you did:

Importing a javascript file and including its contents in generated code, using babel in watch mode or babel-loader and webpack-dev-server.

What happened:

The contents of the imported file is output correctly, but changes to the imported file that happens after babel was started are ignored until babel is shut down and started again. Changing the file that does the code generation does not cause the import to update. Steps to reproduce are described in the README of the below repo.

Reproduction repository:

https://github.com/asbjornh/babel-plugin-codegen-watch

Problem description:

For some reason it seems like imports are read once and then never again when running in watch mode.

Suggested solution:

Cannot get past "Must module.exports a string."

  • babel-plugin-codegen version: 3.0.0
  • node version: 10.15.0
  • npm (or yarn) version: yarn 1.13.0
  • babel: 7.4.5
  • babel-plugin-macros: 2.5.1 (required by another dep)

Relevant code or config

// my.js
codegen`module.exports = ''`;

// babel.config.js
module.exports = {
  presets: [
    [
      '@babel/env',
      {
        targets: {
          browsers: [
            'last 2 versions',
            'ie 11',
          ]
        },
        useBuiltIns: 'usage',
        corejs: 2,
      },
    ],
  ],
  plugins: [
    'macros',
    'codegen',
    '@babel/plugin-syntax-dynamic-import',
  ],
};

What you did:

Try to compile my.js

What happened:

codegen: Must module.exports a string.

      at getReplacement (node_modules/babel-plugin-codegen/dist/helpers.js:43:11)
      at replace (node_modules/babel-plugin-codegen/dist/helpers.js:69:21)
      at asFunction (node_modules/babel-plugin-codegen/dist/replace.js:57:5)
      at asIdentifier (node_modules/babel-plugin-codegen/dist/replace.js:127:22)
      at PluginPass.Identifier (node_modules/babel-plugin-codegen/dist/index.js:37:11)
      at newFn (node_modules/@babel/traverse/lib/visitors.js:193:21)
      at NodePath._call (node_modules/@babel/traverse/lib/path/context.js:53:20)
      at NodePath.call (node_modules/@babel/traverse/lib/path/context.js:40:17)
      at NodePath.visit (node_modules/@babel/traverse/lib/path/context.js:88:12)
      at TraversalContext.visitQueue (node_modules/@babel/traverse/lib/context.js:118:16)

Reproduction repository:

Problem description:

I cannot seem to get past the Must module.exports a string. I've tried using escaped backticks, double quotes and single quotes, joining arrays, concatenating strings some other way (e.g., with + operator), etc.

What am I doing wrong?

Suggested solution:

n/a

Potential next steps? ("codegen-preval-core", dynamic identifier name)

I'd like to use this Issue for discussion for some ideas I have in mind.
As of #11 and #12 some significant updates have been made to the structure of this plugin.
Codegen and preval are sharing a significant amount of code. Does it make sense to bring those codebases closer together? Now that this repo has dropped all direct babel dependencies it feels quite archaic to me to still have them in preval.
As far as I can see the main difference lies in what is done with the replacement result and the name of the identifier.
It should be possible to create a plugin that shares most of the code and exposes configuration to either do pre evaluation or code generation (including a dynamic name for the identifier).
babel-plugin-preval and babel-plugin-codegen could become a very thin wrapper around this core package.
Maybe another sensible step could be to concentrate all efforts in a mono-repo.

Hopefully I am making sense. 😃

SyntaxError when a single import/export statement is used

  • babel-plugin-codegen version: 4.0.0
  • node version: not sure, I used Code Sandbox
  • npm (or yarn) version: not sure, I used Code Sandbox

Relevant code or config

import codegen from "babel-plugin-codegen/macro";

// Based on https://github.com/kentcdodds/babel-plugin-codegen#use-with-babel-plugin-macros
// except using 1 item in the array, not several.
codegen`module.exports = ['a'].map(l => 'export const ' + l + ' = ' + JSON.stringify(l)).join(';')`;

// Or more simply:
codegen`module.exports = 'export const a = "a";'`;

What you did: a little hard to see from the CodeSandbox, but the above input will be compiled like so:

//    ↓ ↓ ↓ ↓ ↓ ↓

(function () {
  export var a = "a";
})();

What happened: led to a SyntaxError

SyntaxError: Unexpected token 'export'

because it was wrapped into an IIFE by Babel.

Note that if you check out the repo instead of CodeSandbox, the error you get is

./src/codegen.js 4:2
Module parse failed: 'import' and 'export' may only appear at the top level (4:2)
You may need an appropriate loader to handle this file type.
| // Or more simply:
| (function () {
> export var a = "a";
| })();

Reproduction repository: https://github.com/NMinhNguyen/babel-plugin-codegen-single-export-import-issue/blob/master/src/codegen.js

Problem description: There is currently a workaround such as including an extra semicolon ; to ensure it gets treated as multiple statements:

-codegen`module.exports = 'export const a = "a";'`;
+codegen`module.exports = 'export const a = "a";;'`;

because then multiple statements are emitted, and the logic at

} else if (Array.isArray(replacement)) {
path.replaceWithMultiple(replacement)
} else {
path.replaceWith(replacement)
}
won't call path.replaceWith(replacement) which wraps single statements into an IIFE (https://github.com/babel/babel/blob/d50e78d/packages/babel-traverse/src/path/replacement.js#L213-L224) if toSequenceExpression was false-y.

Suggested solution: I was initially thinking to always call path.replaceWithMultiple(replacement), where replacement could be made a 1-item array if it's not an array already, but I'm not sure of the impact of that. Perhaps we could add this workaround to the README for now? Unless someone else knows that it's a safe thing to do for sure?

Add support for full module resolution in require & import

I've created a reusable codegen which works great (thanks for the library!). However, once I published & consume the codegen as an npm module (@ceteio/next-layout-loader), it no longer works:

const Layout = codegen.require("@ceteio/next-layout-loader", __filename);
ModuleBuildError: Module build failed (from ./node_modules/next/dist/build/babel/loader/index.js):
Error: Cannot find module '/sandbox/pages/@ceteio/next-layout-loader'
Require stack:
- /sandbox/node_modules/babel-plugin-codegen/dist/helpers.js

See an example on codesandbox

It looks like the code for loading codegen.require / import statements is hard-coded to assume a relative path is always passed:

function resolveModuleContents({
filename,
module,
}: {
filename: string
module: string
}) {
const resolvedPath = p.resolve(p.dirname(filename), module)
const code = fs.readFileSync(require.resolve(resolvedPath))
return {code, resolvedPath}
}

Suggested fix

I'm not 100% sure how the lookup is meant to work here, but perhaps this could be replaced with the resolve module to take into account both relative imports and module-style ones?

How to return object literal?

codegen.macro: 3.0

Relevant code or config

// or shorthand property
const obj = codegen`
  module.exports = '{fn: function() {}}'
`

What you did:

{ SyntaxError: Unexpected token (2:13)
  1 | /* @babel/template */;
> 2 | {fn: function() {}}

And if using arrow function, it returns an IIFE:

const obj = codegen`
  module.exports = '{fn: () => {}}'
`
// =>
const obj = function () {
  {
    fn: () => {};
  }
}();

// workaround, add `return`:
const obj = codegen`
  module.exports = 'return {fn: () => {}}'
`
// =>
const obj = function () {
  return {
    fn: () => {}
  };
}();

Output duplicated CommentBlock

  • babel-plugin-codegen version: git repo default branch
  • node version: v14.17.4
  • npm version: 7.21.0

Relevant code or config

// build workflow within kentcdodds/babel-plugin-codegen
// test unit `codegen includes code comments: includes code comments 1`

What you did:

Reproduce

$ git clone https://github.com/kentcdodds/babel-plugin-codegen
$ cd babel-plugin-codegen
$ npm install
$ npm run test:update
$ git difftool -t meld --dir-diff HEAD

What happened:

Actual

exports[`codegen includes code comments: includes code comments 1`] = `

codegen\`
  module.exports = \\\`
    // before
    var x = 'hi'
    /*
     * after
     */

    // call foo
    console.log(foo())

     /**
      * jsdoc
      * @return {string} cool I guess
      */
     function foo() {
       return 'foo'
     }
  \\\`
\`

      ↓ ↓ ↓ ↓ ↓ ↓

// before
var x = 'hi'
/*
 * after
 */
// call foo

/*
 * after
 */
// call foo
console.log(foo())
/**
 * jsdoc
 * @return {string} cool I guess
 */

/**
 * jsdoc
 * @return {string} cool I guess
 */
function foo() {
  return 'foo'
}


`;

Expected

exports[`codegen includes code comments: includes code comments 1`] = `

codegen\`
  module.exports = \\\`
    // before
    var x = 'hi'
    /*
     * after
     */

    // call foo
    console.log(foo())

     /**
      * jsdoc
      * @return {string} cool I guess
      */
     function foo() {
       return 'foo'
     }
  \\\`
\`

      ↓ ↓ ↓ ↓ ↓ ↓

// before
var x = 'hi'
/*
 * after
 */
// call foo

console.log(foo())
/**
 * jsdoc
 * @return {string} cool I guess
 */

function foo() {
  return 'foo'
}


`;

Reproduction repository:

https://github.com/kentcdodds/babel-plugin-codegen

Problem description:
Output duplicated CommentBlock.

As you can see, it is expected to be seen one jsdoc block, but actually current kentcdodds/babel-plugin-codegen output duplicated jsdoc block, which is wrong.

Suggested solution:

Support new babel feature allowing plugins to indicate external dependencies

Hey Kent, thanks for this awesome plugin, been using it for years and it's really handy! Also saw you got in a car accident recently and I hope you're not too beat up and recovering well.

I've been following this feature which just got merged to babel: babel/babel#14065

I think that might be useful for this plugin to implement. It could allow us to invalidate the codegen output if the code has a dependency on some files on disk.

It seems pretty simple to utilize the new feature, if I'm right you just call api.addExternalDependency(external) where external is a filepath. https://github.com/babel/babel/pull/14065/files#diff-02893c5f57e6e79d081162d32cbfe84ccfac5ed70b8933be563e1dd7256f179cR15


Here's an example of a codegen module whose result depends on files on the filesystem, and could benefit from external dependency awareness:

// @codegen
const join = require('lodash/join')
const replace = require('lodash/replace')
const glob = require('glob')
const path = require('path')

const examplesFiles = glob.sync(path.resolve(__dirname, '**/examples.*'))

export default `export default {
  ${join(examplesFiles.map((exampleFile) => {
    const chopSrcFromPath = replace(exampleFile, /(.*):?src\//, '')
    return `'${chopSrcFromPath}': require('./${chopSrcFromPath}')`
  }), ',\n')}
}
/* 02-03-2022-09:22:00 */`

Right now we resort to updating the timestamp comment to force an invalidation + codegen rebuild. (Maybe there's a better way that I don't know about?)

I'm not sure the internals of this library but do you think it makes sense to implement? I might be able to take a stab at implementing it. Let me know if you have any pointers. Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.