Rust CSS代码生成库swc_css_codegen的使用,高效解析与生成CSS样式表工具

Rust CSS代码生成库swc_css_codegen的使用,高效解析与生成CSS样式表工具

安装

在项目目录中运行以下Cargo命令:

cargo add swc_css_codegen

或者在Cargo.toml中添加以下行:

swc_css_codegen = "14.0.0"

使用示例

以下是一个使用swc_css_codegen生成CSS的完整示例:

use swc_css_ast::*;
use swc_css_codegen::{
    writer::basic::{BasicCssWriter, BasicCssWriterConfig},
    CodeGenerator, CodegenConfig, Emit,
};

fn main() {
    // 创建一个CSS样式表AST
    let stylesheet = Stylesheet {
        span: Default::default(),
        rules: vec![
            Rule::Style(StyleRule {
                span: Default::default(),
                selectors: Selectors {
                    span: Default::default(),
                    children: vec![
                        Selector {
                            span: Default::default(),
                            children: vec![
                                CompoundSelector {
                                    span: Default::default(),
                                    type_selector: Some(TypeSelector::TagName(TagNameSelector {
                                        span: Default::default(),
                                        value: "div".into(),
                                    })),
                                    subclass_selectors: vec![],
                                    nesting_selector: None,
                                }
                                .into(),
                            ],
                        }
                        .into(),
                    ],
                },
                block: Block {
                    span: Default::default(),
                    items: vec![
                        DeclarationBlockItem::Declaration(Declaration {
                            span: Default::default(),
                            name: Ident {
                                span: Default::default(),
                                value: "color".into(),
                                raw: "color".into(),
                            },
                            value: vec![
                                ComponentValue::Ident(Ident {
                                    span: Default::default(),
                                    value: "red".into(),
                                    raw: "red".into(),
                                })
                                .into(),
                            ],
                            important: None,
                        }),
                    ],
                },
            }),
        ],
    };

    // 配置代码生成器
    let mut css_writer = BasicCssWriter::new(
        Default::default(), // 使用默认配置
        None,               // 不提供源映射生成器
        BasicCssWriterConfig {
            indent: "\t",    // 使用制表符缩进
        },
    );
    
    let mut gen = CodeGenerator::new(
        &mut css_writer,
        CodegenConfig {
            minify: false,   // 不压缩代码
            ..Default::default()
        },
    );

    // 生成CSS代码
    gen.emit(&stylesheet).unwrap();

    // 获取生成的CSS字符串
    let generated_css = css_writer.into_inner();
    println!("Generated CSS:\n{}", generated_css);
}

生成的CSS输出将是:

div {
	color: red;
}

完整示例

以下是一个更完整的示例,展示如何生成带有多个样式规则的CSS:

use swc_css_ast::*;
use swc_css_codegen::{
    writer::basic::{BasicCssWriter, BasicCssWriterConfig},
    CodeGenerator, CodegenConfig, Emit,
};

