Skip to content

Commit c0f944a

Browse files
committed
feat(docs): add Exclude and README Index plugins, regroup plugin pages
1 parent b662af9 commit c0f944a

17 files changed

Lines changed: 453 additions & 134 deletions

File tree

‎README.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ It documents BinaryNoir's open-source VitePress plugins, Vite plugins and comman
1616
| [`markdown-it-glossary`](https://github.com/binarynoir/markdown-it-glossary) | Hover definitions from `docs/reference/glossary.md` |
1717
| [`@binarynoir/vitepress-html-escape`](https://github.com/binarynoir/vitepress-html-escape) | Stray tags like `Array<string>` and `{{ }}` render as text; hints underline them in `docs:dev` |
1818
| [`@binarynoir/vitepress-broken-links`](https://github.com/binarynoir/vitepress-broken-links) | Dead links render as text with a fix-it popover instead of failing the build |
19+
| [`@binarynoir/vitepress-exclude`](https://github.com/binarynoir/vitepress-exclude) | `.exclude` files keep pages out of the build (a draft in `docs/plugins/exclude/` on purpose) |
20+
| [`@binarynoir/vitepress-readme-index`](https://github.com/binarynoir/vitepress-readme-index) | `README.md` served as a folder's index page, for VuePress migrations |
1921
| [`@binarynoir/vite-plugin-optimize-images`](https://github.com/binarynoir/vite-plugin-optimize-images) | Re-compresses images in the build output |
2022
| [`@binarynoir/vite-plugin-image-fallback`](https://github.com/binarynoir/vite-plugin-image-fallback) | Placeholder for missing images (one is missing on purpose) |
2123

‎docs/.vitepress/config.mts‎

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import { downloadsMarkdown, downloadsVitePlugin } from '@binarynoir/vitepress-do
1212
import { downloadsSrcExclude } from '@binarynoir/vitepress-downloads/vitepress';
1313
import { markdownHtmlEscape } from '@binarynoir/vitepress-html-escape';
1414
import { markdownBrokenLinks } from '@binarynoir/vitepress-broken-links';
15+
import { excludeSrc, excludeVitePlugin } from '@binarynoir/vitepress-exclude';
16+
import { readmeLinks, readmeRewrites } from '@binarynoir/vitepress-readme-index';
1517

1618
// import.meta.dirname, not __dirname: VitePress configs are ESM.
1719
const docsRoot = path.resolve(import.meta.dirname, '..');
@@ -28,8 +30,17 @@ export default defineConfig({
2830
cleanUrls: true,
2931
lastUpdated: true,
3032

31-
// Files in a `downloads` or `files` folder are published as-is, never built as pages.
32-
srcExclude: downloadsSrcExclude(downloadsOptions),
33+
srcExclude: [
34+
// Files in a `downloads` or `files` folder are published as-is, never built as pages.
35+
...downloadsSrcExclude(downloadsOptions),
36+
// @binarynoir/vitepress-exclude: whatever a folder's `.exclude` file lists is not built.
37+
// The same files hide those pages from the sidebar and navbar.
38+
...excludeSrc(docsRoot),
39+
],
40+
41+
// @binarynoir/vitepress-readme-index: a folder's README.md is served as its index page,
42+
// as VuePress did, so a VuePress site can move over without renaming files.
43+
rewrites: readmeRewrites(docsRoot),
3344

3445
sitemap: { hostname: SITE_URL },
3546

@@ -110,6 +121,8 @@ export default defineConfig({
110121
md.use(markdownTags);
111122
// @binarynoir/vitepress-downloads: links into a `downloads` or `files` folder become file downloads.
112123
md.use(downloadsMarkdown, downloadsOptions);
124+
// @binarynoir/vitepress-readme-index: a link to README.md goes to the page it is served as.
125+
md.use(readmeLinks);
113126
// @binarynoir/vitepress-html-escape: stray tags like Array<string>, and {{ }} in prose,
114127
// render as text instead of breaking the Vue compile. It runs after every other rule.
115128
// In `vitepress dev`, hints underline each fix and explain it; `vitepress build` leaves them out.
@@ -141,6 +154,8 @@ export default defineConfig({
141154
taggedPagesVitePlugin(),
142155
// Publishes the files in each `downloads` or `files` folder at their page-relative URL.
143156
downloadsVitePlugin(downloadsOptions),
157+
// Restarts `vitepress dev` when an `.exclude` file changes, so new rules apply right away.
158+
excludeVitePlugin(),
144159
],
145160
},
146161
});

‎docs/guide/how-this-site-works.md‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ title: How this site works
66

77
[[readingTime]]
88

9-
This site is plain VitePress 2 plus ten plugins. There is no hand-written navigation anywhere: add a Markdown file in the right folder and it shows up in the sidebar, the navbar, search and the sitemap.
9+
This site is plain VitePress 2 plus twelve plugins. There is no hand-written navigation anywhere: add a Markdown file in the right folder and it shows up in the sidebar, the navbar, search and the sitemap.
1010

1111
## Folder layout
1212

@@ -19,6 +19,8 @@ docs/
1919
plugins/ developer docs for each plugin
2020
.sidebar order and titles for this section
2121
downloads/ files the Downloads demo publishes as-is
22+
exclude/ a .exclude file and the draft it keeps out of the build
23+
readme-index/ pages served from README.md, as in VuePress
2224
apps/ user docs for the CLI apps
2325
guide/ this section
2426
reference/ glossary terms and the generated list of every tag
@@ -41,6 +43,8 @@ docs/
4143
| File download links | [Downloads](/plugins/downloads) | `markdown.config` and `vite.plugins` |
4244
| Stray `<tags>` shown as text | [HTML Escape](/plugins/html-escape/) | `markdown.config`, plus the theme |
4345
| Dead links shown as text | [Broken Links](/plugins/broken-links) | `markdown.config`, plus the theme |
46+
| Pages left out by `.exclude` | [Exclude](/plugins/exclude/) | `srcExclude` and `vite.plugins` |
47+
| `README.md` as a folder's index | [README Index](/plugins/readme-index/) | `rewrites` and `markdown.config` |
4448
| Smaller images | [Optimize Images](/plugins/optimize-images) | `vite.plugins` |
4549
| Placeholder for a missing image | [Image Fallback](/plugins/image-fallback) | `vite.plugins` |
4650

‎docs/index.md‎

Lines changed: 24 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -25,73 +25,46 @@ features:
2525
dark: /icons/layout-dark.svg
2626
width: 28
2727
height: 28
28-
title: Auto Sidebar & Navbar
29-
details: Menus built from your folder structure, ordered and titled by tiny plain-text files.
30-
link: /plugins/auto-sidebar
31-
linkText: See the sidebar plugin
28+
title: Navigation from your folders
29+
details: Auto Sidebar and Auto Navbar build the menus from your folder tree, ordered and titled by small plain-text files.
30+
link: /plugins/#navigation
31+
linkText: Navigation plugins
3232
- icon:
3333
light: /icons/tag-light.svg
3434
dark: /icons/tag-dark.svg
3535
width: 28
3636
height: 28
37-
title: Markdown Tags
38-
details: Inline status badges for VitePress, VS Code and Obsidian, plus site-wide pages that list every tag.
39-
link: /plugins/markdown-tags/
40-
linkText: See the tags plugin
37+
title: Richer pages
38+
details: Markdown Tags, Glossary Tooltips and Reading Time add status badges, hover definitions and reading-time estimates.
39+
link: /plugins/#pages
40+
linkText: Page plugins
4141
- icon:
42-
light: /icons/book-light.svg
43-
dark: /icons/book-dark.svg
42+
light: /icons/folder-light.svg
43+
dark: /icons/folder-dark.svg
4444
width: 28
4545
height: 28
46-
title: Glossary Tooltips
47-
details: Define a term once and every mention in your docs gets a hover definition.
48-
link: /plugins/glossary
49-
linkText: See the glossary plugin
50-
- icon:
51-
light: /icons/clock-light.svg
52-
dark: /icons/clock-dark.svg
53-
width: 28
54-
height: 28
55-
title: Reading Time
56-
details: One line in a page gets an estimated reading time, computed at build time.
57-
link: /plugins/reading-time-tag
58-
linkText: See the reading-time plugin
59-
- icon:
60-
light: /icons/download-light.svg
61-
dark: /icons/download-dark.svg
62-
width: 28
63-
height: 28
64-
title: Downloads
65-
details: Keep a .sql, .zip or .xlsx next to the page that links to it, and the link downloads the file.
66-
link: /plugins/downloads
67-
linkText: See the downloads plugin
46+
title: Content where it lives
47+
details: Downloads next to the page that links them, drafts left out with a .exclude file, and README.md index pages for VuePress migrations.
48+
link: /plugins/#content
49+
linkText: Content plugins
6850
- icon:
6951
light: /icons/escape-light.svg
7052
dark: /icons/escape-dark.svg
7153
width: 28
7254
height: 28
73-
title: HTML Escape
74-
details: A stray Array&lt;string&gt; or {{ }} in your Markdown shows up as text instead of breaking the build.
75-
link: /plugins/html-escape/
76-
linkText: See the HTML Escape plugin
77-
- icon:
78-
light: /icons/link-light.svg
79-
dark: /icons/link-dark.svg
80-
width: 28
81-
height: 28
82-
title: Broken Links
83-
details: A link to a page that doesn't exist shows up as text with a fix-it hint instead of failing the build.
84-
link: /plugins/broken-links
85-
linkText: See the Broken Links plugin
55+
title: Builds that don't break
56+
details: HTML Escape and Broken Links turn a stray Array&lt;string&gt; or a dead link into a fix-it hint instead of a failed build.
57+
link: /plugins/#builds
58+
linkText: Build plugins
8659
- icon:
8760
light: /icons/image-light.svg
8861
dark: /icons/image-dark.svg
8962
width: 28
9063
height: 28
91-
title: Image Optimization & Fallback
92-
details: Smaller images in the build output, and a placeholder instead of a failed build when one goes missing.
93-
link: /plugins/optimize-images
94-
linkText: See the image plugins
64+
title: Images handled
65+
details: Optimize Images shrinks every image in the build output, and Image Fallback stands in for one that goes missing.
66+
link: /plugins/#images
67+
linkText: Image plugins
9568
- icon:
9669
light: /icons/terminal-light.svg
9770
dark: /icons/terminal-dark.svg
@@ -109,23 +82,9 @@ features:
10982
- **Want a tool for your terminal?** Pick one on the [apps page](/apps/). Each installs with one Homebrew command.
11083
- **Building a site like this one?** Read [how this site works](/guide/how-this-site-works) and copy what is useful.
11184

112-
## Install the whole VitePress toolkit
113-
114-
```sh
115-
npm install --save-dev \
116-
@binarynoir/vitepress-auto-sidebar \
117-
@binarynoir/vitepress-auto-navbar \
118-
@binarynoir/vitepress-markdown-tags \
119-
@binarynoir/vitepress-reading-time-tag \
120-
@binarynoir/vitepress-downloads \
121-
@binarynoir/vitepress-html-escape \
122-
@binarynoir/vitepress-broken-links \
123-
@binarynoir/vite-plugin-optimize-images \
124-
@binarynoir/vite-plugin-image-fallback \
125-
markdown-it-glossary
126-
```
85+
## Install the VitePress toolkit
12786

128-
Every plugin is optional and independent. Take one, or take them all. Each plugin's page shows how to register it, and the VitePress plugins need Node 22 or newer.
87+
Every plugin is optional and independent: take one, or take them all. The [plugins overview](/plugins/#install-them-all) has the one-line install for the whole set, and each plugin's page shows how to register it. The VitePress plugins need Node 22 or newer.
12988

13089
## Support the work
13190

‎docs/plugins/.sidebar‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,21 @@
11
# Titles are set here, not in each page's H1, so the ((tag|...)) badges in the
22
# headings stay out of the menu. The navbar reuses these titles automatically.
3+
# [Group] lines match the groups on the home page and the plugins overview.
34
index.md:Overview
5+
[Navigation from your folders]
46
auto-sidebar.md:Auto Sidebar
57
auto-navbar.md:Auto Navbar
8+
[Richer pages]
69
markdown-tags:Markdown Tags
10+
glossary:Glossary Tooltips
711
reading-time-tag.md:Reading Time Tag
12+
[Content where it lives]
813
downloads.md:Downloads
9-
glossary:Glossary Tooltips
14+
exclude:Exclude
15+
readme-index:README Index
16+
[Builds that don't break]
1017
html-escape:HTML Escape
1118
broken-links.md:Broken Links
19+
[Images handled]
1220
optimize-images.md:Optimize Images
1321
image-fallback.md:Image Fallback

‎docs/plugins/exclude/.exclude‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Demo for the Exclude plugin: draft.md stays in the repository but is not built,
2+
# and Auto Sidebar leaves it out of the menu.
3+
draft.md

‎docs/plugins/exclude/draft.md‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
title: Draft
3+
---
4+
5+
# Draft
6+
7+
This page is the live demo for [Exclude](./index.md). It is listed in this folder's `.exclude` file, so it is never built: if you are reading this on the site, the plugin is not working.

‎docs/plugins/exclude/index.md‎

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
---
2+
title: Exclude
3+
---
4+
5+
# Exclude ((tag|VitePress plugin|blue))
6+
7+
[[readingTime]]
8+
9+
[![GitHub repo](https://img.shields.io/badge/GitHub-binarynoir%2Fvitepress--exclude-181717?logo=github)](https://github.com/binarynoir/vitepress-exclude) [![npm version](https://img.shields.io/npm/v/@binarynoir/vitepress-exclude)](https://www.npmjs.com/package/@binarynoir/vitepress-exclude) [![CI](https://img.shields.io/github/actions/workflow/status/binarynoir/vitepress-exclude/ci.yml?branch=main&label=CI)](https://github.com/binarynoir/vitepress-exclude/actions/workflows/ci.yml) [![License](https://img.shields.io/github/license/binarynoir/vitepress-exclude)](https://github.com/binarynoir/vitepress-exclude/blob/main/LICENSE)
10+
11+
`@binarynoir/vitepress-exclude` keeps pages out of the build with a `.exclude` file in the folder that holds them. VitePress's own `srcExclude` is one list of globs in `config.mts`, far from the pages it hides. With this plugin, each folder says what to leave out, next to the files themselves.
12+
13+
```txt
14+
docs/guide/
15+
.exclude
16+
index.md
17+
draft.md
18+
internal-notes.md
19+
drafts/
20+
```
21+
22+
```txt
23+
# docs/guide/.exclude
24+
draft.md
25+
internal-*.md
26+
drafts/
27+
```
28+
29+
Those pages are not built, not in search and not in the sitemap. The files stay where they are.
30+
31+
## See it live
32+
33+
This page's folder has a [`draft.md`](https://github.com/binarynoir/binarynoir.github.io/blob/main/docs/plugins/exclude/draft.md) next to it, and an [`.exclude`](https://github.com/binarynoir/binarynoir.github.io/blob/main/docs/plugins/exclude/.exclude) file that lists it. The draft is in the repository, but it is not on this site: it is missing from the sidebar, from search and from the build.
34+
35+
[Auto Sidebar](/plugins/auto-sidebar) and [Auto Navbar](/plugins/auto-navbar) read the same `.exclude` files, so one line hides a page from the menus and keeps it out of the build.
36+
37+
## Install
38+
39+
```sh
40+
npm install --save-dev @binarynoir/vitepress-exclude
41+
```
42+
43+
## Use
44+
45+
Wrap the config with `withExclude` and pass it the docs source directory:
46+
47+
```ts
48+
// .vitepress/config.mts
49+
import path from 'node:path';
50+
import { defineConfig } from 'vitepress';
51+
import { withExclude } from '@binarynoir/vitepress-exclude/vitepress';
52+
53+
export default withExclude(
54+
defineConfig({
55+
// ...your config
56+
}),
57+
path.resolve(import.meta.dirname, '..'),
58+
);
59+
```
60+
61+
`withExclude` keeps your existing `srcExclude` and `vite.plugins`, so it composes with other wrappers in any order.
62+
63+
Or wire the two pieces by hand, as this site does to combine them with [Downloads](/plugins/downloads):
64+
65+
```ts
66+
import { excludeSrc, excludeVitePlugin } from '@binarynoir/vitepress-exclude';
67+
68+
const docsRoot = path.resolve(import.meta.dirname, '..');
69+
70+
export default defineConfig({
71+
srcExclude: [...excludeSrc(docsRoot), '**/_snippets/**'],
72+
vite: {
73+
plugins: [excludeVitePlugin()],
74+
},
75+
});
76+
```
77+
78+
## `.exclude` files
79+
80+
One rule per line. Blank lines and lines starting with `#` are ignored. Rules are relative to the folder the `.exclude` file is in, and a `.exclude` file in the docs root works too.
81+
82+
| Rule | Excludes |
83+
| ---------------- | ------------------------------------------------------------- |
84+
| `draft.md` | That file. A name without a `/` also matches a folder. |
85+
| `drafts/` | That folder and everything in it. |
86+
| `internal-*.md` | Matching files in this folder. `*` and `?` stay in one level. |
87+
| `**/internal.md` | Matching files in this folder or any folder below it. |
88+
| `.` | The whole folder the `.exclude` file is in. |
89+
90+
Two kinds of rule are skipped, with a warning in the log:
91+
92+
- `!keep.md`: VitePress cannot re-include a file that another rule excluded.
93+
- `../other.md`: a rule cannot reach outside its own folder. Put a `.exclude` file in that folder instead.
94+
95+
## Options
96+
97+
| Option | Default | Description |
98+
| ------------------ | -------------- | ---------------------------------------------------------- |
99+
| `excludeFilenames` | `[".exclude"]` | Filenames read in each folder. |
100+
| `verbose` | `false` | Log each `.exclude` file, its rules and the globs it made. |
101+
102+
`withExclude(config, srcDir, options)` and `excludeSrc(srcDir, options)` take both. `excludeVitePlugin(options)` takes `excludeFilenames`; pass it the same list.
103+
104+
## Good to know
105+
106+
- **Live in `vitepress dev`.** Add, change or delete a `.exclude` file and the dev server restarts with the new rules. The rules are read when the config loads, so the plugin registers each `.exclude` file as part of the config.
107+
- **Hidden folders are skipped.** `.vitepress`, `node_modules` and other folders whose names start with `.` are not searched. VitePress never builds pages from them.
108+
- **Excluded is not secret.** An excluded file is not published, but it is still in your repository.
109+
110+
[Source and full README on GitHub](https://github.com/binarynoir/vitepress-exclude)

0 commit comments

Comments
 (0)