lke-component 1.2.22 → 1.2.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lke-component.common.js.LICENSE.txt +0 -2
- package/dist/lke-component.umd.js +1 -1
- package/dist/lke-component.umd.js.LICENSE.txt +0 -2
- package/dist/lke-component.umd.min.js.LICENSE.txt +0 -2
- package/lib/react/msg.min.css +1 -1
- package/lib/react/src/shared/common.js +372 -0
- package/lib/react/src/shared/components/mathjax.js +935 -0
- package/lib/react/src/shared/components/utils.js +46 -0
- package/lib/react/src/shared/const.js +78 -0
- package/lib/react/src/shared/styles/content.less +309 -0
- package/lib/react/src/shared/styles/icon.less +38 -0
- package/lib/react/src/shared/styles/thought.less +92 -0
- package/package.json +1 -1
- package/dist/lke-component.esm.js +0 -2
|
@@ -30,8 +30,6 @@ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
|
30
30
|
PERFORMANCE OF THIS SOFTWARE.
|
|
31
31
|
***************************************************************************** */
|
|
32
32
|
|
|
33
|
-
/*! https://mths.be/punycode v1.4.1 by @mathias */
|
|
34
|
-
|
|
35
33
|
/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */
|
|
36
34
|
|
|
37
35
|
/*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */
|
|
@@ -30,8 +30,6 @@ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
|
30
30
|
PERFORMANCE OF THIS SOFTWARE.
|
|
31
31
|
***************************************************************************** */
|
|
32
32
|
|
|
33
|
-
/*! https://mths.be/punycode v1.4.1 by @mathias */
|
|
34
|
-
|
|
35
33
|
/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */
|
|
36
34
|
|
|
37
35
|
/*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */
|
package/lib/react/msg.min.css
CHANGED
|
@@ -6,4 +6,4 @@
|
|
|
6
6
|
Website: https://highlightjs.org/
|
|
7
7
|
License: see project LICENSE
|
|
8
8
|
Touched: 2021
|
|
9
|
-
*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{background:#f3f3f3;color:#444}.hljs-comment{color:#697070}.hljs-punctuation,.hljs-tag{color:rgba(68,68,68,.6666666666666666)}.hljs-tag .hljs-attr,.hljs-tag .hljs-name{color:#444}.hljs-attribute,.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-name,.hljs-selector-tag{font-weight:700}.hljs-deletion,.hljs-number,.hljs-quote,.hljs-selector-class,.hljs-selector-id,.hljs-string,.hljs-template-tag,.hljs-type{color:#800}.hljs-section,.hljs-title{color:#800;font-weight:700}.hljs-link,.hljs-operator,.hljs-regexp,.hljs-selector-attr,.hljs-selector-pseudo,.hljs-symbol,.hljs-template-variable,.hljs-variable{color:#ab5656}.hljs-literal{color:#695}.hljs-addition,.hljs-built_in,.hljs-bullet,.hljs-code{color:#397300}.hljs-meta{color:#1f7199}.hljs-meta .hljs-string{color:#38a}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}.cursor{display:inline-block;width:2px;height:17px;vertical-align:text-bottom;background-color:#000;animation:blink 1s infinite}.little-tags{cursor:pointer;width:16px;height:16px;display:inline-block;background:var(--color-gray-6);color:#fff;border-radius:10px;text-align:center;line-height:16px;word-break:normal;word-wrap:normal}@keyframes blink{0%{opacity:1}50%{opacity:0}to{opacity:1}}mjx-container mjx-math{display:block;white-space:normal;overflow-wrap:break-word;word-wrap:break-word;word-break:break-word}mjx-container{display:inline-block}mjx-assistive-mml{right:0;bottom:0}.answer-md{font-size:400 14px/20px;word-break:break-word;word-wrap:break-word}.answer-md video{display:none}.answer-md .code-language-label{position:absolute;top:0;right:0;background:#f0f0f0;color:#333;padding:2px 8px;font-size:12px;border-bottom-left-radius:4px}.answer-md .hljs{color:#121319;background:#fff}.answer-md .hljs-comment,.answer-md .hljs-quote{color:#979baa;font-style:italic}.answer-md .hljs-doctag,.answer-md .hljs-formula,.answer-md .hljs-keyword{color:#4a70ff}.answer-md .hljs-deletion,.answer-md .hljs-name,.answer-md .hljs-section,.answer-md .hljs-selector-tag,.answer-md .hljs-subst{color:#ff8345}.answer-md .hljs-literal{color:#1492ff}.answer-md .hljs-addition,.answer-md .hljs-attribute,.answer-md .hljs-meta .hljs-string,.answer-md .hljs-regexp,.answer-md .hljs-string{color:#0fb87f}.answer-md .hljs-attr,.answer-md .hljs-number,.answer-md .hljs-selector-attr,.answer-md .hljs-selector-class,.answer-md .hljs-selector-pseudo,.answer-md .hljs-template-variable,.answer-md .hljs-type,.answer-md .hljs-variable{color:#ffa436}.answer-md .hljs-bullet,.answer-md .hljs-link,.answer-md .hljs-meta,.answer-md .hljs-selector-id,.answer-md .hljs-symbol,.answer-md .hljs-title{color:#d20fd2}.answer-md .hljs-built_in,.answer-md .hljs-class .hljs-title,.answer-md .hljs-title.class_{color:#f7c51e}.answer-md .hljs-emphasis{font-style:italic}.answer-md .hljs-strong{font-weight:700}.answer-md .hljs-link{text-decoration:underline}.answer-md .hljs-ln{border-collapse:collapse}.answer-md .hljs-ln td{padding:0}.answer-md .hljs-ln td.hljs-ln-numbers{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;text-align:left;vertical-align:top;padding:0 10px;color:#abb2bf!important;white-space:nowrap;border-right:1px solid #c5c5c5!important}.answer-md .hljs-ln td.hljs-ln-code{padding-left:10px}.answer-md .hljs-ln-n:before{content:attr(data-line-number)}.answer-md pre{position:relative}.answer-md .table:not(.hljs-ln) ::-webkit-scrollbar-track{background:transparent}.answer-md .table:not(.hljs-ln) ::-webkit-scrollbar-thumb{border-radius:10px;background:rgba(17,32,70,.13)}.answer-md img{max-width:100%;cursor:pointer;border-radius:6px}.answer-md p{word-break:break-word;word-wrap:break-word}.answer-md ::marker{color:rgba(1,11,50,.41)}.answer-md h1{font-size:18px;padding-top:18px}.answer-md h2,.answer-md h3,.answer-md h4,.answer-md h5,.answer-md h6{font-size:16px}.answer-md code{white-space:break-spaces}.answer-md table:not(.hljs-ln){display:inline-block;overflow-x:scroll;background:#fff;border-spacing:0;border-collapse:collapse;border-bottom:1px solid rgba(18,42,79,.08);border-right:1px solid rgba(18,42,79,.08);max-width:100%}.answer-md table:not(.hljs-ln) th{background:#eaecef;color:rgba(1,11,50,.41)}.answer-md table:not(.hljs-ln) td,.answer-md table:not(.hljs-ln) th{border-left:1px solid rgba(18,42,79,.08);border-top:1px solid rgba(18,42,79,.08)}.answer-md table:not(.hljs-ln) td{padding:8px 12px;min-width:20px}.answer-md .table-style:not(.hljs-ln){display:inline-block;white-space:nowrap;max-width:100%;overflow:scroll;background:#fff;border-bottom:1px solid rgba(18,42,79,.08);border-right:1px solid rgba(18,42,79,.08);border-spacing:0;border-collapse:collapse}.answer-md .table-style:not(.hljs-ln) th{color:rgba(1,11,50,.41);padding:12px;font-weight:400;background:#eaecef}.answer-md .table-style:not(.hljs-ln) td,.answer-md .table-style:not(.hljs-ln) th{border-left:1px solid rgba(18,42,79,.08);border-top:1px solid rgba(18,42,79,.08)}.answer-md .table-style:not(.hljs-ln) td{padding:8px 4px;min-width:45px;overflow-wrap:break-word;white-space:break-spaces}.v-icon{display:inline-block;width:16px;height:16px;transition:-webkit-transform .5s;transition:transform .5s;transition:transform .5s,-webkit-transform .5s}.v-icon.is-vertical{-webkit-transform:scaleY(-1);-ms-transform:scaleY(-1);transform:scaleY(-1)}.v-icon.is-horizontal{-webkit-transform:scaleX(-1);-ms-transform:scaleX(-1);transform:scaleX(-1)}.v-icon--fill{fill:#0fb87f}.v-icon--stroke{stroke:#0fb87f}a:hover .v-icon .hover,button:hover .v-icon .hover,span:hover .v-icon .hover,svg:hover .v-icon .hover{opacity:1}a:hover .v-icon--hover-hide-default,button:hover .v-icon--hover-hide-default,span:hover .v-icon--hover-hide-default,svg:hover .v-icon--hover-hide-default{opacity:0}a:active .v-icon .active,button:active .v-icon .active,span:active .v-icon .active,svg:active .v-icon .active{opacity:1}a:active .v-icon--active-hide-default,a:active .v-icon--active-hide-hover,button:active .v-icon--active-hide-default,button:active .v-icon--active-hide-hover,span:active .v-icon--active-hide-default,span:active .v-icon--active-hide-hover,svg:active .v-icon--active-hide-default,svg:active .v-icon--active-hide-hover{opacity:0}.question-text,.question-text-mobile{width:100%}.thought-clps-title{color:rgba(1,11,50,.41);font-size:12px;font-style:normal;font-weight:400;line-height:16px;cursor:pointer;padding:12px 0 8px;display:flex;align-items:center;gap:4px}.thought-clps-content{display:flex;flex-direction:column;gap:12px;align-self:stretch}.thought-clps-content p{margin:0}.thought-clps-content .thought-title{display:flex;align-items:center;justify-content:space-between;cursor:pointer}.thought-clps-content .thought-title .thought-title-container{display:flex;align-items:center;gap:5px}.thought-clps-content .thought-title .thought-title-icon{display:flex;width:16px;height:16px;flex-direction:column;justify-content:center;border-radius:8px}.thought-clps-content .thought-title .thought-title-name{color:rgba(0,1,10,.93);font-size:14px;font-style:normal;font-weight:600;line-height:normal}.thought-clps-content .thought-title .thought-title-elapsed{color:rgba(1,11,50,.41);font-family:Monaco;font-size:12px;font-style:normal;font-weight:400;line-height:normal}.thought-clps-content .thought-detail{display:flex;padding:12px 0;gap:10px;border-bottom:.5px solid rgba(18,42,79,.08);color:rgba(3,10,38,.65);font-size:14px;font-style:normal;font-weight:400;line-height:20px}.thought-clps-content .thought-detail p{word-break:break-all;word-wrap:break-word;margin:0}.thought-clps-content .thought-detail.last-item{border-bottom:1.5px solid #cdd0d9}
|
|
9
|
+
*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{background:#f3f3f3;color:#444}.hljs-comment{color:#697070}.hljs-punctuation,.hljs-tag{color:rgba(68,68,68,.6666666666666666)}.hljs-tag .hljs-attr,.hljs-tag .hljs-name{color:#444}.hljs-attribute,.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-name,.hljs-selector-tag{font-weight:700}.hljs-deletion,.hljs-number,.hljs-quote,.hljs-selector-class,.hljs-selector-id,.hljs-string,.hljs-template-tag,.hljs-type{color:#800}.hljs-section,.hljs-title{color:#800;font-weight:700}.hljs-link,.hljs-operator,.hljs-regexp,.hljs-selector-attr,.hljs-selector-pseudo,.hljs-symbol,.hljs-template-variable,.hljs-variable{color:#ab5656}.hljs-literal{color:#695}.hljs-addition,.hljs-built_in,.hljs-bullet,.hljs-code{color:#397300}.hljs-meta{color:#1f7199}.hljs-meta .hljs-string{color:#38a}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}.cursor{display:inline-block;width:2px;height:17px;vertical-align:text-bottom;background-color:#000;animation:blink 1s infinite}.little-tags{cursor:pointer;width:16px;height:16px;display:inline-block;background:var(--color-gray-6);color:#fff;border-radius:10px;text-align:center;line-height:16px;word-break:normal;word-wrap:normal}@keyframes blink{0%{opacity:1}50%{opacity:0}to{opacity:1}}mjx-container mjx-math{display:block;white-space:normal;overflow-wrap:break-word;word-wrap:break-word;word-break:break-word}mjx-container{display:inline-block}mjx-assistive-mml{right:0;bottom:0}.answer-md{font-size:400 14px/20px;word-break:break-word;word-wrap:break-word}.answer-md video{display:none}.answer-md .code-language-label{position:absolute;top:0;right:0;background:#f0f0f0;color:#333;padding:2px 8px;font-size:12px;border-bottom-left-radius:4px}.answer-md .hljs{color:#121319;background:#fff}.answer-md .hljs-comment,.answer-md .hljs-quote{color:#979baa;font-style:italic}.answer-md .hljs-doctag,.answer-md .hljs-formula,.answer-md .hljs-keyword{color:#4a70ff}.answer-md .hljs-deletion,.answer-md .hljs-name,.answer-md .hljs-section,.answer-md .hljs-selector-tag,.answer-md .hljs-subst{color:#ff8345}.answer-md .hljs-literal{color:#1492ff}.answer-md .hljs-addition,.answer-md .hljs-attribute,.answer-md .hljs-meta .hljs-string,.answer-md .hljs-regexp,.answer-md .hljs-string{color:#0fb87f}.answer-md .hljs-attr,.answer-md .hljs-number,.answer-md .hljs-selector-attr,.answer-md .hljs-selector-class,.answer-md .hljs-selector-pseudo,.answer-md .hljs-template-variable,.answer-md .hljs-type,.answer-md .hljs-variable{color:#ffa436}.answer-md .hljs-bullet,.answer-md .hljs-link,.answer-md .hljs-meta,.answer-md .hljs-selector-id,.answer-md .hljs-symbol,.answer-md .hljs-title{color:#d20fd2}.answer-md .hljs-built_in,.answer-md .hljs-class .hljs-title,.answer-md .hljs-title.class_{color:#f7c51e}.answer-md .hljs-emphasis{font-style:italic}.answer-md .hljs-strong{font-weight:700}.answer-md .hljs-link{text-decoration:underline}.answer-md .hljs-ln{border-collapse:collapse}.answer-md .hljs-ln td{padding:0}.answer-md .hljs-ln td.hljs-ln-numbers{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;text-align:left;vertical-align:top;padding:0 10px;color:#abb2bf!important;white-space:nowrap;border-right:1px solid #c5c5c5!important}.answer-md .hljs-ln td.hljs-ln-code{padding-left:10px}.answer-md .hljs-ln-n:before{content:attr(data-line-number)}.answer-md pre{position:relative}.answer-md .table:not(.hljs-ln) ::-webkit-scrollbar-track{background:transparent}.answer-md .table:not(.hljs-ln) ::-webkit-scrollbar-thumb{border-radius:10px;background:rgba(17,32,70,.13)}.answer-md img{max-width:100%;cursor:pointer;border-radius:6px}.answer-md p{word-break:break-word;word-wrap:break-word}.answer-md ::marker{color:rgba(1,11,50,.41)}.answer-md h1{font-size:18px;padding-top:18px}.answer-md h2,.answer-md h3,.answer-md h4,.answer-md h5,.answer-md h6{font-size:16px}.answer-md code{white-space:break-spaces}.answer-md table:not(.hljs-ln){display:inline-block;overflow-x:scroll;background:#fff;border-spacing:0;border-collapse:collapse;border-bottom:1px solid rgba(18,42,79,.08);border-right:1px solid rgba(18,42,79,.08);max-width:100%}.answer-md table:not(.hljs-ln) th{background:#eaecef;color:rgba(1,11,50,.41)}.answer-md table:not(.hljs-ln) td,.answer-md table:not(.hljs-ln) th{border-left:1px solid rgba(18,42,79,.08);border-top:1px solid rgba(18,42,79,.08)}.answer-md table:not(.hljs-ln) td{padding:8px 12px;min-width:20px}.answer-md .table-style:not(.hljs-ln){display:inline-block;white-space:nowrap;max-width:100%;overflow:scroll;background:#fff;border-bottom:1px solid rgba(18,42,79,.08);border-right:1px solid rgba(18,42,79,.08);border-spacing:0;border-collapse:collapse}.answer-md .table-style:not(.hljs-ln) th{color:rgba(1,11,50,.41);padding:12px;font-weight:400;background:#eaecef}.answer-md .table-style:not(.hljs-ln) td,.answer-md .table-style:not(.hljs-ln) th{border-left:1px solid rgba(18,42,79,.08);border-top:1px solid rgba(18,42,79,.08)}.answer-md .table-style:not(.hljs-ln) td{padding:8px 4px;min-width:45px;overflow-wrap:break-word;white-space:break-spaces}blockquote{padding:4px 12px;border-left:4px solid rgba(1,11,50,.15);color:rgba(1,11,50,.65);background:rgba(1,11,50,.03);border-radius:0 4px 4px 0}blockquote p{margin:0}.v-icon{display:inline-block;width:16px;height:16px;transition:-webkit-transform .5s;transition:transform .5s;transition:transform .5s,-webkit-transform .5s}.v-icon.is-vertical{-webkit-transform:scaleY(-1);-ms-transform:scaleY(-1);transform:scaleY(-1)}.v-icon.is-horizontal{-webkit-transform:scaleX(-1);-ms-transform:scaleX(-1);transform:scaleX(-1)}.v-icon--fill{fill:#0fb87f}.v-icon--stroke{stroke:#0fb87f}a:hover .v-icon .hover,button:hover .v-icon .hover,span:hover .v-icon .hover,svg:hover .v-icon .hover{opacity:1}a:hover .v-icon--hover-hide-default,button:hover .v-icon--hover-hide-default,span:hover .v-icon--hover-hide-default,svg:hover .v-icon--hover-hide-default{opacity:0}a:active .v-icon .active,button:active .v-icon .active,span:active .v-icon .active,svg:active .v-icon .active{opacity:1}a:active .v-icon--active-hide-default,a:active .v-icon--active-hide-hover,button:active .v-icon--active-hide-default,button:active .v-icon--active-hide-hover,span:active .v-icon--active-hide-default,span:active .v-icon--active-hide-hover,svg:active .v-icon--active-hide-default,svg:active .v-icon--active-hide-hover{opacity:0}.question-text,.question-text-mobile{width:100%}.thought-clps-title{color:rgba(1,11,50,.41);font-size:12px;font-style:normal;font-weight:400;line-height:16px;cursor:pointer;padding:12px 0 8px;display:flex;align-items:center;gap:4px}.thought-clps-content{display:flex;flex-direction:column;gap:12px;align-self:stretch}.thought-clps-content p{margin:0}.thought-clps-content .thought-title{display:flex;align-items:center;justify-content:space-between;cursor:pointer}.thought-clps-content .thought-title .thought-title-container{display:flex;align-items:center;gap:5px}.thought-clps-content .thought-title .thought-title-icon{display:flex;width:16px;height:16px;flex-direction:column;justify-content:center;border-radius:8px}.thought-clps-content .thought-title .thought-title-name{color:rgba(0,1,10,.93);font-size:14px;font-style:normal;font-weight:600;line-height:normal}.thought-clps-content .thought-title .thought-title-elapsed{color:rgba(1,11,50,.41);font-family:Monaco;font-size:12px;font-style:normal;font-weight:400;line-height:normal}.thought-clps-content .thought-detail{display:flex;padding:12px 0;gap:10px;border-bottom:.5px solid rgba(18,42,79,.08);color:rgba(3,10,38,.65);font-size:14px;font-style:normal;font-weight:400;line-height:20px}.thought-clps-content .thought-detail p{word-break:break-all;word-wrap:break-word;margin:0}.thought-clps-content .thought-detail.last-item{border-bottom:1.5px solid #cdd0d9}
|
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
export const matchImageLinks = (text) => {
|
|
2
|
+
const regex = new RegExp('!\\[([^\\]]+)\\]\\(([^)]+)\\)', 'g');
|
|
3
|
+
const matches = [];
|
|
4
|
+
let match;
|
|
5
|
+
while ((match = regex.exec(text)) !== null) {
|
|
6
|
+
matches.push(match[0]);
|
|
7
|
+
}
|
|
8
|
+
return matches;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const getQueryVariable = (src, variable) => {
|
|
12
|
+
const query = src.split('?');
|
|
13
|
+
if (query.length < 2) {
|
|
14
|
+
return '';
|
|
15
|
+
}
|
|
16
|
+
const vars = query[1].split('&');
|
|
17
|
+
// eslint-disable-next-line @typescript-eslint/prefer-for-of
|
|
18
|
+
for (let i = 0; i < vars.length; i++) {
|
|
19
|
+
const pair = vars[i].split('=');
|
|
20
|
+
if (pair[0] === variable) {
|
|
21
|
+
return decodeURI(pair[1]);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return '';
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const replaceLinks = (text) => {
|
|
28
|
+
if (!text) return text;
|
|
29
|
+
// 先把里面的图片保留
|
|
30
|
+
const matchImgs = matchImageLinks(text);
|
|
31
|
+
matchImgs.forEach((i, index) => {
|
|
32
|
+
text = text.replace(i, `IMG_URL${index}`);
|
|
33
|
+
});
|
|
34
|
+
const from = getQueryVariable(window.location.hash, 'from');
|
|
35
|
+
const replaceUrl = from ? '' : `${window.location.protocol}//${window.location.host}/lke#/link-info/redirect?target=`;
|
|
36
|
+
const regex = new RegExp(
|
|
37
|
+
'(\\[([^\\]]+)\\]\\(' +
|
|
38
|
+
'(https?:\\/\\/(?!lke\\.cloud\\.tencent\\.com)(?!.*qidian)[^\\s)]+)' +
|
|
39
|
+
'\\))|' +
|
|
40
|
+
'(<a\\s+[^>]*href="' +
|
|
41
|
+
'((?!lke\\.cloud\\.tencent\\.com)(?!.*qidian)[^"]+)' +
|
|
42
|
+
'"[^>]*>(.*?)<\\/a>)',
|
|
43
|
+
'gi'
|
|
44
|
+
);
|
|
45
|
+
text = text.replace(regex, (match, p1, p2, p3, p4, p5, p6) => {
|
|
46
|
+
if (p1 && p2) {
|
|
47
|
+
return `[${p2}](${replaceUrl}${p3})`;
|
|
48
|
+
} else if (p5 && !p5.startsWith('#')) {
|
|
49
|
+
return `<a href="${replaceUrl}${p5}">${p6}</a>`;
|
|
50
|
+
} else {
|
|
51
|
+
return match;
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
matchImgs.forEach((i, index) => {
|
|
55
|
+
text = text.replace(`IMG_URL${index}`, i);
|
|
56
|
+
});
|
|
57
|
+
return text;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export const handleMathStar = (str) => {
|
|
61
|
+
return str.replace(new RegExp('(\\d)\\*(\\d)', 'g'), '$1\\*$2');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// 修复公式
|
|
65
|
+
export const formatMathExpressions = (str) => {
|
|
66
|
+
// console.log('formatMathExpressions start', str)
|
|
67
|
+
// 正则表达式匹配前后可能的换行符和$$之间的内容
|
|
68
|
+
const regex = new RegExp('(^|\\n\\n)?(\\$\\$(.*?)\\$\\$)(\\n\\n|$)?', 'g');
|
|
69
|
+
// 使用回调函数进行替换
|
|
70
|
+
const formattedString = str.replace(regex, (match, p1, p2, p3, p4) => {
|
|
71
|
+
// console.log('formatMathExpressions match', match,'...1...', p1,'...2...', p2,'...3...', p3,'...4...', p4)
|
|
72
|
+
return '\n\n' + p2 + '\n\n'
|
|
73
|
+
});
|
|
74
|
+
// console.log('formatMathExpressions rst', formattedString)
|
|
75
|
+
return formattedString;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// 处理table表格内的markdown图片
|
|
79
|
+
export const convertMarkdownImagesInTable = (input) => {
|
|
80
|
+
// 定义正则表达式来匹配 <table> 和 </table> 之间的内容
|
|
81
|
+
const tableRegex = new RegExp('<table>([\\s\\S]*?)<\\/table>', 'g');
|
|
82
|
+
// 定义正则表达式来匹配 Markdown 格式的图片
|
|
83
|
+
const markdownImageRegex = new RegExp('!\\[([^\\]]*)\\]\\(([^)]+)\\)', 'g');
|
|
84
|
+
|
|
85
|
+
// 使用 replace 方法处理每个匹配的 <table> 块
|
|
86
|
+
return input.replace(tableRegex, (match, tableContent) => {
|
|
87
|
+
// 在 <table> 块中替换 Markdown 图片为 HTML 图片
|
|
88
|
+
const convertedContent = tableContent.replace(markdownImageRegex, (match, altText, url) => {
|
|
89
|
+
return `<img src="${url}" alt="${altText}">`;
|
|
90
|
+
});
|
|
91
|
+
// 返回替换后的 <table> 块
|
|
92
|
+
return `<table>${convertedContent}</table>`;
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// 数字前后的星号转义,去掉数字斜体的MD格式
|
|
97
|
+
export const escapeMarkdownStars = (str) => {
|
|
98
|
+
// 正则表达式匹配乘号的情况
|
|
99
|
+
const regex = new RegExp('(\\d|\\))\\*(\\d|\\()', 'g');
|
|
100
|
+
|
|
101
|
+
// 替换匹配的乘号,并在其前面添加反斜杠
|
|
102
|
+
return str.replace(regex, (match, p1, p2) => `${p1}\\*${p2}`);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// 输出优化,有图片的时候显示正在输出图片
|
|
106
|
+
export const fixContentWithoutImg = (content) => {
|
|
107
|
+
// 正则表达式匹配不完整的 ]*$', 'g');
|
|
109
|
+
// 使用正则表达式替换所有匹配的部分
|
|
110
|
+
const replaced = content.replace(regex, '[正在输出图片...]');
|
|
111
|
+
return replaced;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// 输出优化,去掉字符串所有的html标签,直接输出里面的文本内容
|
|
115
|
+
export const removeUnclosedHtmlTags = (text) => {
|
|
116
|
+
// 定义正则表达式来匹配在 ``` 和 ``` 之间的内容
|
|
117
|
+
const codeBlockPattern = new RegExp('```[\\s\\S]*?```', 'g');
|
|
118
|
+
|
|
119
|
+
// 提取所有的代码块
|
|
120
|
+
const codeBlocks = text.match(codeBlockPattern) || [];
|
|
121
|
+
|
|
122
|
+
// 移除所有代码块
|
|
123
|
+
let textWithoutCodeBlocks = text.replace(codeBlockPattern, 'PLACEHOLDER');
|
|
124
|
+
|
|
125
|
+
// 定义正则表达式来匹配未闭合的 HTML 标签
|
|
126
|
+
const unclosedTagPattern = new RegExp('<[^>\\s]*\\s[^>]*$', 'g');
|
|
127
|
+
|
|
128
|
+
// 使用正则表达式替换未闭合的 HTML 标签为空字符串
|
|
129
|
+
textWithoutCodeBlocks = textWithoutCodeBlocks.replace(unclosedTagPattern, '');
|
|
130
|
+
|
|
131
|
+
if (textWithoutCodeBlocks.endsWith('<')) {
|
|
132
|
+
textWithoutCodeBlocks = textWithoutCodeBlocks.slice(0, -1);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// 将代码块放回原来的位置
|
|
136
|
+
let index = 0;
|
|
137
|
+
textWithoutCodeBlocks = textWithoutCodeBlocks.replace(new RegExp('PLACEHOLDER', 'g'), () => codeBlocks[index++]);
|
|
138
|
+
|
|
139
|
+
return textWithoutCodeBlocks;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export const fixMarkdownOrderedList = (mdText) => {
|
|
143
|
+
// 分割文本为行
|
|
144
|
+
const lines = mdText.split('\n');
|
|
145
|
+
|
|
146
|
+
// 遍历每一行
|
|
147
|
+
for (let i = 0; i < lines.length; i++) {
|
|
148
|
+
// 检查当前行是否是有序列表项
|
|
149
|
+
if (new RegExp('^\\d+\\.\\s').test(lines[i])) {
|
|
150
|
+
// 检查下一行是否是错误的有序列表项
|
|
151
|
+
if (lines[i + 1] && new RegExp('^\\d+\\.\\S').test(lines[i + 1])) {
|
|
152
|
+
// 在序号和点之间添加空格
|
|
153
|
+
lines[i + 1] = lines[i + 1].replace(new RegExp('(\\d+)\\.(\\S)', ''), '$1. $2');
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// 合并行为新的文本
|
|
159
|
+
const fixedMdText = lines.join('\n');
|
|
160
|
+
|
|
161
|
+
return fixedMdText;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// 显示小标处理思路,首先把在应用组件的父层级,把content内容处理为[数字,数字,数字](@ref)形式,然后如果showTags为true,则把[数字,数字,数字](@ref)转为数字小标展示在md中,如果不转则当字符串展示
|
|
165
|
+
export const transformString = (input) => {
|
|
166
|
+
// 正则表达式匹配 [数字,数字,数字](@ref) 模式
|
|
167
|
+
const regex = new RegExp('\\[(\\d+(?:\\s*,\\s*\\d+)*)\\]\\(@ref\\)', 'g');
|
|
168
|
+
|
|
169
|
+
// 替换逻辑
|
|
170
|
+
return input.replace(regex, (match, numbers) => {
|
|
171
|
+
// 将数字分割并转换为 <span> 标签形式
|
|
172
|
+
const spanTags = numbers.split(new RegExp('\\s*,\\s*')).map(number => `<span class="little-tags">${number}</span>`).join('');
|
|
173
|
+
return `<span class="tags-container">${spanTags}</span>`;
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export const replaceBoxedMathAtEnd = (input) => {
|
|
178
|
+
// 正则表达式匹配以 \boxed{...} 结尾的公式
|
|
179
|
+
const regex = new RegExp('\\\\boxed\\{([^}]+)\\}$');
|
|
180
|
+
|
|
181
|
+
// 使用 replace 方法进行替换
|
|
182
|
+
const output = input.replace(regex, '\\( \\boxed{$1} \\)');
|
|
183
|
+
|
|
184
|
+
return output;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const unclosedVideoPlaceholdersRef = {};
|
|
188
|
+
|
|
189
|
+
export const replaceVideo = (text) => {
|
|
190
|
+
if (text.indexOf('<video') < 0) {
|
|
191
|
+
return text;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// 清理已完成的占位符
|
|
195
|
+
Object.keys(unclosedVideoPlaceholdersRef).forEach(key => {
|
|
196
|
+
if (unclosedVideoPlaceholdersRef[key] === null) {
|
|
197
|
+
delete unclosedVideoPlaceholdersRef[key];
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
let processed = text;
|
|
202
|
+
|
|
203
|
+
// 先处理完整的video标签(包含开始和结束标签的)
|
|
204
|
+
const completeVideoRegex = /<video\b[^>]*>[\s\S]*?<\/video>/gi;
|
|
205
|
+
processed = processed.replace(completeVideoRegex, (match) => {
|
|
206
|
+
return match; // 保持完整的video标签不变
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
// 处理未闭合的video标签
|
|
210
|
+
const unClosedVideoRegex = /<video\b[^>]*>(?:(?!<\/video>)[\s\S])*$/gi;
|
|
211
|
+
processed = processed.replace(unClosedVideoRegex, (match) => {
|
|
212
|
+
const placeholderId = `video-placeholder-${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
|
213
|
+
unclosedVideoPlaceholdersRef[placeholderId] = match;
|
|
214
|
+
return `<div class="video-placeholder" data-video-id="${placeholderId}"></div>`;
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
// 处理结束标签,恢复完整的video
|
|
218
|
+
if (processed.includes('</video>')) {
|
|
219
|
+
const placeholderRegex = /<div class="video-placeholder" data-video-id="([^"]+)"><\/div>/g;
|
|
220
|
+
processed = processed.replace(placeholderRegex, (match, placeholderId) => {
|
|
221
|
+
const originalVideo = unclosedVideoPlaceholdersRef[placeholderId];
|
|
222
|
+
if (originalVideo) {
|
|
223
|
+
// 检查后面是否有对应的结束标签
|
|
224
|
+
const afterPlaceholder = processed.split(match)[1];
|
|
225
|
+
if (afterPlaceholder && afterPlaceholder.startsWith('</video>')) {
|
|
226
|
+
delete unclosedVideoPlaceholdersRef[placeholderId];
|
|
227
|
+
return originalVideo; // 返回原始video标签,让结束标签自然匹配
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
return match; // 保持占位符
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
return processed;
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
function parseSimpleText(text) {
|
|
238
|
+
// return text.replace(urlRegex, (url) => {
|
|
239
|
+
// return `[${url}](${url})`;
|
|
240
|
+
// });
|
|
241
|
+
return text;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
function processJsonStructure(jsonData) {
|
|
246
|
+
// 将JSON转换为字符串,但不处理
|
|
247
|
+
let jsonString = JSON.stringify(jsonData, null, 0);
|
|
248
|
+
|
|
249
|
+
// 只匹配直接作为 JSON 值的 URL(前面是 ": 而不是 \": 的情况)
|
|
250
|
+
// 避免处理嵌套在转义 JSON 字符串内的 URL
|
|
251
|
+
const urlPattern = new RegExp('(?<!\\\\)"(https?:\\/\\/[^"]+)"', 'g');
|
|
252
|
+
jsonString = jsonString.replace(urlPattern, function(match, url) {
|
|
253
|
+
// 这些标记稍后会被替换回Markdown链接
|
|
254
|
+
return `"___URL_START___${url}___URL_END___"`;
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
// 替换URL占位符为Markdown链接
|
|
258
|
+
const placeholderPattern = new RegExp('___URL_START___(.*?)___URL_END___', 'g');
|
|
259
|
+
jsonString = jsonString.replace(placeholderPattern, function(match, url) {
|
|
260
|
+
return `[${url}](${url})`;
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
return jsonString;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
export function isMarkdownCodeBlock(text) {
|
|
267
|
+
// 匹配 Markdown 代码块的正则表达式
|
|
268
|
+
const codeBlockRegex = new RegExp('```(\\w*)\\n([\\s\\S]*?)\\n```', 'g');
|
|
269
|
+
return codeBlockRegex.test(text);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
// 解析JSON数据中的链接,避免和链接紧挨着的字符也解析成链接中的字符
|
|
274
|
+
export function parseMixedJSONContent(text) {
|
|
275
|
+
const jsonRegex = new RegExp('(\\[[\\s\\S]*?\\]|\\{[\\s\\S]*?\\})', 'g');
|
|
276
|
+
let lastIndex = 0;
|
|
277
|
+
let result = '';
|
|
278
|
+
let match;
|
|
279
|
+
|
|
280
|
+
// 查找所有可能的JSON片段
|
|
281
|
+
while ((match = jsonRegex.exec(text)) !== null) {
|
|
282
|
+
// 添加JSON前的文本(如果有)
|
|
283
|
+
if (match.index > lastIndex) {
|
|
284
|
+
const textBefore = text.substring(lastIndex, match.index);
|
|
285
|
+
result += parseSimpleText(textBefore);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
const potentialJson = match[0];
|
|
289
|
+
|
|
290
|
+
try {
|
|
291
|
+
// 尝试解析JSON
|
|
292
|
+
const jsonData = JSON.parse(potentialJson);
|
|
293
|
+
// 处理JSON,但保持原始结构,只转换链接
|
|
294
|
+
const processedJson = processJsonStructure(jsonData);
|
|
295
|
+
result += processedJson;
|
|
296
|
+
} catch (e) {
|
|
297
|
+
result += parseSimpleText(potentialJson);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
lastIndex = match.index + match[0].length;
|
|
301
|
+
}
|
|
302
|
+
// 添加最后一部分文本(如果有)
|
|
303
|
+
if (lastIndex < text.length) {
|
|
304
|
+
result += parseSimpleText(text.substring(lastIndex));
|
|
305
|
+
}
|
|
306
|
+
return result;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
export class MarkdownCleaner {
|
|
311
|
+
constructor(options = {}) {
|
|
312
|
+
this.options = {
|
|
313
|
+
removeZeroWidth: true, // 移除零宽字符
|
|
314
|
+
preserveEmoji: true, // 保留 emoji
|
|
315
|
+
preserveComplexScripts: false, // 保留复杂文字(阿拉伯语等)
|
|
316
|
+
normalizeWhitespace: true, // 标准化空白字符
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
clean(markdown) {
|
|
321
|
+
let text = markdown;
|
|
322
|
+
|
|
323
|
+
// 1. 处理 emoji(如果需要保留)
|
|
324
|
+
if (this.options.preserveEmoji) {
|
|
325
|
+
text = this.protectEmojis(text);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// 2. 移除有害的零宽字符
|
|
329
|
+
if (this.options.removeZeroWidth) {
|
|
330
|
+
if (this.options.preserveComplexScripts) {
|
|
331
|
+
// 只移除最常见的问题字符
|
|
332
|
+
text = text.replace(/[\u200B\uFEFF]/g, '');
|
|
333
|
+
} else {
|
|
334
|
+
// 移除所有零宽字符(除了 emoji 中的)
|
|
335
|
+
text = text.replace(/[\u200B-\u200D\uFEFF]/g, '');
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// 3. 标准化空白字符
|
|
340
|
+
// if (this.options.normalizeWhitespace) {
|
|
341
|
+
// text = text
|
|
342
|
+
// .replace(/\u00A0/g, ' ') // 非断行空格 -> 普通空格
|
|
343
|
+
// .replace(/\t/g, ' ') // Tab -> 4 空格
|
|
344
|
+
// .replace(/ +\n/g, '\n') // 删除行尾空格
|
|
345
|
+
// .replace(/\n{3,}/g, '\n\n'); // 最多保留两个连续换行
|
|
346
|
+
// }
|
|
347
|
+
|
|
348
|
+
// 4. 恢复 emoji
|
|
349
|
+
if (this.options.preserveEmoji) {
|
|
350
|
+
text = this.restoreEmojis(text);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
return text;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
protectEmojis(text) {
|
|
357
|
+
this.emojiStore = [];
|
|
358
|
+
return text.replace(
|
|
359
|
+
/([\u{1F000}-\u{1F9FF}\u{2600}-\u{26FF}][\u200D\u{1F000}-\u{1F9FF}\u{2600}-\u{26FF}\u{FE0F}]*)/gu,
|
|
360
|
+
(match) => {
|
|
361
|
+
this.emojiStore.push(match);
|
|
362
|
+
return `__EMOJI_PLACEHOLDER_${this.emojiStore.length - 1}__`;
|
|
363
|
+
}
|
|
364
|
+
);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
restoreEmojis(text) {
|
|
368
|
+
return text.replace(/__EMOJI_PLACEHOLDER_(\d+)__/g, (_, index) => {
|
|
369
|
+
return this.emojiStore[parseInt(index)] || '';
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
}
|