mirror of
https://github.com/codex-team/editor.js
synced 2024-06-10 09:52:36 +02:00
parent
b78707fb78
commit
73ac3e3f5f
77
.github/workflows/bump-version-on-merge-next.yml
vendored
Normal file
77
.github/workflows/bump-version-on-merge-next.yml
vendored
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
name: Bump version on merge
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- next
|
||||||
|
types: [closed]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
# If pull request was merged then we should check for a package version update
|
||||||
|
check-for-no-version-changing:
|
||||||
|
if: github.event.pull_request.merged == true
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
# Checkout to target branch
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
# Get package new version name
|
||||||
|
- name: Get package info
|
||||||
|
id: packageNew
|
||||||
|
uses: codex-team/action-nodejs-package-info@v1
|
||||||
|
|
||||||
|
# Checkout to the base commit before merge
|
||||||
|
- name: Checkout to the base commit before merge
|
||||||
|
run: git checkout ${{ github.event.pull_request.base.sha }}
|
||||||
|
|
||||||
|
# Get package old version name
|
||||||
|
- name: Get package info
|
||||||
|
id: packageOld
|
||||||
|
uses: codex-team/action-nodejs-package-info@v1
|
||||||
|
|
||||||
|
# Stop workflow and do not bump version if it was changed already
|
||||||
|
- name: Stop workflow and do not bump version if it was changed already
|
||||||
|
uses: actions/github-script@v3
|
||||||
|
if: steps.packageOld.outputs.version != steps.packageNew.outputs.version
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
core.setFailed('Version was changed! ${{ steps.packageOld.outputs.version }} -> ${{ steps.packageNew.outputs.version }}')
|
||||||
|
|
||||||
|
bump-version:
|
||||||
|
needs: check-for-no-version-changing
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
# Checkout to target branch
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
# Setup node environment
|
||||||
|
- uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: 15
|
||||||
|
registry-url: https://registry.npmjs.org/
|
||||||
|
|
||||||
|
# Bump version to the next prerelease (patch) with rc suffix
|
||||||
|
- name: Suggest the new version
|
||||||
|
run: yarn version --prerelease --preid rc --no-git-tag-version
|
||||||
|
|
||||||
|
# Get package new version name
|
||||||
|
- name: Get package info
|
||||||
|
id: package
|
||||||
|
uses: codex-team/action-nodejs-package-info@v1
|
||||||
|
|
||||||
|
# Create pull request with changes
|
||||||
|
- name: Create Pull Request
|
||||||
|
uses: peter-evans/create-pull-request@v3
|
||||||
|
with:
|
||||||
|
commit-message: Bump version
|
||||||
|
committer: github-actions <action@github.com>
|
||||||
|
author: github-actions <action@github.com>
|
||||||
|
branch: auto-bump-version
|
||||||
|
base: ${{ steps.vars.outputs.base_branch }}
|
||||||
|
delete-branch: true
|
||||||
|
title: "Bump version up to ${{ steps.package.outputs.version }}"
|
||||||
|
body: |
|
||||||
|
Auto-generated bump version suggestion because of PR:
|
||||||
|
**${{ github.event.pull_request.title }}** #${{ github.event.pull_request.number }}
|
108
.github/workflows/create-a-release-draft.yml
vendored
Normal file
108
.github/workflows/create-a-release-draft.yml
vendored
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
name: Create a release draft
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- next
|
||||||
|
types: [closed]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
# If pull request was merged then we should check for a package version update
|
||||||
|
check-version-changing:
|
||||||
|
if: github.event.pull_request.merged == true
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
# Checkout to target branch
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
# Get package new version name
|
||||||
|
- name: Get package info
|
||||||
|
id: packageNew
|
||||||
|
uses: codex-team/action-nodejs-package-info@v1
|
||||||
|
|
||||||
|
# Checkout to the base commit before merge
|
||||||
|
- name: Checkout to the base commit before merge
|
||||||
|
run: git checkout ${{ github.event.pull_request.base.sha }}
|
||||||
|
|
||||||
|
# Get package old version name
|
||||||
|
- name: Get package info
|
||||||
|
id: packageOld
|
||||||
|
uses: codex-team/action-nodejs-package-info@v1
|
||||||
|
|
||||||
|
# Stop workflow if version was not changed
|
||||||
|
- name: Stop workflow if version was not changed
|
||||||
|
uses: actions/github-script@v3
|
||||||
|
if: steps.packageOld.outputs.version == steps.packageNew.outputs.version
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
core.setFailed('No version changes. ${{ steps.packageOld.outputs.version }}')
|
||||||
|
|
||||||
|
# Create a new draft release
|
||||||
|
release-draft:
|
||||||
|
needs: check-version-changing
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
# Checkout to target branch
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
# Pull submodules
|
||||||
|
submodules: 'recursive'
|
||||||
|
|
||||||
|
# Setup node environment
|
||||||
|
- uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: 15
|
||||||
|
registry-url: https://registry.npmjs.org/
|
||||||
|
|
||||||
|
# Prepare, build and publish project
|
||||||
|
- name: Install dependencies
|
||||||
|
run: yarn
|
||||||
|
|
||||||
|
# Build Editor.js
|
||||||
|
- name: Build output files
|
||||||
|
run: yarn build
|
||||||
|
|
||||||
|
# Get package version name
|
||||||
|
- name: Get package info
|
||||||
|
id: package
|
||||||
|
uses: codex-team/action-nodejs-package-info@v1
|
||||||
|
|
||||||
|
- name: Create Release
|
||||||
|
id: create_release
|
||||||
|
uses: actions/create-release@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
tag_name: v${{ steps.package.outputs.version }}
|
||||||
|
release_name: v${{ steps.package.outputs.version }}
|
||||||
|
|
||||||
|
# Fill release description from pull request body name
|
||||||
|
body: "${{ github.event.pull_request.title }} #${{ github.event.pull_request.number }}"
|
||||||
|
|
||||||
|
# Save as a draft release
|
||||||
|
draft: true
|
||||||
|
|
||||||
|
# If version name contains "-rc" suffix than mark a "pre-release" checkbox
|
||||||
|
prerelease: ${{ contains(steps.package.outputs.version, '-rc') }}
|
||||||
|
|
||||||
|
# Build and upload target Editor.js build to release as artifact
|
||||||
|
- name: Upload Release Asset
|
||||||
|
uses: actions/upload-release-asset@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
|
asset_path: dist/editor.js
|
||||||
|
asset_name: editor.js
|
||||||
|
asset_content_type: application/javascript
|
||||||
|
|
||||||
|
# Send a notification message
|
||||||
|
- name: Send a message
|
||||||
|
uses: codex-team/action-codexbot-notify@v1
|
||||||
|
with:
|
||||||
|
webhook: ${{ secrets.CODEX_BOT_WEBHOOK_FRONTEND }}
|
||||||
|
message: '🦥 [Draft release v${{ steps.package.outputs.version }}](${{ steps.create_release.outputs.html_url }}) for package [${{ steps.package.outputs.name }}](${{ steps.package.outputs.npmjs-link }}) has been created. Add changelog and publish it!'
|
||||||
|
parse_mode: 'markdown'
|
||||||
|
disable_web_page_preview: true
|
53
.github/workflows/publish-package-to-npm.yml
vendored
Normal file
53
.github/workflows/publish-package-to-npm.yml
vendored
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
name: Publish package to NPM
|
||||||
|
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types:
|
||||||
|
- published
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
publish:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
# Checkout to target branch
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
# Pull submodules
|
||||||
|
submodules: 'recursive'
|
||||||
|
|
||||||
|
# Setup node environment
|
||||||
|
- uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: 15
|
||||||
|
registry-url: https://registry.npmjs.org/
|
||||||
|
|
||||||
|
# Prepare, build and publish project
|
||||||
|
- name: Install dependencies
|
||||||
|
run: yarn
|
||||||
|
|
||||||
|
- name: Build output files
|
||||||
|
run: yarn build
|
||||||
|
|
||||||
|
- name: Publish the package
|
||||||
|
run: yarn publish --access=public ${{ github.event.release.prerelease && '--tag=next' || '--tag=latest' }}
|
||||||
|
env:
|
||||||
|
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||||
|
|
||||||
|
notify:
|
||||||
|
needs: publish
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
# Checkout to target branch
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Get package info
|
||||||
|
id: package
|
||||||
|
uses: codex-team/action-nodejs-package-info@v1
|
||||||
|
|
||||||
|
- name: Send a message
|
||||||
|
uses: codex-team/action-codexbot-notify@v1
|
||||||
|
with:
|
||||||
|
webhook: ${{ secrets.CODEX_BOT_NOTIFY_EDITORJS_PUBLIC_CHAT }}
|
||||||
|
message: '📦 [${{ steps.package.outputs.name }}](${{ steps.package.outputs.npmjs-link }}) ${{ steps.package.outputs.version }} was published'
|
||||||
|
parse_mode: 'markdown'
|
||||||
|
disable_web_page_preview: true
|
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -12,3 +12,5 @@ yarn-error.log
|
||||||
|
|
||||||
test/cypress/screenshots
|
test/cypress/screenshots
|
||||||
test/cypress/videos
|
test/cypress/videos
|
||||||
|
|
||||||
|
dist/
|
||||||
|
|
16
.npmignore
16
.npmignore
|
@ -1,19 +1,21 @@
|
||||||
.idea/
|
.idea
|
||||||
build/sprite.svg
|
.github
|
||||||
docs/
|
docs
|
||||||
example/
|
example
|
||||||
src/
|
src
|
||||||
|
test
|
||||||
.babelrc
|
.babelrc
|
||||||
.editorconfig
|
.editorconfig
|
||||||
|
.eslintignore
|
||||||
.eslintrc
|
.eslintrc
|
||||||
.git
|
.git
|
||||||
.gitmodules
|
.gitmodules
|
||||||
.jshintrc
|
.jshintrc
|
||||||
.postcssrc
|
.postcssrc.yml
|
||||||
.stylelintrc
|
.stylelintrc
|
||||||
CODEOWNERS
|
CODEOWNERS
|
||||||
|
cypress.json
|
||||||
tsconfig.json
|
tsconfig.json
|
||||||
tslint.json
|
tslint.json
|
||||||
webpack.config.js
|
webpack.config.js
|
||||||
yarn.lock
|
yarn.lock
|
||||||
.github
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
[![](https://flat.badgen.net/bundlephobia/minzip/@editorjs/editorjs?color=green)](https://www.npmjs.com/package/@editorjs/editorjs)
|
[![](https://flat.badgen.net/bundlephobia/minzip/@editorjs/editorjs?color=green)](https://www.npmjs.com/package/@editorjs/editorjs)
|
||||||
[![Backers on Open Collective](https://opencollective.com/editorjs/backers/badge.svg)](#backers)
|
[![Backers on Open Collective](https://opencollective.com/editorjs/backers/badge.svg)](#backers)
|
||||||
[![Sponsors on Open Collective](https://opencollective.com/editorjs/sponsors/badge.svg)](#sponsors)
|
[![Sponsors on Open Collective](https://opencollective.com/editorjs/sponsors/badge.svg)](#sponsors)
|
||||||
[![](https://flat.badgen.net/npm/license/@editorjs/editorjs)](https://www.npmjs.com/package/@editorjs/editorjs)
|
[![](https://img.shields.io/npm/l/@editorjs/editorjs?style=flat-square)](https://www.npmjs.com/package/@editorjs/editorjs)
|
||||||
[![Join the chat at https://gitter.im/codex-team/editor.js](https://badges.gitter.im/codex-team/editor.js.svg)](https://gitter.im/codex-team/editor.js?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
[![Join the chat at https://gitter.im/codex-team/editor.js](https://badges.gitter.im/codex-team/editor.js.svg)](https://gitter.im/codex-team/editor.js?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||||
|
|
||||||
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari-ios/safari-ios_48x48.png" alt="iOS Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>iOS Safari | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/opera/opera_48x48.png" alt="Opera" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Opera |
|
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari-ios/safari-ios_48x48.png" alt="iOS Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>iOS Safari | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/opera/opera_48x48.png" alt="Opera" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Opera |
|
||||||
|
@ -129,7 +129,6 @@ Choose the most usable method of getting Editor for you.
|
||||||
|
|
||||||
- Node package
|
- Node package
|
||||||
- Source from CDN
|
- Source from CDN
|
||||||
- Local file from project
|
|
||||||
|
|
||||||
##### Option A. NPM install
|
##### Option A. NPM install
|
||||||
|
|
||||||
|
@ -157,9 +156,7 @@ For example, place this in your HTML:
|
||||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/editorjs@latest"></script>
|
<script src="https://cdn.jsdelivr.net/npm/@editorjs/editorjs@latest"></script>
|
||||||
```
|
```
|
||||||
|
|
||||||
##### Option C. Save source within your project
|
Or download the bundle file and use it from your server.
|
||||||
|
|
||||||
Copy the [editor.js](dist/editor.js) file to your project and load it.
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<script src="editor.js"></script>
|
<script src="editor.js"></script>
|
||||||
|
|
2
dist/editor.js
vendored
2
dist/editor.js
vendored
File diff suppressed because one or more lines are too long
67
dist/editor.js.LICENSE.txt
vendored
67
dist/editor.js.LICENSE.txt
vendored
|
@ -1,67 +0,0 @@
|
||||||
/*!
|
|
||||||
* CodeX.Tooltips
|
|
||||||
*
|
|
||||||
* @version 1.0.1
|
|
||||||
*
|
|
||||||
* @licence MIT
|
|
||||||
* @author CodeX <https://codex.so>
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Codex JavaScript Notification module
|
|
||||||
* https://github.com/codex-team/js-notifier
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Editor.js
|
|
||||||
*
|
|
||||||
* @version 2.19.1
|
|
||||||
*
|
|
||||||
* @licence Apache-2.0
|
|
||||||
* @author CodeX <https://codex.so>
|
|
||||||
*
|
|
||||||
* @uses html-janitor
|
|
||||||
* @licence Apache-2.0 (https://github.com/guardian/html-janitor/blob/master/LICENSE)
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Library for handling keyboard shortcuts
|
|
||||||
* @copyright CodeX (https://codex.so)
|
|
||||||
* @license MIT
|
|
||||||
* @author CodeX (https://codex.so)
|
|
||||||
* @version 1.1.1
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If developer uses editor's API, then he can customize sanitize restrictions.
|
|
||||||
* Or, sanitizing config can be defined globally in editors initialization. That config will be used everywhere
|
|
||||||
* At least, if there is no config overrides, that API uses Default configuration
|
|
||||||
*
|
|
||||||
* @see {@link https://www.npmjs.com/package/html-janitor}
|
|
||||||
* @license Apache-2.0
|
|
||||||
* @see {@link https://github.com/guardian/html-janitor/blob/master/LICENSE}
|
|
||||||
*
|
|
||||||
* @param {SanitizerConfig} config - sanitizer extension
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Editor.js
|
|
||||||
*
|
|
||||||
* Short Description (눈_눈;)
|
|
||||||
*
|
|
||||||
* @version 2.18.0
|
|
||||||
*
|
|
||||||
* @license Apache-2.0
|
|
||||||
* @author CodeX-Team <https://ifmo.su>
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base Paragraph Block for the Editor.js.
|
|
||||||
* Represents simple paragraph
|
|
||||||
*
|
|
||||||
* @author CodeX (team@codex.so)
|
|
||||||
* @copyright CodeX 2018
|
|
||||||
* @license The MIT License (MIT)
|
|
||||||
*/
|
|
413
dist/editor.licenses.txt
vendored
413
dist/editor.licenses.txt
vendored
|
@ -1,413 +0,0 @@
|
||||||
@babel/polyfill
|
|
||||||
MIT
|
|
||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2014-present Sebastian McKenzie and other contributors
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
a copy of this software and associated documentation files (the
|
|
||||||
"Software"), to deal in the Software without restriction, including
|
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be
|
|
||||||
included in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
|
|
||||||
@babel/register
|
|
||||||
MIT
|
|
||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2014-present Sebastian McKenzie and other contributors
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
a copy of this software and associated documentation files (the
|
|
||||||
"Software"), to deal in the Software without restriction, including
|
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be
|
|
||||||
included in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
|
|
||||||
@babel/runtime
|
|
||||||
MIT
|
|
||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2014-present Sebastian McKenzie and other contributors
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
a copy of this software and associated documentation files (the
|
|
||||||
"Software"), to deal in the Software without restriction, including
|
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be
|
|
||||||
included in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
|
|
||||||
@codexteam/shortcuts
|
|
||||||
MIT
|
|
||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2018 CodeX
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
|
|
||||||
@editorjs/paragraph
|
|
||||||
MIT
|
|
||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2018 CodeX
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
|
|
||||||
|
|
||||||
codex-notifier
|
|
||||||
MIT
|
|
||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2017 CodeX
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
|
|
||||||
|
|
||||||
codex-tooltip
|
|
||||||
MIT
|
|
||||||
Copyright 2019 CodeX https://codex.so
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
|
|
||||||
core-js
|
|
||||||
MIT
|
|
||||||
Copyright (c) 2014-2019 Denis Pushkarev
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
THE SOFTWARE.
|
|
||||||
|
|
||||||
|
|
||||||
html-janitor
|
|
||||||
Apache License
|
|
||||||
Version 2.0, January 2004
|
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
||||||
|
|
||||||
1. Definitions.
|
|
||||||
|
|
||||||
"License" shall mean the terms and conditions for use, reproduction,
|
|
||||||
and distribution as defined by Sections 1 through 9 of this document.
|
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by
|
|
||||||
the copyright owner that is granting the License.
|
|
||||||
|
|
||||||
"Legal Entity" shall mean the union of the acting entity and all
|
|
||||||
other entities that control, are controlled by, or are under common
|
|
||||||
control with that entity. For the purposes of this definition,
|
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
|
||||||
direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
||||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
||||||
|
|
||||||
"You" (or "Your") shall mean an individual or Legal Entity
|
|
||||||
exercising permissions granted by this License.
|
|
||||||
|
|
||||||
"Source" form shall mean the preferred form for making modifications,
|
|
||||||
including but not limited to software source code, documentation
|
|
||||||
source, and configuration files.
|
|
||||||
|
|
||||||
"Object" form shall mean any form resulting from mechanical
|
|
||||||
transformation or translation of a Source form, including but
|
|
||||||
not limited to compiled object code, generated documentation,
|
|
||||||
and conversions to other media types.
|
|
||||||
|
|
||||||
"Work" shall mean the work of authorship, whether in Source or
|
|
||||||
Object form, made available under the License, as indicated by a
|
|
||||||
copyright notice that is included in or attached to the work
|
|
||||||
(an example is provided in the Appendix below).
|
|
||||||
|
|
||||||
"Derivative Works" shall mean any work, whether in Source or Object
|
|
||||||
form, that is based on (or derived from) the Work and for which the
|
|
||||||
editorial revisions, annotations, elaborations, or other modifications
|
|
||||||
represent, as a whole, an original work of authorship. For the purposes
|
|
||||||
of this License, Derivative Works shall not include works that remain
|
|
||||||
separable from, or merely link (or bind by name) to the interfaces of,
|
|
||||||
the Work and Derivative Works thereof.
|
|
||||||
|
|
||||||
"Contribution" shall mean any work of authorship, including
|
|
||||||
the original version of the Work and any modifications or additions
|
|
||||||
to that Work or Derivative Works thereof, that is intentionally
|
|
||||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
||||||
or by an individual or Legal Entity authorized to submit on behalf of
|
|
||||||
the copyright owner. For the purposes of this definition, "submitted"
|
|
||||||
means any form of electronic, verbal, or written communication sent
|
|
||||||
to the Licensor or its representatives, including but not limited to
|
|
||||||
communication on electronic mailing lists, source code control systems,
|
|
||||||
and issue tracking systems that are managed by, or on behalf of, the
|
|
||||||
Licensor for the purpose of discussing and improving the Work, but
|
|
||||||
excluding communication that is conspicuously marked or otherwise
|
|
||||||
designated in writing by the copyright owner as "Not a Contribution."
|
|
||||||
|
|
||||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
||||||
on behalf of whom a Contribution has been received by Licensor and
|
|
||||||
subsequently incorporated within the Work.
|
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
copyright license to reproduce, prepare Derivative Works of,
|
|
||||||
publicly display, publicly perform, sublicense, and distribute the
|
|
||||||
Work and such Derivative Works in Source or Object form.
|
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
(except as stated in this section) patent license to make, have made,
|
|
||||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
||||||
where such license applies only to those patent claims licensable
|
|
||||||
by such Contributor that are necessarily infringed by their
|
|
||||||
Contribution(s) alone or by combination of their Contribution(s)
|
|
||||||
with the Work to which such Contribution(s) was submitted. If You
|
|
||||||
institute patent litigation against any entity (including a
|
|
||||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
||||||
or a Contribution incorporated within the Work constitutes direct
|
|
||||||
or contributory patent infringement, then any patent licenses
|
|
||||||
granted to You under this License for that Work shall terminate
|
|
||||||
as of the date such litigation is filed.
|
|
||||||
|
|
||||||
4. Redistribution. You may reproduce and distribute copies of the
|
|
||||||
Work or Derivative Works thereof in any medium, with or without
|
|
||||||
modifications, and in Source or Object form, provided that You
|
|
||||||
meet the following conditions:
|
|
||||||
|
|
||||||
(a) You must give any other recipients of the Work or
|
|
||||||
Derivative Works a copy of this License; and
|
|
||||||
|
|
||||||
(b) You must cause any modified files to carry prominent notices
|
|
||||||
stating that You changed the files; and
|
|
||||||
|
|
||||||
(c) You must retain, in the Source form of any Derivative Works
|
|
||||||
that You distribute, all copyright, patent, trademark, and
|
|
||||||
attribution notices from the Source form of the Work,
|
|
||||||
excluding those notices that do not pertain to any part of
|
|
||||||
the Derivative Works; and
|
|
||||||
|
|
||||||
(d) If the Work includes a "NOTICE" text file as part of its
|
|
||||||
distribution, then any Derivative Works that You distribute must
|
|
||||||
include a readable copy of the attribution notices contained
|
|
||||||
within such NOTICE file, excluding those notices that do not
|
|
||||||
pertain to any part of the Derivative Works, in at least one
|
|
||||||
of the following places: within a NOTICE text file distributed
|
|
||||||
as part of the Derivative Works; within the Source form or
|
|
||||||
documentation, if provided along with the Derivative Works; or,
|
|
||||||
within a display generated by the Derivative Works, if and
|
|
||||||
wherever such third-party notices normally appear. The contents
|
|
||||||
of the NOTICE file are for informational purposes only and
|
|
||||||
do not modify the License. You may add Your own attribution
|
|
||||||
notices within Derivative Works that You distribute, alongside
|
|
||||||
or as an addendum to the NOTICE text from the Work, provided
|
|
||||||
that such additional attribution notices cannot be construed
|
|
||||||
as modifying the License.
|
|
||||||
|
|
||||||
You may add Your own copyright statement to Your modifications and
|
|
||||||
may provide additional or different license terms and conditions
|
|
||||||
for use, reproduction, or distribution of Your modifications, or
|
|
||||||
for any such Derivative Works as a whole, provided Your use,
|
|
||||||
reproduction, and distribution of the Work otherwise complies with
|
|
||||||
the conditions stated in this License.
|
|
||||||
|
|
||||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
||||||
any Contribution intentionally submitted for inclusion in the Work
|
|
||||||
by You to the Licensor shall be under the terms and conditions of
|
|
||||||
this License, without any additional terms or conditions.
|
|
||||||
Notwithstanding the above, nothing herein shall supersede or modify
|
|
||||||
the terms of any separate license agreement you may have executed
|
|
||||||
with Licensor regarding such Contributions.
|
|
||||||
|
|
||||||
6. Trademarks. This License does not grant permission to use the trade
|
|
||||||
names, trademarks, service marks, or product names of the Licensor,
|
|
||||||
except as required for reasonable and customary use in describing the
|
|
||||||
origin of the Work and reproducing the content of the NOTICE file.
|
|
||||||
|
|
||||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
||||||
agreed to in writing, Licensor provides the Work (and each
|
|
||||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
implied, including, without limitation, any warranties or conditions
|
|
||||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
||||||
appropriateness of using or redistributing the Work and assume any
|
|
||||||
risks associated with Your exercise of permissions under this License.
|
|
||||||
|
|
||||||
8. Limitation of Liability. In no event and under no legal theory,
|
|
||||||
whether in tort (including negligence), contract, or otherwise,
|
|
||||||
unless required by applicable law (such as deliberate and grossly
|
|
||||||
negligent acts) or agreed to in writing, shall any Contributor be
|
|
||||||
liable to You for damages, including any direct, indirect, special,
|
|
||||||
incidental, or consequential damages of any character arising as a
|
|
||||||
result of this License or out of the use or inability to use the
|
|
||||||
Work (including but not limited to damages for loss of goodwill,
|
|
||||||
work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses), even if such Contributor
|
|
||||||
has been advised of the possibility of such damages.
|
|
||||||
|
|
||||||
9. Accepting Warranty or Additional Liability. While redistributing
|
|
||||||
the Work or Derivative Works thereof, You may choose to offer,
|
|
||||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
||||||
or other liability obligations and/or rights consistent with this
|
|
||||||
License. However, in accepting such obligations, You may act only
|
|
||||||
on Your own behalf and on Your sole responsibility, not on behalf
|
|
||||||
of any other Contributor, and only if You agree to indemnify,
|
|
||||||
defend, and hold each Contributor harmless for any liability
|
|
||||||
incurred by, or claims asserted against, such Contributor by reason
|
|
||||||
of your accepting any such warranty or additional liability.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
APPENDIX: How to apply the Apache License to your work.
|
|
||||||
|
|
||||||
To apply the Apache License to your work, attach the following
|
|
||||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
|
||||||
replaced with your own identifying information. (Don't include
|
|
||||||
the brackets!) The text should be enclosed in the appropriate
|
|
||||||
comment syntax for the file format. We also recommend that a
|
|
||||||
file or class name and description of purpose be included on the
|
|
||||||
same "printed page" as the copyright notice for easier
|
|
||||||
identification within third-party archives.
|
|
||||||
|
|
||||||
Copyright {yyyy} {name of copyright owner}
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
|
|
||||||
|
|
||||||
regenerator-runtime
|
|
||||||
MIT
|
|
||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2014-present, Facebook, Inc.
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
47
dist/sprite.svg
vendored
47
dist/sprite.svg
vendored
|
@ -1,47 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<symbol id="arrow-down" viewBox="0 0 14 14">
|
|
||||||
<path transform="matrix(1 0 0 -1 0 14)" d="M8.024 4.1v8.6a1.125 1.125 0 0 1-2.25 0V4.1L2.18 7.695A1.125 1.125 0 1 1 .59 6.104L6.103.588c.44-.439 1.151-.439 1.59 0l5.516 5.516a1.125 1.125 0 0 1-1.59 1.59L8.023 4.1z"/>
|
|
||||||
|
|
||||||
</symbol>
|
|
||||||
<symbol id="arrow-up" viewBox="0 0 14 14">
|
|
||||||
<path d="M8.024 4.1v8.6a1.125 1.125 0 0 1-2.25 0V4.1L2.18 7.695A1.125 1.125 0 1 1 .59 6.104L6.103.588c.44-.439 1.151-.439 1.59 0l5.516 5.516a1.125 1.125 0 0 1-1.59 1.59L8.023 4.1z"/>
|
|
||||||
|
|
||||||
</symbol>
|
|
||||||
<symbol id="bold" viewBox="0 0 12 14"><path d="M5.997 14H1.72c-.618 0-1.058-.138-1.323-.415C.132 13.308 0 12.867 0 12.262V1.738C0 1.121.135.676.406.406.676.136 1.114 0 1.719 0h4.536c.669 0 1.248.041 1.738.124.49.083.93.242 1.318.478a3.458 3.458 0 0 1 1.461 1.752c.134.366.2.753.2 1.16 0 1.401-.7 2.426-2.1 3.075 1.84.586 2.76 1.726 2.76 3.42 0 .782-.2 1.487-.602 2.114a3.61 3.61 0 0 1-1.623 1.39 5.772 5.772 0 0 1-1.471.377c-.554.073-1.2.11-1.939.11zm-.21-6.217h-2.95v4.087h3.046c1.916 0 2.874-.69 2.874-2.072 0-.707-.248-1.22-.745-1.537-.496-.319-1.238-.478-2.225-.478zM2.837 2.13v3.619h2.597c.707 0 1.252-.067 1.638-.2.385-.134.68-.389.883-.765.16-.267.239-.566.239-.897 0-.707-.252-1.176-.755-1.409-.503-.232-1.27-.348-2.301-.348H2.836z"/>
|
|
||||||
</symbol>
|
|
||||||
<symbol id="cross" viewBox="0 0 237 237">
|
|
||||||
<path transform="rotate(45 280.675 51.325)" d="M191 191V73c0-5.523 4.477-10 10-10h25c5.523 0 10 4.477 10 10v118h118c5.523 0 10 4.477 10 10v25c0 5.523-4.477 10-10 10H236v118c0 5.523-4.477 10-10 10h-25c-5.523 0-10-4.477-10-10V236H73c-5.523 0-10-4.477-10-10v-25c0-5.523 4.477-10 10-10h118z"/>
|
|
||||||
|
|
||||||
</symbol>
|
|
||||||
<symbol id="dots" viewBox="0 0 8 8">
|
|
||||||
<circle cx="6.5" cy="1.5" r="1.5"/>
|
|
||||||
<circle cx="6.5" cy="6.5" r="1.5"/>
|
|
||||||
<circle cx="1.5" cy="1.5" r="1.5"/>
|
|
||||||
<circle cx="1.5" cy="6.5" r="1.5"/>
|
|
||||||
|
|
||||||
</symbol>
|
|
||||||
<symbol id="italic" viewBox="0 0 4 11">
|
|
||||||
<path d="M3.289 4.17L2.164 9.713c-.078.384-.238.674-.48.87-.243.198-.52.296-.831.296-.312 0-.545-.1-.699-.302-.153-.202-.192-.49-.116-.864L1.15 4.225c.077-.38.232-.665.466-.857a1.25 1.25 0 01.818-.288c.312 0 .55.096.713.288.163.192.21.46.141.801zm-.667-2.09c-.295 0-.53-.09-.706-.273-.176-.181-.233-.439-.173-.77.055-.302.207-.55.457-.745C2.45.097 2.716 0 3 0c.273 0 .5.088.68.265.179.176.238.434.177.771-.06.327-.21.583-.45.767-.24.185-.502.277-.785.277z"/>
|
|
||||||
|
|
||||||
</symbol>
|
|
||||||
<symbol id="link" viewBox="0 0 14 10">
|
|
||||||
<path d="M6 0v2H5a3 3 0 000 6h1v2H5A5 5 0 115 0h1zm2 0h1a5 5 0 110 10H8V8h1a3 3 0 000-6H8V0zM5 4h4a1 1 0 110 2H5a1 1 0 110-2z"/>
|
|
||||||
|
|
||||||
</symbol>
|
|
||||||
<symbol id="plus" viewBox="0 0 14 14">
|
|
||||||
<path d="M8.05 5.8h4.625a1.125 1.125 0 0 1 0 2.25H8.05v4.625a1.125 1.125 0 0 1-2.25 0V8.05H1.125a1.125 1.125 0 0 1 0-2.25H5.8V1.125a1.125 1.125 0 0 1 2.25 0V5.8z"/>
|
|
||||||
|
|
||||||
</symbol>
|
|
||||||
<symbol id="sad-face" viewBox="0 0 52 52">
|
|
||||||
<path fill="#D76B6B" fill-rule="nonzero" d="M26 52C11.64 52 0 40.36 0 26S11.64 0 26 0s26 11.64 26 26-11.64 26-26 26zm0-3.25c12.564 0 22.75-10.186 22.75-22.75S38.564 3.25 26 3.25 3.25 13.436 3.25 26 13.436 48.75 26 48.75zM15.708 33.042a2.167 2.167 0 1 1 0-4.334 2.167 2.167 0 0 1 0 4.334zm23.834 0a2.167 2.167 0 1 1 0-4.334 2.167 2.167 0 0 1 0 4.334zm-15.875 5.452a1.083 1.083 0 1 1-1.834-1.155c1.331-2.114 3.49-3.179 6.334-3.179 2.844 0 5.002 1.065 6.333 3.18a1.083 1.083 0 1 1-1.833 1.154c-.913-1.45-2.366-2.167-4.5-2.167s-3.587.717-4.5 2.167z"/>
|
|
||||||
|
|
||||||
</symbol>
|
|
||||||
<symbol id="toggler-down">
|
|
||||||
<path d="M6.5 9.294a.792.792 0 01-.562-.232L2.233 5.356a.794.794 0 011.123-1.123L6.5 7.377l3.144-3.144a.794.794 0 011.123 1.123L7.062 9.062a.792.792 0 01-.562.232z"/>
|
|
||||||
|
|
||||||
</symbol>
|
|
||||||
<symbol id="unlink" viewBox="0 0 15 11">
|
|
||||||
<path d="M13.073 2.099l-1.448 1.448A3 3 0 009 2H8V0h1c1.68 0 3.166.828 4.073 2.099zM6.929 4l-.879.879L7.172 6H5a1 1 0 110-2h1.929zM6 0v2H5a3 3 0 100 6h1v2H5A5 5 0 115 0h1zm6.414 7l2.122 2.121-1.415 1.415L11 8.414l-2.121 2.122L7.464 9.12 9.586 7 7.464 4.879 8.88 3.464 11 5.586l2.121-2.122 1.415 1.415L12.414 7z"/>
|
|
||||||
|
|
||||||
</symbol></svg>
|
|
Before Width: | Height: | Size: 3.9 KiB |
|
@ -1,17 +1,36 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
### 2.19.2
|
||||||
|
|
||||||
|
- `New` - `toolbar.toggleBlockSettings()` API method added [#1442](https://github.com/codex-team/editor.js/issues/1421).
|
||||||
|
- `Improvements` - A generic type for Tool config added [#1516](https://github.com/codex-team/editor.js/issues/1516)
|
||||||
|
- `Improvements` - Remove unused `force` option in `Caret.navigateNext()` and `Caret.navigatePrevious()` [#857](https://github.com/codex-team/editor.js/issues/857#issuecomment-770363438).
|
||||||
|
- `Improvements` - Remove bundles from the repo [#1541](https://github.com/codex-team/editor.js/pull/1541).
|
||||||
|
- `Improvements` - Document will be scrolled when blocks are selected with `SHIFT+UP` or `SHIFT+DOWN` [#1447](https://github.com/codex-team/editor.js/issues/1447)
|
||||||
|
- `Improvements` - The caret will be set on editor copy/paste [#1470](https://github.com/codex-team/editor.js/pull/1470)
|
||||||
|
- `Improvements` - Added generic types to OutputBlockData [#1551](https://github.com/codex-team/editor.js/issues/1551).
|
||||||
|
- `Fix` - Fix BlockManager.setCurrentBlockByChildNode() with multiple Editor.js instances [#1503](https://github.com/codex-team/editor.js/issues/1503).
|
||||||
|
- `Fix` - Fix an unstable block cut process [#1489](https://github.com/codex-team/editor.js/issues/1489).
|
||||||
|
- `Fix` - Type definition of the Sanitizer config: the sanitize function now contains param definition [#1491](https://github.com/codex-team/editor.js/pull/1491).
|
||||||
|
- `Fix` - Fix unexpected behavior on an empty link pasting [#1348](https://github.com/codex-team/editor.js/issues/1348).
|
||||||
|
- `Fix` - Fix SanitizerConfig type definition [#1513](https://github.com/codex-team/editor.js/issues/1513)
|
||||||
|
- `Refactoring` - The Listeners module now is a util.
|
||||||
|
- `Refactoring` - The Events module now is a util.
|
||||||
|
- `Fix` - Editor Config now immutable [#1552](https://github.com/codex-team/editor.js/issues/1552).
|
||||||
|
- `Refactoring` - Shortcuts module is util now.
|
||||||
|
- `Fix` - Fix bubbling on BlockManagers' listener [#1433](https://github.com/codex-team/editor.js/issues/1433).
|
||||||
|
|
||||||
### 2.19.1
|
### 2.19.1
|
||||||
|
|
||||||
- `Improvements` - The [Cypress](https://www.cypress.io) was integrated as the end-to-end testing framework
|
- `Improvements` - The [Cypress](https://www.cypress.io) was integrated as the end-to-end testing framework
|
||||||
- `Improvements` - Native `typeof`replaced with custom utils methods
|
- `Improvements` - Native `typeof`replaced with custom utils methods
|
||||||
- `Improvements` - Bind shortcuts listeners on the editor wrapper instead of document (#1391)(https://github.com/codex-team/editor.js/issues/1391)
|
- `Improvements` - Bind shortcuts listeners on the editor wrapper instead of document [#1391](https://github.com/codex-team/editor.js/issues/1391)
|
||||||
- `Fix` - The problem with destroy() method [#1380](https://github.com/codex-team/editor.js/issues/1380).
|
- `Fix` - The problem with destroy() method [#1380](https://github.com/codex-team/editor.js/issues/1380).
|
||||||
- `Fix` - add getter keyword to `block.mergeable` method [#1415](https://github.com/codex-team/editor.js/issues/1415).
|
- `Fix` - add getter keyword to `block.mergeable` method [#1415](https://github.com/codex-team/editor.js/issues/1415).
|
||||||
- `Fix` — Fix problem with entering to Editor.js by Tab key [#1393](https://github.com/codex-team/editor.js/issues/1393)
|
- `Fix` — Fix problem with entering to Editor.js by Tab key [#1393](https://github.com/codex-team/editor.js/issues/1393)
|
||||||
- `Fix` - Sanitize pasted block data [#1396](https://github.com/codex-team/editor.js/issues/1396).
|
- `Fix` - Sanitize pasted block data [#1396](https://github.com/codex-team/editor.js/issues/1396).
|
||||||
- `Fix` - Unnecessary block creation after arrow navigation at last non-default block[#1414](https://github.com/codex-team/editor.js/issues/1414)
|
- `Fix` - Unnecessary block creation after arrow navigation at last non-default block[#1414](https://github.com/codex-team/editor.js/issues/1414)
|
||||||
|
|
||||||
|
|
||||||
### 2.19
|
### 2.19
|
||||||
|
|
||||||
- `New` - Read-only mode 🥳 [#837](https://github.com/codex-team/editor.js/issues/837)
|
- `New` - Read-only mode 🥳 [#837](https://github.com/codex-team/editor.js/issues/837)
|
||||||
|
|
100
docs/releases.md
Normal file
100
docs/releases.md
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
# Branches, versions and releases — complete guideline
|
||||||
|
|
||||||
|
## Branches
|
||||||
|
|
||||||
|
The project has two main branches: `master` and `next`.
|
||||||
|
|
||||||
|
Branch `master` contains the latest stable version of the editor.
|
||||||
|
The latest version published to NPM available by default or by the tag `latest`.
|
||||||
|
|
||||||
|
Branch `next` used for development the next (release candidate) version of the editor.
|
||||||
|
It may contain bug fixes, improvements or features. This version is available in NPM by `next` tag.
|
||||||
|
|
||||||
|
## Versions
|
||||||
|
|
||||||
|
We use [semantic versioning](https://semver.org) as a main guide for naming updates.
|
||||||
|
|
||||||
|
`<major>.<minor>.<patch>`
|
||||||
|
|
||||||
|
You need to bump the part of version according the changes:
|
||||||
|
|
||||||
|
- `patch` — for bug fixes, docs updates, code style fixes and other changes which do not affect the result project bundle
|
||||||
|
- `minor` — for new features with no backward compatibility problems.
|
||||||
|
- `major` — for breaking changes without backward compatibility with the api of the previous version of the project.
|
||||||
|
|
||||||
|
Pre-release versions may contain additional `-rc.*` suffix.
|
||||||
|
|
||||||
|
## Release publishing
|
||||||
|
|
||||||
|
Drafts for new releases are created automatically via [create-a-release-draft.yml](.github/workflows/create-a-release-draft.yml)
|
||||||
|
workflow when pull request to `next` branch was merged with an updated version in the package.json file.
|
||||||
|
|
||||||
|
There is a [workflow](.github/workflows/publish-package-to-npm.yml) that fired on a new release publishing on GitHub.
|
||||||
|
|
||||||
|
Use target version changelog as a description.
|
||||||
|
|
||||||
|
![](https://capella.pics/57267bab-f2f0-411b-a9d1-69abee6abab5.jpg)
|
||||||
|
|
||||||
|
Then you can publish the release and wait for package publishing via action.
|
||||||
|
|
||||||
|
This package version will be published to NPM with default `latest` tag.
|
||||||
|
|
||||||
|
### Release candidate publishing
|
||||||
|
|
||||||
|
If you want to publish release candidate version, use suffix `-rc.*` for package
|
||||||
|
version in package.json file and in tag on releases page. Workflow will detect it and mark a release as "pre-release".
|
||||||
|
|
||||||
|
![](https://capella.pics/796de9eb-bbe0-485c-bc8f-9a4cb76641b7.jpg)
|
||||||
|
|
||||||
|
This package version will be published to NPM with `next` tag.
|
||||||
|
|
||||||
|
Stable version: `2.19.0`
|
||||||
|
Release candidate: `2.19.1-rc.0`, `2.19.1-rc.1`, ...
|
||||||
|
Next version: `2.19.1`
|
||||||
|
|
||||||
|
## Auto-bump version
|
||||||
|
|
||||||
|
After each PR merge to the `next` branch [bump-version-on-merge-next.yml](.github/workflows/bump-version-on-merge-next.yml)
|
||||||
|
workflow will check if a package version was updated. If there is no update then it will open a new PR with a next
|
||||||
|
prerelease version.
|
||||||
|
|
||||||
|
### How it works
|
||||||
|
|
||||||
|
The command for bumping a version will be running in a workflow.
|
||||||
|
|
||||||
|
`yarn version --prerelease --preid rc --no-git-tag-version`
|
||||||
|
|
||||||
|
Prerelease version will be bumped or a new prerelease patch will be created:
|
||||||
|
|
||||||
|
- `2.19.1` -> `2.19.2-rc.0`
|
||||||
|
- `2.19.2-rc.0` -> `2.19.2-rc.1`
|
||||||
|
|
||||||
|
### Change version
|
||||||
|
|
||||||
|
You can edit version (and PR name of course) if you need to publish not a pre-release version or any other.
|
||||||
|
|
||||||
|
If the next update is planned to raise the minor version (`2.19.1` -> `2.20.0`), then change it before version update merge.
|
||||||
|
|
||||||
|
- `2.19.1` will be bumped to `2.19.2-rc.0` be default, change `2.19.2-rc.0` to `2.20.0-rc.0`
|
||||||
|
|
||||||
|
### Ignore update
|
||||||
|
|
||||||
|
If you do not need to upgrade and publish the update with the merged pull request (docs update or any other non-important changes),
|
||||||
|
you can close the pull request generated by the workflow.
|
||||||
|
|
||||||
|
## Example pipeline
|
||||||
|
|
||||||
|
Let's imagine that package version is `2.19.0` and you want to add some bug fixes and publish an update as `2.19.1`.
|
||||||
|
|
||||||
|
1. Merge a single update or a few pulls with fixes to the default branch `next`.
|
||||||
|
2. Workflow [bump-version-on-merge-next.yml](.github/workflows/bump-version-on-merge-next.yml) will bump the version up
|
||||||
|
to `2.19.1-rc.0` in the package.json and open a new pull request.
|
||||||
|
3. After bump version PR merge, the workflow [create-a-release-draft.yml](.github/workflows/create-a-release-draft.yml)
|
||||||
|
will automatically create a draft release on GitHub.
|
||||||
|
4. Check this new draft release on the releases page. Check tag `v2.19.1-rc.0` and notice "This is pre-release" checkbox
|
||||||
|
if it should be for a release candidate versions. Then publish that release.
|
||||||
|
5. [Workflow](.github/workflows/publish-package-to-npm.yml) will automatically push the package to NPM with tag `next`.
|
||||||
|
6. When you ready to publish a release, remove suffix from version name in package.json (`2.19.1-rc.0` -> `v2.19.1`)
|
||||||
|
in pull request from workflow [bump-version-on-merge-next.yml](.github/workflows/bump-version-on-merge-next.yml).
|
||||||
|
Follow steps 3-5 with workflows and publish a new version as `latest` update.
|
||||||
|
7. Merge branch `next` to `master` and save sources for history.
|
|
@ -69,6 +69,12 @@ body {
|
||||||
padding: 0 15px;
|
padding: 0 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ce-example__content--with-bg {
|
||||||
|
background: #f4f4f4;
|
||||||
|
max-width: none;
|
||||||
|
margin-top: -30px;
|
||||||
|
}
|
||||||
|
|
||||||
.ce-example__output {
|
.ce-example__output {
|
||||||
background: #1B202B;
|
background: #1B202B;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
|
@ -187,3 +193,16 @@ body {
|
||||||
.ce-example h4.ce-header {
|
.ce-example h4.ce-header {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ce-example-multiple {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: calc(50% - 15px) calc(50% - 15px);
|
||||||
|
gap: 30px;
|
||||||
|
padding: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ce-example-multiple > div {
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 7px;
|
||||||
|
padding: 30px;
|
||||||
|
}
|
||||||
|
|
|
@ -28,7 +28,10 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="ce-example__content _ce-example__content--small">
|
<div class="ce-example__content _ce-example__content--small">
|
||||||
<div id="editorjs"></div>
|
<div id="editorjs"></div>
|
||||||
<div id="hint" style="text-align: center;">
|
<div id="hint-core" style="text-align: center;">
|
||||||
|
No core bundle file found. Run <code class="inline-code">yarn build</code>
|
||||||
|
</div>
|
||||||
|
<div id="hint-tools" style="text-align: center;">
|
||||||
No submodules found. Run <code class="inline-code">yarn pull_tools</code>
|
No submodules found. Run <code class="inline-code">yarn pull_tools</code>
|
||||||
</div>
|
</div>
|
||||||
<div class="ce-example__button" id="saveButton">
|
<div class="ce-example__button" id="saveButton">
|
||||||
|
@ -62,7 +65,7 @@
|
||||||
Read more in Tool's README file. For example:
|
Read more in Tool's README file. For example:
|
||||||
https://github.com/editor-js/header#installation
|
https://github.com/editor-js/header#installation
|
||||||
-->
|
-->
|
||||||
<script src="./tools/header/dist/bundle.js" onload="document.getElementById('hint').hidden = true"></script><!-- Header -->
|
<script src="./tools/header/dist/bundle.js" onload="document.getElementById('hint-tools').hidden = true"></script><!-- Header -->
|
||||||
<script src="./tools/simple-image/dist/bundle.js"></script><!-- Image -->
|
<script src="./tools/simple-image/dist/bundle.js"></script><!-- Image -->
|
||||||
<script src="./tools/delimiter/dist/bundle.js"></script><!-- Delimiter -->
|
<script src="./tools/delimiter/dist/bundle.js"></script><!-- Delimiter -->
|
||||||
<script src="./tools/list/dist/bundle.js"></script><!-- List -->
|
<script src="./tools/list/dist/bundle.js"></script><!-- List -->
|
||||||
|
@ -79,7 +82,7 @@
|
||||||
<script src="./tools/inline-code/dist/bundle.js"></script><!-- Inline Code -->
|
<script src="./tools/inline-code/dist/bundle.js"></script><!-- Inline Code -->
|
||||||
|
|
||||||
<!-- Load Editor.js's Core -->
|
<!-- Load Editor.js's Core -->
|
||||||
<script src="../dist/editor.js"></script>
|
<script src="../dist/editor.js" onload="document.getElementById('hint-core').hidden = true;"></script>
|
||||||
|
|
||||||
<!-- Initialization -->
|
<!-- Initialization -->
|
||||||
<script>
|
<script>
|
||||||
|
|
|
@ -28,6 +28,9 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="ce-example__content _ce-example__content--small">
|
<div class="ce-example__content _ce-example__content--small">
|
||||||
<div id="editorjs"></div>
|
<div id="editorjs"></div>
|
||||||
|
<div id="hint-core" style="text-align: center;">
|
||||||
|
No core bundle file found. Run <code class="inline-code">yarn build</code>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="ce-example__button" id="saveButton">
|
<div class="ce-example__button" id="saveButton">
|
||||||
editor.save()
|
editor.save()
|
||||||
|
@ -58,7 +61,7 @@
|
||||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/inline-code@latest"></script><!-- Inline Code -->
|
<script src="https://cdn.jsdelivr.net/npm/@editorjs/inline-code@latest"></script><!-- Inline Code -->
|
||||||
|
|
||||||
<!-- Load Editor.js's Core -->
|
<!-- Load Editor.js's Core -->
|
||||||
<script src="../dist/editor.js"></script>
|
<script src="../dist/editor.js" onload="document.getElementById('hint-core').hidden = true"></script>
|
||||||
|
|
||||||
<!-- Initialization -->
|
<!-- Initialization -->
|
||||||
<script>
|
<script>
|
||||||
|
|
76
example/example-multiple.html
Normal file
76
example/example-multiple.html
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Use this page for debugging purposes.
|
||||||
|
|
||||||
|
This page can be used for testing multiple editor instances on the same page.
|
||||||
|
-->
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Editor.js 🤩🧦🤨 example: Multiple instances</title>
|
||||||
|
<link href="assets/demo.css" rel="stylesheet">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="ce-example">
|
||||||
|
<div class="ce-example__header">
|
||||||
|
<a class="ce-example__header-logo" href="https://codex.so/editor">Editor.js 🤩🧦🤨</a>
|
||||||
|
|
||||||
|
<div class="ce-example__header-menu">
|
||||||
|
<a href="https://github.com/editor-js" target="_blank">Plugins</a>
|
||||||
|
<a href="https://editorjs.io/usage" target="_blank">Usage</a>
|
||||||
|
<a href="https://editorjs.io/configuration" target="_blank">Configuration</a>
|
||||||
|
<a href="https://editorjs.io/creating-a-block-tool" target="_blank">API</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ce-example__content ce-example__content--with-bg _ce-example__content--small">
|
||||||
|
<div id="hint-core" style="text-align: center; padding-top: 20px">
|
||||||
|
No core bundle file found. Run <code class="inline-code">yarn build</code>
|
||||||
|
</div>
|
||||||
|
<div class="ce-example-multiple">
|
||||||
|
<div id="editorjs1"></div>
|
||||||
|
<div id="editorjs2"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ce-example__output">
|
||||||
|
<div class="ce-example__output-footer">
|
||||||
|
<a href="https://codex.so" style="font-weight: bold;">Made by CodeX</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Load Editor.js's Core -->
|
||||||
|
<script src="../dist/editor.js" onload="document.getElementById('hint-core').hidden = true"></script>
|
||||||
|
<script src="./tools/header/dist/bundle.js"></script><!-- Header -->
|
||||||
|
|
||||||
|
<!-- Initialization -->
|
||||||
|
<script>
|
||||||
|
/**
|
||||||
|
* Instance #1
|
||||||
|
*/
|
||||||
|
var editor1 = new EditorJS({
|
||||||
|
holder: 'editorjs1',
|
||||||
|
tools: {
|
||||||
|
header: {
|
||||||
|
class: Header,
|
||||||
|
shortcut: 'CMD+SHIFT+H'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instance #2
|
||||||
|
*/
|
||||||
|
var editor2 = new EditorJS({
|
||||||
|
holder: 'editorjs2',
|
||||||
|
tools: {
|
||||||
|
header: {
|
||||||
|
class: Header,
|
||||||
|
shortcut: 'CMD+SHIFT+H'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -27,7 +27,10 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="ce-example__content _ce-example__content--small">
|
<div class="ce-example__content _ce-example__content--small">
|
||||||
<div id="editorjs"></div>
|
<div id="editorjs"></div>
|
||||||
<div id="hint" style="text-align: center;">
|
<div id="hint-core" style="text-align: center;">
|
||||||
|
No core bundle file found. Run <code class="inline-code">yarn build</code>
|
||||||
|
</div>
|
||||||
|
<div id="hint-tools" style="text-align: center;">
|
||||||
No submodules found. Run <code class="inline-code">yarn pull_tools</code>
|
No submodules found. Run <code class="inline-code">yarn pull_tools</code>
|
||||||
</div>
|
</div>
|
||||||
<div class="ce-example__button" id="saveButton">
|
<div class="ce-example__button" id="saveButton">
|
||||||
|
@ -50,7 +53,7 @@
|
||||||
Read more in Tool's README file. For example:
|
Read more in Tool's README file. For example:
|
||||||
https://github.com/editor-js/header#installation
|
https://github.com/editor-js/header#installation
|
||||||
-->
|
-->
|
||||||
<script src="./tools/header/dist/bundle.js" onload="document.getElementById('hint').hidden = true"></script><!-- Header -->
|
<script src="./tools/header/dist/bundle.js" onload="document.getElementById('hint-tools').hidden = true"></script><!-- Header -->
|
||||||
<script src="./tools/simple-image/dist/bundle.js"></script><!-- Image -->
|
<script src="./tools/simple-image/dist/bundle.js"></script><!-- Image -->
|
||||||
<script src="./tools/delimiter/dist/bundle.js"></script><!-- Delimiter -->
|
<script src="./tools/delimiter/dist/bundle.js"></script><!-- Delimiter -->
|
||||||
<script src="./tools/list/dist/bundle.js"></script><!-- List -->
|
<script src="./tools/list/dist/bundle.js"></script><!-- List -->
|
||||||
|
@ -67,7 +70,7 @@
|
||||||
<script src="./tools/inline-code/dist/bundle.js"></script><!-- Inline Code -->
|
<script src="./tools/inline-code/dist/bundle.js"></script><!-- Inline Code -->
|
||||||
|
|
||||||
<!-- Load Editor.js's Core -->
|
<!-- Load Editor.js's Core -->
|
||||||
<script src="../dist/editor.js"></script>
|
<script src="../dist/editor.js" onload="document.getElementById('hint-core').hidden = true"></script>
|
||||||
|
|
||||||
<!-- Initialization -->
|
<!-- Initialization -->
|
||||||
<script>
|
<script>
|
||||||
|
|
|
@ -48,12 +48,12 @@
|
||||||
|
|
||||||
<!-- Load Tools -->
|
<!-- Load Tools -->
|
||||||
<!--
|
<!--
|
||||||
You can upload Tools to your project's directory and use as in example below.
|
You can upload Tools to your project's directory and connect them by relative links.
|
||||||
|
|
||||||
Also you can load each Tool from CDN or use NPM/Yarn packages.
|
Also you can load each Tool from CDN or use NPM/Yarn packages.
|
||||||
|
|
||||||
Read more in Tool's README file. For example:
|
Read more at Tools Connection doc:
|
||||||
https://github.com/editor-js/header#installation
|
https://editorjs.io/getting-started#tools-connection
|
||||||
-->
|
-->
|
||||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/header@latest"></script><!-- Header -->
|
<script src="https://cdn.jsdelivr.net/npm/@editorjs/header@latest"></script><!-- Header -->
|
||||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/simple-image@latest"></script><!-- Image -->
|
<script src="https://cdn.jsdelivr.net/npm/@editorjs/simple-image@latest"></script><!-- Image -->
|
||||||
|
@ -71,7 +71,7 @@
|
||||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/inline-code@latest"></script><!-- Inline Code -->
|
<script src="https://cdn.jsdelivr.net/npm/@editorjs/inline-code@latest"></script><!-- Inline Code -->
|
||||||
|
|
||||||
<!-- Load Editor.js's Core -->
|
<!-- Load Editor.js's Core -->
|
||||||
<script src="../dist/editor.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/@editorjs/editorjs@latest"></script>
|
||||||
|
|
||||||
<!-- Initialization -->
|
<!-- Initialization -->
|
||||||
<script>
|
<script>
|
||||||
|
|
13
package.json
13
package.json
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@editorjs/editorjs",
|
"name": "@editorjs/editorjs",
|
||||||
"version": "2.19.1",
|
"version": "2.19.2",
|
||||||
"description": "Editor.js — Native JS, based on API and Open Source",
|
"description": "Editor.js — Native JS, based on API and Open Source",
|
||||||
"main": "dist/editor.js",
|
"main": "dist/editor.js",
|
||||||
"types": "./types/index.d.ts",
|
"types": "./types/index.d.ts",
|
||||||
|
@ -12,15 +12,15 @@
|
||||||
"editorjs"
|
"editorjs"
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "rimraf dist/* && yarn svg && yarn build:prod",
|
"clear": "rimraf dist && mkdirp dist",
|
||||||
"build:win": "rimraf dist && yarn svg:win && yarn build:prod",
|
"build": "yarn clear && yarn svg && yarn build:webpack:prod",
|
||||||
"build:dev": "webpack --mode development --progress --display-error-details --display-entrypoints --watch",
|
"build:dev": "yarn clear && yarn svg && yarn build:webpack:dev",
|
||||||
"build:prod": "webpack --mode production",
|
"build:webpack:dev": "webpack --mode development --progress --display-error-details --display-entrypoints --watch",
|
||||||
|
"build:webpack:prod": "webpack --mode production",
|
||||||
"lint": "eslint src/ --ext .ts && yarn lint:tests",
|
"lint": "eslint src/ --ext .ts && yarn lint:tests",
|
||||||
"lint:errors": "eslint src/ --ext .ts --quiet",
|
"lint:errors": "eslint src/ --ext .ts --quiet",
|
||||||
"lint:fix": "eslint src/ --ext .ts --fix",
|
"lint:fix": "eslint src/ --ext .ts --fix",
|
||||||
"lint:tests": "eslint test/ --ext .ts",
|
"lint:tests": "eslint test/ --ext .ts",
|
||||||
"svg:win": "if not exist dist md dist && yarn svg",
|
|
||||||
"svg": "svg-sprite-generate -d src/assets/ -o dist/sprite.svg",
|
"svg": "svg-sprite-generate -d src/assets/ -o dist/sprite.svg",
|
||||||
"pull_tools": "git submodule update --init --recursive",
|
"pull_tools": "git submodule update --init --recursive",
|
||||||
"checkout_tools": "git submodule foreach git pull origin master",
|
"checkout_tools": "git submodule foreach git pull origin master",
|
||||||
|
@ -56,6 +56,7 @@
|
||||||
"extract-text-webpack-plugin": "^3.0.2",
|
"extract-text-webpack-plugin": "^3.0.2",
|
||||||
"html-janitor": "^2.0.4",
|
"html-janitor": "^2.0.4",
|
||||||
"license-webpack-plugin": "^2.1.4",
|
"license-webpack-plugin": "^2.1.4",
|
||||||
|
"mkdirp": "^1.0.4",
|
||||||
"postcss-apply": "^0.12.0",
|
"postcss-apply": "^0.12.0",
|
||||||
"postcss-import": "^12.0.1",
|
"postcss-import": "^12.0.1",
|
||||||
"postcss-loader": "^3.0.0",
|
"postcss-loader": "^3.0.0",
|
||||||
|
|
|
@ -87,6 +87,7 @@ export default class EditorJS {
|
||||||
if (_.isFunction(moduleInstance.destroy)) {
|
if (_.isFunction(moduleInstance.destroy)) {
|
||||||
moduleInstance.destroy();
|
moduleInstance.destroy();
|
||||||
}
|
}
|
||||||
|
moduleInstance.listeners.removeAll();
|
||||||
});
|
});
|
||||||
|
|
||||||
editor = null;
|
editor = null;
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import { EditorModules } from '../types-internal/editor-modules';
|
import { EditorModules } from '../types-internal/editor-modules';
|
||||||
import { EditorConfig } from '../../types';
|
import { EditorConfig } from '../../types';
|
||||||
import { ModuleConfig } from '../types-internal/module-config';
|
import { ModuleConfig } from '../types-internal/module-config';
|
||||||
|
import Listeners from './utils/listeners';
|
||||||
|
import EventsDispatcher from './utils/events';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type <T> of the Module generic.
|
* The type <T> of the Module generic.
|
||||||
|
@ -38,6 +40,16 @@ export default class Module<T extends ModuleNodes = {}> {
|
||||||
*/
|
*/
|
||||||
protected config: EditorConfig;
|
protected config: EditorConfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Editor event dispatcher class
|
||||||
|
*/
|
||||||
|
protected eventsDispatcher: EventsDispatcher;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Util for bind/unbind DOM event listeners
|
||||||
|
*/
|
||||||
|
protected listeners: Listeners = new Listeners();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This object provides methods to push into set of listeners that being dropped when read-only mode is enabled
|
* This object provides methods to push into set of listeners that being dropped when read-only mode is enabled
|
||||||
*/
|
*/
|
||||||
|
@ -56,10 +68,8 @@ export default class Module<T extends ModuleNodes = {}> {
|
||||||
handler: (event: Event) => void,
|
handler: (event: Event) => void,
|
||||||
options: boolean | AddEventListenerOptions = false
|
options: boolean | AddEventListenerOptions = false
|
||||||
): void => {
|
): void => {
|
||||||
const { Listeners } = this.Editor;
|
|
||||||
|
|
||||||
this.mutableListenerIds.push(
|
this.mutableListenerIds.push(
|
||||||
Listeners.on(element, eventType, handler, options)
|
this.listeners.on(element, eventType, handler, options)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -67,10 +77,8 @@ export default class Module<T extends ModuleNodes = {}> {
|
||||||
* Clears all mutable listeners
|
* Clears all mutable listeners
|
||||||
*/
|
*/
|
||||||
clearAll: (): void => {
|
clearAll: (): void => {
|
||||||
const { Listeners } = this.Editor;
|
|
||||||
|
|
||||||
for (const id of this.mutableListenerIds) {
|
for (const id of this.mutableListenerIds) {
|
||||||
Listeners.offById(id);
|
this.listeners.offById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.mutableListenerIds = [];
|
this.mutableListenerIds = [];
|
||||||
|
@ -84,14 +92,17 @@ export default class Module<T extends ModuleNodes = {}> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class
|
* @class
|
||||||
|
*
|
||||||
* @param {EditorConfig} config - Editor's config
|
* @param {EditorConfig} config - Editor's config
|
||||||
|
* @param {EventsDispatcher} eventsDispatcher - Editor's event dispatcher
|
||||||
*/
|
*/
|
||||||
constructor({ config }: ModuleConfig) {
|
constructor({ config, eventsDispatcher }: ModuleConfig) {
|
||||||
if (new.target === Module) {
|
if (new.target === Module) {
|
||||||
throw new TypeError('Constructors for abstract class Module are not allowed.');
|
throw new TypeError('Constructors for abstract class Module are not allowed.');
|
||||||
}
|
}
|
||||||
|
|
||||||
this.config = config;
|
this.config = config;
|
||||||
|
this.eventsDispatcher = eventsDispatcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import $ from './dom';
|
import $ from './dom';
|
||||||
import * as _ from './utils';
|
import * as _ from './utils';
|
||||||
import { EditorConfig, OutputData, SanitizerConfig } from '../../types';
|
import { EditorConfig, SanitizerConfig } from '../../types';
|
||||||
import { EditorModules } from '../types-internal/editor-modules';
|
import { EditorModules } from '../types-internal/editor-modules';
|
||||||
import I18n from './i18n';
|
import I18n from './i18n';
|
||||||
import { CriticalError } from './errors/critical';
|
import { CriticalError } from './errors/critical';
|
||||||
|
import EventsDispatcher from './utils/events';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {Core} Core - editor core class
|
* @typedef {Core} Core - editor core class
|
||||||
|
@ -53,6 +54,11 @@ export default class Core {
|
||||||
*/
|
*/
|
||||||
public isReady: Promise<void>;
|
public isReady: Promise<void>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event Dispatcher util
|
||||||
|
*/
|
||||||
|
private eventsDispatcher: EventsDispatcher = new EventsDispatcher();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {EditorConfig} config - user configuration
|
* @param {EditorConfig} config - user configuration
|
||||||
*
|
*
|
||||||
|
@ -115,12 +121,21 @@ export default class Core {
|
||||||
* @param {EditorConfig|string} config - Editor's config to set
|
* @param {EditorConfig|string} config - Editor's config to set
|
||||||
*/
|
*/
|
||||||
public set configuration(config: EditorConfig|string) {
|
public set configuration(config: EditorConfig|string) {
|
||||||
|
/**
|
||||||
|
* Place config into the class property
|
||||||
|
*
|
||||||
|
* @type {EditorConfig}
|
||||||
|
*/
|
||||||
|
if (_.isObject(config)) {
|
||||||
|
this.config = {
|
||||||
|
...config,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
/**
|
/**
|
||||||
* Process zero-configuration or with only holderId
|
* Process zero-configuration or with only holderId
|
||||||
* Make config object
|
* Make config object
|
||||||
*/
|
*/
|
||||||
if (!_.isObject(config)) {
|
this.config = {
|
||||||
config = {
|
|
||||||
holder: config,
|
holder: config,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -128,19 +143,12 @@ export default class Core {
|
||||||
/**
|
/**
|
||||||
* If holderId is preset, assign him to holder property and work next only with holder
|
* If holderId is preset, assign him to holder property and work next only with holder
|
||||||
*/
|
*/
|
||||||
_.deprecationAssert(!!config.holderId, 'config.holderId', 'config.holder');
|
_.deprecationAssert(!!this.config.holderId, 'config.holderId', 'config.holder');
|
||||||
if (config.holderId && !config.holder) {
|
if (this.config.holderId && !this.config.holder) {
|
||||||
config.holder = config.holderId;
|
this.config.holder = this.config.holderId;
|
||||||
config.holderId = null;
|
this.config.holderId = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Place config into the class property
|
|
||||||
*
|
|
||||||
* @type {EditorConfig}
|
|
||||||
*/
|
|
||||||
this.config = config;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If holder is empty then set a default value
|
* If holder is empty then set a default value
|
||||||
*/
|
*/
|
||||||
|
@ -188,7 +196,7 @@ export default class Core {
|
||||||
this.config.hideToolbar = this.config.hideToolbar ? this.config.hideToolbar : false;
|
this.config.hideToolbar = this.config.hideToolbar ? this.config.hideToolbar : false;
|
||||||
this.config.tools = this.config.tools || {};
|
this.config.tools = this.config.tools || {};
|
||||||
this.config.i18n = this.config.i18n || {};
|
this.config.i18n = this.config.i18n || {};
|
||||||
this.config.data = this.config.data || {} as OutputData;
|
this.config.data = this.config.data || { blocks: [] };
|
||||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||||
this.config.onReady = this.config.onReady || ((): void => {});
|
this.config.onReady = this.config.onReady || ((): void => {});
|
||||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||||
|
@ -198,13 +206,8 @@ export default class Core {
|
||||||
/**
|
/**
|
||||||
* Initialize default Block to pass data to the Renderer
|
* Initialize default Block to pass data to the Renderer
|
||||||
*/
|
*/
|
||||||
if (_.isEmpty(this.config.data)) {
|
if (_.isEmpty(this.config.data) || !this.config.data.blocks || this.config.data.blocks.length === 0) {
|
||||||
this.config.data = {} as OutputData;
|
this.config.data = { blocks: [ defaultBlockData ] };
|
||||||
this.config.data.blocks = [ defaultBlockData ];
|
|
||||||
} else {
|
|
||||||
if (!this.config.data.blocks || this.config.data.blocks.length === 0) {
|
|
||||||
this.config.data.blocks = [ defaultBlockData ];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.config.readOnly = this.config.readOnly as boolean || false;
|
this.config.readOnly = this.config.readOnly as boolean || false;
|
||||||
|
@ -212,14 +215,14 @@ export default class Core {
|
||||||
/**
|
/**
|
||||||
* Adjust i18n
|
* Adjust i18n
|
||||||
*/
|
*/
|
||||||
if (config.i18n?.messages) {
|
if (this.config.i18n?.messages) {
|
||||||
I18n.setDictionary(config.i18n.messages);
|
I18n.setDictionary(this.config.i18n.messages);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Text direction. If not set, uses ltr
|
* Text direction. If not set, uses ltr
|
||||||
*/
|
*/
|
||||||
this.config.i18n.direction = config.i18n?.direction || 'ltr';
|
this.config.i18n.direction = this.config.i18n?.direction || 'ltr';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -251,7 +254,7 @@ export default class Core {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (holder && _.isObject(holder) && !$.isElement(holder)) {
|
if (holder && _.isObject(holder) && !$.isElement(holder)) {
|
||||||
throw Error('holder as HTMLElement if provided must be inherit from Element class.');
|
throw Error('«holder» value must be an Element node');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -341,6 +344,7 @@ export default class Core {
|
||||||
*/
|
*/
|
||||||
this.moduleInstances[Module.displayName] = new Module({
|
this.moduleInstances[Module.displayName] = new Module({
|
||||||
config: this.configuration,
|
config: this.configuration,
|
||||||
|
eventsDispatcher: this.eventsDispatcher,
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
_.log(`Module ${Module.displayName} skipped because`, 'warn', e);
|
_.log(`Module ${Module.displayName} skipped because`, 'warn', e);
|
||||||
|
|
|
@ -291,6 +291,8 @@ export default class LinkInlineTool implements InlineTool {
|
||||||
this.unlink();
|
this.unlink();
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
this.closeActions();
|
this.closeActions();
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.validateURL(value)) {
|
if (!this.validateURL(value)) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Events } from '../../../../types/api';
|
|
||||||
import Module from '../../__module';
|
import Module from '../../__module';
|
||||||
|
import { Events } from '../../../../types/api';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class EventsAPI
|
* @class EventsAPI
|
||||||
|
@ -26,7 +26,7 @@ export default class EventsAPI extends Module {
|
||||||
* @param {Function} callback - event handler
|
* @param {Function} callback - event handler
|
||||||
*/
|
*/
|
||||||
public on(eventName, callback): void {
|
public on(eventName, callback): void {
|
||||||
this.Editor.Events.on(eventName, callback);
|
this.eventsDispatcher.on(eventName, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -36,7 +36,7 @@ export default class EventsAPI extends Module {
|
||||||
* @param {object} data - event's data
|
* @param {object} data - event's data
|
||||||
*/
|
*/
|
||||||
public emit(eventName, data): void {
|
public emit(eventName, data): void {
|
||||||
this.Editor.Events.emit(eventName, data);
|
this.eventsDispatcher.emit(eventName, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -46,6 +46,6 @@ export default class EventsAPI extends Module {
|
||||||
* @param {Function} callback - event handler
|
* @param {Function} callback - event handler
|
||||||
*/
|
*/
|
||||||
public off(eventName, callback): void {
|
public off(eventName, callback): void {
|
||||||
this.Editor.Events.off(eventName, callback);
|
this.eventsDispatcher.off(eventName, callback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ export default class ListenersAPI extends Module {
|
||||||
* @param {boolean} useCapture - capture event or not
|
* @param {boolean} useCapture - capture event or not
|
||||||
*/
|
*/
|
||||||
public on(element: HTMLElement, eventType: string, handler: () => void, useCapture?: boolean): void {
|
public on(element: HTMLElement, eventType: string, handler: () => void, useCapture?: boolean): void {
|
||||||
this.Editor.Listeners.on(element, eventType, handler, useCapture);
|
this.listeners.on(element, eventType, handler, useCapture);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -39,6 +39,6 @@ export default class ListenersAPI extends Module {
|
||||||
* @param {boolean} useCapture - capture event or not
|
* @param {boolean} useCapture - capture event or not
|
||||||
*/
|
*/
|
||||||
public off(element: Element, eventType: string, handler: () => void, useCapture?: boolean): void {
|
public off(element: Element, eventType: string, handler: () => void, useCapture?: boolean): void {
|
||||||
this.Editor.Listeners.off(element, eventType, handler, useCapture);
|
this.listeners.off(element, eventType, handler, useCapture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Toolbar } from '../../../../types/api';
|
import { Toolbar } from '../../../../types/api';
|
||||||
import Module from '../../__module';
|
import Module from '../../__module';
|
||||||
|
import * as _ from './../../utils';
|
||||||
/**
|
/**
|
||||||
* @class ToolbarAPI
|
* @class ToolbarAPI
|
||||||
* Provides methods for working with the Toolbar
|
* Provides methods for working with the Toolbar
|
||||||
|
@ -15,6 +15,7 @@ export default class ToolbarAPI extends Module {
|
||||||
return {
|
return {
|
||||||
close: (): void => this.close(),
|
close: (): void => this.close(),
|
||||||
open: (): void => this.open(),
|
open: (): void => this.open(),
|
||||||
|
toggleBlockSettings: (openingState?: boolean): void => this.toggleBlockSettings(openingState),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,4 +32,35 @@ export default class ToolbarAPI extends Module {
|
||||||
public close(): void {
|
public close(): void {
|
||||||
this.Editor.Toolbar.close();
|
this.Editor.Toolbar.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggles Block Setting of the current block
|
||||||
|
*
|
||||||
|
* @param {boolean} openingState — opening state of Block Setting
|
||||||
|
*/
|
||||||
|
public toggleBlockSettings(openingState?: boolean): void {
|
||||||
|
if (this.Editor.BlockManager.currentBlockIndex === -1) {
|
||||||
|
_.logLabeled('Could\'t toggle the Toolbar because there is no block selected ', 'warn');
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Check that opening state is set or not */
|
||||||
|
const canOpenBlockSettings = openingState ?? !this.Editor.BlockSettings.opened;
|
||||||
|
|
||||||
|
/** Check if state same as current state */
|
||||||
|
if (openingState === this.Editor.BlockSettings.opened) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (canOpenBlockSettings) {
|
||||||
|
if (!this.Editor.Toolbar.opened) {
|
||||||
|
this.Editor.Toolbar.open(true, false);
|
||||||
|
this.Editor.Toolbar.plusButton.hide();
|
||||||
|
}
|
||||||
|
this.Editor.BlockSettings.open();
|
||||||
|
} else {
|
||||||
|
this.Editor.BlockSettings.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -167,7 +167,7 @@ export default class BlockEvents extends Module {
|
||||||
*
|
*
|
||||||
* @param {ClipboardEvent} event - clipboard event
|
* @param {ClipboardEvent} event - clipboard event
|
||||||
*/
|
*/
|
||||||
public handleCommandC(event: ClipboardEvent): void {
|
public handleCommandC(event: ClipboardEvent): Promise<void> {
|
||||||
const { BlockSelection } = this.Editor;
|
const { BlockSelection } = this.Editor;
|
||||||
|
|
||||||
if (!BlockSelection.anyBlockSelected) {
|
if (!BlockSelection.anyBlockSelected) {
|
||||||
|
@ -175,7 +175,7 @@ export default class BlockEvents extends Module {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy Selected Blocks
|
// Copy Selected Blocks
|
||||||
BlockSelection.copySelectedBlocks(event);
|
return BlockSelection.copySelectedBlocks(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -183,14 +183,14 @@ export default class BlockEvents extends Module {
|
||||||
*
|
*
|
||||||
* @param {ClipboardEvent} event - clipboard event
|
* @param {ClipboardEvent} event - clipboard event
|
||||||
*/
|
*/
|
||||||
public handleCommandX(event: ClipboardEvent): void {
|
public async handleCommandX(event: ClipboardEvent): Promise<void> {
|
||||||
const { BlockSelection, BlockManager, Caret } = this.Editor;
|
const { BlockSelection, BlockManager, Caret } = this.Editor;
|
||||||
|
|
||||||
if (!BlockSelection.anyBlockSelected) {
|
if (!BlockSelection.anyBlockSelected) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockSelection.copySelectedBlocks(event);
|
await BlockSelection.copySelectedBlocks(event);
|
||||||
|
|
||||||
const selectionPositionIndex = BlockManager.removeSelectedBlocks();
|
const selectionPositionIndex = BlockManager.removeSelectedBlocks();
|
||||||
|
|
||||||
|
|
|
@ -184,7 +184,7 @@ export default class BlockManager extends Module {
|
||||||
});
|
});
|
||||||
|
|
||||||
/** Copy event */
|
/** Copy event */
|
||||||
this.Editor.Listeners.on(
|
this.listeners.on(
|
||||||
document,
|
document,
|
||||||
'copy',
|
'copy',
|
||||||
(e: ClipboardEvent) => this.Editor.BlockEvents.handleCommandC(e)
|
(e: ClipboardEvent) => this.Editor.BlockEvents.handleCommandC(e)
|
||||||
|
@ -560,10 +560,9 @@ export default class BlockManager extends Module {
|
||||||
* 2) Mark it as current
|
* 2) Mark it as current
|
||||||
*
|
*
|
||||||
* @param {Node} childNode - look ahead from this node.
|
* @param {Node} childNode - look ahead from this node.
|
||||||
*
|
* @returns {Block | undefined} can return undefined in case when the passed child note is not a part of the current editor instance
|
||||||
* @throws Error - when passed Node is not included at the Block
|
|
||||||
*/
|
*/
|
||||||
public setCurrentBlockByChildNode(childNode: Node): Block {
|
public setCurrentBlockByChildNode(childNode: Node): Block | undefined {
|
||||||
/**
|
/**
|
||||||
* If node is Text TextNode
|
* If node is Text TextNode
|
||||||
*/
|
*/
|
||||||
|
@ -573,7 +572,23 @@ export default class BlockManager extends Module {
|
||||||
|
|
||||||
const parentFirstLevelBlock = (childNode as HTMLElement).closest(`.${Block.CSS.wrapper}`);
|
const parentFirstLevelBlock = (childNode as HTMLElement).closest(`.${Block.CSS.wrapper}`);
|
||||||
|
|
||||||
if (parentFirstLevelBlock) {
|
if (!parentFirstLevelBlock) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Support multiple Editor.js instances,
|
||||||
|
* by checking whether the found block belongs to the current instance
|
||||||
|
*
|
||||||
|
* @see {@link Ui#documentTouched}
|
||||||
|
*/
|
||||||
|
const editorWrapper = parentFirstLevelBlock.closest(`.${this.Editor.UI.CSS.editorWrapper}`);
|
||||||
|
const isBlockBelongsToCurrentInstance = editorWrapper?.isEqualNode(this.Editor.UI.nodes.wrapper);
|
||||||
|
|
||||||
|
if (!isBlockBelongsToCurrentInstance) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update current Block's index
|
* Update current Block's index
|
||||||
*
|
*
|
||||||
|
@ -587,9 +602,6 @@ export default class BlockManager extends Module {
|
||||||
this.currentBlock.updateCurrentInput();
|
this.currentBlock.updateCurrentInput();
|
||||||
|
|
||||||
return this.currentBlock;
|
return this.currentBlock;
|
||||||
} else {
|
|
||||||
throw new Error('Can not find a Block from this child Node');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -707,7 +719,7 @@ export default class BlockManager extends Module {
|
||||||
|
|
||||||
this.readOnlyMutableListeners.on(block.holder, 'keydown', (event: KeyboardEvent) => {
|
this.readOnlyMutableListeners.on(block.holder, 'keydown', (event: KeyboardEvent) => {
|
||||||
BlockEvents.keydown(event);
|
BlockEvents.keydown(event);
|
||||||
}, true);
|
});
|
||||||
|
|
||||||
this.readOnlyMutableListeners.on(block.holder, 'keyup', (event: KeyboardEvent) => {
|
this.readOnlyMutableListeners.on(block.holder, 'keyup', (event: KeyboardEvent) => {
|
||||||
BlockEvents.keyup(event);
|
BlockEvents.keyup(event);
|
||||||
|
|
|
@ -9,6 +9,7 @@ import Module from '../__module';
|
||||||
import Block from '../block';
|
import Block from '../block';
|
||||||
import * as _ from '../utils';
|
import * as _ from '../utils';
|
||||||
import $ from '../dom';
|
import $ from '../dom';
|
||||||
|
import Shortcuts from '../utils/shortcuts';
|
||||||
|
|
||||||
import SelectionUtils from '../selection';
|
import SelectionUtils from '../selection';
|
||||||
import { SanitizerConfig } from '../../../types/configs';
|
import { SanitizerConfig } from '../../../types/configs';
|
||||||
|
@ -145,8 +146,6 @@ export default class BlockSelection extends Module {
|
||||||
* to select all and copy them
|
* to select all and copy them
|
||||||
*/
|
*/
|
||||||
public prepare(): void {
|
public prepare(): void {
|
||||||
const { Shortcuts } = this.Editor;
|
|
||||||
|
|
||||||
this.selection = new SelectionUtils();
|
this.selection = new SelectionUtils();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -181,6 +180,7 @@ export default class BlockSelection extends Module {
|
||||||
|
|
||||||
this.handleCommandA(event);
|
this.handleCommandA(event);
|
||||||
},
|
},
|
||||||
|
on: this.Editor.UI.nodes.redactor,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -361,10 +361,8 @@ export default class BlockSelection extends Module {
|
||||||
* De-registers Shortcut CMD+A
|
* De-registers Shortcut CMD+A
|
||||||
*/
|
*/
|
||||||
public destroy(): void {
|
public destroy(): void {
|
||||||
const { Shortcuts } = this.Editor;
|
|
||||||
|
|
||||||
/** Selection shortcut */
|
/** Selection shortcut */
|
||||||
Shortcuts.remove('CMD+A');
|
Shortcuts.remove(this.Editor.UI.nodes.redactor, 'CMD+A');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -388,11 +388,9 @@ export default class Caret extends Module {
|
||||||
* Before moving caret, we should check if caret position is at the end of Plugins node
|
* Before moving caret, we should check if caret position is at the end of Plugins node
|
||||||
* Using {@link Dom#getDeepestNode} to get a last node and match with current selection
|
* Using {@link Dom#getDeepestNode} to get a last node and match with current selection
|
||||||
*
|
*
|
||||||
* @param {boolean} force - force navigation even if caret is not at the end
|
|
||||||
*
|
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
public navigateNext(force = false): boolean {
|
public navigateNext(): boolean {
|
||||||
const { BlockManager, Tools } = this.Editor;
|
const { BlockManager, Tools } = this.Editor;
|
||||||
const { currentBlock, nextContentfulBlock } = BlockManager;
|
const { currentBlock, nextContentfulBlock } = BlockManager;
|
||||||
const { nextInput } = currentBlock;
|
const { nextInput } = currentBlock;
|
||||||
|
@ -422,7 +420,7 @@ export default class Caret extends Module {
|
||||||
nextBlock = BlockManager.insertAtEnd();
|
nextBlock = BlockManager.insertAtEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (force || isAtEnd) {
|
if (isAtEnd) {
|
||||||
/** If next Tool`s input exists, focus on it. Otherwise set caret to the next Block */
|
/** If next Tool`s input exists, focus on it. Otherwise set caret to the next Block */
|
||||||
if (!nextInput) {
|
if (!nextInput) {
|
||||||
this.setToBlock(nextBlock, this.positions.START);
|
this.setToBlock(nextBlock, this.positions.START);
|
||||||
|
@ -441,11 +439,9 @@ export default class Caret extends Module {
|
||||||
* Before moving caret, we should check if caret position is start of the Plugins node
|
* Before moving caret, we should check if caret position is start of the Plugins node
|
||||||
* Using {@link Dom#getDeepestNode} to get a last node and match with current selection
|
* Using {@link Dom#getDeepestNode} to get a last node and match with current selection
|
||||||
*
|
*
|
||||||
* @param {boolean} force - force navigation even if caret is not at the start
|
|
||||||
*
|
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
public navigatePrevious(force = false): boolean {
|
public navigatePrevious(): boolean {
|
||||||
const { currentBlock, previousContentfulBlock } = this.Editor.BlockManager;
|
const { currentBlock, previousContentfulBlock } = this.Editor.BlockManager;
|
||||||
|
|
||||||
if (!currentBlock) {
|
if (!currentBlock) {
|
||||||
|
@ -458,7 +454,7 @@ export default class Caret extends Module {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (force || this.isAtStart) {
|
if (this.isAtStart) {
|
||||||
/** If previous Tool`s input exists, focus on it. Otherwise set caret to the previous Block */
|
/** If previous Tool`s input exists, focus on it. Otherwise set caret to the previous Block */
|
||||||
if (!previousInput) {
|
if (!previousInput) {
|
||||||
this.setToBlock(previousContentfulBlock, this.positions.END);
|
this.setToBlock(previousContentfulBlock, this.positions.END);
|
||||||
|
|
|
@ -23,9 +23,7 @@ export default class CrossBlockSelection extends Module {
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
public async prepare(): Promise<void> {
|
public async prepare(): Promise<void> {
|
||||||
const { Listeners } = this.Editor;
|
this.listeners.on(document, 'mousedown', (event: MouseEvent) => {
|
||||||
|
|
||||||
Listeners.on(document, 'mousedown', (event: MouseEvent) => {
|
|
||||||
this.enableCrossBlockSelection(event);
|
this.enableCrossBlockSelection(event);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -40,13 +38,13 @@ export default class CrossBlockSelection extends Module {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { BlockManager, Listeners } = this.Editor;
|
const { BlockManager } = this.Editor;
|
||||||
|
|
||||||
this.firstSelectedBlock = BlockManager.getBlock(event.target as HTMLElement);
|
this.firstSelectedBlock = BlockManager.getBlock(event.target as HTMLElement);
|
||||||
this.lastSelectedBlock = this.firstSelectedBlock;
|
this.lastSelectedBlock = this.firstSelectedBlock;
|
||||||
|
|
||||||
Listeners.on(document, 'mouseover', this.onMouseOver);
|
this.listeners.on(document, 'mouseover', this.onMouseOver);
|
||||||
Listeners.on(document, 'mouseup', this.onMouseUp);
|
this.listeners.on(document, 'mouseup', this.onMouseUp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -98,6 +96,10 @@ export default class CrossBlockSelection extends Module {
|
||||||
|
|
||||||
/** close InlineToolbar when Blocks selected */
|
/** close InlineToolbar when Blocks selected */
|
||||||
this.Editor.InlineToolbar.close();
|
this.Editor.InlineToolbar.close();
|
||||||
|
|
||||||
|
nextBlock.holder.scrollIntoView({
|
||||||
|
block: 'nearest',
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -172,10 +174,8 @@ export default class CrossBlockSelection extends Module {
|
||||||
* Removes the listeners
|
* Removes the listeners
|
||||||
*/
|
*/
|
||||||
private onMouseUp = (): void => {
|
private onMouseUp = (): void => {
|
||||||
const { Listeners } = this.Editor;
|
this.listeners.off(document, 'mouseover', this.onMouseOver);
|
||||||
|
this.listeners.off(document, 'mouseup', this.onMouseUp);
|
||||||
Listeners.off(document, 'mouseover', this.onMouseOver);
|
|
||||||
Listeners.off(document, 'mouseup', this.onMouseUp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -87,16 +87,16 @@ export default class DragNDrop extends Module {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try to set current block by drop target.
|
* Try to set current block by drop target.
|
||||||
* If drop target (error will be thrown) is not part of the Block, set last Block as current.
|
* If drop target is not part of the Block, set last Block as current.
|
||||||
*/
|
*/
|
||||||
try {
|
|
||||||
const targetBlock = BlockManager.setCurrentBlockByChildNode(dropEvent.target as Node);
|
const targetBlock = BlockManager.setCurrentBlockByChildNode(dropEvent.target as Node);
|
||||||
|
|
||||||
|
if (targetBlock) {
|
||||||
this.Editor.Caret.setToBlock(targetBlock, Caret.positions.END);
|
this.Editor.Caret.setToBlock(targetBlock, Caret.positions.END);
|
||||||
} catch (e) {
|
} else {
|
||||||
const targetBlock = BlockManager.setCurrentBlockByChildNode(BlockManager.lastBlock.holder);
|
const lastBlock = BlockManager.setCurrentBlockByChildNode(BlockManager.lastBlock.holder);
|
||||||
|
|
||||||
this.Editor.Caret.setToBlock(targetBlock, Caret.positions.END);
|
this.Editor.Caret.setToBlock(lastBlock, Caret.positions.END);
|
||||||
}
|
}
|
||||||
|
|
||||||
await Paste.processDataTransfer(dropEvent.dataTransfer, true);
|
await Paste.processDataTransfer(dropEvent.dataTransfer, true);
|
||||||
|
|
|
@ -58,7 +58,7 @@ export default class ModificationsObserver extends Module {
|
||||||
this.observer.disconnect();
|
this.observer.disconnect();
|
||||||
}
|
}
|
||||||
this.observer = null;
|
this.observer = null;
|
||||||
this.nativeInputs.forEach((input) => this.Editor.Listeners.off(input, 'input', this.mutationDebouncer));
|
this.nativeInputs.forEach((input) => this.listeners.off(input, 'input', this.mutationDebouncer));
|
||||||
this.mutationDebouncer = null;
|
this.mutationDebouncer = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,13 +163,13 @@ export default class ModificationsObserver extends Module {
|
||||||
private updateNativeInputs(): void {
|
private updateNativeInputs(): void {
|
||||||
if (this.nativeInputs) {
|
if (this.nativeInputs) {
|
||||||
this.nativeInputs.forEach((input) => {
|
this.nativeInputs.forEach((input) => {
|
||||||
this.Editor.Listeners.off(input, 'input');
|
this.listeners.off(input, 'input');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
this.nativeInputs = Array.from(this.Editor.UI.nodes.redactor.querySelectorAll('textarea, input, select'));
|
this.nativeInputs = Array.from(this.Editor.UI.nodes.redactor.querySelectorAll('textarea, input, select'));
|
||||||
|
|
||||||
this.nativeInputs.forEach((input) => this.Editor.Listeners.on(input, 'input', this.mutationDebouncer));
|
this.nativeInputs.forEach((input) => this.listeners.on(input, 'input', this.mutationDebouncer));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -263,18 +263,14 @@ export default class Paste extends Module {
|
||||||
* Set onPaste callback handler
|
* Set onPaste callback handler
|
||||||
*/
|
*/
|
||||||
private setCallback(): void {
|
private setCallback(): void {
|
||||||
const { Listeners } = this.Editor;
|
this.listeners.on(this.Editor.UI.nodes.holder, 'paste', this.handlePasteEvent);
|
||||||
|
|
||||||
Listeners.on(this.Editor.UI.nodes.holder, 'paste', this.handlePasteEvent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unset onPaste callback handler
|
* Unset onPaste callback handler
|
||||||
*/
|
*/
|
||||||
private unsetCallback(): void {
|
private unsetCallback(): void {
|
||||||
const { Listeners } = this.Editor;
|
this.listeners.off(this.Editor.UI.nodes.holder, 'paste', this.handlePasteEvent);
|
||||||
|
|
||||||
Listeners.off(this.Editor.UI.nodes.holder, 'paste', this.handlePasteEvent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -760,7 +756,7 @@ export default class Paste extends Module {
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
private insertEditorJSData(blocks: Array<Pick<SavedData, 'data' | 'tool'>>): void {
|
private insertEditorJSData(blocks: Array<Pick<SavedData, 'data' | 'tool'>>): void {
|
||||||
const { BlockManager, Sanitizer, Tools } = this.Editor;
|
const { BlockManager, Caret, Sanitizer, Tools } = this.Editor;
|
||||||
const sanitizedBlocks = Sanitizer.sanitizeBlocks(blocks);
|
const sanitizedBlocks = Sanitizer.sanitizeBlocks(blocks);
|
||||||
|
|
||||||
sanitizedBlocks.forEach(({ tool, data }, i) => {
|
sanitizedBlocks.forEach(({ tool, data }, i) => {
|
||||||
|
@ -772,11 +768,13 @@ export default class Paste extends Module {
|
||||||
needToReplaceCurrentBlock = isCurrentBlockDefault && BlockManager.currentBlock.isEmpty;
|
needToReplaceCurrentBlock = isCurrentBlockDefault && BlockManager.currentBlock.isEmpty;
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockManager.insert({
|
const block = BlockManager.insert({
|
||||||
tool,
|
tool,
|
||||||
data,
|
data,
|
||||||
replace: needToReplaceCurrentBlock,
|
replace: needToReplaceCurrentBlock,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Caret.setToBlock(block, Caret.positions.END);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -179,26 +179,25 @@ export default class RectangleSelection extends Module {
|
||||||
* Sets Module necessary event handlers
|
* Sets Module necessary event handlers
|
||||||
*/
|
*/
|
||||||
private enableModuleBindings(): void {
|
private enableModuleBindings(): void {
|
||||||
const { Listeners } = this.Editor;
|
|
||||||
const { container } = this.genHTML();
|
const { container } = this.genHTML();
|
||||||
|
|
||||||
Listeners.on(container, 'mousedown', (mouseEvent: MouseEvent) => {
|
this.listeners.on(container, 'mousedown', (mouseEvent: MouseEvent) => {
|
||||||
this.processMouseDown(mouseEvent);
|
this.processMouseDown(mouseEvent);
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
Listeners.on(document.body, 'mousemove', (mouseEvent: MouseEvent) => {
|
this.listeners.on(document.body, 'mousemove', (mouseEvent: MouseEvent) => {
|
||||||
this.processMouseMove(mouseEvent);
|
this.processMouseMove(mouseEvent);
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
Listeners.on(document.body, 'mouseleave', () => {
|
this.listeners.on(document.body, 'mouseleave', () => {
|
||||||
this.processMouseLeave();
|
this.processMouseLeave();
|
||||||
});
|
});
|
||||||
|
|
||||||
Listeners.on(window, 'scroll', (mouseEvent: MouseEvent) => {
|
this.listeners.on(window, 'scroll', (mouseEvent: MouseEvent) => {
|
||||||
this.processScroll(mouseEvent);
|
this.processScroll(mouseEvent);
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
Listeners.on(document.body, 'mouseup', () => {
|
this.listeners.on(document.body, 'mouseup', () => {
|
||||||
this.processMouseUp();
|
this.processMouseUp();
|
||||||
}, false);
|
}, false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,74 +0,0 @@
|
||||||
import Shortcut from '@codexteam/shortcuts';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Contains keyboard and mouse events binded on each Block by Block Manager
|
|
||||||
*/
|
|
||||||
import Module from '../__module';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ShortcutData interface
|
|
||||||
* Each shortcut must have name and handler
|
|
||||||
* `name` is a shortcut, like 'CMD+K', 'CMD+B' etc
|
|
||||||
* `handler` is a callback
|
|
||||||
*
|
|
||||||
* @interface ShortcutData
|
|
||||||
*/
|
|
||||||
export interface ShortcutData {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shortcut name
|
|
||||||
* Ex. CMD+I, CMD+B ....
|
|
||||||
*/
|
|
||||||
name: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shortcut handler
|
|
||||||
*/
|
|
||||||
handler(event): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @class Shortcut
|
|
||||||
* @classdesc Allows to register new shortcut
|
|
||||||
*
|
|
||||||
* Internal Shortcuts Module
|
|
||||||
*/
|
|
||||||
export default class Shortcuts extends Module {
|
|
||||||
/**
|
|
||||||
* All registered shortcuts
|
|
||||||
*
|
|
||||||
* @type {Shortcut[]}
|
|
||||||
*/
|
|
||||||
private registeredShortcuts: Shortcut[] = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register shortcut
|
|
||||||
*
|
|
||||||
* @param {ShortcutData} shortcut - shortcut options
|
|
||||||
*/
|
|
||||||
public add(shortcut: ShortcutData): void {
|
|
||||||
const newShortcut = new Shortcut({
|
|
||||||
name: shortcut.name,
|
|
||||||
on: this.Editor.UI.nodes.redactor,
|
|
||||||
callback: shortcut.handler,
|
|
||||||
});
|
|
||||||
|
|
||||||
this.registeredShortcuts.push(newShortcut);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove shortcut
|
|
||||||
*
|
|
||||||
* @param {string} shortcut - shortcut name
|
|
||||||
*/
|
|
||||||
public remove(shortcut: string): void {
|
|
||||||
const index = this.registeredShortcuts.findIndex((shc) => shc.name === shortcut);
|
|
||||||
|
|
||||||
if (index === -1 || !this.registeredShortcuts[index]) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.registeredShortcuts[index].remove();
|
|
||||||
this.registeredShortcuts.splice(index, 1);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -147,7 +147,7 @@ export default class BlockSettings extends Module<BlockSettingsNodes> {
|
||||||
this.addDefaultSettings();
|
this.addDefaultSettings();
|
||||||
|
|
||||||
/** Tell to subscribers that block settings is opened */
|
/** Tell to subscribers that block settings is opened */
|
||||||
this.Editor.Events.emit(this.events.opened);
|
this.eventsDispatcher.emit(this.events.opened);
|
||||||
|
|
||||||
this.flipper.activate(this.blockTunesButtons);
|
this.flipper.activate(this.blockTunesButtons);
|
||||||
}
|
}
|
||||||
|
@ -171,12 +171,19 @@ export default class BlockSettings extends Module<BlockSettingsNodes> {
|
||||||
|
|
||||||
this.selection.clearSaved();
|
this.selection.clearSaved();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove highlighted content of a Block we are working with
|
||||||
|
*/
|
||||||
|
if (!this.Editor.CrossBlockSelection.isCrossBlockSelectionStarted && this.Editor.BlockManager.currentBlock) {
|
||||||
|
this.Editor.BlockManager.currentBlock.selected = false;
|
||||||
|
}
|
||||||
|
|
||||||
/** Clear settings */
|
/** Clear settings */
|
||||||
this.nodes.toolSettings.innerHTML = '';
|
this.nodes.toolSettings.innerHTML = '';
|
||||||
this.nodes.defaultSettings.innerHTML = '';
|
this.nodes.defaultSettings.innerHTML = '';
|
||||||
|
|
||||||
/** Tell to subscribers that block settings is closed */
|
/** Tell to subscribers that block settings is closed */
|
||||||
this.Editor.Events.emit(this.events.closed);
|
this.eventsDispatcher.emit(this.events.closed);
|
||||||
|
|
||||||
/** Clear cached buttons */
|
/** Clear cached buttons */
|
||||||
this.buttons = [];
|
this.buttons = [];
|
||||||
|
|
|
@ -325,7 +325,7 @@ export default class ConversionToolbar extends Module<ConversionToolbarNodes> {
|
||||||
$.append(this.nodes.tools, tool);
|
$.append(this.nodes.tools, tool);
|
||||||
this.tools[toolName] = tool;
|
this.tools[toolName] = tool;
|
||||||
|
|
||||||
this.Editor.Listeners.on(tool, 'click', async () => {
|
this.listeners.on(tool, 'click', async () => {
|
||||||
await this.replaceWithBlock(toolName);
|
await this.replaceWithBlock(toolName);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,8 @@ import { InlineTool, InlineToolConstructable, ToolConstructable, ToolSettings }
|
||||||
import Flipper from '../../flipper';
|
import Flipper from '../../flipper';
|
||||||
import I18n from '../../i18n';
|
import I18n from '../../i18n';
|
||||||
import { I18nInternalNS } from '../../i18n/namespace-internal';
|
import { I18nInternalNS } from '../../i18n/namespace-internal';
|
||||||
|
import Shortcuts from '../../utils/shortcuts';
|
||||||
|
import { EditorModules } from '../../../types-internal/editor-modules';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inline Toolbar elements
|
* Inline Toolbar elements
|
||||||
|
@ -87,6 +89,38 @@ export default class InlineToolbar extends Module<InlineToolbarNodes> {
|
||||||
*/
|
*/
|
||||||
private flipper: Flipper = null;
|
private flipper: Flipper = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal inline tools: Link, Bold, Italic
|
||||||
|
*/
|
||||||
|
private internalTools: {[name: string]: InlineToolConstructable} = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Editor modules setter
|
||||||
|
*
|
||||||
|
* @param {EditorModules} Editor - Editor's Modules
|
||||||
|
*/
|
||||||
|
public set state(Editor: EditorModules) {
|
||||||
|
this.Editor = Editor;
|
||||||
|
|
||||||
|
const { Tools } = Editor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set internal inline tools
|
||||||
|
*/
|
||||||
|
Object
|
||||||
|
.entries(Tools.internalTools)
|
||||||
|
.filter(([, toolClass]: [string, ToolConstructable | ToolSettings]) => {
|
||||||
|
if (_.isFunction(toolClass)) {
|
||||||
|
return toolClass[Tools.INTERNAL_SETTINGS.IS_INLINE];
|
||||||
|
}
|
||||||
|
|
||||||
|
return (toolClass as ToolSettings).class[Tools.INTERNAL_SETTINGS.IS_INLINE];
|
||||||
|
})
|
||||||
|
.map(([name, toolClass]: [string, InlineToolConstructable | ToolSettings]) => {
|
||||||
|
this.internalTools[name] = _.isFunction(toolClass) ? toolClass : (toolClass as ToolSettings).class;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Toggles read-only mode
|
* Toggles read-only mode
|
||||||
*
|
*
|
||||||
|
@ -185,7 +219,13 @@ export default class InlineToolbar extends Module<InlineToolbarNodes> {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.nodes.wrapper.classList.remove(this.CSS.inlineToolbarShowed);
|
this.nodes.wrapper.classList.remove(this.CSS.inlineToolbarShowed);
|
||||||
this.toolsInstances.forEach((toolInstance) => {
|
Array.from(this.toolsInstances.entries()).forEach(([name, toolInstance]) => {
|
||||||
|
const shortcut = this.getToolShortcut(name);
|
||||||
|
|
||||||
|
if (shortcut) {
|
||||||
|
Shortcuts.remove(this.Editor.UI.nodes.redactor, shortcut);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @todo replace 'clear' with 'destroy'
|
* @todo replace 'clear' with 'destroy'
|
||||||
*/
|
*/
|
||||||
|
@ -357,7 +397,7 @@ export default class InlineToolbar extends Module<InlineToolbarNodes> {
|
||||||
this.nodes.actions = $.make('div', this.CSS.actionsWrapper);
|
this.nodes.actions = $.make('div', this.CSS.actionsWrapper);
|
||||||
|
|
||||||
// To prevent reset of a selection when click on the wrapper
|
// To prevent reset of a selection when click on the wrapper
|
||||||
this.Editor.Listeners.on(this.nodes.wrapper, 'mousedown', (event) => {
|
this.listeners.on(this.nodes.wrapper, 'mousedown', (event) => {
|
||||||
const isClickedOnActionsWrapper = (event.target as Element).closest(`.${this.CSS.actionsWrapper}`);
|
const isClickedOnActionsWrapper = (event.target as Element).closest(`.${this.CSS.actionsWrapper}`);
|
||||||
|
|
||||||
// If click is on actions wrapper,
|
// If click is on actions wrapper,
|
||||||
|
@ -479,7 +519,7 @@ export default class InlineToolbar extends Module<InlineToolbarNodes> {
|
||||||
|
|
||||||
this.nodes.togglerAndButtonsWrapper.appendChild(this.nodes.conversionToggler);
|
this.nodes.togglerAndButtonsWrapper.appendChild(this.nodes.conversionToggler);
|
||||||
|
|
||||||
this.Editor.Listeners.on(this.nodes.conversionToggler, 'click', () => {
|
this.listeners.on(this.nodes.conversionToggler, 'click', () => {
|
||||||
this.Editor.ConversionToolbar.toggle((conversionToolbarOpened) => {
|
this.Editor.ConversionToolbar.toggle((conversionToolbarOpened) => {
|
||||||
/**
|
/**
|
||||||
* When ConversionToolbar is opening on activated InlineToolbar flipper
|
* When ConversionToolbar is opening on activated InlineToolbar flipper
|
||||||
|
@ -594,7 +634,6 @@ export default class InlineToolbar extends Module<InlineToolbarNodes> {
|
||||||
*/
|
*/
|
||||||
private addTool(toolName: string, tool: InlineTool): void {
|
private addTool(toolName: string, tool: InlineTool): void {
|
||||||
const {
|
const {
|
||||||
Listeners,
|
|
||||||
Tools,
|
Tools,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
} = this.Editor;
|
} = this.Editor;
|
||||||
|
@ -617,45 +656,12 @@ export default class InlineToolbar extends Module<InlineToolbarNodes> {
|
||||||
this.nodes.actions.appendChild(actions);
|
this.nodes.actions.appendChild(actions);
|
||||||
}
|
}
|
||||||
|
|
||||||
Listeners.on(button, 'click', (event) => {
|
this.listeners.on(button, 'click', (event) => {
|
||||||
this.toolClicked(tool);
|
this.toolClicked(tool);
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
const shortcut = this.getToolShortcut(toolName);
|
||||||
* Enable shortcuts
|
|
||||||
* Ignore tool that doesn't have shortcut or empty string
|
|
||||||
*/
|
|
||||||
const toolSettings = Tools.getToolSettings(toolName);
|
|
||||||
|
|
||||||
let shortcut = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get internal inline tools
|
|
||||||
*/
|
|
||||||
const internalTools: string[] = Object
|
|
||||||
.entries(Tools.internalTools)
|
|
||||||
.filter(([, toolClass]: [string, ToolConstructable | ToolSettings]) => {
|
|
||||||
if (_.isFunction(toolClass)) {
|
|
||||||
return toolClass[Tools.INTERNAL_SETTINGS.IS_INLINE];
|
|
||||||
}
|
|
||||||
|
|
||||||
return (toolClass as ToolSettings).class[Tools.INTERNAL_SETTINGS.IS_INLINE];
|
|
||||||
})
|
|
||||||
.map(([ name ]: [string, InlineToolConstructable | ToolSettings]) => name);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 1) For internal tools, check public getter 'shortcut'
|
|
||||||
* 2) For external tools, check tool's settings
|
|
||||||
* 3) If shortcut is not set in settings, check Tool's public property
|
|
||||||
*/
|
|
||||||
if (internalTools.includes(toolName)) {
|
|
||||||
shortcut = this.inlineTools[toolName][Tools.INTERNAL_SETTINGS.SHORTCUT];
|
|
||||||
} else if (toolSettings && toolSettings[Tools.USER_SETTINGS.SHORTCUT]) {
|
|
||||||
shortcut = toolSettings[Tools.USER_SETTINGS.SHORTCUT];
|
|
||||||
} else if (tool.shortcut) {
|
|
||||||
shortcut = tool.shortcut;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shortcut) {
|
if (shortcut) {
|
||||||
this.enableShortcuts(tool, shortcut);
|
this.enableShortcuts(tool, shortcut);
|
||||||
|
@ -684,6 +690,35 @@ export default class InlineToolbar extends Module<InlineToolbarNodes> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get shortcut name for tool
|
||||||
|
*
|
||||||
|
* @param toolName — Tool name
|
||||||
|
*/
|
||||||
|
private getToolShortcut(toolName): string | void {
|
||||||
|
const { Tools } = this.Editor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable shortcuts
|
||||||
|
* Ignore tool that doesn't have shortcut or empty string
|
||||||
|
*/
|
||||||
|
const toolSettings = Tools.getToolSettings(toolName);
|
||||||
|
const tool = this.toolsInstances.get(toolName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1) For internal tools, check public getter 'shortcut'
|
||||||
|
* 2) For external tools, check tool's settings
|
||||||
|
* 3) If shortcut is not set in settings, check Tool's public property
|
||||||
|
*/
|
||||||
|
if (Object.keys(this.internalTools).includes(toolName)) {
|
||||||
|
return this.inlineTools[toolName][Tools.INTERNAL_SETTINGS.SHORTCUT];
|
||||||
|
} else if (toolSettings && toolSettings[Tools.USER_SETTINGS.SHORTCUT]) {
|
||||||
|
return toolSettings[Tools.USER_SETTINGS.SHORTCUT];
|
||||||
|
} else if (tool.shortcut) {
|
||||||
|
return tool.shortcut;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable Tool shortcut with Editor Shortcuts Module
|
* Enable Tool shortcut with Editor Shortcuts Module
|
||||||
*
|
*
|
||||||
|
@ -691,7 +726,7 @@ export default class InlineToolbar extends Module<InlineToolbarNodes> {
|
||||||
* @param {string} shortcut - shortcut according to the ShortcutData Module format
|
* @param {string} shortcut - shortcut according to the ShortcutData Module format
|
||||||
*/
|
*/
|
||||||
private enableShortcuts(tool: InlineTool, shortcut: string): void {
|
private enableShortcuts(tool: InlineTool, shortcut: string): void {
|
||||||
this.Editor.Shortcuts.add({
|
Shortcuts.add({
|
||||||
name: shortcut,
|
name: shortcut,
|
||||||
handler: (event) => {
|
handler: (event) => {
|
||||||
const { currentBlock } = this.Editor.BlockManager;
|
const { currentBlock } = this.Editor.BlockManager;
|
||||||
|
@ -719,6 +754,7 @@ export default class InlineToolbar extends Module<InlineToolbarNodes> {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
this.toolClicked(tool);
|
this.toolClicked(tool);
|
||||||
},
|
},
|
||||||
|
on: this.Editor.UI.nodes.redactor,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import Flipper from '../../flipper';
|
||||||
import { BlockToolAPI } from '../../block';
|
import { BlockToolAPI } from '../../block';
|
||||||
import I18n from '../../i18n';
|
import I18n from '../../i18n';
|
||||||
import { I18nInternalNS } from '../../i18n/namespace-internal';
|
import { I18nInternalNS } from '../../i18n/namespace-internal';
|
||||||
|
import Shortcuts from '../../utils/shortcuts';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HTMLElements used for Toolbox UI
|
* HTMLElements used for Toolbox UI
|
||||||
|
@ -225,7 +226,7 @@ export default class Toolbox extends Module<ToolboxNodes> {
|
||||||
/**
|
/**
|
||||||
* Add click listener
|
* Add click listener
|
||||||
*/
|
*/
|
||||||
this.Editor.Listeners.on(button, 'click', (event: KeyboardEvent|MouseEvent) => {
|
this.listeners.on(button, 'click', (event: KeyboardEvent|MouseEvent) => {
|
||||||
this.toolButtonActivate(event, toolName);
|
this.toolButtonActivate(event, toolName);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -306,12 +307,13 @@ export default class Toolbox extends Module<ToolboxNodes> {
|
||||||
* @param {string} shortcut - shortcut according to the ShortcutData Module format
|
* @param {string} shortcut - shortcut according to the ShortcutData Module format
|
||||||
*/
|
*/
|
||||||
private enableShortcut(tool: BlockToolConstructable, toolName: string, shortcut: string): void {
|
private enableShortcut(tool: BlockToolConstructable, toolName: string, shortcut: string): void {
|
||||||
this.Editor.Shortcuts.add({
|
Shortcuts.add({
|
||||||
name: shortcut,
|
name: shortcut,
|
||||||
handler: (event: KeyboardEvent) => {
|
handler: (event: KeyboardEvent) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
this.insertNewBlock(tool, toolName);
|
this.insertNewBlock(tool, toolName);
|
||||||
},
|
},
|
||||||
|
on: this.Editor.UI.nodes.redactor,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -327,7 +329,7 @@ export default class Toolbox extends Module<ToolboxNodes> {
|
||||||
const shortcut = this.getToolShortcut(toolName, tools[toolName]);
|
const shortcut = this.getToolShortcut(toolName, tools[toolName]);
|
||||||
|
|
||||||
if (shortcut) {
|
if (shortcut) {
|
||||||
this.Editor.Shortcuts.remove(shortcut);
|
Shortcuts.remove(this.Editor.UI.nodes.redactor, shortcut);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,8 @@ import BoldInlineTool from '../inline-tools/inline-tool-bold';
|
||||||
import ItalicInlineTool from '../inline-tools/inline-tool-italic';
|
import ItalicInlineTool from '../inline-tools/inline-tool-italic';
|
||||||
import LinkInlineTool from '../inline-tools/inline-tool-link';
|
import LinkInlineTool from '../inline-tools/inline-tool-link';
|
||||||
import Stub from '../tools/stub';
|
import Stub from '../tools/stub';
|
||||||
|
import { ModuleConfig } from '../../types-internal/module-config';
|
||||||
|
import EventsDispatcher from '../utils/events';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @module Editor.js Tools Submodule
|
* @module Editor.js Tools Submodule
|
||||||
|
@ -198,9 +200,13 @@ export default class Tools extends Module {
|
||||||
* @class
|
* @class
|
||||||
*
|
*
|
||||||
* @param {EditorConfig} config - Editor's configuration
|
* @param {EditorConfig} config - Editor's configuration
|
||||||
|
* @param {EventsDispatcher} eventsDispatcher - Editor's event dispatcher
|
||||||
*/
|
*/
|
||||||
constructor({ config }) {
|
constructor({ config, eventsDispatcher }: ModuleConfig) {
|
||||||
super({ config });
|
super({
|
||||||
|
config,
|
||||||
|
eventsDispatcher,
|
||||||
|
});
|
||||||
|
|
||||||
this.toolsClasses = {};
|
this.toolsClasses = {};
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@ import Module from '../__module';
|
||||||
* Use external module CodeX Tooltip
|
* Use external module CodeX Tooltip
|
||||||
*/
|
*/
|
||||||
import CodeXTooltips, { TooltipContent, TooltipOptions } from 'codex-tooltip';
|
import CodeXTooltips, { TooltipContent, TooltipOptions } from 'codex-tooltip';
|
||||||
import { ModuleConfig } from '../../types-internal/module-config';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tooltip
|
* Tooltip
|
||||||
|
@ -20,14 +19,6 @@ export default class Tooltip extends Module {
|
||||||
*/
|
*/
|
||||||
private lib: CodeXTooltips = new CodeXTooltips();
|
private lib: CodeXTooltips = new CodeXTooltips();
|
||||||
|
|
||||||
/**
|
|
||||||
* @class
|
|
||||||
* @param {EditorConfig} - Editor's config
|
|
||||||
*/
|
|
||||||
constructor({ config }: ModuleConfig) {
|
|
||||||
super({ config });
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shows tooltip on element with passed HTML content
|
* Shows tooltip on element with passed HTML content
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* TextRange interface fot IE9-
|
* TextRange interface for IE9-
|
||||||
*/
|
*/
|
||||||
import * as _ from './utils';
|
import * as _ from './utils';
|
||||||
import $ from './dom';
|
import $ from './dom';
|
||||||
|
|
|
@ -1,19 +1,17 @@
|
||||||
import Module from '../__module';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @module eventDispatcher
|
* @class EventDispatcher
|
||||||
*
|
*
|
||||||
* Has two important methods:
|
* Has two important methods:
|
||||||
* - {Function} on - appends subscriber to the event. If event doesn't exist - creates new one
|
* - {Function} on - appends subscriber to the event. If event doesn't exist - creates new one
|
||||||
* - {Function} emit - fires all subscribers with data
|
* - {Function} emit - fires all subscribers with data
|
||||||
* - {Function off - unsubsribes callback
|
* - {Function off - unsubscribes callback
|
||||||
*
|
*
|
||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
*
|
*
|
||||||
* @typedef {Events} Events
|
* @typedef {Events} Events
|
||||||
* @property {object} subscribers - all subscribers grouped by event name
|
* @property {object} subscribers - all subscribers grouped by event name
|
||||||
*/
|
*/
|
||||||
export default class Events extends Module {
|
export default class EventsDispatcher {
|
||||||
/**
|
/**
|
||||||
* Object with events` names as key and array of callback functions as value
|
* Object with events` names as key and array of callback functions as value
|
||||||
*
|
*
|
|
@ -1,4 +1,3 @@
|
||||||
import Module from '../__module';
|
|
||||||
import * as _ from '../utils';
|
import * as _ from '../utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -36,11 +35,9 @@ export interface ListenerData {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Editor.js Listeners module
|
* Editor.js Listeners helper
|
||||||
*
|
*
|
||||||
* @module Listeners
|
* Decorator for event listeners assignment
|
||||||
*
|
|
||||||
* Module-decorator for event listeners assignment
|
|
||||||
*
|
*
|
||||||
* @author Codex Team
|
* @author Codex Team
|
||||||
* @version 2.0.0
|
* @version 2.0.0
|
||||||
|
@ -50,7 +47,7 @@ export interface ListenerData {
|
||||||
* @typedef {Listeners} Listeners
|
* @typedef {Listeners} Listeners
|
||||||
* @property {ListenerData[]} allListeners - listeners store
|
* @property {ListenerData[]} allListeners - listeners store
|
||||||
*/
|
*/
|
||||||
export default class Listeners extends Module {
|
export default class Listeners {
|
||||||
/**
|
/**
|
||||||
* Stores all listeners data to find/remove/process it
|
* Stores all listeners data to find/remove/process it
|
||||||
*
|
*
|
||||||
|
@ -114,7 +111,7 @@ export default class Listeners extends Module {
|
||||||
existingListeners.forEach((listener, i) => {
|
existingListeners.forEach((listener, i) => {
|
||||||
const index = this.allListeners.indexOf(existingListeners[i]);
|
const index = this.allListeners.indexOf(existingListeners[i]);
|
||||||
|
|
||||||
if (index > 0) {
|
if (index > -1) {
|
||||||
this.allListeners.splice(index, 1);
|
this.allListeners.splice(index, 1);
|
||||||
|
|
||||||
listener.element.removeEventListener(listener.eventType, listener.handler, listener.options);
|
listener.element.removeEventListener(listener.eventType, listener.handler, listener.options);
|
107
src/components/utils/shortcuts.ts
Normal file
107
src/components/utils/shortcuts.ts
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
import Shortcut from '@codexteam/shortcuts';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains keyboard and mouse events binded on each Block by Block Manager
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ShortcutData interface
|
||||||
|
* Each shortcut must have name and handler
|
||||||
|
* `name` is a shortcut, like 'CMD+K', 'CMD+B' etc
|
||||||
|
* `handler` is a callback
|
||||||
|
*
|
||||||
|
* @interface ShortcutData
|
||||||
|
*/
|
||||||
|
export interface ShortcutData {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shortcut name
|
||||||
|
* Ex. CMD+I, CMD+B ....
|
||||||
|
*/
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shortcut handler
|
||||||
|
*/
|
||||||
|
handler(event): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Element handler should be added for
|
||||||
|
*/
|
||||||
|
on: HTMLElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class Shortcut
|
||||||
|
* @classdesc Allows to register new shortcut
|
||||||
|
*
|
||||||
|
* Internal Shortcuts Module
|
||||||
|
*/
|
||||||
|
class Shortcuts {
|
||||||
|
/**
|
||||||
|
* All registered shortcuts
|
||||||
|
*
|
||||||
|
* @type {Map<Element, Shortcut[]>}
|
||||||
|
*/
|
||||||
|
private registeredShortcuts: Map<Element, Shortcut[]> = new Map();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register shortcut
|
||||||
|
*
|
||||||
|
* @param shortcut - shortcut options
|
||||||
|
*/
|
||||||
|
public add(shortcut: ShortcutData): void {
|
||||||
|
const foundShortcut = this.findShortcut(shortcut.on, shortcut.name);
|
||||||
|
|
||||||
|
if (foundShortcut) {
|
||||||
|
throw Error(
|
||||||
|
`Shortcut ${shortcut.name} is already registered for ${shortcut.on}. Please remove it before add a new handler.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const newShortcut = new Shortcut({
|
||||||
|
name: shortcut.name,
|
||||||
|
on: shortcut.on,
|
||||||
|
callback: shortcut.handler,
|
||||||
|
});
|
||||||
|
const shortcuts = this.registeredShortcuts.get(shortcut.on) || [];
|
||||||
|
|
||||||
|
this.registeredShortcuts.set(shortcut.on, [...shortcuts, newShortcut]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove shortcut
|
||||||
|
*
|
||||||
|
* @param element - Element shortcut is set for
|
||||||
|
* @param name - shortcut name
|
||||||
|
*/
|
||||||
|
public remove(element: Element, name: string): void {
|
||||||
|
const shortcut = this.findShortcut(element, name);
|
||||||
|
|
||||||
|
if (!shortcut) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
shortcut.remove();
|
||||||
|
|
||||||
|
const shortcuts = this.registeredShortcuts.get(element);
|
||||||
|
|
||||||
|
this.registeredShortcuts.set(element, shortcuts.filter(el => el !== shortcut));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Shortcut instance if exist
|
||||||
|
*
|
||||||
|
* @param element - Element shorcut is set for
|
||||||
|
* @param shortcut - shortcut name
|
||||||
|
*
|
||||||
|
* @returns {number} index - shortcut index if exist
|
||||||
|
*/
|
||||||
|
private findShortcut(element: Element, shortcut: string): Shortcut | void {
|
||||||
|
const shortcuts = this.registeredShortcuts.get(element) || [];
|
||||||
|
|
||||||
|
return shortcuts.find(({ name }) => name === shortcut);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default new Shortcuts();
|
6
src/types-internal/editor-modules.d.ts
vendored
6
src/types-internal/editor-modules.d.ts
vendored
|
@ -1,12 +1,9 @@
|
||||||
import UI from '../components/modules/ui';
|
import UI from '../components/modules/ui';
|
||||||
import BlockEvents from '../components/modules/blockEvents';
|
import BlockEvents from '../components/modules/blockEvents';
|
||||||
import Listeners from '../components/modules/listeners';
|
|
||||||
import Toolbar from '../components/modules/toolbar/index';
|
import Toolbar from '../components/modules/toolbar/index';
|
||||||
import InlineToolbar from '../components/modules/toolbar/inline';
|
import InlineToolbar from '../components/modules/toolbar/inline';
|
||||||
import Toolbox from '../components/modules/toolbar/toolbox';
|
import Toolbox from '../components/modules/toolbar/toolbox';
|
||||||
import BlockSettings from '../components/modules/toolbar/blockSettings';
|
import BlockSettings from '../components/modules/toolbar/blockSettings';
|
||||||
import Events from '../components/modules/events';
|
|
||||||
import Shortcuts from '../components/modules/shortcuts';
|
|
||||||
import Paste from '../components/modules/paste';
|
import Paste from '../components/modules/paste';
|
||||||
import Notifier from '../components/modules/notifier';
|
import Notifier from '../components/modules/notifier';
|
||||||
import Tooltip from '../components/modules/tooltip';
|
import Tooltip from '../components/modules/tooltip';
|
||||||
|
@ -44,14 +41,11 @@ export interface EditorModules {
|
||||||
BlockEvents: BlockEvents;
|
BlockEvents: BlockEvents;
|
||||||
BlockSelection: BlockSelection;
|
BlockSelection: BlockSelection;
|
||||||
RectangleSelection: RectangleSelection;
|
RectangleSelection: RectangleSelection;
|
||||||
Listeners: Listeners;
|
|
||||||
Toolbar: Toolbar;
|
Toolbar: Toolbar;
|
||||||
InlineToolbar: InlineToolbar;
|
InlineToolbar: InlineToolbar;
|
||||||
Toolbox: Toolbox;
|
Toolbox: Toolbox;
|
||||||
BlockSettings: BlockSettings;
|
BlockSettings: BlockSettings;
|
||||||
ConversionToolbar: ConversionToolbar;
|
ConversionToolbar: ConversionToolbar;
|
||||||
Events: Events;
|
|
||||||
Shortcuts: Shortcuts;
|
|
||||||
Paste: Paste;
|
Paste: Paste;
|
||||||
DragNDrop: DragNDrop;
|
DragNDrop: DragNDrop;
|
||||||
ModificationsObserver: ModificationsObserver;
|
ModificationsObserver: ModificationsObserver;
|
||||||
|
|
8
src/types-internal/html-janitor.d.ts
vendored
8
src/types-internal/html-janitor.d.ts
vendored
|
@ -3,9 +3,15 @@
|
||||||
* After that we can use it at the TS modules
|
* After that we can use it at the TS modules
|
||||||
*/
|
*/
|
||||||
declare module 'html-janitor' {
|
declare module 'html-janitor' {
|
||||||
|
/**
|
||||||
|
* Sanitizer config of each HTML element
|
||||||
|
* @see {@link https://github.com/guardian/html-janitor#options}
|
||||||
|
*/
|
||||||
|
type TagConfig = boolean | { [attr: string]: boolean | string };
|
||||||
|
|
||||||
interface Config {
|
interface Config {
|
||||||
tags: {
|
tags: {
|
||||||
[key: string]: boolean|{[attr: string]: boolean|string}|(() => any)
|
[key: string]: TagConfig | ((el: Element) => TagConfig)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
2
src/types-internal/module-config.d.ts
vendored
2
src/types-internal/module-config.d.ts
vendored
|
@ -1,8 +1,10 @@
|
||||||
import { EditorConfig } from '../../types/index';
|
import { EditorConfig } from '../../types/index';
|
||||||
|
import EventsDispatcher from '../components/utils/events';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describes object passed to Editor modules constructor
|
* Describes object passed to Editor modules constructor
|
||||||
*/
|
*/
|
||||||
export interface ModuleConfig {
|
export interface ModuleConfig {
|
||||||
config: EditorConfig;
|
config: EditorConfig;
|
||||||
|
eventsDispatcher: EventsDispatcher;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,6 @@ describe('Editor basic initialization', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create a visible UI', () => {
|
it('should create a visible UI', () => {
|
||||||
cy.window().then((window) => {
|
|
||||||
/**
|
/**
|
||||||
* Assert if created instance is visible or not.
|
* Assert if created instance is visible or not.
|
||||||
*/
|
*/
|
||||||
|
@ -27,4 +26,3 @@ describe('Editor basic initialization', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
82
test/testcases.md
Normal file
82
test/testcases.md
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
# Editor.js specs
|
||||||
|
|
||||||
|
This document will describe various test cases of the editor.js functionality. Features will be organized by modules. Cases covered by tests should be marked by the checkmark.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
- [ ] Zero configuration
|
||||||
|
- [ ] Editor.js should be initialized on the element with the default `editorjs` id.
|
||||||
|
- [ ] Editor.js should throw an error in case when there is no element with `editorjs` id.
|
||||||
|
- [ ] Editor.js should be initialized with the Paragraph tool only.
|
||||||
|
- [ ] The Inline Toolbar of the Paragraph tool should contain all default Inline Tools - `bold`, `italic`, `link`.
|
||||||
|
|
||||||
|
- [ ] `holder` property
|
||||||
|
- [ ] Editor.js should be initialized on the element with passed via `holder` property.
|
||||||
|
- [ ] Editor.js should throw an error if passed `holder` value is not an Element node.
|
||||||
|
|
||||||
|
- [ ] `autofocus` property
|
||||||
|
- [ ] With the empty editor
|
||||||
|
- [ ] If `true` passed, the caret should be placed to the first empty block.
|
||||||
|
- [ ] If `false` passed, the caret shouldn't be placed anywhere.
|
||||||
|
- [ ] If omitted, the caret shouldn't be placed anywhere.
|
||||||
|
- [ ] With the not-empty editor
|
||||||
|
- [ ] If `true` passed, the caret should be placed to the end of the last block.
|
||||||
|
- [ ] If `false` passed, the caret shouldn't be placed anywhere.
|
||||||
|
- [ ] If omitted, the caret shouldn't be placed anywhere.
|
||||||
|
|
||||||
|
- [ ] `placeholder` property
|
||||||
|
- [ ] With the empty editor
|
||||||
|
- [ ] If `string` passed, the string should be placed as a placeholder to the first empty block only.
|
||||||
|
- [ ] If `false` passed, the first empty block should be placed without a placeholder.
|
||||||
|
- [ ] If omitted, the first empty block should be placed without a placeholder.
|
||||||
|
|
||||||
|
- [ ] `minHeight` property
|
||||||
|
- [ ] If `number` passed, the height of the editor's bottom area from the last Block should be the `number`.
|
||||||
|
- [ ] If omitted the height of editor's bottom area from the last Block should be the default `300`.
|
||||||
|
|
||||||
|
- [ ] `logLevel` property
|
||||||
|
- [ ] If `VERBOSE` passed, the editor should output all messages to the console.
|
||||||
|
- [ ] If `INFO` passed, the editor should output info and debug messages to the console.
|
||||||
|
- [ ] If `WARN` passed, the editor should output only warning messages to the console.
|
||||||
|
- [ ] If `ERROR` passed, the editor should output only error messages to the console.
|
||||||
|
- [ ] If omitted, the editor should output all messages to the console.
|
||||||
|
|
||||||
|
- [ ] `defaultBlock` property
|
||||||
|
- [ ] If `string` passed
|
||||||
|
- [ ] If passed `string` in the `tools` option, the passed tool should be used as the default tool.
|
||||||
|
- [ ] If passed `string` not in the `tools` option, the Paragraph tool should be used as the default tool.
|
||||||
|
- [ ] If omitted the Paragraph tool should be used as default tool.
|
||||||
|
|
||||||
|
- [ ] `sanitizer` property
|
||||||
|
- [ ] If `object` passed
|
||||||
|
- [ ] The Editor.js should clean the HTML tags according to mentioned configuration.
|
||||||
|
- [ ] If omitted the Editor.js should be initialized with the default `sanitizer` configuration, which allows the tags like `paragraph`, `anchor`, and `bold` for cleaning HTML.
|
||||||
|
|
||||||
|
- [ ] `tools` property
|
||||||
|
- [ ] If omitted
|
||||||
|
- [ ] Editor.js should be initialized with the Paragraph tool only.
|
||||||
|
- [ ] If `object` passed
|
||||||
|
- [ ] Editor.js should be initialized with all the passed tools.
|
||||||
|
- [ ] The keys of the object should be represented as `type` fields for corresponded blocks in output JSON
|
||||||
|
- [ ] If value is a JavaScript class
|
||||||
|
- [ ] This class should be used as a tool
|
||||||
|
- [ ] If value is an `object`
|
||||||
|
- [ ] Checking the `class` property
|
||||||
|
- [ ] If omitted, the tool should be skipped with a warning in a console.
|
||||||
|
- [ ] If existed, the value of the `class` property should be used as a tool
|
||||||
|
- [ ] Checking the `config` property
|
||||||
|
- [ ] If `object` passed Editor.js should initialize `tool` and pass this object as `config` parameter of the tool's constructor
|
||||||
|
- [ ] Checking the `shortcut` property
|
||||||
|
- [ ] If `string` passed Editor.js should append the `tool` when such keys combination executed.
|
||||||
|
- [ ] Checking the `inilineToolbar` property
|
||||||
|
- [ ] If `true`
|
||||||
|
- [ ] Editor.js should show the Inline Toolbar for this tool with [common](https://editorjs.io/configuration#inline-toolbar-order) settings.
|
||||||
|
- [ ] If `false`
|
||||||
|
- [ ] Editor.js should not show the Inline Toolbar for this tool.
|
||||||
|
- [ ] If `array`
|
||||||
|
- [ ] Editor.js should show the Inline Toolbar for this tool with a passed list of tools and their order.
|
||||||
|
- [ ] If omitted
|
||||||
|
- [ ] Editor.js should not show the Inline Toolbar for this tool.
|
||||||
|
- [ ] Checking the `toolbox` property
|
||||||
|
- [ ] If it contains `title`, this title should be used as a tool title
|
||||||
|
- [ ] If it contains `icon`, this HTML code (maybe SVG) should be used as a tool icon
|
6
types/api/toolbar.d.ts
vendored
6
types/api/toolbar.d.ts
vendored
|
@ -11,4 +11,10 @@ export interface Toolbar {
|
||||||
* Opens Toolbar
|
* Opens Toolbar
|
||||||
*/
|
*/
|
||||||
open(): void;
|
open(): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggles Block Setting of the current block
|
||||||
|
* @param {boolean} openingState — opening state of Block Setting
|
||||||
|
*/
|
||||||
|
toggleBlockSettings(openingState?: boolean): void;
|
||||||
}
|
}
|
||||||
|
|
2
types/configs/editor-config.d.ts
vendored
2
types/configs/editor-config.d.ts
vendored
|
@ -11,7 +11,7 @@ export interface EditorConfig {
|
||||||
holderId?: string | HTMLElement;
|
holderId?: string | HTMLElement;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Element where Editor will be append
|
* Element where Editor will be appended
|
||||||
*/
|
*/
|
||||||
holder?: string | HTMLElement;
|
holder?: string | HTMLElement;
|
||||||
|
|
||||||
|
|
8
types/configs/sanitizer-config.d.ts
vendored
8
types/configs/sanitizer-config.d.ts
vendored
|
@ -1,3 +1,9 @@
|
||||||
|
/**
|
||||||
|
* Sanitizer config of each HTML element
|
||||||
|
* @see {@link https://github.com/guardian/html-janitor#options}
|
||||||
|
*/
|
||||||
|
type TagConfig = boolean | { [attr: string]: boolean | string };
|
||||||
|
|
||||||
export interface SanitizerConfig {
|
export interface SanitizerConfig {
|
||||||
/**
|
/**
|
||||||
* Tag name and params not to be stripped off
|
* Tag name and params not to be stripped off
|
||||||
|
@ -31,5 +37,5 @@ export interface SanitizerConfig {
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
[key: string]: boolean|{[attr: string]: boolean|string}|(() => any);
|
[key: string]: TagConfig | ((el: Element) => TagConfig);
|
||||||
}
|
}
|
||||||
|
|
11
types/data-formats/output-data.d.ts
vendored
11
types/data-formats/output-data.d.ts
vendored
|
@ -2,16 +2,19 @@ import {BlockToolData} from '../tools';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Output of one Tool
|
* Output of one Tool
|
||||||
|
*
|
||||||
|
* @template Type - the string literal describing a tool type
|
||||||
|
* @template Data - the structure describing a data object supported by the tool
|
||||||
*/
|
*/
|
||||||
export interface OutputBlockData {
|
export interface OutputBlockData<Type extends string = string, Data extends object = any> {
|
||||||
/**
|
/**
|
||||||
* Too type
|
* Tool type
|
||||||
*/
|
*/
|
||||||
type: string;
|
type: Type;
|
||||||
/**
|
/**
|
||||||
* Saved Block data
|
* Saved Block data
|
||||||
*/
|
*/
|
||||||
data: BlockToolData;
|
data: BlockToolData<Data>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface OutputData {
|
export interface OutputData {
|
||||||
|
|
2
types/index.d.ts
vendored
2
types/index.d.ts
vendored
|
@ -104,8 +104,6 @@ declare class EditorJS {
|
||||||
|
|
||||||
public blocks: Blocks;
|
public blocks: Blocks;
|
||||||
public caret: Caret;
|
public caret: Caret;
|
||||||
public events: Events;
|
|
||||||
public listeners: Listeners;
|
|
||||||
public sanitizer: Sanitizer;
|
public sanitizer: Sanitizer;
|
||||||
public saver: Saver;
|
public saver: Saver;
|
||||||
public selection: Selection;
|
public selection: Selection;
|
||||||
|
|
6
types/tools/tool-settings.d.ts
vendored
6
types/tools/tool-settings.d.ts
vendored
|
@ -18,8 +18,10 @@ export interface ToolboxConfig {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Object passed to the Tool's constructor by {@link EditorConfig#tools}
|
* Object passed to the Tool's constructor by {@link EditorConfig#tools}
|
||||||
|
*
|
||||||
|
* @template Config - the structure describing a config object supported by the tool
|
||||||
*/
|
*/
|
||||||
export interface ToolSettings {
|
export interface ToolSettings <Config extends object = any> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tool's class
|
* Tool's class
|
||||||
|
@ -29,7 +31,7 @@ export interface ToolSettings {
|
||||||
/**
|
/**
|
||||||
* User configuration object that will be passed to the Tool's constructor
|
* User configuration object that will be passed to the Tool's constructor
|
||||||
*/
|
*/
|
||||||
config?: ToolConfig;
|
config?: ToolConfig<Config>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is need to show Inline Toolbar.
|
* Is need to show Inline Toolbar.
|
||||||
|
|
10
yarn.lock
10
yarn.lock
|
@ -3620,8 +3620,9 @@ inherits@2.0.3:
|
||||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
|
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
|
||||||
|
|
||||||
ini@^1.3.4, ini@^1.3.5:
|
ini@^1.3.4, ini@^1.3.5:
|
||||||
version "1.3.5"
|
version "1.3.8"
|
||||||
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
|
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c"
|
||||||
|
integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==
|
||||||
|
|
||||||
inquirer@^7.0.0:
|
inquirer@^7.0.0:
|
||||||
version "7.1.0"
|
version "7.1.0"
|
||||||
|
@ -4564,6 +4565,11 @@ mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.4, mkdirp@~0.5.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
minimist "^1.2.5"
|
minimist "^1.2.5"
|
||||||
|
|
||||||
|
mkdirp@^1.0.4:
|
||||||
|
version "1.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
|
||||||
|
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
|
||||||
|
|
||||||
moment@^2.27.0:
|
moment@^2.27.0:
|
||||||
version "2.29.1"
|
version "2.29.1"
|
||||||
resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3"
|
resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3"
|
||||||
|
|
Loading…
Reference in a new issue