From 87890a10ed786f85677f83336771aa97dcb252d7 Mon Sep 17 00:00:00 2001
From: weicw
Date: Sat, 8 Aug 2026 06:48:09 +0800
Subject: [PATCH] =?UTF-8?q?feat(ai-house):=20=E6=94=AF=E6=8C=81=20Markdown?=
=?UTF-8?q?=20=E5=B9=B6=E4=BC=98=E5=8C=96=E6=89=BE=E6=88=BF=E4=BA=A4?=
=?UTF-8?q?=E4=BA=92?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
config.js | 4 +-
pages/ai-house/index.vue | 219 ++----------------
tests/check-ai-house-location-response.js | 64 ++---
tests/check-ai-house-markdown.js | 24 ++
tests/check-ai-house-quick-questions.js | 24 ++
.../components/mp-html/markdown/index.js | 34 +++
.../components/mp-html/markdown/marked.min.js | 6 +
.../mp-html/components/mp-html/mp-html.vue | 4 +-
8 files changed, 138 insertions(+), 241 deletions(-)
create mode 100644 tests/check-ai-house-markdown.js
create mode 100644 tests/check-ai-house-quick-questions.js
create mode 100644 uni_modules/mp-html/components/mp-html/markdown/index.js
create mode 100644 uni_modules/mp-html/components/mp-html/markdown/marked.min.js
diff --git a/config.js b/config.js
index b8ca12b..4d253f4 100755
--- a/config.js
+++ b/config.js
@@ -10,8 +10,8 @@ module.exports = {
// 生产环境
serverUrl: 'https://server.websoft.top/api',
- // apiUrl: 'http://127.0.0.1:9200/api',
- apiUrl: 'https://cms-api.websoft.top/api',
+ apiUrl: 'http://127.0.0.1:9200/api',
+ // apiUrl: 'https://cms-api.websoft.top/api',
socketUrl: 'wss://server.websoft.top',
fileUrl: 'https://file.wsdns.cn',
diff --git a/pages/ai-house/index.vue b/pages/ai-house/index.vue
index 0cfa67c..f75ddc0 100644
--- a/pages/ai-house/index.vue
+++ b/pages/ai-house/index.vue
@@ -2,14 +2,6 @@
AI找房助手
-
-
- 清空
-
@@ -41,7 +33,7 @@
>
- {{ message.content || '您好,请填写您的找房需求' }}
+
填写楼盘、面积和预算,我来帮您筛选合适的房源。
楼盘
@@ -118,7 +110,12 @@
- {{ message.content }}
+
+ {{ message.content }}
@@ -132,25 +129,6 @@
-
- {{ message.content }}
-
- {{ item.locationName }}
-
- {{ [item.city, item.parentLocationName].filter(Boolean).join(' / ') }}
-
-
- {{ tag }}
-
-
- {{ knowledge.title }}
-
- {{ locationKnowledgeFacts(knowledge) }}
-
- {{ knowledge.content }}
-
-
-
@@ -218,6 +196,14 @@
>
{{ item.label }}
+
+
+ 清空
+
{
- if (!item || typeof item !== 'object') {
- return null
- }
- return {
- ...item,
- locationId: item.locationId ?? item.location_id ?? `location-${index}`,
- locationName: item.locationName ?? item.location_name ?? item.name ?? '地点资料',
- parentLocationName: item.parentLocationName ?? item.parent_location_name ?? '',
- tags: this.normalizeLocationTags(item.tags),
- knowledgeItems: this.normalizeLocationKnowledgeItems(
- item.knowledgeItems !== undefined ? item.knowledgeItems : item.knowledge_items
- )
- }
- })
- .filter(Boolean)
- },
- normalizeStructuredArray(value) {
- if (Array.isArray(value)) {
- return value
- }
- if (typeof value === 'string') {
- try {
- const parsed = JSON.parse(value)
- return Array.isArray(parsed) ? parsed : (parsed && typeof parsed === 'object' ? [parsed] : [])
- } catch (error) {
- return []
- }
- }
- return value && typeof value === 'object' ? [value] : []
- },
- normalizeLocationTags(value) {
- if (Array.isArray(value)) {
- return value.filter(Boolean).map((item) => String(item))
- }
- if (typeof value === 'string') {
- const tags = this.normalizeStructuredArray(value)
- if (tags.length) {
- return tags.filter(Boolean).map((item) => String(item))
- }
- return value.split(/[,,]/).map((item) => item.trim()).filter(Boolean)
- }
- return []
- },
- normalizeLocationKnowledgeItems(value) {
- return this.normalizeStructuredArray(value)
- .map((item, index) => {
- if (!item || typeof item !== 'object') {
- return null
- }
- return {
- ...item,
- topic: item.topic || `knowledge-${index}`,
- name: item.name || '',
- title: item.title || '补充信息',
- propertyCompany: item.propertyCompany ?? item.property_company,
- propertyFees: item.propertyFees ?? item.property_fees,
- waterBillingType: item.waterBillingType ?? item.water_billing_type,
- waterUnitPrice: item.waterUnitPrice ?? item.water_unit_price,
- electricityBillingType: item.electricityBillingType ?? item.electricity_billing_type,
- electricityUnitPrice: item.electricityUnitPrice ?? item.electricity_unit_price,
- parkingAvailable: this.normalizeBoolean(item.parkingAvailable ?? item.parking_available),
- parkingFee: item.parkingFee ?? item.parking_fee
- }
- })
- .filter(Boolean)
- },
- normalizeBoolean(value) {
- if (value === 'true' || value === 1 || value === '1') {
- return true
- }
- if (value === 'false' || value === 0 || value === '0') {
- return false
- }
- return value
- },
connectWebSocket() {
if (!this.loginUserId) {
return
@@ -847,17 +755,6 @@
})
)
}
- const locationCards = this.normalizeLocationCards(
- data.locationCards !== undefined ? data.locationCards : data.location_cards
- )
- if (locationCards.length) {
- this.messages.push(
- this.createMessage('ai', 'location', {
- content: '以下地点资料来自已维护的知识库:',
- locationCards
- })
- )
- }
if (data.showContactForm) {
this.messages.push(this.createMessage('ai', 'messageForm'))
}
@@ -872,19 +769,6 @@
url: `/sub_pages/house/detail?houseId=${item.houseId}`
})
},
- locationKnowledgeFacts(item) {
- const facts = []
- if (item.propertyCompany) facts.push(`物业公司:${item.propertyCompany}`)
- if (item.propertyFees !== null && item.propertyFees !== undefined) facts.push(`物业费:${item.propertyFees}`)
- if (item.waterBillingType) facts.push(`水费:${item.waterBillingType}`)
- if (item.waterUnitPrice !== null && item.waterUnitPrice !== undefined) facts.push(`水费单价:${item.waterUnitPrice}`)
- if (item.electricityBillingType) facts.push(`电费:${item.electricityBillingType}`)
- if (item.electricityUnitPrice !== null && item.electricityUnitPrice !== undefined) facts.push(`电费单价:${item.electricityUnitPrice}`)
- if (item.parkingAvailable === true) facts.push('停车:可用')
- if (item.parkingAvailable === false) facts.push('停车:不可用')
- if (item.parkingFee) facts.push(`停车费用:${item.parkingFee}`)
- return facts.join(';')
- },
scrollToBottom() {
this.$nextTick(() => {
setTimeout(() => {
@@ -939,6 +823,10 @@
opacity: 0.45;
}
+ .clear-session-btn-inline {
+ margin-left: auto;
+ }
+
.message-scroll {
padding: 24rpx 24rpx 0;
box-sizing: border-box;
@@ -1055,69 +943,6 @@
justify-content: flex-start;
}
- .location-message {
- padding: 20rpx;
- border-radius: 24rpx;
- background: #f8fbff;
- border: 1rpx solid #e6eefc;
- }
-
- .location-card {
- margin-top: 16rpx;
- padding: 20rpx;
- border-radius: 16rpx;
- background: #ffffff;
- border: 1rpx solid #e9edf5;
- }
-
- .location-card-title {
- font-size: 30rpx;
- font-weight: 600;
- color: #1f2937;
- }
-
- .location-card-path {
- margin-top: 8rpx;
- font-size: 23rpx;
- color: #667085;
- }
-
- .location-tag-row {
- display: flex;
- flex-wrap: wrap;
- gap: 8rpx;
- margin-top: 14rpx;
- }
-
- .location-tag {
- padding: 4rpx 12rpx;
- border-radius: 8rpx;
- background: #eef6ff;
- color: #2f5f9f;
- font-size: 21rpx;
- }
-
- .location-knowledge-item {
- margin-top: 16rpx;
- padding-top: 16rpx;
- border-top: 1rpx solid #eef1f6;
- }
-
- .location-knowledge-title {
- font-size: 26rpx;
- font-weight: 600;
- color: #344054;
- }
-
- .location-knowledge-facts,
- .location-knowledge-content {
- margin-top: 8rpx;
- font-size: 24rpx;
- line-height: 1.55;
- color: #667085;
- word-break: break-all;
- }
-
.faq-message {
padding: 8rpx 0 0;
}
diff --git a/tests/check-ai-house-location-response.js b/tests/check-ai-house-location-response.js
index 9fa5991..22eb9f8 100644
--- a/tests/check-ai-house-location-response.js
+++ b/tests/check-ai-house-location-response.js
@@ -29,47 +29,29 @@ function createPageVm() {
return vm
}
-function receiveLocationResponse(fieldName, locationCards) {
- const vm = createPageVm()
- const response = {
- type: 'house_ai_result',
- answer: '已按已维护的地点资料筛选,以下地点可供参考。'
- }
- response[fieldName] = locationCards
- vm.handleSocketMessage(JSON.stringify(response))
- return vm.messages.find((message) => message.type === 'location')
-}
-
-const locationCard = {
- location_id: 101,
- city: '南宁市',
- location_name: '五象航洋城',
- parent_location_name: '五象新区',
- tags: ['停车方便'],
- knowledge_items: [{
- topic: 'parking',
- title: '停车',
- parking_available: true,
- parking_fee: '月租 300 元'
+const vm = createPageVm()
+vm.handleSocketMessage(JSON.stringify({
+ type: 'house_ai_result',
+ answer: '航洋城附近通勤方便,停车以现场政策为准。',
+ locationCards: [{
+ locationId: 101,
+ locationName: '航洋城',
+ knowledgeItems: [{ title: '停车' }]
+ }],
+ houses: [{
+ houseId: 201,
+ houseTitle: '航洋城附近两居室',
+ files: []
}]
-}
+}))
-const locationMessage = receiveLocationResponse('location_cards', JSON.stringify([locationCard]))
+assert.equal(vm.messages.filter((message) => message.type === 'location').length, 0,
+ '地点资料不应在小程序中创建卡片消息')
+assert.equal(vm.messages.filter((message) => message.type === 'text').length, 1,
+ '地点资料应由 AI 直接组织为文本回答')
+assert.equal(vm.messages.find((message) => message.type === 'text').content,
+ '航洋城附近通勤方便,停车以现场政策为准。')
+assert.equal(vm.messages.filter((message) => message.type === 'list').length, 1,
+ '房源结果仍应创建房源卡片消息')
-assert.ok(locationMessage, '地点咨询回包应创建地点卡片消息')
-assert.ok(Array.isArray(locationMessage.locationCards), '地点卡片应转换为数组')
-assert.equal(locationMessage.locationCards[0].locationId, 101)
-assert.equal(locationMessage.locationCards[0].locationName, '五象航洋城')
-assert.equal(locationMessage.locationCards[0].knowledgeItems[0].parkingAvailable, true)
-
-const backendLocationMessage = receiveLocationResponse('locationCards', [{
- locationId: 102,
- city: '南宁市',
- locationName: '会展航洋城',
- knowledgeItems: []
-}])
-
-assert.ok(backendLocationMessage, '后端驼峰地点卡片回包应保持兼容')
-assert.equal(backendLocationMessage.locationCards[0].locationName, '会展航洋城')
-
-console.log('地点咨询回包能够创建可渲染的地点卡片消息')
+console.log('地点资料仅由 AI 组织为文本,页面不渲染地点卡片')
diff --git a/tests/check-ai-house-markdown.js b/tests/check-ai-house-markdown.js
new file mode 100644
index 0000000..ed9afb4
--- /dev/null
+++ b/tests/check-ai-house-markdown.js
@@ -0,0 +1,24 @@
+const assert = require('node:assert/strict')
+const fs = require('node:fs')
+const path = require('node:path')
+
+const root = path.resolve(__dirname, '..')
+const pagePath = path.join(root, 'pages/ai-house/index.vue')
+const componentPath = path.join(root, 'uni_modules/mp-html/components/mp-html/mp-html.vue')
+const markdownPluginPath = path.join(root, 'uni_modules/mp-html/components/mp-html/markdown/index.js')
+
+const page = fs.readFileSync(pagePath, 'utf8')
+const component = fs.readFileSync(componentPath, 'utf8')
+
+assert.match(page, /v-if="message\.role === 'ai'"[\s\S]*:content="message\.content"[\s\S]*markdown/)
+assert.match(component, /markdown:\s*Boolean/)
+assert.match(component, /require\('\.\/markdown\/index\.js'\)/)
+
+const Markdown = require(markdownPluginPath)
+const html = new Markdown({ markdown: true }).onUpdate('# 标题\n\n**重点**\n\n- 房源 A')
+
+assert.match(html, /]*>标题<\/h1>/)
+assert.match(html, /重点<\/strong>/)
+assert.match(html, /房源 A<\/li>/)
+
+console.log('AI 找房 Markdown 渲染配置检查通过')
diff --git a/tests/check-ai-house-quick-questions.js b/tests/check-ai-house-quick-questions.js
new file mode 100644
index 0000000..a9f250d
--- /dev/null
+++ b/tests/check-ai-house-quick-questions.js
@@ -0,0 +1,24 @@
+const assert = require('node:assert/strict')
+const fs = require('node:fs')
+const path = require('node:path')
+
+const pagePath = path.resolve(__dirname, '../pages/ai-house/index.vue')
+const page = fs.readFileSync(pagePath, 'utf8')
+
+for (const label of ['面积和价格', '物业和水电', '空调和停车']) {
+ assert.match(page, new RegExp(`label: '${label}'`))
+}
+
+for (const question of [
+ '介绍一下所有楼盘的面积和价格。',
+ '介绍一下所有楼盘的物业费和水电收费情况。',
+ '介绍一下所有楼盘是否配备空调和停车位。'
+]) {
+ assert.ok(page.includes(`question: '${question}'`))
+}
+
+assert.ok(!page.includes('这套房的面积和价格是多少?'))
+assert.ok(!page.includes('这套房的物业费和水电怎么收费?'))
+assert.ok(!page.includes('这套房有空调和停车位吗?'))
+
+console.log('AI 找房全量楼盘快捷提问检查通过')
diff --git a/uni_modules/mp-html/components/mp-html/markdown/index.js b/uni_modules/mp-html/components/mp-html/markdown/index.js
new file mode 100644
index 0000000..4f5c5a2
--- /dev/null
+++ b/uni_modules/mp-html/components/mp-html/markdown/index.js
@@ -0,0 +1,34 @@
+/**
+ * @fileoverview markdown 插件
+ * Include marked (https://github.com/markedjs/marked)
+ * Include github-markdown-css (https://github.com/sindresorhus/github-markdown-css)
+ */
+const marked = require('./marked.min')
+let index = 0
+
+function Markdown (vm) {
+ this.vm = vm
+ vm._ids = {}
+}
+
+Markdown.prototype.onUpdate = function (content) {
+ if (this.vm.markdown) {
+ return marked(content)
+ }
+}
+
+Markdown.prototype.onParse = function (node, vm) {
+ if (vm.options.markdown) {
+ // 中文 id 需要转换,否则无法跳转
+ if (vm.options.useAnchor && node.attrs && /[\u4e00-\u9fa5]/.test(node.attrs.id)) {
+ const id = 't' + index++
+ this.vm._ids[node.attrs.id] = id
+ node.attrs.id = id
+ }
+ if (node.name === 'p' || node.name === 'table' || node.name === 'tr' || node.name === 'th' || node.name === 'td' || node.name === 'blockquote' || node.name === 'pre' || node.name === 'code') {
+ node.attrs.class = `md-${node.name} ${node.attrs.class || ''}`
+ }
+ }
+}
+
+module.exports = Markdown
diff --git a/uni_modules/mp-html/components/mp-html/markdown/marked.min.js b/uni_modules/mp-html/components/mp-html/markdown/marked.min.js
new file mode 100644
index 0000000..96bc7e9
--- /dev/null
+++ b/uni_modules/mp-html/components/mp-html/markdown/marked.min.js
@@ -0,0 +1,6 @@
+/*!
+ * marked - a markdown parser
+ * Copyright (c) 2011-2020, Christopher Jeffrey. (MIT Licensed)
+ * https://github.com/markedjs/marked
+ */
+!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).marked=t()}(this,function(){"use strict";function i(e,t){for(var n=0;ne.length)&&(t=e.length);for(var n=0,r=new Array(t);n=e.length?{done:!0}:{done:!1,value:e[r++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function n(e){return c[e]}var e,t=(function(t){function e(){return{baseUrl:null,breaks:!1,gfm:!0,headerIds:!0,headerPrefix:"",highlight:null,langPrefix:"language-",mangle:!0,pedantic:!1,renderer:null,sanitize:!1,sanitizer:null,silent:!1,smartLists:!1,smartypants:!1,tokenizer:null,walkTokens:null,xhtml:!1}}t.exports={defaults:e(),getDefaults:e,changeDefaults:function(e){t.exports.defaults=e}}}(e={exports:{}}),e.exports),r=(t.defaults,t.getDefaults,t.changeDefaults,/[&<>"']/),l=/[&<>"']/g,a=/[<>"']|&(?!#?\w+;)/,o=/[<>"']|&(?!#?\w+;)/g,c={"&":"&","<":"<",">":">",'"':""","'":"'"};var u=/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/gi;function h(e){return e.replace(u,function(e,t){return"colon"===(t=t.toLowerCase())?":":"#"===t.charAt(0)?"x"===t.charAt(1)?String.fromCharCode(parseInt(t.substring(2),16)):String.fromCharCode(+t.substring(1)):""})}var g=/(^|[^\[])\^/g;var f=/[^\w:]/g,d=/^$|^[a-z][a-z0-9+.-]*:|^[?#]/i;var k={},b=/^[^:]+:\/*[^/]*$/,m=/^([^:]+:)[\s\S]*$/,x=/^([^:]+:\/*[^/]*)[\s\S]*$/;function w(e,t){k[" "+e]||(b.test(e)?k[" "+e]=e+"/":k[" "+e]=v(e,"/",!0));var n=-1===(e=k[" "+e]).indexOf(":");return"//"===t.substring(0,2)?n?t:e.replace(m,"$1")+t:"/"===t.charAt(0)?n?t:e.replace(x,"$1")+t:e+t}function v(e,t,n){var r=e.length;if(0===r)return"";for(var i=0;it)n.splice(t);else for(;n.length>=1,e+=e;return n+e},q=t.defaults,O=v,C=R,U=_,j=T;function E(e,t,n){var r=t.href,i=t.title?U(t.title):null,t=e[1].replace(/\\([\[\]])/g,"$1");return"!"!==e[0].charAt(0)?{type:"link",raw:n,href:r,title:i,text:t}:{type:"image",raw:n,href:r,title:i,text:U(t)}}var D=function(){function e(e){this.options=e||q}var t=e.prototype;return t.space=function(e){e=this.rules.block.newline.exec(e);if(e)return 1=n.length?e.slice(n.length):e}).join("\n")}(n,t[3]||"");return{type:"code",raw:n,lang:t[2]&&t[2].trim(),text:e}}},t.heading=function(e){e=this.rules.block.heading.exec(e);if(e)return{type:"heading",raw:e[0],depth:e[1].length,text:e[2]}},t.nptable=function(e){e=this.rules.block.nptable.exec(e);if(e){var t={type:"table",header:C(e[1].replace(/^ *| *\| *$/g,"")),align:e[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:e[3]?e[3].replace(/\n$/,"").split("\n"):[],raw:e[0]};if(t.header.length===t.align.length){for(var n=t.align.length,r=0;r ?/gm,"");return{type:"blockquote",raw:t[0],text:e}}},t.list=function(e){e=this.rules.block.list.exec(e);if(e){for(var t,n,r,i,s,l=e[0],a=e[2],o=1g[0].length||3/i.test(e[0])&&(t=!1),!n&&/^<(pre|code|kbd|script)(\s|>)/i.test(e[0])?n=!0:n&&/^<\/(pre|code|kbd|script)(\s|>)/i.test(e[0])&&(n=!1),{type:this.options.sanitize?"text":"html",raw:e[0],inLink:t,inRawBlock:n,text:this.options.sanitize?this.options.sanitizer?this.options.sanitizer(e[0]):U(e[0]):e[0]}},t.link=function(e){var t=this.rules.inline.link.exec(e);if(t){e=j(t[2],"()");-1$/,"$1"))&&e.replace(this.rules.inline._escapes,"$1"),title:r&&r.replace(this.rules.inline._escapes,"$1")},t[0])}},t.reflink=function(e,t){if((n=this.rules.inline.reflink.exec(e))||(n=this.rules.inline.nolink.exec(e))){e=(n[2]||n[1]).replace(/\s+/g," ");if((e=t[e.toLowerCase()])&&e.href)return E(n,e,n[0]);var n=n[0].charAt(0);return{type:"text",raw:n,text:n}}},t.strong=function(e,t,n){void 0===n&&(n="");var r=this.rules.inline.strong.start.exec(e);if(r&&(!r[1]||r[1]&&(""===n||this.rules.inline.punctuation.exec(n)))){t=t.slice(-1*e.length);var i,s="**"===r[0]?this.rules.inline.strong.endAst:this.rules.inline.strong.endUnd;for(s.lastIndex=0;null!=(r=s.exec(t));)if(i=this.rules.inline.strong.middle.exec(t.slice(0,r.index+3)))return{type:"strong",raw:e.slice(0,i[0].length),text:e.slice(2,i[0].length-2)}}},t.em=function(e,t,n){void 0===n&&(n="");var r=this.rules.inline.em.start.exec(e);if(r&&(!r[1]||r[1]&&(""===n||this.rules.inline.punctuation.exec(n)))){t=t.slice(-1*e.length);var i,s="*"===r[0]?this.rules.inline.em.endAst:this.rules.inline.em.endUnd;for(s.lastIndex=0;null!=(r=s.exec(t));)if(i=this.rules.inline.em.middle.exec(t.slice(0,r.index+2)))return{type:"em",raw:e.slice(0,i[0].length),text:e.slice(1,i[0].length-1)}}},t.codespan=function(e){var t=this.rules.inline.code.exec(e);if(t){var n=t[2].replace(/\n/g," "),r=/[^ ]/.test(n),e=n.startsWith(" ")&&n.endsWith(" ");return r&&e&&(n=n.substring(1,n.length-1)),n=U(n,!0),{type:"codespan",raw:t[0],text:n}}},t.br=function(e){e=this.rules.inline.br.exec(e);if(e)return{type:"br",raw:e[0]}},t.del=function(e){e=this.rules.inline.del.exec(e);if(e)return{type:"del",raw:e[0],text:e[2]}},t.autolink=function(e,t){e=this.rules.inline.autolink.exec(e);if(e){var n,t="@"===e[2]?"mailto:"+(n=U(this.options.mangle?t(e[1]):e[1])):n=U(e[1]);return{type:"link",raw:e[0],text:n,href:t,tokens:[{type:"text",raw:n,text:n}]}}},t.url=function(e,t){var n,r,i,s;if(n=this.rules.inline.url.exec(e)){if("@"===n[2])i="mailto:"+(r=U(this.options.mangle?t(n[0]):n[0]));else{for(;s=n[0],n[0]=this.rules.inline._backpedal.exec(n[0])[0],s!==n[0];);r=U(n[0]),i="www."===n[1]?"http://"+r:r}return{type:"link",raw:n[0],text:r,href:i,tokens:[{type:"text",raw:r,text:r}]}}},t.inlineText=function(e,t,n){e=this.rules.inline.text.exec(e);if(e){n=t?this.options.sanitize?this.options.sanitizer?this.options.sanitizer(e[0]):U(e[0]):e[0]:U(this.options.smartypants?n(e[0]):e[0]);return{type:"text",raw:e[0],text:n}}},e}(),R=$,T=z,$=A,z={newline:/^\n+/,code:/^( {4}[^\n]+\n*)+/,fences:/^ {0,3}(`{3,}(?=[^`\n]*\n)|~{3,})([^\n]*)\n(?:|([\s\S]*?)\n)(?: {0,3}\1[~`]* *(?:\n+|$)|$)/,hr:/^ {0,3}((?:- *){3,}|(?:_ *){3,}|(?:\* *){3,})(?:\n+|$)/,heading:/^ {0,3}(#{1,6}) +([^\n]*?)(?: +#+)? *(?:\n+|$)/,blockquote:/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/,list:/^( {0,3})(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?! {0,3}bull )\n*|\s*$)/,html:"^ {0,3}(?:<(script|pre|style)[\\s>][\\s\\S]*?(?:\\1>[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>\\n*|$)|\\n*|$)|\\n*|$)|?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:\\n{2,}|$)|<(?!script|pre|style)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:\\n{2,}|$)|(?!script|pre|style)[a-z][\\w-]*\\s*>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:\\n{2,}|$))",def:/^ {0,3}\[(label)\]: *\n? *([^\s>]+)>?(?:(?: +\n? *| *\n *)(title))? *(?:\n+|$)/,nptable:R,table:R,lheading:/^([^\n]+)\n {0,3}(=+|-+) *(?:\n+|$)/,_paragraph:/^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html)[^\n]+)*)/,text:/^[^\n]+/,_label:/(?!\s*\])(?:\\[\[\]]|[^\[\]])+/,_title:/(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/};z.def=T(z.def).replace("label",z._label).replace("title",z._title).getRegex(),z.bullet=/(?:[*+-]|\d{1,9}[.)])/,z.item=/^( *)(bull) ?[^\n]*(?:\n(?! *bull ?)[^\n]*)*/,z.item=T(z.item,"gm").replace(/bull/g,z.bullet).getRegex(),z.listItemStart=T(/^( *)(bull)/).replace("bull",z.bullet).getRegex(),z.list=T(z.list).replace(/bull/g,z.bullet).replace("hr","\\n+(?=\\1?(?:(?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$))").replace("def","\\n+(?="+z.def.source+")").getRegex(),z._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",z._comment=/|$)/,z.html=T(z.html,"i").replace("comment",z._comment).replace("tag",z._tag).replace("attribute",/ +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(),z.paragraph=T(z._paragraph).replace("hr",z.hr).replace("heading"," {0,3}#{1,6} ").replace("|lheading","").replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html","?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|!--)").replace("tag",z._tag).getRegex(),z.blockquote=T(z.blockquote).replace("paragraph",z.paragraph).getRegex(),z.normal=$({},z),z.gfm=$({},z.normal,{nptable:"^ *([^|\\n ].*\\|.*)\\n {0,3}([-:]+ *\\|[-| :]*)(?:\\n((?:(?!\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)",table:"^ *\\|(.+)\\n {0,3}\\|?( *[-:]+[-| :]*)(?:\\n *((?:(?!\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)"}),z.gfm.nptable=T(z.gfm.nptable).replace("hr",z.hr).replace("heading"," {0,3}#{1,6} ").replace("blockquote"," {0,3}>").replace("code"," {4}[^\\n]").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html","?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|!--)").replace("tag",z._tag).getRegex(),z.gfm.table=T(z.gfm.table).replace("hr",z.hr).replace("heading"," {0,3}#{1,6} ").replace("blockquote"," {0,3}>").replace("code"," {4}[^\\n]").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html","?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|!--)").replace("tag",z._tag).getRegex(),z.pedantic=$({},z.normal,{html:T("^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+?\\1> *(?:\\n{2,}|\\s*$)|\\s]*)*?/?> *(?:\\n{2,}|\\s*$))").replace("comment",z._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+|$)/,heading:/^ *(#{1,6}) *([^\n]+?) *(?:#+ *)?(?:\n+|$)/,fences:R,paragraph:T(z.normal._paragraph).replace("hr",z.hr).replace("heading"," *#{1,6} *[^\n]").replace("lheading",z.lheading).replace("blockquote"," {0,3}>").replace("|fences","").replace("|list","").replace("|html","").getRegex()});R={escape:/^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,autolink:/^<(scheme:[^\s\x00-\x1f<>]*|email)>/,url:R,tag:"^comment|^[a-zA-Z][\\w:-]*\\s*>|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^|^",link:/^!?\[(label)\]\(\s*(href)(?:\s+(title))?\s*\)/,reflink:/^!?\[(label)\]\[(?!\s*\])((?:\\[\[\]]?|[^\[\]\\])+)\]/,nolink:/^!?\[(?!\s*\])((?:\[[^\[\]]*\]|\\[\[\]]|[^\[\]])*)\](?:\[\])?/,reflinkSearch:"reflink|nolink(?!\\()",strong:{start:/^(?:(\*\*(?=[*punctuation]))|\*\*)(?![\s])|__/,middle:/^\*\*(?:(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)|\*(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)*?\*)+?\*\*$|^__(?![\s])((?:(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)|_(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)*?_)+?)__$/,endAst:/[^punctuation\s]\*\*(?!\*)|[punctuation]\*\*(?!\*)(?:(?=[punctuation_\s]|$))/,endUnd:/[^\s]__(?!_)(?:(?=[punctuation*\s])|$)/},em:{start:/^(?:(\*(?=[punctuation]))|\*)(?![*\s])|_/,middle:/^\*(?:(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)|\*(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)*?\*)+?\*$|^_(?![_\s])(?:(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)|_(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)*?_)+?_$/,endAst:/[^punctuation\s]\*(?!\*)|[punctuation]\*(?!\*)(?:(?=[punctuation_\s]|$))/,endUnd:/[^\s]_(?!_)(?:(?=[punctuation*\s])|$)/},code:/^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,br:/^( {2,}|\\)\n(?!\s*$)/,del:R,text:/^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\?@\\[\\]`^{|}~"};R.punctuation=T(R.punctuation).replace(/punctuation/g,R._punctuation).getRegex(),R._blockSkip="\\[[^\\]]*?\\]\\([^\\)]*?\\)|`[^`]*?`|<[^>]*?>",R._overlapSkip="__[^_]*?__|\\*\\*\\[^\\*\\]*?\\*\\*",R._comment=T(z._comment).replace("(?:--\x3e|$)","--\x3e").getRegex(),R.em.start=T(R.em.start).replace(/punctuation/g,R._punctuation).getRegex(),R.em.middle=T(R.em.middle).replace(/punctuation/g,R._punctuation).replace(/overlapSkip/g,R._overlapSkip).getRegex(),R.em.endAst=T(R.em.endAst,"g").replace(/punctuation/g,R._punctuation).getRegex(),R.em.endUnd=T(R.em.endUnd,"g").replace(/punctuation/g,R._punctuation).getRegex(),R.strong.start=T(R.strong.start).replace(/punctuation/g,R._punctuation).getRegex(),R.strong.middle=T(R.strong.middle).replace(/punctuation/g,R._punctuation).replace(/overlapSkip/g,R._overlapSkip).getRegex(),R.strong.endAst=T(R.strong.endAst,"g").replace(/punctuation/g,R._punctuation).getRegex(),R.strong.endUnd=T(R.strong.endUnd,"g").replace(/punctuation/g,R._punctuation).getRegex(),R.blockSkip=T(R._blockSkip,"g").getRegex(),R.overlapSkip=T(R._overlapSkip,"g").getRegex(),R._escapes=/\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/g,R._scheme=/[a-zA-Z][a-zA-Z0-9+.-]{1,31}/,R._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])?)+(?![-_])/,R.autolink=T(R.autolink).replace("scheme",R._scheme).replace("email",R._email).getRegex(),R._attribute=/\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/,R.tag=T(R.tag).replace("comment",R._comment).replace("attribute",R._attribute).getRegex(),R._label=/(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/,R._href=/<(?:\\[<>]?|[^\s<>\\])*>|[^\s\x00-\x1f]*/,R._title=/"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/,R.link=T(R.link).replace("label",R._label).replace("href",R._href).replace("title",R._title).getRegex(),R.reflink=T(R.reflink).replace("label",R._label).getRegex(),R.reflinkSearch=T(R.reflinkSearch,"g").replace("reflink",R.reflink).replace("nolink",R.nolink).getRegex(),R.normal=$({},R),R.pedantic=$({},R.normal,{strong:{start:/^__|\*\*/,middle:/^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,endAst:/\*\*(?!\*)/g,endUnd:/__(?!_)/g},em:{start:/^_|\*/,middle:/^()\*(?=\S)([\s\S]*?\S)\*(?!\*)|^_(?=\S)([\s\S]*?\S)_(?!_)/,endAst:/\*(?!\*)/g,endUnd:/_(?!_)/g},link:T(/^!?\[(label)\]\((.*?)\)/).replace("label",R._label).getRegex(),reflink:T(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label",R._label).getRegex()}),R.gfm=$({},R.normal,{escape:T(R.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~])\1(?=[^~]|$)/,text:/^([`~]+|[^`~])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\'+(n?e:V(e,!0))+"\n":""+(n?e:V(e,!0))+"
\n"},t.blockquote=function(e){return"\n"+e+"
\n"},t.html=function(e){return e},t.heading=function(e,t,n,r){return this.options.headerIds?"\n":""+e+"\n"},t.hr=function(){return this.options.xhtml?"
\n":"
\n"},t.list=function(e,t,n){var r=t?"ol":"ul";return"<"+r+(t&&1!==n?' start="'+n+'"':"")+">\n"+e+""+r+">\n"},t.listitem=function(e){return""+e+"\n"},t.checkbox=function(e){return" "},t.paragraph=function(e){return""+e+"
\n"},t.table=function(e,t){return"\n\n"+e+"\n"+(t=t&&""+t+"")+"
\n"},t.tablerow=function(e){return"\n"+e+"
\n"},t.tablecell=function(e,t){var n=t.header?"th":"td";return(t.align?"<"+n+' align="'+t.align+'">':"<"+n+">")+e+""+n+">\n"},t.strong=function(e){return""+e+""},t.em=function(e){return""+e+""},t.codespan=function(e){return""+e+""},t.br=function(){return this.options.xhtml?"
":"
"},t.del=function(e){return""+e+""},t.link=function(e,t,n){if(null===(e=G(this.options.sanitize,this.options.baseUrl,e)))return n;e='"+n+""},t.image=function(e,t,n){if(null===(e=G(this.options.sanitize,this.options.baseUrl,e)))return n;n='
":">"},t.text=function(e){return e},e}(),J=function(){function e(){}var t=e.prototype;return t.strong=function(e){return e},t.em=function(e){return e},t.codespan=function(e){return e},t.del=function(e){return e},t.html=function(e){return e},t.text=function(e){return e},t.link=function(e,t,n){return""+n},t.image=function(e,t,n){return""+n},t.br=function(){return""},e}(),K=function(){function e(){this.seen={}}var t=e.prototype;return t.serialize=function(e){return e.toLowerCase().trim().replace(/<[!\/a-z].*?>/gi,"").replace(/[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,./:;<=>?@[\]^`{|}~]/g,"").replace(/\s/g,"-")},t.getNextSafeSlug=function(e,t){var n=e,r=0;if(this.seen.hasOwnProperty(n))for(r=this.seen[e];n=e+"-"+ ++r,this.seen.hasOwnProperty(n););return t||(this.seen[e]=r,this.seen[n]=0),n},t.slug=function(e,t){void 0===t&&(t={});var n=this.serialize(e);return this.getNextSafeSlug(n,t.dryrun)},e}(),Q=t.defaults,Y=y,ee=function(){function n(e){this.options=e||Q,this.options.renderer=this.options.renderer||new H,this.renderer=this.options.renderer,this.renderer.options=this.options,this.textRenderer=new J,this.slugger=new K}n.parse=function(e,t){return new n(t).parse(e)},n.parseInline=function(e,t){return new n(t).parseInline(e)};var e=n.prototype;return e.parse=function(e,t){void 0===t&&(t=!0);for(var n,r,i,s,l,a,o,c,u,p,h,g,f,d,k,b="",m=e.length,x=0;xAn error occurred:
"+re(e.message+"",!0)+"
";throw e}}return se.options=se.setOptions=function(e){return te(se.defaults,e),ie(se.defaults),se},se.getDefaults=_,se.defaults=t,se.use=function(a){var t,n=te({},a);a.renderer&&function(){var e,l=se.defaults.renderer||new H;for(e in a.renderer)!function(i){var s=l[i];l[i]=function(){for(var e=arguments.length,t=new Array(e),n=0;nAn error occurred:"+re(e.message+"",!0)+"
";throw e}},se.Parser=ee,se.parser=ee.parse,se.Renderer=H,se.TextRenderer=J,se.Lexer=W,se.lexer=W.lex,se.Tokenizer=D,se.Slugger=K,se.parse=se});
\ No newline at end of file
diff --git a/uni_modules/mp-html/components/mp-html/mp-html.vue b/uni_modules/mp-html/components/mp-html/mp-html.vue
index f277ad2..03398af 100755
--- a/uni_modules/mp-html/components/mp-html/mp-html.vue
+++ b/uni_modules/mp-html/components/mp-html/mp-html.vue
@@ -39,7 +39,7 @@
// #ifndef APP-PLUS-NVUE
import node from './node/node'
// #endif
-const plugins=[]
+const plugins=[require('./markdown/index.js')]
const Parser = require('./parser')
// #ifdef APP-PLUS-NVUE
const dom = weex.requireModule('dom')
@@ -55,6 +55,7 @@ export default {
}
},
props: {
+ markdown: Boolean,
containerStyle: {
type: String,
default: ''
@@ -152,6 +153,7 @@ export default {
* @returns {Promise}
*/
navigateTo (id, offset) {
+ id = this._ids[decodeURI(id)] || id
return new Promise((resolve, reject) => {
if (!this.useAnchor) {
reject(Error('Anchor is disabled'))