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

Added new template mapping for using Rettiwt provider #1409

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 37 additions & 1 deletion packages/kg-default-nodes/lib/nodes/embed/types/twitter.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export default function render(node, document, options) {

const tweetData = metadata && metadata.tweet_data;
const isEmail = options.target === 'email';
const source = tweetData && tweetData.source;

if (tweetData && isEmail) {
const tweetId = tweetData.id;
Expand Down Expand Up @@ -39,7 +40,8 @@ export default function render(node, document, options) {
}
const hasPoll = tweetData.attachments && tweetData.attachments && tweetData.attachments.poll_ids;

if (mentions) {
// for compatibility with previous api provider
if (mentions && source !== 'rettiwt') {
let last = 0;
let parts = [];
let content = toArray(tweetContent);
Expand Down Expand Up @@ -92,6 +94,40 @@ export default function render(node, document, options) {
}, '');
}

// for compatibility with new api provider
if (tweetData && source === 'rettiwt') {
const wrapWithStyle = (text, style) => `<span style="${style}">${text}</span>`;

let formattedContent = tweetContent.replace(/\n/g, '<br>');

const tcoLinks = formattedContent.match(/https:\/\/t\.co\/[a-zA-Z0-9]+/g) || [];
const displayUrls = urls.map(urlObj => urlObj.display_url);
tcoLinks.forEach((tcoLink, index) => {
if (index < displayUrls.length) {
formattedContent = formattedContent.replace(
tcoLink,
wrapWithStyle(displayUrls[index], 'color: #1DA1F2; word-break: break-all;')
);
}
});
Comment on lines +103 to +112
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With Rettiwt we don't have the start / end positioning of links like we have with the official API, in order to replace the shortened link with the actual link for better aesthetics.
However we do get an array with the urls from the tweet eg ['https://url1.com', 'https://url2.com'] and based on manual experimenting they appear in the order of which links appear in a post - however I don't think that's guaranteed based on the documentation.

Do you think it's worth the risk of a potential bad render should the ordering not render in the order as expected?


mentions.forEach(({username}) => {
formattedContent = formattedContent.replace(
`@${username}`,
wrapWithStyle(`@${username}`, 'color: #1DA1F2;')
);
});

hashtags.forEach(({tag}) => {
formattedContent = formattedContent.replace(
`#${tag}`,
wrapWithStyle(`#${tag}`, 'color: #1DA1F2;')
);
});

tweetContent = formattedContent;
}

html = `
<table cellspacing="0" cellpadding="0" border="0" class="kg-twitter-card">
<tr>
Expand Down
292 changes: 292 additions & 0 deletions packages/kg-default-nodes/test/nodes/embed.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,298 @@ describe('EmbedNode', function () {
element.outerHTML.should.containEql(`<a href="https://twitter.com/twitter/status/${tweetData.id}"`);
}));

it('renders twitter email embed with source as rettiwt', editorTest(function () {
const options = {
target: 'email'
};
const tweetData = {
id: '1630581157568839683',
created_at: '2023-02-28T14:50:17.000Z',
author_id: '767545134',
edit_history_tweet_ids: ['1630581157568839683'],
public_metrics: {
retweet_count: 10,
reply_count: 2,
like_count: 38,
quote_count: 6,
impression_count: 10770
},
entities: {
urls: [{
url: 'https://twitter.com',
display_url: 'twitter.com'
}, {
url: 'https://twitter.com/ghost',
display_url: 'twitter.com/ghost'
}]
},
text: 'With the decline of traditional local news outlets, publishers like @MadisonMinutes, @RANGEMedia4all, and @sfsimplified are leading the charge in creating sustainable, community-driven journalism through websites and newsletters.\n' +
'\n' +
'Check out their impact 👇\n' +
'https://t.co/RdNNyY18Iv',

source: 'rettiwt'
};

const embedNode = $createEmbedNode({
url: 'https://twitter.com/ghost/status/1395670367216619520',
embedType: 'twitter',
html: '<blockquote class="twitter-tweet"><p lang="en" dir="ltr">Ghost 4.0 is out now! 🎉</p>&mdash; Ghost (@ghost) <a href="https://twitter.com/ghost/status/1395670367216619520?ref_src=twsrc%5Etfw">May 21, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>',
metadata: {
tweet_data: tweetData,
height: 500,
provider_name: 'Twitter',
provider_url: 'https://twitter.com',
thumbnail_height: 150,
thumbnail_url: 'https://pbs.twimg.com/media/E1Y1q3bXMAU7m4n?format=jpg&name=small',
thumbnail_width: 150,
title: 'Ghost on Twitter: "Ghost 4.0 is out now! 🎉"',
type: 'rich',
version: '1.0',
width: 550
},
caption: 'caption text'
});

const {element} = embedNode.exportDOM({...exportOptions, ...options});

element.outerHTML.should.containEql('<table cellspacing="0" cellpadding="0" border="0" class="kg-twitter-card">');
element.outerHTML.should.containEql(`<a href="https://twitter.com/twitter/status/${tweetData.id}"`);
}));

it('Replaces twitter links with display urls from entities', editorTest(function () {
const options = {
target: 'email'
};
const tweetData = {
id: '1630581157568839683',
created_at: '2023-02-28T14:50:17.000Z',
author_id: '767545134',
edit_history_tweet_ids: ['1630581157568839683'],
public_metrics: {
retweet_count: 10,
reply_count: 2,
like_count: 38,
quote_count: 6,
impression_count: 10770
},
text: 'With the decline of traditional local news outlets, publishers like @MadisonMinutes, @RANGEMedia4all, and @sfsimplified are leading the charge in creating sustainable, community-driven journalism through websites and newsletters.\n' +
'\n' +
'https://t.co/fakehome' +
'Check out their impact 👇\n' +
'https://t.co/fakeghost',
lang: 'en',
conversation_id: '1630581157568839683',
possibly_sensitive: false,
reply_settings: 'everyone',
entities: {
urls: [
{
url: 'https://home.com',
display_url: 'home.com'
},
{
url: 'https://ghost.org',
display_url: 'ghost.org'
}
]
},
source: 'rettiwt'
};

const embedNode = $createEmbedNode({
url: 'https://twitter.com/ghost/status/1395670367216619520',
embedType: 'twitter',
html: '<blockquote class="twitter-tweet"><p lang="en" dir="ltr">Ghost 4.0 is out now! 🎉</p>&mdash; Ghost (@ghost) <a href="https://twitter.com/ghost/status/1395670367216619520?ref_src=twsrc%5Etfw">May 21, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>',
metadata: {
tweet_data: tweetData,
height: 500,
provider_name: 'Twitter',
provider_url: 'https://twitter.com',
thumbnail_height: 150,
thumbnail_url: 'https://pbs.twimg.com/media/E1Y1q3bXMAU7m4n?format=jpg&name=small',
thumbnail_width: 150,
title: 'Ghost on Twitter: "Ghost 4.0 is out now! 🎉"',
type: 'rich',
version: '1.0',
width: 550
},
caption: 'caption text'
});

const {element} = embedNode.exportDOM({...exportOptions, ...options});

element.outerHTML.should.containEql('<table cellspacing="0" cellpadding="0" border="0" class="kg-twitter-card">');
// the first link should be replaced with the display_url
element.outerHTML.should.containEql('<span style="color: #1DA1F2; word-break: break-all;">home.com</span>');

element.outerHTML.should.containEql('<span style="color: #1DA1F2; word-break: break-all;">ghost.org</span>');
// the second link should be replaced with the display_url
}));

it('Wraps mentions in blue span', editorTest(function () {
const options = {
target: 'email'
};
const tweetData = {
id: '1630581157568839683',
created_at: '2023-02-28T14:50:17.000Z',
author_id: '767545134',
edit_history_tweet_ids: ['1630581157568839683'],
public_metrics: {
retweet_count: 10,
reply_count: 2,
like_count: 38,
quote_count: 6,
impression_count: 10770
},
text: 'With the decline of traditional local news outlets, publishers like @MadisonMinutes, @RANGEMedia4all, and @sfsimplified are leading the charge in creating sustainable, community-driven journalism through websites and newsletters.\n' +
'\n' +
'https://t.co/fakehome' +
'Check out their impact 👇\n' +
'https://t.co/fakeghost',
lang: 'en',
conversation_id: '1630581157568839683',
possibly_sensitive: false,
reply_settings: 'everyone',
entities: {
urls: [
{
url: 'https://twitter.com',
display_url: 'twitter.com'
},
{
url: 'https://twitter.com/ghost',
display_url: 'twitter.com/ghost'
}
],
mentions: [
{
username: 'MadisonMinutes'
},
{
username: 'RANGEMedia4all'
},
{
username: 'sfsimplified'
}
]
},
source: 'rettiwt'
};

const embedNode = $createEmbedNode({
url: 'https://twitter.com/ghost/status/1395670367216619520',
embedType: 'twitter',
html: '<blockquote class="twitter-tweet"><p lang="en" dir="ltr">Ghost 4.0 is out now! 🎉</p>&mdash; Ghost (@ghost) <a href="https://twitter.com/ghost/status/1395670367216619520?ref_src=twsrc%5Etfw">May 21, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>',
metadata: {
tweet_data: tweetData,
height: 500,
provider_name: 'Twitter',
provider_url: 'https://twitter.com',
thumbnail_height: 150,
thumbnail_url: 'https://pbs.twimg.com/media/E1Y1q3bXMAU7m4n?format=jpg&name=small',
thumbnail_width: 150,
title: 'Ghost on Twitter: "Ghost 4.0 is out now! 🎉"',
type: 'rich',
version: '1.0',
width: 550
},
caption: 'caption text'
});

const {element} = embedNode.exportDOM({...exportOptions, ...options});

element.outerHTML.should.containEql('<span style="color: #1DA1F2;">@MadisonMinutes</span>');
element.outerHTML.should.containEql('<span style="color: #1DA1F2;">@RANGEMedia4all</span>');
element.outerHTML.should.containEql('<span style="color: #1DA1F2;">@sfsimplified</span>');
}));

it('Wraps hashtags in blue span', editorTest(function () {
const options = {
target: 'email'
};
const tweetData = {
id: '1630581157568839683',
created_at: '2023-02-28T14:50:17.000Z',
author_id: '767545134',
edit_history_tweet_ids: ['1630581157568839683'],
public_metrics: {
retweet_count: 10,
reply_count: 2,
like_count: 38,
quote_count: 6,
impression_count: 10770
},
text: 'With the decline of traditional local news outlets, publishers like @MadisonMinutes, @RANGEMedia4all, and @sfsimplified are leading the charge in creating #sustainable, community-driven #journalism through websites and newsletters.\n' +
'\n' +
'https://t.co/fakehome' +
'Check out their impact 👇\n' +
'https://t.co/fakeghost',
lang: 'en',
conversation_id: '1630581157568839683',
possibly_sensitive: false,
reply_settings: 'everyone',
entities: {
urls: [
{
url: 'https://twitter.com',
display_url: 'twitter.com'
},
{
url: 'https://twitter.com/ghost',
display_url: 'twitter.com/ghost'
}
],
mentions: [
{
username: 'MadisonMinutes'
},
{
username: 'RANGEMedia4all'
},
{
username: 'sfsimplified'
}
],
hashtags: [
{
tag: 'sustainable'
},
{
tag: 'journalism'
}
]
},
source: 'rettiwt'
};

const embedNode = $createEmbedNode({
url: 'https://twitter.com/ghost/status/1395670367216619520',
embedType: 'twitter',
html: '<blockquote class="twitter-tweet"><p lang="en" dir="ltr">Ghost 4.0 is out now! 🎉</p>&mdash; Ghost (@ghost) <a href="https://twitter.com/ghost/status/1395670367216619520?ref_src=twsrc%5Etfw">May 21, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>',
metadata: {
tweet_data: tweetData,
height: 500,
provider_name: 'Twitter',
provider_url: 'https://twitter.com',
thumbnail_height: 150,
thumbnail_url: 'https://pbs.twimg.com/media/E1Y1q3bXMAU7m4n?format=jpg&name=small',
thumbnail_width: 150,
title: 'Ghost on Twitter: "Ghost 4.0 is out now! 🎉"',
type: 'rich',
version: '1.0',
width: 550
},
caption: 'caption text'
});

const {element} = embedNode.exportDOM({...exportOptions, ...options});

element.outerHTML.should.containEql('<span style="color: #1DA1F2;">#sustainable</span>');
element.outerHTML.should.containEql('<span style="color: #1DA1F2;">#journalism</span>');
}));

it('renders video in email', editorTest(function () {
const options = {
target: 'email'
Expand Down
Loading