ghost-github-portfolio 0.3.4 → 0.4.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.
package/dist/github.js CHANGED
@@ -9,9 +9,9 @@ function headers(token) {
9
9
  h.Authorization = `Bearer ${token}`;
10
10
  return h;
11
11
  }
12
- export async function fetchRepos(config, verbose = false) {
12
+ /** Fetch every public repo the user owns, unfiltered. */
13
+ export async function fetchAllRepos(config, verbose = false) {
13
14
  const { username, token } = config.github;
14
- const { minStars, maxRepos, excludeRepos, includeForked } = config.portfolio;
15
15
  const allRepos = [];
16
16
  let page = 1;
17
17
  const perPage = 100;
@@ -41,97 +41,125 @@ export async function fetchRepos(config, verbose = false) {
41
41
  break;
42
42
  page++;
43
43
  }
44
+ return allRepos;
45
+ }
46
+ export function isAwesomeList(repo) {
47
+ return (repo.name.toLowerCase().startsWith("awesome") ||
48
+ repo.topics.includes("awesome-list"));
49
+ }
50
+ /**
51
+ * Apply every filter, sort by stars and only then cut to maxRepos, so an
52
+ * excluded repo never takes a slot.
53
+ */
54
+ export function selectRepos(repos, config) {
55
+ const { minStars, maxRepos, excludeRepos, includeForked, includeArchived, excludeAwesomeLists, } = config.portfolio;
44
56
  const excludeSet = new Set(excludeRepos.map((r) => r.toLowerCase()));
45
- return allRepos
57
+ const patterns = config.github.excludePatterns.map((p) => new RegExp(p, "i"));
58
+ return repos
46
59
  .filter((r) => r.stargazers_count >= minStars)
47
60
  .filter((r) => includeForked || !r.fork)
61
+ .filter((r) => includeArchived || !r.archived)
48
62
  .filter((r) => !excludeSet.has(r.name.toLowerCase()))
49
63
  .filter((r) => !config.portfolio.repos[r.name]?.exclude)
64
+ .filter((r) => !patterns.some((p) => p.test(r.name)))
65
+ .filter((r) => !excludeAwesomeLists || !isAwesomeList(r))
50
66
  .sort((a, b) => b.stargazers_count - a.stargazers_count)
51
67
  .slice(0, maxRepos);
52
68
  }
53
- const BANNER_CANDIDATES = [
54
- "docs/images/banner.svg",
55
- "docs/images/banner.png",
56
- "media/banner.svg",
57
- "media/banner.png",
58
- "assets/banner.svg",
59
- "assets/banner.png",
60
- "banner.svg",
61
- "banner.png",
62
- ];
63
- export async function detectBanner(repo, config) {
64
- if (!config.portfolio.showBanner)
65
- return null;
66
- try {
67
- const { username } = config.github;
68
- const branch = repo.default_branch;
69
- // Config override for this specific repo
70
- const overridePath = config.portfolio.repos[repo.name]?.bannerPath ??
71
- config.portfolio.bannerPaths[repo.name];
72
- if (overridePath) {
73
- const url = `https://raw.githubusercontent.com/${username}/${repo.name}/${branch}/${overridePath}`;
74
- if (await urlExists(url))
75
- return url;
76
- }
77
- // Try default path
78
- const defaultUrl = `https://raw.githubusercontent.com/${username}/${repo.name}/${branch}/${config.portfolio.defaultBannerPath}`;
79
- if (await urlExists(defaultUrl))
80
- return defaultUrl;
81
- // Try candidates
82
- for (const candidate of BANNER_CANDIDATES) {
83
- if (candidate === config.portfolio.defaultBannerPath)
69
+ /**
70
+ * List every reference in an SVG that a browser would have to load from
71
+ * somewhere else. Inside an `<img>` those are never loaded, so the banner
72
+ * renders blank or broken. `#id` and `data:` references are fine.
73
+ */
74
+ export function findExternalRefs(svg) {
75
+ const refs = [];
76
+ const attr = /\b(?:xlink:)?href\s*=\s*(?:"([^"]*)"|'([^']*)')/gi;
77
+ const cssUrl = /url\(\s*(?:"([^"]*)"|'([^']*)'|([^)"'\s]*))\s*\)/gi;
78
+ const cssImport = /@import\s+(?:"([^"]*)"|'([^']*)')/gi;
79
+ for (const re of [attr, cssUrl, cssImport]) {
80
+ for (const m of svg.matchAll(re)) {
81
+ const value = (m[1] ?? m[2] ?? m[3] ?? "").trim();
82
+ if (value === "" || value.startsWith("#") || /^data:/i.test(value))
84
83
  continue;
85
- const url = `https://raw.githubusercontent.com/${username}/${repo.name}/${branch}/${candidate}`;
86
- if (await urlExists(url))
87
- return url;
84
+ refs.push(value);
88
85
  }
89
- return null;
90
86
  }
91
- catch {
92
- // Banner detection is non-critical; skip banner on persistent errors
87
+ return [...new Set(refs)];
88
+ }
89
+ function isSvg(path, contentType) {
90
+ return (path.toLowerCase().split("?")[0].endsWith(".svg") ||
91
+ (contentType ?? "").toLowerCase().includes("svg"));
92
+ }
93
+ async function checkBanner(url, path) {
94
+ let res;
95
+ try {
96
+ res = await fetchWithRetry(url, { redirect: "follow" });
97
+ }
98
+ catch (err) {
99
+ const message = err instanceof Error ? err.message : String(err);
100
+ return `${path}: request failed (${message})`;
101
+ }
102
+ if (res.status === 404)
103
+ return `${path}: missing (HTTP 404)`;
104
+ if (res.status !== 200)
105
+ return `${path}: HTTP ${res.status}`;
106
+ if (!isSvg(path, res.headers.get("content-type")))
93
107
  return null;
108
+ const refs = findExternalRefs(await res.text());
109
+ if (refs.length > 0) {
110
+ const shown = refs.slice(0, 3).join(", ");
111
+ const more = refs.length > 3 ? ` and ${refs.length - 3} more` : "";
112
+ return `${path}: not self-contained, it loads ${shown}${more}`;
94
113
  }
114
+ return null;
115
+ }
116
+ /**
117
+ * Pick the banner for a repo: the per-repo path first (repos.<name>.bannerPath
118
+ * or bannerPaths.<name>), then defaultBannerPath. A banner is used only when
119
+ * it answers 200 and, for SVG, loads nothing from outside itself.
120
+ */
121
+ export async function resolveBanner(repo, config) {
122
+ if (!config.portfolio.showBanner)
123
+ return { url: null, problems: [] };
124
+ const override = config.portfolio.repos[repo.name]?.bannerPath ??
125
+ config.portfolio.bannerPaths[repo.name];
126
+ const paths = [
127
+ ...new Set([override, config.portfolio.defaultBannerPath].filter((p) => Boolean(p))),
128
+ ];
129
+ const problems = [];
130
+ for (const path of paths) {
131
+ const clean = path.replace(/^\/+/, "");
132
+ const url = `https://raw.githubusercontent.com/${repo.full_name}/${repo.default_branch}/${clean}`;
133
+ const problem = await checkBanner(url, clean);
134
+ if (!problem)
135
+ return { url, problems: [] };
136
+ problems.push(problem);
137
+ }
138
+ return { url: null, problems };
95
139
  }
96
140
  const PORTFOLIO_CONFIG_FILE = ".ghost-portfolio.yml";
97
- export async function fetchPortfolioConfig(repo, config) {
98
- const { username } = config.github;
141
+ export async function fetchPortfolioConfig(repo) {
99
142
  const branch = repo.default_branch;
100
- const url = `https://raw.githubusercontent.com/${username}/${repo.name}/${branch}/${PORTFOLIO_CONFIG_FILE}`;
143
+ const url = `https://raw.githubusercontent.com/${repo.full_name}/${branch}/${PORTFOLIO_CONFIG_FILE}`;
101
144
  try {
102
145
  const res = await fetchWithRetry(url, { redirect: "follow" });
103
146
  if (!res.ok)
104
147
  return null;
105
148
  const text = await res.text();
106
- // Dynamic import to avoid adding yaml as a runtime dep for github.ts
107
- // yaml is already a project dependency
108
149
  const { parse } = await import("yaml");
109
150
  const data = parse(text);
110
151
  if (!data || typeof data !== "object")
111
152
  return null;
153
+ const pick = (v) => (typeof v === "string" ? v : undefined);
112
154
  return {
113
- description: data.description ?? undefined,
114
- personalNote: data.personalNote ?? undefined,
115
- dockerImage: data.dockerImage ?? undefined,
116
- keyFeatures: Array.isArray(data.keyFeatures) ? data.keyFeatures : undefined,
117
- techStack: data.techStack ?? undefined,
118
- badges: Array.isArray(data.badges) ? data.badges : undefined,
119
- bannerPath: data.bannerPath ?? undefined,
155
+ description: pick(data.description),
156
+ homepage: pick(data.homepage),
157
+ siteLabel: pick(data.siteLabel),
158
+ bannerPath: pick(data.bannerPath),
120
159
  };
121
160
  }
122
161
  catch {
123
162
  return null;
124
163
  }
125
164
  }
126
- async function urlExists(url) {
127
- const res = await fetchWithRetry(url, {
128
- method: "HEAD",
129
- redirect: "follow",
130
- });
131
- if (res.ok)
132
- return true;
133
- if (res.status === 404)
134
- return false;
135
- throw new Error(`Banner check failed for ${url}: HTTP ${res.status}`);
136
- }
137
165
  //# sourceMappingURL=github.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"github.js","sourceRoot":"","sources":["../src/github.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"github.js","sourceRoot":"","sources":["../src/github.ts"],"names":[],"mappings":"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"}
package/dist/http.d.ts CHANGED
@@ -2,8 +2,17 @@ interface RetryOptions {
2
2
  maxRetries?: number;
3
3
  baseDelay?: number;
4
4
  onRetry?: (attempt: number, delay: number, reason: string) => void;
5
+ /** Request function to use instead of the global fetch. */
6
+ fetchImpl?: (url: string, init?: RequestInit) => Promise<Response>;
5
7
  }
6
8
  export declare function fetchWithRetry(url: string, init?: RequestInit, opts?: RetryOptions): Promise<Response>;
9
+ /**
10
+ * A minimal fetch over node:http and node:https that sends the headers it is
11
+ * given as they are, Host included. The global fetch drops a custom Host
12
+ * header, which the Ghost origin option depends on. It never follows
13
+ * redirects: a redirect from the origin would lead back to the public URL.
14
+ */
15
+ export declare function rawRequest(url: string, init?: RequestInit): Promise<Response>;
7
16
  export declare function parseRateLimitHeaders(res: Response): RateLimitInfo | null;
8
17
  export interface RateLimitInfo {
9
18
  limit: number;
@@ -1 +1 @@
1
- {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAGA,UAAU,YAAY;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CACpE;AAED,wBAAsB,cAAc,CAClC,GAAG,EAAE,MAAM,EACX,IAAI,CAAC,EAAE,WAAW,EAClB,IAAI,CAAC,EAAE,YAAY,GAClB,OAAO,CAAC,QAAQ,CAAC,CAmEnB;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,QAAQ,GAAG,aAAa,GAAG,IAAI,CAYzE;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,IAAI,CAAC;CACf"}
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAMA,UAAU,YAAY;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACnE,2DAA2D;IAC3D,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;CACpE;AAED,wBAAsB,cAAc,CAClC,GAAG,EAAE,MAAM,EACX,IAAI,CAAC,EAAE,WAAW,EAClB,IAAI,CAAC,EAAE,YAAY,GAClB,OAAO,CAAC,QAAQ,CAAC,CAoEnB;AAID;;;;;GAKG;AACH,wBAAgB,UAAU,CACxB,GAAG,EAAE,MAAM,EACX,IAAI,GAAE,WAAgB,GACrB,OAAO,CAAC,QAAQ,CAAC,CAuCnB;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,QAAQ,GAAG,aAAa,GAAG,IAAI,CAYzE;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,IAAI,CAAC;CACf"}
package/dist/http.js CHANGED
@@ -1,13 +1,16 @@
1
+ import { request as httpRequest } from "node:http";
2
+ import { request as httpsRequest } from "node:https";
1
3
  const MAX_RETRIES = 3;
2
4
  const BASE_DELAY_MS = 1000;
3
5
  export async function fetchWithRetry(url, init, opts) {
4
6
  const maxRetries = opts?.maxRetries ?? MAX_RETRIES;
5
7
  const baseDelay = opts?.baseDelay ?? BASE_DELAY_MS;
8
+ const doFetch = opts?.fetchImpl ?? ((u, i) => fetch(u, i));
6
9
  let lastError;
7
10
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
8
11
  let res;
9
12
  try {
10
- res = await fetch(url, init);
13
+ res = await doFetch(url, init);
11
14
  }
12
15
  catch (error) {
13
16
  lastError = error;
@@ -46,6 +49,49 @@ export async function fetchWithRetry(url, init, opts) {
46
49
  const message = lastError instanceof Error ? lastError.message : String(lastError);
47
50
  throw new Error(`Request to ${url} failed after ${maxRetries + 1} attempts: ${message}`);
48
51
  }
52
+ const NULL_BODY_STATUS = new Set([101, 204, 205, 304]);
53
+ /**
54
+ * A minimal fetch over node:http and node:https that sends the headers it is
55
+ * given as they are, Host included. The global fetch drops a custom Host
56
+ * header, which the Ghost origin option depends on. It never follows
57
+ * redirects: a redirect from the origin would lead back to the public URL.
58
+ */
59
+ export function rawRequest(url, init = {}) {
60
+ return new Promise((resolve, reject) => {
61
+ const target = new URL(url);
62
+ const headers = { ...init.headers };
63
+ const hostHeader = Object.entries(headers).find(([k]) => k.toLowerCase() === "host")?.[1];
64
+ const isHttps = target.protocol === "https:";
65
+ const send = isHttps ? httpsRequest : httpRequest;
66
+ const req = send(target, {
67
+ method: init.method ?? "GET",
68
+ headers,
69
+ // Present the public name for TLS too, so the origin can pick its certificate.
70
+ ...(isHttps && hostHeader ? { servername: hostHeader.replace(/:\d+$/, "") } : {}),
71
+ }, (res) => {
72
+ const chunks = [];
73
+ res.on("data", (c) => chunks.push(c));
74
+ res.on("error", reject);
75
+ res.on("end", () => {
76
+ const out = new Headers();
77
+ for (const [k, v] of Object.entries(res.headers)) {
78
+ if (v === undefined)
79
+ continue;
80
+ for (const item of Array.isArray(v) ? v : [v])
81
+ out.append(k, item);
82
+ }
83
+ const status = res.statusCode ?? 502;
84
+ const body = NULL_BODY_STATUS.has(status) ? null : Buffer.concat(chunks);
85
+ resolve(new Response(body, { status, headers: out }));
86
+ });
87
+ });
88
+ req.setTimeout(30_000, () => req.destroy(new Error("timed out after 30s")));
89
+ req.on("error", reject);
90
+ if (typeof init.body === "string")
91
+ req.write(init.body);
92
+ req.end();
93
+ });
94
+ }
49
95
  export function parseRateLimitHeaders(res) {
50
96
  const limit = res.headers.get("x-ratelimit-limit");
51
97
  const remaining = res.headers.get("x-ratelimit-remaining");
package/dist/http.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,GAAG,CAAC,CAAC;AACtB,MAAM,aAAa,GAAG,IAAI,CAAC;AAQ3B,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,GAAW,EACX,IAAkB,EAClB,IAAmB;IAEnB,MAAM,UAAU,GAAG,IAAI,EAAE,UAAU,IAAI,WAAW,CAAC;IACnD,MAAM,SAAS,GAAG,IAAI,EAAE,SAAS,IAAI,aAAa,CAAC;IACnD,IAAI,SAAkB,CAAC;IAEvB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,UAAU,EAAE,OAAO,EAAE,EAAE,CAAC;QACvD,IAAI,GAAa,CAAC;QAClB,IAAI,CAAC;YACH,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC/B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,SAAS,GAAG,KAAK,CAAC;YAClB,IAAI,OAAO,IAAI,UAAU;gBAAE,MAAM;YAEjC,MAAM,KAAK,GAAG,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;YAC/C,MAAM,OAAO,GACX,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACzD,IAAI,EAAE,OAAO,EAAE,CACb,OAAO,GAAG,CAAC,EACX,KAAK,EACL,kBAAkB,OAAO,iBAAiB,KAAK,IAAI,CACpD,CAAC;YACF,MAAM,KAAK,CAAC,KAAK,CAAC,CAAC;YACnB,SAAS;QACX,CAAC;QAED,mCAAmC;QACnC,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAC7C,MAAM,kBAAkB,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;YACpE,MAAM,cAAc,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;YAE5D,IAAI,kBAAkB,KAAK,GAAG,IAAI,cAAc,EAAE,CAAC;gBACjD,MAAM,SAAS,GAAG,QAAQ,CAAC,cAAc,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC;gBACtD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;gBAEnD,IAAI,MAAM,GAAG,CAAC,IAAI,MAAM,GAAG,OAAO,IAAI,OAAO,GAAG,UAAU,EAAE,CAAC;oBAC3D,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;oBACzC,IAAI,EAAE,OAAO,EAAE,CACb,OAAO,GAAG,CAAC,EACX,MAAM,EACN,yBAAyB,OAAO,aAAa,CAC9C,CAAC;oBACF,MAAM,KAAK,CAAC,MAAM,CAAC,CAAC;oBACpB,SAAS;gBACX,CAAC;YACH,CAAC;QACH,CAAC;QAED,yBAAyB;QACzB,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,IAAI,OAAO,GAAG,UAAU,EAAE,CAAC;YAC9C,MAAM,KAAK,GAAG,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;YAC/C,IAAI,EAAE,OAAO,EAAE,CACb,OAAO,GAAG,CAAC,EACX,KAAK,EACL,gBAAgB,GAAG,CAAC,MAAM,iBAAiB,KAAK,IAAI,CACrD,CAAC;YACF,MAAM,KAAK,CAAC,KAAK,CAAC,CAAC;YACnB,SAAS;QACX,CAAC;QAED,OAAO,GAAG,CAAC;IACb,CAAC;IAED,MAAM,OAAO,GACX,SAAS,YAAY,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACrE,MAAM,IAAI,KAAK,CACb,cAAc,GAAG,iBAAiB,UAAU,GAAG,CAAC,cAAc,OAAO,EAAE,CACxE,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,GAAa;IACjD,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;IACnD,MAAM,SAAS,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;IAC3D,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;IAEnD,IAAI,CAAC,KAAK,IAAI,CAAC,SAAS,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IAEhD,OAAO;QACL,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC;QAC1B,SAAS,EAAE,QAAQ,CAAC,SAAS,EAAE,EAAE,CAAC;QAClC,OAAO,EAAE,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC;KAC9C,CAAC;AACJ,CAAC;AAQD,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC"}
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,102 +1,101 @@
1
1
  #!/usr/bin/env node
2
2
  import { Command } from "commander";
3
3
  import { writeFileSync } from "node:fs";
4
+ import { createRequire } from "node:module";
4
5
  import { loadConfig, generateExampleConfig } from "./config.js";
5
- import { fetchRepos, detectBanner, fetchPortfolioConfig } from "./github.js";
6
+ import { fetchAllRepos, selectRepos, resolveBanner, fetchPortfolioConfig, } from "./github.js";
6
7
  import { fetchPage, updatePage } from "./ghost.js";
7
- import { generateCard, generateFooter, buildLexical } from "./generator.js";
8
+ import { generateCard, generatePortfolioHtml, buildLexical, buildPreviewPage, wrapHtmlCard, } from "./generator.js";
9
+ const { version } = createRequire(import.meta.url)("../package.json");
8
10
  const program = new Command();
9
11
  program
10
12
  .name("ghost-github-portfolio")
11
- .description("Auto-sync GitHub repositories to a Ghost CMS portfolio page. Fetches repos, sorts by stars, generates cards with banners and badges, and updates Ghost via the Admin API.")
12
- .version("0.3.4");
13
+ .description("Write your most starred GitHub repositories to a Ghost page as a grid of cards, through the Ghost Admin API.")
14
+ .version(version);
13
15
  program
14
16
  .command("sync")
15
17
  .description("Sync GitHub repos to your Ghost portfolio page")
16
18
  .requiredOption("-c, --config <path>", "Path to config YAML file")
17
- .option("--dry-run", "Output generated HTML without updating Ghost")
18
- .option("--json", "Output raw lexical JSON (implies --dry-run)")
19
+ .option("--dry-run", "Build the page without updating Ghost")
20
+ .option("--json", "Print the lexical JSON (implies --dry-run)")
21
+ .option("--html-out <file>", "Write a standalone preview page of the card (implies --dry-run)")
19
22
  .option("-v, --verbose", "Show detailed progress")
20
23
  .action(async (opts) => {
21
24
  try {
22
25
  const config = loadConfig(opts.config);
23
26
  const verbose = opts.verbose || false;
24
- const dryRun = opts.dryRun || opts.json || false;
25
- // Fetch repos
27
+ const dryRun = opts.dryRun || opts.json || Boolean(opts.htmlOut);
26
28
  if (verbose)
27
29
  console.log(`Fetching repos for ${config.github.username} (min ${config.portfolio.minStars} stars)...`);
28
- const allRepos = await fetchRepos(config);
29
- // Filter awesome lists for display only (stats use all repos)
30
- const displayRepos = config.portfolio.excludeAwesomeLists
31
- ? allRepos.filter((r) => !r.name.toLowerCase().startsWith("awesome") && !r.topics.includes("awesome-list"))
32
- : allRepos;
33
- console.log(`Found ${allRepos.length} repos matching criteria (${config.portfolio.minStars}+ stars)${displayRepos.length < allRepos.length ? `, displaying ${displayRepos.length}` : ""}`);
34
- if (displayRepos.length === 0) {
30
+ const allRepos = await fetchAllRepos(config, verbose);
31
+ const repos = selectRepos(allRepos, config);
32
+ console.log(`Found ${allRepos.length} public repos, showing ${repos.length}`);
33
+ if (repos.length === 0) {
35
34
  console.log("No repos found. Check your config.");
36
35
  return;
37
36
  }
38
- // Detect banners (parallel)
37
+ // Per-repo .ghost-portfolio.yml: the file gives defaults, config.yml wins.
38
+ // Its description stands in for the GitHub one and is cleaned the same
39
+ // way; only a description in config.yml is used verbatim.
39
40
  if (verbose)
40
- console.log("Detecting banner images...");
41
- const bannerResults = await Promise.all(displayRepos.map(async (repo) => {
42
- const banner = await detectBanner(repo, config);
43
- if (verbose) {
44
- console.log(` ${repo.name}: ${banner ? "found" : "no banner"}`);
45
- }
46
- return { repo, banner };
41
+ console.log("Fetching portfolio configs...");
42
+ await Promise.all(repos.map(async (repo) => {
43
+ const portfolioConfig = await fetchPortfolioConfig(repo);
44
+ if (!portfolioConfig)
45
+ return;
46
+ const { description, ...fileOverrides } = portfolioConfig;
47
+ if (description)
48
+ repo.description = description;
49
+ const existing = config.portfolio.repos[repo.name] ?? {};
50
+ config.portfolio.repos[repo.name] = {
51
+ ...Object.fromEntries(Object.entries(fileOverrides).filter(([, v]) => v !== undefined)),
52
+ ...Object.fromEntries(Object.entries(existing).filter(([, v]) => v !== undefined)),
53
+ };
54
+ if (verbose)
55
+ console.log(` ${repo.name}: loaded .ghost-portfolio.yml`);
47
56
  }));
48
- // Fetch per-repo portfolio configs (.ghost-portfolio.yml)
49
57
  if (verbose)
50
- console.log("Fetching portfolio configs...");
51
- await Promise.all(displayRepos.map(async (repo) => {
52
- const portfolioConfig = await fetchPortfolioConfig(repo, config);
53
- if (portfolioConfig) {
54
- // Merge: per-repo file provides defaults, config.yml overrides
55
- const existing = config.portfolio.repos[repo.name] ?? {};
56
- config.portfolio.repos[repo.name] = {
57
- ...portfolioConfig,
58
- ...Object.fromEntries(Object.entries(existing).filter(([, v]) => v !== undefined)),
59
- };
60
- if (verbose)
61
- console.log(` ${repo.name}: loaded .ghost-portfolio.yml`);
58
+ console.log("Checking banners...");
59
+ const banners = await Promise.all(repos.map((repo) => resolveBanner(repo, config)));
60
+ repos.forEach((repo, i) => {
61
+ const { problems } = banners[i];
62
+ if (problems.length > 0) {
63
+ console.warn(`Warning: ${repo.name} gets a name tile: ${problems.join("; ")}`);
62
64
  }
63
- }));
64
- // Generate cards
65
- const cards = bannerResults.map(({ repo, banner }) => generateCard(repo, banner, config));
66
- const footer = generateFooter(allRepos, config);
67
- const lexical = buildLexical(cards, footer);
65
+ });
66
+ const cards = repos.map((repo, i) => generateCard(repo, banners[i].url, config));
67
+ const html = generatePortfolioHtml({ cards, totalRepos: allRepos.length }, config);
68
+ const lexical = buildLexical(html);
68
69
  if (opts.json) {
69
70
  console.log(JSON.stringify(lexical, null, 2));
70
71
  return;
71
72
  }
72
73
  if (dryRun) {
73
- console.log("\n--- DRY RUN: Generated HTML ---\n");
74
- for (const { repo, banner } of bannerResults) {
75
- console.log(`${repo.name} (${repo.stargazers_count} stars) ${banner ? "[banner]" : "[no banner]"}`);
76
- }
74
+ console.log("\n--- DRY RUN ---\n");
75
+ repos.forEach((repo, i) => {
76
+ console.log(`${repo.name} (${repo.stargazers_count} stars) ${banners[i].url ? "[banner]" : "[tile]"}`);
77
+ });
77
78
  console.log(`\nTotal cards: ${cards.length}`);
78
- console.log(`Total stars: ${displayRepos.reduce((s, r) => s + r.stargazers_count, 0)}`);
79
- // Write to temp file for inspection
80
- const tmpPath = "/tmp/ghost-portfolio-preview.html";
81
- const htmlPreview = cards.join("\n<br>\n");
82
- writeFileSync(tmpPath, htmlPreview);
83
- console.log(`\nPreview written to ${tmpPath}`);
79
+ const cardPath = "/tmp/ghost-portfolio-preview.html";
80
+ writeFileSync(cardPath, wrapHtmlCard(html));
81
+ console.log(`\nHtml card written to ${cardPath}`);
82
+ if (opts.htmlOut) {
83
+ writeFileSync(opts.htmlOut, buildPreviewPage(html));
84
+ console.log(`Preview page written to ${opts.htmlOut}`);
85
+ }
84
86
  return;
85
87
  }
86
- // Fetch current page
87
88
  if (verbose)
88
89
  console.log("Fetching Ghost page...");
89
90
  const page = await fetchPage(config);
90
91
  if (verbose)
91
92
  console.log(` Page: ${page.title} (${page.id})`);
92
- // Update page
93
93
  if (verbose)
94
94
  console.log("Updating Ghost page...");
95
95
  const updated = await updatePage(config, page.id, page.updated_at, lexical);
96
96
  console.log(`Portfolio updated: ${updated.title}`);
97
- console.log(` ${displayRepos.length} projects displayed`);
98
- console.log(` ${displayRepos.reduce((s, r) => s + r.stargazers_count, 0)} total stars`);
99
- console.log(` ${bannerResults.filter((b) => b.banner).length} banners loaded`);
97
+ console.log(` ${repos.length} projects displayed`);
98
+ console.log(` ${banners.filter((b) => b.url).length} banners, ${banners.filter((b) => !b.url).length} tiles`);
100
99
  }
101
100
  catch (err) {
102
101
  console.error(`Error: ${err instanceof Error ? err.message : String(err)}`);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}