@automattic/social-previews 1.0.4 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -5
- package/README.md +38 -0
- package/dist/cjs/facebook-preview/index.js +51 -72
- package/dist/cjs/helpers.js +10 -29
- package/dist/cjs/index.js +8 -8
- package/dist/cjs/search-preview/index.js +31 -31
- package/dist/cjs/twitter-preview/index.js +32 -79
- package/dist/cjs/twitter-preview/style.scss +214 -98
- package/dist/cjs/twitter-preview/tweet.js +346 -0
- package/dist/esm/facebook-preview/index.js +49 -67
- package/dist/esm/helpers.js +9 -28
- package/dist/esm/search-preview/index.js +31 -30
- package/dist/esm/twitter-preview/index.js +30 -74
- package/dist/esm/twitter-preview/style.scss +214 -98
- package/dist/esm/twitter-preview/tweet.js +325 -0
- package/package.json +58 -52
- package/src/facebook-preview/index.jsx +2 -9
- package/src/helpers.js +5 -7
- package/src/search-preview/index.jsx +0 -8
- package/src/twitter-preview/index.jsx +31 -46
- package/src/twitter-preview/style.scss +214 -98
- package/src/twitter-preview/tweet.jsx +296 -0
- package/LICENSE.md +0 -264
|
@@ -1,112 +1,228 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* CSS values in this file are specific and
|
|
3
|
-
* designed to match the CSS on
|
|
4
|
-
* such as Google and Facebook. Therefore there
|
|
3
|
+
* designed to match the CSS on Twitter. Therefore there
|
|
5
4
|
* will be exceptions to our CSS guidelines here
|
|
6
|
-
* but please do not "update" this file to
|
|
7
|
-
* conform.
|
|
5
|
+
* but please do not "update" this file to conform.
|
|
8
6
|
*
|
|
9
|
-
* @blame:
|
|
10
|
-
*/
|
|
7
|
+
* @blame: pento
|
|
8
|
+
*/
|
|
11
9
|
|
|
12
10
|
@import '../variables.scss';
|
|
13
11
|
|
|
14
12
|
/* stylelint-disable scales/font-size */
|
|
15
13
|
|
|
16
14
|
.twitter-preview {
|
|
15
|
+
background-color: #fff;
|
|
17
16
|
padding: 20px;
|
|
18
|
-
|
|
17
|
+
width: 635px;
|
|
19
18
|
}
|
|
20
19
|
|
|
21
|
-
.twitter-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
margin:
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
.twitter-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
20
|
+
.twitter-preview__container {
|
|
21
|
+
display: grid;
|
|
22
|
+
grid-template-columns: 65px auto;
|
|
23
|
+
margin-bottom: 5px;
|
|
24
|
+
margin-right: 24px;
|
|
25
|
+
|
|
26
|
+
.twitter-preview__sidebar {
|
|
27
|
+
display: grid;
|
|
28
|
+
grid-template-rows: 35px auto;
|
|
29
|
+
justify-items: center;
|
|
30
|
+
|
|
31
|
+
.twitter-preview__profile-image {
|
|
32
|
+
img {
|
|
33
|
+
height: 30px;
|
|
34
|
+
width: 30px;
|
|
35
|
+
border-radius: 15px;
|
|
36
|
+
object-fit: cover;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.twitter-preview__connector {
|
|
41
|
+
width: 2px;
|
|
42
|
+
background-color: #8c8f94;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.twitter-preview__name {
|
|
47
|
+
font-weight: bold;
|
|
48
|
+
font-size: 16px;
|
|
49
|
+
line-height: 19px;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.twitter-preview__screen-name,
|
|
53
|
+
.twitter-preview__date {
|
|
54
|
+
color: #667886;
|
|
55
|
+
font-size: 16px;
|
|
56
|
+
line-height: 18px;
|
|
57
|
+
letter-spacing: -0.3px;
|
|
58
|
+
margin-left: 15px;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.twitter-preview__content {
|
|
62
|
+
margin: 7px 0;
|
|
63
|
+
|
|
64
|
+
.twitter-preview__text {
|
|
65
|
+
font-size: 14px;
|
|
66
|
+
line-height: 18px;
|
|
67
|
+
letter-spacing: -0.3px;
|
|
68
|
+
color: #787c82;
|
|
69
|
+
white-space: pre-wrap;
|
|
70
|
+
word-break: break-word;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.twitter-preview__media {
|
|
74
|
+
border-radius: 15px;
|
|
75
|
+
overflow: hidden;
|
|
76
|
+
display: grid;
|
|
77
|
+
grid-gap: 2px;
|
|
78
|
+
grid-template-areas: 'a';
|
|
79
|
+
height: 300px;
|
|
80
|
+
margin-top: 10px;
|
|
81
|
+
|
|
82
|
+
img,
|
|
83
|
+
video {
|
|
84
|
+
width: 100%;
|
|
85
|
+
height: 100%;
|
|
86
|
+
object-fit: cover;
|
|
87
|
+
|
|
88
|
+
&:nth-child( 1 ) {
|
|
89
|
+
grid-area: a;
|
|
90
|
+
}
|
|
91
|
+
&:nth-child( 2 ) {
|
|
92
|
+
grid-area: b;
|
|
93
|
+
}
|
|
94
|
+
&:nth-child( 3 ) {
|
|
95
|
+
grid-area: c;
|
|
96
|
+
}
|
|
97
|
+
&:nth-child( 4 ) {
|
|
98
|
+
grid-area: d;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
&.twitter-preview__media-children-2 {
|
|
103
|
+
grid-template-areas: 'a b';
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
&.twitter-preview__media-children-3 {
|
|
107
|
+
grid-template-areas: 'a b'
|
|
108
|
+
'a c';
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
&.twitter-preview__media-children-4 {
|
|
112
|
+
grid-template-areas: 'a b'
|
|
113
|
+
'c d';
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.twitter-preview__quote-tweet {
|
|
118
|
+
margin-top: 10px;
|
|
119
|
+
min-height: 200px;
|
|
120
|
+
|
|
121
|
+
.twitter-preview__quote-tweet-overlay {
|
|
122
|
+
position: absolute;
|
|
123
|
+
top: 0;
|
|
124
|
+
left: 0;
|
|
125
|
+
right: 0;
|
|
126
|
+
bottom: 0;
|
|
127
|
+
opacity: 0;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.twitter-preview__card {
|
|
132
|
+
margin-top: 10px;
|
|
133
|
+
overflow: hidden;
|
|
134
|
+
border: 1px solid #e1e8ed;
|
|
135
|
+
border-radius: 12px;
|
|
136
|
+
|
|
137
|
+
.twitter-preview__card-summary {
|
|
138
|
+
display: grid;
|
|
139
|
+
|
|
140
|
+
&.twitter-preview__card-has-image {
|
|
141
|
+
height: 125px;
|
|
142
|
+
display: grid;
|
|
143
|
+
grid-template-columns: 125px auto;
|
|
144
|
+
|
|
145
|
+
.twitter-preview__card-body {
|
|
146
|
+
border-left: 1px solid #e1e8ed;
|
|
147
|
+
height: 100%;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.twitter-preview__card-description {
|
|
151
|
+
-webkit-line-clamp: 3;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.twitter-preview__card-summary_large_image {
|
|
157
|
+
display: grid;
|
|
158
|
+
grid-template-rows: 254px auto;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
.twitter-preview__card-image {
|
|
162
|
+
width: 100%;
|
|
163
|
+
height: 100%;
|
|
164
|
+
object-fit: cover;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
.twitter-preview__card-body {
|
|
168
|
+
padding: 0.75em;
|
|
169
|
+
text-decoration: none;
|
|
170
|
+
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
|
171
|
+
font-size: $font-body-small;
|
|
172
|
+
color: black;
|
|
173
|
+
text-align: left;
|
|
174
|
+
line-height: 1.3em;
|
|
175
|
+
overflow: hidden;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
.twitter-preview__card-title {
|
|
179
|
+
max-height: 1.3em;
|
|
180
|
+
white-space: nowrap;
|
|
181
|
+
font-weight: bold;
|
|
182
|
+
font-size: 1em;
|
|
183
|
+
margin: 0 0 0.15em;
|
|
184
|
+
overflow: hidden;
|
|
185
|
+
text-overflow: ellipsis;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.twitter-preview__card-description {
|
|
189
|
+
margin-top: 0.32333em;
|
|
190
|
+
max-height: 3.9em;
|
|
191
|
+
text-overflow: ellipsis;
|
|
192
|
+
//clamp after two lines
|
|
193
|
+
display: -webkit-box;
|
|
194
|
+
-webkit-line-clamp: 2;
|
|
195
|
+
-webkit-box-orient: vertical;
|
|
196
|
+
overflow: hidden;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
.twitter-preview__card-url {
|
|
200
|
+
text-transform: lowercase;
|
|
201
|
+
color: #8899a6;
|
|
202
|
+
max-height: 1.3em;
|
|
203
|
+
white-space: nowrap;
|
|
204
|
+
overflow-inline: hidden;
|
|
205
|
+
text-overflow: ellipsis;
|
|
206
|
+
margin-top: 0.32333em;
|
|
207
|
+
|
|
208
|
+
svg {
|
|
209
|
+
fill: #8899a6;
|
|
210
|
+
height: 15px;
|
|
211
|
+
width: 15px;
|
|
212
|
+
margin: 0 2px -4px 0;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
.twitter-preview__footer {
|
|
219
|
+
display: grid;
|
|
220
|
+
grid-template-columns: repeat( 4, auto );
|
|
221
|
+
|
|
222
|
+
svg {
|
|
223
|
+
fill: #787c82;
|
|
224
|
+
height: 16px;
|
|
225
|
+
width: 16px;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
112
228
|
}
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
import { SandBox } from '@wordpress/components';
|
|
2
|
+
import { __ as alias__ } from '@wordpress/i18n';
|
|
3
|
+
const __ = alias__;
|
|
4
|
+
import classnames from 'classnames';
|
|
5
|
+
import moment from 'moment';
|
|
6
|
+
import PropTypes from 'prop-types';
|
|
7
|
+
import { PureComponent } from 'react';
|
|
8
|
+
import { firstValid, hardTruncation, shortEnough, stripHtmlTags } from '../helpers';
|
|
9
|
+
import './style.scss';
|
|
10
|
+
import { jsx as _jsx } from "@emotion/react/jsx-runtime";
|
|
11
|
+
import { jsxs as _jsxs } from "@emotion/react/jsx-runtime";
|
|
12
|
+
const DESCRIPTION_LENGTH = 200;
|
|
13
|
+
|
|
14
|
+
const baseDomain = url => url.replace(/^[^/]+[/]*(www\.)?/, '') // Strip leading protocol and "www.".
|
|
15
|
+
.replace(/\/.*$/, ''); // Strip everything after the domain.
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
const twitterDescription = firstValid(shortEnough(DESCRIPTION_LENGTH), hardTruncation(DESCRIPTION_LENGTH));
|
|
19
|
+
export class Tweet extends PureComponent {
|
|
20
|
+
/**
|
|
21
|
+
* Renders the sidebar beside the tweet.
|
|
22
|
+
*
|
|
23
|
+
* @param {string} profileImage URL of the Twitter profile image.
|
|
24
|
+
* @param {boolean} isLast Whether or not this is the last tweet in the in a thread.
|
|
25
|
+
* @returns {import('react').Element} The sidebar.
|
|
26
|
+
*/
|
|
27
|
+
renderSidebar(profileImage, isLast) {
|
|
28
|
+
return _jsxs("div", {
|
|
29
|
+
className: "twitter-preview__sidebar",
|
|
30
|
+
children: [_jsx("div", {
|
|
31
|
+
className: "twitter-preview__profile-image",
|
|
32
|
+
children: _jsx("img", {
|
|
33
|
+
alt: __('Twitter profile image'),
|
|
34
|
+
src: profileImage
|
|
35
|
+
})
|
|
36
|
+
}), !isLast && _jsx("div", {
|
|
37
|
+
className: "twitter-preview__connector"
|
|
38
|
+
})]
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Renders the header section of a single tweet.
|
|
43
|
+
*
|
|
44
|
+
* @param {string} name The display name of the Twitter account.
|
|
45
|
+
* @param {string} screenName The at-name of the Twitter account.
|
|
46
|
+
* @param {Date} date The date to be shown for this preview.
|
|
47
|
+
* @returns {import('react').Element} The header.
|
|
48
|
+
*/
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
renderHeader(name, screenName, date) {
|
|
52
|
+
return _jsxs("div", {
|
|
53
|
+
className: "twitter-preview__header",
|
|
54
|
+
children: [_jsx("span", {
|
|
55
|
+
className: "twitter-preview__name",
|
|
56
|
+
children: name
|
|
57
|
+
}), _jsx("span", {
|
|
58
|
+
className: "twitter-preview__screen-name",
|
|
59
|
+
children: screenName
|
|
60
|
+
}), _jsx("span", {
|
|
61
|
+
className: "twitter-preview__date",
|
|
62
|
+
children: moment(date).format('MMM D')
|
|
63
|
+
})]
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Renders the text section of the tweet.
|
|
68
|
+
*
|
|
69
|
+
* @param {string} text The text of the tweet.
|
|
70
|
+
* @param {Array} urls Optional. An array of URLs that are in the text.
|
|
71
|
+
* @param {object} card Optional. The card data for this tweet.
|
|
72
|
+
* @returns {import('react').Element} The text section.
|
|
73
|
+
*/
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
renderText(text) {
|
|
77
|
+
let urls = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
|
|
78
|
+
let card = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
79
|
+
// If the text ends with the card URL, remove it.
|
|
80
|
+
const cardUrl = card.url || '';
|
|
81
|
+
const deCardedText = text.endsWith(cardUrl) ? text.substr(0, text.lastIndexOf(cardUrl)) : text;
|
|
82
|
+
|
|
83
|
+
const __html = urls.reduce((html, url) => html.replace(new RegExp('\\(' + url + '\\)', 'g'), `(<a href="${url}">${url}</a>)`), stripHtmlTags(deCardedText).replace(new RegExp('\\n', 'g'), '<br/>')); // We can enable dangerouslySetInnerHTML here, since the text we're using is stripped
|
|
84
|
+
// of all HTML tags, then only has safe tags added in createTweetMarkup().
|
|
85
|
+
|
|
86
|
+
/* eslint-disable react/no-danger */
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
return _jsx("div", {
|
|
90
|
+
className: "twitter-preview__text",
|
|
91
|
+
dangerouslySetInnerHTML: {
|
|
92
|
+
__html
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
/* eslint-enabled react/no-danger */
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Renders the media section of the tweet. It will render up to four individual images, or a single
|
|
99
|
+
* GIF, or a single video. Any media beyond these limits will be discarded.
|
|
100
|
+
*
|
|
101
|
+
* @param {Array} media The media to include in this tweet.
|
|
102
|
+
* @returns {import('react').Element} The media section.
|
|
103
|
+
*/
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
renderMedia(media) {
|
|
107
|
+
if (!media) {
|
|
108
|
+
return;
|
|
109
|
+
} // Ensure we're only trying to show valid media, and the correct quantity.
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
const filteredMedia = media // Only image/ and video/ mime types are supported.
|
|
113
|
+
.filter(mediaItem => mediaItem.type.startsWith('image/') || mediaItem.type.startsWith('video/')).filter((mediaItem, idx, array) => {
|
|
114
|
+
// We'll always keep the first item.
|
|
115
|
+
if (0 === idx) {
|
|
116
|
+
return true;
|
|
117
|
+
} // If the first item was a video or GIF, discard all subsequent items.
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
if (array[0].type.startsWith('video/') || 'image/gif' === array[0].type) {
|
|
121
|
+
return false;
|
|
122
|
+
} // The first item wasn't a video or GIF, so discard all subsequent videos and GIFs.
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
if (mediaItem.type.startsWith('video/') || 'image/gif' === mediaItem.type) {
|
|
126
|
+
return false;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return true;
|
|
130
|
+
}) // We only want the first four items of the array, at most.
|
|
131
|
+
.slice(0, 4);
|
|
132
|
+
const isVideo = filteredMedia.length > 0 && filteredMedia[0].type.startsWith('video/');
|
|
133
|
+
const mediaClasses = classnames(['twitter-preview__media', 'twitter-preview__media-children-' + filteredMedia.length]);
|
|
134
|
+
|
|
135
|
+
if (0 === filteredMedia.length) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return _jsxs("div", {
|
|
140
|
+
className: mediaClasses,
|
|
141
|
+
children: [
|
|
142
|
+
/* eslint-disable jsx-a11y/media-has-caption */
|
|
143
|
+
isVideo && filteredMedia.map((mediaItem, index) => _jsxs("video", {
|
|
144
|
+
controls: true,
|
|
145
|
+
children: [_jsx("source", {
|
|
146
|
+
src: mediaItem.url,
|
|
147
|
+
type: mediaItem.type
|
|
148
|
+
}), ' ']
|
|
149
|
+
}, `twitter-preview__media-item-${index}`))
|
|
150
|
+
/* eslint-disable jsx-a11y/media-has-caption */
|
|
151
|
+
, !isVideo && filteredMedia.map((mediaItem, index) => _jsx("img", {
|
|
152
|
+
alt: mediaItem.alt,
|
|
153
|
+
src: mediaItem.url
|
|
154
|
+
}, `twitter-preview__media-item-${index}`))]
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Given a tweet URL, renders it as a quoted tweet.
|
|
159
|
+
*
|
|
160
|
+
* @param {string} tweet The tweet URL.
|
|
161
|
+
* @returns {import('react').Element} The quoted tweet.
|
|
162
|
+
*/
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
renderQuoteTweet(tweet) {
|
|
166
|
+
if (!tweet) {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return _jsxs("div", {
|
|
171
|
+
className: "twitter-preview__quote-tweet",
|
|
172
|
+
children: [_jsx(SandBox, {
|
|
173
|
+
html: `<blockquote class="twitter-tweet" data-conversation="none" data-dnt="true"><a href="${tweet}"></a></blockquote>`,
|
|
174
|
+
scripts: ['https://platform.twitter.com/widgets.js'],
|
|
175
|
+
title: "Embedded tweet",
|
|
176
|
+
onFocus: this.hideOverlay
|
|
177
|
+
}), _jsx("div", {
|
|
178
|
+
className: "twitter-preview__quote-tweet-overlay"
|
|
179
|
+
})]
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Given card data, renders the Twitter-style card.
|
|
184
|
+
*
|
|
185
|
+
* @param {object} card The card data.
|
|
186
|
+
* @returns {import('react').Element} The card tweet.
|
|
187
|
+
*/
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
renderCard(card) {
|
|
191
|
+
if (!card) {
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const {
|
|
196
|
+
description,
|
|
197
|
+
image,
|
|
198
|
+
title,
|
|
199
|
+
type,
|
|
200
|
+
url
|
|
201
|
+
} = card;
|
|
202
|
+
const cardClassNames = classnames(`twitter-preview__card-${type}`, {
|
|
203
|
+
'twitter-preview__card-has-image': !!image
|
|
204
|
+
});
|
|
205
|
+
return _jsx("div", {
|
|
206
|
+
className: "twitter-preview__card",
|
|
207
|
+
children: _jsxs("div", {
|
|
208
|
+
className: cardClassNames,
|
|
209
|
+
children: [image && _jsx("img", {
|
|
210
|
+
className: "twitter-preview__card-image",
|
|
211
|
+
src: image,
|
|
212
|
+
alt: ""
|
|
213
|
+
}), _jsxs("div", {
|
|
214
|
+
className: "twitter-preview__card-body",
|
|
215
|
+
children: [_jsx("div", {
|
|
216
|
+
className: "twitter-preview__card-title",
|
|
217
|
+
children: title
|
|
218
|
+
}), _jsx("div", {
|
|
219
|
+
className: "twitter-preview__card-description",
|
|
220
|
+
children: twitterDescription(stripHtmlTags(description))
|
|
221
|
+
}), _jsxs("div", {
|
|
222
|
+
className: "twitter-preview__card-url",
|
|
223
|
+
children: [_jsx("svg", {
|
|
224
|
+
viewBox: "0 0 24 24",
|
|
225
|
+
children: _jsxs("g", {
|
|
226
|
+
children: [_jsx("path", {
|
|
227
|
+
d: "M11.96 14.945c-.067 0-.136-.01-.203-.027-1.13-.318-2.097-.986-2.795-1.932-.832-1.125-1.176-2.508-.968-3.893s.942-2.605 2.068-3.438l3.53-2.608c2.322-1.716 5.61-1.224 7.33 1.1.83 1.127 1.175 2.51.967 3.895s-.943 2.605-2.07 3.438l-1.48 1.094c-.333.246-.804.175-1.05-.158-.246-.334-.176-.804.158-1.05l1.48-1.095c.803-.592 1.327-1.463 1.476-2.45.148-.988-.098-1.975-.69-2.778-1.225-1.656-3.572-2.01-5.23-.784l-3.53 2.608c-.802.593-1.326 1.464-1.475 2.45-.15.99.097 1.975.69 2.778.498.675 1.187 1.15 1.992 1.377.4.114.633.528.52.928-.092.33-.394.547-.722.547z"
|
|
228
|
+
}), _jsx("path", {
|
|
229
|
+
d: "M7.27 22.054c-1.61 0-3.197-.735-4.225-2.125-.832-1.127-1.176-2.51-.968-3.894s.943-2.605 2.07-3.438l1.478-1.094c.334-.245.805-.175 1.05.158s.177.804-.157 1.05l-1.48 1.095c-.803.593-1.326 1.464-1.475 2.45-.148.99.097 1.975.69 2.778 1.225 1.657 3.57 2.01 5.23.785l3.528-2.608c1.658-1.225 2.01-3.57.785-5.23-.498-.674-1.187-1.15-1.992-1.376-.4-.113-.633-.527-.52-.927.112-.4.528-.63.926-.522 1.13.318 2.096.986 2.794 1.932 1.717 2.324 1.224 5.612-1.1 7.33l-3.53 2.608c-.933.693-2.023 1.026-3.105 1.026z"
|
|
230
|
+
})]
|
|
231
|
+
})
|
|
232
|
+
}), baseDomain(url || '')]
|
|
233
|
+
})]
|
|
234
|
+
})]
|
|
235
|
+
})
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Renders the footer section of a single tweet, showing (non-functioning) reply, retweet, etc buttons.
|
|
240
|
+
*
|
|
241
|
+
* @returns {import('react').Element} The footer.
|
|
242
|
+
*/
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
renderFooter() {
|
|
246
|
+
return _jsxs("div", {
|
|
247
|
+
className: "twitter-preview__footer",
|
|
248
|
+
children: [_jsx("span", {
|
|
249
|
+
className: "twitter-preview__icon-replies",
|
|
250
|
+
children: _jsx("svg", {
|
|
251
|
+
viewBox: "0 0 24 24",
|
|
252
|
+
children: _jsx("path", {
|
|
253
|
+
d: "M14.046 2.242l-4.148-.01h-.002c-4.374 0-7.8 3.427-7.8 7.802 0 4.098 3.186 7.206 7.465 7.37v3.828c0 .108.044.286.12.403.142.225.384.347.632.347.138 0 .277-.038.402-.118.264-.168 6.473-4.14 8.088-5.506 1.902-1.61 3.04-3.97 3.043-6.312v-.017c-.006-4.367-3.43-7.787-7.8-7.788zm3.787 12.972c-1.134.96-4.862 3.405-6.772 4.643V16.67c0-.414-.335-.75-.75-.75h-.396c-3.66 0-6.318-2.476-6.318-5.886 0-3.534 2.768-6.302 6.3-6.302l4.147.01h.002c3.532 0 6.3 2.766 6.302 6.296-.003 1.91-.942 3.844-2.514 5.176z"
|
|
254
|
+
})
|
|
255
|
+
})
|
|
256
|
+
}), _jsx("span", {
|
|
257
|
+
className: "twitter-preview__icon-retweets",
|
|
258
|
+
children: _jsx("svg", {
|
|
259
|
+
viewBox: "0 0 24 24",
|
|
260
|
+
children: _jsx("path", {
|
|
261
|
+
d: "M23.77 15.67c-.292-.293-.767-.293-1.06 0l-2.22 2.22V7.65c0-2.068-1.683-3.75-3.75-3.75h-5.85c-.414 0-.75.336-.75.75s.336.75.75.75h5.85c1.24 0 2.25 1.01 2.25 2.25v10.24l-2.22-2.22c-.293-.293-.768-.293-1.06 0s-.294.768 0 1.06l3.5 3.5c.145.147.337.22.53.22s.383-.072.53-.22l3.5-3.5c.294-.292.294-.767 0-1.06zm-10.66 3.28H7.26c-1.24 0-2.25-1.01-2.25-2.25V6.46l2.22 2.22c.148.147.34.22.532.22s.384-.073.53-.22c.293-.293.293-.768 0-1.06l-3.5-3.5c-.293-.294-.768-.294-1.06 0l-3.5 3.5c-.294.292-.294.767 0 1.06s.767.293 1.06 0l2.22-2.22V16.7c0 2.068 1.683 3.75 3.75 3.75h5.85c.414 0 .75-.336.75-.75s-.337-.75-.75-.75z"
|
|
262
|
+
})
|
|
263
|
+
})
|
|
264
|
+
}), _jsx("span", {
|
|
265
|
+
className: "twitter-preview__icon-likes",
|
|
266
|
+
children: _jsx("svg", {
|
|
267
|
+
viewBox: "0 0 24 24",
|
|
268
|
+
children: _jsx("path", {
|
|
269
|
+
d: "M12 21.638h-.014C9.403 21.59 1.95 14.856 1.95 8.478c0-3.064 2.525-5.754 5.403-5.754 2.29 0 3.83 1.58 4.646 2.73.814-1.148 2.354-2.73 4.645-2.73 2.88 0 5.404 2.69 5.404 5.755 0 6.376-7.454 13.11-10.037 13.157H12zM7.354 4.225c-2.08 0-3.903 1.988-3.903 4.255 0 5.74 7.034 11.596 8.55 11.658 1.518-.062 8.55-5.917 8.55-11.658 0-2.267-1.823-4.255-3.903-4.255-2.528 0-3.94 2.936-3.952 2.965-.23.562-1.156.562-1.387 0-.014-.03-1.425-2.965-3.954-2.965z"
|
|
270
|
+
})
|
|
271
|
+
})
|
|
272
|
+
}), _jsx("span", {
|
|
273
|
+
className: "twitter-preview__icon-share",
|
|
274
|
+
children: _jsxs("svg", {
|
|
275
|
+
viewBox: "0 0 24 24",
|
|
276
|
+
children: [_jsx("path", {
|
|
277
|
+
d: "M17.53 7.47l-5-5c-.293-.293-.768-.293-1.06 0l-5 5c-.294.293-.294.768 0 1.06s.767.294 1.06 0l3.72-3.72V15c0 .414.336.75.75.75s.75-.336.75-.75V4.81l3.72 3.72c.146.147.338.22.53.22s.384-.072.53-.22c.293-.293.293-.767 0-1.06z"
|
|
278
|
+
}), _jsx("path", {
|
|
279
|
+
d: "M19.708 21.944H4.292C3.028 21.944 2 20.916 2 19.652V14c0-.414.336-.75.75-.75s.75.336.75.75v5.652c0 .437.355.792.792.792h15.416c.437 0 .792-.355.792-.792V14c0-.414.336-.75.75-.75s.75.336.75.75v5.652c0 1.264-1.028 2.292-2.292 2.292z"
|
|
280
|
+
})]
|
|
281
|
+
})
|
|
282
|
+
})]
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
render() {
|
|
287
|
+
const {
|
|
288
|
+
isLast,
|
|
289
|
+
profileImage,
|
|
290
|
+
name,
|
|
291
|
+
screenName,
|
|
292
|
+
date,
|
|
293
|
+
text,
|
|
294
|
+
media,
|
|
295
|
+
tweet,
|
|
296
|
+
urls,
|
|
297
|
+
card
|
|
298
|
+
} = this.props;
|
|
299
|
+
return _jsxs("div", {
|
|
300
|
+
className: "twitter-preview__container",
|
|
301
|
+
children: [this.renderSidebar(profileImage, isLast), _jsxs("div", {
|
|
302
|
+
className: "twitter-preview__main",
|
|
303
|
+
children: [this.renderHeader(name, screenName, date), _jsxs("div", {
|
|
304
|
+
className: "twitter-preview__content",
|
|
305
|
+
children: [this.renderText(text, urls, card), this.renderMedia(media), this.renderQuoteTweet(tweet), this.renderCard(card)]
|
|
306
|
+
}), this.renderFooter()]
|
|
307
|
+
})]
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
}
|
|
312
|
+
Tweet.propTypes = {
|
|
313
|
+
tweets: PropTypes.array,
|
|
314
|
+
isLast: PropTypes.bool,
|
|
315
|
+
profileImage: PropTypes.string,
|
|
316
|
+
name: PropTypes.string,
|
|
317
|
+
screenName: PropTypes.string,
|
|
318
|
+
date: PropTypes.number,
|
|
319
|
+
text: PropTypes.string,
|
|
320
|
+
media: PropTypes.array,
|
|
321
|
+
tweet: PropTypes.string,
|
|
322
|
+
urls: PropTypes.array,
|
|
323
|
+
card: PropTypes.object
|
|
324
|
+
};
|
|
325
|
+
export default Tweet;
|