Skip to content

fix(svgcanvas): Handle 'none' stroke color in SVG elements#1084

Merged
jfhenon merged 1 commit into
SVG-Edit:masterfrom
shfshanyue:master
Mar 16, 2026
Merged

fix(svgcanvas): Handle 'none' stroke color in SVG elements#1084
jfhenon merged 1 commit into
SVG-Edit:masterfrom
shfshanyue:master

Conversation

@shfshanyue
Copy link
Copy Markdown
Contributor

@shfshanyue shfshanyue commented Mar 16, 2026

This update modifies the stroke color handling in both the SvgCanvas and ext-connector modules. When the stroke color is set to 'none', it now correctly assigns an empty string or 'none' instead of a hex value, ensuring proper rendering of SVG elements without strokes.

PR description

Checklist

Note that we require UI tests to ensure that the added feature will not be
nixed by some future fix and that there is at least some test-as-documentation
to indicate how the fix or enhancement is expected to behave.

  • - Added Cypress UI tests
  • - Ran npm test, ensuring linting passes and that Cypress UI tests keep
    coverage to at least the same percent (reflected in the coverage badge
    that should be updated after the tests run)
  • - Added any user documentation. Though not required, this can be a big
    help both for future users and for the PR reviewer.

Summary by Sourcery

Handle SVG stroke color set to 'none' without converting it to a hex value, ensuring connectors and newly created elements render correctly without strokes.

Bug Fixes:

  • Ensure connectors created by the ext-connector extension preserve a 'none' stroke value instead of forcing a hex color.
  • Prevent SvgCanvas from prefixing a hex marker when the initial stroke color is 'none', allowing elements to have no stroke as intended.

This update modifies the stroke color handling in both the SvgCanvas and ext-connector modules. When the stroke color is set to 'none', it now correctly assigns an empty string or 'none' instead of a hex value, ensuring proper rendering of SVG elements without strokes.
@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented Mar 16, 2026

Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Adjusts stroke color initialization so that a stroke value of 'none' is preserved (or becomes an empty string) instead of being converted to a hex color, fixing rendering of no-stroke SVG elements in both SvgCanvas and the connector extension.

Class diagram for SvgCanvas stroke configuration handling

classDiagram
  class SvgCanvas {
    +InitConfig curConfig
  }

  class InitConfig {
    +InitFillConfig initFill
    +InitStrokeConfig initStroke
  }

  class InitFillConfig {
    +string color
    +number opacity
  }

  class InitStrokeConfig {
    +string color
    +number opacity
    +number width
  }

  SvgCanvas --> InitConfig : uses
  InitConfig --> InitFillConfig : has
  InitConfig --> InitStrokeConfig : has

  class NewShapeAttributes {
    +string stroke
    +number stroke_opacity
    +number stroke_width
  }

  SvgCanvas ..> NewShapeAttributes : computes

  class ConnectorAttributes {
    +string id
    +string points
    +string stroke
    +number stroke_width
  }

  SvgCanvas ..> ConnectorAttributes : used_by_ext_connector
Loading

Flow diagram for stroke attribute computation when initStroke.color may be none

