1# @alchemy.run/vite-plugin-copy-editor
2
3Edit hardcoded copy in the browser while `vite dev` runs, and have each edit
4written back to the source file.
5
6```ts
7// vite.config.ts (or `vite.plugins` in astro.config.ts)
8import { copyEditor } from "@alchemy.run/vite-plugin-copy-editor";
9
10export default defineConfig({
11 // Register before framework plugins so it sees the raw source.
12 plugins: [copyEditor(), react()],
13});
14```
15
16Mark any piece of hardcoded copy with a bare `data-copy` attribute:
17
18```html
19<h1 data-copy>Reach for the better primitives.</h1>
20<p data-copy>Snap together cloud resources with <code>Alchemy</code>.</p>
21```
22
23- **Dev** (`vite serve`): every `data-copy` element is editable. Click and type;
24 leaving the element or pressing Enter saves, Escape reverts. Only the changed
25 words are rewritten, so tags, entities, and line wrapping are preserved.
26 Ctrl/Cmd+click still follows links inside editable copy.
27- **Build**: the attribute is stripped and none of the editor ships.
28
29Works with `.astro`, `.html`, `.jsx`, `.tsx`, `.vue`, and `.svelte` files
30(configure with `copyEditor({ include: /\.(tsx|html)$/ })`). An editable
31element may contain only text and plain HTML tags; elements containing
32`{expressions}` or components are rejected with an explanation in the browser.
33
34## Markdown sections
35
36Content that comes from markdown (docs pages, a CMS, generated reference) can
37be edited as markdown instead of rendered text. Mark the section's container
38and supply a handler for its id scheme:
39
40```html
41<div data-copy="docs:intro" data-copy-format="markdown" data-copy-style="docs">
42 …rendered markdown…
43</div>
44```
45
46```ts
47copyEditor({
48 handlers: {
49 docs: {
50 readSource: async (id) => loadMarkdown(id),
51 writeSource: async ({ id, source, base }) => saveMarkdown(id, source, base),
52 },
53 },
54 markdownStyles: {
55 docs: {
56 elements: {
57 code: { class: "inline-code" }, // inline code
58 pre: { class: "code-block" }, // code blocks
59 a: { class: "link" },
60 ul: { class: "bullets" },
61 },
62 css: `[data-copy-style="docs"] .code-block { background: #111; }`,
63 },
64 },
65});
66```
67
68Focusing the section swaps in its markdown source (Enter adds a line,
69Ctrl/Cmd+Enter or leaving the section saves, Escape cancels). One-line
70template copy is edited as inline markdown: Enter saves, and Shift+Enter
71adds a line break (`<br>`). After saving,
72the section shows a preview rendered with its `data-copy-style` preset.
73Once the handler's follow-up work (for example regenerating pages) finishes,
74the page's own rendering replaces the preview. If the handler reports a
75structural change (`reload: true`), the page reloads instead.
76
77Content that isn't rendered through Vite (markdown files) can mark a single
78element with a trailing `<!--copy:<scheme>:<id>-->` comment for inline
79editing; handlers implement `edit` for those.