diff --git a/admin/src/index.css b/admin/src/index.css
index a7330448e..a038888d7 100644
--- a/admin/src/index.css
+++ b/admin/src/index.css
@@ -263,6 +263,7 @@ td, th {
outline: none;
width: 100%;
resize: none;
+ font-family: monospace;
}
#response {
diff --git a/admin/src/pages/SettingsPage.tsx b/admin/src/pages/SettingsPage.tsx
index 94d7d25ad..f781f67e1 100644
--- a/admin/src/pages/SettingsPage.tsx
+++ b/admin/src/pages/SettingsPage.tsx
@@ -1,12 +1,12 @@
import {useStore} from "../store/store.ts";
-import {isJSONClean} from "../utils/utils.ts";
+import {isJSONClean, cleanComments} from "../utils/utils.ts";
import {Trans} from "react-i18next";
import {IconButton} from "../components/IconButton.tsx";
import {RotateCw, Save} from "lucide-react";
export const SettingsPage = ()=>{
const settingsSocket = useStore(state=>state.settingsSocket)
- const settings = useStore(state=>state.settings)
+ const settings = cleanComments(useStore(state=>state.settings))
return
diff --git a/admin/src/utils/utils.ts b/admin/src/utils/utils.ts
index 2e8f52a05..960de455f 100644
--- a/admin/src/utils/utils.ts
+++ b/admin/src/utils/utils.ts
@@ -1,5 +1,14 @@
-const minify = (json: string)=>{
+export const cleanComments = (json: string|undefined)=>{
+ if (json !== undefined){
+ json = json.replace(/\/\*.*?\*\//g, ""); // remove single line comments
+ json = json.replace(/ *\/\*.*(.|\n)*?\*\//g, ""); // remove multi line comments
+ json = json.replace(/[ \t]+$/gm, ""); // trim trailing spaces
+ json = json.replace(/^(\n)/gm, ""); // remove empty lines
+ }
+ return json;
+}
+export const minify = (json: string)=>{
let tokenizer = /"|(\/\*)|(\*\/)|(\/\/)|\n|\r/g,
in_string = false,
in_multiline_comment = false,
@@ -49,9 +58,6 @@ const minify = (json: string)=>{
return new_str.join("");
}
-
-
-
export const isJSONClean = (data: string) => {
let cleanSettings = minify(data);
// this is a bit naive. In theory some key/value might contain the sequences ',]' or ',}'
diff --git a/package.json b/package.json
index 64164995b..fd275c913 100644
--- a/package.json
+++ b/package.json
@@ -15,6 +15,7 @@
"scripts": {
"lint": "pnpm --filter ep_etherpad-lite run lint",
"test": "pnpm --filter ep_etherpad-lite run test",
+ "test-utils": "pnpm --filter ep_etherpad-lite run test-utils",
"test-container": "pnpm --filter ep_etherpad-lite run test-container",
"dev": "pnpm --filter ep_etherpad-lite run dev",
"prod": "pnpm --filter ep_etherpad-lite run prod",
diff --git a/src/package.json b/src/package.json
index e3a858656..fd3a737b1 100644
--- a/src/package.json
+++ b/src/package.json
@@ -122,6 +122,7 @@
"scripts": {
"lint": "eslint .",
"test": "mocha --import=tsx --timeout 120000 --recursive tests/backend/specs/**.ts ../node_modules/ep_*/static/tests/backend/specs/**",
+ "test-utils": "mocha --import=tsx --timeout 5000 --recursive tests/backend/specs/*utils.ts",
"test-container": "mocha --import=tsx --timeout 5000 tests/container/specs/api",
"dev": "node --require tsx/cjs node/server.ts",
"prod": "node --require tsx/cjs node/server.ts",
diff --git a/src/tests/backend/specs/admin_utils.ts b/src/tests/backend/specs/admin_utils.ts
new file mode 100644
index 000000000..bd8690445
--- /dev/null
+++ b/src/tests/backend/specs/admin_utils.ts
@@ -0,0 +1,38 @@
+'use strict';
+
+
+import {strict as assert} from "assert";
+import {cleanComments, minify} from "../../../../admin/src/utils/utils.js";
+
+const fs = require('fs');
+const fsp = fs.promises;
+let template:string;
+
+describe(__filename, function () {
+ before(async function () {
+ template = await fsp.readFile('../settings.json.template', 'utf8')
+ });
+ describe('adminUtils', function () {
+ it('cleanComments function empty', async function () {
+ assert.equal(cleanComments(""), "");
+ });
+ it('cleanComments function HelloWorld no comment', async function () {
+ assert.equal(cleanComments("HelloWorld"), "HelloWorld");
+ });
+ it('cleanComments function HelloWorld with comment', async function () {
+ assert.equal(cleanComments("Hello/*abc*/World/*def*/"), "HelloWorld");
+ });
+ it('cleanComments function HelloWorld with comment and multiline', async function () {
+ assert.equal(cleanComments("Hello \n/*abc\nxyz*/World/*def*/"), "Hello\nWorld");
+ });
+ it('cleanComments function HelloWorld with multiple line breaks', async function () {
+ assert.equal(cleanComments(" \nHello \n \n \nWorld/*def*/"), "Hello\nWorld");
+ });
+ it('cleanComments function same after minified', async function () {
+ assert.equal(minify(template), minify(cleanComments(template)!));
+ });
+ it('minified results are smaller', async function () {
+ assert.equal(minify(template).length < template.length, true);
+ });
+ });
+});