@webpieces/nx-webpieces-rules 0.4.911 → 0.4.912

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webpieces/nx-webpieces-rules",
3
- "version": "0.4.911",
3
+ "version": "0.4.912",
4
4
  "description": "Nx-specific webpieces validation rules, graph tooling, executors, and inference plugin.",
5
5
  "type": "commonjs",
6
6
  "main": "./src/index.js",
@@ -20,12 +20,12 @@
20
20
  "README.md"
21
21
  ],
22
22
  "dependencies": {
23
- "@webpieces/api-doc-model": "0.4.911",
24
- "@webpieces/core-util": "0.4.911",
25
- "@webpieces/eslint-rules": "0.4.911",
26
- "@webpieces/rules-config": "0.4.911",
23
+ "@webpieces/api-doc-model": "0.4.912",
24
+ "@webpieces/core-util": "0.4.912",
25
+ "@webpieces/eslint-rules": "0.4.912",
26
+ "@webpieces/rules-config": "0.4.912",
27
27
  "madge": "8.0.0",
28
- "@webpieces/rules-sdk": "0.4.911"
28
+ "@webpieces/rules-sdk": "0.4.912"
29
29
  },
30
30
  "peerDependencies": {
31
31
  "@nx/devkit": ">=18.0.0"
@@ -41,7 +41,7 @@
41
41
  "access": "public"
42
42
  },
43
43
  "devDependencies": {
44
- "@webpieces/tooling-testkit": "0.4.911"
44
+ "@webpieces/tooling-testkit": "0.4.912"
45
45
  },
46
46
  "types": "./src/index.d.ts",
