{"id":21420240,"url":"https://github.com/lovelysystems/lovely-editor","last_synced_at":"2025-07-14T06:32:08.757Z","repository":{"id":32720810,"uuid":"107418892","full_name":"lovelysystems/lovely-editor","owner":"lovelysystems","description":"A react component which lets you use multiple editors (e.g Quill) for a single document.","archived":false,"fork":false,"pushed_at":"2023-02-04T17:32:09.000Z","size":13131,"stargazers_count":5,"open_issues_count":13,"forks_count":0,"subscribers_count":14,"default_branch":"master","last_synced_at":"2024-04-24T02:15:06.140Z","etag":null,"topics":["editor","react"],"latest_commit_sha":null,"homepage":"https://lovely-editor.netlify.com/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lovelysystems.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGES.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-10-18T14:23:10.000Z","updated_at":"2024-04-14T11:04:54.000Z","dependencies_parsed_at":"2023-01-14T22:01:52.332Z","dependency_job_id":null,"html_url":"https://github.com/lovelysystems/lovely-editor","commit_stats":null,"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lovelysystems%2Flovely-editor","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lovelysystems%2Flovely-editor/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lovelysystems%2Flovely-editor/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lovelysystems%2Flovely-editor/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lovelysystems","download_url":"https://codeload.github.com/lovelysystems/lovely-editor/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225958011,"owners_count":17551331,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["editor","react"],"created_at":"2024-11-22T20:14:05.196Z","updated_at":"2024-11-22T20:14:06.333Z","avatar_url":"https://github.com/lovelysystems.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# LovelyEditor\n\nLovelyEditor is a React component to provide a variety of editors to be added to your\napp. It also gives you the opportunity to create your own editor and add it to\nthe LovelyEditor-component. As a result the edited content will come in the shape of\nHTML markup to be added to your page. Each editor will create an isolated HTML\nmarkup of its part.\nThis makes it very easy for you to include a variety of different Editors\ninto your App and organise them and their returned value exactly the way you need\nit. Also including a new Editor that is not supported yet can be accomplished\nwithin just a few easy steps.\n\n\nThis makes it very easy for you to include a variety of different Editors\ninto your App and organise them and their returned value exactly the way you need\nit. Also including a new Editor that is not supported yet can be accomplished\nwithin just a few easy steps.\n\n\n![Example App](./assets/example_app.gif)\n\nThe Example-App shows what our LovelyEditor can do. The app consists of 2 main parts, a toolbar and our LovelyEditor.\nThe toolbar adds additional (pre-defined) Editors to our LovelyEditor. Each Editor block is extended by a Delete button, which removes an editor block from our LovelyEditor.\nDrag \u0026 Drop was added to illustrate that our LovelyEditor plays nice with other libraries.\n\n## Table of Contents\n\n* [Features](#features)\n* [Examples](#examples)\n* [Requirements](#requirements)\n* [Installation](#installation)\n* [LovelyEditor components](#lovelyeditor-components)\n* [Quickstart](#quickstart)\n  * [Example App](#example-app)\n  * [Editor State](#editor-state)\n  * [Editor Config](#editor-config)\n  * [LovelyEditor Integration in your App](#lovelyeditor-integration-in-your-app)\n  * [How to use the styling from our Showcases](#how-to-use-the-styling-from-our-showcases)\n* [How to include your own custom Editor](#how-to-include-your-own-custom-editor)\n* [How to contribute and develop](#how-to-contribute-and-develop)\n* [How to create a release](#how-to-create-a-release-deployment)\n\n## Features\n\n* Provides a variety of pre-designed editors: eg. EditorQuill\n* design and features are largely customisable: make it your own!\n* easy way to create and add your own custom editor or extend existing ones\n* use every EditorComponent (eg. EditorQuill) independently without need to\n  look out you for the others\n\n## Examples\n\nThe following link will provide you with certain examples on how the component\nmay be used: https://lovely-editor.netlify.com. By selecting one of the options\nwithin \"App Example\" you will see a variety of possibilities on what you are\nable to use the component for. For example within \"Menu and Quill Block Editor\"\nthere is an example-menu included to quickly add different editor-types (eg.\nRichtext, CodeMirror, etc.) to the application. It is also possible to use the\nsame editor-type several times.\n\n###### HTML-Output\n![HTML-Output](./assets/html_preview.gif)\n\nTo see what kind of HTML-Output the Editors return check out our [example](https://lovely-editor.netlify.com/?selectedKind=App%20Example%2FContent\u0026selectedStory=with%20HTML%20Preview%20of%20the%20content%20of%20all%20Editors\u0026full=0\u0026addons=1\u0026stories=1\u0026panelRight=0\u0026addonPanel=REACT_STORYBOOK%2Freadme%2Fpanel).\nThe generated HTML of all editors is ready to be used in your app.\n\n###### Example with two Editors and an Example-Menu to add additional Editors\n![Two Editors with Example-Menu](./assets/two_with_menu.png)\n\n## Requirements\n\n```\nnode 8.6.x\nnpm 5.3.x\n```\n\n## Installation\n\nThe following environment variables need to be set, scoped to `read: packages`\n\nGITHUB_TOKEN=**YOUR_PAT_FROM_GITHUB_HERE**\n\n```\nnpm install --save lovely-editor\n```\n\nand import it in your App with:\n\n```js\nimport { LovelyEditor } from 'lovely-editor'\n```\n\nIf you want to use the basic styling as well you can either import it in your index.js\n\n```js\nimport('lovely-editor/dist/lovely-editor.min.css')\n```\n\nOr add it to your index.html.\n\n## LovelyEditor components\n\nThe LovelyEditor basically consists out of three main components:\n\n1. [LovelyEditor](src/components/lovely-editor)\n2. [EditorBlock](src/components/editor-block)\n3. Editors (eg. [EditorQuill](src/components/editor-quill))\n\n###### Structure of the LovelyEditor\n![LovelyEditor Structure](./assets/lovely_editor.png)\n\nThe `LovelyEditor` rendered components tree looks like this:\n\n```js\n\u003cLovelyEditor\u003e\n  \u003cEditorBlock\u003e\n    // a EditorComponent, eg. \u003cEditorQuill /\u003e\n  \u003c/EditorBlock\u003e\n\u003c/LovelyEditor\u003e\n```\n\n###### Single EditorBlock with eg. EditorQuill\n![Single CodeMirror Editor](./assets/react_quill.png)\n\nThe main entry point in your app is the `LovelyEditor`. Its properties have to\nbe specified and all necessary `EditorBlock` and `EditorComponent`s are rendered\nautomatically, based on the [editorState](#editor-state) and\n[blocksConfig](#editor-config).\n\n## Quickstart\n\nFollow the [Installation](#installation) first before taking a look at the\nfollowing comprehensive example:\n\n### Example App\n\nThe following app showcases the usage of the `LovelyEditor` with one pre-configured Editor \n(in this case `EditorQuill`) and a current `editorState`.\nThe app itself controls the `LovelyEditor` by not only subscribing to the `LovelyEditor`'s\n`onChange` but also by providing it's `editorState` as a property. The changes are\nreceived and the `YourApp`'s `state` updated. This leads to a re-rendering of\nthe `LovelyEditor` with a new valid editorState. You can find a similar example also\n[in our Storybook](https://lovely-editor.netlify.com/?selectedKind=App%20Example\u0026selectedStory=with%20an%20example%20Menu%20and%20EditorQuill%20Block\u0026full=0\u0026addons=1\u0026stories=1\u0026panelRight=0\u0026addonPanel=REACT_STORYBOOK%2Freadme%2Fpanel).\n\n```js\nimport { LovelyEditor } from 'lovely-editor'\nimport { EditorQuill } from 'lovely-editor/dist/components/editor-quill'\n\n// current state of LovelyEditor\nconst editorState = [\n  {\n    id: 1,\n    type: 'richtext',\n    data: {\n      value: '\u003cp\u003eHello World. \u003cstrong\u003eThis is bold.\u003c/strong\u003e\u003c/p\u003e'\n    },\n    meta: {\n      title: 'Quill Block'\n    }\n  },\n]\n\n// renders a specific component for the requested block.type\n// in this case EditorQuill would be rendered for all blocks of type \"richtext\"\nconst editorQuillConfig = {\n  type: 'richtext',\n  component: EditorQuill\n}\n\n// sets which editor component should be rendered for which block.type\nconst blocksConfig = [editorQuillConfig]\n\nclass YourApp extends React.Component {\n  constructor(props) {\n    super(props)\n    this.state = {\n      editorState\n    }\n    this.onChange = this.onChange.bind(this)\n  }\n\n  onChange(change) {\n    this.setState({ editorState: change.editorState })\n  }\n\n  render() {\n    return (\n      \u003cLovelyEditor\n        blocksConfig={blocksConfig}\n        editorState={this.state.editorState}\n        onChange={this.onChange}\n      /\u003e\n    )\n  }\n}\n```\n\n### Editor State\n\nTo tell the editor it's current state we need to specify the `editorState`.\nIt is responsible for telling the component which `Editor` gets what kind of\ndata (eg. current content for the richtext editor).\n\nThe function of the `editorState` is, as the name says, to represent the current\nstate of the `\u003cLovelyEditor /\u003e`. That means if you e.g. type in a new text into\na `\u003cEditorQuill /\u003e` the `editorState` will change. Your app can access the\ncurrent `editorState` by subscribing to the `onChange` property of the `\u003cLovelyEditor /\u003e`.\n\nThrough this any changes to an Editor (eg. EditorQuill) lead to an onChange event\nof the `\u003cLovelyEditor /\u003e` and lets you use the change for your own purposes\n(eg. validate changes or show \"unsaved\" messages).\n\nA `editorState` can look similar to:\n\n```js\nconst editorState = [\n  {\n    id: 1, // block.id, must be unique\n    type: 'richtext',\n    data: {\n      value: '\u003cp\u003eHello World. \u003cstrong\u003eThis is bold.\u003c/strong\u003e\u003c/p\u003e'\n    },\n    meta: {\n      title: 'Quill Block'\n    }\n  }\n]\n```\n\n###### Example of Quill Editor within the LovelyEditor-Component\n![Example-Editor](./assets/quill.png)\n\n**Attention**: the block.id must be unique! Make sure each block has it's own\nindividual (it can be random though) id. The id is used to identify each block\nwith the LovelyEditor.\n\nNote, that each block type (eg. \"richtext\") in the `editorState` must have a\nmatching type configuration in the `blocksConfig` to be rendered.\n\n### Editor Config\n\nThen you have to provide a `blocksConfig` configurations. This means telling\nthe `\u003cLovelyEditor /\u003e` which `EditorComponent` to use for which specified type (e.g.\n`\u003cEditorQuill /\u003e` for type \"richtext\").\n\nBut the order and number of currently rendered Editors are specified through\nthe `editorState` (see [Editor State](#editor-state)).\n\nAn example config could look like:\n\n```js\nconst editorQuillConfig = {\n  type: 'richtext',\n  component: EditorQuill\n}\n\nconst blocksConfig = [editorQuillConfig]\n```\n\n### LovelyEditor Integration in your App\n\nAs a final step we define our App component where we first set the `editorState`\nas `this.state` and create an `onChange`-method to sync the changes in the\n`\u003cLovelyEditor /\u003e` with the `editorState` of the App and set it as the new\nstate (or do even more if we want to).\n\n```js\nclass YourApp extends React.Component {\n  constructor(props) {\n    super(props)\n    this.state = {\n      editorState\n    }\n    this.onChange = this.onChange.bind(this)\n  }\n\n  onChange(change) {\n    // get the change from the LovelyEditor and sync the YourApp's state\n    this.setState({ editorState: change.editorState })\n  }\n\n  //...\n}\n```\n\nThe final step is the `render()`-method for our App component. Here we put in\nour `Editor` with its 3 necessary properties (`blocksConfig`, `editorState`\nand `onChange`). As we have defined the requirements for those properties we\nonly have to assign them to the `Editor`.\n\n```js\nrender() {\n  return (\n    \u003cLovelyEditor\n      blocksConfig={blocksConfig}\n      editorState={this.state.editorState}\n      onChange={this.onChange}\n    /\u003e\n  )\n}\n```\n\nThe entire code of the example can be found in the [Quickstart](#quickstart) section.\n\n## How to use the styling from our Showcases\n\nIf you want to use the same styling like the basic styling in our Storybook,\nyou have to include the CSS from lovely-editor in your own application. Example\nimport in SCSS:\n\n```SCSS\n@import \"~lovely-editor/dist/lovely-editor.min.css\";\n```\n\n## How to include your own custom Editor\n\nTake a look at the [Quill Editor implementation](https://github.com/lovelysystems/lovely-editor/tree/develop/src/components/editor-quill) which illustrates how one can add a new custom editor.\n\n## How to contribute and develop\n\n### Development Setup\n\nOnce you have cloned the repository enter `nvm use \u0026\u0026 npm install` to\ninstall all the dependencies, required to develop.\n\n### Development Scripts\n\nThe package comes with the following npm scripts:\n\n* `npm run build`: builds the package to ./dist\n* `npm run build:storybook`: build static production version of component\n  library to ./build/storybook\n* `npm run coverage`: runs the tests and reports the coverage with\n  [nyc](https://github.com/istanbuljs/nyc)\n* `npm run lint`: lints JS code\n* `npm run storybook`: run local server with component library and\n  [Storybook](https://storybook.js.org)\n* `npm start`: similar to `npm run storybook`\n* `npm run test`: runs the tests (test files path and pattern:\n  `src/**/*.spec.js`)\n* `npm run test:node`: verifies the installed and used node version\n\n### Showcases\n\nThis package uses [Storybook](https://storybook.js.org) to showcase the\ncomponents. Just enter `npm run storybook` to start it on your local machine or\nvisit [https://lovely-editor.netlify.com](https://lovely-editor.netlify.com).\n\n### Pre-commit and Pre-push Hooks\n\nWhen attempting to commit files in this repository, some taks will\nautomatically run to ensure a consistently high level of code quality:\n\n* **JavaScript files (.js):**\n  * runs `eslint` and automatically fixes auto-fixable issues\n    ([see related JS guidelines here](https://github.com/airbnb/javascript))\n  * runs `prettier` and auto-formats your code\n    ([see what it does here](https://github.com/prettier/prettier))\n  * runs all unit tests concerning the committed files with `mocha`\n\nIf any of the tasks fail (which means your code does not lint or unit tests are\nfailing), your commit or push will be aborted.\n\n### How to create a release (Deployment)\n\n1. Update [CHANGES](CHANGES.md)\n\n2. Commit it as \"prepare release x.y.z\"\n\n3. Create a git tag:\n\n```\nnpm version major | minor | patch\n```\n\nThis will update the version in packages.json and create a git tag.\n\n4. Push the git tag and changes\n\n```\ngit push \u0026\u0026 git push --tags\n```\n\n5. Merge release in release branch (eg. `release/x.y`)\n\n## How to publish this package to GitHubPackages\n\n### Github Authentication Setup\n\nGithub uses personal access tokens (PAT) for authentication. To generate one go to your Github token settings page. Consult the Github Docs for more information on how tokens work.\n\nThe following environment variables need to be set:\n\nGITHUB_TOKEN=**YOUR_PAT_FROM_GITHUB_HERE**\n\n### Upload package\n\nWe are using GitHub Packages to host this repo to npm.\n[GitHub Packages Docs](https://github.com/features/packages) and [here](https://docs.github.com/en/packages/learn-github-packages/introduction-to-github-packages)\n\n- increase version in `package.json`\n- Check in all changes and commit\n- run `git tag \u003cversion\u003e`\n- run `git push --tags`\n- run `npm run build`\n- run `npm publish`\n\n## How to install this package in your project\n\nAdd the following to your project's `.npmrc`:\n\n```\n@lovelysystems:registry=https://npm.pkg.github.com\n//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}\n```\n\nIf you use yarn add `always-auth=true` to the `.npmrc` as well.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flovelysystems%2Flovely-editor","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flovelysystems%2Flovely-editor","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flovelysystems%2Flovely-editor/lists"}