mirror of
https://github.com/BTMuli/TeyvatGuide.git
synced 2025-12-12 09:18:14 +08:00
🌱 公告解析重构
This commit is contained in:
@@ -308,7 +308,7 @@ onUnmounted(() => {
|
|||||||
if (urlListener) urlListener();
|
if (urlListener) urlListener();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
<style lang="css">
|
<style lang="css" scoped>
|
||||||
.app-container {
|
.app-container {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background: var(--app-page-bg);
|
background: var(--app-page-bg);
|
||||||
|
|||||||
@@ -1 +1,30 @@
|
|||||||
<!-- todo 公告解析 -->
|
<template>
|
||||||
|
<component
|
||||||
|
v-for="(ta, index) in parseAnnoContent(props.data)"
|
||||||
|
:key="index"
|
||||||
|
:is="getTaName(ta)"
|
||||||
|
:data="ta"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { parseAnnoContent } from "../../web/utils/annoParser.js";
|
||||||
|
import TpBackupText from "../post/tp-backupText.vue";
|
||||||
|
import TpImage from "../post/tp-image.vue";
|
||||||
|
import TpText from "../post/tp-text.vue";
|
||||||
|
import TpTexts from "../post/tp-texts.vue";
|
||||||
|
import TpUnknown from "../post/tp-unknown.vue";
|
||||||
|
|
||||||
|
interface TaParserProps {
|
||||||
|
data: TGApp.BBS.Announcement.ContentItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<TaParserProps>();
|
||||||
|
|
||||||
|
function getTaName(ta: TGApp.Plugins.Mys.SctPost.Base) {
|
||||||
|
if (ta.children) return TpTexts;
|
||||||
|
if (typeof ta.insert === "string") return TpText;
|
||||||
|
if ("image" in ta.insert) return TpImage;
|
||||||
|
if ("backup_text" in ta.insert) return TpBackupText;
|
||||||
|
return TpUnknown;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ export interface TpImage {
|
|||||||
align?: "center"; // 待补充
|
align?: "center"; // 待补充
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TpImageProps {
|
interface TpImageProps {
|
||||||
data: TpImage;
|
data: TpImage;
|
||||||
}
|
}
|
||||||
@@ -66,6 +67,7 @@ function getImageTitle(): string {
|
|||||||
function getImageUrl(): string {
|
function getImageUrl(): string {
|
||||||
const img = props.data.insert.image;
|
const img = props.data.insert.image;
|
||||||
const append = "?x-oss-process=image/format,png";
|
const append = "?x-oss-process=image/format,png";
|
||||||
|
console.log("getImageUrl", img, append);
|
||||||
if (img.endsWith(".gif")) return img;
|
if (img.endsWith(".gif")) return img;
|
||||||
return img + append;
|
return img + append;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,25 +89,15 @@ function getParsedText(data: TpTextType): TpTextType[] {
|
|||||||
|
|
||||||
function getTpName(tp: TGApp.Plugins.Mys.SctPost.Base) {
|
function getTpName(tp: TGApp.Plugins.Mys.SctPost.Base) {
|
||||||
if (tp.children) return TpTexts;
|
if (tp.children) return TpTexts;
|
||||||
if (typeof tp.insert === "string") {
|
if (typeof tp.insert === "string") return TpText;
|
||||||
return TpText;
|
if ("image" in tp.insert) return TpImage;
|
||||||
} else if ("image" in tp.insert) {
|
if ("vod" in tp.insert) return TpVod;
|
||||||
return TpImage;
|
if ("video" in tp.insert) return TpVideo;
|
||||||
} else if ("vod" in tp.insert) {
|
if ("backup_text" in tp.insert) return TpBackupText;
|
||||||
return TpVod;
|
if ("link_card" in tp.insert) return TpLinkCard;
|
||||||
} else if ("video" in tp.insert) {
|
if ("divider" in tp.insert) return TpDivider;
|
||||||
return TpVideo;
|
if ("mention" in tp.insert) return TpMention;
|
||||||
} else if ("backup_text" in tp.insert) {
|
if ("vote" in tp.insert) return TpVote;
|
||||||
return TpBackupText;
|
|
||||||
} else if ("link_card" in tp.insert) {
|
|
||||||
return TpLinkCard;
|
|
||||||
} else if ("divider" in tp.insert) {
|
|
||||||
return TpDivider;
|
|
||||||
} else if ("mention" in tp.insert) {
|
|
||||||
return TpMention;
|
|
||||||
} else if ("vote" in tp.insert) {
|
|
||||||
return TpVote;
|
|
||||||
}
|
|
||||||
return TpUnknown;
|
return TpUnknown;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { webviewWindow } from "@tauri-apps/api";
|
|
||||||
import { ref, onMounted, reactive } from "vue";
|
import { ref, onMounted, reactive } from "vue";
|
||||||
import JsonViewer from "vue-json-viewer";
|
import JsonViewer from "vue-json-viewer";
|
||||||
import { useRoute } from "vue-router";
|
import { useRoute } from "vue-router";
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
:title="annoTitle"
|
:title="annoTitle"
|
||||||
/>
|
/>
|
||||||
<ToLoading v-model="loading" :title="loadingTitle" :subtitle="loadingSub" :empty="loadingEmpty" />
|
<ToLoading v-model="loading" :title="loadingTitle" :subtitle="loadingSub" :empty="loadingEmpty" />
|
||||||
<div class="anno-body">
|
<div class="anno-body" v-if="annoData">
|
||||||
<div class="anno-info">AnnoID: {{ annoId }} | Render by TeyvatGuide v{{ appVersion }}</div>
|
<div class="anno-info">AnnoID: {{ annoId }} | Render by TeyvatGuide v{{ appVersion }}</div>
|
||||||
<div class="anno-title">
|
<div class="anno-title">
|
||||||
{{ annoData.title }}
|
{{ annoData.title }}
|
||||||
@@ -17,8 +17,10 @@
|
|||||||
<div class="anno-subtitle">
|
<div class="anno-subtitle">
|
||||||
{{ parseText(annoData.subtitle) }}
|
{{ parseText(annoData.subtitle) }}
|
||||||
</div>
|
</div>
|
||||||
<img v-if="annoData.banner !== ''" :src="annoBanner" alt="cover" class="anno-img" />
|
<!-- <div class="anno-content" v-html="annoHtml" />-->
|
||||||
<div class="anno-content" v-html="annoHtml" />
|
<div class="anno-content">
|
||||||
|
<TaParser :data="annoData" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
@@ -26,16 +28,15 @@ import { app, webviewWindow } from "@tauri-apps/api";
|
|||||||
import { ref, onMounted, watch, onUnmounted } from "vue";
|
import { ref, onMounted, watch, onUnmounted } from "vue";
|
||||||
import { useRoute } from "vue-router";
|
import { useRoute } from "vue-router";
|
||||||
|
|
||||||
|
import TaParser from "../components/anno/ta-parser.vue";
|
||||||
import TSwitchTheme from "../components/app/t-switchTheme.vue";
|
import TSwitchTheme from "../components/app/t-switchTheme.vue";
|
||||||
import TShareBtn from "../components/main/t-shareBtn.vue";
|
import TShareBtn from "../components/main/t-shareBtn.vue";
|
||||||
import ToLoading from "../components/overlay/to-loading.vue";
|
import ToLoading from "../components/overlay/to-loading.vue";
|
||||||
import { useAppStore } from "../store/modules/app.js";
|
import { useAppStore } from "../store/modules/app.js";
|
||||||
import TGLogger from "../utils/TGLogger.js";
|
import TGLogger from "../utils/TGLogger.js";
|
||||||
import { saveImgLocal } from "../utils/TGShare.js";
|
|
||||||
import { createTGWindow } from "../utils/TGWindow.js";
|
import { createTGWindow } from "../utils/TGWindow.js";
|
||||||
import { AnnoLang, AnnoServer } from "../web/request/getAnno.js";
|
import { AnnoLang, AnnoServer } from "../web/request/getAnno.js";
|
||||||
import TGRequest from "../web/request/TGRequest.js";
|
import TGRequest from "../web/request/TGRequest.js";
|
||||||
import TGUtils from "../web/utils/TGUtils.js";
|
|
||||||
|
|
||||||
// loading
|
// loading
|
||||||
const loading = ref<boolean>(true);
|
const loading = ref<boolean>(true);
|
||||||
@@ -54,9 +55,7 @@ const annoId = Number(route.params.anno_id);
|
|||||||
const region = <AnnoServer>route.params.region;
|
const region = <AnnoServer>route.params.region;
|
||||||
const lang = <AnnoLang>route.params.lang;
|
const lang = <AnnoLang>route.params.lang;
|
||||||
const appVersion = ref<string>();
|
const appVersion = ref<string>();
|
||||||
const annoData = ref<TGApp.BBS.Announcement.ContentItem>(<TGApp.BBS.Announcement.ContentItem>{});
|
const annoData = ref<TGApp.BBS.Announcement.ContentItem | undefined>();
|
||||||
const annoHtml = ref<string>();
|
|
||||||
const annoBanner = ref<string>();
|
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
appVersion.value = await app.getVersion();
|
appVersion.value = await app.getVersion();
|
||||||
@@ -72,8 +71,6 @@ onMounted(async () => {
|
|||||||
try {
|
try {
|
||||||
annoData.value = await TGRequest.Anno.getContent(annoId, region, lang);
|
annoData.value = await TGRequest.Anno.getContent(annoId, region, lang);
|
||||||
loadingTitle.value = "正在渲染数据...";
|
loadingTitle.value = "正在渲染数据...";
|
||||||
annoHtml.value = await TGUtils.Anno.parseContent(annoData.value.content);
|
|
||||||
if (annoData.value.banner !== "") annoBanner.value = await saveImgLocal(annoData.value.banner);
|
|
||||||
annoTitle.value = `Anno_${annoId}`;
|
annoTitle.value = `Anno_${annoId}`;
|
||||||
await webviewWindow
|
await webviewWindow
|
||||||
.getCurrentWebviewWindow()
|
.getCurrentWebviewWindow()
|
||||||
|
|||||||
349
src/web/utils/annoParser.ts
Normal file
349
src/web/utils/annoParser.ts
Normal file
@@ -0,0 +1,349 @@
|
|||||||
|
/**
|
||||||
|
* @file web/utils/annoParser.ts
|
||||||
|
* @description 解析游戏内公告数据
|
||||||
|
* @since Beta v0.5.3
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { decodeRegExp } from "./tools.js";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 解析公告内容,转换为结构化数据
|
||||||
|
* @since Beta v0.5.3
|
||||||
|
* @param {TGApp.BBS.Announcement.ContentItem} anno - 公告内容
|
||||||
|
* @returns {TGApp.Plugins.Mys.SctPost.Base[]} 结构化数据
|
||||||
|
*/
|
||||||
|
export function parseAnnoContent(
|
||||||
|
anno: TGApp.BBS.Announcement.ContentItem,
|
||||||
|
): TGApp.Plugins.Mys.SctPost.Base[] {
|
||||||
|
const parser = new DOMParser();
|
||||||
|
const doc = parser.parseFromString(anno.content, "text/html");
|
||||||
|
const children: TGApp.Plugins.Mys.SctPost.Base[] = [];
|
||||||
|
const bannerNode: TGApp.Plugins.Mys.SctPost.Base = {
|
||||||
|
insert: {
|
||||||
|
image: anno.banner,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
children.push(bannerNode);
|
||||||
|
doc.body.childNodes.forEach((child) => {
|
||||||
|
children.push(...parseAnnoNode(child));
|
||||||
|
});
|
||||||
|
return children;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 解析公告节点
|
||||||
|
* @since Beta v0.5.3
|
||||||
|
* @param {Node} node - 节点
|
||||||
|
* @returns {TGApp.Plugins.Mys.SctPost.Base} 结构化数据
|
||||||
|
*/
|
||||||
|
function parseAnnoNode(node: Node): TGApp.Plugins.Mys.SctPost.Base[] {
|
||||||
|
let defaultRes: TGApp.Plugins.Mys.SctPost.Base = {
|
||||||
|
insert: {
|
||||||
|
tag: node.nodeName,
|
||||||
|
text: node.textContent,
|
||||||
|
type: node.nodeType,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
if (node.nodeType !== Node.ELEMENT_NODE && node.nodeType !== Node.TEXT_NODE) {
|
||||||
|
return [defaultRes];
|
||||||
|
}
|
||||||
|
if (node.nodeType === Node.TEXT_NODE) {
|
||||||
|
return [{ insert: node.textContent }];
|
||||||
|
}
|
||||||
|
const element = <HTMLElement>node;
|
||||||
|
defaultRes = {
|
||||||
|
insert: {
|
||||||
|
tag: element.tagName,
|
||||||
|
text: element.textContent,
|
||||||
|
style: element.style.cssText,
|
||||||
|
html: element.innerHTML,
|
||||||
|
outerHtml: element.outerHTML,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
if (element.tagName === "P") {
|
||||||
|
return [parseAnnoParagraph(element)];
|
||||||
|
}
|
||||||
|
if (element.tagName === "OL" || element.tagName === "LI" || element.tagName === "UL") {
|
||||||
|
const res: TGApp.Plugins.Mys.SctPost.Base[] = [];
|
||||||
|
Array.from(element.children).forEach((child) => {
|
||||||
|
res.push(...parseAnnoNode(child));
|
||||||
|
});
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
if (element.tagName === "DETAILS") {
|
||||||
|
return [parseAnnoDetails(element)];
|
||||||
|
}
|
||||||
|
// todo table解析
|
||||||
|
if (element.tagName === "TABLE") {
|
||||||
|
return [defaultRes];
|
||||||
|
}
|
||||||
|
if (element.tagName === "DIV") {
|
||||||
|
if (element.childNodes.length > 1) {
|
||||||
|
const res: TGApp.Plugins.Mys.SctPost.Base[] = [];
|
||||||
|
element.childNodes.forEach((child) => {
|
||||||
|
res.push(...parseAnnoNode(child));
|
||||||
|
});
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
if (element.childNodes.length === 0) return [defaultRes];
|
||||||
|
const child = element.childNodes[0];
|
||||||
|
if (child.nodeType !== Node.ELEMENT_NODE) return [defaultRes];
|
||||||
|
return parseAnnoNode(child);
|
||||||
|
}
|
||||||
|
if (element.tagName === "SUMMARY") {
|
||||||
|
const p = document.createElement("p");
|
||||||
|
p.innerHTML = element.innerHTML;
|
||||||
|
return [parseAnnoParagraph(p)];
|
||||||
|
}
|
||||||
|
if (element.tagName === "SPAN") {
|
||||||
|
return [parseAnnoSpan(element)];
|
||||||
|
}
|
||||||
|
return [defaultRes];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 解析公告段落
|
||||||
|
* @since Beta v0.5.3
|
||||||
|
* @param {HTMLElement} p - 段落元素
|
||||||
|
* @returns {TGApp.Plugins.Mys.SctPost.Base} 结构化数据
|
||||||
|
*/
|
||||||
|
function parseAnnoParagraph(p: HTMLElement): TGApp.Plugins.Mys.SctPost.Base {
|
||||||
|
const defaultRes = {
|
||||||
|
insert: {
|
||||||
|
tag: p.tagName,
|
||||||
|
text: p.textContent,
|
||||||
|
style: p.style.cssText,
|
||||||
|
html: p.innerHTML,
|
||||||
|
outerHtml: p.outerHTML,
|
||||||
|
childrenLength: p.childNodes.length,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
if (p.childNodes.length === 0) {
|
||||||
|
return {
|
||||||
|
insert: p.innerHTML === "" ? "\n" : p.textContent,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (p.childNodes.length === 1) {
|
||||||
|
if (
|
||||||
|
p.childNodes[0].nodeType !== Node.ELEMENT_NODE &&
|
||||||
|
p.childNodes[0].nodeType !== Node.TEXT_NODE
|
||||||
|
) {
|
||||||
|
return defaultRes;
|
||||||
|
}
|
||||||
|
if (p.childNodes[0].nodeType === Node.TEXT_NODE) {
|
||||||
|
const span = document.createElement("span");
|
||||||
|
span.innerHTML = p.innerHTML;
|
||||||
|
return {
|
||||||
|
insert: "",
|
||||||
|
children: [parseAnnoSpan(span)],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const child = <HTMLElement>p.childNodes[0];
|
||||||
|
if (child.tagName === "SPAN") {
|
||||||
|
return {
|
||||||
|
insert: "",
|
||||||
|
children: [parseAnnoSpan(child)],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (child.tagName === "IMG") {
|
||||||
|
return parseAnnoImage(child);
|
||||||
|
}
|
||||||
|
if (child.tagName === "A") {
|
||||||
|
return {
|
||||||
|
insert: "",
|
||||||
|
children: [parseAnnoAnchor(child)],
|
||||||
|
attributes: { align: "center" },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (child.tagName === "STRONG") {
|
||||||
|
return {
|
||||||
|
insert: child.innerHTML,
|
||||||
|
attributes: { bold: true },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return defaultRes;
|
||||||
|
}
|
||||||
|
const res: TGApp.Plugins.Mys.SctPost.Base = {
|
||||||
|
insert: "",
|
||||||
|
children: [],
|
||||||
|
};
|
||||||
|
p.childNodes.forEach((child) => {
|
||||||
|
let childRes: TGApp.Plugins.Mys.SctPost.Base;
|
||||||
|
if (child.nodeType === Node.TEXT_NODE) {
|
||||||
|
childRes = { insert: child.textContent };
|
||||||
|
} else if (child.nodeType === Node.ELEMENT_NODE) {
|
||||||
|
const element = <HTMLElement>child;
|
||||||
|
if (element.tagName === "SPAN") {
|
||||||
|
childRes = parseAnnoSpan(element);
|
||||||
|
} else if (element.tagName === "BR") {
|
||||||
|
childRes = { insert: "\n" };
|
||||||
|
} else if (element.tagName === "A") {
|
||||||
|
childRes = parseAnnoAnchor(element);
|
||||||
|
} else if (element.tagName === "STRONG") {
|
||||||
|
childRes = {
|
||||||
|
insert: element.innerHTML,
|
||||||
|
attributes: { bold: true },
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
throw new Error(`Unknown node type: ${element.tagName}`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Error(`Unknown node type: ${child.nodeType}`);
|
||||||
|
}
|
||||||
|
res.children!.push(childRes);
|
||||||
|
});
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 解析公告 span
|
||||||
|
* @since Beta v0.5.3
|
||||||
|
* @param {HTMLElement} span - span 元素
|
||||||
|
* @returns {TGApp.Plugins.Mys.SctPost.Base} 结构化数据
|
||||||
|
*/
|
||||||
|
function parseAnnoSpan(span: HTMLElement): TGApp.Plugins.Mys.SctPost.Base {
|
||||||
|
const defaultRes = {
|
||||||
|
insert: {
|
||||||
|
tag: span.tagName,
|
||||||
|
text: span.textContent,
|
||||||
|
style: span.style.cssText,
|
||||||
|
html: span.innerHTML,
|
||||||
|
outerHtml: span.outerHTML,
|
||||||
|
childrenLength: span.childNodes.length,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
if (span.childNodes.length === 0) {
|
||||||
|
console.error(span.innerHTML);
|
||||||
|
return {
|
||||||
|
insert: span.innerHTML === "" ? "\n" : decodeRegExp(span.innerHTML),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (span.childNodes.length === 1) {
|
||||||
|
if (
|
||||||
|
span.childNodes[0].nodeType !== Node.TEXT_NODE &&
|
||||||
|
span.childNodes[0].nodeType !== Node.ELEMENT_NODE
|
||||||
|
) {
|
||||||
|
return defaultRes;
|
||||||
|
}
|
||||||
|
if (span.childNodes[0].nodeType === Node.ELEMENT_NODE) {
|
||||||
|
const res = parseAnnoNode(span.childNodes[0]);
|
||||||
|
if (res.length > 1) return defaultRes;
|
||||||
|
return res[0];
|
||||||
|
}
|
||||||
|
let spanAttrs: Record<string, string> | null = {};
|
||||||
|
if (span.style.color !== "") {
|
||||||
|
spanAttrs.color = span.style.color;
|
||||||
|
} else {
|
||||||
|
spanAttrs = null;
|
||||||
|
}
|
||||||
|
const parse = decodeRegExp(span.innerHTML);
|
||||||
|
if (parse.includes("</t>")) {
|
||||||
|
const dom = new DOMParser().parseFromString(parse, "text/html");
|
||||||
|
return {
|
||||||
|
insert: dom.body.textContent,
|
||||||
|
attributes: spanAttrs,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
insert: parse,
|
||||||
|
attributes: spanAttrs,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return defaultRes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 解析公告图片
|
||||||
|
* @since Beta v0.5.3
|
||||||
|
* @param {HTMLElement} img - 图片元素
|
||||||
|
* @returns {TGApp.Plugins.Mys.SctPost.Base} 结构化数据
|
||||||
|
*/
|
||||||
|
function parseAnnoImage(img: HTMLElement): TGApp.Plugins.Mys.SctPost.Base {
|
||||||
|
if (img.tagName !== "IMG") {
|
||||||
|
return {
|
||||||
|
insert: {
|
||||||
|
tag: img.tagName,
|
||||||
|
text: img.textContent,
|
||||||
|
style: img.style.cssText,
|
||||||
|
html: img.innerHTML,
|
||||||
|
outerHtml: img.outerHTML,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const image = <HTMLImageElement>img;
|
||||||
|
return {
|
||||||
|
insert: {
|
||||||
|
image: image.src,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 解析公告锚点
|
||||||
|
* @since Beta v0.5.3
|
||||||
|
* @param {HTMLElement} a - 锚点元素
|
||||||
|
* @returns {TGApp.Plugins.Mys.SctPost.Base} 结构化数据
|
||||||
|
*/
|
||||||
|
function parseAnnoAnchor(a: HTMLElement): TGApp.Plugins.Mys.SctPost.Base {
|
||||||
|
if (a.tagName !== "A") {
|
||||||
|
return {
|
||||||
|
insert: {
|
||||||
|
tag: a.tagName,
|
||||||
|
text: a.textContent,
|
||||||
|
style: a.style.cssText,
|
||||||
|
html: a.innerHTML,
|
||||||
|
outerHtml: a.outerHTML,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const anchor = <HTMLAnchorElement>a;
|
||||||
|
const regex = /javascript:miHoYoGameJSSDK.openIn(Browser|Webview)\('(.+)('|%27)\);/;
|
||||||
|
let link = anchor.href;
|
||||||
|
if (anchor.href.match(regex)) {
|
||||||
|
const res = anchor.href.match(regex);
|
||||||
|
if (res !== null && res.length > 2) link = res[2];
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
insert: anchor.textContent,
|
||||||
|
attributes: {
|
||||||
|
link: link,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 解析公告详情
|
||||||
|
* @since Beta v0.5.3
|
||||||
|
* @param {HTMLElement} details - 详情元素
|
||||||
|
* @returns {TGApp.Plugins.Mys.SctPost.Base} 结构化数据
|
||||||
|
*/
|
||||||
|
function parseAnnoDetails(details: HTMLElement): TGApp.Plugins.Mys.SctPost.Base {
|
||||||
|
const defaultRes = {
|
||||||
|
insert: {
|
||||||
|
tag: details.tagName,
|
||||||
|
text: details.textContent,
|
||||||
|
style: details.style.cssText,
|
||||||
|
html: details.innerHTML,
|
||||||
|
outerHtml: details.outerHTML,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
if (details.tagName !== "DETAILS") return defaultRes;
|
||||||
|
if (details.childNodes.length !== 2) return defaultRes;
|
||||||
|
if (details.childNodes[0].nodeType !== Node.ELEMENT_NODE) return defaultRes;
|
||||||
|
if (details.childNodes[1].nodeType !== Node.ELEMENT_NODE) return defaultRes;
|
||||||
|
const summary = <HTMLElement>details.childNodes[0];
|
||||||
|
const content = <HTMLElement>details.childNodes[1];
|
||||||
|
if (summary.tagName !== "SUMMARY") return defaultRes;
|
||||||
|
if (content.tagName !== "DIV") return defaultRes;
|
||||||
|
const summaryNode = parseAnnoNode(summary);
|
||||||
|
const contentNode = parseAnnoNode(content);
|
||||||
|
return {
|
||||||
|
insert: {
|
||||||
|
backup_text: "",
|
||||||
|
fold: {
|
||||||
|
title: JSON.stringify(summaryNode),
|
||||||
|
content: JSON.stringify(contentNode),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user