zuby 1.0.79 → 1.0.81

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 (85) hide show
  1. package/README.md +9 -0
  2. package/commands/add.d.ts +1 -0
  3. package/commands/add.js +112 -0
  4. package/commands/build.d.ts +1 -1
  5. package/commands/build.js +21 -5
  6. package/commands/dev.d.ts +1 -1
  7. package/commands/index.js +5 -0
  8. package/commands/info.d.ts +1 -1
  9. package/commands/info.js +1 -1
  10. package/commands/init.d.ts +2 -2
  11. package/commands/init.js +5 -5
  12. package/commands/preview.d.ts +1 -1
  13. package/commands/upgrade.d.ts +1 -1
  14. package/commands/upgrade.js +20 -6
  15. package/config.d.ts +1 -1
  16. package/config.js +7 -24
  17. package/contexts/globalContext.d.ts +2 -2
  18. package/contexts/globalContext.js +1 -1
  19. package/contexts/index.d.ts +4 -4
  20. package/contexts/index.js +0 -3
  21. package/contexts/pageContext.d.ts +1 -1
  22. package/contexts/pageContext.js +5 -5
  23. package/defineConfig.d.ts +1 -1
  24. package/examples/basic/js/components/Card/index.css +25 -25
  25. package/examples/basic/js/components/Card/index.jsx +11 -11
  26. package/examples/basic/js/components/Card/index.module.css +24 -24
  27. package/examples/basic/js/package.json +14 -14
  28. package/examples/basic/js/pages/about.jsx +7 -7
  29. package/examples/basic/js/pages/app.css +33 -33
  30. package/examples/basic/js/pages/app.jsx +1 -1
  31. package/examples/basic/js/pages/index.jsx +18 -23
  32. package/examples/basic/js/pages/products/[id].jsx +5 -5
  33. package/examples/basic/js/zuby.config.mjs +2 -2
  34. package/examples/basic/ts/components/Card/index.module.css +24 -24
  35. package/examples/basic/ts/components/Card/index.tsx +11 -11
  36. package/examples/basic/ts/package.json +19 -19
  37. package/examples/basic/ts/pages/about.tsx +7 -7
  38. package/examples/basic/ts/pages/app.css +33 -33
  39. package/examples/basic/ts/pages/app.tsx +1 -1
  40. package/examples/basic/ts/pages/index.tsx +18 -23
  41. package/examples/basic/ts/pages/products/[id].tsx +5 -5
  42. package/examples/basic/ts/tsconfig.json +6 -6
  43. package/examples/basic/ts/zuby.config.ts +2 -2
  44. package/hooks/useFetch.d.ts +1 -1
  45. package/hooks/useFetch.js +11 -5
  46. package/hooks/useProps.d.ts +1 -1
  47. package/hooks/useProps.js +1 -1
  48. package/i18n/index.js +2 -4
  49. package/image/getNearestSize.d.ts +1 -1
  50. package/image/imageLoader.d.ts +1 -1
  51. package/logger/index.d.ts +1 -1
  52. package/logger/index.js +48 -0
  53. package/logger/types.d.ts +3 -0
  54. package/package.json +58 -57
  55. package/packageConfig.js +3 -1
  56. package/plugins/chunkNamingPlugin/index.d.ts +1 -1
  57. package/plugins/contextPlugin/index.d.ts +1 -1
  58. package/plugins/contextPlugin/index.js +5 -7
  59. package/plugins/dependenciesPlugin/index.d.ts +1 -1
  60. package/plugins/dependenciesPlugin/index.js +31 -3
  61. package/plugins/manifestPlugin/index.js +1 -1
  62. package/plugins/preloadPlugin/index.d.ts +1 -1
  63. package/plugins/preloadPlugin/index.js +2 -2
  64. package/plugins/prerenderPlugin/index.d.ts +1 -1
  65. package/plugins/prerenderPlugin/index.js +5 -12
  66. package/preload/index.js +61 -21
  67. package/server/index.js +146 -59
  68. package/server/types.d.ts +4 -4
  69. package/server/zubyDevRenderer.d.ts +4 -4
  70. package/server/zubyDevRenderer.js +11 -9
  71. package/server/zubyDevServer.d.ts +2 -2
  72. package/server/zubyDevServer.js +2 -5
  73. package/server/zubyRenderer.d.ts +5 -3
  74. package/server/zubyRenderer.js +44 -18
  75. package/server/zubyServer.d.ts +8 -7
  76. package/server/zubyServer.js +25 -30
  77. package/templates/index.d.ts +1 -1
  78. package/templates/index.js +8 -8
  79. package/templates/pathUtils.d.ts +2 -2
  80. package/templates/pathUtils.js +13 -5
  81. package/tsconfigs/default.json +18 -18
  82. package/types.d.ts +13 -6
  83. package/utils/brandingUtils.js +1 -1
  84. package/utils/errorUtils.d.ts +12 -0
  85. package/utils/errorUtils.js +25 -0
