You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
594 lines
18 KiB
594 lines
18 KiB
:packageName: tinymce-react
|
|
|
|
ifeval::["{productUse}" == "bundle"]
|
|
IMPORTANT: {companyname} does not recommend bundling the `tinymce` package. Bundling {productname} can be complex and error prone.
|
|
|
|
endif::[]
|
|
The https://github.com/tinymce/tinymce-react[Official {productname} React component] integrates {productname} into React projects. This procedure creates a https://github.com/vitejs/vite-plugin-react-swc[basic React application] containing a {productname} editor.
|
|
|
|
For examples of the {productname} integration, visit https://tinymce.github.io/tinymce-react/[the tinymce-react storybook].
|
|
|
|
== Prerequisites
|
|
|
|
This procedure requires https://nodejs.org/[Node.js (and npm)].
|
|
|
|
== Procedure
|
|
|
|
. Use the https://github.com/vitejs/vite[Vite] package and the https://github.com/vitejs/vite-plugin-react-swc[React SWC plugin] to create a new React project named `+tinymce-react-demo+`.
|
|
+
|
|
[source,sh]
|
|
----
|
|
# npm 7+, extra double-dash is needed
|
|
npm create vite@5 tinymce-react-demo -- --template react-swc
|
|
----
|
|
. Change to the newly created directory.
|
|
+
|
|
[source,sh]
|
|
----
|
|
cd tinymce-react-demo
|
|
----
|
|
|
|
ifeval::["{productSource}" == "cloud"]
|
|
. Install the `+@tinymce/tinymce-react+` package.
|
|
+
|
|
[source,sh]
|
|
----
|
|
npm install @tinymce/tinymce-react
|
|
----
|
|
|
|
. Using a text editor, open `+./src/App.jsx+` and replace the contents with:
|
|
+
|
|
[source,jsx]
|
|
----
|
|
import { useRef } from 'react';
|
|
import { Editor } from '@tinymce/tinymce-react';
|
|
import './App.css';
|
|
|
|
export default function App() {
|
|
const editorRef = useRef(null);
|
|
const log = () => {
|
|
if (editorRef.current) {
|
|
console.log(editorRef.current.getContent());
|
|
}
|
|
};
|
|
|
|
return (
|
|
<>
|
|
<Editor
|
|
apiKey='no-api-key'
|
|
onInit={ (_evt, editor) => editorRef.current = editor }
|
|
initialValue="<p>This is the initial content of the editor.</p>"
|
|
init={{
|
|
height: 500,
|
|
menubar: false,
|
|
plugins: [
|
|
'advlist', 'autolink', 'lists', 'link', 'image', 'charmap', 'preview',
|
|
'anchor', 'searchreplace', 'visualblocks', 'code', 'fullscreen',
|
|
'insertdatetime', 'media', 'table', 'code', 'help', 'wordcount'
|
|
],
|
|
toolbar: 'undo redo | blocks | ' +
|
|
'bold italic forecolor | alignleft aligncenter ' +
|
|
'alignright alignjustify | bullist numlist outdent indent | ' +
|
|
'removeformat | help',
|
|
content_style: 'body { font-family:Helvetica,Arial,sans-serif; font-size:14px }'
|
|
}}
|
|
/>
|
|
<button onClick={log}>Log editor content</button>
|
|
</>
|
|
);
|
|
}
|
|
----
|
|
+
|
|
This JavaScript file will create a component "`+App+`" containing a {productname} editor configured with basic features.
|
|
|
|
. Update the `+apiKey+` option in the editor element and include your link:{accountsignup}/[{cloudname} API key].
|
|
endif::[]
|
|
ifeval::["{productSource}" == "package-manager"]
|
|
ifeval::["{productUse}" == "host"]
|
|
. Install the `+tinymce+`, `+@tinymce/tinymce-react+` and `+fs-extra+` packages.
|
|
+
|
|
[source,sh]
|
|
----
|
|
npm install tinymce @tinymce/tinymce-react fs-extra
|
|
----
|
|
|
|
. Setup a `postinstall` script to copy {productname} to the public directory for hosting
|
|
+
|
|
.postinstall.js
|
|
[source,js]
|
|
----
|
|
import fse from 'fs-extra';
|
|
import path from 'path';
|
|
const topDir = import.meta.dirname;
|
|
fse.emptyDirSync(path.join(topDir, 'public', 'tinymce'));
|
|
fse.copySync(path.join(topDir, 'node_modules', 'tinymce'), path.join(topDir, 'public', 'tinymce'), { overwrite: true });
|
|
----
|
|
+
|
|
.package.json
|
|
[source,json]
|
|
----
|
|
{
|
|
// ... other content omitted for brevity ...
|
|
"scripts": {
|
|
// ... other scripts omitted for brevity ...
|
|
"postinstall": "node ./postinstall.js"
|
|
}
|
|
}
|
|
----
|
|
+
|
|
..gitignore
|
|
[source,.gitignore]
|
|
----
|
|
# ... other rules omitted for brevity ...
|
|
/public/tinymce/
|
|
----
|
|
|
|
. Run the `postinstall` to copy {productname} to the `public` directory
|
|
+
|
|
[source,sh]
|
|
----
|
|
npm run postinstall
|
|
----
|
|
|
|
. Using a text editor, open `+./src/App.jsx+` and replace the contents with:
|
|
+
|
|
[source,jsx]
|
|
----
|
|
import { useRef } from 'react';
|
|
import { Editor } from '@tinymce/tinymce-react';
|
|
import './App.css';
|
|
|
|
export default function App() {
|
|
const editorRef = useRef(null);
|
|
const log = () => {
|
|
if (editorRef.current) {
|
|
console.log(editorRef.current.getContent());
|
|
}
|
|
};
|
|
return (
|
|
<>
|
|
<Editor
|
|
tinymceScriptSrc='/tinymce/tinymce.min.js'
|
|
licenseKey='your-license-key'
|
|
onInit={(_evt, editor) => editorRef.current = editor}
|
|
initialValue='<p>This is the initial content of the editor.</p>'
|
|
init={{
|
|
height: 500,
|
|
menubar: false,
|
|
plugins: [
|
|
'advlist', 'autolink', 'lists', 'link', 'image', 'charmap',
|
|
'anchor', 'searchreplace', 'visualblocks', 'code', 'fullscreen',
|
|
'insertdatetime', 'media', 'table', 'preview', 'help', 'wordcount'
|
|
],
|
|
toolbar: 'undo redo | blocks | ' +
|
|
'bold italic forecolor | alignleft aligncenter ' +
|
|
'alignright alignjustify | bullist numlist outdent indent | ' +
|
|
'removeformat | help',
|
|
content_style: 'body { font-family:Helvetica,Arial,sans-serif; font-size:14px }'
|
|
}}
|
|
/>
|
|
<button onClick={log}>Log editor content</button>
|
|
</>
|
|
);
|
|
}
|
|
----
|
|
|
|
. Update the `+licenseKey+` option in the editor element and include your xref:license-key.adoc[License Key].
|
|
|
|
endif::[]
|
|
ifeval::["{productUse}" == "bundle"]
|
|
. Install the `+tinymce+` and `+@tinymce/tinymce-react+` packages
|
|
+
|
|
[source,sh]
|
|
----
|
|
npm install tinymce @tinymce/tinymce-react
|
|
----
|
|
|
|
. Using a text editor, create `+./src/BundledEditor.jsx+` and set the contents to:
|
|
+
|
|
[source,jsx]
|
|
----
|
|
import { Editor } from '@tinymce/tinymce-react';
|
|
|
|
// TinyMCE so the global var exists
|
|
import 'tinymce/tinymce';
|
|
// DOM model
|
|
import 'tinymce/models/dom/model'
|
|
// Theme
|
|
import 'tinymce/themes/silver';
|
|
// Toolbar icons
|
|
import 'tinymce/icons/default';
|
|
// Editor styles
|
|
import 'tinymce/skins/ui/oxide/skin';
|
|
|
|
// importing the plugin js.
|
|
// if you use a plugin that is not listed here the editor will fail to load
|
|
import 'tinymce/plugins/advlist';
|
|
import 'tinymce/plugins/anchor';
|
|
import 'tinymce/plugins/autolink';
|
|
import 'tinymce/plugins/autoresize';
|
|
import 'tinymce/plugins/autosave';
|
|
import 'tinymce/plugins/charmap';
|
|
import 'tinymce/plugins/code';
|
|
import 'tinymce/plugins/codesample';
|
|
import 'tinymce/plugins/directionality';
|
|
import 'tinymce/plugins/emoticons';
|
|
import 'tinymce/plugins/fullscreen';
|
|
import 'tinymce/plugins/help';
|
|
import 'tinymce/plugins/help/js/i18n/keynav/en';
|
|
import 'tinymce/plugins/image';
|
|
import 'tinymce/plugins/importcss';
|
|
import 'tinymce/plugins/insertdatetime';
|
|
import 'tinymce/plugins/link';
|
|
import 'tinymce/plugins/lists';
|
|
import 'tinymce/plugins/media';
|
|
import 'tinymce/plugins/nonbreaking';
|
|
import 'tinymce/plugins/pagebreak';
|
|
import 'tinymce/plugins/preview';
|
|
import 'tinymce/plugins/quickbars';
|
|
import 'tinymce/plugins/save';
|
|
import 'tinymce/plugins/searchreplace';
|
|
import 'tinymce/plugins/table';
|
|
import 'tinymce/plugins/visualblocks';
|
|
import 'tinymce/plugins/visualchars';
|
|
import 'tinymce/plugins/wordcount';
|
|
|
|
// importing plugin resources
|
|
import 'tinymce/plugins/emoticons/js/emojis';
|
|
|
|
// Content styles, including inline UI like fake cursors
|
|
import 'tinymce/skins/content/default/content';
|
|
import 'tinymce/skins/ui/oxide/content';
|
|
|
|
export default function BundledEditor(props) {
|
|
return (
|
|
<Editor
|
|
licenseKey='your-license-key'
|
|
{...props}
|
|
/>
|
|
);
|
|
}
|
|
----
|
|
|
|
. Update the `+licenseKey+` option in the editor element and include your xref:license-key.adoc[License Key].
|
|
|
|
. Using a text editor, open `+./src/App.jsx+` and replace the contents with:
|
|
+
|
|
[source,jsx]
|
|
----
|
|
import { useRef } from 'react';
|
|
import BundledEditor from './BundledEditor'
|
|
import './App.css';
|
|
|
|
export default function App() {
|
|
const editorRef = useRef(null);
|
|
const log = () => {
|
|
if (editorRef.current) {
|
|
console.log(editorRef.current.getContent());
|
|
}
|
|
};
|
|
|
|
return (
|
|
<>
|
|
<BundledEditor
|
|
onInit={(_evt, editor) => editorRef.current = editor}
|
|
initialValue='<p>This is the initial content of the editor.</p>'
|
|
init={{
|
|
height: 500,
|
|
menubar: false,
|
|
plugins: [
|
|
'advlist', 'anchor', 'autolink', 'help', 'image', 'link', 'lists',
|
|
'searchreplace', 'table', 'wordcount'
|
|
],
|
|
toolbar: 'undo redo | blocks | ' +
|
|
'bold italic forecolor | alignleft aligncenter ' +
|
|
'alignright alignjustify | bullist numlist outdent indent | ' +
|
|
'removeformat | help',
|
|
content_style: 'body { font-family:Helvetica,Arial,sans-serif; font-size:14px }'
|
|
}}
|
|
/>
|
|
<button onClick={log}>Log editor content</button>
|
|
</>
|
|
);
|
|
}
|
|
----
|
|
endif::[]
|
|
endif::[]
|
|
ifeval::["{productSource}" == "zip"]
|
|
ifeval::["{productUse}" == "host"]
|
|
. Install the `+@tinymce/tinymce-react+` package.
|
|
[source,sh]
|
|
----
|
|
npm install @tinymce/tinymce-react
|
|
----
|
|
|
|
. Unzip the content of the `+tinymce/js+` folder from the link:{download-enterprise}[{productname} zip] into the `+public+` folder. Afterwards the directory listing should be similar to below:
|
|
+
|
|
.> `tree -L 2 public`
|
|
[source,text]
|
|
----
|
|
public
|
|
├── favicon.ico
|
|
├── index.html
|
|
├── logo192.png
|
|
├── logo512.png
|
|
├── manifest.json
|
|
├── robots.txt
|
|
└── tinymce
|
|
├── icons
|
|
├── langs
|
|
├── license.txt
|
|
├── models
|
|
├── plugins
|
|
├── skins
|
|
├── themes
|
|
├── tinymce.d.ts
|
|
└── tinymce.min.js
|
|
----
|
|
|
|
. Using a text editor, open `+./eslint.config.js` and add `+'src/tinymce'+` to the `+ignores+` array.
|
|
+
|
|
.Diff of `.eslint.config.js`
|
|
[source,patch]
|
|
----
|
|
export default tseslint.config(
|
|
- { ignores: ['dist'] },
|
|
+ { ignores: ['dist', 'src/tinymce'] },
|
|
{
|
|
extends: [js.configs.recommended, ...tseslint.configs.recommended],
|
|
files: ['**/*.{ts,tsx}'],
|
|
----
|
|
|
|
. Using a text editor, open `+./src/App.jsx+` and replace the contents with:
|
|
+
|
|
[source,jsx]
|
|
----
|
|
import { useRef } from 'react';
|
|
import { Editor } from '@tinymce/tinymce-react';
|
|
import './App.css';
|
|
|
|
export default function App() {
|
|
const editorRef = useRef(null);
|
|
const log = () => {
|
|
if (editorRef.current) {
|
|
console.log(editorRef.current.getContent());
|
|
}
|
|
};
|
|
return (
|
|
<>
|
|
<Editor
|
|
tinymceScriptSrc='/tinymce/tinymce.min.js'
|
|
licenseKey='your-license-key'
|
|
onInit={(_evt, editor) => editorRef.current = editor}
|
|
initialValue='<p>This is the initial content of the editor.</p>'
|
|
init={{
|
|
height: 500,
|
|
menubar: false,
|
|
plugins: [
|
|
'advlist', 'autolink', 'lists', 'link', 'image', 'charmap',
|
|
'anchor', 'searchreplace', 'visualblocks', 'code', 'fullscreen',
|
|
'insertdatetime', 'media', 'table', 'preview', 'help', 'wordcount'
|
|
],
|
|
toolbar: 'undo redo | blocks | ' +
|
|
'bold italic forecolor | alignleft aligncenter ' +
|
|
'alignright alignjustify | bullist numlist outdent indent | ' +
|
|
'removeformat | help',
|
|
content_style: 'body { font-family:Helvetica,Arial,sans-serif; font-size:14px }'
|
|
}}
|
|
/>
|
|
<button onClick={log}>Log editor content</button>
|
|
</>
|
|
);
|
|
}
|
|
----
|
|
. Update the `+licenseKey+` option in the editor element and include your xref:license-key.adoc[License Key].
|
|
endif::[]
|
|
ifeval::["{productUse}" == "bundle"]
|
|
|
|
. Install the `+@tinymce/tinymce-react+` and `+script-loader+` packages.
|
|
+
|
|
[source,sh]
|
|
----
|
|
npm install @tinymce/tinymce-react script-loader
|
|
----
|
|
|
|
. Unzip the content of the `+tinymce/js+` folder from the link:{download-enterprise}[{productname} zip] into the `+src+` folder. Afterwards the directory listing should be similar to below:
|
|
+
|
|
.> `tree -L 2 src`
|
|
[source,text]
|
|
----
|
|
src
|
|
├── App.css
|
|
├── App.js
|
|
├── App.test.js
|
|
├── index.css
|
|
├── index.js
|
|
├── logo.svg
|
|
├── reportWebVitals.js
|
|
├── setupTests.js
|
|
└── tinymce
|
|
├── icons
|
|
├── langs
|
|
├── license.txt
|
|
├── models
|
|
├── plugins
|
|
├── skins
|
|
├── themes
|
|
├── tinymce.d.ts
|
|
└── tinymce.min.js
|
|
----
|
|
|
|
. Using a text editor, open `+./eslint.config.js+` and add `+'src/tinymce'+` to the `+ignores+` array.
|
|
+
|
|
.Diff of `.eslint.config.js`
|
|
[source,patch]
|
|
----
|
|
diff --git a/eslint.config.js b/eslint.config.js
|
|
index 092408a..1ab8db4 100644
|
|
--- a/eslint.config.js
|
|
+++ b/eslint.config.js
|
|
@@ -5,7 +5,7 @@ import reactRefresh from 'eslint-plugin-react-refresh'
|
|
import tseslint from 'typescript-eslint'
|
|
|
|
export default tseslint.config(
|
|
- { ignores: ['dist'] },
|
|
+ { ignores: ['dist', 'src/tinymce'] },
|
|
{
|
|
extends: [js.configs.recommended, ...tseslint.configs.recommended],
|
|
files: ['**/*.{ts,tsx}'],
|
|
----
|
|
|
|
. Using a text editor, create `+./src/BundledEditor.jsx+` and set the contents to:
|
|
+
|
|
[source,jsx]
|
|
----
|
|
import { Editor } from '@tinymce/tinymce-react';
|
|
|
|
// TinyMCE so the global var exists
|
|
import './tinymce/tinymce.min.js';
|
|
// DOM model
|
|
import './tinymce/models/dom/model.min.js'
|
|
// Theme
|
|
import './tinymce/themes/silver/theme.min.js';
|
|
// Toolbar icons
|
|
import './tinymce/icons/default/icons.min.js';
|
|
// Editor styles
|
|
import './tinymce/skins/ui/oxide/skin.min.js';
|
|
|
|
// importing the plugin index.js file.
|
|
// if you use a plugin that is not listed here the editor will fail to load
|
|
import './tinymce/plugins/advlist';
|
|
import './tinymce/plugins/anchor';
|
|
import './tinymce/plugins/autolink';
|
|
import './tinymce/plugins/autoresize';
|
|
import './tinymce/plugins/autosave';
|
|
import './tinymce/plugins/charmap';
|
|
import './tinymce/plugins/code';
|
|
import './tinymce/plugins/codesample';
|
|
import './tinymce/plugins/directionality';
|
|
import './tinymce/plugins/emoticons';
|
|
import './tinymce/plugins/fullscreen';
|
|
import './tinymce/plugins/help';
|
|
import './tinymce/plugins/image';
|
|
import './tinymce/plugins/importcss';
|
|
import './tinymce/plugins/insertdatetime';
|
|
import './tinymce/plugins/link';
|
|
import './tinymce/plugins/lists';
|
|
import './tinymce/plugins/media';
|
|
import './tinymce/plugins/nonbreaking';
|
|
import './tinymce/plugins/pagebreak';
|
|
import './tinymce/plugins/preview';
|
|
import './tinymce/plugins/quickbars';
|
|
import './tinymce/plugins/save';
|
|
import './tinymce/plugins/searchreplace';
|
|
import './tinymce/plugins/table';
|
|
import './tinymce/plugins/visualblocks';
|
|
import './tinymce/plugins/visualchars';
|
|
import './tinymce/plugins/wordcount';
|
|
|
|
// importing plugin resources
|
|
import './tinymce/plugins/emoticons/js/emojis.js';
|
|
|
|
// Content styles, including inline UI like fake cursors
|
|
import './tinymce/skins/content/default/content.js';
|
|
import './tinymce/skins/ui/oxide/content.js';
|
|
|
|
export default function BundledEditor(props) {
|
|
return (
|
|
<Editor
|
|
licenseKey='your-lisense-key'
|
|
{...props}
|
|
/>
|
|
);
|
|
}
|
|
----
|
|
|
|
. Update the `+licenseKey+` option in the editor element and include your xref:license-key.adoc[License Key].
|
|
|
|
. Using a text editor, open `+./src/App.jsx+` and replace the contents with:
|
|
+
|
|
[source,jsx]
|
|
----
|
|
import { useRef } from 'react';
|
|
import BundledEditor from './BundledEditor'
|
|
import './App.css';
|
|
|
|
export default function App() {
|
|
const editorRef = useRef(null);
|
|
const log = () => {
|
|
if (editorRef.current) {
|
|
console.log(editorRef.current.getContent());
|
|
}
|
|
};
|
|
return (
|
|
<>
|
|
<BundledEditor
|
|
onInit={(_evt, editor) => editorRef.current = editor}
|
|
initialValue='<p>This is the initial content of the editor.</p>'
|
|
init={{
|
|
height: 500,
|
|
menubar: false,
|
|
plugins: [
|
|
'advlist', 'anchor', 'autolink', 'help', 'image', 'link', 'lists',
|
|
'searchreplace', 'table', 'wordcount'
|
|
],
|
|
toolbar: 'undo redo | blocks | ' +
|
|
'bold italic forecolor | alignleft aligncenter ' +
|
|
'alignright alignjustify | bullist numlist outdent indent | ' +
|
|
'removeformat | help',
|
|
content_style: 'body { font-family:Helvetica,Arial,sans-serif; font-size:14px }'
|
|
}}
|
|
/>
|
|
<button onClick={log}>Log editor content</button>
|
|
</>
|
|
);
|
|
}
|
|
----
|
|
endif::[]
|
|
endif::[]
|
|
|
|
. Test the application using the Node.js development server.
|
|
+
|
|
* To start the development server, navigate to the `+tinymce-react-demo+` directory and run:
|
|
+
|
|
[source,sh]
|
|
----
|
|
npm run dev
|
|
----
|
|
|
|
* To stop the development server, select on the command line or command prompt and press _Ctrl+C_.
|
|
|
|
== Deploying the application to a HTTP server
|
|
|
|
The application will require further configuration before it can be deployed to a production environment. For information on configuring the application for deployment, see: https://vitejs.dev/guide/build[Building for Production] or https://vitejs.dev/guide/static-deploy.html[Deploying a Static Site].
|
|
|
|
To deploy the application to a local HTTP Server:
|
|
|
|
. Navigate to the `+tinymce-react-demo+` directory and run:
|
|
+
|
|
[source,sh]
|
|
----
|
|
npm run build
|
|
----
|
|
. You can optionally preview the production build by running:
|
|
+
|
|
[source,sh]
|
|
----
|
|
npm run preview
|
|
----
|
|
. Copy the contents of the `+tinymce-react-demo/dist+` directory to the root directory of the web server.
|
|
|
|
The application has now been deployed on the web server.
|
|
|
|
NOTE: Additional configuration is required to deploy the application outside the web server root directory, such as +http://localhost:<port>/my_react_application+.
|
|
|
|
== Next Steps
|
|
|
|
ifeval::["{productUse}" == "bundle"]
|
|
* For information on bundling, see: xref:introduction-to-bundling-tinymce.adoc[]
|
|
endif::[]
|
|
* For examples of the {productname} integration, see: https://tinymce.github.io/tinymce-react/[the tinymce-react storybook].
|
|
* For information on customizing:
|
|
** {productname} integration, see: xref:react-ref.adoc[].
|
|
** {productname}, see: xref:basic-setup.adoc[].
|
|
** The React application, see: https://vitejs.dev/guide/#getting-started[Getting Started with Vite] or https://react.dev/learn[the React documentation].
|