Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 0 additions & 28 deletions .eslintrc.json

This file was deleted.

33 changes: 33 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import tinyPlugin from '@tinymce/eslint-plugin';
import { defineConfig } from "eslint/config";

export default defineConfig([
tinyPlugin.configs.editor,
{
files: ["**/*.ts", "**/*.tsx"],
languageOptions: {
ecmaVersion: 5,
sourceType: "module",

parserOptions: {
project: "tsconfig.json",
},
},

rules: {
"@tinymce/prefer-fun": "off",
"@typescript-eslint/no-unsafe-argument": "off",
},
},
{
files: ["src/test/**/*"],

rules: {
"@typescript-eslint/no-unused-vars": ["warn", {
argsIgnorePattern: "^_",
}],

"no-var": "off",
},
}
]);
52 changes: 26 additions & 26 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"author": "Ephox Corporation DBA Tiny Technologies, Inc.",
"license": "MIT",
"dependencies": {
"prop-types": "^15.6.2"
"prop-types": "^15.8.1"
},
"peerDependencies": {
"react": "^19.0.0 || ^18.0.0 || ^17.0.1 || ^16.7.0",
Expand All @@ -39,44 +39,44 @@
}
},
"devDependencies": {
"@babel/core": "^7.26.9",
"@babel/preset-env": "^7.26.9",
"@babel/preset-react": "^7.26.3",
"@babel/preset-typescript": "^7.26.0",
"@babel/core": "^7.28.4",
"@babel/preset-env": "^7.28.3",
"@babel/preset-react": "^7.27.1",
"@babel/preset-typescript": "^7.27.1",
"@ephox/agar": "^8.0.1",
"@ephox/bedrock-client": "^15.0.0",
"@ephox/bedrock-server": "^15.0.3-alpha.0",
"@ephox/katamari": "^9.1.5",
"@ephox/mcagar": "^9.0.0-alpha.0",
"@ephox/sand": "^6.0.9",
"@ephox/sugar": "^9.2.1",
"@storybook/addon-essentials": "^8.6.4",
"@storybook/addon-interactions": "^8.6.4",
"@storybook/addon-links": "^8.6.4",
"@storybook/blocks": "^8.6.4",
"@storybook/react": "^8.6.4",
"@storybook/react-vite": "^8.6.4",
"@ephox/katamari": "^9.1.6",
"@ephox/mcagar": "^9.0.1",
"@ephox/sand": "^6.0.10",
"@ephox/sugar": "^9.3.1",
"@storybook/addon-essentials": "^8.6.14",
"@storybook/addon-interactions": "^8.6.14",
"@storybook/addon-links": "8.6.14",
"@storybook/blocks": "^8.6.14",
"@storybook/react": "^8.6.14",
"@storybook/react-vite": "^8.6.14",
"@tinymce/beehive-flow": "^0.19.0",
"@tinymce/eslint-plugin": "^2.4.0",
"@tinymce/eslint-plugin": "^3.0.0",
"@tinymce/miniature": "^6.0.0",
"@types/node": "^22.13.10",
"@types/prop-types": "^15.7.14",
"@types/react": "^19.0.0",
"@types/react-dom": "^19.0.0",
"gh-pages": "^6.1.0",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"@types/node": "^24.5.0",
"@types/prop-types": "^15.7.15",
"@types/react": "^19.1.13",
"@types/react-dom": "^19.1.9",
"gh-pages": "^6.3.0",
"react": "^19.1.1",
"react-dom": "^19.1.1",
"rimraf": "^6.0.1",
"storybook": "^8.6.4",
"tinymce": "^8.0.1",
"storybook": "^8.6.14",
"tinymce": "^8.0.2",
"tinymce-4": "npm:tinymce@^4",
"tinymce-5": "npm:tinymce@^5",
"tinymce-6": "npm:tinymce@^6",
"tinymce-7": "npm:tinymce@^7",
"tinymce-7.5": "npm:tinymce@7.5",
"tinymce-8": "npm:tinymce@^8.0.0",
"typescript": "~5.8.2",
"vite": "^6.2.1"
"vite": "^7.1.5"
},
"version": "6.3.1-rc",
"name": "@tinymce/tinymce-react"
Expand Down
19 changes: 10 additions & 9 deletions src/main/ts/Utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { eventPropTypes, IEventPropTypes } from './components/EditorPropTypes';
import { IAllProps } from './components/Editor';
import type { Editor as TinyMCEEditor, EditorEvent } from 'tinymce';
import type { EditorEvent, TinyMCE, Editor as TinyMCEEditor } from 'tinymce';

import type { IAllProps } from './components/Editor';
import { eventPropTypes, type IEventPropTypes } from './components/EditorPropTypes';
import { getTinymce } from './TinyMCE';

