create-riebeckite 0.0.13 → 0.0.15

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 CHANGED
@@ -6,6 +6,15 @@ Create a new Riebeckite site from an official starter preset.
6
6
 
7
7
  ## Usage
8
8
 
9
+ Interactive (recommended): run without arguments and answer the prompts for
10
+ the project name, preset, content source, and deployment.
11
+
12
+ ```sh
13
+ npx create-riebeckite
14
+ ```
15
+
16
+ Passing any argument keeps the command non-interactive:
17
+
9
18
  ```sh
10
19
  npx create-riebeckite my-site
11
20
  cd my-site
@@ -13,6 +22,23 @@ npm install
13
22
  npm exec riebeckite build
14
23
  ```
15
24
 
25
+ ## Choices
26
+
27
+ The prompts ask, in order:
28
+
29
+ | Prompt | Options | Recommendation |
30
+ | --- | --- | --- |
31
+ | Project name | the folder to create (empty input uses the default name) | any name, e.g. `my-site` |
32
+ | Preset | `starter`, `minimal`, `showcase`, `empty` | `starter` for most sites |
33
+ | Content source | `This project`, `Separate GitHub repository` | `This project` to start |
34
+ | Deployment | `GitHub Actions + Cloudflare Workers`, `Not now` | `Not now` for local development |
35
+
36
+ `Separate GitHub repository` also asks for the content and site repositories,
37
+ and GitHub Actions deployment is then configured for you. That setup is covered
38
+ in the [content repository guide](../../docs/en/docs/guides/content-repositories.md).
39
+ Deployment can be added later, described in
40
+ [Deployment](../../docs/en/docs/getting-started/deployment.md).
41
+
16
42
  ## Options
17
43
 
18
44
  | Option | Description |
@@ -31,6 +57,8 @@ For example, scaffold the complete feature tour:
31
57
  npx create-riebeckite my-site --preset showcase
32
58
  ```
33
59
 
60
+ ## External content repository
61
+
34
62
  To use a separate content repository and deploy after its `main` branch is
35
63
  pushed, generate the common workflow once (the preset does not affect it):
36
64
 
package/README_ja.md CHANGED
@@ -7,6 +7,15 @@ CLI ツールです。
7
7
 
8
8
  ## 使い方
9
9
 
10
+ 対話モード(推奨): 引数なしで実行すると、プロジェクト名・preset・
11
+ コンテンツの格納場所・デプロイについて順に確認します。
12
+
13
+ ```sh
14
+ npx create-riebeckite
15
+ ```
16
+
17
+ 引数を 1 つでも渡すと、従来どおり非対話で動作します。
18
+
10
19
  ```sh
11
20
  npx create-riebeckite my-site
12
21
  cd my-site
@@ -14,6 +23,19 @@ npm install
14
23
  npm exec riebeckite build
15
24
  ```
16
25
 
26
+ ## Choices
27
+
28
+ 対話式の CLI は、次の順に確認します。
29
+
30
+ | 質問 | 選択肢 | 推奨 |
31
+ | --- | --- | --- |
32
+ | Project name | 作るフォルダ名(空なら既定の名前) | 任意。例: `my-site` |
33
+ | Preset | `starter`、`minimal`、`showcase`、`empty` | 大半のサイトは `starter` |
34
+ | Content source | `This project`、`Separate GitHub repository` | 最初は `This project` |
35
+ | デプロイ設定 | `GitHub Actions + Cloudflare Workers`、`Not now` | 手元で試すなら `Not now` |
36
+
37
+ `Separate GitHub repository` を選ぶと content と site のリポジトリ名も入力し、GitHub Actions のデプロイ設定が自動で構成されます。この構成は[content repository ガイド](../../docs/ja/docs/guides/content-repositories.md)に、デプロイの追加方法は [Deployment](../../docs/ja/docs/getting-started/deployment.md) にあります。
38
+
17
39
  ## オプション
18
40
 
19
41
  | オプション | 説明 |
@@ -32,6 +54,8 @@ npm exec riebeckite build
32
54
  npx create-riebeckite my-site --preset showcase
33
55
  ```
