@atom-forge/brickee 0.0.0-stage → 0.0.2
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 +42 -0
- package/LICENSE +21 -0
- package/README-AI.md +286 -0
- package/README.md +41 -2
- package/dist/Editor.svelte +1956 -0
- package/dist/Editor.svelte.d.ts +19 -0
- package/dist/LinkPrompt.svelte +42 -0
- package/dist/LinkPrompt.svelte.d.ts +8 -0
- package/dist/PluginHost.svelte +41 -0
- package/dist/PluginHost.svelte.d.ts +13 -0
- package/dist/Preview.svelte +182 -0
- package/dist/Preview.svelte.d.ts +32 -0
- package/dist/PropsBar.svelte +405 -0
- package/dist/PropsBar.svelte.d.ts +17 -0
- package/dist/code.d.ts +12 -0
- package/dist/code.js +15 -0
- package/dist/dom.d.ts +29 -0
- package/dist/dom.js +224 -0
- package/dist/i18n.d.ts +7 -0
- package/dist/i18n.js +18 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +16 -0
- package/dist/kit/Empty.svelte +24 -0
- package/dist/kit/Empty.svelte.d.ts +8 -0
- package/dist/kit/Frame.svelte +76 -0
- package/dist/kit/Frame.svelte.d.ts +15 -0
- package/dist/kit/util.d.ts +13 -0
- package/dist/kit/util.js +28 -0
- package/dist/locales/hu.d.ts +2 -0
- package/dist/locales/hu.js +142 -0
- package/dist/markdown.d.ts +23 -0
- package/dist/markdown.js +219 -0
- package/dist/model.d.ts +21 -0
- package/dist/model.js +45 -0
- package/dist/palette.d.ts +19 -0
- package/dist/palette.js +23 -0
- package/dist/plugins/Gap.svelte +28 -0
- package/dist/plugins/Gap.svelte.d.ts +15 -0
- package/dist/plugins/GapPreview.svelte +17 -0
- package/dist/plugins/GapPreview.svelte.d.ts +5 -0
- package/dist/plugins/Map.svelte +47 -0
- package/dist/plugins/Map.svelte.d.ts +12 -0
- package/dist/plugins/MapPreview.svelte +26 -0
- package/dist/plugins/MapPreview.svelte.d.ts +5 -0
- package/dist/plugins/Table.svelte +537 -0
- package/dist/plugins/Table.svelte.d.ts +28 -0
- package/dist/plugins/TablePreview.svelte +62 -0
- package/dist/plugins/TablePreview.svelte.d.ts +5 -0
- package/dist/plugins/YouTube.svelte +52 -0
- package/dist/plugins/YouTube.svelte.d.ts +8 -0
- package/dist/plugins/YouTubePreview.svelte +76 -0
- package/dist/plugins/YouTubePreview.svelte.d.ts +5 -0
- package/dist/plugins/index.d.ts +20 -0
- package/dist/plugins/index.js +105 -0
- package/dist/plugins/util.d.ts +3 -0
- package/dist/plugins/util.js +8 -0
- package/dist/schema.d.ts +11 -0
- package/dist/schema.js +25 -0
- package/dist/scroll.d.ts +18 -0
- package/dist/scroll.js +57 -0
- package/dist/types.d.ts +132 -0
- package/dist/types.js +43 -0
- package/dist/view.d.ts +6 -0
- package/dist/view.js +11 -0
- package/docs/en/bundled-plugins.md +99 -0
- package/docs/en/documents-and-markdown.md +114 -0
- package/docs/en/editor-and-preview.md +139 -0
- package/docs/en/getting-started.md +85 -0
- package/docs/en/host-contexts.md +169 -0
- package/docs/en/index.md +38 -0
- package/docs/en/recipes-and-pitfalls.md +123 -0
- package/docs/en/server-side.md +95 -0
- package/docs/en/upgrading.md +71 -0
- package/docs/en/writing-plugins.md +405 -0
- package/docs/hu/bundled-plugins.md +99 -0
- package/docs/hu/documents-and-markdown.md +114 -0
- package/docs/hu/editor-and-preview.md +139 -0
- package/docs/hu/getting-started.md +85 -0
- package/docs/hu/host-contexts.md +169 -0
- package/docs/hu/index.md +38 -0
- package/docs/hu/recipes-and-pitfalls.md +123 -0
- package/docs/hu/server-side.md +95 -0
- package/docs/hu/upgrading.md +71 -0
- package/docs/hu/writing-plugins.md +405 -0
- package/package.json +114 -5
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# A szerkesztő és az előnézet
|
|
2
|
+
|
|
3
|
+
[← Előző](getting-started.md) · [Tartalom](index.md) · [Következő →](documents-and-markdown.md)
|
|
4
|
+
|
|
5
|
+
## Az Editor propjai
|
|
6
|
+
|
|
7
|
+
| Prop | Típus | Alapérték | Jelentés |
|
|
8
|
+
|---|---|---|---|
|
|
9
|
+
| `value` | `StoredBlock[]` (bindable) | `[]` | A dokumentum. Minden változáskor visszaíródik; a kívülről lecserélt dokumentum újra betöltődik. |
|
|
10
|
+
| `plugins` | `BlockPlugin[]` | `[]` | A pluginblokkok, amelyeket ez a szerkesztő megjeleníthet és felkínálhat. |
|
|
11
|
+
| `palette` | `string[]` | minden beépített blokk, utána minden plugin | A perjeles menü által felkínált blokktípusok, ebben a sorrendben (lásd lent). |
|
|
12
|
+
| `messages` | `Messages` | — | Felületi szövegek az alkalmazás nyelvén: angol szöveg → fordítás. |
|
|
13
|
+
| `readonly` | `boolean` | `false` | Szerkesztés nélkül mutatja a dokumentumot; a pluginmezők rejtve vannak. |
|
|
14
|
+
| `placeholder` | `string` | `Write something, or press '/' for blocks…` | Az üres blokk tippszövege. |
|
|
15
|
+
| `nested` | `boolean` | `false` | A beágyazott blokkokat tartalmazó pluginok állítják be a belső szerkesztőjükön; a befogadó alkalmazás soha nem állítja be. |
|
|
16
|
+
|
|
17
|
+
Az üres dokumentum egyetlen üres bekezdésként jelenik meg, így a szerkesztő által visszaírt érték a csatolás után soha nem üres tömb: legalább `[{ type: 'md:p', indent: 0, text: '' }]`. Az előnézet kihagyja az üres bekezdéseket.
|
|
18
|
+
|
|
19
|
+
## A Preview propjai
|
|
20
|
+
|
|
21
|
+
| Prop | Típus | Alapérték | Jelentés |
|
|
22
|
+
|---|---|---|---|
|
|
23
|
+
| `blocks` | `StoredBlock[]` | — | A megjelenítendő dokumentum. |
|
|
24
|
+
| `plugins` | `BlockPlugin[]` | — | A pluginok, amelyek előnézetei a pluginblokkokat renderelik. |
|
|
25
|
+
| `messages` | `Messages` | — | Felületi szövegek az alkalmazás nyelvén. |
|
|
26
|
+
| `markGated` | `boolean` | `true` | Megjelöli a kapus blokk utáni blokkokat (lásd [Egyedi és kapus blokkok](writing-plugins.md#egyedi-és-kapus-blokkok)). |
|
|
27
|
+
| `nested` | `boolean` | `false` | A beágyazott blokkjaikat renderelő plugin-előnézetek állítják be. |
|
|
28
|
+
|
|
29
|
+
Az előnézet a beépített blokkokat sima HTML-ként rendereli (`p`, `h1`…`h6`, `ul`/`ol` beágyazott elemekkel, `blockquote`, `pre > code` `language-<lang>` osztállyal, `hr`), a pluginblokkokat pedig a pluginjuk `preview` komponensével. Az a blokk, amelynek típusához nincs plugin a `plugins` listában, vagy amelynek pluginjának nincs `preview`-ja, nem renderelődik.
|
|
30
|
+
|
|
31
|
+
Hogy használod-e egyáltalán a `Preview`-t, rajtad múlik: a szerkesztő nem függ tőle. Egy saját megjelenítővel dolgozó alkalmazás maga is renderelheti a tárolt blokkokat, és a pluginjai elhagyhatják a `preview`-t.
|
|
32
|
+
|
|
33
|
+
A legfelső szintű szerkesztőnek vagy előnézetnek átadott `messages` öröklődik minden alatta lévő beágyazott szerkesztőre, beágyazott előnézetre és pluginkomponensre.
|
|
34
|
+
|
|
35
|
+
## A paletta
|
|
36
|
+
|
|
37
|
+
A `palette` **palettaazonosítók** listája: `md:p`, `md:h1`…`md:h6`, `md:ul`, `md:ol`, `md:todo`, `md:quote`, `md:code`, `md:hr` a beépített blokkokhoz, pluginoknál pedig a plugin `type` értéke. Ez dönti el:
|
|
38
|
+
|
|
39
|
+
- mely blokkokat kínálja fel a perjeles menü és az „Átalakítás” menü, és milyen sorrendben;
|
|
40
|
+
- mely markdown-gyorsbillentyűk működnek (a `## ` begépelése csak akkor alakít egy bekezdést címsorrá, ha az `md:h2` szerepel a palettán);
|
|
41
|
+
- mivé válhat a beillesztett markdown: a palettán kívüli típusú beillesztett blokk bekezdés lesz, az elválasztó pedig elvész.
|
|
42
|
+
|
|
43
|
+
A sima bekezdés (`md:p`) tartalékként mindig engedélyezett.
|
|
44
|
+
|
|
45
|
+
```svelte
|
|
46
|
+
<script lang="ts">
|
|
47
|
+
import { Editor, type StoredBlock } from '@atom-forge/brickee';
|
|
48
|
+
import { map, table, youtube } from '@atom-forge/brickee/plugins';
|
|
49
|
+
|
|
50
|
+
const plugins = [table, youtube, map];
|
|
51
|
+
// Nincs h1 (az oldal címe az), és nincs kódblokk.
|
|
52
|
+
const palette = ['md:p', 'md:h2', 'md:h3', 'md:ul', 'md:ol', 'md:quote', 'md:hr', ...plugins.map((p) => p.type)];
|
|
53
|
+
|
|
54
|
+
let value = $state<StoredBlock[]>([]);
|
|
55
|
+
</script>
|
|
56
|
+
|
|
57
|
+
<Editor bind:value {plugins} {palette} />
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
A `PALETTE_ITEMS` a beépített blokkokat sorolja fel a címkéikkel, tippjeikkel és ikonjaikkal; a `BUILT_IN_IDS` csak az azonosítóik az alapértelmezett sorrendben.
|
|
61
|
+
|
|
62
|
+
> **A paletta a felkínálást korlátozza, nem a betöltést**
|
|
63
|
+
>
|
|
64
|
+
> Ha egy dokumentumban már van palettán kívüli blokk, az továbbra is megjelenik. Az a pluginblokk, amelynek pluginja hiányzik a `plugins` listából, változatlanul megmarad, és ismeretlen blokkként jelenik meg, amelyet csak törölni lehet. Ha az ilyen dokumentumokat el akarod utasítani, validáld őket a szerveren (lásd [A szerveren](server-side.md)).
|
|
65
|
+
|
|
66
|
+
## Szerkesztés
|
|
67
|
+
|
|
68
|
+
| Művelet | Hogyan |
|
|
69
|
+
|---|---|
|
|
70
|
+
| Blokk beszúrása | A `/` megnyitja a perjeles menüt (címke, tipp, kulcsszavak és ezek fordításai alapján kereshető); a `+` gomb egy blokkot ad hozzá alul. |
|
|
71
|
+
| Markdown-gyorsbillentyűk | Bekezdés elején: `# `…`###### `, `- ` / `* ` / `+ `, `1. `, `[] `, `> `. |
|
|
72
|
+
| Szövegformázás | Jelölj ki szöveget az eszköztárhoz, vagy `Ctrl/Cmd` + `B` félkövér, `I` dőlt, `U` aláhúzott, `Shift+X` áthúzott, `E` kód, `K` link, `\` formázás eltávolítása. Az alsó és a felső index az eszköztáron érhető el. |
|
|
73
|
+
| Behúzás | `Tab` / `Shift+Tab` (legfeljebb 6 szint). |
|
|
74
|
+
| Sortörés | `Shift+Enter`; kódblokkban az `Enter` töri a sort, a `Shift+Enter` vagy a `Ctrl/Cmd+Enter` pedig új blokkot kezd. |
|
|
75
|
+
| Blokkok kijelölése | Kattints egy blokk fogantyújára, nyomj `Esc`-et egy blokkban, `Shift+↑/↓` a blokk szélén túl, vagy húzz szövegkijelölést több blokkon át. Üres blokkban a `Ctrl/Cmd+A` minden blokkot kijelöl. |
|
|
76
|
+
| Blokkok mozgatása | Húzd a fogantyút (beágyazott szerkesztőkbe be és onnan ki is), vagy `Ctrl/Cmd+Shift+↑/↓`. |
|
|
77
|
+
| Átalakítás | Kattints egy blokk vagy egy kijelölés fogantyújára az „Átalakítás” menühöz. |
|
|
78
|
+
| Másolás, kivágás | A kijelölt blokkok másolásakor a markdownjuk kerül a vágólapra (a pluginblokkok a markdown alakjukon keresztül). |
|
|
79
|
+
| Beillesztés | A többsoros szöveg markdownként értelmeződik, és blokkokká válik. |
|
|
80
|
+
| Visszavonás, újra | `Ctrl/Cmd+Z`, `Ctrl/Cmd+Shift+Z` vagy `Ctrl/Cmd+Y`. |
|
|
81
|
+
|
|
82
|
+
Hogy egy blokk mivé alakítható, az attól függ, mit tartalmaz (a `content` értékétől):
|
|
83
|
+
|
|
84
|
+
- a szöveges blokkok egymásba alakíthatók, és megtartják a formázásukat; ha szöveget kóddá alakítasz, csak a betűk maradnak meg;
|
|
85
|
+
- a tartalom nélküli blokk (elválasztó, videó, térkép) csak üres blokkokat vagy más tartalom nélküli blokkokat válthat fel;
|
|
86
|
+
- a beágyazott blokkokat tartalmazó blokk (egy doboz) körbefoghatja a kijelölt blokkokat, ha mindegyiket elfogadja; a **„Kicsomagolás”** kimozgatja a doboz blokkjait; egy doboz átalakítható másik dobozszerű típussá, és az azonos nevű props értékek átkerülnek.
|
|
87
|
+
|
|
88
|
+
## Görgetés-szinkron
|
|
89
|
+
|
|
90
|
+
Ha az alkalmazás egymás mellett mutatja a szerkesztőt és az előnézetet, az előnézet követheti a szerkesztő görgetését. A `scrollSync()` két Svelte actiont és egy függvényt ad vissza:
|
|
91
|
+
|
|
92
|
+
```svelte
|
|
93
|
+
<script lang="ts">
|
|
94
|
+
import { Editor, Preview, scrollSync, type StoredBlock } from '@atom-forge/brickee';
|
|
95
|
+
import { PLUGINS } from '@atom-forge/brickee/plugins';
|
|
96
|
+
|
|
97
|
+
let value = $state<StoredBlock[]>([]);
|
|
98
|
+
const sync = scrollSync();
|
|
99
|
+
</script>
|
|
100
|
+
|
|
101
|
+
<div class="split">
|
|
102
|
+
<div class="pane" use:sync.source>
|
|
103
|
+
<Editor bind:value plugins={PLUGINS} />
|
|
104
|
+
</div>
|
|
105
|
+
<div class="pane" use:sync.target>
|
|
106
|
+
<Preview blocks={value} plugins={PLUGINS} />
|
|
107
|
+
</div>
|
|
108
|
+
</div>
|
|
109
|
+
|
|
110
|
+
<style>
|
|
111
|
+
.split {
|
|
112
|
+
display: grid;
|
|
113
|
+
grid-template-columns: 1fr 1fr;
|
|
114
|
+
height: 100vh;
|
|
115
|
+
}
|
|
116
|
+
.pane {
|
|
117
|
+
overflow-y: auto;
|
|
118
|
+
}
|
|
119
|
+
</style>
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
- A `use:sync.source` a szerkesztő görgethető dobozára kerül, a `use:sync.target` az előnézetére. A cél a görgetési tartományának ugyanakkora hányadáig (0…1) görög, mint a forrás. A szinkron egyirányú: az előnézet görgetése semmi mást nem mozgat.
|
|
123
|
+
- Animációs képkockánként egyszer igazodik, amikor a forrás görög, és akkor is, amikor a céldoboz vagy a gyerekei mérete megváltozik. A `sync.align()` kérésre is igazít, például miután megváltozott az előnézet szélessége.
|
|
124
|
+
- A `use:sync.target={on}` egy logikai értéket kap (alapértéke `true`), ha az alkalmazás két doboz között váltogatja a célt, például egy asztali panel és egy telefonkeret között: a láthatót kapcsold be.
|
|
125
|
+
- A szinkron csak arányos: a két doboz nagyjából ugyanazt a helyet mutatja, nem pontosan ugyanazt a blokkot. Ez szándékos — nem kell hozzá semmilyen jelölés, és bármilyen előnézettel működik.
|
|
126
|
+
|
|
127
|
+
A `scrollFraction(box)` megmondja, mennyire van legörgetve egy doboz (0…1; 0, ha nem görgethető), a `setScrollFraction(box, f)` pedig odagörgeti — például hogy megmaradjon a hely, amikor az önmagában látható előnézet szélessége változik:
|
|
128
|
+
|
|
129
|
+
```ts
|
|
130
|
+
import { scrollFraction, setScrollFraction } from '@atom-forge/brickee';
|
|
131
|
+
import { tick } from 'svelte';
|
|
132
|
+
|
|
133
|
+
export async function keepPlace(box: HTMLElement, change: () => void) {
|
|
134
|
+
const f = scrollFraction(box);
|
|
135
|
+
change(); // pl. az előnézet szélességének váltása
|
|
136
|
+
await tick();
|
|
137
|
+
setScrollFraction(box, f);
|
|
138
|
+
}
|
|
139
|
+
```
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# Első lépések
|
|
2
|
+
|
|
3
|
+
[Tartalom](index.md) · [Következő →](editor-and-preview.md)
|
|
4
|
+
|
|
5
|
+
## Mi a Brickee
|
|
6
|
+
|
|
7
|
+
A Brickee blokkszerkesztő: a dokumentum blokkok listája, mindegyik a saját sorában szerkeszthető, húzással átrendezhető, és a fogantyújáról más típusúvá alakítható. A magban lévő blokkok markdown blokkok — bekezdések, hat címsorszint, felsorolás, számozott lista és teendőlista, idézetek, kód és elválasztók —, így egy pluginok nélküli dokumentum sima markdownként olvasható és másolható.
|
|
8
|
+
|
|
9
|
+
Minden más plugin. A plugin egy egyszerű objektum (`BlockPlugin`), amely megnevez egy blokktípust, és a következőket adja hozzá:
|
|
10
|
+
|
|
11
|
+
- egy **nézetet** — a szerkesztőben megjelenő Svelte-komponenst;
|
|
12
|
+
- egy **előnézetet** — a blokkot az oldalon megjelenítő Svelte-komponenst;
|
|
13
|
+
- **mezőket** — a blokk tetején megjelenő beállításokat (szöveg, szín, választó, csúszka…);
|
|
14
|
+
- opcionálisan egy **markdown alakot**, amelyet a dokumentum markdownként való másolásakor vagy exportálásakor használ.
|
|
15
|
+
|
|
16
|
+
A csomag négy általános plugint is tartalmaz — táblázat, YouTube-videó, térkép és térköz —, de ezek is ugyanolyan pluginok, mint bármelyik más: a magban semmi sem függ tőlük, és csak azokat adod át, amelyeket szeretnél. A képblokkokat, dobozokat és más, az oldalra jellemző blokkokat te írod meg pluginként.
|
|
17
|
+
|
|
18
|
+
## Telepítés
|
|
19
|
+
|
|
20
|
+
```sh
|
|
21
|
+
bun add @atom-forge/brickee @atom-forge/ui @lucide/svelte
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
| Peer dependency | Miért |
|
|
25
|
+
|---|---|
|
|
26
|
+
| `svelte` `^5.0.0` | A szerkesztő, az előnézet és a pluginok Svelte 5 komponensek. |
|
|
27
|
+
| `@atom-forge/ui` `>=0.0.37` | A felugró ablakok (linkbekérő) és a blokkmezők űrlapvezérlői. |
|
|
28
|
+
| `@lucide/svelte` `>=1.0.0` | A blokkok ikonjai. |
|
|
29
|
+
| `zod` `^4.0.0` (opcionális) | Csak az `@atom-forge/brickee/schema` szerveroldali sémájához. |
|
|
30
|
+
|
|
31
|
+
## A befogadó alkalmazás beállítása
|
|
32
|
+
|
|
33
|
+
A blokkmezők és a felugró ablakok `@atom-forge/ui` komponensek, ezért az alkalmazást úgy kell beállítani, ahogy az `@atom-forge/ui` megköveteli:
|
|
34
|
+
|
|
35
|
+
- Tailwind CSS 4, importált `@atom-forge/ui` téma-CSS-sel, a `dist` mappáját pedig add hozzá Tailwind `@source`-ként;
|
|
36
|
+
- az alkalmazás az `@atom-forge/ui` `Root` komponense alatt renderelődjön, amely a témát és az overlay-kontextusokat biztosítja.
|
|
37
|
+
|
|
38
|
+
A legfelső szintű `Editor` saját felugróablak-kezelőt hoz létre, és saját felugróablak-tárolót renderel; a pluginblokkokba ágyazott szerkesztők ezt használják közösen.
|
|
39
|
+
|
|
40
|
+
A szerkesztő a színeit az `@atom-forge/ui` téma tokenjeiből veszi (`--color-surface`, `--color-frame`, `--color-muted-contrast`…), így követi a befogadó alkalmazás világos és sötét módját. Az előnézet keretei és képaláírásai az oldal szövegszínéből számolódnak.
|
|
41
|
+
|
|
42
|
+
A blokkok fogantyúi a **szerkesztő dobozától balra**, egy kb. 22 px széles sávban jelennek meg: a szerkesztőt körülvevő elemnek legyen ennyi bal oldali paddingje, különben a fogantyúk kilógnak belőle.
|
|
43
|
+
|
|
44
|
+
> **Hiányzó téma**
|
|
45
|
+
>
|
|
46
|
+
> Az `@atom-forge/ui` téma-CSS nélkül a szerkesztő továbbra is működik, de a blokkmezők, a színválasztó, a csúszka és a felugró ablakok stílus nélkül jelennek meg.
|
|
47
|
+
|
|
48
|
+
Az előnézet csak azt a kevés stílust adja hozzá, amelyre saját magának szüksége van (teendő-jelölőnégyzetek, képszélességek, körbefuttatás). A címsorok, bekezdések és listák tipográfiája az előnézetet megjelenítő oldalról jön.
|
|
49
|
+
|
|
50
|
+
## Egy első szerkesztő
|
|
51
|
+
|
|
52
|
+
```svelte
|
|
53
|
+
<script lang="ts">
|
|
54
|
+
import { Editor, Preview, type StoredBlock } from '@atom-forge/brickee';
|
|
55
|
+
import { PLUGINS } from '@atom-forge/brickee/plugins';
|
|
56
|
+
|
|
57
|
+
let value = $state<StoredBlock[]>([]);
|
|
58
|
+
</script>
|
|
59
|
+
|
|
60
|
+
<Editor bind:value plugins={PLUGINS} />
|
|
61
|
+
|
|
62
|
+
<article>
|
|
63
|
+
<Preview blocks={value} plugins={PLUGINS} />
|
|
64
|
+
</article>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
- A `value` a dokumentum JSON-ként (`StoredBlock[]`). A szerkesztő minden változáskor visszaírja; mentsd el úgy, ahogy van.
|
|
68
|
+
- A `plugins` felsorolja azokat a pluginblokkokat, amelyeket a szerkesztő megjeleníthet és felkínálhat. Ha elhagyod, egyszerű markdown-szerkesztőt kapsz.
|
|
69
|
+
- A `Preview` ugyanazt a dokumentumot ugyanazokkal a pluginokkal rendereli, úgy, ahogy az oldal megjeleníti.
|
|
70
|
+
|
|
71
|
+
Üres sorban gépelj `/` jelet a blokkmenü megnyitásához.
|
|
72
|
+
|
|
73
|
+
## Belépési pontok
|
|
74
|
+
|
|
75
|
+
| Import | Tartalom |
|
|
76
|
+
|---|---|
|
|
77
|
+
| `@atom-forge/brickee` | `Editor`, `Preview`, a kit (`Frame`, `Empty`, segédfüggvények), a tárolt alak, a markdown-átalakítások, a kontextusok, a paletta, a típusok. |
|
|
78
|
+
| `@atom-forge/brickee/plugins` | A mellékelt pluginok (`table`, `youtube`, `map`, `gap`), a mind a négyet tartalmazó `PLUGINS` és a segédfüggvényeik. |
|
|
79
|
+
| `@atom-forge/brickee/schema` | `blocksSchema` és `blocksSchemaFor` (zod), szerveroldali validáláshoz. |
|
|
80
|
+
| `@atom-forge/brickee/model` | A tárolt alak Svelte nélkül: `StoredBlock`, `MD`, `isMd`, `acceptsId`, `blocksToPlainText`… |
|
|
81
|
+
| `@atom-forge/brickee/locales/hu` | `hu`: a magyar felületi szövegek. |
|
|
82
|
+
|
|
83
|
+
> **Csak az kerül a bundle-be, amit importálsz**
|
|
84
|
+
>
|
|
85
|
+
> A mellékelt pluginok saját belépési ponton érhetők el. Az az alkalmazás, amely csak az `@atom-forge/brickee`-t importálja, a markdown-szerkesztőt kapja, pluginkód nélkül.
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# Az alkalmazás kontextusai
|
|
2
|
+
|
|
3
|
+
[← Előző](writing-plugins.md) · [Tartalom](index.md) · [Következő →](server-side.md)
|
|
4
|
+
|
|
5
|
+
A szerkesztőnek nincsenek propjai az alkalmazás fogalmaihoz. Amit a befogadó alkalmazás tud — az éppen mutatott oldalszélességet, a kiemelhető kódnyelveket, a nyelvét —, az három Svelte-kontextuson keresztül jut el a pluginokhoz. Mindegyikhez tartozik egy `provide…` függvény, amelyet a szerkesztő vagy az előnézet fölötti komponens inicializálásakor hívsz meg, és egy `use…` függvény a plugin-komponensek számára.
|
|
6
|
+
|
|
7
|
+
| Kontextus | Megadás | Olvasás | Mit hordoz |
|
|
8
|
+
|---|---|---|---|
|
|
9
|
+
| Nézet | `provideView(() => key)` | `useView()` | A nézet, amelyet a nézetenkénti mezők szerkesztenek. |
|
|
10
|
+
| Kódnyelvek | `provideCodeLanguages(() => list)` | `useCodeLanguages()` | A nyelvek, amelyeket a kódblokk felkínál. |
|
|
11
|
+
| Szöveg | `messages` prop, vagy `provideText(() => messages)` | `useText()` | Felületi szövegek az alkalmazás nyelvén. |
|
|
12
|
+
|
|
13
|
+
A beágyazott szerkesztők és előnézetek mindhármat a szülőjüktől öröklik.
|
|
14
|
+
|
|
15
|
+
A képek nem kontextuson keresztül érkeznek: hogy egy képblokk mit tárol, és honnan veszi a képeit, azt az alkalmazás saját pluginja dönti el (lásd [Képek](writing-plugins.md#képek)).
|
|
16
|
+
|
|
17
|
+
## Nézetenkénti értékek
|
|
18
|
+
|
|
19
|
+
Egyes beállítások attól függnek, hogyan jelenik meg az oldal: egy képnek telefonon más képarány kellhet, mint széles képernyőn. A `views` beállítással rendelkező `slider` mező nézetenként tárol értéket. Itt ez a [Pluginok írása](writing-plugins.md#képek) fejezet `photo` pluginjának magassága és a mellékelt `gap`:
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
import type { BlockPlugin } from '@atom-forge/brickee';
|
|
23
|
+
import { gap } from '@atom-forge/brickee/plugins';
|
|
24
|
+
import { photo } from './photo';
|
|
25
|
+
|
|
26
|
+
export const VIEWS = [
|
|
27
|
+
{ key: 'desktop', label: 'Desktop' },
|
|
28
|
+
{ key: 'tablet', label: 'Tablet' },
|
|
29
|
+
{ key: 'phone', label: 'Phone' }
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
/** Ugyanaz a plugin, az egyik mezője nézetenként állítva. */
|
|
33
|
+
const perView = (plugin: BlockPlugin, key: string): BlockPlugin => ({
|
|
34
|
+
...plugin,
|
|
35
|
+
fields: plugin.fields?.map((f) => (f.key === key ? { ...f, views: VIEWS } : f))
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
export const plugins = [perView(photo, 'ratio'), perView(gap, 'lines')];
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Hogy milyen nézetek léteznek, és melyik látszik éppen, az az alkalmazás dolga. Az alkalmazás a `provideView`-val közli a szerkesztővel az aktuális nézetet, jellemzően egy szerkesztő melletti szélességváltóból:
|
|
42
|
+
|
|
43
|
+
```svelte
|
|
44
|
+
<script lang="ts">
|
|
45
|
+
import { Editor, provideView, type StoredBlock } from '@atom-forge/brickee';
|
|
46
|
+
import { plugins } from './blocks';
|
|
47
|
+
|
|
48
|
+
let { value = $bindable(), view }: { value: StoredBlock[]; view: string } = $props();
|
|
49
|
+
provideView(() => view);
|
|
50
|
+
</script>
|
|
51
|
+
|
|
52
|
+
<Editor bind:value {plugins} />
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Hogyan viselkednek az értékek:
|
|
56
|
+
|
|
57
|
+
- Az első nézet az **alap**. Minden további nézet, amíg nincs saját értéke, az előtte lévő nézet értékét veszi át; a mező ilyenkor örököltként jelölve mutatja az értéket.
|
|
58
|
+
- A mező az aktuális nézet értékét szerkeszti, és a saját címkéje mellett a nézet címkéjét is mutatja. `provideView` nélkül, vagy ha a kulcs nem szerepel a `views`-ban, az alapértéket szerkeszti.
|
|
59
|
+
- Tárolás: ha csak alapérték van → önmagában, egyszerű értékként tárolódik (`"ratio": "56"`); ha más nézeteknek saját értékük van → nézet szerint kulcsolt objektumként (`"ratio": { "desktop": "56", "phone": "100" }`). Azok a dokumentumok, amelyek még azelőtt íródtak, hogy egy mező nézetenkéntivé vált, érvényesek maradnak.
|
|
60
|
+
|
|
61
|
+
Az előnézet a `viewValues(value, keys)`-szel olvassa ki őket — minden nézet értékét, az öröklést alkalmazva —, vagy csak az alapértéket a `baseValue(value)`-val. A photo előnézetének ez a változata CSS-változókon keresztül szélességenként egy-egy képarányt ad a böngészőnek:
|
|
62
|
+
|
|
63
|
+
```svelte
|
|
64
|
+
<script lang="ts">
|
|
65
|
+
import { viewValues, type PluginPreviewProps } from '@atom-forge/brickee';
|
|
66
|
+
import { aspect, imageSrc, type PhotoProps } from './PhotoView.svelte';
|
|
67
|
+
|
|
68
|
+
let { props }: PluginPreviewProps<PhotoProps> = $props();
|
|
69
|
+
const src = $derived(imageSrc(props.url));
|
|
70
|
+
// desktop, tablet, phone: mindegyikhez egy CSS aspect-ratio ('auto': a kép saját alakja)
|
|
71
|
+
const r = $derived(viewValues(props.ratio, ['desktop', 'tablet', 'phone']).map((v) => aspect(v) ?? 'auto'));
|
|
72
|
+
</script>
|
|
73
|
+
|
|
74
|
+
{#if src}
|
|
75
|
+
<img {src} alt={props.alt ?? ''} style:--r-desktop={r[0]} style:--r-tablet={r[1]} style:--r-phone={r[2]} />
|
|
76
|
+
{/if}
|
|
77
|
+
|
|
78
|
+
<style>
|
|
79
|
+
img {
|
|
80
|
+
width: 100%;
|
|
81
|
+
object-fit: cover;
|
|
82
|
+
aspect-ratio: var(--r-phone);
|
|
83
|
+
}
|
|
84
|
+
@media (min-width: 640px) {
|
|
85
|
+
img {
|
|
86
|
+
aspect-ratio: var(--r-tablet);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
@media (min-width: 1024px) {
|
|
90
|
+
img {
|
|
91
|
+
aspect-ratio: var(--r-desktop);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
</style>
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
> **Csak csúszkák**
|
|
98
|
+
>
|
|
99
|
+
> A `views` a `slider` mezőkön támogatott. A többi mezőfajta figyelmen kívül hagyja.
|
|
100
|
+
|
|
101
|
+
## Kódnyelvek
|
|
102
|
+
|
|
103
|
+
A kódblokk nyelve (`props.lang`, a markdown-kerítés info-szövege) alapból szabad szöveg. Ha az alkalmazás tudja, mely nyelveket tud kiemelni az oldala, megadja a listát, és a kódblokk mezősávjában a mező legördülő lista lesz, elején a *Nincs* opcióval:
|
|
104
|
+
|
|
105
|
+
```svelte
|
|
106
|
+
<script lang="ts">
|
|
107
|
+
import { Editor, provideCodeLanguages, type StoredBlock } from '@atom-forge/brickee';
|
|
108
|
+
|
|
109
|
+
let { value = $bindable() }: { value: StoredBlock[] } = $props();
|
|
110
|
+
provideCodeLanguages(() => [{ value: 'ts', label: 'TypeScript' }, { value: 'svelte', label: 'Svelte' }, 'css', 'bash']);
|
|
111
|
+
</script>
|
|
112
|
+
|
|
113
|
+
<Editor bind:value />
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Egy elem string vagy `{ value, label? }`; a `value` kerül tárolásra. A beágyazott szerkesztők öröklik a listát. Egy tárolt nyelv, amely nincs a listában, opció marad, így egy régebbi dokumentum megnyitásakor semmi sem vész el.
|
|
117
|
+
|
|
118
|
+
## Felületi szövegek
|
|
119
|
+
|
|
120
|
+
A szerkesztő és a pluginok angolul íródtak, és az angol szöveg a fordításának kulcsa. Add át a `messages`-t — egy objektumot, amely az angol szövegeket a te nyelvedre képezi le — a legfelső szintű szerkesztőnek és előnézetnek:
|
|
121
|
+
|
|
122
|
+
```svelte
|
|
123
|
+
<script lang="ts">
|
|
124
|
+
import { Editor, type StoredBlock } from '@atom-forge/brickee';
|
|
125
|
+
import { PLUGINS } from '@atom-forge/brickee/plugins';
|
|
126
|
+
import { hu } from '@atom-forge/brickee/locales/hu';
|
|
127
|
+
|
|
128
|
+
let value = $state<StoredBlock[]>([]);
|
|
129
|
+
</script>
|
|
130
|
+
|
|
131
|
+
<Editor bind:value plugins={PLUGINS} messages={hu} />
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Az `@atom-forge/brickee/locales/hu` a `hu`-t exportálja: a szerkesztő és az összes mellékelt plugin magyar szövegeit. Bővítsd ki a saját pluginjaid és mezőid szövegeivel:
|
|
135
|
+
|
|
136
|
+
```ts
|
|
137
|
+
import type { Messages } from '@atom-forge/brickee';
|
|
138
|
+
import { hu } from '@atom-forge/brickee/locales/hu';
|
|
139
|
+
|
|
140
|
+
export const messages: Messages = {
|
|
141
|
+
...hu,
|
|
142
|
+
Button: 'Gomb',
|
|
143
|
+
'A link as a button': 'Egy link gombként',
|
|
144
|
+
Desktop: 'Asztali',
|
|
145
|
+
Phone: 'Telefon'
|
|
146
|
+
};
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Amit a szerkesztő magától lefordít:
|
|
150
|
+
|
|
151
|
+
- a beépített blokkok és a pluginok `label`, `hint` és `keys` értékeit (a perjeles menü az angol és a lefordított szavak között is keres);
|
|
152
|
+
- egy plugin `tag`-jének részeit, ` · `-nál darabolva;
|
|
153
|
+
- a mezők címkéit, helyőrzőit, az opciók címkéit, a `none` címkéket és a nézetcímkéket;
|
|
154
|
+
- az `Empty` szövegét és a szerkesztő saját felületét.
|
|
155
|
+
|
|
156
|
+
Azt a szöveget, amelyet egy plugin maga renderel — a nézetében vagy az előnézetében —, a `useText()`-en keresztül add ki:
|
|
157
|
+
|
|
158
|
+
```svelte
|
|
159
|
+
<script lang="ts">
|
|
160
|
+
import { useText, type PluginPreviewProps } from '@atom-forge/brickee';
|
|
161
|
+
|
|
162
|
+
let { props }: PluginPreviewProps = $props();
|
|
163
|
+
const tr = useText();
|
|
164
|
+
</script>
|
|
165
|
+
|
|
166
|
+
<p>{tr('Map: {place}', { place: String(props.q ?? '') })}</p>
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
A `{name}` helyőrzőket a második argumentum tölti ki. Komponenseken kívül a `translator(messages)` ugyanilyen függvényt ad vissza. A `messages`-ből hiányzó szöveg angol marad.
|
package/docs/hu/index.md
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Brickee
|
|
2
|
+
|
|
3
|
+
Az `@atom-forge/brickee` blokkszerkesztő Svelte 5-höz. A magja egy markdown blokkszerkesztő — bekezdések, címsorok, listák, teendők, idézetek, kód, elválasztók —, minden más blokk pedig **plugin**: egy blokk, amelynek van szerkesztőnézete, oldali előnézete, vannak mezői, és opcionálisan markdown alakja. A dokumentumok JSON-ként tárolódnak.
|
|
4
|
+
|
|
5
|
+
Ezek az oldalak a [Brickee könyv](https://books.atom-forge.eu) alapján készültek, és angol nyelvű változatuk, a [`../en/index.md`](../en/index.md) fordításai; eltérés esetén az angol változat a mérvadó. Kódoló ágenseknek tömör referencia a [`README-AI.md`](../../README-AI.md).
|
|
6
|
+
|
|
7
|
+
A csomag három rétegből épül fel:
|
|
8
|
+
|
|
9
|
+
```mermaid
|
|
10
|
+
flowchart TB
|
|
11
|
+
core["Mag: markdown blokkok, Editor, Preview, tárolt alak, kit"]
|
|
12
|
+
bundled["Mellékelt pluginok: táblázat, YouTube, térkép, térköz"]
|
|
13
|
+
own["Saját pluginok: ugyanaz a BlockPlugin alak"]
|
|
14
|
+
core --> bundled
|
|
15
|
+
core --> own
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
- **Mag** (`@atom-forge/brickee`) — a markdown blokkok, az `Editor` és a `Preview`, a tárolt alak és annak markdown-átalakításai, valamint a **kit**, amellyel a pluginok készülnek. Pluginok nélkül egyszerű markdown blokkszerkesztő.
|
|
19
|
+
- **Mellékelt pluginok** (`@atom-forge/brickee/plugins`) — ugyanolyan pluginok, mint bármelyik más, és csak abból készültek, amit a mag exportál. Csak azokat kapcsolod be, amelyekre szükséged van.
|
|
20
|
+
- **A saját pluginjaid** — ugyanaz a `BlockPlugin` alak, az alkalmazásodban.
|
|
21
|
+
|
|
22
|
+
Maga a szerkesztő semmit sem tud az alkalmazásodról. Amire egy alkalmazásnak szüksége van — az oldalszélességei, a kódnyelvei, a nyelve —, az **kontextusokon** (nézet, kódnyelvek, szöveg) vagy a pluginok **mezőin** keresztül jut el a pluginokhoz, soha nem külön szerkesztő-propokon át. A képek sem kivételek: a képblokk a saját pluginod, amely úgy tárolja, választja ki és oldja fel a képeit, ahogy az alkalmazásod teszi.
|
|
23
|
+
|
|
24
|
+
## Tartalom
|
|
25
|
+
|
|
26
|
+
1. [Első lépések](getting-started.md) — a három réteg, telepítés, a befogadó alkalmazás beállítása, és egy első szerkesztő az előnézetével.
|
|
27
|
+
2. [A szerkesztő és az előnézet](editor-and-preview.md) — az `Editor` és a `Preview` propjai, a paletta, a szerkesztési funkciók és a görgetés-szinkron.
|
|
28
|
+
3. [Dokumentumok és markdown](documents-and-markdown.md) — a tárolt alak (`StoredBlock`), a beépített blokkok, valamint az átalakítás markdownból és markdownba.
|
|
29
|
+
4. [Mellékelt pluginok](bundled-plugins.md) — mit tartalmaz az `@atom-forge/brickee/plugins`, és hogyan írhatsz felül egy előnézetet vagy adhatsz hozzá mezőket.
|
|
30
|
+
5. [Pluginok írása](writing-plugins.md) — a `BlockPlugin` felépítése, mezők, nézetek és előnézetek, tárolók, markdown alakok, képblokkok és a kit.
|
|
31
|
+
6. [Az alkalmazás kontextusai](host-contexts.md) — nézetenkénti értékek, kódnyelvek és felületi szövegek.
|
|
32
|
+
7. [A szerveren](server-side.md) — sémavalidálás, sima szöveg és védett tartalom.
|
|
33
|
+
8. [Receptek és buktatók](recipes-and-pitfalls.md) — teljes minták és az elkerülendő hibák.
|
|
34
|
+
9. [Frissítés](upgrading.md) — mit kell módosítanod a kódodban, amikor újabb verzióra váltasz.
|
|
35
|
+
|
|
36
|
+
A könyvben van egy AI Notes fejezet is: utasítások, amelyeket a csomagot használó projekt ágens-utasításfájljába másolhatsz.
|
|
37
|
+
|
|
38
|
+
A Svelte-példák teljes komponensek, hacsak másként nem jelzik. Az alkalmazásbeli értékek, például az aktuális oldalszélesség, azt jelölik, amit az alkalmazásod biztosít.
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# Receptek és buktatók
|
|
2
|
+
|
|
3
|
+
[← Előző](server-side.md) · [Tartalom](index.md) · [Következő →](upgrading.md)
|
|
4
|
+
|
|
5
|
+
## Egy hely a blokkbeállításoknak
|
|
6
|
+
|
|
7
|
+
Egy alkalmazás pluginjait, palettáit és szövegeit tartsd egyetlen modulban, a szerkesztőt pedig csomagold be egy saját komponensbe. Az oldalak ezután a csomagolót használják, és soha nem ismétlik meg a beállítást.
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
// lib/blocks.ts
|
|
11
|
+
import type { BlockPlugin, Messages } from '@atom-forge/brickee';
|
|
12
|
+
import * as base from '@atom-forge/brickee/plugins';
|
|
13
|
+
import { hu } from '@atom-forge/brickee/locales/hu';
|
|
14
|
+
import SiteYouTube from './SiteYouTube.svelte';
|
|
15
|
+
import { photo } from './photo';
|
|
16
|
+
import { button } from './button';
|
|
17
|
+
|
|
18
|
+
const withPreview = (plugin: BlockPlugin, preview: BlockPlugin['preview']): BlockPlugin => ({ ...plugin, preview });
|
|
19
|
+
|
|
20
|
+
export const plugins: BlockPlugin[] = [
|
|
21
|
+
withPreview(base.youtube, SiteYouTube),
|
|
22
|
+
base.table,
|
|
23
|
+
base.map,
|
|
24
|
+
base.gap,
|
|
25
|
+
photo,
|
|
26
|
+
button
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
/** A teljes paletta, az oldal saját lapjainak szerkesztőihez. */
|
|
30
|
+
export const PAGE_PALETTE = ['md:p', 'md:h2', 'md:h3', 'md:ul', 'md:ol', 'md:quote', 'md:hr', ...plugins.map((p) => p.type)];
|
|
31
|
+
|
|
32
|
+
/** Egy kisebb, a felhasználói hozzászólásokhoz. */
|
|
33
|
+
export const COMMENT_PALETTE = ['md:p', 'md:ul', 'md:ol', 'md:quote', 'photo'];
|
|
34
|
+
|
|
35
|
+
export const messages: Messages = { ...hu, Button: 'Gomb', 'A link as a button': 'Egy link gombként' };
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
```svelte
|
|
39
|
+
<!-- lib/BlockEditor.svelte -->
|
|
40
|
+
<script lang="ts">
|
|
41
|
+
import { Editor, provideView, type StoredBlock } from '@atom-forge/brickee';
|
|
42
|
+
import { messages, PAGE_PALETTE, plugins } from './blocks';
|
|
43
|
+
|
|
44
|
+
let {
|
|
45
|
+
value = $bindable(),
|
|
46
|
+
palette = PAGE_PALETTE,
|
|
47
|
+
view
|
|
48
|
+
}: { value: StoredBlock[]; palette?: string[]; view?: string } = $props();
|
|
49
|
+
|
|
50
|
+
provideView(() => view);
|
|
51
|
+
</script>
|
|
52
|
+
|
|
53
|
+
<Editor bind:value {plugins} {palette} {messages} />
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
A közzétett oldalt a `<Preview blocks={doc} {plugins} {messages} />`-val és ugyanazokkal a `plugins`-szal rendereld, így egy blokk ugyanúgy néz ki a szerkesztő előnézetében és az oldalon.
|
|
57
|
+
|
|
58
|
+
## A teljes dokumentum másolása markdownként
|
|
59
|
+
|
|
60
|
+
A kijelölt blokkok másolása már most is markdownt tesz a vágólapra. Egy, a teljes dokumentumot másoló „Copy as markdown” gombhoz:
|
|
61
|
+
|
|
62
|
+
```svelte
|
|
63
|
+
<script lang="ts">
|
|
64
|
+
import { fromStored, toMarkdown, type StoredBlock } from '@atom-forge/brickee';
|
|
65
|
+
import { plugins } from './blocks';
|
|
66
|
+
|
|
67
|
+
let { doc }: { doc: StoredBlock[] } = $props();
|
|
68
|
+
|
|
69
|
+
// Kattintáskezelőben fut, így a csak böngészőben működő toMarkdown itt biztonságos.
|
|
70
|
+
const copy = () => navigator.clipboard.writeText(toMarkdown(doc.map(fromStored), { plugins }));
|
|
71
|
+
</script>
|
|
72
|
+
|
|
73
|
+
<button type="button" onclick={copy}>Copy as markdown</button>
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Dokumentum indítása markdownból
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
import { fromMarkdown, toStored, type StoredBlock } from '@atom-forge/brickee';
|
|
80
|
+
|
|
81
|
+
// Böngészőben: a toStored a DOM-on keresztül olvassa be a soron belüli HTML-t.
|
|
82
|
+
export const fromText = (text: string): StoredBlock[] => fromMarkdown(text).map(toStored);
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Ne feledd, hogy minden nem üres sorból külön blokk lesz.
|
|
86
|
+
|
|
87
|
+
## Fejlesztés helyi másolattal
|
|
88
|
+
|
|
89
|
+
Ha a csomag egy helyi checkoutját linkeled be egy alkalmazásba (`bun link`), a linkelt mappa a saját `node_modules`-át hozza magával. Vedd rá a Vite-ot, hogy a közös csomagokból az alkalmazás egyetlen példányát használja, különben a Svelte-kontextusok — a popupkezelő, a téma — nem találhatók meg a két példány között:
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
// az alkalmazás vite.config.ts-e
|
|
93
|
+
export default defineConfig({
|
|
94
|
+
plugins: [sveltekit()],
|
|
95
|
+
resolve: {
|
|
96
|
+
dedupe: ['svelte', '@atom-forge/ui', '@lucide/svelte', 'zod']
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Az alkalmazás a csomag lefordított `dist/` mappáját olvassa, ezért minden változtatás után buildeld újra a csomagot.
|
|
102
|
+
|
|
103
|
+
## Buktatók
|
|
104
|
+
|
|
105
|
+
| Tünet | Ok | Megoldás |
|
|
106
|
+
|---|---|---|
|
|
107
|
+
| A blokkmezők és a popupok stílus nélkülinek tűnnek | Hiányzik az `@atom-forge/ui` téma CSS-e vagy a Tailwind `@source`-a | Állítsd be az `@atom-forge/ui`-t a dokumentációja szerint, és az alkalmazást a `Root`-ja alatt rendereld. |
|
|
108
|
+
| A blokkfogantyúk balra kilógnak | A fogantyúk a szerkesztő dobozától balra jelennek meg | Adj a szerkesztőt körülvevő elemnek kb. 22 px bal oldali paddinget. |
|
|
109
|
+
| A popupok nem nyílnak meg, vagy „context not found” hibák linkelt csomaggal | A `svelte` vagy az `@atom-forge/ui` két példányban van jelen | Vedd fel őket a Vite `resolve.dedupe` listájába. |
|
|
110
|
+
| Egy plugin blokkja „Unknown block” feliratot mutat | A pluginja hiányzik a `plugins`-ból | Egy dokumentumtípus minden szerkesztőjének és előnézetének ugyanazokat a pluginokat add át. |
|
|
111
|
+
| Egy blokk hiányzik a `Preview`-ból | A pluginjának nincs `preview`-ja | Adj a pluginnak `preview`-t (a mellékelt pluginoknak van alapértelmezett), vagy rendereld a blokkot a saját megjelenítőddel. |
|
|
112
|
+
| Egy plugin blokkja hiányzik az oldalról | Az előnézet más `plugins`-t kapott | Ugyanazt a pluginlistát használd a szerkesztőhöz és az előnézethez. |
|
|
113
|
+
| Egy képblokk semmit sem renderel | Az előnézete elutasítja a tárolt címet, vagy az alkalmazás saját keresése nem ismeri a tárolt azonosítót | Olyan címet tárolj, amelyet az előnézet elfogad (`http(s)` vagy az oldalon belüli); az azonosítókat a szerkesztőben és az oldalon ugyanabból az adatból oldd fel. |
|
|
114
|
+
| Egy doboz nem tehető egy másik dobozba | A beágyazott szerkesztők egy szint mélyek | A tárolókat tartalomblokkok befogadására tervezd, ne más tárolókéra. |
|
|
115
|
+
| Egy blokk nem érhető el egy tárolón belül | Az `accepts` vagy az alkalmazás `palette`-je kihagyja | Vedd fel a palettaazonosítót az `accepts`-be (vagy használd az `'md:*'`-ot az összes beépítetthez). |
|
|
116
|
+
| Egy egyedi blokk kétszer jelenik meg | A séma nem kényszeríti ki a `unique`-ot | Ellenőrizd a szerveren, ha az alkalmazásod számít rá. |
|
|
117
|
+
| A védett tartalom mindenkinek látszik | A `gate` csak megjelöli a blokkokat | Renderelés előtt vágd meg a dokumentumot a szerveren. |
|
|
118
|
+
| `document is not defined` | A `toMarkdown` vagy a `toStored` SSR közben futott | Csak a böngészőben hívd őket. |
|
|
119
|
+
| Egy propsból jövő szín vagy link elrontja az oldalt | A props felhasználói bemenet | Használd a `safeColor`-t, ellenőrizd a linkeket, és propsszal soha ne használj `{@html}`-t. |
|
|
120
|
+
| Egy felülírt plugin elveszíti a blokkjait | Megváltozott a `type`-ja | Egy plugin szétterítésekor tartsd meg a `type`-ot. |
|
|
121
|
+
| `bind:blocks` hiba egy saját nézetben | A `props` vagy a `blocks` nincs bindable-ként deklarálva | Deklaráld mindkettőt `$bindable()`-lel. |
|
|
122
|
+
| Az érték soha nem üres tömb | A szerkesztő üres dokumentumnál egy üres bekezdést mutat (és ír) | Az olyan dokumentumot, amelyben csak üres bekezdések vannak, kezeld üresként, például a `blocksToPlainText(doc).trim() === ''` segítségével. |
|
|
123
|
+
| Az előnézet nem követi a szerkesztő görgetését | Az actionök nem a görgethető dobozokon vannak | A `use:sync.source` / `use:sync.target` közvetlenül az `overflow` dobozokra kerüljön. |
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# A szerveren
|
|
2
|
+
|
|
3
|
+
[← Előző](host-contexts.md) · [Tartalom](index.md) · [Következő →](recipes-and-pitfalls.md)
|
|
4
|
+
|
|
5
|
+
A tárolt dokumentum a böngésző által küldött JSON, ezért a szervernek mentés előtt ellenőriznie kell. Két belépési pontnak nincs Svelte-függősége, ezek szerveroldali kódhoz készültek:
|
|
6
|
+
|
|
7
|
+
- `@atom-forge/brickee/model` — `StoredBlock`, `MD`, `MAX_INDENT`, `MAX_DEPTH`, `isMd`, `acceptsId`, `inlineToPlainText`, `blocksToPlainText`;
|
|
8
|
+
- `@atom-forge/brickee/schema` — `blocksSchema` és `blocksSchemaFor`, `zod`-dal építve (opcionális peer dependency: telepítsd, ha ezt a belépési pontot használod).
|
|
9
|
+
|
|
10
|
+
## Dokumentum validálása
|
|
11
|
+
|
|
12
|
+
```ts
|
|
13
|
+
// content.server.ts
|
|
14
|
+
import { blocksSchemaFor } from '@atom-forge/brickee/schema';
|
|
15
|
+
import { plugins } from '$lib/blocks';
|
|
16
|
+
|
|
17
|
+
const contentSchema = blocksSchemaFor(plugins);
|
|
18
|
+
|
|
19
|
+
export function parseContent(input: unknown) {
|
|
20
|
+
const result = contentSchema.safeParse(input);
|
|
21
|
+
if (!result.success) throw new Error('Invalid content');
|
|
22
|
+
return result.data; // StoredBlock[]
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
A `blocksSchema` bármely dokumentum alakját ellenőrzi; a `blocksSchemaFor(plugins)` ehhez hozzáveszi a tárolók `accepts` listáit. Minden pluginból csak a `type` és az `accepts` kell neki, így az a szerver, amely nem akarja importálni a plugin-komponenseket, csak ezeket is átadhatja:
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
const contentSchema = blocksSchemaFor([
|
|
30
|
+
{ type: 'note', accepts: ['md:*', 'youtube'] },
|
|
31
|
+
{ type: 'youtube' }
|
|
32
|
+
]);
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Amit a séma ellenőriz:
|
|
36
|
+
|
|
37
|
+
| Szabály | Korlát |
|
|
38
|
+
|---|---|
|
|
39
|
+
| Blokkkulcsok | Csak `type`, `indent`, `text`, `props`, `blocks` (szigorú objektumok). |
|
|
40
|
+
| `type` | `^[a-z][a-z0-9:-]{0,39}$` |
|
|
41
|
+
| `indent` | Egész szám, 0–6. |
|
|
42
|
+
| `text` | Legfeljebb 100 000 karakter. |
|
|
43
|
+
| `props` | Legfeljebb 60 karakteres kulcsok, JSON-értékek. |
|
|
44
|
+
| `blocks` | Tárolónként legfeljebb 500 beágyazott blokk, csak egy szint mélyen. |
|
|
45
|
+
| Dokumentum | Legfeljebb 2000 legfelső szintű blokk és JSON-ként 1 000 000 karakter. |
|
|
46
|
+
| `accepts` (`blocksSchemaFor`) | Minden beágyazott blokkot befogad a tárolója. |
|
|
47
|
+
|
|
48
|
+
Amit **nem** ellenőriz: hogy egy típus ismert-e, hogy egy egyedi blokk csak egyszer fordul-e elő, és hogy mit tartalmaz a props. Az alkalmazásod által megkövetelt szabályokhoz adj hozzá saját finomításokat – például az ismeretlen blokktípusok elutasításához:
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
import type { StoredBlock } from '@atom-forge/brickee/model';
|
|
52
|
+
import { blocksSchemaFor } from '@atom-forge/brickee/schema';
|
|
53
|
+
import { plugins } from '$lib/blocks';
|
|
54
|
+
|
|
55
|
+
const BUILT_IN = ['md:p', 'md:h1', 'md:h2', 'md:h3', 'md:h4', 'md:h5', 'md:h6', 'md:ul', 'md:ol', 'md:todo', 'md:quote', 'md:code', 'md:hr'];
|
|
56
|
+
const known = new Set([...BUILT_IN, ...plugins.map((p) => p.type)]);
|
|
57
|
+
const allKnown = (list: StoredBlock[]): boolean => list.every((b) => known.has(b.type) && allKnown(b.blocks ?? []));
|
|
58
|
+
|
|
59
|
+
export const contentSchema = blocksSchemaFor(plugins).refine(allKnown, 'Unknown block type.');
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
> **Alak, nem biztonság**
|
|
63
|
+
>
|
|
64
|
+
> A séma szabályos és korlátos méretű dokumentumokat biztosít; a propsokat viszont nem teszi biztonságosan renderelhetővé. A renderelők minden szöveget escape-elnek, és a hivatkozásokat biztonságos sémákra korlátozzák, a saját propsait pedig minden plugin-előnézetnek magának kell megtisztítania (lásd [Pluginok írása](writing-plugins.md)).
|
|
65
|
+
|
|
66
|
+
## Egyszerű szöveg
|
|
67
|
+
|
|
68
|
+
A `blocksToPlainText(blocks)` sorrendben összegyűjti egy dokumentum minden szövegét, üres sorokkal elválasztva: a blokkszövegeket jelölések és hivatkozáscélok nélkül, a szóközt tartalmazó szöveges propsokat (címek, képaláírások – azonosítók és színek nem), a táblázatsorokat és a beágyazott blokkokat. Keresőindexekhez, leadekhez és meta descriptionökhöz használd. Az `inlineToPlainText(md)` ugyanezt teszi egyetlen inline markdown szöveggel.
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
import { blocksToPlainText, type StoredBlock } from '@atom-forge/brickee/model';
|
|
72
|
+
|
|
73
|
+
export const description = (doc: StoredBlock[]) => blocksToPlainText(doc).slice(0, 160);
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Renderelés
|
|
77
|
+
|
|
78
|
+
A `Preview` hagyományos Svelte-komponens, és szerveren is renderelhető; a mag renderelője és a mellékelt előnézetek nem használnak böngésző-API-kat. Csak a markdown-export útvonalnak (`toMarkdown`, `toStored`) kell a böngésző.
|
|
79
|
+
|
|
80
|
+
## Védett tartalom
|
|
81
|
+
|
|
82
|
+
Egy kapus blokk (egy `gate: true` beállítású plugin, például egy csak támogatóknak szóló elválasztó) csak annyit tesz, hogy az előnézet megjelöli az utána következő blokkokat. Hogy a védett részt elzárd azoktól az olvasóktól, akik nem láthatják, vágd el a dokumentumot a szerveren, mielőtt az oldalhoz érne:
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
import type { StoredBlock } from '@atom-forge/brickee/model';
|
|
86
|
+
|
|
87
|
+
/** A dokumentum az első kapus blokkig, azt is beleértve, hozzáférés nélküli olvasóknak. */
|
|
88
|
+
export function publicPart(doc: StoredBlock[], gateTypes: string[], canRead: boolean): StoredBlock[] {
|
|
89
|
+
if (canRead) return doc;
|
|
90
|
+
const at = doc.findIndex((b) => gateTypes.includes(b.type));
|
|
91
|
+
return at < 0 ? doc : doc.slice(0, at + 1);
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Hívd meg a kapus pluginjaid típusaival (például `['paywall']`) és az olvasó hozzáférésével. A hozzáférés nélküli olvasók a kapus blokkig látják a tartalmat, az előzetesével együtt; a hozzáféréssel rendelkezők a teljes dokumentumot kapják, és az előnézet megjelöli számukra a védett részt.
|