brand-intent 0.33.0 → 0.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brand-intent",
3
- "version": "0.33.0",
3
+ "version": "0.35.0",
4
4
  "description": "An open file format specification for making brand intent machine-readable.",
5
5
  "author": "Christophe Stoll <christophe@stoll.studio>",
6
6
  "license": "MIT",
@@ -138,6 +138,8 @@ export interface ParsedPhotoLookDef {
138
138
  duotone?: { shadow: string; highlight: string };
139
139
  /** Keys the person cannot change. All others are starting values. */
140
140
  fixed: PhotoLookKey[];
141
+ /** Darkest a gradient under light text on a photo may get, 0..100 (%). Absent → no scrim. */
142
+ scrim?: number;
141
143
  }
142
144
 
143
145
  export interface ParsedCameraDef {
@@ -1973,7 +1975,7 @@ export function parseBrandFile(content: string, fileName: string): ParsedBrand {
1973
1975
  if (photoLookDeclared) {
1974
1976
  const keys: PhotoLookKey[] = ['saturation', 'contrast', 'warmth', 'fade', 'mono', 'duotone'];
1975
1977
  for (const [key, { line }] of Object.entries(photoLookRaw)) {
1976
- if (key !== 'fixed' && !keys.includes(key as PhotoLookKey)) throw new Error(`${fileName}:${line}: unknown photo-look property "${key}"`);
1978
+ if (key !== 'fixed' && key !== 'scrim' && !keys.includes(key as PhotoLookKey)) throw new Error(`${fileName}:${line}: unknown photo-look property "${key}"`);
1977
1979
  }
1978
1980
  const int = (key: string, min: number, max: number): number => {
1979
1981
  const p = photoLookRaw[key];
@@ -2021,6 +2023,14 @@ export function parseBrandFile(content: string, fileName: string): ParsedBrand {
2021
2023
  look.fixed.push(key as PhotoLookKey);
2022
2024
  }
2023
2025
  }
2026
+ const scrim = photoLookRaw['scrim'];
2027
+ if (scrim) {
2028
+ const m = /^(\d+)%$/.exec(scrim.value);
2029
+ if (!m || Number(m[1]) < 1 || Number(m[1]) > 100) {
2030
+ throw new Error(`${fileName}:${scrim.line}: photo-look scrim must be a percentage from 1% to 100%, got "${scrim.value}"`);
2031
+ }
2032
+ look.scrim = Number(m[1]);
2033
+ }
2024
2034
  result.photoLook = look;
2025
2035
  }
2026
2036
 
@@ -43,6 +43,8 @@ export interface ParsedPurpose {
43
43
  camera?: boolean;
44
44
  /** `camera: front | rear` — overrides the brand's camera facing for this purpose. */
45
45
  cameraFacing?: 'front' | 'rear';
46
+ /** `scrim: none`: no scrim under this purpose's text, whatever the brand declares. */
47
+ scrim?: 'none';
46
48
  /** `framing: <id>` — the brand framing module photos for this purpose are shot in. */
47
49
  framing?: string;
48
50
  /** `goal: <id>` — the identity goal this purpose serves by default. */
@@ -183,6 +185,7 @@ export function parsePurposeFile(content: string, fileName: string): ParsedPurpo
183
185
  let illustrations: string[] | undefined;
184
186
  let camera: boolean | undefined;
185
187
  let cameraFacing: 'front' | 'rear' | undefined;
188
+ let scrim: 'none' | undefined;
186
189
  let framing: string | undefined;
187
190
  let goal: string | undefined;
188
191
  let analyze: boolean | undefined;
@@ -442,6 +445,14 @@ export function parsePurposeFile(content: string, fileName: string): ParsedPurpo
442
445
  continue;
443
446
  }
444
447
 
448
+ // No scrim for this purpose
449
+ if (line.startsWith('scrim:')) {
450
+ const value = line.slice(6).trim();
451
+ if (value !== 'none') throw new Error(`${fileName}:${lineNum}: invalid scrim "${value}" (expected none; how dark is the brand's photo-look scrim)`);
452
+ scrim = 'none';
453
+ continue;
454
+ }
455
+
445
456
  // Camera control
446
457
  if (line.startsWith('camera:')) {
447
458
  const value = line.slice(7).trim();
@@ -832,7 +843,7 @@ export function parsePurposeFile(content: string, fileName: string): ParsedPurpo
832
843
 
833
844
  const parsedExamples = resolveExamples(examples, slots, legacySamplesLine, fileName, warnings);
834
845
 
835
- return { id, name, description, preferredCompositions: compositions, slots, density, palette, scope, context, voice, defaultLogo, defaultPhoto, defaultVideo, illustrations, camera, cameraFacing, framing, goal, analyze, defaultIcon, bgPrompt, examples: parsedExamples, warnings };
846
+ return { id, name, description, preferredCompositions: compositions, slots, density, palette, scope, context, voice, defaultLogo, defaultPhoto, defaultVideo, illustrations, camera, cameraFacing, ...(scrim ? { scrim } : {}), framing, goal, analyze, defaultIcon, bgPrompt, examples: parsedExamples, warnings };
836
847
  }
837
848
 
838
849
  /** Validate `example` blocks against the declared slots, or build examples from deprecated slot
@@ -40,6 +40,8 @@ export interface ParsedStory {
40
40
  format: string;
41
41
  /** Story topic: what the whole story is about, one sentence. */
42
42
  topic?: string;
43
+ /** `scrim: none`: no scrim under the story's text, whatever the brand and purposes declare. */
44
+ scrim?: 'none';
43
45
  pages: ParsedStoryPage[];
44
46
  /** Example fills for the open slots, one story topic each. */
45
47
  examples: ParsedStoryExample[];
@@ -93,6 +95,7 @@ export function parseStoryFile(content: string, fileName: string): ParsedStory {
93
95
  let description = '';
94
96
  let format = '';
95
97
  let topic: string | undefined;
98
+ let scrim: 'none' | undefined;
96
99
  const pages: (ParsedStoryPage & { line: number; keys: Set<string> })[] = [];
97
100
  const examples: (ParsedStoryExample & { line: number })[] = [];
98
101
 
@@ -200,6 +203,11 @@ export function parseStoryFile(content: string, fileName: string): ParsedStory {
200
203
  else topic = value;
201
204
  continue;
202
205
  }
206
+ if (key === 'scrim') {
207
+ if (value !== 'none') throw new Error(`${fileName}:${lineNum}: invalid scrim "${value}" (expected none; how dark is the brand's photo-look scrim)`);
208
+ scrim = 'none';
209
+ continue;
210
+ }
203
211
  throw new Error(`${fileName}:${lineNum}: unexpected "${line}"`);
204
212
  }
205
213
 
@@ -279,6 +287,7 @@ export function parseStoryFile(content: string, fileName: string): ParsedStory {
279
287
  description,
280
288
  format,
281
289
  topic,
290
+ ...(scrim ? { scrim } : {}),
282
291
  pages: pages.map(({ line: _line, keys: _keys, ...p }) => p),
283
292
  examples: examples.map(({ line: _line, ...ex }) => ({
284
293
  ...ex,
@@ -117,7 +117,7 @@
117
117
  }
118
118
  },
119
119
  "camera-field": {
120
- "match": "^(camera:)\\s+(true|false|front|rear)",
120
+ "match": "^(camera:|scrim:)\\s+(true|false|front|rear|none)",
121
121
  "captures": {
122
122
  "1": { "name": "keyword.control.brand-intent-purpose" },
123
123
  "2": { "name": "constant.language.brand-intent-purpose" }
@@ -265,7 +265,7 @@
265
265
  "comment": "Fallback: color the keyword token on incomplete lines (while typing)",
266
266
  "patterns": [
267
267
  {
268
- "match": "^(id:|name:|compositions:|density:|defaultIcon:|scope|voice|palette:|logo:|photo:|video:|illustration:|camera:|framing:|goal:|analyze:|bg-prompt:|context|slot|example)(?=\\s|$)",
268
+ "match": "^(id:|name:|compositions:|density:|defaultIcon:|scope|voice|palette:|logo:|photo:|video:|illustration:|camera:|scrim:|framing:|goal:|analyze:|bg-prompt:|context|slot|example)(?=\\s|$)",
269
269
  "captures": {
270
270
  "1": { "name": "keyword.control.brand-intent-purpose" }
271
271
  }
@@ -17,7 +17,7 @@
17
17
  "name": "comment.line.number-sign.brand-intent-story"
18
18
  },
19
19
  "top-field": {
20
- "match": "^(id:|format:)\\s+(.*)",
20
+ "match": "^(id:|format:|scrim:)\\s+(.*)",
21
21
  "captures": {
22
22
  "1": { "name": "keyword.control.brand-intent-story" },
23
23
  "2": { "name": "entity.name.type.brand-intent-story" }
@@ -60,7 +60,7 @@
60
60
  "comment": "Fallback: color the keyword token on incomplete lines (while typing)",
61
61
  "patterns": [
62
62
  {
63
- "match": "^(id:|name:|format:|topic:|page|example)(?=\\s|$)",
63
+ "match": "^(id:|name:|format:|topic:|scrim:|page|example)(?=\\s|$)",
64
64
  "captures": {
65
65
  "1": { "name": "keyword.control.brand-intent-story" }
66
66
  }