简体   繁体   English

寻找自定义 JSX babel 插件,它可以简单地将 jsx 转换为标记字符串

[英]Looking for custom JSX babel plugin that simply converts jsx to a markup string

It is NOT a react project nor V-DOM related.它既不是 React 项目,也不是 V-DOM 相关的。 I just need a jsx runtime compiler to (HTML/XML) string that will be used later as element.innerHTML = result我只需要一个 jsx 运行时编译器到(HTML/XML)字符串,稍后将用作 element.innerHTML = result

It should be used as a babel-plugin to support a custom library它应该用作 babel-plugin 来支持自定义库

some info: babel-cli@6.26 babel-loader@7.1.2一些信息: 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.而且我必须编写自己的 jsx 解析器,因为任何其他解析器都不会提供我的自定义功能。

This might be what you're looking for:这可能是您正在寻找的:

https://www.npmjs.com/package/jsx-to-html https://www.npmjs.com/package/jsx-to-html

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.这将 jsx 转换为带标签的模板文字(或可选的空字符串以省略标签),并且可以用作起点或直接使用。

(<a href={url} {...o}>#</a>) becomes jsx'<a href=${url} ${{...o}}>#</a>' where the single-quotes are backticks (<a href={url} {...o}>#</a>)变成jsx'<a href=${url} ${{...o}}>#</a>'其中单引号是反引号

https://astexplorer.net/#/gist/fdaed19a884dc75fe4a92092826bd635/9bc3c34e276eaf74cc318da9b87bbe0cfd37ff6d https://astexplorer.net/#/gist/fdaed19a884dc75fe4a92092826bd635/9bc3c34e276eaf74cc318da9b87bbe0cfd37ff6d

transformer js with sample input+output also at (git clonable with the embed-selector) https://gist.github.com/jimmont/63b3a0506d0c5da9a9831e30be22a758带有示例输入+输出的转换器 js 也在(带有嵌入选择器的 git 可克隆) 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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM