Rust学习之markdown转换
前言
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