Showing preview only (1,245K chars total). Download the full file or copy to clipboard to get everything.
Repository: codex-team/editor.js
Branch: next
Commit: 530ec56bb87e
Files: 304
Total size: 1.1 MB
Directory structure:
gitextract_ol6jf4j0/
├── .editorconfig
├── .eslintignore
├── .eslintrc
├── .github/
│ ├── CODE_OF_CONDUCT.md
│ ├── FUNDING.yml
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.md
│ │ ├── config.yml
│ │ └── general_issue.md
│ └── workflows/
│ ├── bump-version-on-merge-next.yml
│ ├── create-a-release-draft.yml
│ ├── cypress.yml
│ ├── eslint.yml
│ └── publish-package-to-npm.yml
├── .gitignore
├── .npmignore
├── .nvmrc
├── .postcssrc.yml
├── .stylelintrc
├── .vscode/
│ └── settings.json
├── CODEOWNERS
├── LICENSE
├── README.md
├── cypress.config.ts
├── docs/
│ ├── CHANGELOG.md
│ ├── api.md
│ ├── block-tunes.md
│ ├── caret.md
│ ├── installation.md
│ ├── releases.md
│ ├── sanitizer.md
│ ├── toolbar-settings.md
│ ├── tools-inline.md
│ ├── tools.md
│ └── usage.md
├── example/
│ ├── example-i18n.html
│ ├── example-multiple.html
│ ├── example-popup.html
│ ├── example-rtl.html
│ └── example.html
├── index.html
├── package.json
├── public/
│ └── assets/
│ ├── demo.css
│ └── json-preview.js
├── src/
│ ├── codex.ts
│ ├── components/
│ │ ├── __module.ts
│ │ ├── block/
│ │ │ ├── api.ts
│ │ │ └── index.ts
│ │ ├── block-tunes/
│ │ │ ├── block-tune-delete.ts
│ │ │ ├── block-tune-move-down.ts
│ │ │ └── block-tune-move-up.ts
│ │ ├── blocks.ts
│ │ ├── constants.ts
│ │ ├── core.ts
│ │ ├── dom.ts
│ │ ├── domIterator.ts
│ │ ├── errors/
│ │ │ └── critical.ts
│ │ ├── events/
│ │ │ ├── BlockChanged.ts
│ │ │ ├── BlockHovered.ts
│ │ │ ├── EditorMobileLayoutToggled.ts
│ │ │ ├── FakeCursorAboutToBeToggled.ts
│ │ │ ├── FakeCursorHaveBeenSet.ts
│ │ │ ├── RedactorDomChanged.ts
│ │ │ └── index.ts
│ │ ├── flipper.ts
│ │ ├── i18n/
│ │ │ ├── index.ts
│ │ │ ├── locales/
│ │ │ │ └── en/
│ │ │ │ └── messages.json
│ │ │ └── namespace-internal.ts
│ │ ├── inline-tools/
│ │ │ ├── inline-tool-bold.ts
│ │ │ ├── inline-tool-convert.ts
│ │ │ ├── inline-tool-italic.ts
│ │ │ └── inline-tool-link.ts
│ │ ├── modules/
│ │ │ ├── api/
│ │ │ │ ├── blocks.ts
│ │ │ │ ├── caret.ts
│ │ │ │ ├── events.ts
│ │ │ │ ├── i18n.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── inlineToolbar.ts
│ │ │ │ ├── listeners.ts
│ │ │ │ ├── notifier.ts
│ │ │ │ ├── readonly.ts
│ │ │ │ ├── sanitizer.ts
│ │ │ │ ├── saver.ts
│ │ │ │ ├── selection.ts
│ │ │ │ ├── styles.ts
│ │ │ │ ├── toolbar.ts
│ │ │ │ ├── tools.ts
│ │ │ │ ├── tooltip.ts
│ │ │ │ └── ui.ts
│ │ │ ├── blockEvents.ts
│ │ │ ├── blockManager.ts
│ │ │ ├── blockSelection.ts
│ │ │ ├── caret.ts
│ │ │ ├── crossBlockSelection.ts
│ │ │ ├── dragNDrop.ts
│ │ │ ├── index.ts
│ │ │ ├── modificationsObserver.ts
│ │ │ ├── paste.ts
│ │ │ ├── readonly.ts
│ │ │ ├── rectangleSelection.ts
│ │ │ ├── renderer.ts
│ │ │ ├── saver.ts
│ │ │ ├── toolbar/
│ │ │ │ ├── blockSettings.ts
│ │ │ │ ├── index.ts
│ │ │ │ └── inline.ts
│ │ │ ├── tools.ts
│ │ │ └── ui.ts
│ │ ├── polyfills.ts
│ │ ├── selection.ts
│ │ ├── tools/
│ │ │ ├── base.ts
│ │ │ ├── block.ts
│ │ │ ├── collection.ts
│ │ │ ├── factory.ts
│ │ │ ├── inline.ts
│ │ │ └── tune.ts
│ │ ├── ui/
│ │ │ └── toolbox.ts
│ │ ├── utils/
│ │ │ ├── api.ts
│ │ │ ├── bem.ts
│ │ │ ├── blocks.ts
│ │ │ ├── caret.ts
│ │ │ ├── events.ts
│ │ │ ├── keyboard.ts
│ │ │ ├── listeners.ts
│ │ │ ├── mutations.ts
│ │ │ ├── notifier.ts
│ │ │ ├── popover/
│ │ │ │ ├── components/
│ │ │ │ │ ├── hint/
│ │ │ │ │ │ ├── hint.const.ts
│ │ │ │ │ │ ├── hint.css
│ │ │ │ │ │ ├── hint.ts
│ │ │ │ │ │ └── index.ts
│ │ │ │ │ ├── popover-header/
│ │ │ │ │ │ ├── index.ts
│ │ │ │ │ │ ├── popover-header.const.ts
│ │ │ │ │ │ ├── popover-header.ts
│ │ │ │ │ │ └── popover-header.types.ts
│ │ │ │ │ ├── popover-item/
│ │ │ │ │ │ ├── index.ts
│ │ │ │ │ │ ├── popover-item-default/
│ │ │ │ │ │ │ ├── popover-item-default.const.ts
│ │ │ │ │ │ │ └── popover-item-default.ts
│ │ │ │ │ │ ├── popover-item-html/
│ │ │ │ │ │ │ ├── popover-item-html.const.ts
│ │ │ │ │ │ │ └── popover-item-html.ts
│ │ │ │ │ │ ├── popover-item-separator/
│ │ │ │ │ │ │ ├── popover-item-separator.const.ts
│ │ │ │ │ │ │ └── popover-item-separator.ts
│ │ │ │ │ │ └── popover-item.ts
│ │ │ │ │ └── search-input/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── search-input.const.ts
│ │ │ │ │ ├── search-input.ts
│ │ │ │ │ └── search-input.types.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── popover-abstract.ts
│ │ │ │ ├── popover-desktop.ts
│ │ │ │ ├── popover-inline.ts
│ │ │ │ ├── popover-mobile.ts
│ │ │ │ ├── popover.const.ts
│ │ │ │ └── utils/
│ │ │ │ └── popover-states-history.ts
│ │ │ ├── promise-queue.ts
│ │ │ ├── resolve-aliases.ts
│ │ │ ├── sanitizer.ts
│ │ │ ├── scroll-locker.ts
│ │ │ ├── shortcuts.ts
│ │ │ ├── tools.ts
│ │ │ └── tooltip.ts
│ │ └── utils.ts
│ ├── env.d.ts
│ ├── styles/
│ │ ├── animations.css
│ │ ├── block.css
│ │ ├── export.css
│ │ ├── inline-toolbar.css
│ │ ├── input.css
│ │ ├── main.css
│ │ ├── placeholders.css
│ │ ├── popover-inline.css
│ │ ├── popover.css
│ │ ├── rtl.css
│ │ ├── stub.css
│ │ ├── toolbar.css
│ │ ├── toolbox.css
│ │ ├── ui.css
│ │ └── variables.css
│ ├── tools/
│ │ └── stub/
│ │ └── index.ts
│ └── types-internal/
│ ├── editor-modules.d.ts
│ ├── html-janitor.d.ts
│ ├── i18n-internal-namespace.d.ts
│ └── module-config.d.ts
├── test/
│ ├── cypress/
│ │ ├── .eslintrc
│ │ ├── fixtures/
│ │ │ ├── test.html
│ │ │ ├── tools/
│ │ │ │ ├── ContentlessTool.ts
│ │ │ │ ├── SimpleHeader.ts
│ │ │ │ ├── ToolMock.ts
│ │ │ │ └── ToolWithoutConversionExport.ts
│ │ │ └── types/
│ │ │ └── PartialBlockMutationEvent.ts
│ │ ├── support/
│ │ │ ├── commands.ts
│ │ │ ├── e2e.ts
│ │ │ ├── index.d.ts
│ │ │ ├── index.ts
│ │ │ └── utils/
│ │ │ ├── createEditorWithTextBlocks.ts
│ │ │ ├── createParagraphMock.ts
│ │ │ └── nestedEditorInstance.ts
│ │ ├── tests/
│ │ │ ├── api/
│ │ │ │ ├── block.cy.ts
│ │ │ │ ├── blocks.cy.ts
│ │ │ │ ├── caret.cy.ts
│ │ │ │ ├── toolbar.cy.ts
│ │ │ │ ├── tools.cy.ts
│ │ │ │ └── tunes.cy.ts
│ │ │ ├── block-ids.cy.ts
│ │ │ ├── copy-paste.cy.ts
│ │ │ ├── i18n.cy.ts
│ │ │ ├── initialization.cy.ts
│ │ │ ├── inline-tools/
│ │ │ │ └── link.cy.ts
│ │ │ ├── modules/
│ │ │ │ ├── BlockEvents/
│ │ │ │ │ ├── ArrowLeft.cy.ts
│ │ │ │ │ ├── ArrowRight.cy.ts
│ │ │ │ │ ├── Backspace.cy.ts
│ │ │ │ │ ├── Delete.cy.ts
│ │ │ │ │ ├── Enter.cy.ts
│ │ │ │ │ ├── Slash.cy.ts
│ │ │ │ │ └── Tab.cy.ts
│ │ │ │ ├── InlineToolbar.cy.ts
│ │ │ │ ├── Renderer.cy.ts
│ │ │ │ ├── Saver.cy.ts
│ │ │ │ ├── Tools.cy.ts
│ │ │ │ └── Ui.cy.ts
│ │ │ ├── onchange.cy.ts
│ │ │ ├── readOnly.cy.ts
│ │ │ ├── sanitisation.cy.ts
│ │ │ ├── selection.cy.ts
│ │ │ ├── tools/
│ │ │ │ ├── BlockTool.cy.ts
│ │ │ │ ├── BlockTune.cy.ts
│ │ │ │ ├── InlineTool.cy.ts
│ │ │ │ ├── ToolsCollection.cy.ts
│ │ │ │ └── ToolsFactory.cy.ts
│ │ │ ├── ui/
│ │ │ │ ├── BlockTunes.cy.ts
│ │ │ │ ├── DataEmpty.cy.ts
│ │ │ │ ├── InlineToolbar.cy.ts
│ │ │ │ ├── Placeholders.cy.ts
│ │ │ │ └── toolbox.cy.ts
│ │ │ ├── utils/
│ │ │ │ ├── flipper.cy.ts
│ │ │ │ └── popover.cy.ts
│ │ │ └── utils.cy.ts
│ │ └── tsconfig.json
│ └── testcases.md
├── tsconfig.build.json
├── tsconfig.json
├── tslint.json
├── types/
│ ├── api/
│ │ ├── block.d.ts
│ │ ├── blocks.d.ts
│ │ ├── caret.d.ts
│ │ ├── events.d.ts
│ │ ├── i18n.d.ts
│ │ ├── index.d.ts
│ │ ├── inline-toolbar.d.ts
│ │ ├── listeners.d.ts
│ │ ├── notifier.d.ts
│ │ ├── readonly.d.ts
│ │ ├── sanitizer.d.ts
│ │ ├── saver.d.ts
│ │ ├── selection.d.ts
│ │ ├── styles.d.ts
│ │ ├── toolbar.d.ts
│ │ ├── tools.d.ts
│ │ ├── tooltip.d.ts
│ │ └── ui.d.ts
│ ├── block-tunes/
│ │ ├── block-tune-data.d.ts
│ │ ├── block-tune.d.ts
│ │ └── index.d.ts
│ ├── configs/
│ │ ├── conversion-config.ts
│ │ ├── editor-config.d.ts
│ │ ├── i18n-config.d.ts
│ │ ├── i18n-dictionary.d.ts
│ │ ├── index.d.ts
│ │ ├── log-levels.d.ts
│ │ ├── paste-config.d.ts
│ │ └── sanitizer-config.d.ts
│ ├── data-formats/
│ │ ├── block-data.d.ts
│ │ ├── block-id.ts
│ │ ├── index.d.ts
│ │ └── output-data.d.ts
│ ├── events/
│ │ └── block/
│ │ ├── Base.ts
│ │ ├── BlockAdded.ts
│ │ ├── BlockChanged.ts
│ │ ├── BlockMoved.ts
│ │ ├── BlockRemoved.ts
│ │ └── index.ts
│ ├── index.d.ts
│ ├── tools/
│ │ ├── adapters/
│ │ │ ├── base-tool-adapter.d.ts
│ │ │ ├── block-tool-adapter.d.ts
│ │ │ ├── block-tune-adapter.d.ts
│ │ │ ├── inline-tool-adapter.d.ts
│ │ │ ├── tool-factory.d.ts
│ │ │ ├── tool-type.ts
│ │ │ └── tools-collection.d.ts
│ │ ├── block-tool-data.d.ts
│ │ ├── block-tool.d.ts
│ │ ├── hook-events.d.ts
│ │ ├── index.d.ts
│ │ ├── inline-tool.d.ts
│ │ ├── menu-config.d.ts
│ │ ├── paste-events.d.ts
│ │ ├── tool-config.d.ts
│ │ ├── tool-settings.d.ts
│ │ └── tool.d.ts
│ └── utils/
│ └── popover/
│ ├── hint.d.ts
│ ├── index.d.ts
│ ├── popover-event.ts
│ ├── popover-item-type.ts
│ ├── popover-item.d.ts
│ └── popover.d.ts
├── vite.config.js
└── vite.config.test.js
================================================
FILE CONTENTS
================================================
================================================
FILE: .editorconfig
================================================
root = false
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
================================================
FILE: .eslintignore
================================================
node_modules
*.d.ts
src/components/tools/paragraph
src/polyfills.ts
================================================
FILE: .eslintrc
================================================
{
"extends": [
"codex/ts"
],
"globals": {
"Node": true,
"Range": true,
"HTMLElement": true,
"HTMLDivElement": true,
"Element": true,
"Selection": true,
"SVGElement": true,
"Text": true,
"InsertPosition": true,
"PropertyKey": true,
"MouseEvent": true,
"TouchEvent": true,
"KeyboardEvent": true,
"ClipboardEvent": true,
"DragEvent": true,
"Event": true,
"EventTarget": true,
"Document": true,
"NodeList": true,
"File": true,
"FileList": true,
"MutationRecord": true,
"AddEventListenerOptions": true,
"DataTransfer": true,
"DOMRect": true,
"ClientRect": true,
"ArrayLike": true,
"InputEvent": true,
"unknown": true,
"requestAnimationFrame": true,
"navigator": true
},
"rules": {
"jsdoc/require-returns-type": "off",
"@typescript-eslint/strict-boolean-expressions": "warn",
"@typescript-eslint/consistent-type-imports": "error",
"@typescript-eslint/consistent-type-exports": "error"
},
"overrides": [
{
"files": [
"tsconfig.json",
"package.json",
"tsconfig.*.json",
"tslint.json"
],
"rules": {
"quotes": [1, "double"],
"semi": [1, "never"],
}
}
]
}
================================================
FILE: .github/CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at team@codex.so. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq
================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms
patreon: editorjs
open_collective: editorjs
custom: https://codex.so/donate
================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a report to help us improve Editor.js
title: ""
labels: bug
assignees: ''
---
Describe a bug.
Steps to reproduce:
1. Go to …
2. Click on …
3. …
Expected behavior:
Screenshots:
Device, Browser, OS:
Editor.js version:
Plugins you use with their versions:
<!--
🤫 If you like Editor.js, please consider supporting us via OpenCollective:
https://opencollective.com/editorjs
-->
================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false
contact_links:
- name: Team
url: mailto:team@codex.so
about: Direct team contact.
- name: 💬 Discussions
url: https://github.com/codex-team/editor.js/discussions
about: Use discussions if you have an issue draft, an idea for improvement or for asking questions.
- name: Editor.js Telegram chat
url: https://t.me/codex_editor
about: Telegram chat for Editor.js users communication.
================================================
FILE: .github/ISSUE_TEMPLATE/general_issue.md
================================================
---
name: General Issue
about: Well-designed, algorithmized feature/idea/improvement issue for Editor.js
title: ''
labels: ''
assignees: ''
---
The question.
Why and how the question has come up.
<!--
🤫 If you like Editor.js, please consider supporting us via OpenCollective:
https://opencollective.com/editorjs
-->
================================================
FILE: .github/workflows/bump-version-on-merge-next.yml
================================================
name: Bump version on merge
# Caution:
# the use of "pull_request_target" trigger allows to successfully
# run workflow even when triggered from a fork. The trigger grants
# access to repo's secrets and gives write permission to the runner.
# This can be used to run malicious code on untrusted PR, so, please
# DO NOT checkout any PR's ongoing commits (aka github.event.pull_request.head.sha)
# while using this trigger.
on:
pull_request_target:
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
permissions:
actions: write
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 if version was changed already
if: steps.packageOld.outputs.version != steps.packageNew.outputs.version
run: |
curl -L \
-X POST \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/cancel
bump-version:
needs: check-for-no-version-changing
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
# Checkout to target branch
- uses: actions/checkout@v2
# Setup node environment
- uses: actions/setup-node@v1
with:
node-version: 16
# 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 }}
================================================
FILE: .github/workflows/create-a-release-draft.yml
================================================
name: Create a release draft
# Caution:
# the use of "pull_request_target" trigger allows to successfully
# run workflow even when triggered from a fork. The trigger grants
# access to repo's secrets and gives write permission to the runner.
# This can be used to run malicious code on untrusted PR, so, please
# DO NOT checkout any PR's ongoing commits (aka github.event.pull_request.head.sha)
# while using this trigger.
on:
pull_request_target:
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
permissions:
actions: write
steps:
- uses: actions/setup-node@v3
with:
node-version: 16
# 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
if: steps.packageOld.outputs.version == steps.packageNew.outputs.version
run: |
curl -L \
-X POST \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/cancel
# Create a new draft release
release-draft:
needs: check-version-changing
runs-on: ubuntu-latest
permissions:
contents: write
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: 16
# 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 UMD 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/editorjs.umd.js
asset_name: editorjs.umd.js
asset_content_type: application/javascript
# Build and upload target Editor.js MJS 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/editorjs.mjs
asset_name: editorjs.mjs
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
================================================
FILE: .github/workflows/cypress.yml
================================================
name: Cypress
on: [pull_request]
jobs:
run-tests:
strategy:
matrix:
browser: [firefox, chrome, edge]
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v3
with:
node-version: 18
- name: Setup Firefox
if: matrix.browser == 'firefox'
uses: browser-actions/setup-firefox@v1
with:
firefox-version: '115.0esr'
- uses: cypress-io/github-action@v6
with:
config: video=false
browser: ${{ matrix.browser }}
build: yarn build:test
================================================
FILE: .github/workflows/eslint.yml
================================================
name: ESLint CodeX
on: [pull_request]
jobs:
lint:
name: ESlint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v3
with:
node-version: 18
- name: Cache dependencies
uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-node-
- run: yarn
- run: yarn lint
================================================
FILE: .github/workflows/publish-package-to-npm.yml
================================================
name: Publish package to NPM
on:
release:
types:
- published
jobs:
publish:
runs-on: ubuntu-latest
steps:
# Checkout to target branch
- uses: actions/checkout@v4
with:
# Pull submodules
submodules: 'recursive'
- name: Get package info
id: package
uses: codex-team/action-nodejs-package-info@v1
# Setup node environment
- uses: actions/setup-node@v1
with:
node-version: 16
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 with a NEXT tag
run: yarn publish --access=public --tag=next
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Add LATEST tag for the published package if this is not a prerelease version
if: github.event.release.prerelease != true
run: npm dist-tag add ${{ steps.package.outputs.name }}@${{ steps.package.outputs.version }} latest
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
notify:
needs: publish
runs-on: ubuntu-latest
env:
GITHUB_LINK: ${{ github.server_url }}/${{ github.repository }}/releases/tag/${{ github.ref_name }}
steps:
# Checkout to target branch
- uses: actions/checkout@v4
- 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.version }}](${{ env.GITHUB_LINK }}) was published'
parse_mode: 'markdown'
disable_web_page_preview: true
================================================
FILE: .gitignore
================================================
# --- proj files ---
.DS_Store
Thumbs.db
/.idea/
/*.sublime-project
/*.sublime-workspace
node_modules/*
npm-debug.log
yarn-error.log
test/cypress/screenshots
test/cypress/videos
dist/
coverage/
.nyc_output/
.vscode/launch.json
================================================
FILE: .npmignore
================================================
*
!/dist/**/*
!/types/**/*
!/LICENSE
!/README.md
!/package.json
================================================
FILE: .nvmrc
================================================
v18.20.1
================================================
FILE: .postcssrc.yml
================================================
plugins:
# Apply custom property sets via @apply rule
# https://github.com/pascalduez/postcss-apply
postcss-apply: {}
# Convert modern CSS into something most browsers can understand
# https://github.com/csstools/postcss-preset-env
postcss-preset-env:
# Polyfill CSS features
# https://github.com/csstools/postcss-preset-env#stage
#
# List of features with levels: https://cssdb.org/
stage: 0
# Define polyfills based on browsers you are supporting
# https://github.com/csstools/postcss-preset-env#browsers
browsers:
- 'last 2 versions'
- '> 1%'
# Instruct all plugins to omit pre-polyfilled CSS
# https://github.com/csstools/postcss-preset-env#preserve
preserve: false
# Nested rules unwrapper
# https://github.com/postcss/postcss-nested
#
# As you know 'postcss-preset-env' plugin has an ability to process
# 'postcss-nesting' feature but it does not work with BEM
# Report: https://github.com/csstools/postcss-preset-env/issues/40
postcss-nested: {}
================================================
FILE: .stylelintrc
================================================
{
"rules": {
"at-rule-empty-line-before": [
"always",
{
except: [
"blockless-after-same-name-blockless",
"first-nested",
],
ignore: [
"after-comment"
],
}
],
"at-rule-name-case": "lower",
"at-rule-name-space-after": "always-single-line",
"at-rule-semicolon-newline-after": "always",
"block-closing-brace-empty-line-before": "never",
"block-closing-brace-newline-after": "always",
"block-closing-brace-newline-before": "always-multi-line",
"block-closing-brace-space-before": "always-single-line",
"block-no-empty": true,
"block-opening-brace-newline-after": "always-multi-line",
"block-opening-brace-space-after": "always-single-line",
"block-opening-brace-space-before": "always",
"color-hex-case": "lower",
"color-hex-length": "short",
"color-no-invalid-hex": true,
"comment-empty-line-before": [
"always",
{
except: [
"first-nested"
],
ignore: [
"stylelint-commands"
],
}
],
"comment-no-empty": true,
"comment-whitespace-inside": "always",
"custom-property-empty-line-before": [
"always",
{
except: [
"after-custom-property",
"first-nested",
],
ignore: [
"after-comment",
"inside-single-line-block",
],
}
],
"declaration-bang-space-after": "never",
"declaration-bang-space-before": "always",
"declaration-block-no-duplicate-properties": [
true,
{
ignore: [
"consecutive-duplicates-with-different-values"
],
}
],
"declaration-block-no-redundant-longhand-properties": true,
"declaration-block-no-shorthand-property-overrides": true,
"declaration-block-semicolon-newline-after": "always-multi-line",
"declaration-block-semicolon-space-after": "always-single-line",
"declaration-block-semicolon-space-before": "never",
"declaration-block-single-line-max-declarations": 1,
"declaration-block-trailing-semicolon": "always",
"declaration-colon-newline-after": "always-multi-line",
"declaration-colon-space-after": "always-single-line",
"declaration-colon-space-before": "never",
"declaration-empty-line-before": [
"always",
{
except: [
"after-declaration",
"first-nested",
],
ignore: [
"after-comment",
"inside-single-line-block",
],
}
],
"font-family-no-duplicate-names": true,
"function-calc-no-unspaced-operator": true,
"function-comma-newline-after": "always-multi-line",
"function-comma-space-after": "always-single-line",
"function-comma-space-before": "never",
"function-linear-gradient-no-nonstandard-direction": true,
"function-max-empty-lines": 0,
"function-name-case": "lower",
"function-parentheses-newline-inside": "always-multi-line",
"function-parentheses-space-inside": "never-single-line",
"function-whitespace-after": "always",
"indentation": 4,
"keyframe-declaration-no-important": true,
"length-zero-no-unit": true,
"max-empty-lines": 1,
"media-feature-colon-space-after": "always",
"media-feature-colon-space-before": "never",
"media-feature-name-case": "lower",
"media-feature-name-no-unknown": true,
"media-feature-parentheses-space-inside": "never",
"media-feature-range-operator-space-after": "always",
"media-feature-range-operator-space-before": "always",
"media-query-list-comma-newline-after": "always-multi-line",
"media-query-list-comma-space-after": "always-single-line",
"media-query-list-comma-space-before": "never",
"no-empty-source": true,
"no-eol-whitespace": true,
"no-extra-semicolons": true,
"no-invalid-double-slash-comments": true,
"no-missing-end-of-source-newline": true,
"number-leading-zero": "always",
"number-no-trailing-zeros": true,
"property-case": "lower",
"property-no-unknown": true,
"rule-empty-line-before": [
"always-multi-line",
{
except: [
"first-nested"
],
ignore: [
"after-comment"
],
}
],
"selector-attribute-brackets-space-inside": "never",
"selector-attribute-operator-space-after": "never",
"selector-attribute-operator-space-before": "never",
"selector-combinator-space-after": "always",
"selector-combinator-space-before": "always",
"selector-descendant-combinator-no-non-space": true,
"selector-list-comma-newline-after": "always",
"selector-list-comma-space-before": "never",
"selector-max-empty-lines": 0,
"selector-pseudo-class-case": "lower",
"selector-pseudo-class-no-unknown": true,
"selector-pseudo-class-parentheses-space-inside": "never",
"selector-pseudo-element-case": "lower",
"selector-pseudo-element-colon-notation": "double",
"selector-pseudo-element-no-unknown": true,
"selector-type-case": "lower",
"selector-type-no-unknown": true,
"shorthand-property-no-redundant-values": true,
"string-no-newline": true,
"unit-case": "lower",
"unit-no-unknown": true,
"value-list-comma-newline-after": "always-multi-line",
"value-list-comma-space-after": "always-single-line",
"value-list-comma-space-before": "never",
"value-list-max-empty-lines": 0,
},
}
================================================
FILE: .vscode/settings.json
================================================
{
"cSpell.words": [
"autofocused",
"Behaviour",
"cacheable",
"childs",
"codexteam",
"colspan",
"contenteditable",
"contentless",
"Convertable",
"cssnano",
"cssnext",
"Debouncer",
"devserver",
"editorjs",
"entrypoints",
"Flippable",
"GRAMMARLY",
"hsablonniere",
"intellij",
"keydown",
"keydowns",
"Kilian",
"mergeable",
"movetostart",
"nofollow",
"opencollective",
"preconfigured",
"resetors",
"rowspan",
"selectall",
"sometool",
"stylelint",
"textareas",
"twitterwidget",
"typeof",
"Unmergeable",
"viewports"
]
}
================================================
FILE: CODEOWNERS
================================================
* @neSpecc @gohabereg @TatianaFomina @ilyamore88
================================================
FILE: LICENSE
================================================
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
Copyright © 2015-present CodeX
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.
================================================
FILE: README.md
================================================
<p align="center">
<a href="https://editorjs.io/">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./assets/logo_night.png">
<source media="(prefers-color-scheme: light)" srcset="./assets/logo_day.png">
<img alt="Editor.js Logo" src="./assets/logo_day.png">
</picture>
</a>
</p>
<p align="center">
<a href="https://editorjs.io/">editorjs.io</a> |
<a href="https://editorjs.io/base-concepts/">documentation</a> |
<a href="https://github.com/codex-team/editor.js/blob/next/docs/CHANGELOG.md">changelog</a>
</p>
<p align="center">
<a href="https://www.npmjs.com/package/@editorjs/editorjs">
<img src="https://flat.badgen.net/npm/v/@editorjs/editorjs?icon=npm" alt="npm"/>
</a>
<a href="https://www.npmjs.com/package/@editorjs/editorjs">
<img src="https://flat.badgen.net/bundlephobia/minzip/@editorjs/editorjs?color=green" alt="Minzipped size"/>
</a>
<a href="https://github.com/codex-team/editor.js#backers">
<img src="https://opencollective.com/editorjs/backers/badge.svg" alt="Backers on Open Collective"/>
</a>
<a href="https://github.com/codex-team/editor.js#sponsors">
<img src="https://opencollective.com/editorjs/sponsors/badge.svg" alt="Sponsors on Open Collective"/>
</a>
</p>
## About
Editor.js is an open-source text editor offering a variety of features to help users create and format content efficiently. It has a modern, block-style interface that allows users to easily add and arrange different types of content, such as text, images, lists, quotes, etc. Each Block is provided via a separate plugin making Editor.js extremely flexible.
Editor.js outputs a clean JSON data instead of heavy HTML markup. Use it in Web, iOS, Android, AMP, Instant Articles, speech readers, AI chatbots — everywhere. Easy to sanitize, extend and integrate with your logic.
- 😍 Modern UI out of the box
- 💎 Clean JSON output
- ⚙️ Well-designed API
- 🛍 Various Tools available
- 💌 Free and open source
<picture>
<img alt="Editor.js Overview" src="./assets/overview.png">
</picture>
## Installation
It's quite simple:
1. Install Editor.js
2. Install tools you need
3. Initialize Editor's instance
Install using NPM, Yarn, or [CDN](https://www.jsdelivr.com/package/npm/@editorjs/editorjs):
```bash
npm i @editorjs/editorjs
```
Choose and install tools:
- [Heading](https://github.com/editor-js/header)
- [Quote](https://github.com/editor-js/quote)
- [Image](https://github.com/editor-js/image)
- [Simple Image](https://github.com/editor-js/simple-image) (without backend requirement)
- [Nested List](https://github.com/editor-js/nested-list)
- [Checklist](https://github.com/editor-js/checklist)
- [Link embed](https://github.com/editor-js/link)
- [Embeds](https://github.com/editor-js/embed) (YouTube, Twitch, Vimeo, Gfycat, Instagram, Twitter, etc)
- [Table](https://github.com/editor-js/table)
- [Delimiter](https://github.com/editor-js/delimiter)
- [Warning](https://github.com/editor-js/warning)
- [Code](https://github.com/editor-js/code)
- [Raw HTML](https://github.com/editor-js/raw)
- [Attaches](https://github.com/editor-js/attaches)
- [Marker](https://github.com/editor-js/marker)
- [Inline Code](https://github.com/editor-js/inline-code)
See the [😎 Awesome Editor.js](https://github.com/editor-js/awesome-editorjs) list for more tools.
Initialize the Editor:
```html
<div id="editorjs"></div>
```
```javascript
import EditorJS from '@editorjs/editorjs'
const editor = new EditorJS({
tools: {
// ... your tools
}
})
````
See details about [Installation](https://editorjs.io/getting-started/) and [Configuration](https://editorjs.io/configuration/) at the documentation.
### Saving Data
Call `editor.save()` and handle returned Promise with saved data.
```javascript
const data = await editor.save()
```
### Example
Take a look at the [example.html](example/example.html) to view more detailed examples.
## Roadmap
<img align="right" width="342" src="./assets/roadmap.png" style="margin-left: 30px">
- Unified Toolbars
- [x] Block Tunes moved left
- [x] Toolbox becomes vertical
- [x] Ability to display several Toolbox buttons by the single Tool
- [x] Block Tunes become vertical
- [x] Block Tunes support nested menus
- [x] Block Tunes support separators
- [x] Conversion Menu added to the Block Tunes
- [x] Unified Toolbar supports hints
- [x] Conversion Toolbar uses Unified Toolbar
- [x] Inline Toolbar uses Unified Toolbar
- Collaborative editing
- [ ] Implement Inline Tools JSON format
- [ ] Operations Observer, Executor, Manager, Transformer
- [ ] Implement Undo/Redo Manager
- [ ] Implement Tools API changes
- [ ] Implement Server and communication
- [ ] Update basic tools to fit the new API
- Other features
- [ ] Blocks drag'n'drop
- [ ] New cross-block selection
- [ ] New cross-block caret moving
- Ecosystem improvements
- [x] CodeX Icons — the way to unify all tools and core icons
- [x] New Homepage and Docs
- [x] @editorjs/create-tool for Tools bootstrapping
- [ ] Editor.js DevTools — stand for core and tools development
- [ ] Editor.js Design System
- [ ] Editor.js Preset Env
- [ ] Editor.js ToolKit
- [ ] New core bundle system
- [ ] New documentation and guides
<a href="https://opencollective.com/editorjs/donate" target="_blank">
<picture>
<source width="162px" media="(prefers-color-scheme: dark)" srcset="./assets/support_night.png">
<source width="162px" media="(prefers-color-scheme: light)" srcset="./assets/support_day.png">
<img width="162px" alt="Support Editor.js" src="./assets/support_day.png">
</picture>
</a>
<br>
## Like Editor.js?
You can support project improvement and development of new features with a donation to our team.
[Donate via OpenCollective](https://opencollective.com/editorjs)
\
[Donate via Crypto](https://codex.so/donate)
\
[Donate via Patreon](https://www.patreon.com/editorjs)
### Why donate
Donations to open-source products have several advantages for your business:
- If your business relies on Editor.js, you'll probably want it to be maintained
- It helps Editor.js to evolve and get the new features
- We can support contributors and the community around the project. You'll receive well organized docs, guides, etc.
- We need to pay for our infrastructure and maintain public resources (domain names, homepages, docs, etc). Supporting it guarantees you to access any resources at the time you need them.
- You can advertise by adding your brand assets and mentions on our public resources
### Sponsors
Support us by becoming a sponsor. Your logo will show up here with a link to your website.
<p>
<a href="https://www.mister-auto.com/" target="_blank">
<img src="https://opencollective-production.s3.us-west-1.amazonaws.com/5131a030-5672-11ec-be79-1d003d12ec5f.png" width="50" alt="Mister Auto">
</a>
<a href="https://www.uplucid.com/" target="_blank">
<img src="https://logo.clearbit.com/uplucid.com" width="50" alt="UPLUCID, K.K.">
</a>
<a href="https://www.contentharmony.com/" target="_blank">
<img src="https://opencollective-production.s3.us-west-1.amazonaws.com/89edb1b0-7d82-11ed-b99e-ab6e6f9cb69f.png" width="50" alt="Kane Jamison">
</a>
<a href="https://www.contentharmony.com/product/" target="_blank">
<img src="https://logo.clearbit.com/contentharmony.com" width="50" alt="Content Harmony">
</a>
</p>
[Become a Sponsor](https://opencollective.com/editorjs/contribute/sir-8679/checkout)
### Backers
Thank you to all our backers
<a href="https://opencollective.com/editorjs#backers" target="_blank"><img src="https://opencollective.com/editorjs/backers.svg?width=890&avatarHeight=34"></a>
[Become a Backer](https://opencollective.com/editorjs/contribute/backer-8632/checkout)
### Contributors
This project exists thanks to all the people who contribute.
<p><img src="https://opencollective.com/editorjs/contributors.svg?width=890&button=false&avatarHeight=34" /></p>
### Need something special?
Hire CodeX experts to resolve technical challenges and match your product requirements.
- Resolve a problem that has high value for you
- Implement a new feature required by your business
- Help with integration or tool development
- Provide any consultation
Contact us via team@codex.so and share your details
## Community
- [Official Tools](https://github.com/editor-js)
- [Awesome Editor.js](https://github.com/editor-js/awesome-editorjs)
- [Good First Tasks](https://github.com/codex-team/editor.js/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+task%22)
- [Contributing](https://editorjs.io/contributing/)
- [Telegram Chat](https://t.me/codex_editor)
# About CodeX
<img align="right" width="120" height="120" src="https://codex.so/public/app/img/codex-logo.svg" hspace="50">
CodeX is a team of digital specialists around the world interested in building high-quality open source products on a global market. We are [open](https://codex.so/join) for young people who want to constantly improve their skills and grow professionally with experiments in cutting-edge technologies.
| 🌐 | Join 👋 | Twitter | Instagram |
| -- | -- | -- | -- |
| [codex.so](https://codex.so) | [codex.so/join](https://codex.so/join) |[@codex_team](http://twitter.com/codex_team) | [@codex_team](http://instagram.com/codex_team/) |
================================================
FILE: cypress.config.ts
================================================
import { defineConfig } from 'cypress';
import path from 'node:path';
import vitePreprocessor from 'cypress-vite';
export default defineConfig({
env: {
NODE_ENV: 'test',
},
fixturesFolder: 'test/cypress/fixtures',
screenshotsFolder: 'test/cypress/screenshots',
video: false,
videosFolder: 'test/cypress/videos',
e2e: {
// We've imported your old cypress plugins here.
// You may want to clean this up later by importing these.
setupNodeEvents(on, config) {
on('file:preprocessor', vitePreprocessor({
configFile: path.resolve(__dirname, './vite.config.test.js'),
}));
/**
* Plugin for cypress that adds better terminal output for easier debugging.
* Prints cy commands, browser console logs, cy.request and cy.intercept data. Great for your pipelines.
* https://github.com/archfz/cypress-terminal-report
*/
require('cypress-terminal-report/src/installLogsPrinter')(on);
require('@cypress/code-coverage/task')(on, config);
},
specPattern: 'test/cypress/tests/**/*.cy.{js,jsx,ts,tsx}',
supportFile: 'test/cypress/support/index.ts',
},
'retries': {
// Configure retry attempts for `cypress run`
'runMode': 2,
// Configure retry attempts for `cypress open`
'openMode': 0,
},
});
================================================
FILE: docs/CHANGELOG.md
================================================
# Changelog
### 2.31.5
- `Fix` - Handle __Ctrl + click__ on links with inline styles applied (e.g., bold, italic)
### 2.31.4
- `Fix` - Prevent inline-toolbar re-renders when linked text is selected
### 2.31.3
- `Fix` - Prevent text formatting removal when applying link
### 2.31.2
- `Fix` - Prevent link removal when applying bold to linked text
### 2.31.1
- `Fix` - Prevent the warning from appearing when `readOnly` mode is initially set to `true`
### 2.31.0
- `New` - Inline tools (those with `isReadOnlySupported` specified) can now be used in read-only mode
- `New` - Inline tools (those with `isReadOnlySupported` specified) shortcuts now work in read-only mode
- `Improvement` - Block manager passes target tool config to the `conversionConfig.import` method on conversion
- `Fix` - Fix selection of first block in read-only initialization with "autofocus=true"
- `Fix` - Incorrect caret position after blocks merging in Safari
- `Fix` - Several toolbox items exported by the one tool have the same shortcut displayed in toolbox
- `Improvement` - The current block reference will be updated in read-only mode when blocks are clicked
- `Fix` - codex-notifier and codex-tooltip moved from devDependencies to dependencies in package.json to solve type errors
- `Fix` - Handle whitespace input in empty placeholder elements to prevent caret from moving unexpectedly to the end of the placeholder
- `Fix` - Fix the memory leak issue in `Shortcuts` class
- `Fix` - Fix when / overides selected text outside of the editor
- `DX` - Tools submodules removed from the repository
- `Improvement` - Shift + Down/Up will allow to select next/previous line instead of Inline Toolbar flipping
- `Improvement` - The API `caret.setToBlock()` offset now works across the entire block content, not just the first or last node.
- `Improvement` - The API `blocks.renderFromHTML()` became async and now can be awaited.
- `Fix` - `blocks.renderFromHTML()` — Error "Can't find a Block to remove." fixed
- `Fix` - The API `.clear()` index invalidation fixed
### 2.30.7
- `Fix` - Link insertion in Safari fixed
### 2.30.6
- `Fix` – Fix the display of ‘Convert To’ near blocks that do not have the ‘conversionConfig.export’ rule specified
- `Fix` – The Plus button does not appear when the editor is loaded in an iframe in Chrome
- `Fix` - Prevent inline toolbar from closing in nested instance of editor
### 2.30.5
– `Fix` – Fix exported types
### 2.30.4
- `Fix` - Tool's exporting types added
### 2.30.3
- `Fix` – I18n in nested popover
### 2.30.2
- `Fix` – The onChange callback won't be fired when editor is initialized in the Read-Only mode
- `Fix` – Convert To supports i18n again
- `Fix` – Prevent form submit on inline tool click
### 2.30.1
- `Fix` – Remove fake selection after multiple "convert to" inline tool toggles
### 2.30.0
- `New` – Block Tunes now supports nesting items
- `New` – Block Tunes now supports separator items
- `New` – *Menu Config* – New item type – HTML
- `New` – *Menu Config* – Default and HTML items now support hints
- `New` – Inline Toolbar has new look 💅
- `New` – Inline Tool's `render()` now supports [Menu Config](https://editorjs.io/menu-config/) format
- `New` – *ToolsAPI* – All installed block tools now accessible via ToolsAPI `getBlockTools()` method
- `New` – *SelectionAPI* – Exposed methods `save()` and `restore()` that allow to save selection to be able to temporally move focus away, methods `setFakeBackground()` and `removeFakeBackground()` that allow to immitate selection while focus moved away
- `New` – *BlocksAPI* – Exposed `getBlockByElement()` method that helps find block by any child html element
- `New` – "Convert to" control is now also available in Block Tunes
- `New` — Editor.js now supports contenteditable placeholders out of the box. Just add `data-placeholder` or `data-placeholder-active` attribute to make it work. The first one will work like native placeholder while the second one will show placeholder only when block is current.
- `Improvement` — Now Paragraph placeholder will be shown for the current paragraph, not only the first one.
- `Improvement` - The API `blocks.update` now accepts `tunes` data as optional third argument and makes `data` - block data as optional.
- `Improvement` — The ability to merge blocks of different types (if both tools provide the conversionConfig)
- `Improvement` - The API `blocks.convert()` now returns the new block API
- `Improvement` - The API `caret.setToBlock()` now can accept either BlockAPI or block index or block id
- `Improvement` – *MenuConfig* – `TunesMenuConfig` type is deprecated, use the `MenuConfig` instead
– `Improvement` — *Types* — `BlockToolConstructorOptions` type improved, `block` and `config` are not optional anymore
- `Improvement` - The Plus button and Block Tunes toggler are now better aligned with large line-height blocks, such as Headings
- `Improvement` — Creating links on Android devices: now the mobile keyboard will have an "Enter" key for accepting the inserted link.
- `Improvement` — Placeholders will stay visible on inputs focus.
– `Refactoring` – Switched to Vite as Cypress bundler
- `Fix` — `onChange` will be called when removing the entire text within a descendant element of a block.
- `Fix` - Unexpected new line on Enter press with selected block without caret
- `Fix` - Search input autofocus loosing after Block Tunes opening
- `Fix` - Block removing while Enter press on Block Tunes
- `Fix` – Unwanted scroll on first typing on iOS devices
- `Fix` - Unwanted soft line break on Enter press after period and space (". |") on iOS devices
- `Fix` - Caret lost after block conversion on mobile devices.
- `Fix` - Caret lost after Backspace at the start of block when previoius block is not convertable
– `Fix` — Deleting whitespaces at the start/end of the block
- `Fix` — The problem caused by missed "import type" in block mutation event types resolved
### 2.29.1
- `Fix` — Toolbox wont be shown when Slash pressed with along with Shift or Alt
- `Fix` — Toolbox will be opened when Slash pressed in non-US keyboard layout where there is no physical '/' key.
### 2.29.0
- `New` — Editor Config now has the `style.nonce` attribute that could be used to allowlist editor style tag for Content Security Policy "style-src"
- `New` — Toolbox now will be opened by '/' in empty Block instead of Tab
- `New` — Block Tunes now will be opened by 'CMD+/' instead of Tab in non-empty block
- `New` — Tab now will navigate through Blocks. In last block Tab will navigate to the next input on page.
- `Fix` — Passing an empty array via initial data or `blocks.render()` won't break the editor
- `Fix` — Layout did not shrink when a large document cleared in Chrome
- `Fix` — Multiple Tooltip elements creation fixed
- `Fix` — When the focusing Block is out of the viewport, the page will be scrolled.
- `Fix` - Compiler error "This import is never used as a value and must use 'import type'..." fixed
- `Fix` — `blocks.render()` won't lead the `onChange` call in Safari
- `Fix` — Editor wrapper element growing on the Inline Toolbar close
- `Fix` — Fix errors thrown by clicks on a document when the editor is being initialized
- `Fix` — Caret losing on Mobile Devices when adding a block via Toolbox or via Backspace at the beginning of a Block
- `Improvement` — Now you can set focus via arrows/Tab to "contentless" (decorative) blocks like Delimiter which have no inputs.
- `Improvement` — Inline Toolbar sometimes opened in an incorrect position. Now it will be aligned by the left side of the selected text. And won't overflow the right side of the text column.
- `Improvement` - Now the `data-mutation-free` supports deep nesting, so you can mark some element with it to prevent the onChange call caused by child element mutating
- `Improvement` - Now the `data-mutation-free` also allows to skip "characterData" mutations (eg. text content change)
- `Refactoring` — `ce-block--focused` class toggling removed as unused.
### 2.28.2
- `Fix` — Get rid of redundant logs from the build
### 2.28.1
- `Fix` — Some Block were be skipped on saving after pasting them as HTML
### 2.28.0
- `New` - Block ids now displayed in DOM via a data-id attribute. Could be useful for plugins that want to access a Block's element by id.
- `New` - The `blocks.convert(blockId, newType)` API method was added. It allows to convert existing Block to a Block of another type.
- `New` - The `blocks.insertMany()` API method added. It allows to insert several Blocks to the specified index.
- `Improvement` - The Delete keydown at the end of the Block will now work opposite a Backspace at the start. Next Block will be removed (if empty) or merged with the current one.
- `Improvement` - The Delete keydown will work like a Backspace when several Blocks are selected.
- `Improvement` - If we have two empty Blocks, and press Backspace at the start of the second one, the previous will be removed instead of the current.
- `Improvement` - Tools shortcuts could be used to convert one Block to another.
- `Improvement` - Tools shortcuts displayed in the Conversion Toolbar
- `Improvement` - Initialization Loader has been removed.
- `Improvement` - Selection style won't override your custom style for `::selection` outside the editor.
- `Improvement` - Performance optimizations: initialization speed increased, `blocks.render()` API method optimized. Big documents will be displayed faster.
- `Improvement` - "Editor saving" log removed
- `Improvement` - "I'm ready" log removed
- `Improvement` - The stub-block style is simplified.
- `Improvement` - If some Block's tool throws an error during construction, we will show Stub block instead of skipping it during render
- `Improvement` - Call of `blocks.clear()` now will trigger onChange with "block-removed" event for all removed blocks.
- `Improvement` - The `blocks.clear()` now can be awaited.
- `Improvement` - `BlockMutationType` and `BlockMutationEvent` types exported
- `Improvement` - `blocks.update(id, data)` now can accept partial data object — it will update only passed properties, others will remain the same.
- `Improvement` - `blocks.update(id, data)` now will trigger onChange with only `block-change` event.
- `Improvement` - `blocks.update(id, data)` will return a promise with BlockAPI object of the changed block.
### 2.27.2
- `Fix` - `onChange` won't be called when element with data-mutation-free changes some attribute
### 2.27.1
- `Fix` - `onChange` will be called on removing the whole text in a block
### 2.27.0
- `New` — *Toolbar API* — Added a new method for toggling the toolbox.
- `New` — Added types for block mutation events
- `New` — Batching added to the `onChange` callback. Now the second argument can contain an array of CustomEvents as well as a single one. Multiple changes made in a short period of time will be batched under a single `onChange` call.
- `Improvement` — *Toolbox* — Number of `close()` method calls optimized.
- `Improvement` — The `onChange` callback can be muted if all mutations contain nodes with the `data-mutation-free` attribute.
- `Improvement` — Pressing "Enter" at the end of a Block won't lead to redundant `block-changed` event triggering. Only `block-added` event will be dispatched.
- `Improvement` — The block mutation handler is now called on every block change (including background changes), instead of only when a block is focused
- `Improvement` — Number of caret saving method calls optimized for Block Tunes opening/closing.
- `Improvement` — Package size reduced by removing redundant files.
- `Refactoring` — Switched from Webpack to Vite as the build system.
- `Refactoring` — *Dependencies* — Upgraded Cypress to v12 and related libraries to the latest versions.
- `Refactoring` — *Dependencies* — Upgraded TypeScript to v5.
- `Refactoring` — `EventDispatcher` types improved. Now we can pass `EventsMap` via generic to specify a map of event names and their payloads that can be used in a particular EventDispatcher instance.
- `Refactoring` — All events in common editor Event Bus now have own type declarations.
- `Refactoring` — Removed the block mutation observer from blocks and attached a single observer to the editor's blocks wrapper element.
- `Refactoring` — Removed the debounce from the block mutation handler and used batching instead.
- `Refactoring` — Refactored the popover class for better performance and maintenance.
- `Fix` — The `onChange` callback won't trigger when block tunes are opened or closed.
- `Fix` — Resolved a compiler error caused by importing the `BlockToolData` type.
- `Fix` — Resolved a problem where the document would scroll to the beginning after moving a block above the viewport.
- `Fix`- Fixed several bugs caused by browser extensions — Removed the search for a block's container in the DOM on saving and kept it in memory instead, updating it when the tool changes a container element.
- `Fix` — *ToolsAPI* — `pasteConfig` getter with `false` value could be used to disable paste handling by Editor.js core. Could be useful if your tool has its own paste handler.
- `CI` — Ubuntu container is now used for Edge tests runner.
- `CI` — Node 16 is used for GitHib Actions.
### 2.26.5
- `Fix` — *Types* — Remove unnecessary import that creates a dependency on the `cypress`.
### 2.26.4
- `Improvement` — *Menu Config* — Property `label` renamed to `title`.
### 2.26.3
- `Fix` — *Paste Module* — fix for a problem with specifying of `pasteConfig().tags` in upper case [#2208](https://github.com/codex-team/editor.js/issues/2208).
### 2.26.2
- `Fix` — *Menu Config* — Installed tunes are rendered above default tunes again.
### 2.26.1
- `Improvement` — *Menu Config* — Now it becomes possible to create toggle groups.
### 2.26.0
- `New` — *UI* — Block Tunes became vertical just like the Toolbox 🤩
- `New` — *Block Tunes API* — Now `render()` method of a Block Tune can return config with just icon, label and callback instead of custom HTML. This improvement is a key to the new straightforward way of configuring tune's appearance in Block Tunes menu.
- `New` — *Tools API* — As well as `render()` in `Tunes API`, Tool's `renderSettings()` now also supports new configuration format.
- `New` — *UI* — Meet the new icons from [CodeX Icons](https://github.com/codex-team/icons) pack 🛍 💝
- `New` — *BlocksAPI* — the `blocks.insert()` method now also have the optional `id` param. If passed, this id will be used instead of the generated one.
- `Deprecated` — *Styles API* — CSS classes `.cdx-settings-button` and `.cdx-settings-button--active` are not recommended to use. Consider configuring your block settings with new JSON API instead.
- `Fix` — Wrong element not highlighted anymore when popover opened.
- `Fix` — When Tunes Menu open keydown events can not be handled inside plugins.
- `Fix` — If a Tool specifies some tags to substitute on paste, all attributes of that tags will be removed before passing them to the tool. Possible XSS vulnerability fixed.
- `Fix` — Pasting from Microsoft Word to Chrome (Mac OS) fixed. Now if there are no image-tools connected, regular text content will be pasted.
- `Fix` — Workaround for the HTMLJanitor bug with Tables (https://github.com/guardian/html-janitor/issues/3) added
- `Fix` — Toolbox shortcuts appearance and execution fixed [#2112](https://github.com/codex-team/editor.js/issues/2112)
- `Fix` — Inline Tools click handling on mobile devices improved
- `Improvement` — *Tools API* — `pasteConfig().tags` now support sanitizing configuration. It allows you to leave some explicitly specified attributes for pasted content.
- `Improvement` — *CodeStyle* — [CodeX ESLint Config](https://github.com/codex-team/eslint-config) has bee updated. All ESLint/Spelling issues resolved
- `Improvement` — *ToolsAPI* — The `icon` property of the `toolbox` getter became optional.
### 2.25.0
- `New` — *Tools API* — Introducing new feature — toolbox now can have multiple entries for one tool! <br>
Due to that API changes: tool's `toolbox` getter now can return either a single config item or an array of config items
- `New` — *Blocks API* — `composeBlockData()` method was added.
### 2.24.4
- `Fix` — Keyboard selection by word [#2045](https://github.com/codex-team/editor.js/issues/2045)
### 2.24.3
- `Fix` — Issue with toolbox preventing text selection fixed
### 2.24.2
- `Fix` — Scrolling issue when opening toolbox on mobile fixed
- `Fix` — Typo in toolbox empty placeholder fixed
- `Fix` — The issue with scroll jumping on block hovering have fixed [2036](https://github.com/codex-team/editor.js/issues/2036)
- `Improvement` — *Dev Example Page* - Add popup example page
- `Improvement` — *UI* - The Toolbox will restore the internal scroll on every opening
### 2.24.1
— `Fix` — The I18n of Tools` titles at the Toolbox now works correctly [#2030](https://github.com/codex-team/editor.js/issues/2030)
### 2.24.0
- `New` — *UI* — The Toolbox became vertical 🥳
- `Improvement` — *UI* — the Plus button will always be shown (previously, it appears only for empty blocks)
- `Improvement` — *Dev Example Page* - Server added to allow opening example page on other devices in network.
- `Fix` — `UI` — the Toolbar won't move on hover at mobile viewports. Resolves [#1972](https://github.com/codex-team/editor.js/issues/1972)
- `Fix` — `OnChange` event invocation after block insertion. [#1997](https://github.com/codex-team/editor.js/issues/1997)
- `Fix` — `ReadOnly` — the `readonly.isEnabled` API getter now works correctly after `readonly.toggle()` calling. Resolves [#1822](https://github.com/codex-team/editor.js/issues/1822)
- `Fix` — `Paste` — the inline HTML tags now will be preserved on pasting. [#1686](https://github.com/codex-team/editor.js/pull/1686)
### 2.23.2
— `Fix` — Crash on initialization in the read-only mode [#1968](https://github.com/codex-team/editor.js/issues/1968)
### 2.23.1
— `Fix` — Incorrect release tag fixed
### 2.23.0
- `Improvement` — *EditorConfig* — The `onChange` callback now accepts two arguments: EditorJS API and the CustomEvent with `type` and `detail` allowing to determine what happened with a Block
- `New` — *Block API* — The new `dispatchChange()` method allows to manually trigger the 'onChange' callback. Useful when Tool made a state mutation that is invisible for editor core.
- `Improvement` — *UI* — Block Tunes toggler moved to the left
- `Improvement` — *UI* — Block Actions (BT toggler + Plus Button) will appear on block hovering instead of click
- `Improvement` — *UI* — Block Tunes toggler icon and Plus button icon updated
- `Improvement` — *Dev Example Page* — The menu with helpful buttons added to the bottom of the screen
- `Improvement` — *Dev Example Page* — The 'dark' theme added. Now we can code at night more comfortably.
- `Improvement` — *Rectangle Selection* — paint optimized
- `Fix` — *Rectangle Selection* — the first click after RS was not clear selection state. Now does.
- `Improvement` — *Blocks API* — toolbar moving logic removed from `blocks.move()` and `blocks.swap()` methods. Instead, you should use Toolbar API (it was used by MoveUp and MoveDown tunes, they were updated).
- `New` — *Blocks API* — The `getBlockIndex()` method added
- `New` — *Blocks API* — the `insert()` method now has the `replace: boolean` parameter
- `New` — *Blocks API* — the `insert()` method now returns the inserted `Block API`
- `New` — *Listeners API* — the `on()` method now returns the listener id.
- `New` — *Listeners API* — the new `offById()` method added
- `New` — `API` — The new `UiApi` section was added. It allows accessing some editor UI nodes and methods.
- `Refactoring` — Toolbox became a standalone class instead of a Module. It can be accessed only through the Toolbar module.
- `Refactoring` — CI flow optimized.
- `Fix` - Recognize async `onPaste` handlers in tools [#1803](https://github.com/codex-team/editor.js/issues/1803).
- `Fix` — Fire onChange event for native inputs [#1750](https://github.com/codex-team/editor.js/issues/1750)
### 2.22.3
- `Fix` — Tool config is passed to `prepare` method [editor-js/embed#68](https://github.com/editor-js/embed/issues/68)
### 2.22.2
- `Improvement` — Inline Toolbar might be used for any contenteditable element inside Editor.js zone
- `Improvement` *Tunes API* - Tunes now can provide sanitize configuration
- `Fix` *Tunes API* - Tune config now passed to constructor under `config` property
- `Fix` *Types* - Add common type for internal and external Tools configuration
- `Fix` — Block's destroy method is called on block deletion
- `Fix` - Fix jump to the button of editor zone on CBS
### 2.22.1
- `Fix` — I18n for internal Block Tunes [#1661](https://github.com/codex-team/editor.js/issues/1661)
### 2.22.0
- `New` - `onChange` callback now receive Block API object of affected block
- `New` - API method `blocks.update(id, data)` added.
### 2.21.0
- `New` - Blocks now have unique ids [#873](https://github.com/codex-team/editor.js/issues/873)
### 2.20.2
- `Fix` — Append default Tunes if user tunes are provided for Block Tool [#1640](https://github.com/codex-team/editor.js/issues/1640)
- `Fix` - Prevent the leak of codex-tooltip when Editor.js is destroyed [#1475](https://github.com/codex-team/editor.js/issues/1475).
- `Refactoring` - Notifier module now is a util.
### 2.20.1
- `Fix` - Create a new block when clicked at the bottom [#1588](https://github.com/codex-team/editor.js/issues/1588).
- `Fix` — Fix sanitization problem with Inline Tools [#1631](https://github.com/codex-team/editor.js/issues/1631)
- `Fix` — Fix copy in FireFox [1625](https://github.com/codex-team/editor.js/issues/1625)
- `Refactoring` - The Sanitizer module is util now.
- `Refactoring` - Tooltip module is util now.
- `Refactoring` — Refactoring based on LGTM [#1577](https://github.com/codex-team/editor.js/issues/1577).
- `Refactoring` — Refactoring based on ESLint [#1636](https://github.com/codex-team/editor.js/issues/1636).
### 2.20.0
- `New` — [Block Tunes API](block-tunes.md) added
### 2.19.3
- `Fix` — Ignore error raised by Shortcut module
### 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
- `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` - 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` - 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` - 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)
### 2.19
- `New` - Read-only mode 🥳 [#837](https://github.com/codex-team/editor.js/issues/837)
- `New` - RTL mode added [#670](https://github.com/codex-team/editor.js/issues/670)
- `New` - Allows users to provide common `inlineToolbar` property which will be used for all tools whose `inlineToolbar` property is set to `true`. It can be overridden by the tool's own `inlineToolbar` property. Also, inline tools will be ordered according to the order of the inline tools in array provided in the `inlineToolbar` property. [#1056](https://github.com/codex-team/editor.js/issues/1056)
- `New` - Tool's `reset` static method added to the API to clean up any data added by Tool on initialization
- `Improvements` - The `initialBlock` property of Editor config is deprecated. Use the `defaultBlock` instead. [#993](https://github.com/codex-team/editor.js/issues/993)
- `Improvements` - BlockAPI `call()` method now returns the result of calling method, thus allowing it to expose arbitrary data as needed [#1205](https://github.com/codex-team/editor.js/pull/1205)
- `Improvements` - Useless log about missed i18n section has been removed [#1269](https://github.com/codex-team/editor.js/issues/1269)
- `Improvements` - Allowed to set `false` as `toolbox` config in order to hide Toolbox button [#1221](https://github.com/codex-team/editor.js/issues/1221)
- `Fix` — Fix problem with types usage [#1183](https://github.com/codex-team/editor.js/issues/1183)
- `Fix` - Fixed issue with Spam clicking the "Click to tune" button duplicates the icons on FireFox. [#1273](https://github.com/codex-team/editor.js/issues/1273)
- `Fix` - Fixed issue with `editor.blocks.delete(index)` method which throws an error when Editor.js is not focused, even after providing a valid index. [#1182](https://github.com/codex-team/editor.js/issues/1182)
- `Fix` - Fixed the issue of toolbar not disappearing on entering input in Chinese, Hindi and some other languages. [#1196](https://github.com/codex-team/editor.js/issues/1196)
- `Fix` - Do not stop events propagation if not needed (essential for React synthetic events) [#1051](https://github.com/codex-team/editor.js/issues/1051) [#946](https://github.com/codex-team/editor.js/issues/946)
- `Fix` - Tool's `destroy` method is not invoked when `editor.destroy()` is called. [#1047](https://github.com/codex-team/editor.js/issues/1047)
- `Fix` - Fixed issue with enter key in inputs and textareas [#920](https://github.com/codex-team/editor.js/issues/920)
- `Fix` - blocks.getBlockByIndex() API method now returns void for indexes out of range [#1270](https://github.com/codex-team/editor.js/issues/1270)
- `Fix` - Fixed the `Tab` key behavior when the caret is not set inside contenteditable element, but the block is selected [#1302](https://github.com/codex-team/editor.js/issues/1302).
- `Fix` - Fixed the `onChange` callback issue. This method didn't be called for native inputs before some contenteditable element changed [#843](https://github.com/codex-team/editor.js/issues/843)
- `Fix` - Fixed the `onChange` callback issue. This method didn't be called after the callback throws an exception [#1339](https://github.com/codex-team/editor.js/issues/1339)
- `Fix` - The internal `shortcut` getter of Tools classes will work now.
- `Deprecated` — The Inline Tool `clear()` method is deprecated because the new instance of Inline Tools will be created on every showing of the Inline Toolbar
### 2.18
- `New` *I18n API* — Ability to provide internalization for Editor.js core and tools. [#751](https://github.com/codex-team/editor.js/issues/751)
- `New` — Block API that allows you to access certain Block properties and methods
- `Improvements` - TSLint (deprecated) replaced with ESLint, old config changed to [CodeX ESLint Config](https://github.com/codex-team/eslint-config).
- `Improvements` - Fix many code-style issues, add missed annotations.
- `Improvements` - Adjusted GitHub action for ESLint.
- `Improvements` - Blocks API: if `blocks.delete` method is called, but no Block is selected, show warning instead of throwing an error [#1102](https://github.com/codex-team/editor.js/issues/1102)
- `Improvements` - Blocks API: allow deletion of blocks by specifying block index via `blocks.delete(index)`.
- `Improvements` - UX: Navigate next Block from the last non-initial one creates new initial Block now [#1103](https://github.com/codex-team/editor.js/issues/1103)
- `Improvements` - Improve performance of DOM traversing at the `isEmpty()` method [#1095](https://github.com/codex-team/editor.js/issues/1095)
- `Improvements` - CODE OF CONDUCT added
- `Improvements` - Disabled useCapture flag for a block keydown handling. That will allow plugins to override keydown and stop event propagation, for example, to make own Tab behavior.
- `Improvements` - All modules now might have `destroy` method called on Editor.js destroy
- `Improvements` - Block settings can contain text inputs, focus will be restored after settings closed [#1090](https://github.com/codex-team/editor.js/issues/1090)
- `Fix` - Editor's styles won't be appended to the `<head>` when another instance have already do that [#1079](https://github.com/codex-team/editor.js/issues/1079)
- `Fix` - Fixed wrong toolbar icon centering in Firefox [#1120](https://github.com/codex-team/editor.js/pull/1120)
- `Fix` - Toolbox: Tool's order in Toolbox now saved in accordance with `tools` object keys order [#1073](https://github.com/codex-team/editor.js/issues/1073)
- `Fix` - Setting `autofocus` config property to `true` cause adding `.ce-block--focused` for the autofocused block [#1073](https://github.com/codex-team/editor.js/issues/1124)
- `Fix` - Public getter `shortcut` now works for Inline Tools [#1132](https://github.com/codex-team/editor.js/issues/1132)
- `Fix` - `CMD+A` handler removed after Editor.js destroy [#1133](https://github.com/codex-team/editor.js/issues/1133)
> *Breaking changes* `blocks.getBlockByIndex` method now returns BlockAPI object. To access old value, use BlockAPI.holder property
### 2.17
- `Improvements` - Editor's [onchange callback](https://editorjs.io/configuration#editor-modifications-callback) now accepts an API as a parameter
- `Fix` - Some mistakes are fixed in [installation.md](installation.md)
- `Fix` - Fixed multiple paste callback triggering in a case when several editors are instantiated [#1011](https://github.com/codex-team/editor.js/issues/1011)
- `Fix` - Fixed inline toolbar flipper activation on closing conversion toolbar [#995](https://github.com/codex-team/editor.js/issues/995)
- `Improvements` - New window tab is opened by clicking on anchor with ctrl [#1057](https://github.com/codex-team/editor.js/issues/1057)
- `Fix` - Fix block-tune buttons alignment in some CSS-resetors that forces `box-sizing: border-box` rule [#1003](https://github.com/codex-team/editor.js/issues/1003)
- `Improvements` - New style of a Block Settings button. Focused block background removed.
- `New` — Add in-house copy-paste support through `application/x-editor-js` mime-type
- `New` Block [lifecycle hook](tools.md#block-lifecycle-hooks) `moved`
- `Deprecated` — [`blocks.swap(fromIndex, toIndex)`](api.md) method is deprecated. Use `blocks.move(toIndex, fromIndex)` instead.
- `Fix` — Improve plain text paste [#1012](https://github.com/codex-team/editor.js/issues/1012)
- `Fix` — Fix multiline paste [#1015](https://github.com/codex-team/editor.js/issues/1015)
### 2.16.1
- `Fix` — Fix Firefox bug with incorrect height and cursor position of empty content editable elements [#947](https://github.com/codex-team/editor.js/issues/947) [#876](https://github.com/codex-team/editor.js/issues/876) [#608](https://github.com/codex-team/editor.js/issues/608) [#876](https://github.com/codex-team/editor.js/issues/876)
- `Fix` — Set initial hidden Inline Toolbar position [#979](https://github.com/codex-team/editor.js/issues/979)
- `Fix` — Fix issue with CodeX.Tooltips TypeScript definitions [#978](https://github.com/codex-team/editor.js/issues/978)
- `Fix` — Fix some issues with Inline and Tunes toolbars.
- `Fix` - Fix `minHeight` option with zero-value issue [#724](https://github.com/codex-team/editor.js/issues/724)
- `Improvements` — Disable Conversion Toolbar if there are no Tools to convert [#984](https://github.com/codex-team/editor.js/issues/984)
### 2.16
- `Improvements` — Inline Toolbar design improved
- `Improvements` — Conversion Toolbar now included in the Inline Toolbar [#853](https://github.com/codex-team/editor.js/issues/853)
- `Improvements` — All buttons now have beautiful Tooltips provided by [CodeX Tooltips](https://github.com/codex-team/codex.tooltips)
- `New` — new Tooltips API for displaying tooltips near your custom elements
- `New` *API* — Block [lifecycle hooks](tools.md#block-lifecycle-hooks)
- `New` *Inline Tools API* — Ability to specify Tool's title via `title` static getter.
- `Fix` — On selection from end to start backspace is working as expected now [#869](https://github.com/codex-team/editor.js/issues/869)
- `Fix` — Fix flipper with empty dom iterator [#926](https://github.com/codex-team/editor.js/issues/926)
- `Fix` — Normalize node before walking through children at `isEmpty` method [#943](https://github.com/codex-team/editor.js/issues/943)
- `Fix` — Fixed Grammarly conflict [#779](https://github.com/codex-team/editor.js/issues/779)
- `Improvements` — Module Listeners now correctly removes events with options [#904](https://github.com/codex-team/editor.js/pull/904)
- `Improvements` — Styles API: `.cdx-block` default vertical margins decreased from 0.7 to 0.4 ems.
- `Fix` — Fixed `getRangeCount` call if range count is 0 [#938](https://github.com/codex-team/editor.js/issues/938)
- `New` — Log levels now available to suppress Editor.js console messages [#962](https://github.com/codex-team/editor.js/issues/962)
- `Fix` — Fixed wrong navigation on block deletion
### 2.15.1
- `Refactoring` — Constants of tools settings separated by internal and external to correspond API
- `Refactoring` — Created universal Flipper class that responses for navigation by keyboard inside of any Toolbars
- `Fix` — First CMD+A on block with now uses default behaviour. Fixed problem with second CMD+A after selection clearing [#827](https://github.com/codex-team/editor.js/issues/827)
- `Improvements` — Style of inline selection and selected blocks improved
- `Fix` - Fixed problem when property 'observer' in modificationObserver is not defined
### 2.15
- `New` — New [`blocks.insert()`](api.md) API method [#715](https://github.com/codex-team/editor.js/issues/715).
- `New` *Conversion Toolbar* — Ability to convert one block to another [#704](https://github.com/codex-team/editor.js/issues/704)
- `New` *Cross-block selection* — Ability to select multiple blocks by mouse and with SHIFT+ARROWS [#703](https://github.com/codex-team/editor.js/issues/703)
- `Deprecated` — [`blocks.insertNewBlock()`](api.md) method is deprecated. Use `blocks.insert()` instead.
- `Improvements` — Inline Toolbar now works on mobile devices [#706](https://github.com/codex-team/editor.js/issues/706)
- `Improvements` — Toolbar looks better on mobile devices [#706](https://github.com/codex-team/editor.js/issues/706)
- `Improvements` — Now `pasteConfig` can return `false` to disable paste handling on your Tool [#801](https://github.com/codex-team/editor.js/issues/801)
- `Fix` — EditorConfig's `onChange` callback now fires when native inputs\` content has been changed [#794](https://github.com/codex-team/editor.js/issues/794)
- `Fix` — Resolve bug with deleting leading new lines [#726](https://github.com/codex-team/editor.js/issues/726)
- `Fix` — Fix inline link Tool to support different link types like `mailto` and `tel` [#809](https://github.com/codex-team/editor.js/issues/809)
- `Fix` — Added `typeof` util method to check exact object type [#805](https://github.com/codex-team/editor.js/issues/805)
- `Fix` — Remove internal `enableLineBreaks` option from external Tool settings type description [#825](https://github.com/codex-team/editor.js/pull/825)
### 2.14
- `Fix` *Config* — User config now has higher priority than internal settings [#771](https://github.com/codex-team/editor.js/issues/771)
- `New` — Ability to work with Block Actions and Inline Toolbar from the keyboard by Tab. [#705](https://github.com/codex-team/editor.js/issues/705)
- `Fix` — Fix error thrown by click on the empty editor after `blocks.clear()` method calling [#761](https://github.com/codex-team/editor.js/issues/761)
- `Fix` — Fix placeholder property appearance. Now you can assign it via `placeholder` property of EditorConfig. [#714](https://github.com/codex-team/editor.js/issues/714)
- `Fix` — Add API shorthands to TS types [#788](https://github.com/codex-team/editor.js/issues/788)
### 2.13
- `Improvements` *BlockSelection* — Block Selection allows to select single editable element via CMD+A
- `New` *API* — Added [API methods](api.md) to open and close inline toolbar [#665](https://github.com/codex-team/editor.js/issues/665)
- `New` *Config* - Added new property in EditorConfig `holder`, use this property for append Editor instead `holderId`. `holder` property now support reference on dom element. [#696](https://github.com/codex-team/editor.js/issues/696)
- `Deprecated` *Config* - `holderId` property now is deprecated and will removed in next major release. Use `holder` instead.
- `Fix` *Types* — Fixed error with `codex-notifier` package [#713](https://github.com/codex-team/editor.js/issues/713)
- `Improvements` — Close inline toolbar after creating a new link.
- `New` *Config* — Option `minHeight` for customizing Editor's bottom zone height added.
### 2.12.4
- `Improvements` — CodeX.Shortcuts version updated to the v1.1 [#684](https://github.com/codex-team/editor.js/issues/684)
- `Fix` — Do not start multi-block selection on Toolbox and Inline Toolbar [#646](https://github.com/codex-team/editor.js/issues/646)
- `Fix` — Minor fixes of caret behaviour [#663](https://github.com/codex-team/editor.js/issues/663)
- `Fix` — Fix inline-link icon position in Firefox [#674](https://github.com/codex-team/editor.js/issues/674)
### 2.12.3
- `Fix` — Make Toolbox tooltip position font-size independent
### 2.12.2
- New *Inline Tools* — pass tool settings from configuration to Tool constructor
### 2.12.1
- `Fix` — Fix processing `color-mod` function in styles
### 2.12.0
- `New` *API* - new `blocks` API method `renderFromHTML`
### 2.11.11
- `New` — Add ability to pass configuration for internal Tools
### 2.11.10
- `Fix` - Fix editor view on mobile devices
### 2.11.9
- `Fix` - Fix inline toolbar buttons margin. Update dependencies list. Update tools for example page.
### 2.11.8
- `Fix` — Block tunes margins now better works with more than 3 buttons
### 2.11.7
- `Fix` *Paste* — Fix pasting into non-initial Blocks
### 2.11.6
- `Fix` *Paste* — Polyfill for Microsoft Edge
### 2.11.5
- `Fix` *RectangleSelection* — Redesign of the scrolling zones
### 2.11.4
- `Fix` - Clear focus when click is outside the Editor instance
### 2.11.3
- `Fix` — Fix CMD+A Selection on multiple Editor instances
### 2.11.2
- `Improvements` — Docs updated and common enhancements
### 2.11.1
- `Fix` *RectangleSelection* — Selection is available only for the main mouse button
### 2.11.0
- `New` — Add API methods shorthands
### 2.10.0
- `New` — Rename from CodeX Editor to Editor.js
### 2.9.5
- `New` — Toolbox now have beautiful helpers with Tool names and shortcuts
### 2.9.4
- `Improvements` — Prevent navigating back on Firefox when Block is removing by backspace
### 2.9.3
- `Fix` — Handle paste only on initial Block
### 2.9.2
- `New` — Blocks selected with Rectangle Selection can be also removed, copied or cut
### 2.9.1
- `Improvements` — Migrate from `postcss-cssnext` to `postcss-preset-env` and disable `postcss-custom-properties` which conflicts with `postcss-preset-env`
### 2.9.0
- `New` *RectangleSelection* — Ability to select Block or several Blocks with mouse
### 2.8.1
- `Fix` *Caret* — Fix "History back" call on backspace in Firefox
### 2.8.0
- `Improvements` *API* — Added [API methods](api.md#caretapi) to manage caret position
### 2.7.32
- `Improvements` *Types* — TypeScript types sre updated
### 2.7.31
- `Fix` — Caret now goes through <input> elements without `type` attribute
### 2.7.30
- `Fix` — Fixed selection behavior when text has modifiers form Inline Toolbar
### 2.7.29
- `Fix` — cmd+x works only for custom selection now
### 2.7.28
- `New` [Tools Validation](https://github.com/codex-team/editor.js/blob/master/docs/tools.md#validate-optional) is added.
### 2.2.27
- `New` *Mobile view* — Editor now adopted for mobile devices
- `New` *Narrow mode* — Editor now adopted for narrow containers
### 2.2.26
- `Improvements` *Caret* — Improvements of the caret behaviour: arrows, backspace and enter keys better handling.
### 2.2.25
- `New` *Autofocus* — Now you can set focus at Editor after page has been loaded
### 2.2.24
- `Improvements` *Paste* handling — minor paste handling improvements
### 2.2.23
- `New` *Shortcuts* — copy and cut Blocks selected by CMD+A
### 2.2—2.7
- `New` *Sanitize API* — [Sanitize Config](https://github.com/codex-team/editor.js/blob/master/docs/tools.md#automatic-sanitize) of `Block Tools` now automatically extends by tags of `Inline Tools` that is enabled by current Tool by `inlineToolbar` option. You don't need more to specify `a, b, mark, code` manually. This feature will be added to fields that supports inline markup.
- `New` *Block Selection* — Ability to select Block by `CMD+A`, and the whole Editor by double `CMD+A`. After that, you can copy (`CMD+C`), remove (`Backspace`) or clear (`Enter`) selected Blocks.
- `New` *[Styles API](https://github.com/codex-team/editor.js/blob/master/types/api/styles.d.ts)* — Added `button` class for stylization of any buttons provided by Tools with one unified style.
- `New` *[Notifier API](https://github.com/codex-team/editor.js/blob/master/docs/api.md#notifierapi)* — methods for showing user notifications: on success, errors, warnings, etc.
- `New` *Block Tool* — [Table](http://github.com/editor-js/table) constructor 💪
- `New` If one of the Tools is unavailable on Editor initialization, its Blocks will be rendered with *Dummy Block*, describing that user can not edit content of this Block. Dummy Blocks can be moved, removed and saved as normal Blocks. So saved data won't be lost if one of the Tools is failed
- `New` [Public TS-types](https://github.com/codex-team/editor.js/tree/master/types) are presented.
- `Changes` *Tools API* — options `irreplaceable` and `contentless` was removed.
- `Changes` *Tools API* — [Paste API](https://github.com/codex-team/editor.js/blob/master/docs/tools.md#paste-handling): tags, patterns and mime-types now should be specified by Tool's `pasteConfig` static property. Custom Paste Event should be handled by `onPaste(event)` that should not be static from now.
- `Changes` *Tools API* — options `displayInToolbox ` and `toolboxIcon` was removed. Use [`toolbox`](https://github.com/codex-team/editor.js/blob/master/docs/tools.md#internal-tool-settings) instead, that should return object with `icon` and `title` field, or `false` if Tool should not be placed at the Toolbox. Also, there are a way to override `toolbox {icon, title}` settings provided by Tool with you own settings at the Initial Config.
- `Improvements` — All Projects code now on TypeScript
- `Improvements` — NPM package size decreased from 1300kb to 422kb
- `Improvements` — Bundle size decreased from 438kb to 252kb
- `Improvements` — `Inline Toolbar`: when you add a Link to the selected fragment, Editor will highlight this fragment even when Caret is placed into the URL-input.
- `Improvements` — Block Settings won't be shown near empty Blocks of `initialType` by default. You should click on them instead.
- `Improvements` — `onChange`-callback now will be fired even with children attributes changing.
- `Improvements` — HTMLJanitor package was updated due to found vulnerability
- `Improvements` — Logging improved: now all Editor's logs will be preceded by beautiful label with current Editor version.
- `Improvements` — Internal `isEmpty` checking was improved for Blocks with many children nodes (200 and more)
- `Improvements` — Paste improvements: tags that can be substituted by Tool now will matched even on deep-level of pasted DOM three.
- `Improvements` — There is no more «unavailable» sound on copying Block by `CMD+C` on macOS
- `Improvements` — Dozens of bugfixes and small improvements
See a whole [Changelog](/docs/)
### 2.1-beta changelog
- `New` *Tools API* — support pasted content via drag-n-drop or from the Buffer. See [documentation](https://github.com/codex-team/editor.js/blob/master/docs/tools.md#paste-handling) and [example](https://github.com/editor-js/simple-image/blob/master/src/index.js#L177) at the Simple Image Tool.
- `New` *Tools API* — new `sanitize` getter for Tools for automatic HTML sanitizing of returned data. See [documentation](https://github.com/codex-team/editor.js/blob/master/docs/tools.md#sanitize) and [example](https://github.com/editor-js/paragraph/blob/master/src/index.js#L121) at the Paragraph Tool
- `New` Added `onChange`-callback, fired after any modifications at the Editor. See [documentation](https://github.com/codex-team/editor.js/blob/master/docs/installation.md#features).
- `New` New Inline Tool example — [Marker](https://github.com/editor-js/marker)
- `New` New Inline Tool example — [Code](https://github.com/editor-js/code)
- `New` New [Editor.js PHP](http://github.com/codex-team/codex.editor.backend) — example of server-side implementation with HTML purifying and data validation.
- `Improvements` - Improvements of Toolbar's position calculation.
- `Improvements` — Improved zero-configuration initialization.
- and many little improvements.
================================================
FILE: docs/api.md
================================================
# Editor.js API
---
Most actual API described by [this interface](../types/api/index.d.ts).
---
📃 See official API documentation [https://editorjs.io/api](https://editorjs.io/api)
---
Tools have access to the public methods provided by Editor.js API Module. Plugin and Tune Developers
can use Editor\`s API as they want.
## Block API
API for certain Block methods and properties. You can access it through `editor.api.block.getBlockByIndex` method or get it form `block` property of [Tool constructor](../types/tools/block-tool.d.ts) argument.
`name: string` — Block's Tool name (key, specified in `tools` property of initial configuration)
`config: ToolConfig` — Tool config passed on Editor initialization
`holder: HTMLElement` — HTML Element that wraps Tool's HTML content
`isEmpty: boolean` — `true` if Block has any editable content
`selected: boolean` - `true` if Block is selected with Cross-Block Selection
`set stretched(state: boolean)` — set Block's stretch state
`stretched: boolean` — `true` if Block is stretched
`call(methodName: string, param?: object): void` — method to call any Tool's instance methods with checks and error handlers under-the-hood. For example, [Block lifecycle hooks](./tools.md#block-lifecycle-hooks)
`save(): Promise<void|SavedData>` — returns data saved from current Block's state, including Tool name and saving exec time
`validate(data: BlockToolData): Promise<boolean>` — calls Tool's validate method if exists
`dispatchChange(): void` - Allows to say Editor that Block was changed. Used to manually trigger Editor's 'onChange' callback. Can be useful for block changes invisible for editor core.
## Api object description
Common API interface.
```js
export interface API {
blocks: IBlocksAPI;
caret: ICaretAPI;
sanitizer: ISanitizerAPI;
toolbar: IToolbarAPI;
// ...
}
```
#### BlocksAPI
Methods that working with Blocks
`render(data)` - render passed JSON data
`renderFromHTML(data)` - parse and render passed HTML string (*not for production use*)
`swap(fromIndex, toIndex)` - swaps two Blocks by their positions (deprecated:
use 'move' instead)
`move(toIndex, fromIndex)` - moves block from one index to another position.
`fromIndex` will be the current block's index by default.
`delete(blockIndex?: Number)` - deletes Block with passed index
`getCurrentBlockIndex()` - current Block index
`getBlockByIndex(index: Number)` - returns Block API object by passed index
`getBlocksCount()` - returns Blocks count
`stretchBlock(index: number, status: boolean)` - _Deprecated. Use Block API interface instead._ make Block stretched.
`insertNewBlock()` - __Deprecated__ insert new Block after working place
`insert(type?: string, data?: BlockToolData, config?: ToolConfig, index?: number, needToFocus?: boolean)` - insert new Block with passed parameters
`update(id: string, data?: BlockToolData, tunes?: {[name: string]: BlockTuneData})` - updates block data and block tunes for the block with passed id
#### SanitizerAPI
`clean(taintString, config)` - method uses HTMLJanitor to clean taint string.
Editor.js provides basic config without attributes, but you can inherit by passing your own config.
If Tool enables inline-tools, we get it's sanitizing rules and merge with your passed custom rules.
Usage:
```js
let taintString = '<div><p style="font-size: 5em;"><b></b>BlockWithText<a onclick="void(0)"></div>'
let customConfig = {
b: true,
p: {
style: true,
},
}
this.api.sanitizer.clean(taintString, customConfig);
```
### ToolbarAPI
Methods that working with Toolbar
`open()` - opens toolbar
`close()` - closes toolbar, toolbox and blockSettings if they are opened
### InlineToolbarAPI
Methods that works with inline toolbar
`open()` - opens inline toolbar, (opens for the current selection)
`close()` - closes inline toolbar
### ListenerAPI
Methods that allows to work with DOM listener. Useful when you forgot to remove listener. Module collects all listeners and destroys automatically
`on(element: HTMLElement, eventType: string, handler: Function, useCapture?: boolean)` - add event listener to HTML element
`off(element: HTMLElement, eventType: string, handler: Function)` - remove event handler from HTML element
### CaretAPI
Methods to manage caret position.
Each method accept `position` and `offset` parameters. `Offset` should be used to shift caret by passed amount of characters.
`Position` can be one of the following values:
| Value | Description
| --------- | -----------
| `start` | Caret will be set at the Block's beginning
| `end` | Caret will be set at the Block end
| `default` | More or less emulates browser behaviour, in most cases behaves as `start`
Each method returns `boolean` value: true if caret is set successfully or false otherwise (e.g. when there is no Block at index);
`setToFirstBlock(position?: 'end'|'start'|'default', offset?: number): boolean;` — set caret to the first Block
`setToLastBlock(position?: 'end'|'start'|'default', offset?: number): boolean;` — set caret to the last Block
`setToNextBlock(position?: 'end'|'start'|'default', offset?: number): boolean;` — set caret to the next Block
`setToPreviousBlock(position?: 'end'|'start'|'default', offset?: number): boolean;` — set caret to the previous Block
`setToBlock(index: number, position?: 'end'|'start'|'default', offset?: number): boolean;` — set caret to the Block by passed `index`
`focus(atEnd?: boolean): boolean;` — set caret to the Editor. If `atEnd` is true, set it at the end.
### NotifierAPI
If you need to show any messages for success or failure events you can use notifications module.
Call on target Editor:
```javascript
let editor = new EditorJS({
onReady: () => {
editor.notifier.show({
message: 'Editor is ready!'
});
},
});
```
In Tool's class:
```javascript
this.api.notifier.show({
message: 'Cannot upload image. Wrong mime-type.',
style: 'error',
});
```

Check out [`codex-notifier` package page](https://github.com/codex-team/js-notifier) on GitHub to find docs, params and examples.
### Destroy API
If there are necessity to remove Editor.js instance from the page you can use `destroy()` method.
It makes following steps:
1. Clear the holder element by setting it\`s innerHTML to empty string
2. Remove all event listeners related to Editor.js
3. Delete all properties from instance object and set it\`s prototype to `null`
After executing the `destroy` method, editor inctance becomes an empty object. This way you will free occupied JS Heap on your page.
### Tooltip API
Methods for showing Tooltip helper near your elements. Parameters are the same as in [CodeX Tooltips](http://github.com/codex-team/codex.tooltips) lib.
#### Show
Method shows tooltip with custom content on passed element
```js
this.api.tooltip.show(element, content, options);
```
| parameter | type | description |
| -- | -- | -- |
| `element` | _HTMLElement_ | Tooltip will be showed near this element |
| `content` | _String_ or _Node_ | Content that will be appended to the Tooltip |
| `options` | _Object_ | Some displaying options, see below |
Available showing options
| name | type | action |
| -- | -- | -- |
| placement | `top`, `bottom`, `left`, `right` | Where to place the tooltip. Default value is `bottom' |
| marginTop | _Number_ | Offset above the tooltip with `top` placement |
| marginBottom | _Number_ | Offset below the tooltip with `bottom` placement |
| marginLeft | _Number_ | Offset at left from the tooltip with `left` placement |
| marginRight | _Number_ | Offset at right from the tooltip with `right` placement |
| delay | _Number_ | Delay before showing, in ms. Default is `70` |
| hidingDelay | _Number_ | Delay before hiding, in ms. Default is `0` |
#### Hide
Method hides the Tooltip.
```js
this.api.tooltip.hide();
```
#### onHover
Decorator for showing tooltip near some element by "mouseenter" and hide by "mouseleave".
```js
this.api.tooltip.onHover(element, content, options);
```
### API Shorthands
Editor`s API provides some shorthands for API methods.
| Alias | Method |
| ------ | --------------- |
| `clear` | `blocks.clear` |
| `render` | `blocks.render` |
| `focus` | `caret.focus` |
| `save` | `saver.save` |
> Example
```javascript
const editor = EditorJS();
editor.focus();
editor.save();
```
================================================
FILE: docs/block-tunes.md
================================================
# Block Tunes
Similar with [Tools](tools.md) represented Blocks, you can create Block Tunes and connect it to particular Tool or for all Tools.
Block Tunes allows you to set any additional options to Blocks. For example, with corresponded Block Tunes you can mark Block as «spoiler», give it an anchor, set a background, and so on.
## Base structure
Tune's class should have the `isTune` property (static getter) set to `true`.
Block Tune must implement the `render()` method which returns an HTML Element that will be appended to the Block Settings panel.
- `render()` — create a button
Also, you can provide optional methods
- `wrap()` — wraps Block content with own HTML elements
- `save()` — save Tunes state on Editor's save
At the constructor of Tune's class exemplar you will receive an object with following parameters:
| Parameter | Description |
| --------- | ----------- |
| api | Editor's [API](api.md) obejct |
| config | Configuration of Block Tool Tune is connected to (might be useful in some cases) |
| block | [Block API](api.md#block-api) methods for block Tune is connected to |
| data | Saved Tune data |
---
### render(): HTMLElement
Method that returns button to append to the block settings area
#### Parameters
Method does not accept any parameters
#### Return value
type | description |
-- | -- |
`HTMLElement` | element that will be added to the block settings area |
---
### wrap(blockContent: HTMLElement): HTMLElement
Method that accepts Block's content and wrap it with your own layout.
Might be useful if you want to modify Block appearance.
```javascript
class Tune {
wrap(blockContent) {
const myWrapper = document.createElement('div');
myWrapper.append(blockContent);
return myWrapper;
}
}
```
#### Parameters
name | type | description |
-- |-- | -- |
blockContent | HTMLElement | Block's content (might be wrapped by other Tunes) |
#### Return value
| type | description |
| -- | -- |
| HTMLElement | Your element that wraps block content |
---
### save()
Method should return Tune's state you want to save to Editor's output
#### Parameters
No parameters
#### Return value
type | description |
-- | -- |
`any` | any data you want to save |
---
### static prepare()
If you need to prepare some data for Tune (eg. load external script, create HTML nodes in the document, etc) you can use the static `prepare()` method.
It accepts tunes config passed on Editor's initialization as an argument:
```javascript
class Tune {
static prepare(config) {
loadScript();
insertNodes();
...
}
}
```
#### Parameters
type | description |
-- | -- |
`object` | your Tune configuration |
#### Return value
No return value
---
### static reset()
On Editor destroy you can use an opposite method `reset` to clean up all prepared data:
```javascript
class Tune {
static reset() {
cleanUpScripts();
deleteNodes();
...
}
}
```
#### Parameters
No parameters
#### Return value
No return value
---
### static get sanitize()
If your Tune inserts any HTML markup into Block's content you need to provide sanitize configuration, so your HTML is not trimmed on save.
Please see more information at [sanitizer page](sanitizer.md).
```javascript
class Tune {
static get sanitize() {
return {
sup: true
}
}
}
```
## Format
Tunes data is saved to `tunes` property of output object:
```
{
blocks: [
{
type: 'paragraph',
data: {
text: 'This is paragraph with Tune'
},
tunes: {
'my-tune-name': {},
favorite: true,
anchor: 'might be string'
}
}
]
}
```
================================================
FILE: docs/caret.md
================================================
# Editor.js Caret Module
The `Caret` module contains methods working with caret. Uses [Range](https://developer.mozilla.org/en-US/docs/Web/API/Range) methods to navigate caret
between blocks.
Caret class implements basic Module class that holds User configuration
and default Editor.js instances
## Properties
## Methods
### setToBlock
```javascript
Caret.setToBlock(block, position, offset)
```
> Method gets Block instance and puts caret to the text node with offset
#### params
| Param | Type | Description|
| -------------|------ |:-------------:|
| block | Object | Block instance that BlockManager created|
| position | String | Can be 'start', 'end' or 'default'. Other values will be treated as 'default'. Shows position of the caret regarding to the Block.|
| offset | Number | caret offset regarding to the text node (Default: 0)|
### setToTheLastBlock
```javascript
Caret.setToTheLastBlock()
```
> sets Caret at the end of last Block
If last block is not empty, inserts another empty Block which is passed as initial
================================================
FILE: docs/installation.md
================================================
# Installation Guide
There are few steps to run Editor.js on your site.
1. [Load Editor's core](#load-editors-core)
2. [Load Tools](#load-tools)
3. [Initialize Editor's instance](#create-editor-instance)
## Load Editor's core
Firstly you need to get Editor.js itself. It is a [minified script](../dist/editor.js) with minimal available
Choose the most usable method of getting an Editor for you.
- Node package
- Source from CDN
- Local file from a project
### Node.js
Install the package via NPM or Yarn
```shell
npm i @editorjs/editorjs
```
Include module at your application
```javascript
import EditorJS from '@editorjs/editorjs';
```
### Use from CDN
You can load specific version of package from [jsDelivr CDN](https://www.jsdelivr.com/package/npm/@editorjs/editorjs).
`https://cdn.jsdelivr.net/npm/@editorjs/editorjs@2.10.0`
Then require this script.
```html
<script src="..."></script>
```
### Save sources to project
Copy [editor.js](../dist/editor.js) file to your project and load it.
```html
<script src="editor.js"></script>
```
## Load Tools
Each Block at the Editor.js represented by [Tools](tools.md). There are simple external scripts with their own logic. You'll probably want to use several Block Tools that should be connected.
For example, check out our [Header](https://github.com/editor-js/header) Tool that represents heading blocks.
You can install the Header Tool via the same ways as an Editor (Node.js, CDN, local file).
Check [Editor.js's community](https://github.com/editor-js/) to see Tools examples.
**Example:** use Header from CDN
```html
<script src="https://cdn.jsdelivr.net/npm/codex.editor.header@2.1.0/dist/bundle.js"></script>
```
## Create Editor instance
Create an instance of Editor.js and pass [Configuration Object](../src/types-internal/editor-config.ts).
At least the `holder` option is required.
```html
<div id="editorjs"></div>
```
You can create a simple Editor only with a default Paragraph Tool by passing a string with element's Id (wrapper for Editor) as a configuration param or use default `editorjs`.
```javascript
var editor = new EditorJS(); /** Zero-configuration */
// equals
var editor = new EditorJS('editorjs');
````
Or pass a whole settings object.
```javascript
var editor = new EditorJS({
/**
* Create a holder for the Editor and pass its ID
*/
holder : 'editorjs',
/**
* Available Tools list.
* Pass Tool's class or Settings object for each Tool you want to use
*/
tools: {
header: {
class: Header,
inlineToolbar : true
},
// ...
},
/**
* Previously saved data that should be rendered
*/
data: {}
});
```
## Ready callback
Editor.js needs a bit of time to initialize. It is an asynchronous action so it won't block execution of your main script.
If you need to know when the editor instance is ready you can use one of the following ways:
##### Pass `onReady` property to the configuration object.
It must be a function:
```javascript
var editor = new EditorJS({
// Other configuration properties
/**
* onReady callback
*/
onReady: () => {console.log('Editor.js is ready to work!')}
});
```
#### Use `isReady` promise.
After you create a new `EditorJS` object it will contain `isReady` property.
It is a Promise object that resolves when the editor will be ready to work and rejected otherwise.
If there is an error during initialization `isReady` promise will be rejected with an error message.
```javascript
var editor = new EditorJS();
editor.isReady
.then(() => {
/** Do anything you need after editor initialization */
})
.catch((reason) => {
console.log(`Editor.js initialization failed because of ${reason}`)
});
```
You can use `async/await` to keep your code looking synchronous:
```javascript
var editor = new EditorJS();
try {
await editor.isReady;
/** Do anything you need after editor initialization */
} catch (reason) {
console.log(`Editor.js initialization failed because of ${reason}`)
}
```
## Saving Data
Call `editor.saver.save()` and handle returned Promise with saved data.
```javascript
editor.saver.save()
.then((savedData) => {
console.log(savedData);
});
```
## Features
Also, Editor.js provides useful methods to work with Editor's state.
```javascript
var editor = new EditorJS({
// Other configuration properties
/**
* onReady callback
*/
onReady: () => {console.log('Editor.js is ready to work!')},
/**
* onChange callback
* Accepts CustomEvent describing what happened
*/
onChange: (editorAPI, event) => {console.log('Now I know that Editor\'s content changed!')}
});
```
## Example
Take a look at the [example.html](../example/example.html) to view more detailed examples.
================================================
FILE: docs/releases.md
================================================
# 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.

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".

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.
================================================
FILE: docs/sanitizer.md
================================================
# Editor.js Sanitizer Module
The `Sanitizer` module represents a set of methods that clears taint strings.
Uses lightweight npm package with simple API [html-janitor](https://www.npmjs.com/package/html-janitor)
## Methods
### clean
```javascript
clean(taintString, customConfig)
```
> Cleans up the passed taint string
#### params
| Param | Type | Description|
| -------------|------ |:-------------:|
| taintString | String | string that needs to be cleaned|
| customConfig | Object | Can be passed new config per usage (Default: uses default configuration)|
================================================
FILE: docs/toolbar-settings.md
================================================
# Editor.js Toolbar Block Settings Module
Toolbar Module has space for Block settings. Settings divided into:
- space for plugin's settings, that is described by «Plugin»'s Developer
- space for default settings. This option is also can be implemented and expanded
They difference between zones is that the first option is specified by plugin
and each Block can have different options, when second option is for every Block
regardless to the plugin's option.
### Let's look the examples:
«Plugin»'s Developers need to expand «renderSettings» method that returns HTML.
Every user action will be handled by itself. So, you can easily write
callbacks that switches your content or makes better. For more information
read [Tools](tools.md).
---
«Tune»'s Developers need to implement core-provided interface to develop
tunes that will be appeared in Toolbar default settings zone.
Tunes must expand two important methods:
- `render()` - returns HTML and it is appended to the default settings zone
- `save()` - extracts important information to be saved
No restrictions. Handle user action by yourself
Create Class that implements block-tune.ts
Your Tune's constructor gets argument as object and it includes:
- {Object} api - object contains public methods from modules. @see [API](api.md)
- {Object} settings - settings contains block default state.
This object could have information about cover, anchor and so on.
Example on TypeScript:
```js
import IBlockTune from './block-tune';
export default class YourCustomTune implements IBlockTune {
public constructor({api, settings}) {
this.api = api;
this.settings = settings;
}
render() {
let someHTML = '...';
return someHTML;
}
save() {
// Return the important data that needs to be saved
return object
}
someMethod() {
// moves current block down
this.api.blocks.moveDown();
}
}
```
Example on ES6
```js
export default class YourCustomTune {
constructor({api, settings}) {
this.api = api;
this.settings = settings;
}
render() {
let someHTML = '...';
return someHTML;
}
save() {
// Return the important data that needs to be saved
return object
}
someMethod() {
// moves current block down
this.api.blocks.moveDown();
}
}
```
================================================
FILE: docs/tools-inline.md
================================================
# Tools for the Inline Toolbar
Similar with [Tools](tools.md) represented Blocks, you can create Tools for the Inline Toolbar. It will work with
selected fragment of text. The simplest example is `bold` or `italic` Tools.
## Base structure
First of all, Tool's class should have a `isInline` property (static getter) set as `true`.
After that Inline Tool should implement next methods.
- `render()` — create a button
- `surround()` — works with selected range
- `checkState()` — get Tool's activated state by selected range
Also, you can provide optional methods
- `renderActions()` — create additional element below the buttons
- `clear()` — clear Tool's stuff on opening/closing of Inline Toolbar
- `sanitize()` — sanitizer configuration
At the constructor of Tool's class exemplar you will accept an object with the [API](api.md) as a parameter.
---
### render()
Method that returns button to append at the Inline Toolbar
#### Parameters
Method does not accept any parameters
#### Return value
type | description |
-- | -- |
`HTMLElement` | element that will be added to the Inline Toolbar |
---
### surround(range: Range)
Method that accepts selected range and wrap it somehow
#### Parameters
name | type | description |
-- |-- | -- |
range | Range | first range of current Selection |
#### Return value
There is no return value
---
### checkState(selection: Selection)
Get Selection and detect if Tool was applied. For example, after that Tool can highlight button or show some details.
#### Parameters
name | type | description |
-- |-- | -- |
selection | Selection | current Selection |
#### Return value
type | description |
-- | -- |
`Boolean` | `true` if Tool is active, otherwise `false` |
---
### renderActions()
Optional method that returns additional Element with actions.
For example, input for the 'link' tool or textarea for the 'comment' tool.
It will be places below the buttons list at Inline Toolbar.
#### Parameters
Method does not accept any parameters
#### Return value
type | description |
-- | -- |
`HTMLElement` | element that will be added to the Inline Toolbar |
---
### clear()
Optional method that will be called on opening/closing of Inline Toolbar.
Can contain logic for clearing Tool's stuff, such as inputs, states and other.
#### Parameters
Method does not accept any parameters
#### Return value
Method should not return a value.
### static get sanitize()
We recommend to specify the Sanitizer config that corresponds with inline tags that is used by your Tool.
In that case, your config will be merged with sanitizer configuration of Block Tool
that is using the Inline Toolbar with your Tool.
Example:
If your Tool wrapps selected text with `<b>` tag, the sanitizer config should looks like this:
```js
static get sanitize() {
return {
b: {} // {} means clean all attributes. true — leave all attributes
}
}
```
Read more about Sanitizer configuration at the [Tools#sanitize](tools.md#sanitize)
### Specifying a title
You can pass your Tool's title via `title` static getter. It can be used, for example, in the Tooltip with
icon description that appears by hover.
```ts
export default class BoldInlineTool implements InlineTool {
/**
* Specifies Tool as Inline Toolbar Tool
*
* @return {boolean}
*/
public static isInline = true;
/**
* Title for hover-tooltip
*/
public static title: string = 'Bold';
// ... other methods
}
```
================================================
FILE: docs/tools.md
================================================
# Editor.js Tools
Editor.js is a block-oriented editor. It means that entry composed with the list of `Blocks` of different types: `Texts`, `Headers`, `Images`, `Quotes` etc.
`Tool` — is a class that provide custom `Block` type. All Tools represented by `Plugins`.
Each Tool should have an installation guide.
## Tool class structure
### constructor()
Each Tool's instance called with an params object.
| Param | Type | Description |
| ------ | ------------------------------------------------------ | ----------------------------------------------- |
| api | [`IAPI`](../types/index.d.ts) | Editor.js's API methods |
| config | [`ToolConfig`](../types/tools/tool-config.d.ts) | Special configuration params passed in «config» |
| data | [`BlockToolData`](../types/tools/block-tool-data.d.ts) | Data to be rendered in this Tool |
| block | [`BlockAPI`](../types/api/block.d.ts) | Block's API methods |
[iapi-link]: ../src/types-internal/api.ts
#### Example
```javascript
constructor({data, config, api}) {
this.data = data;
this.api = api;
this.config = config;
// ...
}
```
### render()
Method that returns Tool's element {HTMLElement} that will be placed into Editor.
### save()
Process Tool's element created by `render()` function in DOM and return Block's data.
### validate(data: BlockToolData): boolean|Promise\<boolean\> _optional_
Allows to check correctness of Tool's data. If data didn't pass the validation it won't be saved. Receives Tool's `data` as input param and returns `boolean` result of validation.
### merge() _optional_
Method that specifies how to merge two `Blocks` of the same type, for example on `Backspace` keypress.
Method does accept data object in same format as the `Render` and it should provide logic how to combine new
data with the currently stored value.
## Internal Tool Settings
Options that Tool can specify. All settings should be passed as static properties of Tool's class.
| Name | Type | Default Value | Description |
| -- | -- | -- | -- |
| `toolbox` | _Object_ | `undefined` | Pass the `icon` and the `title` there to display this `Tool` in the Editor's `Toolbox` <br /> `icon` - HTML string with icon for the Toolbox <br /> `title` - title to be displayed at the Toolbox. <br /><br />May contain an array of `{icon, title, data}` to display the several variants of the tool, for example "Ordered list", "Unordered list". See details at [the documentation](https://editorjs.io/tools-api#toolbox) |
| `enableLineBreaks` | _Boolean_ | `false` | With this option, Editor.js won't handle Enter keydowns. Can be helpful for Tools like `<code>` where line breaks should be handled by default behaviour. |
| `isInline` | _Boolean_ | `false` | Describes Tool as a [Tool for the Inline Toolbar](tools-inline.md) |
| `isTune` | _Boolean_ | `false` | Describes Tool as a [Block Tune](block-tunes.md) |
| `sanitize` | _Object_ | `undefined` | Config for automatic sanitizing of saved data. See [Sanitize](#sanitize) section. |
| `conversionConfig` | _Object_ | `undefined` | Config allows Tool to specify how it can be converted into/from another Tool. See [Conversion config](#conversion-config) section. |
## User configuration
All Tools can be configured by users. You can set up some of available settings along with Tool's class
to the `tools` property of Editor Config.
```javascript
var editor = new EditorJS({
holder : 'editorjs',
tools: {
text: {
class: Text,
inlineToolbar : true,
// other settings..
},
header: Header
},
defaultBlock : 'text',
});
```
There are few options available by Editor.js.
| Name | Type | Default Value | Description |
| -- | -- | -- | -- |
| `inlineToolbar` | _Boolean/Array_ | `false` | Pass `true` to enable the Inline Toolbar with all Tools, or pass an array with specified Tools list |
| `config` | _Object_ | `null` | User's configuration for Plugin.
## Tool prepare and reset
If you need to prepare some data for Tool (eg. load external script, create HTML nodes in the document, etc) you can use static prepare method.
It accepts tools config passed on Editor's initialization as an argument:
```javascript
class Tool {
static prepare(config) {
loadScript();
insertNodes();
...
}
}
```
On Editor destroy you can use an opposite method `reset` to clean up all prepared data:
```javascript
class Tool {
static reset() {
cleanUpScripts();
deleteNodes();
...
}
}
```
Both methods might be async.
## Paste handling
Editor.js handles paste on Blocks and provides API for Tools to process the pasted data.
When user pastes content into Editor, pasted content will be splitted into blocks.
1. If plain text will be pasted, it will be splitted by new line characters
2. If HTML string will be pasted, it will be splitted by block tags
Also Editor API allows you to define your own pasting scenario. You can either:
1. Specify **HTML tags**, that can be represented by your Tool. For example, Image Tool can handle `<img>` tags.
If tags you specified will be found on content pasting, your Tool will be rendered.
2. Specify **RegExp** for pasted strings. If pattern has been matched, your Tool will be rendered.
3. Specify **MIME type** or **extensions** of files that can be handled by your Tool on pasting by drag-n-drop or from clipboard.
For each scenario, you should do 2 next things:
1. Define static getter `pasteConfig` in Tool class. Specify handled patterns there.
2. Define public method `onPaste` that will handle PasteEvent to process pasted data.
### HTML tags handling
To handle pasted HTML elements object returned from `pasteConfig` getter should contain following field:
| Name | Type | Description |
| -- | -- | -- |
| `tags` | `String[]` | _Optional_. Should contain all tag names you want to be extracted from pasted data and processed by your `onPaste` method |
For correct work you MUST provide `onPaste` handler at least for `defaultBlock` Tool.
#### Example
Header Tool can handle `H1`-`H6` tags using paste handling API
```javascript
static get pasteConfig() {
return {
tags: ['H1', 'H2', 'H3', 'H4', 'H5', 'H6'],
}
}
```
**Note. Same tag can be handled by one (first specified) Tool only.**
**Note. All attributes of pasted tag will be removed. To leave some attribute, you should explicitly specify them. Se below**
Let's suppose you want to leave the 'src' attribute when handle pasting of the `img` tags. Your config should look like this:
```javascript
static get pasteConfig() {
return {
tags: [
{
img: {
src: true
}
}
],
}
}
```
[Read more](https://editorjs.io/sanitizer) about the sanitizing configuration.
### RegExp patterns handling
Your Tool can analyze text by RegExp patterns to substitute pasted string with data you want. Object returned from `pasteConfig` getter should contain following field to use patterns:
| Name | Type | Description |
| -- | -- | -- |
| `patterns` | `Object` | _Optional_. `patterns` object contains RegExp patterns with their names as object's keys |
**Note** Editor will check pattern's full match, so don't forget to handle all available chars in there.
Pattern will be processed only if paste was on `defaultBlock` Tool and pasted string length is less than 450 characters.
> Example
You can handle YouTube links and insert embeded video instead:
```javascript
static get pasteConfig() {
return {
patterns: {
youtube: /http(?:s?):\/\/(?:www\.)?youtu(?:be\.com\/watch\?v=|\.be\/)([\w\-\_]*)(&(amp;)?[\w\?=]*)?/
},
}
}
```
### Files pasting
Your Tool can handle files pasted or dropped into the Editor.
To handle file you should provide `files` property in your `pasteConfig` configuration object.
`files` property is an object with the following fields:
| Name | Type | Description |
| ---- | ---- | ----------- |
| `extensions` | `string[]` | _Optional_ Array of extensions your Tool can handle |
| `mimeTypes` | `sring[]` | _Optional_ Array of MIME types your Tool can handle |
Example
```javascript
static get pasteConfig() {
return {
files: {
mimeTypes: ['image/png'],
extensions: ['json']
}
}
}
```
### Pasted data handling
If you registered some paste substitutions in `pasteConfig` property, you **should** provide `onPaste` callback in your Tool class.
`onPaste` should be public non-static method. It accepts custom _PasteEvent_ object as argument.
PasteEvent is an alias for three types of events - `tag`, `pattern` and `file`. You can get the type from _PasteEvent_ object's `type` property.
Each of these events provide `detail` property with info about pasted content.
| Type | Detail |
| ----- | ------ |
| `tag` | `data` - pasted HTML element |
| `pattern` | `key` - matched pattern key you specified in `pasteConfig` object <br /> `data` - pasted string |
| `file` | `file` - pasted file |
Example
```javascript
onPaste (event) {
switch (event.type) {
case 'tag':
const element = event.detail.data;
this.handleHTMLPaste(element);
break;
case 'pattern':
const text = event.detail.data;
const key = event.detail.key;
this.handlePatternPaste(key, text);
break;
case 'file':
const file = event.detail.file;
this.handleFilePaste(file);
break;
}
}
```
### Disable paste handling
If you need to disable paste handling on your Tool for some reason, you can provide `false` as `pasteConfig` value.
That way paste event won't be processed if fired on your Tool:
```javascript
static get pasteConfig {
return false;
}
```
## Sanitize <a name="sanitize"></a>
Editor.js provides [API](sanitizer.md) to clean taint strings.
Use it manually at the `save()` method or or pass `sanitizer` config to do it automatically.
### Sanitizer Configuration
The example of sanitizer configuration
```javascript
let sanitizerConfig = {
b: true, // leave <b>
p: true, // leave <p>
}
```
Keys of config object is tags and the values is a rules.
#### Rule
Rule can be boolean, object or function. Object is a dictionary of rules for tag's attributes.
You can set `true`, to allow tag with all attributes or `false|{}` to remove all attributes,
but leave tag.
Also you can pass special attributes that you want to leave.
```javascript
a: {
href: true
}
```
If you want to use a custom handler, use should specify a function
that returns a rule.
```javascript
b: function(el) {
return !el.textContent.includes('bad text');
}
```
or
```javascript
a: function(el) {
let anchorHref = el.getAttribute('href');
if (anchorHref && anchorHref.substring(0, 4) === 'http') {
return {
href: true,
target: '_blank'
}
} else {
return {
href: true
}
}
}
```
### Manual sanitize
Call API method `sanitizer.clean()` at the save method for each field in returned data.
```javascript
save() {
return {
text: this.api.sanitizer.clean(taintString, sanitizerConfig)
}
}
```
### Automatic sanitize
If you pass the sanitizer config as static getter, Editor.js will automatically sanitize your saved data.
Note that if your Tool is allowed to use the Inline Toolbar, we will get sanitizing rules for each Inline Tool
and merge with your passed config.
You can define rules for each field
```javascript
static get sanitize() {
return {
text: {},
items: {
b: true, // leave <b>
a: false, // remove <a>
}
}
}
```
Don't forget to set the rule for each embedded subitems otherwise they will
not be sanitized.
if you want to sanitize everything and get data without any tags, use `{}` or just
ignore field in case if you want to get pure HTML
```javascript
static get sanitize() {
return {
text: {},
items: {}, // this rules will be used for all properties of this object
// or
items: {
// other objects here won't be sanitized
subitems: {
// leave <a> and <b> in subitems
a: true,
b: true,
}
}
}
}
```
## Conversion config <a name="conversion-config"></a>
Editor.js has a Conversion Toolbar that allows user to convert one Block to another.

1. You can add ability to your Tool to be converted. Specify «export» property of `conversionConfig`.
2. You can add ability to convert other Tools to your Tool. Specify «import» property of `conversionConfig`.
Conversion Toolbar will be shown only near Blocks that specified an «export» rule, when user selected almost all block's content.
This Toolbar will contain only Tools that specified an «import» rule.
Example:
```js
class Header {
constructor(){
this.data = {
text: '',
level: 2
}
}
/**
* Rules specified how our Tool can be converted to/from other Tool.
*/
static get conversionConfig() {
return {
export: 'text', // this property of tool data will be used as string to pass to other tool
import: 'text' // to this property imported string will be passed
};
}
}
```
### Your Tool -> other Tool
The «export» field specifies how to represent your Tool's data as a string to pass it to other tool.
It can be a `String` or a `Function`.
`String` means a key of your Tool data object that should be used as string to export.
`Function` is a method that accepts your Tool data and compose a string to export from it. See example below:
```js
class ListTool {
constructor(){
this.data = {
items: [
'Fisrt item',
'Second item',
'Third item'
],
type: 'ordered'
}
}
static get conversionConfig() {
return {
export: (data) => {
return data.items.join('.'); // in this example, all list items will be concatenated to an export string
},
// ... import rule
};
}
}
```
### Other Tool -> your Tool
The «import» rule specifies how to create your Tool's data object from the string created by original block.
It can be a `String` or a `Function`.
`String` means the key in tool data that will be filled by an exported string.
For example, `import: 'text'` means that `constructor` of your block will accept a `data` object with `text` property filled with string composed by original block.
`Function` allows you to specify own logic, how a string should be converted to your tool data. For example:
```js
class ListTool {
constructor(data){
this.data = data || {
items: [],
type: 'unordered'
}
}
static get conversionConfig() {
return {
// ... export rule
/**
* In this example, List Tool creates items by splitting original text by a dot symbol.
*/
import: (string) => {
const items = string.split('.');
return {
items: items.filter( (text) => text.trim() !== ''),
type: 'unordered'
};
}
};
}
}
```
## Block Lifecycle hooks
### `rendered()`
Called after Block contents is added to the page
### `updated()`
Called each time Block contents is updated
### `removed()`
Called after Block contents is removed from the page but before Block instance deleted
### `moved(MoveEvent)`
Called after Block was moved. `MoveEvent` contains `fromIndex` and `toIndex`
respectively.
================================================
FILE: docs/usage.md
================================================
# So how to use Editor.js
## Basics
Editor.js is a Block-Styled editor. Blocks is a structural units, of which the Entry is composed.
For example, `Paragraph`, `Heading`, `Image`, `Video`, `List` are Blocks. Each Block is represented by a Plugin.
We have [many](http://github.com/editor-js/) ready-to-use Plugins and the [simple API](tools.md) for creation new ones.
So how to use the Editor after [Installation](installation.md).
- Create new Blocks by Enter or with the Plus Button
- Press `TAB` or click on the Plus Button to view the Toolbox
- Press `TAB` again to leaf Toolbox and select a Block you need. Then press Enter.

- Select text fragment and apply a style or insert a link from the Inline Toolbar

- Use «three-dots» button on the right to open Block Settings. From here, you can move and delete a Block
or apply Tool's settings, if it provided. For example, set a Heading level or List style.

## Shortcuts
We really appreciate shortcuts. So there are few presets.
Action | Shortcut | Restrictions
-- | -- | --
`TAB` | Show/leaf a Toolbox. | On empty block
`SHIFT+TAB` | Leaf back a Toolbox. | While Toolbox is opened
`ENTER` | Create a Block | While Toolbox is opened and some Tool is selected
`CMD+B` | Bold style | On selection
`CMD+I` | Italic style | On selection
`CMD+K` | Insert a link | On selection
Also we support shortcuts on the all type of Tools. Specify a shortcut with the Tools configuration. For example:
```js
var editor = new EditorJS({
//...
tools: {
header: {
class: Header,
shortcut: 'CMD+SHIFT+H'
},
list: {
class: List,
shortcut: 'CMD+SHIFT+L'
}
}
//...
});
```
## Autofocus
If you want to focus Editor after page has been loaded, you can enable autofocus by passing `autofocus` to the initial config
```js
var editor = new EditorJS({
//...
autofocus: true
//...
});
```
## Holder
The `holder` property supports an id or a reference to dom element.
```js
var editor = new EditorJS({
holder: document.querySelector('.editor'),
})
var editor2 = new EditorJS({
holder: 'codex-editor' // like document.getElementById('codex-editor')
})
```
## Placeholder
By default Editor\`s placeholder is empty.
You can pass your own placeholder via `placeholder` field:
```js
var editor = new EditorJS({
//...
placeholder: 'My awesome placeholder'
//...
});
```
If you are using your custom `Initial Block`, `placeholder` property is passed in `config` to your Tool constructor.
## Log level
You can specify log level for Editor.js console messages via `logLevel` property of configuration:
```js
var editor = new EditorJS({
//...
logLevel: 'WARN'
//..
})
```
Possible values:
| Value | Description |
| ----- | ---------------------------- |
| `VERBOSE` | Show all messages |
| `INFO` | Show info and debug messages |
| `WARN` | Show errors and warns only |
| `ERROR` | Show errors only |
================================================
FILE: example/example-i18n.html
================================================
<!--
This page contains example of editor.js internalization.
See <script> section -> i18n property of the configuration object
\ (•◡•) /
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Editor.js 🤩🧦🤨 example</title>
<link href="https://fonts.googleapis.com/css?family=PT+Mono" rel="stylesheet">
<link href="../public/assets/demo.css" rel="stylesheet">
<script src="../public/assets/json-preview.js"></script>
<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--small">
<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">
editor.save()
</div>
</div>
<div class="ce-example__output">
<pre class="ce-example__output-content" id="output"></pre>
<div class="ce-example__output-footer">
<a href="https://codex.so" style="font-weight: bold;">Made by CodeX</a>
</div>
</div>
</div>
<!-- Load Tools -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/header@latest"></script><!-- Header -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/image@latest"></script><!-- Image -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/delimiter@latest"></script><!-- Delimiter -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/list@latest"></script><!-- List -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/quote@latest"></script><!-- Quote -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/code@latest"></script><!-- Code -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/embed@latest"></script><!-- Embed -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/table@latest"></script><!-- Table -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/link@latest"></script><!-- Link -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/warning@latest"></script><!-- Warning -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/marker@latest"></script><!-- Marker -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/inline-code@latest"></script><!-- Inline Code -->
<!-- Load Editor.js's Core -->
<script src="../dist/editorjs.umd.js" onload="document.getElementById('hint-core').hidden = true"></script>
<!-- Initialization -->
<script>
/**
* Saving button
*/
const saveButton = document.getElementById('saveButton');
/**
* To initialize the Editor, create a new instance with configuration object
* @see docs/installation.md for mode details
*/
var editor = new EditorJS({
/**
* Wrapper of Editor
*/
holder: 'editorjs',
/**
* Tools list
*/
tools: {
paragraph: {
config: {
placeholder: "Enter something"
}
},
/**
* Each Tool is a Plugin. Pass them via 'class' option with necessary settings {@link docs/tools.md}
*/
header: {
class: Header,
inlineToolbar: ['link'],
config: {
placeholder: 'Header'
},
shortcut: 'CMD+SHIFT+H'
},
/**
* Or pass class directly without any configuration
*/
image: ImageTool,
list: {
class: EditorjsList,
inlineToolbar: true,
shortcut: 'CMD+SHIFT+L'
},
quote: {
class: Quote,
inlineToolbar: true,
config: {
quotePlaceholder: 'Enter a quote',
captionPlaceholder: 'Quote\'s author',
},
shortcut: 'CMD+SHIFT+O'
},
warning: Warning,
marker: {
class: Marker,
shortcut: 'CMD+SHIFT+M'
},
code: {
class: CodeTool,
shortcut: 'CMD+SHIFT+C'
},
delimiter: Delimiter,
inlineCode: {
class: InlineCode,
shortcut: 'CMD+SHIFT+C'
},
linkTool: LinkTool,
embed: Embed,
table: {
class: Table,
inlineToolbar: true,
shortcut: 'CMD+ALT+T'
},
},
/**
* To provide localization of the editor.js you need to provide 'i18n' option with 'messages' dictionary:
*
* 1. At the 'ui' section of 'messages' there are translations for the internal editor.js UI elements.
* You can create or find/download a dictionary for your language
*
* 2. As long as tools list is a user-specific thing (we do not know which tools you use and under which names),
* so we can't provide a ready-to-use tool names dictionary.
* There is a 'toolNames' section for that reason. Put translations for the names of your tools there.
*
* 3. Also, the UI of the tools you use is also invisible to editor.js core.
* To pass translations for specific tools (that supports I18n API), there are 'tools' and 'blockTunes' section.
* Pass dictionaries for specific plugins through them.
*/
i18n: {
/**
* @type {I18nDictionary}
*/
messages: {
/**
* Other below: translation of different UI components of the editor.js core
*/
"ui": {
"blockTunes": {
"toggler": {
"Click to tune": "Нажмите, чтобы настроить",
"or drag to move": "или перетащите"
},
},
"inlineToolbar": {
"converter": {
"Convert to": "Конвертировать в"
}
},
"toolbar": {
"toolbox": {
"Add": "Добавить",
}
},
"popover": {
"Filter": "Поиск",
"Nothing found": "Ничего не найдено",
/**
* Translation of "Convert To" at the Block Tunes Popover
*/
"Convert to": "Конвертировать в",
}
},
/**
* Section for translation Tool Names: both block and inline tools
*/
"toolNames": {
"Text": "Параграф",
"Heading": "Заголовок",
"Ordered List": "Нумерованный список",
"Unordered List": "Маркированный список",
"Warning": "Примечание",
"Checklist": "Чеклист",
"Quote": "Цитата",
"Code": "Код",
"Delimiter": "Разделитель",
"Raw HTML": "HTML-фрагмент",
"Table": "Таблица",
"Link": "Ссылка",
"Marker": "Маркер",
"Bold": "Полужирный",
"Italic": "Курсив",
"InlineCode": "Моноширинный",
"Image": "Картинка",
},
/**
* Section for passing translations to the external tools classes
*/
"tools": {
/**
* Each subsection is the i18n dictionary that will be passed to the corresponded plugin
* The name of a plugin should be equal the name you specify in the 'tool' section for that plugin
*/
"warning": { // <-- 'Warning' tool will accept this dictionary section
"Title": "Название",
"Message": "Сообщение",
},
/**
* Link is the internal Inline Tool
*/
"link": {
"Add a link": "Вставьте ссылку"
},
/**
* The "stub" is an internal block tool, used to fit blocks that does not have the corresponded plugin
*/
"stub": {
'The block can not be displayed correctly.': 'Блок не может быть отображен'
},
"image": {
"Caption": "Подпись",
"Select an Image": "Выберите файл",
"With border": "Добавить рамку",
"Stretch image": "Растянуть",
"With background": "Добавить подложку",
},
"code": {
"Enter a code": "Код",
},
"linkTool": {
"Link": "Ссылка",
"Couldn't fetch the link data": "Не удалось получить данные",
"Couldn't get this link data, try the other one": "Не удалось получить данные по ссылке, попробуйте другую",
"Wrong response format from the server": "Неполадки на сервере",
},
"header": {
"Heading 1": "Заголовок 1",
"Heading 2": "Заголовок 2",
"Heading 3": "Заголовок 3",
"Heading 4": "Заголовок 4",
"Heading 5": "Заголовок 5",
"Heading 6": "Заголовок 6",
},
"paragraph": {
"Enter something": "Введите текст"
},
"list": {
"Ordered": "Нумерованный",
"Unordered": "Маркированный",
"Checklist": "Чеклист",
},
/**
* Translation of "Convert To" at the Inline Toolbar hint
*/
"convertTo": {
"Convert to": "Конвертировать в"
},
},
/**
* Section allows to translate Block Tunes
*/
"blockTunes": {
/**
* Each subsection is the i18n dictionary that will be passed to the corresponded Block Tune plugin
* The name of a plugin should be equal the name you specify in the 'tunes' section for that plugin
*
* Also, there are few internal block tunes: "delete", "moveUp" and "moveDown"
*/
"delete": {
"Delete": "Удалить",
"Click to delete": "Подтвердить удаление"
},
"moveUp": {
"Move up": "Переместить вверх"
},
"moveDown": {
"Move down": "Переместить вниз"
},
},
}
},
/**
* Initial Editor data
*/
data: {
blocks: [
{
type: "header",
data: {
text: "Editor.js",
level: 2
}
},
{
type : 'paragraph',
data : {
text : 'Hey. Meet the new Editor. On this page you can see it in action — try to edit this text. Source code of the page contains the example of connection and configuration.'
}
},
{
type: "header",
data: {
text: "Key features",
level: 3
}
},
{
type : 'list',
data : {
items : [
'It is a block-styled editor',
'It returns clean data output in JSON',
'Designed to be extendable and pluggable with a simple API',
],
style: 'unordered'
}
},
{
type: "header",
data: {
text: "What does it mean «block-styled editor»",
level: 3
}
},
{
type : 'paragraph',
data : {
text : 'Workspace in classic editors is made of a single contenteditable element, used to create different HTML markups. Editor.js <mark class=\"cdx-marker\">workspace consists of separate Blocks: paragraphs, headings, images, lists, quotes, etc</mark>. Each of them is an independent contenteditable element (or more complex structure) provided by Plugin and united by Editor\'s Core.'
}
},
{
type : 'paragraph',
data : {
text : `There are dozens of <a href="https://github.com/editor-js">ready-to-use Blocks</a> and the <a href="https://editorjs.io/creating-a-block-tool">simple API</a> for creation any Block you need. For example, you can implement Blocks for Tweets, Instagram posts, surveys and polls, CTA-buttons and even games.`
}
},
{
type: "header",
data: {
text: "What does it mean clean data output",
level: 3
}
},
{
type : 'paragraph',
data : {
text : 'Classic WYSIWYG-editors produce raw HTML-markup with both content data and content appearance. On the contrary, Editor.js outputs JSON object with data of each Block. You can see an example below'
}
},
{
type : 'paragraph',
data : {
text : `Given data can be used as you want: render with HTML for <code class="inline-code">Web clients</code>, render natively for <code class="inline-code">mobile apps</code>, create markup for <code class="inline-code">Facebook Instant Articles</code> or <code class="inline-code">Google AMP</code>, generate an <code class="inline-code">audio version</code> and so on.`
}
},
{
type : 'paragraph',
data : {
text : 'Clean data is useful to sanitize, validate and process on the backend.'
}
},
{
type : 'delimiter',
data : {}
},
{
type : 'paragraph',
data : {
text : 'We have been working on this project more than three years. Several large media projects help us to test and debug the Editor, to make its core more stable. At the same time we significantly improved the API. Now, it can be used to create any plugin for any task. Hope you enjoy. 😏'
}
},
{
type: 'image',
data: {
file : {
url: 'assets/codex2x.png',
},
caption: '',
stretched: false,
withBorder: true,
withBackground: false,
}
},
]
},
onReady: function(){
saveButton.click();
},
});
/**
* Saving example
*/
saveButton.addEventListener('click', function () {
editor.save().then((savedData) => {
cPreview.show(savedData, document.getElementById("output"));
});
});
</script>
</body>
</html>
================================================
FILE: example/example-multiple.html
================================================
<!--
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="../public/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/editorjs.umd.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>
================================================
FILE: example/example-popup.html
================================================
<!--
Use this page for debugging purposes.
This page can be used for testing editor nested in a popup.
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Editor.js 🤩🧦🤨 example: Popup</title>
<link href="../public/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 ce-example--popup">
<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="stub">
<h1>Base concepts</h1>
<p>
Editor.js is a block-style editor for rich media stories. It outputs clean data in JSON instead of heavy HTML markup. And more important thing is that Editor.js is designed to be API extendable and pluggable.
</p>
<p>
So there are a few key features:
</p>
<ul>
<li>Clean data output</li>
<li>API pluggable</li>
<li>Open source</li>
</ul>
<h2>
What does it mean block-styled
</h2>
<p>
In other editors, the workspace is provided by single contenteditable element in where you can create different HTML markup. All of us saw permanent bugs with moving text fragments or scaling images, while page parts are jumping and twitches. Or highlighting big parts of the text in the case when you just want to make few words to be a heading or bold.
</p>
<p>
The Editor.js workspace consists of separate Blocks: paragraphs, headings, images, lists, quotes, etc. Each of them is an independent contenteditable element (or more complex structure) provided by Plugin and united by Editor's Core.
</p>
<p>
At the same time, most useful features as arrow-navigation, copy & paste, cross block selection, and others works almost as in the familiar editors.
</p>
<h2>
What is clean data
</h2>
<p>
But the more interesting thing is, as mentioned above, that Editor.js returns clean data instead of HTML-markup. Take a look at the example.
</p>
<p>
If our entry consists of few paragraphs and a heading, in popular Medium editor after saving we will have something like this:
</p>
<p>
As you can see, there are only data we need: a list of structural Blocks with their content description.
</p>
<p>
You can use this data to easily render in Web, native mobile/desktop application, pass to Audio Readers, create templates for Facebook Instant Articles, AMP, RSS, create chat-bots, and many others.
</p>
<p>
Also, the clean data can be useful for backend processing: sanitizing, validation, injecting an advertising or other stuff, extracting Headings, make covers for social networks from Image Blocks, and other.
</p>
<h2>
API pluggable?
</h2>
<p>
A key value of the Editor is the API. All main functional units of the editor — Blocks, Inline Formatting Tools, Block Tunes — are provided by external plugins that use Editor's API.
</p>
<p>
We decide to extract all these Tools to separate scripts to make Editor's Core more abstract and make API more powerful. Any challenges and tasks you are facing can be implemented by your own plugins using the API.
</p>
<p>
At the same time, API is created to be easy-to-understand and simple-to-use.
</p>
<h2>
Open Source, so?
</h2>
<p>
Editor.js is more than just an editor. It is a big open-source community of developers and contributors. Anyone can suggest an improvement or a bug fix. Anyone can create new cool API features and plugins.
</p>
<p>
We will support each developer of Editor.js plugins: the best solutions will be collected to the Awesome List and promoted to the community. Together we can create a big suite of different Blocks, Inline Tools, Block Tunes that can hit a wide specter of tasks.
</p>
<p>
Thanks for your interest. Hope you enjoy Editor.js.
</p>
</div>
<div class="ce-example-popup">
<div class="ce-example-popup__overlay"></div>
<div class="ce-example-popup__popup">
<div id="editorjs"></div>
</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/editorjs.umd.js" onload="document.getElementById('hint-core').hidden = true"></script>
<script src="./tools/header/dist/bundle.js"></script><!-- Header -->
<!-- Initialization -->
<script>
var editor1 = new EditorJS({
holder: 'editorjs',
tools: {
header: {
class: Header,
shortcut: 'CMD+SHIFT+H'
}
}
});
</script>
</body>
</html>
================================================
FILE: example/example-rtl.html
================================================
<!--
Use this page for RTL mode debugging.
Editor Tools are loaded as git-submodules.
You can pull modules by running `yarn pull_tools` and start experimenting.
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Editor.js RTL example</title>
<link href="https://fonts.googleapis.com/css?family=PT+Mono" rel="stylesheet">
<link href="../public/assets/demo.css" rel="stylesheet">
<script src="../public/assets/json-preview.js"></script>
<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--small">
<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 id="hint-tools" style="text-align: center;">
No submodules found. Run <code class="inline-code">yarn pull_tools && yarn tools:update</code>
</div>
<div class="ce-example__button" id="saveButton">
editor.save()
</div>
</div>
<div class="ce-example__output">
<pre class="ce-example__output-content" id="output"></pre>
<div class="ce-example__output-footer">
<a href="https://codex.so" style="font-weight: bold;">Made by CodeX</a>
</div>
</div>
</div>
<!-- Load Tools -->
<!--
You can upload Tools to your project's directory and use as in example below.
Also you can load each Tool from CDN or use NPM/Yarn packages.
Read more in Tool's README file. For example:
https://github.com/editor-js/header#installation
-->
<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/delimiter@latest"></script><!-- Delimiter -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/nested-list@latest"></script><!-- List -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/checklist@latest"></script><!-- Checklist -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/quote@latest"></script><!-- Quote -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/code@latest"></script><!-- Code -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/embed@latest"></script><!-- Embed -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/table@latest"></script><!-- Table -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/link@latest"></script><!-- Link -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/warning@latest"></script><!-- Warning -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/raw@latest"></script><!-- Raw -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/marker@latest"></script><!-- Marker -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/inline-code@latest"></script><!-- Inline Code -->
<!-- Load Editor.js's Core -->
<script src="../dist/editorjs.umd.js" onload="document.getElementById('hint-core').hidden = true"></script>
<!-- Initialization -->
<script>
/**
* Saving button
*/
const saveButton = document.getElementById('saveButton');
/**
* To initialize the Editor, create a new instance with configuration object
* @see docs/installation.md for mode details
*/
var editor = new EditorJS({
/**
* Wrapper of Editor
*/
holder: 'editorjs',
i18n: {
/**
* Text direction
*/
direction: 'rtl',
},
/**
* Tools list
*/
tools: {
/**
* Each Tool is a Plugin. Pass them via 'class' option with necessary settings {@link docs/tools.md}
*/
header: {
class: Header,
inlineToolbar: ['link'],
config: {
placeholder: 'Header'
},
shortcut: 'CMD+SHIFT+H'
},
/**
* Or pass class directly without any configuration
*/
image: {
class: SimpleImage,
inlineToolbar: ['link'],
},
checklist: {
class: Checklist,
inlineToolbar: true,
},
quote: {
class: Quote,
inlineToolbar: true,
config: {
quotePlaceholder: 'Enter a quote',
captionPlaceholder: 'Quote\'s author',
},
shortcut: 'CMD+SHIFT+O'
},
warning: Warning,
marker: {
class: Marker,
shortcut: 'CMD+SHIFT+M'
},
code: {
class: CodeTool,
shortcut: 'CMD+SHIFT+C'
},
delimiter: Delimiter,
inlineCode: {
class: InlineCode,
shortcut: 'CMD+SHIFT+C'
},
linkTool: LinkTool,
raw: RawTool,
embed: Embed,
table: {
class: Table,
inlineToolbar: true,
shortcut: 'CMD+ALT+T'
},
},
/**
* This Tool will be used as default
*/
// initialBlock: 'paragraph',
/**
* Initial Editor data
*/
data: {
blocks: [
{
type: "header",
data: {
text: "محرر.js",
level: 2
}
},
{
type : 'paragraph',
data : {
text : 'مرحبا! تعرف على المحرر الجديد. في هذه الصفحة ، يمكنك رؤيتها في العمل - حاول تحرير هذا النص.'
}
},
{
type: "header",
data: {
text: "دلائل الميزات",
level: 3
}
},
{
type : 'list',
data : {
items : [
'وهو محرر بنمط الكتلة',
'تقوم بإرجاع إخراج بيانات نظيفة في JSON',
'مصممة لتكون قابلة للتوسيع والتوصيل مع واجهة برمجة تطبيقات بسيطة'
],
style: 'unordered'
}
}
]
},
onReady: function(){
saveButton.click();
},
onChange: function() {
console.log('something changed');
}
});
/**
* Saving example
*/
saveButton.addEventListener('click', function () {
editor.save().then((savedData) => {
cPreview.show(savedData, document.getElementById("output"));
});
});
</script>
</body>
</html>
================================================
FILE: example/example.html
================================================
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Editor.js 🤩🧦🤨 example</title>
<link href="https://fonts.googleapis.com/css?family=PT+Mono" rel="stylesheet">
<link href="../public/assets/demo.css" rel="stylesheet">
<script src="../public/assets/json-preview.js"></script>
<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--small">
<div id="editorjs"></div>
<div class="ce-example__button" id="saveButton">
editor.save()
</div>
<div class="ce-example__statusbar">
Readonly:
<b id="readonly-state">
Off
</b>
<div class="ce-example__statusbar-button" id="toggleReadOnlyButton">
toggle
</div>
</div>
</div>
<div class="ce-example__output">
<pre class="ce-example__output-content" id="output"></pre>
<div class="ce-example__output-footer">
<a href="https://codex.so" style="font-weight: bold;">Made by CodeX</a>
</div>
</div>
</div>
<!-- Load Tools -->
<!--
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.
Read more at Tools Connection doc:
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/simple-image@latest"></script><!-- Image -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/delimiter@latest"></script><!-- Delimiter -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/list@latest"></script><!-- List -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/checklist@latest"></script><!-- Checklist -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/quote@latest"></script><!-- Quote -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/code@latest"></script><!-- Code -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/embed@latest"></script><!-- Embed -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/table@latest"></script><!-- Table -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/link@latest"></script><!-- Link -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/warning@latest"></script><!-- Warning -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/marker@latest"></script><!-- Marker -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/inline-code@latest"></script><!-- Inline Code -->
<!-- Load Editor.js's Core -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/editorjs@latest"></script>
<!-- Initialization -->
<script>
/**
* To initialize the Editor, create a new instance with configuration object
* @see docs/installation.md for mode details
*/
var editor = new EditorJS({
/**
* Enable/Disable the read only mode
*/
readOnly: false,
/**
* Wrapper of Editor
*/
holder: 'editorjs',
/**
* Common Inline Toolbar settings
* - if true (or not specified), the order from 'tool' property will be used
* - if an array of tool names, this order will be used
*/
// inlineToolbar: ['link', 'marker', 'bold', 'italic'],
// inlineToolbar: true,
/**
* Tools list
*/
tools: {
/**
* Each Tool is a Plugin. Pass them via 'class' option with necessary settings {@link docs/tools.md}
*/
header: {
class: Header,
inlineToolbar: ['marker', 'link'],
config: {
placeholder: 'Header'
},
shortcut: 'CMD+SHIFT+H'
},
/**
* Or pass class directly without any configuration
*/
image: SimpleImage,
list: {
class: List,
inlineToolbar: true,
shortcut: 'CMD+SHIFT+L'
},
checklist: {
class: Checklist,
inlineToolbar: true,
},
quote: {
class: Quote,
inlineToolbar: true,
config: {
quotePlaceholder: 'Enter a quote',
captionPlaceholder: 'Quote\'s author',
},
shortcut: 'CMD+SHIFT+O'
},
warning: Warning,
marker: {
class: Marker,
shortcut: 'CMD+SHIFT+M'
},
code: {
class: CodeTool,
shortcut: 'CMD+SHIFT+C'
},
delimiter: Delimiter,
inlineCode: {
class: InlineCode,
shortcut: 'CMD+SHIFT+C'
},
linkTool: LinkTool,
embed: Embed,
table: {
class: Table,
inlineToolbar: true,
shortcut: 'CMD+ALT+T'
},
},
/**
* This Tool will be used as default
*/
// defaultBlock: 'paragraph',
/**
* Initial Editor data
*/
data: {
blocks: [
{
type: "header",
data: {
text: "Editor.js",
level: 2
}
},
{
type : 'paragraph',
data : {
text : 'Hey. Meet the new Editor. On this page you can see it in action — try to edit this text. Source code of the page contains the example of connection and configuration.'
}
},
{
type: "header",
data: {
text: "Key features",
level: 3
}
},
{
type : 'list',
data : {
items : [
'It is a block-styled editor',
'It returns clean data output in JSON',
'Designed to be extendable and pluggable with a simple API',
],
style: 'unordered'
}
},
{
type: "header",
data: {
text: "What does it mean «block-styled editor»",
level: 3
}
},
{
type : 'paragraph',
data : {
text : 'Workspace in classic editors is made of a single contenteditable element, used to create different HTML markups. Editor.js <mark class=\"cdx-marker\">workspace consists of separate Blocks: paragraphs, headings, images, lists, quotes, etc</mark>. Each of them is an independent contenteditable element (or more complex structure) provided by Plugin and united by Editor\'s Core.'
}
},
{
type : 'paragraph',
data : {
text : `There are dozens of <a href="https://github.com/editor-js">ready-to-use Blocks</a> and the <a href="https://editorjs.io/creating-a-block-tool">simple API</a> for creation any Block you need. For example, you can implement Blocks for Tweets, Instagram posts, surveys and polls, CTA-buttons and even games.`
}
},
{
type: "header",
data: {
text: "What does it mean clean data output",
level: 3
}
},
{
type : 'paragraph',
data : {
text : 'Classic WYSIWYG-editors produce raw HTML-markup with both content data and content appearance. On the contrary, Editor.js outputs JSON object with data of each Block. You can see an example below'
}
},
{
type : 'paragraph',
data : {
text : `Given data can be used as you want: render with HTML for <code class="inline-code">Web clients</code>, render natively for <code class="inline-code">mobile apps</code>, create markup for <code class="inline-code">Facebook Instant Articles</code> or <code class="inline-code">Google AMP</code>, generate an <code class="inline-code">audio version</code> and so on.`
}
},
{
type : 'paragraph',
data : {
text : 'Clean data is useful to sanitize, validate and process on the backend.'
}
},
{
type : 'delimiter',
data : {}
},
{
type : 'paragraph',
data : {
text : 'We have been working on this project more than three years. Several large media projects help us to test and debug the Editor, to make its core more stable. At the same time we significantly improved the API. Now, it can be used to create any plugin for any task. Hope you enjoy. 😏'
}
},
{
type: 'image',
data: {
url: 'assets/codex2x.png',
caption: '',
stretched: false,
withBorder: true,
withBackground: false,
}
},
]
},
onReady: function(){
saveButton.click();
},
onChange: function(api, event) {
console.log('something changed', event);
}
});
/**
* Saving button
*/
const saveButton = document.getElementById('saveButton');
/**
* Toggle read-only button
*/
const toggleReadOnlyButton = document.getElementById('toggleReadOnlyButton');
const readOnlyIndicator = document.getElementById('readonly-state');
/**
* Saving example
*/
saveButton.addEventListener('click', function () {
editor.save()
.then((savedData) => {
cPreview.show(savedData, document.getElementById("output"));
})
.catch((error) => {
console.error('Saving error', error);
});
});
/**
* Toggle read-only example
*/
toggleReadOnlyButton.addEventListener('click', async () => {
const readOnlyState = await editor.readOnly.toggle();
readOnlyIndicator.textContent = readOnlyState ? 'On' : 'Off';
});
</script>
</body>
</html>
================================================
FILE: index.html
================================================
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Editor.js 🤩🧦🤨 example</title>
<link href="https://fonts.googleapis.com/css?family=PT+Mono" rel="stylesheet">
<link href="/assets/demo.css" rel="stylesheet">
<script src="/assets/json-preview.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
</head>
<body>
<script>
if (localStorage.getItem('theme') === 'dark') {
document.body.classList.add("dark-mode");
}
</script>
<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">
<div id="editorjs"></div>
<div class="ce-example__button" id="saveButton">
editor.save()
</div>
<div class="ce-example__statusbar">
<div class="ce-example__statusbar-item">
Readonly:
<b id="readonly-state">
Off
</b>
<div class="ce-example__statusbar-button" id="toggleReadOnlyButton">
toggle
</div>
</div>
<div class="ce-example__statusbar-item">
<div class="ce-example__statusbar-button" id="showBlocksBoundariesButton">
<span data-toggled-text="Hide">Show</span>
blocks boundaries
</div>
</div>
<div class="ce-example__statusbar-item">
<div class="ce-example__statusbar-button" id="enableThinModeButton">
<span data-toggled-text="Disable">Enable</span>
thin mode
</div>
</div>
<div class="ce-example__statusbar-item ce-example__statusbar-item--right">
<div class="ce-example__statusbar-toggler" id="darkThemeToggler">
</div>
</div>
</div>
</div>
<div class="ce-example__output">
<pre class="ce-example__output-content" id="output"></pre>
<div class="ce-example__output-footer">
<a href="https://codex.so" style="font-weight: bold;">Made by CodeX</a>
</div>
</div>
</div>
<!-- Load Tools -->
<!--
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.
Read more at Tools Connection doc:
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/simple-image@latest"></script><!-- Image -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/delimiter@latest"></script><!-- Delimiter -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/nested-list@latest"></script><!-- List -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/checklist@latest"></script><!-- Checklist -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/quote@latest"></script><!-- Quote -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/code@latest"></script><!-- Code -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/embed@latest"></script><!-- Embed -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/table@latest"></script><!-- Table -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/link@latest"></script><!-- Link -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/warning@latest"></script><!-- Warning -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/raw@latest"></script><!-- Raw -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/marker@latest"></script><!-- Marker -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/inline-code@latest"></script><!-- Inline Code -->
<!-- Initialization -->
<script type="module">
import EditorJS from './src/codex.ts';
window.EditorJS = EditorJS;
/**
* To initialize the Editor, create a new instance with configuration object
* @see docs/installation.md for mode details
*/
const editorConfig = {
/**
* Enable/Disable the read only mode
*/
readOnly: false,
/**
* Wrapper of Editor
*/
holder: 'editorjs',
/**
* Common Inline Toolbar settings
* - if true (or not specified), the order from 'tool' property will be used
* - if an array of tool names, this order will be used
*/
// inlineToolbar: ['link', 'marker', 'bold', 'italic'],
// inlineToolbar: true,
/**
* Tools list
*/
tools: {
/**
* Each Tool is a Plugin. Pass them via 'class' option with necessary settings {@link docs/tools.md}
*/
header: {
class: Header,
inlineToolbar: ['link', 'marker'],
config: {
placeholder: 'Header'
},
shortcut: 'CMD+SHIFT+H'
},
/**
* Or pass class directly without any configuration
*/
image: SimpleImage,
list: {
class: NestedList,
inlineToolbar: true,
shortcut: 'CMD+SHIFT+L'
},
checklist: {
class: Checklist,
inlineToolbar: true,
},
quote: {
class: Quote,
inlineToolbar: true,
config: {
quotePlaceholder: 'Enter a quote',
captionPlaceholder: 'Quote\'s author',
},
shortcut: 'CMD+SHIFT+O'
},
warning: Warning,
marker: {
class: Marker,
shortcut: 'CMD+SHIFT+M'
},
code: {
class: CodeTool,
shortcut: 'CMD+SHIFT+C'
},
delimiter: Delimiter,
inlineCode: {
class: InlineCode,
shortcut: 'CMD+SHIFT+C'
},
linkTool: LinkTool,
raw: RawTool,
embed: Embed,
table: {
class: Table,
inlineToolbar: true,
shortcut: 'CMD+ALT+T'
},
},
/**
* This Tool will be used as default
*/
// defaultBlock: 'paragraph',
placeholder: 'Write something or press / to select a tool',
autofocus: true,
/**
* Initial Editor data
*/
data: {
blocks: [
{
id: "zcKCF1S7X8",
type: "header",
data: {
text: "Editor.js",
level: 1
}
},
{
id: "b6ji-DvaKb",
type: "paragraph",
data: {
text: "Hey. Meet the new Editor. On this page you can see it in action — try to edit this text. Source code of the page contains the example of connection and configuration."
}
},
{
type: "header",
id: "7ItVl5biRo",
data: {
text: "Key features",
level: 2
}
},
{
type : 'list',
id: "SSBSguGvP7",
data : {
items : [
{
content: 'It is a block-styled editor',
items: []
},
{
content: 'It returns clean data output in JSON',
items: []
},
{
content: 'Designed to be extendable and pluggable with a simple API',
items: []
}
],
style: 'unordered'
}
},
{
type: "header",
id: "QZFox1m_ul",
data: {
text: "What does it mean «block-styled editor»",
level: 2
}
},
{
type : 'paragraph',
id: "bwnFX5LoX7",
data : {
text : 'Workspace in classic editors is made of a single contenteditable element, used to create different HTML markups. Editor.js <mark class=\"cdx-marker\">workspace consists of separate Blocks: paragraphs, headings, images, lists, quotes, etc</mark>. Each of them is an independent contenteditable element (or more complex structure) provided by Plugin and united by Editor\'s Core.'
}
},
{
type : 'paragraph',
id: "mTrPOHAQTe",
data : {
text : `There are dozens of <a href="https://github.com/editor-js">ready-to-use Blocks</a> and the <a href="https://editorjs.io/creating-a-block-tool">simple API</a> for creation any Block you need. For example, you can implement Blocks for Tweets, Instagram posts, surveys and polls, CTA-buttons and even games.`
}
},
{
type: "header",
id: "1sYMhUrznu",
data: {
text: "What does it mean clean data output",
level: 2
}
},
{
type : 'paragraph',
id: "jpd7WEXrJG",
data : {
text : 'Classic WYSIWYG-editors produce raw HTML-markup with both content data and content appearance. On the contrary, Editor.js outputs JSON object with data of each Block. You can see an example below'
}
},
{
type : 'paragraph',
id: "0lOGNUKxqt",
data : {
text : `Given data can be used as you want: render with HTML for <code class="inline-code">Web clients</code>, render natively for <code class="inline-code">mobile apps</code>, create markup for <code class="inline-code">Facebook Instant Articles</code> or <code class="inline-code">Google AMP</code>, generate an <code class="inline-code">audio version</code> and so on.`
}
},
{
type : 'paragraph',
id: "WvX7kBjp0I",
data : {
text : 'Clean data is useful to sanitize, validate and process on the backend.'
}
},
{
type : 'delimiter',
id: "H9LWKQ3NYd",
data : {}
},
{
type : 'paragraph',
id: "h298akk2Ad",
data : {
text : 'We have been working on this project more than three years. Several large media projects help us to test and debug the Editor, to make its core more stable. At the same time we significantly improved the API. Now, it can be used to create any plugin for any task. Hope you enjoy. 😏'
}
},
{
type: 'image',
id: "9802bjaAA2",
data: {
url: '/assets/codex2x.png',
caption: '',
stretched: false,
withBorder: true,
withBackground: false,
}
},
]
},
onReady: function(){
saveButton.click();
},
onChange: function(api, event) {
console.log('something changed', event);
},
}
/**
* To initialize the Editor, create a new instance with configuration object
* @see docs/installation.md for mode details
*/
var editor = new EditorJS(editorConfig);
/**
* Saving button
*/
const saveButton = document.getElementById('saveButton');
/**
* Toggle read-only button
*/
const toggleReadOnlyButton = document.getElementById('toggleReadOnlyButton');
const readOnlyIndicator = document.getElementById('readonly-state');
/**
* Saving example
*/
saveButton.addEventListener('click', function () {
editor.save()
.then((savedData) => {
cPreview.show(savedData, document.getElementById("output"));
})
.catch((error) => {
console.error('Saving error', error);
});
});
/**
* Toggle read-only example
*/
toggleReadOnlyButton.addEventListener('click', async () => {
const readOnlyState = await editor.readOnly.toggle();
readOnlyIndicator.textContent = readOnlyState ? 'On' : 'Off';
});
/**
* Button for displaying blocks borders. Useful for UI development
*/
const showBlocksBoundariesButton = document.getElementById("showBlocksBoundariesButton");
showBlocksBoundariesButton.addEventListener('click', () => {
document.body.classList.toggle("show-block-boundaries")
})
/**
* Button for enabling the 'Thin' mode
*/
const enableThinModeButton = document.getElementById("enableThinModeButton");
enableThinModeButton.addEventListener('click', () => {
document.body.classList.toggle("thin-mode")
editor.destroy();
editor = new EditorJS(editorConfig);
})
/**
* Toggler for toggling the dark mode
*/
const darkThemeToggler = document.getElementById("darkThemeToggler");
darkThemeToggler.addEventListener('click', () => {
document.body.classList.toggle("dark-mode");
localStorage.setItem('theme', document.body.classList.contains("dark-mode") ? 'dark' : 'default');
})
window.editor = editor;
</script>
</body>
</html>
================================================
FILE: package.json
================================================
{
"name": "@editorjs/editorjs",
"version": "2.31.5",
"description": "Editor.js — open source block-style WYSIWYG editor with JSON output",
"main": "dist/editorjs.umd.js",
"module": "dist/editorjs.mjs",
"types": "./types/index.d.ts",
"keywords": [
"codex editor",
"text editor",
"editor",
"editor.js",
"editorjs",
"wysiwyg"
],
"scripts": {
"dev": "vite",
"build": "vite build --mode production",
"build:test": "vite build --mode test",
"lint": "eslint src/ --ext .ts && yarn lint:tests",
"lint:errors": "eslint src/ --ext .ts --quiet",
"lint:fix": "eslint src/ --ext .ts --fix",
"lint:tests": "eslint test/ --ext .ts",
"test:e2e": "yarn build:test && cypress run",
"test:e2e:open": "yarn build:test && cypress open"
},
"author": "CodeX",
"licen
gitextract_ol6jf4j0/ ├── .editorconfig ├── .eslintignore ├── .eslintrc ├── .github/ │ ├── CODE_OF_CONDUCT.md │ ├── FUNDING.yml │ ├── ISSUE_TEMPLATE/ │ │ ├── bug_report.md │ │ ├── config.yml │ │ └── general_issue.md │ └── workflows/ │ ├── bump-version-on-merge-next.yml │ ├── create-a-release-draft.yml │ ├── cypress.yml │ ├── eslint.yml │ └── publish-package-to-npm.yml ├── .gitignore ├── .npmignore ├── .nvmrc ├── .postcssrc.yml ├── .stylelintrc ├── .vscode/ │ └── settings.json ├── CODEOWNERS ├── LICENSE ├── README.md ├── cypress.config.ts ├── docs/ │ ├── CHANGELOG.md │ ├── api.md │ ├── block-tunes.md │ ├── caret.md │ ├── installation.md │ ├── releases.md │ ├── sanitizer.md │ ├── toolbar-settings.md │ ├── tools-inline.md │ ├── tools.md │ └── usage.md ├── example/ │ ├── example-i18n.html │ ├── example-multiple.html │ ├── example-popup.html │ ├── example-rtl.html │ └── example.html ├── index.html ├── package.json ├── public/ │ └── assets/ │ ├── demo.css │ └── json-preview.js ├── src/ │ ├── codex.ts │ ├── components/ │ │ ├── __module.ts │ │ ├── block/ │ │ │ ├── api.ts │ │ │ └── index.ts │ │ ├── block-tunes/ │ │ │ ├── block-tune-delete.ts │ │ │ ├── block-tune-move-down.ts │ │ │ └── block-tune-move-up.ts │ │ ├── blocks.ts │ │ ├── constants.ts │ │ ├── core.ts │ │ ├── dom.ts │ │ ├── domIterator.ts │ │ ├── errors/ │ │ │ └── critical.ts │ │ ├── events/ │ │ │ ├── BlockChanged.ts │ │ │ ├── BlockHovered.ts │ │ │ ├── EditorMobileLayoutToggled.ts │ │ │ ├── FakeCursorAboutToBeToggled.ts │ │ │ ├── FakeCursorHaveBeenSet.ts │ │ │ ├── RedactorDomChanged.ts │ │ │ └── index.ts │ │ ├── flipper.ts │ │ ├── i18n/ │ │ │ ├── index.ts │ │ │ ├── locales/ │ │ │ │ └── en/ │ │ │ │ └── messages.json │ │ │ └── namespace-internal.ts │ │ ├── inline-tools/ │ │ │ ├── inline-tool-bold.ts │ │ │ ├── inline-tool-convert.ts │ │ │ ├── inline-tool-italic.ts │ │ │ └── inline-tool-link.ts │ │ ├── modules/ │ │ │ ├── api/ │ │ │ │ ├── blocks.ts │ │ │ │ ├── caret.ts │ │ │ │ ├── events.ts │ │ │ │ ├── i18n.ts │ │ │ │ ├── index.ts │ │ │ │ ├── inlineToolbar.ts │ │ │ │ ├── listeners.ts │ │ │ │ ├── notifier.ts │ │ │ │ ├── readonly.ts │ │ │ │ ├── sanitizer.ts │ │ │ │ ├── saver.ts │ │ │ │ ├── selection.ts │ │ │ │ ├── styles.ts │ │ │ │ ├── toolbar.ts │ │ │ │ ├── tools.ts │ │ │ │ ├── tooltip.ts │ │ │ │ └── ui.ts │ │ │ ├── blockEvents.ts │ │ │ ├── blockManager.ts │ │ │ ├── blockSelection.ts │ │ │ ├── caret.ts │ │ │ ├── crossBlockSelection.ts │ │ │ ├── dragNDrop.ts │ │ │ ├── index.ts │ │ │ ├── modificationsObserver.ts │ │ │ ├── paste.ts │ │ │ ├── readonly.ts │ │ │ ├── rectangleSelection.ts │ │ │ ├── renderer.ts │ │ │ ├── saver.ts │ │ │ ├── toolbar/ │ │ │ │ ├── blockSettings.ts │ │ │ │ ├── index.ts │ │ │ │ └── inline.ts │ │ │ ├── tools.ts │ │ │ └── ui.ts │ │ ├── polyfills.ts │ │ ├── selection.ts │ │ ├── tools/ │ │ │ ├── base.ts │ │ │ ├── block.ts │ │ │ ├── collection.ts │ │ │ ├── factory.ts │ │ │ ├── inline.ts │ │ │ └── tune.ts │ │ ├── ui/ │ │ │ └── toolbox.ts │ │ ├── utils/ │ │ │ ├── api.ts │ │ │ ├── bem.ts │ │ │ ├── blocks.ts │ │ │ ├── caret.ts │ │ │ ├── events.ts │ │ │ ├── keyboard.ts │ │ │ ├── listeners.ts │ │ │ ├── mutations.ts │ │ │ ├── notifier.ts │ │ │ ├── popover/ │ │ │ │ ├── components/ │ │ │ │ │ ├── hint/ │ │ │ │ │ │ ├── hint.const.ts │ │ │ │ │ │ ├── hint.css │ │ │ │ │ │ ├── hint.ts │ │ │ │ │ │ └── index.ts │ │ │ │ │ ├── popover-header/ │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ ├── popover-header.const.ts │ │ │ │ │ │ ├── popover-header.ts │ │ │ │ │ │ └── popover-header.types.ts │ │ │ │ │ ├── popover-item/ │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ ├── popover-item-default/ │ │ │ │ │ │ │ ├── popover-item-default.const.ts │ │ │ │ │ │ │ └── popover-item-default.ts │ │ │ │ │ │ ├── popover-item-html/ │ │ │ │ │ │ │ ├── popover-item-html.const.ts │ │ │ │ │ │ │ └── popover-item-html.ts │ │ │ │ │ │ ├── popover-item-separator/ │ │ │ │ │ │ │ ├── popover-item-separator.const.ts │ │ │ │ │ │ │ └── popover-item-separator.ts │ │ │ │ │ │ └── popover-item.ts │ │ │ │ │ └── search-input/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── search-input.const.ts │ │ │ │ │ ├── search-input.ts │ │ │ │ │ └── search-input.types.ts │ │ │ │ ├── index.ts │ │ │ │ ├── popover-abstract.ts │ │ │ │ ├── popover-desktop.ts │ │ │ │ ├── popover-inline.ts │ │ │ │ ├── popover-mobile.ts │ │ │ │ ├── popover.const.ts │ │ │ │ └── utils/ │ │ │ │ └── popover-states-history.ts │ │ │ ├── promise-queue.ts │ │ │ ├── resolve-aliases.ts │ │ │ ├── sanitizer.ts │ │ │ ├── scroll-locker.ts │ │ │ ├── shortcuts.ts │ │ │ ├── tools.ts │ │ │ └── tooltip.ts │ │ └── utils.ts │ ├── env.d.ts │ ├── styles/ │ │ ├── animations.css │ │ ├── block.css │ │ ├── export.css │ │ ├── inline-toolbar.css │ │ ├── input.css │ │ ├── main.css │ │ ├── placeholders.css │ │ ├── popover-inline.css │ │ ├── popover.css │ │ ├── rtl.css │ │ ├── stub.css │ │ ├── toolbar.css │ │ ├── toolbox.css │ │ ├── ui.css │ │ └── variables.css │ ├── tools/ │ │ └── stub/ │ │ └── index.ts │ └── types-internal/ │ ├── editor-modules.d.ts │ ├── html-janitor.d.ts │ ├── i18n-internal-namespace.d.ts │ └── module-config.d.ts ├── test/ │ ├── cypress/ │ │ ├── .eslintrc │ │ ├── fixtures/ │ │ │ ├── test.html │ │ │ ├── tools/ │ │ │ │ ├── ContentlessTool.ts │ │ │ │ ├── SimpleHeader.ts │ │ │ │ ├── ToolMock.ts │ │ │ │ └── ToolWithoutConversionExport.ts │ │ │ └── types/ │ │ │ └── PartialBlockMutationEvent.ts │ │ ├── support/ │ │ │ ├── commands.ts │ │ │ ├── e2e.ts │ │ │ ├── index.d.ts │ │ │ ├── index.ts │ │ │ └── utils/ │ │ │ ├── createEditorWithTextBlocks.ts │ │ │ ├── createParagraphMock.ts │ │ │ └── nestedEditorInstance.ts │ │ ├── tests/ │ │ │ ├── api/ │ │ │ │ ├── block.cy.ts │ │ │ │ ├── blocks.cy.ts │ │ │ │ ├── caret.cy.ts │ │ │ │ ├── toolbar.cy.ts │ │ │ │ ├── tools.cy.ts │ │ │ │ └── tunes.cy.ts │ │ │ ├── block-ids.cy.ts │ │ │ ├── copy-paste.cy.ts │ │ │ ├── i18n.cy.ts │ │ │ ├── initialization.cy.ts │ │ │ ├── inline-tools/ │ │ │ │ └── link.cy.ts │ │ │ ├── modules/ │ │ │ │ ├── BlockEvents/ │ │ │ │ │ ├── ArrowLeft.cy.ts │ │ │ │ │ ├── ArrowRight.cy.ts │ │ │ │ │ ├── Backspace.cy.ts │ │ │ │ │ ├── Delete.cy.ts │ │ │ │ │ ├── Enter.cy.ts │ │ │ │ │ ├── Slash.cy.ts │ │ │ │ │ └── Tab.cy.ts │ │ │ │ ├── InlineToolbar.cy.ts │ │ │ │ ├── Renderer.cy.ts │ │ │ │ ├── Saver.cy.ts │ │ │ │ ├── Tools.cy.ts │ │ │ │ └── Ui.cy.ts │ │ │ ├── onchange.cy.ts │ │ │ ├── readOnly.cy.ts │ │ │ ├── sanitisation.cy.ts │ │ │ ├── selection.cy.ts │ │ │ ├── tools/ │ │ │ │ ├── BlockTool.cy.ts │ │ │ │ ├── BlockTune.cy.ts │ │ │ │ ├── InlineTool.cy.ts │ │ │ │ ├── ToolsCollection.cy.ts │ │ │ │ └── ToolsFactory.cy.ts │ │ │ ├── ui/ │ │ │ │ ├── BlockTunes.cy.ts │ │ │ │ ├── DataEmpty.cy.ts │ │ │ │ ├── InlineToolbar.cy.ts │ │ │ │ ├── Placeholders.cy.ts │ │ │ │ └── toolbox.cy.ts │ │ │ ├── utils/ │ │ │ │ ├── flipper.cy.ts │ │ │ │ └── popover.cy.ts │ │ │ └── utils.cy.ts │ │ └── tsconfig.json │ └── testcases.md ├── tsconfig.build.json ├── tsconfig.json ├── tslint.json ├── types/ │ ├── api/ │ │ ├── block.d.ts │ │ ├── blocks.d.ts │ │ ├── caret.d.ts │ │ ├── events.d.ts │ │ ├── i18n.d.ts │ │ ├── index.d.ts │ │ ├── inline-toolbar.d.ts │ │ ├── listeners.d.ts │ │ ├── notifier.d.ts │ │ ├── readonly.d.ts │ │ ├── sanitizer.d.ts │ │ ├── saver.d.ts │ │ ├── selection.d.ts │ │ ├── styles.d.ts │ │ ├── toolbar.d.ts │ │ ├── tools.d.ts │ │ ├── tooltip.d.ts │ │ └── ui.d.ts │ ├── block-tunes/ │ │ ├── block-tune-data.d.ts │ │ ├── block-tune.d.ts │ │ └── index.d.ts │ ├── configs/ │ │ ├── conversion-config.ts │ │ ├── editor-config.d.ts │ │ ├── i18n-config.d.ts │ │ ├── i18n-dictionary.d.ts │ │ ├── index.d.ts │ │ ├── log-levels.d.ts │ │ ├── paste-config.d.ts │ │ └── sanitizer-config.d.ts │ ├── data-formats/ │ │ ├── block-data.d.ts │ │ ├── block-id.ts │ │ ├── index.d.ts │ │ └── output-data.d.ts │ ├── events/ │ │ └── block/ │ │ ├── Base.ts │ │ ├── BlockAdded.ts │ │ ├── BlockChanged.ts │ │ ├── BlockMoved.ts │ │ ├── BlockRemoved.ts │ │ └── index.ts │ ├── index.d.ts │ ├── tools/ │ │ ├── adapters/ │ │ │ ├── base-tool-adapter.d.ts │ │ │ ├── block-tool-adapter.d.ts │ │ │ ├── block-tune-adapter.d.ts │ │ │ ├── inline-tool-adapter.d.ts │ │ │ ├── tool-factory.d.ts │ │ │ ├── tool-type.ts │ │ │ └── tools-collection.d.ts │ │ ├── block-tool-data.d.ts │ │ ├── block-tool.d.ts │ │ ├── hook-events.d.ts │ │ ├── index.d.ts │ │ ├── inline-tool.d.ts │ │ ├── menu-config.d.ts │ │ ├── paste-events.d.ts │ │ ├── tool-config.d.ts │ │ ├── tool-settings.d.ts │ │ └── tool.d.ts │ └── utils/ │ └── popover/ │ ├── hint.d.ts │ ├── index.d.ts │ ├── popover-event.ts │ ├── popover-item-type.ts │ ├── popover-item.d.ts │ └── popover.d.ts ├── vite.config.js └── vite.config.test.js
SYMBOL INDEX (1269 symbols across 205 files)
FILE: cypress.config.ts
method setupNodeEvents (line 16) | setupNodeEvents(on, config) {
FILE: public/assets/json-preview.js
function encodeHTMLEntities (line 23) | function encodeHTMLEntities(string) {
function stylize (line 30) | function stylize(string) {
FILE: src/codex.ts
class EditorJS (line 24) | class EditorJS {
method version (line 37) | public static get version(): string {
method constructor (line 44) | constructor(configuration?: EditorConfig|string) {
method exportAPI (line 83) | public exportAPI(editor: Core): void {
FILE: src/components/__module.ts
type ModuleNodes (line 12) | type ModuleNodes = object;
class Module (line 22) | class Module<T extends ModuleNodes = Record<string, HTMLElement>> {
method constructor (line 99) | constructor({ config, eventsDispatcher }: ModuleConfig) {
method state (line 113) | public set state(Editor: EditorModules) {
method removeAllNodes (line 120) | public removeAllNodes(): void {
method isRtl (line 133) | protected get isRtl(): boolean {
FILE: src/components/block-tunes/block-tune-delete.ts
class DeleteTune (line 13) | class DeleteTune implements BlockTune {
method constructor (line 31) | constructor({ api }) {
method render (line 38) | public render(): MenuConfig {
method handleClick (line 53) | public handleClick(): void {
FILE: src/components/block-tunes/block-tune-move-down.ts
class MoveDownTune (line 15) | class MoveDownTune implements BlockTune {
method constructor (line 40) | constructor({ api }) {
method render (line 47) | public render(): TunesMenuConfig {
method handleClick (line 59) | public handleClick(): void {
FILE: src/components/block-tunes/block-tune-move-up.ts
class MoveUpTune (line 13) | class MoveUpTune implements BlockTune {
method constructor (line 38) | constructor({ api }) {
method render (line 45) | public render(): TunesMenuConfig {
method handleClick (line 57) | public handleClick(): void {
FILE: src/components/block/api.ts
function BlockAPI (line 12) | function BlockAPI(
FILE: src/components/block/index.ts
type BlockConstructorOptions (line 35) | interface BlockConstructorOptions {
type BlockToolAPI (line 77) | enum BlockToolAPI {
type BlockEvents (line 95) | interface BlockEvents {
class Block (line 105) | class Block extends EventsDispatcher<BlockEvents> {
method CSS (line 111) | public static get CSS(): { [name: string]: string } {
method constructor (line 218) | constructor({
method inputs (line 271) | public get inputs(): HTMLElement[] {
method currentInput (line 300) | public get currentInput(): HTMLElement | undefined {
method currentInput (line 309) | public set currentInput(element: HTMLElement) {
method firstInput (line 321) | public get firstInput(): HTMLElement | undefined {
method lastInput (line 329) | public get lastInput(): HTMLElement | undefined {
method nextInput (line 339) | public get nextInput(): HTMLElement | undefined {
method previousInput (line 347) | public get previousInput(): HTMLElement | undefined {
method data (line 356) | public get data(): Promise<BlockToolData> {
method sanitize (line 371) | public get sanitize(): SanitizerConfig {
method mergeable (line 381) | public get mergeable(): boolean {
method focusable (line 388) | public get focusable(): boolean {
method isEmpty (line 397) | public get isEmpty(): boolean {
method hasMedia (line 409) | public get hasMedia(): boolean {
method selected (line 435) | public set selected(state: boolean) {
method selected (line 459) | public get selected(): boolean {
method stretched (line 468) | public set stretched(state: boolean) {
method stretched (line 477) | public get stretched(): boolean {
method dropTarget (line 486) | public set dropTarget(state) {
method pluginsContent (line 495) | public get pluginsContent(): HTMLElement {
method call (line 507) | public call(methodName: string, params?: object): void {
method mergeWith (line 534) | public async mergeWith(data: BlockToolData): Promise<void> {
method save (line 544) | public async save(): Promise<undefined | SavedData> {
method validate (line 594) | public async validate(data: BlockToolData): Promise<boolean> {
method getTunes (line 608) | public getTunes(): {
method updateCurrentInput (line 658) | public updateCurrentInput(): void {
method dispatchChange (line 674) | public dispatchChange(): void {
method destroy (line 681) | public destroy(): void {
method getActiveToolboxEntry (line 696) | public async getActiveToolboxEntry(): Promise<ToolboxConfigEntry | und...
method exportDataAsString (line 734) | public async exportDataAsString(): Promise<string> {
method compose (line 745) | private compose(): HTMLDivElement {
method composeTunes (line 800) | private composeTunes(tunesData: { [name: string]: BlockTuneData }): vo...
method addInputEvents (line 835) | private addInputEvents(): void {
method removeInputEvents (line 851) | private removeInputEvents(): void {
method watchBlockMutations (line 958) | private watchBlockMutations(): void {
method unwatchBlockMutations (line 980) | private unwatchBlockMutations(): void {
method detectToolRootChange (line 990) | private detectToolRootChange(mutations: MutationRecord[]): void {
method dropInputsCache (line 1005) | private dropInputsCache(): void {
method toggleInputsEmptyMark (line 1012) | private toggleInputsEmptyMark(): void {
FILE: src/components/blocks.ts
class Blocks (line 13) | class Blocks {
method constructor (line 28) | constructor(workingArea: HTMLElement) {
method length (line 38) | public get length(): number {
method array (line 47) | public get array(): Block[] {
method nodes (line 56) | public get nodes(): HTMLElement[] {
method set (line 70) | public static set(instance: Blocks, property: PropertyKey, value: Bloc...
method get (line 98) | public static get(instance: Blocks, property: PropertyKey): Block | un...
method push (line 117) | public push(block: Block): void {
method swap (line 129) | public swap(first: number, second: number): void {
method move (line 150) | public move(toIndex: number, fromIndex: number): void {
method insert (line 189) | public insert(index: number, block: Block, replace = false): void {
method replace (line 230) | public replace(index: number, block: Block): void {
method insertMany (line 248) | public insertMany(blocks: Block[], index: number ): void {
method remove (line 285) | public remove(index: number): void {
method removeAll (line 300) | public removeAll(): void {
method insertAfter (line 315) | public insertAfter(targetBlock: Block, newBlock: Block): void {
method get (line 327) | public get(index: number): Block | undefined {
method indexOf (line 337) | public indexOf(block: Block): number {
method insertToDOM (line 348) | private insertToDOM(block: Block, position?: InsertPosition, target?: ...
method composeBlockEvent (line 364) | private composeBlockEvent(type: string, detail: object): MoveEvent {
FILE: src/components/core.ts
class Core (line 14) | class Core {
method constructor (line 38) | constructor(config?: EditorConfig|string) {
method configuration (line 85) | public set configuration(config: EditorConfig|string) {
method configuration (line 196) | public get configuration(): EditorConfig {
method validate (line 203) | public validate(): void {
method init (line 227) | public init(): void {
method start (line 246) | public async start(): Promise<void> {
method render (line 283) | private render(): Promise<void> {
method constructModules (line 290) | private constructModules(): void {
method configureModules (line 308) | private configureModules(): void {
method getModulesDiff (line 324) | private getModulesDiff(name: string): EditorModules {
FILE: src/components/dom.ts
class Dom (line 8) | class Dom {
method isSingleTag (line 15) | public static isSingleTag(tag: HTMLElement): boolean {
method isLineBreakTag (line 42) | public static isLineBreakTag(element: HTMLElement): element is HTMLBRE...
method make (line 57) | public static make(tagName: string, classNames: string | (string | und...
method text (line 83) | public static text(content: string): Text {
method append (line 93) | public static append(
method prepend (line 110) | public static prepend(parent: Element, elements: Element | Element[]):...
method swap (line 126) | public static swap(el1: HTMLElement, el2: HTMLElement): void {
method find (line 152) | public static find(el: Element | Document = document, selector: string...
method get (line 162) | public static get(id: string): HTMLElement | null {
method findAll (line 175) | public static findAll(el: Element | Document = document, selector: str...
method allInputsSelector (line 182) | public static get allInputsSelector(): string {
method findAllInputs (line 194) | public static findAllInputs(holder: Element): HTMLElement[] {
method getDeepestNode (line 219) | public static getDeepestNode(node: Node, atLast = false): Node | null {
method isElement (line 272) | public static isElement(node: any): node is Element {
method isFragment (line 287) | public static isFragment(node: any): node is DocumentFragment {
method isContentEditable (line 301) | public static isContentEditable(element: HTMLElement): boolean {
method isNativeInput (line 312) | public static isNativeInput(target: any): target is HTMLInputElement |...
method canSetCaret (line 327) | public static canSetCaret(target: HTMLElement): boolean {
method isNodeEmpty (line 359) | public static isNodeEmpty(node: Node, ignoreChars?: string): boolean {
method isLeaf (line 385) | public static isLeaf(node: Node): boolean {
method isEmpty (line 402) | public static isEmpty(node: Node, ignoreChars?: string): boolean {
method isHTMLString (line 430) | public static isHTMLString(str: string): boolean {
method getContentLength (line 444) | public static getContentLength(node: Node): number {
method blockElements (line 461) | public static get blockElements(): string[] {
method containsOnlyInlineElements (line 511) | public static containsOnlyInlineElements(data: string | HTMLElement): ...
method getDeepestBlockElements (line 535) | public static getDeepestBlockElements(parent: HTMLElement): HTMLElemen...
method getHolder (line 551) | public static getHolder(element: string | HTMLElement): HTMLElement {
method isAnchor (line 565) | public static isAnchor(element: Element): element is HTMLAnchorElement {
method getClosestAnchor (line 575) | public static getClosestAnchor(element: Element): HTMLAnchorElement | ...
method offset (line 585) | public static offset(el): { top: number; left: number; right: number; ...
method getNodeByOffset (line 608) | public static getNodeByOffset(root: Node, totalOffset: number): {node:...
function isCollapsedWhitespaces (line 689) | function isCollapsedWhitespaces(textContent: string): boolean {
function calculateBaseline (line 717) | function calculateBaseline(element: Element): number {
function toggleEmptyMark (line 751) | function toggleEmptyMark(element: HTMLElement): void {
FILE: src/components/domIterator.ts
class DomIterator (line 9) | class DomIterator {
method constructor (line 42) | constructor(
method currentItem (line 55) | public get currentItem(): HTMLElement {
method setCursor (line 68) | public setCursor(cursorPosition: number): void {
method setItems (line 81) | public setItems(nodeList: HTMLElement[]): void {
method next (line 88) | public next(): void {
method previous (line 95) | public previous(): void {
method dropCursor (line 102) | public dropCursor(): void {
method leafNodesAndReturnIndex (line 117) | private leafNodesAndReturnIndex(direction: string): number {
FILE: src/components/errors/critical.ts
class CriticalError (line 4) | class CriticalError extends Error {
FILE: src/components/events/BlockChanged.ts
type BlockChangedPayload (line 11) | interface BlockChangedPayload {
FILE: src/components/events/BlockHovered.ts
type BlockHoveredPayload (line 11) | interface BlockHoveredPayload {
FILE: src/components/events/EditorMobileLayoutToggled.ts
type EditorMobileLayoutToggledPayload (line 9) | interface EditorMobileLayoutToggledPayload {
FILE: src/components/events/FakeCursorAboutToBeToggled.ts
type FakeCursorAboutToBeToggledPayload (line 11) | interface FakeCursorAboutToBeToggledPayload {
FILE: src/components/events/FakeCursorHaveBeenSet.ts
type FakeCursorHaveBeenSetPayload (line 11) | interface FakeCursorHaveBeenSetPayload {
FILE: src/components/events/RedactorDomChanged.ts
type RedactorDomChangedPayload (line 9) | interface RedactorDomChangedPayload {
FILE: src/components/events/index.ts
type EditorEventMap (line 27) | interface EditorEventMap {
FILE: src/components/flipper.ts
type FlipperOptions (line 9) | interface FlipperOptions {
class Flipper (line 42) | class Flipper {
method isActivated (line 46) | public get isActivated(): boolean {
method constructor (line 78) | constructor(options: FlipperOptions) {
method usedKeys (line 90) | public static get usedKeys(): number[] {
method activate (line 107) | public activate(items?: HTMLElement[], cursorPosition?: number): void {
method deactivate (line 132) | public deactivate(): void {
method focusFirst (line 142) | public focusFirst(): void {
method flipLeft (line 150) | public flipLeft(): void {
method flipRight (line 158) | public flipRight(): void {
method hasFocus (line 166) | public hasFocus(): boolean {
method onFlip (line 175) | public onFlip(cb: () => void): void {
method removeOnFlip (line 184) | public removeOnFlip(cb: () => void): void {
method dropCursor (line 193) | private dropCursor(): void {
method isEventReadyForHandling (line 252) | private isEventReadyForHandling(event: KeyboardEvent): boolean {
method handleTabPress (line 261) | private handleTabPress(event: KeyboardEvent): void {
method handleEnterPress (line 281) | private handleEnterPress(event: KeyboardEvent): void {
method flipCallback (line 303) | private flipCallback(): void {
FILE: src/components/i18n/index.ts
type DictKeys (line 8) | type DictKeys = LeavesDictKeys<typeof defaultDictionary>;
class I18n (line 13) | class I18n {
method ui (line 27) | public static ui(internalNamespace: string, dictKey: DictKeys): string {
method t (line 38) | public static t(namespace: string, dictKey: string): string {
method setDictionary (line 47) | public static setDictionary(dictionary: I18nDictionary): void {
method _t (line 58) | private static _t(namespace: string, dictKey: string): string {
method getNamespace (line 80) | private static getNamespace(namespace: string): Dictionary {
FILE: src/components/i18n/namespace-internal.ts
function getNamespaces (line 11) | function getNamespaces(dict: object, keyPath?: string): DictNamespaces<t...
FILE: src/components/inline-tools/inline-tool-bold.ts
class BoldInlineTool (line 12) | class BoldInlineTool implements InlineTool {
method sanitize (line 31) | public static get sanitize(): SanitizerConfig {
method render (line 45) | public render(): MenuConfig {
method shortcut (line 61) | public get shortcut(): string {
FILE: src/components/inline-tools/inline-tool-convert.ts
class ConvertInlineTool (line 14) | class ConvertInlineTool implements InlineTool {
method constructor (line 48) | constructor({ api }: { api: API }) {
method render (line 59) | public async render(): Promise<MenuConfig> {
FILE: src/components/inline-tools/inline-tool-italic.ts
class ItalicInlineTool (line 11) | class ItalicInlineTool implements InlineTool {
method sanitize (line 30) | public static get sanitize(): SanitizerConfig {
method render (line 60) | public render(): HTMLElement {
method surround (line 72) | public surround(): void {
method checkState (line 79) | public checkState(): boolean {
method shortcut (line 90) | public get shortcut(): string {
FILE: src/components/inline-tools/inline-tool-link.ts
class LinkInlineTool (line 14) | class LinkInlineTool implements InlineTool {
method sanitize (line 33) | public static get sanitize(): SanitizerConfig {
method constructor (line 110) | constructor({ api }: { api: API }) {
method render (line 121) | public render(): HTMLElement {
method renderActions (line 134) | public renderActions(): HTMLElement {
method surround (line 153) | public surround(range: Range): void {
method checkState (line 201) | public checkState(): boolean {
method clear (line 230) | public clear(): void {
method shortcut (line 237) | public get shortcut(): string {
method toggleActions (line 244) | private toggleActions(): void {
method openActions (line 255) | private openActions(needFocus = false): void {
method closeActions (line 269) | private closeActions(clearSavedSelection = true): void {
method enterPressed (line 296) | private enterPressed(event: KeyboardEvent): void {
method validateURL (line 342) | private validateURL(str: string): boolean {
method prepareLink (line 356) | private prepareLink(link: string): string {
method addProtocol (line 368) | private addProtocol(link: string): string {
method insertLink (line 398) | private insertLink(link: string): void {
method unlink (line 414) | private unlink(): void {
FILE: src/components/modules/api/blocks.ts
class BlocksAPI (line 14) | class BlocksAPI extends Module {
method methods (line 20) | public get methods(): Blocks {
method getBlocksCount (line 49) | public getBlocksCount(): number {
method getCurrentBlockIndex (line 58) | public getCurrentBlockIndex(): number {
method getBlockIndex (line 67) | public getBlockIndex(id: string): number | undefined {
method getBlockByIndex (line 84) | public getBlockByIndex(index: number): BlockAPIInterface | undefined {
method getById (line 101) | public getById(id: string): BlockAPIInterface | null {
method getBlockByElement (line 118) | public getBlockByElement(element: HTMLElement): BlockAPIInterface | un...
method swap (line 137) | public swap(fromIndex: number, toIndex: number): void {
method move (line 153) | public move(toIndex: number, fromIndex?: number): void {
method delete (line 162) | public delete(blockIndex: number = this.Editor.BlockManager.currentBlo...
method clear (line 194) | public async clear(): Promise<void> {
method render (line 204) | public async render(data: OutputData): Promise<void> {
method renderFromHTML (line 227) | public async renderFromHTML(data: string): Promise<void> {
method stretchBlock (line 240) | public stretchBlock(index: number, status = true): void {
method insertNewBlock (line 314) | public insertNewBlock(): void {
method validateIndex (line 415) | private validateIndex(index: unknown): void {
FILE: src/components/modules/api/caret.ts
class CaretAPI (line 9) | class CaretAPI extends Module {
method methods (line 15) | public get methods(): Caret {
FILE: src/components/modules/api/events.ts
class EventsAPI (line 8) | class EventsAPI extends Module {
method methods (line 14) | public get methods(): Events {
method on (line 28) | public on(eventName, callback): void {
method emit (line 38) | public emit(eventName, data): void {
method off (line 48) | public off(eventName, callback): void {
FILE: src/components/modules/api/i18n.ts
class I18nAPI (line 9) | class I18nAPI extends Module {
method getNamespace (line 16) | private static getNamespace(toolName, isTune): string {
method methods (line 27) | public get methods(): I18n {
method getMethodsForTool (line 43) | public getMethodsForTool(toolName: string, isTune: boolean): I18n {
FILE: src/components/modules/api/index.ts
class API (line 14) | class API extends Module {
method methods (line 18) | public get methods(): APIInterfaces {
method getMethodsForTool (line 45) | public getMethodsForTool(toolName: string, isTune: boolean): APIInterf...
FILE: src/components/modules/api/inlineToolbar.ts
class InlineToolbarAPI (line 8) | class InlineToolbarAPI extends Module {
method methods (line 14) | public get methods(): InlineToolbar {
method open (line 24) | public open(): void {
method close (line 31) | public close(): void {
FILE: src/components/modules/api/listeners.ts
class ListenersAPI (line 8) | class ListenersAPI extends Module {
method methods (line 14) | public get methods(): Listeners {
method on (line 30) | public on(element: HTMLElement, eventType: string, handler: () => void...
method off (line 42) | public off(element: Element, eventType: string, handler: () => void, u...
method offById (line 51) | public offById(id: string): void {
FILE: src/components/modules/api/notifier.ts
class NotifierAPI (line 10) | class NotifierAPI extends Module {
method constructor (line 21) | constructor({ config, eventsDispatcher }: ModuleConfig) {
method methods (line 33) | public get methods(): INotifier {
method show (line 44) | public show(options: NotifierOptions | ConfirmNotifierOptions | Prompt...
FILE: src/components/modules/api/readonly.ts
class ReadOnlyAPI (line 8) | class ReadOnlyAPI extends Module {
method methods (line 12) | public get methods(): ReadOnly {
method toggle (line 30) | public toggle(state?: boolean): Promise<boolean> {
method isEnabled (line 37) | public get isEnabled(): boolean {
FILE: src/components/modules/api/sanitizer.ts
class SanitizerAPI (line 10) | class SanitizerAPI extends Module {
method methods (line 16) | public get methods(): ISanitizer {
method clean (line 29) | public clean(taintString: string, config: SanitizerConfig): string {
FILE: src/components/modules/api/saver.ts
class SaverAPI (line 10) | class SaverAPI extends Module {
method methods (line 16) | public get methods(): Saver {
method save (line 27) | public save(): Promise<OutputData> {
FILE: src/components/modules/api/selection.ts
class SelectionAPI (line 9) | class SelectionAPI extends Module {
method methods (line 20) | public get methods(): SelectionAPIInterface {
method findParentTag (line 38) | public findParentTag(tagName: string, className?: string): HTMLElement...
method expandToTag (line 47) | public expandToTag(node: HTMLElement): void {
FILE: src/components/modules/api/styles.ts
class StylesAPI (line 7) | class StylesAPI extends Module {
method classes (line 11) | public get classes(): Styles {
FILE: src/components/modules/api/toolbar.ts
class ToolbarAPI (line 8) | class ToolbarAPI extends Module {
method methods (line 14) | public get methods(): Toolbar {
method open (line 26) | public open(): void {
method close (line 33) | public close(): void {
method toggleBlockSettings (line 42) | public toggleBlockSettings(openingState?: boolean): void {
method toggleToolbox (line 66) | public toggleToolbox(openingState: boolean): void {
FILE: src/components/modules/api/tools.ts
class ToolsAPI (line 7) | class ToolsAPI extends Module {
method methods (line 11) | public get methods(): ToolsAPIInterface {
FILE: src/components/modules/api/tooltip.ts
class TooltipAPI (line 10) | class TooltipAPI extends Module {
method constructor (line 17) | constructor({ config, eventsDispatcher }: ModuleConfig) {
method methods (line 27) | public get methods(): ITooltip {
method show (line 48) | public show(element: HTMLElement, content: TooltipContent, options?: T...
method hide (line 55) | public hide(): void {
method onHover (line 66) | public onHover(element: HTMLElement, content: TooltipContent, options?...
FILE: src/components/modules/api/ui.ts
class UiAPI (line 7) | class UiAPI extends Module {
method methods (line 11) | public get methods(): Ui {
method editorNodes (line 23) | private get editorNodes(): UiNodes {
FILE: src/components/modules/blockEvents.ts
class BlockEvents (line 16) | class BlockEvents extends Module {
method keydown (line 22) | public keydown(event: KeyboardEvent): void {
method beforeKeydownProcessing (line 83) | public beforeKeydownProcessing(event: KeyboardEvent): void {
method keyup (line 119) | public keyup(event: KeyboardEvent): void {
method dragOver (line 138) | public dragOver(event: DragEvent): void {
method dragLeave (line 149) | public dragLeave(event: DragEvent): void {
method handleCommandC (line 161) | public handleCommandC(event: ClipboardEvent): void {
method handleCommandX (line 177) | public handleCommandX(event: ClipboardEvent): void {
method tabPressed (line 204) | private tabPressed(event: KeyboardEvent): void {
method commandSlashPressed (line 226) | private commandSlashPressed(): void {
method slashPressed (line 239) | private slashPressed(event: KeyboardEvent): void {
method enter (line 275) | private enter(event: KeyboardEvent): void {
method backspace (line 347) | private backspace(event: KeyboardEvent): void {
method delete (line 434) | private delete(event: KeyboardEvent): void {
method mergeBlocks (line 515) | private mergeBlocks(targetBlock: Block, blockToMerge: Block): void {
method arrowRightAndDown (line 536) | private arrowRightAndDown(event: KeyboardEvent): void {
method arrowLeftAndUp (line 597) | private arrowLeftAndUp(event: KeyboardEvent): void {
method needToolbarClosing (line 659) | private needToolbarClosing(event: KeyboardEvent): boolean {
method activateToolbox (line 682) | private activateToolbox(): void {
method activateBlockSettings (line 693) | private activateBlockSettings(): void {
FILE: src/components/modules/blockManager.ts
class BlockManager (line 30) | class BlockManager extends Module {
method currentBlockIndex (line 36) | public get currentBlockIndex(): number {
method currentBlockIndex (line 45) | public set currentBlockIndex(newIndex: number) {
method firstBlock (line 54) | public get firstBlock(): Block {
method lastBlock (line 63) | public get lastBlock(): Block {
method currentBlock (line 72) | public get currentBlock(): Block | undefined {
method currentBlock (line 81) | public set currentBlock(block: Block) {
method nextBlock (line 90) | public get nextBlock(): Block | null {
method nextContentfulBlock (line 105) | public get nextContentfulBlock(): Block {
method previousContentfulBlock (line 116) | public get previousContentfulBlock(): Block {
method previousBlock (line 127) | public get previousBlock(): Block | null {
method blocks (line 142) | public get blocks(): Block[] {
method isEditorEmpty (line 151) | public get isEditorEmpty(): boolean {
method prepare (line 174) | public prepare(): void {
method toggleReadOnly (line 213) | public toggleReadOnly(readOnlyEnabled: boolean): void {
method composeBlock (line 230) | public composeBlock({
method insert (line 268) | public insert({
method insertMany (line 332) | public insertMany(blocks: Block[], index = 0): void {
method update (line 348) | public async update(block: Block, data?: Partial<BlockToolData>, tunes...
method replace (line 380) | public replace(block: Block, newTool: string, data: BlockToolData): Bl...
method paste (line 398) | public paste(
method insertDefaultBlockAtIndex (line 435) | public insertDefaultBlockAtIndex(index: number, needToFocus = false): ...
method insertAtEnd (line 461) | public insertAtEnd(): Block {
method mergeBlocks (line 480) | public async mergeBlocks(targetBlock: Block, blockToMerge: Block): Pro...
method removeBlock (line 525) | public removeBlock(block: Block, addLastBlock = true): Promise<void> {
method removeSelectedBlocks (line 573) | public removeSelectedBlocks(): number | undefined {
method removeAllBlocks (line 596) | public removeAllBlocks(): void {
method split (line 613) | public split(): Block {
method getBlockByIndex (line 655) | public getBlockByIndex(index: number): Block | undefined {
method getBlockIndex (line 668) | public getBlockIndex(block: Block): number {
method getBlockById (line 678) | public getBlockById(id): Block | undefined {
method getBlock (line 687) | public getBlock(element: HTMLElement): Block | undefined {
method setCurrentBlockByChildNode (line 708) | public setCurrentBlockByChildNode(childNode: Node): Block | undefined {
method getBlockByChildNode (line 756) | public getBlockByChildNode(childNode: Node): Block | undefined {
method swap (line 780) | public swap(fromIndex, toIndex): void {
method move (line 794) | public move(toIndex, fromIndex = this.currentBlockIndex): void {
method convert (line 831) | public async convert(blockToConvert: Block, targetToolName: string, bl...
method unsetCurrentBlock (line 883) | public unsetCurrentBlock(): void {
method clear (line 894) | public async clear(needToAddDefaultBlock = false): Promise<void> {
method destroy (line 924) | public async destroy(): Promise<void> {
method bindBlockEvents (line 935) | private bindBlockEvents(block: Block): void {
method disableModuleBindings (line 964) | private disableModuleBindings(): void {
method enableModuleBindings (line 971) | private enableModuleBindings(): void {
method validateIndex (line 990) | private validateIndex(index: number): boolean {
method blockDidMutated (line 1001) | private blockDidMutated<Type extends BlockMutationType>(mutationType: ...
type BlockMutationEventDetailWithoutTarget (line 1020) | type BlockMutationEventDetailWithoutTarget<Type extends BlockMutationTyp...
FILE: src/components/modules/blockSelection.ts
class BlockSelection (line 20) | class BlockSelection extends Module {
method sanitizerConfig (line 35) | private get sanitizerConfig(): SanitizerConfig {
method allBlocksSelected (line 67) | public get allBlocksSelected(): boolean {
method allBlocksSelected (line 78) | public set allBlocksSelected(state: boolean) {
method anyBlockSelected (line 93) | public get anyBlockSelected(): boolean {
method selectedBlocks (line 108) | public get selectedBlocks(): Block[] {
method prepare (line 148) | public prepare(): void {
method toggleReadOnly (line 193) | public toggleReadOnly(): void {
method unSelectBlockByIndex (line 205) | public unSelectBlockByIndex(index?): void {
method clearSelection (line 227) | public clearSelection(reason?: Event, restoreSelection = false): void {
method copySelectedBlocks (line 286) | public copySelectedBlocks(e: ClipboardEvent): Promise<void> {
method selectBlockByIndex (line 328) | public selectBlockByIndex(index: number): void {
method selectBlock (line 345) | public selectBlock(block: Block): void {
method unselectBlock (line 364) | public unselectBlock(block: Block): void {
method clearCache (line 373) | public clearCache(): void {
method destroy (line 381) | public destroy(): void {
method handleCommandA (line 392) | private handleCommandA(event: KeyboardEvent): void {
method selectAllBlocks (line 456) | private selectAllBlocks(): void {
FILE: src/components/modules/caret.ts
class Caret (line 13) | class Caret extends Module {
method positions (line 20) | public get positions(): {START: string; END: string; DEFAULT: string} {
method CSS (line 31) | private static get CSS(): {shadowCaret: string} {
method setToBlock (line 48) | public setToBlock(block: Block, position: string = this.positions.DEFA...
method setToInput (line 127) | public setToInput(input: HTMLElement, position: string = this.position...
method set (line 155) | public set(element: HTMLElement, offset = 0): void {
method setToTheLastBlock (line 174) | public setToTheLastBlock(): void {
method extractFragmentFromCaretPosition (line 197) | public extractFragmentFromCaretPosition(): void|DocumentFragment {
method navigateNext (line 242) | public navigateNext(force = false): boolean {
method navigatePrevious (line 308) | public navigatePrevious(force = false): boolean {
method createShadow (line 347) | public createShadow(element: Element): void {
method restoreCaret (line 359) | public restoreCaret(element: HTMLElement): void {
method insertContentAtCaretPosition (line 389) | public insertContentAtCaretPosition(content: string): void {
FILE: src/components/modules/crossBlockSelection.ts
class CrossBlockSelection (line 9) | class CrossBlockSelection extends Module {
method prepare (line 25) | public async prepare(): Promise<void> {
method watchSelection (line 36) | public watchSelection(event: MouseEvent): void {
method isCrossBlockSelectionStarted (line 54) | public get isCrossBlockSelectionStarted(): boolean {
method toggleBlockSelectedState (line 64) | public toggleBlockSelectedState(next = true): void {
method clear (line 110) | public clear(reason?: Event): void {
method enableCrossBlockSelection (line 144) | private enableCrossBlockSelection(event: MouseEvent): void {
method toggleBlocksSelectedState (line 235) | private toggleBlocksSelectedState(firstBlock: Block, lastBlock: Block)...
FILE: src/components/modules/dragNDrop.ts
class DragNDrop (line 7) | class DragNDrop extends Module {
method toggleReadOnly (line 27) | public toggleReadOnly(readOnlyEnabled: boolean): void {
method enableModuleBindings (line 38) | private enableModuleBindings(): void {
method disableModuleBindings (line 60) | private disableModuleBindings(): void {
method processDrop (line 69) | private async processDrop(dropEvent: DragEvent): Promise<void> {
method processDragStart (line 108) | private processDragStart(): void {
method processDragOver (line 119) | private processDragOver(dragEvent: DragEvent): void {
FILE: src/components/modules/modificationsObserver.ts
type UniqueBlockMutationKey (line 12) | type UniqueBlockMutationKey = `block:${BlockId}:event:${BlockMutationTyp...
class ModificationsObserver (line 17) | class ModificationsObserver extends Module {
method constructor (line 52) | constructor({ config, eventsDispatcher }: ModuleConfig) {
method enable (line 81) | public enable(): void {
method disable (line 97) | public disable(): void {
method particularBlockChanged (line 107) | private particularBlockChanged(event: BlockMutationEvent): void {
method redactorChanged (line 143) | private redactorChanged(mutations: MutationRecord[]): void {
FILE: src/components/modules/paste.ts
type TagSubstitute (line 19) | interface TagSubstitute {
type PatternSubstitute (line 36) | interface PatternSubstitute {
type FilesSubstitution (line 56) | interface FilesSubstitution {
type PasteData (line 77) | interface PasteData {
class Paste (line 111) | class Paste extends Module {
method prepare (line 144) | public async prepare(): Promise<void> {
method toggleReadOnly (line 153) | public toggleReadOnly(readOnlyEnabled: boolean): void {
method processDataTransfer (line 167) | public async processDataTransfer(dataTransfer: DataTransfer, isDragNDr...
method processText (line 233) | public async processText(data: string, isHTML = false): Promise<void> {
method setCallback (line 266) | private setCallback(): void {
method unsetCallback (line 273) | private unsetCallback(): void {
method processTools (line 280) | private processTools(): void {
method collectTagNames (line 325) | private collectTagNames(tagOrSanitizeConfig: string | SanitizerConfig)...
method getTagsConfig (line 348) | private getTagsConfig(tool: BlockToolAdapter): void {
method getFilesConfig (line 393) | private getFilesConfig(tool: BlockToolAdapter): void {
method getPatternsConfig (line 438) | private getPatternsConfig(tool: BlockToolAdapter): void {
method isNativeBehaviour (line 470) | private isNativeBehaviour(element: EventTarget): boolean {
method processFiles (line 512) | private async processFiles(items: FileList): Promise<void> {
method processFile (line 539) | private async processFile(file: File): Promise<{ event: PasteEvent; ty...
method processHTML (line 579) | private processHTML(innerHTML: string): PasteData[] {
method processPlain (line 709) | private processPlain(plain: string): PasteData[] {
method processSingleBlock (line 744) | private async processSingleBlock(dataToInsert: PasteData): Promise<voi...
method processInlinePaste (line 772) | private async processInlinePaste(dataToInsert: PasteData): Promise<voi...
method processPattern (line 814) | private async processPattern(text: string): Promise<{ event: PasteEven...
method insertBlock (line 847) | private insertBlock(data: PasteData, canReplaceCurrentBlock = false): ...
method insertEditorJSData (line 870) | private insertEditorJSData(blocks: Pick<SavedData, 'id' | 'data' | 'to...
method processElementNode (line 902) | private processElementNode(node: Node, nodes: Node[], destNode: Node):...
method getNodes (line 945) | private getNodes(wrapper: Node): Node[] {
method composePasteEvent (line 1000) | private composePasteEvent(type: string, detail: PasteEventDetail): Pas...
FILE: src/components/modules/readonly.ts
class ReadOnly (line 13) | class ReadOnly extends Module {
method isEnabled (line 29) | public get isEnabled(): boolean {
method prepare (line 36) | public async prepare(): Promise<void> {
method toggle (line 65) | public async toggle(state = !this.readOnlyEnabled, isInitial = false):...
method throwCriticalError (line 123) | private throwCriticalError(): never {
FILE: src/components/modules/rectangleSelection.ts
class RectangleSelection (line 17) | class RectangleSelection extends Module {
method CSS (line 23) | public static get CSS(): {[name: string]: string} {
method prepare (line 108) | public prepare(): void {
method startSelection (line 118) | public startSelection(pageX, pageY): void {
method endSelection (line 157) | public endSelection(): void {
method isRectActivated (line 167) | public isRectActivated(): boolean {
method clearSelection (line 174) | public clearSelection(): void {
method enableModuleBindings (line 181) | private enableModuleBindings(): void {
method processMouseDown (line 216) | private processMouseDown(mouseEvent: MouseEvent): void {
method processMouseMove (line 237) | private processMouseMove(mouseEvent: MouseEvent): void {
method processMouseLeave (line 245) | private processMouseLeave(): void {
method processScroll (line 253) | private processScroll(mouseEvent: MouseEvent): void {
method processMouseUp (line 260) | private processMouseUp(): void {
method scrollByZones (line 270) | private scrollByZones(clientY): void {
method genHTML (line 296) | private genHTML(): {container: Element; overlay: Element} {
method scrollVertical (line 321) | private scrollVertical(speed): void {
method changingRectangle (line 339) | private changingRectangle(event: MouseEvent): void {
method shrinkRectangleToPoint (line 385) | private shrinkRectangleToPoint(): void {
method inverseSelection (line 395) | private inverseSelection(): void {
method updateRectangleSize (line 415) | private updateRectangleSize(): void {
method genInfoForMouseSelection (line 440) | private genInfoForMouseSelection(): {index: number; leftPos: number; r...
method addBlockInSelection (line 468) | private addBlockInSelection(index): void {
method trySelectNextBlock (line 480) | private trySelectNextBlock(index): void {
FILE: src/components/modules/renderer.ts
class Renderer (line 11) | class Renderer extends Module {
method render (line 17) | public async render(blocksData: OutputBlockData[]): Promise<void> {
method composeStubDataForTool (line 89) | private composeStubDataForTool(tool: string, data: BlockToolData, id?:...
FILE: src/components/modules/saver.ts
class Saver (line 23) | class Saver extends Module {
method save (line 29) | public async save(): Promise<OutputData> {
method getSavedData (line 56) | private async getSavedData(block: Block): Promise<ValidatedData> {
method makeOutput (line 72) | private makeOutput(allExtractedData): OutputData {
FILE: src/components/modules/toolbar/blockSettings.ts
type BlockSettingsNodes (line 21) | interface BlockSettingsNodes {
class BlockSettings (line 33) | class BlockSettings extends Module<BlockSettingsNodes> {
method events (line 37) | public get events(): { opened: string; closed: string } {
method CSS (line 47) | public get CSS(): { [name: string]: string } {
method flipper (line 63) | public get flipper(): Flipper | undefined {
method make (line 92) | public make(): void {
method destroy (line 106) | public destroy(): void {
method open (line 121) | public async open(targetBlock: Block = this.Editor.BlockManager.curren...
method getElement (line 164) | public getElement(): HTMLElement | undefined {
method getTunesItems (line 217) | private async getTunesItems(currentBlock: Block, commonTunes: MenuConf...
method resolveTuneAliases (line 283) | private resolveTuneAliases(item: MenuConfigItem): PopoverItemParams {
FILE: src/components/modules/toolbar/index.ts
type ToolbarNodes (line 36) | interface ToolbarNodes {
class Toolbar (line 95) | class Toolbar extends Module<ToolbarNodes> {
method constructor (line 113) | constructor({ config, eventsDispatcher }: ModuleConfig) {
method CSS (line 125) | public get CSS(): { [name: string]: string } {
method opened (line 147) | public get opened(): boolean {
method toolbox (line 154) | public get toolbox(): {
method blockActions (line 202) | private get blockActions(): { hide: () => void; show: () => void } {
method blockTunesToggler (line 216) | private get blockTunesToggler(): { hide: () => void; show: () => void } {
method toggleReadOnly (line 229) | public toggleReadOnly(readOnlyEnabled: boolean): void {
method moveAndOpen (line 247) | public moveAndOpen(block: Block = this.Editor.BlockManager.currentBloc...
method close (line 372) | public close(): void {
method reset (line 389) | private reset(): void {
method open (line 399) | private open(withBlockActions = true): void {
method make (line 412) | private async make(): Promise<void> {
method makeToolbox (line 500) | private makeToolbox(): Element {
method plusButtonClicked (line 545) | private plusButtonClicked(): void {
method enableModuleBindings (line 558) | private enableModuleBindings(): void {
method disableModuleBindings (line 606) | private disableModuleBindings(): void {
method settingsTogglerClicked (line 613) | private settingsTogglerClicked(): void {
method drawUI (line 638) | private drawUI(): void {
method destroy (line 654) | private destroy(): void {
FILE: src/components/modules/toolbar/inline.ts
type InlineToolbarNodes (line 20) | interface InlineToolbarNodes {
class InlineToolbar (line 31) | class InlineToolbar extends Module<InlineToolbarNodes> {
method constructor (line 65) | constructor({ config, eventsDispatcher }: ModuleConfig) {
method tryToShow (line 87) | public async tryToShow(needToClose = false): Promise<void> {
method close (line 104) | public close(): void {
method containsNode (line 139) | public containsNode(node: Node): boolean {
method destroy (line 150) | public destroy(): void {
method make (line 159) | private make(): void {
method open (line 178) | private async open(): Promise<void> {
method move (line 218) | private move(popoverWidth: number): void {
method reset (line 246) | private reset(): void {
method allowedToShow (line 254) | private allowedToShow(): boolean {
method getTools (line 324) | private getTools(): InlineToolAdapter[] {
method createToolsInstances (line 349) | private createToolsInstances(): void {
method getPopoverItems (line 364) | private async getPopoverItems(): Promise<PopoverItemParams[]> {
method getToolShortcut (line 495) | private getToolShortcut(toolName: string): string | undefined {
method enableShortcuts (line 524) | private enableShortcuts(toolName: string, shortcut: string): void {
method toolClicked (line 564) | private toolClicked(tool: IInlineTool): void {
method checkToolsState (line 574) | private checkToolsState(): void {
method inlineTools (line 584) | private get inlineTools(): { [name: string]: IInlineTool } {
FILE: src/components/modules/tools.ts
class Tools (line 28) | class Tools extends Module {
method available (line 40) | public get available(): ToolsCollection {
method unavailable (line 47) | public get unavailable(): ToolsCollection {
method inlineTools (line 54) | public get inlineTools(): ToolsCollection<InlineToolAdapter> {
method blockTools (line 61) | public get blockTools(): ToolsCollection<BlockToolAdapter> {
method blockTunes (line 70) | public get blockTunes(): ToolsCollection<BlockTuneAdapter> {
method defaultTool (line 77) | public get defaultTool(): BlockToolAdapter {
method internal (line 99) | public get internal(): ToolsCollection {
method prepare (line 108) | public async prepare(): Promise<void> {
method getAllInlineToolsSanitizeConfig (line 152) | public getAllInlineToolsSanitizeConfig(): SanitizerConfig {
method destroy (line 166) | public destroy(): void {
method internalTools (line 178) | private get internalTools(): { [toolName: string]: ToolConstructable |...
method toolPrepareMethodSuccess (line 225) | private toolPrepareMethodSuccess(data: { toolName: string }): void {
method toolPrepareMethodFallback (line 256) | private toolPrepareMethodFallback(data: { toolName: string }): void {
method getListOfPrepareFunctions (line 266) | private getListOfPrepareFunctions(config: {[name: string]: ToolSetting...
method prepareBlockTools (line 294) | private prepareBlockTools(): void {
method assignInlineToolsToBlockTool (line 306) | private assignInlineToolsToBlockTool(tool: BlockToolAdapter): void {
method assignBlockTunesToBlockTool (line 348) | private assignBlockTunesToBlockTool(tool: BlockToolAdapter): void {
method validateTools (line 379) | private validateTools(): void {
method prepareConfig (line 403) | private prepareConfig(): {[name: string]: ToolSettings} {
FILE: src/components/modules/ui.ts
type UINodes (line 23) | interface UINodes {
class UI (line 45) | class UI extends Module<UINodes> {
method CSS (line 51) | public get CSS(): {
method contentRect (line 70) | public get contentRect(): DOMRect {
method prepare (line 129) | public async prepare(): Promise<void> {
method toggleReadOnly (line 157) | public toggleReadOnly(readOnlyEnabled: boolean): void {
method checkEmptiness (line 185) | public checkEmptiness(): void {
method someToolbarOpened (line 197) | public get someToolbarOpened(): boolean {
method someFlipperButtonFocused (line 206) | public get someFlipperButtonFocused(): boolean {
method destroy (line 229) | public destroy(): void {
method closeAllToolbars (line 238) | public closeAllToolbars(): void {
method setIsMobile (line 258) | private setIsMobile(): void {
method make (line 276) | private make(): void {
method loadStyles (line 316) | private loadStyles(): void {
method bindReadOnlyInsensitiveListeners (line 356) | private bindReadOnlyInsensitiveListeners(): void {
method unbindReadOnlyInsensitiveListeners (line 377) | private unbindReadOnlyInsensitiveListeners(): void {
method bindReadOnlySensitiveListeners (line 388) | private bindReadOnlySensitiveListeners(): void {
method watchBlockHoveredEvents (line 417) | private watchBlockHoveredEvents(): void {
method unbindReadOnlySensitiveListeners (line 455) | private unbindReadOnlySensitiveListeners(): void {
method windowResize (line 462) | private windowResize(): void {
method documentKeydown (line 479) | private documentKeydown(event: KeyboardEvent): void {
method defaultBehaviour (line 505) | private defaultBehaviour(event: KeyboardEvent): void {
method backspacePressed (line 540) | private backspacePressed(event: KeyboardEvent): void {
method escapePressed (line 574) | private escapePressed(event): void {
method enterPressed (line 597) | private enterPressed(event: KeyboardEvent): void {
method documentClicked (line 659) | private documentClicked(event: MouseEvent): void {
method documentTouched (line 720) | private documentTouched(event: Event): void {
method redactorClicked (line 765) | private redactorClicked(event: MouseEvent): void {
method processBottomZoneClick (line 800) | private processBottomZoneClick(event: MouseEvent): void {
method selectionChanged (line 846) | private selectionChanged(): void {
method enableInputsEmptyMark (line 918) | private enableInputsEmptyMark(): void {
FILE: src/components/polyfills.ts
type Element (line 6) | interface Element {
type Element (line 97) | interface Element {
FILE: src/components/selection.ts
type TextRange (line 7) | interface TextRange {
type MSSelection (line 19) | interface MSSelection {
type Document (line 27) | interface Document {
class SelectionUtils (line 36) | class SelectionUtils {
method CSS (line 69) | public static get CSS(): { editorWrapper: string; editorZone: string } {
method anchorNode (line 82) | public static get anchorNode(): Node | null {
method anchorElement (line 93) | public static get anchorElement(): Element | null {
method anchorOffset (line 119) | public static get anchorOffset(): number | null {
method isCollapsed (line 130) | public static get isCollapsed(): boolean | null {
method isAtEditor (line 141) | public static get isAtEditor(): boolean {
method isSelectionAtEditor (line 150) | public static isSelectionAtEditor(selection: Selection): boolean {
method isRangeAtEditor (line 181) | public static isRangeAtEditor(range: Range): boolean {
method isSelectionExists (line 207) | public static get isSelectionExists(): boolean {
method range (line 218) | public static get range(): Range | null {
method getRangeFromSelection (line 227) | public static getRangeFromSelection(selection: Selection): Range | null {
method rect (line 236) | public static get rect(): DOMRect | ClientRect {
method text (line 309) | public static get text(): string {
method get (line 319) | public static get(): Selection | null {
method setCursor (line 329) | public static setCursor(element: HTMLElement, offset = 0): DOMRect {
method isRangeInsideContainer (line 359) | public static isRangeInsideContainer(container: HTMLElement): boolean {
method addFakeCursor (line 372) | public static addFakeCursor(): void {
method isFakeCursorInsideContainer (line 392) | public static isFakeCursorInsideContainer(el: HTMLElement): boolean {
method removeFakeCursor (line 401) | public static removeFakeCursor(container: HTMLElement = document.body)...
method removeFakeBackground (line 414) | public removeFakeBackground(): void {
method setFakeBackground (line 426) | public setFakeBackground(): void {
method save (line 435) | public save(): void {
method restore (line 442) | public restore(): void {
method clearSaved (line 456) | public clearSaved(): void {
method collapseToEnd (line 463) | public collapseToEnd(): void {
method findParentTag (line 481) | public findParentTag(tagName: string, className?: string, searchDepth ...
method expandToTag (line 554) | public expandToTag(element: HTMLElement): void {
FILE: src/components/tools/base.ts
type UserSettings (line 13) | enum UserSettings {
type CommonInternalSettings (line 39) | enum CommonInternalSettings {
type InternalBlockToolSettings (line 54) | enum InternalBlockToolSettings {
type InternalInlineToolSettings (line 80) | enum InternalInlineToolSettings {
type InternalTuneSettings (line 100) | enum InternalTuneSettings {
type ToolOptions (line 107) | type ToolOptions = Omit<ToolSettings, 'class'>;
type ConstructorOptions (line 109) | interface ConstructorOptions {
method constructor (line 167) | constructor({
method settings (line 188) | public get settings(): ToolOptions {
method reset (line 201) | public reset(): void | Promise<void> {
method prepare (line 210) | public prepare(): void | Promise<void> {
method shortcut (line 222) | public get shortcut(): string | undefined {
method sanitizeConfig (line 232) | public get sanitizeConfig(): SanitizerConfig {
method isInline (line 239) | public isInline(): this is InlineToolAdapterInterface {
method isBlock (line 246) | public isBlock(): this is BlockToolAdapterInterface {
method isTune (line 253) | public isTune(): this is BlockTuneAdapterInterface {
FILE: src/components/tools/block.ts
class BlockToolAdapter (line 21) | class BlockToolAdapter extends BaseToolAdapter<ToolType.Block, IBlockToo...
method create (line 49) | public create(data: BlockToolData, block: BlockAPI, readOnly: boolean)...
method isReadOnlySupported (line 63) | public get isReadOnlySupported(): boolean {
method isLineBreaksEnabled (line 70) | public get isLineBreaksEnabled(): boolean {
method toolbox (line 87) | public get toolbox(): ToolboxConfigEntry[] | undefined {
method conversionConfig (line 141) | public get conversionConfig(): ConversionConfig | undefined {
method enabledInlineTools (line 148) | public get enabledInlineTools(): boolean | string[] {
method enabledBlockTunes (line 155) | public get enabledBlockTunes(): boolean | string[] {
method pasteConfig (line 162) | public get pasteConfig(): PasteConfig {
method sanitizeConfig (line 170) | public get sanitizeConfig(): SanitizerConfig {
method baseSanitizeConfig (line 204) | public get baseSanitizeConfig(): SanitizerConfig {
FILE: src/components/tools/collection.ts
type ToolClass (line 7) | type ToolClass = BlockToolAdapter | InlineToolAdapter | BlockTuneAdapter;
class ToolsCollection (line 12) | class ToolsCollection<V extends ToolClass = ToolClass> extends Map<strin...
method blockTools (line 16) | public get blockTools(): ToolsCollection<BlockToolAdapter> {
method inlineTools (line 27) | public get inlineTools(): ToolsCollection<InlineToolAdapter> {
method blockTunes (line 38) | public get blockTunes(): ToolsCollection<BlockTuneAdapter> {
method internalTools (line 49) | public get internalTools(): ToolsCollection<V> {
method externalTools (line 60) | public get externalTools(): ToolsCollection<V> {
FILE: src/components/tools/factory.ts
type ToolConstructor (line 9) | type ToolConstructor = typeof InlineToolAdapter | typeof BlockToolAdapte...
class ToolsFactory (line 14) | class ToolsFactory {
method constructor (line 36) | constructor(
method get (line 51) | public get(name: string): InlineToolAdapter | BlockToolAdapter | Block...
method getConstructor (line 73) | private getConstructor(constructable: ToolConstructable): ToolConstruc...
FILE: src/components/tools/inline.ts
class InlineToolAdapter (line 9) | class InlineToolAdapter extends BaseToolAdapter<ToolType.Inline, IInline...
method title (line 23) | public get title(): string {
method create (line 30) | public create(): IInlineTool {
method isReadOnlySupported (line 42) | public get isReadOnlySupported(): boolean {
FILE: src/components/tools/tune.ts
class BlockTuneAdapter (line 12) | class BlockTuneAdapter extends BaseToolAdapter<ToolType.Tune, IBlockTune...
method create (line 29) | public create(data: BlockTuneData, block: BlockAPI): IBlockTune {
FILE: src/components/ui/toolbox.ts
type ToolboxEvent (line 24) | enum ToolboxEvent {
type ToolboxEventMap (line 46) | interface ToolboxEventMap {
type ToolboxTextLabelsKeys (line 57) | type ToolboxTextLabelsKeys = 'filter' | 'nothingFound';
class Toolbox (line 66) | class Toolbox extends EventsDispatcher<ToolboxEventMap> {
method isEmpty (line 72) | public get isEmpty(): boolean {
method CSS (line 119) | private static get CSS(): {
method constructor (line 134) | constructor({ api, tools, i18nLabels }: {api: API; tools: ToolsCollect...
method getElement (line 159) | public getElement(): HTMLElement | null {
method hasFocus (line 166) | public hasFocus(): boolean | undefined {
method destroy (line 177) | public destroy(): void {
method toolButtonActivated (line 196) | public toolButtonActivated(toolName: string, blockDataOverrides: Block...
method open (line 203) | public open(): void {
method close (line 216) | public close(): void {
method toggle (line 225) | public toggle(): void {
method initPopover (line 244) | private initPopover(): void {
method destroyPopover (line 264) | private destroyPopover(): void {
method toolsToBeDisplayed (line 289) | private get toolsToBeDisplayed(): BlockToolAdapter[] {
method toolboxItemsToBeDisplayed (line 307) | private get toolboxItemsToBeDisplayed(): PopoverItemParams[] {
method enableShortcuts (line 340) | private enableShortcuts(): void {
method enableShortcutForTool (line 356) | private enableShortcutForTool(toolName: string, shortcut: string): void {
method removeAllShortcuts (line 389) | private removeAllShortcuts(): void {
method insertNewBlock (line 406) | private async insertNewBlock(toolName: string, blockDataOverrides?: Bl...
FILE: src/components/utils.ts
type LogLevels (line 11) | enum LogLevels {
type ChainData (line 29) | interface ChainData {
function _log (line 82) | function _log(
function setLogLevel (line 163) | function setLogLevel(logLevel: LogLevels): void {
function typeOf (line 184) | function typeOf(object: any): string {
function isFunction (line 195) | function isFunction(fn: any): fn is (...args: any[]) => any {
function isObject (line 206) | function isObject(v: any): v is object {
function isString (line 217) | function isString(v: any): v is string {
function isBoolean (line 228) | function isBoolean(v: any): v is boolean {
function isNumber (line 239) | function isNumber(v: any): v is number {
function isUndefined (line 250) | function isUndefined(v: any): v is undefined {
function isClass (line 261) | function isClass(fn: any): boolean {
function isEmpty (line 271) | function isEmpty(object: object): boolean {
function isPromise (line 286) | function isPromise(object: any): object is Promise<any> {
function isPrintableKey (line 297) | function isPrintableKey(keyCode: number): boolean {
function sequence (line 317) | async function sequence(
function array (line 366) | function array(collection: ArrayLike<any>): any[] {
function delay (line 377) | function delay(method: (...args: any[]) => any, timeout: number) {
function getFileExtension (line 394) | function getFileExtension(file: File): string {
function isValidMimeType (line 404) | function isValidMimeType(type: string): boolean {
function debounce (line 419) | function debounce(func: (...args: unknown[]) => void, wait?: number, imm...
function throttle (line 454) | function throttle(func, wait, options: {leading?: boolean; trailing?: bo...
function copyTextToClipboard (line 512) | function copyTextToClipboard(text): void {
function getUserOS (line 534) | function getUserOS(): {[key: string]: boolean} {
function capitalize (line 559) | function capitalize(text: string): string {
function deepMerge (line 570) | function deepMerge<T extends object>(target, ...sources): T {
function beautifyShortcut (line 609) | function beautifyShortcut(shortcut: string): string {
function getValidUrl (line 641) | function getValidUrl(url: string): string {
function generateBlockId (line 662) | function generateBlockId(): string {
function openTab (line 673) | function openTab(url: string): void {
function generateId (line 683) | function generateId(prefix = ''): string {
function deprecationAssert (line 695) | function deprecationAssert(condition: boolean, oldProperty: string, newP...
function cacheable (line 710) | function cacheable<Target, Value, Arguments extends unknown[] = unknown[]>(
function isMobileScreen (line 761) | function isMobileScreen(): boolean {
function equals (line 782) | function equals(var1: unknown, var2: unknown): boolean {
FILE: src/components/utils/api.ts
function resolveBlock (line 11) | function resolveBlock(attribute: BlockAPI | BlockAPI['id'] | number, edi...
FILE: src/components/utils/bem.ts
constant ELEMENT_DELIMITER (line 1) | const ELEMENT_DELIMITER = '__';
constant MODIFIER_DELIMITER (line 2) | const MODIFIER_DELIMITER = '--';
function bem (line 13) | function bem(blockName: string) {
FILE: src/components/utils/blocks.ts
function isBlockConvertable (line 17) | function isBlockConvertable(block: Block, direction: 'export' | 'import'...
function isSameBlockData (line 38) | function isSameBlockData(data1: BlockToolData, data2: BlockToolData): bo...
function getConvertibleToolsForBlock (line 50) | async function getConvertibleToolsForBlock(block: BlockAPI, allBlockTool...
function areBlocksMergeable (line 123) | function areBlocksMergeable(targetBlock: Block, blockToMerge: Block): bo...
function convertBlockDataToString (line 152) | function convertBlockDataToString(blockData: BlockToolData, conversionCo...
function convertStringToBlockData (line 179) | function convertStringToBlockData(stringToImport: string, conversionConf...
FILE: src/components/utils/caret.ts
function getCaretNodeAndOffset (line 10) | function getCaretNodeAndOffset(): [ Node | null, number ] {
function checkContenteditableSliceForEmptiness (line 60) | function checkContenteditableSliceForEmptiness(contenteditable: HTMLElem...
function isCaretAtStartOfInput (line 114) | function isCaretAtStartOfInput(input: HTMLElement): boolean {
function isCaretAtEndOfInput (line 161) | function isCaretAtEndOfInput(input: HTMLElement): boolean {
FILE: src/components/utils/events.ts
type Listener (line 6) | type Listener<Data> = (data: Data) => void;
type Subscriptions (line 13) | type Subscriptions<EventMap> = {
class EventsDispatcher (line 23) | class EventsDispatcher<EventMap> {
method on (line 36) | public on<Name extends keyof EventMap>(eventName: Name, callback: List...
method once (line 51) | public once<Name extends keyof EventMap>(eventName: Name, callback: Li...
method emit (line 78) | public emit<Name extends keyof EventMap>(eventName: Name, data?: Event...
method off (line 96) | public off<Name extends keyof EventMap>(eventName: Name, callback: Lis...
method destroy (line 115) | public destroy(): void {
FILE: src/components/utils/keyboard.ts
type KeyboardLayoutMap (line 5) | interface KeyboardLayoutMap {
type Keyboard (line 21) | interface Keyboard {
type Navigator (line 25) | interface Navigator {
function getKeyboardKeyForCode (line 43) | async function getKeyboardKeyForCode(code: string, fallback: string): Pr...
FILE: src/components/utils/listeners.ts
type ListenerData (line 8) | interface ListenerData {
class Listeners (line 50) | class Listeners {
method on (line 66) | public on(
method off (line 101) | public off(
method offById (line 126) | public offById(id: string): void {
method findOne (line 144) | public findOne(element: EventTarget, eventType?: string, handler?: (ev...
method findAll (line 158) | public findAll(element: EventTarget, eventType?: string, handler?: (ev...
method removeAll (line 176) | public removeAll(): void {
method destroy (line 187) | public destroy(): void {
method findByEventTarget (line 197) | private findByEventTarget(element: EventTarget): ListenerData[] {
method findByType (line 211) | private findByType(eventType: string): ListenerData[] {
method findByHandler (line 225) | private findByHandler(handler: (event: Event) => void): ListenerData[] {
method findById (line 239) | private findById(id: string): ListenerData {
FILE: src/components/utils/mutations.ts
function isMutationBelongsToElement (line 7) | function isMutationBelongsToElement(mutationRecord: MutationRecord, elem...
FILE: src/components/utils/notifier.ts
class Notifier (line 12) | class Notifier {
method show (line 18) | public show(options: NotifierOptions | ConfirmNotifierOptions | Prompt...
FILE: src/components/utils/popover/components/hint/hint.ts
class Hint (line 10) | class Hint {
method constructor (line 25) | constructor(params: HintParams) {
method getElement (line 43) | public getElement(): HTMLElement {
FILE: src/components/utils/popover/components/popover-header/popover-header.ts
class PopoverHeader (line 10) | class PopoverHeader {
method constructor (line 40) | constructor({ text, onBackButtonClick }: PopoverHeaderParams) {
method getElement (line 60) | public getElement(): HTMLElement | null {
method destroy (line 67) | public destroy(): void {
FILE: src/components/utils/popover/components/popover-header/popover-header.types.ts
type PopoverHeaderParams (line 4) | interface PopoverHeaderParams {
FILE: src/components/utils/popover/components/popover-item/popover-item-default/popover-item-default.ts
class PopoverItemDefault (line 19) | class PopoverItemDefault extends PopoverItem {
method isDisabled (line 23) | public get isDisabled(): boolean {
method toggle (line 30) | public get toggle(): boolean | string | undefined {
method title (line 37) | public get title(): string | undefined {
method isConfirmationStateEnabled (line 44) | public get isConfirmationStateEnabled(): boolean {
method isFocused (line 51) | public get isFocused(): boolean {
method constructor (line 82) | constructor(protected readonly params: PopoverItemDefaultParams, rende...
method getElement (line 91) | public getElement(): HTMLElement | null {
method handleClick (line 98) | public handleClick(): void {
method toggleActive (line 113) | public toggleActive(isActive?: boolean): void {
method toggleHidden (line 122) | public override toggleHidden(isHidden: boolean): void {
method reset (line 129) | public reset(): void {
method onFocus (line 138) | public onFocus(): void {
method make (line 148) | private make(params: PopoverItemDefaultParams, renderParams?: PopoverI...
method enableConfirmationMode (line 205) | private enableConfirmationMode(newState: PopoverItemDefaultParams): vo...
method disableConfirmationMode (line 228) | private disableConfirmationMode(): void {
method enableSpecialHoverAndFocusBehavior (line 246) | private enableSpecialHoverAndFocusBehavior(): void {
method disableSpecialHoverAndFocusBehavior (line 256) | private disableSpecialHoverAndFocusBehavior(): void {
method activateOrEnableConfirmationMode (line 282) | private activateOrEnableConfirmationMode(item: PopoverItemDefaultParam...
method animateError (line 298) | private animateError(): void {
FILE: src/components/utils/popover/components/popover-item/popover-item-html/popover-item-html.ts
class PopoverItemHtml (line 9) | class PopoverItemHtml extends PopoverItem {
method constructor (line 22) | constructor(params: PopoverItemHtmlParams, renderParams?: PopoverItemR...
method getElement (line 46) | public getElement(): HTMLElement {
method toggleHidden (line 55) | public toggleHidden(isHidden: boolean): void {
method getControls (line 62) | public getControls(): HTMLElement[] {
FILE: src/components/utils/popover/components/popover-item/popover-item-separator/popover-item-separator.ts
class PopoverItemSeparator (line 8) | class PopoverItemSeparator extends PopoverItem {
method constructor (line 17) | constructor() {
method getElement (line 31) | public getElement(): HTMLElement {
method toggleHidden (line 40) | public toggleHidden(isHidden: boolean): void {
FILE: src/components/utils/popover/components/popover-item/popover-item.ts
method constructor (line 14) | constructor(protected readonly params?: PopoverItemParams) {}
method name (line 19) | public get name(): string | undefined {
method destroy (line 31) | public destroy(): void {
method onChildrenOpen (line 38) | public onChildrenOpen(): void {
method onChildrenClose (line 51) | public onChildrenClose(): void {
method handleClick (line 64) | public handleClick(): void {
method addHint (line 82) | protected addHint(itemElement: HTMLElement, hintData: { title: string, d...
method children (line 107) | public get children(): PopoverItemParams[] {
method hasChildren (line 114) | public get hasChildren(): boolean {
method isChildrenOpen (line 121) | public get isChildrenOpen(): boolean {
method isChildrenFlippable (line 128) | public get isChildrenFlippable(): boolean {
method isChildrenSearchable (line 147) | public get isChildrenSearchable(): boolean {
method closeOnActivate (line 154) | public get closeOnActivate(): boolean | undefined {
method isActive (line 161) | public get isActive(): boolean {
FILE: src/components/utils/popover/components/search-input/search-input.ts
class SearchInput (line 12) | class SearchInput extends EventsDispatcher<SearchInputEventMap> {
method constructor (line 43) | constructor({ items, placeholder }: {
method getElement (line 85) | public getElement(): HTMLElement {
method focus (line 92) | public focus(): void {
method clear (line 99) | public clear(): void {
method destroy (line 112) | public destroy(): void {
method foundItems (line 119) | private get foundItems(): SearchableItem[] {
method checkItem (line 128) | private checkItem(item: SearchableItem): boolean {
FILE: src/components/utils/popover/components/search-input/search-input.types.ts
type SearchableItem (line 4) | interface SearchableItem {
type SearchInputEvent (line 15) | enum SearchInputEvent {
type SearchInputEventMap (line 25) | interface SearchInputEventMap {
FILE: src/components/utils/popover/index.ts
type Popover (line 11) | type Popover = PopoverDesktop | PopoverMobile | PopoverInline;
FILE: src/components/utils/popover/popover-abstract.ts
method itemsDefault (line 35) | protected get itemsDefault(): PopoverItemDefault[] {
method constructor (line 59) | constructor(
method getElement (line 111) | public getElement(): HTMLElement {
method show (line 118) | public show(): void {
method hide (line 129) | public hide(): void {
method destroy (line 145) | public destroy(): void {
method activateItemByName (line 157) | public activateItemByName(name: string): void {
method buildItems (line 168) | protected buildItems(items: PopoverItemParams[]): Array<PopoverItem> {
method getTargetItem (line 186) | protected getTargetItem(event: Event): PopoverItemDefault | PopoverItemH...
method handleItemClick (line 205) | protected handleItemClick(item: PopoverItem): void {
method handleClick (line 241) | private handleClick(event: Event): void {
method toggleItemActivenessIfNeeded (line 259) | private toggleItemActivenessIfNeeded(clickedItem: PopoverItem): void {
FILE: src/components/utils/popover/popover-desktop.ts
class PopoverDesktop (line 21) | class PopoverDesktop extends PopoverAbstract {
method constructor (line 63) | constructor(params: PopoverParams, itemsRenderParams?: PopoverItemRend...
method hasFocus (line 105) | public hasFocus(): boolean {
method scrollTop (line 116) | public get scrollTop(): number {
method offsetTop (line 127) | public get offsetTop(): number {
method show (line 138) | public show(): void {
method destroy (line 169) | public destroy(): void {
method showNestedItems (line 179) | protected override showNestedItems(item: PopoverItem): void {
method handleHover (line 194) | protected handleHover(event: Event): void {
method setTriggerItemPosition (line 223) | protected setTriggerItemPosition(nestedPopoverEl: HTMLElement, item: P...
method destroyNestedPopoverIfExists (line 234) | protected destroyNestedPopoverIfExists(): void {
method showNestedPopoverForItem (line 255) | protected showNestedPopoverForItem(item: PopoverItem): PopoverDesktop {
method shouldOpenBottom (line 291) | private get shouldOpenBottom(): boolean {
method shouldOpenRight (line 309) | private get shouldOpenRight(): boolean {
method size (line 329) | public get size(): { height: number; width: number } {
method flippableElements (line 361) | private get flippableElements(): HTMLElement[] {
method addSearch (line 389) | private addSearch(): void {
method toggleNothingFoundMessage (line 444) | private toggleNothingFoundMessage(isDisplayed: boolean): void {
FILE: src/components/utils/popover/popover-inline.ts
class PopoverInline (line 12) | class PopoverInline extends PopoverDesktop {
method constructor (line 18) | constructor(params: PopoverParams) {
method offsetLeft (line 70) | public get offsetLeft(): number {
method show (line 81) | public override show(): void {
method handleHover (line 98) | protected override handleHover(): void {
method setTriggerItemPosition (line 109) | protected override setTriggerItemPosition(
method showNestedItems (line 129) | protected override showNestedItems(item: PopoverItemDefault | PopoverI...
method showNestedPopoverForItem (line 147) | protected showNestedPopoverForItem(item: PopoverItem): PopoverDesktop {
method handleItemClick (line 166) | protected override handleItemClick(item: PopoverItem): void {
FILE: src/components/utils/popover/popover-mobile.ts
class PopoverMobile (line 16) | class PopoverMobile extends PopoverAbstract<PopoverMobileNodes> {
method constructor (line 45) | constructor(params: PopoverParams) {
method show (line 73) | public show(): void {
method hide (line 86) | public hide(): void {
method destroy (line 104) | public destroy(): void {
method showNestedItems (line 115) | protected override showNestedItems(item: PopoverItemDefault): void {
method updateItemsAndHeader (line 131) | private updateItemsAndHeader(items: PopoverItemParams[], title?: strin...
FILE: src/components/utils/popover/popover.const.ts
type CSSVariables (line 32) | enum CSSVariables {
FILE: src/components/utils/popover/utils/popover-states-history.ts
type PopoverStatesHistoryItem (line 6) | interface PopoverStatesHistoryItem {
class PopoverStatesHistory (line 21) | class PopoverStatesHistory {
method push (line 32) | public push(state: PopoverStatesHistoryItem): void {
method pop (line 39) | public pop(): PopoverStatesHistoryItem | undefined {
method currentTitle (line 46) | public get currentTitle(): string | undefined {
method currentItems (line 57) | public get currentItems(): PopoverItemParams[] {
method reset (line 68) | public reset(): void {
FILE: src/components/utils/promise-queue.ts
class PromiseQueue (line 9) | class PromiseQueue {
method add (line 20) | public add(operation: (value: void) => void | PromiseLike<void>): Prom...
FILE: src/components/utils/resolve-aliases.ts
function resolveAliases (line 9) | function resolveAliases<ObjectType>(obj: ObjectType, aliases: { [alias: ...
FILE: src/components/utils/sanitizer.ts
function sanitizeBlocks (line 44) | function sanitizeBlocks(
function clean (line 68) | function clean(taintString: string, customConfig: SanitizerConfig = {} a...
function deepSanitize (line 87) | function deepSanitize(dataToSanitize: object | string, rules: SanitizerC...
function cleanArray (line 124) | function cleanArray(array: Array<object | string>, ruleForItem: Sanitize...
function cleanObject (line 135) | function cleanObject(object: object, rules: SanitizerConfig|{[field: str...
function cleanOneItem (line 165) | function cleanOneItem(taintString: string, rule: SanitizerConfig|boolean...
function isRule (line 182) | function isRule(config: SanitizerConfig): boolean {
FILE: src/components/utils/scroll-locker.ts
class ScrollLocker (line 6) | class ScrollLocker {
method lock (line 23) | public lock(): void {
method unlock (line 34) | public unlock(): void {
method lockHard (line 45) | private lockHard(): void {
method unlockHard (line 57) | private unlockHard(): void {
FILE: src/components/utils/shortcuts.ts
type ShortcutData (line 15) | interface ShortcutData {
class Shortcuts (line 40) | class Shortcuts {
method add (line 53) | public add(shortcut: ShortcutData): void {
method remove (line 78) | public remove(element: Element, name: string): void {
method findShortcut (line 107) | private findShortcut(element: Element, shortcut: string): Shortcut | v...
FILE: src/components/utils/tools.ts
function isToolConvertable (line 10) | function isToolConvertable(tool: BlockToolAdapter, direction: 'export' |...
FILE: src/components/utils/tooltip.ts
function prepare (line 20) | function prepare(): void {
function show (line 35) | function show(element: HTMLElement, content: TooltipContent, options?: T...
function hide (line 46) | function hide(skipHidingDelay = false): void {
function onHover (line 59) | function onHover(element: HTMLElement, content: TooltipContent, options?...
function destroy (line 68) | function destroy(): void {
FILE: src/env.d.ts
type ImportMetaEnv (line 1) | interface ImportMetaEnv {
type ImportMeta (line 9) | interface ImportMeta {
FILE: src/tools/stub/index.ts
type StubData (line 5) | interface StubData extends BlockToolData {
class Stub (line 14) | class Stub implements BlockTool {
method constructor (line 62) | constructor({ data, api }: BlockToolConstructorOptions<StubData>) {
method render (line 76) | public render(): HTMLElement {
method save (line 85) | public save(): BlockToolData {
method make (line 94) | private make(): HTMLElement {
FILE: src/types-internal/editor-modules.d.ts
type EditorModules (line 41) | interface EditorModules {
FILE: src/types-internal/html-janitor.d.ts
type TagConfig (line 10) | type TagConfig = boolean | { [attr: string]: boolean | string };
type Config (line 12) | interface Config {
class HTMLJanitor (line 18) | class HTMLJanitor {
FILE: src/types-internal/i18n-internal-namespace.d.ts
type Indexed (line 4) | type Indexed<T> = { [key: string]: T };
type LeavesDictKeys (line 14) | type LeavesDictKeys<D> = D extends string
type DictNamespaces (line 50) | type DictNamespaces<D extends object> = {
FILE: src/types-internal/module-config.d.ts
type ModuleConfig (line 8) | interface ModuleConfig {
FILE: test/cypress/fixtures/tools/ContentlessTool.ts
type ContentlessToolData (line 6) | interface ContentlessToolData {}
class ContentlessToolMock (line 11) | class ContentlessToolMock implements BlockTool {
method render (line 15) | public render(): HTMLElement {
method save (line 28) | public save(): ContentlessToolData {
method contentless (line 35) | public static get contentless(): boolean {
FILE: test/cypress/fixtures/tools/SimpleHeader.ts
class SimpleHeader (line 11) | class SimpleHeader implements BaseTool {
method constructor (line 19) | constructor({ data }: BlockToolConstructorOptions) {
method render (line 29) | public render(): HTMLHeadingElement {
method merge (line 41) | public merge(data: BlockToolData): void {
method save (line 50) | public save(toolsContent: HTMLHeadingElement): BlockToolData {
method conversionConfig (line 60) | public static get conversionConfig(): ConversionConfig {
FILE: test/cypress/fixtures/tools/ToolMock.ts
type MockToolData (line 6) | interface MockToolData {
class ToolMock (line 14) | class ToolMock implements BlockTool {
method constructor (line 25) | constructor(options: BlockToolConstructorOptions<MockToolData>) {
method render (line 32) | public render(): HTMLElement {
method save (line 49) | public save(block: HTMLElement): MockToolData {
FILE: test/cypress/fixtures/tools/ToolWithoutConversionExport.ts
class ToolWithoutConversionExport (line 9) | class ToolWithoutConversionExport extends ToolMock {
method conversionConfig (line 13) | public static get conversionConfig(): ConversionConfig {
FILE: test/cypress/fixtures/types/PartialBlockMutationEvent.ts
type PartialBlockMutationEvent (line 6) | interface PartialBlockMutationEvent {
FILE: test/cypress/support/e2e.ts
function assertToBeCalledWithBatchedEvents (line 22) | function assertToBeCalledWithBatchedEvents(expectedEvents: PartialBlockM...
FILE: test/cypress/support/index.d.ts
type Chainable (line 10) | interface Chainable<Subject = any> {
type ApplicationWindow (line 105) | interface ApplicationWindow {
type Chainer (line 112) | interface Chainer<Subject> {
type Assertion (line 130) | interface Assertion {
FILE: test/cypress/support/utils/createEditorWithTextBlocks.ts
function createEditorWithTextBlocks (line 12) | function createEditorWithTextBlocks(textBlocks: string[], editorConfig?:...
FILE: test/cypress/support/utils/createParagraphMock.ts
function createParagraphMock (line 9) | function createParagraphMock(text: string): {
FILE: test/cypress/support/utils/nestedEditorInstance.ts
constant NESTED_EDITOR_ID (line 4) | const NESTED_EDITOR_ID = 'nested-editor';
class NestedEditor (line 9) | class NestedEditor implements BlockTool {
method constructor (line 12) | constructor(value: BlockToolConstructorOptions) {
method render (line 16) | public render(): HTMLDivElement {
method save (line 28) | public save(): string {
FILE: test/cypress/tests/api/block.cy.ts
function createEditor (line 31) | function createEditor(data = undefined): void {
FILE: test/cypress/tests/api/blocks.cy.ts
class ExampleTune (line 110) | class ExampleTune {
method constructor (line 116) | constructor({ data }) {
method isTune (line 125) | public static get isTune(): boolean {
method render (line 134) | public render(): Element {
method CSS (line 141) | public static get CSS(): object {
method save (line 150) | public save(): object | string {
class ConvertableTool (line 297) | class ConvertableTool extends ToolMock {
method conversionConfig (line 301) | public static get conversionConfig(): ConversionConfig {
method toolbox (line 310) | public static get toolbox(): ToolboxConfig {
class ToolWithoutConversionConfig (line 421) | class ToolWithoutConversionConfig extends ToolMock {}
class ToolWithConversionConfig (line 464) | class ToolWithConversionConfig extends ToolMock {
method conversionConfig (line 468) | public static get conversionConfig(): {
FILE: test/cypress/tests/api/tools.cy.ts
constant ICON (line 7) | const ICON = '<svg width="17" height="15" viewBox="0 0 336 276" xmlns="h...
class TestTool (line 15) | class TestTool {
method toolbox (line 19) | public static get toolbox(): ToolboxConfigEntry {
method toolbox (line 58) | public static get toolbox(): ToolboxConfig {
method constructor (line 120) | constructor({ data }) {
method toolbox (line 127) | public static get toolbox(): ToolboxConfig {
method render (line 140) | public render(): HTMLElement {
method save (line 153) | public save(el: HTMLElement): BlockToolData {
method toolbox (line 202) | public static get toolbox(): ToolboxConfigEntry {
method renderSettings (line 210) | public renderSettings(): TunesMenuConfig {
method save (line 221) | public save(): void { }
method render (line 224) | public render(): HTMLElement {
method toolbox (line 271) | public static get toolbox(): ToolboxConfigEntry {
method renderSettings (line 279) | public renderSettings(): TunesMenuConfig {
method save (line 299) | public save(): void { }
method render (line 302) | public render(): HTMLElement {
method toolbox (line 352) | public static get toolbox(): ToolboxConfigEntry {
method renderSettings (line 360) | public renderSettings(): HTMLElement {
method save (line 369) | public save(): void { }
method render (line 372) | public render(): HTMLElement {
method toolbox (line 421) | public static get toolbox(): ToolboxConfigEntry {
method renderSettings (line 429) | public renderSettings(): TunesMenuConfig {
method save (line 451) | public save(): void {}
method render (line 454) | public render(): HTMLElement {
method pasteConfig (line 780) | public static get pasteConfig(): PasteConfig {
method onPaste (line 794) | public onPaste(): void { }
method save (line 797) | public save(): void { }
method render (line 800) | public render(): HTMLElement {
method pasteConfig (line 862) | public static get pasteConfig(): PasteConfig {
method onPaste (line 878) | public onPaste(): void { }
method save (line 881) | public save(): void { }
method render (line 884) | public render(): HTMLElement {
method pasteConfig (line 936) | public static get pasteConfig(): PasteConfig {
method onPaste (line 954) | public onPaste(): void { }
method save (line 957) | public save(): void { }
method render (line 960) | public render(): HTMLElement {
class TestTool (line 54) | class TestTool {
method toolbox (line 19) | public static get toolbox(): ToolboxConfigEntry {
method toolbox (line 58) | public static get toolbox(): ToolboxConfig {
method constructor (line 120) | constructor({ data }) {
method toolbox (line 127) | public static get toolbox(): ToolboxConfig {
method render (line 140) | public render(): HTMLElement {
method save (line 153) | public save(el: HTMLElement): BlockToolData {
method toolbox (line 202) | public static get toolbox(): ToolboxConfigEntry {
method renderSettings (line 210) | public renderSettings(): TunesMenuConfig {
method save (line 221) | public save(): void { }
method render (line 224) | public render(): HTMLElement {
method toolbox (line 271) | public static get toolbox(): ToolboxConfigEntry {
method renderSettings (line 279) | public renderSettings(): TunesMenuConfig {
method save (line 299) | public save(): void { }
method render (line 302) | public render(): HTMLElement {
method toolbox (line 352) | public static get toolbox(): ToolboxConfigEntry {
method renderSettings (line 360) | public renderSettings(): HTMLElement {
method save (line 369) | public save(): void { }
method render (line 372) | public render(): HTMLElement {
method toolbox (line 421) | public static get toolbox(): ToolboxConfigEntry {
method renderSettings (line 429) | public renderSettings(): TunesMenuConfig {
method save (line 451) | public save(): void {}
method render (line 454) | public render(): HTMLElement {
method pasteConfig (line 780) | public static get pasteConfig(): PasteConfig {
method onPaste (line 794) | public onPaste(): void { }
method save (line 797) | public save(): void { }
method render (line 800) | public render(): HTMLElement {
method pasteConfig (line 862) | public static get pasteConfig(): PasteConfig {
method onPaste (line 878) | public onPaste(): void { }
method save (line 881) | public save(): void { }
method render (line 884) | public render(): HTMLElement {
method pasteConfig (line 936) | public static get pasteConfig(): PasteConfig {
method onPaste (line 954) | public onPaste(): void { }
method save (line 957) | public save(): void { }
method render (line 960) | public render(): HTMLElement {
class TestTool (line 110) | class TestTool {
method toolbox (line 19) | public static get toolbox(): ToolboxConfigEntry {
method toolbox (line 58) | public static get toolbox(): ToolboxConfig {
method constructor (line 120) | constructor({ data }) {
method toolbox (line 127) | public static get toolbox(): ToolboxConfig {
method render (line 140) | public render(): HTMLElement {
method save (line 153) | public save(el: HTMLElement): BlockToolData {
method toolbox (line 202) | public static get toolbox(): ToolboxConfigEntry {
method renderSettings (line 210) | public renderSettings(): TunesMenuConfig {
method save (line 221) | public save(): void { }
method render (line 224) | public render(): HTMLElement {
method toolbox (line 271) | public static get toolbox(): ToolboxConfigEntry {
method renderSettings (line 279) | public renderSettings(): TunesMenuConfig {
method save (line 299) | public save(): void { }
method render (line 302) | public render(): HTMLElement {
method toolbox (line 352) | public static get toolbox(): ToolboxConfigEntry {
method renderSettings (line 360) | public renderSettings(): HTMLElement {
method save (line 369) | public save(): void { }
method render (line 372) | public render(): HTMLElement {
method toolbox (line 421) | public static get toolbox(): ToolboxConfigEntry {
method renderSettings (line 429) | public renderSettings(): TunesMenuConfig {
method save (line 451) | public save(): void {}
method render (line 454) | public render(): HTMLElement {
method pasteConfig (line 780) | public static get pasteConfig(): PasteConfig {
method onPaste (line 794) | public onPaste(): void { }
method save (line 797) | public save(): void { }
method render (line 800) | public render(): HTMLElement {
method pasteConfig (line 862) | public static get pasteConfig(): PasteConfig {
method onPaste (line 878) | public onPaste(): void { }
method save (line 881) | public save(): void { }
method render (line 884) | public render(): HTMLElement {
method pasteConfig (line 936) | public static get pasteConfig(): PasteConfig {
method onPaste (line 954) | public onPaste(): void { }
method save (line 957) | public save(): void { }
method render (line 960) | public render(): HTMLElement {
class TestTool (line 200) | class TestTool {
method toolbox (line 19) | public static get toolbox(): ToolboxConfigEntry {
method toolbox (line 58) | public static get toolbox(): ToolboxConfig {
method constructor (line 120) | constructor({ data }) {
method toolbox (line 127) | public static get toolbox(): ToolboxConfig {
method render (line 140) | public render(): HTMLElement {
method save (line 153) | public save(el: HTMLElement): BlockToolData {
method toolbox (line 202) | public static get toolbox(): ToolboxConfigEntry {
method renderSettings (line 210) | public renderSettings(): TunesMenuConfig {
method save (line 221) | public save(): void { }
method render (line 224) | public render(): HTMLElement {
method toolbox (line 271) | public static get toolbox(): ToolboxConfigEntry {
method renderSettings (line 279) | public renderSettings(): TunesMenuConfig {
method save (line 299) | public save(): void { }
method render (line 302) | public render(): HTMLElement {
method toolbox (line 352) | public static get toolbox(): ToolboxConfigEntry {
method renderSettings (line 360) | public renderSettings(): HTMLElement {
method save (line 369) | public save(): void { }
method render (line 372) | public render(): HTMLElement {
method toolbox (line 421) | public static get toolbox(): ToolboxConfigEntry {
method renderSettings (line 429) | public renderSettings(): TunesMenuConfig {
method save (line 451) | public save(): void {}
method render (line 454) | public render(): HTMLElement {
method pasteConfig (line 780) | public static get pasteConfig(): PasteConfig {
method onPaste (line 794) | public onPaste(): void { }
method save (line 797) | public save(): void { }
method render (line 800) | public render(): HTMLElement {
method pasteConfig (line 862) | public static get pasteConfig(): PasteConfig {
method onPaste (line 878) | public onPaste(): void { }
method save (line 881) | public save(): void { }
method render (line 884) | public render(): HTMLElement {
method pasteConfig (line 936) | public static get pasteConfig(): PasteConfig {
method onPaste (line 954) | public onPaste(): void { }
method save (line 957) | public save(): void { }
method render (line 960) | public render(): HTMLElement {
class TestTool (line 269) | class TestTool {
method toolbox (line 19) | public static get toolbox(): ToolboxConfigEntry {
method toolbox (line 58) | public static get toolbox(): ToolboxConfig {
method constructor (line 120) | constructor({ data }) {
method toolbox (line 127) | public static get toolbox(): ToolboxConfig {
method render (line 140) | public render(): HTMLElement {
method save (line 153) | public save(el: HTMLElement): BlockToolData {
method toolbox (line 202) | public static get toolbox(): ToolboxConfigEntry {
method renderSettings (line 210) | public renderSettings(): TunesMenuConfig {
method save (line 221) | public save(): void { }
method render (line 224) | public render(): HTMLElement {
method toolbox (line 271) | public static get toolbox(): ToolboxConfigEntry {
method renderSettings (line 279) | public renderSettings(): TunesMenuConfig {
method save (line 299) | public save(): void { }
method render (line 302) | public render(): HTMLElement {
method toolbox (line 352) | public static get toolbox(): ToolboxConfigEntry {
method renderSettings (line 360) | public renderSettings(): HTMLElement {
method save (line 369) | public save(): void { }
method render (line 372) | public render(): HTMLElement {
method toolbox (line 421) | public static get toolbox(): ToolboxConfigEntry {
method renderSettings (line 429) | public renderSettings(): TunesMenuConfig {
method save (line 451) | public save(): void {}
method render (line 454) | public render(): HTMLElement {
method pasteConfig (line 780) | public static get pasteConfig(): PasteConfig {
method onPaste (line 794) | public onPaste(): void { }
method save (line 797) | public save(): void { }
method render (line 800) | public render(): HTMLElement {
method pasteConfig (line 862) | public static get pasteConfig(): PasteConfig {
method onPaste (line 878) | public onPaste(): void { }
method save (line 881) | public save(): void { }
method render (line 884) | public render(): HTMLElement {
method pasteConfig (line 936) | public static get pasteConfig(): PasteConfig {
method onPaste (line 954) | public onPaste(): void { }
method save (line 957) | public save(): void { }
method render (line 960) | public render(): HTMLElement {
class TestTool (line 350) | class TestTool {
method toolbox (line 19) | public static get toolbox(): ToolboxConfigEntry {
method toolbox (line 58) | public static get toolbox(): ToolboxConfig {
method constructor (line 120) | constructor({ data }) {
method toolbox (line 127) | public static get toolbox(): ToolboxConfig {
method render (line 140) | public render(): HTMLElement {
method save (line 153) | public save(el: HTMLElement): BlockToolData {
method toolbox (line 202) | public static get toolbox(): ToolboxConfigEntry {
method renderSettings (line 210) | public renderSettings(): TunesMenuConfig {
method save (line 221) | public save(): void { }
method render (line 224) | public render(): HTMLElement {
method toolbox (line 271) | public static get toolbox(): ToolboxConfigEntry {
method renderSettings (line 279) | public renderSettings(): TunesMenuConfig {
method save (line 299) | public save(): void { }
method render (line 302) | public render(): HTMLElement {
method toolbox (line 352) | public static get toolbox(): ToolboxConfigEntry {
method renderSettings (line 360) | public renderSettings(): HTMLElement {
method save (line 369) | public save(): void { }
method render (line 372) | public render(): HTMLElement {
method toolbox (line 421) | public static get toolbox(): ToolboxConfigEntry {
method renderSettings (line 429) | public renderSettings(): TunesMenuConfig {
method save (line 451) | public save(): void {}
method render (line 454) | public render(): HTMLElement {
method pasteConfig (line 780) | public static get pasteConfig(): PasteConfig {
method onPaste (line 794) | public onPaste(): void { }
method save (line 797) | public save(): void { }
method render (line 800) | public render(): HTMLElement {
method pasteConfig (line 862) | public static get pasteConfig(): PasteConfig {
method onPaste (line 878) | public onPaste(): void { }
method save (line 881) | public save(): void { }
method render (line 884) | public render(): HTMLElement {
method pasteConfig (line 936) | public static get pasteConfig(): PasteConfig {
method onPaste (line 954) | public onPaste(): void { }
method save (line 957) | public save(): void { }
method render (line 960) | public render(): HTMLElement {
class TestTool (line 419) | class TestTool {
method toolbox (line 19) | public static get toolbox(): ToolboxConfigEntry {
method toolbox (line 58) | public static get toolbox(): ToolboxConfig {
method constructor (line 120) | constructor({ data }) {
method toolbox (line 127) | public static get toolbox(): ToolboxConfig {
method render (line 140) | public render(): HTMLElement {
method save (line 153) | public save(el: HTMLElement): BlockToolData {
method toolbox (line 202) | public static get toolbox(): ToolboxConfigEntry {
method renderSettings (line 210) | public renderSettings(): TunesMenuConfig {
method save (line 221) | public save(): void { }
method render (line 224) | public render(): HTMLElement {
method toolbox (line 271) | public static get toolbox(): ToolboxConfigEntry {
method renderSettings (line 279) | public renderSettings(): TunesMenuConfig {
method save (line 299) | public save(): void { }
method render (line 302) | public render(): HTMLElement {
method toolbox (line 352) | public static get toolbox(): ToolboxConfigEntry {
method renderSettings (line 360) | public renderSettings(): HTMLElement {
method save (line 369) | public save(): void { }
method render (line 372) | public render(): HTMLElement {
method toolbox (line 421) | public static get toolbox(): ToolboxConfigEntry {
method renderSettings (line 429) | public renderSettings(): TunesMenuConfig {
method save (line 451) | public save(): void {}
method render (line 454) | public render(): HTMLElement {
method pasteConfig (line 780) | public static get pasteConfig(): PasteConfig {
method onPaste (line 794) | public onPaste(): void { }
method save (line 797) | public save(): void { }
method render (line 800) | public render(): HTMLElement {
method pasteConfig (line 862) | public static get pasteConfig(): PasteConfig {
method onPaste (line 878) | public onPaste(): void { }
method save (line 881) | public save(): void { }
method render (line 884) | public render(): HTMLElement {
method pasteConfig (line 936) | public static get pasteConfig(): PasteConfig {
method onPaste (line 954) | public onPaste(): void { }
method save (line 957) | public save(): void { }
method render (line 960) | public render(): HTMLElement {
class TestImgTool (line 511) | class TestImgTool {
method pasteConfig (line 513) | public static get pasteConfig(): PasteConfig {
method onPaste (line 520) | public onPaste(): void { }
method save (line 523) | public save(): void { }
method render (line 526) | public render(): HTMLElement {
class TestImageTool (line 563) | class TestImageTool {
method pasteConfig (line 565) | public static get pasteConfig(): PasteConfig {
method onPaste (line 572) | public onPaste(): void { }
method save (line 575) | public save(): void { }
method render (line 578) | public render(): HTMLElement {
method pasteConfig (line 703) | public static get pasteConfig(): PasteConfig {
method onPaste (line 716) | public onPaste(): void { }
method save (line 719) | public save(): void { }
method render (line 722) | public render(): HTMLElement {
class TestListTool (line 626) | class TestListTool {
method pasteConfig (line 628) | public static get pasteConfig(): PasteConfig {
method onPaste (line 635) | public onPaste(): void { }
method save (line 638) | public save(): void { }
method render (line 641) | public render(): HTMLElement {
class TestImageTool (line 701) | class TestImageTool {
method pasteConfig (line 565) | public static get pasteConfig(): PasteConfig {
method onPaste (line 572) | public onPaste(): void { }
method save (line 575) | public save(): void { }
method render (line 578) | public render(): HTMLElement {
method pasteConfig (line 703) | public static get pasteConfig(): PasteConfig {
method onPaste (line 716) | public onPaste(): void { }
method save (line 719) | public save(): void { }
method render (line 722) | public render(): HTMLElement {
class TestTool (line 778) | class TestTool {
method toolbox (line 19) | public static get toolbox(): ToolboxConfigEntry {
method toolbox (line 58) | public static get toolbox(): ToolboxConfig {
method constructor (line 120) | constructor({ data }) {
method toolbox (line 127) | public static get toolbox(): ToolboxConfig {
method render (line 140) | public render(): HTMLElement {
method save (line 153) | public save(el: HTMLElement): BlockToolData {
method toolbox (line 202) | public static get toolbox(): ToolboxConfigEntry {
method renderSettings (line 210) | public renderSettings(): TunesMenuConfig {
method save (line 221) | public save(): void { }
method render (line 224) | public render(): HTMLElement {
method toolbox (line 271) | public static get toolbox(): ToolboxConfigEntry {
method renderSettings (line 279) | public renderSettings(): TunesMenuConfig {
method save (line 299) | public save(): void { }
method render (line 302) | public render(): HTMLElement {
method toolbox (line 352) | public static get toolbox(): ToolboxConfigEntry {
method renderSettings (line 360) | public renderSettings(): HTMLElement {
method save (line 369) | public save(): void { }
method render (line 372) | public render(): HTMLElement {
method toolbox (line 421) | public static get toolbox(): ToolboxConfigEntry {
method renderSettings (line 429) | public renderSettings(): TunesMenuConfig {
method save (line 451) | public save(): void {}
method render (line 454) | public render(): HTMLElement {
method pasteConfig (line 780) | public static get pasteConfig(): PasteConfig {
method onPaste (line 794) | public onPaste(): void { }
method save (line 797) | public save(): void { }
method render (line 800) | public render(): HTMLElement {
method pasteConfig (line 862) | public static get pasteConfig(): PasteConfig {
method onPaste (line 878) | public onPaste(): void { }
method save (line 881) | public save(): void { }
method render (line 884) | public render(): HTMLElement {
method pasteConfig (line 936) | public static get pasteConfig(): PasteConfig {
method onPaste (line 954) | public onPaste(): void { }
method save (line 957) | public save(): void { }
method render (line 960) | public render(): HTMLElement {
class TestTool (line 860) | class TestTool {
method toolbox (line 19) | public static get toolbox(): ToolboxConfigEntry {
method toolbox (line 58) | public static get toolbox(): ToolboxConfig {
method constructor (line 120) | constructor({ data }) {
method toolbox (line 127) | public static get toolbox(): ToolboxConfig {
method render (line 140) | public render(): HTMLElement {
method save (line 153) | public save(el: HTMLElement): BlockToolData {
method toolbox (line 202) | public static get toolbox(): ToolboxConfigEntry {
method renderSettings (line 210) | public renderSettings(): TunesMenuConfig {
method save (line 221) | public save(): void { }
method render (line 224) | public render(): HTMLElement {
method toolbox (line 271) | public static get toolbox(): ToolboxConfigEntry {
method renderSettings (line 279) | public renderSettings(): TunesMenuConfig {
method save (line 299) | public save(): void { }
method render (line 302) | public render(): HTMLElement {
method toolbox (line 352) | public static get toolbox(): ToolboxConfigEntry {
method renderSettings (line 360) | public renderSettings(): HTMLElement {
method save (line 369) | public save(): void { }
method render (line 372) | public render(): HTMLElement {
method toolbox (line 421) | public static get toolbox(): ToolboxConfigEntry {
method renderSettings (line 429) | public renderSettings(): TunesMenuConfig {
method save (line 451) | public save(): void {}
method render (line 454) | public render(): HTMLElement {
method pasteConfig (line 780) | public static get pasteConfig(): PasteConfig {
method onPaste (line 794) | public onPaste(): void { }
method save (line 797) | public save(): void { }
method render (line 800) | public render(): HTMLElement {
method pasteConfig (line 862) | public static get pasteConfig(): PasteConfig {
method onPaste (line 878) | public onPaste(): void { }
method save (line 881) | public save(): void { }
method render (line 884) | public render(): HTMLElement {
method pasteConfig (line 936) | public static get pasteConfig(): PasteConfig {
method onPaste (line 954) | public onPaste(): void { }
method save (line 957) | public save(): void { }
method render (line 960) | public render(): HTMLElement {
class TestTool (line 934) | class TestTool {
method toolbox (line 19) | public static get toolbox(): ToolboxConfigEntry {
method toolbox (line 58) | public static get toolbox(): ToolboxConfig {
method constructor (line 120) | constructor({ data }) {
method toolbox (line 127) | public static get toolbox(): ToolboxConfig {
method render (line 140) | public render(): HTMLElement {
method save (line 153) | public save(el: HTMLElement): BlockToolData {
method toolbox (line 202) | public static get toolbox(): ToolboxConfigEntry {
method renderSettings (line 210) | public renderSettings(): TunesMenuConfig {
method save (line 221) | public save(): void { }
method render (line 224) | public render(): HTMLElement {
method toolbox (line 271) | public static get toolbox(): ToolboxConfigEntry {
method renderSettings (line 279) | public renderSettings(): TunesMenuConfig {
method save (line 299) | public save(): void { }
method render (line 302) | public render(): HTMLElement {
method toolbox (line 352) | public static get toolbox(): ToolboxConfigEntry {
method renderSettings (line 360) | public renderSettings(): HTMLElement {
method save (line 369) | public save(): void { }
method render (line 372) | public render(): HTMLElement {
method toolbox (line 421) | public static get toolbox(): ToolboxConfigEntry {
method renderSettings (line 429) | public renderSettings(): TunesMenuConfig {
method save (line 451) | public save(): void {}
method render (line 454) | public render(): HTMLElement {
method pasteConfig (line 780) | public static get pasteConfig(): PasteConfig {
method onPaste (line 794) | public onPaste(): void { }
method save (line 797) | public save(): void { }
method render (line 800) | public render(): HTMLElement {
method pasteConfig (line 862) | public static get pasteConfig(): PasteConfig {
method onPaste (line 878) | public onPaste(): void { }
method save (line 881) | public save(): void { }
method render (line 884) | public render(): HTMLElement {
method pasteConfig (line 936) | public static get pasteConfig(): PasteConfig {
method onPaste (line 954) | public onPaste(): void { }
method save (line 957) | public save(): void { }
method render (line 960) | public render(): HTMLElement {
FILE: test/cypress/tests/api/tunes.cy.ts
class TestTune (line 8) | class TestTune {
method render (line 13) | public render(): TunesMenuConfig {
method save (line 24) | public save(): void {}
method render (line 53) | public render(): TunesMenuConfig {
method save (line 72) | public save(): void {}
method render (line 104) | public render(): HTMLElement {
method save (line 113) | public save(): void {}
method render (line 144) | public render(): TunesMenuConfig {
method save (line 165) | public save(): void {}
method render (line 197) | public render(): TunesMenuConfig {
method save (line 210) | public save(): void {}
class TestTune (line 48) | class TestTune {
method render (line 13) | public render(): TunesMenuConfig {
method save (line 24) | public save(): void {}
method render (line 53) | public render(): TunesMenuConfig {
method save (line 72) | public save(): void {}
method render (line 104) | public render(): HTMLElement {
method save (line 113) | public save(): void {}
method render (line 144) | public render(): TunesMenuConfig {
method save (line 165) | public save(): void {}
method render (line 197) | public render(): TunesMenuConfig {
method save (line 210) | public save(): void {}
class TestTune (line 99) | class TestTune {
method render (line 13) | public render(): TunesMenuConfig {
method save (line 24) | public save(): void {}
method render (line 53) | public render(): TunesMenuConfig {
method save (line 72) | public save(): void {}
method render (line 104) | public render(): HTMLElement {
method save (line 113) | public save(): void {}
method render (line 144) | public render(): TunesMenuConfig {
method save (line 165) | public save(): void {}
method render (line 197) | public render(): TunesMenuConfig {
method save (line 210) | public save(): void {}
class TestTune (line 139) | class TestTune {
method render (line 13) | public render(): TunesMenuConfig {
method save (line 24) | public save(): void {}
method render (line 53) | public render(): TunesMenuConfig {
method save (line 72) | public save(): void {}
method render (line 104) | public render(): HTMLElement {
method save (line 113) | public save(): void {}
method render (line 144) | public render(): TunesMenuConfig {
method save (line 165) | public save(): void {}
method render (line 197) | public render(): TunesMenuConfig {
method save (line 210) | public save(): void {}
class TestTune (line 192) | class TestTune {
method render (line 13) | public render(): TunesMenuConfig {
method save (line 24) | public save(): void {}
method render (line 53) | public render(): TunesMenuConfig {
method save (line 72) | public save(): void {}
method render (line 104) | public render(): HTMLElement {
method save (line 113) | public save(): void {}
method render (line 144) | public render(): TunesMenuConfig {
method save (line 165) | public save(): void {}
method render (line 197) | public render(): TunesMenuConfig {
method save (line 210) | public save(): void {}
FILE: test/cypress/tests/copy-paste.cy.ts
class BlockToolWithPasteHandler (line 187) | class BlockToolWithPasteHandler implements BlockTool {
method render (line 193) | public render(): HTMLElement {
method save (line 206) | public save(): BlockToolData {
FILE: test/cypress/tests/i18n.cy.ts
class TestTool (line 50) | class TestTool {
method toolbox (line 54) | public static get toolbox(): ToolboxConfig {
method toolbox (line 110) | public static get toolbox(): ToolboxConfig {
class TestTool (line 106) | class TestTool {
method toolbox (line 54) | public static get toolbox(): ToolboxConfig {
method toolbox (line 110) | public static get toolbox(): ToolboxConfig {
FILE: test/cypress/tests/modules/BlockEvents/Backspace.cy.ts
class ExampleOfToolWithSeveralInputs (line 186) | class ExampleOfToolWithSeveralInputs {
method render (line 190) | public render(): HTMLElement {
method save (line 209) | public save(): void { }
class UnmergeableToolWithoutConversionConfig (line 552) | class UnmergeableToolWithoutConversionConfig {
method render (line 556) | public render(): HTMLElement {
method save (line 570) | public save(): void { }
class UnmergeableToolWithConversionConfig (line 622) | class UnmergeableToolWithConversionConfig {
method render (line 626) | public render(): HTMLElement {
method save (line 639) | public save(): { key: string } {
method conversionConfig (line 648) | public static get conversionConfig(): ConversionConfig {
FILE: test/cypress/tests/modules/BlockEvents/Delete.cy.ts
class ExampleOfToolWithSeveralInputs (line 179) | class ExampleOfToolWithSeveralInputs {
method render (line 183) | public render(): HTMLElement {
method save (line 202) | public save(): void {}
class ExampleOfUnmergeableTool (line 413) | class ExampleOfUnmergeableTool {
method render (line 417) | public render(): HTMLElement {
method save (line 431) | public save(): void {}
FILE: test/cypress/tests/modules/BlockEvents/Tab.cy.ts
class ToolWithTwoInputs (line 6) | class ToolWithTwoInputs extends ToolMock {
method render (line 10) | public render(): HTMLElement {
class ContentlessTool (line 30) | class ContentlessTool extends ToolMock {
method render (line 35) | public render(): HTMLElement {
constant CARET_MOVE_TIME (line 49) | const CARET_MOVE_TIME = 100;
FILE: test/cypress/tests/modules/InlineToolbar.cy.ts
method render (line 93) | public render(): MenuConfig {
FILE: test/cypress/tests/modules/Renderer.cy.ts
class ToolWithError (line 89) | class ToolWithError extends ToolMock {
method constructor (line 93) | constructor(options) {
FILE: test/cypress/tests/modules/Tools.cy.ts
function constructModule (line 17) | function constructModule(config: EditorConfig = defaultConfig): Tools {
class WithSuccessfulPrepare (line 79) | class WithSuccessfulPrepare {
method prepare (line 117) | public static prepare(): void {}
method prepare (line 123) | public static prepare(): void {
method render (line 141) | public render(): void {}
method surround (line 144) | public surround(): void {}
method checkState (line 147) | public checkState(): void {}
method render (line 153) | public render(): void {}
method surround (line 156) | public surround(): void {}
method checkState (line 159) | public checkState(): void {}
method prepare (line 176) | public static prepare(): void {
FILE: test/cypress/tests/onchange.cy.ts
function createEditor (line 28) | function createEditor(blocks = null): void {
function createEditorWithSave (line 52) | function createEditorWithSave(blocks = null): void {
class ToolWithMutationFreeAttribute (line 499) | class ToolWithMutationFreeAttribute {
method render (line 503) | public render(): HTMLElement {
method save (line 511) | public save(): void {}
method render (line 570) | public render(): HTMLElement {
method save (line 578) | public save(): void {}
method render (line 640) | public render(): HTMLElement {
method save (line 648) | public save(): void {}
class ToolWithMutationFreeAttribute (line 566) | class ToolWithMutationFreeAttribute {
method render (line 503) | public render(): HTMLElement {
method save (line 511) | public save(): void {}
method render (line 570) | public render(): HTMLElement {
method save (line 578) | public save(): void {}
method render (line 640) | public render(): HTMLElement {
method save (line 648) | public save(): void {}
class ToolWithMutationFreeAttribute (line 636) | class ToolWithMutationFreeAttribute {
method render (line 503) | public render(): HTMLElement {
method save (line 511) | public save(): void {}
method render (line 570) | public render(): HTMLElement {
method save (line 578) | public save(): void {}
method render (line 640) | public render(): HTMLElement {
method save (line 648) | public save(): void {}
class ToolWithContentEditableDescendant (line 799) | class ToolWithContentEditableDescendant extends ToolMock {
method render (line 803) | public render(): HTMLElement {
FILE: test/cypress/tests/readOnly.cy.ts
function createEditor (line 10) | function createEditor(config?: EditorConfig): void {
FILE: test/cypress/tests/tools/BlockTool.cy.ts
method constructor (line 52) | constructor({ data, block, readOnly, api, config }) {
method method (line 549) | method(): void {}
FILE: test/cypress/tests/tools/BlockTune.cy.ts
method constructor (line 24) | constructor({ api, config, block, data }) {
method method (line 142) | method(): void {}
FILE: test/cypress/tests/tools/InlineTool.cy.ts
method constructor (line 34) | constructor({ api, config }) {
FILE: test/cypress/tests/tools/ToolsCollection.cy.ts
method isBlock (line 9) | isBlock(): boolean {
method isInline (line 12) | isInline(): boolean {
method isTune (line 15) | isTune(): boolean {
method isBlock (line 23) | isBlock(): boolean {
method isInline (line 30) | isInline(): boolean {
method isTune (line 37) | isTune(): boolean {
FILE: test/cypress/tests/tools/ToolsFactory.cy.ts
method getMethodsForTool (line 32) | getMethodsForTool(): object {
FILE: test/cypress/tests/ui/BlockTunes.cy.ts
class TestTool (line 225) | class TestTool {
method conversionConfig (line 229) | public static get conversionConfig(): ConversionConfig {
method toolbox (line 239) | public static get toolbox(): ToolboxConfig {
method render (line 261) | public render(): HTMLDivElement {
method save (line 272) | public save(): { text: string; level: number } {
method toolbox (line 392) | public static get toolbox(): ToolboxConfig {
method render (line 407) | public render(): HTMLDivElement {
method renderSettings (line 418) | public renderSettings(): MenuConfig {
method save (line 430) | public save(): { text: string; level: number } {
class TestTool (line 388) | class TestTool {
method conversionConfig (line 229) | public static get conversionConfig(): ConversionConfig {
method toolbox (line 239) | public static get toolbox(): ToolboxConfig {
method render (line 261) | public render(): HTMLDivElement {
method save (line 272) | public save(): { text: string; level: number } {
method toolbox (line 392) | public static get toolbox(): ToolboxConfig {
method render (line 407) | public render(): HTMLDivElement {
method renderSettings (line 418) | public renderSettings(): MenuConfig {
method save (line 430) | public save(): { text: string; level: number } {
FILE: test/cypress/tests/ui/InlineToolbar.cy.ts
method render (line 57) | public render(): MenuConfig {
method render (line 126) | public render(): MenuConfig {
class Marker (line 183) | class Marker implements InlineTool {
method render (line 187) | public render(): MenuConfig {
FILE: test/cypress/tests/ui/Placeholders.cy.ts
constant PLACEHOLDER_TEXT (line 4) | const PLACEHOLDER_TEXT = 'Write something or press / to select a tool';
FILE: test/cypress/tests/ui/toolbox.cy.ts
class ConvertableTool (line 11) | class ConvertableTool extends ToolMock {
method conversionConfig (line 15) | public static get conversionConfig(): ConversionConfig {
method toolbox (line 24) | public static get toolbox(): ToolboxConfig {
class ToolWithoutConversionConfig (line 79) | class ToolWithoutConversionConfig extends ToolMock {
method toolbox (line 83) | public static get toolbox(): ToolboxConfig {
class ToolWithSeveralToolboxItems (line 122) | class ToolWithSeveralToolboxItems extends ToolMock {
method toolbox (line 126) | public static get toolbox(): ToolboxConfig {
class ToolWithOneToolboxItems (line 180) | class ToolWithOneToolboxItems extends ToolMock {
method toolbox (line 184) | public static get toolbox(): ToolboxConfig {
FILE: test/cypress/tests/utils.cy.ts
function syncFunction (line 7) | function syncFunction(): void {}
function asyncFunction (line 12) | async function asyncFunction(): Promise<void> {}
FILE: test/cypress/tests/utils/flipper.cy.ts
class SomePlugin (line 6) | class SomePlugin {
method pluginInternalKeydownHandler (line 11) | public static pluginInternalKeydownHandler(): void {}
method render (line 16) | public render(): HTMLElement {
method toolbox (line 29) | public static get toolbox(): PopoverItemParams {
method save (line 41) | public save(): {data: string} {
FILE: test/cypress/tests/utils/popover.cy.ts
class TestTune (line 253) | class TestTune {
method render (line 257) | public render(): HTMLElement {
method render (line 400) | public render(): MenuConfig {
method render (line 476) | public render(): MenuConfig {
method render (line 585) | public render(): MenuConfig {
method render (line 636) | public render(): MenuConfig {
method render (line 699) | public render(): MenuConfig {
method render (line 786) | public render(): MenuConfig {
method render (line 892) | public render(): MenuConfig {
class TestTune1 (line 305) | class TestTune1 {
method render (line 309) | public render(): HTMLElement {
class TestTune2 (line 322) | class TestTune2 {
method render (line 326) | public render(): HTMLElement {
class TestTune (line 396) | class TestTune {
method render (line 257) | public render(): HTMLElement {
method render (line 400) | public render(): MenuConfig {
method render (line 476) | public render(): MenuConfig {
method render (line 585) | public render(): MenuConfig {
method render (line 636) | public render(): MenuConfig {
method render (line 699) | public render(): MenuConfig {
method render (line 786) | public render(): MenuConfig {
method render (line 892) | public render(): MenuConfig {
class TestTune (line 472) | class TestTune {
method render (line 257) | public render(): HTMLElement {
method render (line 400) | public render(): MenuConfig {
method render (line 476) | public render(): MenuConfig {
method render (line 585) | public render(): MenuConfig {
method render (line 636) | public render(): MenuConfig {
method render (line 699) | public render(): MenuConfig {
method render (line 786) | public render(): MenuConfig {
method render (line 892) | public render(): MenuConfig {
class TestTune (line 581) | class TestTune {
method render (line 257) | public render(): HTMLElement {
method render (line 400) | public render(): MenuConfig {
method render (line 476) | public render(): MenuConfig {
method render (line 585) | public render(): MenuConfig {
method render (line 636) | public render(): MenuConfig {
method render (line 699) | public render(): MenuConfig {
method render (line 786) | public render(): MenuConfig {
method render (line 892) | public render(): MenuConfig {
class TestTune (line 632) | class TestTune {
method render (line 257) | public render(): HTMLElement {
method render (line 400) | public render(): MenuConfig {
method render (line 476) | public render(): MenuConfig {
method render (line 585) | public render(): MenuConfig {
method render (line 636) | public render(): MenuConfig {
method render (line 699) | public render(): MenuConfig {
method render (line 786) | public render(): MenuConfig {
method render (line 892) | public render(): MenuConfig {
class TestTune (line 695) | class TestTune {
method render (line 257) | public render(): HTMLElement {
method render (line 400) | public render(): MenuConfig {
method render (line 476) | public render(): MenuConfig {
method render (line 585) | public render(): MenuConfig {
method render (line 636) | public render(): MenuConfig {
method render (line 699) | public render(): MenuConfig {
method render (line 786) | public render(): MenuConfig {
method render (line 892) | public render(): MenuConfig {
class TestTune (line 782) | class TestTune {
method render (line 257) | public render(): HTMLElement {
method render (line 400) | public render(): MenuConfig {
method render (line 476) | public render(): MenuConfig {
method render (line 585) | public render(): MenuConfig {
method render (line 636) | public render(): MenuConfig {
method render (line 699) | public render(): MenuConfig {
method render (line 786) | public render(): MenuConfig {
method render (line 892) | public render(): MenuConfig {
class TestTune (line 888) | class TestTune {
method render (line 257) | public render(): HTMLElement {
method render (line 400) | public render(): MenuConfig {
method render (line 476) | public render(): MenuConfig {
method render (line 585) | public render(): MenuConfig {
method render (line 636) | public render(): MenuConfig {
method render (line 699) | public render(): MenuConfig {
method render (line 786) | public render(): MenuConfig {
method render (line 892) | public render(): MenuConfig {
FILE: types/api/block.d.ts
type BlockAPI (line 7) | interface BlockAPI {
FILE: types/api/blocks.d.ts
type Blocks (line 9) | interface Blocks {
FILE: types/api/caret.d.ts
type Caret (line 6) | interface Caret {
FILE: types/api/events.d.ts
type Events (line 4) | interface Events {
FILE: types/api/i18n.d.ts
type I18n (line 4) | interface I18n {
FILE: types/api/inline-toolbar.d.ts
type InlineToolbar (line 4) | interface InlineToolbar {
FILE: types/api/listeners.d.ts
type Listeners (line 4) | interface Listeners {
FILE: types/api/notifier.d.ts
type Notifier (line 6) | interface Notifier {
FILE: types/api/readonly.d.ts
type ReadOnly (line 4) | interface ReadOnly {
FILE: types/api/sanitizer.d.ts
type Sanitizer (line 6) | interface Sanitizer {
FILE: types/api/saver.d.ts
type Saver (line 6) | interface Saver {
FILE: types/api/selection.d.ts
type Selection (line 4) | interface Selection {
FILE: types/api/styles.d.ts
type Styles (line 4) | interface Styles {
FILE: types/api/toolbar.d.ts
type Toolbar (line 4) | interface Toolbar {
FILE: types/api/tools.d.ts
type Tools (line 6) | interface Tools {
FILE: types/api/tooltip.d.ts
type Tooltip (line 6) | interface Tooltip {
FILE: types/api/ui.d.ts
type Ui (line 4) | interface Ui {
type UiNodes (line 14) | interface UiNodes {
FILE: types/block-tunes/block-tune-data.d.ts
type BlockTuneData (line 1) | type BlockTuneData = any;
FILE: types/block-tunes/block-tune.d.ts
type BlockTune (line 8) | interface BlockTune {
type BlockTuneConstructable (line 36) | interface BlockTuneConstructable {
FILE: types/configs/conversion-config.ts
type ConversionConfig (line 6) | interface ConversionConfig {
FILE: types/configs/editor-config.d.ts
type EditorConfig (line 7) | interface EditorConfig {
FILE: types/configs/i18n-config.d.ts
type I18nConfig (line 6) | interface I18nConfig {
FILE: types/configs/i18n-dictionary.d.ts
type I18nDictionary (line 4) | interface I18nDictionary {
type Dictionary (line 64) | interface Dictionary {
type DictValue (line 92) | type DictValue = {[key: string]: Dictionary | string} | string;
FILE: types/configs/log-levels.d.ts
type LogLevels (line 4) | enum LogLevels {
FILE: types/configs/paste-config.d.ts
type PasteConfigSpecified (line 6) | interface PasteConfigSpecified {
type PasteConfig (line 38) | type PasteConfig = PasteConfigSpecified | false;
FILE: types/configs/sanitizer-config.d.ts
type TagConfig (line 5) | type TagConfig = boolean | { [attr: string]: boolean | string };
type SanitizerRule (line 7) | type SanitizerRule = TagConfig | ((el: Element) => TagConfig)
type SanitizerConfig (line 9) | interface SanitizerConfig {
FILE: types/data-formats/block-data.d.ts
type SavedData (line 7) | interface SavedData {
type ValidatedData (line 17) | interface ValidatedData {
FILE: types/data-formats/block-id.ts
type BlockId (line 4) | type BlockId = string;
FILE: types/data-formats/output-data.d.ts
type OutputBlockData (line 11) | interface OutputBlockData<Type extends string = string, Data extends obj...
type OutputData (line 31) | interface OutputData {
FILE: types/events/block/Base.ts
type BlockMutationEventDetail (line 6) | interface BlockMutationEventDetail {
FILE: types/events/block/BlockAdded.ts
type BlockAddedEventDetail (line 11) | interface BlockAddedEventDetail extends BlockMutationEventDetail {
type BlockAddedEvent (line 21) | type BlockAddedEvent = CustomEvent<BlockAddedEventDetail>;
FILE: types/events/block/BlockChanged.ts
type BlockChangedEventDetail (line 11) | interface BlockChangedEventDetail extends BlockMutationEventDetail {
type BlockChangedEvent (line 21) | type BlockChangedEvent = CustomEvent<BlockChangedEventDetail>;
FILE: types/events/block/BlockMoved.ts
type BlockMovedEventDetail (line 11) | interface BlockMovedEventDetail extends BlockMutationEventDetail {
type BlockMovedEvent (line 26) | type BlockMovedEvent = CustomEvent<BlockMovedEventDetail>;
FILE: types/events/block/BlockRemoved.ts
type BlockRemovedEventDetail (line 11) | interface BlockRemovedEventDetail extends BlockMutationEventDetail {
type BlockRemovedEvent (line 21) | type BlockRemovedEvent = CustomEvent<BlockRemovedEventDetail>;
FILE: types/events/block/index.ts
type BlockMutationEventMap (line 9) | interface BlockMutationEventMap {
type BlockMutationType (line 34) | type BlockMutationType = keyof BlockMutationEventMap;
type ValueOf (line 39) | type ValueOf<T> = T[keyof T];
type BlockMutationEvent (line 44) | type BlockMutationEvent = ValueOf<BlockMutationEventMap>;
FILE: types/index.d.ts
type API (line 106) | interface API {
class EditorJS (line 128) | class EditorJS {
FILE: types/tools/adapters/base-tool-adapter.d.ts
type BaseToolAdapter (line 9) | interface BaseToolAdapter<Type extends ToolType, ToolClass extends Tool> {
FILE: types/tools/adapters/block-tool-adapter.d.ts
type BlockToolAdapter (line 14) | interface BlockToolAdapter extends BaseToolAdapter<ToolType.Block, Block...
FILE: types/tools/adapters/block-tune-adapter.d.ts
type BlockTuneAdapter (line 6) | interface BlockTuneAdapter extends BaseToolAdapter<ToolType.Tune, BlockT...
FILE: types/tools/adapters/inline-tool-adapter.d.ts
type InlineToolAdapter (line 5) | interface InlineToolAdapter extends BaseToolAdapter<ToolType.Inline, Inl...
FILE: types/tools/adapters/tool-factory.d.ts
type ToolFactory (line 5) | type ToolFactory = BlockToolAdapter | InlineToolAdapter | BlockTuneAdapter;
FILE: types/tools/adapters/tool-type.ts
type ToolType (line 4) | enum ToolType {
FILE: types/tools/adapters/tools-collection.d.ts
type ToolsCollection (line 9) | interface ToolsCollection<V extends ToolFactory = ToolFactory> {
FILE: types/tools/block-tool-data.d.ts
type BlockToolData (line 5) | type BlockToolData<T extends object = any> = T;
FILE: types/tools/block-tool.d.ts
type BlockTool (line 14) | interface BlockTool extends BaseTool {
type BlockToolConstructorOptions (line 86) | interface BlockToolConstructorOptions<D extends object = any, C extends ...
type BlockToolConstructable (line 92) | interface BlockToolConstructable extends BaseToolConstructable {
FILE: types/tools/hook-events.d.ts
type MoveEventDetail (line 4) | interface MoveEventDetail {
type MoveEvent (line 18) | interface MoveEvent extends CustomEvent {
FILE: types/tools/index.d.ts
type Tool (line 15) | type Tool = BlockTool | InlineTool | BlockTune;
type ToolConstructable (line 16) | type ToolConstructable = BlockToolConstructable | InlineToolConstructabl...
FILE: types/tools/inline-tool.d.ts
type InlineTool (line 7) | interface InlineTool extends BaseTool<HTMLElement | MenuConfig> {
type InlineToolConstructorOptions (line 48) | interface InlineToolConstructorOptions {
type InlineToolConstructable (line 53) | interface InlineToolConstructable extends BaseToolConstructable {
FILE: types/tools/menu-config.d.ts
type MenuConfig (line 7) | type MenuConfig = MenuConfigItem | MenuConfigItem[];
type MenuConfigDefaultBaseParams (line 12) | type MenuConfigDefaultBaseParams = PopoverItemDefaultBaseParams & {
type MenuConfigItemDefaultWithConfirmationParams (line 25) | type MenuConfigItemDefaultWithConfirmationParams = Omit<MenuConfigDefaul...
type MenuConfigItemDefaultParams (line 42) | type MenuConfigItemDefaultParams =
type MenuConfigItem (line 50) | type MenuConfigItem =
FILE: types/tools/paste-events.d.ts
type HTMLPasteEventDetail (line 4) | interface HTMLPasteEventDetail {
type HTMLPasteEvent (line 14) | interface HTMLPasteEvent extends CustomEvent {
type FilePasteEventDetail (line 21) | interface FilePasteEventDetail {
type FilePasteEvent (line 28) | interface FilePasteEvent extends CustomEvent {
type PatternPasteEventDetail (line 35) | interface PatternPasteEventDetail {
type PatternPasteEvent (line 47) | interface PatternPasteEvent extends CustomEvent {
type PasteEvent (line 51) | type PasteEvent = HTMLPasteEvent | FilePasteEvent | PatternPasteEvent;
type PasteEventDetail (line 52) | type PasteEventDetail = HTMLPasteEventDetail | FilePasteEventDetail | Pa...
FILE: types/tools/tool-config.d.ts
type ToolConfig (line 4) | type ToolConfig<T extends object = any> = T;
FILE: types/tools/tool-settings.d.ts
type ToolboxConfig (line 8) | type ToolboxConfig = ToolboxConfigEntry | ToolboxConfigEntry[];
type ToolboxConfigEntry (line 13) | interface ToolboxConfigEntry {
type ExternalToolSettings (line 35) | interface ExternalToolSettings<Config extends object = any> {
type TunesMenuConfig (line 75) | type TunesMenuConfig = MenuConfig;
type TunesMenuConfigItem (line 81) | type TunesMenuConfigItem = MenuConfigItem;
type InternalToolSettings (line 86) | type InternalToolSettings<Config extends object = any> = Omit<ExternalTo...
type ToolSettings (line 91) | type ToolSettings<Config extends object = any> = InternalToolSettings<Co...
FILE: types/tools/tool.d.ts
type BaseTool (line 9) | interface BaseTool<RenderReturnType = HTMLElement> {
type BaseToolConstructorOptions (line 21) | interface BaseToolConstructorOptions<C extends object = any> {
type BaseToolConstructable (line 33) | interface BaseToolConstructable {
FILE: types/utils/popover/hint.d.ts
type HintParams (line 4) | interface HintParams {
type HintPosition (line 24) | type HintPosition = 'top' | 'bottom' | 'left' | 'right';
type HintTextAlignment (line 29) | type HintTextAlignment = 'start' | 'center';
FILE: types/utils/popover/popover-event.ts
type PopoverEvent (line 5) | enum PopoverEvent {
FILE: types/utils/popover/popover-item-type.ts
type PopoverItemType (line 4) | enum PopoverItemType {
FILE: types/utils/popover/popover-item.d.ts
type PopoverItemChildren (line 9) | interface PopoverItemChildren {
type WithChildren (line 47) | type WithChildren<T> = Omit<T, 'onActivate'> & {
type PopoverItemDefaultWithConfirmationParams (line 62) | type PopoverItemDefaultWithConfirmationParams = Omit<PopoverItemDefaultB...
type PopoverItemSeparatorParams (line 79) | interface PopoverItemSeparatorParams {
type PopoverItemHtmlParams (line 89) | interface PopoverItemHtmlParams {
type PopoverItemDefaultBaseParams (line 120) | interface PopoverItemDefaultBaseParams {
type PopoverItemDefaultParams (line 186) | type PopoverItemDefaultParams =
type PopoverItemParams (line 194) | type PopoverItemParams =
type PopoverItemHintRenderParams (line 203) | type PopoverItemHintRenderParams = {
type PopoverItemRenderParamsMap (line 228) | type PopoverItemRenderParamsMap = {
FILE: types/utils/popover/popover.d.ts
type PopoverParams (line 7) | interface PopoverParams {
type PopoverMessages (line 50) | interface PopoverMessages {
type PopoverEventMap (line 62) | interface PopoverEventMap {
type PopoverNodes (line 78) | interface PopoverNodes {
type PopoverMobileNodes (line 95) | interface PopoverMobileNodes extends PopoverNodes {
FILE: vite.config.js
constant NODE_ENV (line 8) | const NODE_ENV = process.argv.mode || 'development';
constant VERSION (line 9) | const VERSION = pkg.version;
Condensed preview — 304 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,257K chars).
[
{
"path": ".editorconfig",
"chars": 148,
"preview": "root = false\n\n[*]\ncharset = utf-8\nindent_style = space\nindent_size = 2\nend_of_line = lf\ninsert_final_newline = true\ntrim"
},
{
"path": ".eslintignore",
"chars": 68,
"preview": "node_modules\n*.d.ts\nsrc/components/tools/paragraph\nsrc/polyfills.ts\n"
},
{
"path": ".eslintrc",
"chars": 1285,
"preview": "{\n \"extends\": [\n \"codex/ts\"\n ],\n \"globals\": {\n \"Node\": true,\n \"Range\": true,\n \"HTMLElement\": true,\n \"H"
},
{
"path": ".github/CODE_OF_CONDUCT.md",
"chars": 3345,
"preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, w"
},
{
"path": ".github/FUNDING.yml",
"chars": 122,
"preview": "# These are supported funding model platforms\n\npatreon: editorjs\nopen_collective: editorjs\ncustom: https://codex.so/dona"
},
{
"path": ".github/ISSUE_TEMPLATE/bug_report.md",
"chars": 417,
"preview": "---\nname: Bug report\nabout: Create a report to help us improve Editor.js\ntitle: \"\"\nlabels: bug\nassignees: ''\n\n---\n\nDescr"
},
{
"path": ".github/ISSUE_TEMPLATE/config.yml",
"chars": 437,
"preview": "blank_issues_enabled: false\ncontact_links:\n - name: Team\n url: mailto:team@codex.so\n about: Direct team contact.\n"
},
{
"path": ".github/ISSUE_TEMPLATE/general_issue.md",
"chars": 320,
"preview": "---\nname: General Issue\nabout: Well-designed, algorithmized feature/idea/improvement issue for Editor.js\ntitle: ''\nlabel"
},
{
"path": ".github/workflows/bump-version-on-merge-next.yml",
"chars": 3182,
"preview": "name: Bump version on merge\n\n# Caution:\n# the use of \"pull_request_target\" trigger allows to successfully\n# run workflow"
},
{
"path": ".github/workflows/create-a-release-draft.yml",
"chars": 4715,
"preview": "name: Create a release draft\n\n# Caution:\n# the use of \"pull_request_target\" trigger allows to successfully\n# run workflo"
},
{
"path": ".github/workflows/cypress.yml",
"chars": 601,
"preview": "name: Cypress\n\non: [pull_request]\n\njobs:\n run-tests:\n strategy:\n matrix:\n browser: [firefox, chrome, edg"
},
{
"path": ".github/workflows/eslint.yml",
"chars": 496,
"preview": "name: ESLint CodeX\n\non: [pull_request]\n\njobs:\n lint:\n name: ESlint\n runs-on: ubuntu-latest\n steps:\n - use"
},
{
"path": ".github/workflows/publish-package-to-npm.yml",
"chars": 1915,
"preview": "name: Publish package to NPM\n\non:\n release:\n types:\n - published\n\njobs:\n publish:\n runs-on: ubuntu-latest\n "
},
{
"path": ".gitignore",
"chars": 232,
"preview": "# --- proj files ---\n.DS_Store\nThumbs.db\n/.idea/\n/*.sublime-project\n/*.sublime-workspace\n\nnode_modules/*\n\nnpm-debug.log\n"
},
{
"path": ".npmignore",
"chars": 64,
"preview": "*\n!/dist/**/*\n!/types/**/*\n!/LICENSE\n!/README.md\n!/package.json\n"
},
{
"path": ".nvmrc",
"chars": 9,
"preview": "v18.20.1\n"
},
{
"path": ".postcssrc.yml",
"chars": 1039,
"preview": "plugins:\n # Apply custom property sets via @apply rule\n # https://github.com/pascalduez/postcss-apply\n postcss-apply:"
},
{
"path": ".stylelintrc",
"chars": 5470,
"preview": "{\n \"rules\": {\n \"at-rule-empty-line-before\": [\n \"always\",\n {\n except: [\n \"blockless-after-s"
},
{
"path": ".vscode/settings.json",
"chars": 743,
"preview": "{\n \"cSpell.words\": [\n \"autofocused\",\n \"Behaviour\",\n \"cacheable\",\n \"childs\",\n \"codexteam\",\n "
},
{
"path": "CODEOWNERS",
"chars": 57,
"preview": "* @neSpecc @gohabereg @TatianaFomina @ilyamore88\n\n"
},
{
"path": "LICENSE",
"chars": 10760,
"preview": " Apache License\n Version 2.0, January 2004\n "
},
{
"path": "README.md",
"chars": 9375,
"preview": "<p align=\"center\">\n <a href=\"https://editorjs.io/\">\n <picture>\n <source media=\"(prefers-color-scheme: dark)\" s"
},
{
"path": "cypress.config.ts",
"chars": 1307,
"preview": "import { defineConfig } from 'cypress';\nimport path from 'node:path';\nimport vitePreprocessor from 'cypress-vite';\n\nexpo"
},
{
"path": "docs/CHANGELOG.md",
"chars": 46962,
"preview": "# Changelog\n\n### 2.31.5\n\n- `Fix` - Handle __Ctrl + click__ on links with inline styles applied (e.g., bold, italic)\n\n###"
},
{
"path": "docs/api.md",
"chars": 8427,
"preview": "# Editor.js API\n\n---\nMost actual API described by [this interface](../types/api/index.d.ts).\n\n---\n📃 See official API doc"
},
{
"path": "docs/block-tunes.md",
"chars": 3667,
"preview": "# Block Tunes\n\nSimilar with [Tools](tools.md) represented Blocks, you can create Block Tunes and connect it to particula"
},
{
"path": "docs/caret.md",
"chars": 1066,
"preview": "# Editor.js Caret Module\n\nThe `Caret` module contains methods working with caret. Uses [Range](https://developer.mozilla"
},
{
"path": "docs/installation.md",
"chars": 4826,
"preview": "# Installation Guide\n\nThere are few steps to run Editor.js on your site.\n\n1. [Load Editor's core](#load-editors-core)\n2."
},
{
"path": "docs/releases.md",
"chars": 4503,
"preview": "# Branches, versions and releases — complete guideline\n\n## Branches\n\nThe project has two main branches: `master` and `ne"
},
{
"path": "docs/sanitizer.md",
"chars": 578,
"preview": "# Editor.js Sanitizer Module\n\nThe `Sanitizer` module represents a set of methods that clears taint strings.\nUses lightwe"
},
{
"path": "docs/toolbar-settings.md",
"chars": 2299,
"preview": "# Editor.js Toolbar Block Settings Module\n\nToolbar Module has space for Block settings. Settings divided into:\n - space "
},
{
"path": "docs/tools-inline.md",
"chars": 3474,
"preview": "# Tools for the Inline Toolbar\n\nSimilar with [Tools](tools.md) represented Blocks, you can create Tools for the Inline T"
},
{
"path": "docs/tools.md",
"chars": 15479,
"preview": "# Editor.js Tools\n\nEditor.js is a block-oriented editor. It means that entry composed with the list of `Blocks` of diffe"
},
{
"path": "docs/usage.md",
"chars": 3166,
"preview": "# So how to use Editor.js\n\n## Basics\n\nEditor.js is a Block-Styled editor. Blocks is a structural units, of which the Ent"
},
{
"path": "example/example-i18n.html",
"chars": 14335,
"preview": "<!--\n This page contains example of editor.js internalization.\n See <script> section -> i18n property of the configura"
},
{
"path": "example/example-multiple.html",
"chars": 2343,
"preview": "\n<!--\n Use this page for debugging purposes.\n\n This page can be used for testing multiple editor instances on the same p"
},
{
"path": "example/example-popup.html",
"chars": 5952,
"preview": "\n<!--\n Use this page for debugging purposes.\n\n This page can be used for testing editor nested in a popup.\n -->\n <!DOCTY"
},
{
"path": "example/example-rtl.html",
"chars": 6677,
"preview": "<!--\n Use this page for RTL mode debugging.\n Editor Tools are loaded as git-submodules.\n You can pull modules by running"
},
{
"path": "example/example.html",
"chars": 10603,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <title>Editor.js 🤩🧦🤨 example</title>\n <link href=\"ht"
},
{
"path": "index.html",
"chars": 13498,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <title>Editor.js 🤩🧦🤨 example</title>\n <link href=\"ht"
},
{
"path": "package.json",
"chars": 2276,
"preview": "{\n \"name\": \"@editorjs/editorjs\",\n \"version\": \"2.31.5\",\n \"description\": \"Editor.js — open source block-style WYSIWYG e"
},
{
"path": "public/assets/demo.css",
"chars": 8025,
"preview": "/**\n * Styles for the example page\n */\n\n:root {\n --color-bg-main: #fff;\n --color-border-light: #E8E8EB;\n --color-text"
},
{
"path": "public/assets/json-preview.js",
"chars": 1457,
"preview": "/**\n * Module to compose output JSON preview\n */\nconst cPreview = (function (module) {\n /**\n * Shows JSON in pretty p"
},
{
"path": "src/codex.ts",
"chars": 3340,
"preview": "'use strict';\n\nimport type { EditorConfig } from '../types';\n\n/**\n * Apply polyfills\n */\nimport '@babel/register';\n\nimpo"
},
{
"path": "src/components/__module.ts",
"chars": 3572,
"preview": "import type { EditorModules } from '../types-internal/editor-modules';\nimport type { EditorConfig } from '../../types';\n"
},
{
"path": "src/components/block/api.ts",
"chars": 3223,
"preview": "import type Block from './index';\nimport type { BlockToolData, ToolConfig, ToolboxConfigEntry } from '../../../types/too"
},
{
"path": "src/components/block/index.ts",
"chars": 28082,
"preview": "import type {\n BlockAPI as BlockAPIInterface,\n BlockTool as IBlockTool,\n BlockToolData,\n BlockTune as IBlockTune,\n "
},
{
"path": "src/components/block-tunes/block-tune-delete.ts",
"chars": 1144,
"preview": "/**\n * @class DeleteTune\n * @classdesc Editor's default tune that moves up selected block\n * @copyright <CodeX Team> 201"
},
{
"path": "src/components/block-tunes/block-tune-move-down.ts",
"chars": 2063,
"preview": "/**\n * @class MoveDownTune\n * @classdesc Editor's default tune - Moves down highlighted block\n * @copyright <CodeX Team>"
},
{
"path": "src/components/block-tunes/block-tune-move-up.ts",
"chars": 2587,
"preview": "/**\n * @class MoveUpTune\n * @classdesc Editor's default tune that moves up selected block\n * @copyright <CodeX Team> 201"
},
{
"path": "src/components/blocks.ts",
"chars": 9008,
"preview": "import * as _ from './utils';\nimport $ from './dom';\nimport type Block from './block';\nimport { BlockToolAPI } from './b"
},
{
"path": "src/components/constants.ts",
"chars": 310,
"preview": "/**\n * Debounce timeout for selection change event\n * {@link modules/ui.ts}\n */\nexport const selectionChangeDebounceTime"
},
{
"path": "src/components/core.ts",
"chars": 9249,
"preview": "import $ from './dom';\nimport * as _ from './utils';\nimport type { EditorConfig, SanitizerConfig } from '../../types';\ni"
},
{
"path": "src/components/dom.ts",
"chars": 21433,
"preview": "import * as _ from './utils';\n\n/**\n * DOM manipulations helper\n *\n * @todo get rid of class and make separate utility fu"
},
{
"path": "src/components/domIterator.ts",
"chars": 4938,
"preview": "import Dom from './dom';\nimport * as _ from './utils';\nimport SelectionUtils from './selection';\n\n/**\n * Iterator above "
},
{
"path": "src/components/errors/critical.ts",
"chars": 129,
"preview": "/**\n * This type of exception will destroy the Editor! Be careful when using it\n */\nexport class CriticalError extends E"
},
{
"path": "src/components/events/BlockChanged.ts",
"chars": 348,
"preview": "import type { BlockMutationEvent } from '../../../types/events/block';\n\n/**\n * Fired when some block state has changed\n "
},
{
"path": "src/components/events/BlockHovered.ts",
"chars": 276,
"preview": "import type Block from '../block';\n\n/**\n * Fired when some block is hovered by user\n */\nexport const BlockHovered = 'blo"
},
{
"path": "src/components/events/EditorMobileLayoutToggled.ts",
"chars": 304,
"preview": "/**\n * Fired when editor mobile layout toggled\n */\nexport const EditorMobileLayoutToggled = 'editor mobile layout toggle"
},
{
"path": "src/components/events/FakeCursorAboutToBeToggled.ts",
"chars": 407,
"preview": "/**\n * Fired before we're adding/removing a fake cursor.\n *\n * Allows to disable mutation observer to skip this block ch"
},
{
"path": "src/components/events/FakeCursorHaveBeenSet.ts",
"chars": 392,
"preview": "/**\n * Fired after we've added/removed a fake cursor.\n *\n * Allows to enable mutation observer which was disabled before"
},
{
"path": "src/components/events/RedactorDomChanged.ts",
"chars": 321,
"preview": "/**\n * Fired when blocks wrapper (.codex-editor-redactor) dom changed\n */\nexport const RedactorDomChanged = 'redactor do"
},
{
"path": "src/components/events/index.ts",
"chars": 1349,
"preview": "import type { RedactorDomChangedPayload } from './RedactorDomChanged';\nimport { RedactorDomChanged } from './RedactorDom"
},
{
"path": "src/components/flipper.ts",
"chars": 7637,
"preview": "import DomIterator from './domIterator';\nimport * as _ from './utils';\n\n/**\n * Flipper construction options\n *\n * @inter"
},
{
"path": "src/components/i18n/index.ts",
"chars": 2879,
"preview": "import defaultDictionary from './locales/en/messages.json';\nimport type { I18nDictionary, Dictionary } from '../../../ty"
},
{
"path": "src/components/i18n/locales/en/messages.json",
"chars": 783,
"preview": "{\n \"ui\": {\n \"blockTunes\": {\n \"toggler\": {\n \"Click to tune\": \"\",\n \"or drag to move\": \"\"\n }\n "
},
{
"path": "src/components/i18n/namespace-internal.ts",
"chars": 1585,
"preview": "import defaultDictionary from './locales/en/messages.json';\nimport type { DictNamespaces } from '../../types-internal/i1"
},
{
"path": "src/components/inline-tools/inline-tool-bold.ts",
"chars": 1221,
"preview": "import type { InlineTool, SanitizerConfig } from '../../../types';\nimport { IconBold } from '@codexteam/icons';\nimport t"
},
{
"path": "src/components/inline-tools/inline-tool-convert.ts",
"chars": 3246,
"preview": "import { IconReplace } from '@codexteam/icons';\nimport type { InlineTool, API } from '../../../types';\nimport type { Men"
},
{
"path": "src/components/inline-tools/inline-tool-italic.ts",
"chars": 1898,
"preview": "import type { InlineTool, SanitizerConfig } from '../../../types';\nimport { IconItalic } from '@codexteam/icons';\n\n/**\n "
},
{
"path": "src/components/inline-tools/inline-tool-link.ts",
"chars": 9813,
"preview": "import SelectionUtils from '../selection';\nimport * as _ from '../utils';\nimport type { InlineTool, SanitizerConfig, API"
},
{
"path": "src/components/modules/api/blocks.ts",
"chars": 12804,
"preview": "import type { BlockAPI as BlockAPIInterface, Blocks } from '../../../../types/api';\nimport type { BlockToolData, OutputB"
},
{
"path": "src/components/modules/api/caret.ts",
"chars": 3540,
"preview": "import type { BlockAPI, Caret } from '../../../../types/api';\nimport Module from '../../__module';\nimport { resolveBlock"
},
{
"path": "src/components/modules/api/events.ts",
"chars": 1316,
"preview": "import Module from '../../__module';\nimport type { Events } from '../../../../types/api';\n\n/**\n * @class EventsAPI\n * pr"
},
{
"path": "src/components/modules/api/i18n.ts",
"chars": 1277,
"preview": "import type { I18n } from '../../../../types/api';\nimport I18nInternal from '../../i18n';\nimport { logLabeled } from '.."
},
{
"path": "src/components/modules/api/index.ts",
"chars": 1600,
"preview": "/**\n * @module API\n * @copyright <CodeX> 2018\n *\n * Each block has an Editor API instance to use provided public methods"
},
{
"path": "src/components/modules/api/inlineToolbar.ts",
"chars": 687,
"preview": "import type { InlineToolbar } from '../../../../types/api/inline-toolbar';\nimport Module from '../../__module';\n\n/**\n * "
},
{
"path": "src/components/modules/api/listeners.ts",
"chars": 1697,
"preview": "import type { Listeners } from '../../../../types/api';\nimport Module from '../../__module';\n\n/**\n * @class ListenersAPI"
},
{
"path": "src/components/modules/api/notifier.ts",
"chars": 1275,
"preview": "import type { Notifier as INotifier } from '../../../../types/api';\nimport Notifier from '../../utils/notifier';\nimport "
},
{
"path": "src/components/modules/api/readonly.ts",
"chars": 942,
"preview": "import type { ReadOnly } from '../../../../types/api';\nimport Module from '../../__module';\n\n/**\n * @class ReadOnlyAPI\n "
},
{
"path": "src/components/modules/api/sanitizer.ts",
"chars": 891,
"preview": "import type { Sanitizer as ISanitizer } from '../../../../types/api';\nimport type { SanitizerConfig } from '../../../../"
},
{
"path": "src/components/modules/api/saver.ts",
"chars": 831,
"preview": "import type { Saver } from '../../../../types/api';\nimport type { OutputData } from '../../../../types';\nimport * as _ f"
},
{
"path": "src/components/modules/api/selection.ts",
"chars": 1572,
"preview": "import SelectionUtils from '../../selection';\nimport type { Selection as SelectionAPIInterface } from '../../../../types"
},
{
"path": "src/components/modules/api/styles.ts",
"chars": 738,
"preview": "import type { Styles } from '../../../../types/api';\nimport Module from '../../__module';\n\n/**\n *\n */\nexport default cla"
},
{
"path": "src/components/modules/api/toolbar.ts",
"chars": 2135,
"preview": "import type { Toolbar } from '../../../../types/api';\nimport Module from '../../__module';\nimport * as _ from './../../u"
},
{
"path": "src/components/modules/api/tools.ts",
"chars": 406,
"preview": "import type { Tools as ToolsAPIInterface } from '../../../../types/api';\nimport Module from '../../__module';\n\n/**\n * Pr"
},
{
"path": "src/components/modules/api/tooltip.ts",
"chars": 2117,
"preview": "import type { Tooltip as ITooltip } from '../../../../types/api';\nimport type { TooltipOptions, TooltipContent } from 'c"
},
{
"path": "src/components/modules/api/ui.ts",
"chars": 744,
"preview": "import Module from '../../__module';\nimport type { Ui, UiNodes } from '../../../../types/api';\n\n/**\n * API module allowi"
},
{
"path": "src/components/modules/blockEvents.ts",
"chars": 19764,
"preview": "/**\n * Contains keyboard and mouse events bound on each Block by Block Manager\n */\nimport Module from '../__module';\nimp"
},
{
"path": "src/components/modules/blockManager.ts",
"chars": 27611,
"preview": "/**\n * @class BlockManager\n * @classdesc Manage editor`s blocks storage and appearance\n * @module BlockManager\n * @versi"
},
{
"path": "src/components/modules/blockSelection.ts",
"chars": 11485,
"preview": "/**\n * @class BlockSelection\n * @classdesc Manages Block selection with shortcut CMD+A\n * @module BlockSelection\n * @ver"
},
{
"path": "src/components/modules/caret.ts",
"chars": 12786,
"preview": "import Selection from '../selection';\nimport Module from '../__module';\nimport type Block from '../block';\nimport * as c"
},
{
"path": "src/components/modules/crossBlockSelection.ts",
"chars": 7268,
"preview": "import Module from '../__module';\nimport type Block from '../block';\nimport SelectionUtils from '../selection';\nimport *"
},
{
"path": "src/components/modules/dragNDrop.ts",
"chars": 3003,
"preview": "import SelectionUtils from '../selection';\n\nimport Module from '../__module';\n/**\n *\n */\nexport default class DragNDrop "
},
{
"path": "src/components/modules/index.ts",
"chars": 1939,
"preview": "/** ./api */\nimport BlocksAPI from './api/blocks';\nimport CaretAPI from './api/caret';\nimport EventsAPI from './api/even"
},
{
"path": "src/components/modules/modificationsObserver.ts",
"chars": 3998,
"preview": "import type { BlockId } from '../../../types';\nimport type { BlockMutationEvent, BlockMutationType } from '../../../type"
},
{
"path": "src/components/modules/paste.ts",
"chars": 27942,
"preview": "import Module from '../__module';\nimport $ from '../dom';\nimport * as _ from '../utils';\nimport type {\n BlockAPI,\n Pas"
},
{
"path": "src/components/modules/readonly.ts",
"chars": 3249,
"preview": "import Module from '../__module';\nimport { CriticalError } from '../errors/critical';\n\n/**\n * @module ReadOnly\n *\n * Has"
},
{
"path": "src/components/modules/rectangleSelection.ts",
"chars": 15467,
"preview": "/**\n * @class RectangleSelection\n * @classdesc Manages Block selection with mouse\n * @module RectangleSelection\n * @vers"
},
{
"path": "src/components/modules/renderer.ts",
"chars": 3017,
"preview": "import Module from '../__module';\nimport * as _ from '../utils';\nimport type { BlockId, BlockToolData, OutputBlockData }"
},
{
"path": "src/components/modules/saver.ts",
"chars": 2707,
"preview": "/**\n * Editor.js Saver\n *\n * @module Saver\n * @author Codex Team\n * @version 2.0.0\n */\nimport Module from '../__module';"
},
{
"path": "src/components/modules/toolbar/blockSettings.ts",
"chars": 8486,
"preview": "import Module from '../../__module';\nimport $ from '../../dom';\nimport SelectionUtils from '../../selection';\nimport typ"
},
{
"path": "src/components/modules/toolbar/index.ts",
"chars": 20619,
"preview": "import Module from '../../__module';\nimport $, { calculateBaseline } from '../../dom';\nimport * as _ from '../../utils';"
},
{
"path": "src/components/modules/toolbar/inline.ts",
"chars": 15712,
"preview": "/* eslint-disable @typescript-eslint/no-non-null-assertion */\nimport Module from '../../__module';\nimport $ from '../../"
},
{
"path": "src/components/modules/tools.ts",
"chars": 11660,
"preview": "import Paragraph from '@editorjs/paragraph';\nimport Module from '../__module';\nimport * as _ from '../utils';\nimport typ"
},
{
"path": "src/components/modules/ui.ts",
"chars": 26654,
"preview": "/* eslint-disable jsdoc/no-undefined-types */\n/**\n * Module UI\n *\n * @type {UI}\n */\nimport Module from '../__module';\nim"
},
{
"path": "src/components/polyfills.ts",
"chars": 5636,
"preview": "'use strict';\n\n/**\n * Extend Element interface to include prefixed and experimental properties\n */\ninterface Element {\n "
},
{
"path": "src/components/selection.ts",
"chars": 13388,
"preview": "/**\n * TextRange interface for IE9-\n */\nimport * as _ from './utils';\nimport $ from './dom';\n\ninterface TextRange {\n bo"
},
{
"path": "src/components/tools/base.ts",
"chars": 6145,
"preview": "import type { Tool, ToolConstructable, ToolSettings } from '@/types/tools';\nimport type { SanitizerConfig, API as ApiMet"
},
{
"path": "src/components/tools/block.ts",
"chars": 6170,
"preview": "import BaseToolAdapter, { InternalBlockToolSettings, UserSettings } from './base';\nimport type {\n BlockAPI,\n BlockTool"
},
{
"path": "src/components/tools/collection.ts",
"chars": 1921,
"preview": "import type BlockToolAdapter from './block';\nimport type InlineToolAdapter from './inline';\nimport type BlockTuneAdapter"
},
{
"path": "src/components/tools/factory.ts",
"chars": 2363,
"preview": "import type { ToolConstructable, ToolSettings } from '../../../types/tools';\nimport { InternalInlineToolSettings, Intern"
},
{
"path": "src/components/tools/inline.ts",
"chars": 1406,
"preview": "import BaseToolAdapter, { InternalInlineToolSettings } from './base';\nimport type { InlineTool as IInlineTool, InlineToo"
},
{
"path": "src/components/tools/tune.ts",
"chars": 1127,
"preview": "import BaseToolAdapter from './base';\nimport type { BlockAPI, BlockTune as IBlockTune, BlockTuneConstructable } from '@/"
},
{
"path": "src/components/ui/toolbox.ts",
"chars": 11552,
"preview": "import * as _ from '../utils';\nimport { BlockToolAPI } from '../block';\nimport Shortcuts from '../utils/shortcuts';\nimpo"
},
{
"path": "src/components/utils/api.ts",
"chars": 721,
"preview": "import type { BlockAPI } from '../../../types/api/block';\nimport type { EditorModules } from '../../types-internal/edito"
},
{
"path": "src/components/utils/bem.ts",
"chars": 895,
"preview": "const ELEMENT_DELIMITER = '__';\nconst MODIFIER_DELIMITER = '--';\n\n/**\n * Utility function that allows to construct class"
},
{
"path": "src/components/utils/blocks.ts",
"chars": 6071,
"preview": "import type { BlockAPI, ToolConfig } from '../../../types';\nimport type { ConversionConfig } from '../../../types/config"
},
{
"path": "src/components/utils/caret.ts",
"chars": 5757,
"preview": "import $, { isCollapsedWhitespaces } from '../dom';\n\n/**\n * Returns TextNode containing a caret and a caret offset in it"
},
{
"path": "src/components/utils/events.ts",
"chars": 3344,
"preview": "import { isEmpty } from '../utils';\n\n/**\n * Event Dispatcher event listener\n */\ntype Listener<Data> = (data: Data) => vo"
},
{
"path": "src/components/utils/keyboard.ts",
"chars": 1918,
"preview": "declare global {\n /**\n * https://developer.mozilla.org/en-US/docs/Web/API/KeyboardLayoutMap\n */\n interface Keyboar"
},
{
"path": "src/components/utils/listeners.ts",
"chars": 6329,
"preview": "import * as _ from '../utils';\n\n/**\n * Event listener information\n *\n * @interface ListenerData\n */\nexport interface Lis"
},
{
"path": "src/components/utils/mutations.ts",
"chars": 1271,
"preview": "/**\n * Check if passed mutation belongs to a passed element\n *\n * @param mutationRecord - mutation to check\n * @param el"
},
{
"path": "src/components/utils/notifier.ts",
"chars": 611,
"preview": "/**\n * Use external package module for notifications\n *\n * @see https://github.com/codex-team/js-notifier\n */\nimport typ"
},
{
"path": "src/components/utils/popover/components/hint/hint.const.ts",
"chars": 380,
"preview": "import { bem } from '../../../bem';\n\n/**\n * Hint block CSS class constructor\n */\nconst className = bem('ce-hint');\n\n/**\n"
},
{
"path": "src/components/utils/popover/components/hint/hint.css",
"chars": 171,
"preview": ".ce-hint {\n &--align-start {\n text-align: start;\n }\n\n &--align-center {\n text-align: center;\n }\n\n &__descript"
},
{
"path": "src/components/utils/popover/components/hint/hint.ts",
"chars": 1149,
"preview": "import Dom from '../../../../dom';\nimport { css } from './hint.const';\nimport type { HintParams } from '@/types/utils/po"
},
{
"path": "src/components/utils/popover/components/hint/index.ts",
"chars": 125,
"preview": "export * from './hint';\nexport type {\n HintParams,\n HintPosition,\n HintTextAlignment\n} from '@/types/utils/popover/hi"
},
{
"path": "src/components/utils/popover/components/popover-header/index.ts",
"chars": 74,
"preview": "export * from './popover-header';\nexport * from './popover-header.types';\n"
},
{
"path": "src/components/utils/popover/components/popover-header/popover-header.const.ts",
"chars": 310,
"preview": "import { bem } from '../../../bem';\n\n/**\n * Popover header block CSS class constructor\n */\nconst className = bem('ce-pop"
},
{
"path": "src/components/utils/popover/components/popover-header/popover-header.ts",
"chars": 1674,
"preview": "import type { PopoverHeaderParams } from './popover-header.types';\nimport Dom from '../../../../dom';\nimport { css } fro"
},
{
"path": "src/components/utils/popover/components/popover-header/popover-header.types.ts",
"chars": 219,
"preview": "/**\n * Popover header params\n */\nexport interface PopoverHeaderParams {\n /**\n * Text to be displayed inside header\n "
},
{
"path": "src/components/utils/popover/components/popover-item/index.ts",
"chars": 494,
"preview": "import { PopoverItemDefault } from './popover-item-default/popover-item-default';\nimport { PopoverItemSeparator } from '"
},
{
"path": "src/components/utils/popover/components/popover-item/popover-item-default/popover-item-default.const.ts",
"chars": 768,
"preview": "import { bem } from '../../../../bem';\n\n/**\n * Popover item block CSS class constructor\n */\nconst className = bem('ce-po"
},
{
"path": "src/components/utils/popover/components/popover-item/popover-item-default/popover-item-default.ts",
"chars": 8601,
"preview": "import Dom from '../../../../../dom';\nimport { IconDotCircle, IconChevronRight } from '@codexteam/icons';\nimport type {\n"
},
{
"path": "src/components/utils/popover/components/popover-item/popover-item-html/popover-item-html.const.ts",
"chars": 282,
"preview": "import { bem } from '../../../../bem';\n\n/**\n * Popover item block CSS class constructor\n */\nconst className = bem('ce-po"
},
{
"path": "src/components/utils/popover/components/popover-item/popover-item-html/popover-item-html.ts",
"chars": 1912,
"preview": "import { PopoverItem } from '../popover-item';\nimport type { PopoverItemHtmlParams, PopoverItemRenderParamsMap, PopoverI"
},
{
"path": "src/components/utils/popover/components/popover-item/popover-item-separator/popover-item-separator.const.ts",
"chars": 329,
"preview": "import { bem } from '../../../../bem';\n\n/**\n * Popover separator block CSS class constructor\n */\nconst className = bem('"
},
{
"path": "src/components/utils/popover/components/popover-item/popover-item-separator/popover-item-separator.ts",
"chars": 913,
"preview": "import Dom from '../../../../../dom';\nimport { PopoverItem } from '../popover-item';\nimport { css } from './popover-item"
},
{
"path": "src/components/utils/popover/components/popover-item/popover-item.ts",
"chars": 4183,
"preview": "import * as tooltip from '../../../../utils/tooltip';\nimport { type HintPosition, Hint } from '../hint';\nimport type { P"
},
{
"path": "src/components/utils/popover/components/search-input/index.ts",
"chars": 70,
"preview": "export * from './search-input';\nexport * from './search-input.types';\n"
},
{
"path": "src/components/utils/popover/components/search-input/search-input.const.ts",
"chars": 313,
"preview": "import { bem } from '../../../bem';\n\n/**\n * Popover search input block CSS class constructor\n */\nconst className = bem('"
},
{
"path": "src/components/utils/popover/components/search-input/search-input.ts",
"chars": 3101,
"preview": "import Dom from '../../../../dom';\nimport Listeners from '../../../listeners';\nimport { IconSearch } from '@codexteam/ic"
},
{
"path": "src/components/utils/popover/components/search-input/search-input.types.ts",
"chars": 486,
"preview": "/**\n * Item that could be searched\n */\nexport interface SearchableItem {\n /**\n * Items title\n */\n title?: string;\n"
},
{
"path": "src/components/utils/popover/index.ts",
"chars": 440,
"preview": "import { PopoverDesktop } from './popover-desktop';\nimport { PopoverInline } from './popover-inline';\nimport { PopoverMo"
},
{
"path": "src/components/utils/popover/popover-abstract.ts",
"chars": 8058,
"preview": "import type { PopoverItem, PopoverItemRenderParamsMap } from './components/popover-item';\nimport { PopoverItemDefault, P"
},
{
"path": "src/components/utils/popover/popover-desktop.ts",
"chars": 13388,
"preview": "import Flipper from '../../flipper';\nimport { PopoverAbstract } from './popover-abstract';\nimport type { PopoverItem, Po"
},
{
"path": "src/components/utils/popover/popover-inline.ts",
"chars": 5154,
"preview": "import { isMobileScreen } from '../../utils';\nimport type { PopoverItem } from './components/popover-item';\nimport { Pop"
},
{
"path": "src/components/utils/popover/popover-mobile.ts",
"chars": 4219,
"preview": "import { PopoverAbstract } from './popover-abstract';\nimport ScrollLocker from '../scroll-locker';\nimport { PopoverHeade"
},
{
"path": "src/components/utils/popover/popover.const.ts",
"chars": 1592,
"preview": "import { bem } from '../bem';\n\n/**\n * Popover block CSS class constructor\n */\nconst className = bem('ce-popover');\n\n/**\n"
},
{
"path": "src/components/utils/popover/utils/popover-states-history.ts",
"chars": 1399,
"preview": "import type { PopoverItemParams } from '@/types/utils/popover/popover-item';\n\n/**\n * Represents single states history it"
},
{
"path": "src/components/utils/promise-queue.ts",
"chars": 769,
"preview": "/**\n * Class allows to make a queue of async jobs and wait until they all will be finished one by one\n *\n * @example con"
},
{
"path": "src/components/utils/resolve-aliases.ts",
"chars": 753,
"preview": "/**\n * Resolves aliases in specified object according to passed aliases info\n *\n * @example resolveAliases(obj, { label:"
},
{
"path": "src/components/utils/sanitizer.ts",
"chars": 4926,
"preview": "/* eslint-disable @typescript-eslint/no-use-before-define */\n/**\n * CodeX Sanitizer\n *\n * Clears HTML from taint tags\n *"
},
{
"path": "src/components/utils/scroll-locker.ts",
"chars": 1446,
"preview": "import { isIosDevice } from '../utils';\n\n/**\n * Utility allowing to lock body scroll on demand\n */\nexport default class "
},
{
"path": "src/components/utils/shortcuts.ts",
"chars": 2563,
"preview": "import Shortcut from '@codexteam/shortcuts';\n\n/**\n * Contains keyboard and mouse events binded on each Block by Block Ma"
},
{
"path": "src/components/utils/tools.ts",
"chars": 575,
"preview": "import type BlockToolAdapter from '../tools/block';\nimport { isFunction, isString } from '../utils';\n\n/**\n * Check if to"
},
{
"path": "src/components/utils/tooltip.ts",
"chars": 1639,
"preview": "/* eslint-disable jsdoc/no-undefined-types */\n/**\n * Use external module CodeX Tooltip\n */\nimport CodeXTooltips from 'co"
},
{
"path": "src/components/utils.ts",
"chars": 19841,
"preview": "/**\n * Class Util\n */\n\nimport { nanoid } from 'nanoid';\nimport Dom from './dom';\n\n/**\n * Possible log levels\n */\nexport "
},
{
"path": "src/env.d.ts",
"chars": 276,
"preview": "interface ImportMetaEnv {\n /**\n * Build environment.\n * For example, used to detect building for tests and add \"dat"
},
{
"path": "src/styles/animations.css",
"chars": 840,
"preview": "@keyframes bounceIn {\n from,\n 20%,\n 40%,\n 60%,\n 80%,\n to {\n animation-timing-function: cubic-bezier(0.215, 0.61"
},
{
"path": "src/styles/block.css",
"chars": 1537,
"preview": "@keyframes fade-in {\n from {\n opacity: 0;\n }\n\n to {\n opacity: 1;\n }\n}\n\n.ce-block {\n animation: fade-in 300ms "
},
{
"path": "src/styles/export.css",
"chars": 2797,
"preview": "/**\n * Block Tool wrapper\n */\n.cdx-block {\n padding: var(--block-padding-vertical) 0;\n\n &::-webkit-input-placeholder {"
},
{
"path": "src/styles/inline-toolbar.css",
"chars": 2782,
"preview": ".ce-inline-toolbar {\n --y-offset: 8px;\n\n /** These variables duplicate the ones defined in popover. @todo move them to"
},
{
"path": "src/styles/input.css",
"chars": 939,
"preview": ".cdx-search-field {\n --icon-margin-right: 10px;\n\n background: #F8F8F8;\n border: 1px solid rgba(226,226,229,0.20);\n b"
},
{
"path": "src/styles/main.css",
"chars": 358,
"preview": "@import './variables.css';\n@import './ui.css';\n@import './toolbar.css';\n@import './toolbox.css';\n@import './inline-toolb"
},
{
"path": "src/styles/placeholders.css",
"chars": 1215,
"preview": "\n/**\n * We support two types of placeholders for contenteditable:\n *\n * 1. Regular-like placeholders. Will be visible wh"
},
{
"path": "src/styles/popover-inline.css",
"chars": 2414,
"preview": "/**\n * Styles overrides for inline popover\n */\n.ce-popover--inline {\n --height: 38px;\n --height-mobile: 46px;\n --cont"
},
{
"path": "src/styles/popover.css",
"chars": 8323,
"preview": "/** \n * Popover styles\n *\n * @todo split into separate files popover styles\n * @todo make css variables work\n */\n.ce-pop"
},
{
"path": "src/styles/rtl.css",
"chars": 1285,
"preview": ".codex-editor.codex-editor--rtl {\n direction: rtl;\n\n .cdx-list {\n padding-left: 0;\n padding-right: 40px;\n }\n\n "
},
{
"path": "src/styles/stub.css",
"chars": 420,
"preview": ".ce-stub {\n display: flex;\n align-items: center;\n padding: 12px 18px;\n margin: 10px 0;\n border-radius: 10px;\n back"
},
{
"path": "src/styles/toolbar.css",
"chars": 1327,
"preview": ".ce-toolbar {\n position: absolute;\n left: 0;\n right: 0;\n top: 0;\n transition: opacity 100ms ease;\n will-change: op"
},
{
"path": "src/styles/toolbox.css",
"chars": 144,
"preview": ".ce-toolbox {\n\n}\n\n.codex-editor--narrow .ce-toolbox {\n @media (--not-mobile){\n .ce-popover {\n right: 0;\n l"
},
{
"path": "src/styles/ui.css",
"chars": 1823,
"preview": "/**\n* Editor wrapper\n*/\n.codex-editor {\n position: relative;\n box-sizing: border-box;\n z-index: 1;\n\n .hide {\n dis"
},
{
"path": "src/styles/variables.css",
"chars": 3633,
"preview": "/**\n * Updating values in media queries should also include changes in utils.ts@isMobile\n */\n@custom-media --mobile (wid"
},
{
"path": "src/tools/stub/index.ts",
"chars": 2532,
"preview": "import $ from '../../components/dom';\nimport type { API, BlockTool, BlockToolConstructorOptions, BlockToolData } from '."
},
{
"path": "src/types-internal/editor-modules.d.ts",
"chars": 3037,
"preview": "/** ./api */\nimport BlocksAPI from '../components/modules/api/blocks';\nimport CaretAPI from '../components/modules/api/c"
},
{
"path": "src/types-internal/html-janitor.d.ts",
"chars": 600,
"preview": "/**\n * Declaration for external JS module\n * After that we can use it at the TS modules\n */\ndeclare module 'html-janitor"
},
{
"path": "src/types-internal/i18n-internal-namespace.d.ts",
"chars": 1833,
"preview": "/**\n* Decorator above the type object\n*/\ntype Indexed<T> = { [key: string]: T };\n\n/**\n * Type for I18n dictionary values"
},
{
"path": "src/types-internal/module-config.d.ts",
"chars": 342,
"preview": "import { EditorConfig } from '../../types/index';\nimport { EditorEventMap } from '../components/events';\nimport EventsDi"
},
{
"path": "test/cypress/.eslintrc",
"chars": 437,
"preview": "{\n \"plugins\": [\n \"cypress\",\n \"chai-friendly\"\n ],\n \"env\": {\n \"cypress/globals\": true\n },"
},
{
"path": "test/cypress/fixtures/test.html",
"chars": 178,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n<body>\n <!-- Load Editor.js's Core -->\n <script src=\"./../../../dist/editorjs.umd.js\""
},
{
"path": "test/cypress/fixtures/tools/ContentlessTool.ts",
"chars": 760,
"preview": "import type { BlockTool } from '../../../../types';\n\n/**\n * In the simplest Contentless Tool (eg. Delimiter) there is no"
},
{
"path": "test/cypress/fixtures/tools/SimpleHeader.ts",
"chars": 1463,
"preview": "import type {\n BaseTool,\n BlockToolConstructorOptions,\n BlockToolData,\n ConversionConfig\n} from '../../../../types';"
},
{
"path": "test/cypress/fixtures/tools/ToolMock.ts",
"chars": 1176,
"preview": "import type { BlockTool, BlockToolConstructorOptions } from '../../../../types';\n\n/**\n * Simple structure for Tool data\n"
},
{
"path": "test/cypress/fixtures/tools/ToolWithoutConversionExport.ts",
"chars": 712,
"preview": "import type { ConversionConfig } from '@/types/configs/conversion-config';\nimport ToolMock from './ToolMock';\n\n/**\n * Th"
},
{
"path": "test/cypress/fixtures/types/PartialBlockMutationEvent.ts",
"chars": 396,
"preview": "import type { BlockMutationEvent, BlockMutationType } from '../../../../types';\n\n/**\n * Simplified version of the BlockM"
},
{
"path": "test/cypress/support/commands.ts",
"chars": 7437,
"preview": "/* eslint-disable @typescript-eslint/no-explicit-any */\n/**\n * This file contains custom commands for Cypress.\n * Also i"
},
{
"path": "test/cypress/support/e2e.ts",
"chars": 1957,
"preview": "import '@cypress/code-coverage/support';\n\n/* global chai */\n// because this file is imported from cypress/support/e2e.js"
},
{
"path": "test/cypress/support/index.d.ts",
"chars": 4492,
"preview": "// load type definitions that come with Cypress module\n/// <reference types=\"cypress\" />\n\nimport type { EditorConfig, Ou"
},
{
"path": "test/cypress/support/index.ts",
"chars": 723,
"preview": "/**\n * This file is processed and\n * loaded automatically before the test files.\n *\n * This is a great place to put glob"
},
{
"path": "test/cypress/support/utils/createEditorWithTextBlocks.ts",
"chars": 693,
"preview": "import type { EditorConfig } from '../../../../types/index';\nimport Chainable = Cypress.Chainable;\nimport type EditorJS "
},
{
"path": "test/cypress/support/utils/createParagraphMock.ts",
"chars": 331,
"preview": "import { nanoid } from 'nanoid';\n\n/**\n * Creates a paragraph mock\n *\n * @param text - text for the paragraph\n * @returns"
},
{
"path": "test/cypress/support/utils/nestedEditorInstance.ts",
"chars": 813,
"preview": "import type { BlockTool, BlockToolConstructorOptions } from '../../../../types';\nimport { createEditorWithTextBlocks } f"
},
{
"path": "test/cypress/tests/api/block.cy.ts",
"chars": 1646,
"preview": "import type EditorJS from '../../../../types';\nimport { BlockChangedMutationType } from '../../../../types/events/block/"
},
{
"path": "test/cypress/tests/api/blocks.cy.ts",
"chars": 14237,
"preview": "import type EditorJS from '../../../../types/index';\nimport type { ConversionConfig, ToolboxConfig, ToolConfig } from '."
},
{
"path": "test/cypress/tests/api/caret.cy.ts",
"chars": 7950,
"preview": "import { createParagraphMock } from '../../support/utils/createParagraphMock';\nimport type EditorJS from '../../../../ty"
},
{
"path": "test/cypress/tests/api/toolbar.cy.ts",
"chars": 2181,
"preview": "/**\n * There will be described test cases of 'api.toolbar.*' API\n */\nimport type EditorJS from '../../../../types';\n\ndes"
},
{
"path": "test/cypress/tests/api/tools.cy.ts",
"chars": 28953,
"preview": "import type { ToolboxConfig, BlockToolData, ToolboxConfigEntry, PasteConfig } from '../../../../types';\nimport type Edit"
},
{
"path": "test/cypress/tests/api/tunes.cy.ts",
"chars": 6010,
"preview": "import type { TunesMenuConfig } from '../../../../types/tools';\n\n/* eslint-disable @typescript-eslint/no-empty-function "
}
]
// ... and 104 more files (download for full content)
About this extraction
This page contains the full source code of the codex-team/editor.js GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 304 files (1.1 MB), approximately 291.8k tokens, and a symbol index with 1269 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.