Skip to content

Commit 7112947

Browse files
authored
Disable using global window and document (#3240)
1 parent 64b0b02 commit 7112947

File tree

17 files changed

+175
-118
lines changed

17 files changed

+175
-118
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
};

packages/roosterjs-content-model-core/lib/editor/Editor.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ export class Editor implements IEditor {
225225
* @returns The HTML document which contains this editor
226226
*/
227227
getDocument(): Document {
228-
return this.getCore().physicalRoot.ownerDocument;
228+
return this.getCore().environment.document;
229229
}
230230

231231
/**

packages/roosterjs-content-model-core/lib/editor/core/createEditorCore.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ function createEditorEnvironment(
6969
const appVersion = navigator?.appVersion ?? '';
7070

7171
return {
72+
document: contentDiv.ownerDocument,
7273
domToModelSettings: createDomToModelSettings(options),
7374
modelToDomSettings: createModelToDomSettings(options),
7475
isMac: appVersion.indexOf('Mac') != -1,

packages/roosterjs-content-model-core/test/command/cutCopy/getContentForCopyTest.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ describe('getContentForCopy', () => {
3636
getContentModelCopy: (): ContentModelDocument => createContentModelDocument(),
3737
getEnvironment: (): EditorEnvironment => {
3838
return {
39+
document: mockDocument,
3940
isSafari: false,
4041
domToModelSettings: {} as ContentModelSettings<
4142
DomToModelOption,

packages/roosterjs-content-model-core/test/corePlugin/format/FormatPluginTest.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ describe('FormatPlugin', () => {
2020
const mockedEnvironment = {
2121
domToModelSettings: createDomToModelSettings({}),
2222
modelToDomSettings: createModelToDomSettings({}),
23+
document,
2324
} as EditorEnvironment;
2425

2526
beforeEach(() => {
@@ -271,6 +272,7 @@ describe('FormatPlugin for default format', () => {
271272
const mockedEnvironment = {
272273
domToModelSettings: createDomToModelSettings({}),
273274
modelToDomSettings: createModelToDomSettings({}),
275+
document,
274276
} as EditorEnvironment;
275277

276278
beforeEach(() => {

packages/roosterjs-content-model-core/test/editor/core/createEditorCoreTest.ts

Lines changed: 53 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ describe('createEditorCore', () => {
4242
htmlToDOM: mockedDOMHelper,
4343
};
4444
const mockedTrustHtmlHandler = 'TRUSTED' as any;
45+
const mockedDocument: Document = 'DOCUMENT' as any;
4546

4647
beforeEach(() => {
4748
spyOn(createEditorCorePlugins, 'createEditorCorePlugins').and.returnValue(mockedPlugins);
@@ -83,6 +84,7 @@ describe('createEditorCore', () => {
8384
mockedLifeCyclePlugin,
8485
],
8586
environment: {
87+
document: mockedDocument,
8688
isMac: false,
8789
isAndroid: false,
8890
isIOS: false,
@@ -120,7 +122,7 @@ describe('createEditorCore', () => {
120122

121123
it('No options', () => {
122124
const mockedDiv = {
123-
ownerDocument: {},
125+
ownerDocument: mockedDocument,
124126
attributes: {
125127
a: 'b',
126128
},
@@ -143,7 +145,7 @@ describe('createEditorCore', () => {
143145

144146
it('With options', () => {
145147
const mockedDiv = {
146-
ownerDocument: {},
148+
ownerDocument: mockedDocument,
147149
attributes: {
148150
a: 'b',
149151
},
@@ -201,14 +203,15 @@ describe('createEditorCore', () => {
201203
});
202204

203205
it('Android', () => {
204-
const mockedDiv = {
205-
ownerDocument: {
206-
defaultView: {
207-
navigator: {
208-
userAgent: 'Android',
209-
},
206+
const mockedDocument: Document = {
207+
defaultView: {
208+
navigator: {
209+
userAgent: 'Android',
210210
},
211211
},
212+
} as any;
213+
const mockedDiv = {
214+
ownerDocument: mockedDocument,
212215
attributes: {
213216
a: 'b',
214217
},
@@ -217,6 +220,7 @@ describe('createEditorCore', () => {
217220

218221
runTest(mockedDiv, mockedOptions, {
219222
environment: {
223+
document: mockedDocument,
220224
isMac: false,
221225
isAndroid: true,
222226
isIOS: false,
@@ -236,14 +240,15 @@ describe('createEditorCore', () => {
236240
});
237241

238242
it('Android+Safari', () => {
239-
const mockedDiv = {
240-
ownerDocument: {
241-
defaultView: {
242-
navigator: {
243-
userAgent: 'Android AppleWebKit',
244-
},
243+
const mockedDocument: Document = {
244+
defaultView: {
245+
navigator: {
246+
userAgent: 'Android AppleWebKit',
245247
},
246248
},
249+
} as any;
250+
const mockedDiv = {
251+
ownerDocument: mockedDocument,
247252
attributes: {
248253
a: 'b',
249254
},
@@ -252,6 +257,7 @@ describe('createEditorCore', () => {
252257

253258
runTest(mockedDiv, mockedOptions, {
254259
environment: {
260+
document: mockedDocument,
255261
isMac: false,
256262
isAndroid: true,
257263
isIOS: false,
@@ -271,14 +277,15 @@ describe('createEditorCore', () => {
271277
});
272278

273279
it('Mac', () => {
274-
const mockedDiv = {
275-
ownerDocument: {
276-
defaultView: {
277-
navigator: {
278-
appVersion: 'Mac',
279-
},
280+
const mockedDocument: Document = {
281+
defaultView: {
282+
navigator: {
283+
appVersion: 'Mac',
280284
},
281285
},
286+
} as any;
287+
const mockedDiv = {
288+
ownerDocument: mockedDocument,
282289
attributes: {
283290
a: 'b',
284291
},
@@ -287,6 +294,7 @@ describe('createEditorCore', () => {
287294

288295
runTest(mockedDiv, mockedOptions, {
289296
environment: {
297+
document: mockedDocument,
290298
isMac: true,
291299
isAndroid: false,
292300
isIOS: false,
@@ -306,14 +314,15 @@ describe('createEditorCore', () => {
306314
});
307315

308316
it('Safari', () => {
309-
const mockedDiv = {
310-
ownerDocument: {
311-
defaultView: {
312-
navigator: {
313-
userAgent: 'AppleWebKit',
314-
},
317+
const mockedDocument: Document = {
318+
defaultView: {
319+
navigator: {
320+
userAgent: 'AppleWebKit',
315321
},
316322
},
323+
} as any;
324+
const mockedDiv = {
325+
ownerDocument: mockedDocument,
317326
attributes: {
318327
a: 'b',
319328
},
@@ -322,6 +331,7 @@ describe('createEditorCore', () => {
322331

323332
runTest(mockedDiv, mockedOptions, {
324333
environment: {
334+
document: mockedDocument,
325335
isMac: false,
326336
isAndroid: false,
327337
isIOS: false,
@@ -341,14 +351,15 @@ describe('createEditorCore', () => {
341351
});
342352

343353
it('Chrome', () => {
344-
const mockedDiv = {
345-
ownerDocument: {
346-
defaultView: {
347-
navigator: {
348-
userAgent: 'AppleWebKit Chrome',
349-
},
354+
const mockedDocument: Document = {
355+
defaultView: {
356+
navigator: {
357+
userAgent: 'AppleWebKit Chrome',
350358
},
351359
},
360+
} as any;
361+
const mockedDiv = {
362+
ownerDocument: mockedDocument,
352363
attributes: {
353364
a: 'b',
354365
},
@@ -357,6 +368,7 @@ describe('createEditorCore', () => {
357368

358369
runTest(mockedDiv, mockedOptions, {
359370
environment: {
371+
document: mockedDocument,
360372
isMac: false,
361373
isAndroid: false,
362374
isIOS: false,
@@ -376,15 +388,16 @@ describe('createEditorCore', () => {
376388
});
377389

378390
it('iOS iPhone Safari', () => {
379-
const mockedDiv = {
380-
ownerDocument: {
381-
defaultView: {
382-
navigator: {
383-
userAgent:
384-
'Mozilla/5.0 (iPhone; CPU iPhone OS 18_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148',
385-
},
391+
const mockedDocument: Document = {
392+
defaultView: {
393+
navigator: {
394+
userAgent:
395+
'Mozilla/5.0 (iPhone; CPU iPhone OS 18_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148',
386396
},
387397
},
398+
} as any;
399+
const mockedDiv = {
400+
ownerDocument: mockedDocument,
388401
attributes: {
389402
a: 'b',
390403
},
@@ -393,6 +406,7 @@ describe('createEditorCore', () => {
393406

394407
runTest(mockedDiv, mockedOptions, {
395408
environment: {
409+
document: mockedDocument,
396410
isMac: false,
397411
isAndroid: false,
398412
isIOS: true,

packages/roosterjs-content-model-dom/lib/modelApi/common/normalizeSegmentFormat.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { createContentModelDocument } from '../creators/createContentModelDocument';
2+
import { createDomToModelContextWithConfig } from '../../domToModel/context/createDomToModelContext';
3+
import { createModelToDomContextWithConfig } from '../../modelToDom/context/createModelToDomContext';
24
import { createText } from '../creators/createText';
35
import { ensureParagraph } from './ensureParagraph';
4-
import { createModelToDomContextWithConfig } from '../../modelToDom/context/createModelToDomContext';
5-
import { createDomToModelContextWithConfig } from '../../domToModel/context/createDomToModelContext';
66
import type {
77
ContentModelSegmentFormat,
88
DomToModelContext,
@@ -20,7 +20,7 @@ export function normalizeSegmentFormat(
2020
format: ContentModelSegmentFormat,
2121
environment: EditorEnvironment
2222
): ContentModelSegmentFormat {
23-
const span = document.createElement('span');
23+
const span = environment.document.createElement('span');
2424
const segment = createText('text', format);
2525

2626
const domToModelContext: DomToModelContext = createDomToModelContextWithConfig(

packages/roosterjs-content-model-dom/lib/modelToDom/handlers/handleImage.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export const handleImage: ContentModelSegmentHandler<ContentModelImage> = (
1414
segmentNodes
1515
) => {
1616
const img = doc.createElement('img');
17-
const element = document.createElement('span');
17+
const element = doc.createElement('span');
1818

1919
parent.appendChild(element);
2020
element.appendChild(img);

packages/roosterjs-content-model-dom/test/modelApi/common/normalizeSegmentFormatTest.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ describe('normalizeSegmentFormat', () => {
1414
modelToDomSettings: {
1515
calculated: createModelToDomConfig([]),
1616
},
17+
document: document,
1718
} as EditorEnvironment;
1819
});
1920

packages/roosterjs-content-model-plugins/lib/autoFormat/AutoFormatPlugin.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -178,8 +178,12 @@ export class AutoFormatPlugin implements EditorPlugin {
178178
autoMailto,
179179
});
180180

181-
if (linkSegment) {
182-
return createAnchor(linkSegment.link?.format.href || '', linkSegment.text);
181+
if (linkSegment && this.editor) {
182+
return createAnchor(
183+
this.editor.getDocument(),
184+
linkSegment.link?.format.href || '',
185+
linkSegment.text
186+
);
183187
}
184188
return false;
185189
},
@@ -339,8 +343,8 @@ export class AutoFormatPlugin implements EditorPlugin {
339343
}
340344
}
341345

342-
const createAnchor = (url: string, text: string) => {
343-
const anchor = document.createElement('a');
346+
const createAnchor = (doc: Document, url: string, text: string) => {
347+
const anchor = doc.createElement('a');
344348
anchor.href = url;
345349
anchor.textContent = text;
346350
return anchor;

0 commit comments

Comments
 (0)