Skip to content

Commit eab3186

Browse files
committed
reafctor
1 parent 9f9ec23 commit eab3186

File tree

248 files changed

+12302
-1246
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

248 files changed

+12302
-1246
lines changed

.eslintrc.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,17 @@ module.exports = {
151151
'no-var': 'error',
152152
'etc/no-const-enum': ['error', { allowLocal: true }],
153153
'import/no-default-export': 'error',
154+
'no-restricted-globals': [
155+
'error',
156+
{
157+
name: 'window',
158+
message: 'Do not use global window',
159+
},
160+
{
161+
name: 'document',
162+
message: 'Do not use global document',
163+
},
164+
],
154165
},
155166
overrides: [
156167
{
@@ -159,5 +170,15 @@ module.exports = {
159170
'import/no-default-export': 'off',
160171
},
161172
},
173+
{
174+
files: [
175+
'roosterjs-editor-adapter/**/*.ts',
176+
'roosterjs-react/**/*.ts',
177+
'roosterjs-react/**/*.tsx',
178+
],
179+
rules: {
180+
'no-restricted-globals': 'off',
181+
},
182+
},
162183
],
163184
};

.github/workflows/publish.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ on:
33
push:
44
branches:
55
- release
6+
7+
permissions:
8+
id-token: write # Required for OIDC
9+
contents: read
10+
611
jobs:
712
build-and-deploy:
813
runs-on: ubuntu-latest
@@ -25,4 +30,4 @@ jobs:
2530
run: npm run-script build:ci
2631

2732
- name: Publish
28-
run: node tools/build.js publish --token ${{ secrets.NPM_TOKEN }}
33+
run: node tools/build.js publish

.vscode/settings.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
"builddemo",
3333
"builddoc",
3434
"Calibri",
35+
"cellspacing",
3536
"checkdep",
3637
"colspan",
3738
"compositionend",

demo/scripts/controlsV2/demoButtons/createImageEditButtons.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ function createImageFlipButton(handler: ImageEditor): RibbonButton<'buttonNameFl
6262
items: flipDirections,
6363
},
6464
isDisabled: formatState => !formatState.canAddImageAltText,
65-
onClick: (editor, flipDirection) => {
65+
onClick: (_editor, flipDirection) => {
6666
handler.flipImage(flipDirection as 'horizontal' | 'vertical');
6767
},
6868
};

demo/scripts/controlsV2/mainPane/MainPane.tsx

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ import {
5959
Snapshots,
6060
} from 'roosterjs-content-model-types';
6161
import {
62+
AnnouncePlugin,
6263
AutoFormatPlugin,
6364
CustomReplacePlugin,
6465
EditPlugin,
@@ -71,6 +72,9 @@ import {
7172
TableEditPlugin,
7273
WatermarkPlugin,
7374
TouchPlugin,
75+
FindReplacePlugin,
76+
FindReplaceContext,
77+
createFindReplaceContext,
7478
} from 'roosterjs-content-model-plugins';
7579
import DOMPurify = require('dompurify');
7680

@@ -111,6 +115,8 @@ export class MainPane extends React.Component<{}, MainPaneState> {
111115
private snapshots: Snapshots;
112116
private markdownPanePlugin: MarkdownPanePlugin;
113117
private imageEditPlugin: ImageEditPlugin;
118+
private findReplacePlugin: FindReplacePlugin;
119+
private findReplaceContext: FindReplaceContext;
114120

115121
protected sidePane = React.createRef<SidePane>();
116122
protected updateContentPlugin: UpdateContentPlugin;
@@ -150,6 +156,9 @@ export class MainPane extends React.Component<{}, MainPaneState> {
150156
this.samplePickerPlugin = new SamplePickerPlugin();
151157
this.markdownPanePlugin = new MarkdownPanePlugin();
152158

159+
this.findReplaceContext = createFindReplaceContext();
160+
this.findReplacePlugin = new FindReplacePlugin(this.findReplaceContext);
161+
153162
this.state = {
154163
showSidePane: window.location.hash != '',
155164
popoutWindow: null,
@@ -286,6 +295,10 @@ export class MainPane extends React.Component<{}, MainPaneState> {
286295
});
287296
}
288297

298+
getFindReplaceContext(): FindReplaceContext {
299+
return this.findReplaceContext;
300+
}
301+
289302
private renderTitleBar() {
290303
return <TitleBar className={styles.noGrow} />;
291304
}
@@ -367,6 +380,7 @@ export class MainPane extends React.Component<{}, MainPaneState> {
367380
...this.getToggleablePlugins(imageEditPlugin),
368381
this.contentModelPanePlugin.getInnerRibbonPlugin(),
369382
this.updateContentPlugin,
383+
this.findReplacePlugin,
370384
];
371385

372386
if (this.state.showSidePane || this.state.popoutWindow) {
@@ -561,6 +575,7 @@ export class MainPane extends React.Component<{}, MainPaneState> {
561575
undeletableLinkChecker: undeletableLinkChecker,
562576
}),
563577
pluginList.touch && new TouchPlugin(),
578+
pluginList.announce && new AnnouncePlugin(),
564579
].filter(x => !!x);
565580
}
566581
}
@@ -569,6 +584,14 @@ const AnnounceStringMap: Record<KnownAnnounceStrings, string> = {
569584
announceListItemBullet: 'Auto corrected Bullet',
570585
announceListItemNumbering: 'Auto corrected {0}',
571586
announceOnFocusLastCell: 'Warning, pressing tab here adds an extra row.',
587+
announceBoldOn: 'Bold On',
588+
announceBoldOff: 'Bold Off',
589+
announceItalicOn: 'Italic On',
590+
announceItalicOff: 'Italic Off',
591+
announceUnderlineOn: 'Underline On',
592+
announceUnderlineOff: 'Underline Off',
593+
selected: '{0}, selected',
594+
unselected: '{0}, unselected',
572595
};
573596

