放假了,马上要封楼,先大概记录一下思路与实现过程,细节年后再完善。(其实我是怕自己年后给忘了。。。。)

依赖docsify  和 docsify-pdf-converter@2.1.0-beta.0

可参考《docsify(一)》

要求原docsify工程中index.html里的配置参数,单独写成独立的docsify.config.js文件。

其余无需改动

项目部署完成,执行 npm run convert,会生成在项目目录中生成pdf文档和词库(dictionaries.json)

再正常启动docsify工程 执行docsify serve

服务启动后,平台端可以通过访问http://localhost:3000/dictionaries.json来获取词库,再返回给ics项目前端,从而完成项目web页面中对文档的检索功能。

前端(或后台)拿到词库后,按照docsify中的dosearch函数逻辑即可完成检索

具体实现方式,新增以下代码:

相关文件:

markdown-combine.js  源文件  改动了部分代码(中文注释处);

slugify.js  新增文件  此文件中的代码取自docsify源码slugify.函数部分;

marked.js 新增文件 此文件中的代码取自docsify源码marked函数部分;

createLibrary.js 新增文件  此文件中代码都是新开发的,重要逻辑已添加注释;

1. node_modules\docsify-pdf-converter\src\markdown-combine.js

const fs = require("fs");
const util = require("util");
const path = require("path");
const logger = require("./logger.js");
const processImagesPaths = require("./process-images-paths.js");
const processInnerLinks = require("./process-inner-links.js");
const createLibrary = require("./createLibrary");const [readFile, writeFile, exists] = [fs.readFile, fs.writeFile, fs.exists].map(fn =>util.promisify(fn),
);const combineMarkdowns = ({ contents, pathToStatic, mainMdFilename, mkdir }) => async links => {let contentsPaths = Array.isArray(contents) ? contents : [contents];//是否开启目录mkdir && links.unshift(contentsPaths[0].replace(/\//g, '\\'))//获取根路径  40行传给process-inner-links模块let dir = path.dirname(path.resolve(contentsPaths[0]))try {const files = await Promise.all(await links.map(async filename => {const fileExist = await exists(filename);if (fileExist) {const content = await readFile(filename, {encoding: "utf8",});return {content,name: filename,};}throw new Error(`file ${filename} is not exist, but listed in ${contents}`);}),);const resultFilePath = path.resolve(pathToStatic, mainMdFilename);// 所有内容前面拼接的字符串let baseContentStart = ''//创建字典备用的两个参数let tempLinks = [...links]let tempFiles = [...files]//如果开启目录if (mkdir) {//创建字典时需要把目录页忽略tempLinks.shift()tempFiles.shift()//目录页后 另起新的页面files[0].content = files[0].content + "<div style='page-break-after:always;'></div>"//在“目录”前拼接目录标题baseContentStart = '# **目录** \r\n'}createLibrary(tempLinks, tempFiles, dir)try {const content = files.map((...rest) => processInnerLinks(dir, ...rest)) //设置内部链接.map(processImagesPaths({ pathToStatic })).join("\n\n\n\n\n\n");await writeFile(resultFilePath, baseContentStart + content);} catch (e) {logger.err("markdown combining error", e);throw e;}return resultFilePath;} catch (err) {logger.err("combineMarkdowns", err);throw err;}
};module.exports = config => ({combineMarkdowns: combineMarkdowns(config),
});

2. node_modules\docsify-pdf-converter\src\slugify.js

