portosaurus 0.14.0 → 0.16.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.

Potentially problematic release.


This version of portosaurus might be problematic. Click here for more details.

Files changed (119) hide show
  1. package/README.md +36 -45
  2. package/bin/cli.ts +60 -0
  3. package/docusaurus.config.ts +221 -0
  4. package/lib/bin/cli.js +49 -0
  5. package/lib/docusaurus.config.js +204 -0
  6. package/lib/src/cli/commands/build.js +26 -0
  7. package/lib/src/cli/commands/init.js +134 -0
  8. package/lib/src/cli/commands/serve.js +22 -0
  9. package/lib/src/cli/commands/start.js +37 -0
  10. package/lib/src/cli/utils/config-loader.js +28 -0
  11. package/lib/src/cli/utils/logger.js +18 -0
  12. package/lib/src/components/AboutSection/index.js +9 -0
  13. package/lib/src/components/ContactSection/index.js +38 -0
  14. package/lib/src/components/ExperienceSection/index.js +5 -0
  15. package/lib/src/components/HeroSection/index.js +17 -0
  16. package/lib/src/components/NoteIndex/index.js +65 -0
  17. package/lib/src/components/ProjectsSection/index.js +289 -0
  18. package/lib/src/components/ScrollToTop/index.js +68 -0
  19. package/lib/src/components/SocialLinks/index.js +82 -0
  20. package/lib/src/components/Tooltip/index.js +8 -0
  21. package/lib/src/config/iconMappings.js +266 -0
  22. package/lib/src/config/metaTags.js +233 -0
  23. package/lib/src/config/prism.js +177 -0
  24. package/lib/src/config/sidebar.js +16 -0
  25. package/lib/src/index.js +1 -0
  26. package/lib/src/pages/index.js +31 -0
  27. package/lib/src/pages/notes.js +57 -0
  28. package/lib/src/pages/tasks.js +74 -0
  29. package/lib/src/types/config.js +1 -0
  30. package/lib/src/utils/HashNavigation.js +177 -0
  31. package/lib/src/utils/UpdateTitle.js +76 -0
  32. package/lib/src/utils/appVersion.js +19 -0
  33. package/lib/src/utils/compileConfig.js +66 -0
  34. package/lib/src/utils/cssUtils.js +85 -0
  35. package/lib/src/utils/filterEnabledItems.js +19 -0
  36. package/lib/src/utils/generateFavicon.js +179 -0
  37. package/lib/src/utils/generateRobotsTxt.js +74 -0
  38. package/lib/src/utils/iconExtractor.js +135 -0
  39. package/lib/src/utils/imageDownloader.js +63 -0
  40. package/lib/src/utils/imageProcessor.js +91 -0
  41. package/lib/templates/config.js +100 -0
  42. package/package.json +73 -13
  43. package/src/cli/commands/build.ts +31 -0
  44. package/src/cli/commands/init.ts +151 -0
  45. package/src/cli/commands/serve.ts +26 -0
  46. package/src/cli/commands/start.ts +44 -0
  47. package/src/cli/utils/config-loader.ts +26 -0
  48. package/src/cli/utils/logger.ts +23 -0
  49. package/src/{theme/components/AboutSection/index.js → components/AboutSection/index.tsx} +14 -3
  50. package/src/{theme/components/ContactSection/index.js → components/ContactSection/index.tsx} +23 -8
  51. package/src/{theme/components/ExperienceSection/index.js → components/ExperienceSection/index.tsx} +8 -1
  52. package/src/{theme/components/HeroSection/index.js → components/HeroSection/index.tsx} +15 -9
  53. package/src/{theme/components/NoteIndex/index.js → components/NoteIndex/index.tsx} +35 -15
  54. package/src/{theme/components/ProjectsSection/index.js → components/ProjectsSection/index.tsx} +49 -27
  55. package/src/{theme/components/ScrollToTop/index.js → components/ScrollToTop/index.tsx} +6 -2
  56. package/src/{theme/components/SocialLinks/index.js → components/SocialLinks/index.tsx} +23 -11
  57. package/src/{theme/components/Tooltip/index.js → components/Tooltip/index.tsx} +10 -3
  58. package/src/config/{iconMappings.js → iconMappings.ts} +7 -3
  59. package/src/config/{prism.js → prism.ts} +2 -2
  60. package/src/config/{sidebar.js → sidebar.ts} +4 -3
  61. package/src/index.ts +1 -0
  62. package/src/pages/{index.js → index.tsx} +14 -15
  63. package/src/pages/{notes.js → notes.tsx} +11 -9
  64. package/src/pages/{tasks.js → tasks.tsx} +25 -12
  65. package/src/types/config.ts +99 -0
  66. package/src/types.d.ts +1 -0
  67. package/src/utils/{HashNavigation.js → HashNavigation.tsx} +25 -20
  68. package/src/utils/{updateTitle.js → UpdateTitle.tsx} +10 -10
  69. package/src/utils/{appVersion.js → appVersion.ts} +6 -10
  70. package/src/{configLoader.js → utils/compileConfig.ts} +27 -39
  71. package/src/utils/{cssUtils.js → cssUtils.ts} +12 -12
  72. package/src/utils/{filterEnabledItems.js → filterEnabledItems.ts} +12 -5
  73. package/src/utils/{generateFavicon.js → generateFavicon.ts} +60 -90
  74. package/src/utils/{generateRobotsTxt.js → generateRobotsTxt.ts} +19 -7
  75. package/src/utils/{iconExtractor.js → iconExtractor.ts} +44 -28
  76. package/src/utils/{imageDownloader.js → imageDownloader.ts} +19 -37
  77. package/src/utils/{imageProcessor.js → imageProcessor.ts} +5 -24
  78. package/templates/README.md +29 -0
  79. package/templates/_tsconfig.json +7 -0
  80. package/templates/blog/welcome.md +17 -0
  81. package/templates/config.js +110 -0
  82. package/templates/notes/intro.md +9 -0
  83. package/tsconfig.json +28 -0
  84. package/.vscode/snippets.code-snippets +0 -79
  85. package/AGENTS.md +0 -37
  86. package/GG/config.js +0 -233
  87. package/GG/package.json +0 -14
  88. package/GG/static/.nojekyll +0 -0
  89. package/GG/static/docusaurus-snippet.css +0 -3
  90. package/GG/static/img/icon-bg.png +0 -0
  91. package/GG/static/img/icon-old.png +0 -0
  92. package/GG/static/img/icon.png +0 -0
  93. package/GG/static/img/project-blank.png +0 -0
  94. package/GG/static/img/social-card.jpeg +0 -0
  95. package/LICENSE +0 -674
  96. package/bin/portosaurus.js +0 -136
  97. package/src/index.js +0 -79
  98. package/src/theme/staticLink/.nojekyll +0 -0
  99. package/src/theme/staticLink/docusaurus-snippet.css +0 -3
  100. package/src/theme/staticLink/img/icon-bg.png +0 -0
  101. package/src/theme/staticLink/img/icon-old.png +0 -0
  102. package/src/theme/staticLink/img/icon.png +0 -0
  103. package/src/theme/staticLink/img/project-blank.png +0 -0
  104. package/src/theme/staticLink/img/social-card.jpeg +0 -0
  105. package/src/utils/linkShortner.js +0 -0
  106. /package/src/{theme/components → components}/AboutSection/styles.module.css +0 -0
  107. /package/src/{theme/components → components}/ContactSection/styles.module.css +0 -0
  108. /package/src/{theme/components → components}/ExperienceSection/styles.module.css +0 -0
  109. /package/src/{theme/components → components}/HeroSection/styles.module.css +0 -0
  110. /package/src/{theme/components → components}/NoteIndex/styles.module.css +0 -0
  111. /package/src/{theme/components → components}/ProjectsSection/styles.module.css +0 -0
  112. /package/src/{theme/components → components}/ScrollToTop/styles.module.css +0 -0
  113. /package/src/{theme/components → components}/SocialLinks/styles.module.css +0 -0
  114. /package/src/{theme/components → components}/Tooltip/styles.module.css +0 -0
  115. /package/src/config/{metaTags.js → metaTags.ts} +0 -0
  116. /package/src/{theme/css → css}/bootstrap.css +0 -0
  117. /package/src/{theme/css → css}/catppuccin.css +0 -0
  118. /package/src/{theme/css → css}/custom.css +0 -0
  119. /package/src/{theme/css → css}/tasks.css +0 -0
