{"id":28456235,"url":"https://github.com/ertgl/babel-plugin-comment-attributes","last_synced_at":"2025-06-29T10:32:36.093Z","repository":{"id":290350014,"uuid":"973696467","full_name":"ertgl/babel-plugin-comment-attributes","owner":"ertgl","description":"Babel plugin to support free-form metadata in comment attributes.","archived":false,"fork":false,"pushed_at":"2025-06-25T08:17:11.000Z","size":999,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-27T07:40:08.231Z","etag":null,"topics":["babel","babel-plugin","javascript","metadata","preprocessor","typescript"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ertgl.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-04-27T14:49:02.000Z","updated_at":"2025-06-25T08:17:08.000Z","dependencies_parsed_at":"2025-05-05T13:23:38.195Z","dependency_job_id":"18a6a18d-bb41-4d7a-b8a6-bca14fad9361","html_url":"https://github.com/ertgl/babel-plugin-comment-attributes","commit_stats":null,"previous_names":["ertgl/babel-plugin-comment-attributes"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/ertgl/babel-plugin-comment-attributes","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ertgl%2Fbabel-plugin-comment-attributes","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ertgl%2Fbabel-plugin-comment-attributes/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ertgl%2Fbabel-plugin-comment-attributes/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ertgl%2Fbabel-plugin-comment-attributes/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ertgl","download_url":"https://codeload.github.com/ertgl/babel-plugin-comment-attributes/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ertgl%2Fbabel-plugin-comment-attributes/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262217917,"owners_count":23276867,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["babel","babel-plugin","javascript","metadata","preprocessor","typescript"],"created_at":"2025-06-06T23:07:25.387Z","updated_at":"2025-06-29T10:32:36.076Z","avatar_url":"https://github.com/ertgl.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# babel-plugin-comment-attributes\n\n[Babel](https://babeljs.io/) plugin to support free-form metadata in comment\nattributes. Inspired by [Rust](https://www.rust-lang.org/) language.\n\n## Overview\n\n`babel-plugin-comment-attributes` is a Babel plugin that introduces\ncompile-time preprocessing capabilities to the JavaScript language family.\n\nThis can be useful for various purposes, including:\n\n- **Conditional compilation**: Include or exclude code elements based on\n  specific conditions.\n- **Code generation**: Generate code based on attributes specified in comments,\n  similar to macros in functional programming languages.\n- **Metadata annotation**: Attach metadata to code elements for documentation,\n  analysis, optimization, or other purposes.\n\n**Note**: Depending on the use case, using a preprocessor or a loosely coupled\nmacro system in a regular imperative programming language may be considered an\nanti-pattern. The necessary solution must be carefully determined in accordance\nwith the purpose.\n\n## Installation\n\nThe package is available on npm and can be installed using any compatible\npackage manager.\n\n```sh\nnpm install --save-dev babel-plugin-comment-attributes\n```\n\n## Usage\n\nFor the plugin to work, it must be added to the Babel configuration. See the\nfollowing code snippet as a reference.\n\n```js\n/**\n * @import {\n *   type Options as CommentAttributesOptions,\n * } from \"babel-plugin-comment-attributes\";\n */\n\n/**\n * @type {CommentAttributesOptions}\n */\nconst commentAttributesOptions = {\n  context: {\n    // The key-value pairs in the context object are used as global variables\n    // in the meta-sources. The values can be any valid JavaScript expression,\n    // including functions, objects, and primitive values.\n    esm: true,\n  },\n};\n\nmodule.exports = {\n  plugins: [\n    [\n      require.resolve(\"babel-plugin-comment-attributes\"),\n      commentAttributesOptions,\n    ],\n  ],\n};\n```\n\n## Example\n\nThe following example demonstrates how to use the plugin to conditionally\ncompile code based on the presence of a directive in a comment.\n\n```txt\n// #[cfg(esm) ?? __NODE_PATH__.remove()]\nconst __filename = new URL(import.meta.url).pathname;\n```\n\nLet's break down this example. The JavaScript code extracted from the comment\nis the following:\n\n```ts\ncfg(esm) ?? __NODE_PATH__.remove()\n```\n\nWhich is equivalent to the following JavaScript code:\n\n```ts\n(esm ? esm : null) ?? __NODE_PATH__.remove()\n```\n\nThe special variable `__NODE_PATH__` is a Babel object that contains the\nAST node of the code element following the comment currently being processed.\nThe `remove()` method removes the node from the AST. Which means that the code\nelement will be removed from the output if the `esm` variable is falsy. `esm`\nvariable here comes from the context object, as it is set to `true` in the\nBabel configuration (see the previous section). Because the value of `esm` is\ntruthy, the code element will be present in the output.\n\nMore information about the syntax and semantics of the comment attributes can be\nfound in the [Syntax and Semantics](#syntax-and-semantics) section.\n\n## Syntax and Semantics\n\nThe whole logic is quite simple. The plugin parses specially formatted comments\n(`meta-comments`), extracts the directives (`meta-source`), then compiles the\nmeta-source using Babel, and evaluates the transpiled code with\n[Node.js VM](https://nodejs.org/api/vm.html).\n\n### Meta-comments\n\nMeta-comments are comments that contain directives. They are written in a\nspecial format that allows the plugin to recognize them. The format is as\nfollows:\n\n- Starts with `#[` prefix.\n- Continues with a meta-source that can be parsed by Babel (JavaScript by\n  default).\n- Ends with `]` suffix.\n\n### Meta-source\n\nMeta-source is the code that is extracted from the meta-comment. It can be any\nvalid code. The plugin will parse the meta-source and evaluate it at compile\ntime.\n\n### Meta-operator\n\nMeta-operators are special JavaScript functions. They are used in meta-sources\nwithout being called directly. After evaluating the meta-source, processor\nchecks if the result is a meta-operator. If it is, the processor calls the\noperator with the following arguments:\n\n- `__PROGRAM_PATH__`: The path object for the AST node of the program currently\n  being processed.\n- `__PROGRAM_STATE__`: The state object for the AST node of the program\n  currently being processed.\n- `__NODE_PATH__`: The path object for the AST node of the code element\n  following the meta-comment currently being processed.\n- `__NOTE_STATE__`: The state object for the AST node of the code element\n  following the meta-comment currently being processed.\n- Context: The context object passed to the plugin. It also contains the\n  special variables at this stage.\n\nTo be able to use a meta-operator, it must be provided in the context object.\nThe function `defineMetaOperator` can be used to define a meta-operator with\nthe guide of the type definitions.\n\nFor demonstration purposes, the following code defines a meta-operator that\nremoves the node from the AST:\n\n```ts\nimport { defineMetaOperator } from \"babel-plugin-comment-attributes\";\n\nexport const OPERATOR_REMOVE = defineMetaOperator({\n  name: \"remove\",\n  operate: (\n    programPath,\n    programState,\n    nodePath,\n    nodeState,\n    context,\n  ) =\u003e\n  {\n    nodePath.remove();\n  },\n});\n\nconst remove = () =\u003e OPERATOR_REMOVE;\n```\n\nAfter that, usage of this meta-operator in a meta-source would look like this:\n\n```ts\n// #[cfg(esm) ?? remove()]\nconst require = createRequire(new URL(import.meta.url).pathname);\n```\n\n### Context\n\nThe context object stores the global variables to be available in meta-sources.\nIt can be extended with any key-value pairs using the `context` option in the\nplugin options. The special variables (except `cfg`) in the context object\ncannot be overridden.\n\n### Special Variables\n\nThe plugin provides a set of special variables that can be used in\nmeta-sources. These variables are available in the context of\nmeta-sources and they can be used to access/set information about the code\nbeing processed, and/or to control the behavior of the processor.\n\nThe following table lists the special variables provided by the plugin:\n\n\u003ctable\u003e\n  \u003cthead\u003e\n    \u003ctr\u003e\n      \u003cth\u003eName\u003c/th\u003e\n      \u003cth\u003eDescription\u003c/th\u003e\n    \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003ccode\u003ecfg\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003e\n        Function that accepts a single argument. Returns \u003ccode\u003enull\u003c/code\u003e if\n        the argument is falsy, otherwise returns the argument itself. It can be\n        overridden by providing a custom implementation in the\n        \u003ccode\u003econtext\u003c/code\u003e object.\n      \u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003ccode\u003e__COMMENT__\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003e\n        Code element of the leading meta-comment currently being processed.\n      \u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003ccode\u003e__COMMENT_IDX__\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003e\n        Index of the leading meta-comment currently being processed.\n      \u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003ccode\u003e__KEEP_COMMENT_BY_IDX__\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003e\n        Function that accepts a comment index as an argument. Marks the comment\n        at the specified index to be kept in the output.\n      \u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003ccode\u003e__META_AST__\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003e\n        The AST of the meta-source currently being processed.\n      \u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003ccode\u003e__META_BABEL_FILE__\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003e\n        The Babel file object of the meta-source currently being processed.\n      \u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003ccode\u003e__META_SOURCE__\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003e\n        The meta-source currently being processed.\n      \u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003ccode\u003e__NODE__\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003e\n        The AST node of the code element following the leading meta-comment\n        currently being processed.\n      \u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003ccode\u003e__NODE_PATH__\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003e\n        The path object for the AST node of the code element following the\n        leading meta-comment currently being processed.\n      \u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003ccode\u003e__NODE_STATE__\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003e\n        The state object for the AST node of the code element following the\n        leading meta-comment currently being processed.\n      \u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003ccode\u003e__PROGRAM_NODE__\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003e\n        The AST node of the program currently being processed.\n      \u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003ccode\u003e__PROGRAM_NODE_PATH__\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003e\n        The path object for the AST node of the program currently being\n        processed.\n      \u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003ccode\u003e__PROGRAM_STATE__\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003e\n        The state object for the AST node of the program currently being\n        processed.\n      \u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003ccode\u003e__REMOVE_COMMENT_BY_IDX__\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003e\n        Function that accepts a comment index as an argument. Marks the\n        comment at the specified index to be removed from the output.\n        Meta-comments are removed from the output by default, unless overridden\n        by the \u003ccode\u003eremoveMetaComments\u003c/code\u003e option.\n      \u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\n## References\n\n- [Attributes - The Rust Reference](https://doc.rust-lang.org/reference/attributes.html)\n- [Conditional compilation - Wikipedia](https://en.wikipedia.org/wiki/Conditional_compilation)\n- [Macro (computer science) - Wikipedia](https://en.wikipedia.org/wiki/Macro_(computer_science))\n\n## License\n\nThis project is licensed under the\n[MIT License](https://opensource.org/license/mit).\nSee the [LICENSE](LICENSE) file for more information.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fertgl%2Fbabel-plugin-comment-attributes","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fertgl%2Fbabel-plugin-comment-attributes","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fertgl%2Fbabel-plugin-comment-attributes/lists"}