34
56
 
57
+ ## External content repository
58
+
35
59
  別の記事リポジトリを使い、その `main` への push でデプロイする場合は、共通の
36
60
  workflow を一度だけ生成します。preset による違いはありません。
37
61
 
@@ -63,7 +87,7 @@ npx create-riebeckite --list-presets
63
87
  | --- | --- |
64
88
  | `starter` | 大半のサイトにおすすめ |
65
89
  | `minimal` | 最小限の設定で作る Markdown サイト |
66
- | `showcase` | 描画例とローカルのフィクスチャで Riebeckite の機能と Plugin を確認する構成 |
90
+ | `showcase` | 描画例とローカルの fixture で Riebeckite の機能と Plugin を確認する構成 |
67
91
  | `empty` | 独自構成のための空のシェル |
68
92
 
69
93
  各 preset の説明は次のとおりです(`--list-presets` で表示される内容と同じです)。
@@ -0,0 +1,12 @@
1
+ import { type ScaffoldPresetName } from "@riebeckite/honox";
2
+ export type CreateRiebeckiteOptions = {
3
+ readonly directory: string;
4
+ readonly force: boolean;
5
+ readonly preset: ScaffoldPresetName;
6
+ readonly listPresets: boolean;
7
+ readonly githubActions: boolean;
8
+ readonly contentRepository?: string;
9
+ readonly siteRepository?: string;
10
+ };
11
+ export declare function parseArguments(arguments_: readonly string[]): CreateRiebeckiteOptions;
12
+ export declare function printPresets(): void;
@@ -1,11 +1,2 @@
1
- import { type ScaffoldPresetName } from "@riebeckite/honox";
2
- export type CreateRiebeckiteOptions = {
3
- readonly directory: string;
4
- readonly force: boolean;
5
- readonly preset: ScaffoldPresetName;
6
- readonly listPresets: boolean;
7
- readonly githubActions: boolean;
8
- readonly contentRepository?: string;
9
- readonly siteRepository?: string;
10
- };
1
+ export type { CreateRiebeckiteOptions } from "./arguments.js";
11
2
  export declare function runCreateRiebeckite(arguments_: readonly string[]): Promise<void>;
package/dist/src/index.js CHANGED
@@ -2,54 +2,16 @@
2
2
  import path from "node:path";
3
3
  import {
4
4
  formatScaffoldNextSteps,
5
- isScaffoldPresetName,
6
- SCAFFOLD_PRESET_NAMES,
7
5
  ScaffoldSiteError,
8
- scaffoldPresets,
9
6
  scaffoldRiebeckiteSite
10
7
  } from "@riebeckite/honox";
11
- async function runCreateRiebeckite(arguments_) {
12
- let options;
13
- try {
14
- options = parseArguments(arguments_);
15
- } catch (error) {
16
- console.error(error instanceof Error ? error.message : String(error));
17
- process.exitCode = 1;
18
- return;
19
- }
20
- if (options.listPresets) {
21
- printPresets();
22
- return;
23
- }
24
- const targetDirectory = path.resolve(process.cwd(), options.directory);
25
- try {
26
- const result = await scaffoldRiebeckiteSite({
27
- targetDirectory,
28
- overwrite: options.force,
29
- preset: options.preset,
30
- githubActions: options.githubActions,
31
- contentRepository: options.contentRepository,
32
- siteRepository: options.siteRepository
33
- });
34
- const relative = path.relative(process.cwd(), result.targetDirectory) || ".";
35
- console.log(`Created a ${options.preset} Riebeckite site in ${relative}`);
36
- console.log("");
37
- console.log(formatScaffoldNextSteps(relative));
38
- if (options.contentRepository !== void 0) {
39
- console.log("");
40
- console.log(
41
- "Copy github/notify-site.yml to the content repository as .github/workflows/notify-site.yml."
42
- );
43
- }
44
- } catch (error) {
45
- if (error instanceof ScaffoldSiteError) {
46
- console.error(error.message);
47
- process.exitCode = 1;
48
- return;
49
- }
50
- throw error;
51
- }
52
- }
8
+
9
+ // src/arguments.ts
10
+ import {
11
+ isScaffoldPresetName,
12
+ SCAFFOLD_PRESET_NAMES,
13
+ scaffoldPresets
14
+ } from "@riebeckite/honox";
53
15
  function parseArguments(arguments_) {
54
16
  let directory;
55
17
  let force = false;
@@ -120,6 +82,145 @@ function printPresets() {
120
82
  console.log(` ${name}: ${scaffoldPresets[name].description}`);
121
83
  }
122
84
  }
