From 921e8ef6f8dd0562a9c4b0be81cc94956b4ac495 Mon Sep 17 00:00:00 2001 From: Thomas Bouffard <27200110+tbouffard@users.noreply.github.com> Date: Sat, 8 Feb 2025 17:04:56 +0100 Subject: [PATCH 1/3] refactor: improve StencilRegistry method signatures Also improve the JSDoc. --- .../node/StencilShapeRegistry.test.ts | 24 +++++++++++++ packages/core/src/view/cell/CellRenderer.ts | 5 ++- .../src/view/geometry/node/StencilShape.ts | 4 +-- .../geometry/node/StencilShapeRegistry.ts | 34 +++++++------------ packages/html/stories/Stencils.stories.ts | 2 +- 5 files changed, 40 insertions(+), 29 deletions(-) create mode 100644 packages/core/__tests__/view/geometry/node/StencilShapeRegistry.test.ts diff --git a/packages/core/__tests__/view/geometry/node/StencilShapeRegistry.test.ts b/packages/core/__tests__/view/geometry/node/StencilShapeRegistry.test.ts new file mode 100644 index 0000000000..5ff1d7dd92 --- /dev/null +++ b/packages/core/__tests__/view/geometry/node/StencilShapeRegistry.test.ts @@ -0,0 +1,24 @@ +/* +Copyright 2025-present The maxGraph project Contributors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { describe, expect, test } from '@jest/globals'; +import { StencilShapeRegistry } from '../../../../src'; + +describe('getStencil', () => { + test.each([null, undefined, 'unknown'])('pass %s, return undefined', (name) => { + expect(StencilShapeRegistry.getStencil(name)).toBeUndefined(); + }); +}); diff --git a/packages/core/src/view/cell/CellRenderer.ts b/packages/core/src/view/cell/CellRenderer.ts index 0ce7d2771f..189ceb82e9 100644 --- a/packages/core/src/view/cell/CellRenderer.ts +++ b/packages/core/src/view/cell/CellRenderer.ts @@ -178,9 +178,8 @@ class CellRenderer { createShape(state: CellState) { let shape = null; - // Checks if there is a stencil for the name and creates - // a shape instance for the stencil if one exists - const stencil = StencilShapeRegistry.getStencil(state.style.shape); + // Checks if there is a stencil for the name and creates a shape instance for the stencil if one exists + const stencil = StencilShapeRegistry.getStencil(state.style.shape); if (stencil) { shape = new Shape(stencil); diff --git a/packages/core/src/view/geometry/node/StencilShape.ts b/packages/core/src/view/geometry/node/StencilShape.ts index a8418339ae..76b9520a4d 100644 --- a/packages/core/src/view/geometry/node/StencilShape.ts +++ b/packages/core/src/view/geometry/node/StencilShape.ts @@ -558,9 +558,7 @@ class StencilShape extends Shape { ); } } else if (name === 'include-shape') { - const stencil = StencilShapeRegistry.getStencil( - node.getAttribute('name') as string - ); + const stencil = StencilShapeRegistry.getStencil(node.getAttribute('name')); if (stencil) { const x = x0 + Number(node.getAttribute('x')) * sx; diff --git a/packages/core/src/view/geometry/node/StencilShapeRegistry.ts b/packages/core/src/view/geometry/node/StencilShapeRegistry.ts index f9ddbf2ffb..7fa66bd2b0 100644 --- a/packages/core/src/view/geometry/node/StencilShapeRegistry.ts +++ b/packages/core/src/view/geometry/node/StencilShapeRegistry.ts @@ -23,48 +23,38 @@ type Stencils = { }; /** - * A singleton class that provides a registry for stencils and the methods - * for painting those stencils onto a canvas or into a DOM. + * A singleton class that provides a registry for stencils and the methods for painting those stencils onto a canvas or into a DOM. * * Code to add stencils: * ```javascript - * let req = mxUtils.load('test/stencils.xml'); - * let root = req.getDocumentElement(); - * let shape = root.firstChild; + * const req = load('test/stencils.xml'); + * const root = req.getDocumentElement(); + * const shape = root.firstChild; * - * while (shape != null) - * { - * if (shape.nodeType === mxConstants.NODETYPE_ELEMENT) - * { - * mxStencilRegistry.addStencil(shape.getAttribute('name'), new mxStencil(shape)); + * while (shape) { + * if (shape.nodeType === mxConstants.NODETYPE_ELEMENT) { + * StencilRegistry.addStencil(shape.getAttribute('name'), new mxStencil(shape)); * } * * shape = shape.nextSibling; * } * ``` - * @class StencilShapeRegistry */ class StencilShapeRegistry { static stencils: Stencils = {}; /** - * Adds the given {@link Stencil}. - * @static - * @param {string} name - * @param {StencilShape} stencil + * Adds the given {@link StencilShape}. */ - static addStencil(name: string, stencil: StencilShape) { + static addStencil(name: string, stencil: StencilShape): void { StencilShapeRegistry.stencils[name] = stencil; } /** - * Returns the {@link Stencil} for the given name. - * @static - * @param {string} name - * @returns {StencilShape} + * Returns the {@link StencilShape} for the given name. */ - static getStencil(name: string) { - return StencilShapeRegistry.stencils[name]; + static getStencil(name?: string | null): StencilShape | undefined { + return StencilShapeRegistry.stencils[name!]; } } diff --git a/packages/html/stories/Stencils.stories.ts b/packages/html/stories/Stencils.stories.ts index ac19120876..5355963c8d 100644 --- a/packages/html/stories/Stencils.stories.ts +++ b/packages/html/stories/Stencils.stories.ts @@ -95,7 +95,7 @@ const Template = ({ label, ...args }: Record) => { // Uses the shape for resize previews createSelectionShape(bounds: Rectangle) { - const stencil = StencilShapeRegistry.getStencil(this.state.style.shape ?? ''); + const stencil = StencilShapeRegistry.getStencil(this.state.style.shape); let shape: Shape; if (stencil) { From b989ba76964c2b3b16db16755cd6f5f3464c5b13 Mon Sep 17 00:00:00 2001 From: Thomas Bouffard <27200110+tbouffard@users.noreply.github.com> Date: Sat, 8 Feb 2025 17:20:14 +0100 Subject: [PATCH 2/3] add comment to explain usage of the non-null assertion --- packages/core/src/view/geometry/node/StencilShapeRegistry.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/core/src/view/geometry/node/StencilShapeRegistry.ts b/packages/core/src/view/geometry/node/StencilShapeRegistry.ts index 7fa66bd2b0..82a6c2fa95 100644 --- a/packages/core/src/view/geometry/node/StencilShapeRegistry.ts +++ b/packages/core/src/view/geometry/node/StencilShapeRegistry.ts @@ -54,6 +54,7 @@ class StencilShapeRegistry { * Returns the {@link StencilShape} for the given name. */ static getStencil(name?: string | null): StencilShape | undefined { + // Tests are validating that using the non-null assertion (!) is safe return StencilShapeRegistry.stencils[name!]; } } From 8e3904039dcf5dcc38c578a80ba13b10bfb2f100 Mon Sep 17 00:00:00 2001 From: Thomas Bouffard <27200110+tbouffard@users.noreply.github.com> Date: Tue, 11 Feb 2025 16:02:33 +0100 Subject: [PATCH 3/3] StencilShapeRegistry: improve example in JSDoc [skip ci] --- .../core/src/view/geometry/node/StencilShapeRegistry.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/core/src/view/geometry/node/StencilShapeRegistry.ts b/packages/core/src/view/geometry/node/StencilShapeRegistry.ts index 82a6c2fa95..823da43572 100644 --- a/packages/core/src/view/geometry/node/StencilShapeRegistry.ts +++ b/packages/core/src/view/geometry/node/StencilShapeRegistry.ts @@ -27,13 +27,13 @@ type Stencils = { * * Code to add stencils: * ```javascript - * const req = load('test/stencils.xml'); - * const root = req.getDocumentElement(); - * const shape = root.firstChild; + * const response = load('test/stencils.xml'); + * const root = response.getDocumentElement(); + * let shape = root.firstChild; * * while (shape) { * if (shape.nodeType === mxConstants.NODETYPE_ELEMENT) { - * StencilRegistry.addStencil(shape.getAttribute('name'), new mxStencil(shape)); + * StencilShapeRegistry.addStencil(shape.getAttribute('name'), new mxStencil(shape)); * } * * shape = shape.nextSibling;