前言
上一篇文章完成了markdown转JSON的逻辑与 自定义指令的添加介绍
本文将详细讲解一些 从输入指令timec -oj filepath1 filepath2 ....
到正确执行的逻辑
功能开发
批量MD转JSON详细逻辑
将传入的相对路径转绝对路径
- 其中
process.cwd()
标识命令的执行目录
const path = require('path') // 首先获得命令执行目录 const cwd = process.cwd() // 将传入的相对文件路径批量转为绝对路径 filenames = filenames.map(f=>{ return path.join(cwd,f) })
批量获取多个文件的内容:
- 使用
fs.readFileSync
获取单个文件的内容 - 利用
Array.prototype.reduce
合并多个文件的内容,以\n
分割
const fs = require('fs') /** * 获取文件内容 * @param {string} filepath */ function getFileContent(filepath) { return fs.readFileSync(filepath, { encoding: 'utf-8' }) } /** * 获取多个文件的内容 * @param {string[]} files */ function getFilesContent(files) { return files.reduce((pre, now) => { pre += '\n' pre += getFileContent(now) return pre }, '') }
将MD转为JSON并输出到文件:
- 转为JSON的详细逻辑看上一篇文章的介绍
- 创建文件时需判断原文件是否已存在,存在则使用新的名称,避免覆盖内容
// 获取所有文件的内容 const content = getFilesContent(filenames) let outFileName = 'res' // 转为JSON对象,并执行JSON.stringify createFile(path.join(cwd, `${outFileName}.json`), outputJson(content), false) // ------------------------------------------------ function outputJson(content) { return JSON.stringify(getJSON(content)) } /** * 创建一个新文件 * @param {string} path * @param {string} content * @param {boolean} judgeRepeat */ function createFile(path, content, judgeRepeat = true) { if (!fs.existsSync(path)) { fs.writeFileSync(path, content, { encoding: 'utf-8' }) return true } if (judgeRepeat) { console.error(`${path} 已存在`); return false } fs.writeFileSync(getNoRepeatFilePath(path), content, { encoding: 'utf-8' }) return true }
根据已存在的路径,生成一个新的路径逻辑如下
- 往文件名末尾添加一个自增的数字
- 通过
path.parse
方法解析路径 (/user/home/abc.txt)
- dir:目录 (/user/home)
- name:文件名 (abc)
- ext:文件后缀 (.txt)
- 如果数字存在则自增这个数字,直至数字不存在
/** * 获取与原文件不重复的一个文件路经 * @param {string} originPath */ function getNoRepeatFilePath(originPath) { let num = 1 const { dir, name, ext } = path.parse(originPath) if (!fs.existsSync(originPath)) { return originPath } while (fs.existsSync(getFilePath(dir, `${name}-${num}${ext}`))) { num += 1 } return getFilePath(dir, `${name}-${num}${ext}`) }
到此从 MD读取
-> 转换为JSON
-> 写出到文件
流程都拆解阐述完毕
合并MD记录并按时间排序
咱们再给它添加一个--markdown
options用与后续的合并多个markdown逻辑
commander.arguments('<filenames...>') // 多个文件/目录 .option('-m, --markdown', 'Export the result as a markdown file') .action((filenames, cmdObj) => { const { output,markdown } = cmdObj // 导出 if (output) { let outFileName = 'res' // 获取所有文件的内容(同上) const content = getFilesContent(filenames.map(filename => { return getFilePath(cwd, filename) })) if (markdown) { createFile(getFilePath(cwd, `${outFileName}.md`), outPutMarkdown(getJSON(content),time), false) } } })
代码涉及到的其它函前面些文章已经做了详细介绍
下面围绕outPutMarkdown
逻辑展开:
- 先获取所有md文件的内容,再调用
getJSON
方法转为JSON对象 - 调用
sort
方法对title(时间)进行排序 - 将排序后的json对象,调用
getEverydayData
详细转换每一天的数据
function outPutMarkdown(jsonSchema,withTime = false) { // 从小到大排 jsonSchema = jsonSchema.sort((a, b) => { const d1 = new Date(a.title) const d2 = new Date(b.title) return d1 - d2 }) const res = [] res.push(...getEverydayData(jsonSchema, withTime)) return res.join('\n') }
遍历每一天的数据,利用reduce
嵌套配合unshift
方法
从每一个具体事件(以 *
开头)开始遍历,解析事件的内容和消耗时间,然后累加得出任务耗时与每一天的耗时
function getEverydayData(timeDesc, withTime = false) { let res = [] // 按天任务时间汇总 timeDesc.forEach(oneDay => { const _oneRes = [] const { title, tasks } = oneDay const sum = tasks.reduce((pre, task, _i) => { const { title, things } = task const sum = things.reduce((pre, thing) => { // 某件事情况 const { content, time } = thing _oneRes.unshift(`* ${content} -- ${fixedNum(time)}`) return pre + (+thing.time) }, 0) // 某一个任务 _oneRes.unshift(`## ${title} -- ${fixedNum(sum)}`) return pre + sum }, 0) // 一天的标题 _oneRes.unshift(`# ${title} -- ${fixedNum(sum)}`) res.push(..._oneRes, '') }) // 去掉统计的时间 if (!withTime) { res = res.map(v => { return v.replace(/\s--.*/, '') }) } return res }
指令效果
网络异常,图片无法展示
|
其它
下一期根据已有的功能整个周报生成
由于每天空闲时间有限,本文就先到这
如果读者还感觉意犹未尽,敬请期待后续更新,或先关注一下仓库
欢迎评论区提需求,交流探讨
本系列会不断的更新迭代,直至产品初代完成