@berlysia/vertical-writing-slide-system 0.0.3 → 0.0.5
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 +25 -4
- package/cli.js +10 -21
- package/index.html +19 -0
- package/package.json +12 -6
- package/scripts/{build-pages.ts → build-pages.js} +12 -20
- package/src/vite-plugin-slides.ts +10 -9
- package/tsconfig.app.json +26 -0
- package/tsconfig.cli.json +24 -0
- package/tsconfig.json +7 -0
- package/tsconfig.node.json +24 -0
- package/vite.config.ts +34 -0
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ A React-based slides application built with Vite that supports markdown-based pr
|
|
|
12
12
|
## Usage
|
|
13
13
|
|
|
14
14
|
```bash
|
|
15
|
-
vertical-
|
|
15
|
+
npx @berlysia/vertical-writing-slide-system <command> [options]
|
|
16
16
|
```
|
|
17
17
|
|
|
18
18
|
### Commands
|
|
@@ -31,15 +31,36 @@ vertical-slides <command> [options]
|
|
|
31
31
|
|
|
32
32
|
```bash
|
|
33
33
|
# Start development server for slides in './my-slides' directory
|
|
34
|
-
vertical-
|
|
34
|
+
npx @berlysia/vertical-writing-slide-system dev --dir ./my-slides
|
|
35
35
|
|
|
36
36
|
# Build all slides from specified directory
|
|
37
|
-
vertical-
|
|
37
|
+
npx @berlysia/vertical-writing-slide-system buildAll --dir ./my-slides
|
|
38
38
|
|
|
39
39
|
# Build specific slides with custom name
|
|
40
|
-
vertical-
|
|
40
|
+
npx @berlysia/vertical-writing-slide-system build --dir ./my-slides --name custom-presentation
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
+
## Slides Directory Structure
|
|
44
|
+
|
|
45
|
+
Your slides directory should follow this structure:
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
slides/
|
|
49
|
+
├── presentation-name/ # Directory for each presentation
|
|
50
|
+
│ ├── index.mdx # Main presentation content
|
|
51
|
+
│ └── images/ # (Optional) Images used in the presentation
|
|
52
|
+
│ └── example.png
|
|
53
|
+
└── another-presentation/
|
|
54
|
+
├── index.mdx
|
|
55
|
+
└── images/
|
|
56
|
+
└── slide-image.png
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Each presentation should be in its own directory containing:
|
|
60
|
+
|
|
61
|
+
- `index.mdx`: The main presentation file with your MDX content. \*.md is also fine
|
|
62
|
+
- `images/`: (Optional) Directory containing images used in the presentation
|
|
63
|
+
|
|
43
64
|
For development documentation, see [DEVELOPMENT.md](DEVELOPMENT.md).
|
|
44
65
|
|
|
45
66
|
## Writing Modes
|
package/cli.js
CHANGED
|
@@ -1,42 +1,31 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import { resolve } from "path";
|
|
4
3
|
import { execSync } from "child_process";
|
|
5
4
|
import { parseArgs } from "node:util";
|
|
6
5
|
|
|
7
6
|
async function runDev() {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
await server.listen();
|
|
16
|
-
console.log(`Development server running at ${server.resolvedUrls?.local[0]}`);
|
|
17
|
-
console.log("Press Ctrl+C to exit");
|
|
7
|
+
try {
|
|
8
|
+
execSync("npx vite", { stdio: "inherit" });
|
|
9
|
+
} catch (error) {
|
|
10
|
+
console.error("Error during build:", error);
|
|
11
|
+
process.exit(1);
|
|
12
|
+
}
|
|
18
13
|
}
|
|
19
14
|
|
|
20
15
|
async function runBuildAll() {
|
|
21
|
-
const
|
|
22
|
-
import.meta.dirname,
|
|
23
|
-
"scripts",
|
|
24
|
-
"build-pages.ts",
|
|
25
|
-
);
|
|
26
|
-
const command = `npx tsx ${buildPagesPath}`;
|
|
27
|
-
|
|
16
|
+
const { buildPages } = await import("./scripts/build-pages.js");
|
|
28
17
|
try {
|
|
29
|
-
|
|
18
|
+
await buildPages({ slidesDir: process.env.SLIDES_DIR });
|
|
19
|
+
console.log("Build completed successfully");
|
|
30
20
|
} catch (error) {
|
|
31
21
|
console.error("Error during build:", error);
|
|
32
22
|
process.exit(1);
|
|
33
23
|
}
|
|
34
|
-
console.log("Build completed successfully");
|
|
35
24
|
}
|
|
36
25
|
|
|
37
26
|
async function runBuild() {
|
|
38
27
|
try {
|
|
39
|
-
execSync("
|
|
28
|
+
execSync("npx vite build", { stdio: "inherit" });
|
|
40
29
|
} catch (error) {
|
|
41
30
|
console.error("Error during build:", error);
|
|
42
31
|
process.exit(1);
|
package/index.html
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="ja">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
+
<title>Vite + React + TS</title>
|
|
8
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
9
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
10
|
+
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP&family=Noto+Sans+Mono:wght@100..900&display=swap" rel="stylesheet">
|
|
11
|
+
<link rel="stylesheet" href="/src/index.css" />
|
|
12
|
+
<link rel="stylesheet" media="screen" href="/src/screen.css" />
|
|
13
|
+
<link rel="stylesheet" media="print" href="/src/print.css" />
|
|
14
|
+
</head>
|
|
15
|
+
<body>
|
|
16
|
+
<div id="root"></div>
|
|
17
|
+
<script type="module" src="/src/main.tsx"></script>
|
|
18
|
+
</body>
|
|
19
|
+
</html>
|
package/package.json
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@berlysia/vertical-writing-slide-system",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"vertical-slides": "./cli.js"
|
|
7
7
|
},
|
|
8
8
|
"files": [
|
|
9
|
+
"package.json",
|
|
10
|
+
"vite.config.ts",
|
|
11
|
+
"tsconfig.json",
|
|
12
|
+
"tsconfig.*.json",
|
|
9
13
|
"cli.js",
|
|
10
|
-
"scripts",
|
|
11
|
-
"src"
|
|
14
|
+
"scripts/build-pages.js",
|
|
15
|
+
"src",
|
|
16
|
+
"index.html"
|
|
12
17
|
],
|
|
13
18
|
"dependencies": {
|
|
14
19
|
"@emotion/react": "^11.14.0",
|
|
@@ -22,7 +27,8 @@
|
|
|
22
27
|
"remark-rehype": "^11.1.1",
|
|
23
28
|
"tsx": "^4.19.3",
|
|
24
29
|
"unified": "^11.0.5",
|
|
25
|
-
"vfile": "^6.0.3"
|
|
30
|
+
"vfile": "^6.0.3",
|
|
31
|
+
"vite": "^6.2.1"
|
|
26
32
|
},
|
|
27
33
|
"devDependencies": {
|
|
28
34
|
"@eslint/js": "^9.21.0",
|
|
@@ -45,12 +51,12 @@
|
|
|
45
51
|
"prompts": "^2.4.2",
|
|
46
52
|
"typescript": "~5.8.2",
|
|
47
53
|
"typescript-eslint": "^8.26.0",
|
|
48
|
-
"unist-util-visit": "^5.0.0"
|
|
49
|
-
"vite": "^6.2.1"
|
|
54
|
+
"unist-util-visit": "^5.0.0"
|
|
50
55
|
},
|
|
51
56
|
"scripts": {
|
|
52
57
|
"dev": "vite",
|
|
53
58
|
"build": "tsc -b && vite build",
|
|
59
|
+
"build:cli": "tsc --project tsconfig.cli.json",
|
|
54
60
|
"lint": "eslint .",
|
|
55
61
|
"preview": "vite preview",
|
|
56
62
|
"build:pages": "node scripts/build-pages.ts",
|
|
@@ -1,32 +1,23 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
1
|
import { execSync } from "child_process";
|
|
4
2
|
import { existsSync } from "fs";
|
|
5
3
|
import { mkdir, readdir, stat, cp, writeFile } from "fs/promises";
|
|
6
4
|
import { join, resolve } from "path";
|
|
7
|
-
|
|
8
5
|
const defaultSlidesDir = resolve(import.meta.dirname, "..", "slides");
|
|
9
|
-
const slidesDir = process.env.SLIDES_DIR;
|
|
10
6
|
const pagesDir = "pages";
|
|
11
|
-
|
|
12
7
|
// Ensure pages directory exists
|
|
13
8
|
await mkdir(pagesDir, { recursive: true });
|
|
14
|
-
|
|
15
|
-
async function buildSlide(slideName: string) {
|
|
9
|
+
async function buildSlide(slideName) {
|
|
16
10
|
console.log(`Building ${slideName}...`);
|
|
17
11
|
process.env.SLIDE_NAME = slideName;
|
|
18
|
-
execSync("
|
|
19
|
-
|
|
12
|
+
execSync("npx vite build", { stdio: "inherit" });
|
|
20
13
|
const slideOutputDir = join(pagesDir, slideName);
|
|
21
14
|
await mkdir(slideOutputDir, { recursive: true });
|
|
22
15
|
await cp("dist", slideOutputDir, { recursive: true });
|
|
23
16
|
}
|
|
24
|
-
|
|
25
|
-
async function createIndexPage(slideNames: string[]) {
|
|
17
|
+
async function createIndexPage(slideNames) {
|
|
26
18
|
const slides = slideNames
|
|
27
19
|
.map((name) => ` <li><a href="${name}/">${name}</a></li>`)
|
|
28
20
|
.join("\n");
|
|
29
|
-
|
|
30
21
|
const html = `<!DOCTYPE html>
|
|
31
22
|
<html>
|
|
32
23
|
<head>
|
|
@@ -40,12 +31,10 @@ ${slides}
|
|
|
40
31
|
</ul>
|
|
41
32
|
</body>
|
|
42
33
|
</html>`;
|
|
43
|
-
|
|
44
34
|
await writeFile(join(pagesDir, "index.html"), html);
|
|
45
35
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
const resolvedSlidesDir = slidesDir ?? defaultSlidesDir;
|
|
36
|
+
export async function buildPages(options = {}) {
|
|
37
|
+
const resolvedSlidesDir = options.slidesDir ?? defaultSlidesDir;
|
|
49
38
|
// Build all slides
|
|
50
39
|
if (!existsSync(resolvedSlidesDir)) {
|
|
51
40
|
throw new Error(`Slides directory not found (tried: ${resolvedSlidesDir})`);
|
|
@@ -57,15 +46,18 @@ async function main() {
|
|
|
57
46
|
const slides = slideNames.filter((_, index) =>
|
|
58
47
|
slideStats[index].isDirectory(),
|
|
59
48
|
);
|
|
60
|
-
|
|
61
49
|
if (slides.length === 0) {
|
|
62
50
|
throw new Error("No slides found");
|
|
63
51
|
}
|
|
64
|
-
|
|
65
52
|
for (const slide of slides) {
|
|
66
53
|
await buildSlide(slide);
|
|
67
54
|
}
|
|
68
55
|
await createIndexPage(slides);
|
|
69
56
|
}
|
|
70
|
-
|
|
71
|
-
|
|
57
|
+
// CLI entry point
|
|
58
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
59
|
+
buildPages({ slidesDir: process.env.SLIDES_DIR }).catch((error) => {
|
|
60
|
+
console.error(error);
|
|
61
|
+
process.exit(1);
|
|
62
|
+
});
|
|
63
|
+
}
|
|
@@ -127,12 +127,12 @@ const nullPrefixedVirtualFilePageIdPattern =
|
|
|
127
127
|
export default async function slidesPlugin(
|
|
128
128
|
options: SlidesPluginOptions = {},
|
|
129
129
|
): Promise<Plugin> {
|
|
130
|
-
const
|
|
130
|
+
const config = { ...defaultOptions, ...options };
|
|
131
131
|
|
|
132
132
|
// Validate slides directory
|
|
133
133
|
try {
|
|
134
|
-
validateSlidesDir(
|
|
135
|
-
logger.info(`Using slides directory: ${
|
|
134
|
+
validateSlidesDir(config.slidesDir);
|
|
135
|
+
logger.info(`Using slides directory: ${config.slidesDir}`);
|
|
136
136
|
} catch (error) {
|
|
137
137
|
if (error instanceof Error) {
|
|
138
138
|
logger.error("Failed to validate slides directory", error);
|
|
@@ -140,12 +140,13 @@ export default async function slidesPlugin(
|
|
|
140
140
|
throw error;
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
}
|
|
143
|
+
if (config.collection) {
|
|
144
|
+
logger.info(`Using slide: ${config.collection}`);
|
|
145
|
+
} else {
|
|
146
|
+
logger.info("No slide collection specified, prompting for selection");
|
|
147
|
+
config.collection = await selectSlideCollection(config.slidesDir);
|
|
148
|
+
}
|
|
149
|
+
|
|
149
150
|
let base: string;
|
|
150
151
|
let compiledSlides: string[] = [];
|
|
151
152
|
return {
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
|
4
|
+
"target": "ES2020",
|
|
5
|
+
"useDefineForClassFields": true,
|
|
6
|
+
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
|
7
|
+
"module": "ESNext",
|
|
8
|
+
"skipLibCheck": true,
|
|
9
|
+
|
|
10
|
+
/* Bundler mode */
|
|
11
|
+
"moduleResolution": "bundler",
|
|
12
|
+
"allowImportingTsExtensions": true,
|
|
13
|
+
"isolatedModules": true,
|
|
14
|
+
"moduleDetection": "force",
|
|
15
|
+
"noEmit": true,
|
|
16
|
+
"jsx": "react-jsx",
|
|
17
|
+
|
|
18
|
+
/* Linting */
|
|
19
|
+
"strict": true,
|
|
20
|
+
"noUnusedLocals": true,
|
|
21
|
+
"noUnusedParameters": true,
|
|
22
|
+
"noFallthroughCasesInSwitch": true,
|
|
23
|
+
"noUncheckedSideEffectImports": true
|
|
24
|
+
},
|
|
25
|
+
"include": ["src"]
|
|
26
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
|
|
4
|
+
"target": "ES2022",
|
|
5
|
+
"lib": ["ES2023"],
|
|
6
|
+
"module": "ESNext",
|
|
7
|
+
"skipLibCheck": true,
|
|
8
|
+
|
|
9
|
+
/* Bundler mode */
|
|
10
|
+
"moduleResolution": "bundler",
|
|
11
|
+
"allowImportingTsExtensions": true,
|
|
12
|
+
"rewriteRelativeImportExtensions": true,
|
|
13
|
+
"isolatedModules": true,
|
|
14
|
+
"moduleDetection": "force",
|
|
15
|
+
|
|
16
|
+
/* Linting */
|
|
17
|
+
"strict": true,
|
|
18
|
+
"noUnusedLocals": true,
|
|
19
|
+
"noUnusedParameters": true,
|
|
20
|
+
"noFallthroughCasesInSwitch": true,
|
|
21
|
+
"noUncheckedSideEffectImports": true
|
|
22
|
+
},
|
|
23
|
+
"include": ["scripts/**/*.ts"]
|
|
24
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
|
|
4
|
+
"target": "ES2022",
|
|
5
|
+
"lib": ["ES2023"],
|
|
6
|
+
"module": "ESNext",
|
|
7
|
+
"skipLibCheck": true,
|
|
8
|
+
|
|
9
|
+
/* Bundler mode */
|
|
10
|
+
"moduleResolution": "bundler",
|
|
11
|
+
"allowImportingTsExtensions": true,
|
|
12
|
+
"isolatedModules": true,
|
|
13
|
+
"moduleDetection": "force",
|
|
14
|
+
"noEmit": true,
|
|
15
|
+
|
|
16
|
+
/* Linting */
|
|
17
|
+
"strict": true,
|
|
18
|
+
"noUnusedLocals": true,
|
|
19
|
+
"noUnusedParameters": true,
|
|
20
|
+
"noFallthroughCasesInSwitch": true,
|
|
21
|
+
"noUncheckedSideEffectImports": true
|
|
22
|
+
},
|
|
23
|
+
"include": ["vite.config.ts"]
|
|
24
|
+
}
|
package/vite.config.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { defineConfig } from "vite";
|
|
2
|
+
import react from "@vitejs/plugin-react-swc";
|
|
3
|
+
import mdx from "@mdx-js/rollup";
|
|
4
|
+
import * as path from "node:path";
|
|
5
|
+
import slidesPlugin from "./src/vite-plugin-slides";
|
|
6
|
+
|
|
7
|
+
export default defineConfig(async () => {
|
|
8
|
+
return {
|
|
9
|
+
base: "./",
|
|
10
|
+
resolve: {
|
|
11
|
+
alias: {
|
|
12
|
+
"@components": "/src/slide-components",
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
plugins: [
|
|
16
|
+
await slidesPlugin({
|
|
17
|
+
slidesDir:
|
|
18
|
+
process.env.SLIDES_DIR || path.resolve(import.meta.dirname, "slides"),
|
|
19
|
+
collection:
|
|
20
|
+
process.env.SLIDE_NAME || (process.env.isAI ? "vrt-test" : undefined),
|
|
21
|
+
}),
|
|
22
|
+
mdx({
|
|
23
|
+
jsx: true,
|
|
24
|
+
jsxImportSource: "react",
|
|
25
|
+
providerImportSource: "@mdx-js/react",
|
|
26
|
+
}),
|
|
27
|
+
react(),
|
|
28
|
+
],
|
|
29
|
+
optimizeDeps: {
|
|
30
|
+
// Add virtual module to optimization
|
|
31
|
+
// include: ["virtual:slides.js", "virtual:slides-page-*.js"],
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
});
|