Skip to content

Commit

Permalink
Fix line breaks when pasting from word to draft (facebookarchive#828)
Browse files Browse the repository at this point in the history
* Making sure that pasted paragraphs are not converged when pasting

* Adding documentation for introducing alias

* Simplifying the logic

* Adding flow types

* Updaing docs
  • Loading branch information
mitermayer authored and flarnie committed Dec 3, 2016
1 parent 6c6946b commit b298df2
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 5 deletions.
13 changes: 13 additions & 0 deletions docs/Advanced-Topics-Custom-Block-Render.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,19 @@ class RichEditor extends React.Component {
}
```

When Draft parses pasted HTML, it maps from HTML elements back into
Draft block types. If you want to specify other HTML elements that map to a
particular block type, you can add an array `aliasedElements` to the block config.

*example of unstyled block type alias usage:*

```
'unstyled': {
element: 'div',
aliasedElements: ['p'],
}
```

## Custom block wrappers

By default the html element is used to wrap block types however a react component
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/**
* Copyright (c) 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @emails oncall+ui_infra
*/

'use strict';

jest.disableAutomock();

const convertFromHTMLToContentBlocks = require('convertFromHTMLToContentBlocks');

function testConvertingAdjacentHtmlElementsToContentBlocks(
tag: string
) {
it(`must not merge tags when converting adjacent <${tag} />`, () => {
const html_string = `
<${tag}>a</${tag}>
<${tag}>b</${tag}>
`;

const blocks = convertFromHTMLToContentBlocks(html_string);

expect(blocks.contentBlocks.length).toBe(2);
});
}

describe('convertFromHTMLToContentBlocks', () => {
[
'blockquote',
'div',
'figure',
'h1',
'h2',
'h3',
'h4',
'h5',
'h6',
'li',
'p',
'pre',
].forEach(tag => testConvertingAdjacentHtmlElementsToContentBlocks(tag));
});
29 changes: 24 additions & 5 deletions src/model/encoding/convertFromHTMLToContentBlocks.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ const invariant = require('invariant');
const nullthrows = require('nullthrows');
const sanitizeDraftText = require('sanitizeDraftText');

const {Set} = require('immutable');

import type {DraftBlockRenderMap} from 'DraftBlockRenderMap';
import type {DraftBlockRenderConfig} from 'DraftBlockRenderConfig';
import type {DraftBlockType} from 'DraftBlockType';
import type {DraftInlineStyle} from 'DraftInlineStyle';
import type {EntityMap} from 'EntityMap';
Expand Down Expand Up @@ -154,10 +157,19 @@ function getBlockMapSupportedTags(
blockRenderMap: DraftBlockRenderMap
): Array<string> {
const unstyledElement = blockRenderMap.get('unstyled').element;
return blockRenderMap
.map((config) => config.element)
.valueSeq()
.toSet()
let tags = new Set([]);

blockRenderMap.forEach((draftBlock: DraftBlockRenderConfig) => {
if (draftBlock.aliasedElements) {
draftBlock.aliasedElements.forEach((tag) => {
tags = tags.add(tag);
});
}

tags = tags.add(draftBlock.element);
});

return tags
.filter((tag) => tag && tag !== unstyledElement)
.toArray()
.sort();
Expand All @@ -184,7 +196,14 @@ function getBlockTypeForTag(
blockRenderMap: DraftBlockRenderMap
): DraftBlockType {
const matchedTypes = blockRenderMap
.filter((config) => config.element === tag || config.wrapper === tag)
.filter((draftBlock: DraftBlockRenderConfig) => (
draftBlock.element === tag ||
draftBlock.wrapper === tag ||
(
draftBlock.aliasedElements &&
draftBlock.aliasedElements.some(alias => alias === tag)
)
))
.keySeq()
.toSet()
.toArray()
Expand Down
1 change: 1 addition & 0 deletions src/model/immutable/DefaultDraftBlockRenderMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,5 +60,6 @@ module.exports = Map({
},
'unstyled': {
element: 'div',
aliasedElements: ['p'],
},
});
1 change: 1 addition & 0 deletions src/model/immutable/DraftBlockRenderConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@
export type DraftBlockRenderConfig = {
element: string,
wrapper?: React$Element<any>,
aliasedElements?: Array<string>,
};

0 comments on commit b298df2

Please sign in to comment.