@exor404/mdslides 0.1.0 → 0.1.3
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 +108 -29
- package/app/integrations/mdslides-assets.js +9 -1
- package/bin/cli.js +20 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,32 +12,78 @@ dev server or builds a self-contained `dist/` you can host anywhere static.
|
|
|
12
12
|
## Quick start
|
|
13
13
|
|
|
14
14
|
```bash
|
|
15
|
-
mdslides
|
|
15
|
+
npx @exor404/mdslides@latest
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
`
|
|
23
|
-
|
|
18
|
+
No install step. It **asks for a name**, scaffolds `<name>/<name>.md` (three
|
|
19
|
+
sample slides — a title page, a list, and a help slide) plus a
|
|
20
|
+
`mdslides.config.js`, and opens the dev server. The name defaults to the current
|
|
21
|
+
folder, so pressing Enter at `Name your presentation (chemistry):` gives you
|
|
22
|
+
`chemistry/chemistry.md`. That file *is* your deck — edit it and the slides
|
|
23
|
+
live-reload.
|
|
24
|
+
|
|
25
|
+
Point it at a folder for the other commands:
|
|
24
26
|
|
|
25
27
|
```bash
|
|
26
|
-
mdslides ./chemistry # present (dev server, live-reload)
|
|
27
|
-
mdslides build ./chemistry # static build → ./chemistry/dist/
|
|
28
|
-
mdslides preview ./chemistry # serve the built dist/
|
|
29
|
-
mdslides export ./chemistry # → chemistry.pdf (one page per slide)
|
|
28
|
+
npx @exor404/mdslides ./chemistry # present (dev server, live-reload)
|
|
29
|
+
npx @exor404/mdslides build ./chemistry # static build → ./chemistry/dist/
|
|
30
|
+
npx @exor404/mdslides preview ./chemistry # serve the built dist/
|
|
31
|
+
npx @exor404/mdslides export ./chemistry # → chemistry.pdf (one page per slide)
|
|
30
32
|
```
|
|
31
33
|
|
|
32
|
-
Already have a deck? Point straight at the file: `mdslides ./chemistry.md`.
|
|
34
|
+
Already have a deck? Point straight at the file: `npx @exor404/mdslides ./chemistry.md`.
|
|
35
|
+
|
|
36
|
+
> **Heads-up:** `npm install @exor404/mdslides` only *installs* the package —
|
|
37
|
+
> running the CLI (via `npx`, as above) is what scaffolds and presents. Using
|
|
38
|
+
> `npx` also keeps the engine's dependencies in npx's cache instead of bloating
|
|
39
|
+
> a project's `node_modules`.
|
|
33
40
|
|
|
34
|
-
|
|
41
|
+
Prefer a global command? `npm i -g @exor404/mdslides` makes `mdslides` available
|
|
42
|
+
directly (`mdslides ./chemistry`).
|
|
43
|
+
|
|
44
|
+
Try the bundled example from a clone:
|
|
35
45
|
|
|
36
46
|
```bash
|
|
37
47
|
npm install
|
|
38
48
|
npm run dev # opens ./example
|
|
39
49
|
```
|
|
40
50
|
|
|
51
|
+
## Install
|
|
52
|
+
|
|
53
|
+
The package is published on the public npm registry as
|
|
54
|
+
[`@exor404/mdslides`](https://www.npmjs.com/package/@exor404/mdslides). Pick the
|
|
55
|
+
option that suits you:
|
|
56
|
+
|
|
57
|
+
**No install (recommended).** `npx` fetches and caches the latest version, then
|
|
58
|
+
runs it — nothing is added to your project:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
npx @exor404/mdslides@latest # prompts for a name, scaffolds + presents
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
**Global install.** Puts an `mdslides` command on your `PATH`:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
npm install -g @exor404/mdslides
|
|
68
|
+
mdslides ./chemistry # then use it anywhere
|
|
69
|
+
mdslides --help # (or run with no folder to start fresh)
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Update later with `npm update -g @exor404/mdslides`; remove with
|
|
73
|
+
`npm uninstall -g @exor404/mdslides`.
|
|
74
|
+
|
|
75
|
+
**As a project dependency.** Add it to a repo so collaborators get the same
|
|
76
|
+
version via `npm install`:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
npm install -D @exor404/mdslides
|
|
80
|
+
npx mdslides ./chemistry # resolves from local node_modules
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
> Requires **Node 18+**. Installing the package pulls in its rendering engine
|
|
84
|
+
> (Astro, Shiki, KaTeX) — that's why `npx` is the lightest way to try it: those
|
|
85
|
+
> dependencies stay in npx's cache instead of your project's `node_modules`.
|
|
86
|
+
|
|
41
87
|
## The deck model
|
|
42
88
|
|
|
43
89
|
**One markdown file is the whole deck.** Every `#` (H1) heading starts a new
|
|
@@ -147,33 +193,66 @@ fragments shown). It uses [Playwright](https://playwright.dev) if installed
|
|
|
147
193
|
Releases go to the **public npm registry** (npmjs.com), so anyone can
|
|
148
194
|
`npx @exor404/mdslides`. A tag-triggered GitHub Actions pipeline
|
|
149
195
|
([`.github/workflows/package-publish.yml`](.github/workflows/package-publish.yml))
|
|
150
|
-
|
|
151
|
-
|
|
196
|
+
does the publishing for you: it runs **only when you push a `v*` tag**, verifies
|
|
197
|
+
the tag matches `package.json`, and runs `npm publish` against npmjs.com using an
|
|
198
|
+
automation token stored as the `NPM_TOKEN` repository secret.
|
|
152
199
|
|
|
153
|
-
|
|
154
|
-
existing package):
|
|
200
|
+
### How the pipeline works
|
|
155
201
|
|
|
156
|
-
```bash
|
|
157
|
-
npm login # browser sign-in to npmjs.com
|
|
158
|
-
npm publish --access public # publish the first version by hand
|
|
159
202
|
```
|
|
203
|
+
push tag v0.1.3 ──► GitHub Actions ──► checkout ──► setup Node 22
|
|
204
|
+
│
|
|
205
|
+
├─ guard: tag (v0.1.3) must equal
|
|
206
|
+
│ package.json "version" (0.1.3),
|
|
207
|
+
│ else the run fails
|
|
208
|
+
│
|
|
209
|
+
└─ npm publish (auth: NPM_TOKEN)
|
|
210
|
+
└──► npmjs.com
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
The version guard means the git tag and the published version can never drift —
|
|
214
|
+
if they disagree, the run stops before publishing.
|
|
160
215
|
|
|
161
|
-
|
|
162
|
-
Actions** and register:
|
|
216
|
+
### One-time setup
|
|
163
217
|
|
|
164
|
-
|
|
165
|
-
|
|
218
|
+
You only do this once. It wires an npm token into the repo so Actions can publish
|
|
219
|
+
on your behalf.
|
|
166
220
|
|
|
167
|
-
|
|
221
|
+
1. **Create an npm automation token.** On npmjs.com: avatar → **Access Tokens** →
|
|
222
|
+
**Generate New Token** → **Automation** (or a **Granular** token scoped to the
|
|
223
|
+
`@exor404/mdslides` package with **Read and write**). Copy the value — npm
|
|
224
|
+
shows it only once.
|
|
225
|
+
2. **Add it to GitHub as a secret.** Repo → **Settings** → **Secrets and
|
|
226
|
+
variables** → **Actions** → **New repository secret**. Name it exactly
|
|
227
|
+
`NPM_TOKEN`, paste the token, **Add secret**. (It's a *secret*, not a
|
|
228
|
+
*variable* — secrets are encrypted and hidden from logs.)
|
|
229
|
+
|
|
230
|
+
> The very first version must exist on npm before automation can update it.
|
|
231
|
+
> If the package isn't published yet, do one manual publish first:
|
|
232
|
+
> `npm login && npm publish --access public`.
|
|
233
|
+
|
|
234
|
+
### Cutting a release
|
|
235
|
+
|
|
236
|
+
Once the secret is in place, every release is three commands:
|
|
168
237
|
|
|
169
238
|
```bash
|
|
170
|
-
npm version patch # bumps package.json (0.1.
|
|
239
|
+
npm version patch # bumps package.json (0.1.2 → 0.1.3) and commits + tags v0.1.3
|
|
171
240
|
git push origin main # push the version-bump commit
|
|
172
|
-
git push origin v0.1.
|
|
241
|
+
git push origin v0.1.3 # push the tag → the pipeline publishes
|
|
173
242
|
```
|
|
174
243
|
|
|
175
|
-
`npm version`
|
|
176
|
-
|
|
244
|
+
`npm version patch` (or `minor` / `major`) bumps `package.json`, makes the commit,
|
|
245
|
+
and creates the matching `vX.Y.Z` tag in one step. Pushing that tag is what
|
|
246
|
+
triggers the workflow. Watch it run under the repo's **Actions** tab; when it goes
|
|
247
|
+
green the new version is live on npm.
|
|
248
|
+
|
|
249
|
+
**Prefer to bump by hand?** Edit `"version"` in `package.json`, then:
|
|
250
|
+
|
|
251
|
+
```bash
|
|
252
|
+
git commit -am "🔖 Release 0.1.3"
|
|
253
|
+
git tag v0.1.3 # must match package.json exactly, or the guard fails
|
|
254
|
+
git push && git push --tags
|
|
255
|
+
```
|
|
177
256
|
|
|
178
257
|
## Requirements
|
|
179
258
|
|
|
@@ -23,7 +23,15 @@ const MIME = {
|
|
|
23
23
|
};
|
|
24
24
|
|
|
25
25
|
const EXCLUDED_TOP = new Set(['dist', 'node_modules', '.git', '.astro', '.vscode', '.idea']);
|
|
26
|
-
const EXCLUDED_FILES = new Set([
|
|
26
|
+
const EXCLUDED_FILES = new Set([
|
|
27
|
+
'mdslides.config.js',
|
|
28
|
+
// Project scaffolding that lives alongside the deck (npm create … layout) —
|
|
29
|
+
// never part of the presentation, so keep it out of the built dist/.
|
|
30
|
+
'package.json',
|
|
31
|
+
'package-lock.json',
|
|
32
|
+
'yarn.lock',
|
|
33
|
+
'pnpm-lock.yaml',
|
|
34
|
+
]);
|
|
27
35
|
|
|
28
36
|
function isExcludedRel(rel) {
|
|
29
37
|
if (!rel || rel === '.' || rel === '..') return true;
|
package/bin/cli.js
CHANGED
|
@@ -60,7 +60,10 @@ function parseArgs(argv) {
|
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
|
|
63
|
+
// No target + the default `dev` command → start a brand-new project: we'll
|
|
64
|
+
// prompt for a name and scaffold it. Any other command needs an explicit
|
|
65
|
+
// target (there's nothing to build/preview/export yet).
|
|
66
|
+
if (!file && cmd !== 'dev') {
|
|
64
67
|
fail('Missing target.\nUsage: mdslides [dev|build|preview|export] [--theme <name>] <folder|file.md>');
|
|
65
68
|
}
|
|
66
69
|
|
|
@@ -130,6 +133,21 @@ async function scaffoldProject(dir) {
|
|
|
130
133
|
return scaffoldDeck(resolve(dir, `${stem}.md`));
|
|
131
134
|
}
|
|
132
135
|
|
|
136
|
+
// Start a project from scratch when `mdslides` is run with no target (e.g.
|
|
137
|
+
// `npx @exor404/mdslides`): ask for a name, then create `<name>/<name>.md` in
|
|
138
|
+
// the current directory and present it. No install or extra command needed.
|
|
139
|
+
async function scaffoldNewProject() {
|
|
140
|
+
const fallback = slugify(basename(process.cwd())) || 'presentation';
|
|
141
|
+
const answer = await ask(`Name your presentation (${fallback}): `, fallback);
|
|
142
|
+
const stem = slugify(answer.replace(/\.md$/i, '')) || fallback;
|
|
143
|
+
const dir = resolve(process.cwd(), stem);
|
|
144
|
+
if (existsSync(dir) && statSync(dir).isDirectory() && findDeckInDir(dir)) {
|
|
145
|
+
// A deck already lives here — open it instead of clobbering anything.
|
|
146
|
+
return findDeckInDir(dir);
|
|
147
|
+
}
|
|
148
|
+
return scaffoldDeck(resolve(dir, `${stem}.md`));
|
|
149
|
+
}
|
|
150
|
+
|
|
133
151
|
function scaffoldDeck(deckPath) {
|
|
134
152
|
const templatePath = resolve(__dirname, 'templates', 'slides.md');
|
|
135
153
|
try {
|
|
@@ -169,7 +187,7 @@ async function loadUserConfig(source) {
|
|
|
169
187
|
}
|
|
170
188
|
|
|
171
189
|
const { cmd, theme: cliTheme, file } = parseArgs(process.argv);
|
|
172
|
-
const deckFile = await resolveDeck(file);
|
|
190
|
+
const deckFile = file ? await resolveDeck(file) : await scaffoldNewProject();
|
|
173
191
|
const source = dirname(deckFile);
|
|
174
192
|
|
|
175
193
|
ensureDefaultConfig(source);
|