Skip to content

Commit

Permalink
Bump content model packages (#2312)
Browse files Browse the repository at this point in the history
* change image

* Content Model: Better hide cursor for table and image selection (#2270)

* Standalone Editor: CreateStandaloneEditorCore

* Standalone Editor: Port LifecyclePlugin

* fix build

* fix test

* improve

* fix test

* Standalone Editor: Support keyboard input (init step)

* Standalone Editor: Port EntityPlugin

* improve

* Add test

* improve

* port selection api

* improve

* improve

* fix build

* fix build

* fix build

* improve

* Improve

* improve

* improve

* fix test

* improve

* add test

* remove unused code

* Standalone Editor: port ImageSelection plugin

* add test

* Standalone Editor: Port UndoPlugin

* improve

* Port undo api

* fix test

* improve

* improve

* fix build

* Improve

* Improve

* Improve

* fix build

* Improve

* Add test

* fix test

* Add undo/redo API

* Standalone Editor: Port event core API

* fix build

* fix build

* Standalone Editor: Port transformColor API

* Improve

* Content Model: Better hide cursor for table and image selection

* fix build

---------

Co-authored-by: Bryan Valverde U <bvalverde@microsoft.com>

* gif treatment

* Move Paste from publicApi to coreApi to leverage the same domToModelOptions #2275

* selection

* WIP

* fix mac image selection

* constant

* Standalone Editor: Port paste API step 1 (#2279)

* Standalone Editor: Port paste API step 2 (#2280)

* Standalone Editor: Port paste API step 1

* Standalone Editor: Port paste API step 2

* improve

* improve

* Table Fidelity improvement: Width Attribute and Cellpadding attribute (#2284)

* init

* add test

* update name of test

* adjust link selection

* Standalone Editor: Port paste API step 3 (#2281)

* Standalone Editor: Port paste API step 1

* Standalone Editor: Port paste API step 2

* Standalone Editor: Port paste API step 3

* improve

* improve

* Improve

* Improve

* Adjust Selection on Cut/Copy first table cell  (#2287)

* init

* fix

* address comments

* address additional scenario

* adjust space for underline

* adjust space for underline

* fix multiple blocks

* fixes

* Standalone Editor: Port paste API step 4 (#2282)

* Standalone Editor: Port paste API step 1

* Standalone Editor: Port paste API step 2

* Standalone Editor: Port paste API step 3

* Standalone Editor: Port paste API step 4

* improve

* improve

* fix test

* Standalone Editor: Decouple core package from roosterjs-editor-dom (#2283)

* Standalone Editor: Port paste API step 1

* Standalone Editor: Port paste API step 2

* Standalone Editor: Port paste API step 3

* Standalone Editor: Port paste API step 4

* Standalone Editor: Decouple core package from roosterjs-editor-dom

* Set Deprecated font color to black instead of undefined (#2290)

* init

* use jasmine anything

* Remove negative margins from Word (#2277)

* Remove negative margins from Word

* remove

* Standalone Editor step 1 (#2291)

* Fix GetFormatState not returning Font size after paste (#2299)

* init

* fix build

* Standalone Editor step 2 (#2292)

* keyboard input on mac

* fix test

* change isMac for isIME

* iscomposing

* Support rem unit (#2300)

* Support rem unit

* Use already existing case

* justify-content-api

* aligment list item

* add justify to map

* Content Model: Improve paste and sanitization behavior (#2304)

* Fix couple of issues in Word Desktop Paste (#2311)

* init

* fix build

* try fix build

* fix again

* Add a test

* Re-activate tested without model check

* Change borderLeft/Right to borderInlineStart/End (#2286)

* fix RTL border application

* fix table direction change

* add tests

* Update versions

---------

Co-authored-by: Júlia Roldi <juliaroldi@microsoft.com>
Co-authored-by: Jiuqing Song <jisong@microsoft.com>
Co-authored-by: Bryan Valverde U <bvalverde@microsoft.com>
Co-authored-by: Julia Roldi <87443959+juliaroldi@users.noreply.github.com>
Co-authored-by: Andres-CT98 <107568016+Andres-CT98@users.noreply.github.com>
  • Loading branch information
6 people authored Jan 6, 2024
1 parent b333ded commit 5d48fd9
Show file tree
Hide file tree
Showing 157 changed files with 10,451 additions and 3,247 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as React from 'react';
import { alignCenterButton } from './alignCenterButton';
import { alignJustifyButton } from './alignJustifyButton';
import { alignLeftButton } from './alignLeftButton';
import { alignRightButton } from './alignRightButton';
import { backgroundColorButton } from './backgroundColorButton';
Expand Down Expand Up @@ -83,6 +84,7 @@ const buttons = [
alignLeftButton,
alignCenterButton,
alignRightButton,
alignJustifyButton,
insertLinkButton,
removeLinkButton,
insertTableButton,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { isContentModelEditor } from 'roosterjs-content-model-editor';
import { RibbonButton } from 'roosterjs-react';
import { setAlignment } from 'roosterjs-content-model-api';

/**
* @internal
* "Align justify" button on the format ribbon
*/
export const alignJustifyButton: RibbonButton<'buttonNameAlignJustify'> = {
key: 'buttonNameAlignJustify',
unlocalizedText: 'Align justify',
iconName: 'AlignJustify',
onClick: editor => {
if (isContentModelEditor(editor)) {
setAlignment(editor, 'justify');
}
return true;
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import type {
} from 'roosterjs-content-model-types';

const ResultMap: Record<
'left' | 'center' | 'right',
Record<'ltr' | 'rtl', 'start' | 'center' | 'end'>
'left' | 'center' | 'right' | 'justify',
Record<'ltr' | 'rtl', 'start' | 'center' | 'end' | 'justify'>
> = {
left: {
ltr: 'start',
Expand All @@ -22,6 +22,10 @@ const ResultMap: Record<
ltr: 'end',
rtl: 'start',
},
justify: {
ltr: 'justify',
rtl: 'justify',
},
};

const TableAlignMap: Record<
Expand All @@ -47,7 +51,7 @@ const TableAlignMap: Record<
*/
export function setModelAlignment(
model: ContentModelDocument,
alignment: 'left' | 'center' | 'right'
alignment: 'left' | 'center' | 'right' | 'justify'
) {
const paragraphOrListItemOrTable = getOperationalBlocks<ContentModelListItem>(
model,
Expand All @@ -56,15 +60,21 @@ export function setModelAlignment(
);

paragraphOrListItemOrTable.forEach(({ block }) => {
const newAligment = ResultMap[alignment][block.format.direction == 'rtl' ? 'rtl' : 'ltr'];
if (block.blockType === 'Table') {
const newAlignment = ResultMap[alignment][block.format.direction == 'rtl' ? 'rtl' : 'ltr'];
if (block.blockType === 'Table' && alignment !== 'justify') {
alignTable(
block,
TableAlignMap[alignment][block.format.direction == 'rtl' ? 'rtl' : 'ltr']
);
} else if (block) {
if (block.blockType === 'BlockGroup' && block.blockGroupType === 'ListItem') {
block.blocks.forEach(b => {
const { format } = b;
format.textAlign = newAlignment;
});
}
const { format } = block;
format.textAlign = newAligment;
format.textAlign = newAlignment;
}
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import { findListItemsInSameThread } from '../list/findListItemsInSameThread';
import { getOperationalBlocks, isBlockGroupOfType } from 'roosterjs-content-model-core';
import {
applyTableFormat,
getOperationalBlocks,
isBlockGroupOfType,
updateTableCellMetadata,
} from 'roosterjs-content-model-core';
import type {
BorderFormat,
ContentModelBlock,
ContentModelBlockFormat,
ContentModelDocument,
ContentModelListItem,
Expand Down Expand Up @@ -30,14 +37,18 @@ export function setModelDirection(model: ContentModelDocument, direction: 'ltr'
item.blocks.forEach(block => internalSetDirection(block.format, direction));
});
} else if (block) {
internalSetDirection(block.format, direction);
internalSetDirection(block.format, direction, block);
}
});

return paragraphOrListItemOrTable.length > 0;
}

function internalSetDirection(format: ContentModelBlockFormat, direction: 'ltr' | 'rtl') {
function internalSetDirection(
format: ContentModelBlockFormat,
direction: 'ltr' | 'rtl',
block?: ContentModelBlock
) {
const wasRtl = format.direction == 'rtl';
const isRtl = direction == 'rtl';

Expand All @@ -46,20 +57,39 @@ function internalSetDirection(format: ContentModelBlockFormat, direction: 'ltr'

// Adjust margin when change direction
// TODO: make margin and padding direction-aware, like what we did for textAlign. So no need to adjust them here
// TODO: Do we also need to handle border here?
const marginLeft = format.marginLeft;
const paddingLeft = format.paddingLeft;

setProperty(format, 'marginLeft', format.marginRight);
setProperty(format, 'marginRight', marginLeft);
setProperty(format, 'paddingLeft', format.paddingRight);
setProperty(format, 'paddingRight', paddingLeft);

// If whole Table direction changed, flip cell side borders
if (block && block.blockType == 'Table') {
block.rows.forEach(row => {
row.cells.forEach(cell => {
// Optimise by skipping cells with unchanged borders
updateTableCellMetadata(cell, metadata => {
if (metadata?.borderOverride) {
const storeBorderLeft = cell.format.borderLeft;
setProperty(cell.format, 'borderLeft', cell.format.borderRight);
setProperty(cell.format, 'borderRight', storeBorderLeft);
}
return metadata;
});
});
});

// Apply changed borders
applyTableFormat(block, undefined /* newFormat */, true /* keepCellShade*/);
}
}
}

function setProperty(
format: MarginFormat & PaddingFormat,
key: keyof (MarginFormat & PaddingFormat),
format: MarginFormat & PaddingFormat & BorderFormat,
key: keyof (MarginFormat & PaddingFormat & BorderFormat),
value: string | undefined
) {
if (value) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { parseValueWithUnit } from 'roosterjs-content-model-dom';
import {
extractBorderValues,
getClosestAncestorBlockGroupIndex,
Expand Down Expand Up @@ -150,7 +151,13 @@ function retrieveSegmentFormat(
mergeValue(result, 'letterSpacing', mergedFormat.letterSpacing, isFirst);

mergeValue(result, 'fontName', mergedFormat.fontFamily, isFirst);
mergeValue(result, 'fontSize', mergedFormat.fontSize, isFirst);
mergeValue(
result,
'fontSize',
mergedFormat.fontSize,
isFirst,
val => parseValueWithUnit(val, undefined, 'pt') + 'pt'
);
mergeValue(result, 'backgroundColor', mergedFormat.backgroundColor, isFirst);
mergeValue(result, 'textColor', mergedFormat.textColor, isFirst);
mergeValue(result, 'fontWeight', mergedFormat.fontWeight, isFirst);
Expand Down Expand Up @@ -232,13 +239,14 @@ function mergeValue<K extends keyof ContentModelFormatState>(
format: ContentModelFormatState,
key: K,
newValue: ContentModelFormatState[K] | undefined,
isFirst: boolean
isFirst: boolean,
parseFn: (val: ContentModelFormatState[K]) => ContentModelFormatState[K] = val => val
) {
if (isFirst) {
if (newValue !== undefined) {
format[key] = newValue;
}
} else if (newValue !== format[key]) {
} else if (parseFn(newValue) !== parseFn(format[key])) {
delete format[key];
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { createText } from 'roosterjs-content-model-dom';
import { iterateSelections } from 'roosterjs-content-model-core';
import type {
ContentModelDocument,
ContentModelParagraph,
ContentModelText,
} from 'roosterjs-content-model-types';

/**
* If a format cannot be applied to be applied to a trailing space, split the trailing space into a separate segment
* @internal
*/
export function adjustTrailingSpaceSelection(model: ContentModelDocument) {
iterateSelections(model, (_, __, block, segments) => {
if (block?.blockType === 'Paragraph' && segments && segments.length > 0) {
if (
segments.length === 1 &&
segments[0].segmentType === 'Text' &&
shouldSplitTrailingSpace(segments[0])
) {
splitTextSegment(block, segments[0]);
} else {
const lastTextSegment =
segments[segments.length - 1].segmentType === 'SelectionMarker'
? segments[segments.length - 2]
: segments[segments.length - 1];
if (
lastTextSegment &&
lastTextSegment.segmentType === 'Text' &&
shouldSplitTrailingSpace(lastTextSegment)
) {
splitTextSegment(block, lastTextSegment);
}
}
}

return false;
});
}

function shouldSplitTrailingSpace(segment: ContentModelText) {
return segment.isSelected && hasTrailingSpace(segment.text) && !isTrailingSpace(segment.text);
}

function hasTrailingSpace(text: string) {
return text.trimRight() !== text;
}

function isTrailingSpace(text: string) {
return text.trimRight().length == 0;
}

function splitTextSegment(block: ContentModelParagraph, textSegment: Readonly<ContentModelText>) {
const text = textSegment.text.trimRight();
const trailingSpace = textSegment.text.substring(text.length);
const newText = createText(text, textSegment.format, textSegment.link, textSegment.code);
newText.isSelected = true;
const trailingSpaceLink = textSegment.link
? {
...textSegment.link,
format: {
...textSegment.link?.format,
underline: false, // Remove underline for trailing space link
},
}
: undefined;
const trailingSpaceSegment = createText(
trailingSpace,
undefined,
trailingSpaceLink,
textSegment.code
);
trailingSpaceSegment.isSelected = true;
const index = block.segments.indexOf(textSegment);
block.segments.splice(index, 1, newText, trailingSpaceSegment);
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import type { IStandaloneEditor } from 'roosterjs-content-model-types';
*/
export default function setAlignment(
editor: IStandaloneEditor,
alignment: 'left' | 'center' | 'right'
alignment: 'left' | 'center' | 'right' | 'justify'
) {
editor.focus();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { adjustTrailingSpaceSelection } from '../../modelApi/selection/adjustTrailingSpaceSelection';
import { ChangeSource, getSelectedSegments, mergeModel } from 'roosterjs-content-model-core';
import { HtmlSanitizer, matchLink } from 'roosterjs-editor-dom';
import type { ContentModelLink, IStandaloneEditor } from 'roosterjs-content-model-types';
Expand Down Expand Up @@ -91,6 +92,7 @@ export default function insertLink(
});
}

adjustTrailingSpaceSelection(model);
return segments.length > 0;
},
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { adjustTrailingSpaceSelection } from '../../modelApi/selection/adjustTrailingSpaceSelection';
import { formatSegmentWithContentModel } from '../utils/formatSegmentWithContentModel';
import type { IStandaloneEditor } from 'roosterjs-content-model-types';

Expand All @@ -18,6 +19,8 @@ export default function toggleUnderline(editor: IStandaloneEditor) {
segment.link.format.underline = !!isTurningOn;
}
},
(format, segment) => !!format.underline || !!segment?.link?.format?.underline
(format, segment) => !!format.underline || !!segment?.link?.format?.underline,
false /*includingFormatHolder*/,
adjustTrailingSpaceSelection
);
}
Loading

0 comments on commit 5d48fd9

Please sign in to comment.