Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Overlapping styles and entities in convertToHTML not working when intersecting no style #46

Closed
jebarjonet opened this issue Feb 22, 2017 · 13 comments

Comments

@jebarjonet
Copy link

I just noticed the release of #43 which is super cool. Unfortunately, it does not work for intersections situations, which is problematic.

Here is my code:

convertToHTML({
    blockToHTML: { // I put this here to have <div> in my output instead of <p>
        unstyled: {
            start: '<div>',
            end: '</div>',
            empty: '<br>',
        }
    },
    entityToHTML: (entity, originalText) => {
        if (entity.type === 'link') {
            return {
                start: `<a href="${entity.data.url}" target="_blank">`,
                end: '</a>',
            }
        }
        return originalText
    }
})(contentState)

Overlapping styles

1. Add link

screen shot 2017-02-22 at 11 49 21

2. Add bold intersecting link

screen shot 2017-02-22 at 11 49 29

3. Result

<div>t<strong>e<</strong>a href="http://google.com" target="_blank">st test</a></div>

4. Render

screen shot 2017-02-22 at 11 51 33

Situation

  1. Style strictly inside link ✅

screen shot 2017-02-22 at 11 58 18

  1. Style over link ✅

screen shot 2017-02-22 at 11 58 11

  1. Style outside link ✅

screen shot 2017-02-22 at 11 58 21

  1. Style intersecting link 🔴

Intersect start

screen shot 2017-02-22 at 12 01 41

Result:

screen shot 2017-02-22 at 12 01 44

Code:

<div>t<strong>e<</strong>a href="http://google.com" target="_blank">st test te</a>st</div>

Intersect end

screen shot 2017-02-22 at 11 56 14

Result:

screen shot 2017-02-22 at 11 58 14

Code:

<div>te<a href="http://google.com" target="_blank">st test t<strong>e<</strong>/a>st</div>
@noahlemen
Copy link

Should resulting tags overlap, or be close/opened around the intersect?

In the Intersect start example, for example, which of these possibilities would be desired?

  • <div>t<strong>e<a href="http://google.com" target="_blank">s</strong>t test te</a>st</div>
  • <div>t<strong>e</strong><a href="http://google.com" target="_blank"><strong>s</strong>t test te</a>st</div>

For HTML5, either one should be valid. Is there any preference here?

@benbriggs
Copy link
Contributor

I think the latter is what we want here - it's how overlapping style ranges currently work and I'm not so sure the first is valid.

@benbriggs
Copy link
Contributor

closed via #57 🎉

@liyantang
Copy link

@benbriggs Found a breaking case:

Given that you style text not overlapping to links, and have more that one link in text block, style is left on stack and error is thrown.

Example:

testing testing testing testing testing

Uncaught Error: Character 73: -1 styles left on stack that should no longer be there

Error is thrown in blockInlineStyles: https://github.com/HubSpot/draft-convert/blob/master/src/blockInlineStyles.js#L119

@benbriggs
Copy link
Contributor

Hmm I can't seem to reproduce that @liyantang, can you provide a failing test? Here's one I tried to mimic your example that passes:

    const contentState = buildContentState([
      {
        type: 'unstyled',
        text: 'testing testing testing testing testing',
        styleRanges: [
          {
            style: 'BOLD',
            offset: 8,
            length: 7
          }
        ],
        entityRanges: [
          {
            key: 0,
            offset: 16,
            length: 7
          },
          {
            key: 1,
            offset: 24,
            length: 7
          }
        ]
      }
    ], {
      0: {
        type: 'LINK',
        mutability: 'MUTABLE',
        data: {
          url: 'asdf'
        }
      },
      1: {
        type: 'LINK',
        mutability: 'MUTABLE',
        data: {
          url: 'asdf'
        }
      }
    });

    const html = convertToHTML({
      entityToHTML: (entity, originalText) => {
        if (entity.type === 'LINK') {
          return <a>{originalText}</a>;
        }
      }
    })(contentState);

    expect(html).toBe('<p>testing <strong>testing</strong> <a>testing</a> <a>testing</a> testing</p>');

@liyantang
Copy link

liyantang commented Apr 27, 2017

@benbriggs

Example:

    it('failing test', () => {
      const contentState = buildContentState([
        {
          type: 'unstyled',
          text: 'overlapping test Hello World',
          styleRanges: [
            {
              offset: 0,
              length: 11,
              style: 'BOLD'
            },
            {
              offset: 23,
              length: 5,
              style: 'ITALIC'
            }
          ],
          entityRanges: [
            {
              key: 0,
              offset: 17,
              length: 5,
              prefixLength: '<a href="http://google.com">'.length,
              suffixLength: '</a>'.length
            },
            {
              key: 1,
              offset: 23,
              length: 5,
              prefixLength: '<a href="http://google.com">'.length,
              suffixLength: '</a>'.length
            }
          ],
        },
      ], {
        0: {
          type: 'LINK',
          mutability: 'IMMUTABLE',
          data: {
            href: 'http://google.com',
          }
        },
        1: {
          type: 'LINK',
          mutability: 'IMMUTABLE',
          data: {
            href: 'http://google.com',
          }
        }
      });

      const result = convertToHTML(convertToHTMLProps)(contentState);

      expect(result).toBe('<strong>overlapping</strong> test <a href="http://google.com">Hello</a> <em><a href="http://google.com">World</a></em>');
    });

@benbriggs
Copy link
Contributor

benbriggs commented Apr 27, 2017

Hmm...that still passes for me as well (after adding wrapping <p> tags and defining convertToHTMLProps). Is your local fork/clone up to date to draft-convert@1.4.5?

@liyantang
Copy link

I am on the latest of master branch of 1.4.5. I added this test to the existing tests in converToHTML.js and it throws the error for me.

@benbriggs
Copy link
Contributor

Strange! Could you try submitting it as a PR so that the test runs in Travis and we can have an isolated place to verify that it can be fixed? Thanks for digging into this!

@liyantang
Copy link

liyantang commented Apr 27, 2017

@benbriggs
Copy link
Contributor

Perfect, thanks! I'll dig into it now.

@liyantang
Copy link

Great, thanks!

@benbriggs
Copy link
Contributor

Fix is landed in 1.4.6 - thanks so much for your help @liyantang!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants