From 918000749d7cc4dc0363f54266094540d4e9a53c Mon Sep 17 00:00:00 2001 From: a-phe-lei-a <12548652+a-phe-lei-a@users.noreply.github.com> Date: Mon, 21 Apr 2025 09:39:02 +0200 Subject: [PATCH 1/2] [FIX]: Bump rollup version and sanitize highlighter names --- package-lock.json | 94 +++++++++++++++++++++------------------ package.json | 2 +- src/icons/customIcons.ts | 3 +- src/plugin/main.ts | 5 ++- src/ui/highlighterMenu.ts | 4 +- src/utils/util.ts | 10 +++++ 6 files changed, 70 insertions(+), 48 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5a30e39..6c666c1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,7 +24,7 @@ "@types/node": "^14.14.37", "@types/sortablejs": "^1.13.0", "obsidian": "^0.16.0", - "rollup": "^2.32.1", + "rollup": "^2.79.2", "tslib": "^2.2.0", "typescript": "^4.2.4" } @@ -260,11 +260,12 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "license": "MIT", "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -403,9 +404,10 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -548,6 +550,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -611,21 +614,23 @@ } }, "node_modules/micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "license": "MIT", "dependencies": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" + "braces": "^3.0.3", + "picomatch": "^2.3.1" }, "engines": { "node": ">=8.6" } }, "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -700,9 +705,10 @@ } }, "node_modules/picomatch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "license": "MIT", "engines": { "node": ">=8.6" }, @@ -764,9 +770,10 @@ } }, "node_modules/rollup": { - "version": "2.53.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.53.2.tgz", - "integrity": "sha512-1CtEYuS5CRCzFZ7SNW5528SlDlk4VDXIRGwbm/2POQxA/G4+7/crIqJwkmnj8Q/74hGx4oVlNvh4E1CJQ5hZ6w==", + "version": "2.79.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.2.tgz", + "integrity": "sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==", + "license": "MIT", "bin": { "rollup": "dist/bin/rollup" }, @@ -870,6 +877,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -1113,11 +1121,11 @@ } }, "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "requires": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" } }, "builtin-modules": { @@ -1220,9 +1228,9 @@ } }, "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "requires": { "to-regex-range": "^5.0.1" } @@ -1385,18 +1393,18 @@ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" }, "micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "requires": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" + "braces": "^3.0.3", + "picomatch": "^2.3.1" } }, "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "requires": { "brace-expansion": "^1.1.7" } @@ -1452,9 +1460,9 @@ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" }, "picomatch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==" + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" }, "queue-microtask": { "version": "1.2.3", @@ -1486,9 +1494,9 @@ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" }, "rollup": { - "version": "2.53.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.53.2.tgz", - "integrity": "sha512-1CtEYuS5CRCzFZ7SNW5528SlDlk4VDXIRGwbm/2POQxA/G4+7/crIqJwkmnj8Q/74hGx4oVlNvh4E1CJQ5hZ6w==", + "version": "2.79.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.2.tgz", + "integrity": "sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==", "requires": { "fsevents": "~2.3.2" } diff --git a/package.json b/package.json index 771862d..bea55d4 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "@types/node": "^14.14.37", "@types/sortablejs": "^1.13.0", "obsidian": "^0.16.0", - "rollup": "^2.32.1", + "rollup": "^2.79.2", "tslib": "^2.2.0", "typescript": "^4.2.4" }, diff --git a/src/icons/customIcons.ts b/src/icons/customIcons.ts index d93dcb5..1d8c75b 100644 --- a/src/icons/customIcons.ts +++ b/src/icons/customIcons.ts @@ -1,6 +1,7 @@ import { addIcon } from "obsidian"; import HighlightrPlugin from "src/plugin/main"; import { HighlightrSettings } from "src/settings/settingsData"; +import { sanitizeForClassName } from "src/utils/util"; const icons: Record = { "highlightr-eraser": ``, @@ -18,7 +19,7 @@ export function createHighlighterIcons( const highlighterIcons: Record = {}; for (const key of plugin.settings.highlighterOrder) { - let highlighterpen = `highlightr-pen-${key}`.toLowerCase(); + let highlighterpen = `highlightr-pen-${sanitizeForClassName(key)}`; highlighterIcons[ highlighterpen ] = ``; diff --git a/src/plugin/main.ts b/src/plugin/main.ts index c69aa5a..2eeadbe 100644 --- a/src/plugin/main.ts +++ b/src/plugin/main.ts @@ -1,5 +1,5 @@ import { Editor, Menu, Plugin, PluginManifest } from "obsidian"; -import { wait } from "src/utils/util"; +import { wait, sanitizeForClassName } from "src/utils/util"; // Import the function import addIcons from "src/icons/customIcons"; import { HighlightrSettingTab } from "../settings/settingsTab"; import { HighlightrSettings } from "../settings/settingsData"; @@ -151,7 +151,8 @@ export default class HighlightrPlugin extends Plugin { }; Object.keys(commandsMap).forEach((type) => { - let highlighterpen = `highlightr-pen-${highlighterKey}`.toLowerCase(); + // Sanitize the highlighter name for the icon + let highlighterpen = `highlightr-pen-${sanitizeForClassName(highlighterKey)}`; this.addCommand({ id: highlighterKey, name: highlighterKey, diff --git a/src/ui/highlighterMenu.ts b/src/ui/highlighterMenu.ts index ff6989b..425dc0e 100644 --- a/src/ui/highlighterMenu.ts +++ b/src/ui/highlighterMenu.ts @@ -6,6 +6,7 @@ import { EnhancedEditor, EnhancedMenu, } from "src/settings/types"; +import { sanitizeForClassName } from "src/utils/util"; // Import the function const highlighterMenu = ( app: EnhancedApp, @@ -26,7 +27,8 @@ const highlighterMenu = ( settings.highlighterOrder.forEach((highlighter) => { menu.addItem((highlighterItem) => { highlighterItem.setTitle(highlighter); - highlighterItem.setIcon(`highlightr-pen-${highlighter}`.toLowerCase()); + // Sanitize the highlighter name for the icon + highlighterItem.setIcon(`highlightr-pen-${sanitizeForClassName(highlighter)}`); highlighterItem.onClick(() => { app.commands.executeCommandById(`highlightr-plugin:${highlighter}`); }); diff --git a/src/utils/util.ts b/src/utils/util.ts index a188ef4..621bd54 100644 --- a/src/utils/util.ts +++ b/src/utils/util.ts @@ -1,3 +1,13 @@ export async function wait(delay: number) { return new Promise((resolve) => setTimeout(resolve, delay)); } + +export function sanitizeForClassName(name: string): string { + return name + .normalize("NFD") // Separate accents from letters + .replace(/[\u0300-\u036f]/g, "") // Remove accents + .toLowerCase() + .replace(/[^a-z0-9-]+/g, '-') // Replace non-alphanumeric/hyphen with hyphen + .replace(/-+/g, '-') // Collapse multiple hyphens + .replace(/^-+|-+$/g, ''); // Trim leading/trailing hyphens +} From 29653fe96ce19d1896283ec4f7e865289aa8c4de Mon Sep 17 00:00:00 2001 From: a-phe-lei-a <12548652+a-phe-lei-a@users.noreply.github.com> Date: Mon, 21 Apr 2025 14:47:02 +0200 Subject: [PATCH 2/2] update: Enhance color input handling and add highlighter name input functionality --- src/settings/settingsTab.ts | 99 +++++++++++++++++++++++++++++++------ 1 file changed, 84 insertions(+), 15 deletions(-) diff --git a/src/settings/settingsTab.ts b/src/settings/settingsTab.ts index 010ad1c..0eab959 100644 --- a/src/settings/settingsTab.ts +++ b/src/settings/settingsTab.ts @@ -10,6 +10,7 @@ import Pickr from "@simonwep/pickr"; import Sortable from "sortablejs"; import { HIGHLIGHTER_METHODS, HIGHLIGHTER_STYLES } from "./settingsData"; import { setAttributes } from "src/utils/setAttributes"; +import { sanitizeForClassName } from "src/utils/util"; export class HighlightrSettingTab extends PluginSettingTab { plugin: HighlightrPlugin; @@ -155,9 +156,14 @@ export class HighlightrSettingTab extends PluginSettingTab { .on("change", function (color: Pickr.HSVaColor) { colorHex = color.toHEXA().toString(); let newColor; - colorHex.length == 6 - ? (newColor = `${color.toHEXA().toString()}A6`) - : (newColor = color.toHEXA().toString()); + if (colorHex.length === 6) { + newColor = `#${colorHex}A6`; + } else if (colorHex.length === 8) { + newColor = `#${colorHex}`; + } else { + newColor = colorHex; + } + colorInput.inputEl.setAttribute( "style", `background-color: ${newColor}; color: var(--text-normal);` @@ -168,16 +174,15 @@ export class HighlightrSettingTab extends PluginSettingTab { style: `background-color: ${newColor}; color: var(--text-normal);`, }); input.setText(newColor); - input.textContent = newColor; - input.value = newColor; input.trigger("change"); }) .on("save", function (color: Pickr.HSVaColor, instance: Pickr) { let newColorValue = color.toHEXA().toString(); + if (newColorValue.length === 6 || newColorValue.length === 8) { + newColorValue = `#${newColorValue}`; + } input.setText(newColorValue); - input.textContent = newColorValue; - input.value = newColorValue; input.trigger("change"); instance.hide(); @@ -191,10 +196,19 @@ export class HighlightrSettingTab extends PluginSettingTab { .setIcon("highlightr-save") .setTooltip("Save") .onClick(async (buttonEl: any) => { - let color = colorInput.inputEl.value.replace(" ", "-"); - let value = valueInput.inputEl.value; + let color = colorInput.inputEl.value.trim(); + let value = valueInput.inputEl.value.trim(); + + if (value && !value.startsWith('#') && /^[0-9a-fA-F]{6,8}$/.test(value)) { + value = `#${value}`; + } if (color && value) { + if (!/^#[0-9a-fA-F]{6,8}$/i.test(value)) { + new Notice("Invalid hex code format. Use #RRGGBB or #RRGGBBAA."); + return; + } + if (!this.plugin.settings.highlighterOrder.includes(color)) { this.plugin.settings.highlighterOrder.push(color); this.plugin.settings.highlighters[color] = value; @@ -208,11 +222,13 @@ export class HighlightrSettingTab extends PluginSettingTab { new Notice("This color already exists"); } } - color && !value - ? new Notice("Highlighter hex code missing") - : !color && value - ? new Notice("Highlighter name missing") - : new Notice("Highlighter values missing"); // else + if (!color && !value) { + new Notice("Highlighter name and hex code missing"); + } else if (!color) { + new Notice("Highlighter name missing"); + } else if (!value) { + new Notice("Highlighter hex code missing"); + } }); }); @@ -246,10 +262,58 @@ export class HighlightrSettingTab extends PluginSettingTab { colorIcon.addClass("highlighter-setting-icon"); colorIcon.innerHTML = icon; + const nameInput = new TextComponent(settingItem) + .setValue(highlighter) + .setPlaceholder("Highlighter name"); + new Setting(settingItem) .setClass("highlighter-setting-item") - .setName(highlighter) .setDesc(this.plugin.settings.highlighters[highlighter]) + .addButton((button) => { + button + .setClass("HighlightrSettingsButton") + .setIcon("highlightr-save") + .setTooltip("Save Name") + .onClick(async () => { + const oldName = highlighter; + const newName = nameInput.getValue().trim(); + const colorValue = this.plugin.settings.highlighters[oldName]; + + if (!newName) { + new Notice("Highlighter name cannot be empty."); + return; + } + + if (newName === oldName) { + return; + } + + if (this.plugin.settings.highlighterOrder.includes(newName)) { + new Notice(`Highlighter name "${newName}" already exists.`); + return; + } + + delete this.plugin.settings.highlighters[oldName]; + this.plugin.settings.highlighters[newName] = colorValue; + + const index = this.plugin.settings.highlighterOrder.indexOf(oldName); + if (index > -1) { + this.plugin.settings.highlighterOrder[index] = newName; + } + + (this.app as any).commands.removeCommand( + `highlightr-plugin:${oldName}` + ); + + setTimeout(() => { + dispatchEvent(new Event("Highlightr-NewCommand")); + }, 100); + + await this.plugin.saveSettings(); + new Notice(`Renamed "${oldName}" to "${newName}"`); + this.display(); + }); + }) .addButton((button) => { button .setClass("HighlightrSettingsButton") @@ -271,6 +335,11 @@ export class HighlightrSettingTab extends PluginSettingTab { }); }); + settingItem + .querySelector(".setting-item-info .setting-item-name") + ?.prepend(nameInput.inputEl); + nameInput.inputEl.addClass("highlighter-name-input"); + const a = createEl("a"); a.setAttribute("href", ""); });