47
47
  "bin": {
package/src/index.d.ts CHANGED
@@ -28,7 +28,7 @@ export type { ApiDocMode } from './configs/api-doc-rules-config';
28
28
  export { ApiClientPackagesEntry, ApiLibDependenciesConfig, ApiLibPathConfig, FrameworkFolderEntry, FrameworkFolderConfig, ProductDependencyEntry, ProductTagsConfig } from './configs/tag-truth-configs';
29
29
  export { GraphRenderModel, RenderNode, RenderEdge, NodeTags } from './lib/graph-render-model';
30
30
  export { GraphMode, NodeModeDots, LegendFacts, ProductCount } from './lib/graph-color-modes';
31
- export { ProductMembership, RuntimeProductMembership, ProductPalette, ProductColor, ProductBoundary } from './lib/graph-products';
31
+ export { ProductMembership, RuntimeProductMembership, ProductPalette, ProductColor, ProductPaletteSlot, PRODUCT_PALETTE_SLOTS, ProductBoundary, } from './lib/graph-products';
32
32
  export { ProductDependencyMatrix } from './lib/product-dependencies';
33
33
  export { ProductResolver, ProductResolution, PRODUCT_TAG_PREFIX } from './lib/product-resolver';
34
34
  export { EntryPointLevels } from './lib/graph-entry-levels';
package/src/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.EntryPointLevels = exports.PRODUCT_TAG_PREFIX = exports.ProductResolution = exports.ProductResolver = exports.ProductDependencyMatrix = exports.ProductBoundary = exports.ProductColor = exports.ProductPalette = exports.RuntimeProductMembership = exports.ProductMembership = exports.ProductCount = exports.LegendFacts = exports.NodeModeDots = exports.GraphMode = exports.NodeTags = exports.RenderEdge = exports.RenderNode = exports.GraphRenderModel = exports.ProductTagsConfig = exports.ProductDependencyEntry = exports.FrameworkFolderConfig = exports.FrameworkFolderEntry = exports.ApiLibPathConfig = exports.ApiLibDependenciesConfig = exports.ApiClientPackagesEntry = exports.ApiRulesForMcpConfig = exports.ApiRulesForOpenApiConfig = exports.API_DOC_MODES = exports.NoRootUnionApiTypeConfig = exports.WiringFormatConfig = exports.ValidateEslintSyncConfig = exports.ValidateVersionsLockedConfig = exports.ValidatePackageJsonConfig = exports.ValidateNoArchitectureCyclesConfig = exports.ValidateArchitectureUnchangedConfig = exports.MissingDesignAnnotationConfig = exports.DiGraphConfig = exports.NxWiringConfig = exports.RuntimeArchitectureConfig = exports.NoFileImportCyclesConfig = exports.STRUCTURAL_MODES = exports.createNodesV2 = void 0;
3
+ exports.EntryPointLevels = exports.PRODUCT_TAG_PREFIX = exports.ProductResolution = exports.ProductResolver = exports.ProductDependencyMatrix = exports.ProductBoundary = exports.PRODUCT_PALETTE_SLOTS = exports.ProductPaletteSlot = exports.ProductColor = exports.ProductPalette = exports.RuntimeProductMembership = exports.ProductMembership = exports.ProductCount = exports.LegendFacts = exports.NodeModeDots = exports.GraphMode = exports.NodeTags = exports.RenderEdge = exports.RenderNode = exports.GraphRenderModel = exports.ProductTagsConfig = exports.ProductDependencyEntry = exports.FrameworkFolderConfig = exports.FrameworkFolderEntry = exports.ApiLibPathConfig = exports.ApiLibDependenciesConfig = exports.ApiClientPackagesEntry = exports.ApiRulesForMcpConfig = exports.ApiRulesForOpenApiConfig = exports.API_DOC_MODES = exports.NoRootUnionApiTypeConfig = exports.WiringFormatConfig = exports.ValidateEslintSyncConfig = exports.ValidateVersionsLockedConfig = exports.ValidatePackageJsonConfig = exports.ValidateNoArchitectureCyclesConfig = exports.ValidateArchitectureUnchangedConfig = exports.MissingDesignAnnotationConfig = exports.DiGraphConfig = exports.NxWiringConfig = exports.RuntimeArchitectureConfig = exports.NoFileImportCyclesConfig = exports.STRUCTURAL_MODES = exports.createNodesV2 = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  tslib_1.__exportStar(require("./lib/graph-generator"), exports);
6
6
  tslib_1.__exportStar(require("./lib/graph-sorter"), exports);
@@ -62,6 +62,8 @@ Object.defineProperty(exports, "ProductMembership", { enumerable: true, get: fun
62
62
  Object.defineProperty(exports, "RuntimeProductMembership", { enumerable: true, get: function () { return graph_products_1.RuntimeProductMembership; } });
63
63
  Object.defineProperty(exports, "ProductPalette", { enumerable: true, get: function () { return graph_products_1.ProductPalette; } });
64
64
  Object.defineProperty(exports, "ProductColor", { enumerable: true, get: function () { return graph_products_1.ProductColor; } });
65
+ Object.defineProperty(exports, "ProductPaletteSlot", { enumerable: true, get: function () { return graph_products_1.ProductPaletteSlot; } });
66
+ Object.defineProperty(exports, "PRODUCT_PALETTE_SLOTS", { enumerable: true, get: function () { return graph_products_1.PRODUCT_PALETTE_SLOTS; } });
65
67
  Object.defineProperty(exports, "ProductBoundary", { enumerable: true, get: function () { return graph_products_1.ProductBoundary; } });
66
68
  var product_dependencies_1 = require("./lib/product-dependencies");
67
69
  Object.defineProperty(exports, "ProductDependencyMatrix", { enumerable: true, get: function () { return product_dependencies_1.ProductDependencyMatrix; } });
package/src/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../packages/tooling/nx-webpieces-rules/src/index.ts"],"names":[],"mappings":";;;;AAAA,gEAAsC;AACtC,6DAAmC;AACnC,iEAAuC;AACvC,kEAAwC;AACxC,6DAAmC;AACnC,iEAAuC;AACvC,+DAAqC;AACrC,mEAAyC;AACzC,6EAAmD;AACnD,6DAAmC;AACnC,iEAAuC;AACvC,6DAAmC;AACnC,2EAAiD;AACjD,uEAA6C;AAC7C,qCAAyC;AAChC,8FADA,sBAAa,OACA;AACtB,kBAAe,EAAE,IAAI,EAAE,+BAA+B,EAAE,aAAa,EAAb,sBAAa,EAAE,CAAC;AAExE,uDAAyU;AAAhU,gHAAA,gBAAgB,OAAA;AAAE,wHAAA,wBAAwB,OAAA;AAAE,yHAAA,yBAAyB,OAAA;AAAE,8GAAA,cAAc,OAAA;AAAE,6GAAA,aAAa,OAAA;AAAE,6HAAA,6BAA6B,OAAA;AAAE,mIAAA,mCAAmC,OAAA;AAAE,kIAAA,kCAAkC,OAAA;AAAE,yHAAA,yBAAyB,OAAA;AAAE,4HAAA,4BAA4B,OAAA;AAAE,wHAAA,wBAAwB,OAAA;AAExS,uEAAoE;AAA3D,0HAAA,kBAAkB,OAAA;AAC3B,uEAA0E;AAAjE,gIAAA,wBAAwB,OAAA;AACjC,uEAA+G;AAAtG,qHAAA,aAAa,OAAA;AAAE,gIAAA,wBAAwB,OAAA;AAAE,4HAAA,oBAAoB,OAAA;AAEtE,iEAAyM;AAAhM,2HAAA,sBAAsB,OAAA;AAAE,6HAAA,wBAAwB,OAAA;AAAE,qHAAA,gBAAgB,OAAA;AAAE,yHAAA,oBAAoB,OAAA;AAAE,0HAAA,qBAAqB,OAAA;AAAE,2HAAA,sBAAsB,OAAA;AAAE,sHAAA,iBAAiB,OAAA;AAEnK,+DAA8F;AAArF,sHAAA,gBAAgB,OAAA;AAAE,gHAAA,UAAU,OAAA;AAAE,gHAAA,UAAU,OAAA;AAAE,8GAAA,QAAQ,OAAA;AAC3D,6DAA6F;AAApF,8GAAA,SAAS,OAAA;AAAE,iHAAA,YAAY,OAAA;AAAE,gHAAA,WAAW,OAAA;AAAE,iHAAA,YAAY,OAAA;AAC3D,uDAAkI;AAAzH,mHAAA,iBAAiB,OAAA;AAAE,0HAAA,wBAAwB,OAAA;AAAE,gHAAA,cAAc,OAAA;AAAE,8GAAA,YAAY,OAAA;AAAE,iHAAA,eAAe,OAAA;AACnG,mEAAqE;AAA5D,+HAAA,uBAAuB,OAAA;AAChC,2DAAgG;AAAvF,mHAAA,eAAe,OAAA;AAAE,qHAAA,iBAAiB,OAAA;AAAE,sHAAA,kBAAkB,OAAA;AAC/D,+DAA4D;AAAnD,sHAAA,gBAAgB,OAAA","sourcesContent":["export * from './lib/graph-generator';\nexport * from './lib/graph-sorter';\nexport * from './lib/graph-comparator';\nexport * from './lib/package-validator';\nexport * from './lib/graph-loader';\nexport * from './lib/graph-visualizer';\nexport * from './lib/graph-metadata';\nexport * from './lib/framework-resolver';\nexport * from './lib/runtime-participant-resolver';\nexport * from './lib/project-info';\nexport * from './lib/responsibilities';\nexport * from './lib/di-graph/dot';\nexport * from './lib/di-graph/design-visualizer';\nexport * from './lib/di-graph/design-finder';\nimport { createNodesV2 } from './plugin';\nexport { createNodesV2 };\nexport default { name: '@webpieces/nx-webpieces-rules', createNodesV2 };\n\nexport { STRUCTURAL_MODES, NoFileImportCyclesConfig, RuntimeArchitectureConfig, NxWiringConfig, DiGraphConfig, MissingDesignAnnotationConfig, ValidateArchitectureUnchangedConfig, ValidateNoArchitectureCyclesConfig, ValidatePackageJsonConfig, ValidateVersionsLockedConfig, ValidateEslintSyncConfig } from './configs/rule-configs';\nexport type { StructuralMode } from './configs/rule-configs';\nexport { WiringFormatConfig } from './configs/wiring-format-config';\nexport { NoRootUnionApiTypeConfig } from './configs/no-root-union-config';\nexport { API_DOC_MODES, ApiRulesForOpenApiConfig, ApiRulesForMcpConfig } from './configs/api-doc-rules-config';\nexport type { ApiDocMode } from './configs/api-doc-rules-config';\nexport { ApiClientPackagesEntry, ApiLibDependenciesConfig, ApiLibPathConfig, FrameworkFolderEntry, FrameworkFolderConfig, ProductDependencyEntry, ProductTagsConfig } from './configs/tag-truth-configs';\n\nexport { GraphRenderModel, RenderNode, RenderEdge, NodeTags } from './lib/graph-render-model';\nexport { GraphMode, NodeModeDots, LegendFacts, ProductCount } from './lib/graph-color-modes';\nexport { ProductMembership, RuntimeProductMembership, ProductPalette, ProductColor, ProductBoundary } from './lib/graph-products';\nexport { ProductDependencyMatrix } from './lib/product-dependencies';\nexport { ProductResolver, ProductResolution, PRODUCT_TAG_PREFIX } from './lib/product-resolver';\nexport { EntryPointLevels } from './lib/graph-entry-levels';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../packages/tooling/nx-webpieces-rules/src/index.ts"],"names":[],"mappings":";;;;AAAA,gEAAsC;AACtC,6DAAmC;AACnC,iEAAuC;AACvC,kEAAwC;AACxC,6DAAmC;AACnC,iEAAuC;AACvC,+DAAqC;AACrC,mEAAyC;AACzC,6EAAmD;AACnD,6DAAmC;AACnC,iEAAuC;AACvC,6DAAmC;AACnC,2EAAiD;AACjD,uEAA6C;AAC7C,qCAAyC;AAChC,8FADA,sBAAa,OACA;AACtB,kBAAe,EAAE,IAAI,EAAE,+BAA+B,EAAE,aAAa,EAAb,sBAAa,EAAE,CAAC;AAExE,uDAAyU;AAAhU,gHAAA,gBAAgB,OAAA;AAAE,wHAAA,wBAAwB,OAAA;AAAE,yHAAA,yBAAyB,OAAA;AAAE,8GAAA,cAAc,OAAA;AAAE,6GAAA,aAAa,OAAA;AAAE,6HAAA,6BAA6B,OAAA;AAAE,mIAAA,mCAAmC,OAAA;AAAE,kIAAA,kCAAkC,OAAA;AAAE,yHAAA,yBAAyB,OAAA;AAAE,4HAAA,4BAA4B,OAAA;AAAE,wHAAA,wBAAwB,OAAA;AAExS,uEAAoE;AAA3D,0HAAA,kBAAkB,OAAA;AAC3B,uEAA0E;AAAjE,gIAAA,wBAAwB,OAAA;AACjC,uEAA+G;AAAtG,qHAAA,aAAa,OAAA;AAAE,gIAAA,wBAAwB,OAAA;AAAE,4HAAA,oBAAoB,OAAA;AAEtE,iEAAyM;AAAhM,2HAAA,sBAAsB,OAAA;AAAE,6HAAA,wBAAwB,OAAA;AAAE,qHAAA,gBAAgB,OAAA;AAAE,yHAAA,oBAAoB,OAAA;AAAE,0HAAA,qBAAqB,OAAA;AAAE,2HAAA,sBAAsB,OAAA;AAAE,sHAAA,iBAAiB,OAAA;AAEnK,+DAA8F;AAArF,sHAAA,gBAAgB,OAAA;AAAE,gHAAA,UAAU,OAAA;AAAE,gHAAA,UAAU,OAAA;AAAE,8GAAA,QAAQ,OAAA;AAC3D,6DAA6F;AAApF,8GAAA,SAAS,OAAA;AAAE,iHAAA,YAAY,OAAA;AAAE,gHAAA,WAAW,OAAA;AAAE,iHAAA,YAAY,OAAA;AAC3D,uDAQ8B;AAP1B,mHAAA,iBAAiB,OAAA;AACjB,0HAAA,wBAAwB,OAAA;AACxB,gHAAA,cAAc,OAAA;AACd,8GAAA,YAAY,OAAA;AACZ,oHAAA,kBAAkB,OAAA;AAClB,uHAAA,qBAAqB,OAAA;AACrB,iHAAA,eAAe,OAAA;AAEnB,mEAAqE;AAA5D,+HAAA,uBAAuB,OAAA;AAChC,2DAAgG;AAAvF,mHAAA,eAAe,OAAA;AAAE,qHAAA,iBAAiB,OAAA;AAAE,sHAAA,kBAAkB,OAAA;AAC/D,+DAA4D;AAAnD,sHAAA,gBAAgB,OAAA","sourcesContent":["export * from './lib/graph-generator';\nexport * from './lib/graph-sorter';\nexport * from './lib/graph-comparator';\nexport * from './lib/package-validator';\nexport * from './lib/graph-loader';\nexport * from './lib/graph-visualizer';\nexport * from './lib/graph-metadata';\nexport * from './lib/framework-resolver';\nexport * from './lib/runtime-participant-resolver';\nexport * from './lib/project-info';\nexport * from './lib/responsibilities';\nexport * from './lib/di-graph/dot';\nexport * from './lib/di-graph/design-visualizer';\nexport * from './lib/di-graph/design-finder';\nimport { createNodesV2 } from './plugin';\nexport { createNodesV2 };\nexport default { name: '@webpieces/nx-webpieces-rules', createNodesV2 };\n\nexport { STRUCTURAL_MODES, NoFileImportCyclesConfig, RuntimeArchitectureConfig, NxWiringConfig, DiGraphConfig, MissingDesignAnnotationConfig, ValidateArchitectureUnchangedConfig, ValidateNoArchitectureCyclesConfig, ValidatePackageJsonConfig, ValidateVersionsLockedConfig, ValidateEslintSyncConfig } from './configs/rule-configs';\nexport type { StructuralMode } from './configs/rule-configs';\nexport { WiringFormatConfig } from './configs/wiring-format-config';\nexport { NoRootUnionApiTypeConfig } from './configs/no-root-union-config';\nexport { API_DOC_MODES, ApiRulesForOpenApiConfig, ApiRulesForMcpConfig } from './configs/api-doc-rules-config';\nexport type { ApiDocMode } from './configs/api-doc-rules-config';\nexport { ApiClientPackagesEntry, ApiLibDependenciesConfig, ApiLibPathConfig, FrameworkFolderEntry, FrameworkFolderConfig, ProductDependencyEntry, ProductTagsConfig } from './configs/tag-truth-configs';\n\nexport { GraphRenderModel, RenderNode, RenderEdge, NodeTags } from './lib/graph-render-model';\nexport { GraphMode, NodeModeDots, LegendFacts, ProductCount } from './lib/graph-color-modes';\nexport {\n ProductMembership,\n RuntimeProductMembership,\n ProductPalette,\n ProductColor,\n ProductPaletteSlot,\n PRODUCT_PALETTE_SLOTS,\n ProductBoundary,\n} from './lib/graph-products';\nexport { ProductDependencyMatrix } from './lib/product-dependencies';\nexport { ProductResolver, ProductResolution, PRODUCT_TAG_PREFIX } from './lib/product-resolver';\nexport { EntryPointLevels } from './lib/graph-entry-levels';\n"]}
@@ -140,6 +140,13 @@ export declare class LegendFacts {
140
140
  noRuntime: boolean;
141
141
  /** One count per declared product, in palette (sorted-name) order; empty when none is declared. */
142
142
  products: ProductCount[];
143
+ /**
144
+ * The ONE palette every box was painted with (#1244), built over the full declared product set.
145
+ * The legend, the Filter's product chips and the crossing edges read their colors from it, never
146
+ * from a palette of their own: collision resolution depends on the set, so a second palette built
147
+ * from a subset could disagree with the boxes.
148
+ */
149
+ palette: ProductPalette;
143
150
  /** Boxes shared by every product (two or more declared). */
144
151
  sharedByAll: number;
145
152
  /** Boxes in no product. */
@@ -219,6 +219,13 @@ class LegendFacts {
219
219
  noRuntime = false;
220
220
  /** One count per declared product, in palette (sorted-name) order; empty when none is declared. */
221
221
  products = [];
222
+ /**
223
+ * The ONE palette every box was painted with (#1244), built over the full declared product set.
224
+ * The legend, the Filter's product chips and the crossing edges read their colors from it, never
225
+ * from a palette of their own: collision resolution depends on the set, so a second palette built
226
+ * from a subset could disagree with the boxes.
227
+ */
228
+ palette = new graph_products_1.ProductPalette([]);
222
229
  /** Boxes shared by every product (two or more declared). */
223
230
  sharedByAll = 0;
224
231
  /** Boxes in no product. */
@@ -290,6 +297,7 @@ class NodeModeStyler {
290
297
  }
291
298
  /** The Product section's counts: per product (total, and only-this-product), shared-by-all, none. */
292
299
  recordProducts(legend, facts, palette) {
300
+ legend.palette = palette;
293
301
  if (legend.products.length === 0 && palette.colors.length > 0) {
294
302
  legend.products = palette.names().map((product) => new ProductCount(product, 0, 0));
295
303
  }
@@ -1 +1 @@
1
- {"version":3,"file":"graph-color-modes.js","sourceRoot":"","sources":["../../../../../../packages/tooling/nx-webpieces-rules/src/lib/graph-color-modes.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Graph color modes (#1155, restyled by #1158)\n *\n * The architecture graph answers ONE question at a time instead of asking every box to encode two\n * (fill = framework AND border = role). Each box is emitted once per mode, so the page can switch\n * modes and re-render without regenerating anything. Every mode writes the SAME three lines on a box\n * (level + name, role, every framework tag); only the color changes:\n *\n * - RUNTIME \"where the code can run\". One runtime is a solid fill. One runtime plus a\n * specialization (angular/react inside browser, express inside node) is NESTED: an\n * outer frame in the base color around an inner rounded box in the specialization's\n * color, carrying the text. Several runtimes are full-height vertical stripes in the\n * fixed order browser | node | react-native, with the text written across them. The\n * dependency rule becomes visual: a box may depend on a box carrying every color it has.\n * - ARCHITECTURE \"servers · clients · APIs\". A solid fill by ROLE; framework color is not shown.\n * - IMPACT \"what changed\" — on this branch, or in the last commit (graph-impact.ts).\n * Projects owning a changed file are solid amber (\"touched\"); the rest of nx's affected set is light amber (\"affected\": their ci\n * re-runs); every transitive dependency of the affected set that is not itself\n * affected is light slate with a dashed border (\"build input\": compiled or restored\n * from cache, unchanged); everything else is grey. Which box is which is only known\n * per checkout, so every box carries all four variants and the page picks one from the\n * sidecar (graph-impact.ts). The state is never written on the box: color + legend.\n * The words are the Filter's: changed · dependent · dependency (built, unchanged) ·\n * not in this build.\n * - PRODUCT \"which products it belongs to\" (#1179, graph-products.ts). One product is a solid\n * fill in that product's palette color; two or more (but not all) are the same\n * vertical stripes the multi-runtime box uses, one per product; a box shared by EVERY\n * product is one neutral fill (otherwise a shared foundation would be four-stripe\n * noise); a box in no product is white with a dashed border. The Filter HIDES other\n * products' boxes; this mode keeps every box and makes ownership visible.\n */\n\nimport { KNOWN_FRAMEWORKS, KnownFramework } from '@webpieces/rules-sdk';\nimport { dotValue, htmlLabelText } from './dot-syntax';\nimport { PRODUCT_NONE_BORDER, PRODUCT_NONE_FILL, PRODUCT_SHARED_FILL, ProductColor, ProductPalette } from './graph-products';\nimport type { ProductDependencyEntry } from '../configs/tag-truth-configs';\n\nexport enum GraphMode {\n RUNTIME = 'runtime',\n ARCHITECTURE = 'architecture',\n IMPACT = 'impact',\n PRODUCT = 'product',\n}\n\n/** One selectable mode as the drawer's Color-by pulldown shows it. */\nexport class ModeInfo {\n constructor(\n public readonly mode: GraphMode,\n public readonly name: string,\n public readonly subtitle: string,\n ) {}\n}\n\n/** In key order: `1` selects the first, `2` the second, `3` the third, `4` the fourth. */\nexport const GRAPH_MODES: readonly ModeInfo[] = [\n new ModeInfo(GraphMode.RUNTIME, 'Runtime', 'where the code can run'),\n new ModeInfo(GraphMode.ARCHITECTURE, 'Architecture', 'servers · clients · APIs'),\n new ModeInfo(GraphMode.IMPACT, 'Impact', 'what changed'),\n new ModeInfo(GraphMode.PRODUCT, 'Product', 'which products it belongs to'),\n];\n\n/** Text on a light fill. */\nexport const DARK_TEXT = '#1a1c22';\n/** Text on a dark fill. */\nexport const LIGHT_TEXT = '#ffffff';\n\n/**\n * A framework value's color, the text color that reads on it, and the BASE runtime it is drawn\n * inside (itself, for a base).\n */\nexport class FrameworkStyle {\n constructor(\n public readonly framework: KnownFramework,\n public readonly base: KnownFramework,\n public readonly color: string,\n public readonly fontColor: string,\n public readonly description: string,\n ) {}\n\n isBase(): boolean {\n return this.framework === this.base;\n }\n}\n\n/**\n * Keyed by the shared vocabulary, so a framework added to KNOWN_FRAMEWORKS without a color here is a\n * COMPILE error — not a box silently painted grey and missing from the legend, which is exactly how\n * react-native shipped (#1155). Every base is mid-light, so dark text reads on every stripe.\n */\nexport const FRAMEWORK_STYLES: Record<KnownFramework, FrameworkStyle> = {\n browser: new FrameworkStyle('browser', 'browser', '#7d8cf2', DARK_TEXT, 'browser base runtime'),\n node: new FrameworkStyle('node', 'node', '#6fcf8a', DARK_TEXT, 'node base runtime'),\n 'react-native': new FrameworkStyle(\n 'react-native',\n 'react-native',\n '#34b8a6',\n DARK_TEXT,\n 'its own runtime, not a browser',\n ),\n angular: new FrameworkStyle('angular', 'browser', '#c8243f', LIGHT_TEXT, 'inside browser'),\n react: new FrameworkStyle('react', 'browser', '#7fd8ff', DARK_TEXT, 'inside browser'),\n express: new FrameworkStyle('express', 'node', '#2e7d4f', LIGHT_TEXT, 'inside node'),\n};\n\n/** Stripe order, left to right. Fixed, so the same set always reads the same way. */\nexport const BASE_ORDER: readonly KnownFramework[] = ['browser', 'node', 'react-native'];\n\n/**\n * The Filter popover's Runtime chips, and the order line 3 of a box lists framework tags in: the\n * bases first, then the specializations.\n */\nexport const FRAMEWORK_ORDER: readonly KnownFramework[] = [\n 'browser',\n 'node',\n 'react-native',\n 'angular',\n 'react',\n 'express',\n];\n\n/** A box with no known framework tag. */\nexport const NO_RUNTIME_COLOR = '#e4e6ec';\n\n/** The class Graphviz stamps on a multi-runtime box's `<g>`: its outline is its LAST shape. */\nexport const STRIPED_CLASS = 'wp-striped';\n\n/** Margin of base color around a specialization's inner box. */\nconst NEST_PAD = 5;\n/** Padding between the inner box's edge and its text. */\nconst INNER_PAD = 6;\n\n/** A role's solid fill and the text color that stays readable on it. */\nexport class RoleStyle {\n constructor(\n public readonly role: string,\n public readonly fill: string,\n public readonly fontColor: string,\n public readonly description: string,\n ) {}\n}\n\n/**\n * Every role role-resolver knows, in legend order (runnable things first) — also the Filter popover's\n * Role chips. `bundle` is indigo so no box color equals the page's violet accent.\n */\nexport const ROLE_STYLES: readonly RoleStyle[] = [\n new RoleStyle('server', '#4caf50', LIGHT_TEXT, 'runnable server'),\n new RoleStyle('client', '#e5533d', LIGHT_TEXT, 'browser or mobile client app'),\n new RoleStyle('app', '#1e88e5', LIGHT_TEXT, 'runnable non-HTTP app'),\n new RoleStyle('bundle', '#4b44c8', LIGHT_TEXT, 'bundles several apps'),\n new RoleStyle('api-lib', '#f08a24', DARK_TEXT, 'contract + DTOs'),\n new RoleStyle('api-client', '#1a9aa6', LIGHT_TEXT, 'contract + SDK implementation'),\n new RoleStyle('designed-lib', '#7d8597', LIGHT_TEXT, 'library with a generated design'),\n new RoleStyle('lib', '#d7dae2', DARK_TEXT, 'plain library'),\n];\n\n/** The four impact shades (graph-impact.ts decides which box gets which). */\nexport const IMPACT_TOUCHED = '#f5a524';\nexport const IMPACT_AFFECTED = '#fde3b0';\nexport const IMPACT_BUILD_INPUT = '#e3e9f2';\nexport const IMPACT_BUILD_INPUT_BORDER = '#7c8aa3';\nexport const IMPACT_UNTOUCHED = '#eef0f4';\nconst IMPACT_UNTOUCHED_TEXT = '#6b7180';\n\n/** What a box's per-mode rendering — and the page's Filter — is computed from. */\nexport class NodeFacts {\n constructor(\n public readonly nodeId: string,\n public readonly shortName: string,\n public readonly level: number,\n public readonly role: string,\n public readonly frameworks: string[],\n /** The products the project belongs to (dependencies.json `products`), sorted; empty for none. */\n public readonly products: string[],\n public readonly summary: string = '',\n ) {}\n}\n\n/** One box's DOT statement for every mode (and for each impact state). */\nexport class NodeModeDots {\n constructor(\n public readonly runtime: string,\n public readonly architecture: string,\n public readonly touched: string,\n public readonly affected: string,\n public readonly buildInput: string,\n public readonly untouched: string,\n public readonly product: string,\n ) {}\n}\n\n/** How many drawn boxes one product holds, and how many of them no other product does. */\nexport class ProductCount {\n constructor(\n public readonly product: string,\n public total: number,\n public only: number,\n ) {}\n}\n\n/** Which colors and roles the drawn projects actually use, so the legend lists exactly those. */\nexport class LegendFacts {\n frameworks: string[] = [];\n roles: string[] = [];\n multiRuntime = false;\n noRuntime = false;\n /** One count per declared product, in palette (sorted-name) order; empty when none is declared. */\n products: ProductCount[] = [];\n /** Boxes shared by every product (two or more declared). */\n sharedByAll = 0;\n /** Boxes in no product. */\n noProduct = 0;\n /** Some box belongs to two or more products, but not to every one: it is striped. */\n multiProduct = false;\n /** Dependency edges crossing into another product (#1204), drawn dashed in the Product mode. */\n crossProductEdges = 0;\n /**\n * The `product-tags` rule's matrix (#1204), listed in the Product legend; null when the rule is\n * OFF or the page was drawn without it.\n */\n productDependencies: ProductDependencyEntry[] | null = null;\n}\n\nexport class NodeModeStyler {\n styleOf(framework: string): FrameworkStyle | undefined {\n if (!(KNOWN_FRAMEWORKS as readonly string[]).includes(framework)) return undefined;\n return FRAMEWORK_STYLES[framework as KnownFramework];\n }\n\n roleStyle(role: string): RoleStyle {\n const style = ROLE_STYLES.find((candidate: RoleStyle): boolean => candidate.role === role);\n return style ?? (ROLE_STYLES.find((s: RoleStyle): boolean => s.role === 'lib') as RoleStyle);\n }\n\n /** Every role the renderer styles; a spec asserts this covers role-resolver's KNOWN_ROLES. */\n styledRoles(): string[] {\n return ROLE_STYLES.map((style: RoleStyle): string => style.role);\n }\n\n /** The base runtimes of a framework set, in stripe order (a specialization implies its base). */\n bases(frameworks: string[]): KnownFramework[] {\n const present = new Set<KnownFramework>();\n for (const framework of frameworks) {\n const style = this.styleOf(framework);\n if (style !== undefined) present.add(style.base);\n }\n return BASE_ORDER.filter((base: KnownFramework): boolean => present.has(base));\n }\n\n /** The specialization drawn inside `base`, if the set carries one. */\n specialization(base: KnownFramework, frameworks: string[]): FrameworkStyle | undefined {\n for (const framework of KNOWN_FRAMEWORKS) {\n const style = FRAMEWORK_STYLES[framework];\n if (style.isBase() || style.base !== base) continue;\n if (frameworks.includes(framework)) return style;\n }\n return undefined;\n }\n\n dots(facts: NodeFacts, palette: ProductPalette): NodeModeDots {\n return new NodeModeDots(\n this.runtime(facts),\n this.plain(facts, this.roleStyle(facts.role).fill, this.roleStyle(facts.role).fontColor, ''),\n this.plain(facts, IMPACT_TOUCHED, DARK_TEXT, ''),\n this.plain(facts, IMPACT_AFFECTED, DARK_TEXT, `, color=\"${IMPACT_TOUCHED}\", penwidth=2`),\n this.plain(\n facts,\n IMPACT_BUILD_INPUT,\n DARK_TEXT,\n `, color=\"${IMPACT_BUILD_INPUT_BORDER}\", penwidth=1.5`,\n 'filled,dashed',\n ),\n this.plain(facts, IMPACT_UNTOUCHED, IMPACT_UNTOUCHED_TEXT, ', color=\"#b4b9c4\"'),\n this.product(facts, palette),\n );\n }\n\n /** Fold one drawn box into the legend facts. */\n record(legend: LegendFacts, facts: NodeFacts, palette: ProductPalette): void {\n this.recordProducts(legend, facts, palette);\n for (const framework of facts.frameworks) {\n if (this.styleOf(framework) !== undefined && !legend.frameworks.includes(framework))\n legend.frameworks.push(framework);\n }\n const role = this.roleStyle(facts.role).role;\n if (!legend.roles.includes(role)) legend.roles.push(role);\n const bases = this.bases(facts.frameworks);\n if (bases.length > 1) legend.multiRuntime = true;\n if (bases.length === 0) legend.noRuntime = true;\n }\n\n /** The Product section's counts: per product (total, and only-this-product), shared-by-all, none. */\n private recordProducts(legend: LegendFacts, facts: NodeFacts, palette: ProductPalette): void {\n if (legend.products.length === 0 && palette.colors.length > 0) {\n legend.products = palette.names().map((product: string): ProductCount => new ProductCount(product, 0, 0));\n }\n if (facts.products.length === 0) legend.noProduct++;\n if (palette.sharedByAll(facts.products)) legend.sharedByAll++;\n else if (facts.products.length > 1) legend.multiProduct = true;\n for (const count of legend.products) {\n if (!facts.products.includes(count.product)) continue;\n count.total++;\n if (facts.products.length === 1) count.only++;\n }\n }\n\n /**\n * Line 3 of every box: every framework tag, bases before specializations, any tag outside the\n * shared vocabulary last (it still runs somewhere somebody declared).\n */\n frameworkLine(frameworks: string[]): string {\n if (frameworks.length === 0) return 'no framework tag';\n const known = FRAMEWORK_ORDER.filter((framework: KnownFramework): boolean =>\n frameworks.includes(framework),\n );\n const unknown = frameworks.filter((framework: string): boolean => this.styleOf(framework) === undefined);\n return [...known, ...unknown].join(' · ');\n }\n\n /**\n * The three lines, identical in every mode: `L3 name` (level dimmed, name bold), the role, and\n * the framework tags. The level is dimmed by giving its text color an alpha channel, which\n * Graphviz writes as `fill-opacity`, so it dims on any fill.\n */\n labelText(facts: NodeFacts, fontColor: string): string {\n return (\n `<FONT COLOR=\"${fontColor}99\">L${facts.level}</FONT>&#160;&#160;<B>${htmlLabelText(facts.shortName)}</B>` +\n `<BR/>${htmlLabelText(facts.role)}<BR/>${htmlLabelText(this.frameworkLine(facts.frameworks))}` +\n (facts.summary === '' ? '' : `<BR/>${htmlLabelText(facts.summary)}`)\n );\n }\n\n /** `filled` for one runtime; equal `striped` weights for several (the last takes the remainder). */\n stripeAttrs(bases: KnownFramework[]): string {\n return this.stripes(bases.map((base: KnownFramework): string => FRAMEWORK_STYLES[base].color));\n }\n\n /**\n * One equal vertical stripe per color — the renderer the multi-runtime box and the multi-product\n * box share. A single color is a plain fill.\n */\n stripes(colors: string[]): string {\n if (colors.length === 1) return `style=\"filled\", fillcolor=\"${colors[0]}\"`;\n const share = (1 / colors.length).toFixed(3);\n const weighted = colors.map((color: string, index: number): string =>\n index === colors.length - 1 ? color : `${color};${share}`,\n );\n return `style=\"striped\", fillcolor=\"${weighted.join(':')}\", class=\"${STRIPED_CLASS}\"`;\n }\n\n private statement(facts: NodeFacts, attrs: string, label: string): string {\n return ` \"${dotValue(facts.nodeId)}\" [${attrs}, label=<${label}>];\\n`;\n }\n\n /** A solid fill, the three lines on it. `extra` carries border attributes. */\n private plain(facts: NodeFacts, fill: string, fontColor: string, extra: string, style = 'filled'): string {\n return this.statement(\n facts,\n `style=\"${style}\", fillcolor=\"${fill}\", fontcolor=\"${fontColor}\"${extra}`,\n this.labelText(facts, fontColor),\n );\n }\n\n /**\n * Product mode (#1179): one product solid in its color; several (not all) striped, one stripe per\n * product; every product the neutral shared fill; no product a white box with a dashed border.\n */\n private product(facts: NodeFacts, palette: ProductPalette): string {\n if (facts.products.length === 0)\n return this.plain(facts, PRODUCT_NONE_FILL, DARK_TEXT, `, color=\"${PRODUCT_NONE_BORDER}\", penwidth=1.5`, 'filled,dashed');\n if (palette.sharedByAll(facts.products)) return this.plain(facts, PRODUCT_SHARED_FILL, DARK_TEXT, '');\n const colors = facts.products.map((product: string): ProductColor => palette.colorOf(product));\n if (colors.length === 1) return this.plain(facts, colors[0].color, colors[0].fontColor, '');\n return this.statement(\n facts,\n `${this.stripes(colors.map((color: ProductColor): string => color.color))}, fontcolor=\"${DARK_TEXT}\"`,\n this.labelText(facts, DARK_TEXT),\n );\n }\n\n /**\n * Runtime mode. No runtime, or one runtime with no specialization: a solid fill. One runtime with a\n * specialization: NESTED. Several runtimes: full-height stripes with the text across them (a\n * specialization on such a box shows in line 3 only).\n */\n private runtime(facts: NodeFacts): string {\n const bases = this.bases(facts.frameworks);\n if (bases.length === 0) return this.plain(facts, NO_RUNTIME_COLOR, DARK_TEXT, '');\n if (bases.length > 1)\n return this.statement(\n facts,\n `${this.stripeAttrs(bases)}, fontcolor=\"${DARK_TEXT}\"`,\n this.labelText(facts, DARK_TEXT),\n );\n const base = FRAMEWORK_STYLES[bases[0]];\n const inner = this.specialization(bases[0], facts.frameworks);\n if (inner === undefined) return this.plain(facts, base.color, base.fontColor, '');\n return this.statement(\n facts,\n `style=\"filled\", fillcolor=\"${base.color}\", fontcolor=\"${inner.fontColor}\", margin=0`,\n this.nestedTable(base.color, inner, this.labelText(facts, inner.fontColor)),\n );\n }\n\n /**\n * An outer cell in the base color whose padding is the visible frame, holding an inner ROUNDED\n * table in the specialization's color that carries the text. The node's own polygon stays its\n * FIRST shape, so the hover glow and the lock outline land on the outer box only.\n */\n private nestedTable(base: string, inner: FrameworkStyle, text: string): string {\n return (\n '<TABLE BORDER=\"0\" CELLBORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"0\">' +\n `<TR><TD BGCOLOR=\"${base}\" CELLPADDING=\"${NEST_PAD}\">` +\n `<TABLE BORDER=\"0\" CELLBORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"${INNER_PAD}\" BGCOLOR=\"${inner.color}\" STYLE=\"rounded\">` +\n `<TR><TD>${text}</TD></TR></TABLE></TD></TR></TABLE>`\n );\n }\n}\n"]}
1
+ {"version":3,"file":"graph-color-modes.js","sourceRoot":"","sources":["../../../../../../packages/tooling/nx-webpieces-rules/src/lib/graph-color-modes.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Graph color modes (#1155, restyled by #1158)\n *\n * The architecture graph answers ONE question at a time instead of asking every box to encode two\n * (fill = framework AND border = role). Each box is emitted once per mode, so the page can switch\n * modes and re-render without regenerating anything. Every mode writes the SAME three lines on a box\n * (level + name, role, every framework tag); only the color changes:\n *\n * - RUNTIME \"where the code can run\". One runtime is a solid fill. One runtime plus a\n * specialization (angular/react inside browser, express inside node) is NESTED: an\n * outer frame in the base color around an inner rounded box in the specialization's\n * color, carrying the text. Several runtimes are full-height vertical stripes in the\n * fixed order browser | node | react-native, with the text written across them. The\n * dependency rule becomes visual: a box may depend on a box carrying every color it has.\n * - ARCHITECTURE \"servers · clients · APIs\". A solid fill by ROLE; framework color is not shown.\n * - IMPACT \"what changed\" — on this branch, or in the last commit (graph-impact.ts).\n * Projects owning a changed file are solid amber (\"touched\"); the rest of nx's affected set is light amber (\"affected\": their ci\n * re-runs); every transitive dependency of the affected set that is not itself\n * affected is light slate with a dashed border (\"build input\": compiled or restored\n * from cache, unchanged); everything else is grey. Which box is which is only known\n * per checkout, so every box carries all four variants and the page picks one from the\n * sidecar (graph-impact.ts). The state is never written on the box: color + legend.\n * The words are the Filter's: changed · dependent · dependency (built, unchanged) ·\n * not in this build.\n * - PRODUCT \"which products it belongs to\" (#1179, graph-products.ts). One product is a solid\n * fill in that product's palette color; two or more (but not all) are the same\n * vertical stripes the multi-runtime box uses, one per product; a box shared by EVERY\n * product is one neutral fill (otherwise a shared foundation would be four-stripe\n * noise); a box in no product is white with a dashed border. The Filter HIDES other\n * products' boxes; this mode keeps every box and makes ownership visible.\n */\n\nimport { KNOWN_FRAMEWORKS, KnownFramework } from '@webpieces/rules-sdk';\nimport { dotValue, htmlLabelText } from './dot-syntax';\nimport { PRODUCT_NONE_BORDER, PRODUCT_NONE_FILL, PRODUCT_SHARED_FILL, ProductColor, ProductPalette } from './graph-products';\nimport type { ProductDependencyEntry } from '../configs/tag-truth-configs';\n\nexport enum GraphMode {\n RUNTIME = 'runtime',\n ARCHITECTURE = 'architecture',\n IMPACT = 'impact',\n PRODUCT = 'product',\n}\n\n/** One selectable mode as the drawer's Color-by pulldown shows it. */\nexport class ModeInfo {\n constructor(\n public readonly mode: GraphMode,\n public readonly name: string,\n public readonly subtitle: string,\n ) {}\n}\n\n/** In key order: `1` selects the first, `2` the second, `3` the third, `4` the fourth. */\nexport const GRAPH_MODES: readonly ModeInfo[] = [\n new ModeInfo(GraphMode.RUNTIME, 'Runtime', 'where the code can run'),\n new ModeInfo(GraphMode.ARCHITECTURE, 'Architecture', 'servers · clients · APIs'),\n new ModeInfo(GraphMode.IMPACT, 'Impact', 'what changed'),\n new ModeInfo(GraphMode.PRODUCT, 'Product', 'which products it belongs to'),\n];\n\n/** Text on a light fill. */\nexport const DARK_TEXT = '#1a1c22';\n/** Text on a dark fill. */\nexport const LIGHT_TEXT = '#ffffff';\n\n/**\n * A framework value's color, the text color that reads on it, and the BASE runtime it is drawn\n * inside (itself, for a base).\n */\nexport class FrameworkStyle {\n constructor(\n public readonly framework: KnownFramework,\n public readonly base: KnownFramework,\n public readonly color: string,\n public readonly fontColor: string,\n public readonly description: string,\n ) {}\n\n isBase(): boolean {\n return this.framework === this.base;\n }\n}\n\n/**\n * Keyed by the shared vocabulary, so a framework added to KNOWN_FRAMEWORKS without a color here is a\n * COMPILE error — not a box silently painted grey and missing from the legend, which is exactly how\n * react-native shipped (#1155). Every base is mid-light, so dark text reads on every stripe.\n */\nexport const FRAMEWORK_STYLES: Record<KnownFramework, FrameworkStyle> = {\n browser: new FrameworkStyle('browser', 'browser', '#7d8cf2', DARK_TEXT, 'browser base runtime'),\n node: new FrameworkStyle('node', 'node', '#6fcf8a', DARK_TEXT, 'node base runtime'),\n 'react-native': new FrameworkStyle(\n 'react-native',\n 'react-native',\n '#34b8a6',\n DARK_TEXT,\n 'its own runtime, not a browser',\n ),\n angular: new FrameworkStyle('angular', 'browser', '#c8243f', LIGHT_TEXT, 'inside browser'),\n react: new FrameworkStyle('react', 'browser', '#7fd8ff', DARK_TEXT, 'inside browser'),\n express: new FrameworkStyle('express', 'node', '#2e7d4f', LIGHT_TEXT, 'inside node'),\n};\n\n/** Stripe order, left to right. Fixed, so the same set always reads the same way. */\nexport const BASE_ORDER: readonly KnownFramework[] = ['browser', 'node', 'react-native'];\n\n/**\n * The Filter popover's Runtime chips, and the order line 3 of a box lists framework tags in: the\n * bases first, then the specializations.\n */\nexport const FRAMEWORK_ORDER: readonly KnownFramework[] = [\n 'browser',\n 'node',\n 'react-native',\n 'angular',\n 'react',\n 'express',\n];\n\n/** A box with no known framework tag. */\nexport const NO_RUNTIME_COLOR = '#e4e6ec';\n\n/** The class Graphviz stamps on a multi-runtime box's `<g>`: its outline is its LAST shape. */\nexport const STRIPED_CLASS = 'wp-striped';\n\n/** Margin of base color around a specialization's inner box. */\nconst NEST_PAD = 5;\n/** Padding between the inner box's edge and its text. */\nconst INNER_PAD = 6;\n\n/** A role's solid fill and the text color that stays readable on it. */\nexport class RoleStyle {\n constructor(\n public readonly role: string,\n public readonly fill: string,\n public readonly fontColor: string,\n public readonly description: string,\n ) {}\n}\n\n/**\n * Every role role-resolver knows, in legend order (runnable things first) — also the Filter popover's\n * Role chips. `bundle` is indigo so no box color equals the page's violet accent.\n */\nexport const ROLE_STYLES: readonly RoleStyle[] = [\n new RoleStyle('server', '#4caf50', LIGHT_TEXT, 'runnable server'),\n new RoleStyle('client', '#e5533d', LIGHT_TEXT, 'browser or mobile client app'),\n new RoleStyle('app', '#1e88e5', LIGHT_TEXT, 'runnable non-HTTP app'),\n new RoleStyle('bundle', '#4b44c8', LIGHT_TEXT, 'bundles several apps'),\n new RoleStyle('api-lib', '#f08a24', DARK_TEXT, 'contract + DTOs'),\n new RoleStyle('api-client', '#1a9aa6', LIGHT_TEXT, 'contract + SDK implementation'),\n new RoleStyle('designed-lib', '#7d8597', LIGHT_TEXT, 'library with a generated design'),\n new RoleStyle('lib', '#d7dae2', DARK_TEXT, 'plain library'),\n];\n\n/** The four impact shades (graph-impact.ts decides which box gets which). */\nexport const IMPACT_TOUCHED = '#f5a524';\nexport const IMPACT_AFFECTED = '#fde3b0';\nexport const IMPACT_BUILD_INPUT = '#e3e9f2';\nexport const IMPACT_BUILD_INPUT_BORDER = '#7c8aa3';\nexport const IMPACT_UNTOUCHED = '#eef0f4';\nconst IMPACT_UNTOUCHED_TEXT = '#6b7180';\n\n/** What a box's per-mode rendering — and the page's Filter — is computed from. */\nexport class NodeFacts {\n constructor(\n public readonly nodeId: string,\n public readonly shortName: string,\n public readonly level: number,\n public readonly role: string,\n public readonly frameworks: string[],\n /** The products the project belongs to (dependencies.json `products`), sorted; empty for none. */\n public readonly products: string[],\n public readonly summary: string = '',\n ) {}\n}\n\n/** One box's DOT statement for every mode (and for each impact state). */\nexport class NodeModeDots {\n constructor(\n public readonly runtime: string,\n public readonly architecture: string,\n public readonly touched: string,\n public readonly affected: string,\n public readonly buildInput: string,\n public readonly untouched: string,\n public readonly product: string,\n ) {}\n}\n\n/** How many drawn boxes one product holds, and how many of them no other product does. */\nexport class ProductCount {\n constructor(\n public readonly product: string,\n public total: number,\n public only: number,\n ) {}\n}\n\n/** Which colors and roles the drawn projects actually use, so the legend lists exactly those. */\nexport class LegendFacts {\n frameworks: string[] = [];\n roles: string[] = [];\n multiRuntime = false;\n noRuntime = false;\n /** One count per declared product, in palette (sorted-name) order; empty when none is declared. */\n products: ProductCount[] = [];\n /**\n * The ONE palette every box was painted with (#1244), built over the full declared product set.\n * The legend, the Filter's product chips and the crossing edges read their colors from it, never\n * from a palette of their own: collision resolution depends on the set, so a second palette built\n * from a subset could disagree with the boxes.\n */\n palette: ProductPalette = new ProductPalette([]);\n /** Boxes shared by every product (two or more declared). */\n sharedByAll = 0;\n /** Boxes in no product. */\n noProduct = 0;\n /** Some box belongs to two or more products, but not to every one: it is striped. */\n multiProduct = false;\n /** Dependency edges crossing into another product (#1204), drawn dashed in the Product mode. */\n crossProductEdges = 0;\n /**\n * The `product-tags` rule's matrix (#1204), listed in the Product legend; null when the rule is\n * OFF or the page was drawn without it.\n */\n productDependencies: ProductDependencyEntry[] | null = null;\n}\n\nexport class NodeModeStyler {\n styleOf(framework: string): FrameworkStyle | undefined {\n if (!(KNOWN_FRAMEWORKS as readonly string[]).includes(framework)) return undefined;\n return FRAMEWORK_STYLES[framework as KnownFramework];\n }\n\n roleStyle(role: string): RoleStyle {\n const style = ROLE_STYLES.find((candidate: RoleStyle): boolean => candidate.role === role);\n return style ?? (ROLE_STYLES.find((s: RoleStyle): boolean => s.role === 'lib') as RoleStyle);\n }\n\n /** Every role the renderer styles; a spec asserts this covers role-resolver's KNOWN_ROLES. */\n styledRoles(): string[] {\n return ROLE_STYLES.map((style: RoleStyle): string => style.role);\n }\n\n /** The base runtimes of a framework set, in stripe order (a specialization implies its base). */\n bases(frameworks: string[]): KnownFramework[] {\n const present = new Set<KnownFramework>();\n for (const framework of frameworks) {\n const style = this.styleOf(framework);\n if (style !== undefined) present.add(style.base);\n }\n return BASE_ORDER.filter((base: KnownFramework): boolean => present.has(base));\n }\n\n /** The specialization drawn inside `base`, if the set carries one. */\n specialization(base: KnownFramework, frameworks: string[]): FrameworkStyle | undefined {\n for (const framework of KNOWN_FRAMEWORKS) {\n const style = FRAMEWORK_STYLES[framework];\n if (style.isBase() || style.base !== base) continue;\n if (frameworks.includes(framework)) return style;\n }\n return undefined;\n }\n\n dots(facts: NodeFacts, palette: ProductPalette): NodeModeDots {\n return new NodeModeDots(\n this.runtime(facts),\n this.plain(facts, this.roleStyle(facts.role).fill, this.roleStyle(facts.role).fontColor, ''),\n this.plain(facts, IMPACT_TOUCHED, DARK_TEXT, ''),\n this.plain(facts, IMPACT_AFFECTED, DARK_TEXT, `, color=\"${IMPACT_TOUCHED}\", penwidth=2`),\n this.plain(\n facts,\n IMPACT_BUILD_INPUT,\n DARK_TEXT,\n `, color=\"${IMPACT_BUILD_INPUT_BORDER}\", penwidth=1.5`,\n 'filled,dashed',\n ),\n this.plain(facts, IMPACT_UNTOUCHED, IMPACT_UNTOUCHED_TEXT, ', color=\"#b4b9c4\"'),\n this.product(facts, palette),\n );\n }\n\n /** Fold one drawn box into the legend facts. */\n record(legend: LegendFacts, facts: NodeFacts, palette: ProductPalette): void {\n this.recordProducts(legend, facts, palette);\n for (const framework of facts.frameworks) {\n if (this.styleOf(framework) !== undefined && !legend.frameworks.includes(framework))\n legend.frameworks.push(framework);\n }\n const role = this.roleStyle(facts.role).role;\n if (!legend.roles.includes(role)) legend.roles.push(role);\n const bases = this.bases(facts.frameworks);\n if (bases.length > 1) legend.multiRuntime = true;\n if (bases.length === 0) legend.noRuntime = true;\n }\n\n /** The Product section's counts: per product (total, and only-this-product), shared-by-all, none. */\n private recordProducts(legend: LegendFacts, facts: NodeFacts, palette: ProductPalette): void {\n legend.palette = palette;\n if (legend.products.length === 0 && palette.colors.length > 0) {\n legend.products = palette.names().map((product: string): ProductCount => new ProductCount(product, 0, 0));\n }\n if (facts.products.length === 0) legend.noProduct++;\n if (palette.sharedByAll(facts.products)) legend.sharedByAll++;\n else if (facts.products.length > 1) legend.multiProduct = true;\n for (const count of legend.products) {\n if (!facts.products.includes(count.product)) continue;\n count.total++;\n if (facts.products.length === 1) count.only++;\n }\n }\n\n /**\n * Line 3 of every box: every framework tag, bases before specializations, any tag outside the\n * shared vocabulary last (it still runs somewhere somebody declared).\n */\n frameworkLine(frameworks: string[]): string {\n if (frameworks.length === 0) return 'no framework tag';\n const known = FRAMEWORK_ORDER.filter((framework: KnownFramework): boolean =>\n frameworks.includes(framework),\n );\n const unknown = frameworks.filter((framework: string): boolean => this.styleOf(framework) === undefined);\n return [...known, ...unknown].join(' · ');\n }\n\n /**\n * The three lines, identical in every mode: `L3 name` (level dimmed, name bold), the role, and\n * the framework tags. The level is dimmed by giving its text color an alpha channel, which\n * Graphviz writes as `fill-opacity`, so it dims on any fill.\n */\n labelText(facts: NodeFacts, fontColor: string): string {\n return (\n `<FONT COLOR=\"${fontColor}99\">L${facts.level}</FONT>&#160;&#160;<B>${htmlLabelText(facts.shortName)}</B>` +\n `<BR/>${htmlLabelText(facts.role)}<BR/>${htmlLabelText(this.frameworkLine(facts.frameworks))}` +\n (facts.summary === '' ? '' : `<BR/>${htmlLabelText(facts.summary)}`)\n );\n }\n\n /** `filled` for one runtime; equal `striped` weights for several (the last takes the remainder). */\n stripeAttrs(bases: KnownFramework[]): string {\n return this.stripes(bases.map((base: KnownFramework): string => FRAMEWORK_STYLES[base].color));\n }\n\n /**\n * One equal vertical stripe per color — the renderer the multi-runtime box and the multi-product\n * box share. A single color is a plain fill.\n */\n stripes(colors: string[]): string {\n if (colors.length === 1) return `style=\"filled\", fillcolor=\"${colors[0]}\"`;\n const share = (1 / colors.length).toFixed(3);\n const weighted = colors.map((color: string, index: number): string =>\n index === colors.length - 1 ? color : `${color};${share}`,\n );\n return `style=\"striped\", fillcolor=\"${weighted.join(':')}\", class=\"${STRIPED_CLASS}\"`;\n }\n\n private statement(facts: NodeFacts, attrs: string, label: string): string {\n return ` \"${dotValue(facts.nodeId)}\" [${attrs}, label=<${label}>];\\n`;\n }\n\n /** A solid fill, the three lines on it. `extra` carries border attributes. */\n private plain(facts: NodeFacts, fill: string, fontColor: string, extra: string, style = 'filled'): string {\n return this.statement(\n facts,\n `style=\"${style}\", fillcolor=\"${fill}\", fontcolor=\"${fontColor}\"${extra}`,\n this.labelText(facts, fontColor),\n );\n }\n\n /**\n * Product mode (#1179): one product solid in its color; several (not all) striped, one stripe per\n * product; every product the neutral shared fill; no product a white box with a dashed border.\n */\n private product(facts: NodeFacts, palette: ProductPalette): string {\n if (facts.products.length === 0)\n return this.plain(facts, PRODUCT_NONE_FILL, DARK_TEXT, `, color=\"${PRODUCT_NONE_BORDER}\", penwidth=1.5`, 'filled,dashed');\n if (palette.sharedByAll(facts.products)) return this.plain(facts, PRODUCT_SHARED_FILL, DARK_TEXT, '');\n const colors = facts.products.map((product: string): ProductColor => palette.colorOf(product));\n if (colors.length === 1) return this.plain(facts, colors[0].color, colors[0].fontColor, '');\n return this.statement(\n facts,\n `${this.stripes(colors.map((color: ProductColor): string => color.color))}, fontcolor=\"${DARK_TEXT}\"`,\n this.labelText(facts, DARK_TEXT),\n );\n }\n\n /**\n * Runtime mode. No runtime, or one runtime with no specialization: a solid fill. One runtime with a\n * specialization: NESTED. Several runtimes: full-height stripes with the text across them (a\n * specialization on such a box shows in line 3 only).\n */\n private runtime(facts: NodeFacts): string {\n const bases = this.bases(facts.frameworks);\n if (bases.length === 0) return this.plain(facts, NO_RUNTIME_COLOR, DARK_TEXT, '');\n if (bases.length > 1)\n return this.statement(\n facts,\n `${this.stripeAttrs(bases)}, fontcolor=\"${DARK_TEXT}\"`,\n this.labelText(facts, DARK_TEXT),\n );\n const base = FRAMEWORK_STYLES[bases[0]];\n const inner = this.specialization(bases[0], facts.frameworks);\n if (inner === undefined) return this.plain(facts, base.color, base.fontColor, '');\n return this.statement(\n facts,\n `style=\"filled\", fillcolor=\"${base.color}\", fontcolor=\"${inner.fontColor}\", margin=0`,\n this.nestedTable(base.color, inner, this.labelText(facts, inner.fontColor)),\n );\n }\n\n /**\n * An outer cell in the base color whose padding is the visible frame, holding an inner ROUNDED\n * table in the specialization's color that carries the text. The node's own polygon stays its\n * FIRST shape, so the hover glow and the lock outline land on the outer box only.\n */\n private nestedTable(base: string, inner: FrameworkStyle, text: string): string {\n return (\n '<TABLE BORDER=\"0\" CELLBORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"0\">' +\n `<TR><TD BGCOLOR=\"${base}\" CELLPADDING=\"${NEST_PAD}\">` +\n `<TABLE BORDER=\"0\" CELLBORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"${INNER_PAD}\" BGCOLOR=\"${inner.color}\" STYLE=\"rounded\">` +\n `<TR><TD>${text}</TD></TR></TABLE></TD></TR></TABLE>`\n );\n }\n}\n"]}
@@ -84,7 +84,7 @@ class GraphLegend {
84
84
  productRows(facts) {
85
85
  if (facts.products.length === 0)
86
86
  return this.row('no-products', this.solid(graph_products_1.PRODUCT_NONE_FILL, graph_products_1.PRODUCT_NONE_BORDER, '3 2'), 'no products declared', 'tag each project product:<name> to see each product');
87
- const palette = new graph_products_1.ProductPalette(facts.products.map((count) => count.product));
87
+ const palette = facts.palette;
88
88
  let rows = '';
89
89
  for (const count of facts.products) {
90
90
  const color = palette.colorOf(count.product);
@@ -1 +1 @@
1
- {"version":3,"file":"graph-legend.js","sourceRoot":"","sources":["../../../../../../packages/tooling/nx-webpieces-rules/src/lib/graph-legend.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The architecture graph's legend, generated per color mode FROM THE PROJECTS ACTUALLY DRAWN.\n *\n * The hand-written legend this replaces listed five frameworks when six existed and never mentioned\n * the `app` and `bundle` borders the renderer drew (#1155). Generating the rows from the same tables\n * the renderer colors with (graph-color-modes.ts) means a color in use always has a row, and a color\n * nothing uses never does.\n *\n * Swatches are inline SVG drawn with presentation attributes, never `style=`, so the page carries\n * no inline CSS.\n */\n\nimport { KNOWN_FRAMEWORKS, KnownFramework } from '@webpieces/rules-sdk';\nimport {\n BASE_ORDER,\n FRAMEWORK_STYLES,\n FrameworkStyle,\n GraphMode,\n IMPACT_AFFECTED,\n IMPACT_BUILD_INPUT,\n IMPACT_BUILD_INPUT_BORDER,\n IMPACT_TOUCHED,\n IMPACT_UNTOUCHED,\n LegendFacts,\n NO_RUNTIME_COLOR,\n ProductCount,\n ROLE_STYLES,\n RoleStyle,\n} from './graph-color-modes';\nimport {\n PRODUCT_NONE_BORDER,\n PRODUCT_NONE_FILL,\n PRODUCT_SHARED_FILL,\n ProductColor,\n ProductPalette,\n} from './graph-products';\nimport type { ProductDependencyEntry } from '../configs/tag-truth-configs';\n\nconst SWATCH_W = 26;\nconst SWATCH_H = 16;\nconst FRAME = '#3a3c46';\n\nexport class GraphLegend {\n /** One section per mode; the page shows the section of the current mode and hides the rest. */\n sections(facts: LegendFacts): string {\n return (\n this.section(GraphMode.RUNTIME, this.runtimeRows(facts), false) +\n this.section(GraphMode.ARCHITECTURE, this.architectureRows(facts), true) +\n this.section(GraphMode.IMPACT, this.impactRows(), true) +\n this.section(GraphMode.PRODUCT, this.productRows(facts), true)\n );\n }\n\n /** The edge key: why a line exists. Static — every graph can carry every edge kind. */\n edgeKey(): string {\n return (\n '<div class=\"wp-legend-list\">' +\n this.edgeRow('#e9eaf0', '', 'uses', 'calls the API, or a plain library import') +\n this.edgeRow('#e9eaf0', '4 3', 'implements', 'serves the API (labeled with its contracts)') +\n this.edgeRow('#7aa2ff', '4 3', 'uses + implements', 'implements some contracts, uses others') +\n '</div>'\n );\n }\n\n private section(mode: GraphMode, rows: string, hidden: boolean): string {\n const hide = hidden ? ' hidden' : '';\n return `<div class=\"wp-legend-list\" data-wp-legend-mode=\"${mode}\"${hide}>${rows}</div>`;\n }\n\n /** Base runtimes first (stripe order), then specializations, in the shared vocabulary's order. */\n runtimeRows(facts: LegendFacts): string {\n const present = (framework: KnownFramework): boolean => facts.frameworks.includes(framework);\n const ordered: FrameworkStyle[] = [\n ...BASE_ORDER.map((base: KnownFramework): FrameworkStyle => FRAMEWORK_STYLES[base]),\n ...KNOWN_FRAMEWORKS.map((f: KnownFramework): FrameworkStyle => FRAMEWORK_STYLES[f]).filter(\n (style: FrameworkStyle): boolean => !style.isBase(),\n ),\n ];\n let rows = '';\n for (const style of ordered) {\n if (!present(style.framework)) continue;\n rows += this.row(style.framework, this.envSwatch(style), style.framework, style.description);\n }\n if (facts.multiRuntime)\n rows += this.row('multi', this.stripesSwatch(), 'several runtimes', 'one equal stripe per runtime');\n if (facts.noRuntime)\n rows += this.row('none', this.solid(NO_RUNTIME_COLOR, '', ''), 'no framework tag', 'runs nowhere declared');\n return rows;\n }\n\n architectureRows(facts: LegendFacts): string {\n let rows = '';\n for (const style of ROLE_STYLES) {\n if (!facts.roles.includes(style.role)) continue;\n rows += this.row(style.role, this.roleSwatch(style), style.role, style.description);\n }\n return rows;\n }\n\n /**\n * Which box is which is only known from the branch's sidecar, so all four rows always show. The\n * words are the Filter's (#1179): changed · dependent · dependency · not in this build.\n */\n impactRows(): string {\n return (\n this.row('touched', this.solid(IMPACT_TOUCHED, '', ''), 'changed', 'owns a changed file') +\n this.row(\n 'affected',\n this.solid(IMPACT_AFFECTED, IMPACT_TOUCHED, ''),\n 'dependent',\n 'uses a changed project: its tests and build re-run',\n ) +\n this.row(\n 'build-input',\n this.solid(IMPACT_BUILD_INPUT, IMPACT_BUILD_INPUT_BORDER, '3 2'),\n 'dependency (built, unchanged)',\n 'compiled or restored from cache for this build',\n ) +\n this.row('untouched', this.solid(IMPACT_UNTOUCHED, '', ''), 'not in this build', 'nothing here changed or depends on a change') +\n '<p class=\"wp-impact-note\" data-wp-impact-note></p>'\n );\n }\n\n /**\n * Product mode (#1179): one row per product with its counts, then the shared, several-products and\n * no-product rows that some drawn box actually uses.\n */\n productRows(facts: LegendFacts): string {\n if (facts.products.length === 0)\n return this.row(\n 'no-products',\n this.solid(PRODUCT_NONE_FILL, PRODUCT_NONE_BORDER, '3 2'),\n 'no products declared',\n 'tag each project product:<name> to see each product',\n );\n const palette = new ProductPalette(facts.products.map((count: ProductCount): string => count.product));\n let rows = '';\n for (const count of facts.products) {\n const color = palette.colorOf(count.product);\n const detail = `${count.only} only ${count.product}`;\n rows += this.row(`product:${count.product}`, this.solid(color.color, '', ''), `${count.product} · ${count.total}`, detail);\n }\n if (facts.sharedByAll > 0)\n rows += this.row(\n 'shared',\n this.solid(PRODUCT_SHARED_FILL, '', ''),\n `shared by every product · ${facts.sharedByAll}`,\n 'a change here is a change to every product',\n );\n if (facts.multiProduct)\n rows += this.row('several', this.productStripes(palette), 'several products', 'one stripe per product');\n if (facts.noProduct > 0)\n rows += this.row(\n 'no-product',\n this.solid(PRODUCT_NONE_FILL, PRODUCT_NONE_BORDER, '3 2'),\n `no product · ${facts.noProduct}`,\n 'needs a product:<name> tag',\n );\n return rows + this.boundaryRows(facts, palette);\n }\n\n /**\n * #1204: the dashed cross-product edge, and the product dependency matrix that allows each such\n * edge — `example → openapi, platform` — when the `product-tags` rule supplied one.\n */\n boundaryRows(facts: LegendFacts, palette: ProductPalette): string {\n let rows = '';\n if (facts.crossProductEdges > 0)\n rows += this.row(\n 'cross-product',\n this.line(PRODUCT_NONE_BORDER, '4 3'),\n `crosses into another product · ${facts.crossProductEdges}`,\n \"dashed, in the color of the product it depends on\",\n );\n const matrix = facts.productDependencies;\n if (matrix === null) return rows;\n const stated = matrix.filter((entry: ProductDependencyEntry): boolean => entry.allowedToDependOn.length > 0);\n if (stated.length === 0)\n return (\n rows +\n this.row(\n 'allowed-none',\n this.line(PRODUCT_NONE_BORDER, ''),\n 'no product may depend on another',\n 'product-tags.productDependencies allows no crossing',\n )\n );\n for (const entry of [...stated].sort((a: ProductDependencyEntry, b: ProductDependencyEntry): number => a.name.localeCompare(b.name)))\n rows += this.row(\n `allowed:${entry.name}`,\n this.line(palette.colorOf(entry.name).color, ''),\n `${entry.name} → ${[...entry.allowedToDependOn].sort().join(', ')}`,\n 'allowed by product-tags.productDependencies',\n );\n return rows;\n }\n\n private row(key: string, swatch: string, title: string, detail: string): string {\n return (\n `<div class=\"wp-legend-row\" data-wp-legend=\"${key}\">${swatch}` +\n `<span>${title}<small>${detail}</small></span></div>`\n );\n }\n\n private open(): string {\n return `<svg width=\"${SWATCH_W}\" height=\"${SWATCH_H}\" viewBox=\"0 0 ${SWATCH_W} ${SWATCH_H}\" aria-hidden=\"true\">`;\n }\n\n private frame(): string {\n return `<rect x=\"0.5\" y=\"0.5\" width=\"${SWATCH_W - 1}\" height=\"${SWATCH_H - 1}\" fill=\"none\" stroke=\"${FRAME}\"/></svg>`;\n }\n\n /** A base runtime is solid; a specialization is its inset on the base color. */\n private envSwatch(style: FrameworkStyle): string {\n const base = `<rect width=\"${SWATCH_W}\" height=\"${SWATCH_H}\" fill=\"${FRAMEWORK_STYLES[style.base].color}\"/>`;\n if (style.isBase()) return this.open() + base + this.frame();\n const inset = `<rect x=\"4\" y=\"4\" width=\"${SWATCH_W - 8}\" height=\"${SWATCH_H - 8}\" rx=\"2\" fill=\"${style.color}\"/>`;\n return this.open() + base + inset + this.frame();\n }\n\n private stripesSwatch(): string {\n const width = SWATCH_W / BASE_ORDER.length;\n const stripes = BASE_ORDER.map(\n (base: KnownFramework, index: number): string =>\n `<rect x=\"${(index * width).toFixed(2)}\" width=\"${width.toFixed(2)}\" height=\"${SWATCH_H}\" fill=\"${FRAMEWORK_STYLES[base].color}\"/>`,\n ).join('');\n return this.open() + stripes + this.frame();\n }\n\n /** The first three product colors as stripes: the \"several products\" swatch. */\n private productStripes(palette: ProductPalette): string {\n const colors = palette.colors.slice(0, 3);\n const width = SWATCH_W / colors.length;\n const stripes = colors\n .map(\n (color: ProductColor, index: number): string =>\n `<rect x=\"${(index * width).toFixed(2)}\" width=\"${width.toFixed(2)}\" height=\"${SWATCH_H}\" fill=\"${color.color}\"/>`,\n )\n .join('');\n return this.open() + stripes + this.frame();\n }\n\n private roleSwatch(style: RoleStyle): string {\n return this.solid(style.fill, '', '');\n }\n\n /** A filled swatch, optionally with an inner ring (dashed when `dash` is set). */\n private solid(fill: string, outline: string, dash: string): string {\n const dashed = dash === '' ? '' : ` stroke-dasharray=\"${dash}\"`;\n const ring =\n outline === ''\n ? ''\n : `<rect x=\"2\" y=\"2\" width=\"${SWATCH_W - 4}\" height=\"${SWATCH_H - 4}\" fill=\"none\" stroke=\"${outline}\" stroke-width=\"2\"${dashed}/>`;\n return this.open() + `<rect width=\"${SWATCH_W}\" height=\"${SWATCH_H}\" fill=\"${fill}\"/>` + ring + this.frame();\n }\n\n private edgeRow(color: string, dash: string, title: string, detail: string): string {\n return this.row(title, this.line(color, dash), title, detail);\n }\n\n /** An edge swatch: a short line, dashed when `dash` is set. */\n private line(color: string, dash: string): string {\n const dashed = dash === '' ? '' : ` stroke-dasharray=\"${dash}\"`;\n return `<svg width=\"28\" height=\"10\" aria-hidden=\"true\"><line x1=\"0\" y1=\"5\" x2=\"28\" y2=\"5\" stroke=\"${color}\" stroke-width=\"1.6\"${dashed}/></svg>`;\n }\n}\n"]}
1
+ {"version":3,"file":"graph-legend.js","sourceRoot":"","sources":["../../../../../../packages/tooling/nx-webpieces-rules/src/lib/graph-legend.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The architecture graph's legend, generated per color mode FROM THE PROJECTS ACTUALLY DRAWN.\n *\n * The hand-written legend this replaces listed five frameworks when six existed and never mentioned\n * the `app` and `bundle` borders the renderer drew (#1155). Generating the rows from the same tables\n * the renderer colors with (graph-color-modes.ts) means a color in use always has a row, and a color\n * nothing uses never does.\n *\n * Swatches are inline SVG drawn with presentation attributes, never `style=`, so the page carries\n * no inline CSS.\n */\n\nimport { KNOWN_FRAMEWORKS, KnownFramework } from '@webpieces/rules-sdk';\nimport {\n BASE_ORDER,\n FRAMEWORK_STYLES,\n FrameworkStyle,\n GraphMode,\n IMPACT_AFFECTED,\n IMPACT_BUILD_INPUT,\n IMPACT_BUILD_INPUT_BORDER,\n IMPACT_TOUCHED,\n IMPACT_UNTOUCHED,\n LegendFacts,\n NO_RUNTIME_COLOR,\n ROLE_STYLES,\n RoleStyle,\n} from './graph-color-modes';\nimport {\n PRODUCT_NONE_BORDER,\n PRODUCT_NONE_FILL,\n PRODUCT_SHARED_FILL,\n ProductColor,\n ProductPalette,\n} from './graph-products';\nimport type { ProductDependencyEntry } from '../configs/tag-truth-configs';\n\nconst SWATCH_W = 26;\nconst SWATCH_H = 16;\nconst FRAME = '#3a3c46';\n\nexport class GraphLegend {\n /** One section per mode; the page shows the section of the current mode and hides the rest. */\n sections(facts: LegendFacts): string {\n return (\n this.section(GraphMode.RUNTIME, this.runtimeRows(facts), false) +\n this.section(GraphMode.ARCHITECTURE, this.architectureRows(facts), true) +\n this.section(GraphMode.IMPACT, this.impactRows(), true) +\n this.section(GraphMode.PRODUCT, this.productRows(facts), true)\n );\n }\n\n /** The edge key: why a line exists. Static — every graph can carry every edge kind. */\n edgeKey(): string {\n return (\n '<div class=\"wp-legend-list\">' +\n this.edgeRow('#e9eaf0', '', 'uses', 'calls the API, or a plain library import') +\n this.edgeRow('#e9eaf0', '4 3', 'implements', 'serves the API (labeled with its contracts)') +\n this.edgeRow('#7aa2ff', '4 3', 'uses + implements', 'implements some contracts, uses others') +\n '</div>'\n );\n }\n\n private section(mode: GraphMode, rows: string, hidden: boolean): string {\n const hide = hidden ? ' hidden' : '';\n return `<div class=\"wp-legend-list\" data-wp-legend-mode=\"${mode}\"${hide}>${rows}</div>`;\n }\n\n /** Base runtimes first (stripe order), then specializations, in the shared vocabulary's order. */\n runtimeRows(facts: LegendFacts): string {\n const present = (framework: KnownFramework): boolean => facts.frameworks.includes(framework);\n const ordered: FrameworkStyle[] = [\n ...BASE_ORDER.map((base: KnownFramework): FrameworkStyle => FRAMEWORK_STYLES[base]),\n ...KNOWN_FRAMEWORKS.map((f: KnownFramework): FrameworkStyle => FRAMEWORK_STYLES[f]).filter(\n (style: FrameworkStyle): boolean => !style.isBase(),\n ),\n ];\n let rows = '';\n for (const style of ordered) {\n if (!present(style.framework)) continue;\n rows += this.row(style.framework, this.envSwatch(style), style.framework, style.description);\n }\n if (facts.multiRuntime)\n rows += this.row('multi', this.stripesSwatch(), 'several runtimes', 'one equal stripe per runtime');\n if (facts.noRuntime)\n rows += this.row('none', this.solid(NO_RUNTIME_COLOR, '', ''), 'no framework tag', 'runs nowhere declared');\n return rows;\n }\n\n architectureRows(facts: LegendFacts): string {\n let rows = '';\n for (const style of ROLE_STYLES) {\n if (!facts.roles.includes(style.role)) continue;\n rows += this.row(style.role, this.roleSwatch(style), style.role, style.description);\n }\n return rows;\n }\n\n /**\n * Which box is which is only known from the branch's sidecar, so all four rows always show. The\n * words are the Filter's (#1179): changed · dependent · dependency · not in this build.\n */\n impactRows(): string {\n return (\n this.row('touched', this.solid(IMPACT_TOUCHED, '', ''), 'changed', 'owns a changed file') +\n this.row(\n 'affected',\n this.solid(IMPACT_AFFECTED, IMPACT_TOUCHED, ''),\n 'dependent',\n 'uses a changed project: its tests and build re-run',\n ) +\n this.row(\n 'build-input',\n this.solid(IMPACT_BUILD_INPUT, IMPACT_BUILD_INPUT_BORDER, '3 2'),\n 'dependency (built, unchanged)',\n 'compiled or restored from cache for this build',\n ) +\n this.row('untouched', this.solid(IMPACT_UNTOUCHED, '', ''), 'not in this build', 'nothing here changed or depends on a change') +\n '<p class=\"wp-impact-note\" data-wp-impact-note></p>'\n );\n }\n\n /**\n * Product mode (#1179): one row per product with its counts, then the shared, several-products and\n * no-product rows that some drawn box actually uses.\n */\n productRows(facts: LegendFacts): string {\n if (facts.products.length === 0)\n return this.row(\n 'no-products',\n this.solid(PRODUCT_NONE_FILL, PRODUCT_NONE_BORDER, '3 2'),\n 'no products declared',\n 'tag each project product:<name> to see each product',\n );\n const palette = facts.palette;\n let rows = '';\n for (const count of facts.products) {\n const color = palette.colorOf(count.product);\n const detail = `${count.only} only ${count.product}`;\n rows += this.row(`product:${count.product}`, this.solid(color.color, '', ''), `${count.product} · ${count.total}`, detail);\n }\n if (facts.sharedByAll > 0)\n rows += this.row(\n 'shared',\n this.solid(PRODUCT_SHARED_FILL, '', ''),\n `shared by every product · ${facts.sharedByAll}`,\n 'a change here is a change to every product',\n );\n if (facts.multiProduct)\n rows += this.row('several', this.productStripes(palette), 'several products', 'one stripe per product');\n if (facts.noProduct > 0)\n rows += this.row(\n 'no-product',\n this.solid(PRODUCT_NONE_FILL, PRODUCT_NONE_BORDER, '3 2'),\n `no product · ${facts.noProduct}`,\n 'needs a product:<name> tag',\n );\n return rows + this.boundaryRows(facts, palette);\n }\n\n /**\n * #1204: the dashed cross-product edge, and the product dependency matrix that allows each such\n * edge — `example → openapi, platform` — when the `product-tags` rule supplied one.\n */\n boundaryRows(facts: LegendFacts, palette: ProductPalette): string {\n let rows = '';\n if (facts.crossProductEdges > 0)\n rows += this.row(\n 'cross-product',\n this.line(PRODUCT_NONE_BORDER, '4 3'),\n `crosses into another product · ${facts.crossProductEdges}`,\n \"dashed, in the color of the product it depends on\",\n );\n const matrix = facts.productDependencies;\n if (matrix === null) return rows;\n const stated = matrix.filter((entry: ProductDependencyEntry): boolean => entry.allowedToDependOn.length > 0);\n if (stated.length === 0)\n return (\n rows +\n this.row(\n 'allowed-none',\n this.line(PRODUCT_NONE_BORDER, ''),\n 'no product may depend on another',\n 'product-tags.productDependencies allows no crossing',\n )\n );\n for (const entry of [...stated].sort((a: ProductDependencyEntry, b: ProductDependencyEntry): number => a.name.localeCompare(b.name)))\n rows += this.row(\n `allowed:${entry.name}`,\n this.line(palette.colorOf(entry.name).color, ''),\n `${entry.name} → ${[...entry.allowedToDependOn].sort().join(', ')}`,\n 'allowed by product-tags.productDependencies',\n );\n return rows;\n }\n\n private row(key: string, swatch: string, title: string, detail: string): string {\n return (\n `<div class=\"wp-legend-row\" data-wp-legend=\"${key}\">${swatch}` +\n `<span>${title}<small>${detail}</small></span></div>`\n );\n }\n\n private open(): string {\n return `<svg width=\"${SWATCH_W}\" height=\"${SWATCH_H}\" viewBox=\"0 0 ${SWATCH_W} ${SWATCH_H}\" aria-hidden=\"true\">`;\n }\n\n private frame(): string {\n return `<rect x=\"0.5\" y=\"0.5\" width=\"${SWATCH_W - 1}\" height=\"${SWATCH_H - 1}\" fill=\"none\" stroke=\"${FRAME}\"/></svg>`;\n }\n\n /** A base runtime is solid; a specialization is its inset on the base color. */\n private envSwatch(style: FrameworkStyle): string {\n const base = `<rect width=\"${SWATCH_W}\" height=\"${SWATCH_H}\" fill=\"${FRAMEWORK_STYLES[style.base].color}\"/>`;\n if (style.isBase()) return this.open() + base + this.frame();\n const inset = `<rect x=\"4\" y=\"4\" width=\"${SWATCH_W - 8}\" height=\"${SWATCH_H - 8}\" rx=\"2\" fill=\"${style.color}\"/>`;\n return this.open() + base + inset + this.frame();\n }\n\n private stripesSwatch(): string {\n const width = SWATCH_W / BASE_ORDER.length;\n const stripes = BASE_ORDER.map(\n (base: KnownFramework, index: number): string =>\n `<rect x=\"${(index * width).toFixed(2)}\" width=\"${width.toFixed(2)}\" height=\"${SWATCH_H}\" fill=\"${FRAMEWORK_STYLES[base].color}\"/>`,\n ).join('');\n return this.open() + stripes + this.frame();\n }\n\n /** The first three product colors as stripes: the \"several products\" swatch. */\n private productStripes(palette: ProductPalette): string {\n const colors = palette.colors.slice(0, 3);\n const width = SWATCH_W / colors.length;\n const stripes = colors\n .map(\n (color: ProductColor, index: number): string =>\n `<rect x=\"${(index * width).toFixed(2)}\" width=\"${width.toFixed(2)}\" height=\"${SWATCH_H}\" fill=\"${color.color}\"/>`,\n )\n .join('');\n return this.open() + stripes + this.frame();\n }\n\n private roleSwatch(style: RoleStyle): string {\n return this.solid(style.fill, '', '');\n }\n\n /** A filled swatch, optionally with an inner ring (dashed when `dash` is set). */\n private solid(fill: string, outline: string, dash: string): string {\n const dashed = dash === '' ? '' : ` stroke-dasharray=\"${dash}\"`;\n const ring =\n outline === ''\n ? ''\n : `<rect x=\"2\" y=\"2\" width=\"${SWATCH_W - 4}\" height=\"${SWATCH_H - 4}\" fill=\"none\" stroke=\"${outline}\" stroke-width=\"2\"${dashed}/>`;\n return this.open() + `<rect width=\"${SWATCH_W}\" height=\"${SWATCH_H}\" fill=\"${fill}\"/>` + ring + this.frame();\n }\n\n private edgeRow(color: string, dash: string, title: string, detail: string): string {\n return this.row(title, this.line(color, dash), title, detail);\n }\n\n /** An edge swatch: a short line, dashed when `dash` is set. */\n private line(color: string, dash: string): string {\n const dashed = dash === '' ? '' : ` stroke-dasharray=\"${dash}\"`;\n return `<svg width=\"28\" height=\"10\" aria-hidden=\"true\"><line x1=\"0\" y1=\"5\" x2=\"28\" y2=\"5\" stroke=\"${color}\" stroke-width=\"1.6\"${dashed}/></svg>`;\n }\n}\n"]}
@@ -10,6 +10,7 @@
10
10
  * Markup only. Behaviour is graph-visualizer.client.ts; styling is graph-page-styles.ts. No element
11
11
  * carries a `style=` attribute — every look is a class.
12
12
  */
13
+ import { ProductColor } from './graph-products';
13
14
  /**
14
15
  * The Filter popover's "Changes on this branch" choices. The page computes each set from the Impact
15
16
  * sidecar (graph-impact.ts): CHANGED = touched; DEPENDENTS = touched + affected (nx affected: their
@@ -48,15 +49,21 @@ export declare class ShellParts {
48
49
  readonly filterStatus: string;
49
50
  readonly snapshot: string;
50
51
  readonly responsibilities: string;
51
- /** Every declared product, sorted (#1179); empty hides the Filter's Product group. */
52
- readonly products: string[];
52
+ /**
53
+ * One chip per product (#1179), sorted, each colored from the page's ONE palette (#1244);
54
+ * empty hides the Filter's Product group.
55
+ */
56
+ readonly products: ProductColor[];
53
57
  readonly runtime: boolean;
54
58
  readonly frameworks: readonly string[];
55
59
  readonly roles: readonly string[];
56
60
  readonly emptyState: string;
57
61
  constructor(title: string, lockControl: string, legend: string, edgeKey: string, filterStatus: string, snapshot: string, responsibilities: string,
58
- /** Every declared product, sorted (#1179); empty hides the Filter's Product group. */
59
- products: string[], runtime?: boolean, frameworks?: readonly string[], roles?: readonly string[], emptyState?: string);
62
+ /**
63
+ * One chip per product (#1179), sorted, each colored from the page's ONE palette (#1244);
64
+ * empty hides the Filter's Product group.
65
+ */
66
+ products: ProductColor[], runtime?: boolean, frameworks?: readonly string[], roles?: readonly string[], emptyState?: string);
60
67
  }
61
68
  export declare class GraphPageShell {
62
69
  body(parts: ShellParts): string;
@@ -14,7 +14,6 @@
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.GraphPageShell = exports.ShellParts = exports.SCOPE_OPTIONS = exports.ScopeOption = exports.ChangeScope = void 0;
16
16
  const graph_color_modes_1 = require("./graph-color-modes");
17
- const graph_products_1 = require("./graph-products");
18
17
  /**
19
18
  * The Filter popover's "Changes on this branch" choices. The page computes each set from the Impact
20
19
  * sidecar (graph-impact.ts): CHANGED = touched; DEPENDENTS = touched + affected (nx affected: their
@@ -71,7 +70,10 @@ class ShellParts {
71
70
  roles;
72
71
  emptyState;
73
72
  constructor(title, lockControl, legend, edgeKey, filterStatus, snapshot, responsibilities,
74
- /** Every declared product, sorted (#1179); empty hides the Filter's Product group. */
73
+ /**
74
+ * One chip per product (#1179), sorted, each colored from the page's ONE palette (#1244);
75
+ * empty hides the Filter's Product group.
76
+ */
75
77
  products, runtime = false, frameworks = graph_color_modes_1.FRAMEWORK_ORDER, roles = graph_color_modes_1.ROLE_STYLES.map((style) => style.role), emptyState = '') {
76
78
  this.title = title;
77
79
  this.lockControl = lockControl;
@@ -182,8 +184,7 @@ class GraphPageShell {
182
184
  productGroup(products) {
183
185
  if (products.length === 0)
184
186
  return '';
185
- const palette = new graph_products_1.ProductPalette(products);
186
- const chips = palette.colors
187
+ const chips = products
187
188
  .map((color) => `<button type="button" class="wp-chip" data-wp-chip-group="product" data-wp-chip="${color.product}" aria-pressed="false">` +
188
189
  `<svg class="wp-chip-swatch" width="10" height="10" viewBox="0 0 10 10" aria-hidden="true"><circle cx="5" cy="5" r="4.5" fill="${color.color}"/></svg>` +
189
190
  `${color.product}</button>`)