开发个 markdown 和 excel 在线表格 格式互相转换的 在线工具
背景
我经常需要编辑markdown表格,有时需要在markdown和excel(或在线表格)之间来回复制。
所以我需要一个支持markdown和excel(或在线表格)互相转换格式的工具。
我常用网上的在线工具,但是有些工具很卡、有些工具有广告、有些工具甚至有泄露数据的安全风险。所以我自己动手开发了一个工具。
而且,我只想用纯 html js css 实现,不依赖任何库,尽可能减少它的体积。
理想效果
整个页面分为上下两块:
- 上半部分为输入区,用户可以输入 markdown 格式的表格,也可以粘贴 excel(在线表格)到输入框中,它可以自动识别是 markdown 格式还是 excel(在线表格)格式。
- 用户光标点击外部(即监听 textarea 的 change 事件)时,触发更新,上半部分自动格式化为 markdown 格式,下半部分出现表格格式(用 html 展示的)。
- 如果用户需要 markdown 格式(通常是excel或在线表格转 markdown),此时可以在上半部分复制走。
- 如果用户需要 excel(在线表格)格式(通常是 markdown 转excel或在线表格),此时可以在下半部分复制走。
开发难点
- 如何辨别是 markdown 还是 excel(在线表格)。
- 需要开发代码理解 markdown 的语法。
- 需要开发代码理解 excel(在线表格)的语法。
- 需要自动生成 markdown 语法。
- 需要自动生成 excel(在线表格)的 html 文本。
开发实现
如何辨别是 markdown 还是 excel(在线表格)
主要是通过包含|
和\t
的行的数量来比较。如果几乎每行都有|
,说明是markdown。如果\t
比较多,说明是 excel 或在线表格。
const isMarkdown = (lines) => {
let verticalBarLineCount = 0;
let blankLineCount = 0;
let tabLineCount = 0;
for (const line of lines) {
const trimLine = line.trim();
if (trimLine.length === 0) {
blankLineCount += 1;
continue;
}
if (trimLine.length > 3 && trimLine[0] === '|' && trimLine.substr(1).includes('|')) {
verticalBarLineCount += 1;
}
if (trimLine.length > 3 && trimLine.includes('\t')) {
tabLineCount += 1;
}
}
const nonBlankLineCount = lines.length - blankLineCount;
if (verticalBarLineCount === 0) return false;
if (verticalBarLineCount >= nonBlankLineCount * 0.8) return true;
return tabLineCount < verticalBarLineCount;
};
理解 markdown 语法
const content = [];
let gapFlag = false;
for (const line of lines) {
let text = line.trim();
if (text[0] === '|') text = text.substr(1);
if (text[text.length - 1] === '|') text = text.substr(0, text.length - 2);
if (!gapFlag && judgeGap(line)) {
gapFlag = true;
continue;
}
const chars = new Set(line);
if (chars.size === 0) continue;
if (chars.size === 1 && chars.has(' ')) continue;
content.push(text.split('|').map(t => t.trim()));
}
理解 excel(在线表格)语法
在 excel(在线表格)复制到 textarea 后,表格的分隔符是\t
,换行则是\n
。
const content = [];
for (const line of lines) {
content.push(line.split('\t').map(t => t.trim()));
}
自动生成 markdown
const getMarkdown = (content) => {
let markdown = '';
let gapFlag = false;
for (const line of content) {
markdown += '| ';
for (const cell of line) {
markdown += cell + ' | ';
}
markdown = markdown.substr(0, markdown.length - 1);
markdown += '\n';
if (!gapFlag) {
gapFlag = true;
markdown += '| ';
for (const cell of line) {
markdown += '--- | ';
}
markdown = markdown.substr(0, markdown.length - 1);
markdown += '\n';
}
}
return markdown;
};
自动生成 excel(在线表格)的 html 文本
const getTable = (content) => {
let table = '<tbody>';
let gapFlag = false;
for (const line of content) {
table += '<tr>';
for (const cell of line) {
table += gapFlag ? '<td>' : '<th>';
table += cell;
table += gapFlag ? '</td>' : '</th>';
}
table += '</tr>\n';
gapFlag = true;
}
table += '</tbody>';
return table;
};
待优化事项
- 不支持识别
\|
,这在 markdown 并非表格分割线。 - markdown 生成的没有很规整,没有通过增加空格把每个单元格弄成一样长度。
写在最后
我是HullQin,公众号线下聚会游戏的作者(欢迎关注公众号,联系我,交个朋友),转发本文前需获得作者HullQin授权。我独立开发了《联机桌游合集》,是个网页,可以很方便的跟朋友联机玩斗地主、五子棋、象棋等游戏,不收费无广告。还独立开发了《合成大西瓜重制版》。还开发了《Dice Crush》参加Game Jam 2022。喜欢可以关注我噢~我有空了会分享做游戏的相关技术,会在这2个专栏里分享:《教你做小游戏》、《极致用户体验》。
转载自:https://juejin.cn/post/7158850778705166372