/*** 此模块取自docsify 源码部分 slugify相关模块*/
var hasOwn = Object.prototype.hasOwnProperty;
var re = /[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,./:;<=>?@[\]^`{|}~]/g;
var cache$1 = {};function lower(string) {return string.toLowerCase()
}function slugify(str) {if (typeof str !== 'string') {return ''}var slug = str.trim().replace(/[A-Z]+/g, lower).replace(/<[^>\d]+>/g, '').replace(re, '').replace(/\s/g, '-').replace(/-+/g, '-').replace(/^(\d)/, '_$1');var count = cache$1[slug];count = hasOwn.call(cache$1, slug) ? count + 1 : 0;cache$1[slug] = count;if (count) {slug = slug + '-' + count;}return slug
}slugify.clear = function () {cache$1 = {};
};module.exports = slugify

3. node_modules\docsify-pdf-converter\src\marked.js

/*** 此模块取自docsify 源码部分 marked相关模块*/
var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};function createCommonjsModule(fn, module) {return module = { exports: {} }, fn(module, module.exports), module.exports;
}function edit(regex, opt) {regex = regex.source || regex;opt = opt || '';return {replace: function (name, val) {val = val.source || val;val = val.replace(/(^|[^\[])\^/g, '$1');regex = regex.replace(name, val);return this;},getRegex: function () {return new RegExp(regex, opt);}};
}function merge(obj) {var arguments$1 = arguments;var i = 1,target,key;for (; i < arguments.length; i++) {target = arguments$1[i];for (key in target) {if (Object.prototype.hasOwnProperty.call(target, key)) {obj[key] = target[key];}}}return obj;
}module.exports = createCommonjsModule(function (module, exports) {/*** marked - a markdown parser* Copyright (c) 2011-2018, Christopher Jeffrey. (MIT Licensed)* https://github.com/markedjs/marked*/(function (root) {var block = {newline: /^\n+/,code: /^( {4}[^\n]+\n*)+/,fences: noop,hr: /^ {0,3}((?:- *){3,}|(?:_ *){3,}|(?:\* *){3,})(?:\n+|$)/,heading: /^ *(#{1,6}) *([^\n]+?) *(?:#+ *)?(?:\n+|$)/,nptable: noop,blockquote: /^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/,list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,html: '^ {0,3}(?:' // optional indentation+ '<(script|pre|style)[\\s>][\\s\\S]*?(?:</\\1>[^\\n]*\\n+|$)' // (1)+ '|comment[^\\n]*(\\n+|$)' // (2)+ '|<\\?[\\s\\S]*?\\?>\\n*' // (3)+ '|<![A-Z][\\s\\S]*?>\\n*' // (4)+ '|<!\\[CDATA\\[[\\s\\S]*?\\]\\]>\\n*' // (5)+ '|</?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:\\n{2,}|$)' // (6)+ '|<(?!script|pre|style)([a-z][\\w-]*)(?:attribute)*? */?>(?=\\h*\\n)[\\s\\S]*?(?:\\n{2,}|$)' // (7) open tag+ '|</(?!script|pre|style)[a-z][\\w-]*\\s*>(?=\\h*\\n)[\\s\\S]*?(?:\\n{2,}|$)' // (7) closing tag+ ')',def: /^ {0,3}\[(label)\]: *\n? *<?([^\s>]+)>?(?:(?: +\n? *| *\n *)(title))? *(?:\n+|$)/,table: noop,lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,paragraph: /^([^\n]+(?:\n(?!hr|heading|lheading| {0,3}>|<\/?(?:tag)(?: +|\n|\/?>)|<(?:script|pre|style|!--))[^\n]+)*)/,text: /^[^\n]+/};block._label = /(?!\s*\])(?:\\[\[\]]|[^\[\]])+/;block._title = /(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/;block.def = edit(block.def).replace('label', block._label).replace('title', block._title).getRegex();block.bullet = /(?:[*+-]|\d+\.)/;block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;block.item = edit(block.item, 'gm').replace(/bull/g, block.bullet).getRegex();block.list = edit(block.list).replace(/bull/g, block.bullet).replace('hr', '\\n+(?=\\1?(?:(?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$))').replace('def', '\\n+(?=' + block.def.source + ')').getRegex();block._tag = 'address|article|aside|base|basefont|blockquote|body|caption'+ '|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption'+ '|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe'+ '|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option'+ '|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr'+ '|track|ul';block._comment = /<!--(?!-?>)[\s\S]*?-->/;block.html = edit(block.html, 'i').replace('comment', block._comment).replace('tag', block._tag).replace('attribute', / +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex();block.paragraph = edit(block.paragraph).replace('hr', block.hr).replace('heading', block.heading).replace('lheading', block.lheading).replace('tag', block._tag) // pars can be interrupted by type (6) html blocks.getRegex();block.blockquote = edit(block.blockquote).replace('paragraph', block.paragraph).getRegex();/*** Normal Block Grammar*/block.normal = merge({}, block);/*** GFM Block Grammar*/block.gfm = merge({}, block.normal, {fences: /^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\n? *\1 *(?:\n+|$)/,paragraph: /^/,heading: /^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/});block.gfm.paragraph = edit(block.paragraph).replace('(?!', '(?!'+ block.gfm.fences.source.replace('\\1', '\\2') + '|'+ block.list.source.replace('\\1', '\\3') + '|').getRegex();/*** GFM + Tables Block Grammar*/block.tables = merge({}, block.gfm, {nptable: /^ *([^|\n ].*\|.*)\n *([-:]+ *\|[-| :]*)(?:\n((?:.*[^>\n ].*(?:\n|$))*)\n*|$)/,table: /^ *\|(.+)\n *\|?( *[-:]+[-| :]*)(?:\n((?: *[^>\n ].*(?:\n|$))*)\n*|$)/});/*** Pedantic grammar*/block.pedantic = merge({}, block.normal, {html: edit('^ *(?:comment *(?:\\n|\\s*$)'+ '|<(tag)[\\s\\S]+?</\\1> *(?:\\n{2,}|\\s*$)' // closed tag+ '|<tag(?:"[^"]*"|\'[^\']*\'|\\s[^\'"/>\\s]*)*?/?> *(?:\\n{2,}|\\s*$))').replace('comment', block._comment).replace(/tag/g, '(?!(?:'+ 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub'+ '|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)'+ '\\b)\\w+(?!:|[^\\w\\s@]*@)\\b').getRegex(),def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/});/*** Block Lexer*/function Lexer(options) {this.tokens = [];this.tokens.links = Object.create(null);this.options = options || marked.defaults;this.rules = block.normal;if (this.options.pedantic) {this.rules = block.pedantic;} else if (this.options.gfm) {if (this.options.tables) {this.rules = block.tables;} else {this.rules = block.gfm;}}}/*** Expose Block Rules*/Lexer.rules = block;/*** Static Lex Method*/Lexer.lex = function (src, options) {var lexer = new Lexer(options);return lexer.lex(src);};/*** Preprocessing*/Lexer.prototype.lex = function (src) {src = src.replace(/\r\n|\r/g, '\n').replace(/\t/g, '    ').replace(/\u00a0/g, ' ').replace(/\u2424/g, '\n');return this.token(src, true);};/*** Lexing*/Lexer.prototype.token = function (src, top) {var this$1 = this;src = src.replace(/^ +$/gm, '');var next,loose,cap,bull,b,item,listStart,listItems,t,space,i,tag,l,isordered,istask,ischecked;while (src) {// newlineif (cap = this$1.rules.newline.exec(src)) {src = src.substring(cap[0].length);if (cap[0].length > 1) {this$1.tokens.push({type: 'space'});}}// codeif (cap = this$1.rules.code.exec(src)) {src = src.substring(cap[0].length);cap = cap[0].replace(/^ {4}/gm, '');this$1.tokens.push({type: 'code',text: !this$1.options.pedantic? rtrim(cap, '\n'): cap});continue;}// fences (gfm)if (cap = this$1.rules.fences.exec(src)) {src = src.substring(cap[0].length);this$1.tokens.push({type: 'code',lang: cap[2],text: cap[3] || ''});continue;}// headingif (cap = this$1.rules.heading.exec(src)) {src = src.substring(cap[0].length);this$1.tokens.push({type: 'heading',depth: cap[1].length,text: cap[2]});continue;}// table no leading pipe (gfm)if (top && (cap = this$1.rules.nptable.exec(src))) {item = {type: 'table',header: splitCells(cap[1].replace(/^ *| *\| *$/g, '')),align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),cells: cap[3] ? cap[3].replace(/\n$/, '').split('\n') : []};if (item.header.length === item.align.length) {src = src.substring(cap[0].length);for (i = 0; i < item.align.length; i++) {if (/^ *-+: *$/.test(item.align[i])) {item.align[i] = 'right';} else if (/^ *:-+: *$/.test(item.align[i])) {item.align[i] = 'center';} else if (/^ *:-+ *$/.test(item.align[i])) {item.align[i] = 'left';} else {item.align[i] = null;}}for (i = 0; i < item.cells.length; i++) {item.cells[i] = splitCells(item.cells[i], item.header.length);}this$1.tokens.push(item);continue;}}// hrif (cap = this$1.rules.hr.exec(src)) {src = src.substring(cap[0].length);this$1.tokens.push({type: 'hr'});continue;}// blockquoteif (cap = this$1.rules.blockquote.exec(src)) {src = src.substring(cap[0].length);this$1.tokens.push({type: 'blockquote_start'});cap = cap[0].replace(/^ *> ?/gm, '');// Pass `top` to keep the current// "toplevel" state. This is exactly// how markdown.pl works.this$1.token(cap, top);this$1.tokens.push({type: 'blockquote_end'});continue;}// listif (cap = this$1.rules.list.exec(src)) {src = src.substring(cap[0].length);bull = cap[2];isordered = bull.length > 1;listStart = {type: 'list_start',ordered: isordered,start: isordered ? +bull : '',loose: false};this$1.tokens.push(listStart);// Get each top-level item.cap = cap[0].match(this$1.rules.item);listItems = [];next = false;l = cap.length;i = 0;for (; i < l; i++) {item = cap[i];// Remove the list item's bullet// so it is seen as the next token.space = item.length;item = item.replace(/^ *([*+-]|\d+\.) +/, '');// Outdent whatever the// list item contains. Hacky.if (~item.indexOf('\n ')) {space -= item.length;item = !this$1.options.pedantic? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), ''): item.replace(/^ {1,4}/gm, '');}// Determine whether the next list item belongs here.// Backpedal if it does not belong in this list.if (this$1.options.smartLists && i !== l - 1) {b = block.bullet.exec(cap[i + 1])[0];if (bull !== b && !(bull.length > 1 && b.length > 1)) {src = cap.slice(i + 1).join('\n') + src;i = l - 1;}}// Determine whether item is loose or not.// Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/// for discount behavior.loose = next || /\n\n(?!\s*$)/.test(item);if (i !== l - 1) {next = item.charAt(item.length - 1) === '\n';if (!loose) { loose = next; }}if (loose) {listStart.loose = true;}// Check for task list itemsistask = /^\[[ xX]\] /.test(item);ischecked = undefined;if (istask) {ischecked = item[1] !== ' ';item = item.replace(/^\[[ xX]\] +/, '');}t = {type: 'list_item_start',task: istask,checked: ischecked,loose: loose};listItems.push(t);this$1.tokens.push(t);// Recurse.this$1.token(item, false);this$1.tokens.push({type: 'list_item_end'});}if (listStart.loose) {l = listItems.length;i = 0;for (; i < l; i++) {listItems[i].loose = true;}}this$1.tokens.push({type: 'list_end'});continue;}// htmlif (cap = this$1.rules.html.exec(src)) {src = src.substring(cap[0].length);this$1.tokens.push({type: this$1.options.sanitize? 'paragraph': 'html',pre: !this$1.options.sanitizer&& (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'),text: cap[0]});continue;}// defif (top && (cap = this$1.rules.def.exec(src))) {src = src.substring(cap[0].length);if (cap[3]) { cap[3] = cap[3].substring(1, cap[3].length - 1); }tag = cap[1].toLowerCase().replace(/\s+/g, ' ');if (!this$1.tokens.links[tag]) {this$1.tokens.links[tag] = {href: cap[2],title: cap[3]};}continue;}// table (gfm)if (top && (cap = this$1.rules.table.exec(src))) {item = {type: 'table',header: splitCells(cap[1].replace(/^ *| *\| *$/g, '')),align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),cells: cap[3] ? cap[3].replace(/(?: *\| *)?\n$/, '').split('\n') : []};if (item.header.length === item.align.length) {src = src.substring(cap[0].length);for (i = 0; i < item.align.length; i++) {if (/^ *-+: *$/.test(item.align[i])) {item.align[i] = 'right';} else if (/^ *:-+: *$/.test(item.align[i])) {item.align[i] = 'center';} else if (/^ *:-+ *$/.test(item.align[i])) {item.align[i] = 'left';} else {item.align[i] = null;}}for (i = 0; i < item.cells.length; i++) {item.cells[i] = splitCells(item.cells[i].replace(/^ *\| *| *\| *$/g, ''),item.header.length);}this$1.tokens.push(item);continue;}}// lheadingif (cap = this$1.rules.lheading.exec(src)) {src = src.substring(cap[0].length);this$1.tokens.push({type: 'heading',depth: cap[2] === '=' ? 1 : 2,text: cap[1]});continue;}// top-level paragraphif (top && (cap = this$1.rules.paragraph.exec(src))) {src = src.substring(cap[0].length);this$1.tokens.push({type: 'paragraph',text: cap[1].charAt(cap[1].length - 1) === '\n'? cap[1].slice(0, -1): cap[1]});continue;}// textif (cap = this$1.rules.text.exec(src)) {// Top-level should never reach here.src = src.substring(cap[0].length);this$1.tokens.push({type: 'text',text: cap[0]});continue;}if (src) {throw new Error('Infinite loop on byte: ' + src.charCodeAt(0));}}return this.tokens;};/*** Inline-Level Grammar*/var inline = {escape: /^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,autolink: /^<(scheme:[^\s\x00-\x1f<>]*|email)>/,url: noop,tag: '^comment'+ '|^</[a-zA-Z][\\w:-]*\\s*>' // self-closing tag+ '|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>' // open tag+ '|^<\\?[\\s\\S]*?\\?>' // processing instruction, e.g. <?php ?>+ '|^<![a-zA-Z]+\\s[\\s\\S]*?>' // declaration, e.g. <!DOCTYPE html>+ '|^<!\\[CDATA\\[[\\s\\S]*?\\]\\]>', // CDATA sectionlink: /^!?\[(label)\]\(href(?:\s+(title))?\s*\)/,reflink: /^!?\[(label)\]\[(?!\s*\])((?:\\[\[\]]?|[^\[\]\\])+)\]/,nolink: /^!?\[(?!\s*\])((?:\[[^\[\]]*\]|\\[\[\]]|[^\[\]])*)\](?:\[\])?/,strong: /^__([^\s])__(?!_)|^\*\*([^\s])\*\*(?!\*)|^__([^\s][\s\S]*?[^\s])__(?!_)|^\*\*([^\s][\s\S]*?[^\s])\*\*(?!\*)/,em: /^_([^\s_])_(?!_)|^\*([^\s*"<\[])\*(?!\*)|^_([^\s][\s\S]*?[^\s_])_(?!_)|^_([^\s_][\s\S]*?[^\s])_(?!_)|^\*([^\s"<\[][\s\S]*?[^\s*])\*(?!\*)|^\*([^\s*"<\[][\s\S]*?[^\s])\*(?!\*)/,code: /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,br: /^( {2,}|\\)\n(?!\s*$)/,del: noop,text: /^(`+|[^`])[\s\S]*?(?=[\\<!\[`*]|\b_| {2,}\n|$)/};inline._escapes = /\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/g;inline._scheme = /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/;inline._email = /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/;inline.autolink = edit(inline.autolink).replace('scheme', inline._scheme).replace('email', inline._email).getRegex();inline._attribute = /\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/;inline.tag = edit(inline.tag).replace('comment', block._comment).replace('attribute', inline._attribute).getRegex();inline._label = /(?:\[[^\[\]]*\]|\\[\[\]]?|`[^`]*`|[^\[\]\\])*?/;inline._href = /\s*(<(?:\\[<>]?|[^\s<>\\])*>|(?:\\[()]?|\([^\s\x00-\x1f\\]*\)|[^\s\x00-\x1f()\\])*?)/;inline._title = /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/;inline.link = edit(inline.link).replace('label', inline._label).replace('href', inline._href).replace('title', inline._title).getRegex();inline.reflink = edit(inline.reflink).replace('label', inline._label).getRegex();/*** Normal Inline Grammar*/inline.normal = merge({}, inline);/*** Pedantic Inline Grammar*/inline.pedantic = merge({}, inline.normal, {strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/,link: edit(/^!?\[(label)\]\((.*?)\)/).replace('label', inline._label).getRegex(),reflink: edit(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace('label', inline._label).getRegex()});/*** GFM Inline Grammar*/inline.gfm = merge({}, inline.normal, {escape: edit(inline.escape).replace('])', '~|])').getRegex(),_extended_email: /[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/,url: /^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/,_backpedal: /(?:[^?!.,:;*_~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_~)]+(?!$))+/,del: /^~+(?=\S)([\s\S]*?\S)~+/,text: edit(inline.text).replace(']|', '~]|').replace('|$', '|https?://|ftp://|www\\.|[a-zA-Z0-9.!#$%&\'*+/=?^_`{\\|}~-]+@|$').getRegex()});inline.gfm.url = edit(inline.gfm.url).replace('email', inline.gfm._extended_email).getRegex();/*** GFM + Line Breaks Inline Grammar*/inline.breaks = merge({}, inline.gfm, {br: edit(inline.br).replace('{2,}', '*').getRegex(),text: edit(inline.gfm.text).replace('{2,}', '*').getRegex()});/*** Inline Lexer & Compiler*/function InlineLexer(links, options) {this.options = options || marked.defaults;this.links = links;this.rules = inline.normal;this.renderer = this.options.renderer || new Renderer();this.renderer.options = this.options;if (!this.links) {throw new Error('Tokens array requires a `links` property.');}if (this.options.pedantic) {this.rules = inline.pedantic;} else if (this.options.gfm) {if (this.options.breaks) {this.rules = inline.breaks;} else {this.rules = inline.gfm;}}}/*** Expose Inline Rules*/InlineLexer.rules = inline;/*** Static Lexing/Compiling Method*/InlineLexer.output = function (src, links, options) {var inline = new InlineLexer(links, options);return inline.output(src);};/*** Lexing/Compiling*/InlineLexer.prototype.output = function (src) {var this$1 = this;var out = '',link,text,href,title,cap,prevCapZero;while (src) {// escapeif (cap = this$1.rules.escape.exec(src)) {src = src.substring(cap[0].length);out += cap[1];continue;}// autolinkif (cap = this$1.rules.autolink.exec(src)) {src = src.substring(cap[0].length);if (cap[2] === '@') {text = escape(this$1.mangle(cap[1]));href = 'mailto:' + text;} else {text = escape(cap[1]);href = text;}out += this$1.renderer.link(href, null, text);continue;}// url (gfm)if (!this$1.inLink && (cap = this$1.rules.url.exec(src))) {if (cap[2] === '@') {text = escape(cap[0]);href = 'mailto:' + text;} else {// do extended autolink path validationdo {prevCapZero = cap[0];cap[0] = this$1.rules._backpedal.exec(cap[0])[0];} while (prevCapZero !== cap[0]);text = escape(cap[0]);if (cap[1] === 'www.') {href = 'http://' + text;} else {href = text;}}src = src.substring(cap[0].length);out += this$1.renderer.link(href, null, text);continue;}// tagif (cap = this$1.rules.tag.exec(src)) {if (!this$1.inLink && /^<a /i.test(cap[0])) {this$1.inLink = true;} else if (this$1.inLink && /^<\/a>/i.test(cap[0])) {this$1.inLink = false;}if (!this$1.inRawBlock && /^<(pre|code|kbd|script)(\s|>)/i.test(cap[0])) {this$1.inRawBlock = true;} else if (this$1.inRawBlock && /^<\/(pre|code|kbd|script)(\s|>)/i.test(cap[0])) {this$1.inRawBlock = false;}src = src.substring(cap[0].length);out += this$1.options.sanitize? this$1.options.sanitizer? this$1.options.sanitizer(cap[0]): escape(cap[0]): cap[0];continue;}// linkif (cap = this$1.rules.link.exec(src)) {src = src.substring(cap[0].length);this$1.inLink = true;href = cap[2];if (this$1.options.pedantic) {link = /^([^'"]*[^\s])\s+(['"])(.*)\2/.exec(href);if (link) {href = link[1];title = link[3];} else {title = '';}} else {title = cap[3] ? cap[3].slice(1, -1) : '';}href = href.trim().replace(/^<([\s\S]*)>$/, '$1');out += this$1.outputLink(cap, {href: InlineLexer.escapes(href),title: InlineLexer.escapes(title)});this$1.inLink = false;continue;}// reflink, nolinkif ((cap = this$1.rules.reflink.exec(src))|| (cap = this$1.rules.nolink.exec(src))) {src = src.substring(cap[0].length);link = (cap[2] || cap[1]).replace(/\s+/g, ' ');link = this$1.links[link.toLowerCase()];if (!link || !link.href) {out += cap[0].charAt(0);src = cap[0].substring(1) + src;continue;}this$1.inLink = true;out += this$1.outputLink(cap, link);this$1.inLink = false;continue;}// strongif (cap = this$1.rules.strong.exec(src)) {src = src.substring(cap[0].length);out += this$1.renderer.strong(this$1.output(cap[4] || cap[3] || cap[2] || cap[1]));continue;}// emif (cap = this$1.rules.em.exec(src)) {src = src.substring(cap[0].length);out += this$1.renderer.em(this$1.output(cap[6] || cap[5] || cap[4] || cap[3] || cap[2] || cap[1]));continue;}// codeif (cap = this$1.rules.code.exec(src)) {src = src.substring(cap[0].length);out += this$1.renderer.codespan(escape(cap[2].trim(), true));continue;}// brif (cap = this$1.rules.br.exec(src)) {src = src.substring(cap[0].length);out += this$1.renderer.br();continue;}// del (gfm)if (cap = this$1.rules.del.exec(src)) {src = src.substring(cap[0].length);out += this$1.renderer.del(this$1.output(cap[1]));continue;}// textif (cap = this$1.rules.text.exec(src)) {src = src.substring(cap[0].length);if (this$1.inRawBlock) {out += this$1.renderer.text(cap[0]);} else {out += this$1.renderer.text(escape(this$1.smartypants(cap[0])));}continue;}if (src) {throw new Error('Infinite loop on byte: ' + src.charCodeAt(0));}}return out;};InlineLexer.escapes = function (text) {return text ? text.replace(InlineLexer.rules._escapes, '$1') : text;};/*** Compile Link*/InlineLexer.prototype.outputLink = function (cap, link) {var href = link.href,title = link.title ? escape(link.title) : null;return cap[0].charAt(0) !== '!'? this.renderer.link(href, title, this.output(cap[1])): this.renderer.image(href, title, escape(cap[1]));};/*** Smartypants Transformations*/InlineLexer.prototype.smartypants = function (text) {if (!this.options.smartypants) { return text; }return text// em-dashes.replace(/---/g, '\u2014')// en-dashes.replace(/--/g, '\u2013')// opening singles.replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018')// closing singles & apostrophes.replace(/'/g, '\u2019')// opening doubles.replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c')// closing doubles.replace(/"/g, '\u201d')// ellipses.replace(/\.{3}/g, '\u2026');};/*** Mangle Links*/InlineLexer.prototype.mangle = function (text) {if (!this.options.mangle) { return text; }var out = '',l = text.length,i = 0,ch;for (; i < l; i++) {ch = text.charCodeAt(i);if (Math.random() > 0.5) {ch = 'x' + ch.toString(16);}out += '&#' + ch + ';';}return out;};/*** Renderer*/function Renderer(options) {this.options = options || marked.defaults;}Renderer.prototype.code = function (code, lang, escaped) {if (this.options.highlight) {var out = this.options.highlight(code, lang);if (out != null && out !== code) {escaped = true;code = out;}}if (!lang) {return '<pre><code>'+ (escaped ? code : escape(code, true))+ '</code></pre>';}return '<pre><code class="'+ this.options.langPrefix+ escape(lang, true)+ '">'+ (escaped ? code : escape(code, true))+ '</code></pre>\n';};Renderer.prototype.blockquote = function (quote) {return '<blockquote>\n' + quote + '</blockquote>\n';};Renderer.prototype.html = function (html) {return html;};Renderer.prototype.heading = function (text, level, raw) {if (this.options.headerIds) {return '<h'+ level+ ' id="'+ this.options.headerPrefix+ raw.toLowerCase().replace(/[^\w]+/g, '-')+ '">'+ text+ '</h'+ level+ '>\n';}// ignore IDsreturn '<h' + level + '>' + text + '</h' + level + '>\n';};Renderer.prototype.hr = function () {return this.options.xhtml ? '<hr/>\n' : '<hr>\n';};Renderer.prototype.list = function (body, ordered, start) {var type = ordered ? 'ol' : 'ul',startatt = (ordered && start !== 1) ? (' start="' + start + '"') : '';return '<' + type + startatt + '>\n' + body + '</' + type + '>\n';};Renderer.prototype.listitem = function (text) {return '<li>' + text + '</li>\n';};Renderer.prototype.checkbox = function (checked) {return '<input '+ (checked ? 'checked="" ' : '')+ 'disabled="" type="checkbox"'+ (this.options.xhtml ? ' /' : '')+ '> ';};Renderer.prototype.paragraph = function (text) {return '<p>' + text + '</p>\n';};Renderer.prototype.table = function (header, body) {if (body) { body = '<tbody>' + body + '</tbody>'; }return '<table>\n'+ '<thead>\n'+ header+ '</thead>\n'+ body+ '</table>\n';};Renderer.prototype.tablerow = function (content) {return '<tr>\n' + content + '</tr>\n';};Renderer.prototype.tablecell = function (content, flags) {var type = flags.header ? 'th' : 'td';var tag = flags.align? '<' + type + ' align="' + flags.align + '">': '<' + type + '>';return tag + content + '</' + type + '>\n';};// span level rendererRenderer.prototype.strong = function (text) {return '<strong>' + text + '</strong>';};Renderer.prototype.em = function (text) {return '<em>' + text + '</em>';};Renderer.prototype.codespan = function (text) {return '<code>' + text + '</code>';};Renderer.prototype.br = function () {return this.options.xhtml ? '<br/>' : '<br>';};Renderer.prototype.del = function (text) {return '<del>' + text + '</del>';};Renderer.prototype.link = function (href, title, text) {if (this.options.sanitize) {try {var prot = decodeURIComponent(unescape(href)).replace(/[^\w:]/g, '').toLowerCase();} catch (e) {return text;}if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0 || prot.indexOf('data:') === 0) {return text;}}if (this.options.baseUrl && !originIndependentUrl.test(href)) {href = resolveUrl(this.options.baseUrl, href);}try {href = encodeURI(href).replace(/%25/g, '%');} catch (e) {return text;}var out = '<a href="' + escape(href) + '"';if (title) {out += ' title="' + title + '"';}out += '>' + text + '</a>';return out;};Renderer.prototype.image = function (href, title, text) {if (this.options.baseUrl && !originIndependentUrl.test(href)) {href = resolveUrl(this.options.baseUrl, href);}var out = '<img src="' + href + '" alt="' + text + '"';if (title) {out += ' title="' + title + '"';}out += this.options.xhtml ? '/>' : '>';return out;};Renderer.prototype.text = function (text) {return text;};/*** TextRenderer* returns only the textual part of the token*/function TextRenderer() { }// no need for block level renderersTextRenderer.prototype.strong =TextRenderer.prototype.em =TextRenderer.prototype.codespan =TextRenderer.prototype.del =TextRenderer.prototype.text = function (text) {return text;};TextRenderer.prototype.link =TextRenderer.prototype.image = function (href, title, text) {return '' + text;};TextRenderer.prototype.br = function () {return '';};/*** Parsing & Compiling*/function Parser(options) {this.tokens = [];this.token = null;this.options = options || marked.defaults;this.options.renderer = this.options.renderer || new Renderer();this.renderer = this.options.renderer;this.renderer.options = this.options;}/*** Static Parse Method*/Parser.parse = function (src, options) {var parser = new Parser(options);return parser.parse(src);};/*** Parse Loop*/Parser.prototype.parse = function (src) {var this$1 = this;this.inline = new InlineLexer(src.links, this.options);// use an InlineLexer with a TextRenderer to extract pure textthis.inlineText = new InlineLexer(src.links,merge({}, this.options, { renderer: new TextRenderer() }));this.tokens = src.reverse();var out = '';while (this.next()) {out += this$1.tok();}return out;};/*** Next Token*/Parser.prototype.next = function () {return this.token = this.tokens.pop();};/*** Preview Next Token*/Parser.prototype.peek = function () {return this.tokens[this.tokens.length - 1] || 0;};/*** Parse Text Tokens*/Parser.prototype.parseText = function () {var this$1 = this;var body = this.token.text;while (this.peek().type === 'text') {body += '\n' + this$1.next().text;}return this.inline.output(body);};/*** Parse Current Token*/Parser.prototype.tok = function () {var this$1 = this;switch (this.token.type) {case 'space': {return '';}case 'hr': {return this.renderer.hr();}case 'heading': {return this.renderer.heading(this.inline.output(this.token.text),this.token.depth,unescape(this.inlineText.output(this.token.text)));}case 'code': {return this.renderer.code(this.token.text,this.token.lang,this.token.escaped);}case 'table': {var header = '',body = '',i,row,cell,j;// headercell = '';for (i = 0; i < this.token.header.length; i++) {cell += this$1.renderer.tablecell(this$1.inline.output(this$1.token.header[i]),{ header: true, align: this$1.token.align[i] });}header += this.renderer.tablerow(cell);for (i = 0; i < this.token.cells.length; i++) {row = this$1.token.cells[i];cell = '';for (j = 0; j < row.length; j++) {cell += this$1.renderer.tablecell(this$1.inline.output(row[j]),{ header: false, align: this$1.token.align[j] });}body += this$1.renderer.tablerow(cell);}return this.renderer.table(header, body);}case 'blockquote_start': {body = '';while (this.next().type !== 'blockquote_end') {body += this$1.tok();}return this.renderer.blockquote(body);}case 'list_start': {body = '';var ordered = this.token.ordered,start = this.token.start;while (this.next().type !== 'list_end') {body += this$1.tok();}return this.renderer.list(body, ordered, start);}case 'list_item_start': {body = '';var loose = this.token.loose;if (this.token.task) {body += this.renderer.checkbox(this.token.checked);}while (this.next().type !== 'list_item_end') {body += !loose && this$1.token.type === 'text'? this$1.parseText(): this$1.tok();}return this.renderer.listitem(body);}case 'html': {// TODO parse inline content if parameter markdown=1return this.renderer.html(this.token.text);}case 'paragraph': {return this.renderer.paragraph(this.inline.output(this.token.text));}case 'text': {return this.renderer.paragraph(this.parseText());}}};/*** Helpers*/function escape(html, encode) {if (encode) {if (escape.escapeTest.test(html)) {return html.replace(escape.escapeReplace, function (ch) { return escape.replacements[ch] });}} else {if (escape.escapeTestNoEncode.test(html)) {return html.replace(escape.escapeReplaceNoEncode, function (ch) { return escape.replacements[ch] });}}return html;}escape.escapeTest = /[&<>"']/;escape.escapeReplace = /[&<>"']/g;escape.replacements = {'&': '&amp;','<': '&lt;','>': '&gt;','"': '&quot;',"'": '&#39;'};escape.escapeTestNoEncode = /[<>"']|&(?!#?\w+;)/;escape.escapeReplaceNoEncode = /[<>"']|&(?!#?\w+;)/g;function unescape(html) {// explicitly match decimal, hex, and named HTML entitiesreturn html.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig, function (_, n) {n = n.toLowerCase();if (n === 'colon') { return ':'; }if (n.charAt(0) === '#') {return n.charAt(1) === 'x'? String.fromCharCode(parseInt(n.substring(2), 16)): String.fromCharCode(+n.substring(1));}return '';});}function edit(regex, opt) {regex = regex.source || regex;opt = opt || '';return {replace: function (name, val) {val = val.source || val;val = val.replace(/(^|[^\[])\^/g, '$1');regex = regex.replace(name, val);return this;},getRegex: function () {return new RegExp(regex, opt);}};}function resolveUrl(base, href) {if (!baseUrls[' ' + base]) {// we can ignore everything in base after the last slash of its path component,// but we might need to add _that_// https://tools.ietf.org/html/rfc3986#section-3if (/^[^:]+:\/*[^/]*$/.test(base)) {baseUrls[' ' + base] = base + '/';} else {baseUrls[' ' + base] = rtrim(base, '/', true);}}base = baseUrls[' ' + base];if (href.slice(0, 2) === '//') {return base.replace(/:[\s\S]*/, ':') + href;} else if (href.charAt(0) === '/') {return base.replace(/(:\/*[^/]*)[\s\S]*/, '$1') + href;} else {return base + href;}}var baseUrls = {};var originIndependentUrl = /^$|^[a-z][a-z0-9+.-]*:|^[?#]/i;function noop() { }noop.exec = noop;function merge(obj) {var arguments$1 = arguments;var i = 1,target,key;for (; i < arguments.length; i++) {target = arguments$1[i];for (key in target) {if (Object.prototype.hasOwnProperty.call(target, key)) {obj[key] = target[key];}}}return obj;}function splitCells(tableRow, count) {// ensure that every cell-delimiting pipe has a space// before it to distinguish it from an escaped pipevar row = tableRow.replace(/\|/g, function (match, offset, str) {var escaped = false,curr = offset;while (--curr >= 0 && str[curr] === '\\') { escaped = !escaped; }if (escaped) {// odd number of slashes means | is escaped// so we leave it alonereturn '|';} else {// add space before unescaped |return ' |';}}),cells = row.split(/ \|/),i = 0;if (cells.length > count) {cells.splice(count);} else {while (cells.length < count) { cells.push(''); }}for (; i < cells.length; i++) {// leading or trailing whitespace is ignored per the gfm speccells[i] = cells[i].trim().replace(/\\\|/g, '|');}return cells;}// Remove trailing 'c's. Equivalent to str.replace(/c*$/, '').// /c*$/ is vulnerable to REDOS.// invert: Remove suffix of non-c chars instead. Default falsey.function rtrim(str, c, invert) {if (str.length === 0) {return '';}// Length of suffix matching the invert condition.var suffLen = 0;// Step left until we fail to match the invert condition.while (suffLen < str.length) {var currChar = str.charAt(str.length - suffLen - 1);if (currChar === c && !invert) {suffLen++;} else if (currChar !== c && invert) {suffLen++;} else {break;}}return str.substr(0, str.length - suffLen);}/*** Marked*/function marked(src, opt, callback) {// throw error in case of non string inputif (typeof src === 'undefined' || src === null) {throw new Error('marked(): input parameter is undefined or null');}if (typeof src !== 'string') {throw new Error('marked(): input parameter is of type '+ Object.prototype.toString.call(src) + ', string expected');}if (callback || typeof opt === 'function') {if (!callback) {callback = opt;opt = null;}opt = merge({}, marked.defaults, opt || {});var highlight = opt.highlight,tokens,pending,i = 0;try {tokens = Lexer.lex(src, opt);} catch (e) {return callback(e);}pending = tokens.length;var done = function (err) {if (err) {opt.highlight = highlight;return callback(err);}var out;try {out = Parser.parse(tokens, opt);} catch (e) {err = e;}opt.highlight = highlight;return err? callback(err): callback(null, out);};if (!highlight || highlight.length < 3) {return done();}delete opt.highlight;if (!pending) { return done(); }for (; i < tokens.length; i++) {(function (token) {if (token.type !== 'code') {return --pending || done();}return highlight(token.text, token.lang, function (err, code) {if (err) { return done(err); }if (code == null || code === token.text) {return --pending || done();}token.text = code;token.escaped = true;--pending || done();});})(tokens[i]);}return;}try {if (opt) { opt = merge({}, marked.defaults, opt); }return Parser.parse(Lexer.lex(src, opt), opt);} catch (e) {e.message += '\nPlease report this to https://github.com/markedjs/marked.';if ((opt || marked.defaults).silent) {return '<p>An error occurred:</p><pre>'+ escape(e.message + '', true)+ '</pre>';}throw e;}}/*** Options*/marked.options =marked.setOptions = function (opt) {merge(marked.defaults, opt);return marked;};marked.getDefaults = function () {return {baseUrl: null,breaks: false,gfm: true,headerIds: true,headerPrefix: '',highlight: null,langPrefix: 'language-',mangle: true,pedantic: false,renderer: new Renderer(),sanitize: false,sanitizer: null,silent: false,smartLists: false,smartypants: false,tables: true,xhtml: false};};marked.defaults = marked.getDefaults();/*** Expose*/marked.Parser = Parser;marked.parser = Parser.parse;marked.Renderer = Renderer;marked.TextRenderer = TextRenderer;marked.Lexer = Lexer;marked.lexer = Lexer.lex;marked.InlineLexer = InlineLexer;marked.inlineLexer = InlineLexer.output;marked.parse = marked;{module.exports = marked;}})(commonjsGlobal || (typeof window !== 'undefined' ? window : commonjsGlobal));
});

