fix(docs): remove stray tool-call tags breaking the MDX build (#6081)

This is a fix to pnpm deployment which needs testing as the final part of origin/master release
No functional changes

* fix(docs): remove stray tool-call tags breaking the MDX build

platform/docs/docs/migration-guide/3p12-to-3p13/build-tooling.md ended with
two orphan closing tags (leftover tool-call serialization artifacts):

  </content>
  </invoke>

Docusaurus compiles Markdown as MDX (JSX-aware), so the orphan closing tag
failed the docs build:

  MDX compilation failed ... Unexpected closing slash in tag, expected an
  open tag first (build-tooling.md line 402)

This was the remaining blocker for build-and-deploy-docs once the
--no-frozen-lockfile change let the install step succeed. A scan of the docs
tree found no other such artifacts. Verified locally: docusaurus build now
generates static files with no MDX errors.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Update lockfile and avoid freshness check on every command

* fix(release): keep workspace:* in the repo, concretize only at publish

The release flow rewrote internal @ohif/* dependency specifiers to the concrete
version and committed them, so pnpm-lock.yaml (which records workspace links)
drifted from the manifests on every version bump. The resulting
ERR_PNPM_OUTDATED_LOCKFILE broke every frozen install: Netlify (viewer-dev),
the docs deploy, pnpm's pre-run deps check, and post-merge installs.

Keep workspace:* everywhere in the committed repo and move the concrete-version
substitution to publish time only:

- publish-version.mjs: bump each package's own `version` field only; stop
  rewriting @ohif/* dependency/peerDependency specifiers.
- publish-package.mjs: publish with `pnpm publish --no-git-checks` instead of
  `npm publish`. pnpm rewrites workspace:* to the exact version in the published
  tarball; npm would publish the literal "workspace:*", which npm/yarn consumers
  cannot resolve.
- One-time: revert the 25 workspace manifests' @ohif/* specifiers to workspace:*
  (version fields untouched) and regenerate pnpm-lock.yaml to match.

Because internal deps are workspace:* (links, not versions in the lockfile),
version bumps no longer change pnpm-lock.yaml, so it stays in sync and frozen
installs keep working.

Verified: `pnpm install --frozen-lockfile` passes, and `pnpm pack` of @ohif/core
emits a tarball whose @ohif/ui dependency is the exact version (3.13.0-beta.92),
not workspace:*.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs(ci): correct build-docs install comment for workspace:* release flow

publish-version.mjs no longer rewrites @ohif/* deps to concrete versions, so
the old comment was stale. Internal deps stay workspace:* and the lockfile
stays consistent; pnpm publish concretizes only the published tarball.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* ci(docs): use --frozen-lockfile now that the lockfile no longer drifts

With internal deps as workspace:* the lockfile stays in sync across version
bumps, so the docs deploy can install frozen -- failing fast on genuine
lockfile drift instead of silently reconciling. The --no-frozen-lockfile
workaround is no longer needed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* ci: use --frozen-lockfile in CI install steps now that the lockfile is stable

Internal @ohif/* deps are workspace:* so pnpm-lock.yaml no longer drifts; the
UNIT_TESTS/BUILD/NPM_PUBLISH installs can run frozen and fail fast on genuine
drift. Kept --no-frozen-lockfile only where it is still required: the Dockerfile
(platform/docs is excluded from the build context) and the playwright CS3D-version
step (mutates @cornerstonejs versions before installing).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test: stability of seg load mpr test

* Better drag fix for crosshairs

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Bill WallaceandClaude Opus 4.8 authored and GitHub committed 2026-06-16 11:59:04 -04:00
1 parent da9fd9057d
commit 256b8347e7
34 files changed
+179 -176

No files matched your search

+12 -12
View File
@@ -3,7 +3,6 @@ import {
screenShotPaths,
test,
visitStudy,
waitForPaintToSettle,
waitForViewportRenderCycle,
waitForViewportsRendered,
} from './utils';
@@ -36,11 +35,11 @@ test('should properly display MPR for MR', async ({
await leftPanelPageObject.loadSeriesByDescription('SEG');
// SEG load triggers a progressive labelmap volume upload. waitForViewportsRendered
// (waitVolumeLoad defaults to true) polls the viewport volume actors until the
// labelmap reports loadStatus.loaded, then settles, so the screenshot captures the
// finished upload rather than a mid-stream frame.
await waitForViewportsRendered(page);
// SEG load triggers an additional progressive labelmap upload after the
// viewports first report 'rendered'; let that finish before screenshotting.
await page.waitForTimeout(1500);
await waitForPaintToSettle(page);
await checkForScreenshot(
page,
@@ -54,11 +53,11 @@ test('should properly display MPR for MR', async ({
await DOMOverlayPageObject.viewport.segmentationHydration.yes.click();
await viewportRenderCycle;
// Hydration propagates the labelmap volume to the sagittal/coronal MPR
// viewports asynchronously; wait for that propagation to render before
// capturing.
await page.waitForTimeout(1500);
await waitForPaintToSettle(page);
// Hydration propagates the labelmap volume to the sagittal/coronal MPR viewports
// asynchronously, adding new volume actors after the first render cycle resolves.
// waitForViewportsRendered re-polls every viewport's volume actors until those
// propagated labelmaps report loadStatus.loaded, then settles.
await waitForViewportsRendered(page);
await checkForScreenshot(
page,
@@ -71,8 +70,9 @@ test('should properly display MPR for MR', async ({
await mainToolbarPageObject.layoutSelection.axialPrimary.click();
await viewportRenderAfterLayoutChange;
await page.waitForTimeout(1000);
await waitForPaintToSettle(page);
// The layout change rebuilds the viewports; wait for their volume actors (image
// + labelmap) to report loaded before settling and capturing.
await waitForViewportsRendered(page);
await checkForScreenshot(
page,
+26 -18
View File
@@ -1,6 +1,5 @@
import { Locator, Page } from '@playwright/test';
import {
getMousePosition,
simulateClicksOnElement,
simulateDoubleClickOnElement,
simulateNormalizedClicksOnElement,
@@ -362,6 +361,28 @@ export class ViewportPageObject {
throw new Error('Could not find slab thickness handle for crosshairs interaction');
}
// Drive the drag from the handle's own bounding-box center rather than the
// async window.mouseX/Y tracker: the tracker can lag behind the hover, which
// makes the drag start from a stale point and rotate/resize nothing. Stepped
// moves emit intermediate mousemove events so cornerstone registers a real
// drag instead of a single teleport (which can be dropped or mis-deltad).
const DRAG_DISTANCE = 100;
const DRAG_STEPS = 10;
async function dragHandleFromCenter(handle: Locator, dx: number, dy: number) {
const box = await handle.boundingBox();
if (!box) {
throw new Error('Could not resolve crosshairs handle bounding box for drag');
}
const cx = box.x + box.width / 2;
const cy = box.y + box.height / 2;
await page.mouse.move(cx, cy);
await page.mouse.down();
await page.mouse.move(cx + dx, cy + dy, { steps: DRAG_STEPS });
await page.mouse.up();
}
async function increaseSlabThickness(locator: Locator, lineNumber: number, axis: string) {
const lineLocator = locator.locator('line').nth(lineNumber);
await lineLocator.click({ force: true });
@@ -370,18 +391,9 @@ export class ViewportPageObject {
const slabHandleLocator = await getSlabHandleLocator(locator);
await slabHandleLocator.hover({ force: true, timeout: crosshairHoverTimeout });
await page.mouse.down();
const position = await getMousePosition(page);
switch (axis) {
case 'x':
await page.mouse.move(position.x + 100, position.y);
break;
case 'y':
await page.mouse.move(position.x, position.y + 100);
break;
}
await page.mouse.up();
const dx = axis === 'x' ? DRAG_DISTANCE : 0;
const dy = axis === 'y' ? DRAG_DISTANCE : 0;
await dragHandleFromCenter(slabHandleLocator, dx, dy);
}
async function rotateCrosshairs(locator: Locator, lineNumber: number) {
@@ -393,11 +405,7 @@ export class ViewportPageObject {
await circleLocator.waitFor({ state: 'attached', timeout: crosshairHoverTimeout });
await circleLocator.hover({ force: true, timeout: crosshairHoverTimeout });
await page.mouse.down();
const position = await getMousePosition(page);
await page.mouse.move(position.x, position.y + 100);
await page.mouse.up();
await dragHandleFromCenter(circleLocator, 0, DRAG_DISTANCE);
}
function crosshairsFactory(