@bloomneo/uikit 1.5.0
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/CHANGELOG.md +222 -0
- package/LICENSE +21 -0
- package/README.md +513 -0
- package/bin/commands/build.js +232 -0
- package/bin/commands/bundle.js +587 -0
- package/bin/commands/create.js +768 -0
- package/bin/commands/deploy.js +533 -0
- package/bin/commands/generate.js +673 -0
- package/bin/commands/optimize.js +198 -0
- package/bin/commands/prerender.js +306 -0
- package/bin/commands/serve.js +216 -0
- package/bin/templates/fbca/README.md.template +130 -0
- package/bin/templates/fbca/docs/QUICKSTART_FBCA.md +368 -0
- package/bin/templates/fbca/docs/UIKIT_CLI_GUIDE.md +574 -0
- package/bin/templates/fbca/docs/UIKIT_COMPOSITE_UI_SYSTEM.md +649 -0
- package/bin/templates/fbca/docs/UIKIT_LLM_GUIDE.md +2055 -0
- package/bin/templates/fbca/docs/UIKIT_THEME_GUIDE.md +359 -0
- package/bin/templates/fbca/package.json.template +41 -0
- package/bin/templates/fbca/public/favicon.svg +10 -0
- package/bin/templates/fbca/public/hero_fbca.svg +1 -0
- package/bin/templates/fbca/src/utils/asset.ts +6 -0
- package/bin/templates/fbca/src/web/App.tsx.template +20 -0
- package/bin/templates/fbca/src/web/features/auth/pages/index.tsx.template +157 -0
- package/bin/templates/fbca/src/web/features/docs/pages/[...slug].tsx.template +83 -0
- package/bin/templates/fbca/src/web/features/gallery/hooks/useGallery.ts.template +74 -0
- package/bin/templates/fbca/src/web/features/gallery/pages/index.tsx.template +136 -0
- package/bin/templates/fbca/src/web/features/main/components/CTASection.tsx.template +43 -0
- package/bin/templates/fbca/src/web/features/main/pages/About.tsx.template +374 -0
- package/bin/templates/fbca/src/web/features/main/pages/index.tsx.template +214 -0
- package/bin/templates/fbca/src/web/index.html.template +15 -0
- package/bin/templates/fbca/src/web/lib/page-router.tsx.template +134 -0
- package/bin/templates/fbca/src/web/main.tsx.template +14 -0
- package/bin/templates/fbca/src/web/shared/components/Footer.tsx.template +57 -0
- package/bin/templates/fbca/src/web/shared/components/Header.tsx.template +91 -0
- package/bin/templates/fbca/src/web/shared/components/SEO.tsx.template +24 -0
- package/bin/templates/fbca/src/web/shared/components/index.ts.template +3 -0
- package/bin/templates/fbca/src/web/shared/hooks/useSEO.ts.template +85 -0
- package/bin/templates/fbca/src/web/shared/utils/asset.ts +6 -0
- package/bin/templates/fbca/src/web/styles/index.css.template +8 -0
- package/bin/templates/fbca/src/web/utils/asset.ts +6 -0
- package/bin/templates/fbca/tsconfig.json.template +32 -0
- package/bin/templates/fbca/tsconfig.node.json.template +10 -0
- package/bin/templates/fbca/vite.config.ts.template +38 -0
- package/bin/templates/generate/component/component.tsx.template +79 -0
- package/bin/templates/generate/component/index.ts.template +2 -0
- package/bin/templates/generate/component/types.ts.template +58 -0
- package/bin/templates/generate/feature/index.ts.template +14 -0
- package/bin/templates/generate/feature/list-page.tsx.template +34 -0
- package/bin/templates/generate/feature/main-component.tsx.template +37 -0
- package/bin/templates/generate/feature/main-page.tsx.template +30 -0
- package/bin/templates/generate/feature/types.ts.template +34 -0
- package/bin/templates/generate/hook/hook.ts.template +35 -0
- package/bin/templates/generate/index.css.template +10 -0
- package/bin/templates/generate/main.tsx.template +10 -0
- package/bin/templates/generate/page/index.ts.template +2 -0
- package/bin/templates/generate/page/page.tsx.template +86 -0
- package/bin/templates/generate/theme/README.md +31 -0
- package/bin/templates/generate/theme/theme.js.template +155 -0
- package/bin/templates/multi/README.md.template +120 -0
- package/bin/templates/multi/docs/QUICKSTART_MULTI.md +334 -0
- package/bin/templates/multi/docs/UIKIT_CLI_GUIDE.md +574 -0
- package/bin/templates/multi/docs/UIKIT_COMPOSITE_UI_SYSTEM.md +649 -0
- package/bin/templates/multi/docs/UIKIT_LLM_GUIDE.md +2055 -0
- package/bin/templates/multi/docs/UIKIT_THEME_GUIDE.md +359 -0
- package/bin/templates/multi/index.html.template +58 -0
- package/bin/templates/multi/package.json.template +35 -0
- package/bin/templates/multi/public/favicon.svg +10 -0
- package/bin/templates/multi/public/hero_multi.svg +1 -0
- package/bin/templates/multi/src/App.tsx.template +92 -0
- package/bin/templates/multi/src/components/Footer.tsx.template +58 -0
- package/bin/templates/multi/src/components/Header.tsx.template +103 -0
- package/bin/templates/multi/src/components/SEO.tsx.template +19 -0
- package/bin/templates/multi/src/components/index.ts.template +3 -0
- package/bin/templates/multi/src/hooks/useSEO.ts.template +38 -0
- package/bin/templates/multi/src/index.css.template +7 -0
- package/bin/templates/multi/src/main.tsx.template +14 -0
- package/bin/templates/multi/src/pages/About.tsx.template +276 -0
- package/bin/templates/multi/src/pages/Components.tsx.template +288 -0
- package/bin/templates/multi/src/pages/Contact.tsx.template +348 -0
- package/bin/templates/multi/src/pages/Dashboard.tsx.template +306 -0
- package/bin/templates/multi/src/pages/ErrorPage.tsx.template +37 -0
- package/bin/templates/multi/src/pages/Home.tsx.template +201 -0
- package/bin/templates/multi/src/pages/Login.tsx.template +148 -0
- package/bin/templates/multi/src/pages/Themes.tsx.template +207 -0
- package/bin/templates/multi/src/router.tsx.template +34 -0
- package/bin/templates/multi/src/utils/asset.ts +6 -0
- package/bin/templates/multi/tsconfig.json.template +30 -0
- package/bin/templates/multi/tsconfig.node.json +22 -0
- package/bin/templates/multi/vite.config.ts.template +36 -0
- package/bin/templates/single/README.md.template +131 -0
- package/bin/templates/single/docs/QUICKSTART_SINGLE.md +259 -0
- package/bin/templates/single/docs/UIKIT_CLI_GUIDE.md +574 -0
- package/bin/templates/single/docs/UIKIT_COMPOSITE_UI_SYSTEM.md +649 -0
- package/bin/templates/single/docs/UIKIT_LLM_GUIDE.md +2055 -0
- package/bin/templates/single/docs/UIKIT_THEME_GUIDE.md +359 -0
- package/bin/templates/single/index.html.template +37 -0
- package/bin/templates/single/package.json.template +34 -0
- package/bin/templates/single/public/favicon.svg +10 -0
- package/bin/templates/single/public/hero.svg +1 -0
- package/bin/templates/single/src/App.tsx.template +233 -0
- package/bin/templates/single/src/index.css.template +7 -0
- package/bin/templates/single/src/main.tsx.template +14 -0
- package/bin/templates/single/src/styles/fonts.css +99 -0
- package/bin/templates/single/src/utils/asset.ts +6 -0
- package/bin/templates/single/tsconfig.json +31 -0
- package/bin/templates/single/tsconfig.node.json +22 -0
- package/bin/templates/single/vite.config.ts.template +36 -0
- package/bin/templates/spa/README.md.template +105 -0
- package/bin/templates/spa/components/SEO.tsx.template +19 -0
- package/bin/templates/spa/docs/QUICKSTART_SPA.md +300 -0
- package/bin/templates/spa/docs/UIKIT_CLI_GUIDE.md +574 -0
- package/bin/templates/spa/docs/UIKIT_COMPOSITE_UI_SYSTEM.md +649 -0
- package/bin/templates/spa/docs/UIKIT_LLM_GUIDE.md +2055 -0
- package/bin/templates/spa/docs/UIKIT_THEME_GUIDE.md +359 -0
- package/bin/templates/spa/hooks/useSEO.ts.template +38 -0
- package/bin/templates/spa/index.html.template +58 -0
- package/bin/templates/spa/package.json.template +35 -0
- package/bin/templates/spa/public/favicon.svg +15 -0
- package/bin/templates/spa/public/hero_spa.svg +1 -0
- package/bin/templates/spa/src/App.tsx.template +659 -0
- package/bin/templates/spa/src/index.css.template +7 -0
- package/bin/templates/spa/src/main.tsx.template +14 -0
- package/bin/templates/spa/src/utils/asset.ts +6 -0
- package/bin/templates/spa/tsconfig.json.template +30 -0
- package/bin/templates/spa/tsconfig.node.json +22 -0
- package/bin/templates/spa/vite.config.ts.template +36 -0
- package/bin/uikit.js +133 -0
- package/cookbook/README.md +20 -0
- package/cookbook/crud-page.tsx +99 -0
- package/cookbook/dashboard.tsx +89 -0
- package/cookbook/delete-flow.tsx +59 -0
- package/cookbook/login.tsx +85 -0
- package/cookbook/settings.tsx +113 -0
- package/dist/Combination-C0DFrmJW.js +674 -0
- package/dist/Combination-C0DFrmJW.js.map +1 -0
- package/dist/accordion.js +284 -0
- package/dist/accordion.js.map +1 -0
- package/dist/admin.js +429 -0
- package/dist/admin.js.map +1 -0
- package/dist/alert.js +67 -0
- package/dist/alert.js.map +1 -0
- package/dist/auth.js +178 -0
- package/dist/auth.js.map +1 -0
- package/dist/avatar.js +249 -0
- package/dist/avatar.js.map +1 -0
- package/dist/badge.js +40 -0
- package/dist/badge.js.map +1 -0
- package/dist/blank.js +80 -0
- package/dist/blank.js.map +1 -0
- package/dist/breadcrumb.js +104 -0
- package/dist/breadcrumb.js.map +1 -0
- package/dist/button.js +50 -0
- package/dist/button.js.map +1 -0
- package/dist/calendar.js +2785 -0
- package/dist/calendar.js.map +1 -0
- package/dist/card.js +91 -0
- package/dist/card.js.map +1 -0
- package/dist/check-DXouwtzp.js +12 -0
- package/dist/check-DXouwtzp.js.map +1 -0
- package/dist/checkbox.js +268 -0
- package/dist/checkbox.js.map +1 -0
- package/dist/chevron-down-BORJtX8F.js +14 -0
- package/dist/chevron-down-BORJtX8F.js.map +1 -0
- package/dist/chevron-left-C1pkx4AF.js +14 -0
- package/dist/chevron-left-C1pkx4AF.js.map +1 -0
- package/dist/chevron-right-pz9eCjj-.js +14 -0
- package/dist/chevron-right-pz9eCjj-.js.map +1 -0
- package/dist/circle-DHOdTDQh.js +14 -0
- package/dist/circle-DHOdTDQh.js.map +1 -0
- package/dist/collapsible.js +35 -0
- package/dist/collapsible.js.map +1 -0
- package/dist/command.js +481 -0
- package/dist/command.js.map +1 -0
- package/dist/confirm-dialog.js +129 -0
- package/dist/confirm-dialog.js.map +1 -0
- package/dist/container.js +334 -0
- package/dist/container.js.map +1 -0
- package/dist/createLucideIcon-B45kRl5r.js +80 -0
- package/dist/createLucideIcon-B45kRl5r.js.map +1 -0
- package/dist/data-table.js +574 -0
- package/dist/data-table.js.map +1 -0
- package/dist/detail-page.js +454 -0
- package/dist/detail-page.js.map +1 -0
- package/dist/dialog.js +137 -0
- package/dist/dialog.js.map +1 -0
- package/dist/dropdown-menu.js +424 -0
- package/dist/dropdown-menu.js.map +1 -0
- package/dist/ellipsis-BhAoKPVk.js +16 -0
- package/dist/ellipsis-BhAoKPVk.js.map +1 -0
- package/dist/empty-state.js +54 -0
- package/dist/empty-state.js.map +1 -0
- package/dist/errors.js +36 -0
- package/dist/errors.js.map +1 -0
- package/dist/eye-DDKoW0KS.js +46 -0
- package/dist/eye-DDKoW0KS.js.map +1 -0
- package/dist/fonts/caveat-cyrillic-400-normal.woff +0 -0
- package/dist/fonts/caveat-cyrillic-400-normal.woff2 +0 -0
- package/dist/fonts/caveat-cyrillic-700-normal.woff +0 -0
- package/dist/fonts/caveat-cyrillic-700-normal.woff2 +0 -0
- package/dist/fonts/caveat-cyrillic-ext-400-normal.woff +0 -0
- package/dist/fonts/caveat-cyrillic-ext-400-normal.woff2 +0 -0
- package/dist/fonts/caveat-cyrillic-ext-700-normal.woff +0 -0
- package/dist/fonts/caveat-cyrillic-ext-700-normal.woff2 +0 -0
- package/dist/fonts/caveat-latin-400-normal.woff +0 -0
- package/dist/fonts/caveat-latin-400-normal.woff2 +0 -0
- package/dist/fonts/caveat-latin-700-normal.woff +0 -0
- package/dist/fonts/caveat-latin-700-normal.woff2 +0 -0
- package/dist/fonts/caveat-latin-ext-400-normal.woff +0 -0
- package/dist/fonts/caveat-latin-ext-400-normal.woff2 +0 -0
- package/dist/fonts/caveat-latin-ext-700-normal.woff +0 -0
- package/dist/fonts/caveat-latin-ext-700-normal.woff2 +0 -0
- package/dist/fonts/crimson-text-latin-400-normal.woff +0 -0
- package/dist/fonts/crimson-text-latin-400-normal.woff2 +0 -0
- package/dist/fonts/crimson-text-latin-600-normal.woff +0 -0
- package/dist/fonts/crimson-text-latin-600-normal.woff2 +0 -0
- package/dist/fonts/crimson-text-latin-700-normal.woff +0 -0
- package/dist/fonts/crimson-text-latin-700-normal.woff2 +0 -0
- package/dist/fonts/crimson-text-latin-ext-400-normal.woff +0 -0
- package/dist/fonts/crimson-text-latin-ext-400-normal.woff2 +0 -0
- package/dist/fonts/crimson-text-latin-ext-600-normal.woff +0 -0
- package/dist/fonts/crimson-text-latin-ext-600-normal.woff2 +0 -0
- package/dist/fonts/crimson-text-latin-ext-700-normal.woff +0 -0
- package/dist/fonts/crimson-text-latin-ext-700-normal.woff2 +0 -0
- package/dist/fonts/crimson-text-vietnamese-400-normal.woff +0 -0
- package/dist/fonts/crimson-text-vietnamese-400-normal.woff2 +0 -0
- package/dist/fonts/crimson-text-vietnamese-600-normal.woff +0 -0
- package/dist/fonts/crimson-text-vietnamese-600-normal.woff2 +0 -0
- package/dist/fonts/crimson-text-vietnamese-700-normal.woff +0 -0
- package/dist/fonts/crimson-text-vietnamese-700-normal.woff2 +0 -0
- package/dist/fonts/dm-serif-display-latin-400-normal.woff +0 -0
- package/dist/fonts/dm-serif-display-latin-400-normal.woff2 +0 -0
- package/dist/fonts/dm-serif-display-latin-ext-400-normal.woff +0 -0
- package/dist/fonts/dm-serif-display-latin-ext-400-normal.woff2 +0 -0
- package/dist/fonts/libre-baskerville-latin-400-normal.woff +0 -0
- package/dist/fonts/libre-baskerville-latin-400-normal.woff2 +0 -0
- package/dist/fonts/libre-baskerville-latin-700-normal.woff +0 -0
- package/dist/fonts/libre-baskerville-latin-700-normal.woff2 +0 -0
- package/dist/fonts/libre-baskerville-latin-ext-400-normal.woff +0 -0
- package/dist/fonts/libre-baskerville-latin-ext-400-normal.woff2 +0 -0
- package/dist/fonts/libre-baskerville-latin-ext-700-normal.woff +0 -0
- package/dist/fonts/libre-baskerville-latin-ext-700-normal.woff2 +0 -0
- package/dist/fonts/montserrat-cyrillic-400-normal.woff +0 -0
- package/dist/fonts/montserrat-cyrillic-400-normal.woff2 +0 -0
- package/dist/fonts/montserrat-cyrillic-500-normal.woff +0 -0
- package/dist/fonts/montserrat-cyrillic-500-normal.woff2 +0 -0
- package/dist/fonts/montserrat-cyrillic-600-normal.woff +0 -0
- package/dist/fonts/montserrat-cyrillic-600-normal.woff2 +0 -0
- package/dist/fonts/montserrat-cyrillic-ext-400-normal.woff +0 -0
- package/dist/fonts/montserrat-cyrillic-ext-400-normal.woff2 +0 -0
- package/dist/fonts/montserrat-cyrillic-ext-500-normal.woff +0 -0
- package/dist/fonts/montserrat-cyrillic-ext-500-normal.woff2 +0 -0
- package/dist/fonts/montserrat-cyrillic-ext-600-normal.woff +0 -0
- package/dist/fonts/montserrat-cyrillic-ext-600-normal.woff2 +0 -0
- package/dist/fonts/montserrat-latin-400-normal.woff +0 -0
- package/dist/fonts/montserrat-latin-400-normal.woff2 +0 -0
- package/dist/fonts/montserrat-latin-500-normal.woff +0 -0
- package/dist/fonts/montserrat-latin-500-normal.woff2 +0 -0
- package/dist/fonts/montserrat-latin-600-normal.woff +0 -0
- package/dist/fonts/montserrat-latin-600-normal.woff2 +0 -0
- package/dist/fonts/montserrat-latin-ext-400-normal.woff +0 -0
- package/dist/fonts/montserrat-latin-ext-400-normal.woff2 +0 -0
- package/dist/fonts/montserrat-latin-ext-500-normal.woff +0 -0
- package/dist/fonts/montserrat-latin-ext-500-normal.woff2 +0 -0
- package/dist/fonts/montserrat-latin-ext-600-normal.woff +0 -0
- package/dist/fonts/montserrat-latin-ext-600-normal.woff2 +0 -0
- package/dist/fonts/montserrat-vietnamese-400-normal.woff +0 -0
- package/dist/fonts/montserrat-vietnamese-400-normal.woff2 +0 -0
- package/dist/fonts/montserrat-vietnamese-500-normal.woff +0 -0
- package/dist/fonts/montserrat-vietnamese-500-normal.woff2 +0 -0
- package/dist/fonts/montserrat-vietnamese-600-normal.woff +0 -0
- package/dist/fonts/montserrat-vietnamese-600-normal.woff2 +0 -0
- package/dist/fonts/playfair-display-cyrillic-400-normal.woff +0 -0
- package/dist/fonts/playfair-display-cyrillic-400-normal.woff2 +0 -0
- package/dist/fonts/playfair-display-cyrillic-500-normal.woff +0 -0
- package/dist/fonts/playfair-display-cyrillic-500-normal.woff2 +0 -0
- package/dist/fonts/playfair-display-latin-400-normal.woff +0 -0
- package/dist/fonts/playfair-display-latin-400-normal.woff2 +0 -0
- package/dist/fonts/playfair-display-latin-500-normal.woff +0 -0
- package/dist/fonts/playfair-display-latin-500-normal.woff2 +0 -0
- package/dist/fonts/playfair-display-latin-ext-400-normal.woff +0 -0
- package/dist/fonts/playfair-display-latin-ext-400-normal.woff2 +0 -0
- package/dist/fonts/playfair-display-latin-ext-500-normal.woff +0 -0
- package/dist/fonts/playfair-display-latin-ext-500-normal.woff2 +0 -0
- package/dist/fonts/playfair-display-vietnamese-400-normal.woff +0 -0
- package/dist/fonts/playfair-display-vietnamese-400-normal.woff2 +0 -0
- package/dist/fonts/playfair-display-vietnamese-500-normal.woff +0 -0
- package/dist/fonts/playfair-display-vietnamese-500-normal.woff2 +0 -0
- package/dist/fonts/poppins-devanagari-400-normal.woff +0 -0
- package/dist/fonts/poppins-devanagari-400-normal.woff2 +0 -0
- package/dist/fonts/poppins-devanagari-500-normal.woff +0 -0
- package/dist/fonts/poppins-devanagari-500-normal.woff2 +0 -0
- package/dist/fonts/poppins-devanagari-600-normal.woff +0 -0
- package/dist/fonts/poppins-devanagari-600-normal.woff2 +0 -0
- package/dist/fonts/poppins-latin-400-normal.woff +0 -0
- package/dist/fonts/poppins-latin-400-normal.woff2 +0 -0
- package/dist/fonts/poppins-latin-500-normal.woff +0 -0
- package/dist/fonts/poppins-latin-500-normal.woff2 +0 -0
- package/dist/fonts/poppins-latin-600-normal.woff +0 -0
- package/dist/fonts/poppins-latin-600-normal.woff2 +0 -0
- package/dist/fonts/poppins-latin-ext-400-normal.woff +0 -0
- package/dist/fonts/poppins-latin-ext-400-normal.woff2 +0 -0
- package/dist/fonts/poppins-latin-ext-500-normal.woff +0 -0
- package/dist/fonts/poppins-latin-ext-500-normal.woff2 +0 -0
- package/dist/fonts/poppins-latin-ext-600-normal.woff +0 -0
- package/dist/fonts/poppins-latin-ext-600-normal.woff2 +0 -0
- package/dist/fonts/rubik-arabic-400-normal.woff +0 -0
- package/dist/fonts/rubik-arabic-400-normal.woff2 +0 -0
- package/dist/fonts/rubik-arabic-500-normal.woff +0 -0
- package/dist/fonts/rubik-arabic-500-normal.woff2 +0 -0
- package/dist/fonts/rubik-cyrillic-400-normal.woff +0 -0
- package/dist/fonts/rubik-cyrillic-400-normal.woff2 +0 -0
- package/dist/fonts/rubik-cyrillic-500-normal.woff +0 -0
- package/dist/fonts/rubik-cyrillic-500-normal.woff2 +0 -0
- package/dist/fonts/rubik-cyrillic-ext-400-normal.woff +0 -0
- package/dist/fonts/rubik-cyrillic-ext-400-normal.woff2 +0 -0
- package/dist/fonts/rubik-cyrillic-ext-500-normal.woff +0 -0
- package/dist/fonts/rubik-cyrillic-ext-500-normal.woff2 +0 -0
- package/dist/fonts/rubik-hebrew-400-normal.woff +0 -0
- package/dist/fonts/rubik-hebrew-400-normal.woff2 +0 -0
- package/dist/fonts/rubik-hebrew-500-normal.woff +0 -0
- package/dist/fonts/rubik-hebrew-500-normal.woff2 +0 -0
- package/dist/fonts/rubik-latin-400-normal.woff +0 -0
- package/dist/fonts/rubik-latin-400-normal.woff2 +0 -0
- package/dist/fonts/rubik-latin-500-normal.woff +0 -0
- package/dist/fonts/rubik-latin-500-normal.woff2 +0 -0
- package/dist/fonts/rubik-latin-ext-400-normal.woff +0 -0
- package/dist/fonts/rubik-latin-ext-400-normal.woff2 +0 -0
- package/dist/fonts/rubik-latin-ext-500-normal.woff +0 -0
- package/dist/fonts/rubik-latin-ext-500-normal.woff2 +0 -0
- package/dist/fonts/source-serif-pro-cyrillic-400-normal.woff +0 -0
- package/dist/fonts/source-serif-pro-cyrillic-400-normal.woff2 +0 -0
- package/dist/fonts/source-serif-pro-cyrillic-ext-400-normal.woff +0 -0
- package/dist/fonts/source-serif-pro-cyrillic-ext-400-normal.woff2 +0 -0
- package/dist/fonts/source-serif-pro-greek-400-normal.woff +0 -0
- package/dist/fonts/source-serif-pro-greek-400-normal.woff2 +0 -0
- package/dist/fonts/source-serif-pro-latin-400-normal.woff +0 -0
- package/dist/fonts/source-serif-pro-latin-400-normal.woff2 +0 -0
- package/dist/fonts/source-serif-pro-latin-ext-400-normal.woff +0 -0
- package/dist/fonts/source-serif-pro-latin-ext-400-normal.woff2 +0 -0
- package/dist/fonts/source-serif-pro-vietnamese-400-normal.woff +0 -0
- package/dist/fonts/source-serif-pro-vietnamese-400-normal.woff2 +0 -0
- package/dist/fonts/space-grotesk-latin-400-normal.woff +0 -0
- package/dist/fonts/space-grotesk-latin-400-normal.woff2 +0 -0
- package/dist/fonts/space-grotesk-latin-600-normal.woff +0 -0
- package/dist/fonts/space-grotesk-latin-600-normal.woff2 +0 -0
- package/dist/fonts/space-grotesk-latin-700-normal.woff +0 -0
- package/dist/fonts/space-grotesk-latin-700-normal.woff2 +0 -0
- package/dist/fonts/space-grotesk-latin-ext-400-normal.woff +0 -0
- package/dist/fonts/space-grotesk-latin-ext-400-normal.woff2 +0 -0
- package/dist/fonts/space-grotesk-latin-ext-600-normal.woff +0 -0
- package/dist/fonts/space-grotesk-latin-ext-600-normal.woff2 +0 -0
- package/dist/fonts/space-grotesk-latin-ext-700-normal.woff +0 -0
- package/dist/fonts/space-grotesk-latin-ext-700-normal.woff2 +0 -0
- package/dist/fonts/space-grotesk-vietnamese-400-normal.woff +0 -0
- package/dist/fonts/space-grotesk-vietnamese-400-normal.woff2 +0 -0
- package/dist/fonts/space-grotesk-vietnamese-600-normal.woff +0 -0
- package/dist/fonts/space-grotesk-vietnamese-600-normal.woff2 +0 -0
- package/dist/fonts/space-grotesk-vietnamese-700-normal.woff +0 -0
- package/dist/fonts/space-grotesk-vietnamese-700-normal.woff2 +0 -0
- package/dist/fonts/work-sans-latin-400-normal.woff +0 -0
- package/dist/fonts/work-sans-latin-400-normal.woff2 +0 -0
- package/dist/fonts/work-sans-latin-500-normal.woff +0 -0
- package/dist/fonts/work-sans-latin-500-normal.woff2 +0 -0
- package/dist/fonts/work-sans-latin-ext-400-normal.woff +0 -0
- package/dist/fonts/work-sans-latin-ext-400-normal.woff2 +0 -0
- package/dist/fonts/work-sans-latin-ext-500-normal.woff +0 -0
- package/dist/fonts/work-sans-latin-ext-500-normal.woff2 +0 -0
- package/dist/fonts/work-sans-vietnamese-400-normal.woff +0 -0
- package/dist/fonts/work-sans-vietnamese-400-normal.woff2 +0 -0
- package/dist/fonts/work-sans-vietnamese-500-normal.woff +0 -0
- package/dist/fonts/work-sans-vietnamese-500-normal.woff2 +0 -0
- package/dist/footer.js +308 -0
- package/dist/footer.js.map +1 -0
- package/dist/form-field.js +69 -0
- package/dist/form-field.js.map +1 -0
- package/dist/form.js +732 -0
- package/dist/form.js.map +1 -0
- package/dist/format.js +112 -0
- package/dist/format.js.map +1 -0
- package/dist/fouc.js +28 -0
- package/dist/fouc.js.map +1 -0
- package/dist/header.js +289 -0
- package/dist/header.js.map +1 -0
- package/dist/hooks.js +13 -0
- package/dist/hooks.js.map +1 -0
- package/dist/hover-card.js +210 -0
- package/dist/hover-card.js.map +1 -0
- package/dist/index-0ioNhtNM.js +11 -0
- package/dist/index-0ioNhtNM.js.map +1 -0
- package/dist/index-1QHKgw6D.js +55 -0
- package/dist/index-1QHKgw6D.js.map +1 -0
- package/dist/index-B6sSWi7l.js +747 -0
- package/dist/index-B6sSWi7l.js.map +1 -0
- package/dist/index-BCjJQGh8.js +71 -0
- package/dist/index-BCjJQGh8.js.map +1 -0
- package/dist/index-BGQepRFJ.js +28 -0
- package/dist/index-BGQepRFJ.js.map +1 -0
- package/dist/index-BVRIAMfe.js +37 -0
- package/dist/index-BVRIAMfe.js.map +1 -0
- package/dist/index-BY7PeRJA.js +145 -0
- package/dist/index-BY7PeRJA.js.map +1 -0
- package/dist/index-BZPx6jYI.js +9 -0
- package/dist/index-BZPx6jYI.js.map +1 -0
- package/dist/index-Ba4eHUBD.js +243 -0
- package/dist/index-Ba4eHUBD.js.map +1 -0
- package/dist/index-Bke1qZdk.js +35 -0
- package/dist/index-Bke1qZdk.js.map +1 -0
- package/dist/index-C0UREtMP.js +60 -0
- package/dist/index-C0UREtMP.js.map +1 -0
- package/dist/index-CCKe-Mpx.js +7 -0
- package/dist/index-CCKe-Mpx.js.map +1 -0
- package/dist/index-DFZozV_h.js +69 -0
- package/dist/index-DFZozV_h.js.map +1 -0
- package/dist/index-DFi6WydO.js +180 -0
- package/dist/index-DFi6WydO.js.map +1 -0
- package/dist/index-DQH6odE9.js +83 -0
- package/dist/index-DQH6odE9.js.map +1 -0
- package/dist/index-EO5flKM3.js +119 -0
- package/dist/index-EO5flKM3.js.map +1 -0
- package/dist/index-Lf7yDOXW.js +615 -0
- package/dist/index-Lf7yDOXW.js.map +1 -0
- package/dist/index-dhIqEbxW.js +1541 -0
- package/dist/index-dhIqEbxW.js.map +1 -0
- package/dist/index-pWhlqjff.js +32 -0
- package/dist/index-pWhlqjff.js.map +1 -0
- package/dist/index-rKs9bXHr.js +7 -0
- package/dist/index-rKs9bXHr.js.map +1 -0
- package/dist/index-xqkGMOJ8.js +14 -0
- package/dist/index-xqkGMOJ8.js.map +1 -0
- package/dist/index.js +247 -0
- package/dist/index.js.map +1 -0
- package/dist/input.js +22 -0
- package/dist/input.js.map +1 -0
- package/dist/label.js +36 -0
- package/dist/label.js.map +1 -0
- package/dist/layout-wrapper.js +208 -0
- package/dist/layout-wrapper.js.map +1 -0
- package/dist/llms.txt +1140 -0
- package/dist/menu-DBhEanGo.js +16 -0
- package/dist/menu-DBhEanGo.js.map +1 -0
- package/dist/menubar.js +565 -0
- package/dist/menubar.js.map +1 -0
- package/dist/mobile.js +183 -0
- package/dist/mobile.js.map +1 -0
- package/dist/motion.js +119 -0
- package/dist/motion.js.map +1 -0
- package/dist/page-header.js +47 -0
- package/dist/page-header.js.map +1 -0
- package/dist/page.js +214 -0
- package/dist/page.js.map +1 -0
- package/dist/pagination.js +121 -0
- package/dist/pagination.js.map +1 -0
- package/dist/platform.js +194 -0
- package/dist/platform.js.map +1 -0
- package/dist/popover.js +263 -0
- package/dist/popover.js.map +1 -0
- package/dist/popup.js +335 -0
- package/dist/popup.js.map +1 -0
- package/dist/progress.js +108 -0
- package/dist/progress.js.map +1 -0
- package/dist/radio-group.js +272 -0
- package/dist/radio-group.js.map +1 -0
- package/dist/safe-area.js +42 -0
- package/dist/safe-area.js.map +1 -0
- package/dist/search-CpUwRnG-.js +15 -0
- package/dist/search-CpUwRnG-.js.map +1 -0
- package/dist/select.js +985 -0
- package/dist/select.js.map +1 -0
- package/dist/separator.js +45 -0
- package/dist/separator.js.map +1 -0
- package/dist/sheet.js +127 -0
- package/dist/sheet.js.map +1 -0
- package/dist/skeleton.js +16 -0
- package/dist/skeleton.js.map +1 -0
- package/dist/slider.js +485 -0
- package/dist/slider.js.map +1 -0
- package/dist/sonner.js +52 -0
- package/dist/sonner.js.map +1 -0
- package/dist/styles/fonts.css +253 -0
- package/dist/styles.css +2 -0
- package/dist/switch.js +155 -0
- package/dist/switch.js.map +1 -0
- package/dist/tab-bar.js +110 -0
- package/dist/tab-bar.js.map +1 -0
- package/dist/table.js +115 -0
- package/dist/table.js.map +1 -0
- package/dist/tabs.js +218 -0
- package/dist/tabs.js.map +1 -0
- package/dist/textarea.js +19 -0
- package/dist/textarea.js.map +1 -0
- package/dist/theme-provider.js +154 -0
- package/dist/theme-provider.js.map +1 -0
- package/dist/themes.js +873 -0
- package/dist/themes.js.map +1 -0
- package/dist/toast.js +63 -0
- package/dist/toast.js.map +1 -0
- package/dist/toggle.js +70 -0
- package/dist/toggle.js.map +1 -0
- package/dist/tooltip.js +375 -0
- package/dist/tooltip.js.map +1 -0
- package/dist/types/App.d.ts +3 -0
- package/dist/types/App.d.ts.map +1 -0
- package/dist/types/components/layouts/admin.d.ts +117 -0
- package/dist/types/components/layouts/admin.d.ts.map +1 -0
- package/dist/types/components/layouts/auth.d.ts +17 -0
- package/dist/types/components/layouts/auth.d.ts.map +1 -0
- package/dist/types/components/layouts/blank.d.ts +63 -0
- package/dist/types/components/layouts/blank.d.ts.map +1 -0
- package/dist/types/components/layouts/layout-wrapper.d.ts +130 -0
- package/dist/types/components/layouts/layout-wrapper.d.ts.map +1 -0
- package/dist/types/components/layouts/mobile.d.ts +91 -0
- package/dist/types/components/layouts/mobile.d.ts.map +1 -0
- package/dist/types/components/layouts/page.d.ts +181 -0
- package/dist/types/components/layouts/page.d.ts.map +1 -0
- package/dist/types/components/layouts/popup.d.ts +100 -0
- package/dist/types/components/layouts/popup.d.ts.map +1 -0
- package/dist/types/components/sections/container.d.ts +79 -0
- package/dist/types/components/sections/container.d.ts.map +1 -0
- package/dist/types/components/sections/footer.d.ts +128 -0
- package/dist/types/components/sections/footer.d.ts.map +1 -0
- package/dist/types/components/sections/header.d.ts +72 -0
- package/dist/types/components/sections/header.d.ts.map +1 -0
- package/dist/types/components/sections/safe-area.d.ts +46 -0
- package/dist/types/components/sections/safe-area.d.ts.map +1 -0
- package/dist/types/components/sections/tab-bar.d.ts +61 -0
- package/dist/types/components/sections/tab-bar.d.ts.map +1 -0
- package/dist/types/components/ui/accordion.d.ts +8 -0
- package/dist/types/components/ui/accordion.d.ts.map +1 -0
- package/dist/types/components/ui/alert.d.ts +10 -0
- package/dist/types/components/ui/alert.d.ts.map +1 -0
- package/dist/types/components/ui/avatar.d.ts +7 -0
- package/dist/types/components/ui/avatar.d.ts.map +1 -0
- package/dist/types/components/ui/badge.d.ts +10 -0
- package/dist/types/components/ui/badge.d.ts.map +1 -0
- package/dist/types/components/ui/breadcrumb.d.ts +12 -0
- package/dist/types/components/ui/breadcrumb.d.ts.map +1 -0
- package/dist/types/components/ui/button.d.ts +11 -0
- package/dist/types/components/ui/button.d.ts.map +1 -0
- package/dist/types/components/ui/calendar.d.ts +9 -0
- package/dist/types/components/ui/calendar.d.ts.map +1 -0
- package/dist/types/components/ui/card.d.ts +10 -0
- package/dist/types/components/ui/card.d.ts.map +1 -0
- package/dist/types/components/ui/checkbox.d.ts +5 -0
- package/dist/types/components/ui/checkbox.d.ts.map +1 -0
- package/dist/types/components/ui/collapsible.d.ts +6 -0
- package/dist/types/components/ui/collapsible.d.ts.map +1 -0
- package/dist/types/components/ui/command.d.ts +19 -0
- package/dist/types/components/ui/command.d.ts.map +1 -0
- package/dist/types/components/ui/confirm-dialog.d.ts +72 -0
- package/dist/types/components/ui/confirm-dialog.d.ts.map +1 -0
- package/dist/types/components/ui/data-table.d.ts +211 -0
- package/dist/types/components/ui/data-table.d.ts.map +1 -0
- package/dist/types/components/ui/detail-page.d.ts +119 -0
- package/dist/types/components/ui/detail-page.d.ts.map +1 -0
- package/dist/types/components/ui/dialog.d.ts +16 -0
- package/dist/types/components/ui/dialog.d.ts.map +1 -0
- package/dist/types/components/ui/dropdown-menu.d.ts +26 -0
- package/dist/types/components/ui/dropdown-menu.d.ts.map +1 -0
- package/dist/types/components/ui/empty-state.d.ts +30 -0
- package/dist/types/components/ui/empty-state.d.ts.map +1 -0
- package/dist/types/components/ui/form-field.d.ts +57 -0
- package/dist/types/components/ui/form-field.d.ts.map +1 -0
- package/dist/types/components/ui/form.d.ts +185 -0
- package/dist/types/components/ui/form.d.ts.map +1 -0
- package/dist/types/components/ui/hover-card.d.ts +7 -0
- package/dist/types/components/ui/hover-card.d.ts.map +1 -0
- package/dist/types/components/ui/input.d.ts +4 -0
- package/dist/types/components/ui/input.d.ts.map +1 -0
- package/dist/types/components/ui/label.d.ts +5 -0
- package/dist/types/components/ui/label.d.ts.map +1 -0
- package/dist/types/components/ui/menubar.d.ts +27 -0
- package/dist/types/components/ui/menubar.d.ts.map +1 -0
- package/dist/types/components/ui/motion.d.ts +130 -0
- package/dist/types/components/ui/motion.d.ts.map +1 -0
- package/dist/types/components/ui/page-header.d.ts +45 -0
- package/dist/types/components/ui/page-header.d.ts.map +1 -0
- package/dist/types/components/ui/pagination.d.ts +14 -0
- package/dist/types/components/ui/pagination.d.ts.map +1 -0
- package/dist/types/components/ui/popover.d.ts +8 -0
- package/dist/types/components/ui/popover.d.ts.map +1 -0
- package/dist/types/components/ui/progress.d.ts +5 -0
- package/dist/types/components/ui/progress.d.ts.map +1 -0
- package/dist/types/components/ui/radio-group.d.ts +6 -0
- package/dist/types/components/ui/radio-group.d.ts.map +1 -0
- package/dist/types/components/ui/select.d.ts +16 -0
- package/dist/types/components/ui/select.d.ts.map +1 -0
- package/dist/types/components/ui/separator.d.ts +5 -0
- package/dist/types/components/ui/separator.d.ts.map +1 -0
- package/dist/types/components/ui/sheet.d.ts +14 -0
- package/dist/types/components/ui/sheet.d.ts.map +1 -0
- package/dist/types/components/ui/skeleton.d.ts +3 -0
- package/dist/types/components/ui/skeleton.d.ts.map +1 -0
- package/dist/types/components/ui/slider.d.ts +5 -0
- package/dist/types/components/ui/slider.d.ts.map +1 -0
- package/dist/types/components/ui/sonner.d.ts +4 -0
- package/dist/types/components/ui/sonner.d.ts.map +1 -0
- package/dist/types/components/ui/switch.d.ts +5 -0
- package/dist/types/components/ui/switch.d.ts.map +1 -0
- package/dist/types/components/ui/table.d.ts +11 -0
- package/dist/types/components/ui/table.d.ts.map +1 -0
- package/dist/types/components/ui/tabs.d.ts +8 -0
- package/dist/types/components/ui/tabs.d.ts.map +1 -0
- package/dist/types/components/ui/textarea.d.ts +4 -0
- package/dist/types/components/ui/textarea.d.ts.map +1 -0
- package/dist/types/components/ui/toast.d.ts +70 -0
- package/dist/types/components/ui/toast.d.ts.map +1 -0
- package/dist/types/components/ui/toggle.d.ts +10 -0
- package/dist/types/components/ui/toggle.d.ts.map +1 -0
- package/dist/types/components/ui/tooltip.d.ts +8 -0
- package/dist/types/components/ui/tooltip.d.ts.map +1 -0
- package/dist/types/hooks/index.d.ts +14 -0
- package/dist/types/hooks/index.d.ts.map +1 -0
- package/dist/types/hooks/useApi.d.ts +38 -0
- package/dist/types/hooks/useApi.d.ts.map +1 -0
- package/dist/types/hooks/useBreakpoint.d.ts +35 -0
- package/dist/types/hooks/useBreakpoint.d.ts.map +1 -0
- package/dist/types/hooks/useDataTable.d.ts +59 -0
- package/dist/types/hooks/useDataTable.d.ts.map +1 -0
- package/dist/types/hooks/useMediaQuery.d.ts +12 -0
- package/dist/types/hooks/useMediaQuery.d.ts.map +1 -0
- package/dist/types/hooks/useStorage.d.ts +35 -0
- package/dist/types/hooks/useStorage.d.ts.map +1 -0
- package/dist/types/index.d.ts +75 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/lib/errors.d.ts +37 -0
- package/dist/types/lib/errors.d.ts.map +1 -0
- package/dist/types/lib/format.d.ts +80 -0
- package/dist/types/lib/format.d.ts.map +1 -0
- package/dist/types/lib/fouc.d.ts +64 -0
- package/dist/types/lib/fouc.d.ts.map +1 -0
- package/dist/types/lib/platform.d.ts +156 -0
- package/dist/types/lib/platform.d.ts.map +1 -0
- package/dist/types/lib/utils.d.ts +14 -0
- package/dist/types/lib/utils.d.ts.map +1 -0
- package/dist/types/main.d.ts +2 -0
- package/dist/types/main.d.ts.map +1 -0
- package/dist/types/themes/index.d.ts +499 -0
- package/dist/types/themes/index.d.ts.map +1 -0
- package/dist/types/themes/presets/base.d.ts +108 -0
- package/dist/types/themes/presets/base.d.ts.map +1 -0
- package/dist/types/themes/presets/elegant.d.ts +108 -0
- package/dist/types/themes/presets/elegant.d.ts.map +1 -0
- package/dist/types/themes/presets/metro.d.ts +114 -0
- package/dist/types/themes/presets/metro.d.ts.map +1 -0
- package/dist/types/themes/presets/studio.d.ts +115 -0
- package/dist/types/themes/presets/studio.d.ts.map +1 -0
- package/dist/types/themes/presets/vivid.d.ts +115 -0
- package/dist/types/themes/presets/vivid.d.ts.map +1 -0
- package/dist/types/themes/theme-provider.d.ts +122 -0
- package/dist/types/themes/theme-provider.d.ts.map +1 -0
- package/dist/types/types/index.d.ts +813 -0
- package/dist/types/types/index.d.ts.map +1 -0
- package/dist/uikit.css +1 -0
- package/dist/useDataTable-CPiBpEg-.js +254 -0
- package/dist/useDataTable-CPiBpEg-.js.map +1 -0
- package/dist/utils-CwJPJKOE.js +2278 -0
- package/dist/utils-CwJPJKOE.js.map +1 -0
- package/dist/utils.js +5 -0
- package/dist/utils.js.map +1 -0
- package/dist/wrapper.js +13 -0
- package/dist/wrapper.js.map +1 -0
- package/dist/x-BxwubQiM.js +15 -0
- package/dist/x-BxwubQiM.js.map +1 -0
- package/examples/README.md +18 -0
- package/examples/button.tsx +16 -0
- package/examples/confirm-dialog.tsx +44 -0
- package/examples/data-table.tsx +35 -0
- package/examples/dialog.tsx +34 -0
- package/examples/empty-state.tsx +13 -0
- package/examples/form-field.tsx +22 -0
- package/examples/format.tsx +19 -0
- package/examples/page-header.tsx +17 -0
- package/examples/skeleton.tsx +12 -0
- package/examples/theme-provider.tsx +33 -0
- package/examples/toast.tsx +32 -0
- package/examples/use-breakpoint.tsx +17 -0
- package/llms.txt +1140 -0
- package/package.json +430 -0
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Image optimization command
|
|
3
|
+
* @description Compresses PNG/JPG images and converts to WebP format
|
|
4
|
+
* @package @bloomneo/uikit
|
|
5
|
+
* @file /bin/commands/optimize.js
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { readdir, stat } from 'fs/promises';
|
|
9
|
+
import { existsSync } from 'fs';
|
|
10
|
+
import { join, extname, basename, dirname } from 'path';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Check if sharp is installed
|
|
14
|
+
*/
|
|
15
|
+
async function checkSharp() {
|
|
16
|
+
try {
|
|
17
|
+
const sharp = await import('sharp');
|
|
18
|
+
return sharp.default;
|
|
19
|
+
} catch (error) {
|
|
20
|
+
console.error('\n❌ Sharp is required for image optimization but not installed.\n');
|
|
21
|
+
console.log('Install it with:');
|
|
22
|
+
console.log(' npm install sharp\n');
|
|
23
|
+
console.log('Or with pnpm:');
|
|
24
|
+
console.log(' pnpm add sharp\n');
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
let sharpModule = null;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Optimize images in a directory
|
|
33
|
+
* @param {Object} options - Command options
|
|
34
|
+
* @param {string} options.dir - Directory to scan (default: 'public')
|
|
35
|
+
* @param {number} options.quality - WebP quality 0-100 (default: 80)
|
|
36
|
+
* @param {number} options.maxWidth - Max width in pixels (default: 1200)
|
|
37
|
+
* @param {boolean} options.webpOnly - Only generate WebP, skip PNG fallback
|
|
38
|
+
* @param {boolean} options.keepOriginal - Keep original files (default: true)
|
|
39
|
+
*/
|
|
40
|
+
export async function optimizeImages(options = {}) {
|
|
41
|
+
const cwd = process.cwd();
|
|
42
|
+
const targetDir = join(cwd, options.dir || 'public');
|
|
43
|
+
const quality = parseInt(options.quality) || 80;
|
|
44
|
+
const maxWidth = parseInt(options.maxWidth) || 1200;
|
|
45
|
+
const webpOnly = options.webpOnly || false;
|
|
46
|
+
|
|
47
|
+
console.log('\n🖼️ UIKit Image Optimizer\n');
|
|
48
|
+
|
|
49
|
+
// Check if directory exists
|
|
50
|
+
if (!existsSync(targetDir)) {
|
|
51
|
+
console.error(`❌ Error: Directory not found: ${targetDir}`);
|
|
52
|
+
console.log('💡 Tip: Run from project root or specify --dir <path>\n');
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
console.log(`📁 Directory: ${targetDir}`);
|
|
57
|
+
console.log(`📊 Settings: Quality=${quality}, MaxWidth=${maxWidth}px`);
|
|
58
|
+
console.log(`🔧 Mode: ${webpOnly ? 'WebP only' : 'WebP + PNG fallback'}\n`);
|
|
59
|
+
|
|
60
|
+
// Check for sharp
|
|
61
|
+
sharpModule = await checkSharp();
|
|
62
|
+
|
|
63
|
+
// Find all images
|
|
64
|
+
const images = await getImageFiles(targetDir);
|
|
65
|
+
|
|
66
|
+
if (images.length === 0) {
|
|
67
|
+
console.log('📭 No PNG/JPG/JPEG images found to optimize.\n');
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
console.log(`Found ${images.length} image(s) to optimize\n`);
|
|
72
|
+
|
|
73
|
+
let successCount = 0;
|
|
74
|
+
let totalSavedBytes = 0;
|
|
75
|
+
|
|
76
|
+
for (const imagePath of images) {
|
|
77
|
+
const result = await optimizeImage(imagePath, { quality, maxWidth, webpOnly });
|
|
78
|
+
if (result) {
|
|
79
|
+
successCount++;
|
|
80
|
+
totalSavedBytes += result.savedBytes;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const savedMB = (totalSavedBytes / 1024 / 1024).toFixed(2);
|
|
85
|
+
|
|
86
|
+
console.log(`\n✨ Optimization complete!`);
|
|
87
|
+
console.log(` ✅ Processed: ${successCount}/${images.length} images`);
|
|
88
|
+
console.log(` 💾 Total saved: ${savedMB}MB\n`);
|
|
89
|
+
|
|
90
|
+
console.log('📝 Next steps:');
|
|
91
|
+
console.log(' 1. Update image references to use .webp files');
|
|
92
|
+
console.log(' 2. Add <picture> fallback for older browsers:');
|
|
93
|
+
console.log(`
|
|
94
|
+
<picture>
|
|
95
|
+
<source srcset="image.webp" type="image/webp" />
|
|
96
|
+
<img src="image.png" alt="description" />
|
|
97
|
+
</picture>
|
|
98
|
+
`);
|
|
99
|
+
console.log(' 3. Delete original large files after verification\n');
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Recursively get all image files in a directory
|
|
104
|
+
*/
|
|
105
|
+
async function getImageFiles(dir) {
|
|
106
|
+
const files = [];
|
|
107
|
+
|
|
108
|
+
try {
|
|
109
|
+
const items = await readdir(dir, { withFileTypes: true });
|
|
110
|
+
|
|
111
|
+
for (const item of items) {
|
|
112
|
+
const fullPath = join(dir, item.name);
|
|
113
|
+
|
|
114
|
+
if (item.isDirectory()) {
|
|
115
|
+
// Skip node_modules and hidden directories
|
|
116
|
+
if (!item.name.startsWith('.') && item.name !== 'node_modules') {
|
|
117
|
+
files.push(...await getImageFiles(fullPath));
|
|
118
|
+
}
|
|
119
|
+
} else if (/\.(png|jpg|jpeg)$/i.test(item.name)) {
|
|
120
|
+
// Skip already optimized files
|
|
121
|
+
if (!item.name.includes('-optimized') && !item.name.endsWith('.webp')) {
|
|
122
|
+
files.push(fullPath);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
} catch (error) {
|
|
127
|
+
console.error(`⚠️ Error reading directory ${dir}:`, error.message);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return files;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Optimize a single image
|
|
135
|
+
*/
|
|
136
|
+
async function optimizeImage(inputPath, options) {
|
|
137
|
+
const { quality, maxWidth, webpOnly } = options;
|
|
138
|
+
const ext = extname(inputPath).toLowerCase();
|
|
139
|
+
const name = basename(inputPath, ext);
|
|
140
|
+
const dir = dirname(inputPath);
|
|
141
|
+
const webpPath = join(dir, `${name}.webp`);
|
|
142
|
+
|
|
143
|
+
try {
|
|
144
|
+
const stats = await stat(inputPath);
|
|
145
|
+
const originalSize = stats.size;
|
|
146
|
+
const sizeMB = (originalSize / 1024 / 1024).toFixed(2);
|
|
147
|
+
|
|
148
|
+
console.log(`🔄 Processing: ${basename(inputPath)} (${sizeMB}MB)`);
|
|
149
|
+
|
|
150
|
+
// Get image metadata
|
|
151
|
+
const metadata = await sharpModule(inputPath).metadata();
|
|
152
|
+
|
|
153
|
+
// Create pipeline with optional resize
|
|
154
|
+
let pipeline = sharpModule(inputPath);
|
|
155
|
+
if (metadata.width > maxWidth) {
|
|
156
|
+
pipeline = pipeline.resize(maxWidth, null, { withoutEnlargement: true });
|
|
157
|
+
console.log(` 📐 Resizing: ${metadata.width}px → ${maxWidth}px`);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Convert to WebP
|
|
161
|
+
await pipeline
|
|
162
|
+
.webp({ quality })
|
|
163
|
+
.toFile(webpPath);
|
|
164
|
+
|
|
165
|
+
const webpStats = await stat(webpPath);
|
|
166
|
+
const webpSizeMB = (webpStats.size / 1024 / 1024).toFixed(2);
|
|
167
|
+
const savings = ((1 - webpStats.size / originalSize) * 100).toFixed(1);
|
|
168
|
+
|
|
169
|
+
console.log(` ✅ WebP: ${name}.webp (${webpSizeMB}MB) - ${savings}% smaller`);
|
|
170
|
+
|
|
171
|
+
let totalSaved = originalSize - webpStats.size;
|
|
172
|
+
|
|
173
|
+
// Create optimized PNG fallback
|
|
174
|
+
if (!webpOnly) {
|
|
175
|
+
const optimizedPngPath = join(dir, `${name}-optimized.png`);
|
|
176
|
+
|
|
177
|
+
await sharpModule(inputPath)
|
|
178
|
+
.resize(maxWidth, null, { withoutEnlargement: true })
|
|
179
|
+
.png({ compressionLevel: 9 })
|
|
180
|
+
.toFile(optimizedPngPath);
|
|
181
|
+
|
|
182
|
+
const pngStats = await stat(optimizedPngPath);
|
|
183
|
+
const pngSizeMB = (pngStats.size / 1024 / 1024).toFixed(2);
|
|
184
|
+
const pngSavings = ((1 - pngStats.size / originalSize) * 100).toFixed(1);
|
|
185
|
+
|
|
186
|
+
console.log(` ✅ PNG: ${name}-optimized.png (${pngSizeMB}MB) - ${pngSavings}% smaller`);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return {
|
|
190
|
+
input: inputPath,
|
|
191
|
+
webp: webpPath,
|
|
192
|
+
savedBytes: totalSaved
|
|
193
|
+
};
|
|
194
|
+
} catch (error) {
|
|
195
|
+
console.error(` ❌ Error: ${error.message}`);
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Pre-rendering command for generating static HTML pages
|
|
3
|
+
* @description Uses Puppeteer to render SPA routes for SEO optimization
|
|
4
|
+
* @package @bloomneo/uikit
|
|
5
|
+
* @file /bin/commands/prerender.js
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { createServer } from 'http';
|
|
9
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'fs';
|
|
10
|
+
import { join } from 'path';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Check if puppeteer is installed
|
|
14
|
+
*/
|
|
15
|
+
async function checkPuppeteer() {
|
|
16
|
+
try {
|
|
17
|
+
const puppeteer = await import('puppeteer');
|
|
18
|
+
return puppeteer.default;
|
|
19
|
+
} catch (error) {
|
|
20
|
+
console.error('\n❌ Puppeteer is required for pre-rendering but not installed.\n');
|
|
21
|
+
console.log('Install it with:');
|
|
22
|
+
console.log(' npm install puppeteer\n');
|
|
23
|
+
console.log('Or with pnpm:');
|
|
24
|
+
console.log(' pnpm add puppeteer\n');
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Pre-render SPA routes to static HTML for SEO
|
|
31
|
+
* @param {Object} options - Command options
|
|
32
|
+
* @param {string} options.dist - Distribution directory (default: 'dist')
|
|
33
|
+
* @param {number} options.port - Server port (default: 4567)
|
|
34
|
+
* @param {string} options.routes - Comma-separated routes or 'auto'
|
|
35
|
+
* @param {string} options.config - Path to SEO config JSON file
|
|
36
|
+
* @param {string} options.baseUrl - Base URL for canonical links
|
|
37
|
+
*/
|
|
38
|
+
export async function prerenderPages(options = {}) {
|
|
39
|
+
const cwd = process.cwd();
|
|
40
|
+
const distDir = join(cwd, options.dist || 'dist');
|
|
41
|
+
const port = parseInt(options.port) || 4567;
|
|
42
|
+
const baseUrl = options.baseUrl || '';
|
|
43
|
+
|
|
44
|
+
console.log('\n🚀 UIKit Pre-render\n');
|
|
45
|
+
|
|
46
|
+
// Check if dist exists
|
|
47
|
+
if (!existsSync(distDir)) {
|
|
48
|
+
console.error('❌ Error: dist folder not found. Run "npm run build" first.');
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Load SEO config if provided
|
|
53
|
+
let seoConfig = {};
|
|
54
|
+
const configPath = join(cwd, options.config || 'seo.config.json');
|
|
55
|
+
if (existsSync(configPath)) {
|
|
56
|
+
try {
|
|
57
|
+
seoConfig = JSON.parse(readFileSync(configPath, 'utf8'));
|
|
58
|
+
console.log(`📋 Loaded SEO config from ${options.config || 'seo.config.json'}`);
|
|
59
|
+
} catch (e) {
|
|
60
|
+
console.log('⚠️ No SEO config found, using defaults');
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Determine routes to render
|
|
65
|
+
let routes = ['/'];
|
|
66
|
+
if (options.routes && options.routes !== 'auto') {
|
|
67
|
+
routes = options.routes.split(',').map(r => r.trim());
|
|
68
|
+
} else if (seoConfig.routes) {
|
|
69
|
+
routes = Object.keys(seoConfig.routes);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
console.log(`📁 Dist: ${distDir}`);
|
|
73
|
+
console.log(`🔗 Routes: ${routes.join(', ')}\n`);
|
|
74
|
+
|
|
75
|
+
// Check for puppeteer
|
|
76
|
+
const puppeteer = await checkPuppeteer();
|
|
77
|
+
|
|
78
|
+
// Start static server
|
|
79
|
+
const server = await createStaticServer(distDir, port);
|
|
80
|
+
const serverUrl = `http://localhost:${server.address().port}`;
|
|
81
|
+
|
|
82
|
+
// Launch browser
|
|
83
|
+
console.log('🌐 Launching browser...\n');
|
|
84
|
+
const browser = await puppeteer.launch({
|
|
85
|
+
headless: 'new',
|
|
86
|
+
args: ['--no-sandbox', '--disable-setuid-sandbox']
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
let successCount = 0;
|
|
90
|
+
let failCount = 0;
|
|
91
|
+
|
|
92
|
+
// Render each route
|
|
93
|
+
for (const route of routes) {
|
|
94
|
+
const html = await renderRoute(browser, route, serverUrl);
|
|
95
|
+
|
|
96
|
+
if (html) {
|
|
97
|
+
const seo = seoConfig.routes?.[route] || {};
|
|
98
|
+
saveHtml(route, html, distDir, seo, baseUrl);
|
|
99
|
+
successCount++;
|
|
100
|
+
} else {
|
|
101
|
+
failCount++;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Cleanup
|
|
106
|
+
await browser.close();
|
|
107
|
+
server.close();
|
|
108
|
+
|
|
109
|
+
console.log('\n📊 Pre-render complete!');
|
|
110
|
+
console.log(` ✅ Success: ${successCount}`);
|
|
111
|
+
console.log(` ❌ Failed: ${failCount}`);
|
|
112
|
+
console.log(` 📁 Output: ${distDir}\n`);
|
|
113
|
+
|
|
114
|
+
if (successCount > 0) {
|
|
115
|
+
console.log('💡 Tip: Create seo.config.json to customize meta tags per route:');
|
|
116
|
+
console.log(`
|
|
117
|
+
{
|
|
118
|
+
"baseUrl": "https://example.com",
|
|
119
|
+
"routes": {
|
|
120
|
+
"/": { "title": "Home", "description": "Welcome to my site" },
|
|
121
|
+
"/about": { "title": "About", "description": "About us" }
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
`);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Create a simple static file server
|
|
130
|
+
*/
|
|
131
|
+
function createStaticServer(distDir, port) {
|
|
132
|
+
const mimeTypes = {
|
|
133
|
+
'.html': 'text/html',
|
|
134
|
+
'.js': 'application/javascript',
|
|
135
|
+
'.css': 'text/css',
|
|
136
|
+
'.json': 'application/json',
|
|
137
|
+
'.png': 'image/png',
|
|
138
|
+
'.jpg': 'image/jpeg',
|
|
139
|
+
'.jpeg': 'image/jpeg',
|
|
140
|
+
'.svg': 'image/svg+xml',
|
|
141
|
+
'.woff': 'font/woff',
|
|
142
|
+
'.woff2': 'font/woff2',
|
|
143
|
+
'.mp4': 'video/mp4',
|
|
144
|
+
'.webp': 'image/webp'
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
const server = createServer((req, res) => {
|
|
148
|
+
let filePath = join(distDir, req.url === '/' ? '/index.html' : req.url);
|
|
149
|
+
|
|
150
|
+
// Handle SPA routing - serve index.html for all non-file routes
|
|
151
|
+
if (!existsSync(filePath) || !filePath.includes('.')) {
|
|
152
|
+
filePath = join(distDir, 'index.html');
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
try {
|
|
156
|
+
const content = readFileSync(filePath);
|
|
157
|
+
const ext = filePath.substring(filePath.lastIndexOf('.'));
|
|
158
|
+
const contentType = mimeTypes[ext] || 'application/octet-stream';
|
|
159
|
+
|
|
160
|
+
res.writeHead(200, { 'Content-Type': contentType });
|
|
161
|
+
res.end(content);
|
|
162
|
+
} catch (err) {
|
|
163
|
+
res.writeHead(404);
|
|
164
|
+
res.end('Not found');
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
return new Promise((resolve, reject) => {
|
|
169
|
+
server.on('error', (err) => {
|
|
170
|
+
if (err.code === 'EADDRINUSE') {
|
|
171
|
+
console.log(`⚠️ Port ${port} in use, trying ${port + 1}...`);
|
|
172
|
+
server.listen(port + 1, () => {
|
|
173
|
+
console.log(`📦 Static server running at http://localhost:${port + 1}`);
|
|
174
|
+
resolve(server);
|
|
175
|
+
});
|
|
176
|
+
} else {
|
|
177
|
+
reject(err);
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
server.listen(port, () => {
|
|
182
|
+
console.log(`📦 Static server running at http://localhost:${port}`);
|
|
183
|
+
resolve(server);
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Render a single route using Puppeteer
|
|
190
|
+
*/
|
|
191
|
+
async function renderRoute(browser, route, baseUrl) {
|
|
192
|
+
const page = await browser.newPage();
|
|
193
|
+
const url = `${baseUrl}${route}`;
|
|
194
|
+
|
|
195
|
+
console.log(`🔄 Rendering: ${route}`);
|
|
196
|
+
|
|
197
|
+
try {
|
|
198
|
+
await page.goto(url, { waitUntil: 'networkidle0', timeout: 30000 });
|
|
199
|
+
|
|
200
|
+
// Wait for React to mount
|
|
201
|
+
await page.waitForSelector('#root', { timeout: 10000 });
|
|
202
|
+
|
|
203
|
+
// Additional wait for any async content
|
|
204
|
+
await new Promise(resolve => setTimeout(resolve, 1500));
|
|
205
|
+
|
|
206
|
+
// Get the rendered HTML
|
|
207
|
+
const html = await page.content();
|
|
208
|
+
|
|
209
|
+
await page.close();
|
|
210
|
+
return html;
|
|
211
|
+
} catch (error) {
|
|
212
|
+
console.error(`❌ Error rendering ${route}:`, error.message);
|
|
213
|
+
await page.close();
|
|
214
|
+
return null;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Update SEO meta tags in HTML
|
|
220
|
+
*/
|
|
221
|
+
function updateSeoTags(html, route, seo, baseUrl) {
|
|
222
|
+
if (!seo.title && !seo.description) return html;
|
|
223
|
+
|
|
224
|
+
const { title, description } = seo;
|
|
225
|
+
const url = `${baseUrl}${route === '/' ? '' : route}`;
|
|
226
|
+
|
|
227
|
+
// Update <title>
|
|
228
|
+
if (title) {
|
|
229
|
+
html = html.replace(/<title>[^<]*<\/title>/, `<title>${title}</title>`);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Update meta description
|
|
233
|
+
if (description) {
|
|
234
|
+
if (html.includes('name="description"')) {
|
|
235
|
+
html = html.replace(
|
|
236
|
+
/<meta name="description" content="[^"]*">/,
|
|
237
|
+
`<meta name="description" content="${description}">`
|
|
238
|
+
);
|
|
239
|
+
} else {
|
|
240
|
+
html = html.replace('</head>', ` <meta name="description" content="${description}">\n </head>`);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Update/add Open Graph tags
|
|
245
|
+
if (title) {
|
|
246
|
+
if (html.includes('og:title')) {
|
|
247
|
+
html = html.replace(/<meta property="og:title" content="[^"]*">/, `<meta property="og:title" content="${title}">`);
|
|
248
|
+
} else {
|
|
249
|
+
html = html.replace('</head>', ` <meta property="og:title" content="${title}">\n </head>`);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
if (description) {
|
|
254
|
+
if (html.includes('og:description')) {
|
|
255
|
+
html = html.replace(/<meta property="og:description" content="[^"]*">/, `<meta property="og:description" content="${description}">`);
|
|
256
|
+
} else {
|
|
257
|
+
html = html.replace('</head>', ` <meta property="og:description" content="${description}">\n </head>`);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Add/update canonical URL
|
|
262
|
+
if (baseUrl) {
|
|
263
|
+
if (html.includes('rel="canonical"')) {
|
|
264
|
+
html = html.replace(/<link rel="canonical" href="[^"]*">/, `<link rel="canonical" href="${url}">`);
|
|
265
|
+
} else {
|
|
266
|
+
html = html.replace('</head>', ` <link rel="canonical" href="${url}">\n </head>`);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
if (html.includes('og:url')) {
|
|
270
|
+
html = html.replace(/<meta property="og:url" content="[^"]*">/, `<meta property="og:url" content="${url}">`);
|
|
271
|
+
} else {
|
|
272
|
+
html = html.replace('</head>', ` <meta property="og:url" content="${url}">\n </head>`);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
return html;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Save HTML to file
|
|
281
|
+
*/
|
|
282
|
+
function saveHtml(route, html, distDir, seo, baseUrl) {
|
|
283
|
+
let filePath;
|
|
284
|
+
if (route === '/') {
|
|
285
|
+
filePath = join(distDir, 'index.html');
|
|
286
|
+
} else {
|
|
287
|
+
// Create directory structure: /about -> /about/index.html
|
|
288
|
+
const dir = join(distDir, route);
|
|
289
|
+
if (!existsSync(dir)) {
|
|
290
|
+
mkdirSync(dir, { recursive: true });
|
|
291
|
+
}
|
|
292
|
+
filePath = join(dir, 'index.html');
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// Add pre-rendered marker
|
|
296
|
+
let processedHtml = html.replace(
|
|
297
|
+
'<div id="root">',
|
|
298
|
+
'<div id="root" data-server-rendered="true">'
|
|
299
|
+
);
|
|
300
|
+
|
|
301
|
+
// Update SEO tags
|
|
302
|
+
processedHtml = updateSeoTags(processedHtml, route, seo, baseUrl);
|
|
303
|
+
|
|
304
|
+
writeFileSync(filePath, processedHtml);
|
|
305
|
+
console.log(`✅ Saved: ${filePath.replace(distDir, '')}`);
|
|
306
|
+
}
|