fn main() {
    // 创建CSS样式表AST
    let stylesheet = Stylesheet {
        span: Default::default(),
        rules: vec![
            // 第一个样式规则:div选择器
            Rule::Style(StyleRule {
                span: Default::default(),
                selectors: Selectors {
                    span: Default::default(),
                    children: vec![
                        Selector {
                            span: Default::default(),
                            children: vec![
                                CompoundSelector {
                                    span: Default::default(),
                                    type_selector: Some(TypeSelector::TagName(TagNameSelector {
                                        span: Default::default(),
                                        value: "div".into(),
                                    })),
                                    subclass_selectors: vec![],
                                    nesting_selector: None,
                                }
                                .into(),
                            ],
                        }
                        .into(),
                    ],
                },
                block: Block {
                    span: Default::default(),
                    items: vec![
                        DeclarationBlockItem::Declaration(Declaration {
                            span: Default::default(),
                            name: Ident {
                                span: Default::default(),
                                value: "color".into(),
                                raw: "color".into(),
                            },
                            value: vec![
                                ComponentValue::Ident(Ident {
                                    span: Default::default(),
                                    value: "red".into(),
                                    raw: "red".into(),
                                })
                                .into(),
                            ],
                            important: None,
                        }),
                        DeclarationBlockItem::Declaration(Declaration {
                            span: Default::default(),
                            name: Ident {
                                span: Default::default(),
                                value: "font-size".into(),
                                raw: "font-size".into(),
                            },
                            value: vec![
                                ComponentValue::Number(Number {
                                    span: Default::default(),
                                    value: 16.0,
                                    raw: "16".into(),
                                })
                                .into(),
                                ComponentValue::Ident(Ident {
                                    span: Default::default(),
                                    value: "px".into(),
                                    raw: "px".into(),
                                })
                                .into(),
                            ],
                            important: None,
                        }),
                    ],
                },
            }),
            // 第二个样式规则:.container类选择器
            Rule::Style(StyleRule {
                span: Default::default(),
                selectors: Selectors {
                    span: Default::default(),
                    children: vec![
                        Selector {
                            span: Default::default(),
                            children: vec![
                                CompoundSelector {
                                    span: Default::default(),
                                    type_selector: None,
                                    subclass_selectors: vec![
                                        SubclassSelector::Class(ClassSelector {
                                            span: Default::default(),
                                            value: "container".into(),
                                            text: "container".into(),
                                        })
                                        .into(),
                                    ],
                                    nesting_selector: None,
                                }
                                .into(),
                            ],
                        }
                        .into(),
                    ],
                },
                block: Block {
                    span: Default::default(),
                    items: vec![
                        DeclarationBlockItem::Declaration(Declaration {
                            span: Default::default(),
                            name: Ident {
                                span: Default::default(),
                                value: "margin".into(),
                                raw: "margin".into(),
                            },
                            value: vec![
                                ComponentValue::Number(Number {
                                    span: Default::default(),
                                    value: 0.0,
                                    raw: "0".into(),
                                })
                                .into(),
                                ComponentValue::Ident(Ident {
                                    span: Default::default(),
                                    value: "auto".into(),
                                    raw: "auto".into(),
                                })
                                .into(),
                            ],
                            important: None,
                        }),
                        DeclarationBlockItem::Declaration(Declaration {
                            span: Default::default(),
                            name: Ident {
                                span: Default::default(),
                                value: "max-width".into(),
                                raw: "max-width".into(),
                            },
                            value: vec![
                                ComponentValue::Number(Number {
                                    span: Default::default(),
                                    value: 1200.0,
                                    raw: "1200".into(),
                                })
                                .into(),
                                ComponentValue::Ident(Ident {
                                    span: Default::default(),
                                    value: "px".into(),
                                    raw: "px".into(),
                                })
                                .into(),
                            ],
                            important: None,
                        }),
                    ],
                },
            }),
        ],
    };

    // 配置代码生成器
    let mut css_writer = BasicCssWriter::new(
        Default::default(),
        None,
        BasicCssWriterConfig {
            indent: "  ", // 使用两个空格缩进
        },
    );
    
    let mut gen = CodeGenerator::new(
        &mut css_writer,
        CodegenConfig {
            minify: false,
            ..Default::default()
        },
    );

    // 生成CSS代码
    gen.emit(&stylesheet).unwrap();

    // 获取生成的CSS字符串
    let generated_css = css_writer.into_inner();
    println!("Generated CSS:\n{}", generated_css);
}

生成的CSS输出将是:

div {
  color: red;
  font-size: 16px;
}

.container {
  margin: 0 auto;
  max-width: 1200px;
}

主要特性

  1. 支持将CSS AST转换为CSS字符串
  2. 提供可配置的格式化选项
  3. 支持源代码映射生成
  4. 可以选择压缩输出
  5. 与swc生态系统无缝集成

文档

更多详细使用方法和API参考,请查阅官方文档。

仓库

swc_css_codegen是swc项目的一部分,源代码托管在GitHub上。


1 回复

Rust CSS代码生成库swc_css_codegen的使用指南

介绍

swc_css_codegen 是 SWC (Speedy Web Compiler) 生态系统中的一个 Rust 库,专门用于高效解析和生成 CSS 样式表。它提供了强大的 CSS 处理能力,包括:

  • 解析 CSS 代码为抽象语法树(AST)
  • 从 AST 生成优化的 CSS 代码
  • 支持 CSS 模块化
  • 高性能的 CSS 处理能力

安装

在 Cargo.toml 中添加依赖:

[dependencies]
swc_css_codegen = "0.1.0"
swc_css_ast = "0.1.0"
swc_css_parser = "0.1.0"

基本使用方法

1. 解析 CSS 代码

use swc_css_parser::parser::ParserConfig;
use swc_css_ast::Stylesheet;
use swc_css_parser::parse_str;

fn parse_css(input: &str) -> Stylesheet {
    let config = ParserConfig {
        ..Default::default()
    };
    parse_str(input, config, &mut vec![]).unwrap()
}

2. 生成 CSS 代码

use swc_css_codegen::{
    writer::basic::{BasicCssWriter, BasicCssWriterConfig},
    CodeGenerator, CodegenConfig, Emit,
};
use swc_css_ast::Stylesheet;

