UNPKG

kityminder

Version:
168 lines (138 loc) 4.49 kB
/** * @fileOverview * * Markdown 格式导入导出支持 * * @author: techird * @copyright: Baidu FEX, 2014 */ KityMinder.registerProtocol('markdown', function() { var LINE_ENDING_SPLITER = /\r\n|\r|\n/; var EMPTY_LINE = ''; var NOTE_MARK_START = '<!--Note-->'; var NOTE_MARK_CLOSE = '<!--/Note-->'; function encode(json) { return _build(json, 1).join('\n'); } function _build(node, level) { var lines = []; level = level || 1; var sharps = _generateHeaderSharp(level); lines.push(sharps + ' ' + node.data.text); lines.push(EMPTY_LINE); var note = node.data.note; if (note) { var hasSharp = /^#/.test(note); if (hasSharp) { lines.push(NOTE_MARK_START); note = note.replace(/^#+/gm, function($0) { return sharps + $0; }); } lines.push(note); if (hasSharp) { lines.push(NOTE_MARK_CLOSE); } lines.push(EMPTY_LINE); } if (node.children) node.children.forEach(function(child) { lines = lines.concat(_build(child, level + 1)); }); return lines; } function _generateHeaderSharp(level) { var sharps = ''; while(level--) sharps += '#'; return sharps; } function decode(markdown) { var json, parentMap = {}, lines, line, lineInfo, level, node, parent, noteProgress, codeBlock; // 一级标题转换 `{title}\n===` => `# {title}` markdown = markdown.replace(/^(.+)\n={3,}/, function($0, $1) { return '# ' + $1; }); lines = markdown.split(LINE_ENDING_SPLITER); // 按行分析 for (var i = 0; i < lines.length; i++) { line = lines[i]; lineInfo = _resolveLine(line); // 备注标记处理 if (lineInfo.noteClose) { noteProgress = false; continue; } else if (lineInfo.noteStart) { noteProgress = true; continue; } // 代码块处理 codeBlock = lineInfo.codeBlock ? !codeBlock : codeBlock; // 备注条件:备注标签中,非标题定义,或标题越位 if (noteProgress || codeBlock || !lineInfo.level || lineInfo.level > level + 1) { if (node) _pushNote(node, line); continue; } // 标题处理 level = lineInfo.level; node = _initNode(lineInfo.content, parentMap[level - 1]); parentMap[level] = node; } _cleanUp(parentMap[1]); return parentMap[1]; } function _initNode(text, parent) { var node = { data: { text: text, note: '' } }; if (parent) { if (parent.children) parent.children.push(node); else parent.children = [node]; } return node; } function _pushNote(node, line) { node.data.note += line + '\n'; } function _isEmpty(line) { return !/\S/.test(line); } function _resolveLine(line) { var match = /^(#+)?\s*(.*)$/.exec(line); return { level: match[1] && match[1].length || null, content: match[2], noteStart: line == NOTE_MARK_START, noteClose: line == NOTE_MARK_CLOSE, codeBlock: /^\s*```/.test(line) }; } function _cleanUp(node) { if (!/\S/.test(node.data.note)) { node.data.note = null; delete node.data.note; } else { var notes = node.data.note.split('\n'); while(notes.length && !/\S/.test(notes[0])) notes.shift(); while(notes.length && !/\S/.test(notes[notes.length - 1])) notes.pop(); node.data.note = notes.join('\n'); } if (node.children) node.children.forEach(_cleanUp); } return { fileDescription: 'Markdown/GFM 格式', fileExtension: '.md', mineType: 'text/markdown', dataType: 'text', encode: function(json) { return encode(json); }, decode: function(markdown) { return decode(markdown); }, recognizePriority: -1 }; });