🎉 first commit
This commit is contained in:
171
app/components/editor/EditorController.tsx
Normal file
171
app/components/editor/EditorController.tsx
Normal file
@@ -0,0 +1,171 @@
|
||||
import type { Editor, EditorControllerProps } from '~/types/editor';
|
||||
import { executeScript } from '~/utils/execute-scripts';
|
||||
import { isScriptContent } from '~/utils/html-parse';
|
||||
|
||||
export class EditorController implements Editor {
|
||||
private props: EditorControllerProps;
|
||||
|
||||
constructor(props: EditorControllerProps) {
|
||||
this.props = props;
|
||||
}
|
||||
|
||||
setContent(newHTML: string) {
|
||||
const pageElement = this.props.getContentElement();
|
||||
if (!pageElement) {
|
||||
return;
|
||||
}
|
||||
pageElement.innerHTML = newHTML;
|
||||
}
|
||||
|
||||
replaceWith(query: string, newHTML: string, sort?: number) {
|
||||
const pageElement = this.props.getContentElement();
|
||||
if (!pageElement) {
|
||||
return;
|
||||
}
|
||||
|
||||
const targetElement = pageElement.querySelector(query);
|
||||
if (!targetElement) {
|
||||
return;
|
||||
}
|
||||
|
||||
targetElement.outerHTML = newHTML;
|
||||
if (sort === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
const parent = targetElement.parentElement;
|
||||
if (!parent) {
|
||||
return;
|
||||
}
|
||||
|
||||
const children = Array.from(parent.children);
|
||||
const index = children.indexOf(targetElement);
|
||||
if (index === -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (sort !== index) {
|
||||
parent.insertBefore(targetElement, children[sort]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 在指定节点下追加 HTML
|
||||
* @param query 查询条件,待添加元素的父节点 ID。
|
||||
* @param newHTML 新 HTML
|
||||
* @param sort 排序位置,从 0 开始表示应该处于第一位,2 表示应该处于第二位,以此类推。不填写则表示默认或者不变
|
||||
*/
|
||||
append(query: string, newHTML: string, sort?: number) {
|
||||
const pageElement = this.props.getContentElement();
|
||||
if (!pageElement) {
|
||||
return;
|
||||
}
|
||||
|
||||
const targetElement = pageElement.querySelector(query);
|
||||
const parent = targetElement || pageElement;
|
||||
const tempDiv = document.createElement('div');
|
||||
tempDiv.innerHTML = newHTML;
|
||||
const newElement = tempDiv.firstElementChild as HTMLElement;
|
||||
if (!newElement) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (sort === undefined) {
|
||||
parent.appendChild(newElement);
|
||||
} else {
|
||||
parent.insertBefore(newElement, parent.children[sort]);
|
||||
}
|
||||
}
|
||||
|
||||
appendContent(query: string, newHTML: string, sort?: number) {
|
||||
const pageElement = this.props.getContentElement();
|
||||
if (!pageElement) {
|
||||
return;
|
||||
}
|
||||
const tempDiv = document.createElement('div');
|
||||
tempDiv.innerHTML = newHTML;
|
||||
const newElement = tempDiv.firstElementChild as HTMLElement;
|
||||
if (!newElement) {
|
||||
return;
|
||||
}
|
||||
const id = newElement.id;
|
||||
const targetElement = pageElement.querySelector(`#${id}`);
|
||||
if (targetElement) {
|
||||
this.replaceWith(`#${id}`, newHTML, sort);
|
||||
if (isScriptContent(newHTML)) {
|
||||
this.refresh();
|
||||
}
|
||||
return;
|
||||
}
|
||||
this.append(query, newHTML, sort);
|
||||
const element = pageElement.querySelector(`#${id}`);
|
||||
if (element instanceof HTMLScriptElement) {
|
||||
executeScript(element);
|
||||
const frameRef = this.props.getIframeElement();
|
||||
const event = new Event('DOMContentLoaded', {
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
});
|
||||
frameRef?.contentDocument?.dispatchEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
updateContent(query: string, newHTML: string, sort?: number) {
|
||||
const pageElement = this.props.getContentElement();
|
||||
if (!pageElement) {
|
||||
return;
|
||||
}
|
||||
this.replaceWith(query, newHTML, sort);
|
||||
if (isScriptContent(newHTML)) {
|
||||
this.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
deleteContent(query: string) {
|
||||
const pageElement = this.props.getContentElement();
|
||||
if (!pageElement) {
|
||||
return;
|
||||
}
|
||||
|
||||
const targetElement = pageElement.querySelector(query);
|
||||
if (targetElement) {
|
||||
targetElement.remove();
|
||||
}
|
||||
if (targetElement instanceof HTMLScriptElement) {
|
||||
this.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
getContent(query?: string): string {
|
||||
const pageElement = this.props.getContentElement();
|
||||
if (!pageElement) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (query) {
|
||||
const targetElement = pageElement.querySelector(query);
|
||||
return targetElement ? targetElement.innerHTML : '';
|
||||
}
|
||||
|
||||
return pageElement.innerHTML;
|
||||
}
|
||||
|
||||
scrollToElement(query: string) {
|
||||
const pageElement = this.props.getContentElement();
|
||||
if (!pageElement) {
|
||||
return;
|
||||
}
|
||||
const targetElement = pageElement.querySelector(query);
|
||||
if (targetElement) {
|
||||
targetElement.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||||
}
|
||||
}
|
||||
|
||||
refresh() {
|
||||
const iframeElement = this.props.getIframeElement();
|
||||
if (!iframeElement) {
|
||||
return;
|
||||
}
|
||||
iframeElement.contentWindow?.location.reload();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user