@devvit/ui-renderer 0.10.10-next-2023-11-29-39e508cdc.0 → 0.10.10-next-2023-11-29-14b2f3cc0.0
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderImageBlock.d.ts","sourceRoot":"","sources":["../../../library/src/blocks/templates/renderImageBlock.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAGvC,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,
|
|
1
|
+
{"version":3,"file":"renderImageBlock.d.ts","sourceRoot":"","sources":["../../../library/src/blocks/templates/renderImageBlock.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAGvC,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAA6B,YAAY,EAAE,MAAM,WAAW,CAAC;AAKpE,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,aAAa,GAAG,YAAY,CAiD/E"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { nothing } from 'lit';
|
|
2
2
|
import { getTemplateRenderingStrategy } from '@reddit/faceplate-ui/faceplateUIConfig.js';
|
|
3
3
|
import { defaultClasses, defaultStyles, onClickAction, resizeModeClass } from '../attributes.js';
|
|
4
|
-
import { classMap,
|
|
4
|
+
import { classMap, isValidImageURL } from './util.js';
|
|
5
5
|
import { VerifiedPublicImageHosts } from './constants.js';
|
|
6
6
|
const FALLBACK_IMG_URL = 'https://i.redd.it/p1vmc5ulmpib1.png';
|
|
7
7
|
export function renderImageBlock(block, ctx) {
|
|
@@ -27,7 +27,7 @@ export function renderImageBlock(block, ctx) {
|
|
|
27
27
|
const onClick = onClickAction(block, ctx);
|
|
28
28
|
return html `
|
|
29
29
|
<img
|
|
30
|
-
src="${
|
|
30
|
+
src="${imageUrl}"
|
|
31
31
|
width="${width}"
|
|
32
32
|
height="${height}"
|
|
33
33
|
alt="${description}"
|
|
@@ -24,15 +24,6 @@ export declare function parseDataUrl(dataUrl: string): {
|
|
|
24
24
|
data: string;
|
|
25
25
|
} | null;
|
|
26
26
|
export declare function isAcceptableDataUrl(maybeDataUrl: string): boolean;
|
|
27
|
-
/**
|
|
28
|
-
* Attempts to sanitize data URLs to prevent two things:
|
|
29
|
-
*
|
|
30
|
-
* 1. XSS attacks
|
|
31
|
-
* 2. Allowing images to be shown to users that bypass Reddit's safety checks
|
|
32
|
-
*
|
|
33
|
-
* NOTE: We only allow a mime type of image/svg+xml at this time.
|
|
34
|
-
*/
|
|
35
|
-
export declare function sanitizeDataUrl(dataUrl: string): string;
|
|
36
27
|
export declare function isValidImageURL(imageUrl: string): boolean;
|
|
37
28
|
/**
|
|
38
29
|
* Returns a BlockSizes object either directly from the block or constructs
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../../library/src/blocks/templates/util.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../../library/src/blocks/templates/util.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AAC9C,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACxE,OAAO,EAAE,SAAS,EAAE,QAAQ,IAAI,cAAc,EAAE,MAAM,6BAA6B,CAAC;AACpF,OAAO,EAAE,aAAa,EAAE,GAAG,IAAI,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACxE,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAGxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAKnE,OAAO,EACL,KAAK,EACL,UAAU,EACV,UAAU,EACV,0BAA0B,EAC1B,aAAa,EACd,MAAM,gBAAgB,CAAC;AAExB,MAAM,MAAM,YAAY,GAAG,cAAc,GAAG,OAAO,OAAO,CAAC;AAE3D,wBAAgB,QAAQ,CACtB,SAAS,EAAE,SAAS,EACpB,WAAW,CAAC,EAAE,OAAO,GACpB,MAAM,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAiB5C;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,CAAC,cAAc,CAAC,GAAG,YAAY,CAMxF;AAED,wBAAgB,GAAG,CAAC,GAAG,EAAE,aAAa,GAAG,UAAU,CAAC,OAAO,SAAS,CAAC,GAAG,MAAM,CAM7E;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,WAAW,GAAG,OAAO,GAAG,SAAS,GAAG,EAAE,IAAI,WAAW,CAEtF;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CAiBxD;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,SAAS,GAAG,SAAS,CASjE;AAcD,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEhD;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG;IAC7C,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,QAAQ,EAAE,OAAO,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd,GAAG,IAAI,CAWP;AASD,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAMjE;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAazD;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,UAAU,GAAG,SAAS,CA2B7D;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,0BAA0B,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAKhG;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,aAAa,GAAG,SAAS,GAAG,MAAM,CAUpE;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,UAAU,GAAG,SAAS,EAC9B,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,GAC/B,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC,CAIzD"}
|
package/blocks/templates/util.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import DOMPurify from 'isomorphic-dompurify';
|
|
2
1
|
import { classMap as clientClassMap } from 'lit/directives/class-map.js';
|
|
3
2
|
import { ref as clientRef } from 'lit/directives/ref.js';
|
|
4
3
|
import { unsafeHTML as clientUnsafeHTML } from 'lit/directives/unsafe-html.js';
|
|
@@ -108,148 +107,10 @@ export function isAcceptableDataUrl(maybeDataUrl) {
|
|
|
108
107
|
return false;
|
|
109
108
|
return isAcceptableDataUrlMimeType(parsedDataUrl.mimeType);
|
|
110
109
|
}
|
|
111
|
-
/**
|
|
112
|
-
* Attempts to sanitize data URLs to prevent two things:
|
|
113
|
-
*
|
|
114
|
-
* 1. XSS attacks
|
|
115
|
-
* 2. Allowing images to be shown to users that bypass Reddit's safety checks
|
|
116
|
-
*
|
|
117
|
-
* NOTE: We only allow a mime type of image/svg+xml at this time.
|
|
118
|
-
*/
|
|
119
|
-
export function sanitizeDataUrl(dataUrl) {
|
|
120
|
-
const parsedDataUrl = parseDataUrl(dataUrl);
|
|
121
|
-
if (!parsedDataUrl || !parsedDataUrl.data || !parsedDataUrl.mimeType)
|
|
122
|
-
return '';
|
|
123
|
-
if (!isAcceptableDataUrlMimeType(parsedDataUrl.mimeType))
|
|
124
|
-
return '';
|
|
125
|
-
try {
|
|
126
|
-
let dataToSanitize;
|
|
127
|
-
if (parsedDataUrl.isBase64) {
|
|
128
|
-
dataToSanitize = decodeURIComponent(atob(parsedDataUrl.data));
|
|
129
|
-
}
|
|
130
|
-
else {
|
|
131
|
-
dataToSanitize = decodeURIComponent(parsedDataUrl.data);
|
|
132
|
-
}
|
|
133
|
-
const sanitizeCss = (cssText) => {
|
|
134
|
-
// Define a regex pattern that matches CSS properties that can include URLs
|
|
135
|
-
const urlPattern =
|
|
136
|
-
// eslint-disable-next-line security/detect-unsafe-regex
|
|
137
|
-
/(?:background(-image)?|border-image(-source)?)\s*:\s*(url\(['"]?(data:image\/(?:png|jpeg|gif);base64,[^)]+|https?:\/\/[^)]+)['"]?\))(?:;\s*)?/gi;
|
|
138
|
-
// Remove any matching URL patterns from the CSS text
|
|
139
|
-
return cssText.replace(urlPattern, '');
|
|
140
|
-
};
|
|
141
|
-
// This is for <style> tags
|
|
142
|
-
DOMPurify.addHook('uponSanitizeElement', (node) => {
|
|
143
|
-
if (node.tagName === 'style') {
|
|
144
|
-
if (node.textContent) {
|
|
145
|
-
node.textContent = sanitizeCss(node.textContent);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
/**
|
|
149
|
-
* xmlns is optional when using a SVG inside of the DOM. However,
|
|
150
|
-
* since we are using it within a data url, it is required.
|
|
151
|
-
*
|
|
152
|
-
* https://stackoverflow.com/questions/18467982/are-svg-parameters-such-as-xmlns-and-version-needed
|
|
153
|
-
*/
|
|
154
|
-
if (node.tagName === 'svg') {
|
|
155
|
-
if (!node.getAttribute('xmlns')) {
|
|
156
|
-
node.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
});
|
|
160
|
-
// This is for style attribute tags
|
|
161
|
-
DOMPurify.addHook('uponSanitizeAttribute', (_node, data) => {
|
|
162
|
-
if (data.attrName === 'style') {
|
|
163
|
-
data.attrValue = sanitizeCss(data.attrValue);
|
|
164
|
-
}
|
|
165
|
-
});
|
|
166
|
-
const sanitized = DOMPurify.sanitize(dataToSanitize, {
|
|
167
|
-
// Only allow svg and associated tags
|
|
168
|
-
// Note that these are some of the big offenders that are left out:
|
|
169
|
-
// 'script', 'image', 'foreignObject', 'object', 'use'
|
|
170
|
-
//
|
|
171
|
-
// To support more mimeTypes, remove the ALLOWED_TAGS array fully.
|
|
172
|
-
//
|
|
173
|
-
// src: https://github.com/cure53/DOMPurify/blob/2c66eb1f6ae39cc7001a97889a9bb78b688a6f99/src/tags.js#L124
|
|
174
|
-
ALLOWED_TAGS: [
|
|
175
|
-
'svg',
|
|
176
|
-
'altglyph',
|
|
177
|
-
'altglyphdef',
|
|
178
|
-
'altglyphitem',
|
|
179
|
-
'animatecolor',
|
|
180
|
-
'animatemotion',
|
|
181
|
-
'animatetransform',
|
|
182
|
-
'circle',
|
|
183
|
-
'clippath',
|
|
184
|
-
'defs',
|
|
185
|
-
'desc',
|
|
186
|
-
'ellipse',
|
|
187
|
-
'filter',
|
|
188
|
-
'font',
|
|
189
|
-
'g',
|
|
190
|
-
'glyph',
|
|
191
|
-
'glyphref',
|
|
192
|
-
'hkern',
|
|
193
|
-
'line',
|
|
194
|
-
'lineargradient',
|
|
195
|
-
'marker',
|
|
196
|
-
'mask',
|
|
197
|
-
'metadata',
|
|
198
|
-
'mpath',
|
|
199
|
-
'path',
|
|
200
|
-
'pattern',
|
|
201
|
-
'polygon',
|
|
202
|
-
'polyline',
|
|
203
|
-
'radialgradient',
|
|
204
|
-
'rect',
|
|
205
|
-
'stop',
|
|
206
|
-
'style',
|
|
207
|
-
'switch',
|
|
208
|
-
'symbol',
|
|
209
|
-
'text',
|
|
210
|
-
'textpath',
|
|
211
|
-
'title',
|
|
212
|
-
'tref',
|
|
213
|
-
'tspan',
|
|
214
|
-
'view',
|
|
215
|
-
'vkern',
|
|
216
|
-
],
|
|
217
|
-
// These are required for svg animate tags
|
|
218
|
-
ADD_ATTR: ['from', 'to', 'animate'],
|
|
219
|
-
FORBID_ATTR: ['image'],
|
|
220
|
-
});
|
|
221
|
-
// eslint-disable-next-line @reddit/i18n-shreddit/no-unwrapped-strings
|
|
222
|
-
let sanitizedDataUrl = `data:${parsedDataUrl.mimeType}`;
|
|
223
|
-
if (parsedDataUrl.charset) {
|
|
224
|
-
sanitizedDataUrl += `;charset=${parsedDataUrl.charset}`;
|
|
225
|
-
}
|
|
226
|
-
if (parsedDataUrl.isBase64) {
|
|
227
|
-
// eslint-disable-next-line @reddit/i18n-shreddit/no-unwrapped-strings
|
|
228
|
-
sanitizedDataUrl += `;base64`;
|
|
229
|
-
}
|
|
230
|
-
/**
|
|
231
|
-
* In data url land there are characters that need to be encoded that
|
|
232
|
-
* a user may have passed in like hex-code colors that will break
|
|
233
|
-
* the image without giving any relevant messages. To be safe, we
|
|
234
|
-
* encode the entire sanitized string.
|
|
235
|
-
*
|
|
236
|
-
* More info:
|
|
237
|
-
* https://stackoverflow.com/questions/69216560/why-hexadecimal-color-dont-work-with-utf8-data-url-s-for-svg
|
|
238
|
-
*
|
|
239
|
-
* You may be able to get away with just replacing # with %23 in case
|
|
240
|
-
* people complain about the data url being hard to read.
|
|
241
|
-
*/
|
|
242
|
-
sanitizedDataUrl += `,${parsedDataUrl.isBase64 ? btoa(sanitized) : encodeURIComponent(sanitized)}`;
|
|
243
|
-
return sanitizedDataUrl;
|
|
244
|
-
}
|
|
245
|
-
catch (error) {
|
|
246
|
-
return '';
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
110
|
export function isValidImageURL(imageUrl) {
|
|
250
111
|
try {
|
|
251
112
|
if (isDataUrl(imageUrl))
|
|
252
|
-
return
|
|
113
|
+
return false;
|
|
253
114
|
// The second "base" param helps to handle relative paths to local files
|
|
254
115
|
// https://developer.mozilla.org/en-US/docs/Web/API/URL/URL#parameters
|
|
255
116
|
const hostName = new URL(imageUrl, `https://i.${REDD_IT}`)?.hostname;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devvit/ui-renderer",
|
|
3
|
-
"version": "0.10.10-next-2023-11-29-
|
|
3
|
+
"version": "0.10.10-next-2023-11-29-14b2f3cc0.0",
|
|
4
4
|
"license": "BSD-3-Clause",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -54,11 +54,10 @@
|
|
|
54
54
|
},
|
|
55
55
|
"types": "./index.d.ts",
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"@devvit/protos": "0.10.10-next-2023-11-29-
|
|
58
|
-
"@devvit/runtime-lite": "0.10.10-next-2023-11-29-
|
|
59
|
-
"@devvit/runtimes": "0.10.10-next-2023-11-29-
|
|
57
|
+
"@devvit/protos": "0.10.10-next-2023-11-29-14b2f3cc0.0",
|
|
58
|
+
"@devvit/runtime-lite": "0.10.10-next-2023-11-29-14b2f3cc0.0",
|
|
59
|
+
"@devvit/runtimes": "0.10.10-next-2023-11-29-14b2f3cc0.0",
|
|
60
60
|
"@lottiefiles/lottie-player": "1.7.1",
|
|
61
|
-
"isomorphic-dompurify": "1.9.0",
|
|
62
61
|
"p-queue": "7.3.4",
|
|
63
62
|
"rxjs": "7.5.7"
|
|
64
63
|
},
|
|
@@ -84,7 +83,7 @@
|
|
|
84
83
|
"devDependencies": {
|
|
85
84
|
"@devvit/eslint-config": "0.10.9",
|
|
86
85
|
"@devvit/repo-tools": "0.10.9",
|
|
87
|
-
"@devvit/tsconfig": "0.10.10-next-2023-11-29-
|
|
86
|
+
"@devvit/tsconfig": "0.10.10-next-2023-11-29-14b2f3cc0.0",
|
|
88
87
|
"@lit-labs/ssr": "^2.2.3",
|
|
89
88
|
"@lit/localize": "0.11.4",
|
|
90
89
|
"@open-wc/testing-helpers": "2.3.0",
|
|
@@ -116,5 +115,5 @@
|
|
|
116
115
|
"directory": "dist"
|
|
117
116
|
},
|
|
118
117
|
"source": "./src/index.ts",
|
|
119
|
-
"gitHead": "
|
|
118
|
+
"gitHead": "41ba8fd5aa50c57bf6c05b9bfff955e891f9f9f5"
|
|
120
119
|
}
|