html-to-article-json
Version:
Converting HTML to article-json
978 lines (910 loc) • 34.6 kB
JavaScript
import test from './tape-wrapper';
import setupParse from '../lib/parse';
import tsml from 'tsml';
const _parse = setupParse({});
const parse = process.browser
? (html) => {
const node = document.createElement('div');
node.innerHTML = html;
return _parse(node.childNodes);
}
: _parse;
test('parse() single block element node', t => {
const actual = parse('<p></p>');
const expected = [{ type: 'paragraph', children: [] }];
t.same(actual, expected);
});
test('parse() single inline element node', t => {
const actual = parse('<span></span>');
const expected = [];
t.same(actual, expected);
});
test('parse() text in span', t => {
const actual = parse('<span>beep boop</span>');
const expected = [{
bold: false,
content: 'beep boop',
href: null,
italic: false,
type: 'text',
mark: false,
markClass: null,
strikethrough: false
}];
t.same(actual, expected);
});
test('parse() img', t => {
const actual = parse('<img src="http://example.com/image.jpg" />');
const expected = [{
type: 'embed',
embedType: 'image',
caption: [],
attribution: [],
src: 'http://example.com/image.jpg',
width: '',
height: ''
}];
t.same(actual, expected);
});
test('parse() img, with alt-attribute', t => {
const actual = parse('<img src="http://example.com/image.jpg" alt="beep boop" />');
const expected = [{
type: 'embed',
embedType: 'image',
caption: [
{ content: 'beep boop', type: 'text' }
],
attribution: [],
src: 'http://example.com/image.jpg',
width: '',
height: ''
}];
t.same(actual, expected);
});
test('parse() figure + img', t => {
const input = tsml`<figure>
<img src="http://example.com/image.jpg"/>
<figcaption>Hello, <b>world</b></figcaption>
</figure>`;
const actual = parse(input);
const expected = [{
type: 'embed',
embedType: 'image',
caption: [
{ bold: false, content: 'Hello, ', href: null, italic: false, strikethrough: false, type: 'text', mark: false, markClass: null },
{ bold: true, content: 'world', href: null, italic: false, strikethrough: false, type: 'text', mark: false, markClass: null }
],
attribution: [],
src: 'http://example.com/image.jpg',
width: '',
height: ''
}];
t.same(actual, expected);
});
test('parse() figure + img + multiple figcaptions', t => {
const input = tsml`<figure>
<img src="http://example.com/image.jpg"/>
<figcaption>Hello,</figcaption>
<figcaption><b>world</b></figcaption>
</figure>`;
const actual = parse(input);
const expected = [{
type: 'embed',
embedType: 'image',
caption: [
{ bold: false, content: 'Hello,', href: null, italic: false, strikethrough: false, type: 'text', mark: false, markClass: null },
{ bold: true, content: 'world', href: null, italic: false, strikethrough: false, type: 'text', mark: false, markClass: null }
],
attribution: [],
src: 'http://example.com/image.jpg',
width: '',
height: ''
}];
t.same(actual, expected);
});
test('parse() figure + img + figcaption + cite', t => {
const input = tsml`<figure>
<img src="http://example.com/image.jpg"/>
<figcaption>Hello, world<cite><a href="http://example.com">author</a></cite></figcaption>
</figure>`;
const actual = parse(input);
const expected = [{
type: 'embed',
embedType: 'image',
caption: [
{ bold: false, content: 'Hello, world', href: null, italic: false, strikethrough: false, type: 'text', mark: false, markClass: null }
],
attribution: [
{ bold: false, content: 'author', href: 'http://example.com', italic: false, strikethrough: false, type: 'text', mark: false, markClass: null }
],
src: 'http://example.com/image.jpg',
width: '',
height: ''
}];
t.same(actual, expected);
});
test('parse() figure + img + figcaption + cite without anchor tag', t => {
const input = tsml`<figure>
<img src="http://example.com/image.jpg"/>
<figcaption>Hello, world<cite>author</a></figcaption>
</figure>`;
const actual = parse(input);
const expected = [{
type: 'embed',
embedType: 'image',
caption: [
{ bold: false, content: 'Hello, world', href: null, italic: false, strikethrough: false, type: 'text', mark: false, markClass: null }
],
attribution: [
{ bold: false, content: 'author', href: null, italic: false, strikethrough: false, type: 'text', mark: false, markClass: null }
],
src: 'http://example.com/image.jpg',
width: '',
height: ''
}];
t.same(actual, expected);
});
test('parse() figure + img but no figcaption', t => {
const input = tsml`<figure>
<img src="http://example.com/image.jpg"/>
</figure>`;
const actual = parse(input);
const expected = [{
type: 'embed',
embedType: 'image',
caption: [],
attribution: [],
src: 'http://example.com/image.jpg',
width: '',
height: ''
}];
t.same(actual, expected);
});
test('parse() img with width & height', t => {
const input = tsml`<img src="http://example.com/image.jpg" width="100" height="200" />`;
const actual = parse(input);
const expected = [{
type: 'embed',
embedType: 'image',
caption: [],
attribution: [],
src: 'http://example.com/image.jpg',
width: 100,
height: 200
}];
t.same(actual, expected);
});
test('parse() img with width & height css', t => {
const input = tsml`<img src="http://example.com/image.jpg" style="width: 100px; height: 200px" />`;
const actual = parse(input);
const expected = [{
type: 'embed',
embedType: 'image',
caption: [],
attribution: [],
src: 'http://example.com/image.jpg',
width: 100,
height: 200
}];
t.same(actual, expected);
});
test('parse() figure with no content', t => {
const input = tsml`<figure></figure>`;
const actual = parse(input);
const expected = [{
type: 'block',
children: []
}];
t.same(actual, expected);
});
test('parse() figure with unknown content', t => {
const input = tsml`<figure><div>beep</div></figure>`;
const actual = parse(input);
const expected = [{
type: 'block',
children: [{
type: 'block',
children: [{
type: 'text',
mark: false,
markClass: null,
content: 'beep',
href: null,
italic: false,
strikethrough: false,
bold: false
}]
}]
}];
t.same(actual, expected);
});
test('parse() figure + img and figcaption with no content', t => {
const input = tsml`<figure>
<img src="http://example.com/image.jpg"/>
<figcaption></figcaption>
</figure>`;
const actual = parse(input);
const expected = [{
type: 'embed',
embedType: 'image',
caption: [],
attribution: [],
src: 'http://example.com/image.jpg',
width: '',
height: ''
}];
t.same(actual, expected);
});
test('parse() video with src', t => {
const input = '<video src="http://example.com/video.mp4" />';
const actual = parse(input);
const expected = [{
type: 'embed',
embedType: 'video',
caption: [],
attribution: [],
sources: [{
src: 'http://example.com/video.mp4',
type: null
}],
width: '',
height: ''
}];
t.same(actual, expected);
});
test('parse() video with sources', t => {
const input = tsml`<video>
<source src="http://example.com/video.mp4" />
<source src="http://example.com/video2.mp4" type="video/mp4"/>
</video>`;
const actual = parse(input);
const expected = [{
type: 'embed',
embedType: 'video',
caption: [],
attribution: [],
sources: [{
src: 'http://example.com/video.mp4',
type: null
}, {
src: 'http://example.com/video2.mp4',
type: 'video/mp4'
}],
width: '',
height: ''
}];
t.same(actual, expected);
});
test('parse() video with width & height', t => {
const input = '<video src="http://example.com/video.mp4" width="100" height="200" />';
const actual = parse(input);
const expected = [{
type: 'embed',
embedType: 'video',
caption: [],
attribution: [],
sources: [{
src: 'http://example.com/video.mp4',
type: null
}],
width: 100,
height: 200
}];
t.same(actual, expected);
});
test('parse() video with width & height css', t => {
const input = '<video src="http://example.com/video.mp4" style="width:100px;height:200px" />';
const actual = parse(input);
const expected = [{
type: 'embed',
embedType: 'video',
caption: [],
attribution: [],
sources: [{
src: 'http://example.com/video.mp4',
type: null
}],
width: 100,
height: 200
}];
t.same(actual, expected);
});
test('parse() figure + video with src', t => {
const input = '<figure><video src="http://example.com/video.mp4" /></figure>';
const actual = parse(input);
const expected = [{
type: 'embed',
embedType: 'video',
caption: [],
attribution: [],
sources: [{
src: 'http://example.com/video.mp4',
type: null
}],
width: '',
height: ''
}];
t.same(actual, expected);
});
test('parse() figure + video with sources', t => {
const input = tsml`<figure>
<video>
<source src="http://example.com/video.mp4" />
<source src="http://example.com/video2.mp4" type="video/mp4"/>
</video>
</figure>`;
const actual = parse(input);
const expected = [{
type: 'embed',
embedType: 'video',
caption: [],
attribution: [],
sources: [{
src: 'http://example.com/video.mp4',
type: null
}, {
src: 'http://example.com/video2.mp4',
type: 'video/mp4'
}],
width: '',
height: ''
}];
t.same(actual, expected);
});
test('parse() figure + video with src & figcaption', t => {
const input = `<figure>
<video src="http://example.com/video.mp4"></video>
<figcaption>Hello, <b>world</b></figcaption>
</figure>`;
const actual = parse(input);
const expected = [{
type: 'embed',
embedType: 'video',
caption: [
{ bold: false, content: 'Hello, ', href: null, italic: false, strikethrough: false, type: 'text', mark: false, markClass: null },
{ bold: true, content: 'world', href: null, italic: false, strikethrough: false, type: 'text', mark: false, markClass: null }
],
attribution: [],
sources: [{
src: 'http://example.com/video.mp4',
type: null
}],
width: '',
height: ''
}];
t.same(actual, expected);
});
test('parse() youtube iframe', t => {
const input = '<iframe src="https://www.youtube.com/embed/pDVmldTurqk"></iframe>';
const actual = parse(input);
const expected = [{
type: 'embed',
embedType: 'youtube',
caption: [],
attribution: [],
youtubeId: 'pDVmldTurqk'
}];
t.same(actual, expected);
});
test('parse() youtube embedly iframe', t => {
const input = `<iframe
src="//cdn.embedly.com/widgets/media.html?src=http%3A%2F%2Fwww.youtube.com%2Fembed%2F3rS6mZUo3fg%3Ffeature%3Doembed"
></iframe>`;
const actual = parse(input);
const expected = [{
type: 'embed',
embedType: 'youtube',
caption: [],
attribution: [],
youtubeId: '3rS6mZUo3fg'
}];
t.same(actual, expected);
});
test('parse() figure + youtube iframe', t => {
const input = '<figure><iframe src="https://www.youtube.com/embed/pDVmldTurqk"></iframe><figcaption>Hello, <b>world</b></figcaption></figure>';
const actual = parse(input);
const expected = [{
type: 'embed',
embedType: 'youtube',
caption: [
{ bold: false, content: 'Hello, ', href: null, italic: false, strikethrough: false, type: 'text', mark: false, markClass: null },
{ bold: true, content: 'world', href: null, italic: false, strikethrough: false, type: 'text', mark: false, markClass: null }
],
attribution: [],
youtubeId: 'pDVmldTurqk'
}];
t.same(actual, expected);
});
test('parse() tweet - normal', t => {
const input = '<blockquote class="twitter-tweet" lang="en"><p lang="en" dir="ltr">GIF vs. JIF… This <a href="https://t.co/qFAHWgdbL6">pic.twitter.com/qFAHWgdbL6</a></p>— Matt (foo) Navarra (@MattNavarra) <a href="https://twitter.com/MattNavarra/status/684690494841028608">January 6, 2016</a></blockquote><script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>';
const actual = parse(input);
const expected = [{
type: 'embed',
embedType: 'twitter',
embedAs: 'tweet',
caption: [],
attribution: [],
text: [
{ content: 'GIF vs. JIF… This ', href: null },
{ content: 'pic.twitter.com/qFAHWgdbL6', href: 'https://t.co/qFAHWgdbL6' }
],
url: 'https://twitter.com/MattNavarra/status/684690494841028608',
date: 'January 6, 2016',
user: {
slug: 'MattNavarra',
name: 'Matt (foo) Navarra'
},
id: '684690494841028608'
}];
t.same(actual, expected);
});
test('parse() tweet - video', t => {
const input = '<blockquote class="twitter-video" lang="en"><p lang="en" dir="ltr">GIF vs. JIF… This <a href="https://t.co/qFAHWgdbL6">pic.twitter.com/qFAHWgdbL6</a></p>— Matt (foo) Navarra (@MattNavarra) <a href="https://twitter.com/MattNavarra/status/684690494841028608">January 6, 2016</a></blockquote><script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>';
const actual = parse(input);
const expected = [{
type: 'embed',
embedType: 'twitter',
embedAs: 'video',
caption: [],
attribution: [],
text: [
{ content: 'GIF vs. JIF… This ', href: null },
{ content: 'pic.twitter.com/qFAHWgdbL6', href: 'https://t.co/qFAHWgdbL6' }
],
url: 'https://twitter.com/MattNavarra/status/684690494841028608',
date: 'January 6, 2016',
user: {
slug: 'MattNavarra',
name: 'Matt (foo) Navarra'
},
id: '684690494841028608'
}];
t.same(actual, expected);
});
test('parse() tweet - no date', t => {
const input = '<blockquote class="twitter-tweet" lang="en"><p lang="en" dir="ltr">GIF vs. JIF… This <a href="https://t.co/qFAHWgdbL6">pic.twitter.com/qFAHWgdbL6</a></p>— Matt (foo) Navarra (@MattNavarra) <a href="https://twitter.com/MattNavarra/status/684690494841028608"></a></blockquote><script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>';
const actual = parse(input);
const expected = [{
type: 'embed',
embedType: 'twitter',
embedAs: 'tweet',
caption: [],
attribution: [],
text: [
{ content: 'GIF vs. JIF… This ', href: null },
{ content: 'pic.twitter.com/qFAHWgdbL6', href: 'https://t.co/qFAHWgdbL6' }
],
url: 'https://twitter.com/MattNavarra/status/684690494841028608',
date: '',
user: {
slug: 'MattNavarra',
name: 'Matt (foo) Navarra'
},
id: '684690494841028608'
}];
t.same(actual, expected);
});
test('parse() tweet - weird input', t => {
const input = '<blockquote class="twitter-tweet" lang="en"><p lang="en" dir="ltr">foo bar<beep>boop</beep></p>— Matt Navarra (@MattNavarra) <a href="https://twitter.com/MattNavarra/status/684690494841028608">January 6, 2016</a></blockquote><script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>';
const actual = parse(input)[0].text;
const expected = [
{ content: 'foo bar', href: null }
];
t.same(actual, expected);
});
test('parse() tweet - no paragraph, no user', t => {
const input = '<blockquote class="twitter-tweet" lang="en"><a href="https://twitter.com/MattNavarra/status/684690494841028608">January 6, 2016</a></blockquote><script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>';
const actual = parse(input);
const expected = [{
type: 'embed',
embedType: 'twitter',
embedAs: 'tweet',
caption: [],
attribution: [],
text: [],
url: 'https://twitter.com/MattNavarra/status/684690494841028608',
date: 'January 6, 2016',
user: {
slug: null,
name: null
},
id: '684690494841028608'
}];
t.same(actual, expected);
});
test('parse() tweet - no id', t => {
const input = '<blockquote class="twitter-tweet" lang="en"><p lang="en" dir="ltr">GIF vs. JIF… This <a href="https://t.co/qFAHWgdbL6">pic.twitter.com/qFAHWgdbL6</a></p>— Matt (foo) Navarra (@MattNavarra) </blockquote><script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>';
const actual = parse(input);
t.not(actual[0].type, 'embed');
});
test('parse() tweet - href has query string', t => {
const input = '<blockquote class="twitter-tweet" lang="en"><p lang="en" dir="ltr">GIF vs. JIF… This <a href="https://t.co/qFAHWgdbL6">pic.twitter.com/qFAHWgdbL6</a></p>— Matt (foo) Navarra (@MattNavarra) <a href="https://twitter.com/MattNavarra/status/684690494841028608?ref_src=twsrc%5Etfw">January 6, 2016</a></blockquote><script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>';
const actual = parse(input);
const expected = [{
type: 'embed',
embedType: 'twitter',
embedAs: 'tweet',
caption: [],
attribution: [],
text: [
{ content: 'GIF vs. JIF… This ', href: null },
{ content: 'pic.twitter.com/qFAHWgdbL6', href: 'https://t.co/qFAHWgdbL6' }
],
url: 'https://twitter.com/MattNavarra/status/684690494841028608?ref_src=twsrc%5Etfw',
date: 'January 6, 2016',
user: {
slug: 'MattNavarra',
name: 'Matt (foo) Navarra'
},
id: '684690494841028608'
}];
t.same(actual, expected);
});
test('parse() instagram - with caption', t => {
const input = '<blockquote class="instagram-media" data-instgrm-captioned data-instgrm-version="6" style=" background:#FFF; border:0; border-radius:3px; box-shadow:0 0 1px 0 rgba(0,0,0,0.5),0 1px 10px 0 rgba(0,0,0,0.15); margin: 1px; max-width:658px; padding:0; width:99.375%; width:-webkit-calc(100% - 2px); width:calc(100% - 2px);"><div style="padding:8px;"> <div style=" background:#F8F8F8; line-height:0; margin-top:40px; padding:50.0% 0; text-align:center; width:100%;"> <div style=" background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAsCAMAAAApWqozAAAAGFBMVEUiIiI9PT0eHh4gIB4hIBkcHBwcHBwcHBydr+JQAAAACHRSTlMABA4YHyQsM5jtaMwAAADfSURBVDjL7ZVBEgMhCAQBAf//42xcNbpAqakcM0ftUmFAAIBE81IqBJdS3lS6zs3bIpB9WED3YYXFPmHRfT8sgyrCP1x8uEUxLMzNWElFOYCV6mHWWwMzdPEKHlhLw7NWJqkHc4uIZphavDzA2JPzUDsBZziNae2S6owH8xPmX8G7zzgKEOPUoYHvGz1TBCxMkd3kwNVbU0gKHkx+iZILf77IofhrY1nYFnB/lQPb79drWOyJVa/DAvg9B/rLB4cC+Nqgdz/TvBbBnr6GBReqn/nRmDgaQEej7WhonozjF+Y2I/fZou/qAAAAAElFTkSuQmCC); display:block; height:44px; margin:0 auto -44px; position:relative; top:-22px; width:44px;"></div></div> <p style=" margin:8px 0 0 0; padding:0 4px;"> <a href="https://www.instagram.com/p/-7PIhyA6J3/" style=" color:#000; font-family:Arial,sans-serif; font-size:14px; font-style:normal; font-weight:normal; line-height:17px; text-decoration:none; word-wrap:break-word;" target="_blank">Reinsta @karinn In Berlin. Feeling awesome.</a></p> <p style=" color:#c9c8cd; font-family:Arial,sans-serif; font-size:14px; line-height:17px; margin-bottom:0; margin-top:8px; overflow:hidden; padding:8px 0 7px; text-align:center; text-overflow:ellipsis; white-space:nowrap;">A photo posted by David Björklund (@david_bjorklund) on <time style=" font-family:Arial,sans-serif; font-size:14px; line-height:17px;" datetime="2015-12-05T21:40:53+00:00">Dec 5, 2015 at 1:40pm PST</time></p></div></blockquote><script async defer src="//platform.instagram.com/en_US/embeds.js"></script>';
const actual = parse(input);
const expected = [{
type: 'embed',
embedType: 'instagram',
caption: [],
attribution: [],
id: '-7PIhyA6J3',
url: 'https://www.instagram.com/p/-7PIhyA6J3/',
text: 'Reinsta @karinn In Berlin. Feeling awesome.',
date: {string: 'Dec 5, 2015 at 1:40pm PST', utc: '2015-12-05T21:40:53+00:00'},
user: {name: 'David Björklund', slug: 'david_bjorklund'}
}];
t.same(actual, expected);
});
test('parse() instagram figure iframe', t => {
const input = tsml`
<figure contenteditable="false" class="embeddable clearfix embeddable-instagram" id="embeddable-km0e0eo" data-type="instagram">
<div class="embeddable-container">
<iframe src="http://instagram.com/p/fdx1CSuEPV/embed"></iframe>
</div>
</figure>`;
const actual = parse(input);
const expected = [{
type: 'embed',
embedType: 'instagram',
text: '',
id: 'fdx1CSuEPV',
url: 'https://instagram.com/p/fdx1CSuEPV',
caption: [],
attribution: [],
date: '',
user: ''
}];
t.same(actual, expected);
});
test('parse() instagram - without caption', t => {
const input = '<blockquote class="instagram-media" data-instgrm-version="6" style=" background:#FFF; border:0; border-radius:3px; box-shadow:0 0 1px 0 rgba(0,0,0,0.5),0 1px 10px 0 rgba(0,0,0,0.15); margin: 1px; max-width:658px; padding:0; width:99.375%; width:-webkit-calc(100% - 2px); width:calc(100% - 2px);"><div style="padding:8px;"> <div style=" background:#F8F8F8; line-height:0; margin-top:40px; padding:50.0% 0; text-align:center; width:100%;"> <div style=" background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAsCAMAAAApWqozAAAAGFBMVEUiIiI9PT0eHh4gIB4hIBkcHBwcHBwcHBydr+JQAAAACHRSTlMABA4YHyQsM5jtaMwAAADfSURBVDjL7ZVBEgMhCAQBAf//42xcNbpAqakcM0ftUmFAAIBE81IqBJdS3lS6zs3bIpB9WED3YYXFPmHRfT8sgyrCP1x8uEUxLMzNWElFOYCV6mHWWwMzdPEKHlhLw7NWJqkHc4uIZphavDzA2JPzUDsBZziNae2S6owH8xPmX8G7zzgKEOPUoYHvGz1TBCxMkd3kwNVbU0gKHkx+iZILf77IofhrY1nYFnB/lQPb79drWOyJVa/DAvg9B/rLB4cC+Nqgdz/TvBbBnr6GBReqn/nRmDgaQEej7WhonozjF+Y2I/fZou/qAAAAAElFTkSuQmCC); display:block; height:44px; margin:0 auto -44px; position:relative; top:-22px; width:44px;"></div></div><p style=" color:#c9c8cd; font-family:Arial,sans-serif; font-size:14px; line-height:17px; margin-bottom:0; margin-top:8px; overflow:hidden; padding:8px 0 7px; text-align:center; text-overflow:ellipsis; white-space:nowrap;"><a href="https://www.instagram.com/p/-7PIhyA6J3/" style=" color:#c9c8cd; font-family:Arial,sans-serif; font-size:14px; font-style:normal; font-weight:normal; line-height:17px; text-decoration:none;" target="_blank">A photo posted by David Björklund (@david_bjorklund)</a> on <time style=" font-family:Arial,sans-serif; font-size:14px; line-height:17px;" datetime="2015-12-05T21:40:53+00:00">Dec 5, 2015 at 1:40pm PST</time></p></div></blockquote><script async defer src="//platform.instagram.com/en_US/embeds.js"></script>';
const actual = parse(input);
const expected = [{
type: 'embed',
embedType: 'instagram',
caption: [],
attribution: [],
id: '-7PIhyA6J3',
url: 'https://www.instagram.com/p/-7PIhyA6J3/',
text: null,
date: {
string: 'Dec 5, 2015 at 1:40pm PST',
utc: '2015-12-05T21:40:53+00:00'
},
user: {
name: 'David Björklund',
slug: 'david_bjorklund'
}
}];
t.same(actual, expected);
});
test('parse() instagram - bad input', t => {
const input = '<blockquote class="instagram-media" data-instgrm-captioned data-instgrm-version="6" style=" background:#FFF; border:0; border-radius:3px; box-shadow:0 0 1px 0 rgba(0,0,0,0.5),0 1px 10px 0 rgba(0,0,0,0.15); margin: 1px; max-width:658px; padding:0; width:99.375%; width:-webkit-calc(100% - 2px); width:calc(100% - 2px);"></blockquote>';
const actual = parse(input);
const expected = [{ children: [], type: 'blockquote', pullQuote: false }];
t.same(actual, expected);
});
test('parse() facebook - post', t => {
const input = '<div id="fb-root"></div><script>(function(d, s, id) { var js, fjs = d.getElementsByTagName(s)[0]; if (d.getElementById(id)) return; js = d.createElement(s); js.id = id; js.src = "//connect.facebook.net/en_US/sdk.js#xfbml=1&version=v2.3"; fjs.parentNode.insertBefore(js, fjs);}(document, \'script\', \'facebook-jssdk\'));</script><div class="fb-post" data-href="https://www.facebook.com/david.bjorklund/posts/10153809692501070" data-width="500"><div class="fb-xfbml-parse-ignore"><blockquote cite="https://www.facebook.com/david.bjorklund/posts/10153809692501070"><p>Hey!So, for the last few weeks I've worked on http://mic.com/ - the new home for mic.com (on desktop) - please take a look :)</p>Posted by <a href="#" role="button">David Pop Hipsterson</a> on <a href="https://www.facebook.com/david.bjorklund/posts/10153809692501070">Thursday, January 21, 2016</a></blockquote></div></div>';
const actual = parse(input);
const expected = [
{
type: 'block',
children: []
},
{
url: 'https://www.facebook.com/david.bjorklund/posts/10153809692501070',
caption: [],
attribution: [],
type: 'embed',
embedType: 'facebook',
embedAs: 'post',
date: 'Thursday, January 21, 2016',
headline: '',
text: [{
content: 'Hey!So, for the last few weeks I\'ve worked on http://mic.com/ - the new home for mic.com (on desktop) - please take a look :)',
href: null
}],
user: 'David Pop Hipsterson'
}
];
t.same(actual, expected);
});
test('parse() facebook - video', t => {
const input = '<div id="fb-root"></div><script>(function(d, s, id) { var js, fjs = d.getElementsByTagName(s)[0]; if (d.getElementById(id)) return; js = d.createElement(s); js.id = id; js.src = "//connect.facebook.net/en_US/sdk.js#xfbml=1&version=v2.3"; fjs.parentNode.insertBefore(js, fjs);}(document, \'script\', \'facebook-jssdk\'));</script><div class="fb-video" data-allowfullscreen="1" data-href="https://www.facebook.com/MicMedia/videos/1060315987324524/"><div class="fb-xfbml-parse-ignore"><blockquote cite="https://www.facebook.com/MicMedia/videos/1060315987324524/"><a href="https://www.facebook.com/MicMedia/videos/1060315987324524/">Why is breastfeeding in public such a big deal?</a><p>Men and women *both* have nipples — so why do we only shame women for showing theirs... especially when they're breastfeeding?</p>Posted by <a href="https://www.facebook.com/MicMedia/">Mic</a> on Friday, January 15, 2016</blockquote></div></div>';
const actual = parse(input);
const expected = [
{
type: 'block',
children: []
},
{
url: 'https://www.facebook.com/MicMedia/videos/1060315987324524/',
caption: [],
attribution: [],
type: 'embed',
embedType: 'facebook',
embedAs: 'video',
date: 'Friday, January 15, 2016',
headline: 'Why is breastfeeding in public such a big deal?',
text: [{
content: 'Men and women *both* have nipples — so why do we only shame women for showing theirs... especially when they\'re breastfeeding?',
href: null
}],
user: { name: 'Mic', url: 'https://www.facebook.com/MicMedia/' }
}
];
t.same(actual, expected);
});
test('parse() vine', t => {
const input = '<iframe src="https://vine.co/v/bjHh0zHdgZT/embed/simple" width="600" height="600" frameborder="0"></iframe><script src="https://platform.vine.co/static/scripts/embed.js"></script>';
const actual = parse(input);
const expected = [{
id: 'bjHh0zHdgZT',
caption: [],
attribution: [],
type: 'embed',
embedType: 'vine',
url: 'https://vine.co/v/bjHh0zHdgZT/embed/simple'
}];
t.same(actual, expected);
});
test('parse() spotify', t => {
const input = '<iframe src="https://embed.spotify.com/?uri=spotify:user:spotify:playlist:3rgsDhGHZxZ9sB9DQWQfuf" width="200" height="100" frameborder="0"></iframe>';
const actual = parse(input);
const expected = [{
spotifyUri: 'spotify:user:spotify:playlist:3rgsDhGHZxZ9sB9DQWQfuf',
caption: [],
attribution: [],
width: 200,
height: 100,
type: 'embed',
embedType: 'spotify',
url: 'https://embed.spotify.com/?uri=spotify:user:spotify:playlist:3rgsDhGHZxZ9sB9DQWQfuf'
}];
t.same(actual, expected);
});
test('parse() vine embedly', t => {
const input = '<iframe class="embedly-embed" src="//cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fvine.co%2Fv%2FbjHh0zHdgZT%2Fembed%2Fsimple&url=https%3A%2F%2Fvine.co%2Fv%2FbjHh0zHdgZT%2Fembed%2Fsimple&image=https%3A%2F%2Fv.cdn.vine.co%2Fr%2Fthumbs%2F8B474922-0D0E-49AD-B237-6ED46CE85E8A-118-000000FFCD48A9C5_1.0.6.mp4.jpg%3FversionId%3D5mzXl2DXYBvKvF9rhcp.nvEJC.1N86RG&key=25bf3602073943478e54668402a4f5a8&type=text%2Fhtml&schema=vine" width="600" height="600" scrolling="no" frameborder="0" allowfullscreen=""></iframe>';
const actual = parse(input);
const expected = [{
id: 'bjHh0zHdgZT',
caption: [],
attribution: [],
type: 'embed',
embedType: 'vine',
url: 'https://vine.co/v/bjHh0zHdgZT/embed/simple'
}];
t.same(actual, expected);
});
test('parse() iframe no src', t => {
const input = '<iframe class="embedly-embed" width="600" height="600" scrolling="no" frameborder="0" allowfullscreen=""></iframe>';
const actual = parse(input);
const expected = [];
t.same(actual, expected);
});
test('parse() tumblr post', t => {
const input = '<div class="tumblr-post" data-href="https://embed.tumblr.com/embed/post/8_SX4ALNOf1fYyEcjq78YQ/147291233392" data-did="7c08ba46cb75162284770cdee2a59365891a5e18"><a href="http://jencita.tumblr.com/post/147291233392/tswiftdaily-taylor-swift-at-lady-cilento">http://jencita.tumblr.com/post/147291233392/tswiftdaily-taylor-swift-at-lady-cilento</a></div><script async src="https://secure.assets.tumblr.com/post.js"></script>';
const actual = parse(input);
const expected = [{
caption: [],
type: 'embed',
embedType: 'tumblr',
did: '7c08ba46cb75162284770cdee2a59365891a5e18',
url: 'https://embed.tumblr.com/embed/post/8_SX4ALNOf1fYyEcjq78YQ/147291233392',
text: [{
content: 'http://jencita.tumblr.com/post/147291233392/tswiftdaily-taylor-swift-at-lady-cilento',
href: 'http://jencita.tumblr.com/post/147291233392/tswiftdaily-taylor-swift-at-lady-cilento'
}]
}];
t.same(actual, expected);
});
test('parse() tidal video', t => {
const input = '<div class="tidal-embed" data-type="v" data-id="63196259"></div><script src="https://embed.tidal.com/tidal-embed.js"></script>';
const actual = parse(input);
const expected = [{
caption: [],
type: 'embed',
embedType: 'tidal',
dataId: '63196259',
dataType: 'v'
}];
t.same(actual, expected);
});
test('parse() custom embed', t => {
const input = '<iframe src="http://custom.com" width="600" height="600" frameborder="0"></iframe>';
const actual = parse(input);
const expected = [{
type: 'embed',
embedType: 'custom',
src: 'http://custom.com',
width: 600,
height: 600,
secure: false,
caption: [],
attribution: []
}];
t.same(actual, expected);
});
test('parse() custom secure embed', t => {
const input = '<iframe src="https://custom.com" width="600" height="600" frameborder="0"></iframe>';
const actual = parse(input);
const expected = [{
type: 'embed',
embedType: 'custom',
src: 'https://custom.com',
width: 600,
height: 600,
secure: true,
caption: [],
attribution: []
}];
t.same(actual, expected);
});
test('parse() custom secure embed with no protocol', t => {
const input = '<iframe src="//custom.com" width="600" height="600" frameborder="0"></iframe>';
const actual = parse(input);
const expected = [{
type: 'embed',
embedType: 'custom',
src: '//custom.com',
width: 600,
height: 600,
secure: true,
caption: [],
attribution: []
}];
t.same(actual, expected);
});
test('parse() tricky link', t => {
const input = '<p><i>This is italic and <a href="http://link4.com/">this is a link</i> foo bar</a></p>';
const actual = parse(input);
const expected = [{
type: 'paragraph',
children: [
{
type: 'text',
mark: false,
markClass: null,
content: 'This is italic and ',
href: null,
italic: true,
bold: false,
strikethrough: false
},
{
type: 'text',
mark: false,
markClass: null,
content: 'this is a link',
href: 'http://link4.com/',
italic: true,
bold: false,
strikethrough: false
},
{
type: 'text',
mark: false,
markClass: null,
content: ' foo bar',
href: 'http://link4.com/',
italic: false,
bold: false,
strikethrough: false
}
]
}];
t.same(actual, expected);
});
test('parse() mark', t => {
const input = '<mark class="markclass">mark content</mark>';
const actual = parse(input);
const expected = [{
bold: false,
content: 'mark content',
href: null,
italic: false,
type: 'text',
mark: true,
markClass: 'markclass',
strikethrough: false
}];
t.same(actual, expected);
});
test('parse() empty mark', t => {
const input = '<p><mark class="empty-mark-tag"></mark>Text</p>';
const actual = parse(input);
const expected = [{
type: 'paragraph',
children: [{
bold: false,
content: null,
href: null,
italic: false,
strikethrough: false,
mark: true,
markClass: 'empty-mark-tag',
type: 'text'
}, {
bold: false,
content: 'Text',
href: null,
italic: false,
strikethrough: false,
mark: false,
markClass: null,
type: 'text'
}]
}];
t.same(actual, expected);
});
test('parse() strikethrough', t => {
const inputs = [
'<p><s>text</s></p>',
'<p><strike>text</strike></p>',
'<p><del>text</del></p>'
];
const expected = [{
type: 'paragraph',
children: [{
bold: false,
content: 'text',
href: null,
italic: false,
mark: false,
markClass: null,
type: 'text',
strikethrough: true
}]
}];
inputs.forEach(input => {
const actual = parse(input);
t.same(actual, expected);
});
});
if (process.browser) {
test('parse() empty mark with empty text node', t => {
const emptyTextNode = document.createTextNode('');
const emptyMark = document.createElement('mark');
const paragraph = document.createElement('p');
emptyMark.appendChild(emptyTextNode);
paragraph.appendChild(emptyMark);
document.body.appendChild(paragraph);
const actual = _parse(paragraph);
const expected = [{
type: 'paragraph',
children: [{
type: 'text',
content: null,
href: null,
italic: false,
bold: false,
mark: true,
markClass: null,
strikethrough: false
}]
}];
t.same(actual, expected);
});
}