busybar-kit 1.1.0 → 2.1.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/dist/config-spec.d.ts +63 -19
- package/dist/config-spec.d.ts.map +1 -1
- package/dist/config-spec.js +64 -41
- package/dist/config-spec.js.map +1 -1
- package/dist/image/index.d.ts +5 -2
- package/dist/image/index.d.ts.map +1 -1
- package/dist/image/index.js +5 -2
- package/dist/image/index.js.map +1 -1
- package/dist/image/png.d.ts +9 -0
- package/dist/image/png.d.ts.map +1 -0
- package/dist/image/png.js +165 -0
- package/dist/image/png.js.map +1 -0
- package/dist/image/resize.d.ts +12 -0
- package/dist/image/resize.d.ts.map +1 -0
- package/dist/image/resize.js +83 -0
- package/dist/image/resize.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/input/index.d.ts +3 -0
- package/dist/input/index.d.ts.map +1 -0
- package/dist/input/index.js +3 -0
- package/dist/input/index.js.map +1 -0
- package/dist/input/input.d.ts +54 -0
- package/dist/input/input.d.ts.map +1 -0
- package/dist/input/input.js +222 -0
- package/dist/input/input.js.map +1 -0
- package/dist/input/protobuf.d.ts +28 -0
- package/dist/input/protobuf.d.ts.map +1 -0
- package/dist/input/protobuf.js +81 -0
- package/dist/input/protobuf.js.map +1 -0
- package/dist/preview/png.d.ts.map +1 -1
- package/dist/preview/png.js +20 -4
- package/dist/preview/png.js.map +1 -1
- package/dist/preview/raster.d.ts +8 -0
- package/dist/preview/raster.d.ts.map +1 -1
- package/dist/preview/raster.js +55 -7
- package/dist/preview/raster.js.map +1 -1
- package/dist/rules.d.ts +7 -0
- package/dist/rules.d.ts.map +1 -0
- package/dist/rules.js +71 -0
- package/dist/rules.js.map +1 -0
- package/dist/summary.d.ts +18 -0
- package/dist/summary.d.ts.map +1 -0
- package/dist/summary.js +63 -0
- package/dist/summary.js.map +1 -0
- package/package.json +6 -2
- package/scripts/emit-config-spec.mjs +31 -0
- package/scripts/fix-esm-extensions.mjs +1 -1
package/dist/preview/raster.js
CHANGED
|
@@ -9,8 +9,20 @@ export function renderFront(elements) {
|
|
|
9
9
|
export function renderBack(elements) {
|
|
10
10
|
return render(elements, 'back', BACK.width, BACK.height, true);
|
|
11
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* Draws onto a panel that already has something on it.
|
|
14
|
+
*
|
|
15
|
+
* The device layers elements in the order they arrive, and an app that puts a
|
|
16
|
+
* picture under an outline needs the preview to agree. `renderFront` cannot,
|
|
17
|
+
* having made the bitmap itself; this can.
|
|
18
|
+
*/
|
|
19
|
+
export function renderOnto(bitmap, elements, display) {
|
|
20
|
+
return paintAll(bitmap, elements, display, display === 'back');
|
|
21
|
+
}
|
|
12
22
|
function render(elements, display, width, height, greyscale) {
|
|
13
|
-
|
|
23
|
+
return paintAll(new Bitmap(width, height, shade(OFF_PIXEL, greyscale)), elements, display, greyscale);
|
|
24
|
+
}
|
|
25
|
+
function paintAll(bitmap, elements, display, greyscale) {
|
|
14
26
|
for (const element of elements) {
|
|
15
27
|
if (element.display !== display) {
|
|
16
28
|
continue;
|
|
@@ -38,21 +50,57 @@ function drawRectangle(bitmap, element, greyscale) {
|
|
|
38
50
|
const width = element.width ?? 0;
|
|
39
51
|
const height = element.height ?? 0;
|
|
40
52
|
const { x, y } = anchor(element.align, element.x, element.y, width, height);
|
|
53
|
+
// A radius of half the shorter side is a circle, which is how the device is
|
|
54
|
+
// asked for one. Clamped, because a larger radius has nowhere left to go.
|
|
55
|
+
const radius = Math.max(0, Math.min(element.radius ?? 0, Math.floor(Math.min(width, height) / 2)));
|
|
41
56
|
if (element.fill !== 'none') {
|
|
42
57
|
const fill = shade(parseColor(element.fill_colors?.[0] ?? '#00000000'), greyscale);
|
|
43
|
-
bitmap
|
|
58
|
+
paint(bitmap, x, y, width, height, radius, 0, fill);
|
|
44
59
|
}
|
|
45
60
|
const borderWidth = element.border_width ?? 0;
|
|
46
61
|
if (borderWidth <= 0) {
|
|
47
62
|
return;
|
|
48
63
|
}
|
|
49
64
|
const border = shade(parseColor(element.border_color ?? '#00000000'), greyscale);
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
65
|
+
paint(bitmap, x, y, width, height, radius, borderWidth, border);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* A rounded rectangle, filled or as an outline `thickness` pixels wide.
|
|
69
|
+
*
|
|
70
|
+
* Corners are measured from the centre of the corner's arc, so a radius of
|
|
71
|
+
* half the side collapses the straight edges entirely and what is left is a
|
|
72
|
+
* circle. `thickness` of zero fills; anything else keeps the ring between the
|
|
73
|
+
* outer shape and the same shape inset by that much.
|
|
74
|
+
*/
|
|
75
|
+
function paint(bitmap, x, y, width, height, radius, thickness, color) {
|
|
76
|
+
for (let row = 0; row < height; row += 1) {
|
|
77
|
+
for (let column = 0; column < width; column += 1) {
|
|
78
|
+
if (!within(column, row, width, height, radius)) {
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
if (thickness > 0 &&
|
|
82
|
+
within(column - thickness, row - thickness, width - thickness * 2, height - thickness * 2, Math.max(0, radius - thickness))) {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
bitmap.set(x + column, y + row, color);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/** Whether a pixel is inside a rounded rectangle of this size. */
|
|
90
|
+
function within(column, row, width, height, radius) {
|
|
91
|
+
if (column < 0 || row < 0 || column >= width || row >= height) {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
if (radius <= 0) {
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
// Only the four corner squares are curved; everything else is a rectangle.
|
|
98
|
+
const dx = column < radius ? radius - column : column >= width - radius ? column - (width - radius) + 1 : 0;
|
|
99
|
+
const dy = row < radius ? radius - row : row >= height - radius ? row - (height - radius) + 1 : 0;
|
|
100
|
+
if (dx === 0 || dy === 0) {
|
|
101
|
+
return true;
|
|
55
102
|
}
|
|
103
|
+
return Math.hypot(dx, dy) <= radius + 0.5;
|
|
56
104
|
}
|
|
57
105
|
function drawText(bitmap, element, greyscale) {
|
|
58
106
|
const text = element.text ?? '';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"raster.js","sourceRoot":"","sources":["../../src/preview/raster.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAExC,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAC1E,OAAO,EAAE,MAAM,EAAE,UAAU,EAAa,MAAM,OAAO,CAAC;AAItD,MAAM,SAAS,GAAS,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC;AAExD,MAAM,UAAU,WAAW,CAAC,QAAsB;IAChD,OAAO,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AACrE,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,QAAsB;IAC/C,OAAO,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;AACjE,CAAC;AAED,SAAS,MAAM,CACb,QAAsB,EACtB,OAAyB,EACzB,KAAa,EACb,MAAc,EACd,SAAkB;IAElB,
|
|
1
|
+
{"version":3,"file":"raster.js","sourceRoot":"","sources":["../../src/preview/raster.ts"],"names":[],"mappings":"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"}
|
package/dist/rules.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ConfigField, ValidationRule } from './config-spec.js';
|
|
2
|
+
/**
|
|
3
|
+
* One interpreter for every client — CLI, daemon, and the browser.
|
|
4
|
+
* Empty values are fine unless a `required` rule (or the field flag) says otherwise.
|
|
5
|
+
*/
|
|
6
|
+
export declare function validateValue(rules: readonly ValidationRule[] | undefined, value: string, field?: Pick<ConfigField, 'label' | 'required' | 'type'>, current?: string): string | undefined;
|
|
7
|
+
//# sourceMappingURL=rules.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../src/rules.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAIjE;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,SAAS,cAAc,EAAE,GAAG,SAAS,EAC5C,KAAK,EAAE,MAAM,EACb,KAAK,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,OAAO,GAAG,UAAU,GAAG,MAAM,CAAC,EACxD,OAAO,SAAK,GACX,MAAM,GAAG,SAAS,CAmBpB"}
|
package/dist/rules.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
const LOCAL_DATETIME = /^\d{4}-\d{2}-\d{2}[T ]\d{1,2}:\d{2}$/;
|
|
2
|
+
/**
|
|
3
|
+
* One interpreter for every client — CLI, daemon, and the browser.
|
|
4
|
+
* Empty values are fine unless a `required` rule (or the field flag) says otherwise.
|
|
5
|
+
*/
|
|
6
|
+
export function validateValue(rules, value, field, current = '') {
|
|
7
|
+
const trimmed = value.trim();
|
|
8
|
+
if (field?.required && !trimmed && !(field.type === 'secret' && current)) {
|
|
9
|
+
return `${field.label} is needed`;
|
|
10
|
+
}
|
|
11
|
+
if (!rules?.length) {
|
|
12
|
+
return undefined;
|
|
13
|
+
}
|
|
14
|
+
for (const rule of rules) {
|
|
15
|
+
const error = checkRule(rule, trimmed, field?.label);
|
|
16
|
+
if (error) {
|
|
17
|
+
return error;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
function checkRule(rule, value, label) {
|
|
23
|
+
switch (rule.kind) {
|
|
24
|
+
case 'required':
|
|
25
|
+
return value
|
|
26
|
+
? undefined
|
|
27
|
+
: (rule.message ?? (label ? `${label} is needed` : 'this is needed'));
|
|
28
|
+
case 'pattern': {
|
|
29
|
+
if (!value) {
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
try {
|
|
33
|
+
return new RegExp(rule.pattern).test(value) ? undefined : rule.message;
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return rule.message;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
case 'integer': {
|
|
40
|
+
if (!value) {
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
const parsed = Number(value);
|
|
44
|
+
if (!Number.isFinite(parsed) || !Number.isInteger(parsed)) {
|
|
45
|
+
return rule.message ?? 'a whole number, please';
|
|
46
|
+
}
|
|
47
|
+
return parsed < rule.min || parsed > rule.max
|
|
48
|
+
? (rule.message ?? `between ${rule.min} and ${rule.max}`)
|
|
49
|
+
: undefined;
|
|
50
|
+
}
|
|
51
|
+
case 'datetime': {
|
|
52
|
+
if (!value) {
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
55
|
+
if (rule.format !== 'local') {
|
|
56
|
+
return rule.message ?? 'unsupported datetime format';
|
|
57
|
+
}
|
|
58
|
+
if (!LOCAL_DATETIME.test(value)) {
|
|
59
|
+
return rule.message ?? 'YYYY-MM-DD HH:MM';
|
|
60
|
+
}
|
|
61
|
+
return Number.isNaN(Date.parse(value.replace(' ', 'T')))
|
|
62
|
+
? (rule.message ?? 'that is not a real date')
|
|
63
|
+
: undefined;
|
|
64
|
+
}
|
|
65
|
+
default: {
|
|
66
|
+
const _exhaustive = rule;
|
|
67
|
+
return `unknown rule ${JSON.stringify(_exhaustive)}`;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=rules.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rules.js","sourceRoot":"","sources":["../src/rules.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one line that stands for a record in a picker.
|
|
3
|
+
*
|
|
4
|
+
* A template rather than a function, because every client has to render it and
|
|
5
|
+
* only one of them can run JavaScript. Deliberately small — anything that needs
|
|
6
|
+
* more than this is a sign the app should be storing a different shape:
|
|
7
|
+
*
|
|
8
|
+
* {key} the value, or nothing
|
|
9
|
+
* {a|b} a if it has a value, else b — `{route|from-to}`
|
|
10
|
+
* {a-b} both joined by what sits between them, or nothing if either
|
|
11
|
+
* is missing, so a half-filled route is not rendered as `SVO-`
|
|
12
|
+
* BO{bo} a literal glued to a token goes when the token does
|
|
13
|
+
*
|
|
14
|
+
* Whitespace left behind by a missing value collapses; whitespace you put
|
|
15
|
+
* between two values that are both there is kept, so columns still line up.
|
|
16
|
+
*/
|
|
17
|
+
export declare function renderSummary(template: string, entry: Record<string, string>): string;
|
|
18
|
+
//# sourceMappingURL=summary.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"summary.d.ts","sourceRoot":"","sources":["../src/summary.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CA6BrF"}
|
package/dist/summary.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one line that stands for a record in a picker.
|
|
3
|
+
*
|
|
4
|
+
* A template rather than a function, because every client has to render it and
|
|
5
|
+
* only one of them can run JavaScript. Deliberately small — anything that needs
|
|
6
|
+
* more than this is a sign the app should be storing a different shape:
|
|
7
|
+
*
|
|
8
|
+
* {key} the value, or nothing
|
|
9
|
+
* {a|b} a if it has a value, else b — `{route|from-to}`
|
|
10
|
+
* {a-b} both joined by what sits between them, or nothing if either
|
|
11
|
+
* is missing, so a half-filled route is not rendered as `SVO-`
|
|
12
|
+
* BO{bo} a literal glued to a token goes when the token does
|
|
13
|
+
*
|
|
14
|
+
* Whitespace left behind by a missing value collapses; whitespace you put
|
|
15
|
+
* between two values that are both there is kept, so columns still line up.
|
|
16
|
+
*/
|
|
17
|
+
export function renderSummary(template, entry) {
|
|
18
|
+
const parts = [];
|
|
19
|
+
let carry = '';
|
|
20
|
+
// One pass: a token plus whatever literal is glued to its left, so the
|
|
21
|
+
// literal can leave with it.
|
|
22
|
+
const pattern = /([^\s{}]*)\{([^{}]+)\}/g;
|
|
23
|
+
let at = 0;
|
|
24
|
+
for (let match = pattern.exec(template); match; match = pattern.exec(template)) {
|
|
25
|
+
carry += template.slice(at, match.index);
|
|
26
|
+
at = match.index + match[0].length;
|
|
27
|
+
const value = resolve(match[2] ?? '', entry);
|
|
28
|
+
if (value) {
|
|
29
|
+
parts.push(`${carry}${match[1] ?? ''}${value}`);
|
|
30
|
+
carry = '';
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
// The token and its glued prefix are dropped; the separator before them
|
|
34
|
+
// is dropped with them rather than doubling up.
|
|
35
|
+
carry = carry.trimEnd() ? carry : '';
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
const tail = `${carry}${template.slice(at)}`;
|
|
39
|
+
if (tail.trim()) {
|
|
40
|
+
parts.push(tail);
|
|
41
|
+
}
|
|
42
|
+
return parts.join('').replace(/^\s+|\s+$/g, '');
|
|
43
|
+
}
|
|
44
|
+
function resolve(token, entry) {
|
|
45
|
+
const bar = token.indexOf('|');
|
|
46
|
+
if (bar !== -1) {
|
|
47
|
+
const left = resolve(token.slice(0, bar), entry);
|
|
48
|
+
return left || resolve(token.slice(bar + 1), entry);
|
|
49
|
+
}
|
|
50
|
+
// `{from-to}` and friends: two keys with a literal between them, present only
|
|
51
|
+
// when both sides are.
|
|
52
|
+
const joined = /^([A-Za-z_]\w*)(\W+)([A-Za-z_]\w*)$/.exec(token);
|
|
53
|
+
if (joined) {
|
|
54
|
+
const left = value(entry, joined[1]);
|
|
55
|
+
const right = value(entry, joined[3]);
|
|
56
|
+
return left && right ? `${left}${joined[2] ?? ''}${right}` : '';
|
|
57
|
+
}
|
|
58
|
+
return value(entry, token);
|
|
59
|
+
}
|
|
60
|
+
function value(entry, key) {
|
|
61
|
+
return key ? (entry[key] ?? '').trim() : '';
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=summary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"summary.js","sourceRoot":"","sources":["../src/summary.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "busybar-kit",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Shared building blocks for BUSY Bar apps: device geometry, colours, formatters, ticker text, error taxonomy and an offline PNG preview renderer",
|
|
5
5
|
"author": "viirtualp1",
|
|
6
6
|
"license": "MIT",
|
|
@@ -20,11 +20,14 @@
|
|
|
20
20
|
"./colors": "./dist/colors.js",
|
|
21
21
|
"./config": "./dist/config/index.js",
|
|
22
22
|
"./config-spec": "./dist/config-spec.js",
|
|
23
|
+
"./rules": "./dist/rules.js",
|
|
24
|
+
"./summary": "./dist/summary.js",
|
|
23
25
|
"./device": "./dist/device.js",
|
|
24
26
|
"./elements": "./dist/elements.js",
|
|
25
27
|
"./errors": "./dist/errors.js",
|
|
26
28
|
"./format": "./dist/format.js",
|
|
27
29
|
"./image": "./dist/image/index.js",
|
|
30
|
+
"./input": "./dist/input/index.js",
|
|
28
31
|
"./preview": "./dist/preview/index.js",
|
|
29
32
|
"./profile": "./dist/profile.js",
|
|
30
33
|
"./ticker": "./dist/ticker/index.js",
|
|
@@ -34,7 +37,8 @@
|
|
|
34
37
|
"./package.json": "./package.json"
|
|
35
38
|
},
|
|
36
39
|
"bin": {
|
|
37
|
-
"busybar-fix-esm": "scripts/fix-esm-extensions.mjs"
|
|
40
|
+
"busybar-fix-esm": "scripts/fix-esm-extensions.mjs",
|
|
41
|
+
"busybar-emit-spec": "scripts/emit-config-spec.mjs"
|
|
38
42
|
},
|
|
39
43
|
"files": [
|
|
40
44
|
"dist",
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Writes `dist/config-spec.json` from the built `dist/config-spec.js`.
|
|
3
|
+
//
|
|
4
|
+
// Specs are authored in TypeScript for the types and the autocompletion, but a
|
|
5
|
+
// browser or a Dart client cannot import a JS module out of node_modules. The
|
|
6
|
+
// JSON beside it is what makes the spec readable by anything at all — and
|
|
7
|
+
// emitting it from the built module rather than hand-maintaining a second copy
|
|
8
|
+
// is what keeps the two from drifting.
|
|
9
|
+
import { existsSync, writeFileSync } from 'node:fs';
|
|
10
|
+
import { isAbsolute, resolve } from 'node:path';
|
|
11
|
+
import { pathToFileURL } from 'node:url';
|
|
12
|
+
|
|
13
|
+
const argument = process.argv[2] ?? 'dist/config-spec.js';
|
|
14
|
+
const source = isAbsolute(argument) ? argument : resolve(process.cwd(), argument);
|
|
15
|
+
|
|
16
|
+
if (!existsSync(source)) {
|
|
17
|
+
console.error(`busybar-emit-spec: ${source} is not there — build first`);
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const module = await import(pathToFileURL(source).href);
|
|
22
|
+
const spec = module.default;
|
|
23
|
+
|
|
24
|
+
if (!spec || typeof spec !== 'object' || typeof spec.name !== 'string') {
|
|
25
|
+
console.error(`busybar-emit-spec: ${source} has no config spec as its default export`);
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const target = source.replace(/\.js$/, '.json');
|
|
30
|
+
writeFileSync(target, `${JSON.stringify(spec, null, 2)}\n`);
|
|
31
|
+
console.log(`busybar-emit-spec: wrote ${target}`);
|