Skip to content

Commit 9137ba7

Browse files
jonphippsclaude
andcommitted
feat: implement preset factory to replace @ifla/preset-ifla
- Add createIFLAPlugins factory function for flexible plugin configuration - Include createDevelopmentPlugins and createProductionPlugins presets - Update portal to use new plugin factory instead of preset - Maintain all functionality while providing environment-based customization - All functions are pure for Nx caching compatibility - Update comprehensive documentation in shared-config README 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent 7e2c5c2 commit 9137ba7

File tree

4 files changed

+327
-6
lines changed

4 files changed

+327
-6
lines changed

libs/shared-config/README.md

Lines changed: 177 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,181 @@
1-
# shared-config
1+
# @ifla/shared-config
22

3-
This library was generated with [Nx](https://nx.dev).
3+
A collection of pure configuration factory functions for Docusaurus sites in the IFLA Standards monorepo. This library provides environment-based configuration capabilities while maintaining Nx caching compatibility.
4+
5+
## Overview
6+
7+
This library provides factory functions that generate configuration objects for various aspects of Docusaurus sites:
8+
- Base configuration (title, URL, etc.)
9+
- Theme configuration (navbar, footer, etc.)
10+
- Plugin configuration (search, image optimization, etc.)
11+
- Preset configuration (classic preset options)
12+
- Environment utilities
13+
14+
All functions are pure and take configuration options as input, returning configuration objects that can be used directly in `docusaurus.config.ts`.
15+
16+
## Installation
17+
18+
This library is internal to the monorepo and available via workspace reference:
19+
20+
```json
21+
{
22+
"dependencies": {
23+
"@ifla/shared-config": "workspace:*"
24+
}
25+
}
26+
```
27+
28+
## Usage
29+
30+
### Environment-Based Configuration
31+
32+
```typescript
33+
// docusaurus.config.ts
34+
import * as dotenv from 'dotenv';
35+
import * as path from 'path';
36+
import { createBaseConfig, createThemeConfig, createIFLAPlugins, getEnvironmentName, validateEnvConfig } from '@ifla/shared-config';
37+
38+
// Load environment variables
39+
const environment = getEnvironmentName();
40+
const envFiles = ['.env', `.env.${environment}`, '.env.local'];
41+
for (const file of envFiles) {
42+
dotenv.config({ path: path.resolve(__dirname, file) });
43+
}
44+
45+
// Validate environment configuration
46+
const envConfig = validateEnvConfig(process.env, 'site-name');
47+
48+
// Create configuration
49+
const config = {
50+
...createBaseConfig({
51+
title: envConfig.SITE_TITLE,
52+
tagline: envConfig.SITE_TAGLINE,
53+
url: envConfig.SITE_URL,
54+
baseUrl: envConfig.SITE_BASE_URL,
55+
projectName: 'site-name',
56+
}),
57+
58+
presets: [
59+
[
60+
'classic',
61+
{
62+
docs: { /* ... */ },
63+
blog: { /* ... */ },
64+
theme: { /* ... */ },
65+
},
66+
],
67+
],
68+
69+
plugins: [
70+
...createIFLAPlugins({
71+
enableIdealImage: environment === 'production',
72+
enableLocalSearch: true,
73+
searchConfig: {
74+
indexBlog: true,
75+
language: ['en'],
76+
},
77+
}),
78+
],
79+
80+
themeConfig: createThemeConfig({
81+
navbarTitle: envConfig.SITE_TITLE,
82+
navbarItems: [ /* ... */ ],
83+
footerLinks: [ /* ... */ ],
84+
}),
85+
};
86+
```
87+
88+
### Plugin Configuration
89+
90+
The library provides flexible plugin configuration through `createIFLAPlugins`:
91+
92+
```typescript
93+
// Development configuration
94+
const devPlugins = createIFLAPlugins({
95+
enableIdealImage: false, // Disable for faster builds
96+
enableLocalSearch: false, // Disable in development
97+
});
98+
99+
// Production configuration
100+
const prodPlugins = createIFLAPlugins({
101+
enableIdealImage: true,
102+
enableLocalSearch: true,
103+
imageConfig: {
104+
quality: 80,
105+
max: 1200,
106+
steps: 3,
107+
},
108+
searchConfig: {
109+
hashed: true,
110+
indexBlog: true,
111+
language: ['en', 'fr'],
112+
},
113+
});
114+
```
115+
116+
### Environment Files
117+
118+
Create environment files for different deployment targets:
119+
120+
```bash
121+
# .env - Base configuration
122+
SITE_TITLE=My Site
123+
SITE_TAGLINE=Documentation
124+
GITHUB_REPO_URL=https://github.com/org/repo
125+
126+
# .env.development
127+
SITE_URL=http://localhost:3000
128+
SITE_BASE_URL=/
129+
130+
# .env.production
131+
SITE_URL=https://mysite.com
132+
SITE_BASE_URL=/docs/
133+
```
134+
135+
## API Reference
136+
137+
### Configuration Factories
138+
139+
- `createBaseConfig(options)` - Creates base Docusaurus configuration
140+
- `createThemeConfig(options)` - Creates theme configuration
141+
- `createIFLAPlugins(options)` - Creates array of IFLA standard plugins
142+
- `createPluginConfig(options)` - Creates classic preset plugin configuration
143+
144+
### Environment Utilities
145+
146+
- `getEnvironmentName()` - Returns current environment name based on NODE_ENV
147+
- `validateEnvConfig(env, siteKey)` - Validates required environment variables
148+
149+
### URL Utilities
150+
151+
- `buildSiteUrl(envConfig, path)` - Builds complete URL from environment config
152+
- `getSiteUrl(url, baseUrl, path)` - Helper for URL construction
153+
154+
## Migration from @ifla/preset-ifla
155+
156+
Instead of using the preset:
157+
158+
```typescript
159+
// Old approach
160+
presets: [
161+
['classic', { /* ... */ }],
162+
'@ifla/preset-ifla',
163+
],
164+
```
165+
166+
Use the plugin factory:
167+
168+
```typescript
169+
// New approach
170+
presets: [
171+
['classic', { /* ... */ }],
172+
],
173+
plugins: [
174+
...createIFLAPlugins({ /* options */ }),
175+
],
176+
```
177+
178+
This provides more flexibility and better environment-based configuration.
4179

5180
## Building
6181

libs/shared-config/src/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@ export * from './lib/createBaseConfig';
33
export * from './lib/createThemeConfig';
44
export * from './lib/createPluginConfig';
55
export * from './lib/createFooterConfig';
6+
export {
7+
createIFLAPlugins,
8+
createDevelopmentPlugins,
9+
createProductionPlugins,
10+
type IFLAPluginOptions
11+
} from './lib/createPresetConfig';
612
export * from './lib/utils/loadEnvConfig';
713
export * from './lib/utils/getSiteUrl';
814
export * from './lib/types';
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
export interface IFLAPluginOptions {
2+
/** Enable Sass support (default: true) */
3+
enableSass?: boolean;
4+
/** Enable ideal image optimization (default: true) */
5+
enableIdealImage?: boolean;
6+
/** Enable local search (default: true) */
7+
enableLocalSearch?: boolean;
8+
/** Additional plugins to include */
9+
additionalPlugins?: any[];
10+
/** Local search configuration */
11+
searchConfig?: {
12+
hashed?: boolean;
13+
indexBlog?: boolean;
14+
language?: string[];
15+
};
16+
/** Ideal image configuration */
17+
imageConfig?: {
18+
quality?: number;
19+
max?: number;
20+
min?: number;
21+
steps?: number;
22+
disableInDev?: boolean;
23+
};
24+
}
25+
26+
/**
27+
* Create IFLA standard plugins configuration as a pure function
28+
*
29+
* This factory function creates plugin configuration that can be customized
30+
* per site while maintaining consistency across the IFLA standards ecosystem.
31+
*
32+
* @param options Configuration options for plugins
33+
* @returns Array of plugin configurations for direct use in docusaurus.config.ts
34+
*/
35+
export function createIFLAPlugins(options: IFLAPluginOptions = {}): any[] {
36+
const {
37+
enableSass = true,
38+
enableIdealImage = true,
39+
enableLocalSearch = true,
40+
additionalPlugins = [],
41+
searchConfig = {},
42+
imageConfig = {},
43+
} = options;
44+
45+
const plugins: any[] = [];
46+
47+
// Sass support
48+
if (enableSass) {
49+
plugins.push('docusaurus-plugin-sass');
50+
}
51+
52+
// Ideal image optimization
53+
if (enableIdealImage) {
54+
plugins.push([
55+
'@docusaurus/plugin-ideal-image',
56+
{
57+
quality: 70,
58+
max: 1030,
59+
min: 640,
60+
steps: 2,
61+
disableInDev: false,
62+
...imageConfig,
63+
},
64+
]);
65+
}
66+
67+
// Local search functionality
68+
if (enableLocalSearch) {
69+
plugins.push([
70+
'@easyops-cn/docusaurus-search-local',
71+
{
72+
hashed: true,
73+
indexBlog: false,
74+
language: ['en'],
75+
...searchConfig,
76+
},
77+
]);
78+
}
79+
80+
// Add additional plugins
81+
plugins.push(...additionalPlugins);
82+
83+
return plugins;
84+
}
85+
86+
/**
87+
* Create a lightweight plugin set for development/testing
88+
* Disables heavy plugins for faster builds
89+
*
90+
* @returns Array of plugins optimized for development
91+
*/
92+
export function createDevelopmentPlugins(): any[] {
93+
return createIFLAPlugins({
94+
enableIdealImage: false, // Disable image optimization in dev
95+
enableLocalSearch: false, // Disable search indexing in dev
96+
searchConfig: {
97+
indexBlog: false,
98+
},
99+
});
100+
}
101+
102+
/**
103+
* Create a production-optimized plugin set
104+
* Enables all optimizations and plugins
105+
*
106+
* @returns Array of plugins optimized for production
107+
*/
108+
export function createProductionPlugins(): any[] {
109+
return createIFLAPlugins({
110+
enableSass: true,
111+
enableIdealImage: true,
112+
enableLocalSearch: true,
113+
imageConfig: {
114+
quality: 80, // Higher quality for production
115+
max: 1200,
116+
min: 640,
117+
steps: 3, // More responsive breakpoints
118+
disableInDev: false,
119+
},
120+
searchConfig: {
121+
hashed: true,
122+
indexBlog: true, // Index blog in production
123+
language: ['en'], // Add more languages as needed
124+
},
125+
});
126+
}

portal/docusaurus.config.ts

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import * as path from 'path';
33
import type { Config } from '@docusaurus/types';
44
import type * as Preset from '@docusaurus/preset-classic';
55
import { deepmerge } from 'deepmerge-ts';
6-
import { createBaseConfig, createThemeConfig, getEnvironmentName, validateEnvConfig } from '@ifla/shared-config';
6+
import { createBaseConfig, createThemeConfig, createIFLAPlugins, getEnvironmentName, validateEnvConfig } from '@ifla/shared-config';
77
import { getSiteDocusaurusConfig } from '@ifla/theme/config';
88
import { getCurrentEnv } from '@ifla/theme/config/siteConfig.server';
99
import navbarItems from './navbar';
@@ -88,7 +88,23 @@ const config: Config = deepmerge(
8888
},
8989
} satisfies Preset.Options,
9090
],
91-
'@ifla/preset-ifla',
91+
],
92+
93+
plugins: [
94+
...createIFLAPlugins({
95+
// Environment-specific configuration
96+
enableIdealImage: environment === 'production',
97+
enableLocalSearch: true,
98+
searchConfig: {
99+
indexBlog: true, // Portal has a blog
100+
language: ['en'],
101+
},
102+
imageConfig: {
103+
quality: environment === 'production' ? 80 : 70,
104+
max: 1200,
105+
steps: environment === 'production' ? 3 : 2,
106+
},
107+
}),
92108
],
93109

94110
themeConfig: deepmerge(
@@ -164,8 +180,6 @@ const config: Config = deepmerge(
164180
} satisfies Partial<Preset.ThemeConfig>,
165181
),
166182

167-
plugins: [],
168-
169183
i18n: {
170184
defaultLocale: 'en',
171185
locales: ['en'],

0 commit comments

Comments
 (0)