Skip to content

Commit

Permalink
fix(web): plugin playground/ Modify the behavior of the HTML Editor m…
Browse files Browse the repository at this point in the history
…odal (#1282)
  • Loading branch information
devshun authored Nov 29, 2024
1 parent 3444abd commit 564eb7f
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 34 deletions.
91 changes: 76 additions & 15 deletions web/src/beta/features/PluginPlayground/Code/index.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import { OnMount } from "@monaco-editor/react";
import { Button, CodeInput } from "@reearth/beta/lib/reearth-ui";
import { styled } from "@reearth/services/theme";
import { FC, useCallback, useMemo, useState } from "react";
import { FC, useCallback, useState } from "react";

import HtmlEditModal from "./HtmlEditModal";
import {
extractHtmlFromSourceCode,
getLanguageByFileExtension,
injectHtmlIntoSourceCode
} from "./utils";
import { getLanguageByFileExtension } from "./utils";

type Props = {
fileTitle: string;
Expand All @@ -16,26 +13,89 @@ type Props = {
executeCode: () => void;
};

const REEARTH_HTML_INJECTION_PATTERNS = [
/reearth\.ui\.show\((['"`])([\s\S]*?)\1\)/g,
/reearth\.modal\.show\((['"`])([\s\S]*?)\1\)/g,
/reearth\.popup\.show\((['"`])([\s\S]*?)\1\)/g
];

const Code: FC<Props> = ({
fileTitle,
sourceCode,
onChangeSourceCode,
executeCode
}) => {
const editableHtmlSourceCode = useMemo(
() => extractHtmlFromSourceCode(sourceCode),
[sourceCode]
const [editableHtmlSourceCode, setEditableHtmlSourceCode] = useState<
string | null
>(null);
const [isOpenedHtmlEditor, setIsOpenedHtmlEditor] = useState(false);
const [currentMatch, setCurrentMatch] = useState<RegExpExecArray | null>(
null
);

const getMatchAtCursor = useCallback(
(value: string, offset: number): RegExpExecArray | null => {
for (const pattern of REEARTH_HTML_INJECTION_PATTERNS) {
const re = new RegExp(pattern.source, pattern.flags);
const matches = Array.from(value.matchAll(re));
for (const match of matches) {
const start = match.index;
const end = start + match[0].length;
if (offset >= start && offset <= end) {
return match;
}
}
}
return null;
},
[]
);

const onMount: OnMount = useCallback(
(editor) => {
const listener = editor.onDidChangeCursorPosition(() => {
const model = editor.getModel();
if (!model) return;

const value = model.getValue();
const offset = model.getOffsetAt(editor.getPosition());

const match = getMatchAtCursor(value, offset);
if (match) {
setCurrentMatch(match);
setEditableHtmlSourceCode(match[2]);
} else {
setCurrentMatch(null);
setEditableHtmlSourceCode(null);
}
});

editor.onDidDispose(() => {
listener.dispose();
});
},
[getMatchAtCursor]
);

const onSubmitHtmlEditor = useCallback(
(newHtml: string) => {
onChangeSourceCode(injectHtmlIntoSourceCode(newHtml, sourceCode));
if (!currentMatch) return;

const [fullMatch, delimiter] = currentMatch;
const start = currentMatch.index;
const end = start + fullMatch.length;

const updatedSourceCode =
sourceCode.slice(0, start) +
`reearth.${fullMatch.split(".")[1]}.show(${delimiter}${newHtml}${delimiter})` +
sourceCode.slice(end);

onChangeSourceCode(updatedSourceCode);
setIsOpenedHtmlEditor(false);
},
[sourceCode, onChangeSourceCode]
[currentMatch, sourceCode, onChangeSourceCode]
);

const [isOpenedHtmlEditor, setIsOpenedHtmlEditor] = useState(false);

return (
<>
<Wrapper>
Expand All @@ -53,12 +113,13 @@ const Code: FC<Props> = ({
language={getLanguageByFileExtension(fileTitle)}
value={sourceCode}
onChange={onChangeSourceCode}
onMount={onMount}
/>
</Wrapper>
{isOpenedHtmlEditor && (
{editableHtmlSourceCode && isOpenedHtmlEditor && (
<HtmlEditModal
isOpened={isOpenedHtmlEditor}
sourceCode={editableHtmlSourceCode ?? ""}
sourceCode={editableHtmlSourceCode}
onClose={() => setIsOpenedHtmlEditor(false)}
onSubmit={onSubmitHtmlEditor}
/>
Expand Down
18 changes: 0 additions & 18 deletions web/src/beta/features/PluginPlayground/Code/utils.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,3 @@
const REEARTH_HTML_INJECTION_PATTERN =
/reearth\.(ui|modal|popup)\.show\(\s*(['"`])([^]*?)\2\s*\);/;

export const extractHtmlFromSourceCode = (sourceCode: string) => {
const match = REEARTH_HTML_INJECTION_PATTERN.exec(sourceCode);
return match?.[3];
};

export const injectHtmlIntoSourceCode = (
htmlSourceCode: string,
sourceCode: string
) => {
return sourceCode.replace(
REEARTH_HTML_INJECTION_PATTERN,
(_, type) => `reearth.${type}.show(\`${htmlSourceCode}\`);`
);
};

export const getLanguageByFileExtension = (fileTitle: string) => {
const ext = fileTitle.split(".").pop();
switch (ext) {
Expand Down
7 changes: 6 additions & 1 deletion web/src/beta/lib/reearth-ui/components/CodeInput/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export type CodeInputProps = {
height?: number;
onChange?: (val: string | undefined) => void;
onBlur?: (val: string | undefined) => void;
onMount?: OnMount;
};

export const CodeInput: FC<CodeInputProps> = ({
Expand All @@ -20,7 +21,8 @@ export const CodeInput: FC<CodeInputProps> = ({
disabled,
height,
onChange,
onBlur
onBlur,
onMount
}) => {
const theme = useTheme();
const t = useT();
Expand Down Expand Up @@ -62,6 +64,7 @@ export const CodeInput: FC<CodeInputProps> = ({
"editor.background": theme.bg[1]
}
});

monaco.editor.setTheme("myCustomTheme");
editor.getAction("editor.action.formatDocument").run();

Expand All @@ -73,6 +76,8 @@ export const CodeInput: FC<CodeInputProps> = ({
editor.onDidFocusEditorWidget(() => {
setIsActive(true);
});

onMount?.(editor, monaco);
};

const handleChange = useCallback(
Expand Down

0 comments on commit 564eb7f

Please sign in to comment.