From d5e9fec0348b160db90088d1744df937cf993f15 Mon Sep 17 00:00:00 2001 From: kim365my Date: Tue, 2 Apr 2024 18:09:51 +0900 Subject: [PATCH] =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/EnbedDecoratiion.ts | 75 ++++---------------------------- src/LinkThumbnailWidgetParams.ts | 57 ++++++++++++++++++++++++ src/PostProcessor.ts | 9 ++-- styles.css | 2 + 4 files changed, 72 insertions(+), 71 deletions(-) create mode 100644 src/LinkThumbnailWidgetParams.ts diff --git a/src/EnbedDecoratiion.ts b/src/EnbedDecoratiion.ts index 339552f..2037810 100644 --- a/src/EnbedDecoratiion.ts +++ b/src/EnbedDecoratiion.ts @@ -1,9 +1,10 @@ -import {debounce, editorLivePreviewField, requestUrl} from "obsidian"; +import {debounce, editorLivePreviewField} from "obsidian"; import {EditorView, Decoration, DecorationSet, ViewUpdate, ViewPlugin, WidgetType} from "@codemirror/view"; import {StateField, StateEffect, StateEffectType} from "@codemirror/state"; import {Range} from "@codemirror/rangeset"; import {syntaxTree, tokenClassNodeProp} from "@codemirror/language"; import LinkThumbnailPlugin from "./main"; +import { LinkThumbnailWidgetParams } from "./LinkThumbnailWidgetParams"; //based on: https://gist.github.com/nothingislost/faa89aa723254883d37f45fd16162337 @@ -39,9 +40,13 @@ class StatefulDecorationSet { div.addClass("cm-embed-block"); div.addClass("cm-embed-link"); // 넣을 EL 받아오기 - const params = await linkThumbnailWidgetParams(token.value); + const linkEl = createEl("a"); + linkEl.href = token.value; + linkEl.addClass("markdown-rendered"); + div.appendChild(linkEl); + const params = await LinkThumbnailWidgetParams(token.value); if (params != null) { - div.innerHTML = params; + linkEl.innerHTML = params; } else { return Decoration.none; } @@ -152,68 +157,4 @@ class EmojiWidget extends WidgetType { ignoreEvent(): boolean { return false; } -} - -export async function linkThumbnailWidgetParams(url: string) { - try { - // url 정규식 - const urlRegex = new RegExp("^(http:\\/\\/www\\.|https:\\/\\/www\\.|http:\\/\\/|https:\\/\\/)?[a-z0-9]+([\\-.]{1}[a-z0-9]+)*\\.[a-z]{2,5}(:[0-9]{1,5})?(\\/.*)?$"); - const urlT = urlRegex.exec(url); - if (urlT?.length != 0 && urlT != null) { - const domainUrl = url.replace(urlT[4], ""); - - const response = await requestUrl(url); - const responseDomain = await requestUrl(domainUrl); - - if (response.status === 200) { - const htmlString = response.text; - const parser = new DOMParser(); - const document = parser.parseFromString(htmlString, 'text/html'); - - const htmlDomainString = responseDomain.text; - const domainDocument = parser.parseFromString(htmlDomainString, 'text/html'); - - const ogTitle = document.querySelector("meta[property='og:title']")?.getAttribute("content") || document.querySelector("title")?.textContent || domainDocument.querySelector("meta[property='og:title']")?.getAttribute("content") || domainDocument.querySelector("title")?.textContent || ""; - const ogDescription = document.querySelector("meta[property='og:description']")?.getAttribute("content") || domainDocument.querySelector("meta[property='og:description']")?.getAttribute("content") || ""; - const ogImage = document.querySelector("meta[property='og:image']")?.getAttribute("content") || domainDocument.querySelector("meta[property='og:image']")?.getAttribute("content") || ""; - const ogImageAlt = document.querySelector("meta[property='og:image:alt']")?.getAttribute("content") || domainDocument.querySelector("meta[property='og:image']")?.getAttribute("content") || ""; - const ogUrl = document.querySelector("meta[property='og:url']")?.getAttribute("content") || domainUrl; - - let result = ""; - if (ogImage === "") { - result = ` - -
- -
-
- ` - } else { - result = ` - -
- - -
-
- ` - } - return result; - } - } - return null - } catch (error) { - // console.error(error); - return null; - } } \ No newline at end of file diff --git a/src/LinkThumbnailWidgetParams.ts b/src/LinkThumbnailWidgetParams.ts new file mode 100644 index 0000000..0f0e364 --- /dev/null +++ b/src/LinkThumbnailWidgetParams.ts @@ -0,0 +1,57 @@ +import { requestUrl } from "obsidian"; + +// url 정규식 +const urlRegex = new RegExp("^(http:\\/\\/www\\.|https:\\/\\/www\\.|http:\\/\\/|https:\\/\\/)?[a-z0-9]+([\\-.]{1}[a-z0-9]+)*\\.[a-z]{2,5}(:[0-9]{1,5})?(\\/.*)?$"); + +export async function LinkThumbnailWidgetParams(url: string) { + if (urlRegex.test(url)) { + try { + const response = await requestUrl(url); + const contextType = response.headers["content-type"]; + if (contextType.toLocaleLowerCase().trim() === "text/html;charset=ms949") { + return null; + } + + const htmlString = response.text; + const parser = new DOMParser(); + const document = parser.parseFromString(htmlString, 'text/html'); + + const ogTitle = document.querySelector("meta[property='og:title']")?.getAttribute("content") || document.querySelector("title")?.textContent || ""; + const ogDescription = document.querySelector("meta[property='og:description']")?.getAttribute("content") || ""; + const ogImage = document.querySelector("meta[property='og:image']")?.getAttribute("content") || ""; + const ogImageAlt = document.querySelector("meta[property='og:image:alt']")?.getAttribute("content") || ""; + const ogUrl = document.querySelector("meta[property='og:url']")?.getAttribute("content") || url; + + let result = ""; + if (ogImage === "") { + result = ` +
+ +
+ ` + } else { + result = ` +
+ + +
+ ` + } + return result; + } catch (error) { + console.error(error); + return null; + } + } + return null +} \ No newline at end of file diff --git a/src/PostProcessor.ts b/src/PostProcessor.ts index beb97b2..f459441 100644 --- a/src/PostProcessor.ts +++ b/src/PostProcessor.ts @@ -1,6 +1,6 @@ import { MarkdownPostProcessorContext } from "obsidian"; import LinkThumbnailPlugin from "./main"; -import { linkThumbnailWidgetParams } from "./EnbedDecoratiion"; +import { LinkThumbnailWidgetParams } from "./LinkThumbnailWidgetParams"; export class PostProcessor { plugin: LinkThumbnailPlugin; @@ -14,17 +14,18 @@ export class PostProcessor { context: MarkdownPostProcessorContext ) => { // 링크 변환 - const linkEls = element.findAll("a.external-link"); + const linkEls = element.findAll("a.external-link:not(.cm-formatting)"); for (const linkEl of linkEls) { // dataview 클래스를 가진 부모 요소를 확인합니다. if (linkEl.closest(".dataview") !== null) { continue; } - const url = linkEl.innerHTML; - const params = await linkThumbnailWidgetParams(url); + const params = await LinkThumbnailWidgetParams(url); if (params != null) { linkEl.innerHTML = params; + linkEl.removeClass("external-link"); + linkEl.addClass("markdown-rendered"); } } }; diff --git a/styles.css b/styles.css index 004f6cd..dc18d81 100644 --- a/styles.css +++ b/styles.css @@ -8,6 +8,8 @@ If your plugin does not need CSS, delete this file. */ a:has(.openGraphPreview) { + display: block; + padding-right: 0; text-decoration: none; background-image: none; }