@opentabs-dev/plugin-tools 0.0.15 → 0.0.17
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/cli.js +2 -1
- package/dist/cli.js.map +1 -1
- package/dist/commands/build.d.ts +47 -5
- package/dist/commands/build.d.ts.map +1 -1
- package/dist/commands/build.js +260 -20
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/index.d.ts +1 -0
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +1 -0
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/inspect.d.ts +9 -0
- package/dist/commands/inspect.d.ts.map +1 -0
- package/dist/commands/inspect.js +166 -0
- package/dist/commands/inspect.js.map +1 -0
- package/dist/validate-icon.d.ts +34 -0
- package/dist/validate-icon.d.ts.map +1 -0
- package/dist/validate-icon.js +401 -0
- package/dist/validate-icon.js.map +1 -0
- package/package.json +3 -3
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `opentabs-plugin inspect` command — pretty-prints the built plugin manifest.
|
|
3
|
+
* Reads dist/tools.json and package.json from the current directory and displays
|
|
4
|
+
* a human-readable summary of tools, resources, and prompts.
|
|
5
|
+
*/
|
|
6
|
+
import { parsePluginPackageJson } from '@opentabs-dev/shared';
|
|
7
|
+
import pc from 'picocolors';
|
|
8
|
+
import { join } from 'node:path';
|
|
9
|
+
/** Extract field names and types from a JSON Schema object */
|
|
10
|
+
const extractFields = (schema) => {
|
|
11
|
+
const properties = schema.properties;
|
|
12
|
+
if (!properties)
|
|
13
|
+
return [];
|
|
14
|
+
const requiredSet = new Set(Array.isArray(schema.required) ? schema.required : []);
|
|
15
|
+
return Object.entries(properties).map(([name, prop]) => {
|
|
16
|
+
let type = 'unknown';
|
|
17
|
+
if (typeof prop.type === 'string') {
|
|
18
|
+
type = prop.type;
|
|
19
|
+
}
|
|
20
|
+
else if (Array.isArray(prop.anyOf)) {
|
|
21
|
+
const types = prop.anyOf
|
|
22
|
+
.map(t => (typeof t.type === 'string' ? t.type : '?'))
|
|
23
|
+
.join(' | ');
|
|
24
|
+
type = types;
|
|
25
|
+
}
|
|
26
|
+
return { name, type, required: requiredSet.has(name) };
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
/** Truncate a string to maxLen, appending "..." if truncated */
|
|
30
|
+
const truncate = (s, maxLen) => (s.length > maxLen ? s.slice(0, maxLen - 3) + '...' : s);
|
|
31
|
+
const handleInspect = async (options) => {
|
|
32
|
+
const projectDir = process.cwd();
|
|
33
|
+
// Read dist/tools.json
|
|
34
|
+
const toolsJsonPath = join(projectDir, 'dist', 'tools.json');
|
|
35
|
+
const toolsJsonFile = Bun.file(toolsJsonPath);
|
|
36
|
+
if (!(await toolsJsonFile.exists())) {
|
|
37
|
+
console.error(pc.red('No manifest found. Run opentabs-plugin build first.'));
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
let manifest;
|
|
41
|
+
try {
|
|
42
|
+
const parsed = JSON.parse(await toolsJsonFile.text());
|
|
43
|
+
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
|
|
44
|
+
throw new Error('not an object');
|
|
45
|
+
}
|
|
46
|
+
const obj = parsed;
|
|
47
|
+
// Support legacy format (plain array) and current format (object with tools key)
|
|
48
|
+
if (Array.isArray(obj.tools)) {
|
|
49
|
+
manifest = obj;
|
|
50
|
+
}
|
|
51
|
+
else if (Array.isArray(parsed)) {
|
|
52
|
+
manifest = { tools: parsed };
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
throw new Error('unexpected format');
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
console.error(pc.red('Failed to parse dist/tools.json. The file may be corrupted — rebuild with opentabs-plugin build.'));
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
// --json mode: output raw JSON and exit
|
|
63
|
+
if (options.json) {
|
|
64
|
+
console.log(JSON.stringify(manifest, null, 2));
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
// Read package.json for plugin metadata
|
|
68
|
+
let pluginName = '(unknown)';
|
|
69
|
+
let pluginVersion = '(unknown)';
|
|
70
|
+
let displayName;
|
|
71
|
+
const pkgJsonFile = Bun.file(join(projectDir, 'package.json'));
|
|
72
|
+
if (await pkgJsonFile.exists()) {
|
|
73
|
+
try {
|
|
74
|
+
const pkgJsonRaw = JSON.parse(await pkgJsonFile.text());
|
|
75
|
+
const result = parsePluginPackageJson(pkgJsonRaw, projectDir);
|
|
76
|
+
if (result.ok) {
|
|
77
|
+
pluginName = result.value.name;
|
|
78
|
+
pluginVersion = result.value.version;
|
|
79
|
+
displayName = result.value.opentabs.displayName;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
// Non-fatal — we can still show the manifest
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
const tools = manifest.tools;
|
|
87
|
+
const resources = manifest.resources ?? [];
|
|
88
|
+
const prompts = manifest.prompts ?? [];
|
|
89
|
+
// Header
|
|
90
|
+
console.log('');
|
|
91
|
+
console.log(pc.bold(displayName ?? pluginName) + pc.dim(` v${pluginVersion}`));
|
|
92
|
+
if (manifest.sdkVersion) {
|
|
93
|
+
console.log(pc.dim(`SDK version: ${manifest.sdkVersion}`));
|
|
94
|
+
}
|
|
95
|
+
// Summary counts
|
|
96
|
+
const parts = [];
|
|
97
|
+
parts.push(`${tools.length} tool${tools.length === 1 ? '' : 's'}`);
|
|
98
|
+
parts.push(`${resources.length} resource${resources.length === 1 ? '' : 's'}`);
|
|
99
|
+
parts.push(`${prompts.length} prompt${prompts.length === 1 ? '' : 's'}`);
|
|
100
|
+
console.log(pc.dim(parts.join(' · ')));
|
|
101
|
+
console.log('');
|
|
102
|
+
// Tools
|
|
103
|
+
if (tools.length > 0) {
|
|
104
|
+
console.log(pc.bold('Tools'));
|
|
105
|
+
console.log('');
|
|
106
|
+
for (const tool of tools) {
|
|
107
|
+
console.log(` ${pc.cyan(tool.icon)} ${pc.bold(tool.name)} ${pc.dim(tool.displayName)}`);
|
|
108
|
+
console.log(` ${truncate(tool.description, 80)}`);
|
|
109
|
+
const inputFields = extractFields(tool.input_schema);
|
|
110
|
+
if (inputFields.length > 0) {
|
|
111
|
+
const fieldStrs = inputFields.map(f => `${f.name}: ${f.type}${f.required ? '' : '?'}`);
|
|
112
|
+
console.log(` ${pc.dim('Input:')} ${fieldStrs.join(', ')}`);
|
|
113
|
+
}
|
|
114
|
+
const outputFields = extractFields(tool.output_schema);
|
|
115
|
+
if (outputFields.length > 0) {
|
|
116
|
+
const fieldStrs = outputFields.map(f => `${f.name}: ${f.type}${f.required ? '' : '?'}`);
|
|
117
|
+
console.log(` ${pc.dim('Output:')} ${fieldStrs.join(', ')}`);
|
|
118
|
+
}
|
|
119
|
+
console.log('');
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// Resources
|
|
123
|
+
if (resources.length > 0) {
|
|
124
|
+
console.log(pc.bold('Resources'));
|
|
125
|
+
console.log('');
|
|
126
|
+
for (const resource of resources) {
|
|
127
|
+
console.log(` ${pc.cyan(resource.uri)} ${pc.bold(resource.name)}`);
|
|
128
|
+
if (resource.description) {
|
|
129
|
+
console.log(` ${resource.description}`);
|
|
130
|
+
}
|
|
131
|
+
if (resource.mimeType) {
|
|
132
|
+
console.log(` ${pc.dim(`MIME: ${resource.mimeType}`)}`);
|
|
133
|
+
}
|
|
134
|
+
console.log('');
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
// Prompts
|
|
138
|
+
if (prompts.length > 0) {
|
|
139
|
+
console.log(pc.bold('Prompts'));
|
|
140
|
+
console.log('');
|
|
141
|
+
for (const prompt of prompts) {
|
|
142
|
+
console.log(` ${pc.bold(prompt.name)}`);
|
|
143
|
+
if (prompt.description) {
|
|
144
|
+
console.log(` ${prompt.description}`);
|
|
145
|
+
}
|
|
146
|
+
if (prompt.arguments && prompt.arguments.length > 0) {
|
|
147
|
+
const argStrs = prompt.arguments.map(a => `${a.name}${a.required ? '' : '?'}${a.description ? ` — ${a.description}` : ''}`);
|
|
148
|
+
console.log(` ${pc.dim('Args:')} ${argStrs.join(', ')}`);
|
|
149
|
+
}
|
|
150
|
+
console.log('');
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
const registerInspectCommand = (program) => {
|
|
155
|
+
program
|
|
156
|
+
.command('inspect')
|
|
157
|
+
.description('Pretty-print the built plugin manifest (dist/tools.json)')
|
|
158
|
+
.option('--json', 'Output raw JSON instead of formatted summary')
|
|
159
|
+
.addHelpText('after', `
|
|
160
|
+
Examples:
|
|
161
|
+
$ opentabs-plugin inspect
|
|
162
|
+
$ opentabs-plugin inspect --json`)
|
|
163
|
+
.action((options) => handleInspect(options));
|
|
164
|
+
};
|
|
165
|
+
export { registerInspectCommand };
|
|
166
|
+
//# sourceMappingURL=inspect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inspect.js","sourceRoot":"","sources":["../../src/commands/inspect.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SVG icon validation and auto-grayscale generation for plugin icons.
|
|
3
|
+
*
|
|
4
|
+
* Three exports:
|
|
5
|
+
* - validateIconSvg — structural validation (size, viewBox, forbidden elements)
|
|
6
|
+
* - validateInactiveIconColors — ensures only achromatic colors are present
|
|
7
|
+
* - generateInactiveIcon — converts all color values to luminance-equivalent grays
|
|
8
|
+
*/
|
|
9
|
+
declare const MAX_ICON_SIZE: number;
|
|
10
|
+
type ValidationResult = {
|
|
11
|
+
valid: true;
|
|
12
|
+
} | {
|
|
13
|
+
valid: false;
|
|
14
|
+
errors: string[];
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Validate an SVG string for use as a plugin icon.
|
|
18
|
+
* Checks: size <= 8KB, viewBox present and square, no <image>/<script>,
|
|
19
|
+
* no event handler attributes.
|
|
20
|
+
*/
|
|
21
|
+
declare const validateIconSvg: (content: string, _filename: string) => ValidationResult;
|
|
22
|
+
/**
|
|
23
|
+
* Validate that an SVG contains only achromatic colors.
|
|
24
|
+
* Checks fill, stroke, stop-color, and flood-color attributes and inline styles.
|
|
25
|
+
*/
|
|
26
|
+
declare const validateInactiveIconColors: (content: string) => ValidationResult;
|
|
27
|
+
/**
|
|
28
|
+
* Convert all color values in an SVG to luminance-equivalent grays.
|
|
29
|
+
* Processes fill, stroke, stop-color, and flood-color in both attributes and inline styles.
|
|
30
|
+
* Uses ITU-R BT.709: gray = 0.2126*R + 0.7152*G + 0.0722*B
|
|
31
|
+
*/
|
|
32
|
+
declare const generateInactiveIcon: (svgContent: string) => string;
|
|
33
|
+
export { generateInactiveIcon, MAX_ICON_SIZE, validateIconSvg, validateInactiveIconColors };
|
|
34
|
+
//# sourceMappingURL=validate-icon.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-icon.d.ts","sourceRoot":"","sources":["../src/validate-icon.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,QAAA,MAAM,aAAa,QAAW,CAAC;AA0O/B,KAAK,gBAAgB,GAAG;IAAE,KAAK,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAE7E;;;;GAIG;AACH,QAAA,MAAM,eAAe,GAAI,SAAS,MAAM,EAAE,WAAW,MAAM,KAAG,gBA2C7D,CAAC;AAMF;;;GAGG;AACH,QAAA,MAAM,0BAA0B,GAAI,SAAS,MAAM,KAAG,gBAgCrD,CAAC;AAuEF;;;;GAIG;AACH,QAAA,MAAM,oBAAoB,GAAI,YAAY,MAAM,KAAG,MAyBlD,CAAC;AAEF,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,eAAe,EAAE,0BAA0B,EAAE,CAAC"}
|
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SVG icon validation and auto-grayscale generation for plugin icons.
|
|
3
|
+
*
|
|
4
|
+
* Three exports:
|
|
5
|
+
* - validateIconSvg — structural validation (size, viewBox, forbidden elements)
|
|
6
|
+
* - validateInactiveIconColors — ensures only achromatic colors are present
|
|
7
|
+
* - generateInactiveIcon — converts all color values to luminance-equivalent grays
|
|
8
|
+
*/
|
|
9
|
+
const MAX_ICON_SIZE = 8 * 1024; // 8 KB
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
// Named color lookup table (CSS2.1 + common extended names)
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
const NAMED_COLORS = {
|
|
14
|
+
aqua: [0, 255, 255],
|
|
15
|
+
black: [0, 0, 0],
|
|
16
|
+
blue: [0, 0, 255],
|
|
17
|
+
fuchsia: [255, 0, 255],
|
|
18
|
+
gray: [128, 128, 128],
|
|
19
|
+
grey: [128, 128, 128],
|
|
20
|
+
green: [0, 128, 0],
|
|
21
|
+
lime: [0, 255, 0],
|
|
22
|
+
maroon: [128, 0, 0],
|
|
23
|
+
navy: [0, 0, 128],
|
|
24
|
+
olive: [128, 128, 0],
|
|
25
|
+
orange: [255, 165, 0],
|
|
26
|
+
purple: [128, 0, 128],
|
|
27
|
+
red: [255, 0, 0],
|
|
28
|
+
silver: [192, 192, 192],
|
|
29
|
+
teal: [0, 128, 128],
|
|
30
|
+
white: [255, 255, 255],
|
|
31
|
+
yellow: [255, 255, 0],
|
|
32
|
+
gold: [255, 215, 0],
|
|
33
|
+
indigo: [75, 0, 130],
|
|
34
|
+
coral: [255, 127, 80],
|
|
35
|
+
crimson: [220, 20, 60],
|
|
36
|
+
tomato: [255, 99, 71],
|
|
37
|
+
salmon: [250, 128, 114],
|
|
38
|
+
orchid: [218, 112, 214],
|
|
39
|
+
plum: [221, 160, 221],
|
|
40
|
+
chocolate: [210, 105, 30],
|
|
41
|
+
tan: [210, 180, 140],
|
|
42
|
+
peru: [205, 133, 63],
|
|
43
|
+
sienna: [160, 82, 45],
|
|
44
|
+
firebrick: [178, 34, 34],
|
|
45
|
+
darkred: [139, 0, 0],
|
|
46
|
+
darkgreen: [0, 100, 0],
|
|
47
|
+
darkblue: [0, 0, 139],
|
|
48
|
+
darkcyan: [0, 139, 139],
|
|
49
|
+
darkmagenta: [139, 0, 139],
|
|
50
|
+
darkviolet: [148, 0, 211],
|
|
51
|
+
deeppink: [255, 20, 147],
|
|
52
|
+
deepskyblue: [0, 191, 255],
|
|
53
|
+
dodgerblue: [30, 144, 255],
|
|
54
|
+
hotpink: [255, 105, 180],
|
|
55
|
+
lawngreen: [124, 252, 0],
|
|
56
|
+
limegreen: [50, 205, 50],
|
|
57
|
+
mediumblue: [0, 0, 205],
|
|
58
|
+
mediumorchid: [186, 85, 211],
|
|
59
|
+
mediumpurple: [147, 111, 219],
|
|
60
|
+
mediumseagreen: [60, 179, 113],
|
|
61
|
+
mediumslateblue: [123, 104, 238],
|
|
62
|
+
mediumspringgreen: [0, 250, 154],
|
|
63
|
+
mediumturquoise: [72, 209, 204],
|
|
64
|
+
mediumvioletred: [199, 21, 133],
|
|
65
|
+
midnightblue: [25, 25, 112],
|
|
66
|
+
orangered: [255, 69, 0],
|
|
67
|
+
palegreen: [152, 251, 152],
|
|
68
|
+
palevioletred: [219, 112, 147],
|
|
69
|
+
royalblue: [65, 105, 225],
|
|
70
|
+
saddlebrown: [139, 69, 19],
|
|
71
|
+
seagreen: [46, 139, 87],
|
|
72
|
+
skyblue: [135, 206, 235],
|
|
73
|
+
slateblue: [106, 90, 205],
|
|
74
|
+
springgreen: [0, 255, 127],
|
|
75
|
+
steelblue: [70, 130, 180],
|
|
76
|
+
turquoise: [64, 224, 208],
|
|
77
|
+
violet: [238, 130, 238],
|
|
78
|
+
wheat: [245, 222, 179],
|
|
79
|
+
yellowgreen: [154, 205, 50],
|
|
80
|
+
// Achromatic named colors
|
|
81
|
+
dimgray: [105, 105, 105],
|
|
82
|
+
dimgrey: [105, 105, 105],
|
|
83
|
+
darkgray: [169, 169, 169],
|
|
84
|
+
darkgrey: [169, 169, 169],
|
|
85
|
+
lightgray: [211, 211, 211],
|
|
86
|
+
lightgrey: [211, 211, 211],
|
|
87
|
+
gainsboro: [220, 220, 220],
|
|
88
|
+
whitesmoke: [245, 245, 245],
|
|
89
|
+
};
|
|
90
|
+
// ---------------------------------------------------------------------------
|
|
91
|
+
// Achromatic color names (allowed in inactive icons)
|
|
92
|
+
// ---------------------------------------------------------------------------
|
|
93
|
+
const ACHROMATIC_NAMES = new Set([
|
|
94
|
+
'black',
|
|
95
|
+
'white',
|
|
96
|
+
'gray',
|
|
97
|
+
'grey',
|
|
98
|
+
'silver',
|
|
99
|
+
'dimgray',
|
|
100
|
+
'dimgrey',
|
|
101
|
+
'darkgray',
|
|
102
|
+
'darkgrey',
|
|
103
|
+
'lightgray',
|
|
104
|
+
'lightgrey',
|
|
105
|
+
'gainsboro',
|
|
106
|
+
'whitesmoke',
|
|
107
|
+
]);
|
|
108
|
+
// Values that are not actual colors and should be passed through unchanged
|
|
109
|
+
const PASSTHROUGH_VALUES = new Set(['none', 'currentcolor', 'transparent', 'inherit', 'unset', 'initial']);
|
|
110
|
+
// Color-carrying attributes in SVG
|
|
111
|
+
const COLOR_ATTRS = ['fill', 'stroke', 'stop-color', 'flood-color'];
|
|
112
|
+
// Event handler attributes to reject
|
|
113
|
+
const EVENT_HANDLER_RE = /\bon(?:abort|activate|afterprint|beforeprint|beforeunload|blur|cancel|canplay|canplaythrough|change|click|close|contextmenu|copy|cuechange|cut|dblclick|drag|dragend|dragenter|dragleave|dragover|dragstart|drop|durationchange|emptied|ended|error|focus|focusin|focusout|formdata|fullscreenchange|fullscreenerror|hashchange|input|invalid|keydown|keypress|keyup|load|loadeddata|loadedmetadata|loadstart|message|messageerror|mousedown|mouseenter|mouseleave|mousemove|mouseout|mouseover|mouseup|offline|online|open|pagehide|pageshow|paste|pause|play|playing|pointercancel|pointerdown|pointerenter|pointerleave|pointermove|pointerout|pointerover|pointerup|popstate|progress|ratechange|reset|resize|scroll|securitypolicyviolation|seeked|seeking|select|slotchange|stalled|storage|submit|suspend|timeupdate|toggle|touchcancel|touchend|touchmove|touchstart|transitioncancel|transitionend|transitionrun|transitionstart|unhandledrejection|unload|volumechange|waiting|wheel)\s*=/i;
|
|
114
|
+
// ---------------------------------------------------------------------------
|
|
115
|
+
// Color parsing utilities
|
|
116
|
+
// ---------------------------------------------------------------------------
|
|
117
|
+
/** Parse a hex color (#RGB or #RRGGBB) to [R, G, B] */
|
|
118
|
+
const parseHex = (hex) => {
|
|
119
|
+
const h = hex.trim();
|
|
120
|
+
if (h.length === 4) {
|
|
121
|
+
const c1 = h[1] ?? '0';
|
|
122
|
+
const c2 = h[2] ?? '0';
|
|
123
|
+
const c3 = h[3] ?? '0';
|
|
124
|
+
const r = parseInt(c1 + c1, 16);
|
|
125
|
+
const g = parseInt(c2 + c2, 16);
|
|
126
|
+
const b = parseInt(c3 + c3, 16);
|
|
127
|
+
if (Number.isNaN(r) || Number.isNaN(g) || Number.isNaN(b))
|
|
128
|
+
return null;
|
|
129
|
+
return [r, g, b];
|
|
130
|
+
}
|
|
131
|
+
if (h.length === 7) {
|
|
132
|
+
const r = parseInt(h.slice(1, 3), 16);
|
|
133
|
+
const g = parseInt(h.slice(3, 5), 16);
|
|
134
|
+
const b = parseInt(h.slice(5, 7), 16);
|
|
135
|
+
if (Number.isNaN(r) || Number.isNaN(g) || Number.isNaN(b))
|
|
136
|
+
return null;
|
|
137
|
+
return [r, g, b];
|
|
138
|
+
}
|
|
139
|
+
return null;
|
|
140
|
+
};
|
|
141
|
+
/** Convert HSL to RGB. h is 0-360, s/l are 0-100 percentages. */
|
|
142
|
+
const hslToRgb = (h, s, l) => {
|
|
143
|
+
const sn = s / 100;
|
|
144
|
+
const ln = l / 100;
|
|
145
|
+
const c = (1 - Math.abs(2 * ln - 1)) * sn;
|
|
146
|
+
const x = c * (1 - Math.abs(((h / 60) % 2) - 1));
|
|
147
|
+
const m = ln - c / 2;
|
|
148
|
+
let r1, g1, b1;
|
|
149
|
+
if (h < 60) {
|
|
150
|
+
[r1, g1, b1] = [c, x, 0];
|
|
151
|
+
}
|
|
152
|
+
else if (h < 120) {
|
|
153
|
+
[r1, g1, b1] = [x, c, 0];
|
|
154
|
+
}
|
|
155
|
+
else if (h < 180) {
|
|
156
|
+
[r1, g1, b1] = [0, c, x];
|
|
157
|
+
}
|
|
158
|
+
else if (h < 240) {
|
|
159
|
+
[r1, g1, b1] = [0, x, c];
|
|
160
|
+
}
|
|
161
|
+
else if (h < 300) {
|
|
162
|
+
[r1, g1, b1] = [x, 0, c];
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
[r1, g1, b1] = [c, 0, x];
|
|
166
|
+
}
|
|
167
|
+
return [Math.round((r1 + m) * 255), Math.round((g1 + m) * 255), Math.round((b1 + m) * 255)];
|
|
168
|
+
};
|
|
169
|
+
/** Compute luminance-equivalent gray value using ITU-R BT.709 */
|
|
170
|
+
const toLuminanceGray = (r, g, b) => Math.round(0.2126 * r + 0.7152 * g + 0.0722 * b);
|
|
171
|
+
/** Convert a gray value (0-255) to a two-digit hex string */
|
|
172
|
+
const grayToHex = (gray) => {
|
|
173
|
+
const h = Math.max(0, Math.min(255, gray)).toString(16).padStart(2, '0');
|
|
174
|
+
return `#${h}${h}${h}`;
|
|
175
|
+
};
|
|
176
|
+
/**
|
|
177
|
+
* Parse a CSS color value into [R, G, B] or null if not a recognizable color.
|
|
178
|
+
* Returns null for passthrough values (none, currentColor, etc.) and url() references.
|
|
179
|
+
*/
|
|
180
|
+
const parseColor = (value) => {
|
|
181
|
+
const v = value.trim();
|
|
182
|
+
const vLower = v.toLowerCase();
|
|
183
|
+
// Passthrough values
|
|
184
|
+
if (PASSTHROUGH_VALUES.has(vLower))
|
|
185
|
+
return null;
|
|
186
|
+
// URL references (e.g., url(#gradient))
|
|
187
|
+
if (vLower.startsWith('url('))
|
|
188
|
+
return null;
|
|
189
|
+
// Hex colors
|
|
190
|
+
if (v.startsWith('#'))
|
|
191
|
+
return parseHex(v);
|
|
192
|
+
// rgb()/rgba()
|
|
193
|
+
const rgbMatch = vLower.match(/^rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)/);
|
|
194
|
+
if (rgbMatch) {
|
|
195
|
+
return [parseInt(rgbMatch[1] ?? '0', 10), parseInt(rgbMatch[2] ?? '0', 10), parseInt(rgbMatch[3] ?? '0', 10)];
|
|
196
|
+
}
|
|
197
|
+
// hsl()/hsla()
|
|
198
|
+
const hslMatch = vLower.match(/^hsla?\(\s*([\d.]+)\s*,\s*([\d.]+)%\s*,\s*([\d.]+)%/);
|
|
199
|
+
if (hslMatch) {
|
|
200
|
+
return hslToRgb(parseFloat(hslMatch[1] ?? '0'), parseFloat(hslMatch[2] ?? '0'), parseFloat(hslMatch[3] ?? '0'));
|
|
201
|
+
}
|
|
202
|
+
// Named colors
|
|
203
|
+
const named = NAMED_COLORS[vLower];
|
|
204
|
+
if (named)
|
|
205
|
+
return named;
|
|
206
|
+
return null;
|
|
207
|
+
};
|
|
208
|
+
/** Check if a parsed RGB is achromatic (R === G === B) */
|
|
209
|
+
const isAchromatic = (r, g, b) => r === g && g === b;
|
|
210
|
+
/** Check if a CSS color string is achromatic (or a passthrough value) */
|
|
211
|
+
const isAchromaticColor = (value) => {
|
|
212
|
+
const v = value.trim().toLowerCase();
|
|
213
|
+
if (PASSTHROUGH_VALUES.has(v))
|
|
214
|
+
return true;
|
|
215
|
+
if (v.startsWith('url('))
|
|
216
|
+
return true;
|
|
217
|
+
if (ACHROMATIC_NAMES.has(v))
|
|
218
|
+
return true;
|
|
219
|
+
// hsl/hsla — check saturation is 0
|
|
220
|
+
const hslMatch = v.match(/^hsla?\(\s*[\d.]+\s*,\s*([\d.]+)%/);
|
|
221
|
+
if (hslMatch)
|
|
222
|
+
return parseFloat(hslMatch[1] ?? '0') === 0;
|
|
223
|
+
const rgb = parseColor(v);
|
|
224
|
+
if (!rgb)
|
|
225
|
+
return true; // Unrecognized values are considered achromatic
|
|
226
|
+
return isAchromatic(rgb[0], rgb[1], rgb[2]);
|
|
227
|
+
};
|
|
228
|
+
/**
|
|
229
|
+
* Validate an SVG string for use as a plugin icon.
|
|
230
|
+
* Checks: size <= 8KB, viewBox present and square, no <image>/<script>,
|
|
231
|
+
* no event handler attributes.
|
|
232
|
+
*/
|
|
233
|
+
const validateIconSvg = (content, _filename) => {
|
|
234
|
+
const errors = [];
|
|
235
|
+
// Size check (byte count, not string length)
|
|
236
|
+
const byteSize = new TextEncoder().encode(content).byteLength;
|
|
237
|
+
if (byteSize > MAX_ICON_SIZE) {
|
|
238
|
+
errors.push(`SVG size (${byteSize} bytes) exceeds maximum of ${MAX_ICON_SIZE} bytes (8 KB)`);
|
|
239
|
+
}
|
|
240
|
+
// viewBox check
|
|
241
|
+
const viewBoxMatch = content.match(/viewBox\s*=\s*["']([^"']*)["']/);
|
|
242
|
+
if (!viewBoxMatch) {
|
|
243
|
+
errors.push('SVG must have a viewBox attribute');
|
|
244
|
+
}
|
|
245
|
+
else {
|
|
246
|
+
const viewBoxValue = viewBoxMatch[1] ?? '';
|
|
247
|
+
const parts = viewBoxValue.trim().split(/\s+/);
|
|
248
|
+
if (parts.length === 4) {
|
|
249
|
+
const w = parseFloat(parts[2] ?? '0');
|
|
250
|
+
const h = parseFloat(parts[3] ?? '0');
|
|
251
|
+
if (w !== h) {
|
|
252
|
+
errors.push(`SVG viewBox must be square (got ${w}x${h})`);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
else {
|
|
256
|
+
errors.push('SVG viewBox must have exactly 4 values (min-x min-y width height)');
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
// Forbidden elements: <image>
|
|
260
|
+
if (/<image[\s/>]/i.test(content)) {
|
|
261
|
+
errors.push('SVG must not contain <image> elements');
|
|
262
|
+
}
|
|
263
|
+
// Forbidden elements: <script>
|
|
264
|
+
if (/<script[\s/>]/i.test(content)) {
|
|
265
|
+
errors.push('SVG must not contain <script> elements');
|
|
266
|
+
}
|
|
267
|
+
// Event handler attributes
|
|
268
|
+
if (EVENT_HANDLER_RE.test(content)) {
|
|
269
|
+
errors.push('SVG must not contain event handler attributes (e.g., onclick, onload, onerror)');
|
|
270
|
+
}
|
|
271
|
+
return errors.length === 0 ? { valid: true } : { valid: false, errors };
|
|
272
|
+
};
|
|
273
|
+
// ---------------------------------------------------------------------------
|
|
274
|
+
// validateInactiveIconColors
|
|
275
|
+
// ---------------------------------------------------------------------------
|
|
276
|
+
/**
|
|
277
|
+
* Validate that an SVG contains only achromatic colors.
|
|
278
|
+
* Checks fill, stroke, stop-color, and flood-color attributes and inline styles.
|
|
279
|
+
*/
|
|
280
|
+
const validateInactiveIconColors = (content) => {
|
|
281
|
+
const errors = [];
|
|
282
|
+
// Check attribute values: (fill|stroke|stop-color|flood-color)="value"
|
|
283
|
+
const attrPattern = new RegExp(`(${COLOR_ATTRS.join('|')})\\s*=\\s*"([^"]*)"`, 'gi');
|
|
284
|
+
let attrMatch;
|
|
285
|
+
while ((attrMatch = attrPattern.exec(content)) !== null) {
|
|
286
|
+
const attr = attrMatch[1] ?? '';
|
|
287
|
+
const value = (attrMatch[2] ?? '').trim();
|
|
288
|
+
if (value && !isAchromaticColor(value)) {
|
|
289
|
+
errors.push(`Attribute ${attr}="${value}" uses a saturated color`);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
// Check inline style property values: style="fill: value; stroke: value"
|
|
293
|
+
const stylePattern = /style\s*=\s*"([^"]*)"/gi;
|
|
294
|
+
let styleMatch;
|
|
295
|
+
while ((styleMatch = stylePattern.exec(content)) !== null) {
|
|
296
|
+
const styleValue = styleMatch[1] ?? '';
|
|
297
|
+
for (const attr of COLOR_ATTRS) {
|
|
298
|
+
const propPattern = new RegExp(`${attr.replace('-', '\\-')}\\s*:\\s*([^;"]+)`, 'gi');
|
|
299
|
+
let propMatch;
|
|
300
|
+
while ((propMatch = propPattern.exec(styleValue)) !== null) {
|
|
301
|
+
const value = (propMatch[1] ?? '').trim();
|
|
302
|
+
if (value && !isAchromaticColor(value)) {
|
|
303
|
+
errors.push(`Style property ${attr}: ${value} uses a saturated color`);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
return errors.length === 0 ? { valid: true } : { valid: false, errors };
|
|
309
|
+
};
|
|
310
|
+
// ---------------------------------------------------------------------------
|
|
311
|
+
// generateInactiveIcon
|
|
312
|
+
// ---------------------------------------------------------------------------
|
|
313
|
+
/**
|
|
314
|
+
* Convert a single color value to its grayscale equivalent.
|
|
315
|
+
* Returns the original value for passthrough values (none, currentColor, etc.)
|
|
316
|
+
*/
|
|
317
|
+
const convertColorToGray = (value) => {
|
|
318
|
+
const v = value.trim();
|
|
319
|
+
const vLower = v.toLowerCase();
|
|
320
|
+
if (PASSTHROUGH_VALUES.has(vLower))
|
|
321
|
+
return v;
|
|
322
|
+
if (vLower.startsWith('url('))
|
|
323
|
+
return v;
|
|
324
|
+
// hsl/hsla — set saturation to 0, preserve everything else
|
|
325
|
+
const hslaMatch = vLower.match(/^(hsla?)\(\s*([\d.]+)\s*,\s*[\d.]+%\s*,\s*([\d.]+%)\s*(?:,\s*([\d.]+))?\s*\)/);
|
|
326
|
+
if (hslaMatch) {
|
|
327
|
+
const fn = hslaMatch[1] ?? 'hsl';
|
|
328
|
+
const hue = hslaMatch[2] ?? '0';
|
|
329
|
+
const lightness = hslaMatch[3] ?? '50%';
|
|
330
|
+
const alpha = hslaMatch[4];
|
|
331
|
+
if (alpha !== undefined) {
|
|
332
|
+
return `${fn}(${hue}, 0%, ${lightness}, ${alpha})`;
|
|
333
|
+
}
|
|
334
|
+
return `${fn}(${hue}, 0%, ${lightness})`;
|
|
335
|
+
}
|
|
336
|
+
// rgba — convert and preserve alpha
|
|
337
|
+
const rgbaMatch = vLower.match(/^rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*([\d.]+)\s*\)/);
|
|
338
|
+
if (rgbaMatch) {
|
|
339
|
+
const r = parseInt(rgbaMatch[1] ?? '0', 10);
|
|
340
|
+
const g = parseInt(rgbaMatch[2] ?? '0', 10);
|
|
341
|
+
const b = parseInt(rgbaMatch[3] ?? '0', 10);
|
|
342
|
+
const a = rgbaMatch[4] ?? '1';
|
|
343
|
+
const gray = toLuminanceGray(r, g, b);
|
|
344
|
+
return `rgba(${gray}, ${gray}, ${gray}, ${a})`;
|
|
345
|
+
}
|
|
346
|
+
// rgb()
|
|
347
|
+
const rgbMatch = vLower.match(/^rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/);
|
|
348
|
+
if (rgbMatch) {
|
|
349
|
+
const r = parseInt(rgbMatch[1] ?? '0', 10);
|
|
350
|
+
const g = parseInt(rgbMatch[2] ?? '0', 10);
|
|
351
|
+
const b = parseInt(rgbMatch[3] ?? '0', 10);
|
|
352
|
+
const gray = toLuminanceGray(r, g, b);
|
|
353
|
+
return grayToHex(gray);
|
|
354
|
+
}
|
|
355
|
+
// Hex colors
|
|
356
|
+
if (v.startsWith('#')) {
|
|
357
|
+
const rgb = parseHex(v);
|
|
358
|
+
if (rgb) {
|
|
359
|
+
const gray = toLuminanceGray(rgb[0], rgb[1], rgb[2]);
|
|
360
|
+
return grayToHex(gray);
|
|
361
|
+
}
|
|
362
|
+
return v;
|
|
363
|
+
}
|
|
364
|
+
// Named colors
|
|
365
|
+
const named = NAMED_COLORS[vLower];
|
|
366
|
+
if (named) {
|
|
367
|
+
const gray = toLuminanceGray(named[0], named[1], named[2]);
|
|
368
|
+
return grayToHex(gray);
|
|
369
|
+
}
|
|
370
|
+
return v;
|
|
371
|
+
};
|
|
372
|
+
/**
|
|
373
|
+
* Convert all color values in an SVG to luminance-equivalent grays.
|
|
374
|
+
* Processes fill, stroke, stop-color, and flood-color in both attributes and inline styles.
|
|
375
|
+
* Uses ITU-R BT.709: gray = 0.2126*R + 0.7152*G + 0.0722*B
|
|
376
|
+
*/
|
|
377
|
+
const generateInactiveIcon = (svgContent) => {
|
|
378
|
+
let result = svgContent;
|
|
379
|
+
// Convert attribute values: (fill|stroke|stop-color|flood-color)="value"
|
|
380
|
+
const attrPattern = new RegExp(`((?:${COLOR_ATTRS.join('|')})\\s*=\\s*")([^"]*)(")`, 'gi');
|
|
381
|
+
result = result.replace(attrPattern, (_match, prefix, value, suffix) => {
|
|
382
|
+
const converted = convertColorToGray(value);
|
|
383
|
+
return `${prefix}${converted}${suffix}`;
|
|
384
|
+
});
|
|
385
|
+
// Convert inline style property values
|
|
386
|
+
const stylePattern = /style\s*=\s*"([^"]*)"/gi;
|
|
387
|
+
result = result.replace(stylePattern, (fullMatch, styleValue) => {
|
|
388
|
+
let newStyle = styleValue;
|
|
389
|
+
for (const attr of COLOR_ATTRS) {
|
|
390
|
+
const propPattern = new RegExp(`(${attr.replace('-', '\\-')}\\s*:\\s*)([^;"]+)`, 'gi');
|
|
391
|
+
newStyle = newStyle.replace(propPattern, (_m, propPrefix, propValue) => {
|
|
392
|
+
const converted = convertColorToGray(propValue);
|
|
393
|
+
return `${propPrefix}${converted}`;
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
return fullMatch.replace(styleValue, newStyle);
|
|
397
|
+
});
|
|
398
|
+
return result;
|
|
399
|
+
};
|
|
400
|
+
export { generateInactiveIcon, MAX_ICON_SIZE, validateIconSvg, validateInactiveIconColors };
|
|
401
|
+
//# sourceMappingURL=validate-icon.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-icon.js","sourceRoot":"","sources":["../src/validate-icon.ts"],"names":[],"mappings":"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"}
|