@moewolf/moe-icons-cli 0.0.1 → 0.0.3
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 +249 -10
- package/bin/check-node.cjs +36 -0
- package/bin/moeicons.js +12 -1
- package/dist/api/client.d.ts +13 -2
- package/dist/api/client.js +145 -21
- package/dist/auth/device-login.d.ts +10 -7
- package/dist/auth/device-login.js +60 -37
- package/dist/auth/login-schemas.d.ts +24 -0
- package/dist/auth/login-schemas.js +67 -0
- package/dist/catalog/catalog.d.ts +11 -0
- package/dist/catalog/catalog.js +43 -0
- package/dist/catalog/catalog.json +12768 -3965
- package/dist/cli.d.ts +11 -2
- package/dist/cli.js +773 -147
- package/dist/commands/parser.d.ts +13 -2
- package/dist/commands/parser.js +138 -50
- package/dist/config-package/generated/SOURCE.json +25 -0
- package/dist/config-package/generated/moeicons-config.schema.json +191 -0
- package/dist/config-package/generated/moeicons.config.jsonc +42 -0
- package/dist/config-package/generated/render-config.cjs +145 -0
- package/dist/config-package/generated/validate-config.cjs +293 -0
- package/dist/config-package/generated-config.d.ts +32 -0
- package/dist/config-package/generated-config.js +19 -0
- package/dist/core/auth.d.ts +24 -0
- package/dist/core/auth.js +127 -8
- package/dist/core/bitmap-assets.d.ts +19 -5
- package/dist/core/bitmap-assets.js +40 -31
- package/dist/core/bitmap-shard-budget.d.ts +43 -0
- package/dist/core/bitmap-shard-budget.js +16 -0
- package/dist/core/bitmap-shard-cache.d.ts +68 -0
- package/dist/core/bitmap-shard-cache.js +115 -0
- package/dist/core/bitmap-shard-download.d.ts +130 -0
- package/dist/core/bitmap-shard-download.js +359 -0
- package/dist/core/bitmap-shard-resolver.d.ts +129 -0
- package/dist/core/bitmap-shard-resolver.js +262 -0
- package/dist/core/bitmap-shards.d.ts +70 -0
- package/dist/core/bitmap-shards.js +249 -0
- package/dist/core/bootstrap.d.ts +37 -0
- package/dist/core/bootstrap.js +54 -0
- package/dist/core/cache.d.ts +34 -0
- package/dist/core/cache.js +96 -0
- package/dist/core/context.d.ts +26 -0
- package/dist/core/doctor.d.ts +48 -0
- package/dist/core/doctor.js +190 -0
- package/dist/core/free-download.d.ts +64 -6
- package/dist/core/free-download.js +402 -30
- package/dist/core/generate.d.ts +29 -0
- package/dist/core/generate.js +341 -65
- package/dist/core/icon-selection.d.ts +8 -0
- package/dist/core/icon-selection.js +19 -0
- package/dist/core/install.d.ts +14 -0
- package/dist/core/install.js +132 -13
- package/dist/core/library-update.d.ts +5 -1
- package/dist/core/library-update.js +176 -17
- package/dist/core/local-test-env.d.ts +24 -0
- package/dist/core/local-test-env.js +43 -0
- package/dist/core/metadata-sync.d.ts +30 -0
- package/dist/core/metadata-sync.js +97 -0
- package/dist/core/pro-download.d.ts +63 -0
- package/dist/core/pro-download.js +247 -27
- package/dist/core/pro-install.d.ts +11 -3
- package/dist/core/pro-install.js +181 -19
- package/dist/core/pro-resources.d.ts +79 -0
- package/dist/core/pro-resources.js +204 -0
- package/dist/core/pro-selected-download.d.ts +18 -0
- package/dist/core/pro-selected-download.js +269 -0
- package/dist/core/release-descriptor.d.ts +42 -1
- package/dist/core/release-descriptor.js +117 -9
- package/dist/core/resource-variant.d.ts +27 -10
- package/dist/core/resource-variant.js +75 -34
- package/dist/core/selected-resources.d.ts +59 -0
- package/dist/core/selected-resources.js +350 -0
- package/dist/core/signed-artifact.d.ts +8 -1
- package/dist/core/signed-artifact.js +35 -11
- package/dist/core/target-subtree.d.ts +8 -0
- package/dist/core/target-subtree.js +54 -3
- package/dist/core/version-service.d.ts +11 -0
- package/dist/core/version-service.js +129 -24
- package/dist/core/wizard.d.ts +20 -17
- package/dist/core/wizard.js +66 -28
- package/dist/errors/errors.d.ts +2 -1
- package/dist/errors/errors.js +1 -0
- package/dist/generator/generate.d.ts +1 -1
- package/dist/generator/generate.js +420 -213
- package/dist/generator/shared/SOURCE.json +7 -0
- package/dist/generator/shared/svg-model.cjs +156 -0
- package/dist/generator/svg-model.d.ts +16 -0
- package/dist/generator/svg-model.js +4 -0
- package/dist/generator/theme-resolve.d.ts +2 -0
- package/dist/generator/theme-resolve.js +57 -26
- package/dist/mcp/server.d.ts +23 -36
- package/dist/mcp/server.js +74 -152
- package/dist/mcp/services.d.ts +4 -0
- package/dist/mcp/services.js +230 -0
- package/dist/metadata/archive.d.ts +38 -0
- package/dist/metadata/archive.js +94 -0
- package/dist/metadata/manifest.d.ts +33 -0
- package/dist/metadata/manifest.js +136 -0
- package/dist/metadata/version.d.ts +22 -0
- package/dist/metadata/version.js +53 -0
- package/dist/project/anchors/application.d.ts +13 -0
- package/dist/project/anchors/application.js +377 -0
- package/dist/project/anchors/apply.d.ts +28 -0
- package/dist/project/anchors/apply.js +65 -0
- package/dist/project/anchors/diagnose.d.ts +26 -0
- package/dist/project/anchors/diagnose.js +90 -0
- package/dist/project/anchors/helpers.d.ts +20 -0
- package/dist/project/anchors/helpers.js +55 -0
- package/dist/project/anchors/moeicons-config.d.ts +21 -0
- package/dist/project/anchors/moeicons-config.js +83 -0
- package/dist/project/anchors/parse.d.ts +14 -0
- package/dist/project/anchors/parse.js +36 -0
- package/dist/project/anchors/project-manifest.d.ts +19 -0
- package/dist/project/anchors/project-manifest.js +109 -0
- package/dist/project/anchors/style.d.ts +12 -0
- package/dist/project/anchors/style.js +87 -0
- package/dist/project/anchors/types.d.ts +32 -0
- package/dist/project/anchors/types.js +9 -0
- package/dist/project/config.d.ts +59 -5
- package/dist/project/config.js +234 -102
- package/dist/project/install-metadata.d.ts +23 -2
- package/dist/project/install-metadata.js +58 -7
- package/dist/project/install.d.ts +24 -4
- package/dist/project/install.js +402 -190
- package/dist/project/project-lock.d.ts +2 -2
- package/dist/project/project-lock.js +4 -4
- package/dist/project/tailwind.d.ts +2 -2
- package/dist/project/tailwind.js +3 -4
- package/dist/project/tar-gz.d.ts +18 -1
- package/dist/project/tar-gz.js +40 -3
- package/dist/tui/components.d.ts +62 -0
- package/dist/tui/components.js +100 -0
- package/dist/tui/primitives.d.ts +1 -0
- package/dist/tui/primitives.js +8 -1
- package/dist/ui/banner.d.ts +31 -3
- package/dist/ui/banner.js +120 -25
- package/dist/ui/branded-prompts.d.ts +41 -0
- package/dist/ui/branded-prompts.js +80 -0
- package/dist/ui/clack.d.ts +6 -3
- package/dist/ui/clack.js +56 -5
- package/dist/ui/create-ui.d.ts +1 -0
- package/dist/ui/create-ui.js +5 -1
- package/dist/ui/generated/wordmark-large.d.ts +17 -0
- package/dist/ui/generated/wordmark-large.js +28 -0
- package/dist/ui/generated/wordmark.d.ts +2 -0
- package/dist/ui/generated/wordmark.js +2 -0
- package/dist/ui/non-interactive.js +8 -0
- package/dist/ui/stream.js +30 -0
- package/dist/ui/theme.d.ts +42 -0
- package/dist/ui/theme.js +59 -0
- package/package.json +14 -6
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"sourceRepo": "moewolf-dev/moe-icons-code-library",
|
|
3
|
+
"sourcePath": "scripts/svg-model.cjs",
|
|
4
|
+
"sourceCommit": "d8342a7b94ab18aab0581c23ca9e8be919eed8e1",
|
|
5
|
+
"sourceCommitExact": true,
|
|
6
|
+
"sha256": "f03ef4ef87898d5ec74047b2acd62a74656ed094ba484571ad0f8736c3a265fb"
|
|
7
|
+
}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Canonical, dependency-free XML subset for SVG generation. No DTD/entity
|
|
4
|
+
// expansion or browser DOM dependency; malformed input fails before emission.
|
|
5
|
+
function decodeXml(value) {
|
|
6
|
+
return value.replace(/&([^;\s<]*);|&/g, (whole, entity) => {
|
|
7
|
+
const named = { amp: '&', lt: '<', gt: '>', quot: '"', apos: "'" };
|
|
8
|
+
if (Object.hasOwn(named, entity)) return named[entity];
|
|
9
|
+
if (entity && /^#(?:x[0-9a-f]+|[0-9]+)$/i.test(entity)) {
|
|
10
|
+
const point = entity[1].toLowerCase() === 'x' ? parseInt(entity.slice(2), 16) : Number(entity.slice(1));
|
|
11
|
+
if (point === 9 || point === 10 || point === 13 || (point >= 32 && point <= 0x10ffff && !(point >= 0xd800 && point <= 0xdfff) && point !== 0xfffe && point !== 0xffff)) return String.fromCodePoint(point);
|
|
12
|
+
}
|
|
13
|
+
throw new Error(`unsupported or invalid XML entity: ${whole}`);
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function escapeXml(value) {
|
|
18
|
+
return String(value).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function parseAttributes(source) {
|
|
22
|
+
const attrs = [];
|
|
23
|
+
const seen = new Set();
|
|
24
|
+
let rest = source;
|
|
25
|
+
while (rest.trim()) {
|
|
26
|
+
const match = /^\s+([A-Za-z_:][\w:.-]*)\s*=\s*(?:"([^"]*)"|'([^']*)')/.exec(rest);
|
|
27
|
+
if (!match) throw new Error(`invalid SVG attribute syntax: ${rest.slice(0, 80)}`);
|
|
28
|
+
const name = match[1];
|
|
29
|
+
if (seen.has(name)) throw new Error(`duplicate SVG attribute: ${name}`);
|
|
30
|
+
if (/^on/i.test(name)) throw new Error(`unsupported SVG event attribute: ${name}`);
|
|
31
|
+
seen.add(name);
|
|
32
|
+
const encoded = match[2] ?? match[3];
|
|
33
|
+
if (encoded.includes('<')) throw new Error(`invalid XML attribute: ${name}`);
|
|
34
|
+
attrs.push([name, decodeXml(encoded)]);
|
|
35
|
+
rest = rest.slice(match[0].length);
|
|
36
|
+
}
|
|
37
|
+
return attrs;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function parseNodes(source) {
|
|
41
|
+
const root = { children: [] };
|
|
42
|
+
const stack = [root];
|
|
43
|
+
let index = 0;
|
|
44
|
+
while (index < source.length) {
|
|
45
|
+
if (source.startsWith('<!--', index)) {
|
|
46
|
+
const end = source.indexOf('-->', index + 4);
|
|
47
|
+
if (end < 0 || source.slice(index + 4, end).includes('--')) throw new Error('invalid XML comment');
|
|
48
|
+
index = end + 3;
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
if (source.startsWith('<![CDATA[', index)) {
|
|
52
|
+
const end = source.indexOf(']]>', index + 9);
|
|
53
|
+
if (end < 0) throw new Error('unclosed SVG CDATA');
|
|
54
|
+
stack.at(-1).children.push({ text: source.slice(index + 9, end) });
|
|
55
|
+
index = end + 3;
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
if (source.startsWith('<?xml', index) && index === 0) {
|
|
59
|
+
const end = source.indexOf('?>', index + 5);
|
|
60
|
+
if (end < 0) throw new Error('unclosed XML declaration');
|
|
61
|
+
index = end + 2;
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
if (source[index] !== '<') {
|
|
65
|
+
const end = source.indexOf('<', index);
|
|
66
|
+
const text = decodeXml(source.slice(index, end < 0 ? source.length : end));
|
|
67
|
+
// Formatting whitespace outside text nodes has no SVG paint semantics.
|
|
68
|
+
if (text.trim() || ['text', 'tspan'].includes(stack.at(-1).name)) stack.at(-1).children.push({ text });
|
|
69
|
+
index = end < 0 ? source.length : end;
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
let end = index + 1;
|
|
73
|
+
let quote;
|
|
74
|
+
for (; end < source.length; end++) {
|
|
75
|
+
const character = source[end];
|
|
76
|
+
if (quote) { if (character === quote) quote = undefined; }
|
|
77
|
+
else if (character === '"' || character === "'") quote = character;
|
|
78
|
+
else if (character === '>') break;
|
|
79
|
+
}
|
|
80
|
+
if (end === source.length) throw new Error('unclosed SVG tag');
|
|
81
|
+
const tag = source.slice(index + 1, end);
|
|
82
|
+
if (tag.startsWith('/')) {
|
|
83
|
+
const name = tag.slice(1).trim();
|
|
84
|
+
if (stack.length === 1 || stack.at(-1).name !== name) throw new Error(`mismatched SVG closing tag: ${name}`);
|
|
85
|
+
stack.pop();
|
|
86
|
+
} else {
|
|
87
|
+
const selfClosing = /\/\s*$/.test(tag);
|
|
88
|
+
const body = selfClosing ? tag.replace(/\/\s*$/, '') : tag;
|
|
89
|
+
const match = /^([A-Za-z_][\w:.-]*)/.exec(body);
|
|
90
|
+
if (!match || /^(?:script|foreignObject)$/i.test(match[1])) throw new Error(`unsupported SVG element: ${body.slice(0, 80)}`);
|
|
91
|
+
const node = { name: match[1], attrs: parseAttributes(body.slice(match[0].length)), children: [] };
|
|
92
|
+
stack.at(-1).children.push(node);
|
|
93
|
+
if (!selfClosing) stack.push(node);
|
|
94
|
+
}
|
|
95
|
+
index = end + 1;
|
|
96
|
+
}
|
|
97
|
+
if (stack.length !== 1) throw new Error(`unclosed SVG element: ${stack.at(-1).name}`);
|
|
98
|
+
return root.children;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function parseSvg(source) {
|
|
102
|
+
const nodes = parseNodes(source.trim());
|
|
103
|
+
if (nodes.length !== 1 || nodes[0].name !== 'svg') throw new Error('SVG document must have one svg root');
|
|
104
|
+
const root = nodes[0];
|
|
105
|
+
return { viewBox: new Map(root.attrs).get('viewBox') ?? '0 0 24 24', rootAttrs: root.attrs, children: root.children };
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function serializeNodes(nodes) {
|
|
109
|
+
return nodes.map((node) => Object.hasOwn(node, 'text') ? escapeXml(node.text) :
|
|
110
|
+
`<${node.name}${node.attrs.map(([name, value]) => ` ${name}="${escapeXml(value)}"`).join('')}${node.children.length ? `>${serializeNodes(node.children)}</${node.name}>` : ' />'}`).join('');
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const ROOT_METADATA = new Set(['viewBox', 'width', 'height', 'xmlns', 'xmlns:xlink', 'version']);
|
|
114
|
+
function rootPaintAttributes(rootAttrs, strategy) {
|
|
115
|
+
const attrs = new Map(rootAttrs.filter(([name]) => !ROOT_METADATA.has(name)));
|
|
116
|
+
if (strategy === 'outline') {
|
|
117
|
+
if (!attrs.has('stroke')) attrs.set('stroke', 'currentColor');
|
|
118
|
+
if (!attrs.has('fill')) attrs.set('fill', 'none');
|
|
119
|
+
if (!attrs.has('stroke-width')) attrs.set('stroke-width', '2');
|
|
120
|
+
} else if (strategy === 'solid' && !attrs.has('fill')) attrs.set('fill', 'currentColor');
|
|
121
|
+
return attrs;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function normalizePaintChildren(children, strategy, rootAttrs = []) {
|
|
125
|
+
const graphic = new Set(['path', 'circle', 'ellipse', 'line', 'polyline', 'polygon', 'rect', 'text', 'use', 'image']);
|
|
126
|
+
const rootWidth = new Map(rootAttrs).get('stroke-width') ?? '2';
|
|
127
|
+
return children.map((node) => {
|
|
128
|
+
if (Object.hasOwn(node, 'text')) return node;
|
|
129
|
+
const attrs = node.attrs.flatMap(([name, value]) => {
|
|
130
|
+
if (!graphic.has(node.name)) return [[name, value]];
|
|
131
|
+
if (strategy === 'outline' && name === 'stroke-width' && value === '2' && rootWidth === '2') return [];
|
|
132
|
+
const tint = /^(?:black|#000(?:000)?)$/i.test(value);
|
|
133
|
+
return [[name, tint && ((strategy === 'outline' && name === 'stroke') || (strategy === 'solid' && name === 'fill')) ? 'currentColor' : value]];
|
|
134
|
+
});
|
|
135
|
+
const inherited = new Map(rootAttrs);
|
|
136
|
+
const localWidth = new Map(node.attrs).get('stroke-width');
|
|
137
|
+
if (localWidth !== undefined) inherited.set('stroke-width', localWidth);
|
|
138
|
+
return { ...node, attrs, children: normalizePaintChildren(node.children, strategy, [...inherited]) };
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function prepareSvg(source, strategy) {
|
|
143
|
+
const model = parseSvg(source);
|
|
144
|
+
// Approved Figma artboard pair. Never remove a lone/other painted rect.
|
|
145
|
+
const [first, second] = model.children;
|
|
146
|
+
if (first?.name === 'rect' && second?.name === 'rect' && !first.children.length && !second.children.length) {
|
|
147
|
+
const a = new Map(first.attrs), b = new Map(second.attrs);
|
|
148
|
+
if (a.size === 3 && a.get('width') === '24' && a.get('height') === '24' && a.get('fill') === '#1E1E1E' &&
|
|
149
|
+
b.size === 4 && /^\d+$/.test(b.get('width') ?? '') && /^\d+$/.test(b.get('height') ?? '') &&
|
|
150
|
+
/^translate\(-?\d+(?:\.\d+)? -?\d+(?:\.\d+)?\)$/.test(b.get('transform') ?? '') && b.get('fill') === 'white') model.children = model.children.slice(2);
|
|
151
|
+
}
|
|
152
|
+
model.children = normalizePaintChildren(model.children, strategy, model.rootAttrs);
|
|
153
|
+
return model;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
module.exports = { decodeXml, escapeXml, parseAttributes, parseNodes, parseSvg, prepareSvg, serializeNodes, rootPaintAttributes };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type SvgNode = {
|
|
2
|
+
readonly name: string;
|
|
3
|
+
readonly attrs: readonly [string, string][];
|
|
4
|
+
readonly children: readonly SvgNode[];
|
|
5
|
+
readonly text?: never;
|
|
6
|
+
} | {
|
|
7
|
+
readonly text: string;
|
|
8
|
+
};
|
|
9
|
+
interface SvgModel {
|
|
10
|
+
viewBox: string;
|
|
11
|
+
rootAttrs: readonly [string, string][];
|
|
12
|
+
children: readonly SvgNode[];
|
|
13
|
+
}
|
|
14
|
+
export declare const prepareSvg: (source: string, strategy: string) => SvgModel;
|
|
15
|
+
export declare const rootPaintAttributes: (attrs: readonly [string, string][], strategy: string) => Map<string, string>;
|
|
16
|
+
export {};
|
|
@@ -10,6 +10,8 @@ export interface ResolvedTheme {
|
|
|
10
10
|
readonly group: CatalogStyleGroup;
|
|
11
11
|
readonly variant?: ResourceVariant;
|
|
12
12
|
}
|
|
13
|
+
/** Exact availability check: catalog `variants` is authoritative when present. */
|
|
14
|
+
export declare function isVariantAvailable(group: CatalogStyleGroup, resourceVariantId: string): boolean;
|
|
13
15
|
export declare function resolveThemes(config: MoeiconsConfigFile, sourceCatalog?: IconCatalog): {
|
|
14
16
|
readonly ok: true;
|
|
15
17
|
readonly themes: ResolvedTheme[];
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
import { catalog, findCatalogStyleGroup } from "../catalog/catalog.js";
|
|
2
|
-
import { assetRelativePath, resolveResourceVariant, } from "../core/resource-variant.js";
|
|
2
|
+
import { assetRelativePath, buildResourceVariantId, DEFAULT_BITMAP_FORMAT, DEFAULT_BITMAP_SIZE, resolveResourceVariant, } from "../core/resource-variant.js";
|
|
3
3
|
import { toLibraryExportName, toProxyName } from "../core/icon-names.js";
|
|
4
|
+
/** Exact availability check: catalog `variants` is authoritative when present. */
|
|
5
|
+
export function isVariantAvailable(group, resourceVariantId) {
|
|
6
|
+
if (group.variants && group.variants.length > 0)
|
|
7
|
+
return group.variants.includes(resourceVariantId);
|
|
8
|
+
const parts = resourceVariantId.split("-");
|
|
9
|
+
const format = parts[parts.length - 1];
|
|
10
|
+
const imageSize = Number(parts[parts.length - 2]);
|
|
11
|
+
return group.formats.includes(format) && group.imageSizes.includes(imageSize);
|
|
12
|
+
}
|
|
4
13
|
export function resolveThemes(config, sourceCatalog = catalog) {
|
|
5
14
|
const errors = [];
|
|
6
15
|
const themes = [];
|
|
@@ -12,15 +21,25 @@ export function resolveThemes(config, sourceCatalog = catalog) {
|
|
|
12
21
|
}
|
|
13
22
|
if (group.type === "bitmap") {
|
|
14
23
|
try {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
24
|
+
let variant;
|
|
25
|
+
if (entry.format === undefined && entry.imageSize === undefined) {
|
|
26
|
+
// B6: the default is only usable when the group truly declares it.
|
|
27
|
+
const defaultId = buildResourceVariantId(group.id, DEFAULT_BITMAP_FORMAT, DEFAULT_BITMAP_SIZE);
|
|
28
|
+
if (!isVariantAvailable(group, defaultId)) {
|
|
29
|
+
errors.push(`bitmap group "${group.id}" does not include the default ${DEFAULT_BITMAP_FORMAT}/${String(DEFAULT_BITMAP_SIZE)} variant; set format and imageSize explicitly`);
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
variant = resolveResourceVariant(group.id);
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
variant = resolveResourceVariant(group.id, {
|
|
36
|
+
...(entry.format !== undefined ? { format: entry.format } : {}),
|
|
37
|
+
...(entry.imageSize !== undefined ? { imageSize: entry.imageSize } : {}),
|
|
38
|
+
});
|
|
21
39
|
}
|
|
22
|
-
if (!group
|
|
23
|
-
errors.push(`
|
|
40
|
+
if (!isVariantAvailable(group, variant.resourceVariantId)) {
|
|
41
|
+
errors.push(`variant ${variant.resourceVariantId} is unavailable for ${group.id}`);
|
|
42
|
+
continue;
|
|
24
43
|
}
|
|
25
44
|
themes.push({ theme, entry, kind: "bitmap", group, variant });
|
|
26
45
|
}
|
|
@@ -49,24 +68,30 @@ export function relativeAssetImportFromIcons(variant, iconId) {
|
|
|
49
68
|
export function reactBitmapWrapperSource(iconId, wrapperName, variant, themeClassName) {
|
|
50
69
|
const assetImport = relativeAssetImportFromIcons(variant, iconId);
|
|
51
70
|
const defaultClass = themeClassName ? JSON.stringify(themeClassName) : "undefined";
|
|
52
|
-
return `import
|
|
71
|
+
return `import * as React from "react";
|
|
72
|
+
import type { IconProps } from "../types";
|
|
53
73
|
import { cn } from "../cn";
|
|
54
74
|
import assetUrl from "${assetImport}";
|
|
55
75
|
|
|
56
|
-
export
|
|
57
|
-
const { className, size, "aria-label": ariaLabel, strokeWidth: _strokeWidth, ...rest } = props;
|
|
58
|
-
const
|
|
76
|
+
export const ${wrapperName} = /* @__PURE__ */ React.forwardRef<HTMLImageElement, IconProps>((props, ref) => {
|
|
77
|
+
const { className, size, alt, "aria-label": ariaLabel, strokeWidth: _strokeWidth, ...rest } = props;
|
|
78
|
+
const label = ariaLabel ?? alt ?? (typeof rest.title === "string" ? rest.title : undefined);
|
|
79
|
+
const named = Boolean(label || rest["aria-labelledby"]);
|
|
80
|
+
const imageSource = typeof assetUrl === "string" ? assetUrl : (assetUrl as { src: string }).src;
|
|
59
81
|
return (
|
|
60
82
|
<img
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
83
|
+
ref={ref}
|
|
84
|
+
src={imageSource}
|
|
85
|
+
width={size ?? 24}
|
|
86
|
+
height={size ?? 24}
|
|
87
|
+
alt={label ?? ""}
|
|
88
|
+
aria-hidden={named ? undefined : true}
|
|
64
89
|
draggable={false}
|
|
65
|
-
className={cn("moe-icon", ${defaultClass},
|
|
90
|
+
className={cn("moe-icon", ${defaultClass}, className)}
|
|
66
91
|
{...rest}
|
|
67
92
|
/>
|
|
68
93
|
);
|
|
69
|
-
}
|
|
94
|
+
});
|
|
70
95
|
`;
|
|
71
96
|
}
|
|
72
97
|
export function vueBitmapWrapperSource(iconId, wrapperName, variant, themeClassName) {
|
|
@@ -76,21 +101,27 @@ export function vueBitmapWrapperSource(iconId, wrapperName, variant, themeClassN
|
|
|
76
101
|
import { cn } from "../cn";
|
|
77
102
|
import assetUrl from "${assetImport}";
|
|
78
103
|
|
|
79
|
-
export const ${wrapperName} = defineComponent({
|
|
104
|
+
export const ${wrapperName} = /* @__PURE__ */ defineComponent({
|
|
80
105
|
name: "${wrapperName}",
|
|
106
|
+
inheritAttrs: false,
|
|
81
107
|
setup(_props, { attrs }) {
|
|
82
108
|
return () => {
|
|
83
|
-
const className = typeof attrs.class === "string" ? attrs.class : undefined;
|
|
84
109
|
const size = typeof attrs.size === "number" ? attrs.size : undefined;
|
|
85
110
|
const ariaLabel = typeof attrs["aria-label"] === "string" ? attrs["aria-label"] : undefined;
|
|
86
|
-
const
|
|
111
|
+
const alt = typeof attrs.alt === "string" ? attrs.alt : undefined;
|
|
112
|
+
const label = ariaLabel ?? alt ?? (typeof attrs.title === "string" ? attrs.title : undefined);
|
|
113
|
+
const named = Boolean(label || attrs["aria-labelledby"]);
|
|
114
|
+
const imageAttrs = { ...attrs };
|
|
115
|
+
delete imageAttrs.size;
|
|
87
116
|
return h("img", {
|
|
88
|
-
...
|
|
117
|
+
...imageAttrs,
|
|
89
118
|
src: assetUrl,
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
119
|
+
width: attrs.width ?? size ?? 24,
|
|
120
|
+
height: attrs.height ?? size ?? 24,
|
|
121
|
+
alt: label ?? "",
|
|
122
|
+
"aria-hidden": attrs["aria-hidden"] ?? (named ? undefined : true),
|
|
123
|
+
draggable: attrs.draggable ?? false,
|
|
124
|
+
class: cn("moe-icon", ${defaultClass}, attrs.class as Parameters<typeof cn>[number]),
|
|
94
125
|
});
|
|
95
126
|
};
|
|
96
127
|
},
|
package/dist/mcp/server.d.ts
CHANGED
|
@@ -1,32 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
*/
|
|
6
|
-
interface McpRequest {
|
|
7
|
-
readonly jsonrpc: "2.0";
|
|
8
|
-
readonly id: number | string;
|
|
9
|
-
readonly method: string;
|
|
10
|
-
readonly params?: Record<string, unknown>;
|
|
11
|
-
}
|
|
12
|
-
interface McpResponse {
|
|
13
|
-
readonly jsonrpc: "2.0";
|
|
14
|
-
readonly id: number | string;
|
|
15
|
-
readonly result?: unknown;
|
|
16
|
-
readonly error?: {
|
|
17
|
-
code: number;
|
|
18
|
-
message: string;
|
|
19
|
-
};
|
|
1
|
+
export interface McpTool {
|
|
2
|
+
readonly name: string;
|
|
3
|
+
readonly description: string;
|
|
4
|
+
readonly inputSchema: Record<string, unknown>;
|
|
20
5
|
}
|
|
21
6
|
export interface McpServices {
|
|
22
|
-
readonly listIconGroups: () => Promise<
|
|
23
|
-
|
|
24
|
-
displayName: string;
|
|
25
|
-
}[]>;
|
|
26
|
-
readonly getAccount: () => Promise<{
|
|
27
|
-
accountId: string;
|
|
28
|
-
tier: string;
|
|
29
|
-
} | undefined>;
|
|
7
|
+
readonly listIconGroups: () => Promise<unknown>;
|
|
8
|
+
readonly getAccount: () => Promise<unknown>;
|
|
30
9
|
readonly installIconGroup: (args: {
|
|
31
10
|
groupId: string;
|
|
32
11
|
projectPath: string;
|
|
@@ -34,24 +13,32 @@ export interface McpServices {
|
|
|
34
13
|
ok: boolean;
|
|
35
14
|
message: string;
|
|
36
15
|
}>;
|
|
16
|
+
readonly tools?: readonly McpTool[];
|
|
17
|
+
readonly callTool?: (name: string, args: Record<string, unknown>) => Promise<unknown>;
|
|
37
18
|
}
|
|
38
19
|
export interface McpDeps {
|
|
39
20
|
readonly services: McpServices;
|
|
40
21
|
readonly stdout: (text: string) => void;
|
|
41
22
|
readonly stderr: (text: string) => void;
|
|
42
23
|
readonly signal?: AbortSignal;
|
|
24
|
+
readonly projectRoot?: string;
|
|
25
|
+
}
|
|
26
|
+
interface Response {
|
|
27
|
+
jsonrpc: "2.0";
|
|
28
|
+
id: number | string | null;
|
|
29
|
+
result?: unknown;
|
|
30
|
+
error?: {
|
|
31
|
+
code: number;
|
|
32
|
+
message: string;
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
export declare class McpArgumentError extends Error {
|
|
43
36
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
* handles one decoded JSON-RPC message.
|
|
47
|
-
*/
|
|
37
|
+
export declare const isRecord: (v: unknown) => v is Record<string, unknown>;
|
|
38
|
+
export declare function safeMcpValue(value: unknown, projectRoot?: string): unknown;
|
|
48
39
|
export declare function createMcpServer(deps: McpDeps): {
|
|
49
|
-
handle: (
|
|
40
|
+
handle: (value: unknown) => Promise<Response | undefined>;
|
|
50
41
|
};
|
|
51
|
-
/**
|
|
52
|
-
* Read JSON-RPC messages from an async iterable of lines and write responses to
|
|
53
|
-
* stdout. Used by the stdio transport.
|
|
54
|
-
*/
|
|
55
42
|
export declare function runMcpStdio(deps: McpDeps & {
|
|
56
43
|
lines: AsyncIterable<string>;
|
|
57
44
|
}): Promise<void>;
|