Installations
npm install babel-plugin-as-macro
Releases
Unable to fetch releases
Developer
mr-shabani
Developer Guide
Module System
CommonJS
Min. Node Version
Typescript Support
No
Node Version
10.22.0
NPM Version
6.14.6
Statistics
3 Stars
49 Commits
1 Watching
1 Branches
1 Contributors
Updated on 08 Nov 2021
Bundle Size
29.50 kB
Minified
8.88 kB
Minified + Gzipped
Languages
JavaScript (100%)
Total Downloads
Cumulative downloads
Total Downloads
958
Last day
0%
1
Compared to previous day
Last week
200%
3
Compared to previous week
Last month
0%
6
Compared to previous month
Last year
-30.2%
127
Compared to previous year
Daily Downloads
Weekly Downloads
Monthly Downloads
Yearly Downloads
Dependencies
3
Dev Dependencies
3
babel-plugin-as-macro
Power of macro in javascript code.
Motivation
When I was using Next.js, I want to use the y18n module for internationalization. But y18n uses the file system(fs
module) to save words and their meanings. Importing any module that uses the file system is prohibited by next.js. The first solution that I found, was preval module. But my need is more. I want to have a syntax as simple as :
1import React from "react"; 2import /*as macro*/ y18n from "y18n"; 3{/*as macro*/{ 4 y18n = y18n(/* some config */); 5 y18n.setLocal("en") 6 var __ = y18n.__; 7}} 8export default function page() { 9 return ( 10 <div> 11 <p>{__("HELLO WORLD")}</p> 12 <button>{y18n.__n("one button", "%d two button", 2)}</button> 13 </div> 14 ); 15}
Installation
You can install this module via npm.
npm install --save-dev babel-plugin-as-macro
Then, you must configure babel with .babelrc
file.
1{ 2 //... 3 // "presets": ["next/babel"], /* Add this line if you want to use with next.js */ 4 "plugin": [ 5 // other plugins that you want to 6 // be executed before this plugin 7 ["as-macro",/*plugin options*/], 8 // plugins that will be executed 9 // after this plugin 10 ] 11}
Usage
Macro Definition
There are three ways to define a macro. Because of the nature of macro that is not in any scope of your code, we force by default that macro definitions only be possible in the global scope.
Import Declaration
You can define macro by importing a module. You must place the comment block /*as macro*/
after import
identifier.
1import /*as macro*/ y18n from "y18n"; 2import /*as macro*/ X,{x1 as y1,x2 as y2} from "anyModule";
The import statement will be deleted from the code.
In the import statement you can use ECMAScript modules(don't use *.jsx
) or node modules. We use esm module for importing ECMAScript modules.
Variable Declaration
You can define macro by defining variables. You must place the comment block /*as macro*/
after var
identifier.
1var /*as macro*/ y18n = require("y18n")(/*some config*/); 2var /*as macro*/ __ = y18n.__ , str = "some string";
Variable declaration statement will be deleted from the code.
Block Statement
You can run any nodejs code in a macro-block like a macro definition. The syntax of macro-block is a block statement in the global that has a comment block /*as macro*/
at the first and a block statement after that.
1{/*as macro*/{ 2// This block will be run at build time 3}}
You can do anything possible in nodejs in a macro-block. Variables that are defined in macro-block with var
will also be a macro.
1{/*as macro*/{ 2 var y18n = require("y18n"); 3 y18n = y18n(/*some config*/); 4 var __ = y18n.__; 5 console.log("this will be printed at build time"); 6 let x = 1; /* this is not macro because this is 7 a local variable that is only accessible in this block */ 8 while(x<10){ 9 console.log(x); 10 x++; 11 } 12}}
The macro-block will be deleted from the code.
Macro Expression
Macro aims to execute some expression and replace the result in the code. Any expression that is a sequence of object memberships, function calls, and tag templates with a macro name as the main object will be caught as a macro expression.
1macroName; 2macroName`this macro is a function`; 3macroName.property.method(some, argument).tagTemplateMethod`some string` 4 .anotherProperty;
The macro expression will be run in nodejs, and the result will be replaced in the code. For replacement we use json-scriptify module.
Example 1:
1var /*as macro*/ m = { x: 1 }; 2{ 3 /*as macro*/ { 4 m.str = "some string"; 5 } 6} 7let obj = m;
1let obj = { 2 x: 1, 3 str: "some string" 4};
Example 2:
1{ 2 /*as macro*/ { 3 var macroFunction = function computeAtCompileTime() { 4 return "Result"; 5 }; 6 } 7} 8console.log(macroFunction()); 9let obj = macroFunction;
1console.log("Result"); 2 3let obj = function computeAtCompileTime() { 4 return "Result"; 5};
Example 3:
All occurrences of a macro name, except variable definition, will be caught as macro expression. This can bite you.
1var /*as macro*/ m1 = "this is a macro", 2 m2 = "this is another macro"; 3var f = function double(m1) { 4 let m2 = 2 * m1; 5 return m2; 6};
1var f = function double("this is a macro") { 2 let m2 = 2 * "this is a macro"; 3 return "this is another macro"; 4};
Plugin Options
The plugin option is an object. You can access values in this object by info tool.
followScopes
followScopes
is a boolean option that is false
by default. If you set this option to true
, you can use macro-block or define macro variables in any scope. Then, macros only available in that scope.
1var /*as macro*/ m1 = "this is a macro", 2 m2 = "this is another macro"; 3var f = function double(m1) { 4 { 5 /*as macro*/ { 6 var localMacro = "this is local"; 7 } 8 } 9 let m2 = 2 * m1; 10 var str = localMacro; 11 return m2; 12}; 13var globalString = localMacro;
1var f = function double(m1) { 2 let m2 = 2 * m1; 3 var str = "this is local"; 4 return m2; 5}; 6var globalString = localMacro;
But, why we don't set followScopes
to true
by default? Because people may have mistakes like bellow.
1if (bool) { 2 var /*as macro*/ m = "bool is true"; 3} else { 4 var /*as macro*/ m = "bool is false"; 5} 6var string = m;
1if (bool) { 2} else { 3} 4var string = "bool is false";
Regardless of variable bool
, string
is always "bool is false"
. Because both macro definitions are executed and the second definition overwrites first. Moreover, macros are executed at build time when bool
has not been evaluated.
Tools
info
If you want to have some information about the file in which macros are defined and executed in, You can use info
. You can import it from babel-plugin-as-macro/info
in any module and use it.
For example, you can have conf.js
module that detects some config, like language, from the file path.
1// conf.js 2var info = require("babel-plugin-as-macro/info"); 3let someConfigurations = decideFrom(info.absolutePath); 4module.exports = someConfigurations;
Then, you can use this module as macro in your code.
1// main.js 2import /*as macro*/ conf from "./conf.js"; 3/* do something with conf */
info
is an object that will be filled by this plugin when the plugin start.
1info = { 2 options, // plugin options 3 filename, // the name of file or "unknown" if has transformed from string 4 root, // path to root of the project(directory of package.json) 5 absoluteDir, // absolute path to the file directory 6 relativeDir, // path to the directory relative to the root 7 envName //process.env.BABEL_ENV || process.env.NODE_ENV || "development" 8};
License
MIT
No vulnerabilities found.
Reason
no binaries found in the repo
Reason
0 existing vulnerabilities detected
Reason
license file detected
Details
- Info: project has a license file: LICENSE:0
- Info: FSF or OSI recognized license: MIT License: LICENSE:0
Reason
Found 0/30 approved changesets -- score normalized to 0
Reason
0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Reason
no SAST tool detected
Details
- Warn: no pull requests merged into dev branch
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
security policy file not detected
Details
- Warn: no security policy file detected
- Warn: no security file to analyze
- Warn: no security file to analyze
- Warn: no security file to analyze
Reason
project is not fuzzed
Details
- Warn: no fuzzer integrations found
Reason
branch protection not enabled on development/release branches
Details
- Warn: branch protection not enabled for branch 'master'
Score
3
/10
Last Scanned on 2024-11-18
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More