jssm 5.124.0 → 5.125.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2267,15 +2267,85 @@ declare function configure(opts: {
2267
2267
  */
2268
2268
  declare function vc(col: string): string;
2269
2269
  /**
2270
- * Build a graphviz-safe node identifier for a state, by index. Accepts
2271
- * either a `string[]` (used historically; O(n) per call) or a
2272
- * precomputed `Map<state, index>` (used by rendering hot paths; O(1)
2273
- * per call). The map form is used during dot generation; the array
2274
- * form is retained for direct test access via `_test`.
2270
+ * Convert a state name into a URL-friendly slug suitable for use as the
2271
+ * body of a dot/SVG node identifier. The transformation is:
2272
+ *
2273
+ * 1. Lowercase
2274
+ * 2. Any run of characters outside `[a-z0-9]` (after lowercasing) becomes
2275
+ * a single `-`
2276
+ * 3. Leading and trailing `-` are trimmed
2277
+ *
2278
+ * If the result is empty (e.g. for a state named `"!!!"`), the empty
2279
+ * string is returned — callers are expected to fall back to an indexed
2280
+ * placeholder like `node-N`. See {@link slug_states} for the collision-
2281
+ * resolving wrapper that consumes this helper.
2282
+ *
2283
+ * ```typescript
2284
+ * slug_for('Green Light'); // 'green-light'
2285
+ * slug_for('!!!'); // ''
2286
+ * slug_for(' Foo Bar '); // 'foo-bar'
2287
+ * ```
2288
+ *
2289
+ * @param state The state name to slugify.
2290
+ * @returns The lowercase hyphen-separated slug, or empty string if none of
2291
+ * the characters were retainable.
2292
+ *
2293
+ * @internal
2294
+ */
2295
+ declare function slug_for(state: string): string;
2296
+ /**
2297
+ * Build a `Map<state, slug>` assigning every state in `states` a unique,
2298
+ * deterministic, URL-safe slug used as its dot/SVG node identifier.
2299
+ *
2300
+ * Algorithm:
2301
+ *
2302
+ * 1. Slug each state via {@link slug_for}. States whose slug comes out
2303
+ * empty fall back to `node-N`, where `N` is the state's declaration
2304
+ * index (1-based, to match user-visible numbering).
2305
+ * 2. Walk the state list in declaration order, tracking how many times
2306
+ * each base slug has already been used. The first occurrence keeps
2307
+ * the base slug; subsequent collisions get `-2`, `-3`, … suffixes.
2308
+ * If the proposed suffixed slug itself collides with a base slug
2309
+ * used later, the counter advances until a free slot is found.
2310
+ *
2311
+ * This yields a deterministic mapping given the state-declaration order,
2312
+ * so output is stable across runs.
2313
+ *
2314
+ * ```typescript
2315
+ * slug_states(['Red Light', 'red-light']);
2316
+ * // Map { 'Red Light' => 'red-light', 'red-light' => 'red-light-2' }
2317
+ *
2318
+ * slug_states(['!!!', '???']);
2319
+ * // Map { '!!!' => 'node-1', '???' => 'node-2' }
2320
+ * ```
2321
+ *
2322
+ * @param states States in declaration order.
2323
+ * @returns A `Map` from each state name to its unique slug.
2324
+ *
2325
+ * @internal
2326
+ */
2327
+ declare function slug_states(states: string[]): Map<string, string>;
2328
+ /**
2329
+ * Build a graphviz-safe node identifier for a state. Accepts either a
2330
+ * `string[]` (legacy test-only path; returns an index-based `n0`/`n1`
2331
+ * identifier via `indexOf`), or a precomputed `Map<state, slug>` produced
2332
+ * by {@link slug_states} (used by all rendering hot paths).
2333
+ *
2334
+ * When a slug map is supplied, the identifier is the slug wrapped in
2335
+ * double quotes — dot allows quoted identifiers, and the slug alphabet
2336
+ * (lowercase alphanumerics + `-`) requires quoting because bare dot IDs
2337
+ * may not contain `-`. Graphviz round-trips the quoted form through to
2338
+ * the SVG `<title>` element and uses the slug as a stable basis for the
2339
+ * generated SVG element `id` attribute.
2340
+ *
2341
+ * ```typescript
2342
+ * node_of('Red Light', new Map([['Red Light', 'red-light']]));
2343
+ * // '"red-light"'
2344
+ * ```
2275
2345
  *
2276
2346
  * @internal
2277
2347
  */
2278
- declare function node_of(state: string, state_index: string[] | Map<string, number>): string;
2348
+ declare function node_of(state: string, state_index: string[] | Map<string, number> | Map<string, string>): string;
2279
2349
  /**
2280
2350
  * Convert an 8-channel hex color (`#RRGGBBAA`) to a 6-channel hex color
2281
2351
  * (`#RRGGBB`), discarding the alpha channel. Throws if the input is not
@@ -2456,6 +2526,8 @@ declare const _test: {
2456
2526
  u_color8to6: typeof u_color8to6;
2457
2527
  vc: typeof vc;
2458
2528
  node_of: typeof node_of;
2529
+ slug_for: typeof slug_for;
2530
+ slug_states: typeof slug_states;
2459
2531
  shape_for_state: typeof shape_for_state;
2460
2532
  image_for_state: typeof image_for_state;
2461
2533
  style_for_state: typeof style_for_state;
package/jssm_viz.es6.d.ts CHANGED
@@ -2267,15 +2267,85 @@ declare function configure(opts: {
2267
2267
  */
2268
2268
  declare function vc(col: string): string;
2269
2269
  /**
2270
- * Build a graphviz-safe node identifier for a state, by index. Accepts
2271
- * either a `string[]` (used historically; O(n) per call) or a
2272
- * precomputed `Map<state, index>` (used by rendering hot paths; O(1)
2273
- * per call). The map form is used during dot generation; the array
2274
- * form is retained for direct test access via `_test`.
2270
+ * Convert a state name into a URL-friendly slug suitable for use as the
2271
+ * body of a dot/SVG node identifier. The transformation is:
2272
+ *
2273
+ * 1. Lowercase
2274
+ * 2. Any run of characters outside `[a-z0-9]` (after lowercasing) becomes
2275
+ * a single `-`
2276
+ * 3. Leading and trailing `-` are trimmed
2277
+ *
2278
+ * If the result is empty (e.g. for a state named `"!!!"`), the empty
2279
+ * string is returned — callers are expected to fall back to an indexed
2280
+ * placeholder like `node-N`. See {@link slug_states} for the collision-
2281
+ * resolving wrapper that consumes this helper.
2282
+ *
2283
+ * ```typescript
2284
+ * slug_for('Green Light'); // 'green-light'
2285
+ * slug_for('!!!'); // ''
2286
+ * slug_for(' Foo Bar '); // 'foo-bar'
2287
+ * ```
2288
+ *
2289
+ * @param state The state name to slugify.
2290
+ * @returns The lowercase hyphen-separated slug, or empty string if none of
2291
+ * the characters were retainable.
2292
+ *
2293
+ * @internal
2294
+ */
2295
+ declare function slug_for(state: string): string;
2296
+ /**
2297
+ * Build a `Map<state, slug>` assigning every state in `states` a unique,
2298
+ * deterministic, URL-safe slug used as its dot/SVG node identifier.
2299
+ *
2300
+ * Algorithm:
2301
+ *
2302
+ * 1. Slug each state via {@link slug_for}. States whose slug comes out
2303
+ * empty fall back to `node-N`, where `N` is the state's declaration
2304
+ * index (1-based, to match user-visible numbering).
2305
+ * 2. Walk the state list in declaration order, tracking how many times
2306
+ * each base slug has already been used. The first occurrence keeps
2307
+ * the base slug; subsequent collisions get `-2`, `-3`, … suffixes.
2308
+ * If the proposed suffixed slug itself collides with a base slug
2309
+ * used later, the counter advances until a free slot is found.
2310
+ *
2311
+ * This yields a deterministic mapping given the state-declaration order,
2312
+ * so output is stable across runs.
2313
+ *
2314
+ * ```typescript
2315
+ * slug_states(['Red Light', 'red-light']);
2316
+ * // Map { 'Red Light' => 'red-light', 'red-light' => 'red-light-2' }
2317
+ *
2318
+ * slug_states(['!!!', '???']);
2319
+ * // Map { '!!!' => 'node-1', '???' => 'node-2' }
2320
+ * ```
2321
+ *
2322
+ * @param states States in declaration order.
2323
+ * @returns A `Map` from each state name to its unique slug.
2324
+ *
2325
+ * @internal
2326
+ */
2327
+ declare function slug_states(states: string[]): Map<string, string>;
2328
+ /**
2329
+ * Build a graphviz-safe node identifier for a state. Accepts either a
2330
+ * `string[]` (legacy test-only path; returns an index-based `n0`/`n1`
2331
+ * identifier via `indexOf`), or a precomputed `Map<state, slug>` produced
2332
+ * by {@link slug_states} (used by all rendering hot paths).
2333
+ *
2334
+ * When a slug map is supplied, the identifier is the slug wrapped in
2335
+ * double quotes — dot allows quoted identifiers, and the slug alphabet
2336
+ * (lowercase alphanumerics + `-`) requires quoting because bare dot IDs
2337
+ * may not contain `-`. Graphviz round-trips the quoted form through to
2338
+ * the SVG `<title>` element and uses the slug as a stable basis for the
2339
+ * generated SVG element `id` attribute.
2340
+ *
2341
+ * ```typescript
2342
+ * node_of('Red Light', new Map([['Red Light', 'red-light']]));
2343
+ * // '"red-light"'
2344
+ * ```
2275
2345
  *
2276
2346
  * @internal
2277
2347
  */
2278
- declare function node_of(state: string, state_index: string[] | Map<string, number>): string;
2348
+ declare function node_of(state: string, state_index: string[] | Map<string, number> | Map<string, string>): string;
2279
2349
  /**
2280
2350
  * Convert an 8-channel hex color (`#RRGGBBAA`) to a 6-channel hex color
2281
2351
  * (`#RRGGBB`), discarding the alpha channel. Throws if the input is not
@@ -2456,6 +2526,8 @@ declare const _test: {
2456
2526
  u_color8to6: typeof u_color8to6;
2457
2527
  vc: typeof vc;
2458
2528
  node_of: typeof node_of;
2529
+ slug_for: typeof slug_for;
2530
+ slug_states: typeof slug_states;
2459
2531
  shape_for_state: typeof shape_for_state;
2460
2532
  image_for_state: typeof image_for_state;
2461
2533
  style_for_state: typeof style_for_state;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jssm",
3
- "version": "5.124.0",
3
+ "version": "5.125.0",
4
4
  "engines": {
5
5
  "node": ">=10.0.0"
6
6
  },