react-datocms 3.0.10 → 3.0.13
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/Seo/types.js +0 -2
- package/dist/cjs/Seo/types.js.map +1 -1
- package/dist/cjs/StructuredText/index.js.map +1 -1
- package/dist/esm/Seo/types.d.ts +4 -4
- package/dist/esm/Seo/types.js +0 -2
- package/dist/esm/Seo/types.js.map +1 -1
- package/dist/esm/StructuredText/index.d.ts +3 -3
- package/dist/esm/StructuredText/index.js.map +1 -1
- package/dist/types/Seo/types.d.ts +4 -4
- package/dist/types/StructuredText/index.d.ts +3 -3
- package/package.json +3 -2
- package/src/Image/__tests__/__snapshots__/index.test.tsx.snap +948 -0
- package/src/Image/__tests__/index.test.tsx +62 -0
- package/src/Image/index.tsx +294 -0
- package/src/Seo/__tests__/__snapshots__/index.test.tsx.snap +249 -0
- package/src/Seo/__tests__/index.test.tsx +309 -0
- package/src/Seo/index.ts +4 -0
- package/src/Seo/remixUtils.ts +34 -0
- package/src/Seo/renderMetaTags.tsx +32 -0
- package/src/Seo/renderMetaTagsToString.tsx +21 -0
- package/src/Seo/types.tsx +53 -0
- package/src/StructuredText/__tests__/__snapshots__/index.test.tsx.snap +331 -0
- package/src/StructuredText/__tests__/index.test.tsx +271 -0
- package/src/StructuredText/index.tsx +244 -0
- package/src/index.ts +4 -0
- package/src/setupTests.ts +6 -0
- package/src/useQuerySubscription/index.ts +89 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { mount } from 'enzyme';
|
|
3
|
+
import 'intersection-observer';
|
|
4
|
+
import { Image } from '../index';
|
|
5
|
+
import { mockAllIsIntersecting } from 'react-intersection-observer/test-utils';
|
|
6
|
+
|
|
7
|
+
const data = {
|
|
8
|
+
alt: 'DatoCMS swag',
|
|
9
|
+
aspectRatio: 1.7777777777777777,
|
|
10
|
+
base64:
|
|
11
|
+
'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAoHBwgHBgoICAgLFQoLDhgQDg0NDh0eHREYIx8lJCIrHB0dLSs7GikyKSEuKjUlKDk1MjIyHyo4PTc+PDcxPjUBCgsLDg0OHBAQHDsoIig7Ozs7Ozs7OzsvOzs7Ozs7Ozs7Lzs7Ozs7Ozs7OzsvOzs7NTsvLy87NTU1Ly8vLzsvL//AABEIAA0AGAMBIgACEQEDEQH/xAAYAAACAwAAAAAAAAAAAAAAAAAGBwABBP/EACEQAAEEAAYDAAAAAAAAAAAAAAEAAgMEBQYHESEiFWFx/8QAFQEBAQAAAAAAAAAAAAAAAAAAAwL/xAAZEQADAAMAAAAAAAAAAAAAAAAAAQIRITH/2gAMAwEAAhEDEQA/AFxLgDWTsAd1J5TGy7hEYqNAaNgECX7sjLMQAHJTEy1Zcarfia4lJMauAxqBhLY6ZlaOzDurWvUOd3jZPfCiEh4xs//Z',
|
|
12
|
+
height: 421,
|
|
13
|
+
sizes: '(max-width: 750px) 100vw, 750px',
|
|
14
|
+
src: 'https://www.datocms-assets.com/205/image.png?ar=16%3A9&fit=crop&w=750',
|
|
15
|
+
srcSet:
|
|
16
|
+
'https://www.datocms-assets.com/205/image.png?ar=16%3A9&dpr=0.25&fit=crop&w=750 187w,↵https://www.datocms-assets.com/205/image.png?ar=16%3A9&dpr=0.5&fit=crop&w=750 375w,↵https://www.datocms-assets.com/205/image.png?ar=16%3A9&dpr=0.75&fit=crop&w=750 562w,↵https://www.datocms-assets.com/205/image.png?ar=16%3A9&dpr=1&fit=crop&w=750 750w,↵https://www.datocms-assets.com/205/image.png?ar=16%3A9&dpr=1.5&fit=crop&w=750 1125w,↵https://www.datocms-assets.com/205/image.png?ar=16%3A9&dpr=2&fit=crop&w=750 1500w,↵https://www.datocms-assets.com/205/image.png?ar=16%3A9&dpr=3&fit=crop&w=750 2250w,↵https://www.datocms-assets.com/205/image.png?ar=16%3A9&dpr=4&fit=crop&w=750 3000w',
|
|
17
|
+
title: 'These are awesome, we know that.',
|
|
18
|
+
width: 750,
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
describe('Image', () => {
|
|
22
|
+
// intersectionThreshold is an hack to make tests work
|
|
23
|
+
// we need the library to generate a different IntersectionObserver for each test
|
|
24
|
+
// otherwise the IntersectionObserver mocking won't work
|
|
25
|
+
|
|
26
|
+
(['intrinsic', 'fixed', 'responsive', 'fill'] as const).forEach((layout) => {
|
|
27
|
+
describe(`layout=${layout}`, () => {
|
|
28
|
+
describe('not visible', () => {
|
|
29
|
+
it('renders the blur-up thumb', () => {
|
|
30
|
+
const wrapper = mount(
|
|
31
|
+
<Image data={data} layout={layout} intersectionThreshold={0.1} />,
|
|
32
|
+
);
|
|
33
|
+
expect(wrapper).toMatchSnapshot();
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
describe('visible', () => {
|
|
38
|
+
it('renders the image', () => {
|
|
39
|
+
const wrapper = mount(
|
|
40
|
+
<Image data={data} layout={layout} intersectionThreshold={0.2} />,
|
|
41
|
+
);
|
|
42
|
+
mockAllIsIntersecting(true);
|
|
43
|
+
wrapper.update();
|
|
44
|
+
expect(wrapper).toMatchSnapshot();
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
describe('image loaded', () => {
|
|
48
|
+
it('shows the image', () => {
|
|
49
|
+
const wrapper = mount(
|
|
50
|
+
<Image data={data} layout={layout} intersectionThreshold={0.3} />,
|
|
51
|
+
);
|
|
52
|
+
mockAllIsIntersecting(true);
|
|
53
|
+
wrapper.update();
|
|
54
|
+
wrapper.find('img').last().simulate('load');
|
|
55
|
+
wrapper.update();
|
|
56
|
+
expect(wrapper).toMatchSnapshot();
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
});
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
import React, { useState, forwardRef, useCallback, CSSProperties } from 'react';
|
|
2
|
+
import { useInView } from 'react-intersection-observer';
|
|
3
|
+
import { encode } from 'universal-base64';
|
|
4
|
+
|
|
5
|
+
const isSsr = typeof window === 'undefined';
|
|
6
|
+
|
|
7
|
+
const isIntersectionObserverAvailable = isSsr
|
|
8
|
+
? false
|
|
9
|
+
: !!(window as any).IntersectionObserver;
|
|
10
|
+
|
|
11
|
+
type Maybe<T> = T | null;
|
|
12
|
+
|
|
13
|
+
export type ResponsiveImageType = {
|
|
14
|
+
/** The aspect ratio (width/height) of the image */
|
|
15
|
+
aspectRatio: number;
|
|
16
|
+
/** A base64-encoded thumbnail to offer during image loading */
|
|
17
|
+
base64?: Maybe<string>;
|
|
18
|
+
/** The height of the image */
|
|
19
|
+
height?: Maybe<number>;
|
|
20
|
+
/** The width of the image */
|
|
21
|
+
width: number;
|
|
22
|
+
/** The HTML5 `sizes` attribute for the image */
|
|
23
|
+
sizes?: Maybe<string>;
|
|
24
|
+
/** The fallback `src` attribute for the image */
|
|
25
|
+
src?: Maybe<string>;
|
|
26
|
+
/** The HTML5 `srcSet` attribute for the image */
|
|
27
|
+
srcSet?: Maybe<string>;
|
|
28
|
+
/** The HTML5 `srcSet` attribute for the image in WebP format, for browsers that support the format */
|
|
29
|
+
webpSrcSet?: Maybe<string>;
|
|
30
|
+
/** The background color for the image placeholder */
|
|
31
|
+
bgColor?: Maybe<string>;
|
|
32
|
+
/** Alternate text (`alt`) for the image */
|
|
33
|
+
alt?: Maybe<string>;
|
|
34
|
+
/** Title attribute (`title`) for the image */
|
|
35
|
+
title?: Maybe<string>;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
type ImagePropTypes = {
|
|
39
|
+
/** The actual response you get from a DatoCMS `responsiveImage` GraphQL query */
|
|
40
|
+
data: ResponsiveImageType;
|
|
41
|
+
/** Additional CSS className for root node */
|
|
42
|
+
className?: string;
|
|
43
|
+
/** Additional CSS class for the image inside the `<picture />` tag */
|
|
44
|
+
pictureClassName?: string;
|
|
45
|
+
/** Duration (in ms) of the fade-in transition effect upoad image loading */
|
|
46
|
+
fadeInDuration?: number;
|
|
47
|
+
/** @deprecated Use the intersectionThreshold prop */
|
|
48
|
+
intersectionTreshold?: number;
|
|
49
|
+
/** Indicate at what percentage of the placeholder visibility the loading of the image should be triggered. A value of 0 means that as soon as even one pixel is visible, the callback will be run. A value of 1.0 means that the threshold isn't considered passed until every pixel is visible */
|
|
50
|
+
intersectionThreshold?: number;
|
|
51
|
+
/** Margin around the placeholder. Can have values similar to the CSS margin property (top, right, bottom, left). The values can be percentages. This set of values serves to grow or shrink each side of the placeholder element's bounding box before computing intersections */
|
|
52
|
+
intersectionMargin?: string;
|
|
53
|
+
/** Whether enable lazy loading or not */
|
|
54
|
+
lazyLoad?: boolean;
|
|
55
|
+
/** Additional CSS rules to add to the root node */
|
|
56
|
+
style?: React.CSSProperties;
|
|
57
|
+
/** Additional CSS rules to add to the image inside the `<picture />` tag */
|
|
58
|
+
pictureStyle?: React.CSSProperties;
|
|
59
|
+
/**
|
|
60
|
+
* The layout behavior of the image as the viewport changes size
|
|
61
|
+
*
|
|
62
|
+
* Possible values:
|
|
63
|
+
*
|
|
64
|
+
* * `intrinsic` (default): the image will scale the dimensions down for smaller viewports, but maintain the original dimensions for larger viewports
|
|
65
|
+
* * `fixed`: the image dimensions will not change as the viewport changes (no responsiveness) similar to the native img element
|
|
66
|
+
* * `responsive`: the image will scale the dimensions down for smaller viewports and scale up for larger viewports
|
|
67
|
+
* * `fill`: image will stretch both width and height to the dimensions of the parent element, provided the parent element is `relative`
|
|
68
|
+
* */
|
|
69
|
+
layout?: 'intrinsic' | 'fixed' | 'responsive' | 'fill';
|
|
70
|
+
/** Defines how the image will fit into its parent container when using layout="fill" */
|
|
71
|
+
objectFit?: CSSProperties['objectFit'];
|
|
72
|
+
/** Defines how the image is positioned within its parent element when using layout="fill". */
|
|
73
|
+
objectPosition?: CSSProperties['objectPosition'];
|
|
74
|
+
/** Triggered when the image finishes loading */
|
|
75
|
+
onLoad?(): void;
|
|
76
|
+
/** Whether the component should use a blurred image placeholder */
|
|
77
|
+
usePlaceholder?: boolean;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
type State = {
|
|
81
|
+
lazyLoad: boolean;
|
|
82
|
+
inView: boolean;
|
|
83
|
+
loaded: boolean;
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const imageAddStrategy = ({ lazyLoad, inView, loaded }: State) => {
|
|
87
|
+
if (!lazyLoad) {
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (isSsr) {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (isIntersectionObserverAvailable) {
|
|
96
|
+
return inView || loaded;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return true;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
const imageShowStrategy = ({ lazyLoad, loaded }: State) => {
|
|
103
|
+
if (!lazyLoad) {
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (isSsr) {
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (isIntersectionObserverAvailable) {
|
|
112
|
+
return loaded;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return true;
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
export const Image = forwardRef<HTMLDivElement, ImagePropTypes>(
|
|
119
|
+
(
|
|
120
|
+
{
|
|
121
|
+
className,
|
|
122
|
+
fadeInDuration = 500,
|
|
123
|
+
intersectionTreshold,
|
|
124
|
+
intersectionThreshold,
|
|
125
|
+
intersectionMargin,
|
|
126
|
+
pictureClassName,
|
|
127
|
+
lazyLoad = true,
|
|
128
|
+
style,
|
|
129
|
+
pictureStyle,
|
|
130
|
+
layout = 'intrinsic',
|
|
131
|
+
objectFit,
|
|
132
|
+
objectPosition,
|
|
133
|
+
data,
|
|
134
|
+
onLoad,
|
|
135
|
+
usePlaceholder = true,
|
|
136
|
+
},
|
|
137
|
+
ref,
|
|
138
|
+
) => {
|
|
139
|
+
const [loaded, setLoaded] = useState(false);
|
|
140
|
+
|
|
141
|
+
const handleLoad = () => {
|
|
142
|
+
onLoad?.();
|
|
143
|
+
setLoaded(true);
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
const [viewRef, inView] = useInView({
|
|
147
|
+
threshold: intersectionThreshold || intersectionTreshold || 0,
|
|
148
|
+
rootMargin: intersectionMargin || '0px 0px 0px 0px',
|
|
149
|
+
triggerOnce: true,
|
|
150
|
+
fallbackInView: true,
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
const callbackRef = useCallback(
|
|
154
|
+
(_ref: HTMLDivElement) => {
|
|
155
|
+
viewRef(_ref);
|
|
156
|
+
if (ref) (ref as React.MutableRefObject<HTMLDivElement>).current = _ref;
|
|
157
|
+
},
|
|
158
|
+
[viewRef],
|
|
159
|
+
);
|
|
160
|
+
|
|
161
|
+
const absolutePositioning: React.CSSProperties = {
|
|
162
|
+
position: 'absolute',
|
|
163
|
+
left: 0,
|
|
164
|
+
top: 0,
|
|
165
|
+
width: '100%',
|
|
166
|
+
height: '100%',
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
const addImage = imageAddStrategy({
|
|
170
|
+
lazyLoad,
|
|
171
|
+
inView,
|
|
172
|
+
loaded,
|
|
173
|
+
});
|
|
174
|
+
const showImage = imageShowStrategy({
|
|
175
|
+
lazyLoad,
|
|
176
|
+
inView,
|
|
177
|
+
loaded,
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
const webpSource = data.webpSrcSet && (
|
|
181
|
+
<source
|
|
182
|
+
srcSet={data.webpSrcSet}
|
|
183
|
+
sizes={data.sizes ?? undefined}
|
|
184
|
+
type="image/webp"
|
|
185
|
+
/>
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
const regularSource = data.srcSet && (
|
|
189
|
+
<source srcSet={data.srcSet} sizes={data.sizes ?? undefined} />
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
const transition =
|
|
193
|
+
fadeInDuration > 0 ? `opacity ${fadeInDuration}ms` : undefined;
|
|
194
|
+
|
|
195
|
+
const placeholder = usePlaceholder ? (
|
|
196
|
+
<img
|
|
197
|
+
role="presentation"
|
|
198
|
+
aria-hidden="true"
|
|
199
|
+
alt=""
|
|
200
|
+
src={data.base64 ?? undefined}
|
|
201
|
+
style={{
|
|
202
|
+
backgroundColor: data.bgColor ?? undefined,
|
|
203
|
+
opacity: showImage ? 0 : 1,
|
|
204
|
+
transition,
|
|
205
|
+
objectFit,
|
|
206
|
+
objectPosition,
|
|
207
|
+
position: 'absolute',
|
|
208
|
+
left: 0,
|
|
209
|
+
top: 0,
|
|
210
|
+
width: '100%',
|
|
211
|
+
}}
|
|
212
|
+
/>
|
|
213
|
+
) : null;
|
|
214
|
+
|
|
215
|
+
const { width, aspectRatio } = data;
|
|
216
|
+
const height = data.height || width / aspectRatio;
|
|
217
|
+
|
|
218
|
+
const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}"></svg>`;
|
|
219
|
+
|
|
220
|
+
const sizer =
|
|
221
|
+
layout !== 'fill' ? (
|
|
222
|
+
<img
|
|
223
|
+
className={pictureClassName}
|
|
224
|
+
style={{
|
|
225
|
+
display: 'block',
|
|
226
|
+
width: '100%',
|
|
227
|
+
}}
|
|
228
|
+
src={`data:image/svg+xml;base64,${encode(svg)}`}
|
|
229
|
+
aria-hidden="true"
|
|
230
|
+
alt=""
|
|
231
|
+
/>
|
|
232
|
+
) : null;
|
|
233
|
+
|
|
234
|
+
return (
|
|
235
|
+
<div
|
|
236
|
+
ref={callbackRef}
|
|
237
|
+
className={className}
|
|
238
|
+
style={{
|
|
239
|
+
overflow: 'hidden',
|
|
240
|
+
...(layout === 'fill'
|
|
241
|
+
? absolutePositioning
|
|
242
|
+
: layout === 'intrinsic'
|
|
243
|
+
? { position: 'relative', width: '100%', maxWidth: width }
|
|
244
|
+
: layout === 'fixed'
|
|
245
|
+
? { position: 'relative', width }
|
|
246
|
+
: { position: 'relative', width: '100%' }),
|
|
247
|
+
...style,
|
|
248
|
+
}}
|
|
249
|
+
>
|
|
250
|
+
{sizer}
|
|
251
|
+
{placeholder}
|
|
252
|
+
{addImage && (
|
|
253
|
+
<picture>
|
|
254
|
+
{webpSource}
|
|
255
|
+
{regularSource}
|
|
256
|
+
{data.src && (
|
|
257
|
+
<img
|
|
258
|
+
src={data.src}
|
|
259
|
+
alt={data.alt ?? ''}
|
|
260
|
+
title={data.title ?? undefined}
|
|
261
|
+
onLoad={handleLoad}
|
|
262
|
+
className={pictureClassName}
|
|
263
|
+
style={{
|
|
264
|
+
opacity: showImage ? 1 : 0,
|
|
265
|
+
transition,
|
|
266
|
+
...absolutePositioning,
|
|
267
|
+
objectFit,
|
|
268
|
+
objectPosition,
|
|
269
|
+
...pictureStyle,
|
|
270
|
+
}}
|
|
271
|
+
/>
|
|
272
|
+
)}
|
|
273
|
+
</picture>
|
|
274
|
+
)}
|
|
275
|
+
<noscript>
|
|
276
|
+
<picture>
|
|
277
|
+
{webpSource}
|
|
278
|
+
{regularSource}
|
|
279
|
+
{data.src && (
|
|
280
|
+
<img
|
|
281
|
+
src={data.src}
|
|
282
|
+
alt={data.alt ?? ''}
|
|
283
|
+
title={data.title ?? undefined}
|
|
284
|
+
className={pictureClassName}
|
|
285
|
+
style={{ ...absolutePositioning, ...pictureStyle }}
|
|
286
|
+
loading="lazy"
|
|
287
|
+
/>
|
|
288
|
+
)}
|
|
289
|
+
</picture>
|
|
290
|
+
</noscript>
|
|
291
|
+
</div>
|
|
292
|
+
);
|
|
293
|
+
},
|
|
294
|
+
);
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`renderMetaTags generates an array of meta tags 1`] = `
|
|
4
|
+
<head>
|
|
5
|
+
<title
|
|
6
|
+
key="title"
|
|
7
|
+
>
|
|
8
|
+
Remix CMS - The easiest way to manage content with Remix
|
|
9
|
+
</title>
|
|
10
|
+
<meta
|
|
11
|
+
content="Remix CMS - The easiest way to manage content with Remix"
|
|
12
|
+
key="meta-og:title"
|
|
13
|
+
property="og:title"
|
|
14
|
+
/>
|
|
15
|
+
<meta
|
|
16
|
+
content="Remix CMS - The easiest way to manage content with Remix"
|
|
17
|
+
key="meta-twitter:title"
|
|
18
|
+
name="twitter:title"
|
|
19
|
+
/>
|
|
20
|
+
<meta
|
|
21
|
+
content="Remix makes building scalable and fast React apps simple, pair it with a CMS that shares the same intuitiveness. Start a new Remix + Dato project now."
|
|
22
|
+
key="meta-description"
|
|
23
|
+
name="description"
|
|
24
|
+
/>
|
|
25
|
+
<meta
|
|
26
|
+
content="Remix makes building scalable and fast React apps simple, pair it with a CMS that shares the same intuitiveness. Start a new Remix + Dato project now."
|
|
27
|
+
key="meta-og:description"
|
|
28
|
+
property="og:description"
|
|
29
|
+
/>
|
|
30
|
+
<meta
|
|
31
|
+
content="Remix makes building scalable and fast React apps simple, pair it with a CMS that shares the same intuitiveness. Start a new Remix + Dato project now."
|
|
32
|
+
key="meta-twitter:description"
|
|
33
|
+
name="twitter:description"
|
|
34
|
+
/>
|
|
35
|
+
<meta
|
|
36
|
+
content="https://www.datocms-assets.com/205/1642515293-full-logo.svg?fit=max&fm=jpg&w=1000"
|
|
37
|
+
key="meta-og:image"
|
|
38
|
+
property="og:image"
|
|
39
|
+
/>
|
|
40
|
+
<meta
|
|
41
|
+
content="746"
|
|
42
|
+
key="meta-og:image:width"
|
|
43
|
+
property="og:image:width"
|
|
44
|
+
/>
|
|
45
|
+
<meta
|
|
46
|
+
content="186"
|
|
47
|
+
key="meta-og:image:height"
|
|
48
|
+
property="og:image:height"
|
|
49
|
+
/>
|
|
50
|
+
<meta
|
|
51
|
+
content="https://www.datocms-assets.com/205/1642515293-full-logo.svg?fit=max&fm=jpg&w=1000"
|
|
52
|
+
key="meta-twitter:image"
|
|
53
|
+
name="twitter:image"
|
|
54
|
+
/>
|
|
55
|
+
<meta
|
|
56
|
+
content="en"
|
|
57
|
+
key="meta-og:locale"
|
|
58
|
+
property="og:locale"
|
|
59
|
+
/>
|
|
60
|
+
<meta
|
|
61
|
+
content="article"
|
|
62
|
+
key="meta-og:type"
|
|
63
|
+
property="og:type"
|
|
64
|
+
/>
|
|
65
|
+
<meta
|
|
66
|
+
content="DatoCMS"
|
|
67
|
+
key="meta-og:site_name"
|
|
68
|
+
property="og:site_name"
|
|
69
|
+
/>
|
|
70
|
+
<meta
|
|
71
|
+
content="2022-01-18T14:02:47Z"
|
|
72
|
+
key="meta-article:modified_time"
|
|
73
|
+
property="article:modified_time"
|
|
74
|
+
/>
|
|
75
|
+
<meta
|
|
76
|
+
content="summary_large_image"
|
|
77
|
+
key="meta-twitter:card"
|
|
78
|
+
name="twitter:card"
|
|
79
|
+
/>
|
|
80
|
+
<meta
|
|
81
|
+
content="@datocms"
|
|
82
|
+
key="meta-twitter:site"
|
|
83
|
+
name="twitter:site"
|
|
84
|
+
/>
|
|
85
|
+
<link
|
|
86
|
+
href="https://www.datocms-assets.com/205/1525789775-dato.png?h=16&w=16"
|
|
87
|
+
key="link-icon-16x16"
|
|
88
|
+
rel="icon"
|
|
89
|
+
sizes="16x16"
|
|
90
|
+
type="image/png"
|
|
91
|
+
/>
|
|
92
|
+
<link
|
|
93
|
+
href="https://www.datocms-assets.com/205/1525789775-dato.png?h=32&w=32"
|
|
94
|
+
key="link-icon-32x32"
|
|
95
|
+
rel="icon"
|
|
96
|
+
sizes="32x32"
|
|
97
|
+
type="image/png"
|
|
98
|
+
/>
|
|
99
|
+
<link
|
|
100
|
+
href="https://www.datocms-assets.com/205/1525789775-dato.png?h=96&w=96"
|
|
101
|
+
key="link-icon-96x96"
|
|
102
|
+
rel="icon"
|
|
103
|
+
sizes="96x96"
|
|
104
|
+
type="image/png"
|
|
105
|
+
/>
|
|
106
|
+
<link
|
|
107
|
+
href="https://www.datocms-assets.com/205/1525789775-dato.png?h=192&w=192"
|
|
108
|
+
key="link-icon-192x192"
|
|
109
|
+
rel="icon"
|
|
110
|
+
sizes="192x192"
|
|
111
|
+
type="image/png"
|
|
112
|
+
/>
|
|
113
|
+
<link
|
|
114
|
+
href="https://www.datocms-assets.com/205/1525789775-dato.png?h=57&w=57"
|
|
115
|
+
key="link-apple-touch-icon-57x57"
|
|
116
|
+
rel="apple-touch-icon"
|
|
117
|
+
sizes="57x57"
|
|
118
|
+
/>
|
|
119
|
+
<link
|
|
120
|
+
href="https://www.datocms-assets.com/205/1525789775-dato.png?h=60&w=60"
|
|
121
|
+
key="link-apple-touch-icon-60x60"
|
|
122
|
+
rel="apple-touch-icon"
|
|
123
|
+
sizes="60x60"
|
|
124
|
+
/>
|
|
125
|
+
<link
|
|
126
|
+
href="https://www.datocms-assets.com/205/1525789775-dato.png?h=72&w=72"
|
|
127
|
+
key="link-apple-touch-icon-72x72"
|
|
128
|
+
rel="apple-touch-icon"
|
|
129
|
+
sizes="72x72"
|
|
130
|
+
/>
|
|
131
|
+
<link
|
|
132
|
+
href="https://www.datocms-assets.com/205/1525789775-dato.png?h=76&w=76"
|
|
133
|
+
key="link-apple-touch-icon-76x76"
|
|
134
|
+
rel="apple-touch-icon"
|
|
135
|
+
sizes="76x76"
|
|
136
|
+
/>
|
|
137
|
+
<link
|
|
138
|
+
href="https://www.datocms-assets.com/205/1525789775-dato.png?h=114&w=114"
|
|
139
|
+
key="link-apple-touch-icon-114x114"
|
|
140
|
+
rel="apple-touch-icon"
|
|
141
|
+
sizes="114x114"
|
|
142
|
+
/>
|
|
143
|
+
<link
|
|
144
|
+
href="https://www.datocms-assets.com/205/1525789775-dato.png?h=120&w=120"
|
|
145
|
+
key="link-apple-touch-icon-120x120"
|
|
146
|
+
rel="apple-touch-icon"
|
|
147
|
+
sizes="120x120"
|
|
148
|
+
/>
|
|
149
|
+
<link
|
|
150
|
+
href="https://www.datocms-assets.com/205/1525789775-dato.png?h=144&w=144"
|
|
151
|
+
key="link-apple-touch-icon-144x144"
|
|
152
|
+
rel="apple-touch-icon"
|
|
153
|
+
sizes="144x144"
|
|
154
|
+
/>
|
|
155
|
+
<link
|
|
156
|
+
href="https://www.datocms-assets.com/205/1525789775-dato.png?h=152&w=152"
|
|
157
|
+
key="link-apple-touch-icon-152x152"
|
|
158
|
+
rel="apple-touch-icon"
|
|
159
|
+
sizes="152x152"
|
|
160
|
+
/>
|
|
161
|
+
<link
|
|
162
|
+
href="https://www.datocms-assets.com/205/1525789775-dato.png?h=180&w=180"
|
|
163
|
+
key="link-apple-touch-icon-180x180"
|
|
164
|
+
rel="apple-touch-icon"
|
|
165
|
+
sizes="180x180"
|
|
166
|
+
/>
|
|
167
|
+
<meta
|
|
168
|
+
content="https://www.datocms-assets.com/205/1525789775-dato.png?h=70&w=70"
|
|
169
|
+
key="meta-msapplication-square70x70logo"
|
|
170
|
+
name="msapplication-square70x70logo"
|
|
171
|
+
/>
|
|
172
|
+
<meta
|
|
173
|
+
content="https://www.datocms-assets.com/205/1525789775-dato.png?h=150&w=150"
|
|
174
|
+
key="meta-msapplication-square150x150logo"
|
|
175
|
+
name="msapplication-square150x150logo"
|
|
176
|
+
/>
|
|
177
|
+
<meta
|
|
178
|
+
content="https://www.datocms-assets.com/205/1525789775-dato.png?h=310&w=310"
|
|
179
|
+
key="meta-msapplication-square310x310logo"
|
|
180
|
+
name="msapplication-square310x310logo"
|
|
181
|
+
/>
|
|
182
|
+
<meta
|
|
183
|
+
content="https://www.datocms-assets.com/205/1525789775-dato.png?h=150&w=310"
|
|
184
|
+
key="meta-msapplication-square310x150logo"
|
|
185
|
+
name="msapplication-square310x150logo"
|
|
186
|
+
/>
|
|
187
|
+
</head>
|
|
188
|
+
`;
|
|
189
|
+
|
|
190
|
+
exports[`renderMetaTagsToString generates an array of meta tags 1`] = `
|
|
191
|
+
"<title>Remix CMS - The easiest way to manage content with Remix</title>
|
|
192
|
+
<meta property=\\"og:title\\" content=\\"Remix CMS - The easiest way to manage content with Remix\\" />
|
|
193
|
+
<meta name=\\"twitter:title\\" content=\\"Remix CMS - The easiest way to manage content with Remix\\" />
|
|
194
|
+
<meta name=\\"description\\" content=\\"Remix makes building scalable and fast React apps simple, pair it with a CMS that shares the same intuitiveness. Start a new Remix + Dato project now.\\" />
|
|
195
|
+
<meta property=\\"og:description\\" content=\\"Remix makes building scalable and fast React apps simple, pair it with a CMS that shares the same intuitiveness. Start a new Remix + Dato project now.\\" />
|
|
196
|
+
<meta name=\\"twitter:description\\" content=\\"Remix makes building scalable and fast React apps simple, pair it with a CMS that shares the same intuitiveness. Start a new Remix + Dato project now.\\" />
|
|
197
|
+
<meta property=\\"og:image\\" content=\\"https://www.datocms-assets.com/205/1642515293-full-logo.svg?fit=max&fm=jpg&w=1000\\" />
|
|
198
|
+
<meta property=\\"og:image:width\\" content=\\"746\\" />
|
|
199
|
+
<meta property=\\"og:image:height\\" content=\\"186\\" />
|
|
200
|
+
<meta name=\\"twitter:image\\" content=\\"https://www.datocms-assets.com/205/1642515293-full-logo.svg?fit=max&fm=jpg&w=1000\\" />
|
|
201
|
+
<meta property=\\"og:locale\\" content=\\"en\\" />
|
|
202
|
+
<meta property=\\"og:type\\" content=\\"article\\" />
|
|
203
|
+
<meta property=\\"og:site_name\\" content=\\"DatoCMS\\" />
|
|
204
|
+
<meta property=\\"article:modified_time\\" content=\\"2022-01-18T14:02:47Z\\" />
|
|
205
|
+
<meta name=\\"twitter:card\\" content=\\"summary_large_image\\" />
|
|
206
|
+
<meta name=\\"twitter:site\\" content=\\"@datocms\\" />
|
|
207
|
+
<link sizes=\\"16x16\\" type=\\"image/png\\" rel=\\"icon\\" href=\\"https://www.datocms-assets.com/205/1525789775-dato.png?h=16&w=16\\" />
|
|
208
|
+
<link sizes=\\"32x32\\" type=\\"image/png\\" rel=\\"icon\\" href=\\"https://www.datocms-assets.com/205/1525789775-dato.png?h=32&w=32\\" />
|
|
209
|
+
<link sizes=\\"96x96\\" type=\\"image/png\\" rel=\\"icon\\" href=\\"https://www.datocms-assets.com/205/1525789775-dato.png?h=96&w=96\\" />
|
|
210
|
+
<link sizes=\\"192x192\\" type=\\"image/png\\" rel=\\"icon\\" href=\\"https://www.datocms-assets.com/205/1525789775-dato.png?h=192&w=192\\" />
|
|
211
|
+
<link sizes=\\"57x57\\" rel=\\"apple-touch-icon\\" href=\\"https://www.datocms-assets.com/205/1525789775-dato.png?h=57&w=57\\" />
|
|
212
|
+
<link sizes=\\"60x60\\" rel=\\"apple-touch-icon\\" href=\\"https://www.datocms-assets.com/205/1525789775-dato.png?h=60&w=60\\" />
|
|
213
|
+
<link sizes=\\"72x72\\" rel=\\"apple-touch-icon\\" href=\\"https://www.datocms-assets.com/205/1525789775-dato.png?h=72&w=72\\" />
|
|
214
|
+
<link sizes=\\"76x76\\" rel=\\"apple-touch-icon\\" href=\\"https://www.datocms-assets.com/205/1525789775-dato.png?h=76&w=76\\" />
|
|
215
|
+
<link sizes=\\"114x114\\" rel=\\"apple-touch-icon\\" href=\\"https://www.datocms-assets.com/205/1525789775-dato.png?h=114&w=114\\" />
|
|
216
|
+
<link sizes=\\"120x120\\" rel=\\"apple-touch-icon\\" href=\\"https://www.datocms-assets.com/205/1525789775-dato.png?h=120&w=120\\" />
|
|
217
|
+
<link sizes=\\"144x144\\" rel=\\"apple-touch-icon\\" href=\\"https://www.datocms-assets.com/205/1525789775-dato.png?h=144&w=144\\" />
|
|
218
|
+
<link sizes=\\"152x152\\" rel=\\"apple-touch-icon\\" href=\\"https://www.datocms-assets.com/205/1525789775-dato.png?h=152&w=152\\" />
|
|
219
|
+
<link sizes=\\"180x180\\" rel=\\"apple-touch-icon\\" href=\\"https://www.datocms-assets.com/205/1525789775-dato.png?h=180&w=180\\" />
|
|
220
|
+
<meta name=\\"msapplication-square70x70logo\\" content=\\"https://www.datocms-assets.com/205/1525789775-dato.png?h=70&w=70\\" />
|
|
221
|
+
<meta name=\\"msapplication-square150x150logo\\" content=\\"https://www.datocms-assets.com/205/1525789775-dato.png?h=150&w=150\\" />
|
|
222
|
+
<meta name=\\"msapplication-square310x310logo\\" content=\\"https://www.datocms-assets.com/205/1525789775-dato.png?h=310&w=310\\" />
|
|
223
|
+
<meta name=\\"msapplication-square310x150logo\\" content=\\"https://www.datocms-assets.com/205/1525789775-dato.png?h=150&w=310\\" />"
|
|
224
|
+
`;
|
|
225
|
+
|
|
226
|
+
exports[`toRemixMeta generates a meta descriptor 1`] = `
|
|
227
|
+
Object {
|
|
228
|
+
"article:modified_time": "2022-01-18T14:02:47Z",
|
|
229
|
+
"description": "Remix makes building scalable and fast React apps simple, pair it with a CMS that shares the same intuitiveness. Start a new Remix + Dato project now.",
|
|
230
|
+
"msapplication-square150x150logo": "https://www.datocms-assets.com/205/1525789775-dato.png?h=150&w=150",
|
|
231
|
+
"msapplication-square310x150logo": "https://www.datocms-assets.com/205/1525789775-dato.png?h=150&w=310",
|
|
232
|
+
"msapplication-square310x310logo": "https://www.datocms-assets.com/205/1525789775-dato.png?h=310&w=310",
|
|
233
|
+
"msapplication-square70x70logo": "https://www.datocms-assets.com/205/1525789775-dato.png?h=70&w=70",
|
|
234
|
+
"og:description": "Remix makes building scalable and fast React apps simple, pair it with a CMS that shares the same intuitiveness. Start a new Remix + Dato project now.",
|
|
235
|
+
"og:image": "https://www.datocms-assets.com/205/1642515293-full-logo.svg?fit=max&fm=jpg&w=1000",
|
|
236
|
+
"og:image:height": "186",
|
|
237
|
+
"og:image:width": "746",
|
|
238
|
+
"og:locale": "en",
|
|
239
|
+
"og:site_name": "DatoCMS",
|
|
240
|
+
"og:title": "Remix CMS - The easiest way to manage content with Remix",
|
|
241
|
+
"og:type": "article",
|
|
242
|
+
"title": "Remix CMS - The easiest way to manage content with Remix",
|
|
243
|
+
"twitter:card": "summary_large_image",
|
|
244
|
+
"twitter:description": "Remix makes building scalable and fast React apps simple, pair it with a CMS that shares the same intuitiveness. Start a new Remix + Dato project now.",
|
|
245
|
+
"twitter:image": "https://www.datocms-assets.com/205/1642515293-full-logo.svg?fit=max&fm=jpg&w=1000",
|
|
246
|
+
"twitter:site": "@datocms",
|
|
247
|
+
"twitter:title": "Remix CMS - The easiest way to manage content with Remix",
|
|
248
|
+
}
|
|
249
|
+
`;
|