mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-08 10:46:06 +00:00
feat(studio): storyboard markdown source editor (raw + live preview) (#1531)
Fourth PR in the Studio storyboarding stack. Adds an in-context way to view and edit the storyboard's canonical files. - Board | Source sub-toggle inside the storyboard view (StoryboardLoaded). - StoryboardSourceEditor: raw CodeMirror markdown editor + live rendered preview (marked), with a file switcher for STORYBOARD.md and SCRIPT.md. - Loads raw file text and saves via the existing files API (GET/PUT /projects/:id/files/*); on save the Board re-parses (reload), so markdown stays the single source of truth. Cmd/Ctrl+S to save. - Deliberately raw, not WYSIWYG, so the structured frame fields can't be mangled. - SourceEditor gains markdown language support (@codemirror/lang-markdown); adds the marked dependency for preview. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
13af5540c1
commit
29809069c8
@@ -12,26 +12,26 @@ import { bracketMatching, foldGutter, indentOnInput } from "@codemirror/language
|
||||
import { closeBrackets, closeBracketsKeymap } from "@codemirror/autocomplete";
|
||||
import { highlightSelectionMatches, searchKeymap } from "@codemirror/search";
|
||||
import { oneDark } from "@codemirror/theme-one-dark";
|
||||
import type { Extension } from "@codemirror/state";
|
||||
import { html } from "@codemirror/lang-html";
|
||||
import { css } from "@codemirror/lang-css";
|
||||
import { javascript } from "@codemirror/lang-javascript";
|
||||
import { markdown } from "@codemirror/lang-markdown";
|
||||
|
||||
function getLanguageExtension(language: string) {
|
||||
switch (language) {
|
||||
case "html":
|
||||
return html();
|
||||
case "css":
|
||||
return css();
|
||||
case "javascript":
|
||||
case "js":
|
||||
case "typescript":
|
||||
case "ts":
|
||||
return javascript({
|
||||
typescript: language === "typescript" || language === "ts",
|
||||
});
|
||||
default:
|
||||
return html();
|
||||
}
|
||||
const LANGUAGE_EXTENSIONS: Record<string, () => Extension> = {
|
||||
html: () => html(),
|
||||
css: () => css(),
|
||||
markdown: () => markdown(),
|
||||
md: () => markdown(),
|
||||
javascript: () => javascript(),
|
||||
js: () => javascript(),
|
||||
typescript: () => javascript({ typescript: true }),
|
||||
ts: () => javascript({ typescript: true }),
|
||||
};
|
||||
|
||||
function getLanguageExtension(language: string): Extension {
|
||||
const factory = LANGUAGE_EXTENSIONS[language] ?? html;
|
||||
return factory();
|
||||
}
|
||||
|
||||
function detectLanguage(filePath: string): string {
|
||||
@@ -45,6 +45,8 @@ function detectLanguage(filePath: string): string {
|
||||
jsx: "javascript",
|
||||
tsx: "typescript",
|
||||
json: "javascript",
|
||||
md: "markdown",
|
||||
markdown: "markdown",
|
||||
};
|
||||
return map[ext] ?? "html";
|
||||
}
|
||||
@@ -74,6 +76,7 @@ export const SourceEditor = memo(function SourceEditor({
|
||||
const contentRef = useRef(content);
|
||||
contentRef.current = content;
|
||||
|
||||
// fallow-ignore-next-line complexity
|
||||
const mountEditor = useCallback(
|
||||
(node: HTMLDivElement | null) => {
|
||||
if (editorRef.current) {
|
||||
|
||||
Reference in New Issue
Block a user