@refrakt-md/editor 0.8.3 → 0.8.4
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-DwfxgjnU.js → index-3XGwrbJi.js} +1 -1
- package/app/dist/assets/{index-CUmEjEeR.js → index-4QIVBXA2.js} +1 -1
- package/app/dist/assets/{index-CeV-Af4N.js → index-64pKPA7X.js} +1 -1
- package/app/dist/assets/{index-BGy7ixjW.js → index-87jnOwXd.js} +1 -1
- package/app/dist/assets/{index-COFbngzR.js → index-BC2x3b2t.js} +1 -1
- package/app/dist/assets/{index-3MvwKRVQ.js → index-Bb8l840O.js} +1 -1
- package/app/dist/assets/{index-CQDCT-XT.js → index-BcejoAP1.js} +1 -1
- package/app/dist/assets/{index-ChbH55h5.js → index-BfRxJzFS.js} +1 -1
- package/app/dist/assets/{index-BEGy_i8o.js → index-Bx44CkAs.js} +1 -1
- package/app/dist/assets/{index-DezxtfNV.js → index-CARyuClI.js} +1 -1
- package/app/dist/assets/{index-BBljOYQu.js → index-CEUDrca1.js} +1 -1
- package/app/dist/assets/{index-CKfKYVw7.js → index-CNd1XgyZ.js} +1 -1
- package/app/dist/assets/{index-DrI4IfXE.js → index-CO6-R3qL.js} +1 -1
- package/app/dist/assets/{index-B7e694w6.js → index-Chzl2Gom.js} +1 -1
- package/app/dist/assets/{index-BjlNcvOf.js → index-Cj0n5HXq.js} +1 -1
- package/app/dist/assets/{index-ogrpJNou.js → index-DdNJVnBL.js} +4 -4
- package/app/dist/assets/{index-BaLgiiKk.js → index-DiK4QBVK.js} +1 -1
- package/app/dist/assets/{index-D9-aYc3I.js → index-SvR5c3Vk.js} +1 -1
- package/app/dist/assets/{index-CPEo_rvd.js → index-YNSVyj5l.js} +1 -1
- package/app/dist/index.html +1 -1
- package/app/src/lib/editor/attribute-completion.ts +159 -0
- package/app/src/lib/editor/codemirror-theme.ts +115 -0
- package/app/src/lib/editor/content-model-resolver.ts +196 -0
- package/app/src/lib/editor/inline-markdown.ts +237 -0
- package/app/src/lib/editor/markdoc-highlight.ts +74 -0
- package/app/src/lib/editor/rune-palette.ts +77 -0
- package/app/src/lib/editor/section-mapper.ts +476 -0
- package/app/src/lib/state/editor.svelte.ts +151 -0
- package/app/src/lib/utils/frontmatter.ts +43 -0
- package/app/src/lib/utils/layout-parser.ts +197 -0
- package/package.json +10 -8
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { parseFrontmatterClient, serializeFrontmatter, type Frontmatter } from '../utils/frontmatter.js';
|
|
2
|
+
import type { RuneInfo, RouteRule } from '../api/client.js';
|
|
3
|
+
import type { RendererNode } from '@refrakt-md/transform';
|
|
4
|
+
|
|
5
|
+
interface TreeNode {
|
|
6
|
+
name: string;
|
|
7
|
+
type: 'directory' | 'page' | 'layout';
|
|
8
|
+
path: string;
|
|
9
|
+
draft?: boolean;
|
|
10
|
+
children?: TreeNode[];
|
|
11
|
+
layout?: TreeNode;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
class EditorState {
|
|
15
|
+
tree: TreeNode | null = $state(null);
|
|
16
|
+
currentPath: string | null = $state(null);
|
|
17
|
+
savedContent = $state('');
|
|
18
|
+
editorContent = $state('');
|
|
19
|
+
frontmatter: Frontmatter = $state({});
|
|
20
|
+
bodyContent = $state('');
|
|
21
|
+
|
|
22
|
+
/** Whether the frontmatter panel is open */
|
|
23
|
+
frontmatterOpen = $state(false);
|
|
24
|
+
/** Whether raw YAML mode is active */
|
|
25
|
+
frontmatterRawMode = $state(false);
|
|
26
|
+
|
|
27
|
+
/** Editor view mode */
|
|
28
|
+
editorMode: 'preview' | 'blocks' | 'code' = $state('blocks');
|
|
29
|
+
|
|
30
|
+
treeLoading = $state(false);
|
|
31
|
+
fileLoading = $state(false);
|
|
32
|
+
saving = $state(false);
|
|
33
|
+
saveJustCompleted = $state(false);
|
|
34
|
+
error: string | null = $state(null);
|
|
35
|
+
|
|
36
|
+
/** Rune metadata for autocomplete/palette */
|
|
37
|
+
runes: RuneInfo[] = $state([]);
|
|
38
|
+
|
|
39
|
+
/** Route rules from refrakt.config.json */
|
|
40
|
+
routeRules: RouteRule[] = $state([]);
|
|
41
|
+
|
|
42
|
+
/** Preview viewport preset */
|
|
43
|
+
viewport: 'desktop' | 'tablet' | 'mobile' = $state('desktop');
|
|
44
|
+
|
|
45
|
+
/** Preview color scheme */
|
|
46
|
+
previewTheme: 'light' | 'dark' = $state('light');
|
|
47
|
+
|
|
48
|
+
/** Theme CSS for inline block previews */
|
|
49
|
+
themeCss = $state('');
|
|
50
|
+
/** Theme config for inline block previews (JSON-safe, no postTransform) */
|
|
51
|
+
themeConfig: import('@refrakt-md/transform').ThemeConfig | null = $state(null);
|
|
52
|
+
|
|
53
|
+
/** Syntax highlight transform (loaded async via Shiki) */
|
|
54
|
+
highlightTransform: ((tree: RendererNode) => RendererNode) | null = $state(null);
|
|
55
|
+
/** CSS generated by the highlight transform (e.g. theme overrides) */
|
|
56
|
+
highlightCss = $state('');
|
|
57
|
+
|
|
58
|
+
/** Whether the Svelte preview runtime is available */
|
|
59
|
+
previewRuntimeAvailable = $state(false);
|
|
60
|
+
/** Whether the preview runtime iframe has signalled ready */
|
|
61
|
+
previewRuntimeReady = $state(false);
|
|
62
|
+
|
|
63
|
+
/** Directories the user has explicitly expanded (all start collapsed) */
|
|
64
|
+
expandedDirs: Set<string> = $state(new Set());
|
|
65
|
+
|
|
66
|
+
/** External file change notification (set by SSE watcher) */
|
|
67
|
+
externalChange: { path: string; event: string } | null = $state(null);
|
|
68
|
+
|
|
69
|
+
/** Community rune Markdoc schemas (loaded from /api/community-tags.js bundle) */
|
|
70
|
+
communityTags: Record<string, unknown> | null = $state(null);
|
|
71
|
+
/** Community rune postTransform functions (loaded from /api/community-tags.js bundle) */
|
|
72
|
+
communityPostTransforms: Record<string, Function> | null = $state(null);
|
|
73
|
+
/** Community rune styles configs (loaded from /api/community-tags.js bundle) */
|
|
74
|
+
communityStyles: Record<string, Record<string, unknown>> | null = $state(null);
|
|
75
|
+
|
|
76
|
+
/** Aggregated cross-page pipeline data (fetched from /api/aggregated on startup) */
|
|
77
|
+
aggregated: Record<string, unknown> = $state({});
|
|
78
|
+
|
|
79
|
+
/** Whether the left sidenav is open */
|
|
80
|
+
sidenavOpen = $state(true);
|
|
81
|
+
|
|
82
|
+
dirty = $derived(this.editorContent !== this.savedContent);
|
|
83
|
+
|
|
84
|
+
/** Whether the current file is a layout or a regular page */
|
|
85
|
+
currentFileType = $derived<'page' | 'layout'>(
|
|
86
|
+
this.currentPath?.endsWith('_layout.md') ? 'layout' : 'page'
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Load a file's raw content into the editor, splitting frontmatter and body.
|
|
91
|
+
*/
|
|
92
|
+
loadFile(path: string, raw: string) {
|
|
93
|
+
const { frontmatter, body } = parseFrontmatterClient(raw);
|
|
94
|
+
this.currentPath = path;
|
|
95
|
+
this.savedContent = raw;
|
|
96
|
+
this.editorContent = raw;
|
|
97
|
+
this.frontmatter = frontmatter;
|
|
98
|
+
this.bodyContent = body;
|
|
99
|
+
this.frontmatterRawMode = false;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Update the markdown body (called from CodeMirror).
|
|
104
|
+
* Reconstructs editorContent from frontmatter + new body.
|
|
105
|
+
*/
|
|
106
|
+
updateBody(body: string) {
|
|
107
|
+
this.bodyContent = body;
|
|
108
|
+
this.editorContent = serializeFrontmatter(this.frontmatter, body);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Update a single frontmatter field.
|
|
113
|
+
* Reconstructs editorContent from updated frontmatter + body.
|
|
114
|
+
*/
|
|
115
|
+
updateFrontmatterField(key: string, value: unknown) {
|
|
116
|
+
if (value === undefined || value === '' || (Array.isArray(value) && value.length === 0)) {
|
|
117
|
+
const { [key]: _, ...rest } = this.frontmatter;
|
|
118
|
+
this.frontmatter = rest;
|
|
119
|
+
} else {
|
|
120
|
+
this.frontmatter = { ...this.frontmatter, [key]: value };
|
|
121
|
+
}
|
|
122
|
+
this.editorContent = serializeFrontmatter(this.frontmatter, this.bodyContent);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Replace the entire frontmatter object (e.g. from raw YAML editor).
|
|
127
|
+
* Reconstructs editorContent from new frontmatter + body.
|
|
128
|
+
*/
|
|
129
|
+
replaceFrontmatter(fm: Frontmatter) {
|
|
130
|
+
this.frontmatter = fm;
|
|
131
|
+
this.editorContent = serializeFrontmatter(fm, this.bodyContent);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
toggleDir(path: string): void {
|
|
135
|
+
const next = new Set(this.expandedDirs);
|
|
136
|
+
if (next.has(path)) {
|
|
137
|
+
next.delete(path);
|
|
138
|
+
} else {
|
|
139
|
+
next.add(path);
|
|
140
|
+
}
|
|
141
|
+
this.expandedDirs = next;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
isDirExpanded(path: string): boolean {
|
|
145
|
+
return this.expandedDirs.has(path);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export const editorState = new EditorState();
|
|
150
|
+
|
|
151
|
+
export type { TreeNode, Frontmatter, RuneInfo };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import yaml from 'yaml';
|
|
2
|
+
|
|
3
|
+
export interface Frontmatter {
|
|
4
|
+
title?: string;
|
|
5
|
+
description?: string;
|
|
6
|
+
slug?: string;
|
|
7
|
+
draft?: boolean;
|
|
8
|
+
redirect?: string;
|
|
9
|
+
order?: number;
|
|
10
|
+
date?: string;
|
|
11
|
+
author?: string;
|
|
12
|
+
tags?: string[];
|
|
13
|
+
image?: string;
|
|
14
|
+
[key: string]: unknown;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Parse YAML frontmatter from raw markdown content (browser-side).
|
|
19
|
+
* Returns the frontmatter object and the body content without frontmatter.
|
|
20
|
+
*/
|
|
21
|
+
export function parseFrontmatterClient(raw: string): { frontmatter: Frontmatter; body: string } {
|
|
22
|
+
const match = raw.match(/^---\r?\n([\s\S]*?\r?\n)?---\r?\n?([\s\S]*)$/);
|
|
23
|
+
|
|
24
|
+
if (!match) {
|
|
25
|
+
return { frontmatter: {}, body: raw };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const frontmatter = (yaml.parse(match[1] ?? '') as Frontmatter) ?? {};
|
|
29
|
+
const body = match[2];
|
|
30
|
+
|
|
31
|
+
return { frontmatter, body };
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Serialize a frontmatter object and body content back into a raw markdown string.
|
|
36
|
+
* If frontmatter has no keys, returns just the body content.
|
|
37
|
+
*/
|
|
38
|
+
export function serializeFrontmatter(frontmatter: Frontmatter, body: string): string {
|
|
39
|
+
const keys = Object.keys(frontmatter);
|
|
40
|
+
if (keys.length === 0) return body;
|
|
41
|
+
const yamlStr = yaml.stringify(frontmatter, { lineWidth: 0 }).trimEnd();
|
|
42
|
+
return `---\n${yamlStr}\n---\n${body}`;
|
|
43
|
+
}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
// ── Types ────────────────────────────────────────────────────────────────
|
|
2
|
+
|
|
3
|
+
export interface ParsedRegion {
|
|
4
|
+
name: string;
|
|
5
|
+
mode: 'replace' | 'prepend' | 'append';
|
|
6
|
+
content: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface ParsedLayout {
|
|
10
|
+
regions: ParsedRegion[];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface NavGroup {
|
|
14
|
+
title: string;
|
|
15
|
+
items: string[];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface ParsedNav {
|
|
19
|
+
groups: NavGroup[];
|
|
20
|
+
ungrouped: string[];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// ── Layout Parsing ───────────────────────────────────────────────────────
|
|
24
|
+
|
|
25
|
+
const REGION_RE = /\{%\s*region\s+([^%]*?)%\}([\s\S]*?)\{%\s*\/region\s*%\}/g;
|
|
26
|
+
const ATTR_RE = /(\w+)="([^"]*)"/g;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Parse raw `_layout.md` content into structured regions.
|
|
30
|
+
* Extracts `{% region name="..." mode="..." %}...{% /region %}` blocks.
|
|
31
|
+
*/
|
|
32
|
+
export function parseLayoutClient(raw: string): ParsedLayout {
|
|
33
|
+
const regions: ParsedRegion[] = [];
|
|
34
|
+
|
|
35
|
+
let match: RegExpExecArray | null;
|
|
36
|
+
REGION_RE.lastIndex = 0;
|
|
37
|
+
|
|
38
|
+
while ((match = REGION_RE.exec(raw)) !== null) {
|
|
39
|
+
const attrsStr = match[1];
|
|
40
|
+
const content = match[2];
|
|
41
|
+
|
|
42
|
+
const attrs: Record<string, string> = {};
|
|
43
|
+
let attrMatch: RegExpExecArray | null;
|
|
44
|
+
ATTR_RE.lastIndex = 0;
|
|
45
|
+
while ((attrMatch = ATTR_RE.exec(attrsStr)) !== null) {
|
|
46
|
+
attrs[attrMatch[1]] = attrMatch[2];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const name = attrs.name || '';
|
|
50
|
+
const mode = (attrs.mode as ParsedRegion['mode']) || 'replace';
|
|
51
|
+
|
|
52
|
+
// Trim one leading and one trailing newline from content
|
|
53
|
+
let trimmed = content;
|
|
54
|
+
if (trimmed.startsWith('\n')) trimmed = trimmed.slice(1);
|
|
55
|
+
if (trimmed.endsWith('\n')) trimmed = trimmed.slice(0, -1);
|
|
56
|
+
|
|
57
|
+
regions.push({ name, mode, content: trimmed });
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return { regions };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Serialize a `ParsedLayout` back to `_layout.md` format.
|
|
65
|
+
*/
|
|
66
|
+
export function serializeLayout(layout: ParsedLayout): string {
|
|
67
|
+
const parts: string[] = ['{% layout %}'];
|
|
68
|
+
|
|
69
|
+
for (const region of layout.regions) {
|
|
70
|
+
const modeAttr = region.mode !== 'replace' ? ` mode="${region.mode}"` : '';
|
|
71
|
+
parts.push(`{% region name="${region.name}"${modeAttr} %}`);
|
|
72
|
+
parts.push(region.content);
|
|
73
|
+
parts.push('{% /region %}');
|
|
74
|
+
parts.push('');
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
parts.push('{% /layout %}');
|
|
78
|
+
|
|
79
|
+
return parts.join('\n');
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// ── Nav Parsing ──────────────────────────────────────────────────────────
|
|
83
|
+
|
|
84
|
+
const NAV_OPEN_RE = /\{%\s*nav\s*%\}/;
|
|
85
|
+
const NAV_CLOSE_RE = /\{%\s*\/nav\s*%\}/;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Check if a string contains a `{% nav %}` block.
|
|
89
|
+
*/
|
|
90
|
+
export function containsNav(content: string): boolean {
|
|
91
|
+
return NAV_OPEN_RE.test(content);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Extract the content inside `{% nav %}...{% /nav %}` tags.
|
|
96
|
+
* Returns the inner content, or null if no nav block found.
|
|
97
|
+
*/
|
|
98
|
+
export function extractNavContent(content: string): string | null {
|
|
99
|
+
const openMatch = NAV_OPEN_RE.exec(content);
|
|
100
|
+
if (!openMatch) return null;
|
|
101
|
+
|
|
102
|
+
const afterOpen = openMatch.index + openMatch[0].length;
|
|
103
|
+
const closeMatch = NAV_CLOSE_RE.exec(content.slice(afterOpen));
|
|
104
|
+
if (!closeMatch) return null;
|
|
105
|
+
|
|
106
|
+
let inner = content.slice(afterOpen, afterOpen + closeMatch.index);
|
|
107
|
+
if (inner.startsWith('\n')) inner = inner.slice(1);
|
|
108
|
+
if (inner.endsWith('\n')) inner = inner.slice(0, -1);
|
|
109
|
+
return inner;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Replace the content inside `{% nav %}...{% /nav %}` with new content.
|
|
114
|
+
*/
|
|
115
|
+
export function replaceNavContent(regionContent: string, newNavContent: string): string {
|
|
116
|
+
const openMatch = NAV_OPEN_RE.exec(regionContent);
|
|
117
|
+
if (!openMatch) return regionContent;
|
|
118
|
+
|
|
119
|
+
const afterOpen = openMatch.index + openMatch[0].length;
|
|
120
|
+
const closeMatch = NAV_CLOSE_RE.exec(regionContent.slice(afterOpen));
|
|
121
|
+
if (!closeMatch) return regionContent;
|
|
122
|
+
|
|
123
|
+
const before = regionContent.slice(0, afterOpen);
|
|
124
|
+
const after = regionContent.slice(afterOpen + closeMatch.index);
|
|
125
|
+
|
|
126
|
+
return `${before}\n${newNavContent}\n${after}`;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Parse the inner content of a `{% nav %}` block into groups + items.
|
|
131
|
+
* Groups are delimited by `## Heading` lines.
|
|
132
|
+
* Items are `- slug` list items.
|
|
133
|
+
*/
|
|
134
|
+
export function parseNavContent(content: string): ParsedNav {
|
|
135
|
+
const lines = content.split('\n');
|
|
136
|
+
const groups: NavGroup[] = [];
|
|
137
|
+
const ungrouped: string[] = [];
|
|
138
|
+
|
|
139
|
+
let currentGroup: NavGroup | null = null;
|
|
140
|
+
|
|
141
|
+
for (const line of lines) {
|
|
142
|
+
const trimmed = line.trim();
|
|
143
|
+
|
|
144
|
+
// Heading = new group
|
|
145
|
+
const headingMatch = trimmed.match(/^##\s+(.+)$/);
|
|
146
|
+
if (headingMatch) {
|
|
147
|
+
currentGroup = { title: headingMatch[1], items: [] };
|
|
148
|
+
groups.push(currentGroup);
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// List item = nav item
|
|
153
|
+
const itemMatch = trimmed.match(/^-\s+(.+)$/);
|
|
154
|
+
if (itemMatch) {
|
|
155
|
+
const slug = itemMatch[1].trim();
|
|
156
|
+
if (currentGroup) {
|
|
157
|
+
currentGroup.items.push(slug);
|
|
158
|
+
} else {
|
|
159
|
+
ungrouped.push(slug);
|
|
160
|
+
}
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Skip blank lines and anything else
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return { groups, ungrouped };
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Serialize a `ParsedNav` back to nav content markdown.
|
|
172
|
+
*/
|
|
173
|
+
export function serializeNavContent(nav: ParsedNav): string {
|
|
174
|
+
const parts: string[] = [];
|
|
175
|
+
|
|
176
|
+
for (const slug of nav.ungrouped) {
|
|
177
|
+
parts.push(`- ${slug}`);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (nav.ungrouped.length > 0 && nav.groups.length > 0) {
|
|
181
|
+
parts.push('');
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
for (let i = 0; i < nav.groups.length; i++) {
|
|
185
|
+
const group = nav.groups[i];
|
|
186
|
+
parts.push(`## ${group.title}`);
|
|
187
|
+
parts.push('');
|
|
188
|
+
for (const slug of group.items) {
|
|
189
|
+
parts.push(`- ${slug}`);
|
|
190
|
+
}
|
|
191
|
+
if (i < nav.groups.length - 1) {
|
|
192
|
+
parts.push('');
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return parts.join('\n');
|
|
197
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@refrakt-md/editor",
|
|
3
3
|
"description": "Browser-based content editor for refrakt.md",
|
|
4
|
-
"version": "0.8.
|
|
4
|
+
"version": "0.8.4",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
@@ -40,8 +40,10 @@
|
|
|
40
40
|
"dist",
|
|
41
41
|
"app/dist",
|
|
42
42
|
"app/src/lib/components",
|
|
43
|
-
"app/src/lib/editor
|
|
44
|
-
"app/src/lib/preview
|
|
43
|
+
"app/src/lib/editor",
|
|
44
|
+
"app/src/lib/preview",
|
|
45
|
+
"app/src/lib/state",
|
|
46
|
+
"app/src/lib/utils",
|
|
45
47
|
"app/src/lib/api/client.ts",
|
|
46
48
|
"preview-runtime"
|
|
47
49
|
],
|
|
@@ -50,11 +52,11 @@
|
|
|
50
52
|
},
|
|
51
53
|
"dependencies": {
|
|
52
54
|
"@markdoc/markdoc": "0.4.0",
|
|
53
|
-
"@refrakt-md/content": "0.8.
|
|
54
|
-
"@refrakt-md/highlight": "0.8.
|
|
55
|
-
"@refrakt-md/runes": "0.8.
|
|
56
|
-
"@refrakt-md/transform": "0.8.
|
|
57
|
-
"@refrakt-md/types": "0.8.
|
|
55
|
+
"@refrakt-md/content": "0.8.4",
|
|
56
|
+
"@refrakt-md/highlight": "0.8.4",
|
|
57
|
+
"@refrakt-md/runes": "0.8.4",
|
|
58
|
+
"@refrakt-md/transform": "0.8.4",
|
|
59
|
+
"@refrakt-md/types": "0.8.4"
|
|
58
60
|
},
|
|
59
61
|
"devDependencies": {
|
|
60
62
|
"@codemirror/autocomplete": "^6.20.0",
|