devexpress-richedit
Version:
DevExpress Rich Text Editor is an advanced word-processing tool designed for working with rich text documents.
721 lines (720 loc) • 42.4 kB
JavaScript
import { UnitConverter } from '@devexpress/utils/lib/class/unit-converter';
import { FixedInterval } from '@devexpress/utils/lib/intervals/fixed';
import { ColorUtils } from '@devexpress/utils/lib/utils/color';
import { EncodeUtils } from '@devexpress/utils/lib/utils/encode';
import { SearchUtils } from '@devexpress/utils/lib/utils/search';
import { StringUtils } from '@devexpress/utils/lib/utils/string';
import { RichEditUnit } from '../../../utils/unit-converter';
import { LayoutPictureBox } from '../../../layout/main-structures/layout-boxes/layout-picture-box';
import { BorderLineStyle } from '../../../model/borders/enums';
import { CharacterProperties } from '../../../model/character/character-properties';
import { CharacterFormattingScript, UnderlineType } from '../../../model/character/enums';
import { ColorHelper } from '../../../model/color/color';
import { Field } from '../../../model/fields/field';
import { NumberingFormat } from '../../../model/numbering-lists/list-level-properties';
import { NumberingType } from '../../../model/numbering-lists/numbering-list';
import { ParagraphAlignment, ParagraphFirstLineIndent, ParagraphLineSpacingType, } from '../../../model/paragraph/paragraph-properties';
import { RichUtils } from '../../../model/rich-utils';
import { RunType } from '../../../model/runs/run-type';
import { Table } from '../../../model/tables/main-structures/table';
import { TableCellPropertiesMergerShadingInfo, TableCellVerticalAlignmentMerger, } from '../../../model/tables/properties-mergers/table-cell-properties-merger';
import { TablePropertiesMergerBorderHorizontal, TablePropertiesMergerBorderVertical, TablePropertiesMergerCellSpacing, TablePropertiesMergerIndent, } from '../../../model/tables/properties-mergers/table-properties-merger';
import { ConditionalTableStyleFormatting, TableCellMergingState, TableCellVerticalAlignment, } from '../../../model/tables/secondary-structures/table-base-structures';
import { TableWidthUnitType } from '../../../model/tables/secondary-structures/table-units';
import { HtmlConverter } from '../../../rich-utils/html-converter';
import { HtmlBuilder } from './html-builder';
import { isDefined } from '@devexpress/utils/lib/utils/common';
import { createUrlValidationOptions, UrlUtils } from '../../../../common/utils/utils';
import { ListUtils } from '@devexpress/utils/lib/utils/list';
export class HtmlExporter {
get modelManager() { return this.exportModelOptions.modelManager; }
get colorProvider() { return this.modelManager.model.colorProvider; }
get unitConverter() { return this.exportModelOptions.uiUnitConverter; }
get documentRenderer() { return this.exportModelOptions.pictureRenderer; }
get lastMaxNumPages() { return this.exportModelOptions.lastMaxNumPages; }
;
get pageIndex() { return this.exportModelOptions.pageIndex; }
;
constructor(exportModelOptions, htmlExporterOptions = null) {
this.rangeCopy = null;
this.exportModelOptions = exportModelOptions;
this.htmlExporterOptions = htmlExporterOptions;
}
getHtmlElementsByInterval(model, subDocument, interval, guidLabel) {
var _a, _b, _c, _d;
if (interval.length === 0)
return;
const unitTypeToString = this.unitConverter.getUnits() == RichEditUnit.Centimeter ? "cm" : "in";
const iterator = subDocument.getConstRunIterator(interval);
let remainLength = interval.length;
let currentPosition = interval.start;
let resultBuilder = new HtmlBuilder();
const paragraphs = this.getParagraphsByInterval(subDocument, interval);
const lists = this.getListsByParagraphs(paragraphs);
let isInsideFieldCode = false;
let fieldDeep = 0;
let isInsideHyperlink = false;
let hyperlinkInfo = null;
let hyperlinkInnerHtml = new HtmlBuilder();
let hasFields = false;
while (iterator.moveNext()) {
const tableCell = Table.getTableCellByPosition(subDocument.tables, iterator.currentInterval().start);
const isContinueMergingCell = tableCell && tableCell.verticalMerging === TableCellMergingState.Continue;
const run = iterator.currentRun;
const isRunInEmptyParagraph = run.paragraph.length === 1;
if (paragraphs.length && (run.getType() != RunType.ParagraphRun || isRunInEmptyParagraph)) {
const paragraphToStartIndex = SearchUtils.normedInterpolationIndexOf(paragraphs, (p) => p.startLogPosition.value, currentPosition);
if (paragraphToStartIndex > -1) {
const currentParagraph = paragraphs[paragraphToStartIndex];
paragraphs.splice(paragraphToStartIndex, 1);
if (tableCell) {
const row = tableCell.parentRow;
const table = row.parentTable;
const paragraphStartPosition = currentParagraph.startLogPosition.value;
if (table.getStartPosition() == paragraphStartPosition) {
if (table.parentCell)
this.addParentTableRecursively(model, resultBuilder, table.parentCell, paragraphStartPosition);
resultBuilder
.startChild('table')
.configure((el) => {
el.style.cssText = this.getTableStyle(model, table);
})
.startChild('tbody');
}
if (row.getStartPosition() == paragraphStartPosition) {
resultBuilder.startChild('tr');
if (row.gridBefore > 0) {
resultBuilder
.startChild('td')
.configure((el) => {
el.style.cssText = "mso-cell-special:placeholder";
el.setAttribute('colspan', row.gridBefore.toString());
el.innerHTML = " ";
})
.endChild('td');
}
}
if (tableCell.startParagraphPosition.value == paragraphStartPosition && !isContinueMergingCell) {
let rowSpan = 1;
if (tableCell.verticalMerging === TableCellMergingState.Restart) {
let rowIndex = table.rows.indexOf(row);
let cellIndex = row.cells.indexOf(tableCell);
for (let i = rowIndex + 1, row; row = table.rows[i]; i++) {
let nextRowCellIndex = cellIndex;
if (row.cells.length != row.cells.length) {
let extraCellsCount = 0;
let isNextRowLonger = row.cells.length > row.cells.length;
let shorterRow = isNextRowLonger ? row : row;
for (let j = 0; (j < cellIndex) && (j < shorterRow.cells.length); j++) {
extraCellsCount += shorterRow.cells[j].columnSpan - 1;
if (!isNextRowLonger)
extraCellsCount -= row.cells[j].columnSpan - 1;
}
nextRowCellIndex += (isNextRowLonger ? 1 : -1) * extraCellsCount;
}
let nextRowCell = row.cells[nextRowCellIndex];
if (nextRowCell && nextRowCell.verticalMerging === TableCellMergingState.Continue)
rowSpan++;
else
break;
}
}
resultBuilder
.startChild('td')
.configure((el) => {
el.style.cssText = this.getCellStyle(model, tableCell);
if (rowSpan > 1)
el.setAttribute('rowspan', rowSpan.toString());
if (tableCell.columnSpan > 1)
el.setAttribute('colspan', tableCell.columnSpan.toString());
});
}
}
this.startList(model, subDocument, interval, resultBuilder, lists, iterator.currentInterval().start);
if (!isContinueMergingCell) {
const maskedParagraphProperties = currentParagraph.getParagraphMergedProperties();
let paragraphStyle = "";
const firstLineIndentType = maskedParagraphProperties.firstLineIndentType;
if (firstLineIndentType != ParagraphFirstLineIndent.None) {
paragraphStyle += "text-indent: " + (firstLineIndentType == ParagraphFirstLineIndent.Hanging ? "-" : "") +
this.unitConverter.twipsToUI(maskedParagraphProperties.firstLineIndent) + unitTypeToString + ";";
}
if (maskedParagraphProperties.alignment !== undefined) {
paragraphStyle += "text-align: ";
switch (maskedParagraphProperties.alignment) {
case ParagraphAlignment.Left:
paragraphStyle += "left;";
break;
case ParagraphAlignment.Right:
paragraphStyle += "right;";
break;
case ParagraphAlignment.Justify:
case ParagraphAlignment.JustifyHigh:
case ParagraphAlignment.JustifyLow:
case ParagraphAlignment.JustifyMedium:
case ParagraphAlignment.Distribute:
case ParagraphAlignment.ThaiDistribute:
paragraphStyle += "justify;";
break;
case ParagraphAlignment.Center:
paragraphStyle += "center;";
break;
default:
break;
}
}
if (maskedParagraphProperties.lineSpacingType != ParagraphLineSpacingType.Single) {
const lineSpacingInUI = this.unitConverter.twipsToUI(maskedParagraphProperties.lineSpacing) + unitTypeToString + ";";
paragraphStyle += "line-height: ";
switch (maskedParagraphProperties.lineSpacingType) {
case ParagraphLineSpacingType.AtLeast:
paragraphStyle += lineSpacingInUI;
break;
case ParagraphLineSpacingType.Double:
paragraphStyle += "2;";
break;
case ParagraphLineSpacingType.Exactly:
paragraphStyle += lineSpacingInUI + "mso-line-height-rule: exactly;";
break;
case ParagraphLineSpacingType.Multiple:
paragraphStyle += maskedParagraphProperties.lineSpacing + ";";
break;
case ParagraphLineSpacingType.Sesquialteral:
paragraphStyle += "1.5;";
break;
default:
break;
}
}
if (ColorUtils.getAlpha(maskedParagraphProperties.shadingInfo.getActualColor(this.colorProvider)) > 0)
paragraphStyle += "background: " + ColorHelper.getCssStringInternal(maskedParagraphProperties.shadingInfo.getActualColor(this.colorProvider)) + ";";
if (maskedParagraphProperties.leftIndent)
paragraphStyle += "margin-left: " + this.unitConverter.twipsToUI(maskedParagraphProperties.leftIndent) + unitTypeToString + ";";
if (maskedParagraphProperties.rightIndent)
paragraphStyle += "margin-right: " + this.unitConverter.twipsToUI(maskedParagraphProperties.rightIndent) + unitTypeToString + ";";
paragraphStyle += "margin-top: " + this.unitConverter.twipsToUI(maskedParagraphProperties.spacingBefore) + unitTypeToString + ";";
paragraphStyle += "margin-bottom: " + this.unitConverter.twipsToUI(maskedParagraphProperties.spacingAfter) + unitTypeToString + ";";
const topBorderStyle = this.getBorderCssString(maskedParagraphProperties.topBorder);
if (topBorderStyle)
paragraphStyle += "border-top:" + topBorderStyle + ";";
const leftBorderStyle = this.getBorderCssString(maskedParagraphProperties.leftBorder);
if (leftBorderStyle)
paragraphStyle += "border-left:" + leftBorderStyle + ";";
const bottomBorderStyle = this.getBorderCssString(maskedParagraphProperties.bottomBorder);
if (bottomBorderStyle)
paragraphStyle += "border-bottom:" + bottomBorderStyle + ";";
const rightBorderStyle = this.getBorderCssString(maskedParagraphProperties.rightBorder);
if (rightBorderStyle)
paragraphStyle += "border-right:" + rightBorderStyle + ";";
if (isRunInEmptyParagraph) {
const charProps = run.getCharacterMergedProperties();
paragraphStyle += HtmlConverter.getCssRules(charProps, charProps.textColor.toRgb(this.colorProvider), false, false, false)
.join(";");
}
if (currentParagraph.isInList())
resultBuilder.startChild('li');
resultBuilder
.startChild('p')
.configure((e) => {
if (paragraphStyle)
e.style.cssText = paragraphStyle;
if (isRunInEmptyParagraph)
e.innerHTML = " ";
});
}
}
}
let html = new HtmlBuilder();
let innerHtml = new HtmlBuilder();
const length = Math.min(remainLength, iterator.currentInterval().length);
switch (run.getType()) {
case RunType.ParagraphRun:
if (!isContinueMergingCell) {
html.addCallback((builder) => builder.endChild('p'));
if (run.paragraph.isInList()) {
html.addCallback((builder) => builder.endChild('li'));
html.addCallback((builder) => this.endList(model, builder, lists, iterator.currentInterval().end));
}
let paragraphEndPosition = run.paragraph.getEndPosition();
if (tableCell) {
let parentRow = tableCell.parentRow;
let parentTable = parentRow.parentTable;
if (tableCell.endParagrapPosition.value == paragraphEndPosition)
html.addCallback((builder) => builder.endChild('td'));
if (parentRow.getEndPosition() == paragraphEndPosition) {
if (parentRow.gridAfter > 0)
html.addCallback((builder) => {
builder
.addElement('td')
.configure((el) => {
el.style.cssText = "mso-cell-special:placeholder";
el.setAttribute('colspan', parentRow.gridAfter.toString());
el.innerHTML = " ";
})
.endChild('td');
});
html.addCallback((builder) => {
builder.endChild('tr');
});
}
if (parentTable.getEndPosition() == paragraphEndPosition)
html.addCallback((builder) => {
builder
.endChild('tbody')
.endChild('table');
});
}
}
break;
case RunType.InlinePictureRun:
case RunType.AnchoredPictureRun: {
const picRun = run;
const charMergProps = run.getCharacterMergedProperties();
const pictureBox = new LayoutPictureBox(charMergProps, charMergProps.getLayoutColorInfo(this.colorProvider), picRun.cacheInfo, picRun.getActualSize().applyConverter(UnitConverter.twipsToPixels), picRun.info.nonVisualDrawingProperties.description);
const { cacheInfo, hyperlinkTip, description } = pictureBox;
innerHtml
.clear()
.addElement(this.documentRenderer.renderPictureBoxContent(pictureBox.createSize(), cacheInfo, hyperlinkTip, description));
break;
}
case RunType.InlineTextBoxRun:
case RunType.AnchoredTextBoxRun: {
let textBoxRun = run;
let internalSubDocument = model.subDocuments[textBoxRun.subDocId];
innerHtml
.clear()
.startChild('table')
.configure((el) => {
el.setAttribute('border', '1');
el.style.cssText = 'border-width: 0px; border-collapse: collapse; border-spacing: 0px;';
el.setAttribute('id', guidLabel.replace("id=\"", "").replace("\"", ""));
})
.startChild('tbody')
.startChild('tr')
.startChild('td')
.configure((el) => {
el.style.cssText = this.getTextBoxStyleString(textBoxRun);
})
.assignFrom(this.getHtmlElementsByInterval(model, internalSubDocument, new FixedInterval(0, internalSubDocument.getDocumentEndPosition()), guidLabel))
.endChild('td')
.endChild('tr')
.endChild('tbody')
.endChild('table');
break;
}
case RunType.FieldCodeStartRun:
isInsideFieldCode = true;
const fieldIndex = Field.normedBinaryIndexOf(subDocument.fields, currentPosition + 1);
const field = subDocument.fields[fieldIndex];
if (field.isHyperlinkField()) {
hyperlinkInfo = field.getHyperlinkInfo();
isInsideHyperlink = true;
}
fieldDeep++;
break;
case RunType.FieldCodeEndRun:
isInsideFieldCode = false;
break;
case RunType.FieldResultEndRun:
fieldDeep--;
if (!fieldDeep)
isInsideHyperlink = false;
hasFields = true;
break;
case RunType.LayoutDependentRun:
let currentField = subDocument.fields[Field.normedBinaryIndexOf(subDocument.fields, currentPosition)];
if (currentField) {
let codeText = StringUtils.trim(subDocument.getText(currentField.getCodeInterval()).split("\\")[0]).toUpperCase();
if (codeText == "NUMPAGES" && isDefined(this.lastMaxNumPages))
innerHtml
.clear()
.addElement(this.lastMaxNumPages.toString());
else if (codeText == "PAGE" && isDefined(this.pageIndex))
innerHtml
.clear()
.addElement((this.pageIndex + 1).toString());
}
break;
default:
if (!isInsideFieldCode)
innerHtml = this.getHtmlText(subDocument.getText(new FixedInterval(currentPosition, length)));
break;
}
if (hyperlinkInfo && !isInsideHyperlink) {
const sanitaizeHyperlinkURIs = (_b = (_a = this.htmlExporterOptions) === null || _a === void 0 ? void 0 : _a.sanitaizeHyperlinkURIs) !== null && _b !== void 0 ? _b : false;
const convertRelativeURIsToAbsolute = (_d = (_c = this.htmlExporterOptions) === null || _c === void 0 ? void 0 : _c.convertRelativeURIsToAbsolute) !== null && _d !== void 0 ? _d : false;
let url = hyperlinkInfo.uri;
const options = createUrlValidationOptions(this.exportModelOptions.modelManager);
if (!sanitaizeHyperlinkURIs || UrlUtils.isValid(url, options)) {
if (convertRelativeURIsToAbsolute && UrlUtils.isRelative(url))
url = UrlUtils.convertToAbsolute(url).href;
if (hyperlinkInfo.anchor != "")
url = url + "#" + hyperlinkInfo.anchor;
}
else
url = UrlUtils.EmptyPage;
const tooltip = hyperlinkInfo.tip;
html
.clear()
.startChild('a')
.configure((el) => {
el.setAttribute('href', url);
if (tooltip)
el.setAttribute('title', tooltip);
})
.assignFrom(hyperlinkInnerHtml)
.endChild('a');
hyperlinkInfo = null;
hyperlinkInnerHtml.clear();
}
if (html.isEmpty() && !innerHtml.isEmpty()) {
const characterProperties = run.getCharacterMergedProperties();
const boxStyle = HtmlConverter.getCssRules(characterProperties, characterProperties.textColor.toRgb(this.colorProvider), run.getType() == RunType.TextRun, false, false).
join(";");
html
.startChild('span')
.configure((el) => {
el.style.cssText = boxStyle;
})
.assignFrom(innerHtml)
.endChild('span');
if (hyperlinkInfo) {
if (isInsideHyperlink) {
hyperlinkInnerHtml.assignFrom(html);
html.clear();
}
}
else {
if (characterProperties.fontUnderlineType != UnderlineType.None && !characterProperties.underlineWordsOnly) {
const underlineColor = characterProperties.underlineColor.toRgb(this.colorProvider);
const cssColorValue = (underlineColor != ColorHelper.AUTOMATIC_COLOR) ? ColorHelper.getCssStringInternal(underlineColor) : "initial";
const builder = new HtmlBuilder();
builder
.startChild('span')
.configure((el) => {
el.style.cssText = "text-decoration: underline; color: " + cssColorValue;
})
.assignFrom(html)
.endChild('span');
html = builder;
}
if (characterProperties.script !== CharacterFormattingScript.Normal) {
const builder = new HtmlBuilder();
builder
.startChild('span')
.configure((el) => {
el.style.cssText = "font-size: " + characterProperties.fontSize + "px;";
})
.assignFrom(html)
.endChild('span');
html = builder;
}
if (ColorUtils.getAlpha(CharacterProperties.getActualBackgroundColor(characterProperties, this.colorProvider)) > 0) {
const builder = new HtmlBuilder();
builder
.startChild('span')
.configure((el) => {
el.style.cssText = "background: " + ColorHelper.getCssStringInternal(CharacterProperties.getActualBackgroundColor(characterProperties, this.colorProvider));
})
.assignFrom(html)
.endChild('span');
html = builder;
}
}
}
resultBuilder.assignFrom(html);
currentPosition += length;
remainLength -= length;
}
if (/^<td[^>]*>/gi.test(resultBuilder.getHtmlString())) {
const builder = new HtmlBuilder();
builder.startChild('tr');
builder.assignFrom(resultBuilder);
resultBuilder = builder;
}
if (/<\/td>$/gi.test(resultBuilder.getHtmlString()))
resultBuilder.endChild("tr");
if (/^<tr[^>]*>/gi.test(resultBuilder.getHtmlString())) {
const builder = new HtmlBuilder();
builder
.startChild('table')
.configure((el) => {
el.style.cssText = this.getTableStyle(model, null);
})
.startChild('tbody')
.assignFrom(resultBuilder);
resultBuilder = builder;
}
if (/<\/tr>$/gi.test(resultBuilder.getHtmlString()))
resultBuilder
.endChild('tbody')
.endChild('table');
if (hasFields && resultBuilder.isEmpty())
resultBuilder
.startChild('span')
.configure((el) => {
el.classList.add('field-mark');
el.innerHTML = " ";
})
.endChild('span');
return resultBuilder;
}
getParagraphsByInterval(subDocument, interval) {
const paragraphsInInterval = subDocument.getParagraphsByInterval(interval);
const paragraphs = [];
for (let i = 0, paragraphInInterval; paragraphInInterval = paragraphsInInterval[i]; i++) {
if (interval.containsWithIntervalEnd(paragraphInInterval.getEndPosition()))
paragraphs.push(paragraphInInterval);
}
return paragraphs;
}
getListsByParagraphs(paragraphs) {
const listsInInterval = [];
let previousList = null;
for (let i = 0, paragraph; paragraph = paragraphs[i]; i++) {
if (paragraph.isInList()) {
const numberingListIndex = paragraph.getNumberingListIndex();
const listLevelIndex = paragraph.getListLevelIndex();
const start = paragraph.startLogPosition.value;
const end = paragraph.getEndPosition();
let list = ListUtils.reverseElementBy(listsInInterval, (list) => {
return list.listLevelIndex <= (previousList === null || previousList === void 0 ? void 0 : previousList.listLevelIndex)
&& list.numberingListIndex === numberingListIndex
&& list.listLevelIndex === listLevelIndex;
});
if (!list) {
const parentList = (previousList === null || previousList === void 0 ? void 0 : previousList.numberingListIndex) === numberingListIndex ? previousList : null;
list = { parentList, numberingListIndex, listLevelIndex, start, end };
listsInInterval.push(list);
}
previousList = list;
do {
list.end = end;
} while (list = list.parentList);
}
}
return listsInInterval;
}
addParentTableRecursively(model, builder, parentCell, paragraphStartPosition) {
const parentRow = parentCell.parentRow;
const parentTable = parentRow.parentTable;
if (parentTable.parentCell)
this.addParentTableRecursively(model, builder, parentTable.parentCell, paragraphStartPosition);
if (parentTable.getStartPosition() === paragraphStartPosition) {
builder
.startChild('table')
.configure(e => e.style.cssText = this.getTableStyle(model, parentTable))
.startChild('tbody');
}
if (parentRow.getStartPosition() === paragraphStartPosition) {
builder.startChild('tr');
if (parentRow.gridBefore > 0) {
builder
.startChild('td')
.configure(el => {
el.style.cssText = 'mso-cell-special:placeholder';
el.setAttribute('colspan', parentRow.gridBefore.toString());
el.innerHTML = ' ';
})
.endChild('td');
}
}
if (parentCell.startParagraphPosition.value === paragraphStartPosition) {
builder
.startChild('td')
.configure((el) => {
el.style.cssText = this.getCellStyle(model, parentCell);
if (parentCell.columnSpan > 1)
el.setAttribute('colspan', parentCell.columnSpan.toString());
});
}
}
startList(model, subDocument, interval, builder, lists, position) {
if (!lists.length)
return;
let listIndex = lists.findIndex((list) => list.start === position);
if (listIndex < 0 && position === interval.start) {
const firstParagraph = subDocument.getParagraphByPosition(position);
if (firstParagraph.getNumberingListIndex() === lists[0].numberingListIndex)
listIndex = 0;
}
if (listIndex > -1) {
const numberingList = model.numberingLists[lists[listIndex].numberingListIndex];
const numberingListFormat = numberingList.levels[lists[listIndex].listLevelIndex].getListLevelProperties().format;
const numberingListType = numberingList.getListType();
let listFormatType = "";
switch (numberingListFormat) {
case NumberingFormat.Bullet:
listFormatType = "disc";
break;
case NumberingFormat.Decimal:
listFormatType = "decimal";
break;
case NumberingFormat.LowerLetter:
listFormatType = "lower-alpha";
break;
case NumberingFormat.UpperLetter:
listFormatType = "upper-alpha";
break;
case NumberingFormat.LowerRoman:
listFormatType = "lower-roman";
break;
case NumberingFormat.UpperRoman:
listFormatType = "upper-roman";
break;
default:
break;
}
builder
.startChild(numberingListType !== NumberingType.Bullet ? "ol" : "ul")
.configure((e) => e.style.cssText = "list-style-type:" + listFormatType);
}
}
endList(model, builder, lists, endPosition) {
for (let i = lists.length - 1; i >= 0; i--) {
if (lists[i].end === endPosition) {
const listType = model.numberingLists[lists[i].numberingListIndex].getListType();
lists.splice(i, 1);
builder.endChild(listType != NumberingType.Bullet ? "ol" : "ul");
}
}
}
getHtmlText(text) {
const result = new HtmlBuilder();
for (let i = 0; i < text.length; i++) {
const char = text.charAt(i);
switch (char) {
case RichUtils.specialCharacters.PageBreak:
case RichUtils.specialCharacters.ColumnBreak:
case RichUtils.specialCharacters.SectionMark:
result.addCallback((builder) => builder.addBreak("break-before:always"));
break;
case RichUtils.specialCharacters.LineBreak:
result.addCallback((builder) => builder.addBreak());
break;
default:
result.addCallback((builder) => {
builder.configure((el) => el.innerHTML += EncodeUtils.encodeHtml(text.substring(i)));
});
return result;
}
}
return result;
}
getBorderCssString(borderInfo) {
let borderStyle = "";
if (borderInfo) {
if (borderInfo.width)
borderStyle += " " + UnitConverter.twipsToPixels(borderInfo.width) + "px";
switch (borderInfo.style) {
case BorderLineStyle.Dashed:
borderStyle += " dashed";
break;
case BorderLineStyle.Dotted:
borderStyle += " dotted";
break;
case BorderLineStyle.Double:
borderStyle += " double";
break;
case BorderLineStyle.Inset:
borderStyle += " inset";
break;
case BorderLineStyle.None:
borderStyle += " none";
break;
case BorderLineStyle.Outset:
borderStyle += " outset";
break;
case BorderLineStyle.Single:
borderStyle += " solid";
default:
break;
}
const rgba = this.colorProvider.getRgbaFromModelColor(borderInfo.color);
if (ColorUtils.getAlpha(rgba) > 0)
borderStyle += " " + ColorHelper.getCssStringInternal(rgba);
}
return borderStyle;
}
getTableWidthUnitCssString(width) {
return width.type == TableWidthUnitType.FiftiethsOfPercent ? width.value / 50 + "%" : UnitConverter.twipsToPoints(width.value) + "pt";
}
getTableStyle(model, table) {
let defaultTableProperties = model.defaultTableProperties;
let tableProperties = table ? table.properties : defaultTableProperties;
let style = table ? table.style : model.getDefaultTableStyle();
let tableStyle = "";
let tableIndent = new TablePropertiesMergerIndent().getProperty(tableProperties, style, ConditionalTableStyleFormatting.WholeTable, defaultTableProperties);
if (tableIndent.value)
tableStyle += "margin-left:" + this.getTableWidthUnitCssString(tableIndent) + ";";
let cellSpacing = new TablePropertiesMergerCellSpacing().getProperty(tableProperties, style, ConditionalTableStyleFormatting.WholeTable, defaultTableProperties);
tableStyle += (cellSpacing.value ? "border-spacing:" + this.getTableWidthUnitCssString(cellSpacing) : "border-collapse: collapse") + ";";
return tableStyle;
}
getCellStyle(model, cell) {
let cellProperties = cell.properties;
let defaultTableProperties = model.defaultTableProperties;
let defaultCellProperties = model.defaultTableCellProperties;
let parentTable = cell.parentRow.parentTable;
let tableStyle = parentTable.style;
let tableHorizontalBorderStyle = this.getBorderCssString((new TablePropertiesMergerBorderHorizontal())
.getProperty(parentTable.properties, tableStyle, ConditionalTableStyleFormatting.WholeTable, defaultTableProperties));
let tableVerticalBorderStyle = this.getBorderCssString((new TablePropertiesMergerBorderVertical())
.getProperty(parentTable.properties, tableStyle, ConditionalTableStyleFormatting.WholeTable, defaultTableProperties));
let cellStyle = "";
let topBorderStyle = this.getBorderCssString(cell.getActualTopCellBorder(defaultCellProperties)) || tableVerticalBorderStyle;
if (topBorderStyle)
cellStyle += "border-top:" + topBorderStyle + ";";
let leftBorderStyle = this.getBorderCssString(cell.getActualLeftCellBorder(defaultCellProperties)) || tableHorizontalBorderStyle;
if (leftBorderStyle)
cellStyle += "border-left:" + leftBorderStyle + ";";
let bottomBorderStyle = this.getBorderCssString(cell.getActualBottomCellBorder(defaultCellProperties)) || tableVerticalBorderStyle;
if (bottomBorderStyle)
cellStyle += "border-bottom:" + bottomBorderStyle + ";";
let rightBorderStyle = this.getBorderCssString(cell.getActualRightCellBorder(defaultCellProperties)) || tableHorizontalBorderStyle;
if (rightBorderStyle)
cellStyle += "border-right:" + rightBorderStyle + ";";
let marginLeft = cell.getActualLeftCellMargin(model);
if (marginLeft.value)
cellStyle += "padding-left:" + this.getTableWidthUnitCssString(marginLeft) + ";";
let marginTop = cell.getActualTopCellMargin(model);
if (marginTop.value)
cellStyle += "padding-top:" + this.getTableWidthUnitCssString(marginTop) + ";";
let marginRight = cell.getActualRightCellMargin(model);
if (marginRight.value)
cellStyle += "padding-right:" + this.getTableWidthUnitCssString(marginRight) + ";";
let marginBottom = cell.getActualBottomCellMargin(model);
if (marginBottom.value)
cellStyle += "padding-bottom:" + this.getTableWidthUnitCssString(marginBottom) + ";";
let verticalAlignment = new TableCellVerticalAlignmentMerger().getProperty(cellProperties, tableStyle, cell.conditionalFormatting, defaultCellProperties);
switch (verticalAlignment) {
case TableCellVerticalAlignment.Bottom:
cellStyle += "vertical-align:bottom;";
break;
case TableCellVerticalAlignment.Center:
cellStyle += "vertical-align:middle;";
break;
case TableCellVerticalAlignment.Top:
cellStyle += "vertical-align:top;";
break;
default:
break;
}
let cellBackground = new TableCellPropertiesMergerShadingInfo().getProperty(cellProperties, tableStyle, cell.conditionalFormatting, defaultCellProperties)
.getActualColor(this.colorProvider);
if (ColorUtils.getAlpha(cellBackground) > 0)
cellStyle += "background: " + ColorHelper.getCssStringInternal(cellBackground) + ";";
cellStyle += "width: " + UnitConverter.twipsToPixels(cell.preferredWidth.value) + "px;";
return cellStyle;
}
getTextBoxStyleString(textBoxRun) {
let contentMargins = textBoxRun.textBoxProperties.getContentMargins();
let result = "padding-top:" + UnitConverter.twipsToPixels(contentMargins.top) + "px;";
result += "padding-bottom:" + UnitConverter.twipsToPixels(contentMargins.bottom) + "px;";
result += "padding-left:" + UnitConverter.twipsToPixels(contentMargins.left) + "px;";
result += "padding-right:" + UnitConverter.twipsToPixels(contentMargins.right) + "px;";
result += "border:" + UnitConverter.twipsToPixels(textBoxRun.shape.outlineWidth) + "px solid " + ColorHelper.getCssString(textBoxRun.shape.outlineColor, true) + ";";
result += "background-color:" + ColorHelper.getCssString(textBoxRun.shape.fillColor, true) + ";";
return result;
}
}