인코딩 문제 해결

This commit is contained in:
kim365my 2024-04-08 15:18:31 +09:00
parent d1afcdea7a
commit b943ba02c9
5 changed files with 58 additions and 26 deletions

23
package-lock.json generated
View File

@ -1,13 +1,16 @@
{
"name": "obsidian-sample-plugin",
"name": "link-thumbnail-plugin",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "obsidian-sample-plugin",
"name": "link-thumbnail-plugin",
"version": "1.0.0",
"license": "MIT",
"dependencies": {
"iconv-lite": "^0.6.3"
},
"devDependencies": {
"@codemirror/commands": "6.0.0",
"@codemirror/language": "https://github.com/lishid/cm-language",
@ -1587,6 +1590,17 @@
"node": ">=8"
}
},
"node_modules/iconv-lite": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/ignore": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz",
@ -2087,6 +2101,11 @@
"queue-microtask": "^1.2.2"
}
},
"node_modules/safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"node_modules/semver": {
"version": "7.6.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",

View File

@ -12,18 +12,21 @@
"author": "",
"license": "MIT",
"devDependencies": {
"@codemirror/commands": "6.0.0",
"@codemirror/language": "https://github.com/lishid/cm-language",
"@codemirror/search": "6.0.0",
"@codemirror/view": "6.0.0",
"@types/node": "^16.11.6",
"@typescript-eslint/eslint-plugin": "5.29.0",
"@typescript-eslint/parser": "5.29.0",
"builtin-modules": "3.3.0",
"compare-versions": "^4.1.3",
"esbuild": "0.17.3",
"obsidian": "latest",
"tslib": "2.4.0",
"typescript": "4.7.4",
"compare-versions": "^4.1.3",
"@codemirror/search": "6.0.0",
"@codemirror/view": "6.0.0",
"@codemirror/commands": "6.0.0",
"@codemirror/language": "https://github.com/lishid/cm-language"
"typescript": "4.7.4"
},
"dependencies": {
"iconv-lite": "^0.6.3"
}
}

View File

@ -59,7 +59,7 @@ class StatefulDecorationSet {
linkEl.addEventListener("click", (e) => e.stopPropagation());
}
});
deco = this.decoCache[token.value] = Decoration.replace({widget: new EmojiWidget(div), block: true});
deco = this.decoCache[token.value] = Decoration.replace({widget: new ogLinkWidget(div), block: true});
}
decorations.push(deco.range(token.from, token.to));
}
@ -147,7 +147,7 @@ function defineStatefulDecoration(): {
return {update, field};
}
class EmojiWidget extends WidgetType {
class ogLinkWidget extends WidgetType {
private readonly source: HTMLDivElement;
constructor(source: HTMLDivElement) {
@ -155,7 +155,7 @@ class EmojiWidget extends WidgetType {
this.source = source;
}
eq(other: EmojiWidget) {
eq(other: ogLinkWidget) {
return other == this;
}

View File

@ -1,4 +1,5 @@
import { requestUrl } from "obsidian";
import { decode } from 'iconv-lite';
// 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})?(\\/.*)?$");
@ -6,17 +7,30 @@ const urlRegex = new RegExp("^(http:\\/\\/www\\.|https:\\/\\/www\\.|http:\\/\\/|
export async function LinkThumbnailWidgetParams(url: string) {
const urlArr = urlRegex.exec(url);
if (urlArr) {
try {
const response = await requestUrl(url);
const contextType = response.headers["content-type"];
if (contextType.toLocaleLowerCase().trim() === "text/html;charset=ms949") {
return null;
try {
const response = await requestUrl({
url:url,
throw: true
});
if (response && response.headers && response.headers['content-type'] && !response.headers['content-type']?.includes('text/')) {
throw new Error('Page must return a header content-type with text/');
}
const htmlString = response.text;
// 인코딩 문제 해결
const bodyArrayBuffer = response.arrayBuffer;
const charset = response.headers["content-type"].replace("text/html;charset=","").toLowerCase();
let body;
if (charset.trim() === "utf-8") {
body = Buffer.from(bodyArrayBuffer).toString('utf-8');
} else {
body = decode(Buffer.from(bodyArrayBuffer), charset);
}
const parser = new DOMParser();
const document = parser.parseFromString(htmlString, 'text/html');
const document = parser.parseFromString(body, '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") || "";
let ogImage = document.querySelector("meta[property='og:image']")?.getAttribute("content") || "";
@ -39,9 +53,8 @@ export async function LinkThumbnailWidgetParams(url: string) {
`
return result;
} catch (error) {
console.error(error);
return null;
throw new Error(error);
}
}
return null
}
}

View File

@ -16,10 +16,7 @@ export class PostProcessor {
// 링크 변환
const linkEls:Element[] = element.findAll("a.external-link:not(.cm-formatting, .markdown-rendered)");
for (const linkEl of linkEls) {
// dataview 클래스를 가진 부모 요소를 확인합니다.
if (linkEl.closest(".dataview") !== null) {
continue;
}
const url = linkEl.innerHTML;
const params = await LinkThumbnailWidgetParams(url);
if (params != null) {