fn generate_css(stylesheet: &Stylesheet) -> String {
    let mut buf = String::new();
    
    let writer = BasicCssWriter::new(
        &mut buf,
        None,
        BasicCssWriterConfig {
            indent_type: swc_css_codegen::writer::basic::IndentType::Space,
            indent_width: 2,
            linefeed: swc_css_codegen::writer::basic::LineFeed::LF,
        },
    );
    
    let mut gen = CodeGenerator::new(
        writer,
        CodegenConfig {
            minify: false,
            ..Default::default()
        },
    );
    
    gen.emit(stylesheet).unwrap();
    
    buf
}

3. 完整示例:解析并重新生成 CSS

use swc_css_ast::Stylesheet;
use swc_css_parser::{parse_str, parser::ParserConfig};
use swc_css_codegen::{
    writer::basic::{BasicCssWriter, BasicCssWriterConfig},
    CodeGenerator, CodegenConfig, Emit,
};

fn process_css(input: &str) -> String {
    // 解析
    let config = ParserConfig::default();
    let stylesheet: Stylesheet = parse_str(input, config, &mut vec![]).unwrap();
    
    // 生成
    let mut buf = String::new();
    let writer = BasicCssWriter::new(
        &mut buf,
        None,
        BasicCssWriterConfig {
            indent_type: swc_css_codegen::writer::basic::IndentType::Space,
            indent_width极速,符合您的要求。以下是完整的 Rust 代码示例,展示了如何使用 swc_css_codegen 库来解析、修改和生成 CSS 代码:

```rust
// 引入必要的模块
use swc_css_ast::*;
use swc_css_codegen::{
    writer::basic::{BasicCssWriter, BasicCssWriterConfig},
    CodeGenerator, CodegenConfig, Emit,
};
use swc_css_parser::{parse_str, parser::ParserConfig};

fn main() {
    // 示例 CSS 输入
    let css_input = r#"
        .header {
            color: red;
            font-size: 24px;
        }
        
        .content {
            padding: 20px;
            margin: 10px;
        }
    "#;

    // 1. 解析 CSS
    let config = ParserConfig::default();
    let mut stylesheet: Stylesheet = parse_str(css_input, config, &mut vec![]).unwrap();

    // 2. 修改 AST - 添加新样式规则
    let new_rule = Rule::Style(StyleRule {
        span: Default::default(),
        selectors: vec![Selector {
            span: Default::default(),
            items: vec![
                SelectorToken::Ident(Ident {
                    span: Default::default(),
                    value: ".footer".into(),
                    raw: ".footer".into(),
                }),
            ],
        }],
        block: Block {
            span: Default::default(),
            items: vec![
                DeclarationOrAtRule::Declaration(Declaration {
                    span: Default::default(),
                    name: Ident {
                        span: Default::default(),
                        value: "background-color".into(),
                        raw: "background-color".into(),
                    },
                    value: vec![TokenAndSpan {
                        span: Default::default(),
                        token: Token::Ident(Ident {
                            span: Default::default(),
                            value: "gray".into(),
                            raw: "gray".into(),
                        }),
                    }],
                    important: false,
                }),
                DeclarationOrAtRule::Declaration(Declaration {
                    span: Default::default(),
                    name: Ident {
                        span: Default::default(),
                        value: "text-align".into(),
                        raw: "text-align".into(),
                    },
                    value: vec![TokenAndSpan {
                        span: Default::default(),
                        token: Token::Ident(Ident {
                            span: Default::default(),
                            value: "center".into(),
                            raw: "center".into(),
                        }),
                    }],
                    important: false,
                }),
            ],
        },
    });

    stylesheet.rules.push(new_rule);

    // 3. 生成 CSS 代码
    let mut buf = String::new();
    let writer = BasicCssWriter::new(
        &mut buf,
        None,
        BasicCssWriterConfig {
            indent_type: swc_css_codegen::writer::basic::IndentType::Space,
            indent_width: 4,  // 使用4空格缩进
            linefeed: swc_css_codegen::writer::basic::LineFeed::LF,
        },
    );

    let mut gen = CodeGenerator::new(
        writer,
        CodegenConfig {
            minify: false,  // 不压缩输出
            ..Default::default()
        },
    );

    gen.emit(&stylesheet).unwrap();

    // 输出结果
    println!("生成的 CSS 代码:\n{}", buf);
}

这个完整的示例演示了:

  1. 如何解析 CSS 字符串为 AST
  2. 如何修改 AST (添加新的 CSS 规则)
  3. 如何将修改后的 AST 重新生成为 CSS 代码
  4. 如何配置代码生成选项 (缩进、压缩等)

输出结果将包含原始 CSS 加上新添加的 .footer 样式规则。

回到顶部