portosaurus 2.0.2 → 2.1.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.
Files changed (91) hide show
  1. package/bin/portosaurus.mjs +14 -327
  2. package/package.json +16 -11
  3. package/src/cli/build.mjs +43 -0
  4. package/src/cli/dev.mjs +31 -0
  5. package/src/cli/init.mjs +135 -0
  6. package/src/cli/serve.mjs +30 -0
  7. package/src/core/buildDocuConfig.mjs +664 -0
  8. package/src/core/{themePlugin.mjs → plugins/themePlugin.mjs} +1 -1
  9. package/src/template/.github/workflows/deploy.yml +52 -0
  10. package/src/template/.nojekyll +0 -0
  11. package/src/template/README.md +58 -0
  12. package/src/template/blog/authors.yml +1 -1
  13. package/src/template/blog/welcome.md +1 -1
  14. package/src/template/config.js +40 -23
  15. package/src/template/package.json +20 -0
  16. package/src/template/static/img/svg/icon-blog.svg +2 -0
  17. package/src/template/static/img/svg/icon-note.svg +2 -0
  18. package/src/{components → theme/components}/AboutSection/index.js +22 -13
  19. package/src/{components → theme/components}/AboutSection/styles.module.css +59 -48
  20. package/src/{components → theme/components}/ContactSection/index.js +31 -24
  21. package/src/{components → theme/components}/ContactSection/styles.module.css +31 -26
  22. package/src/{components → theme/components}/ExperienceSection/index.js +12 -7
  23. package/src/{components → theme/components}/ExperienceSection/styles.module.css +23 -20
  24. package/src/{components → theme/components}/HeroSection/index.js +9 -11
  25. package/src/{components → theme/components}/HeroSection/styles.module.css +44 -32
  26. package/src/{components → theme/components}/NoteIndex/index.js +10 -3
  27. package/src/{components → theme/components}/Preview/components/PreviewHeader.js +14 -8
  28. package/src/{components → theme/components}/Preview/components/Triggers/Pv.js +32 -7
  29. package/src/{components → theme/components}/Preview/components/Triggers/SrcPv.js +1 -5
  30. package/src/theme/components/Preview/index.js +3 -0
  31. package/src/{components → theme/components}/ProjectsSection/index.js +279 -224
  32. package/src/{components → theme/components}/ProjectsSection/styles.module.css +21 -17
  33. package/src/{components → theme/components}/ScrollToTop/index.js +18 -21
  34. package/src/{components → theme/components}/ScrollToTop/styles.module.css +10 -9
  35. package/src/theme/components/SocialLinks/index.js +125 -0
  36. package/src/{components → theme/components}/SocialLinks/styles.module.css +9 -7
  37. package/src/{components → theme/components}/Tooltip/index.js +4 -1
  38. package/src/theme/config/iconMappings.js +465 -0
  39. package/src/theme/config/metaTags.js +239 -0
  40. package/src/theme/config/prism.js +179 -0
  41. package/src/theme/config/sidebar.js +17 -0
  42. package/src/{css → theme/css}/bootstrap.css +0 -1
  43. package/src/theme/css/catppuccin.css +618 -0
  44. package/src/{css → theme/css}/custom.css +3 -9
  45. package/src/{css → theme/css}/tasks.css +43 -37
  46. package/src/theme/{MDXComponents.js → overrides/MDXComponents.js} +3 -3
  47. package/src/theme/{Root.js → overrides/Root.js} +2 -4
  48. package/src/{pages → theme/pages}/index.js +23 -39
  49. package/src/theme/pages/notes.js +83 -0
  50. package/src/{pages → theme/pages}/tasks.js +115 -56
  51. package/src/{core/client-utils → theme/utils}/HashNavigation.js +60 -49
  52. package/src/{core/client-utils → theme/utils}/updateTitle.js +21 -25
  53. package/src/{core/build-utils → utils/build}/cssUtils.mjs +5 -3
  54. package/src/{core/build-utils → utils/build}/generateFavicon.mjs +44 -12
  55. package/src/{core/build-utils → utils/build}/generateRobotsTxt.mjs +4 -3
  56. package/src/{core/build-utils → utils/build}/iconExtractor.mjs +7 -3
  57. package/src/utils/build/imageDownloader.mjs +159 -0
  58. package/src/{core/build-utils → utils/build}/imageProcessor.mjs +5 -6
  59. package/src/utils/helpers.mjs +153 -0
  60. package/src/utils/logger.mjs +53 -0
  61. package/src/utils/packageManager.mjs +88 -0
  62. package/src/components/Preview/index.js +0 -3
  63. package/src/components/SocialLinks/index.js +0 -130
  64. package/src/config/iconMappings.js +0 -329
  65. package/src/config/metaTags.js +0 -240
  66. package/src/config/prism.js +0 -179
  67. package/src/config/sidebar.js +0 -20
  68. package/src/core/build-utils/imageDownloader.mjs +0 -98
  69. package/src/core/createDocuConf.mjs +0 -490
  70. package/src/core/defaults.mjs +0 -67
  71. package/src/core/logger.mjs +0 -17
  72. package/src/core/packageManager.mjs +0 -72
  73. package/src/css/catppuccin.css +0 -632
  74. package/src/pages/notes.js +0 -87
  75. /package/src/template/notes/{welcome.md → welcome.mdx} +0 -0
  76. /package/src/{components → theme/components}/NoteIndex/styles.module.css +0 -0
  77. /package/src/{components → theme/components}/Preview/components/FeedbackStates.js +0 -0
  78. /package/src/{components → theme/components}/Preview/components/FileTabs.js +0 -0
  79. /package/src/{components → theme/components}/Preview/components/Triggers/index.js +0 -0
  80. /package/src/{components → theme/components}/Preview/components/ViewerWindow.js +0 -0
  81. /package/src/{components → theme/components}/Preview/hooks/useDeepLinkHash.js +0 -0
  82. /package/src/{components → theme/components}/Preview/hooks/useDockLayout.js +0 -0
  83. /package/src/{components → theme/components}/Preview/hooks/useFileFetch.js +0 -0
  84. /package/src/{components → theme/components}/Preview/renderers/CodeRenderer.js +0 -0
  85. /package/src/{components → theme/components}/Preview/renderers/ImageRenderer.js +0 -0
  86. /package/src/{components → theme/components}/Preview/renderers/PdfRenderer.js +0 -0
  87. /package/src/{components → theme/components}/Preview/renderers/WebRenderer.js +0 -0
  88. /package/src/{components → theme/components}/Preview/state/index.js +0 -0
  89. /package/src/{components → theme/components}/Preview/styles.module.css +0 -0
  90. /package/src/{components → theme/components}/Preview/utils/index.js +0 -0
  91. /package/src/{components → theme/components}/Tooltip/styles.module.css +0 -0
