react-inlinesvg 3.0.2 → 3.0.3

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/src/index.tsx CHANGED
@@ -2,14 +2,14 @@ import * as React from 'react';
2
2
  import convert from 'react-from-dom';
3
3
 
4
4
  import { canUseDOM, isSupportedEnvironment, omit, randomString, STATUS } from './helpers';
5
- import { FetchError, Props, State, StorageItem } from './types';
5
+ import { FetchError, Props, State, Status, StorageItem } from './types';
6
6
 
7
7
  export const cacheStore: { [key: string]: StorageItem } = Object.create(null);
8
8
 
9
9
  export default class InlineSVG extends React.PureComponent<Props, State> {
10
- private isInitialized = false;
11
- private isActive = false;
12
10
  private readonly hash: string;
11
+ private isActive = false;
12
+ private isInitialized = false;
13
13
 
14
14
  public static defaultProps = {
15
15
  cacheRequests: true,
@@ -23,7 +23,7 @@ export default class InlineSVG extends React.PureComponent<Props, State> {
23
23
  content: '',
24
24
  element: null,
25
25
  hasCache: !!props.cacheRequests && !!cacheStore[props.src],
26
- status: STATUS.PENDING,
26
+ status: STATUS.IDLE,
27
27
  };
28
28
 
29
29
  this.hash = props.uniqueHash || randomString(8);
@@ -41,7 +41,7 @@ export default class InlineSVG extends React.PureComponent<Props, State> {
41
41
 
42
42
  try {
43
43
  /* istanbul ignore else */
44
- if (status === STATUS.PENDING) {
44
+ if (status === STATUS.IDLE) {
45
45
  /* istanbul ignore else */
46
46
  if (!isSupportedEnvironment()) {
47
47
  throw new Error('Browser does not support SVG');
@@ -91,6 +91,24 @@ export default class InlineSVG extends React.PureComponent<Props, State> {
91
91
  this.isActive = false;
92
92
  }
93
93
 
94
+ private getElement() {
95
+ try {
96
+ const node = this.getNode() as Node;
97
+ const element = convert(node);
98
+
99
+ if (!element || !React.isValidElement(element)) {
100
+ throw new Error('Could not convert the src to a React element');
101
+ }
102
+
103
+ this.setState({
104
+ element,
105
+ status: STATUS.READY,
106
+ });
107
+ } catch (error: any) {
108
+ this.handleError(new Error(error.message));
109
+ }
110
+ }
111
+
94
112
  private getNode() {
95
113
  const { description, title } = this.props;
96
114
 
@@ -138,38 +156,6 @@ export default class InlineSVG extends React.PureComponent<Props, State> {
138
156
  }
139
157
  }
140
158
 
141
- private getElement() {
142
- try {
143
- const node = this.getNode() as Node;
144
- const element = convert(node);
145
-
146
- if (!element || !React.isValidElement(element)) {
147
- throw new Error('Could not convert the src to a React element');
148
- }
149
-
150
- this.setState({
151
- element,
152
- status: STATUS.READY,
153
- });
154
- } catch (error: any) {
155
- this.handleError(new Error(error.message));
156
- }
157
- }
158
-
159
- private handleLoad = (content: string, hasCache = false) => {
160
- /* istanbul ignore else */
161
- if (this.isActive) {
162
- this.setState(
163
- {
164
- content,
165
- hasCache,
166
- status: STATUS.LOADED,
167
- },
168
- this.getElement,
169
- );
170
- }
171
- };
172
-
173
159
  private handleError = (error: Error | FetchError) => {
174
160
  const { onError } = this.props;
175
161
  const status =
@@ -186,69 +172,17 @@ export default class InlineSVG extends React.PureComponent<Props, State> {
186
172
  }
187
173
  };
188
174
 
189
- private request = () => {
190
- const { cacheRequests, fetchOptions, src } = this.props;
191
-
192
- try {
193
- if (cacheRequests) {
194
- cacheStore[src] = { content: '', status: STATUS.LOADING };
195
- }
196
-
197
- return fetch(src, fetchOptions)
198
- .then(response => {
199
- const contentType = response.headers.get('content-type');
200
- const [fileType] = (contentType || '').split(/ ?; ?/);
201
-
202
- if (response.status > 299) {
203
- throw new Error('Not found');
204
- }
205
-
206
- if (!['image/svg+xml', 'text/plain'].some(d => fileType.includes(d))) {
207
- throw new Error(`Content type isn't valid: ${fileType}`);
208
- }
209
-
210
- return response.text();
211
- })
212
- .then(content => {
213
- const { src: currentSrc } = this.props;
214
-
215
- // the current src don't match the previous one, skipping...
216
- if (src !== currentSrc) {
217
- if (cacheStore[src].status === STATUS.LOADING) {
218
- delete cacheStore[src];
219
- }
220
-
221
- return;
222
- }
223
-
224
- this.handleLoad(content);
225
-
226
- /* istanbul ignore else */
227
- if (cacheRequests) {
228
- const cache = cacheStore[src];
229
-
230
- /* istanbul ignore else */
231
- if (cache) {
232
- cache.content = content;
233
- cache.status = STATUS.LOADED;
234
- }
235
- }
236
- })
237
- .catch(error => {
238
- this.handleError(error);
239
-
240
- /* istanbul ignore else */
241
- if (cacheRequests) {
242
- const cache = cacheStore[src];
243
-
244
- /* istanbul ignore else */
245
- if (cache) {
246
- delete cacheStore[src];
247
- }
248
- }
249
- });
250
- } catch (error: any) {
251
- return this.handleError(new Error(error.message));
175
+ private handleLoad = (content: string, hasCache = false) => {
176
+ /* istanbul ignore else */
177
+ if (this.isActive) {
178
+ this.setState(
179
+ {
180
+ content,
181
+ hasCache,
182
+ status: STATUS.LOADED,
183
+ },
184
+ this.getElement,
185
+ );
252
186
  }
253
187
  };
254
188
 
@@ -272,7 +206,7 @@ export default class InlineSVG extends React.PureComponent<Props, State> {
272
206
  return;
273
207
  }
274
208
 
275
- const dataURI = src.match(/data:image\/svg[^,]*?(;base64)?,(.*)/);
209
+ const dataURI = src.match(/^data:image\/svg[^,]*?(;base64)?,(.*)/u);
276
210
  let inlineSrc;
277
211
 
278
212
  if (dataURI) {
@@ -293,6 +227,76 @@ export default class InlineSVG extends React.PureComponent<Props, State> {
293
227
  }
294
228
  }
295
229
 
230
+ private processSVG() {
231
+ const { content } = this.state;
232
+ const { preProcessor } = this.props;
233
+
234
+ if (preProcessor) {
235
+ return preProcessor(content);
236
+ }
237
+
238
+ return content;
239
+ }
240
+
241
+ private request = async () => {
242
+ const { cacheRequests, fetchOptions, src } = this.props;
243
+
244
+ if (cacheRequests) {
245
+ cacheStore[src] = { content: '', status: STATUS.LOADING };
246
+ }
247
+
248
+ try {
249
+ const response = await fetch(src, fetchOptions);
250
+ const contentType = response.headers.get('content-type');
251
+ const [fileType] = (contentType || '').split(/ ?; ?/);
252
+
253
+ if (response.status > 299) {
254
+ throw new Error('Not found');
255
+ }
256
+
257
+ if (!['image/svg+xml', 'text/plain'].some(d => fileType.includes(d))) {
258
+ throw new Error(`Content type isn't valid: ${fileType}`);
259
+ }
260
+
261
+ const content: string = await response.text();
262
+ const { src: currentSrc } = this.props;
263
+
264
+ // the current src don't match the previous one, skipping...
265
+ if (src !== currentSrc) {
266
+ if (cacheStore[src].status === STATUS.LOADING) {
267
+ delete cacheStore[src];
268
+ }
269
+
270
+ return;
271
+ }
272
+
273
+ this.handleLoad(content);
274
+
275
+ /* istanbul ignore else */
276
+ if (cacheRequests) {
277
+ const cache = cacheStore[src];
278
+
279
+ /* istanbul ignore else */
280
+ if (cache) {
281
+ cache.content = content;
282
+ cache.status = STATUS.LOADED;
283
+ }
284
+ }
285
+ } catch (error: any) {
286
+ this.handleError(error);
287
+
288
+ /* istanbul ignore else */
289
+ if (cacheRequests) {
290
+ const cache = cacheStore[src];
291
+
292
+ /* istanbul ignore else */
293
+ if (cache) {
294
+ delete cacheStore[src];
295
+ }
296
+ }
297
+ }
298
+ };
299
+
296
300
  private updateSVGAttributes(node: SVGSVGElement): SVGSVGElement {
297
301
  const { baseURL = '', uniquifyIDs } = this.props;
298
302
  const replaceableAttributes = ['id', 'href', 'xlink:href', 'xlink:role', 'xlink:arcrole'];
@@ -304,7 +308,7 @@ export default class InlineSVG extends React.PureComponent<Props, State> {
304
308
  return node;
305
309
  }
306
310
 
307
- [...node.children].map(d => {
311
+ [...node.children].forEach(d => {
308
312
  if (d.attributes && d.attributes.length) {
309
313
  const attributes = Object.values(d.attributes).map(a => {
310
314
  const attribute = a;
@@ -336,17 +340,6 @@ export default class InlineSVG extends React.PureComponent<Props, State> {
336
340
  return node;
337
341
  }
338
342
 
339
- private processSVG() {
340
- const { content } = this.state;
341
- const { preProcessor } = this.props;
342
-
343
- if (preProcessor) {
344
- return preProcessor(content);
345
- }
346
-
347
- return content;
348
- }
349
-
350
343
  public render(): React.ReactNode {
351
344
  const { element, status } = this.state;
352
345
  const { children = null, innerRef, loader = null } = this.props;
@@ -376,7 +369,7 @@ export default class InlineSVG extends React.PureComponent<Props, State> {
376
369
  return React.cloneElement(element as React.ReactElement, { ref: innerRef, ...elementProps });
377
370
  }
378
371
 
379
- if ([STATUS.UNSUPPORTED, STATUS.FAILED].includes(status)) {
372
+ if (([STATUS.UNSUPPORTED, STATUS.FAILED] as Status[]).includes(status)) {
380
373
  return children;
381
374
  }
382
375
 
package/src/types.ts CHANGED
@@ -1,8 +1,10 @@
1
1
  import * as React from 'react';
2
2
 
3
+ import { STATUS } from './helpers';
4
+
3
5
  export type ErrorCallback = (error: Error | FetchError) => void;
4
6
  export type LoadCallback = (src: string, isCached: boolean) => void;
5
- export type PlainObject<T = unknown> = Record<string | number | symbol, T>;
7
+ export type PlainObject<T = unknown> = Record<string, T>;
6
8
  export type PreProcessorCallback = (code: string) => string;
7
9
 
8
10
  export interface Props extends Omit<React.SVGProps<SVGElement>, 'onLoad' | 'onError' | 'ref'> {
@@ -26,7 +28,7 @@ export interface State {
26
28
  content: string;
27
29
  element: React.ReactNode;
28
30
  hasCache: boolean;
29
- status: string;
31
+ status: Status;
30
32
  }
31
33
 
32
34
  export interface FetchError extends Error {
@@ -36,7 +38,9 @@ export interface FetchError extends Error {
36
38
  type: string;
37
39
  }
38
40
 
41
+ export type Status = (typeof STATUS)[keyof typeof STATUS];
42
+
39
43
  export interface StorageItem {
40
44
  content: string;
41
- status: string;
45
+ status: Status;
42
46
  }