@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.
Files changed (210) hide show
  1. package/README.md +839 -0
  2. package/dist/framework/a11y/components/LiveRegion.d.ts +64 -0
  3. package/dist/framework/a11y/components/LiveRegion.d.ts.map +1 -0
  4. package/dist/framework/a11y/components/LiveRegion.js +43 -0
  5. package/dist/framework/a11y/components/SkipToContent.d.ts +62 -0
  6. package/dist/framework/a11y/components/SkipToContent.d.ts.map +1 -0
  7. package/dist/framework/a11y/components/SkipToContent.js +60 -0
  8. package/dist/framework/a11y/hooks/useFocusManagement.d.ts +60 -0
  9. package/dist/framework/a11y/hooks/useFocusManagement.d.ts.map +1 -0
  10. package/dist/framework/a11y/hooks/useFocusManagement.js +71 -0
  11. package/dist/framework/a11y/hooks/useFocusTrap.d.ts +64 -0
  12. package/dist/framework/a11y/hooks/useFocusTrap.d.ts.map +1 -0
  13. package/dist/framework/a11y/hooks/useFocusTrap.js +185 -0
  14. package/dist/framework/a11y/hooks/useLiveRegion.d.ts +56 -0
  15. package/dist/framework/a11y/hooks/useLiveRegion.d.ts.map +1 -0
  16. package/dist/framework/a11y/hooks/useLiveRegion.js +60 -0
  17. package/dist/framework/a11y/index.d.ts +16 -0
  18. package/dist/framework/a11y/index.d.ts.map +1 -0
  19. package/dist/framework/a11y/index.js +11 -0
  20. package/dist/framework/branding/context.d.ts +52 -0
  21. package/dist/framework/branding/context.d.ts.map +1 -0
  22. package/dist/framework/branding/context.js +96 -0
  23. package/dist/framework/branding/css-vars.d.ts +34 -0
  24. package/dist/framework/branding/css-vars.d.ts.map +1 -0
  25. package/dist/framework/branding/css-vars.js +95 -0
  26. package/dist/framework/branding/tailwind-config.d.ts +38 -0
  27. package/dist/framework/branding/tailwind-config.d.ts.map +1 -0
  28. package/dist/framework/branding/tailwind-config.js +66 -0
  29. package/dist/framework/components/BrandedButton.d.ts +53 -0
  30. package/dist/framework/components/BrandedButton.d.ts.map +1 -0
  31. package/dist/framework/components/BrandedButton.js +40 -0
  32. package/dist/framework/components/BrandedCard.d.ts +52 -0
  33. package/dist/framework/components/BrandedCard.d.ts.map +1 -0
  34. package/dist/framework/components/BrandedCard.js +73 -0
  35. package/dist/framework/components/ErrorBoundary.d.ts +92 -0
  36. package/dist/framework/components/ErrorBoundary.d.ts.map +1 -0
  37. package/dist/framework/components/ErrorBoundary.js +121 -0
  38. package/dist/framework/components/HuaUxLayout.d.ts +29 -0
  39. package/dist/framework/components/HuaUxLayout.d.ts.map +1 -0
  40. package/dist/framework/components/HuaUxLayout.js +32 -0
  41. package/dist/framework/components/HuaUxPage.d.ts +48 -0
  42. package/dist/framework/components/HuaUxPage.d.ts.map +1 -0
  43. package/dist/framework/components/HuaUxPage.js +105 -0
  44. package/dist/framework/components/Providers.d.ts +17 -0
  45. package/dist/framework/components/Providers.d.ts.map +1 -0
  46. package/dist/framework/components/Providers.js +72 -0
  47. package/dist/framework/components/WelcomePage.d.ts +44 -0
  48. package/dist/framework/components/WelcomePage.d.ts.map +1 -0
  49. package/dist/framework/components/WelcomePage.js +80 -0
  50. package/dist/framework/config/index.d.ts +182 -0
  51. package/dist/framework/config/index.d.ts.map +1 -0
  52. package/dist/framework/config/index.js +329 -0
  53. package/dist/framework/config/merge.d.ts +26 -0
  54. package/dist/framework/config/merge.d.ts.map +1 -0
  55. package/dist/framework/config/merge.js +160 -0
  56. package/dist/framework/config/schema.d.ts +25 -0
  57. package/dist/framework/config/schema.d.ts.map +1 -0
  58. package/dist/framework/config/schema.js +122 -0
  59. package/dist/framework/hooks/useMotion.d.ts +45 -0
  60. package/dist/framework/hooks/useMotion.d.ts.map +1 -0
  61. package/dist/framework/hooks/useMotion.js +40 -0
  62. package/dist/framework/index.d.ts +37 -0
  63. package/dist/framework/index.d.ts.map +1 -0
  64. package/dist/framework/index.js +42 -0
  65. package/dist/framework/license/errors.d.ts +15 -0
  66. package/dist/framework/license/errors.d.ts.map +1 -0
  67. package/dist/framework/license/errors.js +52 -0
  68. package/dist/framework/license/index.d.ts +70 -0
  69. package/dist/framework/license/index.d.ts.map +1 -0
  70. package/dist/framework/license/index.js +124 -0
  71. package/dist/framework/license/loader.d.ts +26 -0
  72. package/dist/framework/license/loader.d.ts.map +1 -0
  73. package/dist/framework/license/loader.js +137 -0
  74. package/dist/framework/license/types.d.ts +67 -0
  75. package/dist/framework/license/types.d.ts.map +1 -0
  76. package/dist/framework/license/types.js +18 -0
  77. package/dist/framework/loading/components/SkeletonGroup.d.ts +44 -0
  78. package/dist/framework/loading/components/SkeletonGroup.d.ts.map +1 -0
  79. package/dist/framework/loading/components/SkeletonGroup.js +34 -0
  80. package/dist/framework/loading/components/SuspenseWrapper.d.ts +58 -0
  81. package/dist/framework/loading/components/SuspenseWrapper.d.ts.map +1 -0
  82. package/dist/framework/loading/components/SuspenseWrapper.js +40 -0
  83. package/dist/framework/loading/hoc/withSuspense.d.ts +46 -0
  84. package/dist/framework/loading/hoc/withSuspense.d.ts.map +1 -0
  85. package/dist/framework/loading/hoc/withSuspense.js +54 -0
  86. package/dist/framework/loading/hooks/useDelayedLoading.d.ts +56 -0
  87. package/dist/framework/loading/hooks/useDelayedLoading.d.ts.map +1 -0
  88. package/dist/framework/loading/hooks/useDelayedLoading.js +97 -0
  89. package/dist/framework/loading/hooks/useLoadingState.d.ts +69 -0
  90. package/dist/framework/loading/hooks/useLoadingState.d.ts.map +1 -0
  91. package/dist/framework/loading/hooks/useLoadingState.js +59 -0
  92. package/dist/framework/loading/index.d.ts +16 -0
  93. package/dist/framework/loading/index.d.ts.map +1 -0
  94. package/dist/framework/loading/index.js +13 -0
  95. package/dist/framework/middleware/i18n.d.ts +90 -0
  96. package/dist/framework/middleware/i18n.d.ts.map +1 -0
  97. package/dist/framework/middleware/i18n.js +99 -0
  98. package/dist/framework/plugins/index.d.ts +8 -0
  99. package/dist/framework/plugins/index.d.ts.map +1 -0
  100. package/dist/framework/plugins/index.js +6 -0
  101. package/dist/framework/plugins/registry.d.ts +95 -0
  102. package/dist/framework/plugins/registry.d.ts.map +1 -0
  103. package/dist/framework/plugins/registry.js +160 -0
  104. package/dist/framework/plugins/types.d.ts +97 -0
  105. package/dist/framework/plugins/types.d.ts.map +1 -0
  106. package/dist/framework/plugins/types.js +6 -0
  107. package/dist/framework/seo/geo/examples.d.ts +87 -0
  108. package/dist/framework/seo/geo/examples.d.ts.map +1 -0
  109. package/dist/framework/seo/geo/examples.js +295 -0
  110. package/dist/framework/seo/geo/generateGEOMetadata.d.ts +107 -0
  111. package/dist/framework/seo/geo/generateGEOMetadata.d.ts.map +1 -0
  112. package/dist/framework/seo/geo/generateGEOMetadata.js +404 -0
  113. package/dist/framework/seo/geo/index.d.ts +19 -0
  114. package/dist/framework/seo/geo/index.d.ts.map +1 -0
  115. package/dist/framework/seo/geo/index.js +21 -0
  116. package/dist/framework/seo/geo/presets.d.ts +52 -0
  117. package/dist/framework/seo/geo/presets.d.ts.map +1 -0
  118. package/dist/framework/seo/geo/presets.js +47 -0
  119. package/dist/framework/seo/geo/structuredData.d.ts +187 -0
  120. package/dist/framework/seo/geo/structuredData.d.ts.map +1 -0
  121. package/dist/framework/seo/geo/structuredData.js +354 -0
  122. package/dist/framework/seo/geo/test-utils.d.ts +78 -0
  123. package/dist/framework/seo/geo/test-utils.d.ts.map +1 -0
  124. package/dist/framework/seo/geo/test-utils.js +139 -0
  125. package/dist/framework/seo/geo/types.d.ts +225 -0
  126. package/dist/framework/seo/geo/types.d.ts.map +1 -0
  127. package/dist/framework/seo/geo/types.js +51 -0
  128. package/dist/framework/types/index.d.ts +577 -0
  129. package/dist/framework/types/index.d.ts.map +1 -0
  130. package/dist/framework/types/index.js +6 -0
  131. package/dist/framework/utils/data-fetching.d.ts +45 -0
  132. package/dist/framework/utils/data-fetching.d.ts.map +1 -0
  133. package/dist/framework/utils/data-fetching.js +74 -0
  134. package/dist/framework/utils/file-structure.d.ts +29 -0
  135. package/dist/framework/utils/file-structure.d.ts.map +1 -0
  136. package/dist/framework/utils/file-structure.js +72 -0
  137. package/dist/framework/utils/metadata.d.ts +109 -0
  138. package/dist/framework/utils/metadata.d.ts.map +1 -0
  139. package/dist/framework/utils/metadata.js +105 -0
  140. package/dist/index.d.ts +15 -0
  141. package/dist/index.d.ts.map +1 -0
  142. package/dist/index.js +21 -0
  143. package/dist/presets/index.d.ts +8 -0
  144. package/dist/presets/index.d.ts.map +1 -0
  145. package/dist/presets/index.js +7 -0
  146. package/dist/presets/marketing.d.ts +41 -0
  147. package/dist/presets/marketing.d.ts.map +1 -0
  148. package/dist/presets/marketing.js +81 -0
  149. package/dist/presets/product.d.ts +41 -0
  150. package/dist/presets/product.d.ts.map +1 -0
  151. package/dist/presets/product.js +74 -0
  152. package/package.json +91 -0
  153. package/src/framework/README.md +329 -0
  154. package/src/framework/__tests__/branding/css-vars.test.ts +147 -0
  155. package/src/framework/__tests__/components/ErrorBoundary.test.tsx +146 -0
  156. package/src/framework/__tests__/config/defineConfig.test.ts +138 -0
  157. package/src/framework/__tests__/hooks/useMotion.test.ts +105 -0
  158. package/src/framework/__tests__/seo/geo/generateGEOMetadata.test.ts +207 -0
  159. package/src/framework/__tests__/seo/geo/structuredData.test.ts +262 -0
  160. package/src/framework/a11y/components/LiveRegion.tsx +89 -0
  161. package/src/framework/a11y/components/SkipToContent.tsx +103 -0
  162. package/src/framework/a11y/hooks/useFocusManagement.ts +125 -0
  163. package/src/framework/a11y/hooks/useFocusTrap.ts +239 -0
  164. package/src/framework/a11y/hooks/useLiveRegion.ts +95 -0
  165. package/src/framework/a11y/index.ts +17 -0
  166. package/src/framework/branding/context.tsx +135 -0
  167. package/src/framework/branding/css-vars.ts +110 -0
  168. package/src/framework/branding/tailwind-config.ts +90 -0
  169. package/src/framework/components/BrandedButton.tsx +94 -0
  170. package/src/framework/components/BrandedCard.tsx +87 -0
  171. package/src/framework/components/ErrorBoundary.tsx +215 -0
  172. package/src/framework/components/HuaUxLayout.tsx +36 -0
  173. package/src/framework/components/HuaUxPage.tsx +138 -0
  174. package/src/framework/components/Providers.tsx +98 -0
  175. package/src/framework/components/WelcomePage.tsx +207 -0
  176. package/src/framework/config/index.ts +349 -0
  177. package/src/framework/config/merge.ts +190 -0
  178. package/src/framework/config/schema.ts +140 -0
  179. package/src/framework/hooks/useMotion.ts +57 -0
  180. package/src/framework/index.ts +122 -0
  181. package/src/framework/license/errors.ts +63 -0
  182. package/src/framework/license/index.ts +137 -0
  183. package/src/framework/license/loader.ts +158 -0
  184. package/src/framework/license/types.ts +95 -0
  185. package/src/framework/loading/components/SkeletonGroup.tsx +70 -0
  186. package/src/framework/loading/components/SuspenseWrapper.tsx +88 -0
  187. package/src/framework/loading/hoc/withSuspense.tsx +96 -0
  188. package/src/framework/loading/hooks/useDelayedLoading.ts +127 -0
  189. package/src/framework/loading/hooks/useLoadingState.ts +103 -0
  190. package/src/framework/loading/index.ts +19 -0
  191. package/src/framework/middleware/i18n.ts +161 -0
  192. package/src/framework/middleware/index.ts +7 -0
  193. package/src/framework/plugins/index.ts +13 -0
  194. package/src/framework/plugins/registry.ts +186 -0
  195. package/src/framework/plugins/types.ts +106 -0
  196. package/src/framework/seo/geo/examples.tsx +415 -0
  197. package/src/framework/seo/geo/generateGEOMetadata.ts +441 -0
  198. package/src/framework/seo/geo/index.ts +61 -0
  199. package/src/framework/seo/geo/presets.ts +58 -0
  200. package/src/framework/seo/geo/structuredData.ts +422 -0
  201. package/src/framework/seo/geo/test-utils.ts +179 -0
  202. package/src/framework/seo/geo/types.ts +315 -0
  203. package/src/framework/types/index.ts +623 -0
  204. package/src/framework/utils/data-fetching.ts +95 -0
  205. package/src/framework/utils/file-structure.ts +88 -0
  206. package/src/framework/utils/metadata.ts +152 -0
  207. package/src/index.ts +31 -0
  208. package/src/presets/index.ts +8 -0
  209. package/src/presets/marketing.ts +88 -0
  210. package/src/presets/product.ts +81 -0
