static-anthology 1.0.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/README.md +54 -0
- package/dist/cli.js +215 -0
- package/dist/cli.js.map +1 -0
- package/package.json +38 -0
package/README.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# GitHub Project Web Server
|
|
2
|
+
|
|
3
|
+
This project allows the user to easily host multiple github web projects on a
|
|
4
|
+
single website. After running a single command, all public webapps on a
|
|
5
|
+
github account will be statically rendered and hosted in the static/ directory,
|
|
6
|
+
which then can be hosted on a static web server.
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
## Detecting Projects: Static Web App Manifests
|
|
10
|
+
|
|
11
|
+
In order to determine if a project is a static web app, each repository should have
|
|
12
|
+
a file, `swa_manifest.json` in the root directory. This `json` file must contain
|
|
13
|
+
the following fields:
|
|
14
|
+
```json
|
|
15
|
+
{
|
|
16
|
+
"title":"The title of the web app",
|
|
17
|
+
"root":"The root directory of the repository containing static content",
|
|
18
|
+
"directory": "The output directory of the static subpage"
|
|
19
|
+
}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Additionally, tile images for each site are loaded from `swa_tile.png` if present.
|
|
23
|
+
|
|
24
|
+
## Static Resources
|
|
25
|
+
|
|
26
|
+
Static resources may be added to `static_src`. These will be copied as-is into
|
|
27
|
+
the root of the output directory. This is a good location for styles, images,
|
|
28
|
+
and any other root-level web assets.
|
|
29
|
+
|
|
30
|
+
## Templates
|
|
31
|
+
|
|
32
|
+
The rendering process uses three template files:
|
|
33
|
+
- index.njk - determines the base landing page. Contains multiple tiles.
|
|
34
|
+
- folder.njk - folders store multiple tiles.
|
|
35
|
+
- tile.njk - a single tile. One tile is produced per web app.
|
|
36
|
+
|
|
37
|
+
## Configuration
|
|
38
|
+
|
|
39
|
+
Configuration is best done by adding a `config.json` to the root directory.
|
|
40
|
+
At a minimum, configure a GitHub username and a PAT:
|
|
41
|
+
|
|
42
|
+
```json
|
|
43
|
+
{
|
|
44
|
+
"username":"github username",
|
|
45
|
+
"github_token": "******" // personal access token with repo access
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Running the Compiler
|
|
50
|
+
|
|
51
|
+
Once configured, run
|
|
52
|
+
```
|
|
53
|
+
npm run start
|
|
54
|
+
```
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/cli.ts
|
|
4
|
+
import yargs from "yargs";
|
|
5
|
+
import { hideBin } from "yargs/helpers";
|
|
6
|
+
import fs3 from "fs-extra";
|
|
7
|
+
import path from "path";
|
|
8
|
+
|
|
9
|
+
// src/repoProcessor.ts
|
|
10
|
+
import fs2 from "fs-extra";
|
|
11
|
+
import nunjucks from "nunjucks";
|
|
12
|
+
|
|
13
|
+
// src/utils.ts
|
|
14
|
+
import fs from "fs-extra";
|
|
15
|
+
async function emptyDirectory(path2) {
|
|
16
|
+
await fs.emptyDir(path2);
|
|
17
|
+
}
|
|
18
|
+
function titleToDirectory(title) {
|
|
19
|
+
return title.split("").filter((l) => /\w/.test(l)).join("");
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// src/githubApi.ts
|
|
23
|
+
import axios from "axios";
|
|
24
|
+
import simpleGit from "simple-git";
|
|
25
|
+
function sleep(ms) {
|
|
26
|
+
return new Promise((resolve) => {
|
|
27
|
+
setTimeout(resolve, ms);
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
function getHeaders(githubToken) {
|
|
31
|
+
const headers = {};
|
|
32
|
+
if (githubToken) {
|
|
33
|
+
headers["Authorization"] = `token ${githubToken}`;
|
|
34
|
+
}
|
|
35
|
+
return headers;
|
|
36
|
+
}
|
|
37
|
+
async function getRepos(username, githubToken) {
|
|
38
|
+
await sleep(1e3);
|
|
39
|
+
const repos_response = await axios.get(
|
|
40
|
+
`https://api.github.com/users/${username}/repos`,
|
|
41
|
+
{ headers: getHeaders(githubToken) }
|
|
42
|
+
);
|
|
43
|
+
return repos_response.data;
|
|
44
|
+
}
|
|
45
|
+
async function isStaticWebApp(repo, githubToken) {
|
|
46
|
+
try {
|
|
47
|
+
await sleep(100);
|
|
48
|
+
const manifest = (await axios.get(repo.url + "/contents/swa_manifest.json", {
|
|
49
|
+
headers: getHeaders(githubToken)
|
|
50
|
+
})).data;
|
|
51
|
+
return true;
|
|
52
|
+
} catch (error) {
|
|
53
|
+
if (error.response && error.response.status === 404) {
|
|
54
|
+
return false;
|
|
55
|
+
} else {
|
|
56
|
+
throw error;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
async function clone(clone_url, githubToken) {
|
|
61
|
+
const tmpDir = "./tmp";
|
|
62
|
+
await emptyDirectory(tmpDir);
|
|
63
|
+
const git = simpleGit();
|
|
64
|
+
if (githubToken) {
|
|
65
|
+
const remote = `https://${githubToken}@${clone_url.substring(
|
|
66
|
+
"https://".length
|
|
67
|
+
)}`;
|
|
68
|
+
await git.clone(remote, tmpDir);
|
|
69
|
+
} else {
|
|
70
|
+
await git.clone(clone_url, tmpDir);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// src/repoProcessor.ts
|
|
75
|
+
function repoComparator(r1, r2) {
|
|
76
|
+
const r1_time = new Date(r1.updated_at).getTime();
|
|
77
|
+
const r2_time = new Date(r2.updated_at).getTime();
|
|
78
|
+
return r1_time - r2_time;
|
|
79
|
+
}
|
|
80
|
+
var RepoProcessor = class {
|
|
81
|
+
users;
|
|
82
|
+
repos;
|
|
83
|
+
pages;
|
|
84
|
+
outputDir;
|
|
85
|
+
githubToken;
|
|
86
|
+
constructor(views, staticDir, outputDir, githubToken) {
|
|
87
|
+
this.outputDir = outputDir;
|
|
88
|
+
this.githubToken = githubToken;
|
|
89
|
+
nunjucks.configure(views, {
|
|
90
|
+
autoescape: true
|
|
91
|
+
});
|
|
92
|
+
emptyDirectory(this.outputDir);
|
|
93
|
+
fs2.copySync(staticDir, this.outputDir);
|
|
94
|
+
this.users = [];
|
|
95
|
+
this.repos = [];
|
|
96
|
+
this.pages = [];
|
|
97
|
+
}
|
|
98
|
+
async addUsers(...users) {
|
|
99
|
+
this.users.push(...users);
|
|
100
|
+
}
|
|
101
|
+
async processUsers() {
|
|
102
|
+
while (this.users.length) {
|
|
103
|
+
const username = this.users.pop();
|
|
104
|
+
if (!username) continue;
|
|
105
|
+
const repos = await getRepos(username, this.githubToken);
|
|
106
|
+
for (let i = 0; i < repos.length; i++) {
|
|
107
|
+
const repo = repos[i];
|
|
108
|
+
console.log(`Testing repo: ${repo.name}`);
|
|
109
|
+
if (await isStaticWebApp(repo, this.githubToken)) {
|
|
110
|
+
this.repos.push(repo);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
async processRepos() {
|
|
116
|
+
this.repos.sort(repoComparator).reverse();
|
|
117
|
+
for (const repo of this.repos) {
|
|
118
|
+
await this.processRepo(repo);
|
|
119
|
+
}
|
|
120
|
+
this.repos = [];
|
|
121
|
+
}
|
|
122
|
+
async processRepo(repo_info) {
|
|
123
|
+
console.log(`Processing ${repo_info.name}`);
|
|
124
|
+
await clone(repo_info.clone_url, this.githubToken);
|
|
125
|
+
const manifest = JSON.parse(
|
|
126
|
+
fs2.readFileSync("./tmp/swa_manifest.json", "utf8")
|
|
127
|
+
);
|
|
128
|
+
const { title, root } = manifest;
|
|
129
|
+
const directory = manifest.directory ?? titleToDirectory(title);
|
|
130
|
+
fs2.mkdirSync(`${this.outputDir}/${directory}`);
|
|
131
|
+
fs2.copySync(`./tmp/${root}`, `${this.outputDir}/${directory}`);
|
|
132
|
+
let tile;
|
|
133
|
+
if (fs2.existsSync("./tmp/swa_tile.png")) {
|
|
134
|
+
tile = titleToDirectory(title) + ".png";
|
|
135
|
+
fs2.copySync("./tmp/swa_tile.png", `${this.outputDir}/tiles/${tile}`);
|
|
136
|
+
} else {
|
|
137
|
+
tile = "default.png";
|
|
138
|
+
}
|
|
139
|
+
this.pages.push({
|
|
140
|
+
title,
|
|
141
|
+
directory,
|
|
142
|
+
tile
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
processPages() {
|
|
146
|
+
const indexHtml = nunjucks.render("index.njk", { tiles: this.pages });
|
|
147
|
+
fs2.writeFileSync(`${this.outputDir}/index.html`, indexHtml, "utf8");
|
|
148
|
+
}
|
|
149
|
+
async process() {
|
|
150
|
+
await this.processUsers();
|
|
151
|
+
await this.processRepos();
|
|
152
|
+
this.processPages();
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
// src/cli.ts
|
|
157
|
+
async function main() {
|
|
158
|
+
try {
|
|
159
|
+
const argv = await yargs(hideBin(process.argv)).scriptName("static-anthology").usage("Usage: $0 [options]").config("config", (configPath) => {
|
|
160
|
+
const resolvedPath = path.resolve(configPath);
|
|
161
|
+
if (!fs3.existsSync(resolvedPath)) {
|
|
162
|
+
throw new Error(`Config file not found: ${resolvedPath}`);
|
|
163
|
+
}
|
|
164
|
+
return fs3.readJsonSync(resolvedPath);
|
|
165
|
+
}).default("config", "config.json").option("username", {
|
|
166
|
+
alias: "u",
|
|
167
|
+
type: "string",
|
|
168
|
+
description: "GitHub username to process (can also be set in config)"
|
|
169
|
+
}).option("views", {
|
|
170
|
+
type: "string",
|
|
171
|
+
default: "./views",
|
|
172
|
+
description: "Directory containing Nunjucks templates/views",
|
|
173
|
+
normalize: true
|
|
174
|
+
}).option("static", {
|
|
175
|
+
type: "string",
|
|
176
|
+
default: "./static_src",
|
|
177
|
+
description: "Directory of static assets to copy",
|
|
178
|
+
normalize: true
|
|
179
|
+
}).option("output", {
|
|
180
|
+
alias: "o",
|
|
181
|
+
type: "string",
|
|
182
|
+
default: "./static",
|
|
183
|
+
description: "Output/build directory",
|
|
184
|
+
normalize: true
|
|
185
|
+
}).option("github_token", {
|
|
186
|
+
type: "string",
|
|
187
|
+
description: "GitHub personal access token (also readable from GITHUB_TOKEN env)",
|
|
188
|
+
implies: "username"
|
|
189
|
+
}).env("GITHUB").demandOption(["username"], "You must provide a GitHub username (or use config)").help().alias("help", "h").version().epilogue("For more info, check the README: https://github.com/yourusername/github-web-server").argv;
|
|
190
|
+
const token = argv.github_token || process.env.GITHUB_TOKEN;
|
|
191
|
+
if (!token && argv.username) {
|
|
192
|
+
console.warn("\u26A0\uFE0F No GitHub token provided \u2014 API rate limit will be very low (60 req/h)");
|
|
193
|
+
}
|
|
194
|
+
const processor = new RepoProcessor(
|
|
195
|
+
path.resolve(argv.views),
|
|
196
|
+
path.resolve(argv.static),
|
|
197
|
+
path.resolve(argv.output),
|
|
198
|
+
token
|
|
199
|
+
);
|
|
200
|
+
if (argv.username) {
|
|
201
|
+
await processor.addUsers(argv.username);
|
|
202
|
+
}
|
|
203
|
+
console.log("Starting processing...");
|
|
204
|
+
await processor.process();
|
|
205
|
+
console.log("Done! Output is in:", argv.output);
|
|
206
|
+
} catch (error) {
|
|
207
|
+
console.error("Error:", error instanceof Error ? error.message : String(error));
|
|
208
|
+
process.exitCode = 1;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
main().catch((err) => {
|
|
212
|
+
console.error("Unexpected error:", err);
|
|
213
|
+
process.exit(1);
|
|
214
|
+
});
|
|
215
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/repoProcessor.ts","../src/utils.ts","../src/githubApi.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport yargs from 'yargs';\nimport { hideBin } from 'yargs/helpers';\nimport fs from 'fs-extra';\nimport path from 'path';\nimport RepoProcessor from './repoProcessor.js'; // adjust path if needed\n\ninterface CliArgs {\n config?: string;\n username?: string;\n views: string;\n static: string;\n output: string;\n github_token?: string;\n help?: boolean;\n}\n\nasync function main() {\n try {\n const argv = await yargs(hideBin(process.argv))\n .scriptName('static-anthology')\n .usage('Usage: $0 [options]')\n .config('config', (configPath: string) => {\n const resolvedPath = path.resolve(configPath);\n if (!fs.existsSync(resolvedPath)) {\n throw new Error(`Config file not found: ${resolvedPath}`);\n }\n return fs.readJsonSync(resolvedPath);\n })\n .default('config', 'config.json')\n .option('username', {\n alias: 'u',\n type: 'string',\n description: 'GitHub username to process (can also be set in config)',\n })\n .option('views', {\n type: 'string',\n default: './views',\n description: 'Directory containing Nunjucks templates/views',\n normalize: true,\n })\n .option('static', {\n type: 'string',\n default: './static_src',\n description: 'Directory of static assets to copy',\n normalize: true,\n })\n .option('output', {\n alias: 'o',\n type: 'string',\n default: './static',\n description: 'Output/build directory',\n normalize: true,\n })\n .option('github_token', {\n type: 'string',\n description: 'GitHub personal access token (also readable from GITHUB_TOKEN env)',\n implies: 'username',\n })\n .env('GITHUB') // automatically reads GITHUB_TOKEN from environment\n .demandOption(['username'], 'You must provide a GitHub username (or use config)')\n .help()\n .alias('help', 'h')\n .version()\n .epilogue('For more info, check the README: https://github.com/yourusername/github-web-server')\n .argv as unknown as CliArgs;\n\n // Final token resolution: CLI > config > env\n const token = argv.github_token || process.env.GITHUB_TOKEN;\n\n if (!token && argv.username) {\n console.warn('⚠️ No GitHub token provided — API rate limit will be very low (60 req/h)');\n }\n\n const processor = new RepoProcessor(\n path.resolve(argv.views),\n path.resolve(argv.static),\n path.resolve(argv.output),\n token\n );\n\n if (argv.username) {\n await processor.addUsers(argv.username);\n }\n\n console.log('Starting processing...');\n await processor.process();\n console.log('Done! Output is in:', argv.output);\n\n } catch (error) {\n console.error('Error:', error instanceof Error ? error.message : String(error));\n process.exitCode = 1;\n }\n}\n\nmain().catch((err) => {\n console.error('Unexpected error:', err);\n process.exit(1);\n});","import fs from 'fs-extra';\nimport nunjucks from 'nunjucks';\n\nimport { getRepos, isStaticWebApp, clone } from './githubApi.js';\nimport { emptyDirectory, titleToDirectory } from './utils.js';\nimport { Repo } from './types/github.js';\nimport { PageInfo } from './types/page.js';\nimport { Manifest } from './types/manifest.js';\n\nfunction repoComparator(r1: Repo, r2: Repo) {\n const r1_time = new Date(r1.updated_at).getTime();\n const r2_time = new Date(r2.updated_at).getTime();\n return r1_time - r2_time;\n}\n\nexport default class RepoProcessor {\n users: string[];\n repos: Repo[];\n pages: PageInfo[];\n outputDir: string;\n githubToken?: string;\n\n constructor(\n views: string,\n staticDir: string,\n outputDir: string,\n githubToken?: string,\n ) {\n this.outputDir = outputDir;\n this.githubToken = githubToken;\n nunjucks.configure(views, {\n autoescape: true,\n });\n emptyDirectory(this.outputDir);\n fs.copySync(staticDir, this.outputDir);\n this.users = [];\n this.repos = [];\n this.pages = [];\n }\n\n async addUsers(...users: string[]) {\n this.users.push(...users);\n }\n\n async processUsers() {\n while (this.users.length) {\n const username = this.users.pop();\n if (!username) continue;\n const repos = await getRepos(username, this.githubToken);\n for (let i = 0; i < repos.length; i++) {\n const repo = repos[i];\n console.log(`Testing repo: ${repo.name}`);\n if (await isStaticWebApp(repo, this.githubToken)) {\n this.repos.push(repo);\n }\n }\n }\n }\n\n async processRepos() {\n this.repos.sort(repoComparator).reverse(); // Sort from newest to oldest\n for (const repo of this.repos) {\n await this.processRepo(repo);\n }\n this.repos = []; // Prevent repeated processing\n }\n\n async processRepo(repo_info: Repo) {\n console.log(`Processing ${repo_info.name}`);\n\n await clone(repo_info.clone_url, this.githubToken);\n // Now we have a local copy of the repo. Read the manifest.\n const manifest: Manifest = JSON.parse(\n fs.readFileSync('./tmp/swa_manifest.json', 'utf8'),\n );\n const { title, root } = manifest;\n const directory = manifest.directory ?? titleToDirectory(title);\n\n fs.mkdirSync(`${this.outputDir}/${directory}`);\n fs.copySync(`./tmp/${root}`, `${this.outputDir}/${directory}`);\n\n let tile;\n if (fs.existsSync('./tmp/swa_tile.png')) {\n tile = titleToDirectory(title) + '.png';\n fs.copySync('./tmp/swa_tile.png', `${this.outputDir}/tiles/${tile}`);\n } else {\n tile = 'default.png';\n }\n\n this.pages.push({\n title,\n directory,\n tile,\n });\n }\n\n processPages() {\n // We want to render index.html to contain all tiles.\n const indexHtml = nunjucks.render('index.njk', { tiles: this.pages });\n fs.writeFileSync(`${this.outputDir}/index.html`, indexHtml, 'utf8');\n }\n\n async process() {\n await this.processUsers();\n await this.processRepos();\n this.processPages();\n }\n}\n","import fs from 'fs-extra';\n\nexport async function emptyDirectory(path: string) {\n await fs.emptyDir(path);\n}\n\nexport function titleToDirectory(title: string) {\n return title\n .split('')\n .filter((l) => /\\w/.test(l))\n .join('');\n}\n","import { emptyDirectory } from './utils.js';\nimport axios from 'axios';\nimport simpleGit from 'simple-git';\nimport { Repo } from './types/github.js';\n\nfunction sleep(ms: number) {\n return new Promise((resolve) => {\n setTimeout(resolve, ms);\n });\n}\n\nfunction getHeaders(githubToken?: string) {\n const headers: any = {};\n if (githubToken) {\n headers['Authorization'] = `token ${githubToken}`;\n }\n return headers;\n}\n\nexport async function getRepos(\n username: string,\n githubToken?: string,\n): Promise<Repo[]> {\n await sleep(1000);\n const repos_response = await axios.get(\n `https://api.github.com/users/${username}/repos`,\n { headers: getHeaders(githubToken) },\n );\n return repos_response.data;\n}\n\nexport async function isStaticWebApp(repo: any, githubToken?: string) {\n try {\n await sleep(100);\n const manifest = (\n await axios.get(repo.url + '/contents/swa_manifest.json', {\n headers: getHeaders(githubToken),\n })\n ).data;\n return true;\n } catch (error: any) {\n if (error.response && error.response.status === 404) {\n return false;\n } else {\n throw error;\n }\n }\n}\n\nexport async function clone(clone_url: string, githubToken?: string) {\n const tmpDir = './tmp';\n await emptyDirectory(tmpDir);\n //@ts-ignore\n const git = simpleGit();\n\n if (githubToken) {\n const remote = `https://${githubToken}@${clone_url.substring(\n 'https://'.length,\n )}`;\n await git.clone(remote, tmpDir);\n } else {\n await git.clone(clone_url, tmpDir);\n }\n}\n"],"mappings":"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","names":["fs","fs","path","fs","fs"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "static-anthology",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Static site renderer for project showcases",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"bin": {
|
|
10
|
+
"github-web-server": "./dist/cli.js"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"dist"
|
|
14
|
+
],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"dev": "tsx src/cli.ts",
|
|
17
|
+
"build": "tsup",
|
|
18
|
+
"start": "node dist/cli.js",
|
|
19
|
+
"format": "prettier --write src",
|
|
20
|
+
"prepublishOnly": "npm run build"
|
|
21
|
+
},
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"axios": "^1.13.2",
|
|
24
|
+
"fs-extra": "^11.2.0",
|
|
25
|
+
"nunjucks": "^3.2.4",
|
|
26
|
+
"simple-git": "^3.24.0",
|
|
27
|
+
"yargs": "^18.0.0"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"@types/fs-extra": "^11.0.4",
|
|
31
|
+
"@types/nunjucks": "^3.2.6",
|
|
32
|
+
"@types/yargs": "^17.0.35",
|
|
33
|
+
"prettier": "^3.8.0",
|
|
34
|
+
"tsup": "^8.3.5",
|
|
35
|
+
"tsx": "^4.21.0",
|
|
36
|
+
"typescript": "^5.6.3"
|
|
37
|
+
}
|
|
38
|
+
}
|