|
|
@@ -15,7 +15,6 @@
|
|
|
<script setup>
|
|
|
import {
|
|
|
ref,
|
|
|
- computed,
|
|
|
watch
|
|
|
} from 'vue'
|
|
|
import MarkdownIt from './lib/markdown-it.min.js'
|
|
|
@@ -68,17 +67,14 @@
|
|
|
if (clearLinkTmpTimeout.value) {
|
|
|
clearTimeout(clearLinkTmpTimeout.value);
|
|
|
}
|
|
|
- // 提取单独的链接
|
|
|
- let matches = parsedContent.value.matchAll(linkRegex);
|
|
|
- if (matches.length > 0) {
|
|
|
- for (const match of matches) {
|
|
|
- console.log(match);
|
|
|
- // 存储链接信息
|
|
|
- linkMaps.value.push({
|
|
|
- text: match[2],
|
|
|
- href: match[1].replace(/&/g, "&")
|
|
|
- });
|
|
|
- }
|
|
|
+ // 提取单独的链接(使用 exec 循环代替 matchAll,兼容小程序环境)
|
|
|
+ const linkRegex2 = /<a[^>]+href="([^"]+)"[^>]*>(.*?)<\/a>/gi;
|
|
|
+ let match;
|
|
|
+ while ((match = linkRegex2.exec(parsedContent.value)) !== null) {
|
|
|
+ linkMaps.value.push({
|
|
|
+ text: match[2],
|
|
|
+ href: match[1].replace(/&/g, "&")
|
|
|
+ });
|
|
|
}
|
|
|
clearLinkTmpTimeout.value = setTimeout(() => {
|
|
|
linkTmp.value = '';
|
|
|
@@ -160,12 +156,43 @@
|
|
|
} else {
|
|
|
htmlString = markdown.render(value)
|
|
|
}
|
|
|
- // 解决小程序表格边框型失效问题
|
|
|
- htmlString = htmlString.replace(/<table/g, `<table class="table"`)
|
|
|
- htmlString = htmlString.replace(/<tr/g, `<tr class="tr"`)
|
|
|
- htmlString = htmlString.replace(/<th>/g, `<th class="th">`)
|
|
|
- htmlString = htmlString.replace(/<td/g, `<td class="td"`)
|
|
|
- htmlString = htmlString.replace(/<hr>|<hr\/>|<hr \/>/g, `<hr class="hr">`)
|
|
|
+
|
|
|
+ // 小程序 rich-text 不继承外部CSS,必须使用内联样式
|
|
|
+ // 表格样式
|
|
|
+ htmlString = htmlString.replace(/<table>/g, `<table style="border-collapse:collapse;width:100%;margin:0.8em 0;border:1px solid #e5e5e5;">`)
|
|
|
+ htmlString = htmlString.replace(/<tr>/g, `<tr style="border-top:1px solid #e5e5e5;">`)
|
|
|
+ htmlString = htmlString.replace(/<th>/g, `<th style="padding:6px 13px;border:1px solid #e5e5e5;font-weight:600;background-color:#f5f5f5;">`)
|
|
|
+ htmlString = htmlString.replace(/<td>/g, `<td style="padding:6px 13px;border:1px solid #e5e5e5;">`)
|
|
|
+ htmlString = htmlString.replace(/<hr>|<hr\/>|<hr \/>/g, `<hr style="margin:1em 0;border:0;border-top:1px solid #e5e5e5;">`)
|
|
|
+
|
|
|
+ // 列表样式
|
|
|
+ htmlString = htmlString.replace(/<ul>/g, `<ul style="padding-left:20px;margin:0.5em 0;list-style-type:disc;">`)
|
|
|
+ htmlString = htmlString.replace(/<ol>/g, `<ol style="padding-left:20px;margin:0.5em 0;list-style-type:decimal;">`)
|
|
|
+ htmlString = htmlString.replace(/<li>/g, `<li style="line-height:1.6;margin-bottom:0.2em;">`)
|
|
|
+
|
|
|
+ // 标题样式
|
|
|
+ htmlString = htmlString.replace(/<h1>/g, `<h1 style="font-size:1.8em;margin:1em 0 0.5em;font-weight:bold;line-height:1.3;">`)
|
|
|
+ htmlString = htmlString.replace(/<h2>/g, `<h2 style="font-size:1.5em;margin:1em 0 0.5em;font-weight:bold;line-height:1.3;">`)
|
|
|
+ htmlString = htmlString.replace(/<h3>/g, `<h3 style="font-size:1.25em;margin:0.8em 0 0.4em;font-weight:bold;line-height:1.3;">`)
|
|
|
+ htmlString = htmlString.replace(/<h4>/g, `<h4 style="font-size:1.1em;margin:0.8em 0 0.4em;font-weight:bold;line-height:1.3;">`)
|
|
|
+ htmlString = htmlString.replace(/<h5>/g, `<h5 style="font-size:1em;margin:0.6em 0 0.3em;font-weight:bold;line-height:1.3;">`)
|
|
|
+ htmlString = htmlString.replace(/<h6>/g, `<h6 style="font-size:0.9em;margin:0.6em 0 0.3em;font-weight:bold;line-height:1.3;">`)
|
|
|
+
|
|
|
+ // 段落样式
|
|
|
+ htmlString = htmlString.replace(/<p>/g, `<p style="margin:0.5em 0;line-height:1.6;">`)
|
|
|
+
|
|
|
+ // 引用块样式
|
|
|
+ htmlString = htmlString.replace(/<blockquote>/g, `<blockquote style="padding:10px 15px;margin:0.8em 0;border-left:4px solid #ddd;color:#666;background:#f9f9f9;">`)
|
|
|
+
|
|
|
+ // 行内代码样式
|
|
|
+ htmlString = htmlString.replace(/<code>(?![\s\S]*<\/code>[\s\S]*<code>)/g, `<code style="padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:3px;font-family:monospace;">`)
|
|
|
+
|
|
|
+ // 链接样式
|
|
|
+ htmlString = htmlString.replace(/<a /g, `<a style="color:#3498db;text-decoration:underline;" `)
|
|
|
+
|
|
|
+ // 强调样式
|
|
|
+ htmlString = htmlString.replace(/<strong>/g, `<strong style="font-weight:bold;">`)
|
|
|
+ htmlString = htmlString.replace(/<em>/g, `<em style="font-style:italic;">`)
|
|
|
|
|
|
// #ifndef APP-NVUE
|
|
|
return htmlString
|
|
|
@@ -243,430 +270,18 @@
|
|
|
});
|
|
|
</script>
|
|
|
|
|
|
-<style lang="scss" scoped>
|
|
|
+<style lang="scss">
|
|
|
+ /* 小程序 rich-text 不继承外部CSS,内部元素样式通过内联方式在 parseNodes 中处理 */
|
|
|
+ /* 此处仅保留容器样式和非 rich-text 内的元素样式 */
|
|
|
.ua__markdown {
|
|
|
font-size: 14px;
|
|
|
- line-height: 1.5;
|
|
|
+ line-height: 1.6;
|
|
|
word-break: break-all;
|
|
|
-
|
|
|
- h1,
|
|
|
- h2,
|
|
|
- h3,
|
|
|
- h4,
|
|
|
- h5,
|
|
|
- h6 {
|
|
|
- font-family: inherit;
|
|
|
- font-weight: 500;
|
|
|
- line-height: 1.1;
|
|
|
- color: inherit;
|
|
|
- }
|
|
|
-
|
|
|
- h1,
|
|
|
- h2,
|
|
|
- h3 {
|
|
|
- margin-top: 20px;
|
|
|
- margin-bottom: 10px
|
|
|
- }
|
|
|
-
|
|
|
- h4,
|
|
|
- h5,
|
|
|
- h6 {
|
|
|
- margin-top: 10px;
|
|
|
- margin-bottom: 10px
|
|
|
- }
|
|
|
-
|
|
|
- .h1,
|
|
|
- h1 {
|
|
|
- font-size: 36px
|
|
|
- }
|
|
|
-
|
|
|
- .h2,
|
|
|
- h2 {
|
|
|
- font-size: 30px
|
|
|
- }
|
|
|
-
|
|
|
- .h3,
|
|
|
- h3 {
|
|
|
- font-size: 24px
|
|
|
- }
|
|
|
-
|
|
|
- .h4,
|
|
|
- h4 {
|
|
|
- font-size: 18px
|
|
|
- }
|
|
|
-
|
|
|
- .h5,
|
|
|
- h5 {
|
|
|
- font-size: 14px
|
|
|
- }
|
|
|
-
|
|
|
- .h6,
|
|
|
- h6 {
|
|
|
- font-size: 12px
|
|
|
- }
|
|
|
-
|
|
|
- a {
|
|
|
- background-color: transparent;
|
|
|
- color: #2196f3;
|
|
|
- text-decoration: none;
|
|
|
- /* 添加点击效果样式 */
|
|
|
- cursor: pointer;
|
|
|
- }
|
|
|
-
|
|
|
- /* 鼠标悬停时的样式 */
|
|
|
- a:hover {
|
|
|
- text-decoration: underline;
|
|
|
- }
|
|
|
-
|
|
|
- hr,
|
|
|
- ::v-deep .hr {
|
|
|
- margin-top: 20px;
|
|
|
- margin-bottom: 20px;
|
|
|
- border: 0;
|
|
|
- border-top: 1px solid #e5e5e5;
|
|
|
- }
|
|
|
-
|
|
|
- img {
|
|
|
- max-width: 35%;
|
|
|
- }
|
|
|
-
|
|
|
- p {
|
|
|
- margin: 0 0 10px
|
|
|
- }
|
|
|
-
|
|
|
- em {
|
|
|
- font-style: italic;
|
|
|
- font-weight: inherit;
|
|
|
- }
|
|
|
-
|
|
|
- ol,
|
|
|
- ul {
|
|
|
- margin-top: 0;
|
|
|
- margin-bottom: 10px;
|
|
|
- padding-left: 40px;
|
|
|
- }
|
|
|
-
|
|
|
- ol ol,
|
|
|
- ol ul,
|
|
|
- ul ol,
|
|
|
- ul ul {
|
|
|
- margin-bottom: 0;
|
|
|
- }
|
|
|
-
|
|
|
- ol ol,
|
|
|
- ul ol {
|
|
|
- list-style-type: lower-roman;
|
|
|
- }
|
|
|
-
|
|
|
- ol ol ol,
|
|
|
- ul ul ol {
|
|
|
- list-style-type: lower-alpha;
|
|
|
- }
|
|
|
-
|
|
|
- dl {
|
|
|
- margin-top: 0;
|
|
|
- margin-bottom: 20px;
|
|
|
- }
|
|
|
-
|
|
|
- dt {
|
|
|
- font-weight: 600;
|
|
|
- }
|
|
|
-
|
|
|
- dt,
|
|
|
- dd {
|
|
|
- line-height: 1.4;
|
|
|
- }
|
|
|
-
|
|
|
- .task-list-item {
|
|
|
- list-style-type: none;
|
|
|
- }
|
|
|
-
|
|
|
- .task-list-item input {
|
|
|
- margin: 0 .2em .25em -1.6em;
|
|
|
- vertical-align: middle;
|
|
|
- }
|
|
|
-
|
|
|
- pre {
|
|
|
- position: relative;
|
|
|
- z-index: 11;
|
|
|
- }
|
|
|
-
|
|
|
- code,
|
|
|
- kbd,
|
|
|
- pre,
|
|
|
- samp {
|
|
|
- font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
|
|
|
- }
|
|
|
-
|
|
|
- code:not(.hljs) {
|
|
|
- padding: 2px 4px;
|
|
|
- font-size: 90%;
|
|
|
- color: #c7254e;
|
|
|
- background-color: #ffe7ee;
|
|
|
- border-radius: 4px;
|
|
|
- }
|
|
|
-
|
|
|
- code:empty {
|
|
|
- display: none;
|
|
|
- }
|
|
|
-
|
|
|
- pre code.hljs {
|
|
|
- color: var(--vg__text-1);
|
|
|
- border-radius: 16px;
|
|
|
- background: var(--vg__bg-1);
|
|
|
- font-size: 12px;
|
|
|
- }
|
|
|
-
|
|
|
- .markdown-wrap {
|
|
|
- font-size: 12px;
|
|
|
- margin-bottom: 10px;
|
|
|
- }
|
|
|
-
|
|
|
- pre.code-block-wrapper {
|
|
|
- background: #2b2b2b;
|
|
|
- color: #f8f8f2;
|
|
|
- border-radius: 4px;
|
|
|
- overflow-x: auto;
|
|
|
- padding: 1em;
|
|
|
- position: relative;
|
|
|
- }
|
|
|
-
|
|
|
- pre.code-block-wrapper code {
|
|
|
- padding: auto;
|
|
|
- font-size: inherit;
|
|
|
- color: inherit;
|
|
|
- background-color: inherit;
|
|
|
- border-radius: 0;
|
|
|
- }
|
|
|
-
|
|
|
- .code-block-header__copy {
|
|
|
- font-size: 16px;
|
|
|
- margin-left: 5px;
|
|
|
- }
|
|
|
-
|
|
|
- abbr[data-original-title],
|
|
|
- abbr[title] {
|
|
|
- cursor: help;
|
|
|
- border-bottom: 1px dotted #777;
|
|
|
- }
|
|
|
-
|
|
|
- blockquote {
|
|
|
- padding: 10px 20px;
|
|
|
- margin: 0 0 20px;
|
|
|
- font-size: 17.5px;
|
|
|
- border-left: 5px solid #e5e5e5;
|
|
|
- }
|
|
|
-
|
|
|
- blockquote ol:last-child,
|
|
|
- blockquote p:last-child,
|
|
|
- blockquote ul:last-child {
|
|
|
- margin-bottom: 0
|
|
|
- }
|
|
|
-
|
|
|
- blockquote .small,
|
|
|
- blockquote footer,
|
|
|
- blockquote small {
|
|
|
- display: block;
|
|
|
- font-size: 80%;
|
|
|
- line-height: 1.42857143;
|
|
|
- color: #777
|
|
|
- }
|
|
|
-
|
|
|
- blockquote .small:before,
|
|
|
- blockquote footer:before,
|
|
|
- blockquote small:before {
|
|
|
- content: '\2014 \00A0'
|
|
|
- }
|
|
|
-
|
|
|
- .blockquote-reverse,
|
|
|
- blockquote.pull-right {
|
|
|
- padding-right: 15px;
|
|
|
- padding-left: 0;
|
|
|
- text-align: right;
|
|
|
- border-right: 5px solid #eee;
|
|
|
- border-left: 0
|
|
|
- }
|
|
|
-
|
|
|
- .blockquote-reverse .small:before,
|
|
|
- .blockquote-reverse footer:before,
|
|
|
- .blockquote-reverse small:before,
|
|
|
- blockquote.pull-right .small:before,
|
|
|
- blockquote.pull-right footer:before,
|
|
|
- blockquote.pull-right small:before {
|
|
|
- content: ''
|
|
|
- }
|
|
|
-
|
|
|
- .blockquote-reverse .small:after,
|
|
|
- .blockquote-reverse footer:after,
|
|
|
- .blockquote-reverse small:after,
|
|
|
- blockquote.pull-right .small:after,
|
|
|
- blockquote.pull-right footer:after,
|
|
|
- blockquote.pull-right small:after {
|
|
|
- content: '\00A0 \2014'
|
|
|
- }
|
|
|
-
|
|
|
- .footnotes {
|
|
|
- -moz-column-count: 2;
|
|
|
- -webkit-column-count: 2;
|
|
|
- column-count: 2
|
|
|
- }
|
|
|
-
|
|
|
- .footnotes-list {
|
|
|
- padding-left: 2em
|
|
|
- }
|
|
|
-
|
|
|
- table,
|
|
|
- ::v-deep .table {
|
|
|
- border-spacing: 0;
|
|
|
- border-collapse: collapse;
|
|
|
- width: 100%;
|
|
|
- max-width: 65em;
|
|
|
- overflow: auto;
|
|
|
- margin-top: 0;
|
|
|
- margin-bottom: 16px;
|
|
|
- }
|
|
|
-
|
|
|
- table tr,
|
|
|
- ::v-deep .table .tr {
|
|
|
- border-top: 1px solid #e5e5e5;
|
|
|
- }
|
|
|
-
|
|
|
- table th,
|
|
|
- table td,
|
|
|
- ::v-deep .table .th,
|
|
|
- ::v-deep .table .td {
|
|
|
- padding: 6px 13px;
|
|
|
- border: 1px solid #e5e5e5;
|
|
|
- }
|
|
|
-
|
|
|
- table th,
|
|
|
- ::v-deep .table .th {
|
|
|
- font-weight: 600;
|
|
|
- background-color: #eee;
|
|
|
- }
|
|
|
-
|
|
|
- .hljs[class*=language-]:before {
|
|
|
- position: absolute;
|
|
|
- z-index: 3;
|
|
|
- top: .8em;
|
|
|
- right: 1em;
|
|
|
- font-size: .8em;
|
|
|
- color: #999;
|
|
|
- }
|
|
|
-
|
|
|
- .hljs[class~=language-js]:before {
|
|
|
- content: "js"
|
|
|
- }
|
|
|
-
|
|
|
- .hljs[class~=language-ts]:before {
|
|
|
- content: "ts"
|
|
|
- }
|
|
|
-
|
|
|
- .hljs[class~=language-html]:before {
|
|
|
- content: "html"
|
|
|
- }
|
|
|
-
|
|
|
- .hljs[class~=language-md]:before {
|
|
|
- content: "md"
|
|
|
- }
|
|
|
-
|
|
|
- .hljs[class~=language-vue]:before {
|
|
|
- content: "vue"
|
|
|
- }
|
|
|
-
|
|
|
- .hljs[class~=language-css]:before {
|
|
|
- content: "css"
|
|
|
- }
|
|
|
-
|
|
|
- .hljs[class~=language-sass]:before {
|
|
|
- content: "sass"
|
|
|
- }
|
|
|
-
|
|
|
- .hljs[class~=language-scss]:before {
|
|
|
- content: "scss"
|
|
|
- }
|
|
|
-
|
|
|
- .hljs[class~=language-less]:before {
|
|
|
- content: "less"
|
|
|
- }
|
|
|
-
|
|
|
- .hljs[class~=language-stylus]:before {
|
|
|
- content: "stylus"
|
|
|
- }
|
|
|
-
|
|
|
- .hljs[class~=language-go]:before {
|
|
|
- content: "go"
|
|
|
- }
|
|
|
-
|
|
|
- .hljs[class~=language-java]:before {
|
|
|
- content: "java"
|
|
|
- }
|
|
|
-
|
|
|
- .hljs[class~=language-c]:before {
|
|
|
- content: "c"
|
|
|
- }
|
|
|
-
|
|
|
- .hljs[class~=language-sh]:before {
|
|
|
- content: "sh"
|
|
|
- }
|
|
|
-
|
|
|
- .hljs[class~=language-yaml]:before {
|
|
|
- content: "yaml"
|
|
|
- }
|
|
|
-
|
|
|
- .hljs[class~=language-py]:before {
|
|
|
- content: "py"
|
|
|
- }
|
|
|
-
|
|
|
- .hljs[class~=language-docker]:before {
|
|
|
- content: "docker"
|
|
|
- }
|
|
|
-
|
|
|
- .hljs[class~=language-dockerfile]:before {
|
|
|
- content: "dockerfile"
|
|
|
- }
|
|
|
-
|
|
|
- .hljs[class~=language-makefile]:before {
|
|
|
- content: "makefile"
|
|
|
- }
|
|
|
-
|
|
|
- .hljs[class~=language-javascript]:before {
|
|
|
- content: "js"
|
|
|
- }
|
|
|
-
|
|
|
- .hljs[class~=language-typescript]:before {
|
|
|
- content: "ts"
|
|
|
- }
|
|
|
-
|
|
|
- .hljs[class~=language-markup]:before {
|
|
|
- content: "html"
|
|
|
- }
|
|
|
-
|
|
|
- .hljs[class~=language-markdown]:before {
|
|
|
- content: "md"
|
|
|
- }
|
|
|
-
|
|
|
- .hljs[class~=language-json]:before {
|
|
|
- content: "json"
|
|
|
- }
|
|
|
-
|
|
|
- .hljs[class~=language-ruby]:before {
|
|
|
- content: "rb"
|
|
|
- }
|
|
|
-
|
|
|
- .hljs[class~=language-python]:before {
|
|
|
- content: "py"
|
|
|
- }
|
|
|
-
|
|
|
- .hljs[class~=language-bash]:before {
|
|
|
- content: "sh"
|
|
|
- }
|
|
|
-
|
|
|
- .hljs[class~=language-php]:before {
|
|
|
- content: "php"
|
|
|
- }
|
|
|
+ color: #333;
|
|
|
|
|
|
.links {
|
|
|
+ margin-top: 16rpx;
|
|
|
+
|
|
|
.links-title {
|
|
|
color: #101333;
|
|
|
margin-bottom: 8rpx;
|