package/README.md CHANGED
@@ -46,6 +46,15 @@ Zuby.js supports plugins to extend its functionality.
46
46
  You can find official plugins in the `@zubyjs` namespace on npm.
47
47
  See the complete [ZubyPlugin API](https://zuby.futrou.com/reference/zuby-plugin) to learn how to create your own plugins.
48
48
 
49
+ Official plugins:
50
+ ### Official Plugins
51
+
52
+ - [**@zubyjs/share**](./packages/share) - Share your local development server with others using Cloudflare tunnels
53
+ - [**@zubyjs/sitemap**](./packages/sitemap) - Automatically generate sitemaps for your application
54
+ - [**@zubyjs/tailwind**](./packages/tailwind) - Tailwind CSS integration and optimization
55
+ - [**@zubyjs/purgecss**](./packages/purgecss) - CSS purging and optimization
56
+ - [**@zubyjs/image**](./packages/image) - Image optimization and responsive image generation
57
+
49
58
  ## Acknowledgements
50
59
 
51
60
  Zuby.js is inspired by [Astro](https://astro.build/) and [Next.js](https://nextjs.org/)
@@ -0,0 +1 @@
1
+ export default function add(options: Record<string, any>): Promise<void>;
@@ -0,0 +1,112 @@
1
+ import { createLogger } from '../logger/index.js';
2
+ import { getZubyPackageConfig } from '../packageConfig.js';
3
+ import chalk from 'chalk';
4
+ import { getErrorMessage } from '../utils/errorUtils.js';
5
+ /**
6
+ * Fetches available packages from NPM registry under @zubyjs scope
7
+ */
8
+ async function fetchAvailablePackages() {
9
+ try {
10
+ const response = await fetch('https://registry.npmjs.org/-/v1/search?q=scope:zubyjs', {
11
+ signal: AbortSignal.timeout(5000),
12
+ });
13
+ if (!response.ok) {
14
+ throw new Error(`Failed to fetch packages from NPM registry: ${response.statusText}`);
15
+ }
16
+ const data = (await response.json());
17
+ if (!data.objects) {
18
+ throw new Error('Invalid response format from NPM registry');
19
+ }
20
+ const packages = {};
21
+ data.objects.forEach((item) => {
22
+ const { name, version } = item.package;
23
+ packages[name] = version;
24
+ });
25
+ return packages;
26
+ }
27
+ catch (error) {
28
+ throw new Error(`Failed to fetch available packages: ${getErrorMessage(error)}`);
29
+ }
30
+ }
31
+ /**
32
+ * Gets the package manager command (npm, yarn, or pnpm)
33
+ */
34
+ function getPackageManagerCommand() {
35
+ // Check which package manager is being used
36
+ const userAgent = process.env.npm_config_user_agent || '';
37
+ if (userAgent.includes('yarn')) {
38
+ return 'yarn add';
39
+ }
40
+ if (userAgent.includes('pnpm')) {
41
+ return 'pnpm add';
42
+ }
43
+ return 'npm install';
44
+ }
45
+ /**
46
+ * Installs a plugin package using the appropriate package manager
47
+ */
48
+ async function installPlugin(packageName, version) {
49
+ const { execSync } = await import('child_process');
50
+ const packageManagerCmd = getPackageManagerCommand();
51
+ try {
52
+ const fullPackageName = `${packageName}@${version}`;
53
+ execSync(`${packageManagerCmd} ${fullPackageName}`, { stdio: 'inherit' });
54
+ }
55
+ catch (error) {
56
+ throw new Error(`Failed to install plugin ${packageName}: ${getErrorMessage(error)}`);
57
+ }
58
+ }
59
+ export default async function add(options) {
60
+ const logger = createLogger();
61
+ logger.clearScreen('info');
62
+ const zubyConfig = getZubyPackageConfig();
63
+ const zubyVersion = zubyConfig.version;
64
+ // Get plugin names from rest arguments
65
+ const pluginNames = options.args || [];
66
+ if (pluginNames.length === 0) {
67
+ logger.error('No plugin names provided. Usage: npx zuby add [plugin-name] [another-plugin]');
68
+ process.exit(1);
69
+ }
70
+ logger.info(`Fetching available @zubyjs packages...`);
71
+ try {
72
+ const availablePackages = await fetchAvailablePackages();
73
+ const pluginsToInstall = [];
74
+ // Validate each plugin
75
+ for (const pluginName of pluginNames) {
76
+ const fullPackageName = pluginName.startsWith('@zubyjs/') ? pluginName : `@zubyjs/${pluginName}`;
77
+ if (!(fullPackageName in availablePackages)) {
78
+ logger.error(`Plugin ${chalk.bold(fullPackageName)} not found in @zubyjs scope`);
79
+ logger.info(`Available plugins: ${Object.keys(availablePackages).join(', ')}`);
80
+ process.exit(1);
81
+ }
82
+ const pluginVersion = availablePackages[fullPackageName];
83
+ // Check if plugin version matches Zuby version
84
+ if (pluginVersion !== zubyVersion) {
85
+ logger.warn(`Plugin ${chalk.bold(fullPackageName)} has version ${chalk.bold(pluginVersion)}, but you have Zuby version ${chalk.bold(zubyVersion)}`);
86
+ logger.info('Using the exact version match for compatibility');
87
+ }
88
+ pluginsToInstall.push({
89
+ name: fullPackageName,
90
+ version: zubyVersion,
91
+ });
92
+ }
93
+ logger.info(`\nInstalling ${pluginsToInstall.length} plugin(s) with Zuby version ${chalk.bold(zubyVersion)}...\r\n`);
94
+ // Install all plugins
95
+ for (const plugin of pluginsToInstall) {
96
+ try {
97
+ await installPlugin(plugin.name, plugin.version);
98
+ logger.info(`${chalk.greenBright('✓')} Successfully installed ${chalk.bold(plugin.name)}`);
99
+ }
100
+ catch (error) {
101
+ logger.error(getErrorMessage(error));
102
+ process.exit(1);
103
+ }
104
+ }
105
+ logger.info(`\r\n${chalk.greenBright.bold('All plugins installed successfully! 🎉')}\r\n`);
106
+ logger.info('Update your zuby.config.ts or zuby.config.js to use the installed plugins.');
107
+ }
108
+ catch (error) {
109
+ logger.error(getErrorMessage(error));
110
+ process.exit(1);
111
+ }
112
+ }
@@ -1,3 +1,3 @@
1
- import { BuildCommandOptions, ZubyInternalConfig } from '../types.js';
1
+ import { type BuildCommandOptions, type ZubyInternalConfig } from '../types.js';
2
2
  export default function build(options: BuildCommandOptions): Promise<void>;
3
3
  export declare function getEntryFile(zubyInternalConfig: ZubyInternalConfig): Promise<string>;
package/commands/build.js CHANGED
@@ -5,7 +5,7 @@ import { getTitle } from '../utils/brandingUtils.js';
5
5
  import { build as viteBuild } from 'vite';
6
6
  import { dirname, join, resolve } from 'path';
7
7
  import { normalizePath } from '../utils/pathUtils.js';
8
- import { existsSync, rmSync, writeFileSync, copyFileSync, readFileSync, } from 'fs';
8
+ import { existsSync, rmSync, writeFileSync, copyFileSync, readFileSync } from 'fs';
9
9
  import { TEMPLATES } from '../templates/types.js';
10
10
  import { glob } from 'glob';
11
11
  import { fileURLToPath } from 'url';
@@ -19,7 +19,7 @@ export default async function build(options) {
19
19
  const zubyInternalConfig = await getZubyInternalConfig(options.configFile);
20
20
  const { vite: viteConfig, customLogger: logger, outDir, cacheDir, plugins } = zubyInternalConfig;
21
21
  let buildStep = 1;
22
- const buildSteps = 2 + plugins.filter(plugin => plugin?.buildStep).length;
22
+ const buildSteps = 2 + plugins.filter((plugin) => plugin?.buildStep).length;
23
23
  const nextBuildStep = (description) => {
24
24
  logger?.info(`${chalk.bgYellow.bold.whiteBright(` Step ${buildStep++}/${buildSteps} `)} ${chalk.gray(description)}`);
25
25
  };
@@ -110,10 +110,26 @@ export default async function build(options) {
110
110
  const clientChunksManifestPath = resolve(outDir, CLIENT_CHUNKS_MANIFEST);
111
111
  const serverChunksManifestPath = resolve(outDir, SERVER_CHUNKS_MANIFEST);
112
112
  const clientChunksManifest = existsSync(clientChunksManifestPath)
113
- ? JSON.parse(readFileSync(clientChunksManifestPath, 'utf-8'))
113
+ ? (() => {
114
+ try {
115
+ return JSON.parse(readFileSync(clientChunksManifestPath, 'utf-8'));
116
+ }
117
+ catch (error) {
118
+ logger?.warn(`Failed to parse client chunks manifest: ${error instanceof Error ? error.message : String(error)}`);
119
+ return {};
120
+ }
121
+ })()
114
122
  : {};
115
123
  const serverChunksManifest = existsSync(serverChunksManifestPath)
116
- ? JSON.parse(readFileSync(serverChunksManifestPath, 'utf-8'))
124
+ ? (() => {
125
+ try {
126
+ return JSON.parse(readFileSync(serverChunksManifestPath, 'utf-8'));
127
+ }
128
+ catch (error) {
129
+ logger?.warn(`Failed to parse server chunks manifest: ${error instanceof Error ? error.message : String(error)}`);
130
+ return {};
131
+ }
132
+ })()
117
133
  : {};
118
134
  // Run build done hook
119
135
  // to execute plugins that are part of the build process
@@ -122,7 +138,7 @@ export default async function build(options) {
122
138
  translationFiles,
123
139
  clientChunksManifest,
124
140
  serverChunksManifest,
125
- }, zubyPlugin => {
141
+ }, (zubyPlugin) => {
126
142
  // Hide plugins that are not part of the build process
127
143
  // from the CLI output to avoid confusion
128
144
  if (!zubyPlugin.buildStep)
package/commands/dev.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { ServerCommandOptions } from '../types.js';
1
+ import { type ServerCommandOptions } from '../types.js';
2
2
  export default function dev(options: ServerCommandOptions): Promise<void>;
package/commands/index.js CHANGED
@@ -7,6 +7,7 @@ import preview from './preview.js';
7
7
  import init from './init.js';
8
8
  import info from './info.js';
9
9
  import upgrade from './upgrade.js';
10
+ import add from './add.js';
10
11
  const { name, description, version } = getZubyPackageConfig();
11
12
  const program = new Command().name(name).description(description).version(version);
12
13
  program
@@ -46,4 +47,8 @@ program
46
47
  .description('Upgrades Zuby to the latest compatible version')
47
48
  .option('-t, --tag <tag>', 'The tag to upgrade to (e.g. v1, v2, latest)')
48
49
  .action(async (options) => upgrade(options));
50
+ program
51
+ .command('add [plugins...]')
52
+ .description('Adds one or more Zuby plugins to your project')
53
+ .action(async (plugins, options) => add({ ...options, args: plugins }));
49
54
  program.parse(process.argv);
@@ -1,2 +1,2 @@
1
- import { BaseCommandOptions } from '../types.js';
1
+ import type { BaseCommandOptions } from '../types.js';
2
2
  export default function info({ configFile }: BaseCommandOptions): Promise<void>;
package/commands/info.js CHANGED
@@ -9,6 +9,6 @@ export default async function info({ configFile }) {
9
9
  logger.info(`OS: ${os.type()} ${os.release()}`);
10
10
  logger.info(`Output: ${output}`);
11
11
  logger.info(`Output dir: ${outDir}`);
12
- const pluginNames = plugins.map(plugin => plugin.name).join(', ');
12
+ const pluginNames = plugins.map((plugin) => plugin.name).join(', ');
13
13
  logger.info(`Plugins: ${plugins.length ? pluginNames : 'none'}`);
14
14
  }
@@ -1,5 +1,5 @@
1
- import { InitCommandOptions } from '../types.js';
2
- export default function init({ projectPath, jsxProviderName, exampleName, useTypescript, }: InitCommandOptions): Promise<void>;
1
+ import type { InitCommandOptions } from '../types.js';
2
+ export default function init({ projectPath, jsxProviderName, exampleName, useTypescript }: InitCommandOptions): Promise<void>;
3
3
  export declare function initExample(example: Example, options: InitOptions): Promise<void>;
4
4
  export declare function getExamples(): Example[];
5
5
  export interface Example {
package/commands/init.js CHANGED
@@ -11,16 +11,16 @@ import { getZubyPackageConfig } from '../packageConfig.js';
11
11
  import { globSync } from 'glob';
12
12
  const __filename = fileURLToPath(import.meta.url);
13
13
  const __dirname = dirname(__filename);
14
- export default async function init({ projectPath, jsxProviderName, exampleName, useTypescript, }) {
14
+ export default async function init({ projectPath, jsxProviderName, exampleName, useTypescript }) {
15
15
  const logger = createLogger();
16
16
  logger.clearScreen('info');
17
17
  logger?.info(`${getTitle(`Let's get started with Zuby`)}\r\n`);
18
18
  logger.info('Initializing a new Zuby project');
19
19
  const examples = getExamples();
20
20
  const defaultProjectName = 'my-zuby-app';
21
- const defaultExample = examples.find(example => example.name === 'basic');
21
+ const defaultExample = examples.find((example) => example.name === 'basic');
22
22
  const jsxProviderNames = ['preact', 'react'];
23
- const exampleNames = examples.map(example => example.name);
23
+ const exampleNames = examples.map((example) => example.name);
24
24
  const validateProjectPath = (projectPath) => {
25
25
  if (existsSync(projectPath)) {
26
26
  return 'Project with this name already exists. Please choose a different one.';
@@ -86,7 +86,7 @@ export default async function init({ projectPath, jsxProviderName, exampleName,
86
86
  else {
87
87
  logger.info(`Example project: ${exampleName}`);
88
88
  }
89
- const selectedExample = examples.find(example => example.name === exampleName);
89
+ const selectedExample = examples.find((example) => example.name === exampleName);
90
90
  if (!selectedExample) {
91
91
  logger.error(`Example ${exampleName} was not found`);
92
92
  process.exit(1);
@@ -145,7 +145,7 @@ options) {
145
145
  export function getExamples() {
146
146
  const examplesPath = normalizePath(join(__dirname, '..', 'examples'));
147
147
  const exampleNames = readdirSync(examplesPath);
148
- return exampleNames.map(exampleName => ({
148
+ return exampleNames.map((exampleName) => ({
149
149
  name: exampleName,
150
150
  path: normalizePath(join(examplesPath, exampleName)),
151
151
  isJs: existsSync(normalizePath(join(examplesPath, exampleName, 'js'))),
@@ -1,2 +1,2 @@
1
- import { ServerCommandOptions } from '../types.js';
1
+ import { type ServerCommandOptions } from '../types.js';
2
2
  export default function preview(options: ServerCommandOptions): Promise<void>;
@@ -1,3 +1,3 @@
1
- import { UpgradeCommandOptions } from '../types.js';
1
+ import type { UpgradeCommandOptions } from '../types.js';
2
2
  export default function upgrade({ configFile, tag }: UpgradeCommandOptions): Promise<void>;
3
3
  export declare function installDependencies(): boolean;
@@ -15,12 +15,25 @@ export default async function upgrade({ configFile, tag }) {
15
15
  process.exit(1);
16
16
  }
17
17
  const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
18
- const res = await fetch('https://registry.npmjs.org/-/package/zuby/dist-tags');
19
- if (!res.ok) {
20
- logger.error(`ERROR: Failed to fetch latest version from NPM.`);
18
+ let tags;
19
+ try {
20
+ const res = await fetch('https://registry.npmjs.org/-/package/zuby/dist-tags', {
21
+ signal: AbortSignal.timeout(5000),
22
+ });
23
+ if (!res.ok) {
24
+ logger.error(`ERROR: Failed to fetch latest version from NPM.`);
25
+ process.exit(1);
26
+ }
27
+ tags = (await res.json());
28
+ if (!tags || typeof tags !== 'object' || !tags.latest) {
29
+ logger.error(`ERROR: Invalid response from NPM registry.`);
30
+ process.exit(1);
31
+ }
32
+ }
33
+ catch (error) {
34
+ logger.error(`ERROR: Failed to check for latest version: ${error instanceof Error ? error.message : String(error)}`);
21
35
  process.exit(1);
22
36
  }
23
- const tags = (await res.json());
24
37
  const latestVersion = tags.latest;
25
38
  const selectedVersion = tags[tag || `v${currentMajor}`] || latestVersion;
26
39
  logger.info(getTitle(`Checking...`));
@@ -42,8 +55,9 @@ export default async function upgrade({ configFile, tag }) {
42
55
  Object.keys({
43
56
  ...(packageJson.dependencies || {}),
44
57
  ...(packageJson.devDependencies || {}),
45
- }).forEach(name => {
46
- if (!name.match(/^zuby|@zubyjs\/(.+)$/i))
58
+ }).forEach((name) => {
59
+ // Match packages starting with 'zuby' or '@zubyjs/'
60
+ if (!name.match(/^(zuby|@zubyjs\/)(.+)?$/i))
47
61
  return;
48
62
  if (packageJson.dependencies?.[name]) {
49
63
  packageJson.dependencies[name] = selectedVersion;
package/config.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { PluginHook, ZubyConfig, ZubyHookParams, ZubyInternalConfig, ZubyPlugin } from './types.js';
1
+ import { type PluginHook, type ZubyConfig, type ZubyHookParams, type ZubyInternalConfig, type ZubyPlugin } from './types.js';
2
2
  import type { PluginOption as VitePluginOption, Plugin as VitePlugin } from 'vite';
3
3
  /**
4
4
  * Returns the path to the ZubyConfig file.
package/config.js CHANGED
@@ -1,4 +1,4 @@
1
- import { PLUGIN_HOOKS, } from './types.js';
1
+ import { PLUGIN_HOOKS } from './types.js';
2
2
  import { BUILD_CHUNKS_MANIFEST, ZUBY_CONFIG_FILE } from './constants.js';
3
3
  import { existsSync } from 'fs';
4
4
  import { randomBytes } from 'crypto';
@@ -24,11 +24,7 @@ let zubyInternalConfig;
24
24
  */
25
25
  export const getDefaultConfigPath = () => {
26
26
  // Find the config file with various extensions
27
- return [
28
- ZUBY_CONFIG_FILE,
29
- ZUBY_CONFIG_FILE.replace(/\.mjs$/, '.js'),
30
- ZUBY_CONFIG_FILE.replace(/\.mjs$/, '.ts'),
31
- ].find(file => existsSync(file));
27
+ return [ZUBY_CONFIG_FILE, ZUBY_CONFIG_FILE.replace(/\.mjs$/, '.js'), ZUBY_CONFIG_FILE.replace(/\.mjs$/, '.ts')].find((file) => existsSync(file));
32
28
  };
33
29
  /**
34
30
  * This function loads the config file and returns the config object.
@@ -162,11 +158,7 @@ export const mergeDefaultConfig = async (config) => {
162
158
  config.cacheDir = config.cacheDir ?? '.zuby-cache';
163
159
  config.output = config.output ?? 'static';
164
160
  config.prerenderPaths = config.prerenderPaths ?? [];
165
- config.plugins = await normalizePlugins([
166
- ...getBuiltInPlugins(),
167
- ...(config.jsx?.getPlugins() ?? []),
168
- ...(config.plugins ?? []),
169
- ]);
161
+ config.plugins = await normalizePlugins([...getBuiltInPlugins(), ...(config.jsx?.getPlugins() ?? []), ...(config.plugins ?? [])]);
170
162
  // Default server config
171
163
  config.server = config.server ?? {};
172
164
  config.server.host = config.server.host ?? '127.0.0.1';
@@ -180,8 +172,7 @@ export const mergeDefaultConfig = async (config) => {
180
172
  // Image config
181
173
  config.image = config.image ?? {};
182
174
  config.image.sizes = config.image.sizes ?? [160, 320, 640, 768, 1024, 1280, 1536, 1920, 2048];
183
- config.image.loader =
184
- config.image.loader ?? normalizePath(resolve(__dirname, 'image', 'imageLoader.js'));
175
+ config.image.loader = config.image.loader ?? normalizePath(resolve(__dirname, 'image', 'imageLoader.js'));
185
176
  config.image.defaultFormat = config.image.defaultFormat ?? 'webp';
186
177
  config.image.defaultQuality = config.image.defaultQuality ?? 80;
187
178
  // Build ID generator
@@ -243,15 +234,7 @@ export const mergeDefaultConfig = async (config) => {
243
234
  * before removing any of them.
244
235
  */
245
236
  export const getBuiltInPlugins = () => {
246
- return [
247
- injectPlugin(),
248
- contextPlugin(),
249
- chunkNamingPlugin(),
250
- manifestPlugin(),
251
- prerenderPlugin(),
252
- standaloneBuildPlugin(),
253
- preloadPlugin(),
254
- ];
237
+ return [injectPlugin(), contextPlugin(), chunkNamingPlugin(), manifestPlugin(), prerenderPlugin(), standaloneBuildPlugin(), preloadPlugin()];
255
238
  };
256
239
  /**
257
240
  * Executes the Zuby plugins for the given hook.
@@ -303,9 +286,9 @@ export const normalizePlugins = async (plugins) => {
303
286
  const resolvePlugins = await Promise.resolve(plugins);
304
287
  return resolvePlugins
305
288
  // Flatten the array and normalize inner arrays
306
- .flatMap(plugin => (Array.isArray(plugin) ? normalizePlugins(plugin) : [plugin]))
289
+ .flatMap((plugin) => (Array.isArray(plugin) ? normalizePlugins(plugin) : [plugin]))
307
290
  // Remove false, undefined, null values
308
- .filter(plugin => !!plugin);
291
+ .filter((plugin) => !!plugin);
309
292
  };
310
293
  /**
311
294
  * Returns random base32 like build ID
@@ -1,5 +1,5 @@
1
- import { LazyTemplate } from '../templates/types.js';
2
- import { ImageFormat, ImageLoader, RenderToStream, RenderToString } from '../types.js';
1
+ import type { LazyTemplate } from '../templates/types.js';
2
+ import type { ImageFormat, ImageLoader, RenderToStream, RenderToString } from '../types.js';
3
3
  export interface GlobalContext {
4
4
  /**
5
5
  * The array with templates.
@@ -3,5 +3,5 @@ export const getGlobalContext = () => {
3
3
  if (!globalContext) {
4
4
  globalThis._zubyGlobalContext = {};
5
5
  }
6
- return globalContext;
6
+ return globalThis._zubyGlobalContext;
7
7
  };
@@ -1,6 +1,6 @@
1
1
  export * from './globalContext.js';
2
2
  export * from './pageContext.js';
3
- export { PageContext as HandlerContext } from './pageContext.js';
4
- export { PageContext as ZubyPageContext } from './pageContext.js';
5
- export { PageContext as ZubyHandlerContext } from './pageContext.js';
6
- export { GlobalContext as ZubyGlobalContext } from './globalContext.js';
3
+ export type { PageContext as HandlerContext } from './pageContext.js';
4
+ export type { PageContext as ZubyPageContext } from './pageContext.js';
5
+ export type { PageContext as ZubyHandlerContext } from './pageContext.js';
6
+ export type { GlobalContext as ZubyGlobalContext } from './globalContext.js';
package/contexts/index.js CHANGED
@@ -1,5 +1,2 @@
1
1
  export * from './globalContext.js';
2
2
  export * from './pageContext.js';
3
- export { PageContext as HandlerContext } from './pageContext.js';
4
- export { PageContext as ZubyPageContext } from './pageContext.js';
5
- export { PageContext as ZubyHandlerContext } from './pageContext.js';
@@ -1,4 +1,4 @@
1
- import { GlobalContext } from './globalContext.js';
1
+ import { type GlobalContext } from './globalContext.js';
2
2
  export declare class PageContext {
3
3
  protected _url: URL;
4
4
  protected _initialPath: string;
@@ -233,7 +233,7 @@ export class PageContext {
233
233
  * @example /products/1
234
234
  */
235
235
  get isInitialPath() {
236
- return (this._initialPath.replace(/(.+)\/+$/, '$1') === this.url.pathname.replace(/(.+)\/+$/, '$1'));
236
+ return this._initialPath.replace(/(.+)\/+$/, '$1') === this.url.pathname.replace(/(.+)\/+$/, '$1');
237
237
  }
238
238
  /**
239
239
  * Returns array of all locales
@@ -262,7 +262,7 @@ export class PageContext {
262
262
  */
263
263
  get locale() {
264
264
  const currentPath = `${this.url.pathname}/`;
265
- return this.locales.find(locale => currentPath.startsWith(`/${locale}/`)) || this.defaultLocale;
265
+ return this.locales.find((locale) => currentPath.startsWith(`/${locale}/`)) || this.defaultLocale;
266
266
  }
267
267
  /**
268
268
  * Returns path prefixed for given locale.
@@ -283,7 +283,7 @@ export class PageContext {
283
283
  * @example getPathLocale('/de/products/1') => 'de'
284
284
  */
285
285
  getPathLocale(path) {
286
- return this.locales.find(locale => path.startsWith(`/${locale}`)) || this.defaultLocale;
286
+ return this.locales.find((locale) => path.startsWith(`/${locale}`)) || this.defaultLocale;
287
287
  }
288
288
  /**
289
289
  * Localizes the given text for the current locale
@@ -359,7 +359,7 @@ export class PageContext {
359
359
  * @private
360
360
  */
361
361
  async getHeadElements() {
362
- return Promise.all(this._headElements.map(element => this.getElement(element)));
362
+ return Promise.all(this._headElements.map((element) => this.getElement(element)));
363
363
  }
364
364
  /**
365
365
  * Returns array of all elements as string
@@ -367,7 +367,7 @@ export class PageContext {
367
367
  * @private
368
368
  */
369
369
  async getBodyElements() {
370
- return Promise.all(this._bodyElements.map(element => this.getElement(element)));
370
+ return Promise.all(this._bodyElements.map((element) => this.getElement(element)));
371
371
  }
372
372
  /**
373
373
  * Renders the given HTML element
package/defineConfig.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ZubyConfig } from './types.js';
1
+ import type { ZubyConfig } from './types.js';
2
2
  /**
3
3
  * This helper function is used to define the Zuby config in zuby.config.mjs.
4
4
  *
@@ -1,37 +1,37 @@
1
1
  .link-card {
2
- list-style: none;
3
- display: flex;
4
- padding: 1px;
5
- background-color: #23262d;
6
- background-image: none;
7
- background-size: 400%;
8
- border-radius: 7px;
9
- background-position: 100%;
10
- transition: background-position 0.6s cubic-bezier(0.22, 1, 0.36, 1);
11
- box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.1);
2
+ list-style: none;
3
+ display: flex;
4
+ padding: 1px;
5
+ background-color: #23262d;
6
+ background-image: none;
7
+ background-size: 400%;
8
+ border-radius: 7px;
9
+ background-position: 100%;
10
+ transition: background-position 0.6s cubic-bezier(0.22, 1, 0.36, 1);
11
+ box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.1);
12
12
  }
13
13
  .link-card > a {
14
- width: 100%;
15
- text-decoration: none;
16
- line-height: 1.4;
17
- padding: calc(1.5rem - 1px);
18
- border-radius: 8px;
19
- color: white;
20
- background-color: #23262d;
21
- opacity: 0.8;
14
+ width: 100%;
15
+ text-decoration: none;
16
+ line-height: 1.4;
17
+ padding: calc(1.5rem - 1px);
18
+ border-radius: 8px;
19
+ color: white;
20
+ background-color: #23262d;
21
+ opacity: 0.8;
22
22
  }
23
23
  h2 {
24
- margin: 0;
25
- font-size: 1.25rem;
26
- transition: color 0.6s cubic-bezier(0.22, 1, 0.36, 1);
24
+ margin: 0;
25
+ font-size: 1.25rem;
26
+ transition: color 0.6s cubic-bezier(0.22, 1, 0.36, 1);
27
27
  }
28
28
  p {
29
- margin-top: 0.5rem;
30
- margin-bottom: 0;
29
+ margin-top: 0.5rem;
30
+ margin-bottom: 0;
31
31
  }
32
32
  .link-card:is(:hover, :focus-within) {
33
- background-position: 0;
33
+ background-position: 0;
34
34
  }
35
35
  .link-card:is(:hover, :focus-within) h2 {
36
- color: #ffcc00;
36
+ color: #ffcc00;
37
37
  }
@@ -1,15 +1,15 @@
1
1
  import styles from './index.module.css';
2
2
 
3
3
  export default function Card({ href, title, body }) {
4
- return (
5
- <li className={styles.linkCard}>
6
- <a href={href}>
7
- <h2>
8
- {title}
9
- <span>&rarr;</span>
10
- </h2>
11
- <p>{body}</p>
12
- </a>
13
- </li>
14
- );
4
+ return (
5
+ <li className={styles.linkCard}>
6
+ <a href={href}>
7
+ <h2>
8
+ {title}
9
+ <span>&rarr;</span>
10
+ </h2>
11
+ <p>{body}</p>
12
+ </a>
13
+ </li>
14
+ );
15
15
  }