🎉 first commit

This commit is contained in:
LIlGG
2025-09-24 13:06:25 +08:00
commit 1f4fb103e9
409 changed files with 61222 additions and 0 deletions

View 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();
}
}