Skip to content

Conversation

tbouffard
Copy link
Member

@tbouffard tbouffard commented Apr 11, 2025

Previously, it was only possible to register the default builtins internally.
"Edge Marker" factory functions, used to display start and end arrows (and other shapes), are now public.
This makes it easier for applications to customize the style they need to configure.

Introduce "unregister" functions to clean the maxGraph registries:

  • They reset the loading states of the "default" elements to ensure they can be loaded again
  • Codec unregister is also available.
  • All new unregister functions are used within the story to reduce edge effects between stories.

Notes

Covers #505
Covers #760

Tasks

  • provide the unregisterAllStencilShapes function
  • in examples "without-defaults", do not call "unregister all" functions, create a custom Graph class and override the method that register default builtin styles
  • ensure there is an "unregister all" function for all registries
  • validate usage of EdgeMarker, especially in application bundled with webpack
  • review the name of all new functions and namespaces
  • review the documentation

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Added APIs to unregister all codecs, edge markers, edge styles, perimeters, shapes, and stencil shapes for enhanced configuration control.
    • Introduced a customizable graph class allowing users to disable default built-in style registrations.
  • Refactor

    • Centralized codec registration state management.
    • Reorganized style and marker registration from class-based to functional exports.
    • Updated default registration order and modularized style registrations.
  • Documentation

    • Enhanced usage docs with instructions on registering and unregistering default styles and codecs.
    • Added version tags and clarified shape/style registration guidance.
  • Chores

    • Added copyright and Apache 2.0 license headers to multiple files.

Previously, it was only possible to register the default builtins internally.
"Edge Marker" factory functions, used to display start and end arrows (and other shapes), are now public.
This makes it easier for applications to customize the style they need to configure.

Codec unregister is also available.
All new unregister functions are used within the story to reduce edge effects between stories.
@tbouffard tbouffard added the enhancement New feature or request label Apr 11, 2025
Copy link

coderabbitai bot commented Apr 11, 2025

Walkthrough

This pull request reorganizes the module exports and refactors the registration mechanism for codecs, styles, markers, and shapes. The changes centralize registration state management into a shared object, introduce new unregister functions for cleaning up defaults, and update import paths accordingly. Additionally, default style and marker registration in the Graph class has been revised, and licensing headers have been added to Storybook configuration files. Example projects have been updated to use the new unregistration functions.

Changes

File(s) Change Summary
packages/core/src/index.ts Updated MarkerShape export path; added exports for unregisterAllStencilShapes, register style elements, EdgeMarker namespace, and cell shape registration.
packages/core/src/serialization/register-model-codecs.ts,
packages/core/src/serialization/register-other-codecs.ts,
packages/core/src/serialization/register-shared.ts
Centralized codec registration state with CodecRegistrationStates; replaced local flags; added unregisterAllCodecs in register-other-codecs.
packages/core/src/view/Graph.ts Modified default registration in registerDefaults to use registerDefaultEdgeStyles and registerDefaultPerimeters instead of legacy style elements; adjusted constructor signature.
packages/core/src/view/cell/register-shapes.ts Added unregisterAllShapes function; updated documentation for registerDefaultShapes.
packages/core/src/view/geometry/edge/ConnectorShape.ts Updated import path for MarkerShape to new EdgeMarkerRegistry location.
packages/core/src/view/style/EdgeMarkerRegistry.ts,
packages/core/src/view/style/edge-markers.ts,
packages/core/src/view/style/register.ts
Added new MarkerShape class in EdgeMarkerRegistry.ts for marker registration; removed legacy class-based marker management in edge-markers.ts and replaced with standalone marker factory functions; refactored style registration functions to separate edge styles, perimeters, and markers with corresponding unregister functions.
packages/html/.storybook/main.ts,
packages/html/.storybook/preview.ts
Added copyright/license headers; updated preview configuration to remove manual clearing of codec registries and replaced with unregister functions for codecs, edge markers, styles, shapes, and stencil shapes.
packages/js-example-without-defaults/src/index.js,
packages/ts-example-without-defaults/src/main.ts
Removed direct clearing of default style and marker registries; introduced CustomGraph subclass overriding registerDefaults to prevent loading defaults; updated graph instantiation accordingly.
packages/core/src/view/cell/CellRenderer.ts,
packages/core/src/view/geometry/Shape.ts
Updated import paths for StencilShapeRegistry and StencilShape to new module locations.
packages/core/src/view/geometry/stencil/register.ts Added new function unregisterAllStencilShapes to clear all registered stencil shapes.
packages/js-example-without-defaults/src/style.css Increased #graph-container height from 70vh to 75vh; removed button margin styles.
packages/ts-example-without-defaults/src/style.css Reduced #graph-container height from 80vh to 75vh.
packages/website/docs/usage/codecs.md Added documentation for unregisterAllCodecs() function with usage example.
packages/website/docs/usage/global-configuration.md Extended documentation with examples for registering and unregistering default edge markers, edge styles, perimeters, shapes, and stencil shapes.

