【ES6】Latex总结笔记生成器(网页版)
概述
之前写了Godot版本的ETD2Latex,也就是将Tab缩进格式的层级文本转化成Latex的cases环境嵌套,一直想写个JS版本的,之前基于AI转化代码修改,越改越乱,放弃了。
今天终于沉下心来,从零开始写了一个JS版本。也算把这个坑填了。
用处嘛,就是学习时写各种总结笔记,亲测有效,用来过了一场考试。
界面
实现基础功能,界面都是原生的HTML和JS,所以暂时有点丑。
目前版本:
- 可以使用空格作为缩进,可以是1个或多个空格,只要低一级的缩进数大于高一级的就行
- 实时转化为Latex公式的cases环境嵌套形式(Latex总结笔记)
- 使用KaTex渲染,直接在底部实时生成预览
代码
index.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>JS版ETD2Latex</title><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.9/katex.min.css"><script src="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.9/katex.min.js"></script><script src="ETD2Latex.js"></script><style>h1{text-align: center;margin-bottom: 10px;}.author{text-align: center;margin-bottom: 10px;}textarea{width:calc(100% - 8px);height: 200px;}.colums2{display: grid;gap: 10pt;grid-template-columns: 1fr 1fr;}.col{background-color: #ccc;border:1px solid #444;/* padding: 10pt; */text-align: right;}.col h2{margin: 0pt;padding: 5px;background-color: #444;text-align: center;color:white;}.col .col_body{padding: 10pt;}button{min-width: 100px;min-height: 30px;}/* latex公式预览区域 */#latex_div{min-height: 100px;background-color: #ccc;padding: 10px;}span.info{color:red;margin-right: 5px;}</style>
</head>
<body><h1>Latex总结笔记生成器(网页版)</h1><div class="author">巽星石</div><!-- 分栏 --><div class="colums2"><!-- 左侧列 --><div class="col"><h2>ETD字符串</h2><div class="col_body"><textarea id="etd_txt"></textarea><br><button id="cls_btn">清空</button></div></div><!-- 右侧列 --><div class="col"><h2>Latex公式字符串</h2><div class="col_body"><textarea id="latex_txt"></textarea><br><span class="info" id="info1"></span><button id="copy_btn">复制</button></div></div></div><h2>Latex预览</h2><div id="latex_div"></div></body>
<script>// 解析ETD字符串
let etd_txt = document.getElementById("etd_txt")
let latex_txt = document.getElementById("latex_txt")
let latex_div = document.getElementById("latex_div")
let cls_btn = document.getElementById("cls_btn")
let copy_btn = document.getElementById("copy_btn")
let info_span = document.getElementById("info1")// 清空
cls_btn.onclick = function(){etd_txt.value = ""etd_txt.onkeyup()
}// 实时输入和生成
etd_txt.onkeyup = function(){let tree = ETDTree.with_etd_str(etd_txt.value);latex_txt.value = tree.to_latex();katex.render(latex_txt.value,latex_div); // 渲染
}// 复制
copy_btn.onclick = function(){latex_txt.select();navigator.clipboard.writeText(latex_txt.value);info_span.innerText = "已完成拷贝";
}</script></html>
ETD2Latex.js
// 节点
class ETDNode{children = []constructor(id,deep,text,p_node){this.id = idthis.deep = deepthis.text = textthis.p_node = p_node}// 转化为字符串to_string(is_last = false){let sttr = ""if(is_last){sttr = "\t".repeat(this.deep) + this.text;}else{sttr = "\t".repeat(this.deep) + this.text + "\n";}let idx = 0;if(this.children.length > 0){sttr += "\n"}this.children.forEach(chd => {sttr += chd.to_string(idx == this.children.length - 1);idx += 1;});return sttr;}// 转换为Latexto_latex(is_last = false){let ltx = ""if(this.children.length == 0){if(is_last){ltx = this.text + "\n";}else{ltx = this.text + "\\".repeat(2) + "\n";}}else{ltx = this.text + "\n";ltx += "\\begin{cases}\n"let idx = 0;this.children.forEach(chd => {ltx += chd.to_latex(idx == this.children.length - 1);idx += 1;});ltx += "\\end{cases}" + "\\".repeat(2) + "\n";}return ltx;}
}// 解析后的树
class ETDTree{tree = null;constructor(tree){this.tree = tree;}// 以ETD字符串创建实例static with_etd_str(etd_str){let p_node = null // 父节点let c_node = null // 当前节点let line_idx = 0 // 行号let tree = null // 树的根节点for(let line of etd_str.split("\n")) {let deep = line.length - line.trimStart().length // 当前深度let text = line.trim() // 当前节点文本if(p_node == null){c_node = new ETDNode(line_idx,deep,text,p_node);tree = c_node;p_node = c_node;}else{if(p_node.deep < deep){c_node = new ETDNode(line_idx,deep,text,p_node);p_node.children.push(c_node);p_node = c_node;}else if(p_node.deep == deep){p_node = p_node.p_nodec_node = new ETDNode(line_idx,deep,text,p_node);p_node.children.push(c_node);p_node = c_node;}else{p_node = p_node.p_node.p_nodec_node = new ETDNode(line_idx,deep,text,p_node);p_node.children.push(c_node);p_node = c_node;}}line_idx += 1;}return new ETDTree(tree);}// 转化为字符串to_string(){return this.tree.to_string();}// 转换为Latexto_latex(){return this.tree.to_latex();}
}