6 Commits
v0.2.0 ... main

20 changed files with 364 additions and 251 deletions

2
.npmrc
View File

@@ -1 +1 @@
@add-ideas:registry=https://git.add-ideas.de/api/packages/zemion/npm/ @add-ideas:registry=https://git.add-ideas.de/api/packages/lotobo/npm/

View File

@@ -1,5 +1,54 @@
# Changelog # Changelog
## 0.3.4 - 2026-07-27
- Move the canonical source, manifest schema links, and package registry from
the personal `zemion` namespace to the `lotobo` (LocalToolBox) Gitea
organization.
- Upgrade the Toolbox contract, React shell, and validation testkit to 0.2.3,
republished from the organization-owned registry without functional shell
changes.
## 0.3.3 - 2026-07-23
- Let the OneNote application use the full width supplied by the shared
Toolbox shell, matching the shell bar's `min(100%, 90rem)` content span
instead of retaining the former 76rem application cap.
## 0.3.2 - 2026-07-23
- Upgrade the Toolbox contract, React shell, and validation testkit to 0.2.2,
pinned to SDK revision `53c40a61ba1581246f65773fcbb1c1cfd31ac98e`.
- Move the Toolbox icon and `add·ideas Toolbox` label to the fixed far-left
block and place Help, the OneNote-specific Gitea source link, Apps, and
Personalize in that order in the fixed far-right cluster while retaining the
centered app title and tagline.
- Use the shared portal-style Personalize appearance panel; catalogue counts
and preference import/export remain portal-only controls.
## 0.3.1 - 2026-07-23
- Upgrade the Toolbox contract, React shell, and validation testkit to 0.2.1.
- Adopt the stable shared top bar: the fixed left cluster contains Personalize,
Apps, the OneNote-specific Gitea source link, and Help; the app title and one
tagline remain centered; and the fixed far-right block contains the Toolbox
icon and `add·ideas Toolbox` label.
## 0.3.0 - 2026-07-23
- Adopt the Toolbox SDK 0.2.0 shared header with standard Help and app-specific
Gitea source controls, centered app identity, Personalize, and Apps menus.
- Apply the shared system, light, and dark appearance choice to the OneNote
reader while retaining authored page fonts, colors, highlights, and ink.
- Scope reader controls so application button styling cannot override the
shared Toolbox header.
## 0.2.1 - 2026-07-22
- Preserve the intrinsic aspect ratio of embedded images when their recorded
display width is reduced to fit the reader, including linked images.
- Allow the page reader to scroll when its Toolbox grid area is constrained.
## 0.2.0 - 2026-07-22 ## 0.2.0 - 2026-07-22
- Open unfragmented FSSHTTPB package-store `.one` sections through the same - Open unfragmented FSSHTTPB package-store `.one` sections through the same

View File

@@ -9,7 +9,14 @@ It is also an independent application in the add·ideas Toolbox contract. The
source uses the Toolbox SDK shell and manifest, builds with Vite `base: './'`, source uses the Toolbox SDK shell and manifest, builds with Vite `base: './'`,
and is delivered to Toolbox Portal as a checksummed static ZIP. and is delivered to Toolbox Portal as a checksummed static ZIP.
## What version 0.2.0 supports Version 0.3.4 uses the stable shared top bar, with the Toolbox icon and
`add·ideas Toolbox` label in a fixed far-left block; the app title and one
tagline centered; and Help, the OneNote source link, Apps, and Personalize in a
fixed far-right cluster. Personalize uses the shared portal-style appearance
panel while catalogue counts and preference import/export stay in the portal.
The application content uses the same `min(100%, 90rem)` span as the shell bar.
## What version 0.3.4 supports
- Desktop revision-store and unfragmented FSSHTTPB package-store `.one` - Desktop revision-store and unfragmented FSSHTTPB package-store `.one`
sections from the tested producer families. sections from the tested producer families.
@@ -80,7 +87,7 @@ supplied through the SDK's `?toolbox=` context mechanism. The app uses the SDK
```sh ```sh
npm run release:artifact npm run release:artifact
(cd release && sha256sum -c onenote-tools-0.2.0.sha256) (cd release && sha256sum -c onenote-tools-0.3.4.sha256)
``` ```
The ZIP root contains the built static app and manifest plus the changelog, The ZIP root contains the built static app and manifest plus the changelog,

View File

@@ -1,8 +1,8 @@
# Corresponding source # Corresponding source
The corresponding source for OneNote Tools 0.2.0 is the `v0.2.0` tag: The corresponding source for OneNote Tools 0.3.4 is the `v0.3.4` tag:
https://git.add-ideas.de/zemion/onenote-tools/src/tag/v0.2.0 https://git.add-ideas.de/lotobo/onenote-tools/src/tag/v0.3.4
Build the release from that tag with Node.js 22 or newer: Build the release from that tag with Node.js 22 or newer:

View File

@@ -2,8 +2,8 @@
The production application uses: The production application uses:
- `@add-ideas/toolbox-contract` 0.1.1, Apache-2.0; - `@add-ideas/toolbox-contract` 0.2.3, Apache-2.0;
- `@add-ideas/toolbox-shell-react` 0.1.1, Apache-2.0; - `@add-ideas/toolbox-shell-react` 0.2.3, Apache-2.0;
- fflate 0.8.3, MIT; - fflate 0.8.3, MIT;
- React, React DOM, and Scheduler, MIT. - React, React DOM, and Scheduler, MIT.

View File

@@ -1,6 +1,6 @@
# Format support # Format support
## Version 0.2.0 support matrix ## Version 0.3.4 support matrix
| Input or feature | Status | Tested evidence and boundary | | Input or feature | Status | Tested evidence and boundary |
| -------------------------------- | -------------------- | ---------------------------------------------------------------------------------------------------- | | -------------------------------- | -------------------- | ---------------------------------------------------------------------------------------------------- |

View File

