@atom-forge/brickee 0.0.0-stage → 0.0.1
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 +24 -0
- package/LICENSE +21 -0
- package/README-AI.md +283 -0
- package/README.md +41 -2
- package/dist/Editor.svelte +1968 -0
- package/dist/Editor.svelte.d.ts +22 -0
- package/dist/ImagePicker.svelte +131 -0
- package/dist/ImagePicker.svelte.d.ts +13 -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 +186 -0
- package/dist/Preview.svelte.d.ts +35 -0
- package/dist/PropsBar.svelte +395 -0
- package/dist/PropsBar.svelte.d.ts +20 -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 +147 -0
- package/dist/markdown.d.ts +25 -0
- package/dist/markdown.js +219 -0
- package/dist/media.d.ts +17 -0
- package/dist/media.js +12 -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 +563 -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 +94 -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 +133 -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 +115 -0
- package/docs/en/editor-and-preview.md +141 -0
- package/docs/en/getting-started.md +81 -0
- package/docs/en/host-contexts.md +275 -0
- package/docs/en/index.md +38 -0
- package/docs/en/recipes-and-pitfalls.md +122 -0
- package/docs/en/server-side.md +95 -0
- package/docs/en/upgrading.md +55 -0
- package/docs/en/writing-plugins.md +305 -0
- package/docs/hu/bundled-plugins.md +99 -0
- package/docs/hu/documents-and-markdown.md +115 -0
- package/docs/hu/editor-and-preview.md +141 -0
- package/docs/hu/getting-started.md +81 -0
- package/docs/hu/host-contexts.md +275 -0
- package/docs/hu/index.md +38 -0
- package/docs/hu/recipes-and-pitfalls.md +122 -0
- package/docs/hu/server-side.md +95 -0
- package/docs/hu/upgrading.md +55 -0
- package/docs/hu/writing-plugins.md +305 -0
- package/package.json +110 -5
package/dist/model.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// Block content: what the block editor (src/routes/(+lib)/blocks) writes into the `content` column of pages, news posts
|
|
2
|
+
// and promo boxes. Built-in blocks are `md:<kind>` with inline markdown text (raw text for md:code); every other type
|
|
3
|
+
// belongs to an editor plugin, with its own props and, for some, nested blocks.
|
|
4
|
+
export const MD = 'md:';
|
|
5
|
+
export const MAX_INDENT = 6;
|
|
6
|
+
/** Plugins with nested blocks hold one level only, so a document is at most this deep. */
|
|
7
|
+
export const MAX_DEPTH = 2;
|
|
8
|
+
export const isMd = (b) => b.type.startsWith(MD);
|
|
9
|
+
/** Inline markdown -> plain text: marks, escapes and link targets dropped. */
|
|
10
|
+
export function inlineToPlainText(md) {
|
|
11
|
+
return md
|
|
12
|
+
.replace(/<\/?(u|sub|sup)>/g, '')
|
|
13
|
+
.replace(/\[([^\]]*)\]\([^)]*\)/g, '$1')
|
|
14
|
+
.replace(/(\*\*|~~|`)/g, '')
|
|
15
|
+
.replace(/(?<![\\*])\*(?!\*)/g, '')
|
|
16
|
+
.replace(/\\(.)/g, '$1');
|
|
17
|
+
}
|
|
18
|
+
/** Every text of a document, in order: for search, leads and meta descriptions. */
|
|
19
|
+
export function blocksToPlainText(blocks) {
|
|
20
|
+
const out = [];
|
|
21
|
+
const walk = (list) => {
|
|
22
|
+
for (const b of list) {
|
|
23
|
+
if (b.text)
|
|
24
|
+
out.push(b.type === 'md:code' ? b.text : inlineToPlainText(b.text));
|
|
25
|
+
for (const v of Object.values(b.props ?? {})) {
|
|
26
|
+
// Titles, captions and table cells are text too; ids, colours and switches are not.
|
|
27
|
+
if (typeof v === 'string' && /\s/.test(v.trim()))
|
|
28
|
+
out.push(v.trim());
|
|
29
|
+
if (Array.isArray(v))
|
|
30
|
+
for (const row of v)
|
|
31
|
+
if (Array.isArray(row))
|
|
32
|
+
out.push(row.map((c) => inlineToPlainText(String(c))).join(' '));
|
|
33
|
+
}
|
|
34
|
+
if (b.blocks)
|
|
35
|
+
walk(b.blocks);
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
walk(blocks);
|
|
39
|
+
return out.filter(Boolean).join('\n\n');
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Does a container's `accepts` list take this palette id? The list holds palette ids, and 'md:*' for every built-in
|
|
43
|
+
* block (text, headings, lists, quote, code, divider). No list: everything.
|
|
44
|
+
*/
|
|
45
|
+
export const acceptsId = (accepts, id) => !accepts || accepts.some((a) => a === id || (a === 'md:*' && id.startsWith('md:')));
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Pilcrow } from '@lucide/svelte';
|
|
2
|
+
export type Icon = typeof Pilcrow;
|
|
3
|
+
export interface PaletteItem {
|
|
4
|
+
/** The stored type: md:p, md:h1… for built-in blocks, the plugin's type for plugins. */
|
|
5
|
+
id: string;
|
|
6
|
+
label: string;
|
|
7
|
+
hint: string;
|
|
8
|
+
/** Extra search words for the slash menu. */
|
|
9
|
+
keys: string;
|
|
10
|
+
icon: Icon;
|
|
11
|
+
}
|
|
12
|
+
/** Every built-in block the slash menu can offer, in the default order. */
|
|
13
|
+
export declare const PALETTE_ITEMS: PaletteItem[];
|
|
14
|
+
/** Palette ids of every built-in block (md:p, md:h1…), in the default order. */
|
|
15
|
+
export declare const BUILT_IN_IDS: string[];
|
|
16
|
+
import { acceptsId } from './model';
|
|
17
|
+
export { acceptsId };
|
|
18
|
+
/** The palette of a container's nested editor: the host's, narrowed to what the container accepts (in the host's order). */
|
|
19
|
+
export declare const narrowPalette: (palette: string[], accepts: readonly string[] | undefined) => string[];
|
package/dist/palette.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Heading1, Heading2, Heading3, Heading4, Heading5, Heading6, List, ListOrdered, ListTodo, Pilcrow, SeparatorHorizontal, SquareCode, TextQuote } from '@lucide/svelte';
|
|
2
|
+
/** Every built-in block the slash menu can offer, in the default order. */
|
|
3
|
+
export const PALETTE_ITEMS = [
|
|
4
|
+
{ id: 'md:p', label: 'Text', hint: 'Plain paragraph', keys: 'text paragraph', icon: Pilcrow },
|
|
5
|
+
{ id: 'md:h1', label: 'Heading 1', hint: 'Large heading', keys: 'heading h1 title', icon: Heading1 },
|
|
6
|
+
{ id: 'md:h2', label: 'Heading 2', hint: 'Medium heading', keys: 'heading h2 title', icon: Heading2 },
|
|
7
|
+
{ id: 'md:h3', label: 'Heading 3', hint: 'Small heading', keys: 'heading h3 title', icon: Heading3 },
|
|
8
|
+
{ id: 'md:h4', label: 'Heading 4', hint: 'Sub-heading', keys: 'heading h4 title', icon: Heading4 },
|
|
9
|
+
{ id: 'md:h5', label: 'Heading 5', hint: 'Minor heading', keys: 'heading h5 title', icon: Heading5 },
|
|
10
|
+
{ id: 'md:h6', label: 'Heading 6', hint: 'Smallest heading', keys: 'heading h6 title', icon: Heading6 },
|
|
11
|
+
{ id: 'md:ul', label: 'Bulleted list', hint: 'Simple bullets', keys: 'bullet list ul', icon: List },
|
|
12
|
+
{ id: 'md:ol', label: 'Numbered list', hint: 'Ordered items', keys: 'numbered ordered list ol', icon: ListOrdered },
|
|
13
|
+
{ id: 'md:todo', label: 'To-do', hint: 'Checkable item', keys: 'todo task checkbox', icon: ListTodo },
|
|
14
|
+
{ id: 'md:quote', label: 'Quote', hint: 'Highlighted quote', keys: 'quote blockquote', icon: TextQuote },
|
|
15
|
+
{ id: 'md:code', label: 'Code', hint: 'Monospaced block', keys: 'code snippet pre', icon: SquareCode },
|
|
16
|
+
{ id: 'md:hr', label: 'Divider', hint: 'Horizontal line', keys: 'divider hr line separator', icon: SeparatorHorizontal }
|
|
17
|
+
];
|
|
18
|
+
/** Palette ids of every built-in block (md:p, md:h1…), in the default order. */
|
|
19
|
+
export const BUILT_IN_IDS = PALETTE_ITEMS.map((it) => it.id);
|
|
20
|
+
import { acceptsId } from './model';
|
|
21
|
+
export { acceptsId };
|
|
22
|
+
/** The palette of a container's nested editor: the host's, narrowed to what the container accepts (in the host's order). */
|
|
23
|
+
export const narrowPalette = (palette, accepts) => accepts ? palette.filter((id) => acceptsId(accepts, id)) : palette;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
export interface GapProps extends Record<string, unknown> {
|
|
3
|
+
/** The height in lines of text (of the text around it), as a string from the select. */
|
|
4
|
+
lines: string;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export const GAP_MAX = 8;
|
|
8
|
+
export const GAP_LINES = Array.from({ length: GAP_MAX }, (_, i) => ({ value: String(i + 1), label: i ? '{n} lines' : '1 line' }));
|
|
9
|
+
|
|
10
|
+
/** The number of lines, 1–8 (default 1). */
|
|
11
|
+
export const gapLines = (lines: unknown) => Math.min(GAP_MAX, Math.max(1, Math.round(Number(lines)) || 1));
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<script lang="ts">
|
|
15
|
+
import type { PluginViewProps } from '../types';
|
|
16
|
+
|
|
17
|
+
// Empty space, so many lines high; in the editor a hatched strip of the same height.
|
|
18
|
+
let { props = $bindable() }: PluginViewProps<GapProps> = $props();
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<div class="gap" style:height="{gapLines(props.lines)}lh" aria-hidden="true"></div>
|
|
22
|
+
|
|
23
|
+
<style>
|
|
24
|
+
.gap {
|
|
25
|
+
border-radius: 6px;
|
|
26
|
+
background: repeating-linear-gradient(-45deg, transparent 0 6px, rgb(0 0 0 / 0.05) 6px 12px);
|
|
27
|
+
}
|
|
28
|
+
</style>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface GapProps extends Record<string, unknown> {
|
|
2
|
+
/** The height in lines of text (of the text around it), as a string from the select. */
|
|
3
|
+
lines: string;
|
|
4
|
+
}
|
|
5
|
+
export declare const GAP_MAX = 8;
|
|
6
|
+
export declare const GAP_LINES: {
|
|
7
|
+
value: string;
|
|
8
|
+
label: string;
|
|
9
|
+
}[];
|
|
10
|
+
/** The number of lines, 1–8 (default 1). */
|
|
11
|
+
export declare const gapLines: (lines: unknown) => number;
|
|
12
|
+
import type { PluginViewProps } from '../types';
|
|
13
|
+
declare const Gap: import("svelte").Component<PluginViewProps<GapProps>, {}, "props">;
|
|
14
|
+
type Gap = ReturnType<typeof Gap>;
|
|
15
|
+
export default Gap;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<svelte:options css="injected" />
|
|
2
|
+
|
|
3
|
+
<script lang="ts">
|
|
4
|
+
import type { PluginPreviewProps } from '../types';
|
|
5
|
+
import { gapLines, type GapProps } from './Gap.svelte';
|
|
6
|
+
|
|
7
|
+
let { props }: PluginPreviewProps<GapProps> = $props();
|
|
8
|
+
</script>
|
|
9
|
+
|
|
10
|
+
<div class="gap" style:height="{gapLines(props.lines)}lh" aria-hidden="true"></div>
|
|
11
|
+
|
|
12
|
+
<style>
|
|
13
|
+
.gap {
|
|
14
|
+
clear: both;
|
|
15
|
+
margin: 0;
|
|
16
|
+
}
|
|
17
|
+
</style>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { PluginPreviewProps } from '../types';
|
|
2
|
+
import { type GapProps } from './Gap.svelte';
|
|
3
|
+
declare const GapPreview: import("svelte").Component<PluginPreviewProps<GapProps>, {}, "">;
|
|
4
|
+
type GapPreview = ReturnType<typeof GapPreview>;
|
|
5
|
+
export default GapPreview;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
export interface MapProps extends Record<string, unknown> {
|
|
3
|
+
/** Place or address, as typed into Google Maps. */
|
|
4
|
+
q: string;
|
|
5
|
+
/** Zoom level, 1–20. */
|
|
6
|
+
zoom: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/** Google Maps embed for a place (no API key needed); empty without a place. */
|
|
10
|
+
export const mapSrc = (p: MapProps) =>
|
|
11
|
+
p.q ? `https://www.google.com/maps?q=${encodeURIComponent(p.q)}&z=${Number(p.zoom) || 15}&output=embed` : '';
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<script lang="ts">
|
|
15
|
+
import { useText } from '../i18n';
|
|
16
|
+
import { MapPin } from '@lucide/svelte';
|
|
17
|
+
import type { PluginViewProps } from '../types';
|
|
18
|
+
import Empty from '../kit/Empty.svelte';
|
|
19
|
+
|
|
20
|
+
let { props = $bindable() }: PluginViewProps<MapProps> = $props();
|
|
21
|
+
const tr = useText();
|
|
22
|
+
const src = $derived(mapSrc(props));
|
|
23
|
+
</script>
|
|
24
|
+
|
|
25
|
+
{#if src}
|
|
26
|
+
<div class="map">
|
|
27
|
+
<!-- Not interactive inside the editor, so selecting and dragging the block keep working. -->
|
|
28
|
+
<iframe title={tr('Map: {place}', { place: String(props.q ?? '') })} {src} loading="lazy"></iframe>
|
|
29
|
+
</div>
|
|
30
|
+
{:else}
|
|
31
|
+
<Empty icon={MapPin} text="Set a place or an address above" />
|
|
32
|
+
{/if}
|
|
33
|
+
|
|
34
|
+
<style>
|
|
35
|
+
.map {
|
|
36
|
+
border: 1px solid #e5e5ea;
|
|
37
|
+
border-radius: 10px;
|
|
38
|
+
overflow: hidden;
|
|
39
|
+
}
|
|
40
|
+
iframe {
|
|
41
|
+
display: block;
|
|
42
|
+
width: 100%;
|
|
43
|
+
height: 260px;
|
|
44
|
+
border: 0;
|
|
45
|
+
pointer-events: none;
|
|
46
|
+
}
|
|
47
|
+
</style>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface MapProps extends Record<string, unknown> {
|
|
2
|
+
/** Place or address, as typed into Google Maps. */
|
|
3
|
+
q: string;
|
|
4
|
+
/** Zoom level, 1–20. */
|
|
5
|
+
zoom: string;
|
|
6
|
+
}
|
|
7
|
+
/** Google Maps embed for a place (no API key needed); empty without a place. */
|
|
8
|
+
export declare const mapSrc: (p: MapProps) => string;
|
|
9
|
+
import type { PluginViewProps } from '../types';
|
|
10
|
+
declare const Map: import("svelte").Component<PluginViewProps<MapProps>, {}, "props">;
|
|
11
|
+
type Map = ReturnType<typeof Map>;
|
|
12
|
+
export default Map;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<svelte:options css="injected" />
|
|
2
|
+
|
|
3
|
+
<script lang="ts">
|
|
4
|
+
import { useText } from '../i18n';
|
|
5
|
+
import type { PluginPreviewProps } from '../types';
|
|
6
|
+
import { mapSrc, type MapProps } from './Map.svelte';
|
|
7
|
+
|
|
8
|
+
let { props }: PluginPreviewProps<MapProps> = $props();
|
|
9
|
+
const tr = useText();
|
|
10
|
+
const src = $derived(mapSrc(props));
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
{#if src}
|
|
14
|
+
<iframe class="map" title={tr('Map: {place}', { place: String(props.q ?? '') })} {src} loading="lazy" referrerpolicy="no-referrer-when-downgrade"></iframe>
|
|
15
|
+
{/if}
|
|
16
|
+
|
|
17
|
+
<style>
|
|
18
|
+
.map {
|
|
19
|
+
display: block;
|
|
20
|
+
width: 100%;
|
|
21
|
+
height: 300px;
|
|
22
|
+
margin: 0 0 1em;
|
|
23
|
+
border: 0;
|
|
24
|
+
border-radius: 10px;
|
|
25
|
+
}
|
|
26
|
+
</style>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { PluginPreviewProps } from '../types';
|
|
2
|
+
import { type MapProps } from './Map.svelte';
|
|
3
|
+
declare const MapPreview: import("svelte").Component<PluginPreviewProps<MapProps>, {}, "">;
|
|
4
|
+
type MapPreview = ReturnType<typeof MapPreview>;
|
|
5
|
+
export default MapPreview;
|