Sequence Diagram(s)

sequenceDiagram
    participant Graph
    participant StyleRegistry
    participant MarkerRegistry
    Graph->>StyleRegistry: registerDefaultEdgeStyles()
    StyleRegistry->>StyleRegistry: registerDefaultPerimeters()
    Graph->>MarkerRegistry: registerDefaultEdgeMarkers()
Loading
sequenceDiagram
    participant Config
    participant CodecRegistry
    participant StyleRegistry
    participant ShapeRegistry
    Config->>CodecRegistry: unregisterAllCodecs()
    Config->>StyleRegistry: unregisterAllEdgeStylesAndPerimeters()
    Config->>StyleRegistry: unregisterAllEdgeMarkers()
    Config->>ShapeRegistry: unregisterAllShapes()
Loading

Suggested labels

refactor

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@tbouffard tbouffard marked this pull request as ready for review April 11, 2025 10:35
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (8)
packages/core/src/view/style/EdgeMarkerRegistry.ts (2)

24-65: Consider using a module with functions instead of a class with static members

The MarkerShape class only contains static members, which goes against best practices in modern JavaScript/TypeScript. Consider refactoring this to use a module with exported functions instead, which would be more aligned with functional programming principles.

-class MarkerShape {
-  /**
-   * Maps from markers names to functions to paint the markers.
-   *
-   * Mapping: the attribute name on the object is the marker type, the associated value is the function to paint the marker
-   */
-  static markers: Record<string, MarkerFactoryFunction> = {};
-
-  /**
-   * Adds a factory method that updates a given endpoint and returns a
-   * function to paint the marker onto the given canvas.
-   */
-  static addMarker(type: string, funct: MarkerFactoryFunction) {
-    MarkerShape.markers[type] = funct;
-  }
-
-  /**
-   * Returns a function to paint the given marker.
-   */
-  static createMarker(
-    canvas: AbstractCanvas2D,
-    shape: Shape,
-    type: StyleArrowValue,
-    pe: Point,
-    unitX: number,
-    unitY: number,
-    size: number,
-    source: boolean,
-    sw: number,
-    filled: boolean
-  ) {
-    const markerFunction = MarkerShape.markers[type];
-    return markerFunction
-      ? markerFunction(canvas, shape, type, pe, unitX, unitY, size, source, sw, filled)
-      : null;
-  }
-}
-
-export default MarkerShape;
+/**
+ * Maps from markers names to functions to paint the markers.
+ */
+const markers: Record<string, MarkerFactoryFunction> = {};
+
+/**
+ * Adds a factory method that updates a given endpoint and returns a
+ * function to paint the marker onto the given canvas.
+ */
+export function addMarker(type: string, funct: MarkerFactoryFunction) {
+  markers[type] = funct;
+}
+
+/**
+ * Returns a function to paint the given marker.
+ */
+export function createMarker(
+  canvas: AbstractCanvas2D,
+  shape: Shape,
+  type: StyleArrowValue,
+  pe: Point,
+  unitX: number,
+  unitY: number,
+  size: number,
+  source: boolean,
+  sw: number,
+  filled: boolean
+) {
+  const markerFunction = markers[type];
+  return markerFunction
+    ? markerFunction(canvas, shape, type, pe, unitX, unitY, size, source, sw, filled)
+    : null;
+}
+
+export { markers };

This would also require updating imports and references throughout the codebase.

🧰 Tools
🪛 Biome (1.9.4)

[error] 28-65: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


28-28: Update comment to provide more context

The comment mentions that the signature and name of this class will change. Consider providing more details about the planned changes or removing this comment if the changes are already implemented.

🧰 Tools
🪛 Biome (1.9.4)

[error] 28-65: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)

packages/core/src/view/style/edge-markers.ts (3)

26-27: Improve JSDoc clarity.

Though these lines briefly describe the purpose of the function, consider adding a more explicit note about expected usage or example calls. This can help new contributors quickly understand how to use the marker factories.


86-88: Maintain consistent JSDoc references.

These doc comments mirror the style above but ensure the wording explicitly states the primary function of createOpenArrow (e.g., “Registers or creates open arrow shapes for edge markers”).


135-137: Clarify function description.

The doc comment for oval could include details about the shape’s alignment and sizing rules so others can quickly understand how to customize it, if necessary.

packages/core/src/view/style/register.ts (3)

24-48: Fix possible typo in function name.

registerDefaultEdgStyles might be missing an “e” in “Edge.” Rename this exported function to avoid confusion:

-export const registerDefaultEdgStyles = (): void => {
+export const registerDefaultEdgeStyles = (): void => {

71-82: Potential side effects of fully clearing StyleRegistry.

StyleRegistry.values = {} removes all custom and built-in styles. In some scenarios, users might prefer partial unregistration. Consider providing a more granular approach if there's a risk of accidental data loss.


112-121: Unregistration resets all marker definitions.

MarkerShape.markers = {}— similar to edge styles, any custom markers set after defaults were registered will also be lost. Consider a more targeted removal strategy if the library’s usage requires preserving custom markers.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d621ab6 and 0c9d467.

📒 Files selected for processing (14)
  • packages/core/src/index.ts (3 hunks)
  • packages/core/src/serialization/register-model-codecs.ts (3 hunks)
  • packages/core/src/serialization/register-other-codecs.ts (5 hunks)
  • packages/core/src/serialization/register-shared.ts (1 hunks)
  • packages/core/src/view/Graph.ts (2 hunks)
  • packages/core/src/view/cell/register-shapes.ts (2 hunks)
  • packages/core/src/view/geometry/edge/ConnectorShape.ts (1 hunks)
  • packages/core/src/view/style/EdgeMarkerRegistry.ts (1 hunks)
  • packages/core/src/view/style/edge-markers.ts (5 hunks)
  • packages/core/src/view/style/register.ts (2 hunks)
  • packages/html/.storybook/main.ts (1 hunks)
  • packages/html/.storybook/preview.ts (4 hunks)
  • packages/js-example-without-defaults/src/index.js (2 hunks)
  • packages/ts-example-without-defaults/src/main.ts (2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (6)
packages/core/src/serialization/register-model-codecs.ts (1)
packages/core/src/serialization/register-shared.ts (1)
  • CodecRegistrationStates (25-30)
packages/js-example-without-defaults/src/index.js (2)
packages/core/src/view/style/register.ts (2)
  • unregisterAllEdgeMarkers (118-121)
  • unregisterAllEdgeStylesAndPerimeters (78-82)
packages/core/src/view/cell/register-shapes.ts (1)
  • unregisterAllShapes (81-84)
packages/core/src/view/style/EdgeMarkerRegistry.ts (1)
packages/core/src/types.ts (2)
  • MarkerFactoryFunction (1258-1269)
  • StyleArrowValue (937-937)
packages/core/src/view/Graph.ts (1)
packages/core/src/view/style/register.ts (2)
  • registerDefaultEdgStyles (33-48)
  • registerDefaultPerimeters (59-69)
packages/ts-example-without-defaults/src/main.ts (2)
packages/core/src/view/style/register.ts (2)
  • unregisterAllEdgeMarkers (118-121)
  • unregisterAllEdgeStylesAndPerimeters (78-82)
packages/core/src/view/cell/register-shapes.ts (1)
  • unregisterAllShapes (81-84)
packages/core/src/view/style/register.ts (1)
packages/core/src/view/style/edge-markers.ts (4)
  • createArrow (29-84)
  • createOpenArrow (90-133)
  • oval (138-165)
  • diamond (170-218)
🪛 Biome (1.9.4)
packages/core/src/view/style/EdgeMarkerRegistry.ts

[error] 28-65: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build (windows-2022)
🔇 Additional comments (33)
packages/core/src/view/cell/register-shapes.ts (2)

39-45: Documentation update looks good.

The revised documentation clearly explains what registerDefaultShapes does and includes the version tag, which is helpful for tracking when this function was introduced or formalized.


73-84: Good implementation of unregister functionality.

The new unregisterAllShapes function provides a clean way to reset the shape registry, which aligns with the PR objective of allowing unregistration of default style elements. The implementation correctly:

  1. Clears the defaultShapes object
  2. Resets the registration flag

This will be useful in scenarios where applications need to customize styles or reset between different contexts (as mentioned in the PR objectives).

packages/html/.storybook/main.ts (1)

1-15: License header addition is appropriate.

Adding the Apache License 2.0 header ensures proper licensing attribution for this file, which is good practice for open source projects.

packages/core/src/view/geometry/edge/ConnectorShape.ts (1)

21-21: Import path change reflects appropriate refactoring.

This change aligns with the PR objective of providing public access to "Edge Marker" factory functions. Moving the MarkerShape import to reference the centralized EdgeMarkerRegistry supports better organization and accessibility of these marker functions for customization purposes.

packages/core/src/serialization/register-model-codecs.ts (2)

27-27: Good centralization of codec registration states.

Importing CodecRegistrationStates from a shared module improves the organization of registration state management across the codebase.


45-45: Appropriate use of shared registration state.

Using the centralized CodecRegistrationStates.model instead of a local variable for tracking registration status is a good refactoring that enables consistent state management. This change supports the PR objective of improving the unregistration capabilities by making registration states accessible across modules.

Also applies to: 61-61

packages/core/src/serialization/register-shared.ts (3)

17-18: Clarifying the private nature of these elements is helpful.

This comment accurately indicates that the elements in this file are not meant to be part of the public API, which helps prevent misuse.


22-30: Good implementation of a centralized state tracking mechanism.

Using a shared object to track registration states across different codec types is a more maintainable approach than individual boolean flags. The private annotation in the JSDoc is consistent with the comment at the top of the file.


32-40: Consistent usage of the new registration state tracking.

The function now properly uses the centralized state object instead of a local variable, making it more consistent with other codec registration functions.

packages/core/src/view/Graph.ts (2)

59-63: Improved organization of style registration imports.

The imports have been restructured to be more specific, importing individual functions rather than a single function. This makes dependencies clearer and follows better import practices.


493-498: Better separation of concerns in style registration.

The registerDefaults method now calls separate functions for edge styles and perimeters instead of a single function for all style elements. This follows the Single Responsibility Principle and makes the code more modular.

packages/core/src/serialization/register-other-codecs.ts (4)

37-37: Updated import to use the new centralized registration state.

The import now includes CodecRegistrationStates to leverage the shared registration state tracking.


72-84: Consistent usage of the centralized registration state.

The function now checks and updates the core codec registration state using the shared object instead of a local variable, making it consistent with other codec registration functions.


96-105: Updated editor codecs registration to use shared state.

Similar to the core codecs, the editor codecs registration now uses the centralized state management approach.


122-137: Well-implemented codec unregistration function.

This new function provides a clean way to unregister all codecs and reset their registration states. The comments are clear and the implementation is straightforward, resetting both the registry data structures and the registration state flags.

packages/js-example-without-defaults/src/index.js (2)

17-25: Better API usage with dedicated unregister functions.

The imports have been updated to use specific unregister functions rather than importing low-level components directly. This encapsulates implementation details and provides a cleaner API.


45-49: Improved approach to unregistering built-in defaults.

Using dedicated unregister functions instead of directly manipulating internal properties is a better approach as it provides a stable API and hides implementation details. The comments also clearly explain the rationale behind unregistering these defaults.

packages/ts-example-without-defaults/src/main.ts (2)

22-24: Improved API for managing style elements

These imports of dedicated unregister functions show a better approach to managing styles compared to the previous direct manipulation of internal objects.


45-49: API improvement for unregistering default styles

The old approach involved direct manipulation of internal objects (CellRenderer.defaultShapes = {}, etc.), while this new approach abstracts the unregistration logic into dedicated functions, making the code cleaner and less fragile.

 // Unregister maxGraph builtin style defaults
 // This is because Graph registers them. In the future, we expect to have an implementation of Graph that does not do it.
 unregisterAllEdgeMarkers();
 unregisterAllEdgeStylesAndPerimeters();
 unregisterAllShapes();
packages/html/.storybook/preview.ts (3)

1-15: Adds standard licensing header

Good addition of the copyright and license information for the Storybook configuration files, ensuring proper attribution and licensing clarity.


35-38: Adds new unregister function imports

These imported functions provide a cleaner API for unregistering default style elements and codecs, which aligns with the PR objectives.


74-82: Improved cleanup using dedicated unregister functions

The code now uses dedicated unregister functions instead of directly manipulating internal registry objects, making the reset functionality more maintainable and less error-prone.

packages/core/src/index.ts (3)

107-107: Updated export path for MarkerShape

The export path for MarkerShape has been updated from ./view/geometry/edge/MarkerShape to ./view/style/EdgeMarkerRegistry, reflecting the reorganization of code to provide better access to edge marker factory functions.


160-161: New exports for style registration and edge markers

These exports provide public access to the register functions and edge marker functionality, aligning with the PR objective to enhance customization capabilities of default style elements.


199-199: Export shape registration functions

Exporting all functions from ./view/cell/register-shapes provides users with access to shape registration functions, including the new unregisterAllShapes function, enhancing customization capabilities.

packages/core/src/view/style/edge-markers.ts (5)

19-23: Check for consistent naming and import usage.

These imports correctly reference the relevant types and constants. Ensure that all imported types (e.g., StyleArrowValue, AbstractCanvas2D, Shape, Point) are actually needed and used to avoid clutter.


29-31: Validate arrow function conversion.

Converting from a regular function to an arrow function is appropriate for better scoping and clarity. Confirm that all references to createArrow in the codebase are updated accordingly and ensure no calls were expecting a named function.


90-92: Check arrow function usage.

Similar to createArrow, confirm that all external references to createOpenArrow are updated to this new exported constant form.


138-138: Exporting as a constant.

Switching the shape factory to a constant arrow function improves modular clarity. Ensure there’s no performance regression due to repeated closure creation, though this is likely negligible for typical usage.


167-169: Validate diamond shape logic.

The diamond marker logic correctly subtracts offset and carefully adjusts positions. Confirm that the type === ARROW.DIAMOND distinction for thickness is suitable for all use cases, especially if changing arrow types dynamically.

Also applies to: 170-181

packages/core/src/view/style/register.ts (3)

21-22: Confirm “EdgeMarkerRegistry” import correctness.

MarkerShape is now imported from EdgeMarkerRegistry; verify that this is the intended module. If you plan further refactoring, consider aligning namespaces to keep them consistent across style modules.


50-69: Global state for perimeters.

isDefaultPerimetersRegistered prevents double registration. This is fine, but confirm that calling registerDefaultPerimeters() again in conflicting contexts (e.g., test environments with multiple runs) does not cause stale state.


84-111: Registering default markers.

The approach of using the new MarkerShape.addMarker for each shape is overall clear and consistent. Validate that the shape keys (e.g., “classic” vs. “block”) do not conflict with any built-in or user-defined markers.

@tbouffard tbouffard marked this pull request as draft April 11, 2025 15:38
@tbouffard tbouffard marked this pull request as ready for review April 11, 2025 16:09
@tbouffard tbouffard marked this pull request as draft April 11, 2025 16:17
Copy link

@tbouffard tbouffard marked this pull request as ready for review April 22, 2025 15:39
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🔭 Outside diff range comments (1)
packages/core/src/view/style/edge-markers.ts (1)

36-49: ⚠️ Potential issue

Validate widthFactor to avoid division‑by‑zero traps

widthFactor is later used as a divisor (unitY / widthFactor, unitX / widthFactor).
If client code accidentally passes 0, the generated marker factory will raise a runtime Infinity/NaN, which is hard to trace back.

 export const createArrow =
-  (widthFactor: number) =>
+  (widthFactor: number) => {
+    if (widthFactor === 0) {
+      throw new Error('EdgeMarker.createArrow: widthFactor must be non‑zero');
+    }
+    return
+  }

Apply a similar guard in createOpenArrow.
(If 0 is a meaningful value, document the behaviour explicitly instead.)

🧹 Nitpick comments (7)
packages/core/src/view/style/edge-markers.ts (3)

103-116: Duplicate logic: extract a shared helper for open/filled arrows

createOpenArrow largely duplicates the maths performed in createArrow, differing only in the path/finish logic.
Moving the common geometry into a small internal helper (e.g. computeArrowGeometry) would:

  • Remove ~40 LoC duplication
  • Keep the two public factories trivially readable
  • Reduce the risk of the two drifting out of sync

60-66: Side‑effect on pe merits a JSDoc warning

Both factories mutate the incoming pe (pe.x += …).
Because points are mutable references in maxGraph, callers that reuse the same Point instance after the marker callback may observe unexpected shifts.

Add a short note in the JSDoc explaining that pe is modified in‑place so users can clone beforehand if necessary.


151-178: Return‑type annotations improve DX

The factories currently return an untyped closure.
Declaring a shared type MarkerPainter = () => void (or re‑using an existing one if present) and annotating the return value helps IDE inference and prevents accidental misuse.

packages/js-example-without-defaults/src/index.js (1)

88-97: Consistent vertex‑creation API improves readability

The first two vertices use { position: [x,y], size: [w,h] }, whereas the third uses the legacy { x, y, width, height } shape.
Mixing both styles in one example may confuse newcomers.

Either:

  • switch to the modern tuple form everywhere, or
  • add a comment illustrating that both syntaxes are accepted.
packages/website/docs/usage/global-configuration.md (1)

62-78: Link to API docs for faster discovery

The new sample is great, but readers may not immediately know where the functions live.
Add inline links (or fully qualified import names) for each function, e.g.:

```js
import {
  registerDefaultEdgeMarkers,
  unregisterAllEdgeMarkers,
} from '@maxgraph/core/view/style/register';

This makes the snippet copy‑paste‑ready and reduces friction.

packages/ts-example-without-defaults/src/main.ts (1)

30-32: Consider adding more detail to the method documentation

The comment "// do nothing" is accurate but minimal. Consider expanding it to briefly explain what defaults would normally be registered by the parent class and why you're explicitly choosing not to register them in this context.

 protected override registerDefaults() {
-  // do nothing
+  // do nothing - intentionally not registering default edge markers, styles, perimeters and shapes
+  // that would normally be registered by the Graph class
 }
packages/html/.storybook/preview.ts (1)

61-86: Consider adding explanatory comment about the new reset approach

The function now uses a more systematic approach to reset configurations. Consider adding a comment explaining the significance of using dedicated unregister functions and how this improves maintainability.

const resetMaxGraphConfigs = (): void => {
+  // Using dedicated unregister functions to reset all configurations
+  // instead of directly manipulating registry objects.
+  // This ensures proper cleanup and state reset between stories.
  // Global configuration
  GlobalConfig.i18n = i18nProvider;
  GlobalConfig.logger = defaultLogger;
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2d67db1 and 80f6c88.

📒 Files selected for processing (15)
  • packages/core/src/index.ts (3 hunks)
  • packages/core/src/view/Graph.ts (2 hunks)
  • packages/core/src/view/cell/CellRenderer.ts (1 hunks)
  • packages/core/src/view/cell/register-shapes.ts (2 hunks)
  • packages/core/src/view/geometry/Shape.ts (1 hunks)
  • packages/core/src/view/geometry/stencil/register.ts (1 hunks)
  • packages/core/src/view/style/edge-markers.ts (5 hunks)
  • packages/core/src/view/style/register.ts (2 hunks)
  • packages/html/.storybook/preview.ts (4 hunks)
  • packages/js-example-without-defaults/src/index.js (1 hunks)
  • packages/js-example-without-defaults/src/style.css (1 hunks)
  • packages/ts-example-without-defaults/src/main.ts (1 hunks)
  • packages/ts-example-without-defaults/src/style.css (1 hunks)
  • packages/website/docs/usage/codecs.md (1 hunks)
  • packages/website/docs/usage/global-configuration.md (1 hunks)
✅ Files skipped from review due to trivial changes (6)
  • packages/core/src/view/geometry/Shape.ts
  • packages/js-example-without-defaults/src/style.css
  • packages/website/docs/usage/codecs.md
  • packages/ts-example-without-defaults/src/style.css
  • packages/core/src/view/cell/CellRenderer.ts
  • packages/core/src/view/geometry/stencil/register.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • packages/core/src/view/cell/register-shapes.ts
  • packages/core/src/view/style/register.ts
  • packages/core/src/index.ts
  • packages/core/src/view/Graph.ts
🧰 Additional context used
🧬 Code Graph Analysis (2)
packages/js-example-without-defaults/src/index.js (3)
packages/core/src/view/Graph.ts (1)
  • Graph (1498-1498)
packages/core/src/index.ts (1)
  • Graph (20-20)
packages/js-example/src/index.js (4)
  • initializeGraph (59-73)
  • container (80-80)
  • graph (63-66)
  • graph (81-81)
packages/html/.storybook/preview.ts (5)
packages/core/src/serialization/register-other-codecs.ts (1)
  • unregisterAllCodecs (129-137)
packages/core/src/serialization/codecs/StylesheetCodec.ts (1)
  • StylesheetCodec (34-195)
packages/core/src/view/style/register.ts (2)
  • unregisterAllEdgeMarkers (119-122)
  • unregisterAllEdgeStylesAndPerimeters (79-83)
packages/core/src/view/cell/register-shapes.ts (1)
  • unregisterAllShapes (81-84)
packages/core/src/index.ts (1)
  • unregisterAllStencilShapes (118-118)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build (windows-2022)
🔇 Additional comments (8)
packages/js-example-without-defaults/src/index.js (1)

21-33: Confirm constructor order when overriding registerDefaults

The trick of overriding registerDefaults is elegant, but relies on Graph calling the method after the subclass v‑table is in place.
If Graph is ever refactored to perform default registration in a static helper before the ctor finishes, the override will silently stop working.

Consider adding a unit/integration test or an assertion inside the override:

registerDefaults() {
  // Ensure this override is actually invoked
  console.debug('CustomGraph.registerDefaults() skipped');
}

Or expose an opt‑in flag upstream to avoid subclassing.

packages/ts-example-without-defaults/src/main.ts (2)

20-33: Great approach for preventing default style registration!

Creating a custom Graph subclass that overrides registerDefaults to do nothing is a more elegant solution than the previous approach of registering defaults and then clearing them. This aligns well with the PR objective of enhancing customization capabilities.


39-43: Instantiating CustomGraph correctly

The change to use the new CustomGraph class is properly implemented.

packages/html/.storybook/preview.ts (5)

1-15: Added appropriate license header

The addition of the Apache 2.0 license header is correctly formatted and includes the necessary copyright information.


34-38: Good use of new unregister functions

Importing the dedicated unregister functions aligns well with the PR objectives of introducing unregister functions for default style elements.


74-76: Improved codec cleanup with centralized unregister function

Using unregisterAllCodecs() instead of manually clearing codec registries is more maintainable and aligns with the centralized registration state management approach.


79-83: Comprehensive cleanup of style registries

The addition of calls to unregister edge markers, styles, perimeters, and shapes ensures a complete reset of the style-related configuration, which is important for preventing edge effects between stories.


84-86: Consistent approach for stencil shapes

Using unregisterAllStencilShapes() instead of directly manipulating registry objects maintains consistency with the overall approach of using dedicated unregister functions.

@tbouffard tbouffard merged commit ffba6de into main Apr 22, 2025
7 checks passed
@tbouffard tbouffard deleted the feat/register_unregister_default_styles branch April 22, 2025 15:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant