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); + }); + }); +});