@@ -0,0 +1,187 @@
1
+ /**
2
+ * @hua-labs/hua-ux/framework - Structured Data Helpers
3
+ *
4
+ * Schema.org JSON-LD helpers for AI search engines
5
+ * AI 검색 엔진이 이해하기 쉬운 구조화된 데이터 생성
6
+ */
7
+ import type { GEOConfig, StructuredData } from './types';
8
+ /**
9
+ * Generate Schema.org SoftwareApplication JSON-LD
10
+ *
11
+ * AI 검색 엔진이 소프트웨어를 정확하게 이해하도록 Schema.org 구조화된 데이터 생성
12
+ *
13
+ * @param config - GEO configuration
14
+ * @returns Schema.org JSON-LD structured data
15
+ *
16
+ * @example
17
+ * ```tsx
18
+ * const jsonLd = generateSoftwareApplicationLD({
19
+ * name: 'hua-ux',
20
+ * description: 'Privacy-first UX framework for Next.js',
21
+ * version: '1.0.0',
22
+ * applicationCategory: 'UX Framework',
23
+ * programmingLanguage: ['TypeScript', 'React'],
24
+ * features: ['i18n', 'Motion', 'Accessibility'],
25
+ * });
26
+ * ```
27
+ */
28
+ export declare function generateSoftwareApplicationLD(config: GEOConfig): StructuredData;
29
+ /**
30
+ * Generate Schema.org Code JSON-LD
31
+ *
32
+ * AI가 코드 스니펫과 예제를 이해하도록 Code 구조화된 데이터 생성
33
+ *
34
+ * @param code - Code configuration
35
+ * @returns Schema.org Code JSON-LD
36
+ *
37
+ * @example
38
+ * ```tsx
39
+ * const codeLd = generateCodeLD({
40
+ * programmingLanguage: 'TypeScript',
41
+ * text: 'const x = 1;',
42
+ * name: 'Example Code',
43
+ * });
44
+ * ```
45
+ */
46
+ export declare function generateCodeLD(code: {
47
+ programmingLanguage: string;
48
+ text: string;
49
+ name?: string;
50
+ }): StructuredData;
51
+ /**
52
+ * Generate Schema.org VideoObject JSON-LD
53
+ *
54
+ * AI가 튜토리얼 비디오를 이해하고 추천할 수 있도록 VideoObject 구조화된 데이터 생성
55
+ *
56
+ * @param video - Video configuration
57
+ * @returns Schema.org VideoObject JSON-LD
58
+ *
59
+ * @example
60
+ * ```tsx
61
+ * const videoLd = generateVideoLD({
62
+ * name: 'Getting Started with hua-ux',
63
+ * description: 'Learn how to build with hua-ux',
64
+ * thumbnailUrl: 'https://example.com/thumb.jpg',
65
+ * uploadDate: '2025-12-29',
66
+ * duration: 'PT10M30S',
67
+ * });
68
+ * ```
69
+ */
70
+ export declare function generateVideoLD(video: {
71
+ name: string;
72
+ description: string;
73
+ thumbnailUrl: string;
74
+ uploadDate: string;
75
+ duration?: string;
76
+ contentUrl?: string;
77
+ }): StructuredData;
78
+ /**
79
+ * Generate Schema.org Organization JSON-LD
80
+ *
81
+ * AI가 조직/회사 정보를 이해하도록 Organization 구조화된 데이터 생성
82
+ *
83
+ * @param org - Organization configuration
84
+ * @returns Schema.org Organization JSON-LD
85
+ *
86
+ * @example
87
+ * ```tsx
88
+ * const orgLd = generateOrganizationLD({
89
+ * name: 'hua-labs',
90
+ * url: 'https://hua-labs.dev',
91
+ * logo: 'https://hua-labs.dev/logo.png',
92
+ * description: 'Privacy-first development tools',
93
+ * });
94
+ * ```
95
+ */
96
+ export declare function generateOrganizationLD(org: {
97
+ name: string;
98
+ url?: string;
99
+ logo?: string;
100
+ description?: string;
101
+ }): StructuredData;
102
+ /**
103
+ * Generate Schema.org FAQPage JSON-LD
104
+ *
105
+ * AI가 자주 묻는 질문에 답변할 수 있도록 FAQ 구조화된 데이터 생성
106
+ *
107
+ * @param faqs - Array of FAQ items
108
+ * @returns Schema.org FAQ JSON-LD
109
+ *
110
+ * @example
111
+ * ```tsx
112
+ * const faqLd = generateFAQPageLD([
113
+ * {
114
+ * question: 'What is hua-ux?',
115
+ * answer: 'hua-ux is a privacy-first UX framework for Next.js applications.',
116
+ * },
117
+ * {
118
+ * question: 'How do I install hua-ux?',
119
+ * answer: 'Run: npx @hua-labs/create-hua-ux my-app',
120
+ * },
121
+ * ]);
122
+ * ```
123
+ */
124
+ export declare function generateFAQPageLD(faqs: Array<{
125
+ question: string;
126
+ answer: string;
127
+ }>): StructuredData;
128
+ /**
129
+ * Generate Schema.org TechArticle JSON-LD
130
+ *
131
+ * AI가 기술 문서를 정확하게 이해하도록 기술 아티클 구조화된 데이터 생성
132
+ *
133
+ * @param article - Article configuration
134
+ * @returns Schema.org TechArticle JSON-LD
135
+ *
136
+ * @example
137
+ * ```tsx
138
+ * const articleLd = generateTechArticleLD({
139
+ * headline: 'Getting Started with hua-ux',
140
+ * description: 'Learn how to build privacy-first UX with hua-ux',
141
+ * datePublished: '2025-12-29',
142
+ * author: { name: 'hua-labs' },
143
+ * });
144
+ * ```
145
+ */
146
+ export declare function generateTechArticleLD(article: {
147
+ headline: string;
148
+ description?: string;
149
+ datePublished?: string;
150
+ dateModified?: string;
151
+ author?: {
152
+ name: string;
153
+ url?: string;
154
+ };
155
+ image?: string;
156
+ }): StructuredData;
157
+ /**
158
+ * Generate Schema.org HowTo JSON-LD
159
+ *
160
+ * AI가 튜토리얼/가이드를 이해하고 추천할 수 있도록 HowTo 구조화된 데이터 생성
161
+ *
162
+ * @param howTo - HowTo configuration
163
+ * @returns Schema.org HowTo JSON-LD
164
+ *
165
+ * @example
166
+ * ```tsx
167
+ * const howToLd = generateHowToLD({
168
+ * name: 'How to add i18n to your Next.js app',
169
+ * description: 'Step-by-step guide to internationalization',
170
+ * steps: [
171
+ * { name: 'Install hua-ux', text: 'Run: npx @hua-labs/create-hua-ux my-app' },
172
+ * { name: 'Configure i18n', text: 'Add locales to your config' },
173
+ * ],
174
+ * });
175
+ * ```
176
+ */
177
+ export declare function generateHowToLD(howTo: {
178
+ name: string;
179
+ description?: string;
180
+ steps: Array<{
181
+ name: string;
182
+ text: string;
183
+ image?: string;
184
+ }>;
185
+ totalTime?: string;
186
+ }): StructuredData;
187
+ //# sourceMappingURL=structuredData.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"structuredData.d.ts","sourceRoot":"","sources":["../../../../src/framework/seo/geo/structuredData.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,SAAS,EACT,cAAc,EAKf,MAAM,SAAS,CAAC;AAmBjB;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,SAAS,GAAG,cAAc,CA2G/E;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE;IACnC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,GAAG,cAAc,CAQjB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,GAAG,cAAc,CAWjB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GAAG,cAAc,CASjB;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,KAAK,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,GAChD,cAAc,CA2BhB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE;IAC7C,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,cAAc,CAiBjB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC7D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,cAAc,CAiCjB"}
@@ -0,0 +1,354 @@
1
+ /**
2
+ * @hua-labs/hua-ux/framework - Structured Data Helpers
3
+ *
4
+ * Schema.org JSON-LD helpers for AI search engines
5
+ * AI 검색 엔진이 이해하기 쉬운 구조화된 데이터 생성
6
+ */
7
+ /**
8
+ * Normalize array (single value or array to array)
9
+ */
10
+ function normalizeToArray(value) {
11
+ if (value === undefined)
12
+ return [];
13
+ return Array.isArray(value) ? value : [value];
14
+ }
15
+ /**
16
+ * Join non-empty array values
17
+ */
18
+ function joinNonEmpty(values, separator) {
19
+ if (!values || values.length === 0)
20
+ return undefined;
21
+ const nonEmpty = values.filter(v => v && v.trim().length > 0);
22
+ return nonEmpty.length > 0 ? nonEmpty.join(separator) : undefined;
23
+ }
24
+ /**
25
+ * Generate Schema.org SoftwareApplication JSON-LD
26
+ *
27
+ * AI 검색 엔진이 소프트웨어를 정확하게 이해하도록 Schema.org 구조화된 데이터 생성
28
+ *
29
+ * @param config - GEO configuration
30
+ * @returns Schema.org JSON-LD structured data
31
+ *
32
+ * @example
33
+ * ```tsx
34
+ * const jsonLd = generateSoftwareApplicationLD({
35
+ * name: 'hua-ux',
36
+ * description: 'Privacy-first UX framework for Next.js',
37
+ * version: '1.0.0',
38
+ * applicationCategory: 'UX Framework',
39
+ * programmingLanguage: ['TypeScript', 'React'],
40
+ * features: ['i18n', 'Motion', 'Accessibility'],
41
+ * });
42
+ * ```
43
+ */
44
+ export function generateSoftwareApplicationLD(config) {
45
+ const jsonLd = {
46
+ '@context': 'https://schema.org',
47
+ '@type': 'SoftwareApplication',
48
+ name: config.name,
49
+ description: config.description,
50
+ };
51
+ // Alternative names (filter empty values)
52
+ const alternateNames = normalizeToArray(config.alternateName);
53
+ const validAlternateNames = alternateNames.filter(name => name && name.trim().length > 0);
54
+ if (validAlternateNames.length > 0) {
55
+ jsonLd.alternateName = validAlternateNames;
56
+ }
57
+ // Version
58
+ if (config.version) {
59
+ jsonLd.softwareVersion = config.version;
60
+ }
61
+ // Application category (filter empty values)
62
+ const categories = normalizeToArray(config.applicationCategory);
63
+ const categoryContent = joinNonEmpty(categories, ', ');
64
+ if (categoryContent) {
65
+ jsonLd.applicationCategory = categoryContent;
66
+ }
67
+ // Programming language (filter empty values)
68
+ const languages = normalizeToArray(config.programmingLanguage);
69
+ const languageContent = joinNonEmpty(languages, ', ');
70
+ if (languageContent) {
71
+ jsonLd.programmingLanguage = languageContent;
72
+ }
73
+ // Technology stack (filter empty values)
74
+ // Note: Schema.org doesn't have a direct "technologyStack" field,
75
+ // so we include it in keywords for AI discoverability
76
+ const techStack = normalizeToArray(config.technologyStack);
77
+ const techStackContent = joinNonEmpty(techStack, ', ');
78
+ if (techStackContent && jsonLd.keywords) {
79
+ // Append to existing keywords
80
+ jsonLd.keywords = `${jsonLd.keywords}, ${techStackContent}`;
81
+ }
82
+ else if (techStackContent) {
83
+ // Create keywords if doesn't exist
84
+ jsonLd.keywords = techStackContent;
85
+ }
86
+ // Application type
87
+ if (config.applicationType) {
88
+ jsonLd.applicationSubType = config.applicationType;
89
+ }
90
+ // URLs
91
+ if (config.url) {
92
+ jsonLd.url = config.url;
93
+ }
94
+ if (config.documentationUrl) {
95
+ jsonLd.softwareHelp = {
96
+ '@type': 'CreativeWork',
97
+ url: config.documentationUrl,
98
+ };
99
+ }
100
+ if (config.codeRepository) {
101
+ jsonLd.codeRepository = config.codeRepository;
102
+ }
103
+ // License
104
+ if (config.license) {
105
+ jsonLd.license = config.license;
106
+ }
107
+ // Author
108
+ if (config.author) {
109
+ jsonLd.author = {
110
+ '@type': 'Organization',
111
+ name: config.author.name,
112
+ ...(config.author.url && { url: config.author.url }),
113
+ };
114
+ }
115
+ // Features as keywords (filter empty values)
116
+ const featureList = joinNonEmpty(config.features, ', ');
117
+ if (featureList) {
118
+ jsonLd.featureList = featureList;
119
+ }
120
+ // Keywords (filter empty values)
121
+ const keywordsContent = joinNonEmpty(config.keywords, ', ');
122
+ if (keywordsContent) {
123
+ jsonLd.keywords = keywordsContent;
124
+ }
125
+ // Operating system (filter empty values)
126
+ const osContent = joinNonEmpty(config.operatingSystem, ', ');
127
+ if (osContent) {
128
+ jsonLd.operatingSystem = osContent;
129
+ }
130
+ // Software requirements (filter empty values)
131
+ const requirementsContent = joinNonEmpty(config.softwareRequirements, ', ');
132
+ if (requirementsContent) {
133
+ jsonLd.softwareRequirements = requirementsContent;
134
+ }
135
+ return jsonLd;
136
+ }
137
+ /**
138
+ * Generate Schema.org Code JSON-LD
139
+ *
140
+ * AI가 코드 스니펫과 예제를 이해하도록 Code 구조화된 데이터 생성
141
+ *
142
+ * @param code - Code configuration
143
+ * @returns Schema.org Code JSON-LD
144
+ *
145
+ * @example
146
+ * ```tsx
147
+ * const codeLd = generateCodeLD({
148
+ * programmingLanguage: 'TypeScript',
149
+ * text: 'const x = 1;',
150
+ * name: 'Example Code',
151
+ * });
152
+ * ```
153
+ */
154
+ export function generateCodeLD(code) {
155
+ return {
156
+ '@context': 'https://schema.org',
157
+ '@type': 'Code',
158
+ programmingLanguage: code.programmingLanguage,
159
+ text: code.text,
160
+ ...(code.name && { name: code.name }),
161
+ };
162
+ }
163
+ /**
164
+ * Generate Schema.org VideoObject JSON-LD
165
+ *
166
+ * AI가 튜토리얼 비디오를 이해하고 추천할 수 있도록 VideoObject 구조화된 데이터 생성
167
+ *
168
+ * @param video - Video configuration
169
+ * @returns Schema.org VideoObject JSON-LD
170
+ *
171
+ * @example
172
+ * ```tsx
173
+ * const videoLd = generateVideoLD({
174
+ * name: 'Getting Started with hua-ux',
175
+ * description: 'Learn how to build with hua-ux',
176
+ * thumbnailUrl: 'https://example.com/thumb.jpg',
177
+ * uploadDate: '2025-12-29',
178
+ * duration: 'PT10M30S',
179
+ * });
180
+ * ```
181
+ */
182
+ export function generateVideoLD(video) {
183
+ return {
184
+ '@context': 'https://schema.org',
185
+ '@type': 'VideoObject',
186
+ name: video.name,
187
+ description: video.description,
188
+ thumbnailUrl: video.thumbnailUrl,
189
+ uploadDate: video.uploadDate,
190
+ ...(video.duration && { duration: video.duration }),
191
+ ...(video.contentUrl && { contentUrl: video.contentUrl }),
192
+ };
193
+ }
194
+ /**
195
+ * Generate Schema.org Organization JSON-LD
196
+ *
197
+ * AI가 조직/회사 정보를 이해하도록 Organization 구조화된 데이터 생성
198
+ *
199
+ * @param org - Organization configuration
200
+ * @returns Schema.org Organization JSON-LD
201
+ *
202
+ * @example
203
+ * ```tsx
204
+ * const orgLd = generateOrganizationLD({
205
+ * name: 'hua-labs',
206
+ * url: 'https://hua-labs.dev',
207
+ * logo: 'https://hua-labs.dev/logo.png',
208
+ * description: 'Privacy-first development tools',
209
+ * });
210
+ * ```
211
+ */
212
+ export function generateOrganizationLD(org) {
213
+ return {
214
+ '@context': 'https://schema.org',
215
+ '@type': 'Organization',
216
+ name: org.name,
217
+ ...(org.url && { url: org.url }),
218
+ ...(org.logo && { logo: org.logo }),
219
+ ...(org.description && { description: org.description }),
220
+ };
221
+ }
222
+ /**
223
+ * Generate Schema.org FAQPage JSON-LD
224
+ *
225
+ * AI가 자주 묻는 질문에 답변할 수 있도록 FAQ 구조화된 데이터 생성
226
+ *
227
+ * @param faqs - Array of FAQ items
228
+ * @returns Schema.org FAQ JSON-LD
229
+ *
230
+ * @example
231
+ * ```tsx
232
+ * const faqLd = generateFAQPageLD([
233
+ * {
234
+ * question: 'What is hua-ux?',
235
+ * answer: 'hua-ux is a privacy-first UX framework for Next.js applications.',
236
+ * },
237
+ * {
238
+ * question: 'How do I install hua-ux?',
239
+ * answer: 'Run: npx @hua-labs/create-hua-ux my-app',
240
+ * },
241
+ * ]);
242
+ * ```
243
+ */
244
+ export function generateFAQPageLD(faqs) {
245
+ // Input validation
246
+ if (!faqs || faqs.length === 0) {
247
+ throw new Error('FAQPage requires at least one FAQ item');
248
+ }
249
+ // Filter and validate FAQ items
250
+ const validFaqs = faqs.filter(faq => {
251
+ return faq.question?.trim() && faq.answer?.trim();
252
+ });
253
+ if (validFaqs.length === 0) {
254
+ throw new Error('All FAQ items have empty questions or answers');
255
+ }
256
+ return {
257
+ '@context': 'https://schema.org',
258
+ '@type': 'FAQPage',
259
+ mainEntity: validFaqs.map((faq) => ({
260
+ '@type': 'Question',
261
+ name: faq.question.trim(),
262
+ acceptedAnswer: {
263
+ '@type': 'Answer',
264
+ text: faq.answer.trim(),
265
+ },
266
+ })),
267
+ };
268
+ }
269
+ /**
270
+ * Generate Schema.org TechArticle JSON-LD
271
+ *
272
+ * AI가 기술 문서를 정확하게 이해하도록 기술 아티클 구조화된 데이터 생성
273
+ *
274
+ * @param article - Article configuration
275
+ * @returns Schema.org TechArticle JSON-LD
276
+ *
277
+ * @example
278
+ * ```tsx
279
+ * const articleLd = generateTechArticleLD({
280
+ * headline: 'Getting Started with hua-ux',
281
+ * description: 'Learn how to build privacy-first UX with hua-ux',
282
+ * datePublished: '2025-12-29',
283
+ * author: { name: 'hua-labs' },
284
+ * });
285
+ * ```
286
+ */
287
+ export function generateTechArticleLD(article) {
288
+ return {
289
+ '@context': 'https://schema.org',
290
+ '@type': 'TechArticle',
291
+ headline: article.headline,
292
+ ...(article.description && { description: article.description }),
293
+ ...(article.datePublished && { datePublished: article.datePublished }),
294
+ ...(article.dateModified && { dateModified: article.dateModified }),
295
+ ...(article.author && {
296
+ author: {
297
+ '@type': 'Organization',
298
+ name: article.author.name,
299
+ ...(article.author.url && { url: article.author.url }),
300
+ },
301
+ }),
302
+ ...(article.image && { image: article.image }),
303
+ };
304
+ }
305
+ /**
306
+ * Generate Schema.org HowTo JSON-LD
307
+ *
308
+ * AI가 튜토리얼/가이드를 이해하고 추천할 수 있도록 HowTo 구조화된 데이터 생성
309
+ *
310
+ * @param howTo - HowTo configuration
311
+ * @returns Schema.org HowTo JSON-LD
312
+ *
313
+ * @example
314
+ * ```tsx
315
+ * const howToLd = generateHowToLD({
316
+ * name: 'How to add i18n to your Next.js app',
317
+ * description: 'Step-by-step guide to internationalization',
318
+ * steps: [
319
+ * { name: 'Install hua-ux', text: 'Run: npx @hua-labs/create-hua-ux my-app' },
320
+ * { name: 'Configure i18n', text: 'Add locales to your config' },
321
+ * ],
322
+ * });
323
+ * ```
324
+ */
325
+ export function generateHowToLD(howTo) {
326
+ // Input validation
327
+ if (!howTo.name || howTo.name.trim().length === 0) {
328
+ throw new Error('HowTo.name is required and cannot be empty');
329
+ }
330
+ if (!howTo.steps || howTo.steps.length === 0) {
331
+ throw new Error('HowTo requires at least one step');
332
+ }
333
+ // Filter and validate steps
334
+ const validSteps = howTo.steps
335
+ .filter(step => step.name?.trim() && step.text?.trim())
336
+ .map((step, index) => ({
337
+ '@type': 'HowToStep',
338
+ position: index + 1,
339
+ name: step.name.trim(),
340
+ text: step.text.trim(),
341
+ ...(step.image && { image: step.image }),
342
+ }));
343
+ if (validSteps.length === 0) {
344
+ throw new Error('All HowTo steps have empty names or text');
345
+ }
346
+ return {
347
+ '@context': 'https://schema.org',
348
+ '@type': 'HowTo',
349
+ name: howTo.name.trim(),
350
+ step: validSteps,
351
+ ...(howTo.description && { description: howTo.description }),
352
+ ...(howTo.totalTime && { totalTime: howTo.totalTime }),
353
+ };
354
+ }
@@ -0,0 +1,78 @@
1
+ /**
2
+ * @hua-labs/hua-ux/framework - GEO Test Utilities
3
+ *
4
+ * Testing utilities for GEO metadata validation and debugging
5
+ * GEO 메타데이터 검증 및 디버깅을 위한 테스트 유틸리티
6
+ */
7
+ import type { GEOMetadata } from './types';
8
+ /**
9
+ * Validation result
10
+ * 검증 결과
11
+ */
12
+ export interface GEOValidationResult {
13
+ /**
14
+ * Whether the metadata is valid
15
+ */
16
+ valid: boolean;
17
+ /**
18
+ * Array of error messages
19
+ */
20
+ errors: string[];
21
+ /**
22
+ * Array of warning messages
23
+ */
24
+ warnings: string[];
25
+ }
26
+ /**
27
+ * Validate GEO metadata
28
+ *
29
+ * GEO 메타데이터의 유효성을 검증합니다.
30
+ *
31
+ * @param metadata - GEO metadata to validate
32
+ * @returns Validation result with errors and warnings
33
+ *
34
+ * @example
35
+ * ```tsx
36
+ * const result = validateGEOMetadata(geoMeta);
37
+ * if (!result.valid) {
38
+ * console.error('Validation errors:', result.errors);
39
+ * }
40
+ * ```
41
+ */
42
+ export declare function validateGEOMetadata(metadata: GEOMetadata): GEOValidationResult;
43
+ /**
44
+ * Pretty print GEO metadata
45
+ *
46
+ * GEO 메타데이터를 읽기 쉬운 형식으로 출력합니다.
47
+ *
48
+ * @param metadata - GEO metadata to print
49
+ * @returns Formatted JSON string
50
+ *
51
+ * @example
52
+ * ```tsx
53
+ * console.log(prettyPrintGEOMetadata(geoMeta));
54
+ * ```
55
+ */
56
+ export declare function prettyPrintGEOMetadata(metadata: GEOMetadata): string;
57
+ /**
58
+ * Compare two GEO metadata objects
59
+ *
60
+ * 두 GEO 메타데이터 객체를 비교합니다.
61
+ *
62
+ * @param a - First GEO metadata
63
+ * @param b - Second GEO metadata
64
+ * @returns Comparison result with differences
65
+ *
66
+ * @example
67
+ * ```tsx
68
+ * const result = compareGEOMetadata(meta1, meta2);
69
+ * if (!result.same) {
70
+ * console.log('Differences:', result.differences);
71
+ * }
72
+ * ```
73
+ */
74
+ export declare function compareGEOMetadata(a: GEOMetadata, b: GEOMetadata): {
75
+ same: boolean;
76
+ differences: string[];
77
+ };
78
+ //# sourceMappingURL=test-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-utils.d.ts","sourceRoot":"","sources":["../../../../src/framework/seo/geo/test-utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE3C;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC;;OAEG;IACH,KAAK,EAAE,OAAO,CAAC;IAEf;;OAEG;IACH,MAAM,EAAE,MAAM,EAAE,CAAC;IAEjB;;OAEG;IACH,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,WAAW,GAAG,mBAAmB,CA0D9E;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,WAAW,GAAG,MAAM,CAEpE;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,kBAAkB,CAChC,CAAC,EAAE,WAAW,EACd,CAAC,EAAE,WAAW,GACb;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,WAAW,EAAE,MAAM,EAAE,CAAA;CAAE,CAmC1C"}