85
+
86
+ // src/interactive.ts
87
+ import { isCancel, log, select, text } from "@clack/prompts";
88
+ import {
89
+ SCAFFOLD_PRESET_NAMES as SCAFFOLD_PRESET_NAMES2,
90
+ scaffoldPresets as scaffoldPresets2
91
+ } from "@riebeckite/honox";
92
+ var DEFAULT_DIRECTORY = "my-riebeckite-site";
93
+ function interactiveAnswersToOptions(answers) {
94
+ const external = answers.contentSource === "external";
95
+ return {
96
+ directory: answers.directory,
97
+ force: false,
98
+ preset: answers.preset,
99
+ listPresets: false,
100
+ githubActions: external || answers.deployment === "github-actions",
101
+ contentRepository: external ? answers.contentRepository : void 0,
102
+ siteRepository: external ? answers.siteRepository : void 0
103
+ };
104
+ }
105
+ async function promptInteractiveAnswers() {
106
+ const projectInput = await text({
107
+ message: "Project name",
108
+ placeholder: DEFAULT_DIRECTORY,
109
+ defaultValue: DEFAULT_DIRECTORY
110
+ });
111
+ if (isCancel(projectInput)) return null;
112
+ const directory = projectInput.trim() || DEFAULT_DIRECTORY;
113
+ const preset = await select({
114
+ message: "Choose a preset",
115
+ initialValue: "starter",
116
+ options: SCAFFOLD_PRESET_NAMES2.map((name) => ({
117
+ value: name,
118
+ label: capitalize(name),
119
+ hint: scaffoldPresets2[name].description
120
+ }))
121
+ });
122
+ if (isCancel(preset)) return null;
123
+ const contentSource = await select({
124
+ message: "Where will you write content?",
125
+ initialValue: "local",
126
+ options: [
127
+ { value: "local", label: "This project" },
128
+ { value: "external", label: "Separate GitHub repository" }
129
+ ]
130
+ });
131
+ if (isCancel(contentSource)) return null;
132
+ let answers;
133
+ if (contentSource === "external") {
134
+ const contentRepository = await text({
135
+ message: "Content repository",
136
+ placeholder: "OWNER/notes"
137
+ });
138
+ if (isCancel(contentRepository)) return null;
139
+ const siteRepository = await text({
140
+ message: "Site repository",
141
+ placeholder: "OWNER/site"
142
+ });
143
+ if (isCancel(siteRepository)) return null;
144
+ answers = {
145
+ directory,
146
+ preset,
147
+ contentSource,
148
+ deployment: "github-actions",
149
+ contentRepository: contentRepository.trim(),
150
+ siteRepository: siteRepository.trim()
151
+ };
152
+ } else {
153
+ const deployment = await select({
154
+ message: "Set up deployment?",
155
+ initialValue: "github-actions",
156
+ options: [
157
+ {
158
+ value: "github-actions",
159
+ label: "GitHub Actions + Cloudflare Workers"
160
+ },
161
+ { value: "none", label: "Not now" }
162
+ ]
163
+ });
164
+ if (isCancel(deployment)) return null;
165
+ answers = { directory, preset, contentSource, deployment };
166
+ }
167
+ log.step("Creating Riebeckite site...");
168
+ return answers;
169
+ }
170
+ function capitalize(value) {
171
+ return value.charAt(0).toUpperCase() + value.slice(1);
172
+ }
173
+
174
+ // src/index.ts
175
+ async function runCreateRiebeckite(arguments_) {
176
+ let options;
177
+ if (arguments_.length === 0) {
178
+ const answers = await promptInteractiveAnswers();
179
+ if (answers === null) {
180
+ console.log("Operation cancelled.");
181
+ return;
182
+ }
183
+ options = interactiveAnswersToOptions(answers);
184
+ } else {
185
+ try {
186
+ options = parseArguments(arguments_);
187
+ } catch (error) {
188
+ console.error(error instanceof Error ? error.message : String(error));
189
+ process.exitCode = 1;
190
+ return;
191
+ }
192
+ }
193
+ if (options.listPresets) {
194
+ printPresets();
195
+ return;
196
+ }
197
+ const targetDirectory = path.resolve(process.cwd(), options.directory);
198
+ try {
199
+ const result = await scaffoldRiebeckiteSite({
200
+ targetDirectory,
201
+ overwrite: options.force,
202
+ preset: options.preset,
203
+ githubActions: options.githubActions,
204
+ contentRepository: options.contentRepository,
205
+ siteRepository: options.siteRepository
206
+ });
207
+ const relative = path.relative(process.cwd(), result.targetDirectory) || ".";
208
+ console.log(`Created a ${options.preset} Riebeckite site in ${relative}`);
209
+ console.log("");
210
+ const externalContent = options.contentRepository !== void 0;
211
+ const editFile = !externalContent && result.files.includes("content/index.md") ? "content/index.md" : void 0;
212
+ console.log(
213
+ formatScaffoldNextSteps(relative, { editFile, externalContent })
214
+ );
215
+ } catch (error) {
216
+ if (error instanceof ScaffoldSiteError) {
217
+ console.error(error.message);
218
+ process.exitCode = 1;
219
+ return;
220
+ }
221
+ throw error;
222
+ }
223
+ }
123
224
  export {
124
225
  runCreateRiebeckite
125
226
  };