package/README.md CHANGED
@@ -1,57 +1,48 @@
1
- <div align="center">
2
- <img src="./static/img/icon.png" width=150>
3
- <h1>Postosaurus</h1>
4
- <p>Complete portfolio cum personal website solution for your digital personality.</p>
5
- </div>
1
+ # Portosaurus
6
2
 
7
- <br/>
3
+ > COMPLETE portfolio cum personal website solution for your digital personality.
8
4
 
9
- ## 📁 Project Structure
5
+ Portosaurus is a Docusaurus-based portfolio generator. It allows you to create a beautiful, developer-focused portfolio with a blog and notes section in minutes, using a simple configuration file.
10
6
 
11
- As this project is built upon docusaurus, it follows it's guidelines.
7
+ ## Features
12
8
 
13
- ```
14
- ./
15
- ├── blog/
16
- │ ├── ...
17
- │ └── My mindset
18
- ├── notes/
19
- │ ├── ...
20
- │ ├── sidebars.js
21
- │ └── Self written notes, accessiable in /notes
22
- ├── src/
23
- │ ├── components/
24
- │ ├── css/
25
- │ ├── pages/
26
- │ │ ├─ ...
27
- │ │ ├── index.js - entry point
28
- │ │ └── holds standalone pages
29
- │ └── ...
30
- ├── static/
31
- │ ├── img/
32
- │ ├── ...
33
- │ └── static files
34
- ├── config.js
35
- ├── docusaurus.config.js
36
- └── package.json
9
+ - **Zero Config Setup**: Scaffolds a complete project with one command.
10
+ - **Config Driven**: Customize everything via `config.ts` or `config.js`.
11
+ - **Blog & Notes**: Built-in support for technical blogging and taking notes.
12
+ - **Themes**: Dark mode support and customizable themes.
13
+ - **Fast**: Built on Docusaurus/React.
14
+
15
+ ## Quick Start
16
+
17
+ Create a new project:
18
+
19
+ ```bash
20
+ npx portosaurus init my-portfolio
21
+ cd my-portfolio
22
+ npm start
37
23
  ```
38
24
 
39
- ## 💻 Development
25
+ This will start a local development server at `http://localhost:3000`.
40
26
 
