yfiles-nodestyle-basic — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited yfiles-nodestyle-basic (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Create custom node visualizations by extending NodeStyleBase and implementing SVG rendering with typed visual caching.
Always query the yFiles MCP for current API:
yfiles:yfiles_get_symbol_details(name="NodeStyleBase")
yfiles:yfiles_get_symbol_details(name="TaggedSvgVisual")
yfiles:yfiles_list_members(name="NodeStyleBase")
yfiles:yfiles_search_documentation(query="custom node style")The simplest possible style — no caching, no updateVisual. Suitable for prototyping but not recommended for larger graphs.
import { NodeStyleBase, SvgVisual, type IRenderContext, type INode } from '@yfiles/yfiles'
export class CustomNodeStyle extends NodeStyleBase {
protected createVisual(context: IRenderContext, node: INode): SvgVisual {
const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect')
const { x, y, width, height } = node.layout
rect.setAttribute('x', String(x))
rect.setAttribute('y', String(y))
rect.setAttribute('width', String(width))
rect.setAttribute('height', String(height))
rect.setAttribute('fill', '#0b7189')
return new SvgVisual(rect)
}
}For production implementations, declare a Cache type and a named visual type using TaggedSvgVisual, then pass it as the type argument to NodeStyleBase. This enables typed access to visual.tag in updateVisual and avoids recreating DOM elements on every render frame.
import {
NodeStyleBase,
SvgVisual,
TaggedSvgVisual,
type IRenderContext,
type INode
} from '@yfiles/yfiles'
// 1. Declare the cache shape
type Cache = { width: number; height: number }
// 2. Declare the visual type — ties the SVG element type to the cache type
type CustomNodeStyleVisual = TaggedSvgVisual<SVGPathElement, Cache>
// 3. Pass the visual type as the type argument to NodeStyleBase
export class CustomNodeStyle extends NodeStyleBase<CustomNodeStyleVisual> {
protected createVisual(
context: IRenderContext,
node: INode
): CustomNodeStyleVisual {
const { x, y, width, height } = node.layout
const pathElement = document.createElementNS(
'http://www.w3.org/2000/svg',
'path'
)
// Render at (0,0) and position via transform — required for efficient updates
pathElement.setAttribute('d', createPathData(0, 0, width, height))
SvgVisual.setTranslate(pathElement, x, y)
pathElement.setAttribute('fill', '#0b7189')
pathElement.setAttribute('stroke', '#042d37')
// SvgVisual.from() creates a TaggedSvgVisual with the cache stored in .tag
return SvgVisual.from(pathElement, { width, height })
}
protected updateVisual(
context: IRenderContext,
oldVisual: CustomNodeStyleVisual,
node: INode
): CustomNodeStyleVisual {
const { x, y, width, height } = node.layout
const pathElement = oldVisual.svgElement
const cache = oldVisual.tag // fully typed as Cache
// Only rebuild the path when size actually changed
if (width !== cache.width || height !== cache.height) {
pathElement.setAttribute('d', createPathData(0, 0, width, height))
oldVisual.tag = { width, height }
}
// Always update position via transform
SvgVisual.setTranslate(pathElement, x, y)
return oldVisual
}
}.tagTaggedSvgVisual in one call(0,0) and use SvgVisual.setTranslate() for position — only the transform needs updating when a node movesCache type with the values needed to detect changes in updateVisualCustomNodeStyleVisual = TaggedSvgVisual<TElement, Cache> type aliasNodeStyleBase<CustomNodeStyleVisual>createVisual(): render at (0,0), set translate, return SvgVisual.from(element, cache)updateVisual(): read oldVisual.tag (typed), update only changed attributes, always update translateTo extend this foundation:
/yfiles-nodestyle-configure — Make styles configurable and data-driven/yfiles-nodestyle-interaction — Add hit testing and edge cropping/yfiles-nodestyle-advanced — Viewport culling and group nodes~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.