flowchart TD
  A[Start: initStroke.color or curConfig.initStroke.color] --> B{Context}
  B -->|SvgCanvas element init| C[Check curConfig.initStroke.color]
  B -->|ext-connector connector creation| H[Check initStroke.color]

  C --> D{curConfig.initStroke.color === none}
  D -->|Yes| E[stroke = empty string]
  D -->|No| F[stroke = # + curConfig.initStroke.color]
  E --> G[Apply stroke to new SVG element]
  F --> G[Apply stroke to new SVG element]

  H --> I{initStroke.color === none}
  I -->|Yes| J[stroke = none]
  I -->|No| K[stroke = # + initStroke.color]
  J --> L[Apply stroke to connector polyline]
  K --> L[Apply stroke to connector polyline]

  G --> M[SVG element renders with or without stroke as intended]
  L --> M[Connector renders with or without stroke as intended]
Loading

File-Level Changes

Change Details Files
Preserve 'none' stroke value when creating connector elements instead of forcing a hex color string.
  • Update connector creation attributes to set stroke to 'none' when initStroke.color is 'none'.
  • Fallback to the previous hex color behavior only when initStroke.color is not 'none'.
src/editor/extensions/ext-connector/ext-connector.js
Handle 'none' stroke color in SvgCanvas initial configuration by avoiding prepending a hex hash when stroke is disabled.
  • Change stroke initialization to prepend '#' only when initStroke.color is not 'none'.
  • Ensure that when initStroke.color is 'none', stroke is set to an empty string rather than a hex value.
packages/svgcanvas/svgcanvas.js

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Hey - I've found 1 issue, and left some high level feedback:

  • The handling of initStroke.color === 'none' is implemented slightly differently between ext-connector (explicit 'none') and svgcanvas (empty string + color), which may lead to diverging behavior over time; consider centralizing stroke serialization in a small helper so both callsites stay consistent.
  • In svgcanvas, the expression (this.curConfig.initStroke.color === 'none' ? '' : '#') + this.curConfig.initStroke.color will emit values like 'none', but will also happily stringify unexpected values (e.g., null'#null'); it may be safer to guard for non‑string/empty stroke colors before concatenation.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The handling of `initStroke.color === 'none'` is implemented slightly differently between `ext-connector` (explicit `'none'`) and `svgcanvas` (empty string + color), which may lead to diverging behavior over time; consider centralizing stroke serialization in a small helper so both callsites stay consistent.
- In `svgcanvas`, the expression `(this.curConfig.initStroke.color === 'none' ? '' : '#') + this.curConfig.initStroke.color` will emit values like `'none'`, but will also happily stringify unexpected values (e.g., `null``'#null'`); it may be safer to guard for non‑string/empty stroke colors before concatenation.

## Individual Comments

### Comment 1
<location path="packages/svgcanvas/svgcanvas.js" line_range="202-208" />
<code_context>
         fill_paint: null,
         fill_opacity: this.curConfig.initFill.opacity,
-        stroke: `#${this.curConfig.initStroke.color}`,
+        stroke:
+          (this.curConfig.initStroke.color === 'none' ? '' : '#') +
+          this.curConfig.initStroke.color,
         stroke_paint: null,
</code_context>
<issue_to_address>
**suggestion:** The stroke formatting ternary is a bit opaque and could be made clearer and less error‑prone.

This relies on the reader noticing that `'' + 'none'` evaluates to `'none'`, which is correct but non-obvious and brittle if more sentinel values are added later. You could make this clearer with something like:

```js
stroke = this.curConfig.initStroke.color === 'none'
  ? 'none'
  : `#${this.curConfig.initStroke.color}`;
```

This makes the special case explicit and separates the `#` prefixing from the value logic.

```suggestion
        fill_paint: null,
        fill_opacity: this.curConfig.initFill.opacity,
        stroke:
          this.curConfig.initStroke.color === 'none'
            ? 'none'
            : `#${this.curConfig.initStroke.color}`,
        stroke_paint: null,
        stroke_opacity: this.curConfig.initStroke.opacity,
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines 202 to 208
fill_paint: null,
fill_opacity: this.curConfig.initFill.opacity,
stroke: `#${this.curConfig.initStroke.color}`,
stroke:
(this.curConfig.initStroke.color === 'none' ? '' : '#') +
this.curConfig.initStroke.color,
stroke_paint: null,
stroke_opacity: this.curConfig.initStroke.opacity,
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

suggestion: The stroke formatting ternary is a bit opaque and could be made clearer and less error‑prone.

This relies on the reader noticing that '' + 'none' evaluates to 'none', which is correct but non-obvious and brittle if more sentinel values are added later. You could make this clearer with something like:

stroke = this.curConfig.initStroke.color === 'none'
  ? 'none'
  : `#${this.curConfig.initStroke.color}`;

This makes the special case explicit and separates the # prefixing from the value logic.

Suggested change
fill_paint: null,
fill_opacity: this.curConfig.initFill.opacity,
stroke: `#${this.curConfig.initStroke.color}`,
stroke:
(this.curConfig.initStroke.color === 'none' ? '' : '#') +
this.curConfig.initStroke.color,
stroke_paint: null,
stroke_opacity: this.curConfig.initStroke.opacity,
fill_paint: null,
fill_opacity: this.curConfig.initFill.opacity,
stroke:
this.curConfig.initStroke.color === 'none'
? 'none'
: `#${this.curConfig.initStroke.color}`,
stroke_paint: null,
stroke_opacity: this.curConfig.initStroke.opacity,

@jfhenon jfhenon merged commit 7c6085e into SVG-Edit:master Mar 16, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants