devexpress-richedit
Version:
DevExpress Rich Text Editor is an advanced word-processing tool designed for working with rich text documents.
344 lines (343 loc) • 16.2 kB
JavaScript
import { MapCreator } from '../../../../../../common/utils/map-creator';
import { CrossExistingIterator } from '../../../../../../common/formats/utils/cross-existing-iterator';
import { Field } from '../../../../../../common/model/fields/field';
import { ModelIterator } from '../../../../../../common/model/model-iterator';
import { RunType } from '../../../../../../common/model/runs/run-type';
import { SubDocument } from '../../../../../../common/model/sub-document';
import { Stack } from '@devexpress/utils/lib/class/stack';
import { BoundaryInterval } from '@devexpress/utils/lib/intervals/boundary';
import { Comparers } from '@devexpress/utils/lib/utils/comparers';
import { ListUtils } from '@devexpress/utils/lib/utils/list';
import { StringUtils } from '@devexpress/utils/lib/utils/string';
import { DocxNsType } from '../../../utils/constants';
import { AnchoredDrawingPictureObject, AnchoredDrawingTextObject, InlineDrawingObject } from '../../utils/inline-drawing-object';
import { ExporterBaseWithRootElement } from '../base';
import { DrawingExporter } from '../base/drawing';
import { TableExporter } from '../base/table/table';
import { isDefined } from '@devexpress/utils/lib/utils/common';
export class BaseSubDocumentExporter extends ExporterBaseWithRootElement {
get filePath() { return this._filePath; }
get rootNSPrefix() { return this.data.constants.namespaces[DocxNsType.WordProcessing].prefix; }
get rootNSValue() { return this.data.constants.namespaces[DocxNsType.WordProcessing].namespace; }
constructor(data, filePath) {
super(data);
this.fieldCodeDepth = 0;
this.paragraph = null;
this.firstIteration = true;
this.predefinedGroupNames = new MapCreator()
.add("Everyone", "everyone")
.add("Current User", "current")
.add("Editors", "editors")
.add("Owners", "owners")
.add("Contributors", "contributors")
.add("Administrators", "administrators")
.get();
this._filePath = filePath;
this.hyperlinkRelationsTable = {};
this.fieldsStack = new Stack();
this.runHandlerMap = {
[RunType.TextRun]: this.textRunHandler,
[RunType.ParagraphRun]: this.paragraphRunHandler,
[RunType.SectionRun]: this.sectionRunHandler,
[RunType.FieldCodeStartRun]: this.fieldCodeStartRunHandler,
[RunType.FieldCodeEndRun]: this.fieldCodeEndRunHandler,
[RunType.FieldResultEndRun]: this.fieldResultEndRunHandler,
[RunType.AnchoredPictureRun]: this.anchoredPictureRunHandler,
[RunType.AnchoredTextBoxRun]: this.anchoredTextRunHandler,
[RunType.InlinePictureRun]: this.inlinePictureRunHandler,
[RunType.InlineTextBoxRun]: null,
[RunType.LayoutDependentRun]: this.layoutDependentRunHandler,
[RunType.FootNoteRun]: this.footNoteRunHandler,
[RunType.EndNoteRun]: this.endNoteRunHandler,
[RunType.NoteSeparatorRun]: this.noteSeparatorRunHandler,
[RunType.NoteContinuationSeparatorRun]: this.noteContinuationSeparatorRun,
};
this.tableExporter = new TableExporter(this.data);
}
fillWriter() {
this.data.subDocumentExporterStack.push(this);
this.registerNamespaces();
this.data.pushRelationExporter(this.createRelationExporter());
this.fillWriterCore();
if (!this.isMainContent())
this.data.popRelationExporter();
this.data.subDocumentExporterStack.pop();
}
init() {
this.modelIterator = new ModelIterator(this.subDocument, false);
this.modelIterator.setPosition(0);
this.tableExporter.init();
this.bookmarksIterator = new CrossExistingIterator(this.subDocument.bookmarks);
this.bookmarksIterator.init();
this.rangePermisiionsIterator = new CrossExistingIterator(this.subDocument.rangePermissions);
this.rangePermisiionsIterator.init();
}
endParagraph(pos, section, allowInitNextParagraph) {
if (this.paragraph)
this.writer.endElement();
this.tableExporter.checkTable(pos, allowInitNextParagraph);
if (allowInitNextParagraph) {
this.paragraph = this.modelIterator.run.paragraph;
this.writer.writeWpStartElement('p');
this.data.parPropsExporter.exportParagraphProperties(this.subDocument, section, this.paragraph, this.getCurrentParagraphRun());
}
}
getCurrentParagraphRun() {
if (!this.modelIterator.run)
return null;
if (this.modelIterator.run.isParagraphOrSectionRun())
return this.run;
return this.subDocument.getRunByPosition(this.run.paragraph.interval.end - 1);
}
exportSection(section, sectionInterval) {
const thingEndPos = sectionInterval.end;
for (; this.firstIteration || this.modelIterator.moveToNextChar(); this.firstIteration = false) {
if (this.run != this.modelIterator.run) {
this.run = this.modelIterator.run;
this.runText = this.modelIterator.getRunText();
this.runStartCharOffset = 0;
}
const pos = this.modelIterator.getAbsolutePosition();
if (!this.paragraph || pos >= this.paragraph.getEndPosition()) {
if (pos == thingEndPos)
break;
this.endParagraph(pos, section, true);
}
if (this.bookmarksIterator.update(pos)) {
this.exportRun(new BoundaryInterval(this.runStartCharOffset, this.modelIterator.charOffset));
this.exportBookmark(this.bookmarksIterator);
}
if (this.rangePermisiionsIterator.update(pos)) {
this.exportRun(new BoundaryInterval(this.runStartCharOffset, this.modelIterator.charOffset));
this.exportRangePermission(this.rangePermisiionsIterator);
}
if (this.modelIterator.charOffset + 1 == this.run.getLength())
this.exportRun(new BoundaryInterval(this.runStartCharOffset, this.run.getLength()));
}
if (this.bookmarksIterator.update(thingEndPos))
this.exportBookmark(this.bookmarksIterator);
if (this.rangePermisiionsIterator.update(thingEndPos))
this.exportRangePermission(this.rangePermisiionsIterator);
this.endParagraph(thingEndPos, section, false);
this.paragraph = null;
this.firstIteration = true;
}
registerNamespaces() {
this.ignorableNamespaces = [];
this.registerDefaultNamespaces();
this.registerIgnorableNamespaces();
}
registerDefaultNamespaces() {
this.registerNamespace(DocxNsType.WordProcessing, false);
this.registerNamespace(DocxNsType.Wps, false);
this.registerNamespace(DocxNsType.MC, false);
this.registerNamespace(DocxNsType.W10ML, false);
this.registerNamespace(DocxNsType.VML, false);
this.registerNamespace(DocxNsType.Wpg, false);
this.registerNamespace(DocxNsType.Wpc, false);
this.registerNamespace(DocxNsType.Rels, false);
this.registerNamespace(DocxNsType.DrawingML, false);
this.registerNamespace(DocxNsType.DrawingMLPicture, false);
this.registerNamespace(DocxNsType.WordProcessingDrawing, false);
this.registerNamespace(DocxNsType.WordProcessingDrawing14, true);
}
registerNamespace(type, ignorable) {
this.writer.addNamespaceToRootElement(type);
if (ignorable)
this.ignorableNamespaces.push(this.data.constants.namespaces[type].prefix);
}
registerIgnorableNamespaces() {
if (this.ignorableNamespaces.length) {
this.writer.attrNS(DocxNsType.MC, 'Ignorable', ListUtils.unique(this.ignorableNamespaces, Comparers.string, (a, b) => a == b ? 0 : 1).join(' '));
}
this.ignorableNamespaces = [];
}
exportRun(charInterval) {
if (charInterval.length) {
const handler = this.runHandlerMap[this.run.getType()];
if (handler) {
this.absRunStartPosition = this.modelIterator.getAbsoluteRunPosition();
handler.call(this, this.runText.substring(charInterval.start, charInterval.end));
}
}
this.runStartCharOffset = charInterval.end;
}
textRunHandler(runText) {
this.writer.writeWpStartElement('r');
this.data.charPropsExporter.exportRunProperties(this.run);
this.tryExportNoteCustomMarkReference();
this.data.textExporter.exportTextRunCore(runText);
this.writer.endElement();
}
paragraphRunHandler() {
}
sectionRunHandler() {
}
fieldCodeStartRunHandler() {
this.fieldsStack.push(this.subDocument.fields[Field.binaryIndexOf(this.subDocument.fields, this.absRunStartPosition + 1)]);
this.exportFieldChar('begin', true);
this.fieldCodeDepth++;
}
fieldCodeEndRunHandler() {
this.exportFieldChar('separate', false);
this.fieldCodeDepth--;
}
fieldResultEndRunHandler() {
this.exportFieldChar('end', false);
this.fieldsStack.pop();
}
shouldExportPicture(cacheInfo) {
return cacheInfo.isLoaded || cacheInfo.imageUrl;
}
anchoredPictureRunHandler() {
this.writer.writeWpStartElement('r');
this.data.charPropsExporter.exportRunProperties(this.run);
this.tryExportNoteCustomMarkReference();
const picRun = this.run;
if (this.shouldExportPicture(picRun.cacheInfo))
new DrawingExporter(this.data).writeFloatingObjectDrawing(new AnchoredDrawingPictureObject(picRun), picRun.cacheInfo.currId);
this.writer.endElement();
}
anchoredTextRunHandler() {
this.writer.writeWpStartElement('r');
this.data.charPropsExporter.exportRunProperties(this.run);
this.tryExportNoteCustomMarkReference();
const textBoxRun = this.run;
new DrawingExporter(this.data).writeFloatingObjectTextBoxContent2010(new AnchoredDrawingTextObject(textBoxRun), this.data.model.subDocuments[textBoxRun.subDocId]);
this.writer.endElement();
}
inlinePictureRunHandler() {
this.writer.writeWpStartElement('r');
this.data.charPropsExporter.exportRunProperties(this.run);
this.tryExportNoteCustomMarkReference();
const picRun = this.run;
if (this.shouldExportPicture(picRun.cacheInfo))
new DrawingExporter(this.data).writeFloatingObjectDrawing(new InlineDrawingObject(picRun), picRun.cacheInfo.currId);
this.writer.endElement();
}
layoutDependentRunHandler() {
}
footNoteRunHandler() {
this.writer.writeWpStartElement('r');
this.data.charPropsExporter.exportRunProperties(this.run);
const subDocId = this.run.noteDocumentId;
if (isDefined(subDocId) && subDocId > SubDocument.MAIN_SUBDOCUMENT_ID)
this.exportFootNoteReference(subDocId, false);
else {
this.writer.writeWpStartElement('footnoteRef');
this.writer.endElement();
}
this.writer.endElement();
}
exportFootNoteReference(subDocId, isCustomMark) {
const note = this.data.model.subDocuments[subDocId];
const id = this.data.addFootNote(note);
this.exportNoteReference('footnoteReference', id, isCustomMark);
}
endNoteRunHandler() {
this.writer.writeWpStartElement('r');
this.data.charPropsExporter.exportRunProperties(this.run);
const subDocId = this.run.noteDocumentId;
if (isDefined(subDocId) && subDocId > SubDocument.MAIN_SUBDOCUMENT_ID)
this.exportEndNoteReference(subDocId, false);
else {
this.writer.writeWpStartElement('endnoteRef');
this.writer.endElement();
}
this.writer.endElement();
}
exportEndNoteReference(subDocId, isCustomMark) {
const note = this.data.model.subDocuments[subDocId];
const id = this.data.addEndNote(note);
this.exportNoteReference('endnoteReference', id, isCustomMark);
}
tryExportNoteCustomMarkReference() {
const subDocId = this.run.noteDocumentId;
if (!isDefined(subDocId))
return;
const note = this.data.model.subDocuments[subDocId];
if (note.isFootNote())
this.exportFootNoteReference(subDocId, true);
else
this.exportEndNoteReference(subDocId, true);
}
exportNoteReference(rootElement, id, isCustomMark) {
this.writer.writeWpStartElement(rootElement);
if (isCustomMark)
this.writer.writeWpBoolAttr('customMarkFollows', true);
this.writer.writeWpIntAttr('id', id);
this.writer.endElement();
}
noteSeparatorRunHandler() {
this.exportNoteSeparator('separator');
}
noteContinuationSeparatorRun() {
this.exportNoteSeparator('continuationSeparator');
}
exportNoteSeparator(separator) {
this.writer.writeWpStartElement('r');
this.data.charPropsExporter.exportRunProperties(this.run);
this.writer.writeWpStartElement(separator);
this.writer.endElement();
this.writer.endElement();
}
exportBookmark(bookmarksIterator) {
for (const state of bookmarksIterator.addedObjects) {
this.writer.writeWpStartElement('bookmarkStart');
this.writer.writeWpIntAttr('id', state.index);
this.writer.writeWpStringAttr('name', state.object.name);
this.writer.endElement();
}
for (const state of bookmarksIterator.deletedObjects) {
this.writer.writeWpStartElement('bookmarkEnd');
this.writer.writeWpIntAttr('id', state.index);
this.writer.endElement();
}
}
exportRangePermission(permissionsIterator) {
for (const state of permissionsIterator.addedObjects) {
this.writer.writeWpStartElement('permStart');
this.writer.writeWpIntAttr('id', state.index);
if (!StringUtils.isNullOrEmpty(state.object.userName))
this.writer.writeWpStringAttr('ed', state.object.userName);
if (!StringUtils.isNullOrEmpty(state.object.group))
this.writer.writeWpStringAttr('edGrp', this.getGroupName(state.object.group));
this.writer.endElement();
}
for (const state of permissionsIterator.deletedObjects) {
this.writer.writeWpStartElement('permEnd');
this.writer.writeWpIntAttr('id', state.index);
this.writer.endElement();
}
}
getGroupName(groupName) {
const result = this.predefinedGroupNames[groupName];
return result ? result : groupName;
}
exportFieldChar(fieldCharType, fieldStart) {
this.writer.writeWpStartElement('r');
this.data.charPropsExporter.exportRunProperties(this.run);
this.writer.writeWpStartElement('fldChar');
this.writer.writeWpStringAttr('fldCharType', fieldCharType);
const field = this.fieldsStack.last;
if (fieldStart && field.disableUpdate)
this.writer.writeWpBoolAttr('disableUpdate', true);
if (fieldStart && field.locked)
this.writer.writeWpBoolAttr('fldLock', true);
if (fieldStart && field.hideByParent)
this.writeHideByParent();
this.writer.endElement();
this.writer.endElement();
}
writeHideByParent() {
}
}
export class SingleSubDocumentExoprter extends BaseSubDocumentExporter {
constructor(data, subDocument, filePath) {
super(data, filePath);
this.subDocument = subDocument;
}
isMainContent() {
return this.subDocument.isMain();
}
}