Skip to content

Commit

Permalink
Bump release to 8.33.2 (#1333)
Browse files Browse the repository at this point in the history
* Content Model List step 5: Add model format API (#1298)

* Content Model: improve demo

* add more fix

* Refactor create content model interfaces

* Remove duplicated TableCellMetadataFormat

* Add List types and views

* Add format handlers for list

* Add list processors and test

* Add handlers for list

* fix test

* fix test

* bug fix

* remove unnecessary change

* improve

* merge and fix

* Content Model List step 5: Add model format API

* Content Model List step 6: Public API (#1299)

* Content Model: improve demo

* add more fix

* Refactor create content model interfaces

* Remove duplicated TableCellMetadataFormat

* Add List types and views

* Add format handlers for list

* Add list processors and test

* Add handlers for list

* fix test

* fix test

* bug fix

* remove unnecessary change

* improve

* merge and fix

* Content Model List step 5: Add model format API

* Content Model List step 6: Public API

* Content Model Table bug fixes (#1305)

* Content Model Table bug fixes

* fix test

* Content Model List: Support "type" attribute of OL element (#1307)

* Content Model List: support "type" property of OL

* fix test

* Enable strict mode for "roosterjs-editor-core/lib/corePlugins" (#1287)

* Enable strict mode

* Fix tests

* Revert remove typeAfterLink

* Remove optional chaining

* editor's contains and select can take null

* Update getDarkColor typings

* Fix context menu not working issue (#1309)

* Fix context menu not working issue

* fix build

* Update getSelectionRangeEx typings to match desc (#1312)

* Update getSelectionRangeEx typings to match desc

* Fix build

* Revert "Update getSelectionRangeEx typings to match desc (#1312)" (#1317)

This reverts commit a260017.

* Finish strict mode change for core package (#1318)

* Content Model Entity step 1 (#1313)

* trigger selection when click

* Content Model Entity step 2: Add implementation code (#1314)

* Content Model Entity step 1

* Content Model Entity step 2

* Content Model List bug fix (#1320)

* Content Model List bug fix

* add test case

* Support block format in Content Model step 1 (#1323)

* Support block format in Content Model step 1

* fix build

* Enable strict mode on "roosterjs-editor-plugins" - Phase 1 (#1289)

* Strict AutoFormat & ContextMenu

* Strict CustomReplace

* CutPasteListChain plugin

* Allow nullish dom attribute value

* Strict HyperLink

* Strict Watermark

* Use individual tsconfigs

* Check this.editor at start of onPluginEvent

* Support block format in Content Model step 2 (#1324)

* Support block format in Content Model step 1

* Support block format in Content Model step 2

* fix build

* fix test

* Allow insert entity on region root (#1316)

* Allow insert entity on region root

* improve

* fix comment

* Change version

* 8.34.0

Co-authored-by: Jiuqing Song <jisong@microsoft.com>
Co-authored-by: Júlia Roldi <juliaroldi@microsoft.com>
Co-authored-by: Julia Roldi <87443959+juliaroldi@users.noreply.github.com>
  • Loading branch information
4 people authored Oct 14, 2022
1 parent fd08bb5 commit e71c96b
Show file tree
Hide file tree
Showing 143 changed files with 2,247 additions and 546 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { createDropDownFormatRenderer } from '../utils/createDropDownFormatRenderer';
import { DirectionFormat } from 'roosterjs-content-model';

export const DirectionFormatRenderers = [
createDropDownFormatRenderer<DirectionFormat, 'ltr' | 'rtl'>(
'Direction',
['ltr', 'rtl'],
format => format.direction,
(format, value) => (format.direction = value)
),
createDropDownFormatRenderer<DirectionFormat, 'start' | 'center' | 'end'>(
'Text align',
['start', 'center', 'end'],
format => format.textAlign,
(format, value) => (format.textAlign = value)
),
];

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as React from 'react';
import { ContentModelBlock } from 'roosterjs-content-model';
import { ContentModelBlockGroupView } from './ContentModelBlockGroupView';
import { ContentModelEntityView } from './ContentModelEntityView';
import { ContentModelParagraphView } from './ContentModelParagraphView';
import { ContentModelTableView } from './ContentModelTableView';

Expand All @@ -16,5 +17,8 @@ export function ContentModelBlockView(props: { block: ContentModelBlock }) {

case 'Table':
return <ContentModelTableView table={block} />;

case 'Entity':
return <ContentModelEntityView entity={block} />;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.modelEntity {
background-color: #3b2;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import * as React from 'react';
import { ContentModelEntity } from 'roosterjs-content-model';
import { ContentModelView } from '../ContentModelView';
import { useProperty } from '../../hooks/useProperty';

const styles = require('./ContentModelEntityView.scss');

export function ContentModelEntityView(props: { entity: ContentModelEntity }) {
const { entity } = props;

const [id, setId] = useProperty(entity.id);
const [isReadonly, setIsReadonly] = useProperty(entity.isReadonly);
const [type, setType] = useProperty(entity.type);

const idTextBox = React.useRef<HTMLInputElement>(null);
const isReadonlyCheckBox = React.useRef<HTMLInputElement>(null);
const typeTextBox = React.useRef<HTMLInputElement>(null);

const onIdChange = React.useCallback(() => {
const newValue = idTextBox.current.value;
entity.id = newValue;
setId(newValue);
}, [id, setId]);
const onTypeChange = React.useCallback(() => {
const newValue = typeTextBox.current.value;
entity.type = newValue;
setType(newValue);
}, [type, setType]);
const onReadonlyChange = React.useCallback(() => {
const newValue = isReadonlyCheckBox.current.checked;
entity.isReadonly = newValue;
setIsReadonly(newValue);
}, [id, setId]);

const getContent = React.useCallback(() => {
return (
<>
<div>
Id: <input type="text" value={id} ref={idTextBox} onChange={onIdChange} />
</div>
<div>
Type:
<input type="text" value={type} ref={typeTextBox} onChange={onTypeChange} />
</div>
<div>
IsReadonly:
<input
type="checkbox"
checked={isReadonly}
ref={isReadonlyCheckBox}
onChange={onReadonlyChange}
/>
</div>
</>
);
}, [type, isReadonly, id]);

return (
<ContentModelView
title="Entity"
subTitle={id}
className={styles.modelEntity}
jsonSource={entity}
getContent={getContent}
/>
);
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,24 @@
import * as React from 'react';
import { ContentModelParagraph, hasSelectionInBlock } from 'roosterjs-content-model';
import { BackgroundColorFormatRenderer } from '../format/formatPart/BackgroundColorFormatRenderer';
import { ContentModelSegmentView } from './ContentModelSegmentView';
import { ContentModelView } from '../ContentModelView';
import { DirectionFormatRenderers } from '../format/formatPart/DirectionFormatRenderers';
import { FormatRenderer } from '../format/utils/FormatRenderer';
import { FormatView } from '../format/FormatView';
import { useProperty } from '../../hooks/useProperty';
import {
ContentModelParagraph,
ContentModelBlockFormat,
hasSelectionInBlock,
} from 'roosterjs-content-model';

const styles = require('./ContentModelParagraphView.scss');

const ParagraphFormatRenders: FormatRenderer<ContentModelBlockFormat>[] = [
BackgroundColorFormatRenderer,
...DirectionFormatRenderers,
];

export function ContentModelParagraphView(props: { paragraph: ContentModelParagraph }) {
const { paragraph } = props;
const implicitCheckbox = React.useRef<HTMLInputElement>(null);
Expand Down Expand Up @@ -36,6 +49,10 @@ export function ContentModelParagraphView(props: { paragraph: ContentModelParagr
);
}, [paragraph, value]);

const getFormat = React.useCallback(() => {
return <FormatView format={paragraph.format} renderers={ParagraphFormatRenders} />;
}, [paragraph.format]);

return (
<ContentModelView
title="Paragraph"
Expand All @@ -45,6 +62,7 @@ export function ContentModelParagraphView(props: { paragraph: ContentModelParagr
hasSelection={hasSelectionInBlock(paragraph)}
jsonSource={paragraph}
getContent={getContent}
getFormat={getFormat}
/>
);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as React from 'react';
import { ContentModelBrView } from './ContentModelBrView';
import { ContentModelEntityView } from './ContentModelEntityView';
import { ContentModelGeneralView } from './ContentModelGeneralView';
import { ContentModelSegment } from 'roosterjs-content-model';
import { ContentModelSelectionMarkerView } from './ContentModelSelectionMarkerView';
Expand All @@ -20,5 +21,8 @@ export function ContentModelSegmentView(props: { segment: ContentModelSegment })

case 'Text':
return <ContentModelTextView text={segment} />;

case 'Entity':
return <ContentModelEntityView entity={segment} />;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import { BlockGroupContentView } from './BlockGroupContentView';
import { BorderBoxFormatRenderer } from '../format/formatPart/BorderBoxFormatRenderer';
import { BorderFormatRenderers } from '../format/formatPart/BorderFormatRenderers';
import { ContentModelView } from '../ContentModelView';
import { DirectionFormatRenderers } from '../format/formatPart/DirectionFormatRenderers';
import { FormatRenderer } from '../format/utils/FormatRenderer';
import { FormatView } from '../format/FormatView';
import { PaddingFormatRenderer } from '../format/formatPart/PaddingFormatRenderer';
import { TableCellMetadataFormatRender } from '../format/formatPart/TableCellMetadataFormatRender';
import { TextAlignFormatRenderer } from '../format/formatPart/TextAlignFormatRenderer';
import { useProperty } from '../../hooks/useProperty';
import { VerticalAlignFormatRenderer } from '../format/formatPart/VerticalAlignFormatRenderer';
import {
Expand All @@ -21,10 +21,10 @@ const styles = require('./ContentModelTableCellView.scss');

const TableCellFormatRenderers: FormatRenderer<ContentModelTableCellFormat>[] = [
...BorderFormatRenderers,
...DirectionFormatRenderers,
BorderBoxFormatRenderer,
BackgroundColorFormatRenderer,
PaddingFormatRenderer,
TextAlignFormatRenderer,
VerticalAlignFormatRenderer,
TableCellMetadataFormatRender,
];
Expand Down
25 changes: 11 additions & 14 deletions demo/scripts/controls/editor/ExperimentalContentModelEditor.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ContentPosition, EditorOptions, SelectionRangeTypes } from 'roosterjs-editor-types';
import { Editor } from 'roosterjs-editor-core';
import { EditorOptions, SelectionRangeTypes } from 'roosterjs-editor-types';
import { getComputedStyles, Position } from 'roosterjs-editor-dom';
import {
EditorContext,
Expand All @@ -9,6 +9,7 @@ import {
DomToModelOption,
IExperimentalContentModelEditor,
ModelToDomOption,
mergeFragmentWithEntity,
} from 'roosterjs-content-model';

/**
Expand Down Expand Up @@ -64,34 +65,30 @@ export default class ExperimentalContentModelEditor extends Editor
* @param option Additional options to customize the behavior of Content Model to DOM conversion
*/
setContentModel(model: ContentModelDocument, option?: ModelToDomOption) {
const [fragment, range] = contentModelToDom(model, this.createEditorContext(), option);
const mergingCallback = option?.mergingCallback || this.defaultMergingCallback;
const [fragment, range, entityPairs] = contentModelToDom(
model,
this.createEditorContext(),
option
);
const mergingCallback = option?.mergingCallback || mergeFragmentWithEntity;

switch (range?.type) {
case SelectionRangeTypes.Normal:
const start = Position.getStart(range.ranges[0]);
const end = Position.getEnd(range.ranges[0]);

mergingCallback(fragment);
mergingCallback(fragment, this.contentDiv, entityPairs);
this.select(start, end);
break;

case SelectionRangeTypes.TableSelection:
mergingCallback(fragment);
mergingCallback(fragment, this.contentDiv, entityPairs);
this.select(range.table, range.coordinates);
break;

case undefined:
mergingCallback(fragment);
mergingCallback(fragment, this.contentDiv, entityPairs);
break;
}
}

private defaultMergingCallback = (fragment: DocumentFragment) => {
while (this.contentDiv.firstChild) {
this.contentDiv.removeChild(this.contentDiv.firstChild);
}

this.insertNode(fragment, { position: ContentPosition.Begin });
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export default class InsertEntityPane extends React.Component<ApiPaneProps, Inse
private styleInline = React.createRef<HTMLInputElement>();
private styleBlock = React.createRef<HTMLInputElement>();
private isReadonly = React.createRef<HTMLInputElement>();
private insertAtRoot = React.createRef<HTMLInputElement>();

constructor(props: ApiPaneProps) {
super(props);
Expand Down Expand Up @@ -54,6 +55,10 @@ export default class InsertEntityPane extends React.Component<ApiPaneProps, Inse
<div>
Readonly: <input type="checkbox" ref={this.isReadonly} />
</div>
<div>
Force insert at root of region:{' '}
<input type="checkbox" ref={this.insertAtRoot} />
</div>
<div>
<button onClick={this.insertEntity}>Insert Entity</button>
</div>
Expand All @@ -77,9 +82,22 @@ export default class InsertEntityPane extends React.Component<ApiPaneProps, Inse
node.dataset.hydratedHtml = this.hydratedHtml.current.value.trim();
const isBlock = this.styleBlock.current.checked;
const isReadonly = this.isReadonly.current.checked;
const insertAtRoot = this.insertAtRoot.current.checked;

if (node) {
insertEntity(this.props.getEditor(), entityType, node, isBlock, isReadonly);
const editor = this.props.getEditor();

editor.addUndoSnapshot(() => {
insertEntity(
editor,
entityType,
node,
isBlock,
isReadonly,
undefined /*position*/,
insertAtRoot
);
});
}
};

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "roosterjs",
"version": "8.33.1",
"version": "8.34.0",
"description": "Framework-independent javascript editor",
"repository": {
"type": "git",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
PluginEvent,
PluginEventType,
PluginKeyboardEvent,
PluginKeyDownEvent,
PositionType,
} from 'roosterjs-editor-types';
import {
Expand Down Expand Up @@ -102,7 +103,7 @@ class EmojiPlugin implements ReactEditorPlugin {
* Try to insert emoji is possible
* Intercept arrow keys to move selection if popup is shown
*/
private onKeyDownSuggestingDomEvent(event: PluginDomEvent): void {
private onKeyDownSuggestingDomEvent(event: PluginKeyDownEvent): void {
// If key is enter, try insert emoji at selection
// If key is space and selection is shortcut, try insert emoji

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export function createDomToModelContext(
getDarkColor: undefined,
}),

blockFormat: {},
segmentFormat: {},
isInSelection: false,

Expand All @@ -42,6 +43,10 @@ export function createDomToModelContext(
formatParsers: getFormatParsers(options?.formatParserOverride),
};

if (editorContext?.isRightToLeft) {
context.blockFormat.direction = 'rtl';
}

if (options?.alwaysNormalizeTable) {
context.alwaysNormalizeTable = true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ export const brProcessor: ElementProcessor = (group, element, context) => {
br.isSelected = true;
}

addSegment(group, br);
addSegment(group, br, context.blockFormat);
};
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@ function handleSelection(
if (index == nodeStartOffset) {
context.isInSelection = true;

addSegment(group, createSelectionMarker(context.segmentFormat));
addSegment(group, createSelectionMarker(context.segmentFormat), context.blockFormat);
}

if (index == nodeEndOffset) {
if (!context.regularSelection!.isSelectionCollapsed) {
addSegment(group, createSelectionMarker(context.segmentFormat));
addSegment(group, createSelectionMarker(context.segmentFormat), context.blockFormat);
}
context.isInSelection = false;
}
Expand All @@ -66,7 +66,7 @@ function textNodeProcessor(
textProcessor(group, txt.substring(0, txtStartOffset), context);
context.isInSelection = true;

addSegment(group, createSelectionMarker(context.segmentFormat));
addSegment(group, createSelectionMarker(context.segmentFormat), context.blockFormat);

txt = txt.substring(txtStartOffset);
txtEndOffset -= txtStartOffset;
Expand All @@ -76,7 +76,7 @@ function textNodeProcessor(
textProcessor(group, txt.substring(0, txtEndOffset), context);

if (!context.regularSelection!.isSelectionCollapsed) {
addSegment(group, createSelectionMarker(context.segmentFormat));
addSegment(group, createSelectionMarker(context.segmentFormat), context.blockFormat);
}

context.isInSelection = false;
Expand Down
Loading

0 comments on commit e71c96b

Please sign in to comment.