UNPKG

devexpress-richedit

Version:

DevExpress Rich Text Editor is an advanced word-processing tool designed for working with rich text documents.

287 lines (286 loc) 17.7 kB
import { ApiParametersChecker } from './api-utils/parameter-checker'; import { DocumentFormat } from '../../common/document-format'; import { InsertParagraphManipulatorParams } from '../../common/model/manipulators/paragraph-manipulator/insert-paragraph-manipulator-params'; import { InlinePictureInfo } from '../../common/model/manipulators/picture-manipulator/insert-picture-manipulator-params'; import { ImageLoadingOptions } from '../../common/model/manipulators/picture-manipulator/loader/image-loading-options'; import { InsertTextManipulatorParams } from '../../common/model/manipulators/text-manipulator/insert-text-manipulator-params'; import { ParagraphPropertiesApplier } from '../../common/model/paragraph/paragraph-properties-helper'; import { RichUtils } from '../../common/model/rich-utils'; import { RunType } from '../../common/model/runs/run-type'; import { SubDocumentInterval, SubDocumentPosition } from '../../common/model/sub-document'; import { MaskedParagraphPropertiesBundleFull } from '../../common/rich-utils/properties-bundle'; import { InputPositionBase } from '../../common/selection/input-position-base'; import { SelectionIntervalsInfo } from '../../common/selection/selection-intervals-info'; import { Constants } from '@devexpress/utils/lib/constants'; import { Size } from '@devexpress/utils/lib/geometry/size'; import { FixedInterval } from '@devexpress/utils/lib/intervals/fixed'; import { MathUtils } from '@devexpress/utils/lib/utils/math'; import { isDefined } from '@devexpress/utils/lib/utils/common'; import { getRtfFromSubDocumentPublic, insertRtfInSubDocumentPublic } from '../../common/formats/rtf/importer-in-subdocument'; import { insertHtmlInSubDocument } from '../../common/formats/html/import/insert-html'; import { getHtmlFromSubDocument } from '../../common/formats/html/export/get-html'; import { getRestrictedInterval } from './api-utils/api-utils'; import { ModelParametersChecker } from './api-utils/model-parameter-checker'; import { getCharacterProperties, setCharacterProperties, } from './character-properties'; import { BookmarkCollection } from './collections/bookmark-collection'; import { FieldCollection } from './collections/field-collection'; import { HyperlinkCollection } from './collections/hyperlink-collection'; import { ParagraphCollection } from './collections/paragraph-collection'; import { RangePermissionCollection } from './collections/range-permission-collection'; import { TableCollection } from './collections/table/table-collection'; import { insertContentInSubDocumentPublic } from './formats/importer'; import { ImagesApi } from './images/images'; import { convertToIntervalApi, IntervalApi } from './interval'; import { convertFromParagraphPropertiesApi, convertToParagraphPropertiesApi, ParagraphApi } from './paragraph'; import { SectionApi } from './section'; import { insertTextThroughApi } from './api-utils/insert-text'; export var SubDocumentTypeApi; (function (SubDocumentTypeApi) { SubDocumentTypeApi[SubDocumentTypeApi["Main"] = 0] = "Main"; SubDocumentTypeApi[SubDocumentTypeApi["Header"] = 1] = "Header"; SubDocumentTypeApi[SubDocumentTypeApi["Footer"] = 2] = "Footer"; SubDocumentTypeApi[SubDocumentTypeApi["TextBox"] = 3] = "TextBox"; SubDocumentTypeApi[SubDocumentTypeApi["FootNote"] = 4] = "FootNote"; SubDocumentTypeApi[SubDocumentTypeApi["EndNote"] = 5] = "EndNote"; })(SubDocumentTypeApi || (SubDocumentTypeApi = {})); export var HeaderFooterTypeApi; (function (HeaderFooterTypeApi) { HeaderFooterTypeApi[HeaderFooterTypeApi["First"] = 0] = "First"; HeaderFooterTypeApi[HeaderFooterTypeApi["Odd"] = 1] = "Odd"; HeaderFooterTypeApi[HeaderFooterTypeApi["Even"] = 2] = "Even"; HeaderFooterTypeApi[HeaderFooterTypeApi["Primary"] = 1] = "Primary"; })(HeaderFooterTypeApi || (HeaderFooterTypeApi = {})); export var SectionBreakTypeApi; (function (SectionBreakTypeApi) { SectionBreakTypeApi[SectionBreakTypeApi["NextPage"] = 0] = "NextPage"; SectionBreakTypeApi[SectionBreakTypeApi["OddPage"] = 1] = "OddPage"; SectionBreakTypeApi[SectionBreakTypeApi["EvenPage"] = 2] = "EvenPage"; SectionBreakTypeApi[SectionBreakTypeApi["Continuous"] = 3] = "Continuous"; })(SectionBreakTypeApi || (SectionBreakTypeApi = {})); export class SubDocumentApi { constructor(processor, subDocument) { this._subDocument = subDocument; this._processor = processor; } get paragraphs() { return new ParagraphCollection(this._processor, this._subDocument); } get bookmarks() { return new BookmarkCollection(this._processor, this._subDocument); } get rangePermissions() { return new RangePermissionCollection(this._processor, this._subDocument); } get tables() { return new TableCollection(this._processor, this._subDocument); } get fields() { return new FieldCollection(this._processor, this._subDocument); } get hyperlinks() { return new HyperlinkCollection(this._processor, this._subDocument); } get images() { return new ImagesApi(this._processor, this._subDocument); } get parentSubDocument() { const info = this._subDocument.info; if (info.isTextBox) return new SubDocumentApi(this._processor, this._processor.modelManager.model.subDocuments[info.parentSubDocumentId]); return null; } get id() { return this._subDocument.id; } get type() { return this._subDocument.info.getType(); } get interval() { return new IntervalApi(0, this._subDocument.getDocumentEndPosition()); } get length() { return this._subDocument.getDocumentEndPosition(); } insertText(position, text) { position = ApiParametersChecker.check(position, 1, false, [ ApiParametersChecker.numberDescriptor('position', (val) => val) ]); position = MathUtils.restrictValue(position, 0, this._subDocument.getDocumentEndPosition() - 1); text = ApiParametersChecker.check(text, 2, false, [ ApiParametersChecker.stringDescriptor('text', (v) => v, true) ]); return convertToIntervalApi(insertTextThroughApi(position, text, this._subDocument, this._processor, { wrapIntoBeginUpdate: true })); } insertLineBreak(position) { return insertSpecialCharacter(position, RichUtils.specialCharacters.LineBreak, this._processor, this._subDocument); } insertColumnBreak(position) { return insertSpecialCharacter(position, RichUtils.specialCharacters.ColumnBreak, this._processor, this._subDocument); } insertPageBreak(position) { return insertSpecialCharacter(position, RichUtils.specialCharacters.PageBreak, this._processor, this._subDocument); } insertSectionBreak(position, type) { position = ApiParametersChecker.check(position, 1, false, [ ApiParametersChecker.numberDescriptor('position', (val) => val) ]); position = MathUtils.restrictValue(position, 0, this._subDocument.getDocumentEndPosition() - 1); const secStartType = ApiParametersChecker.check(type, 2, false, [ ApiParametersChecker.enumDescriptor('type', (val) => val, SectionBreakTypeApi, 'SectionBreakType') ]); const inputPos = new InputPositionBase().setIntervals(SelectionIntervalsInfo.fromPosition(this._subDocument, position)); this._processor.beginUpdate(); this._processor.modelManager.modelManipulator.section.insertSectionAndSetStartType(position, secStartType, inputPos.charPropsBundle); this._processor.endUpdate(); return new SectionApi(this._processor, this._processor.modelManager.model.getSectionByPosition(position + 1)); } insertPicture(position, base64, size, callback) { position = ApiParametersChecker.check(position, 1, false, [ ApiParametersChecker.numberDescriptor('position', (val) => val) ]); position = MathUtils.restrictValue(position, 0, this._subDocument.getDocumentEndPosition() - 1); base64 = ApiParametersChecker.check(base64, 2, false, [ ApiParametersChecker.stringDescriptor("base64", (s) => s, false) ]); size = ApiParametersChecker.check(size, 3, true, [ ApiParametersChecker.objectDescriptor('size', 'Size', (val) => val) ]); if (size) { ApiParametersChecker.check(size.width, 3, false, [ ApiParametersChecker.numberDescriptor('size.width', (val) => val, 1, Constants.MAX_SAFE_INTEGER) ]); ApiParametersChecker.check(size.height, 3, false, [ ApiParametersChecker.numberDescriptor('size.height', (val) => val, 1, Constants.MAX_SAFE_INTEGER) ]); } callback = ApiParametersChecker.check(callback, 4, true, [ ApiParametersChecker.functionDescriptor('callback', (val) => val) ]); if (!callback) callback = () => { }; const imageCache = this._processor.modelManager.model.cache.imageCache; const cacheInfo = imageCache.createUnloadedByBase64OrUrl(base64); const actualSize = size ? new Size(size.width, size.height) : undefined; const inputPos = new InputPositionBase().setIntervals(SelectionIntervalsInfo.fromPosition(this._subDocument, position)); this._processor.beginUpdate(); this._processor.modelManager.modelManipulator.picture.insertInlinePictureViaHistory(new SubDocumentPosition(this._subDocument, position), inputPos.charPropsBundle, InlinePictureInfo.defaultInfo(cacheInfo), ImageLoadingOptions.initByActualSize(actualSize, (picInterval, _cacheInfo) => callback(convertToIntervalApi(picInterval)))); this._processor.endUpdate(); } insertParagraph(position) { position = ApiParametersChecker.check(position, 1, false, [ ApiParametersChecker.numberDescriptor('position', (val) => val) ]); position = MathUtils.restrictValue(position, 0, this._subDocument.getDocumentEndPosition()); const inputPos = new InputPositionBase().setIntervals(SelectionIntervalsInfo.fromPosition(this._subDocument, position)); this._processor.beginUpdate(); this._processor.modelManager.modelManipulator.paragraph.insertParagraphViaHistory(new InsertParagraphManipulatorParams(new SubDocumentPosition(this._subDocument, position), inputPos.charPropsBundle, new MaskedParagraphPropertiesBundleFull(undefined, undefined, undefined, undefined), false)); this._processor.endUpdate(); return new ParagraphApi(this._processor, this._subDocument.getParagraphByPosition(position)); } insertHtml(position, htmlText, callback) { const positionDescriptor = ApiParametersChecker.numberDescriptor('position', (val) => val); const htmlTextDescriptor = ApiParametersChecker.stringDescriptor('htmlText', (s) => s, false); const callbackDescriptor = ApiParametersChecker.functionDescriptor('callback', (val) => val); position = ApiParametersChecker.check(position, 1, false, [positionDescriptor]); position = MathUtils.restrictValue(position, 0, this._subDocument.getDocumentEndPosition() - 1); htmlText = ApiParametersChecker.check(htmlText, 2, false, [htmlTextDescriptor]); callback = ApiParametersChecker.check(callback, 3, true, [callbackDescriptor]); if (!callback) callback = () => { }; const callBackWrap = (interval) => callback(isDefined(interval) ? convertToIntervalApi(interval) : null); insertHtmlInSubDocument(this._processor, this._subDocument, position, htmlText, callBackWrap); } getHtml(interval) { const coreInterval = this._checkInterval(interval); return getHtmlFromSubDocument(this._processor, this._subDocument, coreInterval); } insertRtf(position, rtfText, callback) { position = ApiParametersChecker.check(position, 1, false, [ ApiParametersChecker.numberDescriptor('position', (val) => val) ]); position = MathUtils.restrictValue(position, 0, this._subDocument.getDocumentEndPosition() - 1); rtfText = ApiParametersChecker.check(rtfText, 2, false, [ ApiParametersChecker.stringDescriptor("rtf", (s) => s, false) ]); callback = ApiParametersChecker.check(callback, 3, true, [ ApiParametersChecker.functionDescriptor('callback', (val) => val) ]); if (!callback) callback = () => { }; insertRtfInSubDocumentPublic(this._processor, this._subDocument, position, rtfText, (interval, isRtfValid) => callback(isDefined(interval) ? convertToIntervalApi(interval) : null, isRtfValid)); } getRtf(interval) { const coreInterval = this._checkInterval(interval); return getRtfFromSubDocumentPublic(this._processor.modelManager.richOptions, this._subDocument, coreInterval); } insertContent(position, content, documentFormat, callback) { position = ApiParametersChecker.check(position, 1, false, [ ApiParametersChecker.numberDescriptor('position', (val) => val) ]); position = MathUtils.restrictValue(position, 0, this._subDocument.getDocumentEndPosition() - 1); content = ApiParametersChecker.check(content, 2, false, [ ApiParametersChecker.stringDescriptor("contentAsBase64", (s) => s, false), ApiParametersChecker.objectDescriptor("contentAsFile", "File", (s) => s), ApiParametersChecker.objectDescriptor("contentAsBlob", "Blob", (s) => s), ApiParametersChecker.objectDescriptor("contentAsArrayBuffer", "ArrayBuffer", (s) => s), ]); const coreDocumentFormat = ApiParametersChecker.check(documentFormat, 3, false, [ ApiParametersChecker.enumDescriptor('documentFormat', (val) => val, DocumentFormat, 'DevExpress.RichEdit.DocumentFormat') ]); callback = ApiParametersChecker.check(callback, 4, true, [ ApiParametersChecker.functionDescriptor('callback', (val) => val) ]); if (!callback) callback = () => { }; insertContentInSubDocumentPublic(this._processor, this._subDocument, position, content, coreDocumentFormat, (interval, isRtfValid) => callback(convertToIntervalApi(interval), isRtfValid)); } deleteText(interval) { const coreInterval = this._checkInterval(interval); if (coreInterval.length) { this._processor.beginUpdate(); this._processor.modelManager.modelManipulator.range.removeInterval(new SubDocumentInterval(this._subDocument, coreInterval), true, false); this._processor.endUpdate(); } } getText(interval) { const coreInterval = this._checkInterval(interval); return this._subDocument.getText(coreInterval); } getCharacterProperties(interval) { const coreInterval = this._checkInterval(interval); return getCharacterProperties(this._processor, this._subDocument, coreInterval); } setCharacterProperties(interval, characterProperties) { const coreInterval = this._checkInterval(interval); setCharacterProperties(this._processor, this._subDocument, coreInterval, characterProperties); } getParagraphProperties(interval) { const coreInterval = this._checkInterval(interval); const inputPos = new InputPositionBase().setIntervals(new SelectionIntervalsInfo(this._subDocument, [coreInterval])); return convertToParagraphPropertiesApi(inputPos.getMergedParagraphPropertiesFull(), this._processor.modelManager.model.colorProvider); } setParagraphProperties(interval, paragraphProperties) { const coreInterval = this._checkInterval(interval); const propertiesCore = convertFromParagraphPropertiesApi(paragraphProperties, 2); const inputPos = new InputPositionBase().setIntervals(new SelectionIntervalsInfo(this._subDocument, [coreInterval])); this._processor.beginUpdate(); new ParagraphPropertiesApplier(this._processor.modelManager, inputPos, propertiesCore, this._subDocument, [coreInterval]).apply(); this._processor.endUpdate(); } _checkInterval(value, parameterIndex = 1) { if (!value) return this._subDocument.interval; const getResult = (interval) => getRestrictedInterval(interval, 0, this._subDocument.getDocumentEndPosition()); const intervalDescriptor = ModelParametersChecker.intervalDescriptor("interval", getResult); return ApiParametersChecker.check(value, parameterIndex, false, [intervalDescriptor]); } } function insertSpecialCharacter(position, text, processor, subDocument) { position = ApiParametersChecker.check(position, 1, false, [ ApiParametersChecker.numberDescriptor('position', (val) => val) ]); position = MathUtils.restrictValue(position, 0, subDocument.getDocumentEndPosition() - 1); const inputPos = new InputPositionBase().setIntervals(new SelectionIntervalsInfo(subDocument, [new FixedInterval(position, 0)])); const result = processor.modelManager.modelManipulator.text.insertTextViaHistory(new InsertTextManipulatorParams(new SubDocumentPosition(subDocument, position), inputPos.charPropsBundle, RunType.TextRun, text)); return convertToIntervalApi(result.insertedInterval); }