@hua-labs/hua-ux 0.1.0-alpha.0.1
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 +839 -0
- package/dist/framework/a11y/components/LiveRegion.d.ts +64 -0
- package/dist/framework/a11y/components/LiveRegion.d.ts.map +1 -0
- package/dist/framework/a11y/components/LiveRegion.js +43 -0
- package/dist/framework/a11y/components/SkipToContent.d.ts +62 -0
- package/dist/framework/a11y/components/SkipToContent.d.ts.map +1 -0
- package/dist/framework/a11y/components/SkipToContent.js +60 -0
- package/dist/framework/a11y/hooks/useFocusManagement.d.ts +60 -0
- package/dist/framework/a11y/hooks/useFocusManagement.d.ts.map +1 -0
- package/dist/framework/a11y/hooks/useFocusManagement.js +71 -0
- package/dist/framework/a11y/hooks/useFocusTrap.d.ts +64 -0
- package/dist/framework/a11y/hooks/useFocusTrap.d.ts.map +1 -0
- package/dist/framework/a11y/hooks/useFocusTrap.js +185 -0
- package/dist/framework/a11y/hooks/useLiveRegion.d.ts +56 -0
- package/dist/framework/a11y/hooks/useLiveRegion.d.ts.map +1 -0
- package/dist/framework/a11y/hooks/useLiveRegion.js +60 -0
- package/dist/framework/a11y/index.d.ts +16 -0
- package/dist/framework/a11y/index.d.ts.map +1 -0
- package/dist/framework/a11y/index.js +11 -0
- package/dist/framework/branding/context.d.ts +52 -0
- package/dist/framework/branding/context.d.ts.map +1 -0
- package/dist/framework/branding/context.js +96 -0
- package/dist/framework/branding/css-vars.d.ts +34 -0
- package/dist/framework/branding/css-vars.d.ts.map +1 -0
- package/dist/framework/branding/css-vars.js +95 -0
- package/dist/framework/branding/tailwind-config.d.ts +38 -0
- package/dist/framework/branding/tailwind-config.d.ts.map +1 -0
- package/dist/framework/branding/tailwind-config.js +66 -0
- package/dist/framework/components/BrandedButton.d.ts +53 -0
- package/dist/framework/components/BrandedButton.d.ts.map +1 -0
- package/dist/framework/components/BrandedButton.js +40 -0
- package/dist/framework/components/BrandedCard.d.ts +52 -0
- package/dist/framework/components/BrandedCard.d.ts.map +1 -0
- package/dist/framework/components/BrandedCard.js +73 -0
- package/dist/framework/components/ErrorBoundary.d.ts +92 -0
- package/dist/framework/components/ErrorBoundary.d.ts.map +1 -0
- package/dist/framework/components/ErrorBoundary.js +121 -0
- package/dist/framework/components/HuaUxLayout.d.ts +29 -0
- package/dist/framework/components/HuaUxLayout.d.ts.map +1 -0
- package/dist/framework/components/HuaUxLayout.js +32 -0
- package/dist/framework/components/HuaUxPage.d.ts +48 -0
- package/dist/framework/components/HuaUxPage.d.ts.map +1 -0
- package/dist/framework/components/HuaUxPage.js +105 -0
- package/dist/framework/components/Providers.d.ts +17 -0
- package/dist/framework/components/Providers.d.ts.map +1 -0
- package/dist/framework/components/Providers.js +72 -0
- package/dist/framework/components/WelcomePage.d.ts +44 -0
- package/dist/framework/components/WelcomePage.d.ts.map +1 -0
- package/dist/framework/components/WelcomePage.js +80 -0
- package/dist/framework/config/index.d.ts +182 -0
- package/dist/framework/config/index.d.ts.map +1 -0
- package/dist/framework/config/index.js +329 -0
- package/dist/framework/config/merge.d.ts +26 -0
- package/dist/framework/config/merge.d.ts.map +1 -0
- package/dist/framework/config/merge.js +160 -0
- package/dist/framework/config/schema.d.ts +25 -0
- package/dist/framework/config/schema.d.ts.map +1 -0
- package/dist/framework/config/schema.js +122 -0
- package/dist/framework/hooks/useMotion.d.ts +45 -0
- package/dist/framework/hooks/useMotion.d.ts.map +1 -0
- package/dist/framework/hooks/useMotion.js +40 -0
- package/dist/framework/index.d.ts +37 -0
- package/dist/framework/index.d.ts.map +1 -0
- package/dist/framework/index.js +42 -0
- package/dist/framework/license/errors.d.ts +15 -0
- package/dist/framework/license/errors.d.ts.map +1 -0
- package/dist/framework/license/errors.js +52 -0
- package/dist/framework/license/index.d.ts +70 -0
- package/dist/framework/license/index.d.ts.map +1 -0
- package/dist/framework/license/index.js +124 -0
- package/dist/framework/license/loader.d.ts +26 -0
- package/dist/framework/license/loader.d.ts.map +1 -0
- package/dist/framework/license/loader.js +137 -0
- package/dist/framework/license/types.d.ts +67 -0
- package/dist/framework/license/types.d.ts.map +1 -0
- package/dist/framework/license/types.js +18 -0
- package/dist/framework/loading/components/SkeletonGroup.d.ts +44 -0
- package/dist/framework/loading/components/SkeletonGroup.d.ts.map +1 -0
- package/dist/framework/loading/components/SkeletonGroup.js +34 -0
- package/dist/framework/loading/components/SuspenseWrapper.d.ts +58 -0
- package/dist/framework/loading/components/SuspenseWrapper.d.ts.map +1 -0
- package/dist/framework/loading/components/SuspenseWrapper.js +40 -0
- package/dist/framework/loading/hoc/withSuspense.d.ts +46 -0
- package/dist/framework/loading/hoc/withSuspense.d.ts.map +1 -0
- package/dist/framework/loading/hoc/withSuspense.js +54 -0
- package/dist/framework/loading/hooks/useDelayedLoading.d.ts +56 -0
- package/dist/framework/loading/hooks/useDelayedLoading.d.ts.map +1 -0
- package/dist/framework/loading/hooks/useDelayedLoading.js +97 -0
- package/dist/framework/loading/hooks/useLoadingState.d.ts +69 -0
- package/dist/framework/loading/hooks/useLoadingState.d.ts.map +1 -0
- package/dist/framework/loading/hooks/useLoadingState.js +59 -0
- package/dist/framework/loading/index.d.ts +16 -0
- package/dist/framework/loading/index.d.ts.map +1 -0
- package/dist/framework/loading/index.js +13 -0
- package/dist/framework/middleware/i18n.d.ts +90 -0
- package/dist/framework/middleware/i18n.d.ts.map +1 -0
- package/dist/framework/middleware/i18n.js +99 -0
- package/dist/framework/plugins/index.d.ts +8 -0
- package/dist/framework/plugins/index.d.ts.map +1 -0
- package/dist/framework/plugins/index.js +6 -0
- package/dist/framework/plugins/registry.d.ts +95 -0
- package/dist/framework/plugins/registry.d.ts.map +1 -0
- package/dist/framework/plugins/registry.js +160 -0
- package/dist/framework/plugins/types.d.ts +97 -0
- package/dist/framework/plugins/types.d.ts.map +1 -0
- package/dist/framework/plugins/types.js +6 -0
- package/dist/framework/seo/geo/examples.d.ts +87 -0
- package/dist/framework/seo/geo/examples.d.ts.map +1 -0
- package/dist/framework/seo/geo/examples.js +295 -0
- package/dist/framework/seo/geo/generateGEOMetadata.d.ts +107 -0
- package/dist/framework/seo/geo/generateGEOMetadata.d.ts.map +1 -0
- package/dist/framework/seo/geo/generateGEOMetadata.js +404 -0
- package/dist/framework/seo/geo/index.d.ts +19 -0
- package/dist/framework/seo/geo/index.d.ts.map +1 -0
- package/dist/framework/seo/geo/index.js +21 -0
- package/dist/framework/seo/geo/presets.d.ts +52 -0
- package/dist/framework/seo/geo/presets.d.ts.map +1 -0
- package/dist/framework/seo/geo/presets.js +47 -0
- package/dist/framework/seo/geo/structuredData.d.ts +187 -0
- package/dist/framework/seo/geo/structuredData.d.ts.map +1 -0
- package/dist/framework/seo/geo/structuredData.js +354 -0
- package/dist/framework/seo/geo/test-utils.d.ts +78 -0
- package/dist/framework/seo/geo/test-utils.d.ts.map +1 -0
- package/dist/framework/seo/geo/test-utils.js +139 -0
- package/dist/framework/seo/geo/types.d.ts +225 -0
- package/dist/framework/seo/geo/types.d.ts.map +1 -0
- package/dist/framework/seo/geo/types.js +51 -0
- package/dist/framework/types/index.d.ts +577 -0
- package/dist/framework/types/index.d.ts.map +1 -0
- package/dist/framework/types/index.js +6 -0
- package/dist/framework/utils/data-fetching.d.ts +45 -0
- package/dist/framework/utils/data-fetching.d.ts.map +1 -0
- package/dist/framework/utils/data-fetching.js +74 -0
- package/dist/framework/utils/file-structure.d.ts +29 -0
- package/dist/framework/utils/file-structure.d.ts.map +1 -0
- package/dist/framework/utils/file-structure.js +72 -0
- package/dist/framework/utils/metadata.d.ts +109 -0
- package/dist/framework/utils/metadata.d.ts.map +1 -0
- package/dist/framework/utils/metadata.js +105 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/presets/index.d.ts +8 -0
- package/dist/presets/index.d.ts.map +1 -0
- package/dist/presets/index.js +7 -0
- package/dist/presets/marketing.d.ts +41 -0
- package/dist/presets/marketing.d.ts.map +1 -0
- package/dist/presets/marketing.js +81 -0
- package/dist/presets/product.d.ts +41 -0
- package/dist/presets/product.d.ts.map +1 -0
- package/dist/presets/product.js +74 -0
- package/package.json +91 -0
- package/src/framework/README.md +329 -0
- package/src/framework/__tests__/branding/css-vars.test.ts +147 -0
- package/src/framework/__tests__/components/ErrorBoundary.test.tsx +146 -0
- package/src/framework/__tests__/config/defineConfig.test.ts +138 -0
- package/src/framework/__tests__/hooks/useMotion.test.ts +105 -0
- package/src/framework/__tests__/seo/geo/generateGEOMetadata.test.ts +207 -0
- package/src/framework/__tests__/seo/geo/structuredData.test.ts +262 -0
- package/src/framework/a11y/components/LiveRegion.tsx +89 -0
- package/src/framework/a11y/components/SkipToContent.tsx +103 -0
- package/src/framework/a11y/hooks/useFocusManagement.ts +125 -0
- package/src/framework/a11y/hooks/useFocusTrap.ts +239 -0
- package/src/framework/a11y/hooks/useLiveRegion.ts +95 -0
- package/src/framework/a11y/index.ts +17 -0
- package/src/framework/branding/context.tsx +135 -0
- package/src/framework/branding/css-vars.ts +110 -0
- package/src/framework/branding/tailwind-config.ts +90 -0
- package/src/framework/components/BrandedButton.tsx +94 -0
- package/src/framework/components/BrandedCard.tsx +87 -0
- package/src/framework/components/ErrorBoundary.tsx +215 -0
- package/src/framework/components/HuaUxLayout.tsx +36 -0
- package/src/framework/components/HuaUxPage.tsx +138 -0
- package/src/framework/components/Providers.tsx +98 -0
- package/src/framework/components/WelcomePage.tsx +207 -0
- package/src/framework/config/index.ts +349 -0
- package/src/framework/config/merge.ts +190 -0
- package/src/framework/config/schema.ts +140 -0
- package/src/framework/hooks/useMotion.ts +57 -0
- package/src/framework/index.ts +122 -0
- package/src/framework/license/errors.ts +63 -0
- package/src/framework/license/index.ts +137 -0
- package/src/framework/license/loader.ts +158 -0
- package/src/framework/license/types.ts +95 -0
- package/src/framework/loading/components/SkeletonGroup.tsx +70 -0
- package/src/framework/loading/components/SuspenseWrapper.tsx +88 -0
- package/src/framework/loading/hoc/withSuspense.tsx +96 -0
- package/src/framework/loading/hooks/useDelayedLoading.ts +127 -0
- package/src/framework/loading/hooks/useLoadingState.ts +103 -0
- package/src/framework/loading/index.ts +19 -0
- package/src/framework/middleware/i18n.ts +161 -0
- package/src/framework/middleware/index.ts +7 -0
- package/src/framework/plugins/index.ts +13 -0
- package/src/framework/plugins/registry.ts +186 -0
- package/src/framework/plugins/types.ts +106 -0
- package/src/framework/seo/geo/examples.tsx +415 -0
- package/src/framework/seo/geo/generateGEOMetadata.ts +441 -0
- package/src/framework/seo/geo/index.ts +61 -0
- package/src/framework/seo/geo/presets.ts +58 -0
- package/src/framework/seo/geo/structuredData.ts +422 -0
- package/src/framework/seo/geo/test-utils.ts +179 -0
- package/src/framework/seo/geo/types.ts +315 -0
- package/src/framework/types/index.ts +623 -0
- package/src/framework/utils/data-fetching.ts +95 -0
- package/src/framework/utils/file-structure.ts +88 -0
- package/src/framework/utils/metadata.ts +152 -0
- package/src/index.ts +31 -0
- package/src/presets/index.ts +8 -0
- package/src/presets/marketing.ts +88 -0
- package/src/presets/product.ts +81 -0
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @hua-labs/hua-ux/framework - GEO Test Utilities
|
|
3
|
+
*
|
|
4
|
+
* Testing utilities for GEO metadata validation and debugging
|
|
5
|
+
* GEO 메타데이터 검증 및 디버깅을 위한 테스트 유틸리티
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Validate GEO metadata
|
|
9
|
+
*
|
|
10
|
+
* GEO 메타데이터의 유효성을 검증합니다.
|
|
11
|
+
*
|
|
12
|
+
* @param metadata - GEO metadata to validate
|
|
13
|
+
* @returns Validation result with errors and warnings
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```tsx
|
|
17
|
+
* const result = validateGEOMetadata(geoMeta);
|
|
18
|
+
* if (!result.valid) {
|
|
19
|
+
* console.error('Validation errors:', result.errors);
|
|
20
|
+
* }
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export function validateGEOMetadata(metadata) {
|
|
24
|
+
const errors = [];
|
|
25
|
+
const warnings = [];
|
|
26
|
+
// Validate meta tags
|
|
27
|
+
const descMeta = metadata.meta.find(m => m.name === 'description');
|
|
28
|
+
if (!descMeta) {
|
|
29
|
+
errors.push('Missing description meta tag');
|
|
30
|
+
}
|
|
31
|
+
else if (descMeta.content.length === 0) {
|
|
32
|
+
errors.push('Description meta tag is empty');
|
|
33
|
+
}
|
|
34
|
+
else if (descMeta.content.length > 160) {
|
|
35
|
+
warnings.push(`Description exceeds 160 characters (${descMeta.content.length}). ` +
|
|
36
|
+
'Consider keeping it under 160 for better AI parsing.');
|
|
37
|
+
}
|
|
38
|
+
// Validate JSON-LD
|
|
39
|
+
if (!metadata.jsonLd || metadata.jsonLd.length === 0) {
|
|
40
|
+
errors.push('Missing JSON-LD structured data');
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
for (const ld of metadata.jsonLd) {
|
|
44
|
+
if (!ld['@context'] || ld['@context'] !== 'https://schema.org') {
|
|
45
|
+
errors.push('Invalid JSON-LD structure: missing or invalid @context');
|
|
46
|
+
}
|
|
47
|
+
if (!ld['@type']) {
|
|
48
|
+
errors.push('Invalid JSON-LD structure: missing @type');
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
// Validate URLs in meta tags
|
|
53
|
+
metadata.meta.forEach(meta => {
|
|
54
|
+
if (meta.content.startsWith('http')) {
|
|
55
|
+
try {
|
|
56
|
+
new URL(meta.content);
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
errors.push(`Invalid URL in meta tag ${meta.name}: ${meta.content}`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
// Validate Open Graph tags
|
|
64
|
+
if (metadata.openGraph) {
|
|
65
|
+
const requiredOG = ['og:title', 'og:description', 'og:type'];
|
|
66
|
+
const ogProperties = metadata.openGraph.map(og => og.property);
|
|
67
|
+
for (const required of requiredOG) {
|
|
68
|
+
if (!ogProperties.includes(required)) {
|
|
69
|
+
warnings.push(`Missing recommended Open Graph property: ${required}`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
valid: errors.length === 0,
|
|
75
|
+
errors,
|
|
76
|
+
warnings,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Pretty print GEO metadata
|
|
81
|
+
*
|
|
82
|
+
* GEO 메타데이터를 읽기 쉬운 형식으로 출력합니다.
|
|
83
|
+
*
|
|
84
|
+
* @param metadata - GEO metadata to print
|
|
85
|
+
* @returns Formatted JSON string
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```tsx
|
|
89
|
+
* console.log(prettyPrintGEOMetadata(geoMeta));
|
|
90
|
+
* ```
|
|
91
|
+
*/
|
|
92
|
+
export function prettyPrintGEOMetadata(metadata) {
|
|
93
|
+
return JSON.stringify(metadata, null, 2);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Compare two GEO metadata objects
|
|
97
|
+
*
|
|
98
|
+
* 두 GEO 메타데이터 객체를 비교합니다.
|
|
99
|
+
*
|
|
100
|
+
* @param a - First GEO metadata
|
|
101
|
+
* @param b - Second GEO metadata
|
|
102
|
+
* @returns Comparison result with differences
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* ```tsx
|
|
106
|
+
* const result = compareGEOMetadata(meta1, meta2);
|
|
107
|
+
* if (!result.same) {
|
|
108
|
+
* console.log('Differences:', result.differences);
|
|
109
|
+
* }
|
|
110
|
+
* ```
|
|
111
|
+
*/
|
|
112
|
+
export function compareGEOMetadata(a, b) {
|
|
113
|
+
const differences = [];
|
|
114
|
+
// Compare meta tags
|
|
115
|
+
const aMetaMap = new Map(a.meta.map(m => [m.name, m.content]));
|
|
116
|
+
const bMetaMap = new Map(b.meta.map(m => [m.name, m.content]));
|
|
117
|
+
for (const [name, content] of aMetaMap) {
|
|
118
|
+
if (bMetaMap.get(name) !== content) {
|
|
119
|
+
differences.push(`Meta tag '${name}' differs`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
for (const [name] of bMetaMap) {
|
|
123
|
+
if (!aMetaMap.has(name)) {
|
|
124
|
+
differences.push(`Meta tag '${name}' missing in first metadata`);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// Compare JSON-LD count
|
|
128
|
+
if (a.jsonLd.length !== b.jsonLd.length) {
|
|
129
|
+
differences.push(`JSON-LD count differs: ${a.jsonLd.length} vs ${b.jsonLd.length}`);
|
|
130
|
+
}
|
|
131
|
+
// Compare version
|
|
132
|
+
if (a.version !== b.version) {
|
|
133
|
+
differences.push(`Version differs: ${a.version} vs ${b.version}`);
|
|
134
|
+
}
|
|
135
|
+
return {
|
|
136
|
+
same: differences.length === 0,
|
|
137
|
+
differences,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @hua-labs/hua-ux/framework - GEO Types
|
|
3
|
+
*
|
|
4
|
+
* GEO (Generative Engine Optimization) types for AI search engine discoverability
|
|
5
|
+
* ChatGPT, Claude, Gemini, Perplexity 같은 AI가 hua-ux를 잘 찾고 추천하도록 하는 타입 정의
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Meta tag name constants
|
|
9
|
+
* HTML meta 태그 이름 상수
|
|
10
|
+
*/
|
|
11
|
+
export declare const META_NAMES: {
|
|
12
|
+
readonly DESCRIPTION: "description";
|
|
13
|
+
readonly KEYWORDS: "keywords";
|
|
14
|
+
readonly SOFTWARE_VERSION: "software:version";
|
|
15
|
+
readonly SOFTWARE_CATEGORY: "software:category";
|
|
16
|
+
readonly SOFTWARE_LANGUAGE: "software:language";
|
|
17
|
+
readonly AI_CONTEXT: "ai:context";
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Open Graph property constants
|
|
21
|
+
* Open Graph 속성 상수
|
|
22
|
+
*/
|
|
23
|
+
export declare const OG_PROPERTIES: {
|
|
24
|
+
readonly TITLE: "og:title";
|
|
25
|
+
readonly DESCRIPTION: "og:description";
|
|
26
|
+
readonly TYPE: "og:type";
|
|
27
|
+
readonly URL: "og:url";
|
|
28
|
+
readonly SITE_NAME: "og:site_name";
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Software Application Type
|
|
32
|
+
* Schema.org SoftwareApplication types
|
|
33
|
+
*/
|
|
34
|
+
export type SoftwareApplicationType = 'WebApplication' | 'MobileApplication' | 'DesktopApplication' | 'DeveloperApplication';
|
|
35
|
+
/**
|
|
36
|
+
* Programming Language
|
|
37
|
+
* 프로그래밍 언어 (프레임워크가 아닌 실제 언어만)
|
|
38
|
+
*/
|
|
39
|
+
export type ProgrammingLanguage = 'TypeScript' | 'JavaScript' | 'Python' | 'Java' | 'Go' | 'Rust' | 'C#' | 'C++' | 'Ruby' | 'PHP' | 'Swift' | 'Kotlin' | 'Dart' | (string & {});
|
|
40
|
+
/**
|
|
41
|
+
* Technology Stack
|
|
42
|
+
* 기술 스택 (프레임워크, 라이브러리 등)
|
|
43
|
+
*/
|
|
44
|
+
export type TechnologyStack = 'React' | 'Next.js' | 'Vue' | 'Angular' | 'Svelte' | 'Node.js' | 'Express' | 'Tailwind CSS' | 'Zustand' | 'Prisma' | (string & {});
|
|
45
|
+
/**
|
|
46
|
+
* Software Category
|
|
47
|
+
* Categories that help AI understand the software domain
|
|
48
|
+
*/
|
|
49
|
+
export type SoftwareCategory = 'UI Framework' | 'Component Library' | 'Developer Tool' | 'UX Framework' | 'Accessibility Tool' | 'Internationalization Tool' | 'Animation Library';
|
|
50
|
+
/**
|
|
51
|
+
* GEO Configuration
|
|
52
|
+
* AI 검색 엔진이 이해하기 쉬운 구조화된 메타데이터 설정
|
|
53
|
+
*/
|
|
54
|
+
export interface GEOConfig {
|
|
55
|
+
/**
|
|
56
|
+
* Software name
|
|
57
|
+
* AI가 참조할 소프트웨어 이름
|
|
58
|
+
*/
|
|
59
|
+
name: string;
|
|
60
|
+
/**
|
|
61
|
+
* Alternative names or aliases
|
|
62
|
+
* 대체 이름 또는 별칭 (예: "hua-ux", "@hua-labs/hua-ux")
|
|
63
|
+
*/
|
|
64
|
+
alternateName?: string[];
|
|
65
|
+
/**
|
|
66
|
+
* Clear, concise description
|
|
67
|
+
* AI가 이해하기 쉬운 명확하고 간결한 설명 (1-2 문장)
|
|
68
|
+
*/
|
|
69
|
+
description: string;
|
|
70
|
+
/**
|
|
71
|
+
* Software version
|
|
72
|
+
*/
|
|
73
|
+
version?: string;
|
|
74
|
+
/**
|
|
75
|
+
* Application category
|
|
76
|
+
* Schema.org applicationCategory
|
|
77
|
+
*/
|
|
78
|
+
applicationCategory?: SoftwareCategory | SoftwareCategory[];
|
|
79
|
+
/**
|
|
80
|
+
* Programming language(s)
|
|
81
|
+
* 프로그래밍 언어 (TypeScript, JavaScript, Python 등)
|
|
82
|
+
*/
|
|
83
|
+
programmingLanguage?: ProgrammingLanguage | ProgrammingLanguage[];
|
|
84
|
+
/**
|
|
85
|
+
* Technology stack
|
|
86
|
+
* 기술 스택 (React, Next.js, Vue 등)
|
|
87
|
+
*/
|
|
88
|
+
technologyStack?: TechnologyStack | TechnologyStack[];
|
|
89
|
+
/**
|
|
90
|
+
* Software type
|
|
91
|
+
*/
|
|
92
|
+
applicationType?: SoftwareApplicationType;
|
|
93
|
+
/**
|
|
94
|
+
* Homepage URL
|
|
95
|
+
*/
|
|
96
|
+
url?: string;
|
|
97
|
+
/**
|
|
98
|
+
* Documentation URL
|
|
99
|
+
*/
|
|
100
|
+
documentationUrl?: string;
|
|
101
|
+
/**
|
|
102
|
+
* Repository URL (GitHub, GitLab, etc.)
|
|
103
|
+
*/
|
|
104
|
+
codeRepository?: string;
|
|
105
|
+
/**
|
|
106
|
+
* License type (MIT, Apache-2.0, etc.)
|
|
107
|
+
*/
|
|
108
|
+
license?: string;
|
|
109
|
+
/**
|
|
110
|
+
* Author or organization
|
|
111
|
+
*/
|
|
112
|
+
author?: {
|
|
113
|
+
name: string;
|
|
114
|
+
url?: string;
|
|
115
|
+
};
|
|
116
|
+
/**
|
|
117
|
+
* Key features
|
|
118
|
+
* AI가 쉽게 참조할 수 있는 주요 기능 목록
|
|
119
|
+
*/
|
|
120
|
+
features?: string[];
|
|
121
|
+
/**
|
|
122
|
+
* Use cases
|
|
123
|
+
* AI가 추천할 때 사용할 유스케이스 예시
|
|
124
|
+
*/
|
|
125
|
+
useCases?: string[];
|
|
126
|
+
/**
|
|
127
|
+
* Keywords for AI discovery
|
|
128
|
+
* AI 검색을 위한 키워드
|
|
129
|
+
*/
|
|
130
|
+
keywords?: string[];
|
|
131
|
+
/**
|
|
132
|
+
* Operating system compatibility
|
|
133
|
+
*/
|
|
134
|
+
operatingSystem?: string[];
|
|
135
|
+
/**
|
|
136
|
+
* Software requirements or dependencies
|
|
137
|
+
*/
|
|
138
|
+
softwareRequirements?: string[];
|
|
139
|
+
/**
|
|
140
|
+
* Related software or alternatives
|
|
141
|
+
* AI가 비교/추천할 때 사용할 관련 소프트웨어
|
|
142
|
+
*/
|
|
143
|
+
relatedTo?: string[];
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Utility types for better developer experience
|
|
147
|
+
* 더 나은 개발자 경험을 위한 유틸리티 타입
|
|
148
|
+
*/
|
|
149
|
+
/**
|
|
150
|
+
* Required GEO config fields
|
|
151
|
+
* 필수 GEO 설정 필드
|
|
152
|
+
*/
|
|
153
|
+
export type RequiredGEOConfig = Required<Pick<GEOConfig, 'name' | 'description'>>;
|
|
154
|
+
/**
|
|
155
|
+
* Optional GEO config fields
|
|
156
|
+
* 선택적 GEO 설정 필드
|
|
157
|
+
*/
|
|
158
|
+
export type OptionalGEOConfig = Partial<Omit<GEOConfig, 'name' | 'description'>>;
|
|
159
|
+
/**
|
|
160
|
+
* GEO config input type
|
|
161
|
+
* GEO 설정 입력 타입 (필수 + 선택)
|
|
162
|
+
*/
|
|
163
|
+
export type GEOConfigInput = RequiredGEOConfig & OptionalGEOConfig;
|
|
164
|
+
/**
|
|
165
|
+
* Type guard for GEO config validation
|
|
166
|
+
* GEO 설정 유효성 검사를 위한 타입 가드
|
|
167
|
+
*
|
|
168
|
+
* @param config - Unknown value to check
|
|
169
|
+
* @returns True if config is a valid GEOConfig
|
|
170
|
+
*
|
|
171
|
+
* @example
|
|
172
|
+
* ```tsx
|
|
173
|
+
* if (isValidGEOConfig(userInput)) {
|
|
174
|
+
* const geoMeta = generateGEOMetadata(userInput);
|
|
175
|
+
* }
|
|
176
|
+
* ```
|
|
177
|
+
*/
|
|
178
|
+
export declare function isValidGEOConfig(config: unknown): config is GEOConfig;
|
|
179
|
+
/**
|
|
180
|
+
* Structured Data (Schema.org JSON-LD)
|
|
181
|
+
* AI가 파싱하기 쉬운 구조화된 데이터
|
|
182
|
+
*/
|
|
183
|
+
export interface StructuredData {
|
|
184
|
+
'@context': 'https://schema.org';
|
|
185
|
+
'@type': 'SoftwareApplication' | 'FAQPage' | 'TechArticle' | 'HowTo' | 'Question' | 'Answer' | 'Organization' | 'CreativeWork' | 'Code' | 'VideoObject';
|
|
186
|
+
[key: string]: string | number | boolean | object | unknown[] | undefined;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* GEO Metadata Result
|
|
190
|
+
* generateGEOMetadata() 함수의 반환 타입
|
|
191
|
+
*/
|
|
192
|
+
export interface GEOMetadata {
|
|
193
|
+
/**
|
|
194
|
+
* HTML meta tags
|
|
195
|
+
*/
|
|
196
|
+
meta: {
|
|
197
|
+
name: string;
|
|
198
|
+
content: string;
|
|
199
|
+
}[];
|
|
200
|
+
/**
|
|
201
|
+
* JSON-LD structured data
|
|
202
|
+
* Schema.org 구조화된 데이터
|
|
203
|
+
*/
|
|
204
|
+
jsonLd: StructuredData[];
|
|
205
|
+
/**
|
|
206
|
+
* Open Graph tags for social/AI sharing
|
|
207
|
+
*/
|
|
208
|
+
openGraph?: {
|
|
209
|
+
property: string;
|
|
210
|
+
content: string;
|
|
211
|
+
}[];
|
|
212
|
+
/**
|
|
213
|
+
* Twitter Card tags
|
|
214
|
+
*/
|
|
215
|
+
twitter?: {
|
|
216
|
+
name: string;
|
|
217
|
+
content: string;
|
|
218
|
+
}[];
|
|
219
|
+
/**
|
|
220
|
+
* Schema version
|
|
221
|
+
* GEO 메타데이터 스키마 버전 (향후 마이그레이션 및 디버깅용)
|
|
222
|
+
*/
|
|
223
|
+
version?: string;
|
|
224
|
+
}
|
|
225
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/framework/seo/geo/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @hua-labs/hua-ux/framework - GEO Types
|
|
3
|
+
*
|
|
4
|
+
* GEO (Generative Engine Optimization) types for AI search engine discoverability
|
|
5
|
+
* ChatGPT, Claude, Gemini, Perplexity 같은 AI가 hua-ux를 잘 찾고 추천하도록 하는 타입 정의
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Meta tag name constants
|
|
9
|
+
* HTML meta 태그 이름 상수
|
|
10
|
+
*/
|
|
11
|
+
export const META_NAMES = {
|
|
12
|
+
DESCRIPTION: 'description',
|
|
13
|
+
KEYWORDS: 'keywords',
|
|
14
|
+
SOFTWARE_VERSION: 'software:version',
|
|
15
|
+
SOFTWARE_CATEGORY: 'software:category',
|
|
16
|
+
SOFTWARE_LANGUAGE: 'software:language',
|
|
17
|
+
AI_CONTEXT: 'ai:context',
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Open Graph property constants
|
|
21
|
+
* Open Graph 속성 상수
|
|
22
|
+
*/
|
|
23
|
+
export const OG_PROPERTIES = {
|
|
24
|
+
TITLE: 'og:title',
|
|
25
|
+
DESCRIPTION: 'og:description',
|
|
26
|
+
TYPE: 'og:type',
|
|
27
|
+
URL: 'og:url',
|
|
28
|
+
SITE_NAME: 'og:site_name',
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Type guard for GEO config validation
|
|
32
|
+
* GEO 설정 유효성 검사를 위한 타입 가드
|
|
33
|
+
*
|
|
34
|
+
* @param config - Unknown value to check
|
|
35
|
+
* @returns True if config is a valid GEOConfig
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```tsx
|
|
39
|
+
* if (isValidGEOConfig(userInput)) {
|
|
40
|
+
* const geoMeta = generateGEOMetadata(userInput);
|
|
41
|
+
* }
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export function isValidGEOConfig(config) {
|
|
45
|
+
return (typeof config === 'object' &&
|
|
46
|
+
config !== null &&
|
|
47
|
+
'name' in config &&
|
|
48
|
+
'description' in config &&
|
|
49
|
+
typeof config.name === 'string' &&
|
|
50
|
+
typeof config.description === 'string');
|
|
51
|
+
}
|