static-anthology 1.0.0 → 2.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 +23 -21
- package/dist/cli.js +152 -104
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
|
-
#
|
|
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.
|
|
1
|
+
# Static Anthology
|
|
7
2
|
|
|
3
|
+
This project allows the user to easily host multiple web projects as subpages on a
|
|
4
|
+
single website. Pages can be specified using a sitemap json file, with support for
|
|
5
|
+
projects on local filesystems as well as on GitHub.
|
|
8
6
|
|
|
9
7
|
## Detecting Projects: Static Web App Manifests
|
|
10
8
|
|
|
11
|
-
In order to determine if a project is a static web app, each
|
|
9
|
+
In order to determine if a project is a static web app, each source should have
|
|
12
10
|
a file, `swa_manifest.json` in the root directory. This `json` file must contain
|
|
13
11
|
the following fields:
|
|
14
12
|
```json
|
|
@@ -23,9 +21,9 @@ Additionally, tile images for each site are loaded from `swa_tile.png` if presen
|
|
|
23
21
|
|
|
24
22
|
## Static Resources
|
|
25
23
|
|
|
26
|
-
Static resources may be added to `static_src`. These will be
|
|
27
|
-
the root of the output directory. This is a good location for
|
|
28
|
-
and any other root-level web assets.
|
|
24
|
+
Static resources for the root page may be added to `static_src`. These will be
|
|
25
|
+
copied as-is into the root of the output directory. This is a good location for
|
|
26
|
+
styles, images, and any other root-level web assets.
|
|
29
27
|
|
|
30
28
|
## Templates
|
|
31
29
|
|
|
@@ -36,19 +34,23 @@ The rendering process uses three template files:
|
|
|
36
34
|
|
|
37
35
|
## Configuration
|
|
38
36
|
|
|
39
|
-
Configuration
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
```json
|
|
43
|
-
{
|
|
44
|
-
"username":"github username",
|
|
45
|
-
"github_token": "******" // personal access token with repo access
|
|
46
|
-
}
|
|
47
|
-
```
|
|
37
|
+
Configuration for any command-line arguments can also be supplied by adding
|
|
38
|
+
a `config.json` file in the current directory. This is the recommended place
|
|
39
|
+
for your GitHub username and token.
|
|
48
40
|
|
|
49
41
|
## Running the Compiler
|
|
50
42
|
|
|
51
43
|
Once configured, run
|
|
52
44
|
```
|
|
53
|
-
|
|
54
|
-
|
|
45
|
+
npx static-anthology
|
|
46
|
+
OR
|
|
47
|
+
npx static-anthology compile
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Generating a SiteMap from GitHub
|
|
51
|
+
If you would like to generate a sitemap from all of the static web apps on a
|
|
52
|
+
user's GitHub account, you can run
|
|
53
|
+
```
|
|
54
|
+
npx static-anthology source
|
|
55
|
+
```
|
|
56
|
+
Make sure to configure a username and token.
|
package/dist/cli.js
CHANGED
|
@@ -3,17 +3,11 @@
|
|
|
3
3
|
// src/cli.ts
|
|
4
4
|
import yargs from "yargs";
|
|
5
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
6
|
|
|
13
7
|
// src/utils.ts
|
|
14
8
|
import fs from "fs-extra";
|
|
15
|
-
async function emptyDirectory(
|
|
16
|
-
await fs.emptyDir(
|
|
9
|
+
async function emptyDirectory(path4) {
|
|
10
|
+
await fs.emptyDir(path4);
|
|
17
11
|
}
|
|
18
12
|
function titleToDirectory(title) {
|
|
19
13
|
return title.split("").filter((l) => /\w/.test(l)).join("");
|
|
@@ -22,6 +16,7 @@ function titleToDirectory(title) {
|
|
|
22
16
|
// src/githubApi.ts
|
|
23
17
|
import axios from "axios";
|
|
24
18
|
import simpleGit from "simple-git";
|
|
19
|
+
import path from "path";
|
|
25
20
|
function sleep(ms) {
|
|
26
21
|
return new Promise((resolve) => {
|
|
27
22
|
setTimeout(resolve, ms);
|
|
@@ -58,7 +53,7 @@ async function isStaticWebApp(repo, githubToken) {
|
|
|
58
53
|
}
|
|
59
54
|
}
|
|
60
55
|
async function clone(clone_url, githubToken) {
|
|
61
|
-
const tmpDir = "./tmp";
|
|
56
|
+
const tmpDir = path.resolve("./tmp");
|
|
62
57
|
await emptyDirectory(tmpDir);
|
|
63
58
|
const git = simpleGit();
|
|
64
59
|
if (githubToken) {
|
|
@@ -71,57 +66,81 @@ async function clone(clone_url, githubToken) {
|
|
|
71
66
|
}
|
|
72
67
|
}
|
|
73
68
|
|
|
74
|
-
// src/
|
|
69
|
+
// src/sitemapGen.ts
|
|
75
70
|
function repoComparator(r1, r2) {
|
|
76
71
|
const r1_time = new Date(r1.updated_at).getTime();
|
|
77
72
|
const r2_time = new Date(r2.updated_at).getTime();
|
|
78
73
|
return r1_time - r2_time;
|
|
79
74
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
75
|
+
async function generateSitemapFromGithub(user, token) {
|
|
76
|
+
async function getStaticWebApps() {
|
|
77
|
+
const filtered = [];
|
|
78
|
+
const repos2 = await getRepos(user, token);
|
|
79
|
+
for (let i = 0; i < repos2.length; i++) {
|
|
80
|
+
const repo = repos2[i];
|
|
81
|
+
console.log(`Testing repo: ${repo.name}`);
|
|
82
|
+
if (await isStaticWebApp(repo, token)) {
|
|
83
|
+
filtered.push(repo);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return filtered;
|
|
87
|
+
}
|
|
88
|
+
const repos = await getStaticWebApps();
|
|
89
|
+
repos.sort(repoComparator).reverse();
|
|
90
|
+
return repos.map((repo) => ({
|
|
91
|
+
"github": repo.clone_url
|
|
92
|
+
}));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// src/siteProcessor.ts
|
|
96
|
+
import fs2 from "fs-extra";
|
|
97
|
+
import nunjucks from "nunjucks";
|
|
98
|
+
import path2 from "path";
|
|
99
|
+
var SiteProcessor = class {
|
|
100
|
+
views;
|
|
101
|
+
staticDir;
|
|
83
102
|
pages;
|
|
84
103
|
outputDir;
|
|
104
|
+
sitemapLocation;
|
|
85
105
|
githubToken;
|
|
86
|
-
|
|
106
|
+
sitemap;
|
|
107
|
+
constructor(views, staticDir, outputDir, sitemapLocation, githubToken) {
|
|
108
|
+
this.views = views;
|
|
109
|
+
this.staticDir = staticDir;
|
|
87
110
|
this.outputDir = outputDir;
|
|
88
111
|
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
112
|
this.pages = [];
|
|
113
|
+
this.sitemapLocation = sitemapLocation;
|
|
97
114
|
}
|
|
98
|
-
async
|
|
99
|
-
this.
|
|
115
|
+
async prepareOutputDir() {
|
|
116
|
+
nunjucks.configure(this.views, {
|
|
117
|
+
autoescape: true
|
|
118
|
+
});
|
|
119
|
+
await emptyDirectory(this.outputDir);
|
|
120
|
+
fs2.copySync(this.staticDir, this.outputDir);
|
|
100
121
|
}
|
|
101
|
-
async
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
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
|
-
}
|
|
122
|
+
async processSources() {
|
|
123
|
+
if (!this.sitemap) {
|
|
124
|
+
throw new Error("Sitemap must be acquired before processing sources.");
|
|
125
|
+
}
|
|
126
|
+
for (const source of this.sitemap) {
|
|
127
|
+
await this.processSource(source);
|
|
113
128
|
}
|
|
114
129
|
}
|
|
115
|
-
async
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
130
|
+
async copySourceToTmp(source) {
|
|
131
|
+
if ("file" in source) {
|
|
132
|
+
const resolvedPath = path2.resolve(source.file);
|
|
133
|
+
console.log(`Processing dir ${resolvedPath}`);
|
|
134
|
+
fs2.copySync(resolvedPath, "./tmp");
|
|
135
|
+
} else if ("github" in source) {
|
|
136
|
+
console.log(`Processing repo ${source.github}`);
|
|
137
|
+
await clone(source.github, this.githubToken);
|
|
138
|
+
} else if ("folder" in source) {
|
|
139
|
+
throw new Error("Folders are not yet supported");
|
|
119
140
|
}
|
|
120
|
-
this.repos = [];
|
|
121
141
|
}
|
|
122
|
-
async
|
|
123
|
-
|
|
124
|
-
await clone(repo_info.clone_url, this.githubToken);
|
|
142
|
+
async processSource(source) {
|
|
143
|
+
await this.copySourceToTmp(source);
|
|
125
144
|
const manifest = JSON.parse(
|
|
126
145
|
fs2.readFileSync("./tmp/swa_manifest.json", "utf8")
|
|
127
146
|
);
|
|
@@ -142,74 +161,103 @@ var RepoProcessor = class {
|
|
|
142
161
|
tile
|
|
143
162
|
});
|
|
144
163
|
}
|
|
145
|
-
|
|
164
|
+
fetchSitemap() {
|
|
165
|
+
this.sitemap = fs2.readJSONSync(this.sitemapLocation);
|
|
166
|
+
}
|
|
167
|
+
renderHomepage() {
|
|
146
168
|
const indexHtml = nunjucks.render("index.njk", { tiles: this.pages });
|
|
147
169
|
fs2.writeFileSync(`${this.outputDir}/index.html`, indexHtml, "utf8");
|
|
148
170
|
}
|
|
149
171
|
async process() {
|
|
150
|
-
await this.
|
|
151
|
-
|
|
152
|
-
this.
|
|
172
|
+
await this.prepareOutputDir();
|
|
173
|
+
this.fetchSitemap();
|
|
174
|
+
await this.processSources();
|
|
175
|
+
this.renderHomepage();
|
|
153
176
|
}
|
|
154
177
|
};
|
|
155
178
|
|
|
156
|
-
// src/
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
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;
|
|
179
|
+
// src/commands.ts
|
|
180
|
+
import path3 from "path";
|
|
181
|
+
import fs3 from "fs-extra";
|
|
182
|
+
async function compileCommand(args) {
|
|
183
|
+
const token = args.github_token || process.env.GITHUB_TOKEN;
|
|
184
|
+
if (args.username && !token) {
|
|
185
|
+
console.warn("(!) No GitHub token \u2014 API may be rate limited");
|
|
186
|
+
}
|
|
187
|
+
const processor = new SiteProcessor(
|
|
188
|
+
path3.resolve(args.views),
|
|
189
|
+
path3.resolve(args.static),
|
|
190
|
+
path3.resolve(args.output),
|
|
191
|
+
path3.resolve(args.sitemap),
|
|
192
|
+
token
|
|
193
|
+
);
|
|
194
|
+
console.log("Starting build...");
|
|
195
|
+
await processor.process();
|
|
196
|
+
console.log("Done! Output \u2192", args.output);
|
|
197
|
+
}
|
|
198
|
+
async function sourceCommand(args) {
|
|
199
|
+
if (!args.username) {
|
|
200
|
+
throw new Error("(!) Username is required for downloading a sitemap from github");
|
|
209
201
|
}
|
|
202
|
+
const sitemap = await generateSitemapFromGithub(args.username, args.github_token);
|
|
203
|
+
fs3.writeJSONSync("sitemap.json", sitemap);
|
|
210
204
|
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
205
|
+
|
|
206
|
+
// src/cli.ts
|
|
207
|
+
var sharedOptions = {
|
|
208
|
+
config: {
|
|
209
|
+
alias: "c",
|
|
210
|
+
type: "string",
|
|
211
|
+
default: "config.json",
|
|
212
|
+
description: "Path to config file",
|
|
213
|
+
normalize: true,
|
|
214
|
+
config: true
|
|
215
|
+
},
|
|
216
|
+
"github_token": {
|
|
217
|
+
type: "string",
|
|
218
|
+
description: "GitHub token (also reads GITHUB_TOKEN env var)"
|
|
219
|
+
},
|
|
220
|
+
username: {
|
|
221
|
+
alias: "u",
|
|
222
|
+
type: "string",
|
|
223
|
+
description: "GitHub username (required for GitHub features)"
|
|
224
|
+
},
|
|
225
|
+
views: {
|
|
226
|
+
type: "string",
|
|
227
|
+
default: "./views",
|
|
228
|
+
description: "Nunjucks templates directory",
|
|
229
|
+
normalize: true
|
|
230
|
+
},
|
|
231
|
+
static: {
|
|
232
|
+
type: "string",
|
|
233
|
+
default: "./static_src",
|
|
234
|
+
description: "Static assets source directory",
|
|
235
|
+
normalize: true
|
|
236
|
+
},
|
|
237
|
+
sitemap: {
|
|
238
|
+
type: "string",
|
|
239
|
+
default: "./sitemap.json",
|
|
240
|
+
description: "Sitemap JSON file",
|
|
241
|
+
normalize: true
|
|
242
|
+
},
|
|
243
|
+
output: {
|
|
244
|
+
alias: "o",
|
|
245
|
+
type: "string",
|
|
246
|
+
default: "./static",
|
|
247
|
+
description: "Build output directory",
|
|
248
|
+
normalize: true
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
yargs(hideBin(process.argv)).scriptName("static-anthology").usage("Usage: $0 <command> [options]").command({
|
|
252
|
+
command: "compile",
|
|
253
|
+
aliases: ["$0"],
|
|
254
|
+
describe: "Build the static site from sitemap + templates",
|
|
255
|
+
builder: (yargs2) => yargs2.options(sharedOptions),
|
|
256
|
+
handler: compileCommand
|
|
257
|
+
}).command({
|
|
258
|
+
command: "source",
|
|
259
|
+
describe: "Generate sitemap from github",
|
|
260
|
+
builder: (yargs2) => yargs2.options(sharedOptions),
|
|
261
|
+
handler: sourceCommand
|
|
262
|
+
}).help().alias("help", "h").version().recommendCommands().showHelpOnFail(false).parse();
|
|
215
263
|
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +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"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/utils.ts","../src/githubApi.ts","../src/sitemapGen.ts","../src/siteProcessor.ts","../src/commands.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport yargs from 'yargs';\nimport { hideBin } from 'yargs/helpers';\nimport { compileCommand, sourceCommand } from './commands.js';\n\nconst sharedOptions = {\n config: {\n alias: 'c',\n type: 'string',\n default: 'config.json',\n description: 'Path to config file',\n normalize: true,\n config: true,\n },\n 'github_token': {\n type: 'string',\n description: 'GitHub token (also reads GITHUB_TOKEN env var)',\n },\n username: {\n alias: 'u',\n type: 'string',\n description: 'GitHub username (required for GitHub features)',\n },\n views: {\n type: 'string',\n default: './views',\n description: 'Nunjucks templates directory',\n normalize: true,\n },\n static: {\n type: 'string',\n default: './static_src',\n description: 'Static assets source directory',\n normalize: true,\n },\n sitemap: {\n type: 'string',\n default: './sitemap.json',\n description: 'Sitemap JSON file',\n normalize: true,\n },\n output: {\n alias: 'o',\n type: 'string',\n default: './static',\n description: 'Build output directory',\n normalize: true,\n },\n} as const;\n\nyargs(hideBin(process.argv))\n .scriptName('static-anthology')\n .usage('Usage: $0 <command> [options]')\n .command({\n command: 'compile',\n aliases: ['$0'],\n describe: 'Build the static site from sitemap + templates',\n builder: (yargs) => yargs.options(sharedOptions),\n handler: compileCommand as any,\n })\n .command({\n command: 'source',\n describe: 'Generate sitemap from github',\n builder: (yargs) => yargs.options(sharedOptions),\n handler: sourceCommand as any,\n })\n .help()\n .alias('help', 'h')\n .version()\n .recommendCommands()\n .showHelpOnFail(false)\n .parse();","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';\nimport path from 'path';\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 = path.resolve('./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","\n/**\n * Utilities for generating sitemap files. These tools are run via separate commands \n * compared to the compilation process.\n */\n\nimport { getRepos, isStaticWebApp } from \"./githubApi.js\";\nimport { Repo } from \"./types/github.js\";\nimport { Sitemap } from \"./types/sitemapSource.js\";\n\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 async function generateSitemapFromGithub(user: string, token: string): Promise<Sitemap> {\n async function getStaticWebApps() {\n const filtered = [];\n const repos = await getRepos(user, token);\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, token)) {\n filtered.push(repo);\n }\n }\n return filtered;\n }\n\n const repos = await getStaticWebApps()\n repos.sort(repoComparator).reverse(); // Sort from newest to oldest\n\n return repos.map(repo => ({\n \"github\": repo.clone_url\n }))\n}\n","import fs from 'fs-extra';\nimport nunjucks from 'nunjucks';\n\nimport path from 'path';\n\nimport { clone } from './githubApi.js';\nimport { Manifest } from './types/manifest.js';\nimport { PageInfo } from './types/page.js';\nimport { Sitemap, SitemapSource } from './types/sitemapSource.js';\nimport { emptyDirectory, titleToDirectory } from './utils.js';\n\nexport default class SiteProcessor {\n views: string;\n staticDir: string;\n pages: PageInfo[];\n outputDir: string;\n sitemapLocation: string;\n githubToken?: string;\n sitemap?: Sitemap;\n \n constructor(\n views: string,\n staticDir: string,\n outputDir: string,\n sitemapLocation: string,\n githubToken?: string,\n ) {\n this.views = views;\n this.staticDir = staticDir;\n this.outputDir = outputDir;\n this.githubToken = githubToken;\n this.pages = [];\n this.sitemapLocation = sitemapLocation;\n }\n\n async prepareOutputDir() {\n nunjucks.configure(this.views, {\n autoescape: true,\n });\n await emptyDirectory(this.outputDir);\n fs.copySync(this.staticDir, this.outputDir);\n }\n\n async processSources() {\n if (!this.sitemap) {\n throw new Error('Sitemap must be acquired before processing sources.')\n }\n\n for (const source of this.sitemap) {\n await this.processSource(source);\n }\n }\n\n async copySourceToTmp(source: SitemapSource) {\n if ('file' in source) {\n const resolvedPath = path.resolve(source.file)\n console.log(`Processing dir ${resolvedPath}`)\n fs.copySync(resolvedPath, './tmp')\n } else if ('github' in source) {\n console.log(`Processing repo ${source.github}`);\n await clone(source.github, this.githubToken);\n } else if ('folder' in source) {\n throw new Error('Folders are not yet supported')\n }\n }\n\n async processSource(source: SitemapSource) {\n await this.copySourceToTmp(source)\n\n // Now we have a local copy of the source. 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 fetchSitemap() {\n this.sitemap = fs.readJSONSync(this.sitemapLocation)\n }\n\n renderHomepage() {\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.prepareOutputDir()\n this.fetchSitemap();\n await this.processSources();\n this.renderHomepage();\n }\n\n}\n","import { generateSitemapFromGithub } from \"./sitemapGen.js\";\nimport SiteProcessor from \"./siteProcessor.js\";\nimport { Args } from \"./types/args.js\";\nimport path from 'path' \nimport fs from 'fs-extra'\n\nexport async function compileCommand(args: Args) {\n const token = args.github_token || process.env.GITHUB_TOKEN;\n\n if (args.username && !token) {\n console.warn('(!) No GitHub token — API may be rate limited');\n }\n\n const processor = new SiteProcessor(\n path.resolve(args.views as string),\n path.resolve(args.static as string),\n path.resolve(args.output as string),\n path.resolve(args.sitemap as string),\n token\n );\n\n console.log('Starting build...');\n await processor.process();\n console.log('Done! Output →', args.output);\n}\n\nexport async function sourceCommand(args: Args) {\n if (!args.username) {\n throw new Error('(!) Username is required for downloading a sitemap from github')\n }\n const sitemap = await generateSitemapFromGithub(args.username, args.github_token)\n fs.writeJSONSync('sitemap.json', sitemap)\n}"],"mappings":"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","names":["path","repos","fs","path","fs","path","path","fs","yargs"]}
|