@automattic/social-previews 2.0.0 → 2.0.1-beta.1
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/dist/cjs/facebook-preview/custom-text.js +4 -3
- package/dist/cjs/facebook-preview/custom-text.js.map +1 -1
- package/dist/cjs/facebook-preview/helpers.js +2 -4
- package/dist/cjs/facebook-preview/helpers.js.map +1 -1
- package/dist/cjs/helpers.js +80 -17
- package/dist/cjs/helpers.js.map +1 -1
- package/dist/cjs/index.js +1 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/instagram-preview/constants.js +6 -0
- package/dist/cjs/instagram-preview/constants.js.map +1 -0
- package/dist/cjs/instagram-preview/icons/bookmark.js +9 -0
- package/dist/cjs/instagram-preview/icons/bookmark.js.map +1 -0
- package/dist/cjs/instagram-preview/icons/comment.js +9 -0
- package/dist/cjs/instagram-preview/icons/comment.js.map +1 -0
- package/dist/cjs/instagram-preview/icons/default-avatar.js +9 -0
- package/dist/cjs/instagram-preview/icons/default-avatar.js.map +1 -0
- package/dist/cjs/instagram-preview/icons/heart.js +9 -0
- package/dist/cjs/instagram-preview/icons/heart.js.map +1 -0
- package/dist/cjs/instagram-preview/icons/menu.js +9 -0
- package/dist/cjs/instagram-preview/icons/menu.js.map +1 -0
- package/dist/cjs/instagram-preview/icons/share.js +9 -0
- package/dist/cjs/instagram-preview/icons/share.js.map +1 -0
- package/dist/cjs/instagram-preview/index.js +6 -0
- package/dist/cjs/instagram-preview/index.js.map +1 -0
- package/dist/cjs/instagram-preview/post-preview.js +25 -0
- package/dist/cjs/instagram-preview/post-preview.js.map +1 -0
- package/dist/cjs/instagram-preview/previews.js +15 -0
- package/dist/cjs/instagram-preview/previews.js.map +1 -0
- package/dist/cjs/instagram-preview/style.scss +102 -0
- package/dist/cjs/instagram-preview/types.js +3 -0
- package/dist/cjs/instagram-preview/types.js.map +1 -0
- package/dist/cjs/linkedin-preview/post-preview.js +5 -10
- package/dist/cjs/linkedin-preview/post-preview.js.map +1 -1
- package/dist/cjs/twitter-preview/post-preview.js +1 -1
- package/dist/cjs/twitter-preview/post-preview.js.map +1 -1
- package/dist/cjs/twitter-preview/text.js +1 -6
- package/dist/cjs/twitter-preview/text.js.map +1 -1
- package/dist/esm/facebook-preview/custom-text.js +6 -5
- package/dist/esm/facebook-preview/custom-text.js.map +1 -1
- package/dist/esm/facebook-preview/helpers.js +1 -2
- package/dist/esm/facebook-preview/helpers.js.map +1 -1
- package/dist/esm/helpers.js +79 -16
- package/dist/esm/helpers.js.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/instagram-preview/constants.js +3 -0
- package/dist/esm/instagram-preview/constants.js.map +1 -0
- package/dist/esm/instagram-preview/icons/bookmark.js +5 -0
- package/dist/esm/instagram-preview/icons/bookmark.js.map +1 -0
- package/dist/esm/instagram-preview/icons/comment.js +5 -0
- package/dist/esm/instagram-preview/icons/comment.js.map +1 -0
- package/dist/esm/instagram-preview/icons/default-avatar.js +5 -0
- package/dist/esm/instagram-preview/icons/default-avatar.js.map +1 -0
- package/dist/esm/instagram-preview/icons/heart.js +5 -0
- package/dist/esm/instagram-preview/icons/heart.js.map +1 -0
- package/dist/esm/instagram-preview/icons/menu.js +5 -0
- package/dist/esm/instagram-preview/icons/menu.js.map +1 -0
- package/dist/esm/instagram-preview/icons/share.js +5 -0
- package/dist/esm/instagram-preview/icons/share.js.map +1 -0
- package/dist/esm/instagram-preview/index.js +3 -0
- package/dist/esm/instagram-preview/index.js.map +1 -0
- package/dist/esm/instagram-preview/post-preview.js +21 -0
- package/dist/esm/instagram-preview/post-preview.js.map +1 -0
- package/dist/esm/instagram-preview/previews.js +10 -0
- package/dist/esm/instagram-preview/previews.js.map +1 -0
- package/dist/esm/instagram-preview/style.scss +102 -0
- package/dist/esm/instagram-preview/types.js +2 -0
- package/dist/esm/instagram-preview/types.js.map +1 -0
- package/dist/esm/linkedin-preview/post-preview.js +5 -10
- package/dist/esm/linkedin-preview/post-preview.js.map +1 -1
- package/dist/esm/twitter-preview/post-preview.js +1 -1
- package/dist/esm/twitter-preview/post-preview.js.map +1 -1
- package/dist/esm/twitter-preview/text.js +1 -6
- package/dist/esm/twitter-preview/text.js.map +1 -1
- package/dist/tsconfig-cjs.tsbuildinfo +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/facebook-preview/custom-text.d.ts.map +1 -1
- package/dist/types/facebook-preview/helpers.d.ts +1 -1
- package/dist/types/facebook-preview/helpers.d.ts.map +1 -1
- package/dist/types/helpers.d.ts +5 -2
- package/dist/types/helpers.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/instagram-preview/constants.d.ts +3 -0
- package/dist/types/instagram-preview/constants.d.ts.map +1 -0
- package/dist/types/instagram-preview/icons/bookmark.d.ts +2 -0
- package/dist/types/instagram-preview/icons/bookmark.d.ts.map +1 -0
- package/dist/types/instagram-preview/icons/comment.d.ts +2 -0
- package/dist/types/instagram-preview/icons/comment.d.ts.map +1 -0
- package/dist/types/instagram-preview/icons/default-avatar.d.ts +2 -0
- package/dist/types/instagram-preview/icons/default-avatar.d.ts.map +1 -0
- package/dist/types/instagram-preview/icons/heart.d.ts +2 -0
- package/dist/types/instagram-preview/icons/heart.d.ts.map +1 -0
- package/dist/types/instagram-preview/icons/menu.d.ts +2 -0
- package/dist/types/instagram-preview/icons/menu.d.ts.map +1 -0
- package/dist/types/instagram-preview/icons/share.d.ts +2 -0
- package/dist/types/instagram-preview/icons/share.d.ts.map +1 -0
- package/dist/types/instagram-preview/index.d.ts +3 -0
- package/dist/types/instagram-preview/index.d.ts.map +1 -0
- package/dist/types/instagram-preview/post-preview.d.ts +4 -0
- package/dist/types/instagram-preview/post-preview.d.ts.map +1 -0
- package/dist/types/instagram-preview/previews.d.ts +3 -0
- package/dist/types/instagram-preview/previews.d.ts.map +1 -0
- package/dist/types/instagram-preview/types.d.ts +8 -0
- package/dist/types/instagram-preview/types.d.ts.map +1 -0
- package/dist/types/linkedin-preview/post-preview.d.ts.map +1 -1
- package/dist/types/twitter-preview/text.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/facebook-preview/custom-text.tsx +8 -6
- package/src/facebook-preview/helpers.ts +1 -7
- package/src/helpers.tsx +186 -0
- package/src/index.ts +1 -0
- package/src/instagram-preview/constants.tsx +2 -0
- package/src/instagram-preview/icons/bookmark.tsx +21 -0
- package/src/instagram-preview/icons/comment.tsx +20 -0
- package/src/instagram-preview/icons/default-avatar.tsx +10 -0
- package/src/instagram-preview/icons/heart.tsx +14 -0
- package/src/instagram-preview/icons/menu.tsx +24 -0
- package/src/instagram-preview/icons/share.tsx +30 -0
- package/src/instagram-preview/index.tsx +2 -0
- package/src/instagram-preview/post-preview.tsx +71 -0
- package/src/instagram-preview/previews.tsx +33 -0
- package/src/instagram-preview/style.scss +102 -0
- package/src/instagram-preview/types.ts +9 -0
- package/src/linkedin-preview/post-preview.tsx +7 -12
- package/src/twitter-preview/post-preview.tsx +1 -1
- package/src/twitter-preview/text.tsx +3 -9
- package/src/helpers.ts +0 -107
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
.instagram-preview {
|
|
4
|
+
&__wrapper {
|
|
5
|
+
padding: 20px;
|
|
6
|
+
background-color: #fff;
|
|
7
|
+
margin-inline: auto;
|
|
8
|
+
max-width: clamp(200px, 100%, 555px);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// When the preview is in a section of all previews
|
|
12
|
+
&__section &__wrapper {
|
|
13
|
+
padding: 0;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
&__section.social-preview__section {
|
|
17
|
+
width: clamp(200px, 100%, 555px);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
&__container {
|
|
21
|
+
|
|
22
|
+
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.08);
|
|
23
|
+
overflow: hidden;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
&__header {
|
|
27
|
+
|
|
28
|
+
padding: 0.5rem 1rem;
|
|
29
|
+
display: flex;
|
|
30
|
+
gap: 0.5rem;
|
|
31
|
+
|
|
32
|
+
&--avatar {
|
|
33
|
+
display: flex;
|
|
34
|
+
align-items: center;
|
|
35
|
+
max-width: 32px;
|
|
36
|
+
max-height: 32px;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
&--avatar img {
|
|
40
|
+
width: 100%;
|
|
41
|
+
height: 100%;
|
|
42
|
+
border-radius: 50%;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
&--profile {
|
|
46
|
+
display: flex;
|
|
47
|
+
align-items: center;
|
|
48
|
+
justify-content: space-between;
|
|
49
|
+
flex-grow: 1;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
&--profile-name {
|
|
53
|
+
font-weight: 700;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
&__media {
|
|
58
|
+
display: flex;
|
|
59
|
+
|
|
60
|
+
&--image {
|
|
61
|
+
width: 100%;
|
|
62
|
+
object-fit: cover;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
&__content {
|
|
67
|
+
display: flex;
|
|
68
|
+
flex-direction: column;
|
|
69
|
+
gap: 0.5rem;
|
|
70
|
+
padding: 0.5rem 1rem;
|
|
71
|
+
|
|
72
|
+
a {
|
|
73
|
+
text-decoration: none;
|
|
74
|
+
color: rgb(0, 55, 107);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
&--actions {
|
|
78
|
+
display: flex;
|
|
79
|
+
justify-content: space-between;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
&--actions-primary {
|
|
83
|
+
display: flex;
|
|
84
|
+
align-items: center;
|
|
85
|
+
gap: 1rem;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
&--name {
|
|
89
|
+
font-weight: 600;
|
|
90
|
+
display: inline;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
&--text {
|
|
94
|
+
display: inline;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
&--footer {
|
|
98
|
+
font-weight: 400;
|
|
99
|
+
color: rgb(115, 115, 115);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { SocialPreviewBaseProps, SocialPreviewsBaseProps } from '../types';
|
|
2
|
+
|
|
3
|
+
export type InstagramPreviewProps = Pick< SocialPreviewBaseProps, 'image' > & {
|
|
4
|
+
name: string;
|
|
5
|
+
profileImage: string;
|
|
6
|
+
caption?: string;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export type InstagramPreviewsProps = InstagramPreviewProps & SocialPreviewsBaseProps;
|
|
@@ -56,18 +56,13 @@ export function LinkedInPostPreview( {
|
|
|
56
56
|
</div>
|
|
57
57
|
<div className="linkedin-preview__content">
|
|
58
58
|
{ description ? (
|
|
59
|
-
<div
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
maxChars: FEED_TEXT_MAX_LENGTH,
|
|
67
|
-
maxLines: FEED_TEXT_MAX_LINES,
|
|
68
|
-
} ),
|
|
69
|
-
} }
|
|
70
|
-
/>
|
|
59
|
+
<div className="linkedin-preview__caption">
|
|
60
|
+
{ preparePreviewText( description, {
|
|
61
|
+
platform: 'linkedin',
|
|
62
|
+
maxChars: FEED_TEXT_MAX_LENGTH,
|
|
63
|
+
maxLines: FEED_TEXT_MAX_LINES,
|
|
64
|
+
} ) }
|
|
65
|
+
</div>
|
|
71
66
|
) : null }
|
|
72
67
|
{ hasMedia ? (
|
|
73
68
|
<div className="linkedin-preview__media">
|
|
@@ -36,7 +36,7 @@ export const TwitterPostPreview: React.FC< TwitterPreviewProps > = ( {
|
|
|
36
36
|
{ text ? <Text text={ text } url={ url || '' } retainUrl={ hasMedia } /> : null }
|
|
37
37
|
{ hasMedia ? <Media media={ media } /> : null }
|
|
38
38
|
{ tweet ? <QuoteTweet tweet={ tweet } /> : null }
|
|
39
|
-
{ ! hasMedia && title && description &&
|
|
39
|
+
{ ! hasMedia && title && description && url && (
|
|
40
40
|
<Card
|
|
41
41
|
description={ description }
|
|
42
42
|
image={ image }
|
|
@@ -11,15 +11,9 @@ export const Text: React.FC< TextProps > = ( { text, url, retainUrl } ) => {
|
|
|
11
11
|
? text.substring( 0, text.lastIndexOf( url ) )
|
|
12
12
|
: text;
|
|
13
13
|
|
|
14
|
-
const __html = preparePreviewText( tweetText, { platform: 'twitter' } );
|
|
15
|
-
|
|
16
14
|
return (
|
|
17
|
-
<div
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
// of all HTML tags, then only has safe tags added in createTweetMarkup().
|
|
21
|
-
// eslint-disable-next-line react/no-danger
|
|
22
|
-
dangerouslySetInnerHTML={ { __html } }
|
|
23
|
-
/>
|
|
15
|
+
<div className="twitter-preview__text">
|
|
16
|
+
{ preparePreviewText( tweetText, { platform: 'twitter' } ) }
|
|
17
|
+
</div>
|
|
24
18
|
);
|
|
25
19
|
};
|
package/src/helpers.ts
DELETED
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
export type Formatter = ( text: string, options?: any ) => string;
|
|
2
|
-
type AugmentFormatterReturnType< T extends Formatter, TNewReturn > = (
|
|
3
|
-
...a: Parameters< T >
|
|
4
|
-
) => ReturnType< T > | TNewReturn;
|
|
5
|
-
type ConditionalFormatter = AugmentFormatterReturnType< Formatter, boolean >;
|
|
6
|
-
type NullableFormatter = AugmentFormatterReturnType< Formatter, undefined >;
|
|
7
|
-
|
|
8
|
-
export const baseDomain = ( url: string ): string =>
|
|
9
|
-
url
|
|
10
|
-
.replace( /^[^/]+[/]*/, '' ) // strip leading protocol
|
|
11
|
-
.replace( /\/.*$/, '' ); // strip everything after the domain
|
|
12
|
-
|
|
13
|
-
export const shortEnough: ( n: number ) => ConditionalFormatter = ( limit ) => ( title ) =>
|
|
14
|
-
title.length <= limit ? title : false;
|
|
15
|
-
|
|
16
|
-
export const truncatedAtSpace: ( a: number, b: number ) => ConditionalFormatter =
|
|
17
|
-
( lower, upper ) => ( fullTitle ) => {
|
|
18
|
-
const title = fullTitle.slice( 0, upper );
|
|
19
|
-
const lastSpace = title.lastIndexOf( ' ' );
|
|
20
|
-
|
|
21
|
-
return lastSpace > lower && lastSpace < upper
|
|
22
|
-
? title.slice( 0, lastSpace ).concat( '…' )
|
|
23
|
-
: false;
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
export const hardTruncation: ( n: number ) => Formatter = ( limit ) => ( title ) =>
|
|
27
|
-
title.slice( 0, limit ).concat( '…' );
|
|
28
|
-
|
|
29
|
-
export const firstValid: ( ...args: ConditionalFormatter[] ) => NullableFormatter =
|
|
30
|
-
( ...predicates ) =>
|
|
31
|
-
( a ) =>
|
|
32
|
-
( predicates.find( ( p ) => false !== p( a ) ) as Formatter )?.( a );
|
|
33
|
-
|
|
34
|
-
export const stripHtmlTags: Formatter = ( description, allowedTags = [] ) => {
|
|
35
|
-
const pattern = new RegExp( `(<([^${ allowedTags.join( '' ) }>]+)>)`, 'gi' );
|
|
36
|
-
|
|
37
|
-
return description ? description.replace( pattern, '' ) : '';
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
export const hasTag = ( text: string, tag: string ): boolean => {
|
|
41
|
-
const pattern = new RegExp( `<${ tag }[^>]*>`, 'gi' );
|
|
42
|
-
|
|
43
|
-
return pattern.test( text );
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
export const formatTweetDate = new Intl.DateTimeFormat( 'en-US', {
|
|
47
|
-
// Result: "Apr 7", "Dec 31"
|
|
48
|
-
month: 'short',
|
|
49
|
-
day: 'numeric',
|
|
50
|
-
} ).format;
|
|
51
|
-
|
|
52
|
-
type Platform = 'twitter' | 'facebook' | 'linkedin';
|
|
53
|
-
|
|
54
|
-
type PreviewTextOptions = {
|
|
55
|
-
platform: Platform;
|
|
56
|
-
maxChars?: number;
|
|
57
|
-
maxLines?: number;
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Prepares the text for the preview.
|
|
62
|
-
*/
|
|
63
|
-
export function preparePreviewText( text: string, options: PreviewTextOptions ): string {
|
|
64
|
-
const { platform, maxChars, maxLines } = options;
|
|
65
|
-
|
|
66
|
-
let result = stripHtmlTags( text );
|
|
67
|
-
|
|
68
|
-
if ( maxChars && result.length > maxChars ) {
|
|
69
|
-
result = result.substring( 0, maxChars );
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
if ( maxLines ) {
|
|
73
|
-
const lines = result.split( '\n' );
|
|
74
|
-
|
|
75
|
-
if ( lines.length > maxLines ) {
|
|
76
|
-
result = lines.slice( 0, maxLines ).join( '\n' );
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// Convert URLs to hyperlinks.
|
|
81
|
-
result = result.replace(
|
|
82
|
-
// TODO: Use a better regex here to match the URLs without protocol.
|
|
83
|
-
/(https?:\/\/\S+)/g,
|
|
84
|
-
'<a href="$1" rel="noopener noreferrer" target="_blank">$1</a>'
|
|
85
|
-
);
|
|
86
|
-
|
|
87
|
-
let hashtagUrl;
|
|
88
|
-
|
|
89
|
-
if ( 'twitter' === platform ) {
|
|
90
|
-
hashtagUrl = 'https://twitter.com/hashtag/';
|
|
91
|
-
} else if ( 'linkedin' === platform ) {
|
|
92
|
-
hashtagUrl = 'https://www.linkedin.com/feed/hashtag/?keywords=';
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
if ( hashtagUrl ) {
|
|
96
|
-
// Convert hashtags to hyperlinks.
|
|
97
|
-
result = result.replace(
|
|
98
|
-
/(^|\s)#(\w+)/g,
|
|
99
|
-
'$1<a href="' + hashtagUrl + '$2" rel="noopener noreferrer" target="_blank">#$2</a>'
|
|
100
|
-
);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// Convert newlines to <br> tags.
|
|
104
|
-
result = result.replace( /\n/g, '<br/>' );
|
|
105
|
-
|
|
106
|
-
return result;
|
|
107
|
-
}
|