@@ -0,0 +1,24 @@
1
+ import { type ScaffoldPresetName } from "@riebeckite/honox";
2
+ import type { CreateRiebeckiteOptions } from "./arguments.js";
3
+ export type InteractiveContentSource = "local" | "external";
4
+ export type InteractiveDeployment = "github-actions" | "none";
5
+ export type InteractiveAnswers = {
6
+ readonly directory: string;
7
+ readonly preset: ScaffoldPresetName;
8
+ readonly contentSource: InteractiveContentSource;
9
+ readonly deployment: InteractiveDeployment;
10
+ readonly contentRepository?: string;
11
+ readonly siteRepository?: string;
12
+ };
13
+ /**
14
+ * Map interactive answers onto the same options object the non-interactive
15
+ * flags produce. A separate content repository always deploys through GitHub
16
+ * Actions, so the answered deployment never wins in that combination.
17
+ */
18
+ export declare function interactiveAnswersToOptions(answers: InteractiveAnswers): CreateRiebeckiteOptions;
19
+ /**
20
+ * Run the prompt flow. Returns `null` when the user cancels, so the caller can
21
+ * exit without a stack trace. Repository values are only trimmed here; their
22
+ * `owner/repository` shape is validated by the existing scaffold.
23
+ */
24
+ export declare function promptInteractiveAnswers(): Promise<InteractiveAnswers | null>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-riebeckite",
3
- "version": "0.0.13",
3
+ "version": "0.0.15",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "main": "./dist/src/index.js",
@@ -27,7 +27,8 @@
27
27
  "access": "public"
28
28
  },
29
29
  "dependencies": {
30
- "@riebeckite/honox": "0.0.13"
30
+ "@clack/prompts": "^1.8.1",
31
+ "@riebeckite/honox": "0.0.15"
31
32
  },
32
33
  "repository": {
33
34
  "type": "git",
@@ -50,6 +51,7 @@
50
51
  },
51
52
  "sideEffects": false,
52
53
  "scripts": {
53
- "build": "node ../../scripts/build_package.mjs"
54
+ "build": "node ../../scripts/build_package.mjs",
55
+ "test": "node --import tsx --test \"test/*.test.ts\""
54
56
  }
55
57
  }