Skip to content

Commit 3c49d5b

Browse files
Bill LeoutsakosBill Leoutsakos
authored andcommitted
fix: exclude repository artwork from designer notifications
1 parent 7613e12 commit 3c49d5b

9 files changed

Lines changed: 67 additions & 8 deletions

File tree

design-diff.config.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,26 @@
88
"(?:^|/)sandbox/bundles/"
99
],
1010
"mediaModules": ["lucide-react", "react-icons", "next/image", "next/legacy/image"],
11+
"mediaSources": [
12+
"^(?:apps/sim/lib/og/|apps/sim/app/\\(landing\\)/og-utils\\.tsx$|apps/docs/app/api/og/)",
13+
"(?:^|/)(?:opengraph|twitter)-image\\.[jt]sx?$",
14+
"^apps/sim/app/\\(landing\\)/components/hero/components/(?:hero-platform-(?:loop|stage|intro)|hero-visual|hero-chat-loop)/",
15+
"^apps/sim/app/\\(landing\\)/components/features/components/captured-platform-surface\\.tsx$",
16+
"^apps/sim/app/\\(landing\\)/components/footer/components/footer-wordmark-loop/"
17+
],
18+
"mediaSymbols": [
19+
{
20+
"file": "/components/resource-empty-state/",
21+
"names": [
22+
"LogsGraphic",
23+
"TablesGraphic",
24+
"FilesGraphic",
25+
"DocumentsGraphic",
26+
"KnowledgeIsoMark",
27+
"BoreInterior"
28+
]
29+
}
30+
],
1131
"renderedMarkdown": ["apps/docs/content/", "apps/sim/content/"],
1232
"aliases": [
1333
{

scripts/design-diff/README.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,10 @@ Changing an existing control's supported `variant`, `size`, classes or style val
5252
Known style values in conditional branches and React state updates are compared; changing
5353
only the runtime predicate, handler or label does not qualify.
5454

55-
Media exclusion applies to recognized JSX/HTML/MDX media elements and asset files, not an
56-
arbitrary wrapper around an image. A wrapper's custom padding or layout still qualifies.
55+
Media exclusion applies to recognized JSX/HTML/MDX media elements and asset files. Repository
56+
conventions also identify social-card image generators, landing artwork and the named illustration
57+
functions inside empty-state components. Their surrounding product controls remain in scope.
58+
The policy does not treat an arbitrary wrapper around an image as media. A wrapper's custom padding or layout still qualifies.
5759
CSS asset URL substitutions and generated copy are exempt. Source-only analysis cannot
5860
reliably identify every project-specific media wrapper.
5961

@@ -101,7 +103,7 @@ an Icon does not break resolution of Button through the same barrel.
101103

102104
## Report contract
103105

104-
Schema **3.0.0**, engine **0.5.1**, policy **5.0.0**. The schema remains compatible; the policy
106+
Schema **3.0.0**, engine **0.5.2**, policy **5.0.0**. The schema remains compatible; the policy
105107
meaning changes. Readers must inspect versions when comparing historical qualification rates.
106108
All decisions and identifiers are deterministic for the same engine/configuration and commits.
107109
Execution timing and peak memory are recorded separately by the benchmark, never in engine JSON.

scripts/design-diff/analyze.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import type { Change, Config, Definition, Report } from '#design-diff/types'
2424
export function emptyReport(): Report {
2525
return {
2626
schemaVersion: '3.0.0',
27-
engineVersion: '0.5.1',
27+
engineVersion: '0.5.2',
2828
policyVersion: '5.0.0',
2929
commits: null,
3030
status: 'failed',
@@ -138,6 +138,7 @@ export async function analyze(
138138
tailwind: TailwindNormalizer,
139139
file: string
140140
): Promise<Definition[]> => {
141+
if (config.mediaSources?.some((pattern) => new RegExp(pattern).test(file))) return []
141142
const resolver = new Resolver(tree, affected)
142143
const entry = tree.entries.get(file)
143144
if (!entry) return []

scripts/design-diff/benchmark.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ export async function benchmark(args = process.argv.slice(2)): Promise<void> {
205205
result.reportSha256 = hash(bytes)
206206
if (
207207
report.schemaVersion !== '3.0.0' ||
208-
report.engineVersion !== '0.5.1' ||
208+
report.engineVersion !== '0.5.2' ||
209209
report.policyVersion !== '5.0.0'
210210
)
211211
throw new Error('Report version mismatch')

scripts/design-diff/extract/documents.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ export function extractDocument(
184184
typeof item !== 'object' ||
185185
Array.isArray(item) ||
186186
typeof item.name !== 'string' ||
187-
(content && content.contentProps.includes(item.name)) ||
187+
content?.contentProps.includes(item.name) ||
188188
!appearanceAttributes.test(item.name)
189189
)
190190
continue

scripts/design-diff/extract/tsx.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ export function extractTsx(resolver: Resolver, file: string, appearanceOnly = fa
3535
return false
3636
}
3737
const media = (path: NodePath): boolean => {
38+
if (
39+
resolver.tree.config.mediaSymbols?.some(
40+
(entry) => new RegExp(entry.file).test(file) && entry.names.includes(symbolName(path))
41+
)
42+
)
43+
return true
3844
for (let node: NodePath | null = path; node; node = node.parentPath) {
3945
if (!node.isJSXElement()) continue
4046
const name = propertyName(node.node.openingElement.name)
@@ -309,6 +315,7 @@ export function extractTsx(resolver: Resolver, file: string, appearanceOnly = fa
309315
emit(path, 'content', 'expression', resolver.evaluate(child(path, 'expression'), file))
310316
},
311317
CallExpression(path) {
318+
if (appearanceOnly && media(path)) return
312319
const name = propertyName(path.node.callee)
313320
if (resolver.tree.config.variantFunctions.includes(name))
314321
emit(path, 'class', 'variants', resolver.evaluate(path, file))

scripts/design-diff/tests/appearance-policy.test.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,4 +170,31 @@ describe('designer notification policy', () => {
170170
.flagged
171171
).toBe(false)
172172
})
173+
174+
it.each([
175+
'apps/sim/lib/og/cover-image.tsx',
176+
'apps/sim/app/(landing)/components/hero/components/hero-platform-loop/stage.tsx',
177+
])('exempts configured code-rendered artwork: %s', async (art) => {
178+
expect(
179+
(
180+
await compareFiles(
181+
{ [art]: 'export const Art=()=> <div className="p-2"/>' },
182+
{ [art]: 'export const Art=()=> <div className="p-4"/>' }
183+
)
184+
).flagged
185+
).toBe(false)
186+
})
187+
188+
it('exempts an empty-state illustration while retaining surrounding UI styling', async () => {
189+
const art =
190+
'apps/sim/app/workspace/id/components/resource/components/resource-empty-state/logs-empty-state.tsx'
191+
const source = (graphic: string, padding: string) =>
192+
`function LogsGraphic(){return <div className="${graphic}"/>};export function LogsEmptyState(){return <main className="${padding}"><LogsGraphic/></main>}`
193+
expect(
194+
(await compareFiles({ [art]: source('p-2', 'p-2') }, { [art]: source('p-4', 'p-2') })).flagged
195+
).toBe(false)
196+
expect(
197+
(await compareFiles({ [art]: source('p-2', 'p-2') }, { [art]: source('p-2', 'p-4') })).flagged
198+
).toBe(true)
199+
})
173200
})

scripts/design-diff/tests/report.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ it('detects changes after a preview and produces byte-identical bounded reports'
4141
it('keeps failures distinguishable after serialization', () => {
4242
expect(JSON.parse(serializeReport(emptyReport()))).toMatchObject({
4343
schemaVersion: '3.0.0',
44-
engineVersion: '0.5.1',
44+
engineVersion: '0.5.2',
4545
policyVersion: '5.0.0',
4646
status: 'failed',
4747
flagged: null,

scripts/design-diff/types.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ export interface UsageCount {
8282
export interface Config {
8383
sourceRoots: string[]
8484
mediaModules?: string[]
85+
mediaSources?: string[]
86+
mediaSymbols?: { file: string; names: string[] }[]
8587
exclude: string[]
8688
renderedMarkdown: string[]
8789
aliases: { from: string; prefix: string; target: string }[]
@@ -124,7 +126,7 @@ export interface Config {
124126
}
125127
export interface Report {
126128
schemaVersion: '3.0.0'
127-
engineVersion: '0.5.1'
129+
engineVersion: '0.5.2'
128130
policyVersion: '5.0.0'
129131
commits: { base: string; head: string; mergeBase: string } | null
130132
status: 'completed' | 'failed'

0 commit comments

Comments
 (0)