@ncds/ui-admin-mcp 1.0.0-alpha.16 → 1.0.0-alpha.18
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/bin/components.bundle.js +17 -1
- package/bin/definitions/external/step-guide.d.ts +61 -0
- package/bin/definitions/external/step-guide.js +52 -0
- package/bin/definitions/js-api.json +47 -13
- package/bin/tools/external/editor.d.ts +3 -2
- package/bin/tools/external/editor.js +1 -1
- package/bin/tools/external/step-guide.d.ts +19 -0
- package/bin/tools/external/step-guide.js +79 -0
- package/bin/tools/getComponentProps.d.ts +3 -0
- package/bin/tools/getComponentProps.js +2 -2
- package/bin/tools/ping.d.ts +1 -1
- package/bin/tools/renderToHtml.js +9 -1
- package/bin/tools/searchComponent.d.ts +5 -0
- package/bin/tools/searchComponent.js +3 -3
- package/bin/tools/validateHtml.d.ts +8 -6
- package/bin/tools/validateHtml.js +6 -6
- package/bin/utils/bemValidator.d.ts +8 -6
- package/bin/utils/bemValidator.js +16 -4
- package/bin/utils/compliance.d.ts +7 -6
- package/bin/utils/compliance.js +5 -3
- package/bin/utils/dataLoader.d.ts +16 -14
- package/bin/utils/dataLoader.js +3 -2
- package/bin/utils/fuzzyMatch.js +1 -0
- package/bin/utils/response.js +1 -1
- package/bin/utils/tokenValidator.d.ts +4 -3
- package/bin/utils/tokenValidator.js +13 -11
- package/bin/version.d.ts +4 -2
- package/bin/version.js +4 -2
- package/data/_icons.json +317 -2
- package/data/block-container.json +95 -0
- package/data/block-header.json +208 -0
- package/data/combo-box.json +1 -2
- package/data/data-grid.json +33 -5
- package/data/dropdown.json +11 -1
- package/data/file-input.json +6 -5
- package/data/image-file-input.json +6 -5
- package/data/input-base.json +1 -1
- package/data/modal.json +5 -2
- package/data/notification.json +30 -22
- package/data/number-input.json +1 -1
- package/data/page-title.json +135 -0
- package/data/pagination.json +8 -4
- package/data/password-input.json +25 -10
- package/data/progress-bar.json +6 -5
- package/data/progress-circle.json +8 -5
- package/data/radio.json +3 -2
- package/data/select-box.json +17 -10
- package/data/step-guide.json +130 -0
- package/data/table.json +50 -6
- package/data/tag.json +7 -4
- package/package.json +13 -11
|
@@ -3,12 +3,11 @@
|
|
|
3
3
|
*
|
|
4
4
|
* 토큰 검증은 tokenValidator.ts에 분리.
|
|
5
5
|
*/
|
|
6
|
-
import { parse } from 'node-html-parser';
|
|
7
|
-
import type {
|
|
6
|
+
import type { parse } from 'node-html-parser';
|
|
7
|
+
import type { ComplianceError, ComplianceRulesData, ComplianceSummary, ComponentData } from '../types.js';
|
|
8
8
|
import type { ValidationError } from './bemValidator.js';
|
|
9
|
-
export { detectTokenIssues } from './tokenValidator.js';
|
|
10
9
|
/** NCUA 컴포넌트 누락 감지 — 태그 인덱스로 O(n) 매칭 */
|
|
11
|
-
|
|
10
|
+
declare const detectNcuaOmission: (params: {
|
|
12
11
|
root: ReturnType<typeof parse>;
|
|
13
12
|
complianceRules: ComplianceRulesData;
|
|
14
13
|
componentMap: Map<string, ComponentData>;
|
|
@@ -20,7 +19,7 @@ export declare const detectNcuaOmission: (params: {
|
|
|
20
19
|
};
|
|
21
20
|
};
|
|
22
21
|
/** NCUA 컴포넌트 내부 커스텀 스타일 감지 */
|
|
23
|
-
|
|
22
|
+
declare const detectCustomNotSeparated: (params: {
|
|
24
23
|
root: ReturnType<typeof parse>;
|
|
25
24
|
rootClassMap: Map<string, string>;
|
|
26
25
|
warnings: ValidationError[];
|
|
@@ -32,7 +31,7 @@ export declare const detectCustomNotSeparated: (params: {
|
|
|
32
31
|
};
|
|
33
32
|
};
|
|
34
33
|
/** 준수도 점수 + 요약 빌드 */
|
|
35
|
-
|
|
34
|
+
declare const buildComplianceSummary: (params: {
|
|
36
35
|
ncuaErrors: ComplianceError[];
|
|
37
36
|
tokenErrors: ComplianceError[];
|
|
38
37
|
customErrors: ComplianceError[];
|
|
@@ -50,3 +49,5 @@ export declare const buildComplianceSummary: (params: {
|
|
|
50
49
|
violated: number;
|
|
51
50
|
};
|
|
52
51
|
}) => ComplianceSummary;
|
|
52
|
+
export { buildComplianceSummary, detectCustomNotSeparated, detectNcuaOmission };
|
|
53
|
+
export { detectTokenIssues } from './tokenValidator.js';
|
package/bin/utils/compliance.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.detectTokenIssues = exports.detectNcuaOmission = exports.detectCustomNotSeparated = exports.buildComplianceSummary = void 0;
|
|
4
4
|
const bemValidator_js_1 = require("./bemValidator.js");
|
|
5
|
-
var tokenValidator_js_1 = require("./tokenValidator.js");
|
|
6
|
-
Object.defineProperty(exports, "detectTokenIssues", { enumerable: true, get: function () { return tokenValidator_js_1.detectTokenIssues; } });
|
|
7
5
|
// ── 상수 ─────────────────────────────────────────────────────────────────
|
|
8
6
|
const MAX_COMPLIANCE_ERRORS = 10;
|
|
9
7
|
const NCUA_NOT_USED_MEDIUM_WEIGHT = 0.5;
|
|
@@ -188,8 +186,10 @@ const buildComplianceSummary = (params) => {
|
|
|
188
186
|
ncuaNotUsedCount +
|
|
189
187
|
(tokenUsage.correct + tokenUsage.missing + tokenUsage.invalid) +
|
|
190
188
|
(customSeparation.clean + customSeparation.violated);
|
|
189
|
+
// biome-ignore lint/style/noMagicNumbers: 점수 0~1 boundary (clamp)
|
|
191
190
|
const score = totalCheckpoints === 0 ? 1.0 : Math.max(0, Math.min(1, 1 - weightedViolations / totalCheckpoints));
|
|
192
191
|
return {
|
|
192
|
+
// biome-ignore lint/style/noMagicNumbers: 2자리 소수점 반올림 (×100/100)
|
|
193
193
|
score: Math.round(score * 100) / 100,
|
|
194
194
|
errors: allErrors.slice(0, MAX_COMPLIANCE_ERRORS),
|
|
195
195
|
ncuaUsage,
|
|
@@ -199,3 +199,5 @@ const buildComplianceSummary = (params) => {
|
|
|
199
199
|
};
|
|
200
200
|
};
|
|
201
201
|
exports.buildComplianceSummary = buildComplianceSummary;
|
|
202
|
+
var tokenValidator_js_1 = require("./tokenValidator.js");
|
|
203
|
+
Object.defineProperty(exports, "detectTokenIssues", { enumerable: true, get: function () { return tokenValidator_js_1.detectTokenIssues; } });
|
|
@@ -1,34 +1,36 @@
|
|
|
1
|
-
import type { ComponentData, IconData,
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import type { ComplianceRulesData, ComponentData, IconData, JsApiInfo, TokenData } from '../types.js';
|
|
2
|
+
declare const DEFAULT_DATA_DIR: string;
|
|
3
|
+
interface CdnMeta {
|
|
4
4
|
version: string;
|
|
5
5
|
css: string;
|
|
6
6
|
js: string;
|
|
7
7
|
}
|
|
8
|
-
|
|
8
|
+
interface IconMeta {
|
|
9
9
|
packageName: string;
|
|
10
10
|
version: string;
|
|
11
11
|
}
|
|
12
12
|
/** data/ 디렉토리의 JSON 파일을 읽어 componentMap으로 반환 */
|
|
13
|
-
|
|
13
|
+
declare const loadComponentsFromDir: (dataDir: string) => Map<string, ComponentData>;
|
|
14
14
|
/** data/_icons.json을 읽어 IconData로 반환 (파일 없으면 빈 데이터) */
|
|
15
|
-
|
|
15
|
+
declare const loadIconData: (dataDir: string) => IconData;
|
|
16
16
|
/** _meta.json 파싱 결과 */
|
|
17
|
-
|
|
17
|
+
interface MetaData {
|
|
18
18
|
cdn: CdnMeta | null;
|
|
19
19
|
icon: IconMeta | null;
|
|
20
20
|
}
|
|
21
21
|
/** data/_meta.json에서 CDN + icon 메타를 1회 읽기로 로드 */
|
|
22
|
-
|
|
22
|
+
declare const loadMeta: (dataDir: string) => MetaData;
|
|
23
23
|
/** data/_tokens.json을 읽어 TokenData로 반환 (파일 없으면 빈 데이터) */
|
|
24
|
-
|
|
24
|
+
declare const loadTokenData: (dataDir: string) => TokenData;
|
|
25
25
|
/** definitions/compliance-rules.json을 로드하여 ComplianceRulesData로 반환 (파일 없으면 null) */
|
|
26
|
-
|
|
26
|
+
declare const loadComplianceRules: (definitionsDir: string) => ComplianceRulesData | null;
|
|
27
27
|
/** definitions/instructions.md를 로드하여 문자열 반환 */
|
|
28
|
-
|
|
28
|
+
declare const loadInstructions: (definitionsDir: string) => string;
|
|
29
29
|
/** definitions/js-api.json을 로드하여 exportName→JsApiInfo Map 반환 */
|
|
30
|
-
|
|
30
|
+
declare const loadJsApi: (definitionsDir: string) => Map<string, JsApiInfo>;
|
|
31
31
|
/** componentMap에서 이름으로 단일 컴포넌트 조회 */
|
|
32
|
-
|
|
32
|
+
declare const getComponent: (map: Map<string, ComponentData>, name: string) => ComponentData | undefined;
|
|
33
33
|
/** componentMap의 모든 컴포넌트를 배열로 반환 */
|
|
34
|
-
|
|
34
|
+
declare const getAllComponents: (map: Map<string, ComponentData>) => ComponentData[];
|
|
35
|
+
export { DEFAULT_DATA_DIR, getAllComponents, getComponent, loadComplianceRules, loadComponentsFromDir, loadIconData, loadInstructions, loadJsApi, loadMeta, loadTokenData, };
|
|
36
|
+
export type { CdnMeta, IconMeta, MetaData };
|
package/bin/utils/dataLoader.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
6
|
+
exports.loadTokenData = exports.loadMeta = exports.loadJsApi = exports.loadInstructions = exports.loadIconData = exports.loadComponentsFromDir = exports.loadComplianceRules = exports.getComponent = exports.getAllComponents = exports.DEFAULT_DATA_DIR = void 0;
|
|
7
7
|
/**
|
|
8
8
|
* dataLoader — mcp/data/*.json + definitions/ 파일을 읽어 반환
|
|
9
9
|
*
|
|
@@ -17,7 +17,8 @@ const fs_1 = __importDefault(require("fs"));
|
|
|
17
17
|
const path_1 = __importDefault(require("path"));
|
|
18
18
|
const logger_js_1 = require("./logger.js");
|
|
19
19
|
const response_js_1 = require("./response.js");
|
|
20
|
-
|
|
20
|
+
const DEFAULT_DATA_DIR = path_1.default.resolve(__dirname, '../../data');
|
|
21
|
+
exports.DEFAULT_DATA_DIR = DEFAULT_DATA_DIR;
|
|
21
22
|
// ── 검증 헬퍼 (§ 3.8 복잡한 조건을 의도가 드러나는 이름으로 분리) ──────────
|
|
22
23
|
/** JSON.parse 결과가 name: string 필드를 가진 컴포넌트 객체인지 검증 */
|
|
23
24
|
const isValidComponentJson = (data) => !!data && typeof data === 'object' && 'name' in data && typeof data.name === 'string';
|
package/bin/utils/fuzzyMatch.js
CHANGED
|
@@ -63,6 +63,7 @@ exports.similarity = similarity;
|
|
|
63
63
|
*
|
|
64
64
|
* @returns null이면 매칭 실패, FuzzyResult면 매칭 성공
|
|
65
65
|
*/
|
|
66
|
+
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: 정확/포함/퍼지 단계별 매칭 분기 — 알고리즘 본질, 별 리팩토링 거리
|
|
66
67
|
const fuzzyMatch = (query, target) => {
|
|
67
68
|
const q = normalize(query);
|
|
68
69
|
const t = normalize(target);
|
package/bin/utils/response.js
CHANGED
|
@@ -27,7 +27,7 @@ const componentNotFoundResponse = (name) => (0, exports.errorResponse)('COMPONEN
|
|
|
27
27
|
exports.componentNotFoundResponse = componentNotFoundResponse;
|
|
28
28
|
/** ping 미호출 시 응답에 핵심 rules를 주입하는 래퍼 */
|
|
29
29
|
const appendPingReminder = (response, reminder) => {
|
|
30
|
-
const text = response.content[0].text
|
|
30
|
+
const text = `${response.content[0].text}\n\n${reminder}`;
|
|
31
31
|
return { ...response, content: [{ type: 'text', text }] };
|
|
32
32
|
};
|
|
33
33
|
exports.appendPingReminder = appendPingReminder;
|
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
import type { parse } from 'node-html-parser';
|
|
7
7
|
import type { ComplianceError, TokenData } from '../types.js';
|
|
8
8
|
/** hex 값(lowercase) → 토큰 CSS 변수명 배열 역방향 매핑 빌드 — server.ts에서 1회 호출 */
|
|
9
|
-
|
|
9
|
+
declare const buildTokenValueMap: (tokenData: TokenData) => Map<string, string[]>;
|
|
10
10
|
/** inline style + <style> 블록의 CSS 텍스트를 하나로 합침 */
|
|
11
|
-
|
|
11
|
+
declare const extractAllCss: (root: ReturnType<typeof parse>) => string;
|
|
12
12
|
/** 토큰 미사용 + 무효 토큰 감지 */
|
|
13
|
-
|
|
13
|
+
declare const detectTokenIssues: (params: {
|
|
14
14
|
root: ReturnType<typeof parse>;
|
|
15
15
|
tokenData: TokenData;
|
|
16
16
|
tokenValueMap: Map<string, string[]>;
|
|
@@ -22,3 +22,4 @@ export declare const detectTokenIssues: (params: {
|
|
|
22
22
|
invalid: number;
|
|
23
23
|
};
|
|
24
24
|
};
|
|
25
|
+
export { buildTokenValueMap, detectTokenIssues, extractAllCss };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.extractAllCss = exports.detectTokenIssues = exports.buildTokenValueMap = void 0;
|
|
4
4
|
// ── server.ts 사전 계산용 ───────────────────────────────────────────────
|
|
5
5
|
/** hex 값(lowercase) → 토큰 CSS 변수명 배열 역방향 매핑 빌드 — server.ts에서 1회 호출 */
|
|
6
6
|
const buildTokenValueMap = (tokenData) => {
|
|
@@ -25,14 +25,18 @@ const HEX_PATTERN_SOURCE = /#([0-9a-fA-F]{3,8})\b/g.source;
|
|
|
25
25
|
const RGB_PATTERN_SOURCE = /rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)/g.source;
|
|
26
26
|
const VAR_PATTERN_SOURCE = /var\(\s*(--[a-zA-Z0-9-]+)(?:\s*,\s*[^)]+)?\s*\)/g.source;
|
|
27
27
|
// ── 순수 헬퍼 ────────────────────────────────────────────────────────────
|
|
28
|
+
const HEX_RADIX = 16;
|
|
29
|
+
const HEX_BYTE_LENGTH = 2;
|
|
30
|
+
const HEX_SHORT_LENGTH = 3;
|
|
31
|
+
const HEX_FULL_LENGTH = 6;
|
|
28
32
|
/** rgb(r,g,b) → #rrggbb hex 변환 */
|
|
29
|
-
const rgbToHex = (r, g, b) => `#${[r, g, b].map((v) => v.toString(
|
|
33
|
+
const rgbToHex = (r, g, b) => `#${[r, g, b].map((v) => v.toString(HEX_RADIX).padStart(HEX_BYTE_LENGTH, '0')).join('')}`;
|
|
30
34
|
/** 3자리 hex를 6자리로 정규화 */
|
|
31
35
|
const normalizeHex = (hex) => {
|
|
32
36
|
const h = hex.toLowerCase().replace('#', '');
|
|
33
|
-
if (h.length ===
|
|
37
|
+
if (h.length === HEX_SHORT_LENGTH)
|
|
34
38
|
return `#${h[0]}${h[0]}${h[1]}${h[1]}${h[2]}${h[2]}`;
|
|
35
|
-
return `#${h.slice(0,
|
|
39
|
+
return `#${h.slice(0, HEX_FULL_LENGTH)}`;
|
|
36
40
|
};
|
|
37
41
|
/** var()의 prefix가 토큰 시스템에 속하는지 확인 */
|
|
38
42
|
const hasKnownTokenPrefix = (varName, prefixSet) => {
|
|
@@ -83,16 +87,15 @@ exports.extractAllCss = extractAllCss;
|
|
|
83
87
|
/** CSS 텍스트에서 하드코딩된 색상값(hex/rgb)을 추출 */
|
|
84
88
|
const collectHardcodedColors = (css) => {
|
|
85
89
|
const colors = [];
|
|
86
|
-
let match;
|
|
87
90
|
const hexPattern = new RegExp(HEX_PATTERN_SOURCE, 'g');
|
|
88
|
-
|
|
91
|
+
for (const match of css.matchAll(hexPattern)) {
|
|
89
92
|
colors.push({ raw: match[0], normalized: normalizeHex(match[0]) });
|
|
90
93
|
}
|
|
91
94
|
const rgbPattern = new RegExp(RGB_PATTERN_SOURCE, 'g');
|
|
92
|
-
|
|
95
|
+
for (const match of css.matchAll(rgbPattern)) {
|
|
93
96
|
colors.push({
|
|
94
97
|
raw: match[0],
|
|
95
|
-
normalized: rgbToHex(parseInt(match[1], 10), parseInt(match[2], 10), parseInt(match[3], 10)),
|
|
98
|
+
normalized: rgbToHex(Number.parseInt(match[1], 10), Number.parseInt(match[2], 10), Number.parseInt(match[3], 10)),
|
|
96
99
|
});
|
|
97
100
|
}
|
|
98
101
|
return colors;
|
|
@@ -126,9 +129,8 @@ const collectInvalidTokenErrors = (css, tokenNameSet, tokenPrefixSet) => {
|
|
|
126
129
|
const errors = [];
|
|
127
130
|
let correct = 0;
|
|
128
131
|
let invalid = 0;
|
|
129
|
-
let varMatch;
|
|
130
132
|
const varPattern = new RegExp(VAR_PATTERN_SOURCE, 'g');
|
|
131
|
-
|
|
133
|
+
for (const varMatch of css.matchAll(varPattern)) {
|
|
132
134
|
const varName = varMatch[1];
|
|
133
135
|
if (!hasKnownTokenPrefix(varName, tokenPrefixSet))
|
|
134
136
|
continue;
|
|
@@ -151,7 +153,7 @@ const collectInvalidTokenErrors = (css, tokenNameSet, tokenPrefixSet) => {
|
|
|
151
153
|
/** 토큰 미사용 + 무효 토큰 감지 */
|
|
152
154
|
const detectTokenIssues = (params) => {
|
|
153
155
|
const { root, tokenData, tokenValueMap } = params;
|
|
154
|
-
const allCss =
|
|
156
|
+
const allCss = extractAllCss(root);
|
|
155
157
|
const notUsed = collectTokenNotUsedErrors(allCss, tokenValueMap);
|
|
156
158
|
const invalidResult = collectInvalidTokenErrors(allCss, buildTokenNameSet(tokenData), buildTokenPrefixSet(tokenData));
|
|
157
159
|
return {
|
package/bin/version.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* NCDS UI Admin MCP 서버가 노출하는 ui-admin 정합 기준 버전.
|
|
3
|
+
* scripts/generate-version-ts.ts 가 ui-admin/package.json 의 version 으로부터 자동 생성한다.
|
|
4
|
+
* 수동 편집 금지 — 빌드(`pnpm generate:version-ts` 또는 `pnpm build`) 시 덮어쓰여진다.
|
|
3
5
|
*/
|
|
4
|
-
export declare const VERSION = "1.
|
|
6
|
+
export declare const VERSION = "1.8.4";
|
package/bin/version.js
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.VERSION = void 0;
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* NCDS UI Admin MCP 서버가 노출하는 ui-admin 정합 기준 버전.
|
|
6
|
+
* scripts/generate-version-ts.ts 가 ui-admin/package.json 의 version 으로부터 자동 생성한다.
|
|
7
|
+
* 수동 편집 금지 — 빌드(`pnpm generate:version-ts` 또는 `pnpm build`) 시 덮어쓰여진다.
|
|
6
8
|
*/
|
|
7
|
-
exports.VERSION = '1.
|
|
9
|
+
exports.VERSION = '1.8.4';
|