From d5574a0a4493080e70b5aa26861d05f2b43e6f2b Mon Sep 17 00:00:00 2001 From: Albrecht Degering Date: Thu, 23 Jul 2026 00:29:21 +0200 Subject: [PATCH] feat: add shared Toolbox header and themes --- CHANGELOG.md | 14 ++ README.md | 9 +- SOURCE.md | 4 +- THIRD_PARTY_NOTICES.md | 3 + package-lock.json | 45 +++-- package.json | 9 +- public/toolbox-app.json | 9 +- src/App.tsx | 17 +- src/components/HelpDialog.tsx | 16 +- src/editor/CodeMirrorEditor.tsx | 98 +++++++++- src/styles.css | 289 +++++++++++++++++++----------- src/toolboxApp.ts | 7 - src/version.ts | 2 +- tests/editorTheme.test.tsx | 48 +++++ tests/releasePackaging.test.ts | 5 + tests/toolboxIntegration.test.tsx | 52 +++++- 16 files changed, 451 insertions(+), 176 deletions(-) create mode 100644 tests/editorTheme.test.tsx diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ac5d48..0be9a35 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,19 @@ # Changelog +## 0.4.0 + +### Added + +- Added the unified Toolbox top bar with a centered app title, standard Help and Gitea source controls, Personalize, and Apps switching. +- Added persistent System, Light, and Dark appearance choices shared with the Toolbox Portal. +- Added a real dark CodeMirror configuration with dark editor surfaces, gutters, active lines, and syntax highlighting. + +### Changed + +- Upgraded Toolbox Contract, React Shell, and Testkit dependencies to 0.2.0. +- Replaced the app-specific Help and Source actions with the shared shell controls and manifest repository fallback. +- Converted workbench controls, cards, diagnostics, dialogs, tables, and editor chrome to semantic theme variables. + ## 0.3.2 ### Added diff --git a/README.md b/README.md index 1f0e10a..aa51c3e 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ file dialogs where available. XSLT is executable code, however: a trusted stylesheet may access browser or network resources, so processing is not described as guaranteed local-only. -The application is independently deployable and also implements Toolbox Contract v1. When launched with a same-origin `?toolbox=` context, the shared application shell adds toolbox navigation and an application switcher; without that context, the same build runs standalone. +The application is independently deployable and also implements Toolbox Contract v1. The shared top bar keeps the app title centered and provides Help, its Gitea source link, persistent System/Light/Dark personalization, and app selection. When launched with a same-origin `?toolbox=` context, the Apps menu includes the catalogue tools; without that context, the same build runs standalone. ## Features in this MVP @@ -17,6 +17,7 @@ The application is independently deployable and also implements Toolbox Contract - CodeMirror editors with: - line numbers - XML syntax highlighting + - theme-aware light and dark editor, gutter, and highlighting palettes - editor undo/redo - cut/copy/paste helpers - find support via CodeMirror shortcuts @@ -36,7 +37,7 @@ The application is independently deployable and also implements Toolbox Contract - Confirmation dialog before destructive overwrites - LocalStorage persistence - Approximate “explain transformation” table after a run -- Shared toolbox shell with standalone fallback, application switching, and the XSLT-specific Help action +- Shared toolbox shell with standalone fallback, unified Help/source controls, personalization, and application switching - Relocatable static output for deployment at root or nested paths ## SaxonJS note @@ -101,6 +102,10 @@ Toolbox mode is contextual rather than a separate build: An unavailable or invalid catalogue falls back to standalone operation. +## Appearance + +Use **Personalize** in the shared top bar to select System, Light, or Dark. The choice is stored only in this browser using the same preference record as the Toolbox Portal, so it follows you between current Toolbox apps on the same origin. System mode follows the operating-system color preference. CodeMirror is reconfigured when the effective palette changes, including its editor background, gutters, active line, and XML syntax colors. + ## Release archive After a successful build, create the deterministic application ZIP and SHA-256 sidecar with: diff --git a/SOURCE.md b/SOURCE.md index a2502c2..214fc35 100644 --- a/SOURCE.md +++ b/SOURCE.md @@ -1,8 +1,8 @@ # Corresponding source -The corresponding application source for XSLT tools 0.3.2 is available at: +The corresponding application source for XSLT tools 0.4.0 is available at: - + The XSLT tools application source is licensed under AGPL-3.0-only. This release also contains third-party components under separate terms. See diff --git a/THIRD_PARTY_NOTICES.md b/THIRD_PARTY_NOTICES.md index 6dbb529..f639b9f 100644 --- a/THIRD_PARTY_NOTICES.md +++ b/THIRD_PARTY_NOTICES.md @@ -6,6 +6,9 @@ from the XSLT tools application's AGPL-3.0-only licence. - The vendored SaxonJS browser distribution is proprietary software available under Saxonica's free-of-charge terms. Its complete supplied licence is at `LICENSES/SaxonJS-LICENSE.txt` in release archives. +- The CodeMirror packages, including the One Dark editor theme, are distributed + under the MIT licence; their installed licence files are included in release + archives. - Runtime npm dependencies retain their own licences. Release archives include the installed licence and notice files for every production dependency below `LICENSES/npm/`, including the Apache-2.0 Toolbox Contract and React shell diff --git a/package-lock.json b/package-lock.json index 49cb72b..dc2b79d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,21 +1,22 @@ { "name": "xsl-tools", - "version": "0.3.2", + "version": "0.4.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "xsl-tools", - "version": "0.3.2", + "version": "0.4.0", "license": "AGPL-3.0-only", "dependencies": { - "@add-ideas/toolbox-contract": "^0.1.0", - "@add-ideas/toolbox-shell-react": "^0.1.0", + "@add-ideas/toolbox-contract": "0.2.0", + "@add-ideas/toolbox-shell-react": "0.2.0", "@codemirror/commands": "^6.8.1", "@codemirror/lang-xml": "^6.1.0", "@codemirror/lint": "^6.8.5", "@codemirror/search": "^6.5.10", "@codemirror/state": "^6.5.2", + "@codemirror/theme-one-dark": "6.1.3", "@codemirror/view": "^6.38.3", "bootstrap-icons": "^1.11.3", "codemirror": "^6.0.1", @@ -23,7 +24,7 @@ "react-dom": "^19.2.6" }, "devDependencies": { - "@add-ideas/toolbox-testkit": "^0.1.0", + "@add-ideas/toolbox-testkit": "0.2.0", "@eslint/js": "^10.0.1", "@testing-library/react": "^16.3.2", "@testing-library/user-event": "^14.6.1", @@ -45,18 +46,18 @@ } }, "node_modules/@add-ideas/toolbox-contract": { - "version": "0.1.1", - "resolved": "https://git.add-ideas.de/api/packages/zemion/npm/%40add-ideas%2Ftoolbox-contract/-/0.1.1/toolbox-contract-0.1.1.tgz", - "integrity": "sha512-0q2whA5Y4SqG4PNNleXYR8nGbT3UYsZ1x+6ZWVmxuc/WjMxmujhD7ilIISmFzmnNdbyEyv/Zpr+U0fnHqGODqw==", + "version": "0.2.0", + "resolved": "https://git.add-ideas.de/api/packages/zemion/npm/%40add-ideas%2Ftoolbox-contract/-/0.2.0/toolbox-contract-0.2.0.tgz", + "integrity": "sha512-up+wY+ft1L7TbXrflcTeTOwEdcFwHBWFlGFj8skQvcLy5z2mDBpd6/7PVQKDvDTkiODu2npviHm6AFglFw+17Q==", "license": "Apache-2.0" }, "node_modules/@add-ideas/toolbox-shell-react": { - "version": "0.1.1", - "resolved": "https://git.add-ideas.de/api/packages/zemion/npm/%40add-ideas%2Ftoolbox-shell-react/-/0.1.1/toolbox-shell-react-0.1.1.tgz", - "integrity": "sha512-Di2mu1BoJrWJg4/v5jDExROXDpvLXorlUgqcsBQV8ea/LklKoBFTAfgTkk/23HZ2BzixyMIjrhl9kD507s+iPQ==", + "version": "0.2.0", + "resolved": "https://git.add-ideas.de/api/packages/zemion/npm/%40add-ideas%2Ftoolbox-shell-react/-/0.2.0/toolbox-shell-react-0.2.0.tgz", + "integrity": "sha512-qYR+OBXX8rfB+BYCsUbpiCzo2xK12SIPWVNXHre158Da5uT6usr8rRvp5qa5u2oQJ50PNzlXyXMyTeRp0Vz5wg==", "license": "Apache-2.0", "dependencies": { - "@add-ideas/toolbox-contract": "0.1.1" + "@add-ideas/toolbox-contract": "0.2.0" }, "peerDependencies": { "react": ">=18 <20", @@ -64,13 +65,13 @@ } }, "node_modules/@add-ideas/toolbox-testkit": { - "version": "0.1.1", - "resolved": "https://git.add-ideas.de/api/packages/zemion/npm/%40add-ideas%2Ftoolbox-testkit/-/0.1.1/toolbox-testkit-0.1.1.tgz", - "integrity": "sha512-o+H7LfM7ipdgmYz18S0lLuN6JsXUR+8ubAbcjTWTk8rSqNfp1JyeoRHOPbJVEHXrQwIFe/OB86UzRpex2gnKUQ==", + "version": "0.2.0", + "resolved": "https://git.add-ideas.de/api/packages/zemion/npm/%40add-ideas%2Ftoolbox-testkit/-/0.2.0/toolbox-testkit-0.2.0.tgz", + "integrity": "sha512-+BSiWgS0F3vpjPgty9B4UtfdZTRbo97ZElb2BSb0ry57fS3cE7w7pfJW1Mzk/gV1/JChspw3JBY+4ZJDBhkiFw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@add-ideas/toolbox-contract": "0.1.1" + "@add-ideas/toolbox-contract": "0.2.0" }, "bin": { "toolbox-check": "dist/cli.js" @@ -473,6 +474,18 @@ "@marijn/find-cluster-break": "^1.0.0" } }, + "node_modules/@codemirror/theme-one-dark": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/@codemirror/theme-one-dark/-/theme-one-dark-6.1.3.tgz", + "integrity": "sha512-NzBdIvEJmx6fjeremiGp3t/okrLPYT0d9orIc7AFun8oZcRk58aejkqhv6spnz4MLAevrKNPMQYXEWMg4s+sKA==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/highlight": "^1.0.0" + } + }, "node_modules/@codemirror/view": { "version": "6.43.0", "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.43.0.tgz", diff --git a/package.json b/package.json index a3fa9bd..b79e6ab 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "xsl-tools", - "version": "0.3.2", + "version": "0.4.0", "private": true, "type": "module", "license": "AGPL-3.0-only", @@ -28,13 +28,14 @@ "clean": "rm -rf dist node_modules/.vite coverage" }, "dependencies": { - "@add-ideas/toolbox-contract": "^0.1.0", - "@add-ideas/toolbox-shell-react": "^0.1.0", + "@add-ideas/toolbox-contract": "0.2.0", + "@add-ideas/toolbox-shell-react": "0.2.0", "@codemirror/commands": "^6.8.1", "@codemirror/lang-xml": "^6.1.0", "@codemirror/lint": "^6.8.5", "@codemirror/search": "^6.5.10", "@codemirror/state": "^6.5.2", + "@codemirror/theme-one-dark": "6.1.3", "@codemirror/view": "^6.38.3", "bootstrap-icons": "^1.11.3", "codemirror": "^6.0.1", @@ -42,7 +43,7 @@ "react-dom": "^19.2.6" }, "devDependencies": { - "@add-ideas/toolbox-testkit": "^0.1.0", + "@add-ideas/toolbox-testkit": "0.2.0", "@eslint/js": "^10.0.1", "@testing-library/react": "^16.3.2", "@testing-library/user-event": "^14.6.1", diff --git a/public/toolbox-app.json b/public/toolbox-app.json index 906f76d..57f2a5c 100644 --- a/public/toolbox-app.json +++ b/public/toolbox-app.json @@ -3,19 +3,12 @@ "schemaVersion": 1, "id": "de.add-ideas.xslt-tools", "name": "XSLT tools", - "version": "0.3.2", + "version": "0.4.0", "description": "Browser-based XML and XSLT transformations with executable-stylesheet trust controls.", "entry": "./", "icon": "./favicon.svg", "categories": ["documents", "xml", "xslt"], "tags": ["transform", "validate", "format", "explain"], - "actions": [ - { - "id": "source", - "label": "Source", - "url": "https://git.add-ideas.de/zemion/xslt-tools/src/tag/v0.3.2" - } - ], "assets": ["./vendor/saxon/SaxonJS2.js", "./vendor/saxon/LICENSE.txt"], "integration": { "contextVersion": 1, diff --git a/src/App.tsx b/src/App.tsx index 73bd33a..6de5fec 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -536,18 +536,11 @@ const App: React.FC = () => { -