("allowedHtmlTags");
+
+ const parsedValue = useMemo(() => {
+ return allowedHtmlTags.join(" ");
+ }, allowedHtmlTags);
+
+ return (
+
+ {t("import.html_import_tags.description")}
+
+
+ )
}
\ No newline at end of file
diff --git a/apps/client/src/widgets/type_widgets/options/other/html_import_tags.ts b/apps/client/src/widgets/type_widgets/options/other/html_import_tags.ts
deleted file mode 100644
index 0dd140732..000000000
--- a/apps/client/src/widgets/type_widgets/options/other/html_import_tags.ts
+++ /dev/null
@@ -1,176 +0,0 @@
-import OptionsWidget from "../options_widget.js";
-import { t } from "../../../../services/i18n.js";
-import type { OptionMap } from "@triliumnext/commons";
-
-// TODO: Deduplicate with src/services/html_sanitizer once there is a commons project between client and server.
-export const DEFAULT_ALLOWED_TAGS = [
- "h1",
- "h2",
- "h3",
- "h4",
- "h5",
- "h6",
- "blockquote",
- "p",
- "a",
- "ul",
- "ol",
- "li",
- "b",
- "i",
- "strong",
- "em",
- "strike",
- "s",
- "del",
- "abbr",
- "code",
- "hr",
- "br",
- "div",
- "table",
- "thead",
- "caption",
- "tbody",
- "tfoot",
- "tr",
- "th",
- "td",
- "pre",
- "section",
- "img",
- "figure",
- "figcaption",
- "span",
- "label",
- "input",
- "details",
- "summary",
- "address",
- "aside",
- "footer",
- "header",
- "hgroup",
- "main",
- "nav",
- "dl",
- "dt",
- "menu",
- "bdi",
- "bdo",
- "dfn",
- "kbd",
- "mark",
- "q",
- "time",
- "var",
- "wbr",
- "area",
- "map",
- "track",
- "video",
- "audio",
- "picture",
- "del",
- "ins",
- "en-media", // for ENEX import
- // Additional tags (https://github.com/TriliumNext/Trilium/issues/567)
- "acronym",
- "article",
- "big",
- "button",
- "cite",
- "col",
- "colgroup",
- "data",
- "dd",
- "fieldset",
- "form",
- "legend",
- "meter",
- "noscript",
- "option",
- "progress",
- "rp",
- "samp",
- "small",
- "sub",
- "sup",
- "template",
- "textarea",
- "tt"
-];
-
-const TPL = /*html*/`
-`;
-
-export default class HtmlImportTagsOptions extends OptionsWidget {
-
- private $allowedTags!: JQuery;
- private $resetButton!: JQuery;
-
- doRender() {
- this.$widget = $(TPL);
- this.contentSized();
-
- this.$allowedTags = this.$widget.find(".allowed-html-tags");
- this.$resetButton = this.$widget.find(".reset-to-default");
-
- this.$allowedTags.on("change", () => this.saveTags());
- this.$resetButton.on("click", () => this.resetToDefault());
-
- // Load initial tags
- this.refresh();
- }
-
- async optionsLoaded(options: OptionMap) {
- try {
- if (options.allowedHtmlTags) {
- const tags = JSON.parse(options.allowedHtmlTags);
- this.$allowedTags.val(tags.join(" "));
- } else {
- // If no tags are set, show the defaults
- this.$allowedTags.val(DEFAULT_ALLOWED_TAGS.join(" "));
- }
- } catch (e) {
- console.error("Could not load HTML tags:", e);
- // On error, show the defaults
- this.$allowedTags.val(DEFAULT_ALLOWED_TAGS.join(" "));
- }
- }
-
- async saveTags() {
- const tagsText = String(this.$allowedTags.val()) || "";
- const tags = tagsText
- .split(/[\n,\s]+/) // Split on newlines, commas, or spaces
- .map((tag) => tag.trim())
- .filter((tag) => tag.length > 0);
-
- await this.updateOption("allowedHtmlTags", JSON.stringify(tags));
- }
-
- async resetToDefault() {
- this.$allowedTags.val(DEFAULT_ALLOWED_TAGS.join("\n")); // Use actual newline
- await this.saveTags();
- }
-}
diff --git a/apps/server/src/services/html_sanitizer.ts b/apps/server/src/services/html_sanitizer.ts
index da707b7c3..79d80033f 100644
--- a/apps/server/src/services/html_sanitizer.ts
+++ b/apps/server/src/services/html_sanitizer.ts
@@ -1,6 +1,7 @@
import sanitizeHtml from "sanitize-html";
import { sanitizeUrl } from "@braintree/sanitize-url";
import optionService from "./options.js";
+import { SANITIZER_DEFAULT_ALLOWED_TAGS } from "@triliumnext/commons";
// Be consistent with `ALLOWED_PROTOCOLS` in `src\public\app\services\link.js`
// TODO: Deduplicate with client once we can.
@@ -12,105 +13,6 @@ export const ALLOWED_PROTOCOLS = [
'mid'
];
-// Default list of allowed HTML tags
-export const DEFAULT_ALLOWED_TAGS = [
- "h1",
- "h2",
- "h3",
- "h4",
- "h5",
- "h6",
- "blockquote",
- "p",
- "a",
- "ul",
- "ol",
- "li",
- "b",
- "i",
- "strong",
- "em",
- "strike",
- "s",
- "del",
- "abbr",
- "code",
- "hr",
- "br",
- "div",
- "table",
- "thead",
- "caption",
- "tbody",
- "tfoot",
- "tr",
- "th",
- "td",
- "pre",
- "section",
- "img",
- "figure",
- "figcaption",
- "span",
- "label",
- "input",
- "details",
- "summary",
- "address",
- "aside",
- "footer",
- "header",
- "hgroup",
- "main",
- "nav",
- "dl",
- "dt",
- "menu",
- "bdi",
- "bdo",
- "dfn",
- "kbd",
- "mark",
- "q",
- "time",
- "var",
- "wbr",
- "area",
- "map",
- "track",
- "video",
- "audio",
- "picture",
- "del",
- "ins",
- "en-media", // for ENEX import
- // Additional tags (https://github.com/TriliumNext/Trilium/issues/567)
- "acronym",
- "article",
- "big",
- "button",
- "cite",
- "col",
- "colgroup",
- "data",
- "dd",
- "fieldset",
- "form",
- "legend",
- "meter",
- "noscript",
- "option",
- "progress",
- "rp",
- "samp",
- "small",
- "sub",
- "sup",
- "template",
- "textarea",
- "tt"
-] as const;
-
// intended mainly as protection against XSS via import
// secondarily, it (partly) protects against "CSS takeover"
// sanitize also note titles, label values etc. - there are so many usages which make it difficult
@@ -138,7 +40,7 @@ function sanitize(dirtyHtml: string) {
allowedTags = JSON.parse(optionService.getOption("allowedHtmlTags"));
} catch (e) {
// Fallback to default list if option doesn't exist or is invalid
- allowedTags = DEFAULT_ALLOWED_TAGS;
+ allowedTags = SANITIZER_DEFAULT_ALLOWED_TAGS;
}
const colorRegex = [/^#(0x)?[0-9a-f]+$/i, /^rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/, /^hsl\(\s*(\d{1,3})\s*,\s*(\d{1,3})%\s*,\s*(\d{1,3})%\s*\)$/];
diff --git a/apps/server/src/services/options_init.ts b/apps/server/src/services/options_init.ts
index dc2b4b268..91fcf25ca 100644
--- a/apps/server/src/services/options_init.ts
+++ b/apps/server/src/services/options_init.ts
@@ -4,8 +4,7 @@ import { randomSecureToken, isWindows } from "./utils.js";
import log from "./log.js";
import dateUtils from "./date_utils.js";
import keyboardActions from "./keyboard_actions.js";
-import type { KeyboardShortcutWithRequiredActionName, OptionMap, OptionNames } from "@triliumnext/commons";
-import { DEFAULT_ALLOWED_TAGS } from "./html_sanitizer.js";
+import { SANITIZER_DEFAULT_ALLOWED_TAGS, type KeyboardShortcutWithRequiredActionName, type OptionMap, type OptionNames } from "@triliumnext/commons";
function initDocumentOptions() {
optionService.createOption("documentId", randomSecureToken(16), false);
@@ -187,7 +186,7 @@ const defaultOptions: DefaultOption[] = [
{ name: "backgroundEffects", value: "true", isSynced: false },
{
name: "allowedHtmlTags",
- value: JSON.stringify(DEFAULT_ALLOWED_TAGS),
+ value: JSON.stringify(SANITIZER_DEFAULT_ALLOWED_TAGS),
isSynced: true
},
diff --git a/packages/commons/src/index.ts b/packages/commons/src/index.ts
index 151924c8f..432990bc0 100644
--- a/packages/commons/src/index.ts
+++ b/packages/commons/src/index.ts
@@ -7,3 +7,4 @@ export * from "./lib/test-utils.js";
export * from "./lib/mime_type.js";
export * from "./lib/bulk_actions.js";
export * from "./lib/server_api.js";
+export * from "./lib/shared_constants.js";
diff --git a/packages/commons/src/lib/shared_constants.ts b/packages/commons/src/lib/shared_constants.ts
new file mode 100644
index 000000000..00b179d33
--- /dev/null
+++ b/packages/commons/src/lib/shared_constants.ts
@@ -0,0 +1,98 @@
+// Default list of allowed HTML tags
+export const SANITIZER_DEFAULT_ALLOWED_TAGS = [
+ "h1",
+ "h2",
+ "h3",
+ "h4",
+ "h5",
+ "h6",
+ "blockquote",
+ "p",
+ "a",
+ "ul",
+ "ol",
+ "li",
+ "b",
+ "i",
+ "strong",
+ "em",
+ "strike",
+ "s",
+ "del",
+ "abbr",
+ "code",
+ "hr",
+ "br",
+ "div",
+ "table",
+ "thead",
+ "caption",
+ "tbody",
+ "tfoot",
+ "tr",
+ "th",
+ "td",
+ "pre",
+ "section",
+ "img",
+ "figure",
+ "figcaption",
+ "span",
+ "label",
+ "input",
+ "details",
+ "summary",
+ "address",
+ "aside",
+ "footer",
+ "header",
+ "hgroup",
+ "main",
+ "nav",
+ "dl",
+ "dt",
+ "menu",
+ "bdi",
+ "bdo",
+ "dfn",
+ "kbd",
+ "mark",
+ "q",
+ "time",
+ "var",
+ "wbr",
+ "area",
+ "map",
+ "track",
+ "video",
+ "audio",
+ "picture",
+ "del",
+ "ins",
+ "en-media", // for ENEX import
+ // Additional tags (https://github.com/TriliumNext/Trilium/issues/567)
+ "acronym",
+ "article",
+ "big",
+ "button",
+ "cite",
+ "col",
+ "colgroup",
+ "data",
+ "dd",
+ "fieldset",
+ "form",
+ "legend",
+ "meter",
+ "noscript",
+ "option",
+ "progress",
+ "rp",
+ "samp",
+ "small",
+ "sub",
+ "sup",
+ "template",
+ "textarea",
+ "tt"
+] as const;