@atom-forge/brickee 0.0.2 → 0.0.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/CHANGELOG.md +40 -0
- package/README-AI.md +10 -7
- package/dist/Editor.svelte +691 -833
- package/dist/LinkPrompt.svelte +1 -14
- package/dist/Preview.svelte +27 -54
- package/dist/Preview.svelte.d.ts +2 -4
- package/dist/PropsBar.svelte +35 -219
- package/dist/code.js +1 -1
- package/dist/dom.d.ts +8 -0
- package/dist/dom.js +9 -0
- package/dist/editor/BlockMenu.svelte +102 -0
- package/dist/editor/BlockMenu.svelte.d.ts +32 -0
- package/dist/editor/FormatBar.svelte +41 -0
- package/dist/editor/FormatBar.svelte.d.ts +16 -0
- package/dist/editor/drag.svelte.d.ts +63 -0
- package/dist/editor/drag.svelte.js +95 -0
- package/dist/editor/history.d.ts +24 -0
- package/dist/editor/history.js +86 -0
- package/dist/editor/sweep.svelte.d.ts +21 -0
- package/dist/editor/sweep.svelte.js +56 -0
- package/dist/html.d.ts +12 -0
- package/dist/html.js +206 -0
- package/dist/i18n.js +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +3 -2
- package/dist/kit/Empty.svelte +4 -15
- package/dist/kit/Frame.svelte +7 -37
- package/dist/locales/hu.js +4 -1
- package/dist/markdown.d.ts +20 -4
- package/dist/markdown.js +380 -85
- package/dist/model.js +2 -3
- package/dist/plugins/Gap.svelte +5 -8
- package/dist/plugins/GapPreview.svelte +4 -6
- package/dist/plugins/Map.svelte +2 -17
- package/dist/plugins/MapPreview.svelte +8 -10
- package/dist/plugins/Table.svelte +233 -256
- package/dist/plugins/TablePreview.svelte +28 -28
- package/dist/plugins/YouTube.svelte +3 -31
- package/dist/plugins/YouTubePreview.svelte +45 -43
- package/dist/plugins/index.js +3 -1
- package/dist/types.d.ts +21 -3
- package/dist/types.js +8 -1
- package/dist/view.js +1 -1
- package/docs/en/bundled-plugins.md +1 -1
- package/docs/en/documents-and-markdown.md +20 -14
- package/docs/en/editor-and-preview.md +6 -7
- package/docs/en/getting-started.md +8 -0
- package/docs/en/index.md +1 -1
- package/docs/en/recipes-and-pitfalls.md +2 -2
- package/docs/en/server-side.md +0 -17
- package/docs/en/upgrading.md +14 -0
- package/docs/en/writing-plugins.md +36 -10
- package/docs/hu/bundled-plugins.md +1 -1
- package/docs/hu/documents-and-markdown.md +20 -14
- package/docs/hu/editor-and-preview.md +6 -7
- package/docs/hu/getting-started.md +8 -0
- package/docs/hu/index.md +1 -1
- package/docs/hu/recipes-and-pitfalls.md +2 -2
- package/docs/hu/server-side.md +0 -17
- package/docs/hu/upgrading.md +14 -0
- package/docs/hu/writing-plugins.md +36 -10
- package/package.json +9 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,46 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.0.3] - 2026-11-11
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Table cells show their text formatted (bold, italic, code, links…) while they are not edited, instead of the raw markdown; while editing, `Ctrl/Cmd` + `B`, `I`, `E`, `Shift+X` and `K` wrap the selected text in the mark (a link with its address selected to type over).
|
|
15
|
+
- Touch and keyboard: *Move up* / *Move down* in the Turn-into menu (moving without dragging); the Turn-into menu opens from the keyboard (`/`, `Ctrl/Cmd+/`, the menu key or `Shift+F10` on selected blocks, `Ctrl/Cmd+/` in a block's text); on a touch screen a tapped block shows its actions beside its handle; the handle is a button (with a label for screen readers) and its actions also show on focus.
|
|
16
|
+
- Files pasted into the editor or dropped on it from outside the page go to a plugin that takes them: the new optional `BlockPlugin.fromFiles(files)` returns the block's props (or a promise of them, after its own upload) or `null` for the next plugin. A drop line shows where a dropped file lands; the step is undoable.
|
|
17
|
+
- Formatted paste: text pasted from a web page, Google Docs or Word keeps its headings, paragraphs, lists (nested, numbered, to-dos), quotes, code, rules, tables (for a plugin that takes them) and inline marks, instead of arriving as plain text. Exported as `fromHtml(html, { plugins })` (browser only); it reads the HTML through markdown, so the result is as safe as any other text.
|
|
18
|
+
- Pasting or importing a GFM table: `fromMarkdown(text, { plugins })` gives it to the first plugin with the new `BlockPlugin.fromTable(table: MarkdownTable)`, which returns the block's props; the bundled `table` takes them, so a table pasted into an editor that offers it becomes a table block.
|
|
19
|
+
- A numbered list keeps its start number (`props.start` on its first `md:ol` item): read from markdown (`5. …`), numbered from it in the editor and the preview (`<ol start>`), and written back.
|
|
20
|
+
- Tests for the markdown conversions (`bun run test`, vitest), run by the release checks, the publish workflow and a new test workflow on every push and pull request (type check, tests, package).
|
|
21
|
+
- Code review findings and a staged fix plan in `notes/` (not shipped), linked from `TODO.md`.
|
|
22
|
+
- Development tools (not shipped): `scripts/shots.mjs` and `scripts/shots-diff.mjs` photograph the editor's looks in light and dark mode from the dev pages (`/dev/states`, `/dev/perf`) and compare two sets pixel by pixel; `<style lang="scss">` is enabled (compiled at build time, so `dist/` holds plain CSS).
|
|
23
|
+
|
|
24
|
+
### Changed
|
|
25
|
+
|
|
26
|
+
- The undo history shares unchanged blocks between its steps: a step costs only the blocks that changed, not a copy of the whole document (in a 2000-block document about 320 KB a step before, 300 steps kept).
|
|
27
|
+
- The editor's accent (selection, active menu row, checked to-do, links, the focused table cell, the toggles) follows the `@atom-forge/ui` theme's accent colour instead of a fixed blue (blue remains the fallback), and the editor and the table use the page's typeface (the editor keeps its 17px size), so they read like the preview beside them.
|
|
28
|
+
- **Breaking:** the editor is styled with Tailwind classes (with the `@atom-forge/ui` theme's colours) and SCSS instead of scoped CSS, so a host must add the package's `dist` folder as a Tailwind `@source`, like the `@atom-forge/ui` one; otherwise the editor loses its look. The preview is unaffected (its styles still travel with its markup). The slash and turn-into menus and the formatting bar are their own components, and the undo history its own class. See the upgrading chapter.
|
|
29
|
+
- The editor's internal context keys are `brickee:*` (were `block-editor:*`); an "Unknown block" note is translatable (`Unknown block: {type}`, also in the Hungarian locale).
|
|
30
|
+
- `fromMarkdown` reads much more of CommonMark and GFM: fences of any length and `~~~` (closed only by a fence at least as long), indented code, setext headings and closing `#`s, nested quotes, list nesting by the items' markers (also under `1. ` and with four-space indents), reference links, footnotes (as superscripts), and the lines of a paragraph, list item or quote as one block with line breaks instead of one block per line.
|
|
31
|
+
- `inline` reads `_italic_`, `__bold__` and `***both***` (now valid HTML), code spans of any backtick length, link targets with balanced parentheses and titles, `<https://…>` autolinks, images (as links), every ASCII punctuation escape, and inline HTML (marks kept, other tags dropped). A stored text with a word wrapped in single underscores (`_word_`) now shows it in italics.
|
|
32
|
+
- Typing converts only the edited block to its stored form: the other blocks keep their objects in `value`, so the editor and a `<Preview>` beside it do much less work per keystroke (a 2000-block document with a preview: about 50 ms → 33 ms per keystroke). A document from outside is reloaded when `value` is replaced with a new array that differs from the current one; changing the array in place is not picked up.
|
|
33
|
+
- `toMarkdown` writes markdown other readers read the same way: items nested under a numbered item indented to its content, code fenced longer than any backtick run in it, consecutive quotes as one quote, line breaks as a backslash at the line's end, `_` and line starts that would read as markup escaped.
|
|
34
|
+
|
|
35
|
+
### Removed
|
|
36
|
+
|
|
37
|
+
- **Breaking:** gate blocks — gating content is the application's concept, not the editor's. Removed: `BlockPlugin.gate`, the `Preview`'s `markGated` prop and its "For supporters only" section (`.supporters`, `.supporters-label`), and that text in the Hungarian locale; the `Preview` renders every block. `unique` stays. See the upgrading chapter.
|
|
38
|
+
|
|
39
|
+
### Fixed
|
|
40
|
+
|
|
41
|
+
- The slash menu, the turn-into menu, the formatting bar and the link prompt open where they belong when the editor sits in a transformed parent (an animated drawer or dialog); they live in the body now, placed against the viewport.
|
|
42
|
+
- The table block fills the width of the editor on pages that use Tailwind: its root's class `table` collided with Tailwind's `table` utility (`display: table`), which shrank it to its content.
|
|
43
|
+
- A server-rendered editor shows its blocks' text (it was empty until the page's script ran, so a read-only editor showed nothing without JavaScript). A test renders the editor and the preview on the server, and the test workflow builds the showcase site (which prerenders every page).
|
|
44
|
+
- An editor or a table removed in the middle of a block sweep, a drag or typing leaves no window listener or timer behind.
|
|
45
|
+
- Copying and pasting blocks keeps plugin blocks: the clipboard carries the blocks themselves (`application/x-brickee+json`) beside their markdown, so a copied video, table, gap or box is pasted back as that block instead of a link or nothing; an editor that does not offer the plugin (or already has a unique one) gets its markdown form. An empty block takes pasted plugin blocks in its place, and pasting while blocks are selected inserts after them.
|
|
46
|
+
- Changes made in a plugin's view are undoable: table cells, rows and columns, and the blocks of a nested editor (a box) are undo steps of the editor around them, and Ctrl+Z / Ctrl+Shift+Z in a table cell undo and redo there instead of the cell's own short-lived history. A document loaded from outside starts a fresh history.
|
|
47
|
+
- A read-only editor no longer writes its normalized document back into `value` on mount, so a host does not see a change nobody made.
|
|
48
|
+
- Inline markdown and `fromMarkdown` stay fast on hostile text: many unclosed HTML tags, a long run of `[`, unclosed `**` or `_`, or long runs of spaces could freeze the tab for seconds to minutes; every pattern is now linear (100 000 characters take milliseconds). Limits that come with it: a marked span is at most 2000 characters, a link label has no brackets of its own (at most 1000 characters), a link target at most 2000. Inline HTML marks are now always balanced (an unclosed `<b>` is closed, a stray closing tag dropped).
|
|
49
|
+
|
|
10
50
|
## [0.0.2] - 2026-11-10
|
|
11
51
|
|
|
12
52
|
### Added
|
package/README-AI.md
CHANGED
|
@@ -6,8 +6,8 @@ Brickee is a block editor. Its core is a markdown block editor (`md:p`, `md:h1`
|
|
|
6
6
|
|
|
7
7
|
## Rules
|
|
8
8
|
|
|
9
|
-
- Peers: `svelte` 5, `@atom-forge/ui` (popups and field controls), `@lucide/svelte`; `zod` only for `@atom-forge/brickee/schema`. The app must set up `@atom-forge/ui` (Tailwind 4, its theme CSS and `@source`, the app beneath its `Root`).
|
|
10
|
-
- Store the editor's `value` (`StoredBlock[]`) as it is. Built-in types start with `md:`; any other `type` is a plugin's. Never rename a plugin's `type`: stored documents refer to it.
|
|
9
|
+
- Peers: `svelte` 5, `@atom-forge/ui` (popups and field controls), `@lucide/svelte`; `zod` only for `@atom-forge/brickee/schema`. The app must set up `@atom-forge/ui` (Tailwind 4, its theme CSS and `@source`, the app beneath its `Root`) and add `@atom-forge/brickee/dist` as a Tailwind `@source` too (the editor is styled with Tailwind classes); the preview needs no Tailwind.
|
|
10
|
+
- Store the editor's `value` (`StoredBlock[]`) as it is. To change it from outside, assign a new array (an in-place change is not picked up); a read-only editor never writes it. Built-in types start with `md:`; any other `type` is a plugin's. Never rename a plugin's `type`: stored documents refer to it.
|
|
11
11
|
- Pass the same `plugins` to the `Editor` and the `Preview` of a document type. Restrict what an editor offers with `palette` (palette ids: `md:*` kinds and plugin types), not by dropping plugins.
|
|
12
12
|
- The editor's colours come from the `@atom-forge/ui` theme tokens (light/dark follow the host). Its block handles sit ~22 px left of its box: leave that much left padding around it.
|
|
13
13
|
- No app-specific editor props: app data reaches plugins through contexts (`provideView`, `provideCodeLanguages`, `messages` / `provideText`), plugin fields, or the app's own modules and contexts.
|
|
@@ -15,7 +15,7 @@ Brickee is a block editor. Its core is a markdown block editor (`md:p`, `md:h1`
|
|
|
15
15
|
- Plugin props are untrusted user input. Previews sanitize: `safeColor` for colours, check links and image addresses (`http(s)` or site-relative), clamp numbers, never `{@html}` with props.
|
|
16
16
|
- A plugin view declares both `props` and `blocks` with `$bindable()`, even if unused.
|
|
17
17
|
- Containers (`content: 'blocks'`) nest one level only; nested editors never offer containers or unique plugins. `accepts` narrows their content (`'md:*'` = every built-in).
|
|
18
|
-
- `unique`: one per document, top level; not enforced by the schema.
|
|
18
|
+
- `unique`: one per document, top level; not enforced by the schema.
|
|
19
19
|
- `toMarkdown` and `toStored` use the DOM: browser only. `fromMarkdown`, `fromStored`, `inline`, the schema and `./model` run anywhere.
|
|
20
20
|
- Validate saved documents on the server with `blocksSchemaFor(plugins)`; it checks shape and `accepts`, not known types, uniqueness or prop contents.
|
|
21
21
|
- Scroll sync is proportional (same scroll fraction), one way, editor → preview; it needs no markup and shows roughly the same place, not the same block.
|
|
@@ -29,7 +29,7 @@ Brickee is a block editor. Its core is a markdown block editor (`md:p`, `md:h1`
|
|
|
29
29
|
// <Editor bind:value={StoredBlock[]} plugins?={BlockPlugin[]} palette?={string[]} messages?={Messages}
|
|
30
30
|
// readonly?={boolean} placeholder?={string} /> // `nested` is for Frame only
|
|
31
31
|
// <Preview blocks={StoredBlock[]} plugins={BlockPlugin[]} messages?={Messages}
|
|
32
|
-
//
|
|
32
|
+
// nested?={boolean} />
|
|
33
33
|
// <Frame bind:blocks {readonly} {palette} {plugins} heading?={string} empty?={string} image?={string} placeholder?={string} />
|
|
34
34
|
// <Empty icon={Icon} text={string} />
|
|
35
35
|
|
|
@@ -44,7 +44,8 @@ function blocksToPlainText(blocks: StoredBlock[]): string;
|
|
|
44
44
|
function inline(md: string): string; // inline markdown -> safe inline HTML
|
|
45
45
|
function fromStored(s: StoredBlock): Block;
|
|
46
46
|
function toStored(b: Block): StoredBlock; // browser only
|
|
47
|
-
function fromMarkdown(src: string): Block[];
|
|
47
|
+
function fromMarkdown(src: string, opts?: { plugins?: BlockPlugin[] }): Block[]; // CommonMark/GFM blocks; a paragraph's lines stay one block; a GFM table goes to the first plugin with fromTable
|
|
48
|
+
function fromHtml(html: string, opts?: { plugins?: BlockPlugin[] }): Block[]; // browser only; formatted paste (web, Google Docs, Word) via markdown
|
|
48
49
|
function toMarkdown(blocks: Block[], opts?: { plugins?: BlockPlugin[] }): string; // browser only
|
|
49
50
|
|
|
50
51
|
// contexts (call provide* in component init, above the editor/preview; use* in plugin components)
|
|
@@ -95,12 +96,14 @@ interface BlockPlugin<P extends Props = Props> {
|
|
|
95
96
|
preview?: Component<PluginPreviewProps<any>>; // optional: without it <Preview> renders nothing for the block
|
|
96
97
|
accepts?: string[]; // container content as palette ids; 'md:*'
|
|
97
98
|
markdown?(props: P, ctx: MarkdownContext): string; // '' = left out
|
|
99
|
+
fromTable?(table: MarkdownTable): P; // takes a pasted/imported GFM table (bundled `table` does)
|
|
100
|
+
fromFiles?(files: File[]): P | null | Promise<P | null>; // takes pasted/dropped files; null = next plugin; upload is yours
|
|
98
101
|
unique?: boolean;
|
|
99
|
-
gate?: boolean;
|
|
100
102
|
}
|
|
101
103
|
interface PluginViewProps<P> { props: P; blocks: StoredBlock[]; readonly: boolean; palette: string[]; plugins: BlockPlugin[] }
|
|
102
104
|
interface PluginPreviewProps<P> { props: P; blocks: StoredBlock[]; plugins: BlockPlugin[] }
|
|
103
105
|
interface MarkdownContext { inner: string }
|
|
106
|
+
interface MarkdownTable { rows: string[][] /* inline markdown, first row = header */; align: ('left' | 'center' | 'right')[] }
|
|
104
107
|
interface PropField {
|
|
105
108
|
key: string; label: string;
|
|
106
109
|
kind: 'text' | 'textarea' | 'color' | 'select' | 'slider' | 'toggles'; // toggles: icon buttons, stores the list of the ones on
|
|
@@ -256,6 +259,7 @@ const result = blocksSchemaFor(plugins).safeParse(input); // or pass [{ type, ac
|
|
|
256
259
|
| Symptom | Cause | Fix |
|
|
257
260
|
|---|---|---|
|
|
258
261
|
| Fields and popups unstyled | `@atom-forge/ui` theme CSS / `@source` missing | Set up `@atom-forge/ui`; render beneath its `Root`. |
|
|
262
|
+
| Editor rows, menus or table unstyled / shrunk | `@atom-forge/brickee/dist` not a Tailwind `@source` | `@source "../node_modules/@atom-forge/brickee/dist";` |
|
|
259
263
|
| Block handles stick out on the left | Handles are drawn ~22 px left of the editor's box | Give the editor's container ~22 px left padding. |
|
|
260
264
|
| Context errors with a linked local copy | Duplicate `svelte` / `@atom-forge/ui` | Vite `resolve.dedupe: ['svelte', '@atom-forge/ui', '@lucide/svelte', 'zod']`. |
|
|
261
265
|
| A block is missing from `<Preview>` | Its plugin has no `preview` | Add one (bundled plugins have a default) or render it yourself. |
|
|
@@ -264,7 +268,6 @@ const result = blocksSchemaFor(plugins).safeParse(input); // or pass [{ type, ac
|
|
|
264
268
|
| `media` prop, `useMedia`, `findMedia`, `kind: 'image'` missing | Removed: images are the app's business | Own picking and lookup in the app's image plugin (see `docs/en/upgrading.md`). |
|
|
265
269
|
| Box not offered inside a box | One nesting level | By design. |
|
|
266
270
|
| Block not offered inside a container | `accepts` or host `palette` excludes it | Add its palette id (or `'md:*'`). |
|
|
267
|
-
| Gated content visible to all | `gate` only marks | Cut the document on the server. |
|
|
268
271
|
| `document is not defined` | `toMarkdown` / `toStored` during SSR | Call in the browser. |
|
|
269
272
|
| Injected colour / link | Props rendered unchecked | `safeColor`, link checks, no `{@html}`. |
|
|
270
273
|
| Override loses its blocks | `type` changed | Keep `type`. |
|