@@ -1,490 +0,0 @@
1
- import fs from "fs";
2
- import path from "path";
3
- import { fileURLToPath } from "url";
4
- import { createRequire } from "module";
5
-
6
- import { defaults } from "./defaults.mjs";
7
-
8
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
9
- const portosaurusRoot = path.resolve(__dirname, "../../");
10
-
11
- // ─── Helpers ────────────────────────────────────────────────
12
-
13
- /**
14
- * Deep merge two objects. Source values override target values.
15
- * Arrays are replaced, not concatenated.
16
- */
17
- function deepMerge(target, source) {
18
- const result = { ...target };
19
- for (const key of Object.keys(source)) {
20
- if (
21
- source[key] &&
22
- typeof source[key] === "object" &&
23
- !Array.isArray(source[key]) &&
24
- target[key] &&
25
- typeof target[key] === "object" &&
26
- !Array.isArray(target[key])
27
- ) {
28
- result[key] = deepMerge(target[key], source[key]);
29
- } else if (source[key] !== undefined) {
30
- result[key] = source[key];
31
- }
32
- }
33
- return result;
34
- }
35
-
36
- /**
37
- * Resolve ${...} template references inside config string values.
38
- * Supports nested paths like ${hero_section.profile_pic}.
39
- */
40
- function resolveTemplateStrings(obj, rootConfig) {
41
- if (typeof obj === "string") {
42
- return obj.replace(/\$\{([^}]+)\}/g, (match, refPath) => {
43
- const parts = refPath.split(".");
44
- let val = rootConfig;
45
- for (const p of parts) {
46
- if (val == null || typeof val !== "object") return match;
47
- val = val[p];
48
- }
49
- if (val === undefined) return match;
50
- // Recurse in case the resolved value also has template refs
51
- if (typeof val === "string" && val.includes("${")) {
52
- return resolveTemplateStrings(val, rootConfig);
53
- }
54
- return val;
55
- });
56
- }
57
- if (Array.isArray(obj)) {
58
- return obj.map((item) => resolveTemplateStrings(item, rootConfig));
59
- }
60
- if (obj && typeof obj === "object") {
61
- const result = {};
62
- for (const [key, value] of Object.entries(obj)) {
63
- result[key] = resolveTemplateStrings(value, rootConfig);
64
- }
65
- return result;
66
- }
67
- return obj;
68
- }
69
-
70
- /**
71
- * Resolves the site URL based on config value and environment.
72
- */
73
- function resolveSiteUrl(configValue) {
74
- if (configValue === "auto") {
75
- if (process.env.GITHUB_ACTIONS === "true") {
76
- const repoOwner = process.env.GITHUB_REPOSITORY_OWNER;
77
- return `https://${repoOwner}.github.io`;
78
- }
79
- return "http://localhost";
80
- }
81
- return configValue;
82
- }
83
-
84
- /**
85
- * Resolves the base path based on config value and environment.
86
- */
87
- function resolveBasePath(configValue) {
88
- if (configValue === "auto") {
89
- if (process.env.GITHUB_ACTIONS === "true") {
90
- const repoName = process.env.GITHUB_REPOSITORY?.split("/")[1];
91
- const repoOwner = process.env.GITHUB_REPOSITORY_OWNER;
92
- return repoName === `${repoOwner}.github.io` ? "/" : `/${repoName}/`;
93
- }
94
- return "/";
95
- }
96
- return configValue;
97
- }
98
-
99
- /**
100
- * Read the portosaurus package version.
101
- */
102
- function getVersion() {
103
- try {
104
- const pkgPath = path.resolve(portosaurusRoot, "package.json");
105
- const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
106
- return pkg.version || "0.0.0";
107
- } catch {
108
- return "0.0.0";
109
- }
110
- }
111
-
112
- /**
113
- * Filter items that have enable/value conditional structure.
114
- */
115
- function useEnabled(items) {
116
- if (!Array.isArray(items)) return [];
117
- return items.flatMap((item) => {
118
- if (
119
- item &&
120
- typeof item === "object" &&
121
- "enable" in item &&
122
- "value" in item
123
- ) {
124
- return item.enable === true ? [item.value] : [];
125
- }
126
- return [item];
127
- });
128
- }
129
-
130
- // ─── Main Config Generator ─────────────────────────────────
131
-
132
- /**
133
- * Creates a Docusaurus config from a user's Portosaurus config.
134
- *
135
- * @param {Object} rawUserConfig - The user's config object (export of config.js).
136
- * May be { usrConf: {...} } or just {...}.
137
- * @param {string} projectRoot - Absolute path to the user's project root.
138
- * @returns {Object} Complete Docusaurus configuration object.
139
- */
140
- export function createDocuConf(rawUserConfig, projectRoot) {
141
- // Support both { usrConf: {...} } and direct config objects
142
- const rawConf = rawUserConfig.usrConf || rawUserConfig;
143
-
144
- // Step 1: Deep merge user config over defaults
145
- const merged = deepMerge(defaults, rawConf);
146
-
147
- // Step 2: Resolve template strings (${hero_section.profile_pic} etc.)
148
- const usrConf = resolveTemplateStrings(merged, merged);
149
-
150
- // Step 3: Compute derived values
151
- const siteUrl = resolveSiteUrl(usrConf.site_url);
152
- const basePath = resolveBasePath(usrConf.site_path);
153
- const version = getVersion();
154
-
155
- const projName = usrConf.hero_section?.title || "Portosaurus Site";
156
- const projDesc =
157
- usrConf.hero_section?.description ||
158
- "Complete portfolio solution for your digital personality.";
159
-
160
- // Step 4: Resolve internal paths
161
- const require = createRequire(import.meta.url);
162
-
163
- // Prism themes
164
- let catppuccinMocha, catppuccinLatte;
165
- try {
166
- const prism = require(path.resolve(portosaurusRoot, "src/config/prism.js"));
167
- catppuccinMocha = prism.catppuccinMocha;
168
- catppuccinLatte = prism.catppuccinLatte;
169
- } catch {
170
- catppuccinMocha = {};
171
- catppuccinLatte = {};
172
- }
173
-
174
- // Meta tags
175
- let metaTags = [];
176
- try {
177
- const meta = require(
178
- path.resolve(portosaurusRoot, "src/config/metaTags.js"),
179
- );
180
- metaTags = meta.metaTags || [];
181
- } catch {
182
- // OK — no meta tags
183
- }
184
-
185
- // Paths for content — these point directly to the user's project
186
- const notesPath = path.resolve(projectRoot, "notes");
187
- const blogPath = path.resolve(projectRoot, "blog");
188
-
189
- // Static directories — user's static/ + portosaurus internal static assets
190
- const userStaticDir = path.resolve(projectRoot, "static");
191
- const internalImgDir = path.resolve(portosaurusRoot, "src/assets");
192
- const staticDirectories = [userStaticDir, internalImgDir].filter((d) =>
193
- fs.existsSync(d),
194
- );
195
-
196
- // Pages — served from the portosaurus package
197
- const internalPagesDir = path.resolve(portosaurusRoot, "src/pages");
198
-
199
- // Theme overrides — served from the portosaurus package
200
- const internalThemeDir = path.resolve(portosaurusRoot, "src/theme");
201
-
202
- // Sidebar config
203
- const sidebarPath = path.resolve(portosaurusRoot, "src/config/sidebar.js");
204
-
205
- // CSS
206
- const customCssPath = path.resolve(portosaurusRoot, "src/css/custom.css");
207
-
208
- // ─── Build the Docusaurus config ───────────────────────
209
-
210
- const config = {
211
- projectName: projName,
212
- title: projName,
213
- tagline: projDesc,
214
- favicon: usrConf.favicon || "favicon/favicon.ico",
215
- url: siteUrl,
216
- baseUrl: basePath,
217
-
218
- organizationName: projName,
219
- deploymentBranch: "gh-pages",
220
- onBrokenAnchors: "ignore",
221
- onBrokenLinks: "warn",
222
-
223
- i18n: {
224
- defaultLocale: "en",
225
- locales: ["en"],
226
- },
227
-
228
- headTags: metaTags,
229
-
230
- customFields: {
231
- version,
232
-
233
- heroSection: {
234
- profilePic: usrConf.hero_section?.profile_pic || "img/icon.png",
235
- intro: usrConf.hero_section?.intro || "Hello there, I'm",
236
- title: usrConf.hero_section?.title || "Your Name",
237
- subtitle: usrConf.hero_section?.subtitle || "I am a",
238
- profession: usrConf.hero_section?.profession || "Your Profession",
239
- description:
240
- usrConf.hero_section?.description ||
241
- "Short description about your profession, passion, goals.",
242
- learnMoreButtonTxt:
243
- usrConf.hero_section?.learn_more_button_txt || "Learn More",
244
- },
245
-
246
- aboutMe: {
247
- enable: usrConf.about_me?.enable ?? true,
248
- image:
249
- usrConf.about_me?.image ||
250
- usrConf.hero_section?.profile_pic ||
251
- "img/icon.png",
252
- description:
253
- usrConf.about_me?.description || defaults.about_me.description,
254
- skills: usrConf.about_me?.skills || defaults.about_me.skills,
255
- resumeLink: usrConf.about_me?.resume_link || "",
256
- },
257
-
258
- projects: usrConf.project_shelf || defaults.project_shelf,
259
- experience: usrConf.experience || defaults.experience,
260
-
261
- socialLinks: {
262
- enable: usrConf.social_links?.enable ?? true,
263
- links: usrConf.social_links?.links || [],
264
- },
265
-
266
- robotsTxt: {
267
- enable: usrConf.robots_txt ?? true,
268
- rules: [{ disallow: ["/notes/", "/tasks/"] }],
269
- customLines: [],
270
- },
271
-
272
- tasksPage: {
273
- enable: usrConf.tasks_page?.enable ?? false,
274
- title: usrConf.tasks_page?.title || "Tasks",
275
- description:
276
- usrConf.tasks_page?.description ||
277
- "Track your tasks and projects here.",
278
- taskList: usrConf.tasks_page?.tasks || [],
279
- },
280
-
281
- corsProxyList: [
282
- usrConf.cors_proxy,
283
- "https://api.allorigins.win/raw?url=",
284
- ].filter(Boolean),
285
- },
286
-
287
- presets: [
288
- [
289
- require.resolve("@docusaurus/preset-classic"),
290
- {
291
- docs: {
292
- routeBasePath: "notes",
293
- path: notesPath,
294
- sidebarPath,
295
- admonitions: {
296
- keywords: [
297
- "note",
298
- "tip",
299
- "info",
300
- "warning",
301
- "danger",
302
- "question",
303
- ],
304
- extendDefaults: true,
305
- },
306
- },
307
- blog: {
308
- path: blogPath,
309
- feedOptions: usrConf.rss
310
- ? { type: ["rss", "atom"], xslt: true }
311
- : undefined,
312
- showReadingTime: false,
313
- onInlineTags: "warn",
314
- onInlineAuthors: "warn",
315
- onUntruncatedBlogPosts: "warn",
316
- },
317
- theme: {
318
- customCss: customCssPath,
319
- },
320
- pages: {
321
- path: internalPagesDir,
322
- },
323
- },
324
- ],
325
- ],
326
-
327
- // Register portosaurus's src/ as a theme directory
328
- // so Root.js, components, and pages are all natively transpiled by Docusaurus.
329
- themes: [
330
- [
331
- path.resolve(portosaurusRoot, "src/core/themePlugin.mjs"),
332
- { themeDir: path.resolve(portosaurusRoot, "src") },
333
- ],
334
- ],
335
-
336
- markdown: {
337
- mermaid: true,
338
- hooks: {
339
- onBrokenMarkdownLinks: "warn",
340
- },
341
- },
342
-
343
- themeConfig: {
344
- image: usrConf.social_card || "img/social-card.jpeg",
345
- docs: {
346
- sidebar: {
347
- hideable: usrConf.collapsable_sidebar ?? true,
348
- },
349
- },
350
- imageZoom: {
351
- options: {
352
- margin: 2,
353
- background: "rgba(var(--ifm-background-color-rgb), 0.9)",
354
- },
355
- },
356
- colorMode: {
357
- defaultMode: usrConf.dark_mode ? "dark" : "light",
358
- disableSwitch: usrConf.disable_theme_switch || false,
359
- },
360
- navbar: {
361
- title: projName,
362
- hideOnScroll: usrConf.hide_navbar_on_scroll ?? true,
363
- logo: {
364
- alt: "Site Logo",
365
- src: usrConf.favicon || "favicon/favicon.ico",
366
- },
367
- items: useEnabled([
368
- {
369
- type: "search",
370
- position: "right",
371
- className: "navbar-search-bar",
372
- },
373
- {
374
- enable: usrConf.about_me?.enable ?? true,
375
- value: {
376
- label: "About Me",
377
- to: "/#about",
378
- position: "right",
379
- activeBaseRegex: "^/#about",
380
- },
381
- },
382
- {
383
- enable: usrConf.project_shelf?.enable ?? true,
384
- value: {
385
- label: "Projects",
386
- to: "/#projects",
387
- position: "right",
388
- activeBaseRegex: "^/#projects",
389
- },
390
- },
391
- {
392
- enable: usrConf.experience?.enable ?? false,
393
- value: {
394
- label: "Experience",
395
- to: "/#experience",
396
- position: "right",
397
- activeBaseRegex: "^/#experience",
398
- },
399
- },
400
- {
401
- enable: usrConf.social_links?.enable ?? true,
402
- value: {
403
- label: "Contact",
404
- to: "/#contact",
405
- position: "right",
406
- activeBaseRegex: "^/$contact",
407
- },
408
- },
409
- {
410
- type: "dropdown",
411
- label: "More",
412
- position: "right",
413
- className: "_navbar-more-items",
414
- items: useEnabled([
415
- { label: "Notes", to: "/notes" },
416
- { label: "Blog", to: "/blog" },
417
- {
418
- enable: usrConf.tasks_page?.enable ?? false,
419
- value: { label: "Tasks", to: "/tasks" },
420
- },
421
- {
422
- enable: !usrConf.disable_branding,
423
- value: {
424
- label: `Portosaurus v${version}`,
425
- className: "_nav-protosaurus-version",
426
- to: "https://github.com/soymadip/portosaurus",
427
- },
428
- },
429
- ]),
430
- },
431
- ]),
432
- },
433
- tableOfContents: {
434
- minHeadingLevel: 2,
435
- maxHeadingLevel: 4,
436
- },
437
- prism: {
438
- theme: catppuccinLatte,
439
- darkTheme: catppuccinMocha,
440
- additionalLanguages: ["java", "php", "bash"],
441
- },
442
- footer: {},
443
- },
444
-
445
- plugins: [
446
- function portosaurusWebpackTranspiler() {
447
- return {
448
- name: "portosaurus-transpile",
449
- configureWebpack(config) {
450
- if (config.module && config.module.rules) {
451
- console.log(
452
- JSON.stringify(
453
- config.module.rules,
454
- (k, v) => (typeof v === "function" ? v.toString() : v),
455
- 2,
456
- ),
457
- );
458
- process.exit(1);
459
- }
460
- return config;
461
- },
462
- };
463
- },
464
- path.resolve(portosaurusRoot, "src/core/build-utils/generateFavicon.mjs"),
465
- path.resolve(
466
- portosaurusRoot,
467
- "src/core/build-utils/generateRobotsTxt.mjs",
468
- ),
469
- [
470
- require.resolve("@easyops-cn/docusaurus-search-local"),
471
- {
472
- hashed: true,
473
- indexDocs: true,
474
- docsDir: notesPath,
475
- docsRouteBasePath: "notes",
476
- highlightSearchTermsOnTargetPage: true,
477
- explicitSearchResultPath: true,
478
- hideSearchBarWithNoSearchContext: true,
479
- searchContextByPaths: ["notes", "blog"],
480
- language: ["en"],
481
- },
482
- ],
483
- "plugin-image-zoom",
484
- ],
485
-
486
- staticDirectories,
487
- };
488
-
489
- return config;
490
- }
@@ -1,67 +0,0 @@
1
- /**
2
- * Internal default configuration for Portosaurus.
3
- * These values are used when the user's config.js does not provide them.
4
- * The user's config is deep-merged on top of these defaults.
5
- */
6
- export const defaults = {
7
- dark_mode: true,
8
- site_url: "auto",
9
- site_path: "auto",
10
- robots_txt: true,
11
- social_card: "img/social-card.jpeg",
12
- collapsable_sidebar: true,
13
- hide_navbar_on_scroll: true,
14
- disable_theme_switch: false,
15
- rss: true,
16
- cors_proxy: "https://cors-proxy.soymadip.workers.dev/?url=",
17
-
18
- hero_section: {
19
- title: "Your Name",
20
- intro: "Hello there, I'm",
21
- subtitle: "I am a",
22
- profession: "Your Profession",
23
- description:
24
- "Short description about your profession, passion, goals.",
25
- learn_more_button_txt: "Learn More",
26
- profile_pic: "img/icon.png",
27
- },
28
-
29
- about_me: {
30
- enable: true,
31
- image: null, // Falls back to hero_section.profile_pic
32
- description: [
33
- "I'm a passionate developer with expertise in designing and building solutions for real-world problems.",
34
- "My journey in software development started with a simple desire to automate repetitive tasks.",
35
- ],
36
- skills: ["Skill 1", "Skill 2"],
37
- resume_link: "",
38
- },
39
-
40
- project_shelf: {
41
- enable: true,
42
- projects: [],
43
- },
44
-
45
- experience: {
46
- enable: false,
47
- list: [],
48
- },
49
-
50
- social_links: {
51
- enable: true,
52
- links: [],
53
- },
54
-
55
- tasks_page: {
56
- enable: false,
57
- title: "Tasks",
58
- description: "Track your tasks and projects here.",
59
- tasks: [],
60
- },
61
-
62
- link_shortener: {
63
- enable: false,
64
- deploy_path: "/l",
65
- short_links: {},
66
- },
67
- };
@@ -1,17 +0,0 @@
1
- /**
2
- * CLI Logging Utility (ESM)
3
- */
4
- import chalk from "chalk";
5
-
6
- export const logger = {
7
- info: (msg) => console.log(chalk.blue("ℹ ") + msg),
8
- success: (msg) => console.log(chalk.green("✔ ") + msg),
9
- warn: (msg) => console.log(chalk.yellow("⚠ ") + msg),
10
- error: (msg) => console.error(chalk.red("✘ ") + msg),
11
- debug: (msg) => {
12
- if (process.env.DEBUG || process.argv.includes("--debug")) {
13
- console.log(chalk.gray("⚙ " + msg));
14
- }
15
- },
16
- tip: (msg) => console.log(chalk.magenta("💡 ") + msg),
17
- };
@@ -1,72 +0,0 @@
1
- /**
2
- * Package manager detection and CLI utility (ESM)
3
- */
4
- import fs from "fs";
5
- import path from "path";
6
-
7
- export function detectPackageManager(projectRoot) {
8
- // Always prioritize bun if it's in the environment
9
- // or if bun.lockb / bun.lock exists
10
- if (
11
- fs.existsSync(path.join(projectRoot, "bun.lockb")) ||
12
- fs.existsSync(path.join(projectRoot, "bun.lock"))
13
- )
14
- return "bun";
15
-
16
- // Check common lockfiles
17
- if (fs.existsSync(path.join(projectRoot, "pnpm-lock.yaml"))) return "pnpm";
18
- if (fs.existsSync(path.join(projectRoot, "yarn.lock"))) return "yarn";
19
- if (fs.existsSync(path.join(projectRoot, "package-lock.json"))) return "npm";
20
-
21
- if (process.env.npm_config_user_agent) {
22
- if (process.env.npm_config_user_agent.includes("bun")) return "bun";
23
- if (process.env.npm_config_user_agent.includes("pnpm")) return "pnpm";
24
- if (process.env.npm_config_user_agent.includes("yarn")) return "yarn";
25
- }
26
- if (
27
- typeof process !== "undefined" &&
28
- process.versions &&
29
- process.versions.bun
30
- )
31
- return "bun";
32
-
33
- return "npm";
34
- }
35
-
36
- export function getInstallCommand(pm) {
37
- switch (pm) {
38
- case "bun":
39
- return "bun install";
40
- case "pnpm":
41
- return "pnpm install";
42
- case "yarn":
43
- return "yarn install";
44
- default:
45
- return "npm install";
46
- }
47
- }
48
-
49
- export function findDocusaurusBin(projectRoot) {
50
- const pm = detectPackageManager(projectRoot);
51
-
52
- // Check for node_modules/.bin/docusaurus
53
- const localDocusaurus = path.join(
54
- projectRoot,
55
- "node_modules",
56
- ".bin",
57
- "docusaurus",
58
- );
59
-
60
- if (fs.existsSync(localDocusaurus)) {
61
- if (pm === "bun") {
62
- return { command: "bun", args: ["docusaurus"], packageManager: pm };
63
- }
64
- const command = pm === "npm" ? "npm" : pm;
65
- const args = pm === "npm" ? ["run", "docusaurus", "--"] : ["docusaurus"];
66
- return { command, args, packageManager: pm };
67
- }
68
-
69
- // Fallback to npx/bunx if not found locally
70
- const command = pm === "bun" ? "bunx" : "npx";
71
- return { command, args: ["docusaurus"], packageManager: pm };
72
- }