It is NOT a react project nor V-DOM related. I just need a jsx runtime compiler to (HTML/XML) string that will be used later as element.innerHTML = result
It should be used as a babel-plugin to support a custom library
some info: babel-cli@6.26 babel-loader@7.1.2
I have managed to solve my problem.
babel config: ```
{
"presets": ["env"],
"plugins": ["transform-decorators-legacy", "transform-class-properties",
[
"transform-jsx", {
"function": "jsx"
}
]
]
}
```
And i had to write my own jsx parser as any other parser would not provide my custom features.
This might be what you're looking for:
This converts jsx to tagged template literals (or optional empty string to omit the tag) and can be used as a starting point or directly.
(<a href={url} {...o}>#</a>)
becomes jsx'<a href=${url} ${{...o}}>#</a>'
where the single-quotes are backticks
transformer js with sample input+output also at (git clonable with the embed-selector) https://gist.github.com/jimmont/63b3a0506d0c5da9a9831e30be22a758
'use strict';
/*
node --inspect-brk ./node_modules/.bin/babel ./samplein/ --out-dir ./sampleout --config-file ./babelrc.json
Note this plugin is the last in the list (ie processed first, right-to-left)
{ "plugins":["./otherplugins", "./path/to/babel-jsx-templates.js"] }
{ "plugins":[["./path/to/babel-jsx-templates.js", {tagname:'xyz'}]] }
* translate JSX attribute values and children to either quasis or expressions for a TemplateLiteral
* NOTE expressions 1 item less than quasis, and quasis always 1 more than expressions
@usage .reduce or call directly
@param {object} config - eg {expressions: [expressions], quasis: ['strings', 'later translated to TemplateElement']}
@param {any} item - value
@param {number} index - array index key
*/
function itemize(config, item, index){
if(!item){
return config;
};
if(item.expression){
config.expressions.push(item.expression);
}else if(item.extra){
config.quasis[ config.quasis.length - 1 ] += item.extra.raw;
};
return config;
}
/*
* translate JSX attributes to either quasis or expressions for a TemplateLiteral
* NOTE expressions 1 item less than quasis, and quasis always 1 more than expressions
@usage .reduce or call directly
@param {object} config - eg {expressions: [expressions], quasis: ['strings', 'later translated to TemplateElement']}
@param {any} attr - node
@param {number} index - array index key
*/
function jsxAttributes(config, attr, index){
let value = attr.value;
let name = attr.name;
//console.log(attr.type);
let last = config.expressions.length;
if(name){
// must align with expressions 1-1
// "<Tag" => "<Tag attr" add to existing string
config.quasis[ last ] = (config.quasis[ last ] || '') + (' ' +name.name + (value ? '=':''));
}else if(attr.argument){
// {...it} => JSXSpreadAttribute => Identifier.argument.name = "it"
let types = config.types;
config.quasis[ last ] = ' ';
config.expressions.push( types.objectExpression([types.spreadElement(types.identifier(attr.argument.name))]) );
}
return itemize(config, value);
}
/* transform JSX to tagged template literals
<Any attribute={ 4 }></Any>
@param {object} options - {tagname:'theTagName'}
@param {string} options.tagname - optional tag-name theTagName`for template literal` default 'jsx'
@returns jsx`<Any attribute=${ 4 }></Any>`
* */
function jsxTransform(babel, options={}, dir) {
const types = babel.types;
//babel.assertVersion(7);
const tagname = typeof options.tagname === 'string' ? options.tagname : 'jsx';
return {
// enable JSX parsing, adjust to fit your runtime
inherits: require("@babel/plugin-syntax-jsx").default,
visitor: {
JSXElement(path, state){
let node = path.node.openingElement;
const tagName = node.name.name;
const config = node.attributes.reduce(jsxAttributes, {
quasis: [`<${tagName}`]
,expressions: []
,types
});
let last = config.expressions.length;
// close tag
config.quasis[last] = `${ config.quasis[ last ] || '' }>`;
path.node.children.reduce(itemize, config);
last = config.expressions.length;
// closing tag
config.quasis[last] = `${ config.quasis[ last ] || '' }</${ tagName }>`;
// convert
config.quasis = config.quasis.map(function templateElement(str){
return types.templateElement({raw:str})
});
var templateLiteral;
templateLiteral = types.templateLiteral(config.quasis, config.expressions);
if(path.parent.type === "TaggedTemplateExpression"){
path.replaceWith(templateLiteral);
}else{
path.replaceWith(
types.taggedTemplateExpression(
types.identifier( tagname )
,templateLiteral
)
);
};
}
,JSXFragment(path, state){
console.warn('TODO JSXFragment ie <></>',path.type);
}
}
};
};
/* adjust to fit your runtime:
export default jsxTransform;
module.exports = require('@babel/helper-plugin-utils').declare(jsxTransform);
*/
module.exports = require('@babel/helper-plugin-utils').declare(jsxTransform);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.