Ensure unique selectors for loaded extension files

f869b26664516c6a67068c69d3a765c3c5c817b2

Cohee <18619528+Cohee1207@users.noreply.github.com>

2 files changed, +17 -5Showing whitespace changes
public/scripts/extensions.js+7 -5
@@ -4,7 +4,7 @@ import { eventSource, event_types, saveSettings, saveSettingsDebounced, getReque
4import { showLoader } from './loader.js';4import { showLoader } from './loader.js';
5import { POPUP_RESULT, POPUP_TYPE, Popup, callGenericPopup } from './popup.js';5import { POPUP_RESULT, POPUP_TYPE, Popup, callGenericPopup } from './popup.js';
6import { renderTemplate, renderTemplateAsync } from './templates.js';6import { renderTemplate, renderTemplateAsync } from './templates.js';
7import { delay, isSubsetOf, setValueByPath } from './utils.js';7import { delay, isSubsetOf, sanitizeSelector, setValueByPath } from './utils.js';
8import { getContext } from './st-context.js';8import { getContext } from './st-context.js';
9import { isAdmin } from './user.js';9import { isAdmin } from './user.js';
10import { t } from './i18n.js';10import { t } from './i18n.js';
@@ -509,10 +509,11 @@ function addExtensionStyle(name, manifest) {
509509
510 return new Promise((resolve, reject) => {510 return new Promise((resolve, reject) => {
511 const url = `/scripts/extensions/${name}/${manifest.css}`;511 const url = `/scripts/extensions/${name}/${manifest.css}`;
512 const id = sanitizeSelector(`${name}-css`);
512513
513 if ($(`link[id="${name}"]`).length === 0) {514 if ($(`link[id="${id}"]`).length === 0) {
514 const link = document.createElement('link');515 const link = document.createElement('link');
515 link.id = name;516 link.id = id;
516 link.rel = 'stylesheet';517 link.rel = 'stylesheet';
517 link.type = 'text/css';518 link.type = 'text/css';
518 link.href = url;519 link.href = url;
@@ -540,11 +541,12 @@ function addExtensionScript(name, manifest) {
540541
541 return new Promise((resolve, reject) => {542 return new Promise((resolve, reject) => {
542 const url = `/scripts/extensions/${name}/${manifest.js}`;543 const url = `/scripts/extensions/${name}/${manifest.js}`;
544 const id = sanitizeSelector(`${name}-js`);
543 let ready = false;545 let ready = false;
544546
545 if ($(`script[id="${name}"]`).length === 0) {547 if ($(`script[id="${id}"]`).length === 0) {
546 const script = document.createElement('script');548 const script = document.createElement('script');
547 script.id = name;549 script.id = id;
548 script.type = 'module';550 script.type = 'module';
549 script.src = url;551 script.src = url;
550 script.async = true;552 script.async = true;
public/scripts/utils.js+10 -0
@@ -67,6 +67,16 @@ export function escapeHtml(str) {
67 return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');67 return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
68}68}
6969
70/**
71 * Make string safe for use as a CSS selector.
72 * @param {string} str String to sanitize
73 * @param {string} replacement Replacement for invalid characters
74 * @returns {string} Sanitized string
75 */
76export function sanitizeSelector(str, replacement = '_') {
77 return String(str).replace(/[^a-z0-9_-]/ig, replacement);
78}
79
70export function isValidUrl(value) {80export function isValidUrl(value) {
71 try {81 try {
72 new URL(value);82 new URL(value);