@hutusi/amytis 1.14.0 → 1.15.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/.github/workflows/ci.yml +1 -1
- package/.github/workflows/publish.yml +2 -2
- package/CHANGELOG.md +16 -0
- package/README.md +33 -1
- package/README.zh.md +33 -1
- package/TODO.md +10 -0
- package/bun.lock +69 -41
- package/content/series/rst-legacy/deeper-notes/images/test.svg +4 -0
- package/content/series/rst-legacy/deeper-notes/index.rst +15 -0
- package/content/series/rst-legacy/getting-started.rst +24 -0
- package/content/series/rst-legacy/index.rst +9 -0
- package/content/series/rst-readme/README.rst +9 -0
- package/content/series/rst-readme/readme-index-post.rst +10 -0
- package/content/series/rst-toctree/first-post.rst +6 -0
- package/content/series/rst-toctree/index.rst +10 -0
- package/content/series/rst-toctree/second-post.rst +6 -0
- package/content/series/rst-toctree-precedence/first-post.rst +6 -0
- package/content/series/rst-toctree-precedence/index.rst +12 -0
- package/content/series/rst-toctree-precedence/second-post.rst +6 -0
- package/docs/ARCHITECTURE.md +22 -3
- package/docs/CONTRIBUTING.md +11 -0
- package/eslint.config.mjs +2 -0
- package/next.config.ts +2 -2
- package/package.json +22 -16
- package/packages/create-amytis/package.json +1 -1
- package/packages/create-amytis/src/index.test.ts +43 -1
- package/packages/create-amytis/src/index.ts +64 -8
- package/public/next-image-export-optimizer-hashes.json +14 -73
- package/scripts/build-pagefind.ts +172 -0
- package/scripts/copy-assets.ts +246 -56
- package/scripts/generate-knowledge-graph.ts +2 -1
- package/scripts/render-rst.py +719 -0
- package/scripts/run-with-rst-python.ts +42 -0
- package/src/app/[slug]/[postSlug]/page.tsx +20 -10
- package/src/app/[slug]/page/[page]/page.tsx +15 -0
- package/src/app/globals.css +165 -0
- package/src/app/series/[slug]/page/[page]/page.tsx +74 -6
- package/src/app/series/[slug]/page.tsx +11 -13
- package/src/app/series/page.tsx +3 -3
- package/src/components/AuthorCard.tsx +25 -16
- package/src/components/CoverImage.tsx +5 -2
- package/src/components/MarkdownRenderer.test.tsx +16 -0
- package/src/components/MarkdownRenderer.tsx +4 -1
- package/src/components/RstRenderer.test.tsx +93 -0
- package/src/components/RstRenderer.tsx +122 -0
- package/src/layouts/PostLayout.tsx +5 -1
- package/src/layouts/SimpleLayout.tsx +10 -3
- package/src/lib/image-utils.test.ts +19 -0
- package/src/lib/image-utils.ts +11 -0
- package/src/lib/markdown.test.ts +140 -2
- package/src/lib/markdown.ts +731 -210
- package/src/lib/rehype-image-metadata.ts +2 -2
- package/src/lib/rst-renderer.test.ts +355 -0
- package/src/lib/rst-renderer.ts +617 -0
- package/src/lib/rst.test.ts +140 -0
- package/src/lib/rst.ts +470 -0
- package/src/lib/series-redirects.ts +42 -0
- package/tests/integration/feed-utils.test.ts +13 -0
- package/tests/integration/reading-time-headings.test.ts +5 -9
- package/tests/integration/series-draft.test.ts +16 -2
- package/tests/integration/series.test.ts +93 -0
- package/tests/tooling/build-pagefind.test.ts +66 -0
- package/tests/unit/static-params.test.ts +140 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
Getting Started With rST
|
|
2
|
+
========================
|
|
3
|
+
|
|
4
|
+
:date: 2026-01-03
|
|
5
|
+
:excerpt: A simple rST-based post inside a legacy series.
|
|
6
|
+
:category: Legacy
|
|
7
|
+
:tags: rst, migration
|
|
8
|
+
:authors: John Hu
|
|
9
|
+
:redirectFrom: /posts/getting-started-rst
|
|
10
|
+
|
|
11
|
+
Intro paragraph with an inline link to `Amytis <https://github.com/hutusi/amytis>`_.
|
|
12
|
+
|
|
13
|
+
Overview
|
|
14
|
+
--------
|
|
15
|
+
|
|
16
|
+
- Keep the routing layer unchanged.
|
|
17
|
+
- Parse the source format at the series boundary.
|
|
18
|
+
|
|
19
|
+
Code Sample
|
|
20
|
+
~~~~~~~~~~~
|
|
21
|
+
|
|
22
|
+
.. code-block:: ts
|
|
23
|
+
|
|
24
|
+
export const feature = "rst";
|
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
# Architecture Overview
|
|
2
2
|
|
|
3
|
-
Amytis is a static-export-first Next.js 16 App Router project for Markdown/MDX publishing across posts, series, books, flows, and notes.
|
|
3
|
+
Amytis is a static-export-first Next.js 16 App Router project for Markdown/MDX publishing across posts, series, books, flows, and notes, with optional series-scoped rST support for legacy content.
|
|
4
4
|
|
|
5
5
|
## Core Stack
|
|
6
6
|
|
|
7
|
-
- Framework: Next.js 16.1
|
|
7
|
+
- Framework: Next.js 16.2.1 + React 19
|
|
8
8
|
- Runtime/tooling: Bun
|
|
9
9
|
- Styling: Tailwind CSS v4 + CSS variables + `next-themes`
|
|
10
10
|
- Content parsing: `gray-matter` + Zod validation in `src/lib/markdown.ts`
|
|
11
|
+
- rST rendering: Python `docutils` bridge in `scripts/render-rst.py` plus normalization in `src/lib/rst-renderer.ts`
|
|
11
12
|
- Search: Pagefind (`/pagefind/pagefind.js` loaded at runtime)
|
|
12
13
|
- Tests: Bun test suites in `src/` and `tests/`
|
|
13
14
|
|
|
14
15
|
## Content Model
|
|
15
16
|
|
|
16
17
|
- `content/posts/`: standalone posts (`.md/.mdx`) and folder posts (`index.mdx`)
|
|
17
|
-
- `content/series/<slug>/`: series metadata (`index.mdx`) + series posts
|
|
18
|
+
- `content/series/<slug>/`: series metadata (`index.mdx` / `index.md` / `README.mdx` / `README.md` / `index.rst` / `README.rst`) + series posts in the same format
|
|
18
19
|
- `content/books/<slug>/`: book metadata + chapter files
|
|
19
20
|
- `content/flows/YYYY/MM/DD.(md|mdx)`: daily flow entries
|
|
20
21
|
- `content/notes/`: evergreen notes
|
|
@@ -27,6 +28,8 @@ Amytis is a static-export-first Next.js 16 App Router project for Markdown/MDX p
|
|
|
27
28
|
3. Draft/future filtering and sorting are applied (based on `site.config.ts`).
|
|
28
29
|
4. Route files consume typed helpers (`getAllPosts`, `getBookData`, `getAllFlows`, `getAllNotes`, etc.).
|
|
29
30
|
5. `generateStaticParams()` precomputes dynamic routes for static export.
|
|
31
|
+
6. Series content format is inferred from the series index file; ambiguous or mixed-format series fail fast during content loading.
|
|
32
|
+
7. When `docutils` is available, rST files are rendered to HTML through the Python bridge; if the Python runtime is unavailable, Amytis falls back to the lightweight built-in rST compatibility path.
|
|
30
33
|
|
|
31
34
|
## Route Map (App Router)
|
|
32
35
|
|
|
@@ -75,10 +78,16 @@ src/app/
|
|
|
75
78
|
## URL Routing Rules
|
|
76
79
|
|
|
77
80
|
- `next.config.ts` sets `output: "export"` and `trailingSlash: true`.
|
|
81
|
+
- Series format is inferred from the index file:
|
|
82
|
+
- Markdown series: `index.md`, `index.mdx`, `README.md`, or `README.mdx`
|
|
83
|
+
- rST series: `index.rst` or `README.rst`
|
|
84
|
+
- A series may not mix Markdown and rST content files; ambiguous or mixed layouts are treated as build errors.
|
|
78
85
|
- Post URLs use `getPostUrl()` in `src/lib/urls.ts`:
|
|
79
86
|
- Default: `/<posts.basePath>/<post.slug>` (basePath defaults to `posts`)
|
|
80
87
|
- Series auto path: `/<series.slug>/<post.slug>` when `series.autoPaths` is enabled
|
|
81
88
|
- Series override: `/<series.customPaths[seriesSlug]>/<post.slug>`
|
|
89
|
+
- Legacy aliases declared in frontmatter `redirectFrom` are emitted as static redirect pages, so old URLs can continue resolving after a rename or path migration.
|
|
90
|
+
- Dynamic route handlers validate whether a request is canonical or legacy, then either render the content or return `RedirectPage`.
|
|
82
91
|
- Dynamic route params should return raw segment values from `generateStaticParams()` (do not pre-encode values).
|
|
83
92
|
- Links should always target concrete paths, not route placeholders such as `/posts/[slug]`.
|
|
84
93
|
- When moving series posts off the default posts path, `scripts/add-series-redirects.ts` updates frontmatter `redirectFrom` entries so static redirect pages can be generated.
|
|
@@ -99,6 +108,16 @@ src/app/
|
|
|
99
108
|
- Notes: `getAllNotes`, `getNoteBySlug`, `getNotesByTag`
|
|
100
109
|
- Discovery: `buildSlugRegistry`, `getBacklinks`, `getAllTags`, `getAllAuthors`
|
|
101
110
|
|
|
111
|
+
## rST Notes
|
|
112
|
+
|
|
113
|
+
- Full-fidelity rST rendering depends on a Python environment with `docutils` (and ideally `pygments`) available.
|
|
114
|
+
- `src/lib/rst-renderer.ts` uses `AMYTIS_RST_PYTHON` when set; otherwise it falls back to `python3`.
|
|
115
|
+
- Top-of-document docinfo is parsed into Amytis metadata, but it is stripped from rendered article HTML so blog-style posts do not show duplicate author/version blocks above the content.
|
|
116
|
+
- Supported legacy roles are normalized or degraded intentionally:
|
|
117
|
+
- `:doc:` resolves to local site URLs when the target exists in the imported content tree
|
|
118
|
+
- `:ref:` / `:numref:` prefer local anchors
|
|
119
|
+
- unresolved legacy roles degrade to readable inline HTML instead of docutils system-message blocks
|
|
120
|
+
|
|
102
121
|
## Build Pipeline
|
|
103
122
|
|
|
104
123
|
1. `bun scripts/copy-assets.ts`: copy co-located media into `public/`
|
package/docs/CONTRIBUTING.md
CHANGED
|
@@ -47,6 +47,17 @@ bun run new-flow
|
|
|
47
47
|
bun run new-series "My Series Name"
|
|
48
48
|
```
|
|
49
49
|
|
|
50
|
+
Series are format-scoped:
|
|
51
|
+
|
|
52
|
+
- Markdown series use `content/series/<slug>/index.mdx` or `index.md`
|
|
53
|
+
- Markdown series may also use `README.mdx` or `README.md`
|
|
54
|
+
- rST series use `content/series/<slug>/index.rst` or `README.rst`
|
|
55
|
+
- Child posts inside the series must use the same format as the index file
|
|
56
|
+
- Mixed Markdown and rST files in one series are treated as build errors
|
|
57
|
+
- For full-fidelity rST rendering, install `docutils` (and `pygments` for code highlighting) in a Python environment available to the project
|
|
58
|
+
- If needed, set `AMYTIS_RST_PYTHON=/absolute/path/to/python` so Amytis uses a specific interpreter
|
|
59
|
+
- Without Python/docutils, Amytis falls back to a lightweight compatibility parser; that keeps loading/building working, but some legacy rST constructs will render with lower fidelity
|
|
60
|
+
|
|
50
61
|
### Creating Books
|
|
51
62
|
|
|
52
63
|
Books are manually structured in `content/books/`.
|
package/eslint.config.mjs
CHANGED
package/next.config.ts
CHANGED
|
@@ -15,8 +15,8 @@ const nextConfig: NextConfig = {
|
|
|
15
15
|
output: "export",
|
|
16
16
|
images: {
|
|
17
17
|
loader: "custom",
|
|
18
|
-
imageSizes: [
|
|
19
|
-
deviceSizes: [640,
|
|
18
|
+
imageSizes: [64, 128, 256],
|
|
19
|
+
deviceSizes: [640, 1200, 1920],
|
|
20
20
|
},
|
|
21
21
|
transpilePackages: ["next-image-export-optimizer"],
|
|
22
22
|
env: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hutusi/amytis",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.15.0",
|
|
4
4
|
"description": "A high-performance digital garden and blog engine with Next.js 16 and Tailwind CSS v4",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -11,14 +11,18 @@
|
|
|
11
11
|
},
|
|
12
12
|
"homepage": "https://github.com/hutusi/amytis#readme",
|
|
13
13
|
"private": false,
|
|
14
|
-
"packageManager": "bun@1.3.
|
|
14
|
+
"packageManager": "bun@1.3.11",
|
|
15
15
|
"scripts": {
|
|
16
|
-
"dev": "next dev",
|
|
17
|
-
"build": "bun scripts/copy-assets.ts && bun run build:graph && next build && next-image-export-optimizer &&
|
|
18
|
-
"build:dev": "bun scripts/copy-assets.ts && bun run build:graph && next build &&
|
|
16
|
+
"dev": "bun scripts/run-with-rst-python.ts next dev",
|
|
17
|
+
"build": "bun scripts/copy-assets.ts && bun run build:graph && bun scripts/run-with-rst-python.ts next build && next-image-export-optimizer && bun run build:search",
|
|
18
|
+
"build:dev": "bun scripts/copy-assets.ts && bun run build:graph && bun scripts/run-with-rst-python.ts next build && bun run build:search:dev",
|
|
19
19
|
"build:graph": "NODE_ENV=production bun scripts/generate-knowledge-graph.ts",
|
|
20
|
+
"build:search": "bun scripts/build-pagefind.ts --site out --output-path out/pagefind",
|
|
21
|
+
"build:search:dev": "bun scripts/build-pagefind.ts --site out --output-path public/pagefind",
|
|
22
|
+
"build:search:cli": "pagefind --site out",
|
|
23
|
+
"build:search:cli:dev": "pagefind --site out --output-path public/pagefind",
|
|
20
24
|
"validate": "bun run lint && bun run test && bun run build:dev",
|
|
21
|
-
"clean": "rm -rf .next out public/posts public/books public/flows",
|
|
25
|
+
"clean": "rm -rf .next out public/posts public/books public/flows public/images/nextImageExportOptimizer",
|
|
22
26
|
"new": "bun scripts/new-post.ts",
|
|
23
27
|
"new-weekly": "bun scripts/new-post.ts --series ai-nexus-weekly --md --folder --prefix weekly",
|
|
24
28
|
"new-series": "bun scripts/new-series.ts",
|
|
@@ -48,13 +52,13 @@
|
|
|
48
52
|
"github-slugger": "^2.0.0",
|
|
49
53
|
"gray-matter": "^4.0.3",
|
|
50
54
|
"image-size": "^2.0.2",
|
|
51
|
-
"katex": "^0.16.
|
|
52
|
-
"mermaid": "^11.
|
|
53
|
-
"next": "16.2.
|
|
55
|
+
"katex": "^0.16.45",
|
|
56
|
+
"mermaid": "^11.14.0",
|
|
57
|
+
"next": "16.2.3",
|
|
54
58
|
"next-image-export-optimizer": "^1.20.1",
|
|
55
59
|
"next-themes": "^0.4.6",
|
|
56
|
-
"react": "19.2.
|
|
57
|
-
"react-dom": "19.2.
|
|
60
|
+
"react": "19.2.5",
|
|
61
|
+
"react-dom": "19.2.5",
|
|
58
62
|
"react-icons": "^5.6.0",
|
|
59
63
|
"react-markdown": "^10.1.0",
|
|
60
64
|
"react-syntax-highlighter": "^16.1.1",
|
|
@@ -66,26 +70,28 @@
|
|
|
66
70
|
"remark-math": "^6.0.0",
|
|
67
71
|
"remark-parse": "^11.0.0",
|
|
68
72
|
"remark-rehype": "^11.1.2",
|
|
73
|
+
"sanitize-html": "^2.17.2",
|
|
69
74
|
"unified": "^11.0.5",
|
|
70
75
|
"unist-util-visit": "^5.1.0",
|
|
71
76
|
"zod": "^4.3.6"
|
|
72
77
|
},
|
|
73
78
|
"devDependencies": {
|
|
74
|
-
"@playwright/test": "^1.
|
|
79
|
+
"@playwright/test": "^1.59.1",
|
|
75
80
|
"@tailwindcss/postcss": "^4.2.2",
|
|
76
|
-
"@types/bun": "^1.3.
|
|
81
|
+
"@types/bun": "^1.3.12",
|
|
77
82
|
"@types/d3": "^7.4.3",
|
|
78
83
|
"@types/hast": "^3.0.4",
|
|
79
84
|
"@types/image-size": "^0.8.0",
|
|
80
85
|
"@types/mdast": "^4.0.4",
|
|
81
|
-
"@types/node": "^24.12.
|
|
86
|
+
"@types/node": "^24.12.2",
|
|
82
87
|
"@types/react": "^19.2.14",
|
|
83
88
|
"@types/react-dom": "^19.2.3",
|
|
84
89
|
"@types/react-syntax-highlighter": "^15.5.13",
|
|
90
|
+
"@types/sanitize-html": "^2.16.1",
|
|
85
91
|
"babel-plugin-react-compiler": "1.0.0",
|
|
86
92
|
"eslint": "^9.39.4",
|
|
87
|
-
"eslint-config-next": "16.2.
|
|
88
|
-
"pagefind": "^1.
|
|
93
|
+
"eslint-config-next": "16.2.3",
|
|
94
|
+
"pagefind": "^1.5.0",
|
|
89
95
|
"pdf-to-img": "^5.0.0",
|
|
90
96
|
"tailwindcss": "^4.2.2",
|
|
91
97
|
"typescript": "^5.9.3"
|
|
@@ -2,7 +2,7 @@ import { describe, test, expect, afterAll } from "bun:test";
|
|
|
2
2
|
import * as fs from "fs";
|
|
3
3
|
import * as os from "os";
|
|
4
4
|
import * as path from "path";
|
|
5
|
-
import { patchSiteConfig, patchPackageJson } from "./index";
|
|
5
|
+
import { buildExtractCommand, getArchiveMetadata, patchSiteConfig, patchPackageJson } from "./index";
|
|
6
6
|
|
|
7
7
|
// Minimal site.config.ts that mirrors the real file's patchable fields.
|
|
8
8
|
// Inner backticks and `${` are escaped so they appear literally in the string.
|
|
@@ -185,3 +185,45 @@ describe("patchPackageJson", () => {
|
|
|
185
185
|
expect(() => patchPackageJson(dir, "my-garden")).not.toThrow();
|
|
186
186
|
});
|
|
187
187
|
});
|
|
188
|
+
|
|
189
|
+
describe("getArchiveMetadata", () => {
|
|
190
|
+
test("uses zip archives on Windows", () => {
|
|
191
|
+
const archive = getArchiveMetadata("v1.13.0", "win32");
|
|
192
|
+
expect(archive.kind).toBe("zip");
|
|
193
|
+
expect(archive.filename).toBe("amytis-v1.13.0.zip");
|
|
194
|
+
expect(archive.url).toBe("https://github.com/hutusi/amytis/archive/refs/tags/v1.13.0.zip");
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
test("uses tar.gz archives on non-Windows platforms", () => {
|
|
198
|
+
const archive = getArchiveMetadata("v1.13.0", "darwin");
|
|
199
|
+
expect(archive.kind).toBe("tar.gz");
|
|
200
|
+
expect(archive.filename).toBe("amytis-v1.13.0.tar.gz");
|
|
201
|
+
expect(archive.url).toBe("https://github.com/hutusi/amytis/archive/refs/tags/v1.13.0.tar.gz");
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
describe("buildExtractCommand", () => {
|
|
206
|
+
test("builds the PowerShell Expand-Archive command on Windows", () => {
|
|
207
|
+
const command = buildExtractCommand("C:\\tmp\\amytis-v1.13.0.zip", "C:\\tmp\\my-garden.__tmp__", "zip", "win32");
|
|
208
|
+
expect(command.command).toBe("powershell.exe");
|
|
209
|
+
expect(command.args).toEqual([
|
|
210
|
+
"-NoProfile",
|
|
211
|
+
"-NonInteractive",
|
|
212
|
+
"-ExecutionPolicy",
|
|
213
|
+
"Bypass",
|
|
214
|
+
"-Command",
|
|
215
|
+
"Expand-Archive",
|
|
216
|
+
"-LiteralPath",
|
|
217
|
+
"C:\\tmp\\amytis-v1.13.0.zip",
|
|
218
|
+
"-DestinationPath",
|
|
219
|
+
"C:\\tmp\\my-garden.__tmp__",
|
|
220
|
+
"-Force",
|
|
221
|
+
]);
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
test("builds the tar extraction command on non-Windows platforms", () => {
|
|
225
|
+
const command = buildExtractCommand("/tmp/amytis-v1.13.0.tar.gz", "/tmp/my-garden.__tmp__", "tar.gz", "darwin");
|
|
226
|
+
expect(command.command).toBe("tar");
|
|
227
|
+
expect(command.args).toEqual(["xzf", "/tmp/amytis-v1.13.0.tar.gz", "-C", "/tmp/my-garden.__tmp__"]);
|
|
228
|
+
});
|
|
229
|
+
});
|
|
@@ -4,7 +4,7 @@ import * as fs from "fs";
|
|
|
4
4
|
import * as path from "path";
|
|
5
5
|
import * as https from "https";
|
|
6
6
|
import * as readline from "readline";
|
|
7
|
-
import { execSync } from "child_process";
|
|
7
|
+
import { execFileSync, execSync } from "child_process";
|
|
8
8
|
|
|
9
9
|
// ---------------------------------------------------------------------------
|
|
10
10
|
// Helpers
|
|
@@ -77,11 +77,67 @@ function downloadFile(url: string, dest: string): Promise<void> {
|
|
|
77
77
|
});
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
function
|
|
80
|
+
export function getArchiveMetadata(tag: string, platform: NodeJS.Platform = process.platform): {
|
|
81
|
+
url: string;
|
|
82
|
+
filename: string;
|
|
83
|
+
kind: "zip" | "tar.gz";
|
|
84
|
+
} {
|
|
85
|
+
if (platform === "win32") {
|
|
86
|
+
return {
|
|
87
|
+
url: `https://github.com/hutusi/amytis/archive/refs/tags/${tag}.zip`,
|
|
88
|
+
filename: `amytis-${tag}.zip`,
|
|
89
|
+
kind: "zip",
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return {
|
|
94
|
+
url: `https://github.com/hutusi/amytis/archive/refs/tags/${tag}.tar.gz`,
|
|
95
|
+
filename: `amytis-${tag}.tar.gz`,
|
|
96
|
+
kind: "tar.gz",
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function buildExtractCommand(
|
|
101
|
+
archivePath: string,
|
|
102
|
+
tmpDir: string,
|
|
103
|
+
kind: "zip" | "tar.gz",
|
|
104
|
+
platform: NodeJS.Platform = process.platform,
|
|
105
|
+
): { command: string; args: string[] } {
|
|
106
|
+
if (kind === "zip") {
|
|
107
|
+
if (platform !== "win32") {
|
|
108
|
+
throw new Error("ZIP extraction is only supported on Windows in create-amytis");
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return {
|
|
112
|
+
command: "powershell.exe",
|
|
113
|
+
args: [
|
|
114
|
+
"-NoProfile",
|
|
115
|
+
"-NonInteractive",
|
|
116
|
+
"-ExecutionPolicy",
|
|
117
|
+
"Bypass",
|
|
118
|
+
"-Command",
|
|
119
|
+
"Expand-Archive",
|
|
120
|
+
"-LiteralPath",
|
|
121
|
+
archivePath,
|
|
122
|
+
"-DestinationPath",
|
|
123
|
+
tmpDir,
|
|
124
|
+
"-Force",
|
|
125
|
+
],
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return {
|
|
130
|
+
command: "tar",
|
|
131
|
+
args: ["xzf", archivePath, "-C", tmpDir],
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function extractArchive(archivePath: string, outDir: string, kind: "zip" | "tar.gz", platform: NodeJS.Platform = process.platform): void {
|
|
81
136
|
// Extract into a temp dir, then move the inner folder out
|
|
82
137
|
const tmpDir = `${outDir}.__tmp__`;
|
|
83
138
|
fs.mkdirSync(tmpDir, { recursive: true });
|
|
84
|
-
|
|
139
|
+
const { command, args } = buildExtractCommand(archivePath, tmpDir, kind, platform);
|
|
140
|
+
execFileSync(command, args, { stdio: "inherit" });
|
|
85
141
|
|
|
86
142
|
// The tarball unpacks to a single top-level dir like "amytis-1.2.0/"
|
|
87
143
|
const entries = fs.readdirSync(tmpDir);
|
|
@@ -91,7 +147,7 @@ function extractTarball(tarPath: string, outDir: string): void {
|
|
|
91
147
|
const innerDir = path.join(tmpDir, entries[0]);
|
|
92
148
|
fs.renameSync(innerDir, outDir);
|
|
93
149
|
fs.rmdirSync(tmpDir);
|
|
94
|
-
fs.unlinkSync(
|
|
150
|
+
fs.unlinkSync(archivePath);
|
|
95
151
|
}
|
|
96
152
|
|
|
97
153
|
// ---------------------------------------------------------------------------
|
|
@@ -180,14 +236,14 @@ async function main(): Promise<void> {
|
|
|
180
236
|
console.log(` Found: ${tag}`);
|
|
181
237
|
|
|
182
238
|
// 3. Download tarball
|
|
183
|
-
const
|
|
184
|
-
const
|
|
239
|
+
const archive = getArchiveMetadata(tag);
|
|
240
|
+
const archiveDest = path.join(process.cwd(), archive.filename);
|
|
185
241
|
console.log("Downloading tarball...");
|
|
186
|
-
await downloadFile(
|
|
242
|
+
await downloadFile(archive.url, archiveDest);
|
|
187
243
|
|
|
188
244
|
// 4. Extract
|
|
189
245
|
console.log("Extracting...");
|
|
190
|
-
|
|
246
|
+
extractArchive(archiveDest, targetDir, archive.kind);
|
|
191
247
|
console.log(` Scaffolded: ${targetDir}`);
|
|
192
248
|
|
|
193
249
|
// 5-6. Prompt for site metadata
|
|
@@ -1,75 +1,16 @@
|
|
|
1
1
|
{
|
|
2
|
-
"
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"books/agentic-design-patterns/images/chapter-12/image1.png": "4e4AD2MJFSB3GByGxGVr4VCQ4H+eYkR3oq39KuZhzw8=",
|
|
17
|
-
"books/agentic-design-patterns/images/chapter-12/image2.png": "1MyjXYovLBeKJmUGnUnx38T-UgkhRfV5opzOcP+OEdw=",
|
|
18
|
-
"books/agentic-design-patterns/images/chapter-13/image1.png": "PB3msIGhOmq1Oyrv6ubGJZJCvO+dD7XNxZiw5Ck-834=",
|
|
19
|
-
"books/agentic-design-patterns/images/chapter-14/image1.png": "p-06-D2Vp2x7HMXwmkTNLneS9sjsfSvmTsLTlVUjY5k=",
|
|
20
|
-
"books/agentic-design-patterns/images/chapter-14/image2.png": "XvXKYbuijYChfq4+MlZYXLBpxTg11ddJ0AFnzvntLPw=",
|
|
21
|
-
"books/agentic-design-patterns/images/chapter-14/image3.png": "YhmOWyJo3pDKVbKW7RMgTbNrbmsE89RkmaJ2z76vhos=",
|
|
22
|
-
"books/agentic-design-patterns/images/chapter-14/image4.png": "QBNe+Wt65qdLfkC5MJqaiNBJGMa-DbCm3gCOqfB7ehk=",
|
|
23
|
-
"books/agentic-design-patterns/images/chapter-15/image1.png": "I90CSqCb8g-h1F0a3sDusDC+LmHdjJTBBk6iFw4ZnJY=",
|
|
24
|
-
"books/agentic-design-patterns/images/chapter-15/image2.png": "HaxOSZ1f67BhEPa3KXtYAlK0cNm3G4H24dnLXpcgyA0=",
|
|
25
|
-
"books/agentic-design-patterns/images/chapter-16/image1.png": "Blc0vDhlie6PM3f6QSUX3argbfezTNDOLYhmT9uuS6E=",
|
|
26
|
-
"books/agentic-design-patterns/images/chapter-16/image2.png": "9-KZ0VOekDwFVL1dEzB9aleyCYF+WU6bx1h3aVNoOAM=",
|
|
27
|
-
"books/agentic-design-patterns/images/chapter-17/image1.png": "jjGM2Ll5bdszl9xFThVxxJzcq76iYDM1zz8qq2MVVYE=",
|
|
28
|
-
"books/agentic-design-patterns/images/chapter-17/image2.png": "O1KLKrodQew2Pdd7k3vBZhE4dCiK9u6JLvXSXy7h1do=",
|
|
29
|
-
"books/agentic-design-patterns/images/chapter-17/image3.png": "Sd9qFn-U5g8dhinNPJEk5LaeaN8DFH2FCus1Wcm6oSg=",
|
|
30
|
-
"books/agentic-design-patterns/images/chapter-17/image4.png": "eV38Dg78Y2Qo-0sqlsvcK8-p19fgRJqwx42sBKTzC+s=",
|
|
31
|
-
"books/agentic-design-patterns/images/chapter-17/image5.png": "bgKPC1TSVlvfkCG5vILT-4j9gJU7LyeGFkXO+8OFdXE=",
|
|
32
|
-
"books/agentic-design-patterns/images/chapter-17/image6.png": "qMku-C8gxZEFQEl8Qq8Y1ld5zUntH1Q-2izcb4QxLA0=",
|
|
33
|
-
"books/agentic-design-patterns/images/chapter-17/image7.png": "20wopLVN59okB+C-F+U5vi79Lg0uH+5P6wIj72gV7wU=",
|
|
34
|
-
"books/agentic-design-patterns/images/chapter-18/image1.png": "kjCIoNU60icXMOHmYNXWNMjdi5nIdJZYDSp0WFnG2Es=",
|
|
35
|
-
"books/agentic-design-patterns/images/chapter-19/image1.png": "XrQVFAWWsMcwKHgcqx8jGLy4q+6RbiGZ5CuKpRlk4Y0=",
|
|
36
|
-
"books/agentic-design-patterns/images/chapter-19/image2.png": "URHY+cH5AR4KvA6HPnXPhZd5fwwGdlwvFvxgCdTkWjg=",
|
|
37
|
-
"books/agentic-design-patterns/images/chapter-19/image3.png": "VLp1qFNcaj126-RuATV6ikSsow8lrXsn3EuZotvR5N4=",
|
|
38
|
-
"books/agentic-design-patterns/images/chapter-19/image4.png": "CnyNMtPiFSdzqrewwLgPu2X1CKdgMqCl8T8+d7lw2Fw=",
|
|
39
|
-
"books/agentic-design-patterns/images/chapter-2/image1.png": "C6odPDB9zhN28YxfU909JAoQWe0mRm3lUsyG8NzHBWk=",
|
|
40
|
-
"books/agentic-design-patterns/images/chapter-20/image1.png": "qkzjKCUjVFD8IWyoZQXuBuZ4zFJ0Y0CQfKepVcrnEN0=",
|
|
41
|
-
"books/agentic-design-patterns/images/chapter-21/image1.png": "3KpW6uLQDru7DFDdgi6ntD5WhuGS383aYwlQLWoVX+w=",
|
|
42
|
-
"books/agentic-design-patterns/images/chapter-21/image2.png": "wSXMrRuAnhQcEM5fg-sJ5ZikM3olj0vz6FDKWKIUyW8=",
|
|
43
|
-
"books/agentic-design-patterns/images/chapter-3/image1.png": "iHnUE2kckwzB0xiIySSe4O34c6bIs3VlO7pUQBmV8iI=",
|
|
44
|
-
"books/agentic-design-patterns/images/chapter-3/image2.png": "9-G6F+aBymQVTnDQy4zwsXDZMkLaYKBe4xw26tC24R8=",
|
|
45
|
-
"books/agentic-design-patterns/images/chapter-4/image1.png": "8h0PBlqt+JFo7Y803cA9MgfTe8TZeZd6te9l+WEsIss=",
|
|
46
|
-
"books/agentic-design-patterns/images/chapter-4/image2.png": "p-arzpUPFdnKmzTOKaDQys5Eml0jHA7VuUV0FyLYpqM=",
|
|
47
|
-
"books/agentic-design-patterns/images/chapter-5/image1.png": "XE5qhAklrW-7eVf7T9x9vo4xQX3WesZjZ9IjuyeSUkc=",
|
|
48
|
-
"books/agentic-design-patterns/images/chapter-5/image2.png": "MqUdsG5aXQECft+lsCRTeMIJP-YzxWFHC8HdNzio6aw=",
|
|
49
|
-
"books/agentic-design-patterns/images/chapter-6/image1.png": "t6mFrbVSNJYF73t+Q+YydXdwRQr1c4yIUkySvCelw1I=",
|
|
50
|
-
"books/agentic-design-patterns/images/chapter-6/image2.png": "zvwqWis6Ad7Iv1-wgYtTgz2ItXsno2PetcHRHon0-wY=",
|
|
51
|
-
"books/agentic-design-patterns/images/chapter-6/image3.png": "al-H2S7UznxQzP3KT3N0lCTNd83B45bqbPppuhSphy0=",
|
|
52
|
-
"books/agentic-design-patterns/images/chapter-6/image4.png": "u2k2jHjTOABLTlJ3OsxkGyCoOR-fwHeDmTXMACbtQ+4=",
|
|
53
|
-
"books/agentic-design-patterns/images/chapter-7/image1.png": "izX9YjrJ+gHGOiR9RHbuMIupCE2zyB01w-gwJAJr4Is=",
|
|
54
|
-
"books/agentic-design-patterns/images/chapter-7/image2.png": "-0zrZR8CNZqtuyaBRwUbZSfthKwuqrBu4fLar9L4Clg=",
|
|
55
|
-
"books/agentic-design-patterns/images/chapter-7/image3.png": "dKr7VICWOTc-ZRhm4Aaokz+xPZ8IXS0SiDOJeF1Y03c=",
|
|
56
|
-
"books/agentic-design-patterns/images/chapter-8/image1.png": "GWG47Om+9GwRvl8x-X269Sa-Mv3rqkW2xkx1WIB-I-E=",
|
|
57
|
-
"books/agentic-design-patterns/images/chapter-9/image1.png": "fIZ4QE7EIQSAv0K2GmU99OmTBAkpvnYUsFFScCv6VPI=",
|
|
58
|
-
"books/agentic-design-patterns/images/chapter-9/image2.png": "6y-8OjY7oEedk5ZhUUU2YIU3tjMxIzpnxcDxIRWPGpI=",
|
|
59
|
-
"books/agentic-design-patterns/images/chapter-9/image3.png": "69nSkOOPfX9FkIJGhKIrhSuCOZt29L5UAukVXfMXN2E=",
|
|
60
|
-
"books/agentic-design-patterns/images/chapter-9/image4.png": "GQCpjBMz5DRxsHIA8-73IMsxeBPc5ZTMaIsx2iihMME=",
|
|
61
|
-
"books/agentic-design-patterns/images/cover.png": "R47dqw-ws79m6VBfzhWuLi9ihoCaU7JcezquBAB1-bQ=",
|
|
62
|
-
"images/amytis-screenshot.jpg": "t9tzciqJPsNz1hlixAFLrrvD4Fsaih2Kbd1Jd2C-fqs=",
|
|
63
|
-
"images/antelope-canyon.jpg": "xuP3HlbwqA4z1Hsq7s1u2u61yN3SHzIMUd6Wl5yqgK8=",
|
|
64
|
-
"images/avatar.jpg": "SUGxOhDUD96YiVxZJkVJ6ou4W5MdCJ9hTBQMSQanZOM=",
|
|
65
|
-
"images/cappadocia.jpg": "EE2Mt8d9ERKd40SfwyhjFsejZLhFx1SfSAQmlu+TQOo=",
|
|
66
|
-
"images/flowers.jpg": "Lq9dhpZvAIgkYnijDsFIzrKiv8trdM-cUnl-5Y86PuM=",
|
|
67
|
-
"images/galaxy.jpg": "-3YwMkU3PGsm4P2yNsA2S02XRL1j0KbBh6nWKwy0hYc=",
|
|
68
|
-
"images/lake.jpg": "imAORQhxpmoU3jzKBMNFJuFSa0UgiSf2Dmea5Rj8-8M=",
|
|
69
|
-
"images/mountains.jpg": "FsrkZws9EKMqHCk1Hc6i6nEIcTRcrMBa4ddgqR6oRaI=",
|
|
70
|
-
"images/screenshot.png": "FAqbAgLRbWbYq9yJ4iggq2aKxRD8hdeDICc3DI14yhg=",
|
|
71
|
-
"images/vibrant-waves.jpg": "vdBm72ev5ETPM5H2CDK6tqph5t8N5nTCSApBJp2lW6U=",
|
|
72
|
-
"images/wechat-qr.jpg": "DNIzz0Wcl8WP0h-jHHgZ9LEvf3ZKOXHgxlvpw3gK2ME=",
|
|
73
|
-
"posts/02-routing-mastery/assets/m-p-model.png": "fDmvlEkZnE-UCvPK4gmDkJD7SU8coOTl4iw5hpsmcWI=",
|
|
74
|
-
"posts/images/vibrant-waves.jpg": "YogfFJOm4PQV1g3iMRpCL1pKtjPXpMeJDFf6NTILcBQ="
|
|
2
|
+
"images/amytis-screenshot.jpg": "rWj-Nh3prlVpvj8efQnsSHJTSOOVzgz9PGnQRj98jXc=",
|
|
3
|
+
"images/antelope-canyon.jpg": "sub7CbOTPj1Vred2Ow9yJKMqjbP9+0nkjmmaaa5Di2k=",
|
|
4
|
+
"images/avatar.jpg": "4c7EI6nQ6UHOj9drx0D42heSmiYWTt0Gd3Nsri3BQeo=",
|
|
5
|
+
"images/cappadocia.jpg": "eDzJe+p3qkAP83ATa7x0m0od4LxwkZltWsVQ2s9rgDI=",
|
|
6
|
+
"images/flowers.jpg": "oxwbVQa8o5AcEu-vRbHj9o64BTZwCFxPOSA7D53n7tI=",
|
|
7
|
+
"images/galaxy.jpg": "yDGttkksBSUhLDWlVL2BFGg1al1+GHy3BXcEVp07bys=",
|
|
8
|
+
"images/lake.jpg": "NEaTNMMXdrgHLMU7CDEWEVwguVdv1E4y5FN8CMHqTvg=",
|
|
9
|
+
"images/mountains.jpg": "0YIE1wGkreZ1MzM8zGnXCQ9I-IcmA+zO52-dtfL4X94=",
|
|
10
|
+
"images/screenshot.png": "zuBVQ-P-dCmcM9tYPdDvixwAHo7rGTZQE1y+X4o2pJ4=",
|
|
11
|
+
"images/vibrant-waves.jpg": "uWywQzN1RbusnZFato8mb7pqvCUkAr4us50HU6rFYUg=",
|
|
12
|
+
"images/wechat-qr.jpg": "Vhxz8S8TDfXZUjB3M5o5jvis3hu2n8xJEdW3bPjtd+A=",
|
|
13
|
+
"posts/02-routing-mastery/assets/m-p-model.png": "LZQHFy9SfWdBHatT9DwrARlD1sRqLT2blB573YyTv-U=",
|
|
14
|
+
"posts/images/vibrant-waves.jpg": "J+C7EolOmfP3fHl-22UoIx-h0hImPk9iEhL+66I60P4=",
|
|
15
|
+
"posts/welcome-to-amytis/images/vibrant-waves.jpg": "gAUaQXipxs2k7jJ6OoyIJ1+hj9HjM5QeuUuWTQoByps="
|
|
75
16
|
}
|