Skip to content

Commit f971d8b

Browse files
yolo-samsmcllns
andauthored
docs: Simplify README skill placement (#11)
Co-authored-by: Sam Collins <81678+smcllns@users.noreply.github.com>
1 parent 0225a7a commit f971d8b

6 files changed

Lines changed: 130 additions & 49 deletions

File tree

.agents/plans/2026-05-14-authoring-skill-release.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
Scope:
44
- [x] Sync `main` to merged PR #8.
55
- [x] Rebase PR #7 branch onto theme-token work.
6-
- [x] Update canonical `.agents/SKILL.md` for real theme-token injection.
6+
- [x] Update canonical root `SKILL.md` for real theme-token injection.
7+
- [x] Keep `.agents/SKILL.md` as the local-agent mirror.
78
- [x] Bundle `SKILL.md` into `dist/html-docs/` during build.
89
- [x] Include bundled `SKILL.md` in release upload/provenance.
910
- [x] Clarify README optional agent-skill install/discovery.
@@ -14,7 +15,8 @@ Scope:
1415
- [x] Add `skills.sh` install command to README.
1516

1617
Decisions:
17-
- Plugin repo is canonical source.
18+
- Plugin repo root `SKILL.md` is the canonical source.
19+
- `.agents/SKILL.md` mirrors the canonical source for local agent discovery.
1820
- `smcllns/skills` is the installable mirror.
1921
- Obsidian plugin install does not install agent skills.
2022
- Plugin runtime must not write to agent install roots or dotfiles.

README.md

Lines changed: 15 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -15,48 +15,36 @@ A demo page (`test/fixture.html`) demonstrates all the passing HTML features.
1515

1616
![](demo.png)
1717

18-
## Installation
18+
## Install Obsidian Plugin
1919

20-
### Install from Obsidian directly
20+
* Install from Obsidian Community: [HTML Docs](https://community.obsidian.md/plugins/html-docs)
21+
* Build and install from source:
2122

22-
* Go to Obsidian Community Plugins: [community.obsidian.md/plugins/html-docs](https://community.obsidian.md/plugins/html-docs)
23-
* Click Install
24-
25-
### Install manually
26-
27-
1. Download `main.js`, `manifest.json`, and `styles.css` from the [latest release](https://github.com/smcllns/obsidian-plugin-html-docs/releases/latest)
28-
2. Place those files into `<vault>/.obsidian/plugins/html-docs/`.
29-
3. Enable **HTML Docs** in Obsidian's Community Plugins settings.
30-
31-
Releases are built and signed by GitHub Actions ([.github/workflows/release.yml](.github/workflows/release.yml)) so the binaries carry a [build attestation](https://docs.github.com/en/actions/security-for-github-actions/using-artifact-attestations/using-artifact-attestations-to-establish-provenance-for-builds) you can verify against the source.
23+
```bash
24+
git clone https://github.com/smcllns/obsidian-plugin-html-docs/
25+
bun install
26+
bun run dev # watch + rebuild
27+
bun run build # production bundle at `dist/html-docs/`
28+
```
3229

33-
### Optional Agent Skill
30+
### Download Agent Skill (optional)
3431

3532
There is an optional agent skill so your agent can author HTML that fits this plugin's sandbox, theme tokens, assets, and embeds.
3633

37-
- Skills CLI: `npx skills add smcllns/skills --skill obsidian-html-docs`
38-
- Manual: [smcllns/skills/skills/obsidian-html-docs/SKILL.md](https://github.com/smcllns/skills/blob/main/skills/obsidian-html-docs/SKILL.md)
39-
40-
### Build and install from source
41-
42-
```bash
43-
git clone https://github.com/smcllns/obsidian-plugin-html-docs/
44-
npm install
45-
npm run dev # watch + rebuild
46-
npm run build # production bundle at `dist/html-docs/`
47-
```
34+
* Skills CLI: `npx skills add smcllns/skills --skill obsidian-html-docs`
35+
* Manual: [SKILL.md](https://github.com/smcllns/obsidian-plugin-html-docs/blob/main/SKILL.md) (~850 tokens)
4836

4937
## Test
5038

5139
An E2E test runner validates features, embeds, Canvas cards, and sandboxing are working correctly. Requires `obsidian-cli`, Obsidian running with a vault open, the plugin installed and enabled, and `jq` available.
5240

5341

5442
```bash
55-
npm test
56-
npm run release:check
43+
bun run test
44+
bun run release:check
5745
```
5846

59-
`npm run release:check` runs the production build, the official Obsidian plugin lint rules, and the E2E test. The E2E script builds the current plugin, copies it into the active vault's plugin folder, reloads it, copies `test/fixture.html` into the vault temporarily, opens it in Obsidian, verifies the tab view plus markdown and Canvas embeds, collects the iframe’s own self-test results via `postMessage`, then cleans up.
47+
`bun run release:check` runs the production build, the official Obsidian plugin lint rules, and the E2E test. The E2E script builds the current plugin, copies it into the active vault's plugin folder, reloads it, copies `test/fixture.html` into the vault temporarily, opens it in Obsidian, verifies the tab view plus markdown and Canvas embeds, collects the iframe’s own self-test results via `postMessage`, then cleans up.
6048

6149
See `test/fixture.html` for the full list of features exercised — and the inline notes for what is intentionally blocked.
6250

@@ -79,18 +67,6 @@ Embed HTML docs like other Obsidian embeds. Embeds default to about 600px tall;
7967
![[doc.html|600x400]]
8068
```
8169

82-
Each iframe receives a one-way snapshot of Obsidian theme styles. HTML docs can use these CSS variables to match light/dark mode, theme colors, and fonts without giving the iframe permission to read Obsidian or the vault. Use fallbacks so files still work outside Obsidian:
83-
84-
```css
85-
:root {
86-
color-scheme: var(--obsidian-color-scheme, light dark);
87-
--bg: var(--obsidian-bg, light-dark(#fff, #0e1014));
88-
--text: var(--obsidian-text, light-dark(#16161a, #e7e9ec));
89-
}
90-
```
91-
92-
Available CSS variables: `--obsidian-color-scheme`, `--obsidian-bg`, `--obsidian-bg-2`, `--obsidian-text`, `--obsidian-text-muted`, `--obsidian-accent`, `--obsidian-border`, `--obsidian-font`, `--obsidian-font-mono`.
93-
9470
## Obsidian Plugin Docs
9571

9672
* Developer docs: [docs.obsidian.md](https://docs.obsidian.md)

SKILL.md

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
---
2+
name: obsidian-html-docs
3+
description: Author HTML files for the Obsidian HTML Docs plugin (smcllns/obsidian-plugin-html-docs). Use when creating .html docs intended to render inline in Obsidian: theme tokens, sandbox constraints, asset rules, embed sizing, and things that silently do not work.
4+
---
5+
6+
# Obsidian HTML Docs authoring guide
7+
8+
The HTML Docs plugin lets users view `.html` files inside Obsidian tabs, markdown embeds, and Canvas cards. It renders each file in a sandboxed iframe via Blob URL. The iframe is sealed (`sandbox="allow-scripts allow-popups allow-forms"`, no `allow-same-origin`) so it cannot reach into Obsidian or the vault. Everything below works within that envelope.
9+
10+
## Default to Obsidian context unless asked otherwise
11+
12+
Before creating the Blob URL, the plugin appends a `<style data-html-docs-theme>` block to your HTML containing a snapshot of the user's current Obsidian design tokens. The iframe does not reach out for these values. They are written as static CSS into your document at load time, then the sandboxed iframe loads that document. **Security boundary unchanged**: no `allow-same-origin`, no reads from the iframe back into Obsidian.
13+
14+
If the user just wants a styled doc that "fits" their vault, use these as your defaults. If they're asking for a specific aesthetic (brutalist poster, retro terminal, Linear-style, an exact brand palette), design freely — Obsidian context is a *hint*, not a constraint.
15+
16+
Injected as static CSS:
17+
18+
- A `color-scheme: light | dark` declaration matching the user's current Obsidian theme
19+
- `--obsidian-color-scheme`
20+
- `--obsidian-bg`
21+
- `--obsidian-bg-2`
22+
- `--obsidian-text`
23+
- `--obsidian-text-muted`
24+
- `--obsidian-accent`
25+
- `--obsidian-border`
26+
- `--obsidian-font`
27+
- `--obsidian-font-mono`
28+
29+
Use Obsidian tokens if present, fall back if not:
30+
31+
```css
32+
:root {
33+
color-scheme: light dark;
34+
--bg: var(--obsidian-bg, light-dark(#ffffff, #0e1014));
35+
--text: var(--obsidian-text, light-dark(#16161a, #e7e9ec));
36+
}
37+
```
38+
39+
Open HTML tabs and embeds re-render when the Obsidian theme changes, so the injected snapshot follows theme switches.
40+
41+
## Assets: vault paths do not cross into the iframe
42+
43+
The iframe has no base URL pointing into the vault. Obsidian themes, snippets, and `attachments/...` images don't reach the iframe.
44+
45+
| Pattern | Works? |
46+
|---|---|
47+
| `<img src="attachments/foo.png">` | No — fails silently |
48+
| `<img src="data:image/png;base64,...">` | Yes — fully self-contained |
49+
| `<img src="https://example.com/foo.png">` | Yes — CORS permitting |
50+
| Inline `<svg>...</svg>` | Yes — best for icons / diagrams |
51+
| `<link rel="stylesheet" href="https://cdn...">` | Yes — HTTPS only |
52+
53+
Rules of thumb:
54+
55+
- Small graphics & icons → inline SVG or `data:` URL
56+
- Photos / large images → upload to a host (R2, CDN) and reference HTTPS
57+
- Fonts → system stack, or HTTPS CDN
58+
- Never reference `attachments/` or any vault path — the iframe can't see them
59+
60+
## What works
61+
62+
- HTML / CSS (grid, `light-dark()`, custom properties, animations, gradients, SVG with CSS animations)
63+
- JavaScript (ES2020+, fetch with CORS, Promises, DOM events, requestAnimationFrame, Canvas 2D)
64+
- Forms (`allow-forms` is set; intercept `submit` if you don't want navigation)
65+
- `window.parent.postMessage(msg, '*')` — works even with opaque origin
66+
- External HTTPS resources (images, fonts on CDNs, fetch APIs that allow CORS)
67+
- Anchor links (`#section`) and the History API — Blob URL preserves both
68+
69+
## What's blocked
70+
71+
- `localStorage`, `sessionStorage`, `IndexedDB``SecurityError`
72+
- `document.cookie` — throws or silently no-ops
73+
- Reading `window.parent.*` — cross-origin (postMessage still works)
74+
- Service workers, geolocation, clipboard, notifications, most permission-gated APIs
75+
- Top-level navigation from inside the iframe (no `allow-top-navigation`)
76+
- Vault-relative URLs (see Assets above)
77+
78+
## Linking from markdown to HTML
79+
80+
Wikilinks to `.html` files need the explicit extension:
81+
82+
```markdown
83+
See: [[my-doc.html]]
84+
```
85+
86+
`[[my-doc]]` won't resolve to `.html` in stock Obsidian.
87+
88+
## Embed sizing
89+
90+
```markdown
91+
![[doc.html|600x400]]
92+
```
93+
94+
Sets the embed width and height. Default markdown embed height is about 600px; tab views fill the pane.
95+
96+
## Pitfalls (skip the turn cost)
97+
98+
- **Theme scripts that read `window.parent`** — always throw under this plugin's sandbox. Don't write them.
99+
- **Images via `attachments/foo.png`** — won't resolve. Inline as data URL or use HTTPS.
100+
- **`localStorage` / cookies for state** — blocked. Use URL hash or postMessage to parent.
101+
- **Hard-coding a palette when Obsidian tokens are available** — defeats the contextual fit. Use `var(--obsidian-*)` with `light-dark()` fallbacks.
102+
- **Assuming `prefers-color-scheme` == Obsidian theme** — use `--obsidian-color-scheme` or injected colors instead.

docs/handoffs/authoring-skill-release.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,13 @@ Goal:
66
- Be honest that Obsidian plugin installs do not activate agent skills.
77

88
Implemented shape:
9-
- `.agents/SKILL.md` is the canonical source copy in this plugin repo.
10-
- `esbuild.config.mjs` copies `.agents/SKILL.md` to `dist/html-docs/SKILL.md`.
9+
- Root `SKILL.md` is the canonical source copy in this plugin repo.
10+
- `.agents/SKILL.md` mirrors root `SKILL.md` for local agent discovery.
11+
- `esbuild.config.mjs` copies root `SKILL.md` to `dist/html-docs/SKILL.md`.
1112
- The release workflow uploads and attests `dist/html-docs/SKILL.md` alongside runtime files.
12-
- README has an optional agent-skill note explaining discovery roots and the `smcllns/skills` mirror.
13+
- README has a short optional agent-skill note with the `skills.sh` command and root `SKILL.md` reference.
1314
- `smcllns/skills` mirrors the canonical skill at `skills/obsidian-html-docs/SKILL.md`.
14-
- `smcllns/skills` PR #1 was merged first so README can point to the real `skills.sh` install URL.
15+
- `smcllns/skills` PR #1 was merged first so README can point to the real `skills.sh` install command.
1516

1617
Important constraint:
1718
- Plugin runtime must not write to agent install roots, dotfiles, or any other user-level configuration. Agent skill activation belongs to the user's agent tooling, not the Obsidian plugin.
@@ -21,11 +22,11 @@ Verification target:
2122
- `bun run build`
2223
- `bun run lint`
2324
- `bun run test`
24-
- Confirm `dist/html-docs/SKILL.md` matches `.agents/SKILL.md`.
25+
- Confirm root `SKILL.md`, `.agents/SKILL.md`, and `dist/html-docs/SKILL.md` match.
2526

2627
Current verification:
2728
- `bun run build` passed.
2829
- `bun run lint` passed.
2930
- `bun run test` passed against live Obsidian.
30-
- `.agents/SKILL.md`, generated `dist/html-docs/SKILL.md`, and the `smcllns/skills` mirror match.
31+
- Root `SKILL.md`, `.agents/SKILL.md`, generated `dist/html-docs/SKILL.md`, and the `smcllns/skills` mirror match.
3132
- Haiku critical review found one stale `light-dark()` wording mismatch; fixed by keeping `light-dark()` in the supported CSS list.

esbuild.config.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const distDir = path.join("dist", "html-docs");
1616
fs.mkdirSync(distDir, { recursive: true });
1717
fs.copyFileSync("manifest.json", path.join(distDir, "manifest.json"));
1818
fs.copyFileSync("styles.css", path.join(distDir, "styles.css"));
19-
fs.copyFileSync(path.join(".agents", "SKILL.md"), path.join(distDir, "SKILL.md"));
19+
fs.copyFileSync("SKILL.md", path.join(distDir, "SKILL.md"));
2020

2121
const context = await esbuild.context({
2222
banner: { js: banner },

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"dev": "node esbuild.config.mjs",
88
"build": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production",
99
"lint": "eslint .",
10-
"release:check": "npm run build && npm run lint && npm test",
10+
"release:check": "bun run build && bun run lint && bun run test",
1111
"test": "bash test/test.sh"
1212
},
1313
"keywords": [

0 commit comments

Comments
 (0)