Welcome to the OpenTiny monorepo. For OpenTiny itself look to the modules/tinymce folder.
As TinyMCE transitioned to a modern codebase through 2017 and 2018 many external dependencies were added from previously closed-source projects. This became unwieldy to develop, so in June 2019 the decision was made to bring those projects together in a monorepo.
This repo is built with Yarn workspaces and uses publish tooling support from Lerna. NPM is not supported and attempts to use it will fail.
An important feature of this monorepo is the use of TypeScript 3.0 features "project references" and "build mode": https://www.typescriptlang.org/docs/handbook/project-references.html
Most monorepos use a packages folder to hold the included projects, but we have chosen modules instead. There are few reasons for this:
- These projects are not extra packages of OpenTiny, they are self contained libraries used as module dependencies for the editor.
- Enough examples exist of projects not using
packagesthat we don't think it will be difficult to understand - It tab completes better (
packagesoverlaps withpackage.json)
Install Node.js on your system. Clone this repository on your system
$ git clone https://github.com/mild-blue/opentiny.git
yarn
yarn build
This will produce an editor build in modules/tinymce/js, with distribution zips in modules/tinymce/dist/tinymce_[number].zip.
yarn dev
This performs compilation steps which webpack requires but are usually once-off. It also runs tsc to make later commands faster (tsc -b enforces incremental compilation).
To build the editor in development, use yarn tinymce-grunt. This will output to the modules/tinymce/js folder (build is effectively dev followed by tinymce-grunt).
Task names can be included, for example yarn tinymce-grunt bundle will execute the bundle task. More information on the tinymce-grunt tasks is available in the OpenTiny readme.
There are many top-level helper scripts for OpenTiny and Oxide (the default skin) defined in package.json.
yarn start
This boots the OpenTiny webpack dev server at http://localhost:3000. With this running changes to any .ts source file in the monorepo (excluding tests) should be reflected in WebPack within a few seconds.
yarn watch
runs tsc -b -w for those times when you don't need to iterate in the browser.
yarn tsc
an alias to tsc -b just in case you forget
yarn eslint
runs eslint across the entire repository with the rule set that is required to pass in CI. Use yarn eslint --fix to automatically fix minor problems. The ESLint vscode plugin can be used to apply lint fixes on save.
yarn tinymce-grunt
easy access to the tinymce-grunt commands from the root folder.
yarn oxide-build
yarn oxide-icons-build
These commands build the skin and icons but should not normally be required outside of other development scripts.
yarn oxide-start will set up a watch and rebuild process for creating custom skins.
If you are working in a single module and don't want to deal with the overheads of whole-monorepo compilation, you can run yarn --focus from that module's folder to install the latest published versions of monorepo projects in a local node_modules. For more information see this yarn blog post:
https://yarnpkg.com/blog/2018/05/18/focused-workspaces/
Testing relies on yarn lerna changed to determine which modules need testing, and a grunt script then separates them into two groups depending on whether they need GUI browser testing or can be tested with chrome-headless.
yarn browser-test
yarn headless-test
yarn browser-test-manual
yarn headless-test-manual
Development testing will be adjusted in future so that there's only one manual entry point for ease of development. They are still separate for now because there are two projects that use bedrock route configurations; a route config combination process is required to run them at the same time.
To run a single test: yarn bedrock -f file
To run a whole folder of tests: yarn bedrock -d folder
CI builds rely on the ci and ci-all package.json scripts, in addition to the above testing scripts, to run type checking and linting before executing the full test suite. A ci-local package.json script has also been added for convenience to simulate this process in development and then run tests.
It is important that you never hand-edit a package.json file, particularly the dependency and version fields. And we do mean never. Doing so may break the automated scripts. See the publishing section below for more information.
All dev dependencies are in the project root, so to add or upgrade a specific dependency:
yarn add -D -W <package>
To add a dependency inside a monorepo package:
yarn workspace <fullname> add <othername>
This works whether adding an external dependency or a dependency on another monorepo package.
Note that both names must be the entire scoped name of the package, not the folder, for example
yarn workspace @tinymce/oxide add @tinymce/oxide-icons-default
OpenTiny is published to the public npm registry as opentiny by the
npm-publish.yml GitHub Actions workflow. The process is release-driven:
- Merge your changes to
main. - Create a git tag and a GitHub release for it. Tags follow the upstream-style
6.9.xnumbering — pick the next patch (or minor) version as appropriate. - Creating the release triggers
npm-publish.yml, which installs dependencies, runsyarn build, copiespublish/package.jsonintojs/tinymce, sets the package version from the latest git tag, and publishes thejs/tinymceoutput to npm.
Notes:
- The
versionfields committed in the repository'spackage.jsonfiles are not what gets published — the version is injected from the release tag at publish time. - After publishing a new
opentinyversion, update the pinnedopentinydependency in opentiny-react and create a release there too, so the React wrapper is published against the new editor version.
OpenTiny puts a tinymce object in the global namespace, and has a tree of objects down from there.
If you wish to add to this, you need to do the following:
- Ensure your module is located under
modules/tinymce/src/core/main/ts/api - Expose any types under
interface TinyMCEinmodules/tinymce/src/core/main/ts/api/Tinymce.ts - Expose any objects/functions as part of
const publicApiinmodules/tinymce/src/core/main/ts/api/Tinymce.ts - Ensure your values are exposed in
modules/tinymce/src/core/main/json/globals.json
Ensure the paths all match. e.g. if you're exposing modules/tinymce/src/core/main/ts/api/dom/StyleSheetLoader.ts
- The module is under
.../api/dom/StyleSheetLoader.ts - The type is
TinyMCE.dom.StyleSheetLoader - The constructor function is
publicApi.dom.StyleSheetLoader - globals.json contains
"tinymce.core.api.dom.StyleSheetLoader"