@@ -1,11 +1,11 @@
# Specifications and pinned references # Specifications and pinned references
Version 0.2.0 records these immutable implementation revisions: Version 0.3.4 records these immutable implementation revisions:
| Repository | Exact revision | Use | | Repository | Exact revision | Use |
| ---------------------------------------------------------------------------------------------------------------------- | ------------------------------------------ | --------------------------------------------------------------------------------------------- | | ---------------------------------------------------------------------------------------------------------------------- | ------------------------------------------ | ---------------------------------------------------------------------------------------------- |
| [`toolbox-sdk`](https://git.add-ideas.de/zemion/toolbox-sdk/src/commit/5e206baf42dfae5a00f2743fb2cc501bb12d9b7a) | `5e206baf42dfae5a00f2743fb2cc501bb12d9b7a` | App contract, React shell, manifest schema/testkit, and nested-path behavior | | [`toolbox-sdk`](https://git.add-ideas.de/lotobo/toolbox-sdk/src/commit/ef2dab4b46c61812c9a877d8a19fe497b4a4630a) | `ef2dab4b46c61812c9a877d8a19fe497b4a4630a` | App contract, React shell, manifest schema/testkit, package registry, and nested-path behavior |
| [`toolbox-portal`](https://git.add-ideas.de/zemion/toolbox-portal/src/commit/d46f1b61fb85a18299b6b8af2148dcd991ef6b05) | `d46f1b61fb85a18299b6b8af2148dcd991ef6b05` | Reviewed ZIP shape, exact checksum lock, independent-app assembly, and nginx deployment model | | [`toolbox-portal`](https://git.add-ideas.de/lotobo/toolbox-portal/src/commit/d46f1b61fb85a18299b6b8af2148dcd991ef6b05) | `d46f1b61fb85a18299b6b8af2148dcd991ef6b05` | Reviewed ZIP shape, exact checksum lock, independent-app assembly, and nginx deployment model |
| [`onenote.rs`](https://github.com/msiemens/onenote.rs/tree/5138a39a3f4e72b840932f9872fecde52fa9da60) | `5138a39a3f4e72b840932f9872fecde52fa9da60` | Selected desktop/FSSHTTPB OneStore and MS-ONE structures adapted into TypeScript | | [`onenote.rs`](https://github.com/msiemens/onenote.rs/tree/5138a39a3f4e72b840932f9872fecde52fa9da60) | `5138a39a3f4e72b840932f9872fecde52fa9da60` | Selected desktop/FSSHTTPB OneStore and MS-ONE structures adapted into TypeScript |
| [`rust-cab`](https://github.com/mdsteele/rust-cab/tree/c5839f5fdfa4c4e7cc9b22f570c79c96af0560e2) | `c5839f5fdfa4c4e7cc9b22f570c79c96af0560e2` | CAB structures, checksum, enumeration/extraction, MSZIP history, and unit fixtures | | [`rust-cab`](https://github.com/mdsteele/rust-cab/tree/c5839f5fdfa4c4e7cc9b22f570c79c96af0560e2) | `c5839f5fdfa4c4e7cc9b22f570c79c96af0560e2` | CAB structures, checksum, enumeration/extraction, MSZIP history, and unit fixtures |
| [`compcol`](https://github.com/KarpelesLab/compcol/tree/04a6db2aa7bd487a89c559631d79d1b384139f50) | `04a6db2aa7bd487a89c559631d79d1b384139f50` | Quantum bit reader, arithmetic models, LZ window, CAB sentinel behavior, and tests | | [`compcol`](https://github.com/KarpelesLab/compcol/tree/04a6db2aa7bd487a89c559631d79d1b384139f50) | `04a6db2aa7bd487a89c559631d79d1b384139f50` | Quantum bit reader, arithmetic models, LZ window, CAB sentinel behavior, and tests |

32
package-lock.json generated
View File

@@ -1,22 +1,22 @@
{ {
"name": "onenote-tools", "name": "onenote-tools",
"version": "0.2.0", "version": "0.3.4",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "onenote-tools", "name": "onenote-tools",
"version": "0.2.0", "version": "0.3.4",
"license": "MPL-2.0 AND LGPL-2.1-only", "license": "MPL-2.0 AND LGPL-2.1-only",
"dependencies": { "dependencies": {
"@add-ideas/toolbox-contract": "0.1.1", "@add-ideas/toolbox-contract": "0.2.3",
"@add-ideas/toolbox-shell-react": "0.1.1", "@add-ideas/toolbox-shell-react": "0.2.3",
"fflate": "^0.8.3", "fflate": "^0.8.3",
"react": "^19.2.6", "react": "^19.2.6",
"react-dom": "^19.2.6" "react-dom": "^19.2.6"
}, },
"devDependencies": { "devDependencies": {
"@add-ideas/toolbox-testkit": "0.1.1", "@add-ideas/toolbox-testkit": "0.2.3",
"@eslint/js": "^10.0.1", "@eslint/js": "^10.0.1",
"@testing-library/jest-dom": "^6.9.1", "@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^16.3.2", "@testing-library/react": "^16.3.2",
@@ -42,18 +42,18 @@
} }
}, },
"node_modules/@add-ideas/toolbox-contract": { "node_modules/@add-ideas/toolbox-contract": {
"version": "0.1.1", "version": "0.2.3",
"resolved": "https://git.add-ideas.de/api/packages/zemion/npm/%40add-ideas%2Ftoolbox-contract/-/0.1.1/toolbox-contract-0.1.1.tgz", "resolved": "https://git.add-ideas.de/api/packages/lotobo/npm/%40add-ideas%2Ftoolbox-contract/-/0.2.3/toolbox-contract-0.2.3.tgz",
"integrity": "sha512-0q2whA5Y4SqG4PNNleXYR8nGbT3UYsZ1x+6ZWVmxuc/WjMxmujhD7ilIISmFzmnNdbyEyv/Zpr+U0fnHqGODqw==", "integrity": "sha512-T0PVSuMT40GjTDfQJhEEY3ZawQq8zz1/ry95JdKI6W39CdLacaRXdGnEpDCMHt+jUbf1Jz7Nat/M5dFCgKVM9A==",
"license": "Apache-2.0" "license": "Apache-2.0"
}, },
"node_modules/@add-ideas/toolbox-shell-react": { "node_modules/@add-ideas/toolbox-shell-react": {
"version": "0.1.1", "version": "0.2.3",
"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", "resolved": "https://git.add-ideas.de/api/packages/lotobo/npm/%40add-ideas%2Ftoolbox-shell-react/-/0.2.3/toolbox-shell-react-0.2.3.tgz",
"integrity": "sha512-Di2mu1BoJrWJg4/v5jDExROXDpvLXorlUgqcsBQV8ea/LklKoBFTAfgTkk/23HZ2BzixyMIjrhl9kD507s+iPQ==", "integrity": "sha512-DT5lQDH48BFkFcmFLZnQh7+Cm73JzBPcmp5WzUXypfkUXpEyDYHzaXgmW4kZ0edSwh4RK4sPmx+JPtK0X4aKCQ==",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@add-ideas/toolbox-contract": "0.1.1" "@add-ideas/toolbox-contract": "0.2.3"
}, },
"peerDependencies": { "peerDependencies": {
"react": ">=18 <20", "react": ">=18 <20",
@@ -61,13 +61,13 @@
} }
}, },
"node_modules/@add-ideas/toolbox-testkit": { "node_modules/@add-ideas/toolbox-testkit": {
"version": "0.1.1", "version": "0.2.3",
"resolved": "https://git.add-ideas.de/api/packages/zemion/npm/%40add-ideas%2Ftoolbox-testkit/-/0.1.1/toolbox-testkit-0.1.1.tgz", "resolved": "https://git.add-ideas.de/api/packages/lotobo/npm/%40add-ideas%2Ftoolbox-testkit/-/0.2.3/toolbox-testkit-0.2.3.tgz",
"integrity": "sha512-o+H7LfM7ipdgmYz18S0lLuN6JsXUR+8ubAbcjTWTk8rSqNfp1JyeoRHOPbJVEHXrQwIFe/OB86UzRpex2gnKUQ==", "integrity": "sha512-sq1MwhKWfFKen+N+124hl74qQimRSvmQ9sOU7jdcI+2qCKZ67+2B8rWyezeV80uTFu4Jv6deHksfYQ/tKNV6XQ==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@add-ideas/toolbox-contract": "0.1.1" "@add-ideas/toolbox-contract": "0.2.3"
}, },
"bin": { "bin": {
"toolbox-check": "dist/cli.js" "toolbox-check": "dist/cli.js"

View File

@@ -1,6 +1,6 @@
{ {
"name": "onenote-tools", "name": "onenote-tools",
"version": "0.2.0", "version": "0.3.4",
"description": "A local-first browser reader and exporter for OneNote files.", "description": "A local-first browser reader and exporter for OneNote files.",
"license": "MPL-2.0 AND LGPL-2.1-only", "license": "MPL-2.0 AND LGPL-2.1-only",
"private": true, "private": true,
@@ -27,14 +27,14 @@
"check": "npm run manifest:check && npm run typecheck && npm run lint && npm run format:check && npm run test && npm run build && npm run toolbox:check" "check": "npm run manifest:check && npm run typecheck && npm run lint && npm run format:check && npm run test && npm run build && npm run toolbox:check"
}, },
"dependencies": { "dependencies": {
"@add-ideas/toolbox-contract": "0.1.1", "@add-ideas/toolbox-contract": "0.2.3",
"@add-ideas/toolbox-shell-react": "0.1.1", "@add-ideas/toolbox-shell-react": "0.2.3",
"fflate": "^0.8.3", "fflate": "^0.8.3",
"react": "^19.2.6", "react": "^19.2.6",
"react-dom": "^19.2.6" "react-dom": "^19.2.6"
}, },
"devDependencies": { "devDependencies": {
"@add-ideas/toolbox-testkit": "0.1.1", "@add-ideas/toolbox-testkit": "0.2.3",
"@eslint/js": "^10.0.1", "@eslint/js": "^10.0.1",
"@testing-library/jest-dom": "^6.9.1", "@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^16.3.2", "@testing-library/react": "^16.3.2",

View File

@@ -1,5 +1,5 @@
{ {
"$schema": "https://git.add-ideas.de/zemion/toolbox-sdk/raw/branch/main/schemas/toolbox-app.v1.schema.json", "$schema": "https://git.add-ideas.de/lotobo/toolbox-sdk/raw/branch/main/schemas/toolbox-app.v1.schema.json",
"schemaVersion": 1, "schemaVersion": 1,
"id": "de.add-ideas.onenote-tools", "id": "de.add-ideas.onenote-tools",
"name": "OneNote Tools", "name": "OneNote Tools",
@@ -37,8 +37,8 @@
"label": "Local only · no uploads · no storage · no telemetry" "label": "Local only · no uploads · no storage · no telemetry"
}, },
"source": { "source": {
"repository": "https://git.add-ideas.de/zemion/onenote-tools", "repository": "https://git.add-ideas.de/lotobo/onenote-tools",
"license": "MPL-2.0 AND LGPL-2.1-only" "license": "MPL-2.0 AND LGPL-2.1-only"
}, },
"version": "0.2.0" "version": "0.3.4"
} }

View File

@@ -40,7 +40,7 @@ if (sourceVersion !== packageJson.version) {
const manifest = { const manifest = {
$schema: $schema:
'https://git.add-ideas.de/zemion/toolbox-sdk/raw/branch/main/schemas/toolbox-app.v1.schema.json', 'https://git.add-ideas.de/lotobo/toolbox-sdk/raw/branch/main/schemas/toolbox-app.v1.schema.json',
schemaVersion: 1, schemaVersion: 1,
...definition, ...definition,
version: packageJson.version, version: packageJson.version,

View File

@@ -551,11 +551,7 @@ export function App() {
<AppShell <AppShell
app={toolboxApp} app={toolboxApp}
manifestUrl="./toolbox-app.json" manifestUrl="./toolbox-app.json"
appActions={ helpAction={{ onClick: () => setHelpOpen(true) }}
<button type="button" onClick={() => setHelpOpen(true)}>
Help
</button>
}
> >
<OneNoteApplication /> <OneNoteApplication />
{helpOpen ? <HelpDialog onClose={() => setHelpOpen(false)} /> : null} {helpOpen ? <HelpDialog onClose={() => setHelpOpen(false)} /> : null}

73
src/AppShell.test.tsx Normal file
View File

@@ -0,0 +1,73 @@
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { beforeEach, describe, expect, it } from 'vitest';
import { App } from './App.js';
describe('Toolbox application shell', () => {
beforeEach(() => {
localStorage.clear();
});
it('uses the standard app-specific help and source controls', async () => {
const user = userEvent.setup();
render(<App />);
expect(
screen.getByRole('heading', { name: 'OneNote Tools' })
).toBeInTheDocument();
expect(
screen.getByRole('link', {
name: 'Source for OneNote Tools on Gitea',
})
).toHaveAttribute('href', 'https://git.add-ideas.de/lotobo/onenote-tools');
expect(
Array.from(
screen.getByRole('group', { name: 'Toolbox controls' }).children,
(element) => element.getAttribute('aria-label')
)
).toEqual([
'Help',
'Source for OneNote Tools on Gitea',
'Apps',
'Personalize',
]);
expect(
Array.from(
document.querySelector('.toolbox-shell__bar')?.children ?? [],
(element) => element.className
)
).toEqual([
'toolbox-shell__brand',
'toolbox-shell__identity',
'toolbox-shell__controls',
]);
await user.click(screen.getByRole('button', { name: 'Help' }));
expect(
screen.getByRole('dialog', { name: 'About OneNote Tools' })
).toBeVisible();
});
it('applies an explicit appearance choice to the complete app', async () => {
const user = userEvent.setup();
const { container } = render(<App />);
await user.click(screen.getByRole('button', { name: 'Personalize' }));
expect(
screen.getByRole('heading', { name: 'Personalize your toolbox' })
).toBeInTheDocument();
expect(
screen.getByRole('group', { name: 'Appearance' })
).toBeInTheDocument();
expect(
screen.queryByRole('button', { name: 'Export JSON' })
).not.toBeInTheDocument();
await user.click(screen.getByRole('button', { name: 'Dark' }));
expect(container.querySelector('.toolbox-shell')).toHaveAttribute(
'data-toolbox-theme',
'dark'
);
});
});

View File

@@ -0,0 +1,21 @@
import { readFile } from 'node:fs/promises';
import path from 'node:path';
import { describe, expect, it } from 'vitest';
describe('application width', () => {
it('uses the complete width supplied by the shared Toolbox shell', async () => {
const stylesheet = await readFile(
path.join(process.cwd(), 'src', 'styles.css'),
'utf8'
);
const applicationRules = Array.from(
stylesheet.matchAll(/\.application\s*\{([^}]*)\}/g),
(match) => match[1] ?? ''
);
expect(applicationRules).not.toHaveLength(0);
expect(applicationRules.join('\n')).toMatch(/\bwidth:\s*100%;/);
expect(applicationRules.join('\n')).not.toMatch(/\bwidth:\s*min\(/);
});
});

View File

@@ -59,6 +59,9 @@ const page: OneNotePageDto = {
id: 'image-1', id: 'image-1',
resourceId: 'resource-image', resourceId: 'resource-image',
altText: 'Embedded diagram', altText: 'Embedded diagram',
pictureWidth: 8,
pictureHeight: 4,
href: 'https://example.com/diagram',
isBackground: false, isBackground: false,
layout: {}, layout: {},
}, },
@@ -141,6 +144,13 @@ describe('PageReader structured content', () => {
screen.getByRole('img', { name: 'Embedded diagram' }) screen.getByRole('img', { name: 'Embedded diagram' })
).toHaveAttribute('src', 'blob:local-image') ).toHaveAttribute('src', 'blob:local-image')
); );
expect(screen.getByRole('img', { name: 'Embedded diagram' })).toHaveStyle({
width: '384px',
height: 'auto',
});
expect(
screen.getByRole('link', { name: 'Embedded diagram' })
).toHaveAttribute('href', 'https://example.com/diagram');
}); });
it('downloads an attachment only after an explicit user action', async () => { it('downloads an attachment only after an explicit user action', async () => {

View File

@@ -400,7 +400,9 @@ function ImageView({
alt={image.altText ?? image.filename ?? ''} alt={image.altText ?? image.filename ?? ''}
style={{ style={{
width: halfInches(image.pictureWidth), width: halfInches(image.pictureWidth),
height: halfInches(image.pictureHeight), // A fixed height would remain unchanged when max-width scales a
// large image down, distorting its aspect ratio.
height: 'auto',
}} }}
/> />
) : ( ) : (

View File

@@ -1,6 +1,4 @@
:root { :root {
color: #241b2b;
background: #f6f3f8;
font-family: font-family:
Inter, Inter,
ui-sans-serif, ui-sans-serif,
@@ -22,52 +20,93 @@ body {
min-height: 100vh; min-height: 100vh;
} }
button, .toolbox-shell__main {
input { --onenote-page-surface: #fff;
--onenote-page-text: #241b2b;
--onenote-content-surface: #faf7fc;
--onenote-control-surface: #fff;
--onenote-control-hover: #f1e8f8;
--onenote-control-text: #4c1f6b;
--onenote-control-border: #704294;
--onenote-selection-surface: #eee3f5;
--onenote-selection-text: #3e145c;
--onenote-code-surface: #eee7f3;
--onenote-warning-surface: #fbf4e6;
--onenote-warning-text: #66552f;
--onenote-error-surface: #faeaea;
--onenote-error-text: #9b3131;
color: var(--onenote-page-text);
background: var(--toolbox-background);
}
.toolbox-shell[data-toolbox-theme='dark'] .toolbox-shell__main {
--onenote-page-surface: #2b2231;
--onenote-page-text: #f6effa;
--onenote-content-surface: #302638;
--onenote-control-surface: #35283d;
--onenote-control-hover: #3c2b48;
--onenote-control-text: #f4e7fc;
--onenote-control-border: #755e82;
--onenote-selection-surface: #3c2b48;
--onenote-selection-text: #f6effa;
--onenote-code-surface: #3a3040;
--onenote-warning-surface: #493b23;
--onenote-warning-text: #f5e8cd;
--onenote-error-surface: #4d2929;
--onenote-error-text: #ffb3b3;
color-scheme: dark;
}
.toolbox-shell[data-toolbox-theme='light'] .toolbox-shell__main {
color-scheme: light;
}
:where(.toolbox-shell__main) button,
:where(.toolbox-shell__main) input {
font: inherit; font: inherit;
} }
button { :where(.toolbox-shell__main) button {
border: 1px solid #704294; border: 1px solid var(--onenote-control-border);
border-radius: 0.55rem; border-radius: 0.55rem;
padding: 0.55rem 0.9rem; padding: 0.55rem 0.9rem;
color: #4c1f6b; color: var(--onenote-control-text);
background: #fff; background: var(--onenote-control-surface);
cursor: pointer; cursor: pointer;
} }
button:hover:not(:disabled) { :where(.toolbox-shell__main) button:hover:not(:disabled) {
background: #f1e8f8; background: var(--onenote-control-hover);
} }
button:focus-visible, :where(.toolbox-shell__main) button:focus-visible,
summary:focus-visible { :where(.toolbox-shell__main) summary:focus-visible {
outline: 3px solid #b788d4; outline: 3px solid var(--toolbox-focus);
outline-offset: 2px; outline-offset: 2px;
} }
button:disabled { :where(.toolbox-shell__main) button:disabled {
cursor: not-allowed; cursor: not-allowed;
opacity: 0.55; opacity: 0.55;
} }
code { :where(.toolbox-shell__main) code {
border-radius: 0.25rem; border-radius: 0.25rem;
padding: 0.08rem 0.25rem; padding: 0.08rem 0.25rem;
overflow-wrap: anywhere; overflow-wrap: anywhere;
background: #eee7f3; background: var(--onenote-code-surface);
} }
h1, :where(.toolbox-shell__main) h1,
h2, :where(.toolbox-shell__main) h2,
p { :where(.toolbox-shell__main) p {
overflow-wrap: anywhere; overflow-wrap: anywhere;
} }
.application { .application {
display: grid; display: grid;
gap: 1.25rem; gap: 1.25rem;
width: min(76rem, calc(100% - 2rem)); width: 100%;
margin: 2rem auto; margin: 2rem auto;
} }
@@ -77,10 +116,10 @@ p {
.package-inspector, .package-inspector,
.export-controls, .export-controls,
.diagnostics { .diagnostics {
border: 1px solid #c9b9d5; border: 1px solid var(--toolbox-border);
border-radius: 1rem; border-radius: 1rem;
background: #fff; background: var(--toolbox-surface);
box-shadow: 0 0.75rem 2.5rem rgb(62 31 85 / 8%); box-shadow: var(--toolbox-shadow);
} }
.export-controls { .export-controls {
@@ -98,7 +137,7 @@ p {
.export-controls > div > p:last-child { .export-controls > div > p:last-child {
margin: 0.35rem 0 0; margin: 0.35rem 0 0;
color: #716675; color: var(--toolbox-muted);
font-size: 0.86rem; font-size: 0.86rem;
} }
@@ -110,18 +149,18 @@ p {
.export-controls__actions label { .export-controls__actions label {
grid-column: 1 / -1; grid-column: 1 / -1;
color: #574b5b; color: var(--toolbox-muted);
font-size: 0.78rem; font-size: 0.78rem;
font-weight: 700; font-weight: 700;
} }
.export-controls__actions select { .export-controls__actions select {
min-width: 0; min-width: 0;
border: 1px solid #a98ab9; border: 1px solid var(--onenote-control-border);
border-radius: 0.55rem; border-radius: 0.55rem;
padding: 0.55rem 2rem 0.55rem 0.7rem; padding: 0.55rem 2rem 0.55rem 0.7rem;
color: inherit; color: inherit;
background: #fff; background: var(--onenote-control-surface);
font: inherit; font: inherit;
} }
@@ -129,12 +168,12 @@ p {
grid-column: 1 / -1; grid-column: 1 / -1;
min-height: 1.2em; min-height: 1.2em;
margin: 0; margin: 0;
color: #716675; color: var(--toolbox-muted);
font-size: 0.78rem; font-size: 0.78rem;
} }
.export-controls__status--error { .export-controls__status--error {
color: #9b3131; color: var(--onenote-error-text);
} }
.drop-zone, .drop-zone,
@@ -148,8 +187,8 @@ p {
} }
.drop-zone--active { .drop-zone--active {
border-color: #6b368f; border-color: var(--toolbox-accent);
background: #f7effd; background: var(--toolbox-accent-soft);
} }
.drop-zone h2, .drop-zone h2,
@@ -161,7 +200,7 @@ p {
.status-card__label, .status-card__label,
.eyebrow { .eyebrow {
margin: 0; margin: 0;
color: #6b368f; color: var(--toolbox-accent);
font-size: 0.76rem; font-size: 0.76rem;
font-weight: 750; font-weight: 750;
letter-spacing: 0.08em; letter-spacing: 0.08em;
@@ -170,18 +209,18 @@ p {
.primary-button { .primary-button {
margin-top: 0.75rem; margin-top: 0.75rem;
color: #fff; color: var(--toolbox-accent-contrast);
background: #5b2c83; background: var(--toolbox-accent);
} }
.primary-button:hover:not(:disabled) { .primary-button:hover:not(:disabled) {
background: #472164; background: var(--toolbox-accent-hover);
} }
.drop-zone__hint { .drop-zone__hint {
display: block; display: block;
margin-top: 0.75rem; margin-top: 0.75rem;
color: #6f6476; color: var(--toolbox-muted);
font-size: 0.9rem; font-size: 0.9rem;
} }
@@ -211,16 +250,16 @@ p {
grid-template-columns: minmax(16rem, 0.78fr) minmax(0, 2fr); grid-template-columns: minmax(16rem, 0.78fr) minmax(0, 2fr);
min-height: 30rem; min-height: 30rem;
overflow: hidden; overflow: hidden;
border: 1px solid #c9b9d5; border: 1px solid var(--toolbox-border);
border-radius: 1rem; border-radius: 1rem;
background: #fff; background: var(--toolbox-surface);
box-shadow: 0 0.75rem 2.5rem rgb(62 31 85 / 8%); box-shadow: var(--toolbox-shadow);
} }
.source-navigation { .source-navigation {
overflow: auto; overflow: auto;
border-right: 1px solid #d9cedf; border-right: 1px solid var(--toolbox-border);
background: #faf7fc; background: var(--toolbox-surface-soft);
} }
.navigation-heading { .navigation-heading {
@@ -228,8 +267,8 @@ p {
z-index: 1; z-index: 1;
top: 0; top: 0;
padding: 1.2rem; padding: 1.2rem;
border-bottom: 1px solid #ded5e3; border-bottom: 1px solid var(--toolbox-border);
background: #faf7fc; background: var(--toolbox-surface-soft);
} }
.navigation-heading h2 { .navigation-heading h2 {
@@ -239,7 +278,7 @@ p {
.navigation-heading > p:last-child { .navigation-heading > p:last-child {
margin: 0.35rem 0 0; margin: 0.35rem 0 0;
color: #716675; color: var(--toolbox-muted);
font-size: 0.8rem; font-size: 0.8rem;
} }
@@ -271,7 +310,7 @@ p {
.page-list button span { .page-list button span {
display: -webkit-box; display: -webkit-box;
overflow: hidden; overflow: hidden;
color: #716675; color: var(--toolbox-muted);
font-size: 0.78rem; font-size: 0.78rem;
font-weight: 400; font-weight: 400;
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
@@ -280,9 +319,9 @@ p {
.page-list button.is-selected, .page-list button.is-selected,
.notebook-section > button.is-selected { .notebook-section > button.is-selected {
border-color: #af8bc6; border-color: var(--toolbox-accent);
color: #3e145c; color: var(--onenote-selection-text);
background: #eee3f5; background: var(--onenote-selection-surface);
} }
.section-list { .section-list {
@@ -296,21 +335,21 @@ p {
.notebook-tree ul { .notebook-tree ul {
margin-inline-start: 0.7rem; margin-inline-start: 0.7rem;
border-inline-start: 1px solid #ded5e3; border-inline-start: 1px solid var(--toolbox-border);
padding-inline-start: 0.45rem; padding-inline-start: 0.45rem;
} }
.section-group summary { .section-group summary {
cursor: pointer; cursor: pointer;
padding: 0.62rem 0.45rem; padding: 0.62rem 0.45rem;
color: #574b5b; color: var(--toolbox-muted);
font-size: 0.86rem; font-size: 0.86rem;
font-weight: 700; font-weight: 700;
} }
.notebook-section > .page-list { .notebook-section > .page-list {
margin: 0 0 0.4rem 0.7rem; margin: 0 0 0.4rem 0.7rem;
border-inline-start: 1px solid #ded5e3; border-inline-start: 1px solid var(--toolbox-border);
padding: 0.25rem 0 0.2rem 0.45rem; padding: 0.25rem 0 0.2rem 0.45rem;
} }
@@ -328,20 +367,22 @@ p {
.empty-message { .empty-message {
margin: 0; margin: 0;
padding: 1rem 1.2rem; padding: 1rem 1.2rem;
color: #716675; color: var(--toolbox-muted);
} }
.page-reader { .page-reader {
min-width: 0; min-width: 0;
min-height: 0;
overflow: auto;
padding: clamp(1.4rem, 4vw, 3rem); padding: clamp(1.4rem, 4vw, 3rem);
background: #fff; background: var(--onenote-page-surface);
} }
.page-reader--empty { .page-reader--empty {
display: grid; display: grid;
place-items: center; place-items: center;
min-height: 20rem; min-height: 20rem;
color: #716675; color: var(--toolbox-muted);
text-align: center; text-align: center;
} }
@@ -352,7 +393,7 @@ p {
.page-reader__header { .page-reader__header {
margin-bottom: 2rem; margin-bottom: 2rem;
padding-bottom: 1.25rem; padding-bottom: 1.25rem;
border-bottom: 1px solid #e1d9e5; border-bottom: 1px solid var(--toolbox-border);
} }
.page-reader__header h2 { .page-reader__header h2 {
@@ -366,7 +407,7 @@ p {
flex-wrap: wrap; flex-wrap: wrap;
gap: 0.3rem 1rem; gap: 0.3rem 1rem;
margin: 1rem 0 0; margin: 1rem 0 0;
color: #716675; color: var(--toolbox-muted);
font-size: 0.82rem; font-size: 0.82rem;
} }
@@ -407,7 +448,7 @@ p {
} }
.onenote-link { .onenote-link {
color: #5b2c83; color: var(--toolbox-accent);
text-decoration-thickness: 0.08em; text-decoration-thickness: 0.08em;
text-underline-offset: 0.12em; text-underline-offset: 0.12em;
} }
@@ -423,12 +464,12 @@ p {
min-width: min(100%, 28rem); min-width: min(100%, 28rem);
border-spacing: 0; border-spacing: 0;
border-collapse: collapse; border-collapse: collapse;
background: #fff; background: var(--onenote-page-surface);
} }
.onenote-table td { .onenote-table td {
min-width: 5rem; min-width: 5rem;
border: 1px solid #cfc5d4; border: 1px solid var(--toolbox-border);
padding: 0.55rem 0.65rem; padding: 0.55rem 0.65rem;
vertical-align: top; vertical-align: top;
} }
@@ -453,12 +494,18 @@ p {
display: block; display: block;
max-width: 100%; max-width: 100%;
height: auto; height: auto;
object-fit: contain;
border-radius: 0.3rem; border-radius: 0.3rem;
} }
.onenote-image > a {
display: block;
max-width: 100%;
}
.onenote-image figcaption { .onenote-image figcaption {
max-width: 40rem; max-width: 40rem;
color: #716675; color: var(--toolbox-muted);
font-size: 0.82rem; font-size: 0.82rem;
} }
@@ -468,11 +515,11 @@ p {
min-height: 7rem; min-height: 7rem;
max-width: 32rem; max-width: 32rem;
place-items: center; place-items: center;
border: 1px dashed #a58caf; border: 1px dashed var(--toolbox-border);
border-radius: 0.55rem; border-radius: 0.55rem;
padding: 1rem; padding: 1rem;
color: #716675; color: var(--toolbox-muted);
background: #faf7fc; background: var(--onenote-content-surface);
text-align: center; text-align: center;
} }
@@ -482,10 +529,10 @@ p {
align-items: center; align-items: center;
gap: 0.75rem 1rem; gap: 0.75rem 1rem;
margin-block: 0.8rem; margin-block: 0.8rem;
border: 1px solid #d4c8db; border: 1px solid var(--toolbox-border);
border-radius: 0.65rem; border-radius: 0.65rem;
padding: 0.8rem; padding: 0.8rem;
background: #faf7fc; background: var(--onenote-content-surface);
} }
.attachment-card > div { .attachment-card > div {
@@ -496,7 +543,7 @@ p {
.attachment-card span, .attachment-card span,
.attachment-card small { .attachment-card small {
color: #716675; color: var(--toolbox-muted);
font-size: 0.8rem; font-size: 0.8rem;
} }
@@ -509,7 +556,7 @@ p {
max-width: 100%; max-width: 100%;
margin-block: 0.75rem; margin-block: 0.75rem;
overflow: visible; overflow: visible;
color: #241b2b; color: var(--onenote-page-text);
} }
.onenote-ink svg { .onenote-ink svg {
@@ -525,16 +572,16 @@ p {
margin: 0.8rem 0; margin: 0.8rem 0;
border-left: 0.2rem solid #9872ae; border-left: 0.2rem solid #9872ae;
padding: 0.65rem 0.85rem; padding: 0.65rem 0.85rem;
color: #5e5362; color: var(--toolbox-muted);
background: #f5eff8; background: var(--toolbox-surface-soft);
} }
.render-limit-notice { .render-limit-notice {
margin: 1rem 0 0; margin: 1rem 0 0;
border-left: 0.2rem solid #b18124; border-left: 0.2rem solid #b18124;
padding: 0.7rem 0.85rem; padding: 0.7rem 0.85rem;
color: #66552f; color: var(--onenote-warning-text);
background: #fbf4e6; background: var(--onenote-warning-surface);
font-size: 0.85rem; font-size: 0.85rem;
} }
@@ -561,8 +608,8 @@ p {
min-height: 2rem; min-height: 2rem;
place-items: center; place-items: center;
border-radius: 999px; border-radius: 999px;
color: #552477; color: var(--toolbox-accent);
background: #eee3f5; background: var(--toolbox-accent-soft);
font-weight: 700; font-weight: 700;
} }
@@ -576,11 +623,11 @@ p {
.package-summary > div { .package-summary > div {
border-radius: 0.65rem; border-radius: 0.65rem;
padding: 0.75rem; padding: 0.75rem;
background: #f6f1f8; background: var(--toolbox-surface-soft);
} }
.package-summary dt { .package-summary dt {
color: #716675; color: var(--toolbox-muted);
font-size: 0.75rem; font-size: 0.75rem;
} }
@@ -591,13 +638,13 @@ p {
} }
.entry-inspector { .entry-inspector {
border-top: 1px solid #ded5e3; border-top: 1px solid var(--toolbox-border);
padding-top: 0.9rem; padding-top: 0.9rem;
} }
.entry-inspector summary { .entry-inspector summary {
width: fit-content; width: fit-content;
color: #5b2c83; color: var(--toolbox-accent);
cursor: pointer; cursor: pointer;
font-weight: 700; font-weight: 700;
} }
@@ -618,20 +665,20 @@ p {
.entry-table th, .entry-table th,
.entry-table td { .entry-table td {
padding: 0.62rem; padding: 0.62rem;
border-bottom: 1px solid #e5dee9; border-bottom: 1px solid var(--toolbox-border);
vertical-align: top; vertical-align: top;
} }
.entry-table th { .entry-table th {
position: sticky; position: sticky;
top: 0; top: 0;
background: #fff; background: var(--toolbox-surface);
} }
.entry-table small { .entry-table small {
display: block; display: block;
margin-top: 0.3rem; margin-top: 0.3rem;
color: #716675; color: var(--toolbox-muted);
} }
.status { .status {
@@ -669,12 +716,14 @@ p {
.diagnostic { .diagnostic {
border-left: 0.22rem solid #b18124; border-left: 0.22rem solid #b18124;
padding: 0.7rem 0.85rem; padding: 0.7rem 0.85rem;
background: #fbf4e6; color: var(--onenote-warning-text);
background: var(--onenote-warning-surface);
} }
.diagnostic--error { .diagnostic--error {
border-left-color: #b65252; border-left-color: #b65252;
background: #faeaea; color: var(--onenote-error-text);
background: var(--onenote-error-surface);
} }
.diagnostic__summary { .diagnostic__summary {
@@ -711,13 +760,13 @@ p {
.privacy-note { .privacy-note {
border-left: 0.25rem solid #7d4aa0; border-left: 0.25rem solid #7d4aa0;
padding: 0.85rem 1rem; padding: 0.85rem 1rem;
color: #4c4054; color: var(--toolbox-muted);
background: #eee7f3; background: var(--onenote-code-surface);
} }
.dialog-backdrop { .dialog-backdrop {
position: fixed; position: fixed;
z-index: 10; z-index: 70;
inset: 0; inset: 0;
display: grid; display: grid;
place-items: center; place-items: center;
@@ -729,8 +778,8 @@ p {
width: min(32rem, 100%); width: min(32rem, 100%);
border-radius: 0.8rem; border-radius: 0.8rem;
padding: 1.5rem; padding: 1.5rem;
color: #241b2b; color: var(--onenote-page-text);
background: #fff; background: var(--onenote-page-surface);
box-shadow: 0 1rem 3rem rgb(0 0 0 / 25%); box-shadow: 0 1rem 3rem rgb(0 0 0 / 25%);
} }
@@ -752,7 +801,6 @@ p {
@media (max-width: 760px) { @media (max-width: 760px) {
.application { .application {
width: min(100% - 1rem, 76rem);
margin: 0.75rem auto; margin: 0.75rem auto;
} }
@@ -763,7 +811,7 @@ p {
.source-navigation { .source-navigation {
max-height: 20rem; max-height: 20rem;
border-right: 0; border-right: 0;
border-bottom: 1px solid #d9cedf; border-bottom: 1px solid var(--toolbox-border);
} }
.package-summary { .package-summary {
@@ -780,114 +828,21 @@ p {
} }
@media (prefers-color-scheme: dark) { @media (prefers-color-scheme: dark) {
:root { .toolbox-shell[data-toolbox-theme='system'] .toolbox-shell__main {
color: #f6effa; --onenote-page-surface: #2b2231;
background: #1f1923; --onenote-page-text: #f6effa;
} --onenote-content-surface: #302638;
--onenote-control-surface: #35283d;
.drop-zone, --onenote-control-hover: #3c2b48;
.status-card, --onenote-control-text: #f4e7fc;
.source-toolbar, --onenote-control-border: #755e82;
.package-inspector, --onenote-selection-surface: #3c2b48;
.diagnostics, --onenote-selection-text: #f6effa;
.export-controls, --onenote-code-surface: #3a3040;
.reader-workspace, --onenote-warning-surface: #493b23;
.page-reader, --onenote-warning-text: #f5e8cd;
.help-dialog, --onenote-error-surface: #4d2929;
.entry-table th { --onenote-error-text: #ffb3b3;
color: #f6effa; color-scheme: dark;
background: #2b2231;
}
.source-navigation,
.navigation-heading {
background: #251d2a;
}
.drop-zone--active,
button:hover:not(:disabled),
.page-list button.is-selected,
.notebook-section > button.is-selected {
color: #f6effa;
background: #3c2b48;
}
button {
color: #f4e7fc;
background: #35283d;
}
.export-controls__actions select {
border-color: #755e82;
background: #35283d;
}
.export-controls > div > p:last-child,
.export-controls__actions label,
.export-controls__status {
color: #cfc2d6;
}
.export-controls__status--error {
color: #ffb3b3;
}
code,
.privacy-note,
.package-summary > div {
color: #eadff0;
background: #3a3040;
}
.drop-zone__hint,
.navigation-heading > p:last-child,
.navigation-empty,
.empty-message,
.page-metadata,
.page-list button span,
.package-summary dt,
.entry-table small {
color: #cfc2d6;
}
.unsupported-block {
color: #e4dbe9;
background: #3a3040;
}
.onenote-link {
color: #d7acef;
}
.onenote-table,
.attachment-card,
.image-placeholder {
color: #f6effa;
background: #302638;
}
.onenote-table td {
border-color: #62536b;
}
.onenote-image figcaption,
.attachment-card span,
.attachment-card small,
.image-placeholder {
color: #cfc2d6;
}
.onenote-ink {
color: #f6effa;
}
.diagnostic {
color: #f5e8cd;
background: #493b23;
}
.diagnostic--error {
color: #f8dfdf;
background: #4d2929;
} }
} }

View File

@@ -35,7 +35,7 @@
"label": "Local only · no uploads · no storage · no telemetry" "label": "Local only · no uploads · no storage · no telemetry"
}, },
"source": { "source": {
"repository": "https://git.add-ideas.de/zemion/onenote-tools", "repository": "https://git.add-ideas.de/lotobo/onenote-tools",
"license": "MPL-2.0 AND LGPL-2.1-only" "license": "MPL-2.0 AND LGPL-2.1-only"
} }
} }

View File

@@ -1 +1 @@
export const APP_VERSION = '0.2.0'; export const APP_VERSION = '0.3.4';

View File

@@ -53,8 +53,8 @@ describe('release archive', () => {
'react', 'react',
]); ]);
const text = bundle.toString('utf8'); const text = bundle.toString('utf8');
expect(text).toContain('@add-ideas/toolbox-contract@0.1.1'); expect(text).toContain('@add-ideas/toolbox-contract@0.2.3');
expect(text).toContain('@add-ideas/toolbox-shell-react@0.1.1'); expect(text).toContain('@add-ideas/toolbox-shell-react@0.2.3');
expect(text).toContain('react@'); expect(text).toContain('react@');
expect(createHash('sha256').update(bundle).digest('hex')).toMatch( expect(createHash('sha256').update(bundle).digest('hex')).toMatch(
/^[a-f0-9]{64}$/ /^[a-f0-9]{64}$/