create-backbone-template 0.1.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.
Files changed (182) hide show
  1. package/README.md +33 -0
  2. package/bin/create-backbone-template.js +5 -0
  3. package/package.json +30 -0
  4. package/src/create-backbone-template.js +204 -0
  5. package/template/.agents/skills/agent-browser/SKILL.md +55 -0
  6. package/template/.agents/skills/create-plan/SKILL.md +52 -0
  7. package/template/.agents/skills/create-plan/agents/openai.yaml +4 -0
  8. package/template/.agents/skills/create-pr-presentation/SKILL.md +86 -0
  9. package/template/.agents/skills/create-pr-presentation/agents/openai.yaml +4 -0
  10. package/template/.agents/skills/implement-plan/SKILL.md +26 -0
  11. package/template/.agents/skills/implement-plan/agents/openai.yaml +4 -0
  12. package/template/.agents/skills/review-plan/SKILL.md +38 -0
  13. package/template/.agents/skills/review-plan/agents/openai.yaml +4 -0
  14. package/template/.env.schema +30 -0
  15. package/template/.env.test +6 -0
  16. package/template/.oxlintrc.json +67 -0
  17. package/template/.vscode/extensions.json +3 -0
  18. package/template/.vscode/settings.json +23 -0
  19. package/template/AGENTS.md +55 -0
  20. package/template/Cargo.lock +2648 -0
  21. package/template/Cargo.toml +29 -0
  22. package/template/Justfile +140 -0
  23. package/template/README.md +72 -0
  24. package/template/TODO.md +1 -0
  25. package/template/_gitignore +12 -0
  26. package/template/buf.gen.yaml +7 -0
  27. package/template/buf.yaml +10 -0
  28. package/template/client/.oxfmtrc.json +8 -0
  29. package/template/client/.oxlintrc.json +57 -0
  30. package/template/client/README.md +19 -0
  31. package/template/client/_gitignore +5 -0
  32. package/template/client/index.html +12 -0
  33. package/template/client/package.json +47 -0
  34. package/template/client/packages/design-system/package.json +19 -0
  35. package/template/client/packages/design-system/src/index.ts +2 -0
  36. package/template/client/packages/design-system-basic/package.json +18 -0
  37. package/template/client/packages/design-system-basic/src/button.stories.tsx +50 -0
  38. package/template/client/packages/design-system-basic/src/button.tsx +26 -0
  39. package/template/client/packages/design-system-basic/src/empty-state.stories.tsx +18 -0
  40. package/template/client/packages/design-system-basic/src/empty-state.tsx +17 -0
  41. package/template/client/packages/design-system-basic/src/form-field.stories.tsx +15 -0
  42. package/template/client/packages/design-system-basic/src/form-field.tsx +10 -0
  43. package/template/client/packages/design-system-basic/src/form.stories.tsx +27 -0
  44. package/template/client/packages/design-system-basic/src/form.tsx +9 -0
  45. package/template/client/packages/design-system-basic/src/heading.stories.tsx +14 -0
  46. package/template/client/packages/design-system-basic/src/heading.tsx +25 -0
  47. package/template/client/packages/design-system-basic/src/index.tsx +15 -0
  48. package/template/client/packages/design-system-basic/src/inline.stories.tsx +13 -0
  49. package/template/client/packages/design-system-basic/src/inline.tsx +5 -0
  50. package/template/client/packages/design-system-basic/src/layout.stories.tsx +24 -0
  51. package/template/client/packages/design-system-basic/src/layout.tsx +14 -0
  52. package/template/client/packages/design-system-basic/src/loader.stories.tsx +8 -0
  53. package/template/client/packages/design-system-basic/src/loader.tsx +11 -0
  54. package/template/client/packages/design-system-basic/src/navigation.stories.tsx +16 -0
  55. package/template/client/packages/design-system-basic/src/navigation.tsx +18 -0
  56. package/template/client/packages/design-system-basic/src/notice.stories.tsx +13 -0
  57. package/template/client/packages/design-system-basic/src/notice.tsx +5 -0
  58. package/template/client/packages/design-system-basic/src/stack.stories.tsx +17 -0
  59. package/template/client/packages/design-system-basic/src/stack.tsx +5 -0
  60. package/template/client/packages/design-system-basic/src/styles.css +254 -0
  61. package/template/client/packages/design-system-basic/src/text-input.stories.tsx +13 -0
  62. package/template/client/packages/design-system-basic/src/text-input.tsx +5 -0
  63. package/template/client/packages/design-system-basic/src/text.stories.tsx +21 -0
  64. package/template/client/packages/design-system-basic/src/text.tsx +5 -0
  65. package/template/client/packages/design-system-contract/package.json +15 -0
  66. package/template/client/packages/design-system-contract/src/button.ts +10 -0
  67. package/template/client/packages/design-system-contract/src/empty-state.ts +9 -0
  68. package/template/client/packages/design-system-contract/src/form-field.ts +9 -0
  69. package/template/client/packages/design-system-contract/src/form.ts +9 -0
  70. package/template/client/packages/design-system-contract/src/heading.ts +9 -0
  71. package/template/client/packages/design-system-contract/src/index.ts +13 -0
  72. package/template/client/packages/design-system-contract/src/inline.ts +7 -0
  73. package/template/client/packages/design-system-contract/src/layout.ts +8 -0
  74. package/template/client/packages/design-system-contract/src/loader.ts +7 -0
  75. package/template/client/packages/design-system-contract/src/navigation.ts +13 -0
  76. package/template/client/packages/design-system-contract/src/notice.ts +8 -0
  77. package/template/client/packages/design-system-contract/src/stack.ts +8 -0
  78. package/template/client/packages/design-system-contract/src/text-input.ts +5 -0
  79. package/template/client/packages/design-system-contract/src/text.ts +9 -0
  80. package/template/client/packages/design-system-lint/fixtures/invalid/external-ui-import.tsx +5 -0
  81. package/template/client/packages/design-system-lint/fixtures/invalid/raw-dom-jsx.tsx +3 -0
  82. package/template/client/packages/design-system-lint/fixtures/invalid/two-violations.tsx +7 -0
  83. package/template/client/packages/design-system-lint/fixtures/valid/design-system-only.tsx +13 -0
  84. package/template/client/packages/design-system-lint/package.json +23 -0
  85. package/template/client/packages/design-system-lint/src/check-design-system-architecture.ts +22 -0
  86. package/template/client/packages/design-system-lint/src/design-system-architecture.ts +286 -0
  87. package/template/client/packages/design-system-lint/src/oxlint-plugin.ts +11 -0
  88. package/template/client/packages/design-system-lint/src/page-architecture.ts +382 -0
  89. package/template/client/packages/design-system-lint/src/rules.ts +111 -0
  90. package/template/client/packages/design-system-lint/test/design-system-architecture.test.ts +243 -0
  91. package/template/client/packages/design-system-lint/test/oxlint-fixtures.test.ts +159 -0
  92. package/template/client/packages/design-system-lint/test/page-architecture.test.ts +175 -0
  93. package/template/client/packages/design-system-lint/test/rules.test.ts +65 -0
  94. package/template/client/packages/design-system-lint/tsconfig.json +29 -0
  95. package/template/client/src/App.tsx +77 -0
  96. package/template/client/src/design-system-components.test.tsx +75 -0
  97. package/template/client/src/gen/helloworld/v1/helloworld_pb.ts +63 -0
  98. package/template/client/src/main.tsx +18 -0
  99. package/template/client/src/pages/hello/hello-page.stories.tsx +20 -0
  100. package/template/client/src/pages/hello/hello-page.test.tsx +90 -0
  101. package/template/client/src/pages/hello/hello-page.tsx +126 -0
  102. package/template/client/src/pages/page.ts +20 -0
  103. package/template/client/src/testing/create-preview-events.test.ts +36 -0
  104. package/template/client/src/testing/create-preview-events.ts +30 -0
  105. package/template/client/src/vite-env.d.ts +1 -0
  106. package/template/client/tsconfig.json +32 -0
  107. package/template/client/vite.config.ts +21 -0
  108. package/template/client/vite.ladle.config.ts +5 -0
  109. package/template/e2e/.gherkin-lintrc +20 -0
  110. package/template/e2e/.oxfmtrc.json +15 -0
  111. package/template/e2e/.oxlintrc.json +37 -0
  112. package/template/e2e/_gitignore +4 -0
  113. package/template/e2e/features/helloworld.feature +10 -0
  114. package/template/e2e/package.json +42 -0
  115. package/template/e2e/playwright.config.ts +16 -0
  116. package/template/e2e/support/app-gherkin.ts +4 -0
  117. package/template/e2e/support/fixtures.ts +236 -0
  118. package/template/e2e/support/gherkin-fixtures/duplicate-id.feature +9 -0
  119. package/template/e2e/support/gherkin-fixtures/duplicate-id.spec.ts +7 -0
  120. package/template/e2e/support/gherkin-fixtures/extra-implementation.spec.ts +7 -0
  121. package/template/e2e/support/gherkin-fixtures/extra-step.spec.ts +10 -0
  122. package/template/e2e/support/gherkin-fixtures/happy-path.spec.ts +4 -0
  123. package/template/e2e/support/gherkin-fixtures/missing-id.feature +4 -0
  124. package/template/e2e/support/gherkin-fixtures/missing-id.spec.ts +7 -0
  125. package/template/e2e/support/gherkin-fixtures/missing-implementation.spec.ts +7 -0
  126. package/template/e2e/support/gherkin-fixtures/missing-step.spec.ts +7 -0
  127. package/template/e2e/support/gherkin-fixtures/playwright.config.ts +7 -0
  128. package/template/e2e/support/gherkin-fixtures/scenario-outline.feature +9 -0
  129. package/template/e2e/support/gherkin-fixtures/scenario-outline.spec.ts +7 -0
  130. package/template/e2e/support/gherkin-fixtures/step-mismatch.spec.ts +9 -0
  131. package/template/e2e/support/gherkin-fixtures/valid-implementations.ts +23 -0
  132. package/template/e2e/support/gherkin-fixtures/valid-scenarios.feature +26 -0
  133. package/template/e2e/support/gherkin.test.ts +184 -0
  134. package/template/e2e/support/gherkin.ts +321 -0
  135. package/template/e2e/support/oxlint-plugin.test.ts +328 -0
  136. package/template/e2e/support/oxlint-plugin.ts +485 -0
  137. package/template/e2e/tests/helloworld.spec.ts +39 -0
  138. package/template/e2e/tsconfig.json +26 -0
  139. package/template/e2e/tsconfig.oxlint-plugin.json +12 -0
  140. package/template/package.json +9 -0
  141. package/template/pnpm-lock.yaml +10723 -0
  142. package/template/pnpm-workspace.yaml +8 -0
  143. package/template/pr-slide/README.md +95 -0
  144. package/template/pr-slide/package.json +23 -0
  145. package/template/pr-slide/src/cli.js +262 -0
  146. package/template/pr-slide/src/generate-pr-deck.js +833 -0
  147. package/template/pr-slide/src/git-context.js +91 -0
  148. package/template/pr-slide/src/presentation-paths.js +9 -0
  149. package/template/pr-slide/src/presentations.js +53 -0
  150. package/template/pr-slide/test/generate-pr-deck.test.js +118 -0
  151. package/template/pr-slide/test/presentation-paths.test.js +14 -0
  152. package/template/pr-slide/test/presentations.test.js +50 -0
  153. package/template/proto/helloworld/v1/helloworld.proto +15 -0
  154. package/template/scripts/run-e2e.sh +10 -0
  155. package/template/server/Cargo.toml +26 -0
  156. package/template/server/build.rs +9 -0
  157. package/template/server/dylint/backbone_server_lints/.cargo/config.toml +6 -0
  158. package/template/server/dylint/backbone_server_lints/Cargo.lock +1581 -0
  159. package/template/server/dylint/backbone_server_lints/Cargo.toml +21 -0
  160. package/template/server/dylint/backbone_server_lints/README.md +5 -0
  161. package/template/server/dylint/backbone_server_lints/_gitignore +1 -0
  162. package/template/server/dylint/backbone_server_lints/rust-toolchain +3 -0
  163. package/template/server/dylint/backbone_server_lints/src/lib.rs +612 -0
  164. package/template/server/dylint/backbone_server_lints/ui/lib.rs +4 -0
  165. package/template/server/dylint/backbone_server_lints/ui/lib.stderr +10 -0
  166. package/template/server/dylint/backbone_server_lints/ui/long_file.rs +303 -0
  167. package/template/server/dylint/backbone_server_lints/ui/long_file.stderr +6 -0
  168. package/template/server/dylint/backbone_server_lints/ui/main.rs +59 -0
  169. package/template/server/dylint/backbone_server_lints/ui/main.stderr +85 -0
  170. package/template/server/migrations/20260520120000_create_projects.sql +12 -0
  171. package/template/server/migrations/20260524160000_create_hello_world_inputs.sql +12 -0
  172. package/template/server/src/config.rs +27 -0
  173. package/template/server/src/db/hello_world.rs +34 -0
  174. package/template/server/src/db/hello_world_tests.rs +11 -0
  175. package/template/server/src/db/mod.rs +39 -0
  176. package/template/server/src/lib.rs +10 -0
  177. package/template/server/src/main.rs +43 -0
  178. package/template/server/src/rpc/greeter/mod.rs +31 -0
  179. package/template/server/src/rpc/greeter/say_hello.rs +27 -0
  180. package/template/server/src/rpc/mod.rs +8 -0
  181. package/template/server/src/state.rs +13 -0
  182. package/template/skills-lock.json +11 -0
