@refrakt-md/editor 0.7.2 → 0.8.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/app/dist/assets/{index-4SP4_AaD.js → index-BBinZAiy.js} +1 -1
- package/app/dist/assets/index-BD2EBUrQ.css +1 -0
- package/app/dist/assets/{index-D77rckeh.js → index-BLuaHLN3.js} +1 -1
- package/app/dist/assets/{index-30gAspk8.js → index-BgCNqcSo.js} +1 -1
- package/app/dist/assets/index-BlAOhWAQ.js +453 -0
- package/app/dist/assets/{index-BZ4adnS0.js → index-BwFn9q4x.js} +1 -1
- package/app/dist/assets/{index-DFkteo0w.js → index-C72UC2ga.js} +1 -1
- package/app/dist/assets/{index-x67KGOIr.js → index-COIPZ34u.js} +1 -1
- package/app/dist/assets/{index-BEFUVB_B.js → index-CW02bulk.js} +1 -1
- package/app/dist/assets/{index-CI5PewQM.js → index-CXFMPmtf.js} +1 -1
- package/app/dist/assets/{index-ByHhigzw.js → index-CeU_s7BB.js} +1 -1
- package/app/dist/assets/{index-DvgOtlru.js → index-CqHjo2YT.js} +1 -1
- package/app/dist/assets/{index-DKnhR16N.js → index-D3TQo8gu.js} +1 -1
- package/app/dist/assets/{index-Baf7ZSct.js → index-DVM3uoxc.js} +1 -1
- package/app/dist/assets/{index-C9w1RpYY.js → index-DW2zI-Ss.js} +1 -1
- package/app/dist/assets/{index--rGC9bba.js → index-D_Y6J00B.js} +1 -1
- package/app/dist/assets/{index-kPhFxtn-.js → index-DgIg-QAA.js} +2 -2
- package/app/dist/assets/{index-DIuFNfTc.js → index-DmY6uqAw.js} +1 -1
- package/app/dist/assets/{index-D1WOi3EN.js → index-DzHt8ZRh.js} +1 -1
- package/app/dist/assets/{index-BwWzfQVn.js → index-ZLvRNfLb.js} +1 -1
- package/app/dist/index.html +2 -2
- package/app/src/lib/api/client.ts +49 -0
- package/app/src/lib/components/ActionEditPopover.svelte +245 -0
- package/app/src/lib/components/BlockCard.svelte +255 -1
- package/app/src/lib/components/BlockEditPanel.svelte +697 -138
- package/app/src/lib/components/BlockEditor.svelte +467 -389
- package/app/src/lib/components/CodeEditPopover.svelte +226 -0
- package/app/src/lib/components/ContentModelTree.svelte +562 -0
- package/app/src/lib/components/ContentTree.svelte +181 -0
- package/app/src/lib/components/EditorLayout.svelte +1 -6
- package/app/src/lib/components/FrontmatterEditPanel.svelte +0 -1
- package/app/src/lib/components/HeaderBar.svelte +38 -0
- package/app/src/lib/components/InlineEditPopover.svelte +593 -0
- package/app/src/lib/components/InsertBlockDialog.svelte +429 -0
- package/app/src/lib/components/PageCard.svelte +3 -4
- package/app/src/lib/components/PreviewPane.svelte +19 -1
- package/app/src/lib/components/RuneAttributes.svelte +249 -100
- package/app/src/lib/editor/block-parser.ts +463 -0
- package/app/src/lib/preview/block-renderer.ts +30 -14
- package/dist/community-tags-builder.d.ts.map +1 -1
- package/dist/community-tags-builder.js +5 -1
- package/dist/community-tags-builder.js.map +1 -1
- package/dist/server.d.ts +1 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +92 -6
- package/dist/server.js.map +1 -1
- package/package.json +6 -6
- package/preview-runtime/App.svelte +2 -0
- package/app/dist/assets/index-DlrXwdpb.css +0 -1
- package/app/dist/assets/index-GlUHQ_jL.js +0 -324
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { ContentNode } from '../editor/block-parser.js';
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
nodes: ContentNode[];
|
|
6
|
+
activePath: number[];
|
|
7
|
+
onselect: (path: number[]) => void;
|
|
8
|
+
// Root node (only at top level)
|
|
9
|
+
rootLabel?: string;
|
|
10
|
+
onrootclick?: () => void;
|
|
11
|
+
isRootActive?: boolean;
|
|
12
|
+
// Internal (for recursion)
|
|
13
|
+
depth?: number;
|
|
14
|
+
pathPrefix?: number[];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
let {
|
|
18
|
+
nodes, activePath, onselect,
|
|
19
|
+
rootLabel, onrootclick, isRootActive = false,
|
|
20
|
+
depth = 0, pathPrefix = [],
|
|
21
|
+
}: Props = $props();
|
|
22
|
+
|
|
23
|
+
function isActivePath(path: number[]): boolean {
|
|
24
|
+
if (path.length !== activePath.length) return false;
|
|
25
|
+
return path.every((v, i) => v === activePath[i]);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function isInActivePath(path: number[]): boolean {
|
|
29
|
+
if (path.length > activePath.length) return false;
|
|
30
|
+
return path.every((v, i) => v === activePath[i]);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const TYPE_ICONS: Record<string, string> = {
|
|
34
|
+
heading: 'M3 3v10M13 3v10M3 8h10',
|
|
35
|
+
paragraph: 'M2 4h12M2 8h12M2 12h8',
|
|
36
|
+
fence: 'M5 4L2 8l3 4M11 4l3 4-3 4',
|
|
37
|
+
list: 'M4 4h10M4 8h10M4 12h10M2 4h0M2 8h0M2 12h0',
|
|
38
|
+
quote: 'M4 4h8M4 7h6M1 3v8',
|
|
39
|
+
hr: 'M2 8h12',
|
|
40
|
+
image: 'M2 2h12v12H2zM5 5l-3 7h12l-4-5-2 2.5',
|
|
41
|
+
};
|
|
42
|
+
</script>
|
|
43
|
+
|
|
44
|
+
<!-- Root node (only rendered at top level) -->
|
|
45
|
+
{#if rootLabel && onrootclick}
|
|
46
|
+
<div class="tree-node">
|
|
47
|
+
<button
|
|
48
|
+
type="button"
|
|
49
|
+
class="tree-node__btn tree-node__btn--rune"
|
|
50
|
+
class:active={isRootActive}
|
|
51
|
+
onclick={onrootclick}
|
|
52
|
+
>
|
|
53
|
+
<span class="tree-node__indicator">▾</span>
|
|
54
|
+
<span class="tree-node__rune-dot"></span>
|
|
55
|
+
<span class="tree-node__label tree-node__label--rune">{rootLabel}</span>
|
|
56
|
+
</button>
|
|
57
|
+
</div>
|
|
58
|
+
{/if}
|
|
59
|
+
|
|
60
|
+
{#each nodes as node, i}
|
|
61
|
+
{@const nodePath = [...pathPrefix, i]}
|
|
62
|
+
{@const isRune = node.type === 'rune'}
|
|
63
|
+
{@const isActive = isActivePath(nodePath)}
|
|
64
|
+
{@const isAncestor = isInActivePath(nodePath) && !isActive}
|
|
65
|
+
{@const hasChildren = isRune && !node.selfClosing && node.children && node.children.length > 0}
|
|
66
|
+
|
|
67
|
+
<div class="tree-node" style="padding-left: {(depth + (rootLabel ? 1 : 0)) * 16}px">
|
|
68
|
+
{#if isRune}
|
|
69
|
+
<button
|
|
70
|
+
type="button"
|
|
71
|
+
class="tree-node__btn tree-node__btn--rune"
|
|
72
|
+
class:active={isActive}
|
|
73
|
+
class:ancestor={isAncestor}
|
|
74
|
+
onclick={() => onselect(nodePath)}
|
|
75
|
+
>
|
|
76
|
+
<span class="tree-node__indicator">{hasChildren ? '▾' : '▸'}</span>
|
|
77
|
+
<span class="tree-node__rune-dot"></span>
|
|
78
|
+
<span class="tree-node__label tree-node__label--rune">{node.label}</span>
|
|
79
|
+
</button>
|
|
80
|
+
{:else}
|
|
81
|
+
<button
|
|
82
|
+
type="button"
|
|
83
|
+
class="tree-node__btn tree-node__btn--content"
|
|
84
|
+
class:active={isActive}
|
|
85
|
+
onclick={() => onselect(nodePath)}
|
|
86
|
+
>
|
|
87
|
+
<svg class="tree-node__icon" width="12" height="12" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
|
88
|
+
<path d={TYPE_ICONS[node.type] ?? 'M2 4h12M2 8h12M2 12h8'} />
|
|
89
|
+
</svg>
|
|
90
|
+
<span class="tree-node__label tree-node__label--content">{node.label}</span>
|
|
91
|
+
</button>
|
|
92
|
+
{/if}
|
|
93
|
+
</div>
|
|
94
|
+
|
|
95
|
+
{#if hasChildren && node.children}
|
|
96
|
+
<svelte:self
|
|
97
|
+
nodes={node.children}
|
|
98
|
+
{activePath}
|
|
99
|
+
{onselect}
|
|
100
|
+
depth={depth + 1}
|
|
101
|
+
pathPrefix={nodePath}
|
|
102
|
+
/>
|
|
103
|
+
{/if}
|
|
104
|
+
{/each}
|
|
105
|
+
|
|
106
|
+
<style>
|
|
107
|
+
.tree-node {
|
|
108
|
+
display: flex;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.tree-node__btn {
|
|
112
|
+
display: flex;
|
|
113
|
+
align-items: center;
|
|
114
|
+
gap: 0.35rem;
|
|
115
|
+
width: 100%;
|
|
116
|
+
padding: 0.2rem 0.4rem;
|
|
117
|
+
border: none;
|
|
118
|
+
border-radius: calc(var(--ed-radius-sm, 4px) - 1px);
|
|
119
|
+
background: transparent;
|
|
120
|
+
color: var(--ed-text-secondary);
|
|
121
|
+
font-size: var(--ed-text-base);
|
|
122
|
+
cursor: pointer;
|
|
123
|
+
text-align: left;
|
|
124
|
+
transition: background var(--ed-transition-fast);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.tree-node__btn:hover {
|
|
128
|
+
background: var(--ed-surface-2);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.tree-node__btn.active {
|
|
132
|
+
background: var(--ed-accent-muted);
|
|
133
|
+
color: var(--ed-accent);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.tree-node__btn.ancestor {
|
|
137
|
+
color: var(--ed-text-primary);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.tree-node__btn--content {
|
|
141
|
+
color: var(--ed-text-muted);
|
|
142
|
+
font-size: var(--ed-text-sm);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.tree-node__btn--content.active {
|
|
146
|
+
background: var(--ed-surface-2);
|
|
147
|
+
color: var(--ed-text-secondary);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.tree-node__indicator {
|
|
151
|
+
width: 12px;
|
|
152
|
+
font-size: 10px;
|
|
153
|
+
color: var(--ed-text-muted);
|
|
154
|
+
flex-shrink: 0;
|
|
155
|
+
text-align: center;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.tree-node__rune-dot {
|
|
159
|
+
width: 5px;
|
|
160
|
+
height: 5px;
|
|
161
|
+
border-radius: 50%;
|
|
162
|
+
background: var(--ed-warning);
|
|
163
|
+
flex-shrink: 0;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.tree-node__icon {
|
|
167
|
+
flex-shrink: 0;
|
|
168
|
+
opacity: 0.5;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.tree-node__label--rune {
|
|
172
|
+
font-weight: 500;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.tree-node__label--content {
|
|
176
|
+
overflow: hidden;
|
|
177
|
+
text-overflow: ellipsis;
|
|
178
|
+
white-space: nowrap;
|
|
179
|
+
min-width: 0;
|
|
180
|
+
}
|
|
181
|
+
</style>
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
{@render center()}
|
|
42
42
|
</div>
|
|
43
43
|
</div>
|
|
44
|
-
<div class="layout__panel layout__panel--right"
|
|
44
|
+
<div class="layout__panel layout__panel--right">
|
|
45
45
|
{@render right()}
|
|
46
46
|
</div>
|
|
47
47
|
</div>
|
|
@@ -113,10 +113,5 @@
|
|
|
113
113
|
.layout__panel--right {
|
|
114
114
|
background: var(--ed-surface-1);
|
|
115
115
|
align-items: center;
|
|
116
|
-
transition: padding-right var(--ed-transition-slow);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
.layout__panel--right.panel-editing {
|
|
120
|
-
padding-right: 480px;
|
|
121
116
|
}
|
|
122
117
|
</style>
|
|
@@ -113,6 +113,37 @@
|
|
|
113
113
|
</svg>
|
|
114
114
|
</button>
|
|
115
115
|
</div>
|
|
116
|
+
<span class="header__divider"></span>
|
|
117
|
+
<div class="header__group">
|
|
118
|
+
<button
|
|
119
|
+
class="header__btn header__btn--icon"
|
|
120
|
+
class:header__btn--active={editorState.previewTheme === 'light'}
|
|
121
|
+
onclick={() => editorState.previewTheme = 'light'}
|
|
122
|
+
title="Light mode"
|
|
123
|
+
>
|
|
124
|
+
<svg width="15" height="15" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
|
125
|
+
<circle cx="8" cy="8" r="3" />
|
|
126
|
+
<line x1="8" y1="1.5" x2="8" y2="3" />
|
|
127
|
+
<line x1="8" y1="13" x2="8" y2="14.5" />
|
|
128
|
+
<line x1="2.4" y1="2.4" x2="3.5" y2="3.5" />
|
|
129
|
+
<line x1="12.5" y1="12.5" x2="13.6" y2="13.6" />
|
|
130
|
+
<line x1="1.5" y1="8" x2="3" y2="8" />
|
|
131
|
+
<line x1="13" y1="8" x2="14.5" y2="8" />
|
|
132
|
+
<line x1="2.4" y1="13.6" x2="3.5" y2="12.5" />
|
|
133
|
+
<line x1="12.5" y1="3.5" x2="13.6" y2="2.4" />
|
|
134
|
+
</svg>
|
|
135
|
+
</button>
|
|
136
|
+
<button
|
|
137
|
+
class="header__btn header__btn--icon"
|
|
138
|
+
class:header__btn--active={editorState.previewTheme === 'dark'}
|
|
139
|
+
onclick={() => editorState.previewTheme = 'dark'}
|
|
140
|
+
title="Dark mode"
|
|
141
|
+
>
|
|
142
|
+
<svg width="15" height="15" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
|
143
|
+
<path d="M13.5 8.5a5.5 5.5 0 0 1-7-7 5.5 5.5 0 1 0 7 7Z" />
|
|
144
|
+
</svg>
|
|
145
|
+
</button>
|
|
146
|
+
</div>
|
|
116
147
|
{:else if isEdit}
|
|
117
148
|
<div class="header__group">
|
|
118
149
|
<button
|
|
@@ -253,6 +284,13 @@
|
|
|
253
284
|
gap: var(--ed-space-2);
|
|
254
285
|
}
|
|
255
286
|
|
|
287
|
+
.header__divider {
|
|
288
|
+
width: 1px;
|
|
289
|
+
height: 16px;
|
|
290
|
+
background: var(--ed-border-strong);
|
|
291
|
+
opacity: 0.5;
|
|
292
|
+
}
|
|
293
|
+
|
|
256
294
|
/* ── Unified button style ─────────────────────────── */
|
|
257
295
|
|
|
258
296
|
.header__btn {
|