export const isFunction = (x: unknown): x is Function => typeof x === 'function';
Expand Down Expand Up @@ -53,7 +54,7 @@ export const configHandlers = (
lookup,
editor.on.bind(editor),
editor.off.bind(editor),
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument

(handlerLookup, key) => (e) => handlerLookup(key)?.(e, editor),
prevProps,
props,
Expand Down Expand Up @@ -85,9 +86,9 @@ const normalizePluginArray = (plugins?: string | string[]): string[] => {
// eslint-disable-next-line max-len
export const mergePlugins = (initPlugins: string | string[] | undefined, inputPlugins: string | string[] | undefined): string[] => normalizePluginArray(initPlugins).concat(normalizePluginArray(inputPlugins));

export const isBeforeInputEventAvailable = () => window.InputEvent && typeof (InputEvent.prototype as any).getTargetRanges === 'function';
export const isBeforeInputEventAvailable = (): boolean => window.InputEvent && typeof (InputEvent.prototype as any).getTargetRanges === 'function';

export const isInDoc = (elem: Node) => {
export const isInDoc = (elem: Node): boolean => {
if (!('isConnected' in Node.prototype)) {
// Fallback for IE and old Edge
let current = elem;
Expand All @@ -102,7 +103,7 @@ export const isInDoc = (elem: Node) => {
return elem.isConnected;
};

export const setMode = (editor: TinyMCEEditor | undefined, mode: 'readonly' | 'design') => {
export const setMode = (editor: TinyMCEEditor | undefined, mode: 'readonly' | 'design'): void => {
if (editor !== undefined) {
if (editor.mode != null && typeof editor.mode === 'object' && typeof editor.mode.set === 'function') {
editor.mode.set(mode);
Expand All @@ -112,7 +113,7 @@ export const setMode = (editor: TinyMCEEditor | undefined, mode: 'readonly' | 'd
}
};

export const getTinymceOrError = (view: Window) => {
export const getTinymceOrError = (view: Window): TinyMCE => {
const tinymce = getTinymce(view);
if (!tinymce) {
throw new Error('tinymce should have been loaded into global scope');
Expand All @@ -121,4 +122,4 @@ export const getTinymceOrError = (view: Window) => {
return tinymce;
};

export const isDisabledOptionSupported = (editor: TinyMCEEditor) => editor.options && editor.options.isRegistered('disabled');
export const isDisabledOptionSupported = (editor: TinyMCEEditor): boolean => editor.options && editor.options.isRegistered('disabled');
28 changes: 17 additions & 11 deletions src/main/ts/components/Editor.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
import * as React from 'react';
import type { Bookmark, EditorEvent, TinyMCE, Editor as TinyMCEEditor } from 'tinymce';
import { IEvents } from '../Events';
import { ScriptItem, ScriptLoader } from '../ScriptLoader2';
import { configHandlers, isBeforeInputEventAvailable,
isFunction, isInDoc, isTextareaOrInput, mergePlugins,
setMode, uuid, isDisabledOptionSupported,
getTinymceOrError } from '../Utils';
import { EditorPropTypes, IEditorPropTypes } from './EditorPropTypes';

import type { IEvents } from '../Events';
import { type ScriptItem, ScriptLoader } from '../ScriptLoader2';
import { getTinymce } from '../TinyMCE';
import {
configHandlers,
getTinymceOrError,
isBeforeInputEventAvailable,
isDisabledOptionSupported,
isFunction, isInDoc, isTextareaOrInput, mergePlugins,
setMode, uuid
} from '../Utils';

import { EditorPropTypes, type IEditorPropTypes } from './EditorPropTypes';

const changeEvents = 'change keyup compositionend setcontent CommentChange';

Expand Down Expand Up @@ -175,7 +181,7 @@ export class Editor extends React.Component<IAllProps> {
return this.elementRef.current?.ownerDocument.defaultView ?? window;
}

public componentDidUpdate(prevProps: Partial<IAllProps>) {
public componentDidUpdate(prevProps: Partial<IAllProps>): void {
if (this.rollbackTimer) {
clearTimeout(this.rollbackTimer);
this.rollbackTimer = undefined;
Expand Down Expand Up @@ -235,7 +241,7 @@ export class Editor extends React.Component<IAllProps> {
}
}

public componentDidMount() {
public componentDidMount(): void {
if (getTinymce(this.view) !== null) {
this.initialise();
} else if (Array.isArray(this.props.tinymceScriptSrc) && this.props.tinymceScriptSrc.length === 0) {
Expand All @@ -258,7 +264,7 @@ export class Editor extends React.Component<IAllProps> {
}
}

public componentWillUnmount() {
public componentWillUnmount(): void {
const editor = this.editor;
if (editor) {
editor.off(changeEvents, this.handleEditorChange);
Expand All @@ -275,7 +281,7 @@ export class Editor extends React.Component<IAllProps> {
}
}

public render() {
public render(): React.ReactElement {
return this.inline ? this.renderInline() : this.renderIframe();
}

Expand Down
2 changes: 2 additions & 0 deletions src/main/ts/components/EditorPropTypes.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import * as PropTypes from 'prop-types';

import { IEvents } from '../Events';

import { IProps } from './Editor';

export type CopyProps<T> = { [P in keyof T]: PropTypes.Requireable<unknown> };
Expand Down
1 change: 1 addition & 0 deletions src/stories/Editor.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { StoryObj } from '@storybook/react';
import React from 'react';
import { EditorEvent, Events, Editor as TinyMCEEditor } from 'tinymce';

import { Editor, IAllProps } from '../main/ts/components/Editor';

const apiKey = 'qagffr3pkuv17a8on1afax661irst1hbr4e6tbv888sz91jc';
Expand Down
9 changes: 5 additions & 4 deletions src/test/ts/alien/Loader.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { before, context } from '@ephox/bedrock-client';
import { Fun, Optional } from '@ephox/katamari';
import { Remove, SugarElement, SugarNode } from '@ephox/sugar';
import { VersionLoader } from '@tinymce/miniature';
import * as React from 'react';
import * as ReactDOMClient from 'react-dom/client';
import { Editor, IAllProps, IProps, Version } from '../../../main/ts/components/Editor';
import { Editor as TinyMCEEditor } from 'tinymce';
import { before, context } from '@ephox/bedrock-client';
import { VersionLoader } from '@tinymce/miniature';
import { setMode } from 'src/main/ts/Utils';
import { Editor as TinyMCEEditor } from 'tinymce';

import { Editor, IAllProps, IProps, Version } from '../../../main/ts/components/Editor';

// @ts-expect-error Remove when dispose polyfill is not needed
Symbol.dispose ??= Symbol('Symbol.dispose');
Expand Down
18 changes: 12 additions & 6 deletions src/test/ts/alien/TestHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,20 @@ interface EventHandlerArgs<T> {
editor: TinyMCEEditor;
}

interface EventStore {
each: <T>(name: string, assertState: (state: EventHandlerArgs<T>[]) => void) => void;
createHandler: <T>(name: string) => HandlerType<T>;
clearState: () => void;
}

type HandlerType<A> = (a: A, editor: TinyMCEEditor) => unknown;

const VERSIONS: Version[] = [ '5', '6', '7', '8' ];
const CLOUD_VERSIONS: Version[] = [ '5', '6', '7', '8' ];

const VALID_API_KEY = 'qagffr3pkuv17a8on1afax661irst1hbr4e6tbv888sz91jc';

const EventStore = () => {
const EventStore = (): EventStore => {
const state: Cell<Record<string, EventHandlerArgs<unknown>[]>> = Cell({});

const createHandler = <T>(name: string): HandlerType<T> => (event: T, editor) => {
Expand Down Expand Up @@ -48,9 +54,9 @@ const EventStore = () => {
};

export {
VALID_API_KEY,
EventStore,
VERSIONS,
CLOUD_VERSIONS,
Version
};
EventStore,
VALID_API_KEY,
Version,
VERSIONS
};
8 changes: 4 additions & 4 deletions src/test/ts/browser/EditorBehaviorTest.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { PlatformDetection } from '@ephox/sand';
import * as Loader from '../alien/Loader';

import { describe, it } from '@ephox/bedrock-client';

import { Assertions, Waiter } from '@ephox/agar';
import { describe, it } from '@ephox/bedrock-client';
import { TinyAssertions, TinySelections } from '@ephox/mcagar';
import { PlatformDetection } from '@ephox/sand';
import { EditorEvent, Events, Editor as TinyMCEEditor } from 'tinymce';

import { getTinymce } from '../../../main/ts/TinyMCE';
import * as Loader from '../alien/Loader';
import { EventStore, VERSIONS } from '../alien/TestHelpers';

type SetContentEvent = EditorEvent<Events.EditorEventMap['SetContent']>;
Expand Down
3 changes: 2 additions & 1 deletion src/test/ts/browser/EditorDisabledTest.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Assertions, Waiter } from '@ephox/agar';
import { context, describe, it } from '@ephox/bedrock-client';

import * as Loader from '../alien/Loader';
import { Assertions, Waiter } from '@ephox/agar';

describe('EditorDisabledTest', () => {

Expand Down
6 changes: 3 additions & 3 deletions src/test/ts/browser/EditorInitTest.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { Assertions } from '@ephox/agar';
import { context, describe, it } from '@ephox/bedrock-client';

import { VALID_API_KEY, VERSIONS } from '../alien/TestHelpers';
import * as Loader from '../alien/Loader';
import { TinyAssertions } from '@ephox/mcagar';
import { IAllProps } from 'src/main/ts';

import * as Loader from '../alien/Loader';
import { VALID_API_KEY, VERSIONS } from '../alien/TestHelpers';

const assertProperty = (obj: {}, propName: string, expected: unknown) => {
Assertions.assertEq(propName.toString() + ' should be ' + expected, expected, (obj as any)[propName]);
};
Expand Down
Loading