[
  {
    "path": ".all-contributorsrc",
    "content": "{\n  \"projectName\": \"babel-plugin-macros\",\n  \"projectOwner\": \"kentcdodds\",\n  \"imageSize\": 100,\n  \"commit\": false,\n  \"contributorsPerLine\": 7,\n  \"repoHost\": \"https://github.com\",\n  \"repoType\": \"github\",\n  \"skipCi\": false,\n  \"files\": [\n    \"README.md\"\n  ],\n  \"contributors\": [\n    {\n      \"login\": \"kentcdodds\",\n      \"name\": \"Kent C. Dodds\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/1500684?v=3\",\n      \"profile\": \"https://kentcdodds.com\",\n      \"contributions\": [\n        \"code\",\n        \"doc\",\n        \"infra\",\n        \"test\"\n      ]\n    },\n    {\n      \"login\": \"threepointone\",\n      \"name\": \"Sunil Pai\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/18808?v=3\",\n      \"profile\": \"https://github.com/threepointone\",\n      \"contributions\": [\n        \"ideas\"\n      ]\n    },\n    {\n      \"login\": \"suchipi\",\n      \"name\": \"Lily Scott\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/1341513?v=4\",\n      \"profile\": \"http://suchipi.com\",\n      \"contributions\": [\n        \"question\",\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"dralletje\",\n      \"name\": \"Michiel Dral\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/767261?v=4\",\n      \"profile\": \"http://twitter.com/dralletje\",\n      \"contributions\": [\n        \"ideas\"\n      ]\n    },\n    {\n      \"login\": \"tkh44\",\n      \"name\": \"Kye Hohenberger\",\n      \"avatar_url\": \"https://avatars2.githubusercontent.com/u/662750?v=4\",\n      \"profile\": \"https://github.com/tkh44\",\n      \"contributions\": [\n        \"ideas\"\n      ]\n    },\n    {\n      \"login\": \"mitchellhamilton\",\n      \"name\": \"Mitchell Hamilton\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/11481355?v=4\",\n      \"profile\": \"https://hamil.town\",\n      \"contributions\": [\n        \"code\",\n        \"test\"\n      ]\n    },\n    {\n      \"login\": \"wKovacs64\",\n      \"name\": \"Justin Hall\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/1288694?v=4\",\n      \"profile\": \"https://github.com/wKovacs64\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"PiereDome\",\n      \"name\": \"Brian Pedersen\",\n      \"avatar_url\": \"https://avatars3.githubusercontent.com/u/1903016?v=4\",\n      \"profile\": \"https://github.com/PiereDome\",\n      \"contributions\": [\n        \"code\",\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"apalm\",\n      \"name\": \"Andrew Palm\",\n      \"avatar_url\": \"https://avatars3.githubusercontent.com/u/4495237?v=4\",\n      \"profile\": \"https://github.com/apalm\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"evenchange4\",\n      \"name\": \"Michael Hsu\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/1527371?v=4\",\n      \"profile\": \"https://michaelhsu.tw/\",\n      \"contributions\": [\n        \"doc\",\n        \"plugin\"\n      ]\n    },\n    {\n      \"login\": \"citycide\",\n      \"name\": \"Bo Lingen\",\n      \"avatar_url\": \"https://avatars2.githubusercontent.com/u/16605186?v=4\",\n      \"profile\": \"https://github.com/citycide\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"tylerthehaas\",\n      \"name\": \"Tyler Haas\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/11150235?v=4\",\n      \"profile\": \"https://github.com/tylerthehaas\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"FWeinb\",\n      \"name\": \"FWeinb\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/1250430?v=4\",\n      \"profile\": \"https://github.com/FWeinb\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"tricoder42\",\n      \"name\": \"Tomáš Ehrlich\",\n      \"avatar_url\": \"https://avatars2.githubusercontent.com/u/827862?v=4\",\n      \"profile\": \"http://www.tomasehrlich.cz\",\n      \"contributions\": [\n        \"bug\",\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"jgierer12\",\n      \"name\": \"Jonas Gierer\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/4331946?v=4\",\n      \"profile\": \"https://github.com/jgierer12\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"lPadier\",\n      \"name\": \"Loïc Padier\",\n      \"avatar_url\": \"https://avatars2.githubusercontent.com/u/4009640?v=4\",\n      \"profile\": \"http://loicpadier.com\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"pshrmn\",\n      \"name\": \"Paul Sherman\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/1127037?v=4\",\n      \"profile\": \"https://www.pshrmn.com\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"conartist6\",\n      \"name\": \"Conrad Buck\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/540777?v=4\",\n      \"profile\": \"http://burningpotato.com\",\n      \"contributions\": [\n        \"code\",\n        \"test\",\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"InvictusMB\",\n      \"name\": \"InvictusMB\",\n      \"avatar_url\": \"https://avatars3.githubusercontent.com/u/3091209?v=4\",\n      \"profile\": \"https://github.com/InvictusMB\",\n      \"contributions\": [\n        \"test\"\n      ]\n    },\n    {\n      \"login\": \"coderberry\",\n      \"name\": \"Eric Berry\",\n      \"avatar_url\": \"https://avatars2.githubusercontent.com/u/12481?v=4\",\n      \"profile\": \"https://codefund.io\",\n      \"contributions\": [\n        \"fundingFinding\"\n      ]\n    },\n    {\n      \"login\": \"futagoza\",\n      \"name\": \"Futago-za Ryuu\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/1943570?v=4\",\n      \"profile\": \"http://futagoza.github.io/\",\n      \"contributions\": [\n        \"code\",\n        \"test\"\n      ]\n    },\n    {\n      \"login\": \"lucleray\",\n      \"name\": \"Luc\",\n      \"avatar_url\": \"https://avatars3.githubusercontent.com/u/6616955?v=4\",\n      \"profile\": \"https://luc.im\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"wintercounter\",\n      \"name\": \"Victor Vincent\",\n      \"avatar_url\": \"https://avatars2.githubusercontent.com/u/963776?v=4\",\n      \"profile\": \"http://wintercounter.me\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"mvasilkov\",\n      \"name\": \"я котик пур-пур\",\n      \"avatar_url\": \"https://avatars3.githubusercontent.com/u/140257?v=4\",\n      \"profile\": \"http://mvasilkov.ovh\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"soska\",\n      \"name\": \"Armando Sosa\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/139577?v=4\",\n      \"profile\": \"http://armandososa.com\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"matvp91\",\n      \"name\": \"Matthias\",\n      \"avatar_url\": \"https://avatars3.githubusercontent.com/u/12699796?v=4\",\n      \"profile\": \"https://github.com/matvp91\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"JoviDeCroock\",\n      \"name\": \"Jovi De Croock\",\n      \"avatar_url\": \"https://avatars3.githubusercontent.com/u/17125876?v=4\",\n      \"profile\": \"https://www.jovidecroock.com/\",\n      \"contributions\": [\n        \"code\",\n        \"test\"\n      ]\n    },\n    {\n      \"login\": \"VictorArowo\",\n      \"name\": \"Victor Arowo\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/25545108?v=4\",\n      \"profile\": \"http://victorarowo.com\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"alexanderchan\",\n      \"name\": \"Alex Chan\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/1864372?v=4\",\n      \"profile\": \"https://twitter.com/alexandermchan\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"probablyup\",\n      \"name\": \"Evan Jacobs\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/570070?v=4\",\n      \"profile\": \"https://probablyup.com\",\n      \"contributions\": [\n        \"code\"\n      ]\n    }\n  ]\n}\n"
  },
  {
    "path": ".gitattributes",
    "content": "* text=auto eol=lf\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE.md",
    "content": "<!--\nThanks for your interest in the project. I appreciate bugs filed and PRs submitted!\nPlease make sure that you are familiar with and follow the Code of Conduct for\nthis project (found in the CODE_OF_CONDUCT.md file).\n\nPlease fill out this template with all the relevant information so we can\nunderstand what's going on and fix the issue.\n\nI'll probably ask you to submit the fix (after giving some direction). If you've\nnever done that before, that's great! Check this free short video tutorial to\nlearn how: http://kcd.im/pull-request\n-->\n\n- `babel-plugin-macros` version:\n- `node` version:\n- `npm` version:\n\nRelevant code or config\n\n```javascript\n\n```\n\nWhat you did:\n\nWhat happened:\n\n<!-- Please provide the full error message/screenshots/anything -->\n\nReproduction repository:\n\n<!--\nIf possible, please create a repository that reproduces the issue with the\nminimal amount of code possible.\n-->\n\nProblem description:\n\nSuggested solution:\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "<!--\nThanks for your interest in the project. Bugs filed and PRs submitted are appreciated!\n\nPlease make sure that you are familiar with and follow the Code of Conduct for\nthis project (found in the CODE_OF_CONDUCT.md file).\n\nAlso, please make sure you're familiar with and follow the instructions in the\ncontributing guidelines (found in the CONTRIBUTING.md file).\n\nIf you're new to contributing to open source projects, you might find this free\nvideo course helpful: http://kcd.im/pull-request\n\nPlease fill out the information below to expedite the review and (hopefully)\nmerge of your pull request!\n-->\n\n<!-- What changes are being made? (What feature/bug is being fixed here?) -->\n\n**What**:\n\n<!-- Why are these changes necessary? -->\n\n**Why**:\n\n<!-- How were these changes implemented? -->\n\n**How**:\n\n<!-- Have you done all of these things?  -->\n\n**Checklist**:\n\n<!-- add \"N/A\" to the end of each line that's irrelevant to your changes -->\n<!-- to check an item, place an \"x\" in the box like so: \"- [x] Documentation\" -->\n\n- [ ] Documentation\n- [ ] Tests\n- [ ] Ready to be merged\n      <!-- In your opinion, is this ready to be merged as soon as it's reviewed? -->\n\n<!-- feel free to add additional comments -->\n"
  },
  {
    "path": ".github/workflows/validate.yml",
    "content": "name: validate\non:\n  push:\n    branches:\n      - '+([0-9])?(.{+([0-9]),x}).x'\n      - 'main'\n      - 'next'\n      - 'next-major'\n      - 'beta'\n      - 'alpha'\n      - '!all-contributors/**'\n  pull_request: {}\njobs:\n  main:\n    # ignore all-contributors PRs\n    if: ${{ !contains(github.head_ref, 'all-contributors') }}\n    strategy:\n      matrix:\n        node: [10.13, 12, 14, 15]\n    runs-on: ubuntu-latest\n    steps:\n      - name: ⬇️ Checkout repo\n        uses: actions/checkout@v2\n\n      - name: ⎔ Setup node\n        uses: actions/setup-node@v1\n        with:\n          node-version: ${{ matrix.node }}\n\n      - name: 📥 Download deps\n        uses: bahmutov/npm-install@v1\n        with:\n          useLockFile: false\n\n      - name: ▶️ Run validate script\n        run: npm run validate\n\n      - name: ⬆️ Upload coverage report\n        uses: codecov/codecov-action@v1\n\n  release:\n    needs: main\n    runs-on: ubuntu-latest\n    if:\n      ${{ github.repository == 'kentcdodds/babel-plugin-macros' &&\n      contains('refs/heads/main,refs/heads/beta,refs/heads/next,refs/heads/alpha',\n      github.ref) && github.event_name == 'push' }}\n    steps:\n      - name: ⬇️ Checkout repo\n        uses: actions/checkout@v2\n\n      - name: ⎔ Setup node\n        uses: actions/setup-node@v1\n        with:\n          node-version: 14\n\n      - name: 📥 Download deps\n        uses: bahmutov/npm-install@v1\n        with:\n          useLockFile: false\n\n      - name: 🚀 Release\n        uses: cycjimmy/semantic-release-action@v2\n        with:\n          semantic_version: 17\n          branches: |\n            [\n              '+([0-9])?(.{+([0-9]),x}).x',\n              'main',\n              'next',\n              'next-major',\n              {name: 'beta', prerelease: true},\n              {name: 'alpha', prerelease: true}\n            ]\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}\n"
  },
  {
    "path": ".gitignore",
    "content": "node_modules\ncoverage\ndist\n.DS_Store\n\n# these cause more harm than good\n# when working with contributors\npackage-lock.json\nyarn.lock\n"
  },
  {
    "path": ".huskyrc.js",
    "content": "module.exports = require('kcd-scripts/husky')\n"
  },
  {
    "path": ".npmrc",
    "content": "registry=https://registry.npmjs.org/\n"
  },
  {
    "path": ".prettierignore",
    "content": "node_modules\ncoverage\ndist\n"
  },
  {
    "path": ".prettierrc.js",
    "content": "module.exports = require('kcd-scripts/prettier')\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# CHANGELOG\n\nThe changelog is automatically updated using\n[semantic-release](https://github.com/semantic-release/semantic-release). You\ncan see it on the [releases page](../../releases).\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nWe as members, contributors, and leaders pledge to make participation in our\ncommunity a harassment-free experience for everyone, regardless of age, body\nsize, visible or invisible disability, ethnicity, sex characteristics, gender\nidentity and expression, level of experience, education, socio-economic status,\nnationality, personal appearance, race, religion, or sexual identity and\norientation.\n\nWe pledge to act and interact in ways that contribute to an open, welcoming,\ndiverse, inclusive, and healthy community.\n\n## Our Standards\n\nExamples of behavior that contributes to a positive environment for our\ncommunity include:\n\n- Demonstrating empathy and kindness toward other people\n- Being respectful of differing opinions, viewpoints, and experiences\n- Giving and gracefully accepting constructive feedback\n- Accepting responsibility and apologizing to those affected by our mistakes,\n  and learning from the experience\n- Focusing on what is best not just for us as individuals, but for the overall\n  community\n\nExamples of unacceptable behavior include:\n\n- The use of sexualized language or imagery, and sexual attention or advances of\n  any kind\n- Trolling, insulting or derogatory comments, and personal or political attacks\n- Public or private harassment\n- Publishing others' private information, such as a physical or email address,\n  without their explicit permission\n- Other conduct which could reasonably be considered inappropriate in a\n  professional setting\n\n## Enforcement Responsibilities\n\nCommunity leaders are responsible for clarifying and enforcing our standards of\nacceptable behavior and will take appropriate and fair corrective action in\nresponse to any behavior that they deem inappropriate, threatening, offensive,\nor harmful.\n\nCommunity leaders have the right and responsibility to remove, edit, or reject\ncomments, commits, code, wiki edits, issues, and other contributions that are\nnot aligned to this Code of Conduct, and will communicate reasons for moderation\ndecisions when appropriate.\n\n## Scope\n\nThis Code of Conduct applies within all community spaces, and also applies when\nan individual is officially representing the community in public spaces.\nExamples of representing our community include using an official e-mail address,\nposting via an official social media account, or acting as an appointed\nrepresentative at an online or offline event.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported to the community leaders responsible for enforcement at\nme+coc@kentcdodds.com. All complaints will be reviewed and investigated promptly\nand fairly.\n\nAll community leaders are obligated to respect the privacy and security of the\nreporter of any incident.\n\n## Enforcement Guidelines\n\nCommunity leaders will follow these Community Impact Guidelines in determining\nthe consequences for any action they deem in violation of this Code of Conduct:\n\n### 1. Correction\n\n**Community Impact**: Use of inappropriate language or other behavior deemed\nunprofessional or unwelcome in the community.\n\n**Consequence**: A private, written warning from community leaders, providing\nclarity around the nature of the violation and an explanation of why the\nbehavior was inappropriate. A public apology may be requested.\n\n### 2. Warning\n\n**Community Impact**: A violation through a single incident or series of\nactions.\n\n**Consequence**: A warning with consequences for continued behavior. No\ninteraction with the people involved, including unsolicited interaction with\nthose enforcing the Code of Conduct, for a specified period of time. This\nincludes avoiding interactions in community spaces as well as external channels\nlike social media. Violating these terms may lead to a temporary or permanent\nban.\n\n### 3. Temporary Ban\n\n**Community Impact**: A serious violation of community standards, including\nsustained inappropriate behavior.\n\n**Consequence**: A temporary ban from any sort of interaction or public\ncommunication with the community for a specified period of time. No public or\nprivate interaction with the people involved, including unsolicited interaction\nwith those enforcing the Code of Conduct, is allowed during this period.\nViolating these terms may lead to a permanent ban.\n\n### 4. Permanent Ban\n\n**Community Impact**: Demonstrating a pattern of violation of community\nstandards, including sustained inappropriate behavior, harassment of an\nindividual, or aggression toward or disparagement of classes of individuals.\n\n**Consequence**: A permanent ban from any sort of public interaction within the\ncommunity.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage],\nversion 2.0, available at\nhttps://www.contributor-covenant.org/version/2/0/code_of_conduct.html.\n\nCommunity Impact Guidelines were inspired by\n[Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity).\n\n[homepage]: https://www.contributor-covenant.org\n\nFor answers to common questions about this code of conduct, see the FAQ at\nhttps://www.contributor-covenant.org/faq. Translations are available at\nhttps://www.contributor-covenant.org/translations.\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing\n\nThanks for being willing to contribute!\n\n**Working on your first Pull Request?** You can learn how from this _free_\nseries [How to Contribute to an Open Source Project on GitHub][egghead]\n\n## Project setup\n\n1. Fork and clone the repo\n2. Run `npm run setup -s` to install dependencies and run validation\n3. Create a branch for your PR with `git checkout -b pr/your-branch-name`\n\n> Tip: Keep your `main` branch pointing at the original repository and make pull\n> requests from branches on your fork. To do this, run:\n>\n> ```\n> git remote add upstream https://github.com/kentcdodds/babel-plugin-macros\n> git fetch upstream\n> git branch --set-upstream-to=upstream/main main\n> ```\n>\n> This will add the original repository as a \"remote\" called \"upstream,\" Then\n> fetch the git information from that remote, then set your local `main` branch\n> to use the upstream main branch whenever you run `git pull`. Then you can make\n> all of your pull request branches based on this `main` branch. Whenever you\n> want to update your version of `main`, do a regular `git pull`.\n\n## Committing and Pushing changes\n\nPlease make sure to run the tests before you commit your changes. You can run\n`npm run test:update` which will update any snapshots that need updating. Make\nsure to include those changes (if they exist) in your commit.\n\n## Help needed\n\nPlease checkout the [the open issues][issues]\n\nAlso, please watch the repo and respond to questions/bug reports/feature\nrequests! Thanks!\n\n<!-- prettier-ignore-start -->\n[egghead]: https://app.egghead.io/playlists/how-to-contribute-to-an-open-source-project-on-github\n[all-contributors]: https://github.com/all-contributors/all-contributors\n[issues]: https://github.com/kentcdodds/babel-plugin-macros/issues\n<!-- prettier-ignore-end -->\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\nCopyright (c) 2020 Kent C. Dodds\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "<div align=\"center\">\n<h1>babel-plugin-macros 🎣</h1>\n\n<p>Allows you to build simple compile-time libraries</p>\n</div>\n\n---\n\n<!-- prettier-ignore-start -->\n[![Build Status][build-badge]][build]\n[![Code Coverage][coverage-badge]][coverage]\n[![version][version-badge]][package]\n[![downloads][downloads-badge]][npmtrends]\n[![MIT License][license-badge]][license]\n[![All Contributors][all-contributors-badge]](#contributors-)\n[![PRs Welcome][prs-badge]][prs]\n[![Code of Conduct][coc-badge]][coc]\n<!-- prettier-ignore-end -->\n\n## The problem\n\nCheck out\n[this guest post](https://babeljs.io/blog/2017/09/11/zero-config-with-babel-macros)\non the Babel.js blog for a complete write up on the problem, motivation, and\nsolution.\n\nCurrently, each babel plugin in the babel ecosystem requires that you configure\nit individually. This is fine for things like language features, but can be\nfrustrating overhead for libraries that allow for compile-time code\ntransformation as an optimization.\n\n## This solution\n\nbabel-plugin-macros defines a standard interface for libraries that want to use\ncompile-time code transformation without requiring the user to add a babel\nplugin to their build system (other than `babel-plugin-macros`, which is ideally\nalready in place).\n\n<details>\n\n<summary>Expand for more details on the motivation</summary>\n\nFor instance, many css-in-js libraries have a css tagged template string\nfunction:\n\n```js\nconst styles = css`\n  .red {\n    color: red;\n  }\n`\n```\n\nThe function compiles your css into (for example) an object with generated class\nnames for each of the classes you defined in your css:\n\n```js\nconsole.log(styles) // { red: \"1f-d34j8rn43y587t\" }\n```\n\nThis class name can be generated at runtime (in the browser), but this has some\ndisadvantages:\n\n- There is cpu usage/time overhead; the client needs to run the code to generate\n  these classes every time the page loads\n- There is code bundle size overhead; the client needs to receive a CSS parser\n  in order to generate these class names, and shipping this makes the amount of\n  js the client needs to parse larger.\n\nTo help solve those issues, many css-in-js libraries write their own babel\nplugin that generates the class names at compile-time instead of runtime:\n\n```js\n// Before running through babel:\nconst styles = css`\n  .red {\n    color: red;\n  }\n`\n// After running through babel, with the library-specific plugin:\nconst styles = {red: '1f-d34j8rn43y587t'}\n```\n\nIf the css-in-js library supported babel-plugin-macros instead, then they\nwouldn't need their own babel plugin to compile these out; they could instead\nrely on babel-plugin-macros to do it for them. So if a user already had\n`babel-plugin-macros` installed and configured with babel, then they wouldn't\nneed to change their babel configuration to get the compile-time benefits of the\nlibrary. This would be most useful if the boilerplate they were using came with\n`babel-plugin-macros` out of the box, which is true for\n[`create-react-app`][cra].\n\nAlthough css-in-js is the most common example, there are lots of other things\nyou could use `babel-plugin-macros` for, like:\n\n- Compiling GraphQL fragments into objects so that the client doesn't need a\n  GraphQL parser\n- Eval-ing out code at compile time that will be baked into the runtime code,\n  for instance to get a list of directories in the filesystem (see\n  [preval][preval])\n\n</details>\n\n## Table of Contents\n\n<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n\n- [Installation](#installation)\n- [Usage](#usage)\n  - [User docs](#user-docs)\n  - [Author docs](#author-docs)\n  - [Caveats](#caveats)\n- [FAQ](#faq)\n  - [How do I find available macros?](#how-do-i-find-available-macros)\n  - [What's the difference between babel plugins and macros?](#whats-the-difference-between-babel-plugins-and-macros)\n  - [In what order are macros executed?](#in-what-order-are-macros-executed)\n  - [Does it work with function calls only?](#does-it-work-with-function-calls-only)\n  - [How about implicit optimizations at compile time?](#how-about-implicit-optimizations-at-compile-time)\n- [Inspiration](#inspiration)\n- [Other Solutions](#other-solutions)\n- [Issues](#issues)\n  - [🐛 Bugs](#-bugs)\n  - [💡 Feature Requests](#-feature-requests)\n- [Contributors ✨](#contributors-)\n- [LICENSE](#license)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n## Installation\n\nThis module is distributed via [npm][npm] which is bundled with [node][node] and\nshould be installed as one of your project's `devDependencies`:\n\n```\nnpm install --save-dev babel-plugin-macros\n```\n\n## Usage\n\n> You may like to watch\n> [this YouTube video](https://www.youtube.com/watch?v=1queadQ0048&list=PLV5CVI1eNcJgCrPH_e6d57KRUTiDZgs0u)\n> to get an idea of what macros is and how it can be used.\n\n### User docs\n\nAre you trying to use `babel-plugin-macros`? Go to\n[`other/docs/user.md`](other/docs/user.md).\n\n### Author docs\n\nAre you trying to make your own macros that works with `babel-plugin-macros`? Go\nto [`other/docs/author.md`](other/docs/author.md). (you should probably read the\nuser docs too).\n\n### Caveats\n\n#### Babel cache problem\n\n> **Note:** This issue is not present when used in Create React App.\n\nMost of the time you'll probably be using this with the babel cache enabled in\nwebpack to rebuild faster. If your macro function is **not pure** which gets\ndifferent output with same code (e.g., IO side effects) it will cause recompile\nmechanism fail. Unfortunately you'll also experience this problem while\ndeveloping your macro as well. If there's not a change to the source code that's\nbeing transpiled, then babel will use the cache rather than running your macro\nagain.\n\nFor now, to force recompile the code you can simply add a cache busting comment\nin the file:\n\n```diff\nimport macro from 'non-pure.macro';\n\n-// Do some changes of your code or\n+// add a cache busting comment to force recompile.\nmacro('parameters');\n```\n\nThis problem is still being worked on and is not unique to\n`babel-plugin-macros`. For more details and workarounds, please check related\nissues below:\n\n- babel-plugin-preval:\n  [How to force recompile? #19](https://github.com/kentcdodds/babel-plugin-preval/issues/19)\n- graphql.macro:\n  [Recompile problem (babel cache) #6](https://github.com/evenchange4/graphql.macro/issues/6)\n- twin.macro: \n  [Can't change taliwind config #37](https://github.com/ben-rogerson/twin.macro/discussions/37)\n\n## FAQ\n\n### How do I find available macros?\n\nYou can write your own without publishing them to `npm`, but if you'd like to\nsee existing macros you can add to your project, then take a look at the\n[Awesome babel macros](https://github.com/jgierer12/awesome-babel-macros)\nrepository.\n\nPlease add any you don't see listed!\n\n### What's the difference between babel plugins and macros?\n\nLet's use\n[`babel-plugin-console`](https://www.npmjs.com/package/babel-plugin-console) as\nan example.\n\nIf we used `babel-plugin-console`, it would look like this:\n\n1.  Add `babel-plugin-console` to `.babelrc`\n2.  Use it in a code:\n\n```js\nfunction add100(a) {\n  const oneHundred = 100\n  console.scope('Add 100 to another number')\n  return add(a, oneHundred)\n}\n\nfunction add(a, b) {\n  return a + b\n}\n```\n\nWhen that code is run, the `scope` function does some pretty nifty things:\n\n**Browser:**\n\n![Browser console scoping add100](https://github.com/mattphillips/babel-plugin-console/raw/53536cba919d5be49d4f66d957769c07ca7a4207/assets/add100-chrome.gif)\n\n**Node:**\n\n<img alt=\"Node console scoping add100\" src=\"https://github.com/mattphillips/babel-plugin-console/raw/53536cba919d5be49d4f66d957769c07ca7a4207/assets/add100-node.png\" width=\"372\" />\n\nInstead, let's use the macro it's shipped with like this:\n\n1.  Add `babel-plugin-macros` to `.babelrc` (only once for all macros)\n2.  Use it in a code:\n\n```js\nimport scope from 'babel-plugin-console/scope.macro'\nfunction add100(a) {\n  const oneHundred = 100\n  scope('Add 100 to another number')\n  return add(a, oneHundred)\n}\n\nfunction add(a, b) {\n  return a + b\n}\n```\n\nThe result is exactly the same, but this approach has a few advantages:\n\n**Advantages:**\n\n- requires only one entry in `.babelrc` for all macros used in project. Add that\n  once and you can use all the macros you want\n- toolkits (like [create-react-app][cra]) may already support\n  `babel-plugin-macros`, so no configuration is needed at all\n- it's explicit. With `console.scope` people may be fooled that it's just a\n  normal `console` API when there's really a babel transpilation going on. When\n  you import `scope`, it's obvious that it's macro and does something with the\n  code at compile time. Some ESLint rules may also have issues with plugins that\n  look for \"global\" variables\n- macros are safer and easier to write, because they receive exactly the AST\n  node to process\n- If you misconfigure `babel-plugin-console` you wont find out until you run the\n  code. If you misconfigure `babel-plugin-macros` you'll get a compile-time\n  error.\n\n**Drawbacks:**\n\n- Cannot (should not) be used for implicit transpilations (like syntax plugins)\n- Explicitness is more verbose. Which some people might consider a drawback...\n\n### In what order are macros executed?\n\nThis is another advantage of `babel-plugin-macros` over regular plugins. The\nuser of the macro is in control of the ordering! The order of execution is the\nsame order as imported. The order of execution is clear, explicit and in full\ncontrol of the user:\n\n```js\nimport preval from 'preval.macro'\nimport idx from 'idx.macro'\n\n// preval macro is evaluated first, then idx\n```\n\nThis differs from the current situation with babel plugins where it's\nprohibitively difficult to control the order plugins run in a particular file.\n\n### Does it work with function calls only?\n\nNo! Any AST node type is supported.\n\nIt can be tagged template literal:\n\n```js\nimport eval from 'eval.macro'\nconst val = eval`7 * 6`\n```\n\nA function:\n\n```js\nimport eval from 'eval.macro'\nconst val = eval('7 * 6')\n```\n\nJSX Element:\n\n```js\nimport Eval from 'eval.macro'\nconst val = <Eval>7 * 6</Eval>\n```\n\nReally, anything...\n\nSee the [testing snapshot](src/__tests__/__snapshots__/index.js.snap) for more\nexamples.\n\n### How about implicit optimizations at compile time?\n\nAll examples above were _explicit_ - a macro was imported and then evaluated\nwith a specific AST node.\n\nCompletely different story are _implicit_ babel plugins, like\n[transform-react-constant-elements](https://babeljs.io/docs/plugins/transform-react-constant-elements/),\nwhich process whole AST tree.\n\nExplicit is often a better pattern than implicit because it requires others to\nunderstand how things are globally configured. This is in this spirit are\n`babel-plugin-macros` designed. However, some things _do_ need to be implicit,\nand those kinds of babel plugins can't be turned into macros.\n\n## Inspiration\n\n- [threepointone/babel-plugin-macros](https://github.com/threepointone/babel-plugin-macros)\n- [facebookincubator/create-react-app#2730][cra-issue]\n\nThank you to [@phpnode](https://github.com/phpnode) for donating the npm package\n`babel-plugin-macros`.\n\n## Other Solutions\n\n- [sweetjs](http://sweetjs.org/)\n\n## Issues\n\n_Looking to contribute? Look for the [Good First Issue][good-first-issue]\nlabel._\n\n### 🐛 Bugs\n\nPlease file an issue for bugs, missing documentation, or unexpected behavior.\n\n[**See Bugs**][bugs]\n\n### 💡 Feature Requests\n\nPlease file an issue to suggest new features. Vote on feature requests by adding\na 👍. This helps maintainers prioritize what to work on.\n\n[**See Feature Requests**][requests]\n\n## Contributors ✨\n\nThanks goes to these people ([emoji key][emojis]):\n\n<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->\n<!-- prettier-ignore-start -->\n<!-- markdownlint-disable -->\n<table>\n  <tr>\n    <td align=\"center\"><a href=\"https://kentcdodds.com\"><img src=\"https://avatars.githubusercontent.com/u/1500684?v=3?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>Kent C. Dodds</b></sub></a><br /><a href=\"https://github.com/kentcdodds/babel-plugin-macros/commits?author=kentcdodds\" title=\"Code\">💻</a> <a href=\"https://github.com/kentcdodds/babel-plugin-macros/commits?author=kentcdodds\" title=\"Documentation\">📖</a> <a href=\"#infra-kentcdodds\" title=\"Infrastructure (Hosting, Build-Tools, etc)\">🚇</a> <a href=\"https://github.com/kentcdodds/babel-plugin-macros/commits?author=kentcdodds\" title=\"Tests\">⚠️</a></td>\n    <td align=\"center\"><a href=\"https://github.com/threepointone\"><img src=\"https://avatars1.githubusercontent.com/u/18808?v=3?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>Sunil Pai</b></sub></a><br /><a href=\"#ideas-threepointone\" title=\"Ideas, Planning, & Feedback\">🤔</a></td>\n    <td align=\"center\"><a href=\"http://suchipi.com\"><img src=\"https://avatars0.githubusercontent.com/u/1341513?v=4?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>Lily Scott</b></sub></a><br /><a href=\"#question-suchipi\" title=\"Answering Questions\">💬</a> <a href=\"https://github.com/kentcdodds/babel-plugin-macros/commits?author=suchipi\" title=\"Documentation\">📖</a></td>\n    <td align=\"center\"><a href=\"http://twitter.com/dralletje\"><img src=\"https://avatars1.githubusercontent.com/u/767261?v=4?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>Michiel Dral</b></sub></a><br /><a href=\"#ideas-dralletje\" title=\"Ideas, Planning, & Feedback\">🤔</a></td>\n    <td align=\"center\"><a href=\"https://github.com/tkh44\"><img src=\"https://avatars2.githubusercontent.com/u/662750?v=4?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>Kye Hohenberger</b></sub></a><br /><a href=\"#ideas-tkh44\" title=\"Ideas, Planning, & Feedback\">🤔</a></td>\n    <td align=\"center\"><a href=\"https://hamil.town\"><img src=\"https://avatars1.githubusercontent.com/u/11481355?v=4?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>Mitchell Hamilton</b></sub></a><br /><a href=\"https://github.com/kentcdodds/babel-plugin-macros/commits?author=mitchellhamilton\" title=\"Code\">💻</a> <a href=\"https://github.com/kentcdodds/babel-plugin-macros/commits?author=mitchellhamilton\" title=\"Tests\">⚠️</a></td>\n    <td align=\"center\"><a href=\"https://github.com/wKovacs64\"><img src=\"https://avatars1.githubusercontent.com/u/1288694?v=4?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>Justin Hall</b></sub></a><br /><a href=\"https://github.com/kentcdodds/babel-plugin-macros/commits?author=wKovacs64\" title=\"Documentation\">📖</a></td>\n  </tr>\n  <tr>\n    <td align=\"center\"><a href=\"https://github.com/PiereDome\"><img src=\"https://avatars3.githubusercontent.com/u/1903016?v=4?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>Brian Pedersen</b></sub></a><br /><a href=\"https://github.com/kentcdodds/babel-plugin-macros/commits?author=PiereDome\" title=\"Code\">💻</a> <a href=\"https://github.com/kentcdodds/babel-plugin-macros/commits?author=PiereDome\" title=\"Documentation\">📖</a></td>\n    <td align=\"center\"><a href=\"https://github.com/apalm\"><img src=\"https://avatars3.githubusercontent.com/u/4495237?v=4?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>Andrew Palm</b></sub></a><br /><a href=\"https://github.com/kentcdodds/babel-plugin-macros/commits?author=apalm\" title=\"Code\">💻</a></td>\n    <td align=\"center\"><a href=\"https://michaelhsu.tw/\"><img src=\"https://avatars1.githubusercontent.com/u/1527371?v=4?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>Michael Hsu</b></sub></a><br /><a href=\"https://github.com/kentcdodds/babel-plugin-macros/commits?author=evenchange4\" title=\"Documentation\">📖</a> <a href=\"#plugin-evenchange4\" title=\"Plugin/utility libraries\">🔌</a></td>\n    <td align=\"center\"><a href=\"https://github.com/citycide\"><img src=\"https://avatars2.githubusercontent.com/u/16605186?v=4?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>Bo Lingen</b></sub></a><br /><a href=\"https://github.com/kentcdodds/babel-plugin-macros/commits?author=citycide\" title=\"Code\">💻</a></td>\n    <td align=\"center\"><a href=\"https://github.com/tylerthehaas\"><img src=\"https://avatars1.githubusercontent.com/u/11150235?v=4?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>Tyler Haas</b></sub></a><br /><a href=\"https://github.com/kentcdodds/babel-plugin-macros/commits?author=tylerthehaas\" title=\"Documentation\">📖</a></td>\n    <td align=\"center\"><a href=\"https://github.com/FWeinb\"><img src=\"https://avatars0.githubusercontent.com/u/1250430?v=4?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>FWeinb</b></sub></a><br /><a href=\"https://github.com/kentcdodds/babel-plugin-macros/commits?author=FWeinb\" title=\"Code\">💻</a></td>\n    <td align=\"center\"><a href=\"http://www.tomasehrlich.cz\"><img src=\"https://avatars2.githubusercontent.com/u/827862?v=4?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>Tomáš Ehrlich</b></sub></a><br /><a href=\"https://github.com/kentcdodds/babel-plugin-macros/issues?q=author%3Atricoder42\" title=\"Bug reports\">🐛</a> <a href=\"https://github.com/kentcdodds/babel-plugin-macros/commits?author=tricoder42\" title=\"Code\">💻</a></td>\n  </tr>\n  <tr>\n    <td align=\"center\"><a href=\"https://github.com/jgierer12\"><img src=\"https://avatars0.githubusercontent.com/u/4331946?v=4?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>Jonas Gierer</b></sub></a><br /><a href=\"https://github.com/kentcdodds/babel-plugin-macros/commits?author=jgierer12\" title=\"Documentation\">📖</a></td>\n    <td align=\"center\"><a href=\"http://loicpadier.com\"><img src=\"https://avatars2.githubusercontent.com/u/4009640?v=4?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>Loïc Padier</b></sub></a><br /><a href=\"https://github.com/kentcdodds/babel-plugin-macros/commits?author=lPadier\" title=\"Code\">💻</a></td>\n    <td align=\"center\"><a href=\"https://www.pshrmn.com\"><img src=\"https://avatars0.githubusercontent.com/u/1127037?v=4?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>Paul Sherman</b></sub></a><br /><a href=\"https://github.com/kentcdodds/babel-plugin-macros/commits?author=pshrmn\" title=\"Code\">💻</a></td>\n    <td align=\"center\"><a href=\"http://burningpotato.com\"><img src=\"https://avatars1.githubusercontent.com/u/540777?v=4?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>Conrad Buck</b></sub></a><br /><a href=\"https://github.com/kentcdodds/babel-plugin-macros/commits?author=conartist6\" title=\"Code\">💻</a> <a href=\"https://github.com/kentcdodds/babel-plugin-macros/commits?author=conartist6\" title=\"Tests\">⚠️</a> <a href=\"https://github.com/kentcdodds/babel-plugin-macros/commits?author=conartist6\" title=\"Documentation\">📖</a></td>\n    <td align=\"center\"><a href=\"https://github.com/InvictusMB\"><img src=\"https://avatars3.githubusercontent.com/u/3091209?v=4?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>InvictusMB</b></sub></a><br /><a href=\"https://github.com/kentcdodds/babel-plugin-macros/commits?author=InvictusMB\" title=\"Tests\">⚠️</a></td>\n    <td align=\"center\"><a href=\"https://codefund.io\"><img src=\"https://avatars2.githubusercontent.com/u/12481?v=4?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>Eric Berry</b></sub></a><br /><a href=\"#fundingFinding-coderberry\" title=\"Funding Finding\">🔍</a></td>\n    <td align=\"center\"><a href=\"http://futagoza.github.io/\"><img src=\"https://avatars1.githubusercontent.com/u/1943570?v=4?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>Futago-za Ryuu</b></sub></a><br /><a href=\"https://github.com/kentcdodds/babel-plugin-macros/commits?author=futagoza\" title=\"Code\">💻</a> <a href=\"https://github.com/kentcdodds/babel-plugin-macros/commits?author=futagoza\" title=\"Tests\">⚠️</a></td>\n  </tr>\n  <tr>\n    <td align=\"center\"><a href=\"https://luc.im\"><img src=\"https://avatars3.githubusercontent.com/u/6616955?v=4?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>Luc</b></sub></a><br /><a href=\"https://github.com/kentcdodds/babel-plugin-macros/commits?author=lucleray\" title=\"Code\">💻</a></td>\n    <td align=\"center\"><a href=\"http://wintercounter.me\"><img src=\"https://avatars2.githubusercontent.com/u/963776?v=4?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>Victor Vincent</b></sub></a><br /><a href=\"https://github.com/kentcdodds/babel-plugin-macros/commits?author=wintercounter\" title=\"Code\">💻</a></td>\n    <td align=\"center\"><a href=\"http://mvasilkov.ovh\"><img src=\"https://avatars3.githubusercontent.com/u/140257?v=4?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>я котик пур-пур</b></sub></a><br /><a href=\"https://github.com/kentcdodds/babel-plugin-macros/commits?author=mvasilkov\" title=\"Documentation\">📖</a></td>\n    <td align=\"center\"><a href=\"http://armandososa.com\"><img src=\"https://avatars0.githubusercontent.com/u/139577?v=4?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>Armando Sosa</b></sub></a><br /><a href=\"https://github.com/kentcdodds/babel-plugin-macros/commits?author=soska\" title=\"Documentation\">📖</a></td>\n    <td align=\"center\"><a href=\"https://github.com/matvp91\"><img src=\"https://avatars3.githubusercontent.com/u/12699796?v=4?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>Matthias</b></sub></a><br /><a href=\"https://github.com/kentcdodds/babel-plugin-macros/commits?author=matvp91\" title=\"Code\">💻</a></td>\n    <td align=\"center\"><a href=\"https://www.jovidecroock.com/\"><img src=\"https://avatars3.githubusercontent.com/u/17125876?v=4?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>Jovi De Croock</b></sub></a><br /><a href=\"https://github.com/kentcdodds/babel-plugin-macros/commits?author=JoviDeCroock\" title=\"Code\">💻</a> <a href=\"https://github.com/kentcdodds/babel-plugin-macros/commits?author=JoviDeCroock\" title=\"Tests\">⚠️</a></td>\n    <td align=\"center\"><a href=\"http://victorarowo.com\"><img src=\"https://avatars0.githubusercontent.com/u/25545108?v=4?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>Victor Arowo</b></sub></a><br /><a href=\"https://github.com/kentcdodds/babel-plugin-macros/commits?author=VictorArowo\" title=\"Documentation\">📖</a></td>\n  </tr>\n  <tr>\n    <td align=\"center\"><a href=\"https://twitter.com/alexandermchan\"><img src=\"https://avatars.githubusercontent.com/u/1864372?v=4?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>Alex Chan</b></sub></a><br /><a href=\"https://github.com/kentcdodds/babel-plugin-macros/commits?author=alexanderchan\" title=\"Documentation\">📖</a></td>\n    <td align=\"center\"><a href=\"https://probablyup.com\"><img src=\"https://avatars.githubusercontent.com/u/570070?v=4?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>Evan Jacobs</b></sub></a><br /><a href=\"https://github.com/kentcdodds/babel-plugin-macros/commits?author=probablyup\" title=\"Code\">💻</a></td>\n  </tr>\n</table>\n\n<!-- markdownlint-restore -->\n<!-- prettier-ignore-end -->\n\n<!-- ALL-CONTRIBUTORS-LIST:END -->\n\nThis project follows the [all-contributors][all-contributors] specification.\nContributions of any kind welcome!\n\n## LICENSE\n\nMIT\n\n<!-- prettier-ignore-start -->\n[npm]: https://www.npmjs.com\n[node]: https://nodejs.org\n[build-badge]: https://img.shields.io/github/workflow/status/kentcdodds/babel-plugin-macros/validate?logo=github&style=flat-square\n[build]: https://github.com/kentcdodds/babel-plugin-macros/actions?query=workflow%3Avalidate\n[coverage-badge]: https://img.shields.io/codecov/c/github/kentcdodds/babel-plugin-macros.svg?style=flat-square\n[coverage]: https://codecov.io/github/kentcdodds/babel-plugin-macros\n[version-badge]: https://img.shields.io/npm/v/babel-plugin-macros.svg?style=flat-square\n[package]: https://www.npmjs.com/package/babel-plugin-macros\n[downloads-badge]: https://img.shields.io/npm/dm/babel-plugin-macros.svg?style=flat-square\n[npmtrends]: http://www.npmtrends.com/babel-plugin-macros\n[license-badge]: https://img.shields.io/npm/l/babel-plugin-macros.svg?style=flat-square\n[license]: https://github.com/kentcdodds/babel-plugin-macros/blob/main/LICENSE\n[prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square\n[prs]: http://makeapullrequest.com\n[coc-badge]: https://img.shields.io/badge/code%20of-conduct-ff69b4.svg?style=flat-square\n[coc]: https://github.com/kentcdodds/babel-plugin-macros/blob/main/CODE_OF_CONDUCT.md\n[emojis]: https://github.com/all-contributors/all-contributors#emoji-key\n[all-contributors]: https://github.com/all-contributors/all-contributors\n[all-contributors-badge]: https://img.shields.io/github/all-contributors/kentcdodds/babel-plugin-macros?color=orange&style=flat-square\n[bugs]: https://github.com/kentcdodds/babel-plugin-macros/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+sort%3Acreated-desc+label%3Abug\n[requests]: https://github.com/kentcdodds/babel-plugin-macros/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc+label%3Aenhancement\n[good-first-issue]: https://github.com/kentcdodds/babel-plugin-macros/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc+label%3Aenhancement+label%3A%22good+first+issue%22\n[preval]: https://github.com/kentcdodds/babel-plugin-preval\n[cra]: https://github.com/facebook/create-react-app\n[cra-issue]: https://github.com/facebook/create-react-app/issues/2730\n<!-- prettier-ignore-end -->\n"
  },
  {
    "path": "other/MAINTAINING.md",
    "content": "# Maintaining\n\nThis is documentation for maintainers of this project.\n\n## Code of Conduct\n\nPlease review, understand, and be an example of it. Violations of the code of\nconduct are taken seriously, even (especially) for maintainers.\n\n## Issues\n\nWe want to support and build the community. We do that best by helping people\nlearn to solve their own problems. We have an issue template and hopefully most\nfolks follow it. If it's not clear what the issue is, invite them to create a\nminimal reproduction of what they're trying to accomplish or the bug they think\nthey've found.\n\nOnce it's determined that a code change is necessary, point people to\n[makeapullrequest.com](http://makeapullrequest.com) and invite them to make a\npull request. If they're the one who needs the feature, they're the one who can\nbuild it. If they need some hand holding and you have time to lend a hand,\nplease do so. It's an investment into another human being, and an investment\ninto a potential maintainer.\n\nRemember that this is open source, so the code is not yours, it's ours. If\nsomeone needs a change in the codebase, you don't have to make it happen\nyourself. Commit as much time to the project as you want/need to. Nobody can ask\nany more of you than that.\n\n## Pull Requests\n\nAs a maintainer, you're fine to make your branches on the main repo or on your\nown fork. Either way is fine.\n\nWhen we receive a pull request, a github action is kicked off automatically (see\nthe `.github/workflows/validate.yml` for what runs in the action). We avoid\nmerging anything that breaks the validate action.\n\nPlease review PRs and focus on the code rather than the individual. You never\nknow when this is someone's first ever PR and we want their experience to be as\npositive as possible, so be uplifting and constructive.\n\nWhen you merge the pull request, 99% of the time you should use the\n[Squash and merge](https://help.github.com/articles/merging-a-pull-request/)\nfeature. This keeps our git history clean, but more importantly, this allows us\nto make any necessary changes to the commit message so we release what we want\nto release. See the next section on Releases for more about that.\n\n## Release\n\nOur releases are automatic. They happen whenever code lands into `main`. A\ngithub action gets kicked off and if it's successful, a tool called\n[`semantic-release`](https://github.com/semantic-release/semantic-release) is\nused to automatically publish a new release to npm as well as a changelog to\nGitHub. It is only able to determine the version and whether a release is\nnecessary by the git commit messages. With this in mind, **please brush up on\n[the commit message convention][commit] which drives our releases.**\n\n> One important note about this: Please make sure that commit messages do NOT\n> contain the words \"BREAKING CHANGE\" in them unless we want to push a major\n> version. I've been burned by this more than once where someone will include\n> \"BREAKING CHANGE: None\" and it will end up releasing a new major version. Not\n> a huge deal honestly, but kind of annoying...\n\n## Thanks!\n\nThank you so much for helping to maintain this project!\n\n[commit]:\n  https://github.com/conventional-changelog-archived-repos/conventional-changelog-angular/blob/ed32559941719a130bb0327f886d6a32a8cbc2ba/convention.md\n"
  },
  {
    "path": "other/USERS.md",
    "content": "# Users\n\nIf you or your company uses this project, add your name to this list! Eventually\nwe may have a website to showcase these (wanna build it!?)\n\n> No users have been added yet!\n\n<!--\nThis file should just be a bulleted list like this:\n\n- [Company/Project/Person](https://example.com) uses it in [some app](https://example.com)\n-->\n"
  },
  {
    "path": "other/docs/author.md",
    "content": "# `babel-plugin-macros` Usage for macros authors\n\n> See also:\n> [the `user` docs](https://github.com/kentcdodds/babel-plugin-macros/blob/master/other/docs/user.md).\n\nIs this your first time working with ASTs? Here are some resources:\n\n- [Writing custom Babel and ESLint plugins with ASTs](https://youtu.be/VBscbcm2Mok?list=PLV5CVI1eNcJgNqzNwcs4UKrlJdhfDjshf):\n  A 53 minute talk by [@kentcdodds](https://twitter.com/kentcdodds)\n- [babel-handbook](https://github.com/thejameskyle/babel-handbook): A guided\n  handbook on how to use Babel and how to create plugins for Babel by\n  [@thejameskyle](https://twitter.com/thejameskyle)\n- [Code Transformation and Linting](https://kentcdodds.com/workshops/#code-transformation-and-linting):\n  A workshop (recording available on Frontend Masters) with exercises of making\n  custom Babel and ESLint plugins\n\n## Writing a macro\n\n> You might appreciate\n> [this example repo](https://github.com/kentcdodds/cra-macro-example) which\n> shows how to write and use macros in a create-react-app application.\n\nA macro is a JavaScript module that exports a function. Here's a simple example:\n\n```javascript\nconst {createMacro} = require('babel-plugin-macros')\n\n// `createMacro` is simply a function that ensures your macro is only\n// called in the context of a babel transpilation and will throw an\n// error with a helpful message if someone does not have babel-plugin-macros\n// configured correctly\nmodule.exports = createMacro(myMacro)\n\nfunction myMacro({references, state, babel}) {\n  // state is the second argument you're passed to a visitor in a\n  // normal babel plugin. `babel` is the `babel-plugin-macros` module.\n  // do whatever you like to the AST paths you find in `references`\n  // read more below...\n}\n```\n\nIt can be published to the npm registry (for generic macros, like a css-in-js\nlibrary) or used locally (for domain-specific macros, like handling some special\ncase for your company's localization efforts).\n\n> Before you write a custom macro, you might consider whether\n> [`babel-plugin-preval`][preval] help you do what you want as it's pretty\n> powerful.\n\nThere are two parts to the `babel-plugin-macros` API:\n\n1. The filename convention\n2. The function you export\n\n### Filename\n\nThe way that `babel-plugin-macros` determines whether to run a macro is based on\nthe source string of the `import` or `require` statement. It must match this\nregex: `/[./]macro(\\.c?js)?$/` for example:\n\n_matches_:\n\n```\n'my.macro'\n'my.macro.js'\n'my.macro.cjs'\n'my/macro'\n'my/macro.js'\n'my/macro.cjs'\n```\n\n_does not match_:\n\n```\n'my-macro'\n'my.macro.is-sweet'\n'my/macro/rocks'\n```\n\n> So long as your file can be required at a matching path, you're good. So you\n> could put it in: `my/macro/index.js` and people would: `require('my/macro')`\n> which would work fine.\n\n**If you're going to publish this to npm,** the most ergonomic thing would be to\nname it something that ends in `.macro`. If it's part of a larger package, then\ncalling the file `macro.js` or placing it in `macro/index.js` is a great way to\ngo as well. Then people could do:\n\n```js\nimport Nice from 'nice.macro'\n// or\nimport Sweet from 'sweet/macro'\n```\n\nIn addition, please publish your macro with the [`keyword`][keyword] of\n`babel-plugin-macros` (note the \"s\"). That way folks can easily find macros by\nsearching for the [`babel-plugin-macros` keyword on\nnpm][npm-babel-plugin-macros]. In addition, and you can add this badge to the\ntop of your README:\n\n[![Babel Macro](https://img.shields.io/badge/babel--macro-%F0%9F%8E%A3-f5da55.svg?style=flat-square)](https://github.com/kentcdodds/babel-plugin-macros)\n\n```\n[![Babel Macro](https://img.shields.io/badge/babel--macro-%F0%9F%8E%A3-f5da55.svg?style=flat-square)](https://github.com/kentcdodds/babel-plugin-macros)\n```\n\n### Function API\n\nThe macro you create should export a function. That function accepts a single\nparameter which is an object with the following properties:\n\n#### state\n\nThe state of the file being traversed. It's the second argument you receive in a\nvisitor function in a normal babel plugin.\n\n#### babel\n\nThis is the same thing you get as an argument to normal babel plugins. It is\nalso the same thing you get if you `require('babel-core')`.\n\n#### references\n\nThis is an object that contains arrays of all the references to things imported\nfrom macro keyed based on the name of the import. The items in each array are\nthe paths to the references.\n\n<details>\n\n<summary>Some examples:</summary>\n\n```javascript\nimport MyMacro from './my.macro'\n\nMyMacro(\n  {someOption: true},\n  `\n  some stuff\n`,\n)\n\n// references: { default: [BabelPath] }\n```\n\n```javascript\nimport {foo as FooMacro} from './my.macro'\n\nFooMacro(\n  {someOption: true},\n  `\n  some stuff\n`,\n)\n\n// references: { foo: [BabelPath] }\n```\n\n```javascript\nimport {foo as FooMacro} from './my.macro'\n\n// no usage...\n\n// references: {}\n```\n\n</details>\n\nFrom here, it's just a matter of doing stuff with the `BabelPath`s that\nyou're given. For that check out [the babel handbook][babel-handbook].\n\n> One other thing to note is that after your macro has run, babel-plugin-macros\n> will remove the import/require statement for you.\n\n#### source\n\nThis is a string used as import declaration's source - i.e. `'./my.macro'`.\n\n#### config\n\nThere is a feature that allows users to configure your macro.\n\nTo specify that your plugin is configurable, you pass a `configName` to\n`createMacro`.\n\nA configuration is created from data combined from two sources: We use\n[`cosmiconfig`][cosmiconfig] to read a `babel-plugin-macros` configuration which\ncan be located in any of the following files up the directories from the\nimporting file:\n\n- `.babel-plugin-macrosrc`\n- `.babel-plugin-macrosrc.json`\n- `.babel-plugin-macrosrc.yaml`\n- `.babel-plugin-macrosrc.yml`\n- `.babel-plugin-macrosrc.js`\n- `babel-plugin-macros.config.js`\n- `babelMacros` in `package.json`\n\nThe content of the config will be merged with the content of the babel macros\nplugin options. Config options take priority.\n\nAll together specifying and using the config might look like this:\n\n```javascript\n// .babel-plugin-macros.config.js\nmodule.exports = {\n  taggedTranslations: {locale: 'en_US'},\n}\n\n// .babel.config.js\nmodule.exports = {\n  plugins: [\n    [\n      \"macros\",\n      {\n        taggedTranslations: { locale: \"en_GB\" },\n      },\n    ],\n  ],\n}\n\n\n// taggedTranslations.macro.js\nconst {createMacro} = require('babel-plugin-macros')\nmodule.exports = createMacro(taggedTranslationsMacro, {\n  configName: 'taggedTranslations',\n})\nfunction taggedTranslationsMacro({references, state, babel, config}) {\n  const {locale = 'en'} = config\n}\n```\n\nNote that in the above example if both files were specified, the final locale\nvalue would be `en_US`, since that is the value in the plugin config file.\n\n### Keeping imports\n\nAs said before, `babel-plugin-macros` automatically removes an import statement\nof macro. If you want to keep it because you have other plugins processing\nmacros, return `{ keepImports: true }` from your macro:\n\n```javascript\nconst {createMacro} = require('babel-plugin-macros')\n\nmodule.exports = createMacro(taggedTranslationsMacro)\n\nfunction taggedTranslationsMacro({references, state, babel}) {\n  // process node from references\n\n  return {\n    keepImports: true,\n  }\n}\n```\n\n## Throwing Helpful Errors\n\nDebugging stuff that transpiles your code is the worst, especially for\nbeginners. That's why it's important that you make assertions, and catch errors\nto throw more meaningful errors with helpful information for the developer to\nknow what to do to resolve the issue.\n\nIn an effort to make this easier for you, `babel-plugin-macros` will wrap the\ninvocation of your plugin in a `try/catch` and throw as helpful an error message\nas possible for you.\n\nTo make it even better, you can throw your own with more context. For example:\n\n```javascript\nconst {createMacro, MacroError} = require('babel-plugin-macros')\n\nmodule.exports = createMacro(myMacro)\n\nfunction myMacro({references, state, babel}) {\n  // something unexpected happens:\n  throw new MacroError(\n    'Some helpful and contextual message. Learn more: ' +\n      'https://github.com/your-org/your-repo/blob/master/docs/errors.md#learn-more-about-eror-title',\n  )\n}\n```\n\n## Testing your macro\n\nThe best way to test your macro is using [`babel-plugin-tester`][tester]:\n\n```javascript\nimport pluginTester from 'babel-plugin-tester'\nimport plugin from 'babel-plugin-macros'\n\npluginTester({\n  plugin,\n  snapshot: true,\n  babelOptions: {filename: __filename},\n  tests: [\n    `\n      import MyMacro from '../my.macro'\n\n      MyMacro({someOption: true}, \\`\n        some stuff\n      \\`)\n    `,\n  ],\n})\n```\n\nThere is currently no way to get code coverage for your macro this way however.\nIf you want code coverage, you'll have to call your macro yourself.\nContributions to improve this experience are definitely welcome!\n\n## Async logic\n\nUnfortunately, babel plugins are synchronous so you can't do anything\nasynchronous with `babel-plugin-macros`. However, you can cheat a bit by running\n`child_process`'s `spawnSync` to synchronously execute a file. It's definitely a\nhack and is not great for performance, but in most cases it's fast enough™️.\n\nLuckily, [@Zemnmez](https://github.com/Zemnmez) created\n[`do-sync`](https://github.com/Zemnmez/do-sync) which makes doing this much more\nstraightforward:\n\n```javascript\nconst {doSync} = require('do-sync')\nconst {createMacro, MacroError} = require('babel-plugin-macros')\n\nmodule.exports = createMacro(myMacro)\n\nconst getTheFlowers = doSync(async (arg1, arg2) => {\n  const dep = require('some-dependency')\n  const flowers = await dep(arg1, arg2.stuff)\n  return flowers\n})\n\nfunction myMacro({references, state, babel}) {\n  const flowers = getTheFlowers('...', {stuff: '...'})\n  // ... more sync stuff\n}\n```\n\n[preval]: https://github.com/kentcdodds/babel-plugin-preval\n[babel-handbook]:\n  https://github.com/thejameskyle/babel-handbook/blob/master/translations/en/plugin-handbook.md\n[tester]: https://github.com/babel-utils/babel-plugin-tester\n[keyword]: https://docs.npmjs.com/files/package.json#keywords\n[npm-babel-plugin-macros]:\n  https://www.npmjs.com/browse/keyword/babel-plugin-macros\n[cosmiconfig]: https://www.npmjs.com/package/cosmiconfig\n"
  },
  {
    "path": "other/docs/user.md",
    "content": "# `babel-plugin-macros` Usage for users\n\n> See also:\n> [the `author` docs](https://github.com/kentcdodds/babel-plugin-macros/blob/master/other/docs/author.md).\n\n## Adding the plugin to your config\n\n### Via `.babelrc` (Recommended)\n\n**.babelrc**\n\n```json\n{\n  \"plugins\": [\"macros\"]\n}\n```\n\n### Via [`babel.config.js`](https://babeljs.io/docs/en/configuration#babelconfigjs)\n\n**babel.config.js**\n\n```javascript\nmodule.exports = function (api) {\n  return {\n    plugins: ['macros'],\n  }\n}\n```\n\n### Via CLI\n\n```shell\nbabel --plugins babel-plugin-macros script.js\n```\n\n### Via Node API\n\n```js\nrequire('babel-core').transform('code', {\n  plugins: ['macros'],\n})\n```\n\n## Using a macro\n\nWith the `babel-plugin-macros` plugin added to your config, we can now use a\nmacro that works with the `babel-plugin-macros` API. Let's assume we have such a\nmodule in our project called `eval.macro.js`. To use it, we `import` or\n`require` the macro module in our code like so:\n\n```javascript\nimport MyEval from './eval.macro'\n// or\nconst MyEval = require('./eval.macro')\n```\n\nThen we use that variable however the documentation for the macro says.\nIncidentally, `eval.macro.js` actually exists in the tests for\n`babel-plugin-macros` [here][eval-macro] and you can see how it transforms our\ncode in [the `babel-plugin-macros` snapshots][eval-snapshots].\n\n> Note here that the real benefit is that we don't need to configure anything\n> for every macro you add. We simply configure `babel-plugin-macros`, then we\n> can use any macro available. This is part of the benefit of using\n> `babel-plugin-macros`.\n\n[eval-macro]:\n  https://github.com/kentcdodds/babel-plugin-macros/blob/master/src/__tests__/fixtures/eval.macro.js\n[eval-snapshots]:\n  https://github.com/kentcdodds/babel-plugin-macros/blob/master/src/__tests__/__snapshots__/index.js.snap\n\n### Using with create-react-app\n\n> [Checkout the CRA Macro Example repo](https://github.com/kentcdodds/cra-macro-example)\n\n`babel-plugin-macros` ships with `react-scripts` 2.0! This is awesome because it\nallows for babel to be configured in a nice way without having to eject from\n`create-react-app`!\n\nBefore deciding to use this however you should be aware of a few things:\n\n1. Features may be broken or not work as expected\n2. Documentation for new features is still sparse, so look through the pull\n   requests for how they're expected to work\n\nWith that being said you can use all the awesomeness of `babel-plugin-macros`\ninside `create-react-app` by running one of the following commands based on your\nsituation.\n\n```\n$ # Create a new application\n$ npx create-react-app my-app\n$ # Upgrade an existing application\n$ yarn upgrade react-scripts\n```\n\n### config\n\nThere is a feature that allows you to configure your macro. We use\n[`cosmiconfig`][cosmiconfig] to read a `babel-plugin-macros` configuration which\ncan be located in any of the following files up the directories from the\nimporting file:\n\n- `.babel-plugin-macrosrc`\n- `.babel-plugin-macrosrc.json`\n- `.babel-plugin-macrosrc.yaml`\n- `.babel-plugin-macrosrc.yml`\n- `.babel-plugin-macrosrc.js`\n- `babel-plugin-macros.config.js`\n- `babelMacros` in `package.json`\n\nYou need to specify your `configName`. EG: For configuring [styled-components\nmacro][styled-components], the `configName` is `\"styledComponents\"`:\n\n```js\n// babel-plugin-macros.config.js\nmodule.exports = {\n  // ...\n  // Other macros config\n  styledComponents: {\n    pure: true,\n  },\n}\n```\n\n[cosmiconfig]: https://www.npmjs.com/package/cosmiconfig\n[styled-components]: https://www.styled-components.com/docs/tooling#babel-macro\n"
  },
  {
    "path": "other/manual-releases.md",
    "content": "# manual-releases\n\nThis project has an automated release set up. So things are only released when\nthere are useful changes in the code that justify a release. But sometimes\nthings get messed up one way or another and we need to trigger the release\nourselves. When this happens, simply bump the number below and commit that with\nthe following commit message based on your needs:\n\n**Major**\n\n```\nfix(release): manually release a major version\n\nThere was an issue with a major release, so this manual-releases.md\nchange is to release a new major version.\n\nReference: #<the number of a relevant pull request, issue, or commit>\n\nBREAKING CHANGE: <mention any relevant breaking changes (this is what triggers the major version change so don't skip this!)>\n```\n\n**Minor**\n\n```\nfeat(release): manually release a minor version\n\nThere was an issue with a minor release, so this manual-releases.md\nchange is to release a new minor version.\n\nReference: #<the number of a relevant pull request, issue, or commit>\n```\n\n**Patch**\n\n```\nfix(release): manually release a patch version\n\nThere was an issue with a patch release, so this manual-releases.md\nchange is to release a new patch version.\n\nReference: #<the number of a relevant pull request, issue, or commit>\n```\n\nThe number of times we've had to do a manual release is: 0\n"
  },
  {
    "path": "other/mock-modules/@scope/package/macro.js",
    "content": "// this is used to make sure that you can require macro from node_modules\nconst {createMacro} = require('../../../src')\n\nconst innerFn = jest.fn()\nmodule.exports = createMacro(innerFn)\nmodule.exports.innerFn = innerFn\n"
  },
  {
    "path": "other/mock-modules/babel-plugin-macros-test-error-thrower/macro.js",
    "content": "// const printAST = require('ast-pretty-print')\nconst {createMacro} = require('../../src')\n\nmodule.exports = createMacro(evalMacro)\n\nfunction evalMacro() {\n  throw new Error('not helpful')\n}\n"
  },
  {
    "path": "other/mock-modules/babel-plugin-macros-test-error-thrower.macro/index.js",
    "content": "// const printAST = require('ast-pretty-print')\nconst {createMacro} = require('../../src')\n\nmodule.exports = createMacro(evalMacro)\n\nfunction evalMacro() {\n  throw new Error('not helpful')\n}\n"
  },
  {
    "path": "other/mock-modules/babel-plugin-macros-test-fake/macro.js",
    "content": "// this is used to make sure that you can require macro from node_modules\nconst {createMacro} = require('../../src')\n\nconst innerFn = jest.fn()\nmodule.exports = createMacro(innerFn)\nmodule.exports.innerFn = innerFn\n"
  },
  {
    "path": "other/mock-modules/babel-plugin-path-replace/index.js",
    "content": "const types = require('@babel/types')\n\nconst problematicVisitor = {\n  VariableDeclarator: {\n    enter(path) {\n      const initPath = path.get('init')\n\n      initPath.replaceWith(\n        types.sequenceExpression([\n          types.stringLiteral('foobar'),\n          initPath.node,\n        ]),\n      )\n    },\n  },\n}\n\nmodule.exports = () => ({\n  visitor: {\n    Program: {\n      enter(path) {\n        path.traverse(problematicVisitor)\n      },\n    },\n  },\n})\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"babel-plugin-macros\",\n  \"version\": \"0.0.0-semantically-released\",\n  \"description\": \"Allows you to build compile-time libraries\",\n  \"main\": \"src/index.js\",\n  \"scripts\": {\n    \"lint\": \"kcd-scripts lint\",\n    \"setup\": \"npm install && npm run validate -s\",\n    \"test\": \"kcd-scripts test\",\n    \"test:update\": \"npm test -- --updateSnapshot --coverage\",\n    \"validate\": \"kcd-scripts validate\"\n  },\n  \"files\": [\n    \"src/index.js\"\n  ],\n  \"keywords\": [\n    \"babel-plugin\",\n    \"macros\",\n    \"macro\",\n    \"babel-macro\",\n    \"babel-plugin-macro\",\n    \"babel-macros\",\n    \"babel-plugin-macros\"\n  ],\n  \"author\": \"Kent C. Dodds <me@kentcdodds.com> (https://kentcdodds.com)\",\n  \"license\": \"MIT\",\n  \"dependencies\": {\n    \"cosmiconfig\": \"^7.0.0\",\n    \"resolve\": \"^1.19.0\"\n  },\n  \"devDependencies\": {\n    \"@babel/core\": \"^7.12.9\",\n    \"@babel/parser\": \"^7.12.7\",\n    \"@babel/plugin-transform-modules-commonjs\": \"^7.16.7\",\n    \"@babel/types\": \"^7.12.7\",\n    \"ast-pretty-print\": \"^2.0.1\",\n    \"babel-plugin-tester\": \"^10.0.0\",\n    \"babel-plugin-transform-es2015-modules-commonjs\": \"^6.26.2\",\n    \"cpy\": \"^8.1.1\",\n    \"kcd-scripts\": \"^7.1.0\"\n  },\n  \"eslintConfig\": {\n    \"extends\": \"./node_modules/kcd-scripts/eslint.js\"\n  },\n  \"eslintIgnore\": [\n    \"node_modules\",\n    \"coverage\",\n    \"dist\"\n  ],\n  \"babel\": {\n    \"plugins\": [\n      \"@babel/transform-modules-commonjs\"\n    ]\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/kentcdodds/babel-plugin-macros\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/kentcdodds/babel-plugin-macros/issues\"\n  },\n  \"homepage\": \"https://github.com/kentcdodds/babel-plugin-macros#readme\",\n  \"engines\": {\n    \"node\": \">=10\",\n    \"npm\": \">=6\"\n  }\n}\n"
  },
  {
    "path": "src/__tests__/__snapshots__/create-macros.js.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`attempting to create a macros with the configName of options throws an error 1`] = `\"You cannot use the configName \\\\\"options\\\\\". It is reserved for babel-plugin-macros.\"`;\n\nexports[`throws error if it is not transpiled 1`] = `\"The macro you imported from \\\\\"untranspiled.macro\\\\\" 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: https://github.com/kentcdodds/babel-plugin-macros/blob/master/other/docs/user.md\"`;\n"
  },
  {
    "path": "src/__tests__/__snapshots__/index.js.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`unknown plugin Macros are applied in the order respecting plugins order: Macros are applied in the order respecting plugins order 1`] = `\n\nimport Wrap from \"./fixtures/jsx-id-prefix.macro\";\n\nconst bar = Wrap(<div id=\"d1\"><p id=\"p1\"></p></div>);\n\n      ↓ ↓ ↓ ↓ ↓ ↓\n\nconst bar = Wrap(\n  <div id=\"plugin-macro-d1\">\n    <p id=\"plugin-macro-p1\"></p>\n  </div>,\n)\n\n\n`;\n\nexports[`unknown plugin Supports named imports: Supports named imports 1`] = `\n\nimport {css as CSS, styled as STYLED} from './fixtures/emotion.macro'\nconst red = CSS\\`\n  background-color: red;\n\\`\n\nconst Div = STYLED.div\\`\n  composes: \\${red}\n  color: blue;\n\\`\n\n      ↓ ↓ ↓ ↓ ↓ ↓\n\nconst red = 'background-color: red;'\nconst Div = STYLED.div\\`composes: background-color: red;\n  color: blue;\\`\n\n\n`;\n\nexports[`unknown plugin Works as a JSXElement: Works as a JSXElement 1`] = `\n\nimport MyEval from './fixtures/eval.macro'\nconst x = <MyEval>34 + 45</MyEval>\n\n      ↓ ↓ ↓ ↓ ↓ ↓\n\nconst x = 79\n\n\n`;\n\nexports[`unknown plugin appends the npm URL for errors thrown by node modules with a slash: appends the npm URL for errors thrown by node modules with a slash 1`] = `\n\nimport errorThrower from 'babel-plugin-macros-test-error-thrower/macro'\nerrorThrower('hi')\n\n      ↓ ↓ ↓ ↓ ↓ ↓\n\nError: babel-plugin-macros-test-error-thrower/macro: not helpful Learn more: https://www.npmjs.com/package/babel-plugin-macros-test-error-thrower\n\n`;\n\nexports[`unknown plugin appends the npm URL for errors thrown by node modules: appends the npm URL for errors thrown by node modules 1`] = `\n\nimport errorThrower from 'babel-plugin-macros-test-error-thrower.macro'\nerrorThrower('hi')\n\n      ↓ ↓ ↓ ↓ ↓ ↓\n\nError: babel-plugin-macros-test-error-thrower.macro: not helpful Learn more: https://www.npmjs.com/package/babel-plugin-macros-test-error-thrower.macro\n\n`;\n\nexports[`unknown plugin does nothing but remove macros if it is unused: does nothing but remove macros if it is unused 1`] = `\n\nimport foo from \"./fixtures/eval.macro\";\n\nconst bar = 42;\n\n      ↓ ↓ ↓ ↓ ↓ ↓\n\nconst bar = 42\n\n\n`;\n\nexports[`unknown plugin forwards MacroErrors thrown by the macro: forwards MacroErrors thrown by the macro 1`] = `\n\nimport errorThrower from './fixtures/macro-error-thrower.macro'\nerrorThrower('hey')\n\n      ↓ ↓ ↓ ↓ ↓ ↓\n\nMacroError: very helpful\n\n`;\n\nexports[`unknown plugin macros can set their configName and get their config: macros can set their configName and get their config 1`] = `\n\nimport configured from './configurable.macro'\n\n// eslint-disable-next-line babel/no-unused-expressions\nconfigured\\`stuff\\`\n\n      ↓ ↓ ↓ ↓ ↓ ↓\n\n// eslint-disable-next-line babel/no-unused-expressions\nconfigured\\`stuff\\`\n\n\n`;\n\nexports[`unknown plugin optionally keep imports (import declaration): optionally keep imports (import declaration) 1`] = `\n\nimport macro from './fixtures/keep-imports.macro'\nconst red = macro('noop');\n\n      ↓ ↓ ↓ ↓ ↓ ↓\n\nimport macro from './fixtures/keep-imports.macro'\nconst red = macro('noop')\n\n\n`;\n\nexports[`unknown plugin optionally keep imports (variable assignment): optionally keep imports (variable assignment) 1`] = `\n\nconst macro = require('./fixtures/keep-imports.macro')\nconst red = macro('noop');\n\n      ↓ ↓ ↓ ↓ ↓ ↓\n\nconst macro = require('./fixtures/keep-imports.macro')\n\nconst red = macro('noop')\n\n\n`;\n\nexports[`unknown plugin optionally keep imports in combination with babel-preset-env (#80): optionally keep imports in combination with babel-preset-env (#80) 1`] = `\n\nimport macro from './fixtures/keep-imports.macro'\nconst red = macro('noop')\n\n      ↓ ↓ ↓ ↓ ↓ ↓\n\n'use strict'\n\nvar _keepImports = require('./fixtures/keep-imports.macro')\n\nvar _keepImports2 = _interopRequireDefault(_keepImports)\n\nfunction _interopRequireDefault(obj) {\n  return obj && obj.__esModule ? obj : {default: obj}\n}\n\nconst red = (0, _keepImports2.default)('noop')\n\n\n`;\n\nexports[`unknown plugin prepends the relative path for errors thrown by the macro: prepends the relative path for errors thrown by the macro 1`] = `\n\nimport errorThrower from './fixtures/error-thrower.macro'\nerrorThrower('hey')\n\n      ↓ ↓ ↓ ↓ ↓ ↓\n\nError: ./fixtures/error-thrower.macro: very unhelpful\n\n`;\n\nexports[`unknown plugin raises an error if macro does not exist: raises an error if macro does not exist 1`] = `\n\nimport foo from './some-macros-that-doesnt-even-need-to-exist.macro'\nexport default 'something else'\n\n      ↓ ↓ ↓ ↓ ↓ ↓\n\nError: Cannot find module './some-macros-that-doesnt-even-need-to-exist.macro' from '<PROJECT_ROOT>/src/__tests__'\n\n`;\n\nexports[`unknown plugin supports compiled macros (\\`__esModule\\` + \\`export default\\`): supports compiled macros (\\`__esModule\\` + \\`export default\\`) 1`] = `\n\nimport {css, styled} from './fixtures/emotion-esm.macro'\nconst red = css\\`\n  background-color: red;\n\\`\n\nconst Div = styled.div\\`\n  composes: \\${red}\n  color: blue;\n\\`\n\n      ↓ ↓ ↓ ↓ ↓ ↓\n\nconst red = css\\`\n  background-color: red;\n\\`\nconst Div = styled.div\\`\n  composes: \\${red}\n  color: blue;\n\\`\n\n\n`;\n\nexports[`unknown plugin supports macros from node_modules with scope: supports macros from node_modules with scope 1`] = `\n\nimport fakeMacro from '@scope/package/macro'\nfakeMacro('hi')\n\n      ↓ ↓ ↓ ↓ ↓ ↓\n\nfakeMacro('hi')\n\n\n`;\n\nexports[`unknown plugin supports macros from node_modules: supports macros from node_modules 1`] = `\n\nimport fakeMacro from 'babel-plugin-macros-test-fake/macro'\nfakeMacro('hi')\n\n      ↓ ↓ ↓ ↓ ↓ ↓\n\nfakeMacro('hi')\n\n\n`;\n\nexports[`unknown plugin throws an error if the macro is not properly wrapped: throws an error if the macro is not properly wrapped 1`] = `\n\nimport unwrapped from './fixtures/non-wrapped.macro'\nunwrapped('hey')\n\n      ↓ ↓ ↓ ↓ ↓ ↓\n\nError: The macro imported from \"./fixtures/non-wrapped.macro\" must be wrapped in \"createMacro\" which you can get from \"babel-plugin-macros\". Please refer to the documentation to see how to do this properly: https://github.com/kentcdodds/babel-plugin-macros/blob/master/other/docs/author.md#writing-a-macro\n\n`;\n\nexports[`unknown plugin when a custom isMacrosName option is used on a import: when a custom isMacrosName option is used on a import 1`] = `\n\nimport myEval from './fixtures/eval-macro.js'\nconst x = myEval\\`34 + 45\\`\n\n      ↓ ↓ ↓ ↓ ↓ ↓\n\nconst x = 79\n\n\n`;\n\nexports[`unknown plugin when a custom isMacrosName option is used on a require: when a custom isMacrosName option is used on a require 1`] = `\n\nconst evaler = require('./fixtures/eval-macro.js')\nconst x = evaler\\`34 + 45\\`\n\n      ↓ ↓ ↓ ↓ ↓ ↓\n\nconst x = 79\n\n\n`;\n\nexports[`unknown plugin when a plugin that replaces paths is used, macros still work properly: when a plugin that replaces paths is used, macros still work properly 1`] = `\n\nimport myEval from '../eval.macro'\n\nconst result = myEval\\`+('4' + '2')\\`\n\nglobal.result = result\n\n      ↓ ↓ ↓ ↓ ↓ ↓\n\nconst result = ('foobar', 42)\nglobal.result = result\n\n\n`;\n\nexports[`unknown plugin when configuration is specified in plugin options: when configuration is specified in plugin options 1`] = `\n\nimport configured from './configurable.macro'\n\n// eslint-disable-next-line babel/no-unused-expressions\nconfigured\\`stuff\\`\n\n      ↓ ↓ ↓ ↓ ↓ ↓\n\n// eslint-disable-next-line babel/no-unused-expressions\nconfigured\\`stuff\\`\n\n\n`;\n\nexports[`unknown plugin when configuration is specified in plugin options: when configuration is specified in plugin options 2`] = `\n\nconst configured = require('./configurable.macro')\n\n// eslint-disable-next-line babel/no-unused-expressions\nconfigured\\`stuff\\`\n\n      ↓ ↓ ↓ ↓ ↓ ↓\n\n// eslint-disable-next-line babel/no-unused-expressions\nconfigured\\`stuff\\`\n\n\n`;\n\nexports[`unknown plugin when configuration is specified incorrectly in plugin options: when configuration is specified incorrectly in plugin options 1`] = `\n\nimport configured from './configurable.macro'\n\n// eslint-disable-next-line babel/no-unused-expressions\nconfigured\\`stuff\\`\n\n      ↓ ↓ ↓ ↓ ↓ ↓\n\n// eslint-disable-next-line babel/no-unused-expressions\nconfigured\\`stuff\\`\n\n\n`;\n\nexports[`unknown plugin when plugin options configuration cannot be merged with file configuration: when plugin options configuration cannot be merged with file configuration 1`] = `\n\nimport configured from './configurable.macro'\n\n// eslint-disable-next-line babel/no-unused-expressions\nconfigured\\`stuff\\`\n\n      ↓ ↓ ↓ ↓ ↓ ↓\n\nError: <PROJECT_ROOT>/src/__tests__/fixtures/primitive-config/babel-plugin-macros.config.js specified a configurableMacro config of type object, but the the macros plugin's options.configurableMacro did contain an object. Both configs must contain objects for their options to be mergeable.\n\n`;\n\nexports[`unknown plugin when there is an error reading the config, a helpful message is logged 1`] = `\nArray [\n  There was an error trying to load the config \"configurableMacro\" for the macro imported from \"./configurable.macro. Please see the error thrown for more information.,\n]\n`;\n\nexports[`unknown plugin when there is an error reading the config, a helpful message is logged: when there is an error reading the config, a helpful message is logged 1`] = `\n\nimport configured from './configurable.macro'\n\n// eslint-disable-next-line babel/no-unused-expressions\nconfigured\\`stuff\\`\n\n      ↓ ↓ ↓ ↓ ↓ ↓\n\nError: this is a cosmiconfig error\n\n`;\n\nexports[`unknown plugin when there is no config to load, then no config is passed: when there is no config to load, then no config is passed 1`] = `\n\nimport configured from './configurable.macro'\n\n// eslint-disable-next-line babel/no-unused-expressions\nconfigured\\`stuff\\`\n\n      ↓ ↓ ↓ ↓ ↓ ↓\n\n// eslint-disable-next-line babel/no-unused-expressions\nconfigured\\`stuff\\`\n\n\n`;\n\nexports[`unknown plugin works with function calls: works with function calls 1`] = `\n\nimport myEval from './fixtures/eval.macro'\nconst x = myEval('34 + 45')\n\n      ↓ ↓ ↓ ↓ ↓ ↓\n\nconst x = 79\n\n\n`;\n\nexports[`unknown plugin works with import: works with import 1`] = `\n\nimport myEval from './fixtures/eval.macro'\nconst x = myEval\\`34 + 45\\`\n\n      ↓ ↓ ↓ ↓ ↓ ↓\n\nconst x = 79\n\n\n`;\n\nexports[`unknown plugin works with require destructuring and aliasing: works with require destructuring and aliasing 1`] = `\n\nconst {css: CSS, styled: STYLED} = require('./fixtures/emotion.macro')\nconst red = CSS\\`\n  background-color: red;\n\\`\n\nconst Div = STYLED.div\\`\n  composes: \\${red}\n  color: blue;\n\\`\n\n      ↓ ↓ ↓ ↓ ↓ ↓\n\nconst red = 'background-color: red;'\nconst Div = STYLED.div\\`composes: background-color: red;\n  color: blue;\\`\n\n\n`;\n\nexports[`unknown plugin works with require destructuring: works with require destructuring 1`] = `\n\nconst {css, styled} = require('./fixtures/emotion.macro')\nconst red = css\\`\n  background-color: red;\n\\`\n\nconst Div = styled.div\\`\n  composes: \\${red}\n  color: blue;\n\\`\n\n      ↓ ↓ ↓ ↓ ↓ ↓\n\nconst red = 'background-color: red;'\nconst Div = styled.div\\`composes: background-color: red;\n  color: blue;\\`\n\n\n`;\n\nexports[`unknown plugin works with require: works with require 1`] = `\n\nconst evaler = require('./fixtures/eval.macro')\nconst x = evaler\\`34 + 45\\`\n\n      ↓ ↓ ↓ ↓ ↓ ↓\n\nconst x = 79\n\n\n`;\n"
  },
  {
    "path": "src/__tests__/create-macros.js",
    "content": "const {createMacro} = require('../')\n\ntest('throws error if it is not transpiled', () => {\n  const untranspiledMacro = createMacro(() => {})\n  expect(() =>\n    untranspiledMacro({source: 'untranspiled.macro'}),\n  ).toThrowErrorMatchingSnapshot()\n})\n\ntest('attempting to create a macros with the configName of options throws an error', () => {\n  expect(() =>\n    createMacro(() => {}, {configName: 'options'}),\n  ).toThrowErrorMatchingSnapshot()\n})\n"
  },
  {
    "path": "src/__tests__/fixtures/config/babel-plugin-macros.config.js",
    "content": "module.exports = {\n  configurableMacro: {\n    fileConfig: true,\n    someConfig: true,\n  },\n}\n"
  },
  {
    "path": "src/__tests__/fixtures/config/cjs-code.js",
    "content": "const configured = require('./configurable.macro')\n\n// eslint-disable-next-line babel/no-unused-expressions\nconfigured`stuff`\n"
  },
  {
    "path": "src/__tests__/fixtures/config/code.js",
    "content": "import configured from './configurable.macro'\n\n// eslint-disable-next-line babel/no-unused-expressions\nconfigured`stuff`\n"
  },
  {
    "path": "src/__tests__/fixtures/config/configurable.macro.js",
    "content": "const {createMacro} = require('../../..')\n\nconst configName = 'configurableMacro'\nconst realMacro = jest.fn()\nmodule.exports = createMacro(realMacro, {configName})\n// for testing purposes only\nObject.assign(module.exports, {\n  realMacro,\n  configName,\n})\n"
  },
  {
    "path": "src/__tests__/fixtures/emotion-esm.macro.js",
    "content": "const {createMacro} = require('../../')\n\nexport default createMacro(evalMacro)\n\nfunction evalMacro() {\n  // we're lazy right now\n  // we don't want to eval\n}\n"
  },
  {
    "path": "src/__tests__/fixtures/emotion.macro.js",
    "content": "// this is a fake version of emotion\n// const printAST = require('ast-pretty-print')\nconst {createMacro} = require('../../')\n\nmodule.exports = createMacro(emotionMacro)\n\nfunction emotionMacro({references, babel}) {\n  const {types: t} = babel\n  references.css.forEach(cssRef => {\n    if (cssRef.parentPath.type === 'TaggedTemplateExpression') {\n      cssRef.parentPath.replaceWith(\n        t.stringLiteral(cssRef.parentPath.get('quasi').evaluate().value.trim()),\n      )\n    }\n  })\n  references.styled.forEach(styledRef => {\n    if (styledRef.parentPath.parentPath.type === 'TaggedTemplateExpression') {\n      const quasi = styledRef.parentPath.parentPath.get('quasi')\n      const val = quasi.evaluate().value.trim()\n      const replacement = t.templateLiteral(\n        [t.templateElement({raw: val, cooked: val})],\n        [],\n      )\n      quasi.replaceWith(replacement)\n    }\n  })\n}\n"
  },
  {
    "path": "src/__tests__/fixtures/error-thrower.macro.js",
    "content": "// const printAST = require('ast-pretty-print')\nconst {createMacro} = require('../../')\n\nmodule.exports = createMacro(evalMacro)\n\nfunction evalMacro() {\n  throw new Error('very unhelpful')\n}\n"
  },
  {
    "path": "src/__tests__/fixtures/eval-macro.js",
    "content": "module.exports = require('./eval.macro')\n"
  },
  {
    "path": "src/__tests__/fixtures/eval.macro.js",
    "content": "const {parse} = require('@babel/parser')\n// const printAST = require('ast-pretty-print')\nconst {createMacro} = require('../../')\n\nmodule.exports = createMacro(evalMacro)\n\nfunction evalMacro({references, state}) {\n  references.default.forEach(referencePath => {\n    if (referencePath.parentPath.type === 'TaggedTemplateExpression') {\n      asTag(referencePath.parentPath.get('quasi'), state)\n    } else if (referencePath.parentPath.type === 'CallExpression') {\n      asFunction(referencePath.parentPath.get('arguments'), state)\n    } else if (referencePath.parentPath.type === 'JSXOpeningElement') {\n      asJSX(\n        {\n          attributes: referencePath.parentPath.get('attributes'),\n          children: referencePath.parentPath.parentPath.get('children'),\n        },\n        state,\n      )\n    } else {\n      // TODO: throw a helpful error message\n    }\n  })\n}\n\nfunction asTag(quasiPath) {\n  const value = quasiPath.parentPath.get('quasi').evaluate().value\n  quasiPath.parentPath.replaceWith(evalToAST(value))\n}\n\nfunction asFunction(argumentsPaths) {\n  const value = argumentsPaths[0].evaluate().value\n  argumentsPaths[0].parentPath.replaceWith(evalToAST(value))\n}\n\n// eslint-disable-next-line no-unused-vars\nfunction asJSX({attributes, children}) {\n  // It's a shame you cannot use evaluate() with JSX\n  const value = children[0].node.value\n  children[0].parentPath.replaceWith(evalToAST(value))\n}\n\nfunction evalToAST(value) {\n  let x\n  // eslint-disable-next-line\n  eval(`x = ${value}`)\n  return thingToAST(x)\n}\n\nfunction thingToAST(object) {\n  const fileNode = parse(`var x = ${JSON.stringify(object)}`)\n  return fileNode.program.body[0].declarations[0].init\n}\n"
  },
  {
    "path": "src/__tests__/fixtures/jsx-id-prefix.macro.js",
    "content": "// adds \"prefix-\" to each `id` attribute\nconst {createMacro} = require('../../')\n\nmodule.exports = createMacro(wrapWidget)\n\nfunction wrapWidget({references, babel}) {\n  const {types: t} = babel\n  references.default.forEach(wrap => {\n    wrap.parentPath.traverse({\n      JSXAttribute(path) {\n        const name = path.get('name')\n        if (t.isJSXIdentifier(name) && name.node.name === 'id') {\n          const value = path.get('value')\n          if (t.isStringLiteral(value))\n            value.replaceWith(t.stringLiteral(`macro-${value.node.value}`))\n        }\n      },\n    })\n  })\n}\n"
  },
  {
    "path": "src/__tests__/fixtures/jsx-id-prefix.plugin.js",
    "content": "// babel-plugin adding `plugin-` prefix to each \"id\" JSX attribute\nmodule.exports = main\n\nfunction main({types: t}) {\n  return {\n    visitor: {\n      // intentionally traversing from Program,\n      // if it matches JSXAttribute here the issue won't be reproduced\n      Program(progPath) {\n        progPath.traverse({\n          JSXAttribute(path) {\n            const name = path.get('name')\n            if (t.isJSXIdentifier(name) && name.node.name === 'id') {\n              const value = path.get('value')\n              if (t.isStringLiteral(value))\n                value.replaceWith(t.stringLiteral(`plugin-${value.node.value}`))\n            }\n          },\n        })\n      },\n    },\n  }\n}\n"
  },
  {
    "path": "src/__tests__/fixtures/keep-imports.macro.js",
    "content": "const {createMacro} = require('../../')\n\nmodule.exports = createMacro(keepImportMacro)\n\nfunction keepImportMacro() {\n  return {keepImports: true}\n}\n"
  },
  {
    "path": "src/__tests__/fixtures/macro-error-thrower.macro.js",
    "content": "// const printAST = require('ast-pretty-print')\nconst {createMacro, MacroError} = require('../../')\n\nmodule.exports = createMacro(evalMacro)\n\nfunction evalMacro() {\n  throw new MacroError('very helpful')\n}\n"
  },
  {
    "path": "src/__tests__/fixtures/non-wrapped.macro.js",
    "content": "module.exports = () => {}\n"
  },
  {
    "path": "src/__tests__/fixtures/path-replace-issue/.babelrc",
    "content": "{\n  \"plugins\": [\"path-replace\"]\n}\n"
  },
  {
    "path": "src/__tests__/fixtures/path-replace-issue/variable-assignment.js",
    "content": "import myEval from '../eval.macro'\n\nconst result = myEval`+('4' + '2')`\n\nglobal.result = result\n"
  },
  {
    "path": "src/__tests__/fixtures/primitive-config/babel-plugin-macros.config.js",
    "content": "module.exports = {\n  configurableMacro: 4,\n}\n"
  },
  {
    "path": "src/__tests__/fixtures/primitive-config/code.js",
    "content": "import configured from './configurable.macro'\n\n// eslint-disable-next-line babel/no-unused-expressions\nconfigured`stuff`\n"
  },
  {
    "path": "src/__tests__/fixtures/primitive-config/configurable.macro.js",
    "content": "const {createMacro} = require('../../..')\n\nconst configName = 'configurableMacro'\nconst realMacro = jest.fn()\nmodule.exports = createMacro(realMacro, {configName})\n// for testing purposes only\nObject.assign(module.exports, {\n  realMacro,\n  configName,\n})\n"
  },
  {
    "path": "src/__tests__/index.js",
    "content": "import path from 'path'\nimport {cosmiconfigSync as cosmiconfigSyncMock} from 'cosmiconfig'\nimport cpy from 'cpy'\nimport babel from '@babel/core'\nimport pluginTester from 'babel-plugin-tester'\nimport plugin from '../'\n\nconst projectRoot = path.join(__dirname, '../../')\n\njest.mock('cosmiconfig', () => {\n  const cosmiconfigExports = jest.requireActual('cosmiconfig')\n  const actualCosmiconfigSync = cosmiconfigExports.cosmiconfigSync\n  function fakeCosmiconfigSync(...args) {\n    fakeCosmiconfigSync.explorer = actualCosmiconfigSync(...args)\n    return fakeCosmiconfigSync.explorer\n  }\n  return {...cosmiconfigExports, cosmiconfigSync: fakeCosmiconfigSync}\n})\n\nbeforeAll(() => {\n  // copy our mock modules to the node_modules directory\n  // so we can test how things work when importing a macro\n  // from the node_modules directory.\n  return cpy(['**/*.js'], path.join('..', '..', 'node_modules'), {\n    parents: true,\n    cwd: path.join(projectRoot, 'other', 'mock-modules'),\n  })\n})\n\nbeforeEach(() => {\n  jest.spyOn(console, 'error').mockImplementation(() => {})\n})\n\nafterEach(() => {\n  console.error.mockRestore()\n  jest.clearAllMocks()\n})\n\nexpect.addSnapshotSerializer({\n  print(val) {\n    return (\n      val\n        .split(projectRoot)\n        .join('<PROJECT_ROOT>/')\n        .replace(/\\\\/g, '/')\n        // Remove the path of file which thrown an error\n        .replace(/Error:[^:]*:/, 'Error:')\n    )\n  },\n  test(val) {\n    return typeof val === 'string'\n  },\n})\n\npluginTester({\n  plugin,\n  snapshot: true,\n  babelOptions: {\n    filename: __filename,\n    parserOpts: {\n      plugins: ['jsx'],\n    },\n    generatorOpts: {quotes: 'double'},\n  },\n  tests: [\n    {\n      title: 'does nothing to code that does not import macro',\n      snapshot: false,\n      code: `\n        import foo from './some-file-without-macro'\n\n        const bar = require('./some-other-file-without-macro')\n      `,\n    },\n    {\n      title: 'does nothing but remove macros if it is unused',\n      snapshot: true,\n      code: `\n        import foo from \"./fixtures/eval.macro\";\n\n        const bar = 42;\n      `,\n    },\n    {\n      title: 'raises an error if macro does not exist',\n      error: true,\n      code: `\n        import foo from './some-macros-that-doesnt-even-need-to-exist.macro'\n        export default 'something else'\n      `,\n    },\n    {\n      title: 'works with import',\n      code: `\n        import myEval from './fixtures/eval.macro'\n        const x = myEval\\`34 + 45\\`\n      `,\n    },\n    {\n      title: 'works with require',\n      code: `\n        const evaler = require('./fixtures/eval.macro')\n        const x = evaler\\`34 + 45\\`\n      `,\n    },\n    {\n      title: 'works with require destructuring',\n      code: `\n        const {css, styled} = require('./fixtures/emotion.macro')\n        const red = css\\`\n          background-color: red;\n        \\`\n\n        const Div = styled.div\\`\n          composes: \\${red}\n          color: blue;\n        \\`\n      `,\n    },\n    {\n      title: 'works with require destructuring and aliasing',\n      code: `\n        const {css: CSS, styled: STYLED} = require('./fixtures/emotion.macro')\n        const red = CSS\\`\n          background-color: red;\n        \\`\n\n        const Div = STYLED.div\\`\n          composes: \\${red}\n          color: blue;\n        \\`\n      `,\n    },\n    {\n      title: 'works with function calls',\n      code: `\n        import myEval from './fixtures/eval.macro'\n        const x = myEval('34 + 45')\n      `,\n    },\n    {\n      title: 'Works as a JSXElement',\n      code: `\n        import MyEval from './fixtures/eval.macro'\n        const x = <MyEval>34 + 45</MyEval>\n      `,\n    },\n    {\n      title: 'Supports named imports',\n      code: `\n        import {css as CSS, styled as STYLED} from './fixtures/emotion.macro'\n        const red = CSS\\`\n          background-color: red;\n        \\`\n\n        const Div = STYLED.div\\`\n          composes: \\${red}\n          color: blue;\n        \\`\n      `,\n    },\n    {\n      title: 'supports compiled macros (`__esModule` + `export default`)',\n      code: `\n        import {css, styled} from './fixtures/emotion-esm.macro'\n        const red = css\\`\n          background-color: red;\n        \\`\n\n        const Div = styled.div\\`\n          composes: \\${red}\n          color: blue;\n        \\`\n      `,\n    },\n    {\n      title: 'supports macros from node_modules',\n      code: `\n        import fakeMacro from 'babel-plugin-macros-test-fake/macro'\n        fakeMacro('hi')\n      `,\n      teardown() {\n        try {\n          // kinda abusing the babel-plugin-tester API here\n          // to make an extra assertion\n          // eslint-disable-next-line\n          const fakeMacro = require('babel-plugin-macros-test-fake/macro')\n          expect(fakeMacro.innerFn).toHaveBeenCalledTimes(1)\n          expect(fakeMacro.innerFn).toHaveBeenCalledWith({\n            references: expect.any(Object),\n            source: expect.stringContaining(\n              'babel-plugin-macros-test-fake/macro',\n            ),\n            state: expect.any(Object),\n            babel: expect.any(Object),\n            isBabelMacrosCall: true,\n          })\n          expect(fakeMacro.innerFn.mock.calls[0].babel).toBe(babel)\n        } catch (e) {\n          console.error(e)\n          throw e\n        }\n      },\n    },\n    {\n      title: 'supports macros from node_modules with scope',\n      code: `\n        import fakeMacro from '@scope/package/macro'\n        fakeMacro('hi')\n      `,\n      teardown() {\n        try {\n          // kinda abusing the babel-plugin-tester API here\n          // to make an extra assertion\n          // eslint-disable-next-line\n          const fakeMacro = require('@scope/package/macro')\n          expect(fakeMacro.innerFn).toHaveBeenCalledTimes(1)\n          expect(fakeMacro.innerFn).toHaveBeenCalledWith({\n            references: expect.any(Object),\n            source: expect.stringContaining('@scope/package/macro'),\n            state: expect.any(Object),\n            babel: expect.any(Object),\n            isBabelMacrosCall: true,\n          })\n          expect(fakeMacro.innerFn.mock.calls[0].babel).toBe(babel)\n        } catch (e) {\n          console.error(e)\n          throw e\n        }\n      },\n    },\n    {\n      title: 'optionally keep imports (variable assignment)',\n      code: `\n        const macro = require('./fixtures/keep-imports.macro')\n        const red = macro('noop');\n      `,\n    },\n    {\n      title: 'optionally keep imports (import declaration)',\n      code: `\n        import macro from './fixtures/keep-imports.macro'\n        const red = macro('noop');\n      `,\n    },\n    {\n      title:\n        'optionally keep imports in combination with babel-preset-env (#80)',\n      code: `\n        import macro from './fixtures/keep-imports.macro'\n        const red = macro('noop')\n      `,\n      babelOptions: {\n        plugins: [\n          require.resolve('babel-plugin-transform-es2015-modules-commonjs'),\n        ],\n      },\n    },\n    {\n      title: 'throws an error if the macro is not properly wrapped',\n      error: true,\n      code: `\n        import unwrapped from './fixtures/non-wrapped.macro'\n        unwrapped('hey')\n      `,\n    },\n    {\n      title: 'forwards MacroErrors thrown by the macro',\n      error: true,\n      code: `\n        import errorThrower from './fixtures/macro-error-thrower.macro'\n        errorThrower('hey')\n      `,\n    },\n    {\n      title: 'prepends the relative path for errors thrown by the macro',\n      error: true,\n      code: `\n        import errorThrower from './fixtures/error-thrower.macro'\n        errorThrower('hey')\n      `,\n    },\n    {\n      title: 'appends the npm URL for errors thrown by node modules',\n      error: true,\n      code: `\n        import errorThrower from 'babel-plugin-macros-test-error-thrower.macro'\n        errorThrower('hi')\n      `,\n    },\n    {\n      title:\n        'appends the npm URL for errors thrown by node modules with a slash',\n      error: true,\n      code: `\n        import errorThrower from 'babel-plugin-macros-test-error-thrower/macro'\n        errorThrower('hi')\n      `,\n    },\n    {\n      title: 'macros can set their configName and get their config',\n      fixture: path.join(__dirname, 'fixtures/config/code.js'),\n      teardown() {\n        try {\n          const babelMacrosConfig = require('./fixtures/config/babel-plugin-macros.config')\n          const configurableMacro = require('./fixtures/config/configurable.macro')\n          expect(configurableMacro.realMacro).toHaveBeenCalledTimes(1)\n          expect(configurableMacro.realMacro.mock.calls[0][0].config).toEqual(\n            babelMacrosConfig[configurableMacro.configName],\n          )\n\n          configurableMacro.realMacro.mockClear()\n        } catch (e) {\n          console.error(e)\n          throw e\n        }\n      },\n    },\n    {\n      title:\n        'when there is an error reading the config, a helpful message is logged',\n      error: true,\n      fixture: path.join(__dirname, 'fixtures/config/code.js'),\n      setup() {\n        jest\n          .spyOn(cosmiconfigSyncMock.explorer, 'search')\n          .mockImplementationOnce(() => {\n            throw new Error('this is a cosmiconfig error')\n          })\n        jest.spyOn(console, 'error').mockImplementationOnce(() => {})\n        return function teardown() {\n          try {\n            expect(console.error).toHaveBeenCalledTimes(1)\n            expect(console.error.mock.calls[0]).toMatchSnapshot()\n            console.error.mockClear()\n          } catch (e) {\n            console.error(e)\n            console.error.mockClear()\n            throw e\n          }\n        }\n      },\n    },\n    {\n      title: 'when there is no config to load, then no config is passed',\n      fixture: path.join(__dirname, 'fixtures/config/code.js'),\n      setup() {\n        jest\n          .spyOn(cosmiconfigSyncMock.explorer, 'search')\n          .mockImplementationOnce(() => {\n            return null\n          })\n        return function teardown() {\n          try {\n            const configurableMacro = require('./fixtures/config/configurable.macro')\n            expect(configurableMacro.realMacro).toHaveBeenCalledTimes(1)\n            expect(configurableMacro.realMacro.mock.calls[0][0].config).toEqual(\n              {},\n            )\n            configurableMacro.realMacro.mockClear()\n          } catch (e) {\n            console.error(e)\n            throw e\n          }\n        }\n      },\n    },\n    {\n      title: 'when configuration is specified in plugin options',\n      pluginOptions: {\n        configurableMacro: {\n          someConfig: false,\n          somePluginConfig: true,\n        },\n      },\n      fixture: path.join(__dirname, 'fixtures/config/code.js'),\n      teardown() {\n        try {\n          const configurableMacro = require('./fixtures/config/configurable.macro')\n          expect(configurableMacro.realMacro).toHaveBeenCalledTimes(1)\n          expect(configurableMacro.realMacro.mock.calls[0][0].config).toEqual({\n            fileConfig: true,\n            someConfig: true,\n            somePluginConfig: true,\n          })\n          configurableMacro.realMacro.mockClear()\n        } catch (e) {\n          console.error(e)\n          throw e\n        }\n      },\n    },\n    {\n      title: 'when configuration is specified in plugin options',\n      pluginOptions: {\n        configurableMacro: {\n          someConfig: false,\n          somePluginConfig: true,\n        },\n      },\n      fixture: path.join(__dirname, 'fixtures/config/cjs-code.js'),\n      teardown() {\n        try {\n          const configurableMacro = require('./fixtures/config/configurable.macro')\n          expect(configurableMacro.realMacro).toHaveBeenCalledTimes(1)\n          expect(configurableMacro.realMacro.mock.calls[0][0].config).toEqual({\n            fileConfig: true,\n            someConfig: true,\n            somePluginConfig: true,\n          })\n          configurableMacro.realMacro.mockClear()\n        } catch (e) {\n          console.error(e)\n          throw e\n        }\n      },\n    },\n    {\n      title: 'when configuration is specified incorrectly in plugin options',\n      fixture: path.join(__dirname, 'fixtures/config/code.js'),\n      pluginOptions: {\n        configurableMacro: 2,\n      },\n      teardown() {\n        try {\n          const configurableMacro = require('./fixtures/config/configurable.macro')\n          expect(configurableMacro.realMacro).toHaveBeenCalledTimes(1)\n          expect(configurableMacro.realMacro).not.toHaveBeenCalledWith(\n            expect.objectContaining({\n              config: expect.any,\n            }),\n          )\n          configurableMacro.realMacro.mockClear()\n        } catch (e) {\n          console.error(e)\n          throw e\n        }\n      },\n    },\n    {\n      title: 'when a custom isMacrosName option is used on a import',\n      pluginOptions: {\n        isMacrosName(v) {\n          return v.endsWith('-macro.js')\n        },\n      },\n      code: `\n        import myEval from './fixtures/eval-macro.js'\n        const x = myEval\\`34 + 45\\`\n      `,\n    },\n    {\n      title: 'when a custom isMacrosName option is used on a require',\n      pluginOptions: {\n        isMacrosName(v) {\n          return v.endsWith('-macro.js')\n        },\n      },\n      code: `\n        const evaler = require('./fixtures/eval-macro.js')\n        const x = evaler\\`34 + 45\\`\n      `,\n    },\n    {\n      title:\n        'when plugin options configuration cannot be merged with file configuration',\n      error: true,\n      fixture: path.join(__dirname, 'fixtures/primitive-config/code.js'),\n      pluginOptions: {\n        configurableMacro: {},\n      },\n    },\n    {\n      title:\n        'when a plugin that replaces paths is used, macros still work properly',\n      fixture: path.join(\n        __dirname,\n        'fixtures/path-replace-issue/variable-assignment.js',\n      ),\n      babelOptions: {\n        babelrc: true,\n      },\n    },\n    {\n      title: 'Macros are applied in the order respecting plugins order',\n      code: `\n        import Wrap from \"./fixtures/jsx-id-prefix.macro\";\n\n        const bar = Wrap(<div id=\"d1\"><p id=\"p1\"></p></div>);\n      `,\n      babelOptions: {\n        presets: [{plugins: [require('./fixtures/jsx-id-prefix.plugin')]}],\n      },\n    },\n  ],\n})\n\n/* eslint no-console:0 */\n"
  },
  {
    "path": "src/index.js",
    "content": "const p = require('path')\nconst resolve = require('resolve')\n// const printAST = require('ast-pretty-print')\n\nconst macrosRegex = /[./]macro(\\.c?js)?$/\nconst testMacrosRegex = v => macrosRegex.test(v)\n\n// https://stackoverflow.com/a/32749533/971592\nclass MacroError extends Error {\n  constructor(message) {\n    super(message)\n    this.name = 'MacroError'\n    /* istanbul ignore else */\n    if (typeof Error.captureStackTrace === 'function') {\n      Error.captureStackTrace(this, this.constructor)\n    } else if (!this.stack) {\n      this.stack = new Error(message).stack\n    }\n  }\n}\n\nlet _configExplorer = null\nfunction getConfigExplorer() {\n  return (_configExplorer =\n    _configExplorer ||\n    // Lazy load cosmiconfig since it is a relatively large bundle\n    require('cosmiconfig').cosmiconfigSync('babel-plugin-macros', {\n      searchPlaces: [\n        'package.json',\n        '.babel-plugin-macrosrc',\n        '.babel-plugin-macrosrc.json',\n        '.babel-plugin-macrosrc.yaml',\n        '.babel-plugin-macrosrc.yml',\n        '.babel-plugin-macrosrc.js',\n        'babel-plugin-macros.config.js',\n      ],\n      packageProp: 'babelMacros',\n    }))\n}\n\nfunction createMacro(macro, options = {}) {\n  if (options.configName === 'options') {\n    throw new Error(\n      `You cannot use the configName \"options\". It is reserved for babel-plugin-macros.`,\n    )\n  }\n  macroWrapper.isBabelMacro = true\n  macroWrapper.options = options\n  return macroWrapper\n\n  function macroWrapper(args) {\n    const {source, isBabelMacrosCall} = args\n    if (!isBabelMacrosCall) {\n      throw new MacroError(\n        `The macro you imported from \"${source}\" is being executed outside the context of compilation with babel-plugin-macros. ` +\n          `This indicates that you don't have the babel plugin \"babel-plugin-macros\" configured correctly. ` +\n          `Please see the documentation for how to configure babel-plugin-macros properly: ` +\n          'https://github.com/kentcdodds/babel-plugin-macros/blob/master/other/docs/user.md',\n      )\n    }\n    return macro(args)\n  }\n}\n\nfunction nodeResolvePath(source, basedir) {\n  return resolve.sync(source, {\n    basedir,\n    extensions: ['.js', '.ts', '.tsx', '.mjs', '.cjs', '.jsx'],\n    // This is here to support the package being globally installed\n    // read more: https://github.com/kentcdodds/babel-plugin-macros/pull/138\n    paths: [p.resolve(__dirname, '../../')],\n  })\n}\n\nfunction macrosPlugin(\n  babel,\n  // istanbul doesn't like the default of an object for the plugin options\n  // but I think older versions of babel didn't always pass options\n  // istanbul ignore next\n  {\n    require: _require = require,\n    resolvePath = nodeResolvePath,\n    isMacrosName = testMacrosRegex,\n    ...options\n  } = {},\n) {\n  function interopRequire(path) {\n    // eslint-disable-next-line import/no-dynamic-require\n    const o = _require(path)\n    return o && o.__esModule && o.default ? o.default : o\n  }\n\n  return {\n    name: 'macros',\n    visitor: {\n      Program(progPath, state) {\n        progPath.traverse({\n          ImportDeclaration(path) {\n            const isMacros = looksLike(path, {\n              node: {\n                source: {\n                  value: v => isMacrosName(v),\n                },\n              },\n            })\n            if (!isMacros) {\n              return\n            }\n            const imports = path.node.specifiers.map(s => ({\n              localName: s.local.name,\n              importedName:\n                s.type === 'ImportDefaultSpecifier'\n                  ? 'default'\n                  : s.imported.name,\n            }))\n            const source = path.node.source.value\n            const result = applyMacros({\n              path,\n              imports,\n              source,\n              state,\n              babel,\n              interopRequire,\n              resolvePath,\n              options,\n            })\n\n            if (!result || !result.keepImports) {\n              path.remove()\n            }\n          },\n          VariableDeclaration(path) {\n            const isMacros = child =>\n              looksLike(child, {\n                node: {\n                  init: {\n                    callee: {\n                      type: 'Identifier',\n                      name: 'require',\n                    },\n                    arguments: args =>\n                      args.length === 1 && isMacrosName(args[0].value),\n                  },\n                },\n              })\n\n            path\n              .get('declarations')\n              .filter(isMacros)\n              .forEach(child => {\n                const imports = child.node.id.name\n                  ? [{localName: child.node.id.name, importedName: 'default'}]\n                  : child.node.id.properties.map(property => ({\n                      localName: property.value.name,\n                      importedName: property.key.name,\n                    }))\n\n                const call = child.get('init')\n                const source = call.node.arguments[0].value\n                const result = applyMacros({\n                  path: call,\n                  imports,\n                  source,\n                  state,\n                  babel,\n                  interopRequire,\n                  resolvePath,\n                  options,\n                })\n\n                if (!result || !result.keepImports) {\n                  child.remove()\n                }\n              })\n          },\n        })\n      },\n    },\n  }\n}\n\n// eslint-disable-next-line complexity\nfunction applyMacros({\n  path,\n  imports,\n  source,\n  state,\n  babel,\n  interopRequire,\n  resolvePath,\n  options,\n}) {\n  /* istanbul ignore next (pretty much only useful for astexplorer I think) */\n  const {\n    file: {\n      opts: {filename = ''},\n    },\n  } = state\n  let hasReferences = false\n  const referencePathsByImportName = imports.reduce(\n    (byName, {importedName, localName}) => {\n      const binding = path.scope.getBinding(localName)\n\n      byName[importedName] = binding.referencePaths\n      hasReferences = hasReferences || Boolean(byName[importedName].length)\n\n      return byName\n    },\n    {},\n  )\n\n  const isRelative = source.indexOf('.') === 0\n  const requirePath = resolvePath(source, p.dirname(getFullFilename(filename)))\n\n  const macro = interopRequire(requirePath)\n  if (!macro.isBabelMacro) {\n    throw new Error(\n      `The macro imported from \"${source}\" must be wrapped in \"createMacro\" ` +\n        `which you can get from \"babel-plugin-macros\". ` +\n        `Please refer to the documentation to see how to do this properly: https://github.com/kentcdodds/babel-plugin-macros/blob/master/other/docs/author.md#writing-a-macro`,\n    )\n  }\n  const config = getConfig(macro, filename, source, options)\n\n  let result\n  try {\n    /**\n     * Other plugins that run before babel-plugin-macros might use path.replace, where a path is\n     * put into its own replacement. Apparently babel does not update the scope after such\n     * an operation. As a remedy, the whole scope is traversed again with an empty \"Identifier\"\n     * visitor - this makes the problem go away.\n     *\n     * See: https://github.com/kentcdodds/import-all.macro/issues/7\n     */\n    state.file.scope.path.traverse({\n      Identifier() {},\n    })\n\n    result = macro({\n      references: referencePathsByImportName,\n      source,\n      state,\n      babel,\n      config,\n      isBabelMacrosCall: true,\n    })\n  } catch (error) {\n    if (error.name === 'MacroError') {\n      throw error\n    }\n    error.message = `${source}: ${error.message}`\n    if (!isRelative) {\n      error.message = `${\n        error.message\n      } Learn more: https://www.npmjs.com/package/${source.replace(\n        // remove everything after package name\n        // @org/package/macro -> @org/package\n        // package/macro      -> package\n        /^((?:@[^/]+\\/)?[^/]+).*/,\n        '$1',\n      )}`\n    }\n    throw error\n  }\n  return result\n}\n\nfunction getConfigFromFile(configName, filename) {\n  try {\n    const loaded = getConfigExplorer().search(filename)\n\n    if (loaded) {\n      return {\n        options: loaded.config[configName],\n        path: loaded.filepath,\n      }\n    }\n  } catch (e) {\n    return {error: e}\n  }\n  return {}\n}\n\nfunction getConfigFromOptions(configName, options) {\n  if (options.hasOwnProperty(configName)) {\n    if (options[configName] && typeof options[configName] !== 'object') {\n      // eslint-disable-next-line no-console\n      console.error(\n        `The macro plugin options' ${configName} property was not an object or null.`,\n      )\n    } else {\n      return {options: options[configName]}\n    }\n  }\n  return {}\n}\n\nfunction getConfig(macro, filename, source, options) {\n  const {configName} = macro.options\n  if (configName) {\n    const fileConfig = getConfigFromFile(configName, filename)\n    const optionsConfig = getConfigFromOptions(configName, options)\n\n    if (\n      optionsConfig.options === undefined &&\n      fileConfig.options === undefined &&\n      fileConfig.error !== undefined\n    ) {\n      // eslint-disable-next-line no-console\n      console.error(\n        `There was an error trying to load the config \"${configName}\" ` +\n          `for the macro imported from \"${source}. ` +\n          `Please see the error thrown for more information.`,\n      )\n      throw fileConfig.error\n    }\n\n    if (\n      fileConfig.options !== undefined &&\n      optionsConfig.options !== undefined &&\n      typeof fileConfig.options !== 'object'\n    ) {\n      throw new Error(\n        `${fileConfig.path} specified a ${configName} config of type ` +\n          `${typeof optionsConfig.options}, but the the macros plugin's ` +\n          `options.${configName} did contain an object. Both configs must ` +\n          `contain objects for their options to be mergeable.`,\n      )\n    }\n\n    return {\n      ...optionsConfig.options,\n      ...fileConfig.options,\n    }\n  }\n  return undefined\n}\n\n/*\n istanbul ignore next\n because this is hard to test\n and not worth it...\n */\nfunction getFullFilename(filename) {\n  if (p.isAbsolute(filename)) {\n    return filename\n  }\n  return p.join(process.cwd(), filename)\n}\n\nfunction looksLike(a, b) {\n  return (\n    a &&\n    b &&\n    Object.keys(b).every(bKey => {\n      const bVal = b[bKey]\n      const aVal = a[bKey]\n      if (typeof bVal === 'function') {\n        return bVal(aVal)\n      }\n      return isPrimitive(bVal) ? bVal === aVal : looksLike(aVal, bVal)\n    })\n  )\n}\n\nfunction isPrimitive(val) {\n  // eslint-disable-next-line\n  return val == null || /^[sbn]/.test(typeof val)\n}\n\nmodule.exports = macrosPlugin\nObject.assign(module.exports, {\n  createMacro,\n  MacroError,\n})\n"
  }
]