4. node_modules\docsify-pdf-converter\src\createLibrary.js

/*** 创建字典*/const marked = require("docsify-pdf-converter/src/marked");
const slugify = require("docsify-pdf-converter/src/slugify");
const util = require("util");
const fs = require("fs");
const [readFile, writeFile, exists] = [fs.readFile, fs.writeFile, fs.exists].map(fn =>util.promisify(fn),
);function merge(obj) {var arguments$1 = arguments;var i = 1,target,key;for (; i < arguments.length; i++) {target = arguments$1[i];for (key in target) {if (Object.prototype.hasOwnProperty.call(target, key)) {obj[key] = target[key];}}}return obj;
}/*** 获取docsify配置 合并默认配置* @param {Object} params * @returns */
function getConfig(params) {return merge({el: '#app',repo: '',maxLevel: 6,subMaxLevel: 0,loadSidebar: null,loadNavbar: null,homepage: 'README.md',coverpage: '',basePath: '',auto2top: false,name: '',themeColor: '',autoHeader: false,executeScript: null,noEmoji: false,ga: '',ext: '.md',mergeNavbar: false,formatUpdated: '',externalLinkTarget: '_blank',routerMode: 'hash',noCompileLinks: []},params);
}
/*** 读取docsify配置文件  获取配置  指定配置文件为 docsify.config.js* @param {String} dir * @returns */
async function getConfigObj(dir) {let configPath = dir + "/docsify.config.js"const isExists = await exists(configPath);if (isExists) {const configFile = await readFile(configPath, {encoding: "utf8",});let config = eval("(" + configFile.substring(configFile.indexOf("{")) + ")")return config}
}/*** 生成字典* @param {*} path * @param {*} content * @param {*} depth * @returns */
function genIndex(path, content, depth) {if (content === void 0) content = '';var tokens = marked.lexer(content)var index = {};var slug;tokens.forEach(function (token) {if (token.type === 'heading' && token.depth <= depth) {slug = "#" + path + "?id=" + slugify(token.text);index[slug] = { slug: slug, title: token.text, body: '' };} else {if (!slug) {return}if (!index[slug]) {index[slug] = { slug: slug, title: '', body: '' };} else if (index[slug].body) {index[slug].body += '\n' + (token.text || '');} else {index[slug].body = token.text;}}});slugify.clear();return index
}module.exports = function (paths, files, dir) {let fileObj = {}let INDEXS = {}paths.shift()files.shift()dir = dir.replace(/\\/g, '/')files.map(file => {fileObj[file.name] = file.content})getConfigObj(dir).then(res => {let config = getConfig(res)paths.map(path => {// 格式化文件路径  与页面端保持一致let tempPath = path.replace(/\\/g, '/').replace(dir, '').replace('.md', '')INDEXS[tempPath] = genIndex(tempPath, fileObj[path], config.search.depth || 2)})// 将生成的字典保存到项目本地writeFile('dictionaries.json', JSON.stringify(INDEXS), 'utf-8', function (err) {if (err) {console.error(err)} else {console.log("字典创建成功!")}});})}

docsify(二):新增生成字典/词库功能相关推荐

  1. wordweb在线编辑_使用WordWeb享受按需词典和词库功能

    wordweb在线编辑 Run across an unusual word or need a synonym for a word quickly?  Usually that means ope ...

  2. 自编记单词小程序项目(自定义词库,多功能)C/C++语言实现

    一款方便实用又简洁的记单词小程序,自定义单词库,多功能协助记忆!!! github地址:https://github.com/Knock-man/Memorizing-words-program 如今 ...

  3. 手机词库编辑器(可以由词库直接生成手机词典)

    http://www.mobilemate.cn/ [原创]手机词库编辑器(可以由词库直接生成手机词典) 中秋节台风来,也没有出去玩,于是尝试在Ubuntu下,重写了原来基于.Net的C#词库编辑器. ...

  4. 发现新词 | NLP之无监督方式构建词库(一)

    文章目录 一.数据介绍及处理 二.寻找未登录词 1.统计语料库中的词信息 2.利用互信息熵得到初始化词库 3.对语料库进行切分 4.利用搜索引擎判断新词 5.迭代寻找新词 6.方法总结 一.数据介绍及 ...

  5. 敏感词过滤之——自定义构建查询词库与快速查询实现

    关于敏感词过滤的一点思考与实践 业务场景 思考与研究 逻辑分析 代码实现(php) 构建敏感词树 分割字符串 敏感词树长分支的递归实现 读取敏感词库 敏感词树的查询 查询实现 调用 测试.分析与总结 ...

  6. IKAnalyzer实现扩展词库+动态更新词库的方法

    为什么80%的码农都做不了架构师?>>>    当前IKAnalyzer从发布最后一个版本后就一直没有再更新,使用过程中,经常遇到需要扩展词库以及动态更新字典表的问题,此处给出一种解 ...

  7. 深蓝词库转换1.6发布

    由于在技术上和功能上没有什么突破,一直心里的痛就是对QQ拼音分类词库(qpyd格式)的解析,一直无从下手,所以这半年来我一直都没有发布新版本的"深蓝词库转换".期间也收到了很多朋友 ...

  8. python--中文分词与词云制作--入门笔记(附停用词库及Mac字体资源)

    这里写自定义目录标题 一.中文分词基本说明 二.停用词库.自定义词典的使用 (一)停用词 (二)自定义词典 三.词云绘制 四.中文字体的使用说明 (一)Mac 字体使用说明 五.附件 (一)ttf字体 ...

  9. 用sed命令shell扩大王林快码词库

    比如我用王林快码,只有单字和二字组,二字组不太多,不现代,比如没有安卓和微信词组,又下载了搜狗二字组细胞词库已经转化为txt,想把该词组中快码没有的词组用快码的方式生成,就是取前两位加以组合.比如有快 ...

最新文章

  1. hibernate 和 mybatis 的区别
  2. stm32 PWM输出学习
  3. ASCII表完整版(包含16进制对应表)
  4. 网格变形动画MeshTransform
  5. mysql yum安装与配置文件_MySQL 8.0 yum安装和配置
  6. linux 重启服务器_linux入门-----6
  7. java spit 点_java split 的一些用法注意点。
  8. 华为云微认证答题_华为云微认证
  9. 【Oracle11gR2 | 学习】plsql dev存储过程的使用、存储函数、out类型的使用
  10. ERP之什么是物料编码?
  11. js点击第三方广告添加点击事件
  12. R绘图| Kaplan-Meier曲线及美化
  13. 深度学习之车牌识别(中国、越南)
  14. VLAN的接口类型与TAG帧
  15. oracle通过正则验证香港、澳门、台湾的身份证和护照
  16. mysql数据库从入门到高级
  17. Mace-micro引擎编译与测试
  18. rabbitmq组件断链重连机制
  19. 创龙TI TMS320C6678 DSP + Xilinx Kintex-7 FPGA的温度传感器、B2B连接器
  20. 芯片史称:“长平之战”----Intel的东进与ARM的西征(3)--人生如戏,全靠演技

热门文章

  1. 猿创征文 | 国产数据实战之docker部署MyWebSQL数据库管理工具
  2. [图]QQ发送珊瑚虫起诉书内容 会马上被踢并要求激活
  3. OPPO举办K10系列超次元新品发布会,四款超值新品硬核炸场
  4. linux unicode 转换工具,字符集之间转换(UTF-8,UNICODE,Gb2312)
  5. 56个民族按照字母排序,首字母拼音组合
  6. 学术大神推荐的好用科研工具
  7. Komodo调试perl
  8. 用IP地址反查主机名
  9. oracle win 7 64 下载,oracle 安装 win7 64_win732位系统下载 - Win7之家
  10. Springboot 最简单的整合Dubbo框架实战案例