41
- - Run the local development server:
27
+ ## Commands
42
28
 
43
- ```bash
44
- npm run start
45
- ```
29
+ - `npm start`: Start the development server (aliased to `portosaurus start`).
30
+ - `npm run build`: Build the static site for production (aliased to `portosaurus build`).
31
+ - `npm run serve`: Serve the built site locally (aliased to `portosaurus serve`).
46
32
 
47
- - Build the website:
33
+ ## Project Structure
48
34
 
49
- ```bash
50
- npm run build
51
- ```
35
+ Your project will look like this:
36
+
37
+ ```
38
+ my-portfolio/
39
+ ├── config.ts # Main configuration
40
+ ├── blog/ # Your blog posts (MDX)
41
+ ├── notes/ # Your notes (MDX)
42
+ ├── src/ # Static assets (images, etc.)
43
+ └── package.json # Dependency management
44
+ ```
52
45
 
53
- - Serve the built website locally:
46
+ ## Documentation
54
47
 
55
- ```bash
56
- npm run serve
57
- ```
48
+ For full documentation, visit [Portosaurus Docs](https://github.com/StartSomethingStudio/portosaurus).
package/bin/cli.ts ADDED
@@ -0,0 +1,60 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { Command } from 'commander';
4
+ import { createRequire } from 'module';
5
+ import fs from 'fs';
6
+ import path from 'path';
7
+ import { fileURLToPath } from 'url';
8
+
9
+ const cliRequire = createRequire(import.meta.url);
10
+
11
+ // prefix removed as per previous step logic, just keep the declaration once
12
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
13
+
14
+ // Resolve package.json path (handles both dev tsx and prod lib execution)
15
+ const devPkgPath = path.resolve(__dirname, '../package.json');
16
+ const prodPkgPath = path.resolve(__dirname, '../../package.json');
17
+ const packageJsonPath = fs.existsSync(devPkgPath) ? devPkgPath : prodPkgPath;
18
+ const packageJson = cliRequire(packageJsonPath);
19
+
20
+ const program = new Command();
21
+
22
+ program
23
+ .name('portosaurus')
24
+ .description('Complete portfolio cum personal website solution for your digital personality')
25
+ .version(packageJson.version);
26
+
27
+ program
28
+ .command('init')
29
+ .description('Initialize a new Portosaurus project')
30
+ .argument('[directory]', 'Directory to initialize in', '.')
31
+ .action(async (directory) => {
32
+ const { initCommand } = await import('../src/cli/commands/init.js');
33
+ await initCommand(directory);
34
+ });
35
+
36
+ program
37
+ .command('start')
38
+ .description('Start the development server')
39
+ .action(async () => {
40
+ const { startCommand } = await import('../src/cli/commands/start.js');
41
+ await startCommand();
42
+ });
43
+
44
+ program
45
+ .command('build')
46
+ .description('Build the website for production')
47
+ .action(async () => {
48
+ const { buildCommand } = await import('../src/cli/commands/build.js');
49
+ await buildCommand();
50
+ });
51
+
52
+ program
53
+ .command('serve')
54
+ .description('Serve the built website')
55
+ .action(async () => {
56
+ const { serveCommand } = await import('../src/cli/commands/serve.js');
57
+ await serveCommand();
58
+ });
59
+
60
+ program.parse(process.argv);
@@ -0,0 +1,221 @@
1
+ import type { Config } from '@docusaurus/types';
2
+ import type * as Preset from '@docusaurus/preset-classic';
3
+ import { loadUserConfig } from './src/cli/utils/config-loader.js';
4
+ import { createRequire } from 'module';
5
+
6
+ const require = createRequire(import.meta.url);
7
+
8
+ import generateFaviconPlugin from './src/utils/generateFavicon.js';
9
+ import generateRobotsTxtPlugin from './src/utils/generateRobotsTxt.js';
10
+ import { metaTags } from './src/config/metaTags.js';
11
+ import { catppuccinMocha, catppuccinLatte } from './src/config/prism.js';
12
+
13
+ // Helper to filter enabled items
14
+ const useEnabled = (items: any[]) => {
15
+ return items.flatMap(item => {
16
+ if (item && typeof item === 'object' && 'enable' in item && 'value' in item) {
17
+ return item.enable === true ? [item.value] : [];
18
+ }
19
+ return [item];
20
+ });
21
+ };
22
+
23
+ export default async function createConfig(): Promise<Config> {
24
+ const userConfig = await loadUserConfig();
25
+
26
+ if (!userConfig) {
27
+ throw new Error('Config file not found! Please create config.ts or config.js');
28
+ }
29
+
30
+ // --- Map Portosaurus Config to Docusaurus Config ---
31
+
32
+ const siteConfig: Config = {
33
+ headTags: metaTags,
34
+ title: userConfig.hero_section.title,
35
+ tagline: userConfig.hero_section.description,
36
+ favicon: 'img/favicon.ico', // TODO: Make dynamic/configurable
37
+
38
+ // Set the production url of your site here
39
+ url: userConfig.site_url === 'auto' ? 'https://example.com' : userConfig.site_url,
40
+ baseUrl: userConfig.site_path === 'auto' ? '/' : userConfig.site_path,
41
+
42
+ onBrokenLinks: 'throw',
43
+ onBrokenMarkdownLinks: 'warn',
44
+
45
+ i18n: {
46
+ defaultLocale: 'en',
47
+ locales: ['en'],
48
+ },
49
+
50
+ presets: [
51
+ [
52
+ 'classic',
53
+ {
54
+ docs: {
55
+ routeBasePath: 'notes',
56
+ path: 'notes',
57
+ sidebarPath: './src/config/sidebar.ts',
58
+ admonitions: {
59
+ keywords: ["note", "tip", "info", "warning", "danger", "question"],
60
+ extendDefaults: true,
61
+ },
62
+ },
63
+ blog: {
64
+ showReadingTime: true,
65
+ path: 'blog',
66
+ routeBasePath: 'blog',
67
+ feedOptions: userConfig.rss ? {
68
+ type: 'all',
69
+ copyright: `Copyright © ${new Date().getFullYear()} ${userConfig.hero_section.title}`,
70
+ } : undefined,
71
+ onInlineTags: 'warn',
72
+ onInlineAuthors: 'warn',
73
+ onUntruncatedBlogPosts: 'warn',
74
+ },
75
+ theme: {
76
+ customCss: './src/css/custom.css',
77
+ },
78
+ } satisfies Preset.Options,
79
+ ],
80
+ ],
81
+
82
+ plugins: [
83
+ generateFaviconPlugin as any, // TODO: strict plugin types
84
+ generateRobotsTxtPlugin as any,
85
+ [
86
+ require.resolve('@easyops-cn/docusaurus-search-local'),
87
+ {
88
+ hashed: true,
89
+ indexDocs: true,
90
+ docsDir: "notes",
91
+ docsRouteBasePath: "notes",
92
+ highlightSearchTermsOnTargetPage: true,
93
+ explicitSearchResultPath: true,
94
+ hideSearchBarWithNoSearchContext: true,
95
+ searchContextByPaths: ["notes", "blog"],
96
+ language: ["en"],
97
+ },
98
+ ],
99
+ require.resolve('plugin-image-zoom'),
100
+ ],
101
+
102
+ customFields: {
103
+ version: '1.0.0', // TODO: dynamic
104
+ heroSection: {
105
+ profilePic: userConfig.hero_section.profile_pic,
106
+ intro: "Hi, I am",
107
+ title: userConfig.hero_section.title,
108
+ subtitle: "I am a",
109
+ profession: userConfig.hero_section.profession,
110
+ description: userConfig.hero_section.description,
111
+ learnMoreButtonTxt: "Learn More",
112
+ },
113
+ aboutMe: userConfig.about_me,
114
+ projects: userConfig.project_shelf,
115
+ experience: userConfig.experience,
116
+ socialLinks: userConfig.social_links,
117
+ robotsTxt: { enable: userConfig.rebots_txt, rules: [{ disallow: ["/notes/", "/tasks/"] }], customLines: [] },
118
+ tasksPage: userConfig.tasks_page,
119
+ },
120
+
121
+ themeConfig: {
122
+ image: userConfig.social_card || "img/social-card.jpeg",
123
+ docs: {
124
+ sidebar: {
125
+ hideable: userConfig.colapsable_sidebar,
126
+ },
127
+ },
128
+ imageZoom: {
129
+ options: {
130
+ margin: 2,
131
+ background: "rgba(var(--ifm-background-color-rgb), 0.9)",
132
+ },
133
+ },
134
+ colorMode: {
135
+ defaultMode: userConfig.dark_mode ? "dark" : "light",
136
+ disableSwitch: userConfig.disable_theme_switch,
137
+ },
138
+ navbar: {
139
+ title: userConfig.hero_section.title,
140
+ hideOnScroll: userConfig.hide_navbar_on_scroll,
141
+ logo: {
142
+ alt: 'Site Logo',
143
+ src: userConfig.hero_section.profile_pic, // Using profile pic as logo per original config
144
+ },
145
+ items: useEnabled([
146
+ {
147
+ type: "search",
148
+ position: "right",
149
+ className: "navbar-search-bar",
150
+ },
151
+ {
152
+ enable: userConfig.about_me?.enable,
153
+ value: {
154
+ label: "About Me",
155
+ to: "/#about",
156
+ position: "right",
157
+ activeBaseRegex: "^/#about",
158
+ },
159
+ },
160
+ {
161
+ enable: userConfig.project_shelf?.enable,
162
+ value: {
163
+ label: "Projects",
164
+ to: "/#projects",
165
+ position: "right",
166
+ activeBaseRegex: "^/#projects",
167
+ },
168
+ },
169
+ {
170
+ enable: userConfig.experience?.enable,
171
+ value: {
172
+ label: "Experience",
173
+ to: "/#experience",
174
+ position: "right",
175
+ activeBaseRegex: "^/#experience",
176
+ },
177
+ },
178
+ {
179
+ enable: userConfig.social_links?.enable,
180
+ value: {
181
+ label: "Contact",
182
+ to: "/#contact",
183
+ position: "right",
184
+ activeBaseRegex: "^/$contact",
185
+ },
186
+ },
187
+ {
188
+ type: "dropdown",
189
+ label: "More",
190
+ position: "right",
191
+ className: "_navbar-more-items",
192
+ items: useEnabled([
193
+ { label: "Notes", to: "/notes" },
194
+ { label: "Blog", to: "/blog" },
195
+ { label: "Tasks", to: "/tasks" },
196
+ {
197
+ enable: true,
198
+ value: {
199
+ label: `Portosaurus`,
200
+ className: "_nav-protosaurus-version",
201
+ href: "https://github.com/soymadip/portosaurus",
202
+ },
203
+ },
204
+ ]),
205
+ }
206
+ ]),
207
+ },
208
+ footer: {
209
+ // Empty footer per original config
210
+ },
211
+ // tableOfContents: { minHeadingLevel: 2, maxHeadingLevel: 4 }, // Add if needed
212
+ prism: {
213
+ theme: catppuccinLatte as any,
214
+ darkTheme: catppuccinMocha as any,
215
+ additionalLanguages: ["java", "php", "bash"],
216
+ },
217
+ } satisfies Preset.ThemeConfig,
218
+ };
219
+
220
+ return siteConfig;
221
+ }
package/lib/bin/cli.js ADDED
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import { createRequire } from 'module';
4
+ import fs from 'fs';
5
+ import path from 'path';
6
+ import { fileURLToPath } from 'url';
7
+ const cliRequire = createRequire(import.meta.url);
8
+ // prefix removed as per previous step logic, just keep the declaration once
9
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
10
+ // Resolve package.json path (handles both dev tsx and prod lib execution)
11
+ const devPkgPath = path.resolve(__dirname, '../package.json');
12
+ const prodPkgPath = path.resolve(__dirname, '../../package.json');
13
+ const packageJsonPath = fs.existsSync(devPkgPath) ? devPkgPath : prodPkgPath;
14
+ const packageJson = cliRequire(packageJsonPath);
15
+ const program = new Command();
16
+ program
17
+ .name('portosaurus')
18
+ .description('Complete portfolio cum personal website solution for your digital personality')
19
+ .version(packageJson.version);
20
+ program
21
+ .command('init')
22
+ .description('Initialize a new Portosaurus project')
23
+ .argument('[directory]', 'Directory to initialize in', '.')
24
+ .action(async (directory) => {
25
+ const { initCommand } = await import('../src/cli/commands/init.js');
26
+ await initCommand(directory);
27
+ });
28
+ program
29
+ .command('start')
30
+ .description('Start the development server')
31
+ .action(async () => {
32
+ const { startCommand } = await import('../src/cli/commands/start.js');
33
+ await startCommand();
34
+ });
35
+ program
36
+ .command('build')
37
+ .description('Build the website for production')
38
+ .action(async () => {
39
+ const { buildCommand } = await import('../src/cli/commands/build.js');
40
+ await buildCommand();
41
+ });
42
+ program
43
+ .command('serve')
44
+ .description('Serve the built website')
45
+ .action(async () => {
46
+ const { serveCommand } = await import('../src/cli/commands/serve.js');
47
+ await serveCommand();
48
+ });
49
+ program.parse(process.argv);
@@ -0,0 +1,204 @@
1
+ import { loadUserConfig } from './src/cli/utils/config-loader.js';
2
+ import { createRequire } from 'module';
3
+ const require = createRequire(import.meta.url);
4
+ import generateFaviconPlugin from './src/utils/generateFavicon.js';
5
+ import generateRobotsTxtPlugin from './src/utils/generateRobotsTxt.js';
6
+ import { metaTags } from './src/config/metaTags.js';
7
+ import { catppuccinMocha, catppuccinLatte } from './src/config/prism.js';
8
+ // Helper to filter enabled items
9
+ const useEnabled = (items) => {
10
+ return items.flatMap(item => {
11
+ if (item && typeof item === 'object' && 'enable' in item && 'value' in item) {
12
+ return item.enable === true ? [item.value] : [];
13
+ }
14
+ return [item];
15
+ });
16
+ };
17
+ export default async function createConfig() {
18
+ const userConfig = await loadUserConfig();
19
+ if (!userConfig) {
20
+ throw new Error('Config file not found! Please create config.ts or config.js');
21
+ }
22
+ // --- Map Portosaurus Config to Docusaurus Config ---
23
+ const siteConfig = {
24
+ headTags: metaTags,
25
+ title: userConfig.hero_section.title,
26
+ tagline: userConfig.hero_section.description,
27
+ favicon: 'img/favicon.ico', // TODO: Make dynamic/configurable
28
+ // Set the production url of your site here
29
+ url: userConfig.site_url === 'auto' ? 'https://example.com' : userConfig.site_url,
30
+ baseUrl: userConfig.site_path === 'auto' ? '/' : userConfig.site_path,
31
+ onBrokenLinks: 'throw',
32
+ onBrokenMarkdownLinks: 'warn',
33
+ i18n: {
34
+ defaultLocale: 'en',
35
+ locales: ['en'],
36
+ },
37
+ presets: [
38
+ [
39
+ 'classic',
40
+ {
41
+ docs: {
42
+ routeBasePath: 'notes',
43
+ path: 'notes',
44
+ sidebarPath: './src/config/sidebar.ts',
45
+ admonitions: {
46
+ keywords: ["note", "tip", "info", "warning", "danger", "question"],
47
+ extendDefaults: true,
48
+ },
49
+ },
50
+ blog: {
51
+ showReadingTime: true,
52
+ path: 'blog',
53
+ routeBasePath: 'blog',
54
+ feedOptions: userConfig.rss ? {
55
+ type: 'all',
56
+ copyright: `Copyright © ${new Date().getFullYear()} ${userConfig.hero_section.title}`,
57
+ } : undefined,
58
+ onInlineTags: 'warn',
59
+ onInlineAuthors: 'warn',
60
+ onUntruncatedBlogPosts: 'warn',
61
+ },
62
+ theme: {
63
+ customCss: './src/css/custom.css',
64
+ },
65
+ },
66
+ ],
67
+ ],
68
+ plugins: [
69
+ generateFaviconPlugin, // TODO: strict plugin types
70
+ generateRobotsTxtPlugin,
71
+ [
72
+ require.resolve('@easyops-cn/docusaurus-search-local'),
73
+ {
74
+ hashed: true,
75
+ indexDocs: true,
76
+ docsDir: "notes",
77
+ docsRouteBasePath: "notes",
78
+ highlightSearchTermsOnTargetPage: true,
79
+ explicitSearchResultPath: true,
80
+ hideSearchBarWithNoSearchContext: true,
81
+ searchContextByPaths: ["notes", "blog"],
82
+ language: ["en"],
83
+ },
84
+ ],
85
+ require.resolve('plugin-image-zoom'),
86
+ ],
87
+ customFields: {
88
+ version: '1.0.0', // TODO: dynamic
89
+ heroSection: {
90
+ profilePic: userConfig.hero_section.profile_pic,
91
+ intro: "Hi, I am",
92
+ title: userConfig.hero_section.title,
93
+ subtitle: "I am a",
94
+ profession: userConfig.hero_section.profession,
95
+ description: userConfig.hero_section.description,
96
+ learnMoreButtonTxt: "Learn More",
97
+ },
98
+ aboutMe: userConfig.about_me,
99
+ projects: userConfig.project_shelf,
100
+ experience: userConfig.experience,
101
+ socialLinks: userConfig.social_links,
102
+ robotsTxt: { enable: userConfig.rebots_txt, rules: [{ disallow: ["/notes/", "/tasks/"] }], customLines: [] },
103
+ tasksPage: userConfig.tasks_page,
104
+ },
105
+ themeConfig: {
106
+ image: userConfig.social_card || "img/social-card.jpeg",
107
+ docs: {
108
+ sidebar: {
109
+ hideable: userConfig.colapsable_sidebar,
110
+ },
111
+ },
112
+ imageZoom: {
113
+ options: {
114
+ margin: 2,
115
+ background: "rgba(var(--ifm-background-color-rgb), 0.9)",
116
+ },
117
+ },
118
+ colorMode: {
119
+ defaultMode: userConfig.dark_mode ? "dark" : "light",
120
+ disableSwitch: userConfig.disable_theme_switch,
121
+ },
122
+ navbar: {
123
+ title: userConfig.hero_section.title,
124
+ hideOnScroll: userConfig.hide_navbar_on_scroll,
125
+ logo: {
126
+ alt: 'Site Logo',
127
+ src: userConfig.hero_section.profile_pic, // Using profile pic as logo per original config
128
+ },
129
+ items: useEnabled([
130
+ {
131
+ type: "search",
132
+ position: "right",
133
+ className: "navbar-search-bar",
134
+ },
135
+ {
136
+ enable: userConfig.about_me?.enable,
137
+ value: {
138
+ label: "About Me",
139
+ to: "/#about",
140
+ position: "right",
141
+ activeBaseRegex: "^/#about",
142
+ },
143
+ },
144
+ {
145
+ enable: userConfig.project_shelf?.enable,
146
+ value: {
147
+ label: "Projects",
148
+ to: "/#projects",
149
+ position: "right",
150
+ activeBaseRegex: "^/#projects",
151
+ },
152
+ },
153
+ {
154
+ enable: userConfig.experience?.enable,
155
+ value: {
156
+ label: "Experience",
157
+ to: "/#experience",
158
+ position: "right",
159
+ activeBaseRegex: "^/#experience",
160
+ },
161
+ },
162
+ {
163
+ enable: userConfig.social_links?.enable,
164
+ value: {
165
+ label: "Contact",
166
+ to: "/#contact",
167
+ position: "right",
168
+ activeBaseRegex: "^/$contact",
169
+ },
170
+ },
171
+ {
172
+ type: "dropdown",
173
+ label: "More",
174
+ position: "right",
175
+ className: "_navbar-more-items",
176
+ items: useEnabled([
177
+ { label: "Notes", to: "/notes" },
178
+ { label: "Blog", to: "/blog" },
179
+ { label: "Tasks", to: "/tasks" },
180
+ {
181
+ enable: true,
182
+ value: {
183
+ label: `Portosaurus`,
184
+ className: "_nav-protosaurus-version",
185
+ href: "https://github.com/soymadip/portosaurus",
186
+ },
187
+ },
188
+ ]),
189
+ }
190
+ ]),
191
+ },
192
+ footer: {
193
+ // Empty footer per original config
194
+ },
195
+ // tableOfContents: { minHeadingLevel: 2, maxHeadingLevel: 4 }, // Add if needed
196
+ prism: {
197
+ theme: catppuccinLatte,
198
+ darkTheme: catppuccinMocha,
199
+ additionalLanguages: ["java", "php", "bash"],
200
+ },
201
+ },
202
+ };
203
+ return siteConfig;
204
+ }
@@ -0,0 +1,26 @@
1
+ import { execSync } from 'child_process';
2
+ import path from 'path';
3
+ import fs from 'fs';
4
+ import { fileURLToPath } from 'url';
5
+ import { createRequire } from 'module';
6
+ import { logger } from '../utils/logger.js';
7
+ const require = createRequire(import.meta.url);
8
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
9
+ export async function buildCommand() {
10
+ logger.info('Building for production...');
11
+ // Resolve path to docusaurus command
12
+ const docusaurusCorePath = path.dirname(require.resolve('@docusaurus/core/package.json'));
13
+ const docusaurusBin = path.join(docusaurusCorePath, 'bin', 'docusaurus.mjs');
14
+ const sourceConfigPath = path.resolve(__dirname, '../../../docusaurus.config.ts');
15
+ const compiledConfigPath = path.resolve(__dirname, '../../../docusaurus.config.js');
16
+ const configPath = fs.existsSync(sourceConfigPath) ? sourceConfigPath : compiledConfigPath;
17
+ try {
18
+ execSync(`node "${docusaurusBin}" build --config "${configPath}"`, {
19
+ stdio: 'inherit',
20
+ });
21
+ }
22
+ catch (error) {
23
+ logger.error(`Build failed: ${error}`);
24
+ process.exit(1);
25
+ }
26
+ }