i5ting_toc_v2
Version:
tocmd.npm:a npm wrapper of i5ting_ztree_toc with automatic image processing
219 lines (175 loc) • 6.26 kB
JavaScript
require('shelljs/global')
var assign = require('object-assign')
var fs = require('fs')
var path = require('path')
var BufferHelper = require('bufferhelper')
var Handlebars = require('handlebars')
var open = require("open")
// 新增:处理Markdown中的图片
function processImages(markdownContent, sourceDir, previewPath) {
var imagesDir = path.join(previewPath, 'toc', 'images')
// 创建images文件夹(如果不存在)
if (!test('-d', imagesDir)) {
mkdir('-p', imagesDir)
console.log('已创建images文件夹:', imagesDir)
}
// 正则表达式匹配Markdown图片语法:
var imageRegex = /!\[([^\]]*)\]\(([^)]+)\)/g
var processedContent = markdownContent
var match
// 查找所有图片
while ((match = imageRegex.exec(markdownContent)) !== null) {
var altText = match[1]
var imagePath = match[2]
// 跳过网络图片
if (imagePath.startsWith('http://') || imagePath.startsWith('https://')) {
continue
}
// 构建完整的图片源路径
var fullImagePath
if (path.isAbsolute(imagePath)) {
fullImagePath = imagePath
} else {
fullImagePath = path.join(sourceDir, imagePath)
}
// 检查图片文件是否存在
if (test('-f', fullImagePath)) {
// 获取图片文件名
var imageFileName = path.basename(imagePath)
// 构建目标路径
var destImagePath = path.join(imagesDir, imageFileName)
// 复制图片到images文件夹
try {
cp(fullImagePath, destImagePath)
console.log('已复制图片:', imageFileName)
// 更新Markdown中的图片路径
var newImagePath = 'toc/images/' + imageFileName
processedContent = processedContent.replace(
'',
''
)
} catch (err) {
console.error('复制图片失败:', fullImagePath, err.message)
}
} else {
console.warn('图片文件不存在:', fullImagePath)
}
}
return processedContent
}
function generator(pwd, source_file_name, dest_file_path, is_open, options) {
var file_name = source_file_name.split('/').pop()
var _file_name = file_name.split('.')[0]
var is_debug = options.debug
function log(str) {
if (is_debug == true)
console.log(str)
}
// 点号表示当前文件所在路径
var str = fs.realpathSync('.')
log(str)
//函数可以返回当前正在执行的项目路径
//:属性返回的是 nodejs 的安装路径
// processor.execPath
var preview_path = pwd + '/preview'
var source_file_path = source_file_name
var dest_file_path = dest_file_path
if (!test('-d', preview_path)) {
mkdir('-p', preview_path)
}
cp_template_dir(__dirname, preview_path)
function cp_template_dir(_cur_dir, _dest_dir) {
var i = _cur_dir
log(i)
cp('-R', _cur_dir + '/vendor/toc', _dest_dir + '/')
}
var template_path = __dirname + '/vendor/template.html'
log('template_path = ' + template_path)
fs.readFile(source_file_path, function (err, data) {
if (err) throw err
log(data)
// var rs = fs.createReadStream(template_path, {encoding: 'utf-8', bufferSize: 11})
var rs = fs.createReadStream(template_path, { bufferSize: 11 })
var bufferHelper = new BufferHelper()
rs.on("data", function (trunk) {
bufferHelper.concat(trunk)
})
rs.on("end", function () {
var source = bufferHelper.toBuffer().toString('utf8')
var template = Handlebars.compile(source)
log(template)
var marked = require('marked')
// marked = require('gulp-markdown-livereload')
// 新增:处理Markdown中的图片
var markdownContent = data.toString()
var sourceDir = path.dirname(source_file_path)
markdownContent = processImages(markdownContent, sourceDir, preview_path)
function detectLanguage(code){
var text = code || ''
if (/^\s*#include\s+<.+?>/m.test(text) || /\bstd::/m.test(text)) return 'cpp'
if (/\bpublic\s+class\b/.test(text) || /\bSystem\.out\.println\b/.test(text)) return 'java'
if (/^\s*#include\s+".+?\.h"/m.test(text) || /\bprintf\s*\(/.test(text)) return 'c'
if (/^\s*def\s+\w+\s*\(/m.test(text) || /:\s*$/m.test(text) && /\bimport\s+\w+/.test(text)) return 'python'
if (/\bfunction\b/.test(text) || /=>/.test(text) || /console\.log\b/.test(text)) return 'javascript'
if (/\b\{[\s\S]*\}\s*$/.test(text) && /"[^"]+"\s*:/.test(text)) return 'json'
if (/^\s*<\/?[a-zA-Z]/m.test(text)) return 'markup'
if (/\bint\s+main\s*\(/.test(text)) return 'cpp'
if (/^\s*#!/.test(text)) return 'bash'
if (/\bSELECT\b|\bFROM\b|\bWHERE\b/i.test(text)) return 'sql'
return ''
}
function escapeHtml(html){
return String(html)
.replace(/&/g,'&')
.replace(/</g,'<')
.replace(/>/g,'>')
.replace(/\"/g,'"')
}
var renderer = new marked.Renderer()
renderer.code = function (code, infostring) {
var lang = (infostring || '').trim()
if (!lang) {
lang = detectLanguage(code)
}
var cls = lang ? ' class="language-' + lang + '"' : ''
return '<pre><code' + cls + '>' + escapeHtml(code) + '\n</code></pre>'
}
var markedOptions = assign({
langPrefix: 'language-',
renderer: renderer
}, options || {})
// 使用处理后的Markdown内容
marked(markdownContent, markedOptions, function (err, data) {
if (err) {
log('err ' + err)
return
}
log(data)
// 生成唯一的版本号,用于破坏缓存
var version = Date.now().toString(36) + Math.random().toString(36).substr(2)
var data1 = {
"title": "i5ting_ztree_toc:" + _file_name,
"parse_markdown": data,
"theme_css": markedOptions.theme_css || 'toc/style/code-theme/prism-tomorrow.css',
"version": version // 新增版本号
}
var final_html_content = Buffer.from(template(data1), 'utf8')
log(dest_file_path)
if (markedOptions.index === true) {
dest_file_path = dest_file_path.replace('README', 'index')
}
log(dest_file_path)
fs.writeFile(dest_file_path, final_html_content, function (err) {
if (err) throw err
log('It\'s saved!')
if (is_open == true) {
open(dest_file_path)
}
})
})
})
})
}
// generator('sample.md')
module.exports = generator