574597
function getAnnouncingString(key: KnownAnnounceStrings) {

demo/scripts/controlsV2/sidePane/apiPlayground/apiEntries.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import * as React from 'react';
22
import CreateModelFromHtmlPane from './createModelFromHtml/CreateModelFromHtmlPane';
3+
import FindReplacePane from './findReplace/FindReplacePane';
34
import InsertCustomContainerPane from './insertCustomContainer/InsertCustomContainerPane';
45
import InsertEntityPane from './insertEntity/InsertEntityPane';
56
import PastePane from './paste/PastePane';
@@ -34,6 +35,10 @@ const apiEntries: { [key: string]: ApiEntry } = {
3435
name: 'Insert Custom Container',
3536
component: InsertCustomContainerPane,
3637
},
38+
findReplace: {
39+
name: 'Find and Replace',
40+
component: FindReplacePane,
41+
},
3742
more: {
3843
name: 'Coming soon...',
3944
},
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
import * as React from 'react';
2+
import { ApiPaneProps, ApiPlaygroundComponent } from '../ApiPaneProps';
3+
import { find, moveHighlight, replace } from 'roosterjs-content-model-plugins';
4+
import { MainPane } from '../../../mainPane/MainPane';
5+
import { PluginEvent } from 'roosterjs-content-model-types';
6+
7+
interface FindReplacePaneState {
8+
showReplace: boolean;
9+
resultCount: number;
10+
currentIndex: number;
11+
passedEnd: boolean;
12+
}
13+
14+
export default class FindReplacePane extends React.Component<ApiPaneProps, FindReplacePaneState>
15+
implements ApiPlaygroundComponent {
16+
private findTextRef = React.createRef<HTMLInputElement>();
17+
private replaceTextRef = React.createRef<HTMLInputElement>();
18+
private matchCaseRef = React.createRef<HTMLInputElement>();
19+
private wholeWordRef = React.createRef<HTMLInputElement>();
20+
private replaceRef = React.createRef<HTMLInputElement>();
21+
22+
constructor(props: ApiPaneProps) {
23+
super(props);
24+
this.state = {
25+
showReplace: false,
26+
resultCount: 0,
27+
currentIndex: -1,
28+
passedEnd: false,
29+
};
30+
}
31+
32+
public onPluginEvent = (e: PluginEvent) => {
33+
if (e.eventType == 'findResultChanged') {
34+
const { markedIndex, ranges, alternativeRange } = e;
35+
36+
this.setState({
37+
currentIndex: markedIndex,
38+
resultCount: ranges.length,
39+
});
40+
41+
if (markedIndex < 0 && alternativeRange) {
42+
this.props.getEditor().setDOMSelection({
43+
type: 'range',
44+
range: alternativeRange,
45+
isReverted: false,
46+
});
47+
}
48+
}
49+
};
50+
51+
render() {
52+
return (
53+
<>
54+
<div>
55+
Find: <input type="text" ref={this.findTextRef} onChange={this.find} />
56+
</div>
57+
<div>
58+
<input
59+
type="checkbox"
60+
ref={this.matchCaseRef}
61+
onClick={this.find}
62+
id="matchCase"
63+
/>
64+
<label htmlFor="matchCase"> Match Case</label>
65+
</div>
66+
<div>
67+
<input
68+
type="checkbox"
69+
ref={this.wholeWordRef}
70+
onClick={this.find}
71+
id="wholeWord"
72+
/>
73+
<label htmlFor="wholeWord"> Whole Word</label>
74+
</div>
75+
<div>
76+
Results Found:{' '}
77+
{this.state.currentIndex < 0
78+
? this.state.resultCount
79+
: `${this.state.currentIndex + 1} / ${this.state.resultCount}`}
80+
</div>
81+
<div>
82+
<button onClick={this.movePrevious}>Previous</button>
83+
<button onClick={this.moveNext}>Next</button>
84+
</div>
85+
{this.state.passedEnd && <div>You have passed the end of the document.</div>}
86+
<hr />
87+
<div>
88+
<input
89+
type="checkbox"
90+
ref={this.replaceRef}
91+
onChange={this.showHideReplace}
92+
id="replace"
93+
/>
94+
<label htmlFor="replace"> Replace</label>
95+
</div>
96+
{this.state.showReplace && (
97+
<div>
98+
<div>
99+
Replace with: <input type="text" ref={this.replaceTextRef} />
100+
</div>
101+
<div>
102+
<button onClick={this.replace} disabled={this.state.resultCount == 0}>
103+
Replace
104+
</button>
105+
<button
106+
onClick={this.replaceAll}
107+
disabled={this.state.resultCount == 0}>
108+
Replace All
109+
</button>
110+
</div>
111+
</div>
112+
)}
113+
</>
114+
);
115+
}
116+
117+
private find = () => {
118+
const context = MainPane.getInstance().getFindReplaceContext();
119+
120+
find(
121+
this.props.getEditor(),
122+
context,
123+
this.findTextRef.current?.value ?? null,
124+
this.matchCaseRef.current?.checked,
125+
this.wholeWordRef.current?.checked
126+
);
127+
128+
this.setState({ resultCount: context.ranges.length, currentIndex: -1, passedEnd: false });
129+
};
130+
131+
private showHideReplace = () => {
132+
this.setState(prevState => ({ showReplace: !prevState.showReplace }));
133+
};
134+
135+
private replace = () => {
136+
const context = MainPane.getInstance().getFindReplaceContext();
137+
138+
replace(this.props.getEditor(), context, this.replaceTextRef.current?.value || '');
139+
140+
this.setState({ resultCount: context.ranges.length, currentIndex: -1, passedEnd: false });
141+
};
142+
143+
private replaceAll = () => {
144+
const context = MainPane.getInstance().getFindReplaceContext();
145+
146+
replace(this.props.getEditor(), context, this.replaceTextRef.current?.value || '', true);
147+
148+
this.setState({ resultCount: context.ranges.length, currentIndex: -1, passedEnd: false });
149+
};
150+
151+
private movePrevious = () => {
152+
const oldIndex = this.state.currentIndex;
153+
const context = MainPane.getInstance().getFindReplaceContext();
154+
155+
moveHighlight(this.props.getEditor(), context, false);
156+
157+
this.setState({
158+
currentIndex: context.markedIndex,
159+
passedEnd: oldIndex < context.markedIndex,
160+
});
161+
};
162+
163+
private moveNext = () => {
164+
const oldIndex = this.state.currentIndex;
165+
const context = MainPane.getInstance().getFindReplaceContext();
166+
167+
moveHighlight(this.props.getEditor(), context, true);
168+
169+
this.setState({
170+
currentIndex: context.markedIndex,
171+
passedEnd: oldIndex > context.markedIndex,
172+
});
173+
};
174+
}

demo/scripts/controlsV2/sidePane/editorOptions/EditorOptionsPlugin.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ const initialState: OptionState = {
2323
customReplace: true,
2424
hiddenProperty: true,
2525
touch: true,
26+
announce: true,
2627
},
2728
defaultFormat: {
2829
fontFamily: 'Calibri',
@@ -58,16 +59,22 @@ const initialState: OptionState = {
5859
codeFormat: {},
5960
},
6061
editPluginOptions: {
61-
handleTabKey: true,
62+
handleTabKey: {
63+
indentMultipleBlocks: true,
64+
indentTable: true,
65+
appendTableRow: true,
66+
indentList: true,
67+
indentParagraph: true,
68+
},
6269
},
6370
customReplacements: emojiReplacements,
6471
disableSideResize: false,
6572
experimentalFeatures: new Set<ExperimentalFeature>([
66-
'PersistCache',
6773
'HandleEnterKey',
68-
'CustomCopyCut',
6974
'CloneIndependentRoot',
7075
'ImageEditV2',
76+
'CacheList',
77+
'TransformTableBorderColors',
7178
]),
7279
};
7380

demo/scripts/controlsV2/sidePane/editorOptions/ExperimentalFeatures.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,12 @@ export class ExperimentalFeatures extends React.Component<DefaultFormatProps, {}
1111
render() {
1212
return (
1313
<>
14-
{this.renderFeature('PersistCache')}
1514
{this.renderFeature('HandleEnterKey')}
16-
{this.renderFeature('CustomCopyCut')}
15+
{this.renderFeature('KeepSelectionMarkerWhenEnteringTextNode')}
1716
{this.renderFeature('CloneIndependentRoot')}
1817
{this.renderFeature('ImageEditV2')}
18+
{this.renderFeature('CacheList')}
19+
{this.renderFeature('TransformTableBorderColors')}
1920
</>
2021
);
2122
}

0 commit comments

Comments
 (0)