mirror of
https://github.com/moziar/obsidian-external-links-icon.git
synced 2026-07-22 06:45:34 +00:00
fix: solve warnings on obsidian review
This commit is contained in:
parent
dcbca03695
commit
3fbd6287a2
6 changed files with 35 additions and 27 deletions
|
|
@ -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' : '');
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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<string, IconItem> = 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<string, IconItem> = 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<void> {
|
||||
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<string, IconItem> = {};
|
||||
Object.values(this.plugin.settings.customIcons || {}).forEach(it => {
|
||||
this.getCustomIconList().forEach(it => {
|
||||
if (it.linkType !== icon.linkType) {
|
||||
newMap[it.id] = it;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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({
|
||||
|
|
|
|||
18
src/ui.ts
18
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);
|
||||
|
|
|
|||
|
|
@ -15,7 +15,8 @@
|
|||
"DOM",
|
||||
"ES5",
|
||||
"ES6",
|
||||
"ES7"
|
||||
"ES7",
|
||||
"ES2017"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
|
|
|
|||
Loading…
Reference in a new issue