@navipartner/demo-video 0.5.0 → 0.6.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/README.md +102 -105
- package/bin/args.d.mts +0 -3
- package/bin/args.mjs +1 -5
- package/bin/demo-video.mjs +5 -7
- package/bin/init.mjs +5 -10
- package/bin/pick.d.mts +1 -3
- package/bin/pick.mjs +65 -118
- package/bin/pitch.mjs +1 -1
- package/dist/{adapter-D_iU2dh2.d.ts → adapter-CDOXdUZI.d.ts} +0 -7
- package/dist/{chunk-BYAFDWPA.js → chunk-D7UYGNSF.js} +5 -66
- package/dist/index.d.ts +2 -6
- package/dist/index.js +1 -1
- package/dist/runner/index.d.ts +1 -1
- package/dist/runner/index.js +13 -13
- package/package.json +1 -1
- package/skills/np-demo-video/SKILL.md +47 -107
- package/skills/np-demo-video/linear.md +116 -0
- package/skills/np-demo-video/look.md +2 -4
- package/skills/np-demo-video/reference.md +8 -15
- package/skills/np-demo-video/pitch.md +0 -99
package/bin/pick.mjs
CHANGED
|
@@ -1,27 +1,23 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
1
|
import path from "node:path";
|
|
3
|
-
import { fileURLToPath } from "node:url";
|
|
4
2
|
|
|
5
3
|
import { listStories } from "./args.mjs";
|
|
6
4
|
|
|
7
5
|
// `demo-video pick`: turns a `/demo-video …` request into one of the
|
|
8
|
-
// already-made stories
|
|
9
|
-
//
|
|
6
|
+
// already-made stories. No AI and nothing written: stories are a developer's
|
|
7
|
+
// to make (locally, with the skill); a request only chooses. Every video is
|
|
8
|
+
// in NaviPartner's brand: a customer's is researched by @Linear for one video
|
|
9
|
+
// (the skill's linear.md), never kept in a repo.
|
|
10
10
|
//
|
|
11
|
-
// /demo-video
|
|
12
|
-
// /demo-video help
|
|
13
|
-
// /demo-video checkout
|
|
14
|
-
// /demo-video
|
|
11
|
+
// /demo-video → the primary story (one app)
|
|
12
|
+
// /demo-video help → the menu
|
|
13
|
+
// /demo-video checkout → story "checkout"
|
|
14
|
+
// /demo-video checkout in danish → its translation "checkout-da"
|
|
15
|
+
// /demo-video retail checkout → the app whose folder says retail
|
|
15
16
|
//
|
|
16
17
|
// Anything it can't settle on one story is answered with the menu.
|
|
17
18
|
|
|
18
|
-
const engineDir = path.resolve(
|
|
19
|
-
path.dirname(fileURLToPath(import.meta.url)),
|
|
20
|
-
"..",
|
|
21
|
-
);
|
|
22
|
-
|
|
23
19
|
const STOP = new Set(
|
|
24
|
-
"a an and as at by for from in into make me of on or our please show story the this to video with branding brand marketing demo film render".split(
|
|
20
|
+
"a an and as at by for from in into make me of on or our please show story the this to video with branding brand marketing demo film render navipartner på".split(
|
|
25
21
|
" ",
|
|
26
22
|
),
|
|
27
23
|
);
|
|
@@ -31,44 +27,46 @@ const words = (text) =>
|
|
|
31
27
|
(w) => [w, ...(w.includes("-") ? w.split("-") : [])],
|
|
32
28
|
);
|
|
33
29
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
30
|
+
// A translation is a story named for its language (checkout-da): "danish"
|
|
31
|
+
// and "dansk" say its "da" too.
|
|
32
|
+
const languageNames = (part) => {
|
|
33
|
+
if (!/^[a-z]{2}$/.test(part)) {
|
|
34
|
+
return [];
|
|
35
|
+
}
|
|
36
|
+
try {
|
|
37
|
+
return [
|
|
38
|
+
new Intl.DisplayNames(["en"], { type: "language" }).of(part),
|
|
39
|
+
new Intl.DisplayNames([part], { type: "language" }).of(part),
|
|
40
|
+
]
|
|
41
|
+
.filter((name) => name && name.toLowerCase() !== part)
|
|
42
|
+
.map((name) => name.toLowerCase());
|
|
43
|
+
} catch {
|
|
44
|
+
return [];
|
|
45
|
+
}
|
|
49
46
|
};
|
|
50
47
|
|
|
51
|
-
/** What an app offers: its stories
|
|
48
|
+
/** What an app offers: its stories. */
|
|
52
49
|
export const appMenu = (appDir) => ({
|
|
53
50
|
dir: appDir,
|
|
54
51
|
name: path.basename(appDir),
|
|
55
52
|
stories: listStories(path.join(appDir, "demo")),
|
|
56
|
-
brands: [
|
|
57
|
-
...new Set([
|
|
58
|
-
...brandNames(adapterBrandsDir(appDir)),
|
|
59
|
-
...brandNames(path.join(engineDir, "brands")),
|
|
60
|
-
]),
|
|
61
|
-
],
|
|
62
53
|
});
|
|
63
54
|
|
|
55
|
+
const LINEAR =
|
|
56
|
+
"A customer's branding isn't kept in a repo: in Linear, ask @Linear for the video, and it researches their brand for that one video.";
|
|
57
|
+
|
|
64
58
|
/**
|
|
65
|
-
* Picks from `apps` (appMenu results). Returns { app, story
|
|
66
|
-
*
|
|
59
|
+
* Picks from `apps` (appMenu results). Returns { app, story } or
|
|
60
|
+
* { menu: true, reason }.
|
|
67
61
|
*/
|
|
68
62
|
export const pick = (request, apps) => {
|
|
69
63
|
// A bare /demo-video films the primary story; this asks what there is.
|
|
70
64
|
if (/^\s*(help|menu|list)\s*$/i.test(request)) {
|
|
71
|
-
return { menu: true, reason: "The stories
|
|
65
|
+
return { menu: true, reason: "The stories:" };
|
|
66
|
+
}
|
|
67
|
+
const branded = /(?:^|\s)in\s+([\w-]+)\s+brand(?:ing)?\b/i.exec(request);
|
|
68
|
+
if (branded && branded[1].toLowerCase() !== "navipartner") {
|
|
69
|
+
return { menu: true, reason: LINEAR };
|
|
72
70
|
}
|
|
73
71
|
return pickStory(request, apps);
|
|
74
72
|
};
|
|
@@ -76,22 +74,10 @@ export const pick = (request, apps) => {
|
|
|
76
74
|
const pickStory = (request, apps) => {
|
|
77
75
|
const said = words(request);
|
|
78
76
|
const has = (word) => said.includes(word.toLowerCase());
|
|
77
|
+
const saysPart = (part) => has(part) || languageNames(part).some(has);
|
|
79
78
|
|
|
80
|
-
//
|
|
81
|
-
const
|
|
82
|
-
const brands = allBrands.filter(has);
|
|
83
|
-
if (brands.length > 1) {
|
|
84
|
-
return {
|
|
85
|
-
menu: true,
|
|
86
|
-
reason: `Name one brand, not ${brands.join(" and ")}.`,
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
const brand = brands[0] ?? null;
|
|
90
|
-
|
|
91
|
-
// What's left of the request once the brand and filler are gone.
|
|
92
|
-
const content = said.filter(
|
|
93
|
-
(w) => !STOP.has(w) && !brands.includes(w) && !/^\d+$/.test(w),
|
|
94
|
-
);
|
|
79
|
+
// What's left of the request once the filler is gone.
|
|
80
|
+
const content = said.filter((w) => !STOP.has(w) && !/^\d+$/.test(w));
|
|
95
81
|
|
|
96
82
|
// The app: named by its folder, else by a part of it no other app's
|
|
97
83
|
// folder has ("retail", not "self"), else the only one.
|
|
@@ -114,23 +100,18 @@ const pickStory = (request, apps) => {
|
|
|
114
100
|
}
|
|
115
101
|
}
|
|
116
102
|
|
|
117
|
-
// Score every story: its name (or
|
|
103
|
+
// Score every story: its name (or its parts) said outright counts most,
|
|
118
104
|
// then words shared with its description.
|
|
119
|
-
// Variants aren't scored: the base story plus the brand finds them.
|
|
120
105
|
const scored = candidates.flatMap((app) =>
|
|
121
|
-
app.stories
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
(w) => w.length > 2 && description.has(w),
|
|
131
|
-
).length;
|
|
132
|
-
return { app, story, score };
|
|
133
|
-
}),
|
|
106
|
+
app.stories.map((story) => {
|
|
107
|
+
const nameParts = story.name.split("-");
|
|
108
|
+
// "checkout express" says the story checkout-express in full.
|
|
109
|
+
let score = has(story.name) || nameParts.every(saysPart) ? 10 : 0;
|
|
110
|
+
score += nameParts.filter(saysPart).length * 3;
|
|
111
|
+
const description = new Set(words(story.description ?? ""));
|
|
112
|
+
score += content.filter((w) => w.length > 2 && description.has(w)).length;
|
|
113
|
+
return { app, story, score };
|
|
114
|
+
}),
|
|
134
115
|
);
|
|
135
116
|
const best = Math.max(0, ...scored.map((s) => s.score));
|
|
136
117
|
const top = scored.filter((s) => s.score === best);
|
|
@@ -147,7 +128,7 @@ const pickStory = (request, apps) => {
|
|
|
147
128
|
.map((app) => ({ app, story: app.stories.find((s) => s.primary) }))
|
|
148
129
|
.filter((p) => p.story);
|
|
149
130
|
if (noFeature && candidates.length === 1 && primaries.length === 1) {
|
|
150
|
-
return
|
|
131
|
+
return { app: primaries[0].app.dir, story: primaries[0].story.name };
|
|
151
132
|
}
|
|
152
133
|
return {
|
|
153
134
|
menu: true,
|
|
@@ -163,24 +144,7 @@ const pickStory = (request, apps) => {
|
|
|
163
144
|
reason: `That matches ${top.map((t) => `\`${t.story.name}\``).join(", ")}. Pick one by name:`,
|
|
164
145
|
};
|
|
165
146
|
}
|
|
166
|
-
return
|
|
167
|
-
};
|
|
168
|
-
|
|
169
|
-
// The brand must be one the chosen app has: another app's brand would fail
|
|
170
|
-
// at render time with a worse message. A story with a variant for that brand
|
|
171
|
-
// (checkout + acme → checkout.acme) films the variant: its words are the
|
|
172
|
-
// customer's.
|
|
173
|
-
const withBrand = (app, story, brand) => {
|
|
174
|
-
if (brand && !app.brands.includes(brand)) {
|
|
175
|
-
return {
|
|
176
|
-
menu: true,
|
|
177
|
-
reason: `No brand \`${brand}\` in ${app.name}. Pick one:`,
|
|
178
|
-
apps: [app],
|
|
179
|
-
};
|
|
180
|
-
}
|
|
181
|
-
const variant =
|
|
182
|
-
brand && app.stories.find((s) => s.extends === story && s.brand === brand);
|
|
183
|
-
return { app: app.dir, story: variant ? variant.name : story, brand };
|
|
147
|
+
return { app: top[0].app.dir, story: top[0].story.name };
|
|
184
148
|
};
|
|
185
149
|
|
|
186
150
|
/** The menu as Markdown, for the PR reply. */
|
|
@@ -191,36 +155,30 @@ export const menuMarkdown = (apps, reason) => {
|
|
|
191
155
|
if (app.stories.length === 0) {
|
|
192
156
|
lines.push("- no stories yet");
|
|
193
157
|
}
|
|
194
|
-
for (const s of app.stories
|
|
158
|
+
for (const s of app.stories) {
|
|
195
159
|
lines.push(
|
|
196
160
|
`- \`${s.name}\`${s.primary ? " (primary)" : ""}${s.description ? `: ${s.description}` : ""}`,
|
|
197
161
|
);
|
|
198
|
-
for (const v of app.stories.filter((x) => x.extends === s.name)) {
|
|
199
|
-
lines.push(` - in \`${v.brand}\` branding: \`${v.name}\``);
|
|
200
|
-
}
|
|
201
162
|
}
|
|
202
|
-
lines.push(
|
|
163
|
+
lines.push("");
|
|
203
164
|
}
|
|
204
|
-
const example = apps.find((a) => a.stories.
|
|
165
|
+
const example = apps.find((a) => a.stories.length > 0);
|
|
205
166
|
if (example) {
|
|
206
|
-
lines.push(
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
lines.push(
|
|
210
|
-
"",
|
|
211
|
-
"A customer without a brand here: ask @Linear for a pitch draft (see the demo-video README).",
|
|
212
|
-
);
|
|
167
|
+
lines.push(`For example: \`/demo-video ${example.stories[0].name}\``);
|
|
168
|
+
}
|
|
169
|
+
if (reason !== LINEAR) {
|
|
170
|
+
lines.push("", LINEAR);
|
|
213
171
|
}
|
|
214
172
|
return lines.join("\n");
|
|
215
173
|
};
|
|
216
174
|
|
|
217
175
|
/**
|
|
218
|
-
* The form's version (Actions → Run workflow): app
|
|
219
|
-
*
|
|
220
|
-
*
|
|
221
|
-
*
|
|
176
|
+
* The form's version (Actions → Run workflow): app and story by name, no
|
|
177
|
+
* guessing. Empty story = the primary story, empty app = the only app. A
|
|
178
|
+
* name that doesn't exist gets the menu, so a typo never films something
|
|
179
|
+
* else. `apps` in a menu result narrows it.
|
|
222
180
|
*/
|
|
223
|
-
export const pickExact = (apps, { app = "", story = ""
|
|
181
|
+
export const pickExact = (apps, { app = "", story = "" }) => {
|
|
224
182
|
const slashes = (p) => p.split("\\").join("/");
|
|
225
183
|
const wanted = slashes(app).replace(/\/+$/, "");
|
|
226
184
|
const candidates = wanted
|
|
@@ -250,16 +208,5 @@ export const pickExact = (apps, { app = "", story = "", brand = "" }) => {
|
|
|
250
208
|
apps: [chosen],
|
|
251
209
|
};
|
|
252
210
|
}
|
|
253
|
-
|
|
254
|
-
// A variant is made for one brand.
|
|
255
|
-
if (brand && brand !== found.brand) {
|
|
256
|
-
return {
|
|
257
|
-
menu: true,
|
|
258
|
-
reason: `\`${found.name}\` is made for \`${found.brand}\`. Leave Brand empty, or pick \`${found.extends}\`:`,
|
|
259
|
-
apps: [chosen],
|
|
260
|
-
};
|
|
261
|
-
}
|
|
262
|
-
return { app: chosen.dir, story: found.name, brand: found.brand };
|
|
263
|
-
}
|
|
264
|
-
return withBrand(chosen, found.name, brand || null);
|
|
211
|
+
return { app: chosen.dir, story: found.name };
|
|
265
212
|
};
|
package/bin/pitch.mjs
CHANGED
|
@@ -152,13 +152,6 @@ interface DemoAdapter {
|
|
|
152
152
|
setup(page: Page, ctx: {
|
|
153
153
|
brand: Brand;
|
|
154
154
|
}): Promise<void>;
|
|
155
|
-
/**
|
|
156
|
-
* The app's own brands folder, relative to demo/ (default "./brands").
|
|
157
|
-
* Searched before the brands shipped with the engine (navipartner, ...).
|
|
158
|
-
*/
|
|
159
|
-
brands?: string;
|
|
160
|
-
/** Default "navipartner". */
|
|
161
|
-
defaultBrand?: string;
|
|
162
155
|
/**
|
|
163
156
|
* What this app takes from a brand, each with what it is and where it
|
|
164
157
|
* shows ("full-screen photo behind the menu, landscape"). Apps differ: one
|
|
@@ -502,76 +502,15 @@ var parseStoryboard = (raw, adapter, source = "storyboard") => {
|
|
|
502
502
|
throw new StoryboardError(`Invalid ${source}:
|
|
503
503
|
${lines.join("\n")}`);
|
|
504
504
|
};
|
|
505
|
-
var cardChange = z.object({
|
|
506
|
-
eyebrow: cardFields.eyebrow,
|
|
507
|
-
heading: cardFields.heading,
|
|
508
|
-
sub: cardFields.sub,
|
|
509
|
-
logo: cardFields.logo,
|
|
510
|
-
style: z.enum(["pale", "brand"]).optional(),
|
|
511
|
-
seconds: z.number().min(0.5).max(10).optional()
|
|
512
|
-
}).strict();
|
|
513
|
-
var variantSchema = z.object({
|
|
514
|
-
extends: z.string().regex(/^[\w-]+$/, "the base story's name"),
|
|
515
|
-
brand: z.string().regex(/^[\w-]+$/, "a brand name"),
|
|
516
|
-
description: z.string().min(1).max(280).optional(),
|
|
517
|
-
title: cardChange.optional(),
|
|
518
|
-
closing: cardChange.optional(),
|
|
519
|
-
cards: z.array(cardChange).optional()
|
|
520
|
-
}).strict();
|
|
521
505
|
var readJson = (file) => JSON.parse(fs.readFileSync(file, "utf8"));
|
|
522
|
-
var
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
const result = variantSchema.safeParse(raw);
|
|
526
|
-
if (!result.success) {
|
|
527
|
-
const lines = result.error.issues.map(
|
|
528
|
-
(i) => ` ${i.path.join(".") || "(root)"}: ${i.message}`
|
|
529
|
-
);
|
|
530
|
-
throw new StoryboardError(`Invalid ${name}:
|
|
531
|
-
${lines.join("\n")}`);
|
|
532
|
-
}
|
|
533
|
-
const variant = result.data;
|
|
534
|
-
const baseFile = path.join(path.dirname(file), `${variant.extends}.json`);
|
|
535
|
-
if (!fs.existsSync(baseFile)) {
|
|
536
|
-
throw new StoryboardError(
|
|
537
|
-
`${name} extends "${variant.extends}", but there is no ${variant.extends}.json beside it`
|
|
538
|
-
);
|
|
539
|
-
}
|
|
540
|
-
const base = readJson(baseFile);
|
|
541
|
-
if (isVariant(base)) {
|
|
542
|
-
throw new StoryboardError(
|
|
543
|
-
`${name} extends ${variant.extends}.json, which is a variant itself; extend the story it extends`
|
|
544
|
-
);
|
|
545
|
-
}
|
|
546
|
-
const steps = Array.isArray(base.steps) ? base.steps : [];
|
|
547
|
-
const cardAt = steps.flatMap((s, i) => s.do === "card" ? [i] : []);
|
|
548
|
-
if (variant.cards && variant.cards.length !== cardAt.length) {
|
|
506
|
+
var loadStoryboard = (file, adapter) => {
|
|
507
|
+
const raw = readJson(file);
|
|
508
|
+
if (typeof raw === "object" && raw !== null && ("extends" in raw || "brand" in raw)) {
|
|
549
509
|
throw new StoryboardError(
|
|
550
|
-
`${
|
|
510
|
+
`${path.basename(file)} names a brand or extends a story: stories hold neither. A customer's brand is researched by @Linear for one video; a translation is a story of its own (checkout-da.json).`
|
|
551
511
|
);
|
|
552
512
|
}
|
|
553
|
-
|
|
554
|
-
const merged = steps.map(
|
|
555
|
-
(step, i) => variant.cards ? change(step, variant.cards[cardAt.indexOf(i)]) : step
|
|
556
|
-
);
|
|
557
|
-
const rest = { ...base };
|
|
558
|
-
delete rest.primary;
|
|
559
|
-
const story = parseStoryboard(
|
|
560
|
-
{
|
|
561
|
-
...rest,
|
|
562
|
-
description: variant.description ?? base.description,
|
|
563
|
-
title: change(base.title, variant.title),
|
|
564
|
-
closing: change(base.closing, variant.closing),
|
|
565
|
-
steps: merged
|
|
566
|
-
},
|
|
567
|
-
adapter,
|
|
568
|
-
`${name} (on ${variant.extends}.json)`
|
|
569
|
-
);
|
|
570
|
-
return { ...story, brand: variant.brand, variantOf: variant.extends };
|
|
571
|
-
};
|
|
572
|
-
var loadStoryboard = (file, adapter) => {
|
|
573
|
-
const raw = readJson(file);
|
|
574
|
-
return isVariant(raw) ? loadVariant(raw, file, adapter) : parseStoryboard(raw, adapter, path.basename(file));
|
|
513
|
+
return parseStoryboard(raw, adapter, path.basename(file));
|
|
575
514
|
};
|
|
576
515
|
var MIN_ZOOM = MIN_SCALE;
|
|
577
516
|
var MAX_ZOOM = MAX_SCALE;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { D as DemoAdapter } from './adapter-
|
|
2
|
-
export { B as Brand, C as CardSpec, a as DemoAction, b as DirectorApi, T as Target, V as VideoBrand, d as defineAction, c as defineDemo } from './adapter-
|
|
1
|
+
import { D as DemoAdapter } from './adapter-CDOXdUZI.js';
|
|
2
|
+
export { B as Brand, C as CardSpec, a as DemoAction, b as DirectorApi, T as Target, V as VideoBrand, d as defineAction, c as defineDemo } from './adapter-CDOXdUZI.js';
|
|
3
3
|
import { Page } from '@playwright/test';
|
|
4
4
|
import { z } from 'zod';
|
|
5
5
|
export { z } from 'zod';
|
|
@@ -236,10 +236,6 @@ declare const cardSchema: z.ZodEffects<z.ZodObject<{
|
|
|
236
236
|
type Card = z.infer<typeof cardSchema>;
|
|
237
237
|
interface Storyboard {
|
|
238
238
|
app: string;
|
|
239
|
-
/** A variant's brand (see loadStoryboard): it is filmed with this one only. */
|
|
240
|
-
brand?: string;
|
|
241
|
-
/** The story a variant extends. */
|
|
242
|
-
variantOf?: string;
|
|
243
239
|
/** What the story shows, for people choosing one (and the menu). */
|
|
244
240
|
description?: string;
|
|
245
241
|
/** The app's primary journey: the story filmed when none is named. One per app. */
|
package/dist/index.js
CHANGED
package/dist/runner/index.d.ts
CHANGED
package/dist/runner/index.js
CHANGED
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
unionRect,
|
|
31
31
|
visibleRect,
|
|
32
32
|
wideShot
|
|
33
|
-
} from "../chunk-
|
|
33
|
+
} from "../chunk-D7UYGNSF.js";
|
|
34
34
|
|
|
35
35
|
// src/runner/config.ts
|
|
36
36
|
import path from "path";
|
|
@@ -135,10 +135,17 @@ var engineRoot = () => {
|
|
|
135
135
|
}
|
|
136
136
|
};
|
|
137
137
|
var sharedBrandsDir = () => path2.join(engineRoot(), "brands");
|
|
138
|
-
var brandDirs = (
|
|
139
|
-
|
|
138
|
+
var brandDirs = (pitchDir) => [
|
|
139
|
+
...pitchDir ? [pitchDir] : [],
|
|
140
140
|
sharedBrandsDir()
|
|
141
141
|
];
|
|
142
|
+
var refuseRepoBrands = (demoDir) => {
|
|
143
|
+
if (fs.existsSync(path2.join(demoDir, "brands"))) {
|
|
144
|
+
throw new Error(
|
|
145
|
+
`${path2.join(demoDir, "brands")} isn't used: repos keep no brands. NaviPartner's ships with the engine; a customer's is researched by @Linear for one video and never saved. Delete the folder.`
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
};
|
|
142
149
|
var brandNames = (dir) => fs.existsSync(dir) ? fs.readdirSync(dir).filter((f) => f.endsWith(".json")).map((f) => f.slice(0, -".json".length)) : [];
|
|
143
150
|
var loadBrand = (dirs, name) => {
|
|
144
151
|
if (!NAME_RE.test(name)) {
|
|
@@ -1196,17 +1203,10 @@ var registerDemoTests = (test, adapter, demoDir) => {
|
|
|
1196
1203
|
].join("\n")
|
|
1197
1204
|
);
|
|
1198
1205
|
}
|
|
1199
|
-
|
|
1200
|
-
throw new StoryboardError(
|
|
1201
|
-
`${path4.basename(env.storyboardPath, ".json")} is ${storyboard.variantOf} for the brand ${storyboard.brand}. Render it without --brand, or render ${storyboard.variantOf} with --brand ${env.brand}.`
|
|
1202
|
-
);
|
|
1203
|
-
}
|
|
1206
|
+
refuseRepoBrands(demoDir);
|
|
1204
1207
|
const brand = loadBrand(
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
...brandDirs(demoDir, adapter.brands)
|
|
1208
|
-
],
|
|
1209
|
-
env.brand ?? storyboard.brand ?? adapter.defaultBrand ?? "navipartner"
|
|
1208
|
+
brandDirs(env.brandsDir),
|
|
1209
|
+
env.brand ?? "navipartner"
|
|
1210
1210
|
);
|
|
1211
1211
|
const missing = missingNeeds(brand, adapter.brandNeeds);
|
|
1212
1212
|
if (missing.length > 0) {
|
package/package.json
CHANGED