@@ -0,0 +1,8 @@
1
+ packages:
2
+ - "client"
3
+ - "client/packages/*"
4
+ - "e2e"
5
+ - "pr-slide"
6
+
7
+ onlyBuiltDependencies:
8
+ - better-sqlite3
@@ -0,0 +1,95 @@
1
+ # PR Slide
2
+
3
+ Slidev workspace for generating and watching PR presentations from the current branch.
4
+
5
+ ## Generate The Deck
6
+
7
+ ```bash
8
+ just pr-slide-generate
9
+ ```
10
+
11
+ This creates:
12
+
13
+ ```text
14
+ .agents/pr-presentation/<branch-name>/slides.md
15
+ .agents/pr-presentation/<branch-name>/manifest.json
16
+ ```
17
+
18
+ Branch names are normalized into one directory. For example, `feat/hello-history` becomes:
19
+
20
+ ```text
21
+ .agents/pr-presentation/feat-hello-history/slides.md
22
+ ```
23
+
24
+ ## Watch The Presentation
25
+
26
+ ```bash
27
+ just pr-slide
28
+ ```
29
+
30
+ This regenerates the current branch deck and starts Slidev dev mode. The terminal prints the local URLs, usually:
31
+
32
+ ```text
33
+ http://localhost:3030/
34
+ http://localhost:3030/presenter/
35
+ http://localhost:3030/overview/
36
+ ```
37
+
38
+ You can pass Slidev options through pnpm when needed:
39
+
40
+ ```bash
41
+ pnpm --filter @backbone/pr-slide run dev -- --port 3031
42
+ ```
43
+
44
+ ## List Presentations
45
+
46
+ ```bash
47
+ just pr-slide-list
48
+ ```
49
+
50
+ This prints every generated deck under:
51
+
52
+ ```text
53
+ .agents/pr-presentation/
54
+ ```
55
+
56
+ ## Open A Specific Presentation
57
+
58
+ ```bash
59
+ just pr-slide-open feat-hello-history
60
+ ```
61
+
62
+ This opens an existing deck without regenerating the current branch deck.
63
+
64
+ You can pass Slidev options through the lower-level command:
65
+
66
+ ```bash
67
+ pnpm --filter @backbone/pr-slide run open -- feat-hello-history --port 3031
68
+ ```
69
+
70
+ ## Edit The Slides
71
+
72
+ Edit the generated `slides.md` directly:
73
+
74
+ ```text
75
+ .agents/pr-presentation/<branch-name>/slides.md
76
+ ```
77
+
78
+ Regenerating will overwrite the deck, so keep manual polish for the final pass after the generated structure looks right.
79
+
80
+ ## Export
81
+
82
+ ```bash
83
+ pnpm --filter @backbone/pr-slide run export -- --format pptx
84
+ ```
85
+
86
+ Other useful export formats are `pdf`, `png`, and `md`.
87
+
88
+ ## Generator Options
89
+
90
+ ```bash
91
+ pnpm --filter @backbone/pr-slide run generate -- --title "Catchy PR Title"
92
+ pnpm --filter @backbone/pr-slide run generate -- --purpose "What reviewers should remember."
93
+ pnpm --filter @backbone/pr-slide run generate -- --git-base main
94
+ pnpm --filter @backbone/pr-slide run generate -- --deck-out .agents/pr-presentation/custom-name
95
+ ```
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "@backbone/pr-slide",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "generate": "node src/cli.js generate",
8
+ "list": "node src/cli.js list",
9
+ "open": "node src/cli.js open",
10
+ "dev": "node src/cli.js dev",
11
+ "build": "node src/cli.js build",
12
+ "export": "node src/cli.js export",
13
+ "test": "vitest run"
14
+ },
15
+ "dependencies": {
16
+ "@slidev/cli": "^52.4.0",
17
+ "@slidev/theme-default": "^0.25.0"
18
+ },
19
+ "devDependencies": {
20
+ "vitest": "^4.0.14"
21
+ },
22
+ "packageManager": "pnpm@10.22.0"
23
+ }
@@ -0,0 +1,262 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { dirname, join, resolve } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { spawnSync } from "node:child_process";
5
+
6
+ import { buildDeck } from "./generate-pr-deck.js";
7
+ import { collectGitContext } from "./git-context.js";
8
+ import { branchToPresentationDirName } from "./presentation-paths.js";
9
+ import {
10
+ listPresentations,
11
+ resolvePresentationSlidesPath,
12
+ } from "./presentations.js";
13
+
14
+ const packageRoot = dirname(dirname(fileURLToPath(import.meta.url)));
15
+ const repoRoot = resolve(packageRoot, "..");
16
+ const presentationRoot = join(repoRoot, ".agents", "pr-presentation");
17
+ const command = process.argv[2] ?? "dev";
18
+ const args = process.argv.slice(3);
19
+
20
+ if (command === "generate") {
21
+ const output = writeCurrentDeck(parseOptions(args));
22
+ console.log(output.slidesPath);
23
+ } else if (command === "list") {
24
+ printPresentations();
25
+ } else if (command === "open") {
26
+ openPresentation(args);
27
+ } else if (command === "dev" || command === "build" || command === "export") {
28
+ const output = writeCurrentDeck(parseOptions(args));
29
+ runSlidev(command, output.slidesPath, args);
30
+ } else {
31
+ console.error(`Unknown command: ${command}`);
32
+ process.exit(1);
33
+ }
34
+
35
+ export function writeCurrentDeck(options = {}) {
36
+ const context = collectGitContext(options);
37
+ const deckDir = resolve(
38
+ repoRoot,
39
+ options.out ??
40
+ join(presentationRoot, branchToPresentationDirName(context.branch)),
41
+ );
42
+ enrichContextWithAssets(context, deckDir);
43
+ const markdown = buildDeck(context);
44
+ const slidesPath = join(deckDir, "slides.md");
45
+ const manifestPath = join(deckDir, "manifest.json");
46
+
47
+ mkdirSync(deckDir, { recursive: true });
48
+ writeFileSync(slidesPath, markdown);
49
+ writeFileSync(
50
+ manifestPath,
51
+ JSON.stringify(
52
+ {
53
+ title: context.title,
54
+ branch: context.branch,
55
+ base: context.base,
56
+ generatedAt: context.generatedAt.toISOString(),
57
+ changedFiles: context.changedFiles,
58
+ },
59
+ null,
60
+ 2,
61
+ ) + "\n",
62
+ );
63
+
64
+ return { slidesPath, manifestPath };
65
+ }
66
+
67
+ function enrichContextWithAssets(context, deckDir) {
68
+ const sections = context.sections ?? {};
69
+
70
+ for (const items of Object.values(sections)) {
71
+ for (const item of items) {
72
+ const asset = findItemAsset(deckDir, item);
73
+
74
+ if (asset) {
75
+ item.image = asset;
76
+ }
77
+
78
+ enrichItemFromFile(item);
79
+ }
80
+ }
81
+ }
82
+
83
+ function enrichItemFromFile(item) {
84
+ if (!item.detail || !existsSync(join(repoRoot, item.detail))) {
85
+ return;
86
+ }
87
+
88
+ if (item.detail.endsWith(".proto")) {
89
+ item.protoServices = parseProtoServices(readFileSync(join(repoRoot, item.detail), "utf8"));
90
+ }
91
+
92
+ if (item.detail.includes("/migrations/") && item.detail.endsWith(".sql")) {
93
+ item.migrationSummary = summarizeMigrationSql(
94
+ readFileSync(join(repoRoot, item.detail), "utf8"),
95
+ );
96
+ }
97
+ }
98
+
99
+ function parseProtoServices(source) {
100
+ const services = [];
101
+ const servicePattern = /service\s+(\w+)\s*\{([\s\S]*?)\}/g;
102
+
103
+ for (const match of source.matchAll(servicePattern)) {
104
+ const [, name, body] = match;
105
+ const rpcs = [...body.matchAll(/rpc\s+(\w+)\s*\((\w+)\)\s+returns\s+\((\w+)\)/g)].map(
106
+ (rpcMatch) => ({
107
+ name: rpcMatch[1],
108
+ request: rpcMatch[2],
109
+ response: rpcMatch[3],
110
+ description: describeRpc(rpcMatch[1]),
111
+ }),
112
+ );
113
+
114
+ services.push({ name, rpcs });
115
+ }
116
+
117
+ return services;
118
+ }
119
+
120
+ function describeRpc(name) {
121
+ const descriptions = {
122
+ SayHello: "returns a greeting for the submitted name.",
123
+ };
124
+
125
+ return descriptions[name] ?? `${humanizeIdentifier(name).toLowerCase()}.`;
126
+ }
127
+
128
+ function summarizeMigrationSql(source) {
129
+ const statements = [];
130
+
131
+ for (const match of source.matchAll(/ALTER TABLE\s+(\w+)\s+ADD COLUMN\s+(\w+)/gi)) {
132
+ statements.push(`Adds \`${match[2]}\` to \`${match[1]}\`.`);
133
+ }
134
+
135
+ for (const match of source.matchAll(/UPDATE\s+(\w+)\s+SET\s+([^;]+)/gi)) {
136
+ statements.push(`Backfills \`${match[1]}\` rows with ${match[2].trim().replace(/\s+/g, " ")}.`);
137
+ }
138
+
139
+ return statements.length > 0 ? statements : ["Updates the database schema for this PR."];
140
+ }
141
+
142
+ function humanizeIdentifier(value) {
143
+ return value
144
+ .replace(/([a-z0-9])([A-Z])/g, "$1 $2")
145
+ .replace(/_/g, " ")
146
+ .trim();
147
+ }
148
+
149
+ function findItemAsset(deckDir, item) {
150
+ const candidates = [
151
+ item.label,
152
+ item.label.replace(/:.*$/, ""),
153
+ item.detail?.split("/").at(-1)?.replace(/\.[^.]+$/, ""),
154
+ ].filter(Boolean);
155
+
156
+ for (const candidate of candidates) {
157
+ const relativePath = `assets/${slug(candidate)}.png`;
158
+
159
+ if (existsSync(join(deckDir, relativePath))) {
160
+ return `./${relativePath}`;
161
+ }
162
+ }
163
+
164
+ return undefined;
165
+ }
166
+
167
+ function slug(value) {
168
+ return value
169
+ .toLowerCase()
170
+ .replace(/[^a-z0-9]+/g, "-")
171
+ .replace(/^-+|-+$/g, "");
172
+ }
173
+
174
+ function printPresentations() {
175
+ const presentations = listPresentations(presentationRoot);
176
+
177
+ if (presentations.length === 0) {
178
+ console.log("No PR presentations found.");
179
+ return;
180
+ }
181
+
182
+ for (const presentation of presentations) {
183
+ const branch = presentation.branch ? ` (${presentation.branch})` : "";
184
+ console.log(`${presentation.name}${branch} - ${presentation.title}`);
185
+ }
186
+ }
187
+
188
+ function openPresentation(values) {
189
+ const openArgs = values[0] === "--" ? values.slice(1) : values;
190
+ const name = openArgs[0];
191
+
192
+ if (!name) {
193
+ console.error("Usage: pnpm --filter @backbone/pr-slide run open -- <name>");
194
+ process.exit(1);
195
+ }
196
+
197
+ const slidesPath = resolvePresentationSlidesPath(presentationRoot, name);
198
+ runSlidev("dev", slidesPath, openArgs.slice(1));
199
+ }
200
+
201
+ function runSlidev(slidevCommand, slidesPath, originalArgs) {
202
+ const passthrough = stripLocalOptions(originalArgs);
203
+ const themeArgs = passthrough.includes("--theme")
204
+ ? []
205
+ : ["--theme", join(packageRoot, "node_modules", "@slidev", "theme-default")];
206
+ const commandArgs =
207
+ slidevCommand === "dev" ? [slidesPath] : [slidevCommand, slidesPath];
208
+ const result = spawnSync(
209
+ "pnpm",
210
+ ["exec", "slidev", ...commandArgs, ...themeArgs, ...passthrough],
211
+ {
212
+ cwd: packageRoot,
213
+ stdio: "inherit",
214
+ },
215
+ );
216
+
217
+ process.exit(result.status ?? 1);
218
+ }
219
+
220
+ function parseOptions(values) {
221
+ const options = {};
222
+
223
+ for (let index = 0; index < values.length; index += 1) {
224
+ const value = values[index];
225
+
226
+ if (value === "--git-base") {
227
+ options.base = values[index + 1];
228
+ index += 1;
229
+ } else if (value === "--title") {
230
+ options.title = values[index + 1];
231
+ index += 1;
232
+ } else if (value === "--purpose") {
233
+ options.purpose = values[index + 1];
234
+ index += 1;
235
+ } else if (value === "--deck-out") {
236
+ options.out = values[index + 1];
237
+ index += 1;
238
+ }
239
+ }
240
+
241
+ return options;
242
+ }
243
+
244
+ function stripLocalOptions(values) {
245
+ const stripped = [];
246
+
247
+ for (let index = 0; index < values.length; index += 1) {
248
+ const value = values[index];
249
+
250
+ if (value === "--") {
251
+ continue;
252
+ }
253
+
254
+ if (["--git-base", "--title", "--purpose", "--deck-out"].includes(value)) {
255
+ index += 1;
256
+ } else {
257
+ stripped.push(value);
258
+ }
259
+ }
260
+
261
+ return stripped;
262
+ }