{"id":13758294,"url":"https://github.com/thibaudcolas/draftjs-filters","last_synced_at":"2025-04-13T09:51:41.464Z","repository":{"id":39861942,"uuid":"114196732","full_name":"thibaudcolas/draftjs-filters","owner":"thibaudcolas","description":"Filter Draft.js content to preserve only the formatting you allow","archived":false,"fork":false,"pushed_at":"2024-08-13T20:40:33.000Z","size":41455,"stargazers_count":56,"open_issues_count":4,"forks_count":5,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-06T23:18:25.460Z","etag":null,"topics":["draft-js","draftjs-utils","rte","wagtail","wysiwyg"],"latest_commit_sha":null,"homepage":"https://thibaudcolas.github.io/draftjs-filters","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/thibaudcolas.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"docs/CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"docs/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"docs/SECURITY.md","support":"docs/SUPPORT.md","governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-12-14T03:15:52.000Z","updated_at":"2025-03-30T00:44:15.000Z","dependencies_parsed_at":"2023-09-28T18:48:32.282Z","dependency_job_id":"cd1800e4-a5ee-4062-a5df-ceea9fbfb919","html_url":"https://github.com/thibaudcolas/draftjs-filters","commit_stats":{"total_commits":879,"total_committers":6,"mean_commits":146.5,"dds":0.5756541524459613,"last_synced_commit":"34f2f3f5ec807e693ad63863d4e0c3343c623644"},"previous_names":[],"tags_count":22,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thibaudcolas%2Fdraftjs-filters","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thibaudcolas%2Fdraftjs-filters/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thibaudcolas%2Fdraftjs-filters/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thibaudcolas%2Fdraftjs-filters/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thibaudcolas","download_url":"https://codeload.github.com/thibaudcolas/draftjs-filters/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248695301,"owners_count":21146952,"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":["draft-js","draftjs-utils","rte","wagtail","wysiwyg"],"created_at":"2024-08-03T13:00:24.992Z","updated_at":"2025-04-13T09:51:41.437Z","avatar_url":"https://github.com/thibaudcolas.png","language":"TypeScript","funding_links":[],"categories":["Common Utilities"],"sub_categories":[],"readme":"# [Draft.js filters](https://thibaudcolas.github.io/draftjs-filters/)\n\nFilter [Draft.js](https://facebook.github.io/draft-js/) content to preserve only the formatting you allow. Built for [Draftail](https://www.draftail.org/).\n\nThe main use case is to select what formatting to keep when copy-pasting rich text into an editor, for example from Word or Google Docs, addressing Draft.js limitations like [#166](https://github.com/facebook/draft-js/issues/166) and [#504](https://github.com/facebook/draft-js/issues/504). Check out the [online demo](https://thibaudcolas.github.io/draftjs-filters)!\n\n\u003e If you want to learn more about how this is used in practice, have a look at [Rethinking rich text pipelines with Draft.js](https://wagtail.org/blog/rethinking-rich-text-pipelines-with-draft-js/).\n\n## Using the filters\n\nFirst, grab the package from npm:\n\n```sh\nnpm install --save draftjs-filters\n```\n\nThen, in your editor import `filterEditorState` and call it in the Draft.js `onChange` handler. This function takes two parameters: the filtering configuration, and the `editorState`.\n\n```js\nimport { filterEditorState } from \"draftjs-filters\"\n\nfunction onChange(nextState) {\n  const { editorState } = this.state\n  let filteredState = nextState\n\n  const shouldFilterPaste =\n    nextState.getCurrentContent() !== editorState.getCurrentContent() \u0026\u0026\n    nextState.getLastChangeType() === \"insert-fragment\"\n\n  if (shouldFilterPaste) {\n    filteredState = filterEditorState(\n      {\n        blocks: [\"header-two\", \"header-three\", \"unordered-list-item\"],\n        styles: [\"BOLD\"],\n        entities: [\n          {\n            type: \"IMAGE\",\n            attributes: [\"src\"],\n            allowlist: {\n              src: \"^http\",\n            },\n          },\n          {\n            type: \"LINK\",\n            attributes: [\"url\"],\n          },\n        ],\n        maxNesting: 1,\n        whitespacedCharacters: [\"\\n\", \"\\t\", \"📷\"],\n      },\n      filteredState,\n    )\n  }\n\n  this.setState({ editorState: filteredState })\n}\n```\n\nHere are all the available options:\n\n```jsx\n// List of allowed block types. unstyled and atomic are always included.\nblocks: readonly string[]\u003e,\n// List of allowed inline styles.\nstyles: readonly string[]\u003e,\n// List of allowed entities.\nentities: readonly []\u003c{\n  // Entity type, eg. \"LINK\"\n  type: string,\n  // Allowed attributes. Other attributes will be removed. If this is omitted, all attributes are kept.\n  attributes?: readonly string[]\u003e,\n  // Refine which entities are kept by matching acceptable values with regular expression patterns.\n  // It's also possible to use \"true\" to signify that a field is required to be present,\n  // and \"false\" for fields required to be absent.\n  // If this is omitted, all entities are kept.\n  allowlist?: {\n    [attribute: string]: string | boolean,\n  },\n}\u003e,\n// Maximum amount of depth for lists (0 = no nesting).\nmaxNesting: number,\n// Characters to replace with whitespace.\nwhitespacedCharacters: Array\u003cstring\u003e,\n// Optional: Rules used to automatically convert blocks from one type to another\n// based on the block’s text. Also supports setting the block depth.\n// Defaults to the filters’ built-in block prefix rules.\nblockTextRules?: readonly []\u003c{\n  // A regex as a string, to match against block text, e.g. \"^(◦|o |o\\t)\".\n  test: string,\n  // The type to convert the block to if the test regex matches.\n  type: string,\n  // The depth to set (e.g. for list items with different prefixes per depth).\n  depth: number,\n}\u003e,\n```\n\n### Deprecated\n\n`filterEditorState` (and `shouldKeepEntityByAttribute` described further below) used to support a `whitelist` config option. It has been renamed to `allowlist`, and will be removed altogether in a future release.\n\n### Types\n\nIf your project uses [TypeScript](https://www.typescriptlang.org/), type inference should just work. If you don't use TypeScript, it won't get in your way either.\n\n[Flow](https://flow.org/) types were included up to [v2.5.0](https://github.com/thibaudcolas/draftjs-filters/blob/main/CHANGELOG.md#250-2020-11-21) of the package, and have been removed in v3.0.0. They may still be used by manually downloading the [library definitions](https://github.com/thibaudcolas/draftjs-filters/tree/main/docs/flow-typed/npm) and manually adding them to projects.\n\n### Advanced usage\n\n`filterEditorState` isn't very flexible. If you want more control over the filtering, simply compose your own filter function with the other single-purpose utilities. The Draft.js filters are published as ES6 modules using [Rollup](https://rollupjs.org/) – module bundlers like Rollup and Webpack will tree shake (remove) the unused functions so you only bundle the code you use.\n\nIf using filters that remove blocks, be sure to use `applyContentWithSelection` to restore the selection where appropriate after filtering.\n\n#### API\n\n##### preserveAtomicBlocks\n\nCreates atomic blocks where they would be required for a block-level entity\nto work correctly, when such an entity exists.\nNote: at the moment, this is only useful for IMAGE entities that Draft.js\ninjects on arbitrary blocks on paste.\n\n###### Parameters\n\n- `content` **ContentState**\n\n##### resetAtomicBlocks\n\nResets atomic blocks to have a single-space char and no styles.\nThis is how they are stored by Draft.js by default.\n\n###### Parameters\n\n- `content` **ContentState**\n\n##### removeInvalidAtomicBlocks\n\nRemoves atomic blocks for which the entity type isn't allowed.\n\n###### Parameters\n\n- `allowlist` **readonly {type: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)}[]**\n- `content` **ContentState**\n\n##### removeInvalidDepthBlocks\n\nRemoves blocks that have a non-zero depth, and aren't list items.\nHappens with Apple Pages inserting `unstyled` items between list items.\n\n###### Parameters\n\n- `content` **ContentState**\n\n##### preserveBlockByText\n\nChanges block type and depth based on the block's text. – some word processors\nadd a specific prefix within the text, eg. \"· Bulleted list\" in Word 2010.\nAlso removes the matched text.\nThis is meant first and foremost for list items where the list bullet or numeral\nends up in the text. Other use cases may not be well covered.\n\n###### Parameters\n\n- `rules` **readonly {test: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), type: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), depth: [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)}[]**\n- `content` **ContentState**\n\n##### limitBlockDepth\n\nResets the depth of all the content to at most max.\n\n###### Parameters\n\n- `max` **[number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)**\n- `content` **ContentState**\n\n##### filterBlockTypes\n\nConverts all block types not present in the list to unstyled.\nAlso sets depth to 0 (for potentially nested list items).\n\n###### Parameters\n\n- `allowlist` **readonly [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)[]**\n- `content` **ContentState**\n\n##### filterInlineStyles\n\nRemoves all styles not present in the list.\n\n###### Parameters\n\n- `allowlist` **readonly [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)[]**\n- `content` **ContentState**\n\n##### cloneEntities\n\nClones entities in the entityMap, so each range points to its own entity instance.\nThis only clones entities as necessary – if an entity is only referenced\nin a single range, it won't be changed.\n\n###### Parameters\n\n- `content` **ContentState**\n\n##### filterEntityRanges\n\nFilters entity ranges (where entities are applied on text) based on the result of\nthe callback function. Returning true keeps the entity range, false removes it.\nDraft.js automatically removes entities if they are not applied on any text.\n\n###### Parameters\n\n- `filterFn` **function (content: ContentState, entityKey: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), block: BlockNode): [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)**\n- `content` **ContentState**\n\n##### shouldKeepEntityType\n\nKeeps all entity types (images, links, documents, embeds) that are enabled.\n\n###### Parameters\n\n- `allowlist` **readonly {type: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)}[]**\n- `type` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**\n\n##### shouldRemoveImageEntity\n\nRemoves invalid images – they should only be in atomic blocks.\nThis only removes the image entity, not the camera emoji (📷) that Draft.js inserts.\n\n###### Parameters\n\n- `entityType` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**\n- `blockType` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**\n\n##### shouldKeepEntityByAttribute\n\nFilters entities based on the data they contain.\n\n###### Parameters\n\n- `entityTypes` **readonly {type: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), allowlist: {}?, whitelist: {}?}[]**\n- `entityType` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**\n- `data` **{ [attr: string]: any }**\n\n##### filterEntityData\n\nFilters data on an entity to only retain what is allowed.\nThis is crucial for IMAGE and LINK, where Draft.js adds a lot\nof unneeded attributes (width, height, etc).\n\n###### Parameters\n\n- `entityTypes` **readonly {type: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), attributes: readonly [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)\u003e?}[]**\n- `content` **ContentState**\n\n##### replaceTextBySpaces\n\nReplaces the given characters by their equivalent length of spaces, in all blocks.\n\n###### Parameters\n\n- `characters` **readonly [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)[]**\n- `content` **ContentState**\n\n##### applyContentWithSelection\n\nApplies the new content to the editor state, optionally moving the selection\nto be on a valid block, inserting one if needed.\nSee \u003chttps://github.com/thibaudcolas/draftjs-filters/issues/27\u003e.\n\n###### Parameters\n\n- `editorState` **EditorState**\n- `content` **ContentState**\n- `nextContent` **ContentState**\n\n##### filterEditorState\n\nApplies filtering and preservation operations to the editor content,\nto restrict it to supported patterns.\nWill not alter the editor state if there are no changes to make.\n\n###### Parameters\n\n- `options` **FilterOptions**\n- `editorState` **EditorState**\n\n##### condenseBlocks\n\nCondenses an array of content blocks into a single block.\n\n- Skipping the undo-redo stack.\n- Adding a space between each block to match the behavior of vanilla HTML fields.\n- Making sure the space gets the correct styles or entities applied.\n- Placing the selection at the same end offset as the last selection.\n\nThis exhibits two known issues:\n\n- A link / other entity spread over multiple lines will be split into multiple entities of identical data.\n- Upon redo-ing the change, the selection isn’t correctly placed.\n\n###### Parameters\n\n- `nextState` **EditorState**\n- `prevState` **EditorState**\n\n### Browser support and polyfills\n\nThe Draft.js filters only support modern browsers with ES2020 features. Support for legacy browsers can be achieved, up to IE11, by appropriately transpiling the package’s code and including the [required Draft.js polyfills](https://facebook.github.io/draft-js/docs/advanced-topics-issues-and-pitfalls).\n\n#### Word processor support\n\nHave a look at our test data in [`pasting/`](pasting).\n\n| Editor - Browser  | Chrome Windows | Chrome macOS | Firefox Windows | Firefox macOS | Edge Windows | IE11 Windows | Safari macOS | Safari iOS | Chrome Android |\n| ----------------- | -------------- | ------------ | --------------- | ------------- | ------------ | ------------ | ------------ | ---------- | -------------- |\n| **Word 2016**     |                |              |                 |               |              |              |              | N/A        | N/A            |\n| **Word 2010**     |                | N/A          |                 | N/A           |              |              | N/A          | N/A        | N/A            |\n| **Apple Pages**   | N/A            |              | N/A             |               | N/A          | N/A          |              |            | N/A            |\n| **Google Docs**   |                |              |                 |               |              |              |              |            |                |\n| **Word Online**   |                |              |                 |               |              | Unsupported  |              | ?          | ?              |\n| **Dropbox Paper** |                |              |                 |               |              | Unsupported  |              | ?          | ?              |\n| **Draft.js**      |                |              |                 |               |              |              |              |            |                |\n\nUse the [Draft.js Cut/Copy/Paste testing plan](https://github.com/facebook/draft-js/wiki/Manual-Testing#cutcopypaste). We target specific external sources, and have ready-made test documents available to test them:\n\n##### External sources\n\nHere are external sources we want to pay special attention to, and for which we have ready-made test documents with diverse rich content.\n\n- [Microsoft Word 2016](/pasting/documents/Draft.js%20paste%20test%20document%20Word2016%20macOS.docx)\n- [Microsoft Word 2010](/pasting/documents/Draft.js%20paste%20test%20document%20Word2010.docx)\n- [Google Docs](https://docs.google.com/document/d/1YjqkIMC3q4jAzy__-S4fb6mC_w9EssmA6aZbGYWFv80/edit)\n- [Dropbox Paper](https://paper.dropbox.com/doc/Draft.js-paste-test-document-njfdkwmkeGQ9KICjVwLmU)\n- [Apple Pages](/pasting/documents/Draft.js%20paste%20test%20document.pages)\n- [Microsoft Word Online](https://1drv.ms/w/s!AuGin45FpiF5hjzm9QdWHYGqPrqm)\n\n#### IE11\n\nThere are [known Draft.js issues](https://github.com/facebook/draft-js/issues/986) with pasting in IE11. For now, we advise users to turn on `stripPastedStyles` in IE11 only so that Draft.js removes all formatting but preserves whitespace:\n\n```jsx\nconst IS_IE11 = !window.ActiveXObject \u0026\u0026 \"ActiveXObject\" in window\n\nconst editor = \u003cEditor stripPastedStyles={IS_IE11} /\u003e\n```\n\n## Contributing\n\nSee anything you like in here? Anything missing? We welcome all support, whether on bug reports, feature requests, code, design, reviews, tests, documentation, and more. Please have a look at our [contribution guidelines](docs/CONTRIBUTING.md).\n\n## Credits\n\nView the full list of [contributors](https://github.com/springload/draftail/graphs/contributors). [MIT](LICENSE) licensed. Website content available as [CC0](https://creativecommons.org/publicdomain/zero/1.0/).\n\nMicrosoft Word toolbars screenshot from _PCWorld – Microsoft Word Turns 25_ article.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthibaudcolas%2Fdraftjs-filters","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthibaudcolas%2Fdraftjs-filters","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthibaudcolas%2Fdraftjs-filters/lists"}