Skip to content

Commit

Permalink
refactor: #995 封装新的哈希算法,从md5改成sha256 (#998)
Browse files Browse the repository at this point in the history
  • Loading branch information
sunsonliu authored Dec 12, 2024
1 parent 57fb28d commit d9275e6
Show file tree
Hide file tree
Showing 15 changed files with 47 additions and 36 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,6 @@
"juice": "^8.0.0",
"lint-staged": "~12.5.0",
"lodash": "^4.17.20",
"md5": "^2.2.1",
"mitt": "^3.0.0",
"npm-run-all": "^4.1.5",
"openai": "^3.3.0",
Expand All @@ -150,6 +149,7 @@
"dependencies": {
"@types/codemirror": "^0.0.108",
"@types/dompurify": "^2.2.3",
"crypto-js": "^4.2.0",
"jsdom": "~19.0.0"
},
"resolutions": {
Expand Down
36 changes: 24 additions & 12 deletions src/Engine.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import HookCenter from './core/HookCenter';
import hooksConfig from './core/HooksConfig';
import NestedError, { $expectTarget, $expectInherit, $expectInstance } from './utils/error';
import md5 from 'md5';
import CryptoJS from 'crypto-js';
import SyntaxBase from './core/SyntaxBase';
import ParagraphBase from './core/ParagraphBase';
import { PUNCTUATION, imgBase64Reg, imgDrawioXmlReg } from './utils/regexp';
Expand Down Expand Up @@ -46,8 +46,8 @@ export default class Engine {
this.$configInit(markdownParams);
this.hookCenter = new HookCenter(hooksConfig, markdownParams, cherry);
this.hooks = this.hookCenter.getHookList();
this.md5Cache = {};
this.md5StrMap = {};
this.hashCache = {};
this.hashStrMap = {};
this.cachedBigData = {};
this.markdownParams = markdownParams;
this.currentStrMd5 = [];
Expand Down Expand Up @@ -205,23 +205,35 @@ export default class Engine {
return $md;
}

/**
* @deprecated 已废弃,推荐使用 .hash()
*/
md5(str) {
if (!this.md5StrMap[str]) {
this.md5StrMap[str] = md5(str);
return this.hash(str);
}

/**
* 计算哈希值
* @param {String} str 被计算的字符串
* @returns {String} 哈希值
*/
hash(str) {
if (!this.hashStrMap[str]) {
this.hashStrMap[str] = CryptoJS.SHA256(str).toString();
}
return this.md5StrMap[str];
return this.hashStrMap[str];
}

$checkCache(str, func) {
const sign = this.md5(str);
if (typeof this.md5Cache[sign] === 'undefined') {
this.md5Cache[sign] = func(str);
const sign = this.hash(str);
if (typeof this.hashCache[sign] === 'undefined') {
this.hashCache[sign] = func(str);
if (BUILD_ENV !== 'production') {
// 生产环境屏蔽
Logger.log('markdown引擎渲染了:', str);
}
}
return { sign, html: this.md5Cache[sign] };
return { sign, html: this.hashCache[sign] };
}

$dealParagraph(md) {
Expand All @@ -231,12 +243,12 @@ export default class Engine {
// 缓存大文本数据,用以提升渲染性能
$cacheBigData(md) {
let $md = md.replace(imgBase64Reg, (whole, m1, m2) => {
const cacheKey = `bigDataBegin${this.md5(m2)}bigDataEnd`;
const cacheKey = `bigDataBegin${this.hash(m2)}bigDataEnd`;
this.cachedBigData[cacheKey] = m2;
return `${m1}${cacheKey})`;
});
$md = $md.replace(imgDrawioXmlReg, (whole, m1, m2) => {
const cacheKey = `bigDataBegin${this.md5(m2)}bigDataEnd`;
const cacheKey = `bigDataBegin${this.hash(m2)}bigDataEnd`;
this.cachedBigData[cacheKey] = m2;
return `${m1}${cacheKey}}`;
});
Expand Down
4 changes: 2 additions & 2 deletions src/UrlCache.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import md5 from 'md5';
import CryptoJS from 'crypto-js';

let urlCache = {};
const cherryInnerLinkRegex = /^cherry-inner:\/\/([0-9a-f]+)$/i;
Expand Down Expand Up @@ -44,7 +44,7 @@ export default class UrlCache {
* @returns
*/
static set(url) {
const urlSign = md5(url);
const urlSign = CryptoJS.SHA256(url).toString();
urlCache[urlSign] = url;
return `cherry-inner://${urlSign}`;
}
Expand Down
4 changes: 2 additions & 2 deletions src/core/ParagraphBase.js
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ export default class ParagraphBase extends SyntaxBase {
if (!this.needCache) {
return;
}
const $sign = sign || this.$engine.md5(str);
const $sign = sign || this.$engine.hash(str);
const key = `${this.cacheKey}I${$sign}_L${lineCount}$`;
this.cache[$sign] = {
content: str,
Expand Down Expand Up @@ -314,7 +314,7 @@ export default class ParagraphBase extends SyntaxBase {
* @param {string} wholeMatch whole match
*/
checkCache(wholeMatch, sentenceMakeFunc, lineCount = 0) {
this.sign = this.$engine.md5(wholeMatch);
this.sign = this.$engine.hash(wholeMatch);
// miss cache
if (!this.cache[this.sign]) {
return this.toHtml(wholeMatch, sentenceMakeFunc);
Expand Down
2 changes: 1 addition & 1 deletion src/core/hooks/Blockquote.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export default class Blockquote extends ParagraphBase {
handleMatch(str, sentenceMakeFunc) {
return str.replace(this.RULE.reg, (match, lines, content) => {
const lineCount = this.getLineCount(match, lines); // 段落所占行数
const sign = this.$engine.md5(match);
const sign = this.$engine.hash(match);
const testHasCache = this.testHasCache(sign);
if (testHasCache !== false) {
return this.getCacheWithSpace(testHasCache, match);
Expand Down
6 changes: 3 additions & 3 deletions src/core/hooks/CodeBlock.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ export default class CodeBlock extends ParagraphBase {
computeLines(match, leadingContent, code) {
const leadingSpaces = leadingContent;
const lines = this.getLineCount(match, leadingSpaces);
const sign = this.$engine.md5(match.replace(/^\n+/, '') + lines);
const sign = this.$engine.hash(match.replace(/^\n+/, '') + lines);
return {
sign,
lines,
Expand Down Expand Up @@ -247,7 +247,7 @@ export default class CodeBlock extends ParagraphBase {
}
return this.$recoverCodeInIndent(str).replace(this.$getIndentedCodeReg(), (match, code) => {
const lineCount = (match.match(/\n/g) || []).length;
const sign = this.$engine.md5(match);
const sign = this.$engine.hash(match);
const html = `<pre data-sign="${sign}" data-lines="${lineCount}"><code>${escapeHTMLSpecialChar(
code.replace(/\n( {4}|\t)/g, '\n'),
)}</code></pre>`;
Expand Down Expand Up @@ -412,7 +412,7 @@ export default class CodeBlock extends ParagraphBase {
$code = this.$replaceSpecialChar($code);
$code = $code.replace(/\\/g, '\\\\');
const html = `<code>${escapeHTMLSpecialChar($code)}</code>`;
const sign = this.$engine.md5(html);
const sign = this.$engine.hash(html);
CodeBlock.inlineCodeCache[sign] = html;
return `~~CODE${sign}$`;
});
Expand Down
2 changes: 1 addition & 1 deletion src/core/hooks/Detail.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export default class Detail extends ParagraphBase {
makeHtml(str, sentenceMakeFunc) {
return str.replace(this.RULE.reg, (match, preLines, isOpen, title, content) => {
const lineCount = this.getLineCount(match, preLines);
const sign = this.$engine.md5(match);
const sign = this.$engine.hash(match);
const testHasCache = this.testHasCache(sign);
if (testHasCache !== false) {
return prependLineFeedForParagraph(match, testHasCache);
Expand Down
2 changes: 1 addition & 1 deletion src/core/hooks/Footnote.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export default class Footnote extends ParagraphBase {
return '';
}
let html = footnote.map((note) => `<div class="one-footnote">\n${note.fnref}${note.note}\n</div>`).join('');
const sign = this.$engine.md5(html);
const sign = this.$engine.hash(html);
html = `<div class="footnote" data-sign="${sign}" data-lines="0"><div class="footnote-title">脚注</div>${html}</div>`;
return html;
}
Expand Down
2 changes: 1 addition & 1 deletion src/core/hooks/Header.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ export default class Header extends ParagraphBase {
anchorID = this.generateIDNoDup(headerTextRaw.replace(replaceFootNote, ''));
}
const safeAnchorID = `safe_${anchorID}`; // transform header id to avoid being sanitized
const sign = this.$engine.md5(`${level}-${processedText.sign}-${anchorID}-${dataLines}`);
const sign = this.$engine.hash(`${level}-${processedText.sign}-${anchorID}-${dataLines}`);
const result = [
`<h${level} id="${safeAnchorID}" data-sign="${sign}" data-lines="${dataLines}">`,
this.$getAnchor(anchorID),
Expand Down
2 changes: 1 addition & 1 deletion src/core/hooks/InlineMath.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export default class InlineMath extends ParagraphBase {
LoadMathModule.bind(this)('engine');
const linesArr = m1.match(/\n/g);
const lines = linesArr ? linesArr.length + 2 : 2;
const sign = this.$engine.md5(wholeMatch);
const sign = this.$engine.hash(wholeMatch);
// 既无MathJax又无katex时,原样输出
let result = '';
if (this.engine === 'katex' && this.katex?.renderToString) {
Expand Down
2 changes: 1 addition & 1 deletion src/core/hooks/MathBlock.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export default class MathBlock extends ParagraphBase {
const wholeMatchWithoutSpace = wholeMatch.replace(/^[ \f\r\t\v]*/, '').replace(/\s*$/, '');
// 去掉匹配到的第一个换行符
const lineSpaceWithoutPreSpace = lineSpace.replace(/^[ \f\r\t\v]*\n/, '');
const sign = this.$engine.md5(wholeMatch);
const sign = this.$engine.hash(wholeMatch);
let lines = this.getLineCount(wholeMatchWithoutSpace, lineSpaceWithoutPreSpace);
// 判断公式是不是新行输入,如果不是新行,则行号减1
if (!/\n/.test(lineSpace)) {
Expand Down
2 changes: 1 addition & 1 deletion src/core/hooks/Panel.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export default class Panel extends ParagraphBase {
makeHtml(str, sentenceMakeFunc) {
return str.replace(this.RULE.reg, (match, preLines, name, content) => {
const lineCount = this.getLineCount(match, preLines);
const sign = this.$engine.md5(match);
const sign = this.$engine.hash(match);
const testHasCache = this.testHasCache(sign);
if (testHasCache !== false) {
return prependLineFeedForParagraph(match, testHasCache);
Expand Down
4 changes: 2 additions & 2 deletions src/core/hooks/Table.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ export default class Table extends ParagraphBase {
rowLength: rows.length - 2, // 去除表头和控制行
};
const chartOptions = this.$parseChartOptions(rows[0][0]);
const chartOptionsSign = this.$engine.md5(rows[0][0]);
const chartOptionsSign = this.$engine.hash(rows[0][0]);
// 如果需要生成图表,
if (chartOptions) {
rows[0][0] = '';
Expand Down Expand Up @@ -196,7 +196,7 @@ export default class Table extends ParagraphBase {
? `~CTHD${tableHeader}~CTHD$~CTBD${tableRows}~CTBD$`
: `~CTBD${tableRows}~CTBD$`;
const html = cacheSrc;
const sign = this.$engine.md5(html);
const sign = this.$engine.hash(html);
const renderHtml = html
.replace(/~CTHD\$/g, '</thead>')
.replace(/~CTHD/g, '<thead>')
Expand Down
10 changes: 5 additions & 5 deletions src/core/hooks/Toc.js
Original file line number Diff line number Diff line change
Expand Up @@ -243,27 +243,27 @@ export default class Toc extends ParagraphBase {
let $str = super.afterMakeHtml(str);
const headerList = [];
const headerRegex = /<h([1-6])[^>]*? id="([^"]+?)"[^>]*?>(?:<a[^/]+?\/a>|)(.+?)<\/h\1>/g;
let str2Md5 = '';
let str2Hash = '';
$str.replace(headerRegex, (match, level, id, text) => {
const $text = text.replace(/~fn#[0-9]+#/g, '');
headerList.push({ level: +level, id, text: $text });
str2Md5 += `${level}${id}`;
str2Hash += `${level}${id}`;
});
str2Md5 = this.$engine.md5(str2Md5);
str2Hash = this.$engine.hash(str2Hash);
$str = $str.replace(/(?:^|\n)(\[\[|\[|)(toc|TOC)(\]\]|\]|)([<~])/, (match) =>
match.replace(/(\]\]|\]|)([<~])/, '$1\n$2'),
);
// 首先识别扩展语法
// TODO: fix this error
// @ts-expect-error
$str = $str.replace(this.RULE.extend.reg, (match, preLinesMatch) =>
this.$makeToc(headerList, str2Md5, preLinesMatch),
this.$makeToc(headerList, str2Hash, preLinesMatch),
);
// 处理标准语法
// TODO: fix this error
// @ts-expect-error
$str = $str.replace(this.RULE.standard.reg, (match, preLinesMatch) =>
this.$makeToc(headerList, str2Md5, preLinesMatch),
this.$makeToc(headerList, str2Hash, preLinesMatch),
);
// 重置toc状态
this.isFirstTocToken = true;
Expand Down
3 changes: 1 addition & 2 deletions src/toolbars/Toc.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
* limitations under the License.
*/
import { createElement } from '../utils/dom';
import md5 from 'md5';
/**
* 悬浮目录
*/
Expand Down Expand Up @@ -197,7 +196,7 @@ export default class Toc {
tocStr += item.text;
return item;
});
tocStr = md5(tocStr);
tocStr = this.$cherry.engine.hash(tocStr);
if (this.tocStr !== tocStr) {
this.tocStr = tocStr;
let tocHtml = '';
Expand Down

0 comments on commit d9275e6

Please sign in to comment.