likes
comments
collection
share

Rust学习之markdown转换

作者站长头像
站长
· 阅读数 29

前言

rust萌新学习一段时间,想做一些有趣的事情。今天和大家一起来写markdown转换为html的一款rust cli。利用第三方包,不到70行写个cli。如想喷,请轻喷。

实现思路

首先我们来思考一下 cli如何运行, 需要哪些参数

输入参数

  • command param 1: markdown路径
  • command param 2: html路径

输出

  • html文件

运行命令

基于上述思路, 我们得到以下运行命令:

cargo run markdown路径 html路径

这么一看,命令有点复杂,html路径可以省略,作为可选参数传入,默认生成的html路径在markdown目录下。 缩减后得到如下命令:

cargo run markdown路径

编码思路

运行命令搞定接下来就是编码了,具体思路如下:

  • 获取命令的路径
  • 使用pulldown_cmark解析markdown路径,生成html路径
  • 读取markdown内容,转换为html
  • 创建html文件,写入内容
获取参数
pulldown_cmark解析生成
读取内容,转换
创建写入

基于上述思路,分为以下实现函数

  • parse_config 解析配置
  • read_file 读取markdown内容
  • write_file 写入html文件

代码实现

我们先来定义main函数的实现

// env::args().collect() 获取command命令,转为数组
let args:Vec<String> = env::args().collect();
// 把args传入解析函数,返回markdown路径和动态生成的html路径
let params = parse_config(args);
// 读取markdwon内容 转换为html返回
let md_content = read_file(params.md_path);
// 写入
write_file(params.html_path, md_content)

定义params结构

#[derive(Debug)]
struct Config {
    md_path: String,
    html_path: String
}

解析配置 转换为数组后通过next获取下一项

fn parse_config(args: Vec<String>) -> Config {
    let mut args_item = args.iter();
    args_item.next();

    let md_path = match args_item.next() {
        Some(arg) => arg.clone(),
        None => panic!("Markdown 文件路径是必要参数")
    };

    let html_path = match args_item.next() {
        Some(arg) => arg.clone(),
        None => {
            let path = Path::new(&md_path);
            match path.file_stem() {
                Some(stem) => {
                    let mut new_path = PathBuf::from(&md_path);
                    new_path.set_file_name(format!("{}.html", stem.to_string_lossy()));
                    new_path.to_string_lossy().to_string()
                },
                None => panic!("无法生成默认路径")
            }
        }
    };
    Config {
        md_path,
        html_path
    }
}

读取文件转换

fn read_file(path: String) -> String {
    let content = fs::read_to_string(path).expect("文件不存在");
    let parse = pulldown_cmark::Parser::new(&content);
    let mut html_output = String::new();
    pulldown_cmark::html::push_html(&mut html_output, parse);
    html_output
}

写入文件

fn write_file(html_path: String, content: String) {
    let html = format!("<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
  {}
</body>
</html>", content);
    let mut file = fs::File::create(html_path).expect("创建文件失败");
    file.write_all(html.as_bytes()).expect("写入文件失败");
}

结语

以上代码还有很多不足,比如说像报错提示应该使用Result结构返回Err,这里直接使用了painc!。下一节我们来实现自己的markdown解析器。

转载自:https://juejin.cn/post/7399296053214478399
评论
请登录