@zinejs/create 0.9.1
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/index.js +139 -0
- package/package.json +25 -0
- package/templates/image/README.md +25 -0
- package/templates/image/_gitignore +4 -0
- package/templates/image/index.html +25 -0
- package/templates/image/package.json +16 -0
- package/templates/image/public/pages/page-1.png +0 -0
- package/templates/image/public/pages/page-2.png +0 -0
- package/templates/image/public/pages/page-3.png +0 -0
- package/templates/image/public/pages/page-4.png +0 -0
- package/templates/image/src/main.js +11 -0
- package/templates/pdf/README.md +30 -0
- package/templates/pdf/_gitignore +4 -0
- package/templates/pdf/index.html +25 -0
- package/templates/pdf/package.json +17 -0
- package/templates/pdf/public/sample.pdf +0 -0
- package/templates/pdf/src/main.js +8 -0
- package/templates/pdf/vite.config.js +10 -0
package/index.js
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Scaffold a new zinejs flipbook project. Run via `npm create @zinejs`,
|
|
3
|
+
// `pnpm create @zinejs`, or `yarn create @zinejs`. Zero runtime dependencies.
|
|
4
|
+
import * as fs from 'node:fs';
|
|
5
|
+
import * as path from 'node:path';
|
|
6
|
+
import * as readline from 'node:readline/promises';
|
|
7
|
+
import { fileURLToPath } from 'node:url';
|
|
8
|
+
|
|
9
|
+
const HERE = path.dirname(fileURLToPath(import.meta.url));
|
|
10
|
+
const TEMPLATES = new Set(['image', 'pdf']);
|
|
11
|
+
const SELF_VERSION = JSON.parse(fs.readFileSync(path.join(HERE, 'package.json'), 'utf8')).version;
|
|
12
|
+
|
|
13
|
+
function help() {
|
|
14
|
+
console.log(`
|
|
15
|
+
Create a zinejs flipbook project.
|
|
16
|
+
|
|
17
|
+
Usage:
|
|
18
|
+
npm create @zinejs [dir] [options]
|
|
19
|
+
|
|
20
|
+
Options:
|
|
21
|
+
--template <image|pdf> Starter to use (prompted if omitted)
|
|
22
|
+
--force Scaffold into a non-empty directory
|
|
23
|
+
-h, --help Show this help
|
|
24
|
+
`);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** Turn a directory name into a valid npm package name. */
|
|
28
|
+
function toPkgName(s) {
|
|
29
|
+
const name = s
|
|
30
|
+
.toLowerCase()
|
|
31
|
+
.replace(/[^a-z0-9-~._]/g, '-')
|
|
32
|
+
.replace(/^[._]+/, '')
|
|
33
|
+
.replace(/-+/g, '-')
|
|
34
|
+
.replace(/^-|-$/g, '');
|
|
35
|
+
return name || 'zine-book';
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Copy a template tree, renaming `_gitignore` to `.gitignore` (npm strips real .gitignore). */
|
|
39
|
+
function copyTree(from, to) {
|
|
40
|
+
fs.mkdirSync(to, { recursive: true });
|
|
41
|
+
for (const entry of fs.readdirSync(from, { withFileTypes: true })) {
|
|
42
|
+
const src = path.join(from, entry.name);
|
|
43
|
+
const name = entry.name === '_gitignore' ? '.gitignore' : entry.name;
|
|
44
|
+
const dest = path.join(to, name);
|
|
45
|
+
if (entry.isDirectory()) copyTree(src, dest);
|
|
46
|
+
else fs.copyFileSync(src, dest);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** Set the project name and pin @zinejs/* deps to this tool's version. */
|
|
51
|
+
function patchPackageJson(dir, projectName) {
|
|
52
|
+
const file = path.join(dir, 'package.json');
|
|
53
|
+
const pkg = JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
54
|
+
pkg.name = projectName;
|
|
55
|
+
for (const dep of Object.keys(pkg.dependencies ?? {})) {
|
|
56
|
+
if (dep.startsWith('@zinejs/')) pkg.dependencies[dep] = `^${SELF_VERSION}`;
|
|
57
|
+
}
|
|
58
|
+
fs.writeFileSync(file, JSON.stringify(pkg, null, 2) + '\n');
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function parseArgs(argv) {
|
|
62
|
+
const out = { dir: undefined, template: undefined, force: false, help: false };
|
|
63
|
+
for (let i = 0; i < argv.length; i++) {
|
|
64
|
+
const a = argv[i];
|
|
65
|
+
if (a === '-h' || a === '--help') out.help = true;
|
|
66
|
+
else if (a === '--force') out.force = true;
|
|
67
|
+
else if (a === '--template') out.template = argv[++i];
|
|
68
|
+
else if (a.startsWith('--template=')) out.template = a.slice('--template='.length);
|
|
69
|
+
else if (!a.startsWith('-') && out.dir === undefined) out.dir = a;
|
|
70
|
+
}
|
|
71
|
+
return out;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async function main() {
|
|
75
|
+
const args = parseArgs(process.argv.slice(2));
|
|
76
|
+
if (args.help) {
|
|
77
|
+
help();
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const interactive = process.stdin.isTTY && process.stdout.isTTY;
|
|
82
|
+
const rl = interactive
|
|
83
|
+
? readline.createInterface({ input: process.stdin, output: process.stdout })
|
|
84
|
+
: null;
|
|
85
|
+
const ask = async (q, def) => {
|
|
86
|
+
if (!rl) return def;
|
|
87
|
+
const a = (await rl.question(q)).trim();
|
|
88
|
+
return a || def;
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
try {
|
|
92
|
+
const dir = args.dir ?? (await ask('Project directory: (my-zine-book) ', 'my-zine-book'));
|
|
93
|
+
|
|
94
|
+
let template = args.template;
|
|
95
|
+
if (template && !TEMPLATES.has(template)) {
|
|
96
|
+
console.error(`error: unknown template '${template}' (expected image or pdf)`);
|
|
97
|
+
process.exitCode = 1;
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
if (!template) {
|
|
101
|
+
const a = await ask('Source type: image or pdf? (image) ', 'image');
|
|
102
|
+
template = a.toLowerCase();
|
|
103
|
+
if (!TEMPLATES.has(template)) {
|
|
104
|
+
console.error(`error: unknown template '${template}' (expected image or pdf)`);
|
|
105
|
+
process.exitCode = 1;
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const target = path.resolve(process.cwd(), dir);
|
|
111
|
+
if (fs.existsSync(target)) {
|
|
112
|
+
const rest = fs.readdirSync(target).filter((f) => f !== '.git');
|
|
113
|
+
if (rest.length > 0 && !args.force) {
|
|
114
|
+
console.error(`error: ${dir} is not empty. Use --force to scaffold into it anyway.`);
|
|
115
|
+
process.exitCode = 1;
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
copyTree(path.join(HERE, 'templates', template), target);
|
|
121
|
+
patchPackageJson(target, toPkgName(path.basename(target)));
|
|
122
|
+
|
|
123
|
+
console.log(`
|
|
124
|
+
Created a zinejs (${template}) flipbook in ${dir}
|
|
125
|
+
|
|
126
|
+
Next steps:
|
|
127
|
+
cd ${dir}
|
|
128
|
+
npm install
|
|
129
|
+
npm run dev
|
|
130
|
+
`);
|
|
131
|
+
} finally {
|
|
132
|
+
rl?.close();
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
main().catch((err) => {
|
|
137
|
+
console.error(err);
|
|
138
|
+
process.exitCode = 1;
|
|
139
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@zinejs/create",
|
|
3
|
+
"version": "0.9.1",
|
|
4
|
+
"description": "Scaffold a new zinejs flipbook project (npm create @zinejs).",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "PolyForm-Noncommercial-1.0.0",
|
|
7
|
+
"keywords": ["zinejs", "flipbook", "create", "scaffold", "starter"],
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/awecode/zinejs.git",
|
|
11
|
+
"directory": "packages/create"
|
|
12
|
+
},
|
|
13
|
+
"homepage": "https://zinejs.com",
|
|
14
|
+
"bugs": "https://github.com/awecode/zinejs/issues",
|
|
15
|
+
"bin": {
|
|
16
|
+
"create-zine": "index.js"
|
|
17
|
+
},
|
|
18
|
+
"files": ["index.js", "templates"],
|
|
19
|
+
"publishConfig": {
|
|
20
|
+
"access": "public"
|
|
21
|
+
},
|
|
22
|
+
"scripts": {
|
|
23
|
+
"test": "vitest run"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# zinejs flipbook (image book)
|
|
2
|
+
|
|
3
|
+
A flipbook built from page images, powered by [zinejs](https://zinejs.com/docs/).
|
|
4
|
+
|
|
5
|
+
## Develop
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install
|
|
9
|
+
npm run dev
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Your pages
|
|
13
|
+
|
|
14
|
+
Replace the images in `public/pages/` with your own and update the list in
|
|
15
|
+
`src/main.js`. Drag a corner or click near an edge to turn; arrow keys work when
|
|
16
|
+
the book is focused; pinch or Ctrl/Cmd+wheel to zoom.
|
|
17
|
+
|
|
18
|
+
## Build
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm run build # outputs to dist/
|
|
22
|
+
npm run preview # serve the production build
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Docs and options: https://zinejs.com/docs/
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<title>zinejs flipbook</title>
|
|
7
|
+
<style>
|
|
8
|
+
body {
|
|
9
|
+
margin: 0;
|
|
10
|
+
min-height: 100vh;
|
|
11
|
+
display: grid;
|
|
12
|
+
place-items: center;
|
|
13
|
+
background: #14141b;
|
|
14
|
+
}
|
|
15
|
+
/* Size the book by width; zinejs sets the height via aspect-ratio after the first paint. */
|
|
16
|
+
#book {
|
|
17
|
+
width: min(900px, 92vw);
|
|
18
|
+
}
|
|
19
|
+
</style>
|
|
20
|
+
</head>
|
|
21
|
+
<body>
|
|
22
|
+
<div id="book"></div>
|
|
23
|
+
<script type="module" src="/src/main.js"></script>
|
|
24
|
+
</body>
|
|
25
|
+
</html>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "zine-book",
|
|
3
|
+
"private": true,
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "vite",
|
|
7
|
+
"build": "vite build",
|
|
8
|
+
"preview": "vite preview"
|
|
9
|
+
},
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"@zinejs/core": "^0.9.1"
|
|
12
|
+
},
|
|
13
|
+
"devDependencies": {
|
|
14
|
+
"vite": "^8.0.0"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Zine, ImageSource } from '@zinejs/core';
|
|
2
|
+
|
|
3
|
+
// A flipbook from a list of image URLs. Drop your own pages in public/pages/.
|
|
4
|
+
new Zine(document.getElementById('book'), {
|
|
5
|
+
source: new ImageSource([
|
|
6
|
+
'/pages/page-1.png',
|
|
7
|
+
'/pages/page-2.png',
|
|
8
|
+
'/pages/page-3.png',
|
|
9
|
+
'/pages/page-4.png',
|
|
10
|
+
]),
|
|
11
|
+
});
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# zinejs flipbook (PDF book)
|
|
2
|
+
|
|
3
|
+
A flipbook built from a PDF, powered by [zinejs](https://zinejs.com/docs/) and
|
|
4
|
+
[@zinejs/pdf](https://www.npmjs.com/package/@zinejs/pdf).
|
|
5
|
+
|
|
6
|
+
## Develop
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
npm install
|
|
10
|
+
npm run dev
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Your document
|
|
14
|
+
|
|
15
|
+
Replace `public/sample.pdf` with your own and update the path in `src/main.js`.
|
|
16
|
+
Under a bundler the pdf.js worker is resolved automatically; see the
|
|
17
|
+
[worker notes](https://zinejs.com/docs/) for CDN / offline setups. Drag a corner
|
|
18
|
+
or click near an edge to turn; pinch or Ctrl/Cmd+wheel to zoom.
|
|
19
|
+
|
|
20
|
+
`vite.config.js` excludes `@zinejs/pdf` from dependency pre-bundling so Vite can
|
|
21
|
+
resolve the pdf.js worker; keep it when you add your own config.
|
|
22
|
+
|
|
23
|
+
## Build
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm run build # outputs to dist/
|
|
27
|
+
npm run preview # serve the production build
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Docs and options: https://zinejs.com/docs/
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<title>zinejs flipbook</title>
|
|
7
|
+
<style>
|
|
8
|
+
body {
|
|
9
|
+
margin: 0;
|
|
10
|
+
min-height: 100vh;
|
|
11
|
+
display: grid;
|
|
12
|
+
place-items: center;
|
|
13
|
+
background: #14141b;
|
|
14
|
+
}
|
|
15
|
+
/* Size the book by width; zinejs sets the height via aspect-ratio after the first paint. */
|
|
16
|
+
#book {
|
|
17
|
+
width: min(900px, 92vw);
|
|
18
|
+
}
|
|
19
|
+
</style>
|
|
20
|
+
</head>
|
|
21
|
+
<body>
|
|
22
|
+
<div id="book"></div>
|
|
23
|
+
<script type="module" src="/src/main.js"></script>
|
|
24
|
+
</body>
|
|
25
|
+
</html>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "zine-book",
|
|
3
|
+
"private": true,
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "vite",
|
|
7
|
+
"build": "vite build",
|
|
8
|
+
"preview": "vite preview"
|
|
9
|
+
},
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"@zinejs/core": "^0.9.1",
|
|
12
|
+
"@zinejs/pdf": "^0.9.1"
|
|
13
|
+
},
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"vite": "^8.0.0"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Zine } from '@zinejs/core';
|
|
2
|
+
import { PdfSource } from '@zinejs/pdf';
|
|
3
|
+
|
|
4
|
+
// A flipbook from a PDF. Replace public/sample.pdf with your own document.
|
|
5
|
+
// Under a bundler (Vite here) the pdf.js worker is resolved for you.
|
|
6
|
+
new Zine(document.getElementById('book'), {
|
|
7
|
+
source: new PdfSource('/sample.pdf'),
|
|
8
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { defineConfig } from 'vite';
|
|
2
|
+
|
|
3
|
+
// @zinejs/pdf loads the pdf.js worker through a `?url` import that Vite's dependency
|
|
4
|
+
// pre-bundler cannot follow. Excluding it lets Vite's normal pipeline resolve the
|
|
5
|
+
// worker, so PDF books work in dev and build. See https://zinejs.com/docs/ (worker notes).
|
|
6
|
+
export default defineConfig({
|
|
7
|
+
optimizeDeps: {
|
|
8
|
+
exclude: ['@zinejs/pdf'],
|
|
9
|
+
},
|
|
10
|
+
});
|