diff --git a/src/components/RichTextEditor.tsx b/src/components/RichTextEditor.tsx
index 1ab257f9..146125cd 100644
--- a/src/components/RichTextEditor.tsx
+++ b/src/components/RichTextEditor.tsx
@@ -3,10 +3,7 @@ import { StyleSheet, View, Platform } from 'react-native';
import { WebView, type WebViewMessageEvent } from 'react-native-webview';
import { useColors } from '../theme/colors';
import type { ThemePalette } from '../theme/tokens';
-
-// Minimum visible editor height (px). The editor auto-grows beyond this as the
-// user types, and the parent ScrollView handles overflow.
-const MIN_HEIGHT = 220;
+import { buildEditorHtml, MIN_EDITOR_HEIGHT } from '../lib/editor-html';
export type RichTextCommand =
| 'bold'
@@ -66,273 +63,6 @@ interface Props {
onBlur?: () => void;
}
-function buildEditorHtml(opts: {
- initialHtml: string;
- placeholder: string;
- c: ThemePalette;
-}): string {
- const { initialHtml, placeholder, c } = opts;
- // Inject initial content as a JSON-encoded string so any HTML/quotes inside
- // are safely embedded (no template literal collision with the script body).
- const initialJson = JSON.stringify(initialHtml);
- const placeholderJson = JSON.stringify(placeholder);
-
- return `
-
-
-
-
-
-
-
-
-
-
-`;
-}
-
const RichTextEditor = React.forwardRef(function RichTextEditor(
{ initialHtml = '', placeholder = '', onChange, onSelectionChange, onFocus, onBlur },
ref,
@@ -340,7 +70,7 @@ const RichTextEditor = React.forwardRef(function Ri
const c = useColors();
const styles = React.useMemo(() => makeStyles(c), [c]);
const webViewRef = React.useRef(null);
- const [height, setHeight] = React.useState(MIN_HEIGHT);
+ const [height, setHeight] = React.useState(MIN_EDITOR_HEIGHT);
const onChangeRef = React.useRef(onChange);
const onSelectionRef = React.useRef(onSelectionChange);
const onFocusRef = React.useRef(onFocus);
@@ -400,7 +130,7 @@ const RichTextEditor = React.forwardRef(function Ri
break;
case 'height': {
const h = typeof data.payload === 'number' ? data.payload : Number(data.payload);
- if (!Number.isNaN(h) && h > 0) setHeight(Math.max(MIN_HEIGHT, h));
+ if (!Number.isNaN(h) && h > 0) setHeight(Math.max(MIN_EDITOR_HEIGHT, h));
break;
}
case 'selection':
diff --git a/src/lib/__tests__/editor-html.test.ts b/src/lib/__tests__/editor-html.test.ts
new file mode 100644
index 00000000..b69f1808
--- /dev/null
+++ b/src/lib/__tests__/editor-html.test.ts
@@ -0,0 +1,50 @@
+import { describe, expect, it } from 'vitest';
+import { buildEditorHtml } from '../editor-html';
+import { LIGHT_COLORS, DARK_COLORS } from '../../theme/tokens';
+
+function extractScript(html: string): string {
+ const m = html.match(/
+