From 3fbd6287a22382cd369e8e1b91dd46add328b2c8 Mon Sep 17 00:00:00 2001 From: moz Date: Sat, 18 Jul 2026 13:33:10 +0800 Subject: [PATCH] fix: solve warnings on obsidian review --- src/live-preview.ts | 2 +- src/main.ts | 2 ++ src/settings.ts | 33 ++++++++++++++++++--------------- src/svg.ts | 4 +++- src/ui.ts | 18 +++++++++--------- tsconfig.json | 3 ++- 6 files changed, 35 insertions(+), 27 deletions(-) diff --git a/src/live-preview.ts b/src/live-preview.ts index b274e3f..be63b7c 100644 --- a/src/live-preview.ts +++ b/src/live-preview.ts @@ -19,7 +19,7 @@ class IconWidget extends WidgetType { constructor(readonly iconImage: string, readonly hideSuffix: boolean, readonly isBefore: boolean) { super(); } toDOM(_view: EditorView): HTMLElement { - const span = activeDocument.createElement('span'); + const span = createSpan(); span.className = 'external-links-icon-inline' + (this.hideSuffix ? ' external-links-icon-hide-suffix' : '') + (this.isBefore ? ' external-links-icon-position-before' : ''); diff --git a/src/main.ts b/src/main.ts index 2b2e25c..4da573d 100644 --- a/src/main.ts +++ b/src/main.ts @@ -9,6 +9,8 @@ import { ExternalLinksIconSettingTab } from './settings'; import { createLivePreviewExtension } from './live-preview'; import { setLanguage } from './lang/helper'; +declare const process: { env: { NODE_ENV?: string } }; + export default class ExternalLinksIcon extends Plugin { settings!: ExternalLinksIconSettings; private scanner: import('./scanner').Scanner | null = null; diff --git a/src/settings.ts b/src/settings.ts index 3a7e414..db7d12f 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -29,21 +29,20 @@ function renderIconImage( icon: IconItem, isBuiltin: boolean ): void { - const doc = container.ownerDocument; const hasDual = !!(icon.svgData && icon.themeDarkSvgData); try { if (hasDual) { const lightPrepared = prepareSvgForSettings(icon.svgData || '', container); const darkPrepared = prepareSvgForSettings(icon.themeDarkSvgData || '', container); - const imgLight = doc.createElement('img'); + const imgLight = createEl('img'); setIconImgDataset(imgLight, icon, isBuiltin); imgLight.dataset.iconVariant = 'light'; imgLight.dataset.dualVariant = 'true'; imgLight.src = `data:image/svg+xml;utf8,${encodeURIComponent(lightPrepared)}`; imgLight.alt = getIconDisplayName(icon); - const imgDark = doc.createElement('img'); + const imgDark = createEl('img'); setIconImgDataset(imgDark, icon, isBuiltin); imgDark.dataset.iconVariant = 'dark'; imgDark.dataset.dualVariant = 'true'; @@ -56,7 +55,7 @@ function renderIconImage( const preferDark = preferDarkThemeFromDocument(); const svgSource = getSvgSourceForTheme(icon, preferDark); const prepared = prepareSvgForSettings(svgSource, container); - const img = doc.createElement('img'); + const img = createEl('img'); setIconImgDataset(img, icon, isBuiltin); img.src = `data:image/svg+xml;utf8,${encodeURIComponent(prepared)}`; img.alt = getIconDisplayName(icon); @@ -111,17 +110,16 @@ export class ExternalLinksIconSettingTab extends PluginSettingTab { desc: t('Add website or URL scheme icon. The icon name must be unique.'), render: (setting) => { const btnContainer = setting.controlEl.createDiv({ cls: 'add-buttons' }); - const doc = btnContainer.ownerDocument; - const addWebsiteBtn = doc.createElement('button'); - addWebsiteBtn.textContent = t('Add website'); - addWebsiteBtn.onclick = () => { + const addWebsiteBtn = createEl('button'); + addWebsiteBtn.textContent = t('Add website'); + addWebsiteBtn.onclick = () => { const modal = new NewIconModal(this.app, (data) => this.addIconWithData(data), 'url', this.plugin.settings.autoRemoveBackground, this.plugin.settings.autoFitIcon); modal.open(); }; btnContainer.appendChild(addWebsiteBtn); - const addSchemeBtn = doc.createElement('button'); + const addSchemeBtn = createEl('button'); addSchemeBtn.textContent = t('Add URL scheme'); addSchemeBtn.onclick = () => { const modal = new NewIconModal(this.app, (data) => this.addIconWithData(data), 'scheme', this.plugin.settings.autoRemoveBackground, this.plugin.settings.autoFitIcon); @@ -281,7 +279,7 @@ export class ExternalLinksIconSettingTab extends PluginSettingTab { private async addIconWithData(data: { linkType: LinkType; name: string; target: string[]; svgData?: string; themeDarkSvgData?: string }) { const { linkType, name, target, svgData, themeDarkSvgData } = data; const id = name; - const customIcons = this.plugin.settings.customIcons || {}; + const customIcons: Record = this.plugin.settings.customIcons || {}; if (customIcons[id]) { new Notice(`Icon name "${name}" already exists. Please choose a unique name.`); return; @@ -404,9 +402,14 @@ export class ExternalLinksIconSettingTab extends PluginSettingTab { } } + private getCustomIconList(): IconItem[] { + const map: Record = this.plugin.settings.customIcons || {}; + return Object.values(map); + } + private getSortedCustomIcons(): IconItem[] { - return Object.values(this.plugin.settings.customIcons || {}) - .sort((a: IconItem, b: IconItem) => (a.order || 0) - (b.order || 0)); + return this.getCustomIconList() + .sort((a, b) => (a.order || 0) - (b.order || 0)); } private addIconPreview(settingItem: Setting, icon: IconItem): void { @@ -448,7 +451,7 @@ export class ExternalLinksIconSettingTab extends PluginSettingTab { } private addControlButtons(settingItem: Setting, icon: IconItem): void { - const allCustom = Object.values(this.plugin.settings.customIcons || {}); + const allCustom = this.getCustomIconList(); const groupSorted = allCustom .filter(i => i.linkType === icon.linkType) .sort((a, b) => (a.order || 0) - (b.order || 0)); @@ -494,7 +497,7 @@ export class ExternalLinksIconSettingTab extends PluginSettingTab { } private async moveIcon(icon: IconItem, direction: number): Promise { - const allCustom = Object.values(this.plugin.settings.customIcons || {}); + const allCustom = this.getCustomIconList(); const group = allCustom.filter(i => i.linkType === icon.linkType).sort((a, b) => (a.order || 0) - (b.order || 0)); const currentIndex = group.findIndex(i => i.id === icon.id); const targetIndex = currentIndex + direction; @@ -507,7 +510,7 @@ export class ExternalLinksIconSettingTab extends PluginSettingTab { arr.forEach((it, idx) => { it.order = idx; }); const newMap: Record = {}; - Object.values(this.plugin.settings.customIcons || {}).forEach(it => { + this.getCustomIconList().forEach(it => { if (it.linkType !== icon.linkType) { newMap[it.id] = it; } diff --git a/src/svg.ts b/src/svg.ts index e729573..6f7cd85 100644 --- a/src/svg.ts +++ b/src/svg.ts @@ -103,7 +103,7 @@ function normalizeColor(color: string): string | null { } try { if (!_normalizeCtx) { - const canvas = activeDocument.createElement('canvas'); + const canvas = createEl('canvas'); canvas.width = 1; canvas.height = 1; _normalizeCtx = canvas.getContext('2d'); @@ -112,6 +112,7 @@ function normalizeColor(color: string): string | null { _normalizeCtx.fillStyle = '#abcdef'; // sentinel _normalizeCtx.fillStyle = c; const result = _normalizeCtx.fillStyle; + if (typeof result !== 'string') return null; if (result === '#abcdef') return null; // invalid, kept previous // Modern browsers return #rrggbb for opaque, rgba(...) for alpha < 1 const rgbaMatch = result.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)$/i); @@ -376,6 +377,7 @@ export function fitSvgToContent( // Compute content bbox via native getBBox() — accurate for curves/transforms. // Requires the SVG to be attached to a rendered DOM tree. let contentBBox: { x: number; y: number; w: number; h: number }; + // eslint-disable-next-line obsidianmd/prefer-create-el const host = activeDocument.createElementNS('http://www.w3.org/2000/svg', 'svg'); host.setAttribute('xmlns', 'http://www.w3.org/2000/svg'); host.setCssProps({ diff --git a/src/ui.ts b/src/ui.ts index 471bffa..e484a29 100644 --- a/src/ui.ts +++ b/src/ui.ts @@ -171,7 +171,7 @@ function createIconUploadSection(options: IconUploadSectionOptions): { onRemove?.(false); }; - const input = createFileInput(doc, (content, fileName) => { + const input = createFileInput((content, fileName) => { let processed = content; if (autoRemoveBackground) { const result = removeBackground(content); @@ -189,7 +189,7 @@ function createIconUploadSection(options: IconUploadSectionOptions): { newSvgData = processed; clearRemoveState(); badge.classList.remove('external-links-icon-badge-empty'); - renderPreview(doc, preview, processed, fileName); + renderPreview(preview, processed, fileName); }); if (hiddenInputs) hiddenInputs.push(input); doc.body.appendChild(input); @@ -202,7 +202,7 @@ function createIconUploadSection(options: IconUploadSectionOptions): { newSvgData = svgData; clearRemoveState(); badge.classList.remove('external-links-icon-badge-empty'); - renderPreview(doc, preview, svgData, 'copied'); + renderPreview(preview, svgData, 'copied'); }, controlRow: row, }; @@ -473,8 +473,8 @@ export class EditIconModal extends Modal { } } -function createFileInput(doc: Document, onValid: (content: string, fileName: string) => void): HTMLInputElement { - const input = doc.createElement('input'); +function createFileInput(onValid: (content: string, fileName: string) => void): HTMLInputElement { + const input = createEl('input'); input.type = 'file'; input.accept = '.svg,image/svg+xml'; input.classList.add('external-links-icon-hidden-input'); @@ -501,9 +501,9 @@ function createFileInput(doc: Document, onValid: (content: string, fileName: str return input; } -function renderPreview(doc: Document, previewDiv: HTMLElement, content: string, fileName: string): void { +function renderPreview(previewDiv: HTMLElement, content: string, fileName: string): void { try { - const img = doc.createElement('img'); + const img = createEl('img'); img.src = encodeSvgData(content); img.alt = fileName; while (previewDiv.firstChild) previewDiv.removeChild(previewDiv.firstChild); @@ -518,7 +518,7 @@ function downloadSvg(svgData: string, fileName: string): void { const blob = new Blob([svgData], { type: 'image/svg+xml' }); const url = URL.createObjectURL(blob); try { - const a = doc.createElement('a'); + const a = createEl('a'); a.href = url; a.download = fileName; doc.body.appendChild(a); @@ -550,7 +550,7 @@ function createBadgeWithPreview( if (svgData) { try { const prepared = prepareSvgForSettings(svgData, preview); - const img = badge.ownerDocument.createElement('img'); + const img = createEl('img'); img.src = encodeSvgData(prepared); img.alt = variant === 'light' ? 'current' : 'current dark'; preview.appendChild(img); diff --git a/tsconfig.json b/tsconfig.json index c44b729..44a8c57 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -15,7 +15,8 @@ "DOM", "ES5", "ES6", - "ES7" + "ES7", + "ES2017" ] }, "include": [