Branch for hardware verification on a host that meets v0.24.1's peer range.
Base: upstream `dsh-better-sidebar` v0.24.1 (tag v0.24.1 = a2751cf), MIT.
Measured delta carried over from the v0.19.1 line: 78 rename-only files, 11 real
edits, 10 additions. Ported with the same measurement method as the v0.19.1
re-base: build a normalized base (upstream tree + the fork rename, excluding
README.md / package.json / docs/plans/* which deliberately keep the upstream
name), extract the delta against it, then three-way apply onto the renamed
v0.24.1 tree (`git apply -3`). 13 conflicts resolved by hand.
Identity:
- version 1.3.0, SIDEBAR_SERVICE_VERSION 1.3.0 (package.json ↔ service.ts pair
is asserted by tests/service.spec.ts), forkedFrom -> v0.24.1/a2751cf.
- package.json keeps the union of both sides' metadata: upstream's new
`zustand` + `icon`/`locale` files entries, plus the fork's `scripts/switch.sh`
entry and its `forkedFrom` block.
- README.md takes upstream v0.24.1 wholesale (its own v0.24.1 changelog and all
16 sections) and keeps the fork's two deltas: the fork-notice block at the top
(now documenting the 0.2.0-rc.1+ requirement) and the fork package name.
- peerDependencies stay upstream's `^0.2.0-rc.1` — this line does NOT load on
DSH 0.1.x: the host's semver pre-check rejects a caret range across a minor
and silently disables the row (no error, no load).
Carried features, all re-verified against the new base:
- apes:* information-layer tabs (src/client/apes/) — the subtree's session feed
changed shape in 0.1.7 and the port follows the host's own migration notes in
context-types.ts: the per-session catalog is now
`projectionsBySession[id].values.subagentCatalog` (a flat entry list) instead
of 0.1.6's `subagentsByParent` catalog with `entries`/`kind`/`activity`, and
the removed `list.current` is answered by `props.scope.sessionId`. Rows are
normalized to { id, label, mode } with activity read from the durable
summaries, so catalog and byId sources render alike.
- HTML preview delivery through srcdoc (sandbox kept intact).
- Panel host mounted inside the shell's framed content viewport.
Gate: typecheck clean; build clean; 1515 passed / 9 skipped (141 files).
NOT applied to ~/.dsh/profiles/desktop — that profile runs DSH 2.0.10 with
@deepseek-ai/dsh 0.1.5-rc.2, where this line is silently disabled by design.
52 lines
2.0 KiB
TypeScript
52 lines
2.0 KiB
TypeScript
/**
|
||
* HTML preview vocabulary tests: the srcdoc delivery path needs the previewed
|
||
* document's relative references to resolve back into its own
|
||
* `/sidebar/html/…` route (a srcdoc document has no URL of its own — the
|
||
* browser would otherwise resolve `./style.css` against the GUI page).
|
||
*
|
||
* Pure module, plain node environment.
|
||
*/
|
||
import { describe, expect, it } from 'vitest'
|
||
import { previewBaseOf, withPreviewBase } from '../src/client/html-preview.ts'
|
||
|
||
const URL_ = '/sidebar/html/s1/p/a/index.html'
|
||
|
||
describe('previewBaseOf', () => {
|
||
it('keeps everything up to the last slash', () => {
|
||
expect(previewBaseOf(URL_)).toBe('/sidebar/html/s1/p/a/')
|
||
})
|
||
|
||
it('keeps the UNC double slash intact (the route encodes it that way)', () => {
|
||
expect(previewBaseOf('/sidebar/html/s1//server/share/a.html')).toBe('/sidebar/html/s1//server/share/')
|
||
})
|
||
|
||
it('returns the input unchanged when it has no slash', () => {
|
||
expect(previewBaseOf('s1')).toBe('s1')
|
||
})
|
||
})
|
||
|
||
describe('withPreviewBase', () => {
|
||
it('injects the base as the first child of <head>, ahead of the document’s own elements', () => {
|
||
const out = withPreviewBase('<html><head><title>t</title></head><body></body></html>', URL_)
|
||
expect(out).toBe('<html><head><base href="/sidebar/html/s1/p/a/"><title>t</title></head><body></body></html>')
|
||
})
|
||
|
||
it('falls back to <html> when the document declares no head', () => {
|
||
const out = withPreviewBase('<html><body>x</body></html>', URL_)
|
||
expect(out).toBe('<html><base href="/sidebar/html/s1/p/a/"><body>x</body></html>')
|
||
})
|
||
|
||
it('prepends for a headless fragment', () => {
|
||
expect(withPreviewBase('<h1>x</h1>', URL_)).toBe('<base href="/sidebar/html/s1/p/a/"><h1>x</h1>')
|
||
})
|
||
|
||
it('leaves a document that declares its own base alone (the author owns it)', () => {
|
||
const doc = '<head><base href="https://example.com/"></head>'
|
||
expect(withPreviewBase(doc, URL_)).toBe(doc)
|
||
})
|
||
|
||
it('quotes the injected href', () => {
|
||
expect(withPreviewBase('<head></head>', '/x/"y/')).toBe('<head><base href="/x/"y/"></head>')
|
||
})
|
||
})
|