portosaurus 1.16.0 → 1.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -57,25 +57,34 @@ async function prepareDocusaurusRun(projectRoot) {
57
57
 
58
58
  // Ensure internal files are synced to .portosaurus
59
59
  const internalDir = path.join(__dirname, "../src/internal");
60
- const dotPorto = path.join(projectRoot, ".portosaurus");
60
+ const runtimeDir = path.join(projectRoot, ".portosaurus");
61
61
 
62
62
  // Ensure .portosaurus exists and is clean
63
- fs.emptyDirSync(dotPorto);
63
+ fs.emptyDirSync(runtimeDir);
64
+
65
+ // Ensure user has essential folders in project root
66
+ fs.ensureDirSync(path.join(projectRoot, "notes"));
67
+ fs.ensureDirSync(path.join(projectRoot, "blog"));
68
+ fs.ensureDirSync(path.join(projectRoot, "static"));
64
69
 
65
70
  // 1. Copy everything from internal to .portosaurus
66
- fs.copySync(internalDir, dotPorto);
71
+ fs.copySync(internalDir, runtimeDir);
67
72
 
68
73
  // 2. Overwrite with user files if they exist in project root
69
- const internalFiles = readdirSync(internalDir);
70
-
71
- for (const file of internalFiles) {
72
- const userFile = path.join(projectRoot, file);
74
+ const syncItems = [
75
+ ...new Set([...readdirSync(internalDir), "blog", "static"]),
76
+ ];
77
+ for (const file of syncItems) {
78
+ const userFile = path.resolve(projectRoot, file);
79
+ const destFile = path.resolve(runtimeDir, file);
73
80
 
74
81
  if (existsSync(userFile)) {
75
- fs.copySync(userFile, path.join(dotPorto, file), {
82
+ if (fs.statSync(userFile).isDirectory()) {
83
+ fs.ensureDirSync(destFile);
84
+ }
85
+ fs.copySync(userFile, destFile, {
76
86
  overwrite: true,
77
87
  filter: (src) => {
78
- // Ignore notes/index.md
79
88
  if (src.endsWith(path.join("notes", "index.md"))) {
80
89
  return false;
81
90
  }
@@ -85,15 +94,6 @@ async function prepareDocusaurusRun(projectRoot) {
85
94
  }
86
95
  }
87
96
 
88
- // Ensure user has essential folders
89
- const userRootNotes = path.join(projectRoot, "notes");
90
- const userRootBlog = path.join(projectRoot, "blog");
91
- const userRootStatic = path.join(projectRoot, "static");
92
-
93
- fs.ensureDirSync(userRootNotes);
94
- fs.ensureDirSync(userRootBlog);
95
- fs.ensureDirSync(userRootStatic);
96
-
97
97
  // Load user config
98
98
  const require = createRequire(import.meta.url);
99
99
 
@@ -120,7 +120,7 @@ async function prepareDocusaurusRun(projectRoot) {
120
120
  const docusaurusConfig = createConfig(userConfig, projectRoot);
121
121
 
122
122
  // Write temp config file INSIDE .portosaurus
123
- const tempConfigPath = path.join(dotPorto, "docusaurus.config.js");
123
+ const tempConfigPath = path.join(runtimeDir, "docusaurus.config.js");
124
124
 
125
125
  const configContent = `// Auto-generated by Portosaurus
126
126
  module.exports = ${JSON.stringify(docusaurusConfig, null, 2)};`;
@@ -128,10 +128,10 @@ module.exports = ${JSON.stringify(docusaurusConfig, null, 2)};`;
128
128
  writeFileSync(tempConfigPath, configContent);
129
129
  logger.success("Generated Docusaurus config in .portosaurus.");
130
130
 
131
- return { dotPorto };
131
+ return { runtimeDir };
132
132
  }
133
133
 
134
- async function runDocusaurus(command, args, dotPorto, projectRoot) {
134
+ async function runDocusaurus(command, args, runtimeDir, projectRoot) {
135
135
  // Detect package manager and find docusaurus binary
136
136
  const { findDocusaurusBin } = await import("../src/utils/packageManager.js");
137
137
  const docusaurus = findDocusaurusBin(projectRoot || process.cwd());
@@ -142,7 +142,7 @@ async function runDocusaurus(command, args, dotPorto, projectRoot) {
142
142
 
143
143
  const child = spawn(
144
144
  docusaurus.command,
145
- [...docusaurus.args, command, dotPorto, ...args],
145
+ [...docusaurus.args, command, runtimeDir, ...args],
146
146
  {
147
147
  stdio: "inherit",
148
148
  cwd: projectRoot,
@@ -302,8 +302,6 @@ program
302
302
  }
303
303
  });
304
304
 
305
-
306
-
307
305
  // --- START COMMAND ---
308
306
 
309
307
  program
@@ -314,8 +312,8 @@ program
314
312
  const projectRoot = process.cwd();
315
313
  logger.info("Starting development server...");
316
314
  try {
317
- const { dotPorto } = await prepareDocusaurusRun(projectRoot);
318
- await runDocusaurus("start", [], dotPorto, projectRoot);
315
+ const { runtimeDir } = await prepareDocusaurusRun(projectRoot);
316
+ await runDocusaurus("start", [], runtimeDir, projectRoot);
319
317
  } catch (error) {
320
318
  logger.error(`Failed to start: ${error.message}`);
321
319
  process.exit(1);
@@ -334,12 +332,12 @@ program
334
332
  logger.info("Building Portosaurus site...");
335
333
 
336
334
  try {
337
- const { dotPorto } = await prepareDocusaurusRun(projectRoot);
335
+ const { runtimeDir } = await prepareDocusaurusRun(projectRoot);
338
336
 
339
337
  const buildDir = path.join(projectRoot, "build");
340
338
  const args = ["--out-dir", buildDir];
341
339
 
342
- await runDocusaurus("build", args, dotPorto, projectRoot);
340
+ await runDocusaurus("build", args, runtimeDir, projectRoot);
343
341
 
344
342
  // Create .nojekyll for GitHub Pages compatibility
345
343
  const nojekyllPath = path.join(buildDir, ".nojekyll");
@@ -368,7 +366,7 @@ program
368
366
  logger.info("Serving Portosaurus site...");
369
367
 
370
368
  try {
371
- const { dotPorto } = await prepareDocusaurusRun(projectRoot);
369
+ const { runtimeDir } = await prepareDocusaurusRun(projectRoot);
372
370
  const buildDir = path.join(projectRoot, "build");
373
371
 
374
372
  if (!existsSync(buildDir)) {
@@ -378,7 +376,12 @@ program
378
376
  process.exit(1);
379
377
  }
380
378
 
381
- await runDocusaurus("serve", ["--dir", buildDir], dotPorto, projectRoot);
379
+ await runDocusaurus(
380
+ "serve",
381
+ ["--dir", buildDir],
382
+ runtimeDir,
383
+ projectRoot,
384
+ );
382
385
  } catch (error) {
383
386
  logger.error(`Failed to serve: ${error.message}`);
384
387
  process.exit(1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "portosaurus",
3
- "version": "1.16.0",
3
+ "version": "1.16.1",
4
4
  "author": "soymadip",
5
5
  "license": "GPL-3.0-only",
6
6
  "description": "Complete portfolio cum personal website solution for your digital personality.",
@@ -5,9 +5,11 @@ import { fileURLToPath } from "url";
5
5
 
6
6
  const require = createRequire(import.meta.url);
7
7
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
8
-
9
8
  const internalUtils = path.resolve(__dirname, "../internal/src/utils");
10
9
 
10
+
11
+ //---------------------- helpers -------------------------
12
+
11
13
  /**
12
14
  * Resolves the site URL based on config value and environment.
13
15
  * @param {string} configValue - The site_url value from user config.
@@ -43,12 +45,15 @@ function resolveBasePath(configValue) {
43
45
  return configValue;
44
46
  }
45
47
 
48
+ //--------------------- Config Creation ---------------------
49
+
46
50
  /**
47
51
  * Creates a Docusaurus config from the Portosaurus user config.
48
52
  * @param {Object} userConfig - The user configuration object (export of config.js).
49
53
  * @returns {Object} Docusaurus configuration object.
50
54
  **/
51
55
  export function createConfig(userConfig, projectRoot = process.cwd()) {
56
+
52
57
  const usrConf = userConfig.usrConf || {};
53
58
 
54
59
  //------------- Basic mapping -------------
@@ -63,14 +68,11 @@ export function createConfig(userConfig, projectRoot = process.cwd()) {
63
68
  const faviconPath =
64
69
  usrConf.hero_section?.profile_pic || "https://github.com/soymadip.png";
65
70
 
66
- const title = usrConf.hero_section?.title || projName;
67
- const tagline = usrConf.hero_section?.description || projDesc;
68
-
69
71
  // Resolve paths relative to .portosaurus (the build context)
70
- const dotPorto = path.resolve(projectRoot, ".portosaurus");
71
- const notesPath = path.resolve(dotPorto, "notes");
72
- const blogPath = path.resolve(dotPorto, "blog");
73
- const staticPath = path.resolve(dotPorto, "static");
72
+ const runtimeDir = path.resolve(projectRoot, ".portosaurus");
73
+ const notesPath = path.resolve(runtimeDir, "notes");
74
+ const blogPath = path.resolve(runtimeDir, "blog");
75
+ const staticPath = path.resolve(runtimeDir, "static");
74
76
 
75
77
  // ---------- Docusaurus Config -----------
76
78
  const config = {
@@ -210,8 +212,8 @@ export function createConfig(userConfig, projectRoot = process.cwd()) {
210
212
  {
211
213
  hashed: true,
212
214
  indexDocs: true,
213
- docsDir: notesPath,
214
- blogDir: blogPath,
215
+ docsDir: "notes",
216
+ blogDir: "blog",
215
217
  docsRouteBasePath: "notes",
216
218
  highlightSearchTermsOnTargetPage: true,
217
219
  explicitSearchResultPath: true,
@@ -0,0 +1,294 @@
1
+ import { catppuccinMocha, catppuccinLatte } from "./src/config/prism.js";
2
+ import { appVersion } from "./src/utils/appVersion.js";
3
+ import { metaTags } from "./src/config/metaTags.js";
4
+ import { usrConf } from "./src/utils/compileConfig.js";
5
+ import { useEnabled } from "./src/utils/filterEnabledItems.js";
6
+
7
+ const projectName = "Portosaurus";
8
+ const projectVersion = appVersion();
9
+ const faviconPath = 'favicon/favicon.ico';
10
+ const iconPicPath = 'static/img/icon.png';
11
+
12
+ const config = {
13
+
14
+ projectName: `${projectName}`,
15
+
16
+ title: usrConf.hero_section.title || `${projectName}`,
17
+
18
+ tagline: usrConf.hero_section.tagline || "Your complete portfolio solution",
19
+
20
+ favicon: usrConf.favicon || `${faviconPath}`,
21
+
22
+ url: usrConf.site_url,
23
+ baseUrl: usrConf.site_path || "/",
24
+
25
+ // GH Pages config
26
+ organizationName: usrConf.hero_section.title || `${projectName} `,
27
+ deploymentBranch: "gh-pages",
28
+
29
+ onBrokenAnchors: "ignore",
30
+ onBrokenLinks: "warn",
31
+ // onBrokenMarkdownLinks: "warn",
32
+
33
+ i18n: {
34
+ defaultLocale: "en",
35
+ locales: ["en"],
36
+ },
37
+
38
+ headTags: metaTags,
39
+
40
+ customFields: {
41
+ version: `${projectVersion}`,
42
+
43
+ heroSection: {
44
+ profilePic: usrConf.hero_section.profile_pic || `${iconPicPath}`,
45
+ intro: usrConf.hero_section.intro || "Hello there, I'm",
46
+ title: usrConf.hero_section.title || "Your Name",
47
+ subtitle: usrConf.hero_section.subtitle || 'I am a',
48
+ profession: usrConf.hero_section.profession || 'Your Profession',
49
+ description: usrConf.hero_section.description || "Short description about your profession, passion, goals.",
50
+ learnMoreButtonTxt: usrConf.hero_section.learn__more_button_txt || "Learn More",
51
+ },
52
+
53
+ aboutMe: {
54
+ enable: usrConf.about_me.enable || true,
55
+
56
+ image: usrConf.about_me.image || `${iconPicPath}`,
57
+ description: usrConf.about_me.description || [
58
+ "I'm a passionate FOSS developer with expertise in designing and building solutions for real-world problems.",
59
+ "My journey in software development started with a simple desire to automate repetitive tasks, specially in my PC.",
60
+ ],
61
+ skills: usrConf.about_me.skills || ["skill 1", "Skill 2"],
62
+ resumeLink: usrConf.about_me.resume_link || "https://example.com/resume",
63
+ },
64
+
65
+ projects: usrConf.project_shelf,
66
+
67
+ experience: usrConf.experience,
68
+
69
+ socialLinks: {
70
+ enable: usrConf.social_links.enable || true,
71
+
72
+ links: usrConf.social_links.links || [
73
+ {
74
+ name: "Your Instagram",
75
+ icon: "instagram",
76
+ desc: "Your Instagram profile link",
77
+ url: "https://instagram.com/yourprofile",
78
+ },
79
+ ],
80
+ },
81
+
82
+ robotsTxt: {
83
+ enable: usrConf.robots_txt || true,
84
+ rules: [
85
+ {
86
+ disallow: ["/notes/", "/tasks/"],
87
+ },
88
+ ],
89
+ customLines: [],
90
+ },
91
+
92
+ tasksPage: {
93
+ enable: usrConf.tasks_page.enable || true,
94
+ title: usrConf.tasks_page.title || "Tasks",
95
+ description: usrConf.tasks_page.description || "Track your tasks and projects here.",
96
+ taskList: usrConf.tasks_page.tasks || [
97
+ {
98
+ title: "Example Tasks",
99
+ description: "Description of the task",
100
+ status: "active",
101
+ priority: "high",
102
+ },
103
+ ],
104
+ },
105
+ },
106
+
107
+ presets: [
108
+ [
109
+ "classic",
110
+ {
111
+ docs: {
112
+ routeBasePath: "notes",
113
+ path: "notes",
114
+ sidebarPath: "./src/config/sidebar.js",
115
+
116
+ admonitions: {
117
+ keywords: ["note", "tip", "info", "warning", "danger", "question"],
118
+ extendDefaults: true,
119
+ },
120
+ },
121
+
122
+ blog: {
123
+
124
+ feedOptions: usrConf.rss
125
+ ? {
126
+ type: ["rss", "atom"],
127
+ xslt: true,
128
+ }
129
+ : undefined,
130
+
131
+ showReadingTime: false,
132
+
133
+ onInlineTags: "warn",
134
+ onInlineAuthors: "warn",
135
+ onUntruncatedBlogPosts: "warn",
136
+ },
137
+
138
+ theme: {
139
+ customCss: "./src/css/custom.css",
140
+ },
141
+
142
+ },
143
+ ],
144
+ ],
145
+
146
+ // themes: ['@docusaurus/theme-mermaid'],
147
+ markdown: {
148
+ mermaid: true,
149
+ hooks: {
150
+ onBrokenMarkdownLinks: "warn"
151
+ }
152
+ },
153
+
154
+ themeConfig: {
155
+ // Social card
156
+ image: usrConf.social_card || "img/social-card.jpeg",
157
+
158
+ docs: {
159
+ sidebar: {
160
+ hideable: usrConf.collapsable_sidebar || true,
161
+ },
162
+ },
163
+
164
+ imageZoom: {
165
+ options: {
166
+ margin: 2,
167
+ background: "rgba(var(--ifm-background-color-rgb), 0.9)",
168
+ },
169
+ },
170
+
171
+ // Default: Dark mode
172
+ colorMode: {
173
+ defaultMode: usrConf.dark_mode ? "dark" : "light",
174
+ disableSwitch: usrConf.disable_theme_switch || false,
175
+ },
176
+
177
+ navbar: {
178
+ title: usrConf.hero_section.title || `${projectName} `,
179
+ hideOnScroll: usrConf.hide_navbar_on_scroll || true,
180
+
181
+ logo: {
182
+ alt: "Site Logo",
183
+ src: usrConf.favicon || `${faviconPath}`,
184
+ },
185
+
186
+ items: useEnabled([
187
+ {
188
+ type: "search",
189
+ position: "right",
190
+ className: "navbar-search-bar",
191
+ },
192
+ {
193
+ enable: usrConf.about_me?.enable || true,
194
+ value: {
195
+ label: "About Me",
196
+ to: "/#about",
197
+ position: "right",
198
+ activeBaseRegex: "^/#about",
199
+ },
200
+ },
201
+ {
202
+ enable: usrConf.project_shelf?.enable || true,
203
+ value: {
204
+ label: "Projects",
205
+ to: "/#projects",
206
+ position: "right",
207
+ activeBaseRegex: "^/#projects",
208
+ },
209
+ },
210
+ {
211
+ enable: usrConf.experience?.enable || false,
212
+ value: {
213
+ label: "Experience",
214
+ to: "/#experience",
215
+ position: "right",
216
+ activeBaseRegex: "^/#experience",
217
+ },
218
+ },
219
+ {
220
+ enable: usrConf.social_links?.enable || true,
221
+ value: {
222
+ label: "Contact",
223
+ to: "/#contact",
224
+ position: "right",
225
+ activeBaseRegex: "^/$contact",
226
+ },
227
+ },
228
+ {
229
+ type: "dropdown",
230
+ label: "More",
231
+ position: "right",
232
+ className: "_navbar-more-items",
233
+ items: useEnabled([
234
+ { label: "Notes", to: "/notes" },
235
+ { label: "Blog", to: "/blog" },
236
+ { label: "Tasks", to: "/tasks" },
237
+ {
238
+ enable: usrConf.disable_branding ? false : true,
239
+ value: {
240
+ label: `Portosaurus v${projectVersion}`,
241
+ className: "_nav-protosaurus-version",
242
+ to: "https://github.com/soymadip/portosaurus",
243
+ },
244
+ },
245
+ ]),
246
+ }
247
+ ]),
248
+ },
249
+
250
+ tableOfContents: {
251
+ minHeadingLevel: 2,
252
+ maxHeadingLevel: 4,
253
+ },
254
+
255
+ prism: {
256
+ theme: catppuccinLatte,
257
+ darkTheme: catppuccinMocha,
258
+ additionalLanguages: ["java", "php", "bash"],
259
+ },
260
+
261
+ footer: {
262
+ /* links: [
263
+ {
264
+ label: 'GitHub',
265
+ href: 'https://github.com/',
266
+ }
267
+ ],
268
+ copyright: `Copyright © ${new Date().getFullYear()} ` + ownerName,
269
+ */
270
+ },
271
+ },
272
+
273
+ plugins: [
274
+ require.resolve("./src/utils/generateFavicon"),
275
+ require.resolve("./src/utils/generateRobotsTxt"),
276
+ [
277
+ require.resolve("@easyops-cn/docusaurus-search-local"),
278
+ {
279
+ hashed: true,
280
+ indexDocs: true,
281
+ docsDir: "notes",
282
+ docsRouteBasePath: "notes",
283
+ highlightSearchTermsOnTargetPage: true,
284
+ explicitSearchResultPath: true,
285
+ hideSearchBarWithNoSearchContext: true,
286
+ searchContextByPaths: ["notes", "blog"],
287
+ language: ["en"],
288
+ },
289
+ ],
290
+ "plugin-image-zoom",
291
+ ],
292
+ };
293
+
294
+ export default config;