devexpress-richedit
Version:
DevExpress Rich Text Editor is an advanced word-processing tool designed for working with rich text documents.
85 lines (84 loc) • 4.22 kB
JavaScript
import { EmptyBatchUpdatableObject } from "@devexpress/utils/lib/class/batch-updatable";
import { ModelChecker } from "../../../model/model-checks/check-all";
import { ModelCreatorOptions } from "../../../model/creator/options";
import { ModelCreator } from "../../../model/creator/creator";
import { MaskedCharacterProperties } from "../../../model/character/character-properties";
import { SubDocumentPosition } from "../../../model/sub-document";
import { ClientModelManager } from "../../../model-manager";
import { MaskedCharacterPropertiesBundle } from "../../../rich-utils/properties-bundle";
import { Measurer } from "../../../measurer/measurer";
import { DocumentImporterErrors } from "../../document-importer-errors";
import { FormatImagesImporter } from "../../utils/images-import";
import { HtmlImporter } from "./html-importer";
export class HtmlDocumentImporter {
importFromFile(blob, modelOptions, callback, reject) {
this.init(modelOptions);
const reader = new FileReader();
reader.onload = () => {
this.importFromString(reader.result, modelOptions, callback, reject);
};
reader.onerror = (_ev) => {
reject(DocumentImporterErrors.HtmlFileReaderError);
};
reader.readAsText(blob);
}
importFromString(text, modelOptions, callback, reject, charPropsBundle) {
this.init(modelOptions);
try {
this.fillModel(text, charPropsBundle);
if (!new ModelChecker(this.documentModel).checkAll())
throw new Error();
}
catch (err) {
reject(DocumentImporterErrors.HtmlImportError);
return;
}
callback(this.documentModel, this.formatImagesImporter);
}
init(modelOptions) {
const options = new ModelCreatorOptions();
options.addSection = true;
options.addParagraph = true;
this.formatImagesImporter = new FormatImagesImporter();
this.documentModel = new ModelCreator(options).createModel(modelOptions).fillModel();
this.modelManager = new ClientModelManager(this.documentModel, modelOptions, new EmptyBatchUpdatableObject());
}
fillModel(text, charPropsBundle) {
const container = document.body.appendChild(this.createContainer());
try {
container.innerHTML = HtmlImporter.convertHtml(text);
charPropsBundle = charPropsBundle || this.createMaskedCharacterPropertiesBundle();
const measurer = new Measurer('');
const position = new SubDocumentPosition(this.documentModel.mainSubDocument, 0);
const initElements = container.childNodes;
new HtmlImporter(this.modelManager, measurer, position, initElements, charPropsBundle, this.formatImagesImporter).import();
this.removeLastParagraph();
}
finally {
document.body.removeChild(container);
}
}
createMaskedCharacterPropertiesBundle() {
const maskedCharacterProperties = MaskedCharacterProperties.createDefault(this.documentModel);
const style = this.modelManager.model.stylesManager.getDefaultCharacterStyle();
return new MaskedCharacterPropertiesBundle(maskedCharacterProperties, style);
}
createContainer() {
const container = document.createElement('DIV');
container.id = 'import-container';
container.style.width = '0';
container.style.height = '0';
container.style.overflow = 'hidden';
return container;
}
removeLastParagraph() {
const lastParagraph = this.documentModel.mainSubDocument.getLastParagraph();
if (lastParagraph.length > 1)
return;
const section = this.documentModel.getSectionByPosition(lastParagraph.startLogPosition.value);
const lastChunk = this.documentModel.mainSubDocument.getLastChunk();
this.documentModel.mainSubDocument.paragraphs.pop();
section.setLength(this.documentModel.mainSubDocument, section.getLength() - lastParagraph.length);
lastChunk.removeRun(lastChunk.textRuns.length - 1);
}
}