Compare commits

...

4 Commits

Author SHA1 Message Date
CrescentLeaf
7689ec590a fix: 多数据类型消息元素之间的混合显示问题 2025-11-17 00:07:38 +08:00
CrescentLeaf
6517b04215 fix: 移除 chat-mention 换行支持 2025-11-17 00:07:15 +08:00
CrescentLeaf
51fbdc0f71 chore: 修改消息无效附加数据的提示文本 2025-11-17 00:05:10 +08:00
CrescentLeaf
4bf55749bb fix: 避免不同的消息类型之间的换行符导致显示异常 2025-11-17 00:04:45 +08:00
4 changed files with 33 additions and 7 deletions

View File

@@ -89,7 +89,7 @@ const markedInstance = new marked.Marked({
case "ChatMention":
return `<chat-mention chat-id="${escapeHTML(/^tws:\/\/chat\?id=(.*)/.exec(href)?.[1] || '')}" text="${escapeHTML(/^ChatMention=(.*)/.exec(text)?.[1] || '')}">PH</chat-mention>`
}
return `<chat-text em="true">(不支持的附件语法: ![${text}](${href}))</chat-text>`
return `<chat-text em="true">${ escapeHTML(`[无效数据 (<${text}>=${href})]`) }</chat-text>`
},
}
})

View File

@@ -12,6 +12,7 @@ import isMobileUI from "../isMobileUI.ts"
import ReactJson from 'react-json-view'
import User from "../../api/client_data/User.ts"
import getUrlForFileByHash from "../../getUrlForFileByHash.ts"
import escapeHTML from "../../escapeHtml.ts"
interface Args extends React.HTMLAttributes<HTMLElement> {
userId: string
@@ -23,6 +24,9 @@ interface Args extends React.HTMLAttributes<HTMLElement> {
function prettyFlatParsedMessage(html: string) {
const elements = new DOMParser().parseFromString(html, 'text/html').body.children
// 纯文本直接处理
if (elements.length == 0)
return `<chat-text-container><chat-text>${escapeHTML(html)}</chat-text></chat-text-container>`
let ls: Element[] = []
let ret = ''
// 第一个元素时, 不会被聚合在一起
@@ -32,13 +36,26 @@ function prettyFlatParsedMessage(html: string) {
'chat-mention',
]
function checkContinuousElement(tagName: string) {
if (lastElementType != tagName) {
/* console.log('shangyige ', lastElementType)
console.log("dangqian", tagName)
console.log("上一个元素的类型和当前不一致?", lastElementType != tagName)
console.log("上一个元素的类型和这个元素的类型都属于文本类型", (textElementTags.indexOf(lastElementType) != -1 && textElementTags.indexOf(tagName) != -1)) */
// 如果上一个元素的类型和当前不一致, 或者上一个元素的类型和这个元素的类型都属于文本类型 (亦或者到最后一步时) 执行
if ((lastElementType != tagName || (textElementTags.indexOf(lastElementType) != -1 && textElementTags.indexOf(tagName) != -1)) || tagName == 'LAST_CHICKEN') {
/* console.log(tagName, '进入') */
// 如果上一个元素类型为文本类型, 且当前不是文本类型时, 用文本包裹
if (textElementTags.indexOf(lastElementType) != -1) {
// 当前的文本类型不应该和上一个分离, 滚出去
if (textElementTags.indexOf(tagName) != -1) return
/* console.log(tagName, '文字和被') */
// 由于 chat-mention 不是用内部元素实现的, 因此在这个元素的生成中必须放置占位字符串
// 尽管显示上占位字符串不会显示, 但是在这里依然是会被处理的, 因为本身还是 innerHTML
// 当文本非空时, 将文字合并在一起
if (ls.map((v) => v.innerHTML).join('').trim() != '')
ret += `<chat-text-container>${ls.map((v) => v.outerHTML).join('')}</chat-text-container>`
} else
// 非文本类型元素, 各自成块
ret += ls.map((v) => v.outerHTML).join('')
ls = []
}
@@ -46,12 +63,13 @@ function prettyFlatParsedMessage(html: string) {
for (const e of elements) {
// 当出现非文本元素时, 将文本聚合在一起
// 如果是其他类型, 虽然也执行聚合, 但是不会有外层包裹
/* console.log("当前", e, "内容", e.innerHTML) */
checkContinuousElement(e.nodeName.toLowerCase())
ls.push(e)
lastElementType = e.nodeName.toLowerCase()
}
// 最后将剩余的转换
checkContinuousElement('')
checkContinuousElement('LAST_CHICKEN')
return ret
}

View File

@@ -14,7 +14,6 @@ customElements.define('chat-mention', class extends HTMLElement {
const shadow = this.shadowRoot as ShadowRoot
this.span = document.createElement('span')
this.span.style.whiteSpace = 'pre-wrap'
this.span.style.fontSynthesis = 'style weight'
this.span.style.color = 'rgb(var(--mdui-color-primary))'
shadow.appendChild(this.span)

View File

@@ -10,7 +10,7 @@ customElements.define('chat-text', class extends HTMLElement {
}
connectedCallback() {
const shadow = this.shadowRoot as ShadowRoot
this.span = document.createElement('span')
this.span.style.whiteSpace = 'pre-wrap'
this.span.style.fontSynthesis = 'style weight'
@@ -23,8 +23,17 @@ customElements.define('chat-text', class extends HTMLElement {
}
update() {
if (this.span == null) return
this.span.textContent = this.textContent
const isFirstElementInParent = this.parentElement?.firstElementChild == this
const isLastElementInParent = this.parentElement?.lastElementChild == this
// 避免不同的消息类型之间的换行符导致显示异常
if (isFirstElementInParent)
this.span.textContent = this.textContent.trimStart()
else if (isLastElementInParent)
this.span.textContent = this.textContent.trimEnd()
else
this.span.textContent = this.textContent
this.span.style.textDecoration = $(this).attr('underline') ? 'underline' : ''
this.span.style.fontStyle = $(this).attr('em') ? 'italic' : ''
}