219 lines
5.5 KiB
TypeScript
219 lines
5.5 KiB
TypeScript
import { formatHTML } from "~utils/html";
|
|
|
|
const getTitle = () => {
|
|
const title = document.title;
|
|
const metaTitle = document.querySelector<HTMLMetaElement>(`meta[name="title"]`);
|
|
const metaOgTitle = document.querySelector<HTMLMetaElement>(`meta[name="og:title"]`);
|
|
|
|
if (metaOgTitle) {
|
|
return metaOgTitle.getAttribute("content");;
|
|
}
|
|
|
|
if (metaTitle) {
|
|
return metaTitle.getAttribute("content");;
|
|
}
|
|
|
|
if (title.includes(" - ")) {
|
|
const end = title.lastIndexOf(" - ");
|
|
|
|
return title.substring(0, end);
|
|
}
|
|
|
|
if (title.includes(" | ")) {
|
|
const end = title.lastIndexOf(" | ");
|
|
|
|
return title.substring(0, end);
|
|
}
|
|
|
|
return title;
|
|
}
|
|
|
|
const getDesc = () => {
|
|
const articleFirstParagraph = document.querySelector<HTMLParagraphElement>("article p") || document.querySelector<HTMLParagraphElement>("p");
|
|
const metaDescription = document.querySelector<HTMLMetaElement>(`meta[name="description"]`);
|
|
const metaOgDescription = document.querySelector<HTMLMetaElement>(`meta[property="og:description"]`);
|
|
|
|
if (metaOgDescription) {
|
|
return metaOgDescription.getAttribute("content");
|
|
}
|
|
|
|
if (metaDescription) {
|
|
return metaDescription.getAttribute("content");
|
|
}
|
|
|
|
if (articleFirstParagraph) {
|
|
return articleFirstParagraph.innerText;
|
|
}
|
|
|
|
return "";
|
|
}
|
|
|
|
const getAuthor = () => {
|
|
const metaAuthor = document.querySelector<HTMLMetaElement>(`meta[name="author"]`);
|
|
const metaOgAuthor = document.querySelector<HTMLMetaElement>(`meta[property="og:article:author"]`);
|
|
const itemPropAuthor = document.querySelector<HTMLMetaElement>(`[itemprop="author"] [itemprop="name"]`);
|
|
|
|
if (metaAuthor) {
|
|
return metaAuthor.getAttribute("content");
|
|
}
|
|
|
|
if (metaOgAuthor) {
|
|
return metaOgAuthor.getAttribute("content");
|
|
}
|
|
|
|
if (itemPropAuthor) {
|
|
return itemPropAuthor.getAttribute("content");
|
|
}
|
|
|
|
return "";
|
|
}
|
|
|
|
const getImage = () => {
|
|
const metaOgImage = document.querySelector<HTMLMetaElement>(`meta[property="og:image"]`);
|
|
|
|
if (metaOgImage) {
|
|
return metaOgImage.getAttribute("content");
|
|
}
|
|
|
|
return "";
|
|
}
|
|
|
|
const getSiteName = () => {
|
|
const title = document.title;
|
|
const metaSiteName = document.querySelector<HTMLMetaElement>(`meta[property="og:site_name"]`);
|
|
|
|
if (metaSiteName) {
|
|
return metaSiteName.getAttribute("content");
|
|
}
|
|
|
|
if (title.includes(" - ")) {
|
|
const start = title.lastIndexOf(" - ") + 3;
|
|
|
|
return title.substring(start);
|
|
}
|
|
|
|
if (title.includes(" | ")) {
|
|
const start = title.lastIndexOf(" | ") + 3;
|
|
|
|
return title.substring(start);
|
|
}
|
|
|
|
return "";
|
|
}
|
|
|
|
const getTags = () => {
|
|
const metaKeywords = document.querySelector<HTMLMetaElement>(`meta[name="keywords"]`);
|
|
const itemPropKeywords = document.querySelector<HTMLMetaElement>(`meta[itemprop="keywords"]`);
|
|
|
|
if (metaKeywords) {
|
|
return metaKeywords.getAttribute("content");
|
|
}
|
|
|
|
if (itemPropKeywords) {
|
|
return itemPropKeywords.getAttribute("content");
|
|
}
|
|
|
|
return "";
|
|
}
|
|
|
|
const getHTML = () => {
|
|
// 微信
|
|
if (location.host === "mp.weixin.qq.com") {
|
|
console.log("微信");
|
|
|
|
return document.querySelector(".rich_media_content").innerHTML;
|
|
}
|
|
|
|
// 腾讯云开发者社区
|
|
if (location.host === "cloud.tencent.com") {
|
|
console.log("腾讯云");
|
|
|
|
return formatHTML(document.querySelector(".rno-markdown").innerHTML, (doc) => {
|
|
// 替换掉腾讯云自己的链接
|
|
const qcloudLinkEl = doc.querySelectorAll("a");
|
|
qcloudLinkEl.forEach((el) => {
|
|
if (el.href.includes("qcloud")) {
|
|
el.parentNode.replaceChild(document.createTextNode(el.innerText), el);
|
|
}
|
|
});
|
|
|
|
const mdTextEl = doc.querySelectorAll(".rno-markdown__textlink-new") as NodeListOf<HTMLElement>;
|
|
mdTextEl.forEach((el) => {
|
|
el.parentNode.replaceChild(document.createTextNode(el.innerText), el);
|
|
});
|
|
});
|
|
}
|
|
|
|
// 掘金
|
|
const itemPropArticle = document.querySelector("[itemprop=articleBody] .markdown-body");
|
|
|
|
if (itemPropArticle) {
|
|
console.log("掘金");
|
|
|
|
return formatHTML(itemPropArticle.innerHTML);
|
|
}
|
|
|
|
// CSDN
|
|
const contentViews = document.getElementById("content_views");
|
|
|
|
if (contentViews) {
|
|
console.log("CSDN");
|
|
|
|
return formatHTML(contentViews.innerHTML);
|
|
}
|
|
|
|
// 通用模式
|
|
const articleEl = document.querySelector("article");
|
|
|
|
if (articleEl) {
|
|
console.log("文章标签");
|
|
|
|
return formatHTML(articleEl.innerHTML);
|
|
}
|
|
|
|
// 尝试匹配到文章
|
|
const firstParagraph = document.querySelector("p");
|
|
|
|
let continueFindCorrectParent = true;
|
|
let parentEl;
|
|
let limitCount = 0;
|
|
|
|
if (firstParagraph) {
|
|
while (continueFindCorrectParent) {
|
|
if (limitCount > 20) {
|
|
continueFindCorrectParent = false;
|
|
throw new Error("DOM 层级检测遍历次数过多");
|
|
}
|
|
|
|
limitCount += 1;
|
|
|
|
parentEl = parentEl ? parentEl.parentElement : firstParagraph.parentElement;
|
|
|
|
// 这个父下面有多个疑似正文的元素
|
|
if (Array.from(parentEl.querySelectorAll("h2, h3, h4, p")).length > 1) {
|
|
console.log(parentEl, `匹配结束,向上遍历 ${limitCount} 次`);
|
|
continueFindCorrectParent = false;
|
|
}
|
|
}
|
|
|
|
return formatHTML(parentEl.innerHTML);
|
|
}
|
|
|
|
return "";
|
|
}
|
|
|
|
chrome.runtime.onMessage.addListener((req, sender, send) => {
|
|
if (req.type === "toolbox:getInfo") {
|
|
send({
|
|
title: getTitle(),
|
|
link: `${location.origin}${location.pathname}`,
|
|
desc: getDesc(),
|
|
author: getAuthor(),
|
|
image: getImage(),
|
|
sitename: getSiteName(),
|
|
tags: getTags(),
|
|
raw_content: getHTML(),
|
|
});
|
|
}
|
|
});
|