@primer/brand-mcp 0.69.0 → 0.70.0-rc.9ef718be
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/README.md +10 -9
- package/content/page-design.md +76 -0
- package/dist/brand/detect-asset-generator.d.ts +6 -0
- package/dist/brand/detect-asset-generator.js +21 -0
- package/dist/brand/detect-asset-generator.js.map +1 -0
- package/dist/brand/detect-framework.d.ts +3 -4
- package/dist/brand/detect-framework.js +18 -21
- package/dist/brand/detect-framework.js.map +1 -1
- package/dist/brand/docs-source.d.ts +8 -20
- package/dist/brand/docs-source.js +38 -41
- package/dist/brand/docs-source.js.map +1 -1
- package/dist/brand/resolve-assets.d.ts +4 -5
- package/dist/brand/resolve-assets.js +60 -68
- package/dist/brand/resolve-assets.js.map +1 -1
- package/dist/brand/resolve-install.d.ts +2 -4
- package/dist/brand/resolve-install.js +10 -10
- package/dist/brand/resolve-install.js.map +1 -1
- package/dist/catalog/load.js +0 -1
- package/dist/catalog/load.js.map +1 -1
- package/dist/catalog/types.d.ts +24 -14
- package/dist/catalog/types.js +2 -2
- package/dist/catalog/types.js.map +1 -1
- package/dist/catalog.json +105 -2
- package/dist/logger.d.ts +2 -2
- package/dist/review/rules.js +27 -0
- package/dist/review/rules.js.map +1 -1
- package/dist/review/types.d.ts +4 -4
- package/dist/server.js +13 -2
- package/dist/server.js.map +1 -1
- package/dist/tools/primer-brand-asset/primer-brand-asset.js +12 -3
- package/dist/tools/primer-brand-asset/primer-brand-asset.js.map +1 -1
- package/dist/tools/primer-brand-examples/primer-brand-examples.js +23 -4
- package/dist/tools/primer-brand-examples/primer-brand-examples.js.map +1 -1
- package/dist/tools/primer-brand-page-design/index.d.ts +1 -0
- package/dist/tools/primer-brand-page-design/index.js +2 -0
- package/dist/tools/primer-brand-page-design/index.js.map +1 -0
- package/dist/tools/primer-brand-page-design/primer-brand-page-design.d.ts +6 -0
- package/dist/tools/primer-brand-page-design/primer-brand-page-design.js +19 -0
- package/dist/tools/primer-brand-page-design/primer-brand-page-design.js.map +1 -0
- package/dist/tools/primer-brand-review/primer-brand-review.js +23 -19
- package/dist/tools/primer-brand-review/primer-brand-review.js.map +1 -1
- package/dist/tools/primer-brand-setup/primer-brand-setup.js +1 -1
- package/dist/tools/primer-brand-setup/primer-brand-setup.js.map +1 -1
- package/dist/tools/primer-brand-tokens/primer-brand-tokens.js +38 -29
- package/dist/tools/primer-brand-tokens/primer-brand-tokens.js.map +1 -1
- package/dist/tools/register.js +3 -2
- package/dist/tools/register.js.map +1 -1
- package/dist/tools/types.d.ts +11 -12
- package/dist/util/text.d.ts +2 -2
- package/package.json +2 -1
|
@@ -14,6 +14,16 @@ const notFound = {
|
|
|
14
14
|
*/
|
|
15
15
|
export function resolveBrandInstall(fromDir = process.cwd()) {
|
|
16
16
|
let dir = fromDir;
|
|
17
|
+
const readVersion = (packageJsonPath) => {
|
|
18
|
+
try {
|
|
19
|
+
const parsed = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
|
|
20
|
+
return parsed.version ?? null;
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
// Unreadable manifest -> treat the version as unknown rather than failing discovery.
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
};
|
|
17
27
|
for (;;) {
|
|
18
28
|
const packageDir = join(dir, 'node_modules', '@primer', 'react-brand');
|
|
19
29
|
if (existsSync(join(packageDir, 'package.json'))) {
|
|
@@ -50,14 +60,4 @@ export function looksLikeProductProject(fromDir = process.cwd()) {
|
|
|
50
60
|
dir = parent;
|
|
51
61
|
}
|
|
52
62
|
}
|
|
53
|
-
function readVersion(packageJsonPath) {
|
|
54
|
-
try {
|
|
55
|
-
const parsed = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
|
|
56
|
-
return parsed.version ?? null;
|
|
57
|
-
}
|
|
58
|
-
catch {
|
|
59
|
-
// Unreadable manifest -> treat the version as unknown rather than failing discovery.
|
|
60
|
-
return null;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
63
|
//# sourceMappingURL=resolve-install.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve-install.js","sourceRoot":"","sources":["../../src/brand/resolve-install.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAE,YAAY,EAAC,MAAM,SAAS,CAAA;AAChD,OAAO,EAAC,OAAO,EAAE,IAAI,EAAC,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"resolve-install.js","sourceRoot":"","sources":["../../src/brand/resolve-install.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAE,YAAY,EAAC,MAAM,SAAS,CAAA;AAChD,OAAO,EAAC,OAAO,EAAE,IAAI,EAAC,MAAM,WAAW,CAAA;AAevC,MAAM,QAAQ,GAAiB;IAC7B,KAAK,EAAE,KAAK;IACZ,OAAO,EAAE,IAAI;IACb,UAAU,EAAE,IAAI;IAChB,OAAO,EAAE,IAAI;IACb,QAAQ,EAAE,IAAI;CACf,CAAA;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,UAAkB,OAAO,CAAC,GAAG,EAAE;IACjE,IAAI,GAAG,GAAG,OAAO,CAAA;IAEjB,MAAM,WAAW,GAAG,CAAC,eAAuB,EAAiB,EAAE;QAC7D,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC,CAAuB,CAAA;YACtF,OAAO,MAAM,CAAC,OAAO,IAAI,IAAI,CAAA;QAC/B,CAAC;QAAC,MAAM,CAAC;YACP,qFAAqF;YACrF,OAAO,IAAI,CAAA;QACb,CAAC;IACH,CAAC,CAAA;IAED,SAAS,CAAC;QACR,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,cAAc,EAAE,SAAS,EAAE,aAAa,CAAC,CAAA;QACtE,IAAI,UAAU,CAAC,IAAI,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC,EAAE,CAAC;YACjD,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,CAAA;YACxC,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,CAAA;YAC7C,OAAO;gBACL,KAAK,EAAE,IAAI;gBACX,OAAO,EAAE,WAAW,CAAC,IAAI,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;gBACtD,UAAU;gBACV,OAAO,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI;gBAC7C,QAAQ,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI;aACjD,CAAA;QACH,CAAC;QACD,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAA;QAC3B,IAAI,MAAM,KAAK,GAAG;YAAE,OAAO,QAAQ,CAAA;QACnC,GAAG,GAAG,MAAM,CAAA;IACd,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CAAC,UAAkB,OAAO,CAAC,GAAG,EAAE;IACrE,IAAI,mBAAmB,CAAC,OAAO,CAAC,CAAC,KAAK;QAAE,OAAO,KAAK,CAAA;IACpD,IAAI,GAAG,GAAG,OAAO,CAAA;IACjB,SAAS,CAAC;QACR,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,EAAE,SAAS,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC;YAAE,OAAO,IAAI,CAAA;QAC1F,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAA;QAC3B,IAAI,MAAM,KAAK,GAAG;YAAE,OAAO,KAAK,CAAA;QAChC,GAAG,GAAG,MAAM,CAAA;IACd,CAAC;AACH,CAAC"}
|
package/dist/catalog/load.js
CHANGED
|
@@ -2,7 +2,6 @@ import { readFileSync } from 'node:fs';
|
|
|
2
2
|
import { fileURLToPath } from 'node:url';
|
|
3
3
|
import { emptyCatalog } from './types.js';
|
|
4
4
|
export function loadCatalog(logger) {
|
|
5
|
-
// Output next to the compiled output (`dist/catalog.json`) by the build-time generator.
|
|
6
5
|
const path = fileURLToPath(new URL('../catalog.json', import.meta.url));
|
|
7
6
|
try {
|
|
8
7
|
const parsed = JSON.parse(readFileSync(path, 'utf8'));
|
package/dist/catalog/load.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"load.js","sourceRoot":"","sources":["../../src/catalog/load.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAC,MAAM,SAAS,CAAA;AACpC,OAAO,EAAC,aAAa,EAAC,MAAM,UAAU,CAAA;AAGtC,OAAO,EAAe,YAAY,EAAC,MAAM,YAAY,CAAA;AAErD,MAAM,UAAU,WAAW,CAAC,MAAc;IACxC,
|
|
1
|
+
{"version":3,"file":"load.js","sourceRoot":"","sources":["../../src/catalog/load.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAC,MAAM,SAAS,CAAA;AACpC,OAAO,EAAC,aAAa,EAAC,MAAM,UAAU,CAAA;AAGtC,OAAO,EAAe,YAAY,EAAC,MAAM,YAAY,CAAA;AAErD,MAAM,UAAU,WAAW,CAAC,MAAc;IACxC,MAAM,IAAI,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,iBAAiB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;IACvE,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAY,CAAA;QAChE,MAAM,CAAC,KAAK,CACV,mBAAmB,MAAM,CAAC,UAAU,CAAC,MAAM,mDAAmD,MAAM,CAAC,oBAAoB,GAAG,CAC7H,CAAA;QACD,OAAO,MAAM,CAAA;IACf,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,IAAI,CAAC,6BAA6B,IAAI,KAAM,KAAe,CAAC,OAAO,EAAE,CAAC,CAAA;QAC7E,iDAAiD;QACjD,OAAO,YAAY,EAAE,CAAA;IACvB,CAAC;AACH,CAAC"}
|
package/dist/catalog/types.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* All types
|
|
3
|
-
* It is the structured, offline source of truth the tools reason over so they never depend on the network for version-sensitive facts.
|
|
2
|
+
* All types relating to the Catalog
|
|
4
3
|
*/
|
|
5
|
-
export
|
|
4
|
+
export type CatalogProp = {
|
|
6
5
|
name: string;
|
|
7
6
|
type?: string;
|
|
8
7
|
/** Allowed string-literal values, when the prop is an enum. */
|
|
@@ -11,8 +10,8 @@ export interface CatalogProp {
|
|
|
11
10
|
default?: string;
|
|
12
11
|
/** One-line prop description from its JSDoc, when documented in source. */
|
|
13
12
|
description?: string;
|
|
14
|
-
}
|
|
15
|
-
export
|
|
13
|
+
};
|
|
14
|
+
export type CatalogExample = {
|
|
16
15
|
title: string;
|
|
17
16
|
/** Source snippet (JSX), when one could be extracted. */
|
|
18
17
|
code?: string;
|
|
@@ -20,8 +19,8 @@ export interface CatalogExample {
|
|
|
20
19
|
source: 'jsdoc' | 'story' | 'docs';
|
|
21
20
|
/** Storybook story id, when the example comes from a story. */
|
|
22
21
|
storyId?: string;
|
|
23
|
-
}
|
|
24
|
-
export
|
|
22
|
+
};
|
|
23
|
+
export type CatalogComponent = {
|
|
25
24
|
/** Public name, e.g. `Hero`. */
|
|
26
25
|
name: string;
|
|
27
26
|
/** Package the component is imported from. */
|
|
@@ -36,18 +35,28 @@ export interface CatalogComponent {
|
|
|
36
35
|
keywords?: string[];
|
|
37
36
|
/** A usage caveat from the component's JSDoc `@remarks` (e.g. a non-obvious prop interaction). */
|
|
38
37
|
note?: string;
|
|
39
|
-
}
|
|
40
|
-
export
|
|
38
|
+
};
|
|
39
|
+
export type CatalogAsset = {
|
|
41
40
|
name: string;
|
|
42
41
|
module: string;
|
|
43
42
|
kind: 'icon' | 'illustration';
|
|
44
|
-
}
|
|
45
|
-
export
|
|
43
|
+
};
|
|
44
|
+
export type CatalogToken = {
|
|
46
45
|
name: string;
|
|
47
46
|
value: string;
|
|
48
47
|
group: string;
|
|
49
|
-
}
|
|
50
|
-
export
|
|
48
|
+
};
|
|
49
|
+
export type CatalogRecipe = {
|
|
50
|
+
/** The export/file name, e.g. `FlexSuiteAIOverview`. */
|
|
51
|
+
name: string;
|
|
52
|
+
/** A human-readable label for ranking and display, e.g. `Overview / landing page`. */
|
|
53
|
+
title: string;
|
|
54
|
+
/** Page-level keywords used to match a build goal. */
|
|
55
|
+
keywords: string[];
|
|
56
|
+
/** The recipe's full source `.tsx`. */
|
|
57
|
+
source: string;
|
|
58
|
+
};
|
|
59
|
+
export type Catalog = {
|
|
51
60
|
/** Package whose API this catalog describes. */
|
|
52
61
|
brandPackage: string;
|
|
53
62
|
/** Version of `@primer/react-brand` the catalog was generated from. */
|
|
@@ -56,5 +65,6 @@ export interface Catalog {
|
|
|
56
65
|
components: CatalogComponent[];
|
|
57
66
|
assets: CatalogAsset[];
|
|
58
67
|
tokens: CatalogToken[];
|
|
59
|
-
|
|
68
|
+
recipes: CatalogRecipe[];
|
|
69
|
+
};
|
|
60
70
|
export declare function emptyCatalog(): Catalog;
|
package/dist/catalog/types.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* All types
|
|
3
|
-
* It is the structured, offline source of truth the tools reason over so they never depend on the network for version-sensitive facts.
|
|
2
|
+
* All types relating to the Catalog
|
|
4
3
|
*/
|
|
5
4
|
export function emptyCatalog() {
|
|
6
5
|
return {
|
|
@@ -10,6 +9,7 @@ export function emptyCatalog() {
|
|
|
10
9
|
components: [],
|
|
11
10
|
assets: [],
|
|
12
11
|
tokens: [],
|
|
12
|
+
recipes: [],
|
|
13
13
|
};
|
|
14
14
|
}
|
|
15
15
|
//# sourceMappingURL=types.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/catalog/types.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/catalog/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AA4EH,MAAM,UAAU,YAAY;IAC1B,OAAO;QACL,YAAY,EAAE,qBAAqB;QACnC,oBAAoB,EAAE,SAAS;QAC/B,WAAW,EAAE,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;QACtC,UAAU,EAAE,EAAE;QACd,MAAM,EAAE,EAAE;QACV,MAAM,EAAE,EAAE;QACV,OAAO,EAAE,EAAE;KACZ,CAAA;AACH,CAAC"}
|
package/dist/catalog.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"brandPackage": "@primer/react-brand",
|
|
3
|
-
"generatedFromVersion": "0.
|
|
4
|
-
"generatedAt": "2026-
|
|
3
|
+
"generatedFromVersion": "0.70.0-rc.9ef718be",
|
|
4
|
+
"generatedAt": "2026-07-03T08:59:04.357Z",
|
|
5
5
|
"components": [
|
|
6
6
|
{
|
|
7
7
|
"name": "Hero",
|
|
@@ -2663,6 +2663,49 @@
|
|
|
2663
2663
|
"second level"
|
|
2664
2664
|
]
|
|
2665
2665
|
},
|
|
2666
|
+
{
|
|
2667
|
+
"name": "NavList",
|
|
2668
|
+
"module": "@primer/react-brand",
|
|
2669
|
+
"subcomponents": [
|
|
2670
|
+
"NavList.Item",
|
|
2671
|
+
"NavList.SubNav",
|
|
2672
|
+
"NavList.Group",
|
|
2673
|
+
"NavList.testIds"
|
|
2674
|
+
],
|
|
2675
|
+
"props": [
|
|
2676
|
+
{
|
|
2677
|
+
"name": "aria-label",
|
|
2678
|
+
"type": "string",
|
|
2679
|
+
"description": "Accessible label for the navigation landmark.",
|
|
2680
|
+
"required": true
|
|
2681
|
+
},
|
|
2682
|
+
{
|
|
2683
|
+
"name": "aria-labelledby",
|
|
2684
|
+
"type": "string",
|
|
2685
|
+
"description": "ID of an element that labels the navigation landmark.",
|
|
2686
|
+
"required": false
|
|
2687
|
+
},
|
|
2688
|
+
{
|
|
2689
|
+
"name": "children",
|
|
2690
|
+
"type": "ReactNode",
|
|
2691
|
+
"required": true
|
|
2692
|
+
}
|
|
2693
|
+
],
|
|
2694
|
+
"examples": [
|
|
2695
|
+
{
|
|
2696
|
+
"title": "NavList example",
|
|
2697
|
+
"code": "<NavList aria-label={String(t('multipleLevelNavigation'))}>\n <NavList.Item defaultExpanded>\n {t('level1Group')}\n <NavList.SubNav>\n <NavList.Item href=\"#\">{t('level2Leaf')}</NavList.Item>\n <NavList.Item defaultExpanded>\n {t('level2Group')}\n <NavList.SubNav>\n <NavList.Item href=\"#\">{t('level3Leaf')}</NavList.Item>\n <NavList.Item defaultExpanded>\n {t('level3Group')}\n <NavList.SubNav>\n <NavList.Item href=\"#\">{t('level4Leaf')}</NavList.Item>\n <NavList.Item defaultExpanded>\n {t('level4Group')}\n <NavList.SubNav>\n <NavList.Item href=\"#\" aria-current=\"page\">\n {t('level5CurrentLeaf')}\n </NavList.Item>\n <NavList.Item href=\"#\">{t('level5SiblingLeaf')}</NavList.Item>\n </NavList.SubNav>\n </NavList.Item>\n </NavList.SubNav>\n </NavList.Item>\n </NavList.SubNav>\n </NavList.Item>\n </NavList.SubNav>\n </NavList.Item>\n</NavList>",
|
|
2698
|
+
"source": "story"
|
|
2699
|
+
}
|
|
2700
|
+
],
|
|
2701
|
+
"description": "Use NavList to render vertical navigation links with groups and expandable nested lists.",
|
|
2702
|
+
"keywords": [
|
|
2703
|
+
"navigation",
|
|
2704
|
+
"vertical navigation",
|
|
2705
|
+
"sidebar",
|
|
2706
|
+
"nested navigation"
|
|
2707
|
+
]
|
|
2708
|
+
},
|
|
2666
2709
|
{
|
|
2667
2710
|
"name": "IDE",
|
|
2668
2711
|
"module": "@primer/react-brand",
|
|
@@ -8085,6 +8128,11 @@
|
|
|
8085
8128
|
"value": "linear-gradient(180deg, rgba(242, 245, 243, 0.5) 0%, rgba(242, 245, 243, 0) 100%), var(--brand-color-canvas-default)",
|
|
8086
8129
|
"group": "functional"
|
|
8087
8130
|
},
|
|
8131
|
+
{
|
|
8132
|
+
"name": "--brand-NavList-activeIndicator-color",
|
|
8133
|
+
"value": "var(--brand-color-text-emphasized)",
|
|
8134
|
+
"group": "functional"
|
|
8135
|
+
},
|
|
8088
8136
|
{
|
|
8089
8137
|
"name": "--brand-PricingOptions-borderMask",
|
|
8090
8138
|
"value": "linear-gradient(180deg, rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0.3))",
|
|
@@ -9960,5 +10008,60 @@
|
|
|
9960
10008
|
"value": "var(--brand-text-display-weight) var(--brand-text-display-size)/var(--brand-text-display-lineHeight) var(--brand-fontStack-sansSerifDisplay)",
|
|
9961
10009
|
"group": "functional"
|
|
9962
10010
|
}
|
|
10011
|
+
],
|
|
10012
|
+
"recipes": [
|
|
10013
|
+
{
|
|
10014
|
+
"name": "FlexSuiteAIDetailsPlaylist",
|
|
10015
|
+
"title": "Product feature details landing page",
|
|
10016
|
+
"keywords": [
|
|
10017
|
+
"product feature",
|
|
10018
|
+
"feature",
|
|
10019
|
+
"details",
|
|
10020
|
+
"detail",
|
|
10021
|
+
"landing page",
|
|
10022
|
+
"media",
|
|
10023
|
+
"video",
|
|
10024
|
+
"playlist",
|
|
10025
|
+
"watch",
|
|
10026
|
+
"full page",
|
|
10027
|
+
"template"
|
|
10028
|
+
],
|
|
10029
|
+
"source": "import {CodeOfConductIcon, CpuIcon, LightBulbIcon, LogoGithubIcon} from '@primer/octicons-react'\nimport {clsx} from 'clsx'\nimport type {CSSProperties} from 'react'\n\nimport {\n Box,\n Button,\n Card,\n CTABanner,\n Grid,\n Heading,\n Hero,\n Image,\n InlineLink,\n MediaPlaylist,\n Section,\n SectionIntro,\n SubNav,\n Text,\n Token,\n} from '../../../..'\nimport {RedlineBackground} from '../../../../component-helpers'\n\nimport {\n defaultFlexSuiteAIDetailsPlaylistContent,\n type FlexSuiteAIDetailsPlaylistContent,\n} from './FlexSuiteAIDetailsPlaylist.content'\nimport placeholderImage from '../../../../fixtures/images/placeholder.png'\nimport overviewStyles from '../../Overview/FlexSuiteAIOverview.module.css'\n\nexport type FlexSuiteAIDetailsPlaylistTemplateProps = {\n content: FlexSuiteAIDetailsPlaylistContent\n}\n\nconst cardIcons = [CpuIcon, CodeOfConductIcon, LightBulbIcon] as const\nconst videoEmbedStyles: CSSProperties = {\n aspectRatio: '16 / 9',\n border: 0,\n display: 'block',\n width: '100%',\n}\n\nexport function FlexSuiteAIDetailsPlaylist() {\n return <FlexSuiteAIDetailsPlaylistTemplate content={defaultFlexSuiteAIDetailsPlaylistContent} />\n}\n\nexport function FlexSuiteAIDetailsPlaylistTemplate({content}: FlexSuiteAIDetailsPlaylistTemplateProps) {\n return (\n <Box className={overviewStyles.page} backgroundColor=\"default\">\n <Box backgroundColor=\"subtle\" style={{height: 72}} />\n\n <Box style={{minHeight: '56px', position: 'relative'}}>\n <SubNav>\n <SubNav.Heading href=\"#\">{content.subNav.heading}</SubNav.Heading>\n\n {content.subNav.links.map((link, index) => (\n <SubNav.Link key={link} href=\"#\" aria-current={index === 4 ? 'page' : undefined}>\n {link}\n </SubNav.Link>\n ))}\n </SubNav>\n </Box>\n\n <Box\n backgroundColor=\"subtle\"\n borderInlineStartWidth=\"thin\"\n borderInlineEndWidth=\"thin\"\n borderColor=\"muted\"\n borderStyle=\"solid\"\n style={{maxInlineSize: 'var(--brand-breakpoint-xlarge)', marginInline: 'auto'}}\n >\n <Hero\n align=\"center\"\n trailingComponent={() => (\n <Box marginBlockStart={12}>\n <Text size=\"100\">\n {content.hero.secondaryText} <InlineLink href=\"#\">{content.hero.secondaryLinkText}</InlineLink>\n </Text>\n </Box>\n )}\n >\n <Hero.Heading>\n {content.hero.headingPrefix}\n <br /> <b>{content.hero.headingEmphasis}</b>\n </Hero.Heading>\n <Hero.Description>{content.hero.description}</Hero.Description>\n <Hero.PrimaryAction href=\"#\">{content.hero.primaryAction}</Hero.PrimaryAction>\n </Hero>\n </Box>\n\n {content.playlists.map((playlist, index) => (\n <Box\n key={playlist.heading}\n borderColor=\"muted\"\n borderStyle=\"solid\"\n borderBlockStartWidth={index === 0 ? 'thin' : 'none'}\n >\n <Section paddingBlockStart=\"condensed\" paddingBlockEnd=\"condensed\" fullWidth>\n <SectionIntro align=\"center\" fullWidth>\n <SectionIntro.Heading size=\"3\">{playlist.heading}</SectionIntro.Heading>\n </SectionIntro>\n </Section>\n <MediaPlaylist>\n <MediaPlaylist.Heading>{playlist.playlistHeading}</MediaPlaylist.Heading>\n\n {playlist.videos.map(video => (\n <MediaPlaylist.Item\n key={video.id}\n thumbnail={\n <Image\n src={\n process.env.NODE_ENV === 'test'\n ? placeholderImage\n : `https://i.ytimg.com/vi/${video.id}/hqdefault.jpg`\n }\n alt=\"\"\n aspectRatio=\"16:9\"\n loading=\"lazy\"\n />\n }\n >\n <MediaPlaylist.ItemHeading title={video.title} description={video.duration} />\n <MediaPlaylist.ItemContent>\n <Heading as=\"h3\" size=\"subhead-large\">\n {video.title}\n </Heading>\n <Text variant=\"muted\">{video.summary}</Text>\n </MediaPlaylist.ItemContent>\n <MediaPlaylist.ItemMedia>\n <iframe\n style={videoEmbedStyles}\n src={`https://www.youtube-nocookie.com/embed/${video.id}`}\n title={video.title}\n loading=\"lazy\"\n allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\"\n allowFullScreen\n referrerPolicy=\"strict-origin-when-cross-origin\"\n />\n </MediaPlaylist.ItemMedia>\n </MediaPlaylist.Item>\n ))}\n </MediaPlaylist>\n </Box>\n ))}\n\n <Section paddingBlockStart=\"condensed\" paddingBlockEnd=\"condensed\" fullWidth>\n <SectionIntro align=\"center\" fullWidth>\n <SectionIntro.Heading size=\"3\">{content.resources.heading}</SectionIntro.Heading>\n </SectionIntro>\n </Section>\n\n <Box className={overviewStyles.cardGridFrame}>\n <Box className={overviewStyles.cardGridContent}>\n <Grid columnGap=\"none\" rowGap=\"none\" enableGutters={false}>\n {content.resources.cards.map((card, index) => (\n <Grid.Column\n key={card.heading}\n span={{xsmall: 12, large: 4}}\n className={clsx(overviewStyles.cardGridColumn, overviewStyles.cardGridColumnArrowHover)}\n >\n <Box className={overviewStyles.cardGridItem}>\n <Card\n href=\"#\"\n fullWidth\n ctaVariant=\"arrow\"\n ctaText={content.common.learnMore}\n className={overviewStyles.resourceCard}\n >\n <Card.Icon icon={cardIcons[index]} color=\"green\" hasBackground size=\"medium\" />\n <Card.Tokens>\n <Token>{card.tag}</Token>\n </Card.Tokens>\n <Card.Heading>{card.heading}</Card.Heading>\n <Card.Description>{card.description}</Card.Description>\n </Card>\n </Box>\n </Grid.Column>\n ))}\n </Grid>\n </Box>\n </Box>\n\n <Box paddingBlockStart={80} paddingBlockEnd={80}>\n <CTABanner align=\"center\" hasGridLines>\n <CTABanner.Logo>\n <LogoGithubIcon size={64} />\n </CTABanner.Logo>\n <CTABanner.Heading>\n {content.cta.headingPrefix} <br /> <b>{content.cta.headingEmphasis}</b>\n </CTABanner.Heading>\n <CTABanner.Description>{content.cta.description}</CTABanner.Description>\n <CTABanner.ButtonGroup>\n <Button>{content.cta.primaryAction}</Button>\n </CTABanner.ButtonGroup>\n </CTABanner>\n </Box>\n\n <RedlineBackground style={{height: 600, display: 'flex', flexDirection: 'column', gap: 'var(--base-size-32)'}}>\n <RedlineBackground\n style={{height: 84, marginTop: 'auto', backgroundColor: 'var(--brand-color-border-default)'}}\n />\n </RedlineBackground>\n </Box>\n )\n}"
|
|
10030
|
+
},
|
|
10031
|
+
{
|
|
10032
|
+
"name": "FlexSuiteAIOverview",
|
|
10033
|
+
"title": "Product feature overview landing page",
|
|
10034
|
+
"keywords": [
|
|
10035
|
+
"product feature",
|
|
10036
|
+
"feature",
|
|
10037
|
+
"overview",
|
|
10038
|
+
"landing",
|
|
10039
|
+
"landing page",
|
|
10040
|
+
"homepage",
|
|
10041
|
+
"home",
|
|
10042
|
+
"product page",
|
|
10043
|
+
"marketing page",
|
|
10044
|
+
"full page",
|
|
10045
|
+
"template"
|
|
10046
|
+
],
|
|
10047
|
+
"source": "import {CodeOfConductIcon, CpuIcon, LightBulbIcon, LogoGithubIcon, SparkleFillIcon} from '@primer/octicons-react'\nimport {clsx} from 'clsx'\nimport React, {useEffect} from 'react'\n\nimport {\n Box,\n Card,\n ColorModesEnum,\n CTABanner,\n FAQ,\n FAQGroup,\n Grid,\n Hero,\n Heading,\n InlineLink,\n LogoSuite,\n Section,\n SectionIntro,\n SubNav,\n Text,\n River,\n EyebrowText,\n Link,\n Stack,\n Token,\n PricingOptions,\n Tabs,\n Tiles,\n Image,\n useTheme,\n} from '../../..'\nimport {RedlineBackground} from '../../../component-helpers'\nimport placeholderBg from '../../../fixtures/images/dither-bg-landscape-purple.png'\nimport brandDividerWide from '../../../fixtures/images/brand-divider-copilot-wide.png'\nimport mercardo from '../../../fixtures/images/bento/mercado.png'\nimport copilotHeroHead from '../../../fixtures/images/copilot-mascot-head-peeking.png'\nimport renderUI3 from '../../../fixtures/images/copilot-vscode-agent-mode-3.png'\nimport renderUI3Dark from '../../../fixtures/images/copilot-vscode-agent-mode-3-dark.png'\nimport {logos} from '../../../LogoSuite/LogoSuite.fixtures'\nimport {tileItems} from '../../../Tiles/Tiles.fixtures'\n\nimport {defaultFlexSuiteAIOverviewContent, type FlexSuiteAIOverviewContent} from './FlexSuiteAIOverview.content'\nimport styles from './FlexSuiteAIOverview.module.css'\n\nexport type FlexSuiteAIOverviewTemplateProps = {\n content: FlexSuiteAIOverviewContent\n}\n\nconst cardIcons = [CpuIcon, LightBulbIcon, CodeOfConductIcon] as const\n\nexport function FlexSuiteAIOverview() {\n return <FlexSuiteAIOverviewTemplate content={defaultFlexSuiteAIOverviewContent} />\n}\n\nexport function FlexSuiteAIOverviewTemplate({content}: FlexSuiteAIOverviewTemplateProps) {\n const heroImageRef = React.useRef<HTMLDivElement>(null)\n const riverImageRefs = React.useRef<Array<HTMLDivElement | null>>([])\n const {colorMode} = useTheme()\n\n useEffect(() => {\n const cleanups: Array<() => void> = []\n\n if (heroImageRef.current) {\n cleanups.push(TempFadeInBackgroundEffect(heroImageRef.current, placeholderBg, 500))\n }\n\n for (const element of riverImageRefs.current) {\n if (element) {\n cleanups.push(TempFadeInBackgroundEffect(element, placeholderBg, 500))\n }\n }\n\n return () => {\n for (const cleanup of cleanups) {\n cleanup()\n }\n }\n }, [])\n\n return (\n <>\n <Box className={styles.page} backgroundColor=\"default\">\n <Box backgroundColor=\"subtle\" style={{height: 72}} />\n\n <SubNav>\n <SubNav.Heading href=\"#\">{content.subNav.heading}</SubNav.Heading>\n\n {content.subNav.links.map(link => (\n <SubNav.Link key={link} href=\"#\">\n {link}\n </SubNav.Link>\n ))}\n </SubNav>\n <Box paddingBlockStart={64}></Box>\n\n <Section paddingBlockStart=\"none\" paddingBlockEnd=\"none\" fullWidth>\n <Hero\n imageContainerRef={heroImageRef}\n enableAnimation\n variant=\"gridline-expressive\"\n trailingComponent={() => (\n <Box className={styles.heroTrailingPeek}>\n <Text variant=\"muted\">\n {content.hero.trailingText} <InlineLink href=\"#\">{content.hero.trailingLinkText}</InlineLink>\n </Text>\n <Image\n className={styles.heroTrailingPeekImage}\n style={\n {\n ['--hero-peek-left' as string]: '-310px',\n ['--hero-peek-bottom' as string]: '-65px',\n ['--hero-peek-width' as string]: '190px',\n } as React.CSSProperties\n }\n src={copilotHeroHead}\n alt={content.hero.peekAlt}\n />\n </Box>\n )}\n >\n <Hero.Label>{content.hero.label}</Hero.Label>\n <Hero.Heading>\n {content.hero.headingLine1} <br /> {content.hero.headingLine2}\n </Hero.Heading>\n <Hero.Description>{content.hero.description}</Hero.Description>\n <Hero.PrimaryAction href=\"#\">{content.hero.primaryAction}</Hero.PrimaryAction>\n <Hero.SecondaryAction href=\"#\">{content.hero.secondaryAction}</Hero.SecondaryAction>\n <Hero.Image\n enableBorder={false}\n position=\"block-end\"\n src={colorMode === ColorModesEnum.DARK ? renderUI3Dark : renderUI3}\n alt={content.hero.imageAlt}\n />\n </Hero>\n </Section>\n\n <LogoSuite variant=\"gridline-expressive\">\n <LogoSuite.Heading visuallyHidden>{content.logoSuiteHeading}</LogoSuite.Heading>\n <LogoSuite.Logobar marquee={process.env.NODE_ENV !== 'test'}>{logos.slice(0, 8)}</LogoSuite.Logobar>\n </LogoSuite>\n\n <Box className={clsx(styles.cardGridFrame, styles.cardGridFrameNoTopBorder)}>\n <Box className={styles.cardGridContent}>\n <Grid columnGap=\"none\" rowGap=\"none\" enableGutters={false}>\n {content.resourceCards.map((card, index) => (\n <Grid.Column\n key={card.heading}\n span={{xsmall: 12, large: 4}}\n className={clsx(styles.cardGridColumn, styles.cardGridColumnArrowHover)}\n >\n <Box className={styles.cardGridItem} padding={24}>\n <Card\n href=\"#\"\n fullWidth\n ctaVariant=\"arrow\"\n ctaText={content.common.learnMore}\n className={styles.resourceCard}\n >\n <Card.Icon\n icon={cardIcons[index]}\n color=\"green\"\n hasBackground\n size=\"medium\"\n className={styles.resourceCardIcon}\n />\n <Card.Heading>{card.heading}</Card.Heading>\n <Card.Description>{card.description}</Card.Description>\n </Card>\n </Box>\n </Grid.Column>\n ))}\n </Grid>\n </Box>\n </Box>\n\n <Section paddingBlockStart=\"condensed\" paddingBlockEnd=\"none\">\n <SectionIntro align=\"center\" fullWidth>\n <SectionIntro.Label>{content.workflow.label}</SectionIntro.Label>\n <SectionIntro.Heading>{content.workflow.heading}</SectionIntro.Heading>\n <SectionIntro.Description>{content.workflow.description}</SectionIntro.Description>\n </SectionIntro>\n </Section>\n <Section paddingBlockEnd=\"none\">\n <Stack direction=\"vertical\" padding=\"none\" gap=\"spacious\">\n <River variant=\"gridline\">\n <River.Visual\n ref={element => {\n riverImageRefs.current[0] = element\n }}\n imageBackgroundColor=\"subtle\"\n >\n <picture>\n <source\n srcSet={colorMode === ColorModesEnum.DARK ? renderUI3Dark : renderUI3}\n media=\"(max-width: 47.99rem)\"\n />\n <img\n src={colorMode === ColorModesEnum.DARK ? renderUI3Dark : renderUI3}\n alt={content.rivers[0].imageAlt}\n />\n </picture>\n </River.Visual>\n <River.Content>\n <EyebrowText>{content.rivers[0].eyebrow}</EyebrowText>\n <Heading>{content.rivers[0].heading}</Heading>\n <Text>{content.rivers[0].description}</Text>\n <Link href=\"#\">{content.rivers[0].linkText}</Link>\n </River.Content>\n </River>\n <River variant=\"gridline\">\n <River.Visual\n ref={element => {\n riverImageRefs.current[1] = element\n }}\n imageBackgroundColor=\"subtle\"\n >\n <picture>\n <source\n srcSet={colorMode === ColorModesEnum.DARK ? renderUI3Dark : renderUI3}\n media=\"(max-width: 47.99rem)\"\n />\n <img\n src={colorMode === ColorModesEnum.DARK ? renderUI3Dark : renderUI3}\n alt={content.rivers[1].imageAlt}\n />\n </picture>\n </River.Visual>\n <River.Content>\n <EyebrowText>{content.rivers[1].eyebrow}</EyebrowText>\n <Heading>{content.rivers[1].heading}</Heading>\n <Text>{content.rivers[1].description}</Text>\n <Link href=\"#\">{content.rivers[1].linkText}</Link>\n </River.Content>\n </River>\n <River variant=\"gridline\">\n <River.Visual\n ref={element => {\n riverImageRefs.current[2] = element\n }}\n imageBackgroundColor=\"subtle\"\n >\n <picture>\n <source\n srcSet={colorMode === ColorModesEnum.DARK ? renderUI3Dark : renderUI3}\n media=\"(max-width: 47.99rem)\"\n />\n <img\n src={colorMode === ColorModesEnum.DARK ? renderUI3Dark : renderUI3}\n alt={content.rivers[2].imageAlt}\n />\n </picture>\n </River.Visual>\n <River.Content>\n <EyebrowText>{content.rivers[2].eyebrow}</EyebrowText>\n <Heading>{content.rivers[2].heading}</Heading>\n <Text>{content.rivers[2].description}</Text>\n <Link href=\"#\">{content.rivers[2].linkText}</Link>\n </River.Content>\n </River>\n </Stack>\n </Section>\n <Box marginBlockStart={48}>\n <CTABanner variant=\"balanced\" hasGridLines>\n <CTABanner.Logo>{<LogoGithubIcon size={64} />}</CTABanner.Logo>\n <CTABanner.Heading size=\"5\">\n {content.bento.headingPrefix} <b>{content.bento.headingEmphasis}</b>\n </CTABanner.Heading>\n <CTABanner.Link href=\"#\">{content.bento.linkText}</CTABanner.Link>\n <CTABanner.Image src={mercardo} alt={content.bento.imageAlt} />\n </CTABanner>\n </Box>\n <Stack justifyContent=\"center\" padding=\"none\">\n <Box borderBlockEndWidth=\"thin\" borderColor=\"muted\" borderStyle=\"solid\">\n <Image src={brandDividerWide} alt={content.common.brandDividerAlt} style={{display: 'block'}} />\n </Box>\n </Stack>\n <Section paddingBlockStart=\"none\" paddingBlockEnd=\"none\">\n <Box paddingBlockEnd={48} paddingBlockStart={48}>\n <SectionIntro align=\"center\" fullWidth>\n <SectionIntro.Heading>{content.organization.heading}</SectionIntro.Heading>\n <SectionIntro.Description>{content.organization.description}</SectionIntro.Description>\n </SectionIntro>\n </Box>\n </Section>\n\n <Box className={styles.cardGridFrame}>\n <Box className={styles.cardGridContent}>\n <Grid columnGap=\"none\" rowGap=\"none\" enableGutters={false}>\n {content.organization.cards.map((card, index) => (\n <Grid.Column\n key={card.heading}\n span={{xsmall: 12, large: 4}}\n className={clsx(styles.cardGridColumn, styles.cardGridColumnArrowHover)}\n >\n <Box className={styles.cardGridItem}>\n <Card\n href=\"#\"\n fullWidth\n ctaVariant=\"arrow\"\n ctaText={content.common.learnMore}\n className={styles.resourceCard}\n >\n <Card.Icon\n icon={cardIcons[index]}\n color=\"green\"\n hasBackground\n size=\"medium\"\n className={styles.resourceCardIcon}\n />\n <Card.Tokens>\n <Token>{card.tag}</Token>\n </Card.Tokens>\n <Card.Heading>{card.heading}</Card.Heading>\n <Card.Description>{card.description}</Card.Description>\n </Card>\n </Box>\n </Grid.Column>\n ))}\n </Grid>\n </Box>\n </Box>\n\n <Section paddingBlockStart=\"none\" paddingBlockEnd=\"none\">\n <Box paddingBlockEnd={4} paddingBlockStart={60}>\n <SectionIntro align=\"center\" fullWidth>\n <SectionIntro.Label>{content.plans.label}</SectionIntro.Label>\n <SectionIntro.Heading>{content.plans.heading}</SectionIntro.Heading>\n </SectionIntro>\n </Box>\n </Section>\n <Tabs aria-label={content.plans.tabsAriaLabel} variant=\"accent\" className={styles.fullWidthTabsPanel}>\n {content.plans.tabs.map(tab => (\n <Tabs.Item key={tab}>{tab}</Tabs.Item>\n ))}\n {content.plans.tabs.map(tab => (\n <Tabs.Panel key={tab}>\n <Box className={styles.cardGridFrame} backgroundColor=\"default\">\n <Grid>\n <Grid.Column span={12}>\n <PricingOptions\n style={{marginBlock: 'calc(var(--brand-borderWidth-thin) * -1)'}}\n variant=\"default-gradient\"\n >\n <PricingOptions.Item>\n <PricingOptions.Heading>{content.pricing.free.heading}</PricingOptions.Heading>\n <PricingOptions.Description>{content.pricing.free.description}</PricingOptions.Description>\n <PricingOptions.Price>{content.pricing.free.price}</PricingOptions.Price>\n <PricingOptions.FeatureList>\n <PricingOptions.FeatureListItem>\n {content.pricing.free.features[0]}\n </PricingOptions.FeatureListItem>\n <PricingOptions.FeatureListItem>\n {content.pricing.free.features[1]}\n </PricingOptions.FeatureListItem>\n <PricingOptions.FeatureListItem\n leadingVisual={SparkleFillIcon}\n leadingVisualFill=\"var(--base-color-scale-purple-5)\"\n >\n {content.pricing.free.features[2]}\n </PricingOptions.FeatureListItem>\n </PricingOptions.FeatureList>\n <PricingOptions.PrimaryAction as=\"a\" href=\"#\" variant=\"primary\">\n {content.pricing.free.primaryAction}\n </PricingOptions.PrimaryAction>\n {content.pricing.free.secondaryAction ? (\n <PricingOptions.SecondaryAction as=\"a\" href=\"#\" variant=\"subtle\">\n {content.pricing.free.secondaryAction}\n </PricingOptions.SecondaryAction>\n ) : null}\n </PricingOptions.Item>\n <PricingOptions.Item>\n <PricingOptions.Heading>{content.pricing.pro.heading}</PricingOptions.Heading>\n {content.pricing.pro.label ? (\n <PricingOptions.Label>{content.pricing.pro.label}</PricingOptions.Label>\n ) : null}\n <PricingOptions.Description>{content.pricing.pro.description}</PricingOptions.Description>\n <PricingOptions.Price trailingText={content.pricing.pro.trailingText}>\n {content.pricing.pro.price}\n </PricingOptions.Price>\n <PricingOptions.PrimaryAction as=\"a\" href=\"#\" variant=\"primary\">\n {content.pricing.pro.primaryAction}\n </PricingOptions.PrimaryAction>\n <PricingOptions.FeatureList>\n <PricingOptions.FeatureListHeading>\n {content.pricing.pro.featureListHeading}\n </PricingOptions.FeatureListHeading>\n <PricingOptions.FeatureListItem>\n {content.pricing.pro.features[0]}\n </PricingOptions.FeatureListItem>\n <PricingOptions.FeatureListItem>\n {content.pricing.pro.features[1]}\n </PricingOptions.FeatureListItem>\n <PricingOptions.FeatureListItem>\n {content.pricing.pro.features[2]}\n </PricingOptions.FeatureListItem>\n <PricingOptions.FeatureListItem>\n {content.pricing.pro.features[3]}\n </PricingOptions.FeatureListItem>\n </PricingOptions.FeatureList>\n {content.pricing.pro.footnote ? (\n <PricingOptions.Footnote>\n {content.pricing.pro.footnote}{' '}\n {content.pricing.pro.footnoteLinkText ? (\n <InlineLink href=\"#\">{content.pricing.pro.footnoteLinkText}</InlineLink>\n ) : null}\n </PricingOptions.Footnote>\n ) : null}\n </PricingOptions.Item>\n\n <PricingOptions.Item>\n <PricingOptions.Heading>{content.pricing.proPlus.heading}</PricingOptions.Heading>\n <PricingOptions.Description>{content.pricing.proPlus.description}</PricingOptions.Description>\n <PricingOptions.Price trailingText={content.pricing.proPlus.trailingText}>\n {content.pricing.proPlus.price}\n </PricingOptions.Price>\n <PricingOptions.PrimaryAction as=\"a\" href=\"#\" variant=\"primary\">\n {content.pricing.proPlus.primaryAction}\n </PricingOptions.PrimaryAction>\n <PricingOptions.FeatureList>\n <PricingOptions.FeatureListHeading>\n {content.pricing.proPlus.featureListHeading}\n </PricingOptions.FeatureListHeading>\n <PricingOptions.FeatureListItem>\n {content.pricing.proPlus.features[0]}\n </PricingOptions.FeatureListItem>\n <PricingOptions.FeatureListItem>\n {content.pricing.proPlus.features[1]}\n </PricingOptions.FeatureListItem>\n <PricingOptions.FeatureListItem\n leadingVisual={SparkleFillIcon}\n leadingVisualFill=\"var(--base-color-scale-purple-5)\"\n >\n {content.pricing.proPlus.features[2]}\n </PricingOptions.FeatureListItem>\n <PricingOptions.FeatureListItem>\n {content.pricing.proPlus.features[3]}\n </PricingOptions.FeatureListItem>\n </PricingOptions.FeatureList>\n </PricingOptions.Item>\n </PricingOptions>\n </Grid.Column>\n </Grid>\n </Box>\n </Tabs.Panel>\n ))}\n </Tabs>\n\n <Section paddingBlockEnd=\"none\">\n <Tiles variant=\"gridlines\" layout=\"compact\">\n {tileItems.slice(0, 6).map(item => (\n <Tiles.Item key={item.name} name={item.name} href={item.href}>\n {item.icon}\n </Tiles.Item>\n ))}\n </Tiles>\n </Section>\n\n <Section paddingBlockStart=\"none\" paddingBlockEnd=\"none\">\n <Box paddingBlockEnd={32} paddingBlockStart={80}>\n <SectionIntro align=\"center\" fullWidth>\n <SectionIntro.Heading>{content.resources.heading}</SectionIntro.Heading>\n </SectionIntro>\n </Box>\n </Section>\n\n <Box className={styles.cardGridFrame} marginBlockEnd={80}>\n <Box className={styles.cardGridContent}>\n <Grid columnGap=\"none\" rowGap=\"none\" enableGutters={false}>\n {content.resources.cards.map((card, index) => (\n <Grid.Column\n key={card.heading}\n span={{xsmall: 12, large: 4}}\n className={clsx(styles.cardGridColumn, styles.cardGridColumnArrowHover)}\n >\n <Box className={styles.cardGridItem}>\n <Card\n href=\"#\"\n fullWidth\n ctaVariant=\"arrow\"\n ctaText={content.common.learnMore}\n className={styles.resourceCard}\n >\n <Card.Icon\n icon={cardIcons[index]}\n color=\"green\"\n hasBackground\n size=\"medium\"\n className={styles.resourceCardIcon}\n />\n <Card.Tokens>\n <Token>{card.tag}</Token>\n </Card.Tokens>\n <Card.Heading>{card.heading}</Card.Heading>\n <Card.Description>{card.description}</Card.Description>\n </Card>\n </Box>\n </Grid.Column>\n ))}\n </Grid>\n </Box>\n </Box>\n <Box paddingBlockEnd={64}>\n <FAQGroup variant=\"gridline\" defaultSelectedIndex={1}>\n <FAQGroup.Heading>\n {content.faq.headingLine1}\n <br />\n {content.faq.headingLine2}\n </FAQGroup.Heading>\n {content.faq.groups.map(group => (\n <FAQ key={group.heading} variant=\"gridline\">\n <FAQ.Heading>{group.heading}</FAQ.Heading>\n {group.items.map((item, index) => (\n <FAQ.Item key={item.question} name={`faq-${group.heading}`} open={index === 0}>\n <FAQ.Question>{item.question}</FAQ.Question>\n <FAQ.Answer>\n <Text as=\"p\" variant=\"muted\">\n {item.answer}\n </Text>\n </FAQ.Answer>\n </FAQ.Item>\n ))}\n </FAQ>\n ))}\n </FAQGroup>\n </Box>\n\n <RedlineBackground style={{height: 600, display: 'flex', flexDirection: 'column', gap: 'var(--base-size-32)'}}>\n <RedlineBackground\n style={{height: 84, marginTop: 'auto', backgroundColor: 'var(--brand-color-border-default)'}}\n />\n </RedlineBackground>\n </Box>\n </>\n )\n}\n\nfunction TempFadeInBackgroundEffect(element: HTMLDivElement, backgroundImageUrl: string, delay = 100) {\n element.style.position = 'relative'\n\n const bgDiv = document.createElement('div')\n bgDiv.style.cssText = `\n position: absolute;\n inset: 0;\n background-image: url(${backgroundImageUrl});\n background-size: cover;\n background-position: center;\n opacity: 0;\n transition: opacity 1.5s ease-out;\n z-index: 0;\n `\n element.insertBefore(bgDiv, element.firstChild)\n\n const children = element.children\n for (let index = 1; index < children.length; index += 1) {\n ;(children[index] as HTMLElement).style.position = 'relative'\n ;(children[index] as HTMLElement).style.zIndex = '1'\n }\n\n const timer = setTimeout(() => {\n bgDiv.style.opacity = '1'\n }, delay)\n\n return () => {\n clearTimeout(timer)\n bgDiv.remove()\n }\n}"
|
|
10048
|
+
},
|
|
10049
|
+
{
|
|
10050
|
+
"name": "FlexSuiteSecurityCategory",
|
|
10051
|
+
"title": "Product feature category landing page",
|
|
10052
|
+
"keywords": [
|
|
10053
|
+
"product feature",
|
|
10054
|
+
"feature",
|
|
10055
|
+
"category",
|
|
10056
|
+
"landing page",
|
|
10057
|
+
"solution",
|
|
10058
|
+
"solutions",
|
|
10059
|
+
"use case",
|
|
10060
|
+
"topic",
|
|
10061
|
+
"full page",
|
|
10062
|
+
"template"
|
|
10063
|
+
],
|
|
10064
|
+
"source": "import {CodeOfConductIcon, CpuIcon, LightBulbIcon} from '@primer/octicons-react'\nimport {clsx} from 'clsx'\n\nimport {\n Box,\n Card,\n Grid,\n Hero,\n Pillar,\n LogoSuite,\n Section,\n SectionIntro,\n Stack,\n SubNav,\n Image,\n Token,\n Testimonial,\n CTABanner,\n Button,\n Text,\n} from '../../../..'\nimport {logos} from '../../../../LogoSuite/LogoSuite.fixtures'\nimport placeholderBg from '../../../../fixtures/images/security-banner-wide.png'\nimport placeholderImage from '../../../../fixtures/images/placeholder.png'\nimport monaAvatar from '../../../../fixtures/images/avatar-mona.png'\nimport brandDividerWide from '../../../../fixtures/images/brand-divider-security-wide.png'\nimport riverFootstepsChat from './fixtures/images/river-footsteps-chat.png'\nimport riverFootstepsChatMobile from './fixtures/images/river-footsteps-chat-mobile.png'\nimport riverFootstepsReview from './fixtures/images/river-footsteps-review.png'\nimport riverFootstepsReviewMobile from './fixtures/images/river-footsteps-review-mobile.png'\nimport riverFootstepsWorkflow from './fixtures/images/river-footsteps-workflow.png'\nimport riverFootstepsWorkflowMobile from './fixtures/images/river-footsteps-workflow-mobile.png'\n\nimport {\n defaultFlexSuiteSecurityCategoryContent,\n type FlexSuiteSecurityCategoryContent,\n} from './FlexSuiteSecurityCategory.content'\nimport styles from '../../Overview/FlexSuiteAIOverview.module.css'\nimport {RedlineBackground} from '../../../../component-helpers'\nimport {LockIcon} from '@primer/octovisuals-react'\n\nexport type FlexSuiteSecurityCategoryTemplateProps = {\n content: FlexSuiteSecurityCategoryContent\n}\n\nconst cardIcons = [CpuIcon, LightBulbIcon, CodeOfConductIcon] as const\nconst riverFootstepsImages = [riverFootstepsWorkflow, riverFootstepsReview, riverFootstepsChat] as const\nconst riverFootstepsMobileImages = [\n riverFootstepsWorkflowMobile,\n riverFootstepsReviewMobile,\n riverFootstepsChatMobile,\n] as const\n\nexport function FlexSuiteSecurityCategory() {\n return <FlexSuiteSecurityCategoryTemplate content={defaultFlexSuiteSecurityCategoryContent} />\n}\n\nexport function FlexSuiteSecurityCategoryTemplate({content}: FlexSuiteSecurityCategoryTemplateProps) {\n return (\n <Box className={styles.page} backgroundColor=\"default\">\n <Box backgroundColor=\"subtle\" style={{height: 72}} />\n\n <SubNav>\n <SubNav.Heading href=\"#\" aria-current=\"page\">\n {content.subNav.heading}\n </SubNav.Heading>\n\n {content.subNav.links.map(link => (\n <SubNav.Link key={link} href=\"#\">\n {link}\n </SubNav.Link>\n ))}\n </SubNav>\n\n <Section paddingBlockStart=\"none\" paddingBlockEnd=\"none\">\n <Hero align=\"center\">\n <Hero.Label>{content.hero.label}</Hero.Label>\n <Hero.Heading>{content.hero.heading}</Hero.Heading>\n <Hero.PrimaryAction href=\"#\">{content.hero.primaryAction}</Hero.PrimaryAction>\n <Hero.SecondaryAction href=\"#\">{content.hero.secondaryAction}</Hero.SecondaryAction>\n </Hero>\n </Section>\n <Stack justifyContent=\"center\" padding=\"none\" style={{marginTop: 'calc(var(--base-size-64) * -1)'}}>\n <Box borderBlockEndWidth=\"thin\" borderColor=\"muted\" borderStyle=\"solid\">\n <Image src={placeholderBg} alt={content.common.heroImageAlt} style={{display: 'block', width: '100%'}} />\n </Box>\n </Stack>\n <Box\n className={clsx(styles.cardGridFrame)}\n marginBlockStart={{narrow: 24, wide: 80}}\n marginBlockEnd={{narrow: 24, wide: 64}}\n >\n <Box className={styles.cardGridContent}>\n <Grid columnGap=\"none\" rowGap=\"none\" enableGutters={false}>\n {content.highlights.map((card, index) => (\n <Grid.Column\n key={card.heading}\n span={{xsmall: 12, large: 4}}\n className={clsx(styles.cardGridColumn, styles.cardGridColumnArrowHover)}\n >\n <Box className={styles.cardGridItem}>\n <Card\n href=\"#\"\n fullWidth\n ctaVariant=\"arrow\"\n ctaText={content.common.learnMore}\n className={styles.resourceCard}\n >\n <Card.Icon icon={cardIcons[index]} color=\"green\" hasBackground size=\"medium\" />\n {card.tag ? (\n <Card.Tokens>\n <Token>{card.tag}</Token>\n </Card.Tokens>\n ) : null}\n <Card.Heading as=\"h2\">{card.heading}</Card.Heading>\n <Card.Description>{card.description}</Card.Description>\n </Card>\n </Box>\n </Grid.Column>\n ))}\n </Grid>\n </Box>\n </Box>\n\n <Box borderBlockStartWidth=\"thin\" borderColor=\"muted\" borderStyle=\"solid\">\n <LogoSuite variant=\"gridline-expressive\">\n <LogoSuite.Heading visuallyHidden>{content.logoSuiteHeading}</LogoSuite.Heading>\n <LogoSuite.Logobar marquee={process.env.NODE_ENV !== 'test'}>{logos.slice(0, 8)}</LogoSuite.Logobar>\n </LogoSuite>\n </Box>\n\n <Section paddingBlockEnd=\"none\" paddingBlockStart=\"condensed\">\n <SectionIntro align=\"center\">\n <SectionIntro.Label>{content.workflow.label}</SectionIntro.Label>\n <SectionIntro.Heading>{content.workflow.heading}</SectionIntro.Heading>\n </SectionIntro>\n </Section>\n\n <Box className={styles.cardGridFrame} marginBlockStart={48}>\n <Box className={styles.cardGridContent}>\n <Grid columnGap=\"none\" rowGap=\"none\" enableGutters={false}>\n {content.capabilities.map(card => (\n <Grid.Column\n key={card.heading}\n span={{xsmall: 12, large: 6}}\n className={clsx(styles.cardGridColumn, styles.cardGridColumnArrowHover)}\n >\n <Box className={styles.cardGridItem}>\n <Card\n href=\"#\"\n fullWidth\n ctaVariant=\"arrow\"\n ctaText={content.common.learnMore}\n className={styles.resourceCard}\n >\n <Card.Image aspectRatio=\"16:10\" src={placeholderImage} alt=\"\" />\n <Card.Heading>{card.heading}</Card.Heading>\n <Card.Description>{card.description}</Card.Description>\n </Card>\n </Box>\n </Grid.Column>\n ))}\n </Grid>\n </Box>\n </Box>\n\n <Section paddingBlockStart=\"condensed\" paddingBlockEnd=\"none\">\n <SectionIntro align=\"center\" fullWidth>\n <SectionIntro.Label>{content.customerStories.label}</SectionIntro.Label>\n <SectionIntro.Heading>{content.customerStories.heading}</SectionIntro.Heading>\n </SectionIntro>\n </Section>\n\n <Box className={styles.cardGridFrame} marginBlockStart={48}>\n <Box className={styles.cardGridContent}>\n <Grid columnGap=\"none\" rowGap=\"none\" enableGutters={false}>\n {content.customerStories.cards.map(card => (\n <Grid.Column\n key={card.heading}\n span={{xsmall: 12, large: 4}}\n className={clsx(styles.cardGridColumn, styles.cardGridColumnArrowHover)}\n >\n <Box className={styles.cardGridItem}>\n <Card href=\"#\" fullWidth ctaVariant=\"arrow\" className={styles.resourceCard}>\n {card.tag ? (\n <Card.Tokens>\n <Token>{card.tag}</Token>\n </Card.Tokens>\n ) : null}\n <Card.Heading>{card.heading}</Card.Heading>\n <Card.Description>{card.description}</Card.Description>\n </Card>\n </Box>\n </Grid.Column>\n ))}\n </Grid>\n </Box>\n </Box>\n\n <Box\n paddingInlineStart={48}\n paddingInlineEnd={48}\n borderBlockEndWidth=\"thin\"\n borderColor=\"muted\"\n borderStyle=\"solid\"\n >\n <Section>\n <Testimonial variant=\"expressive\" size=\"large\">\n <Testimonial.Quote>\n {content.testimonial.quoteLead} <em>{content.testimonial.quoteEmphasis}</em>{' '}\n {content.testimonial.quoteTrailing}\n </Testimonial.Quote>\n <Testimonial.Link href=\"#\">{content.testimonial.linkText}</Testimonial.Link>\n <Testimonial.Avatar src={monaAvatar} alt={content.testimonial.avatarAlt} />\n <Testimonial.Name position={content.testimonial.position}>{content.testimonial.name}</Testimonial.Name>\n </Testimonial>\n </Section>\n </Box>\n\n <Box borderBlockEndWidth=\"thin\" borderColor=\"muted\" borderStyle=\"solid\">\n <Section paddingBlockEnd=\"none\" paddingBlockStart=\"none\">\n <Box\n borderInlineStartWidth=\"thin\"\n borderInlineEndWidth=\"thin\"\n borderColor=\"muted\"\n borderStyle=\"solid\"\n padding={{narrow: 24, regular: 48, wide: 64}}\n >\n <Grid columnGap=\"none\" rowGap=\"none\" enableGutters={false}>\n <Grid.Column span={{xsmall: 12, large: 5}}>\n <SectionIntro>\n <SectionIntro.Heading>{content.riverFootstepsSection.heading}</SectionIntro.Heading>\n <SectionIntro.Link href=\"#\">{content.riverFootstepsSection.linkText}</SectionIntro.Link>\n </SectionIntro>\n </Grid.Column>\n <Grid.Column span={{xsmall: 12, large: 7}}>\n <Grid className={styles.riverFootstepsGrid}>\n {content.riverFootstepsSection.pillars.map((pillar, index) => (\n <Grid.Column key={pillar.heading} span={{xsmall: 12, medium: 6}}>\n <Pillar fullWidth>\n <Pillar.Image\n as=\"picture\"\n src={riverFootstepsMobileImages[index]}\n alt={pillar.imageAlt}\n sources={[{srcset: riverFootstepsImages[index], media: '(min-width: 48rem)'}]}\n className={styles.riverFootstepsImage}\n />\n <Pillar.Heading>{pillar.heading}</Pillar.Heading>\n <Pillar.Link href=\"#\">{pillar.linkText}</Pillar.Link>\n </Pillar>\n </Grid.Column>\n ))}\n </Grid>\n </Grid.Column>\n </Grid>\n </Box>\n </Section>\n </Box>\n\n <Section paddingBlockStart=\"condensed\" paddingBlockEnd=\"condensed\">\n <SectionIntro align=\"center\" fullWidth>\n <SectionIntro.Heading>{content.resources.heading}</SectionIntro.Heading>\n </SectionIntro>\n </Section>\n\n <Box className={styles.cardGridFrame} marginBlockEnd={80}>\n <Box className={styles.cardGridContent}>\n <Grid columnGap=\"none\" rowGap=\"none\" enableGutters={false}>\n {content.resources.cards.map(card => (\n <Grid.Column\n key={card.heading}\n span={{xsmall: 12, large: 4}}\n className={clsx(styles.cardGridColumn, styles.cardGridColumnArrowHover)}\n >\n <Box className={styles.cardGridItem}>\n <Card\n href=\"#\"\n fullWidth\n ctaVariant=\"arrow\"\n ctaText={content.common.learnMore}\n className={styles.resourceCard}\n >\n {card.tag ? (\n <Card.Tokens>\n <Token>{card.tag}</Token>\n </Card.Tokens>\n ) : null}\n <Card.Heading>{card.heading}</Card.Heading>\n <Card.Description>{card.description}</Card.Description>\n </Card>\n </Box>\n </Grid.Column>\n ))}\n </Grid>\n </Box>\n </Box>\n\n <Box\n borderBlockStartWidth=\"thin\"\n borderBlockEndWidth=\"thin\"\n borderColor=\"muted\"\n borderStyle=\"solid\"\n marginBlockEnd=\"spacious\"\n >\n <Section paddingBlockEnd=\"none\" paddingBlockStart=\"none\">\n <CTABanner\n leadingComponent={() => (\n <Text>\n <LockIcon size={64} />\n </Text>\n )}\n >\n <CTABanner.Heading>{content.cta.heading}</CTABanner.Heading>\n\n <CTABanner.ButtonGroup>\n <Button>{content.cta.primaryAction}</Button>\n <Button>{content.cta.secondaryAction}</Button>\n </CTABanner.ButtonGroup>\n </CTABanner>\n </Section>\n </Box>\n <Stack justifyContent=\"center\" padding=\"none\">\n <Box borderBlockEndWidth=\"thin\" borderColor=\"muted\" borderStyle=\"solid\">\n <Image src={brandDividerWide} alt=\"\" style={{display: 'block'}} />\n </Box>\n </Stack>\n <RedlineBackground style={{height: 600, display: 'flex', flexDirection: 'column', gap: 'var(--base-size-32)'}}>\n <RedlineBackground\n style={{height: 84, marginTop: 'auto', backgroundColor: 'var(--brand-color-border-default)'}}\n />\n </RedlineBackground>\n </Box>\n )\n}"
|
|
10065
|
+
}
|
|
9963
10066
|
]
|
|
9964
10067
|
}
|
package/dist/logger.d.ts
CHANGED
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
* protocol stream (JSON-RPC over stdio), so an accidental `console.log` there would corrupt
|
|
4
4
|
* the transport. Keep this the only logging surface in the server.
|
|
5
5
|
*/
|
|
6
|
-
export
|
|
6
|
+
export type Logger = {
|
|
7
7
|
debug(message: string): void;
|
|
8
8
|
info(message: string): void;
|
|
9
9
|
warn(message: string): void;
|
|
10
10
|
error(message: string): void;
|
|
11
|
-
}
|
|
11
|
+
};
|
|
12
12
|
export declare function createLogger(enabled?: boolean): Logger;
|
package/dist/review/rules.js
CHANGED
|
@@ -71,6 +71,32 @@ const invalidPropValue = {
|
|
|
71
71
|
return findings;
|
|
72
72
|
},
|
|
73
73
|
};
|
|
74
|
+
const invalidPropComboMap = [
|
|
75
|
+
// prevent align="center" + variant="gridline-expressive" beig used in Hero
|
|
76
|
+
{
|
|
77
|
+
component: 'Hero',
|
|
78
|
+
when: { prop: 'variant', value: 'gridline-expressive' },
|
|
79
|
+
disallow: { prop: 'align', value: 'center' },
|
|
80
|
+
message: 'The `Hero` `gridline-expressive` variant is always start-aligned; `align="center"` is unsupported and will be ignored — remove it (the default `align="start"` is correct).',
|
|
81
|
+
},
|
|
82
|
+
];
|
|
83
|
+
const invalidPropCombination = {
|
|
84
|
+
id: 'invalid-prop-combination',
|
|
85
|
+
run(code) {
|
|
86
|
+
const hasAttribute = (tag, prop, value) => new RegExp(`\\b${escapeRegExp(prop)}=["']${escapeRegExp(value)}["']`).test(tag);
|
|
87
|
+
const findings = [];
|
|
88
|
+
for (const constraint of invalidPropComboMap) {
|
|
89
|
+
for (const usage of componentUsage(code, constraint.component)) {
|
|
90
|
+
const tag = usage[0];
|
|
91
|
+
if (hasAttribute(tag, constraint.when.prop, constraint.when.value) &&
|
|
92
|
+
hasAttribute(tag, constraint.disallow.prop, constraint.disallow.value)) {
|
|
93
|
+
findings.push({ severity: 'error', rule: this.id, message: constraint.message, evidence: evidence(tag) });
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return findings;
|
|
98
|
+
},
|
|
99
|
+
};
|
|
74
100
|
const RAW_HTML_PATTERNS = [
|
|
75
101
|
{
|
|
76
102
|
id: 'raw-form-elements',
|
|
@@ -227,6 +253,7 @@ export function brandComponentsUsed(code, catalog) {
|
|
|
227
253
|
export const allRules = [
|
|
228
254
|
unknownSubcomponents,
|
|
229
255
|
invalidPropValue,
|
|
256
|
+
invalidPropCombination,
|
|
230
257
|
rawHtml,
|
|
231
258
|
hardcodedValues,
|
|
232
259
|
offBrandTells,
|
package/dist/review/rules.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rules.js","sourceRoot":"","sources":["../../src/review/rules.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"rules.js","sourceRoot":"","sources":["../../src/review/rules.ts"],"names":[],"mappings":"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"}
|
package/dist/review/types.d.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import type { Catalog } from '../catalog/types.js';
|
|
2
2
|
export type Severity = 'error' | 'warning';
|
|
3
|
-
export
|
|
3
|
+
export type Finding = {
|
|
4
4
|
severity: Severity;
|
|
5
5
|
rule: string;
|
|
6
6
|
message: string;
|
|
7
7
|
/** A short snippet of the offending source, for context. */
|
|
8
8
|
evidence?: string;
|
|
9
|
-
}
|
|
10
|
-
export
|
|
9
|
+
};
|
|
10
|
+
export type Rule = {
|
|
11
11
|
id: string;
|
|
12
12
|
run(code: string, catalog: Catalog): Finding[];
|
|
13
|
-
}
|
|
13
|
+
};
|
|
14
14
|
/** Trim a matched snippet so findings stay compact in the agent's context. */
|
|
15
15
|
export declare function evidence(snippet: string, max?: number): string;
|
package/dist/server.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { readFileSync } from 'node:fs';
|
|
2
2
|
import { fileURLToPath } from 'node:url';
|
|
3
3
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
4
|
+
import { detectAssetGenerator } from './brand/detect-asset-generator.js';
|
|
4
5
|
import { createDocsSource } from './brand/docs-source.js';
|
|
5
6
|
import { resolveInstalledAssets } from './brand/resolve-assets.js';
|
|
6
7
|
import { looksLikeProductProject, resolveBrandInstall } from './brand/resolve-install.js';
|
|
7
8
|
import { loadCatalog } from './catalog/load.js';
|
|
8
9
|
import { createLogger } from './logger.js';
|
|
9
10
|
import { registerTools } from './tools/register.js';
|
|
11
|
+
const assetGenerator = detectAssetGenerator();
|
|
10
12
|
const INSTRUCTIONS = `Primer Brand design system tools for building GitHub web-based marketing experiences and landing pages with @primer/react-brand.
|
|
11
13
|
|
|
12
14
|
Use these tools whenever a project builds marketing/landing pages, or depends on the @primer/react-brand design system.
|
|
@@ -16,7 +18,13 @@ use the Primer (product) tools instead.
|
|
|
16
18
|
Typical flow: primer_brand_setup once at the start of a new page or project, primer_brand_examples to start
|
|
17
19
|
from correct patterns, primer_brand_component for exact props, primer_brand_tokens / primer_brand_asset for tokens and
|
|
18
20
|
icons, primer_brand_docs for guidance, and primer_brand_review as the final gate over your complete output (JSX and
|
|
19
|
-
CSS together) before you finish
|
|
21
|
+
CSS together) before you finish.
|
|
22
|
+
|
|
23
|
+
${assetGenerator.available
|
|
24
|
+
? `Use the GitHub Asset Generator MCP tools (\`asset-generator\`) instead of stock photos or AI art. Use Asset Generator
|
|
25
|
+
for wallpapers, hero or river background images, and product shots.`
|
|
26
|
+
: ''}
|
|
27
|
+
`;
|
|
20
28
|
export function createServer() {
|
|
21
29
|
const logger = createLogger();
|
|
22
30
|
let version = '0.0.0';
|
|
@@ -46,8 +54,11 @@ export function createServer() {
|
|
|
46
54
|
const versions = installedAssets.sources.map(source => `${source.module}@${source.version ?? '?'}`).join(', ');
|
|
47
55
|
logger.info(`resolved icons/illustrations from installed packages: ${versions}`);
|
|
48
56
|
}
|
|
57
|
+
if (detectAssetGenerator().available) {
|
|
58
|
+
logger.info('GitHub Asset Generator MCP server detected; surfacing on-brand imagery guidance');
|
|
59
|
+
}
|
|
49
60
|
const docs = createDocsSource(brand, logger);
|
|
50
|
-
registerTools(server, { catalog, brand, docs, logger, assets, assetsOrigin });
|
|
61
|
+
registerTools(server, { catalog, brand, docs, logger, assets, assetsOrigin, assetGenerator: detectAssetGenerator() });
|
|
51
62
|
return server;
|
|
52
63
|
}
|
|
53
64
|
//# sourceMappingURL=server.js.map
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAC,MAAM,SAAS,CAAA;AACpC,OAAO,EAAC,aAAa,EAAC,MAAM,UAAU,CAAA;AAEtC,OAAO,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAA;AAEjE,OAAO,EAAC,gBAAgB,EAAC,MAAM,wBAAwB,CAAA;AACvD,OAAO,EAAC,sBAAsB,EAAC,MAAM,2BAA2B,CAAA;AAChE,OAAO,EAAC,uBAAuB,EAAE,mBAAmB,EAAC,MAAM,4BAA4B,CAAA;AACvF,OAAO,EAAC,WAAW,EAAC,MAAM,mBAAmB,CAAA;AAC7C,OAAO,EAAC,YAAY,EAAC,MAAM,aAAa,CAAA;AACxC,OAAO,EAAC,aAAa,EAAC,MAAM,qBAAqB,CAAA;AAEjD,MAAM,YAAY,GAAG
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,7 +8,7 @@ const inputSchema = z.object({
|
|
|
8
8
|
.describe('Restrict to Octicons ("icon") or Octovisuals ("illustration").'),
|
|
9
9
|
limit: z.number().int().min(1).max(50).optional().default(12).describe('Max results.'),
|
|
10
10
|
});
|
|
11
|
-
const description = `Find approved Primer Brand visuals as code imports: Octicons (@primer/octicons-react) and Octovisuals (@primer/octovisuals-react). Use these instead of emoji, clip art, or random icon sets
|
|
11
|
+
const description = `Find approved Primer Brand visuals as code imports: Octicons (@primer/octicons-react) and Octovisuals (@primer/octovisuals-react). Use these instead of emoji, clip art, or random icon sets - mismatched or emoji icons are off-brand.`;
|
|
12
12
|
export const primerBrandAssetTool = {
|
|
13
13
|
name: 'primer_brand_asset',
|
|
14
14
|
title: 'Primer Brand icons & illustrations',
|
|
@@ -26,10 +26,19 @@ export const primerBrandAssetTool = {
|
|
|
26
26
|
if (input.kind) {
|
|
27
27
|
assets = assets.filter(asset => asset.kind === input.kind);
|
|
28
28
|
}
|
|
29
|
+
const brandImages = ctx.assetGenerator.available
|
|
30
|
+
? `Use the GitHub Asset Generator MCP tools (\`asset-generator\`) instead of stock photos or AI art. Check images suit usage first. `
|
|
31
|
+
: '';
|
|
29
32
|
const ranked = rank(input.query, assets, asset => [asset.name]).map(entry => entry.item);
|
|
30
33
|
if (ranked.length === 0) {
|
|
31
34
|
return {
|
|
32
|
-
text:
|
|
35
|
+
text: [
|
|
36
|
+
`No ${input.kind ?? 'asset'} matched "${input.query}". Try a simpler term (e.g. "arrow", "check", "shield").`,
|
|
37
|
+
origin,
|
|
38
|
+
brandImages,
|
|
39
|
+
]
|
|
40
|
+
.filter(Boolean)
|
|
41
|
+
.join('\n\n'),
|
|
33
42
|
};
|
|
34
43
|
}
|
|
35
44
|
const shown = ranked.slice(0, input.limit);
|
|
@@ -37,7 +46,7 @@ export const primerBrandAssetTool = {
|
|
|
37
46
|
const lines = shown
|
|
38
47
|
.map(asset => `- \`${asset.name}\` _(${asset.kind})_ — \`import {${asset.name}} from '${asset.module}'\``)
|
|
39
48
|
.join('\n');
|
|
40
|
-
return { text: `${lines}${more}\n\n
|
|
49
|
+
return { text: [`${lines}${more}`, origin, brandImages].filter(Boolean).join('\n\n') };
|
|
41
50
|
},
|
|
42
51
|
};
|
|
43
52
|
//# sourceMappingURL=primer-brand-asset.js.map
|