diff --git a/apps/test-examples/index.tsx b/apps/test-examples/index.tsx index e8615269a..823ebbe5c 100644 --- a/apps/test-examples/index.tsx +++ b/apps/test-examples/index.tsx @@ -4,6 +4,7 @@ import React from 'react'; import ColorTest from './src/ColorTest'; import PointerEventsBoxNone from './src/PointerEventsBoxNone'; import MountUnmount from './src/MountUnmount'; +import Test1318 from './src/Test1318'; import Test1374 from './src/Test1374'; import Test1442 from './src/Test1442'; import Test1451 from './src/Test1451'; diff --git a/apps/test-examples/src/Test1318.tsx b/apps/test-examples/src/Test1318.tsx new file mode 100644 index 000000000..a2a1331f9 --- /dev/null +++ b/apps/test-examples/src/Test1318.tsx @@ -0,0 +1,31 @@ +import React from 'react'; +import {SvgUri} from 'react-native-svg'; +import {SvgCssUri} from 'react-native-svg/css'; + +export default function Test() { + return ( + <> + + + + + ); +} diff --git a/src/ReactNativeSVG.ts b/src/ReactNativeSVG.ts index addd927d7..4aca02df4 100644 --- a/src/ReactNativeSVG.ts +++ b/src/ReactNativeSVG.ts @@ -2,7 +2,6 @@ import Shape from './elements/Shape'; import { AstProps, camelCase, - fetchText, JsxAST, Middleware, parse, @@ -19,6 +18,8 @@ import { XmlState, } from './xml'; +import { fetchText } from './utils/fetchData'; + import { RNSVGCircle, RNSVGClipPath, diff --git a/src/ReactNativeSVG.web.ts b/src/ReactNativeSVG.web.ts index 5117b35fb..ee57bda8e 100644 --- a/src/ReactNativeSVG.web.ts +++ b/src/ReactNativeSVG.web.ts @@ -1,7 +1,6 @@ import { AstProps, camelCase, - fetchText, JsxAST, Middleware, parse, @@ -18,6 +17,8 @@ import { XmlState, } from './xml'; +import { fetchText } from './utils/fetchData'; + export { inlineStyles, loadLocalRawResource, diff --git a/src/utils/fetchData.ts b/src/utils/fetchData.ts new file mode 100644 index 000000000..f08b16ed2 --- /dev/null +++ b/src/utils/fetchData.ts @@ -0,0 +1,29 @@ +import { Platform } from 'react-native'; + +export async function fetchText(uri?: string): Promise { + if (!uri) { + return null; + } + if (uri.startsWith('data:image/svg+xml;utf8') && Platform.OS === 'android') { + return dataUriToXml(uri); + } else { + return fetchUriData(uri); + } +} + +function dataUriToXml(uri: string): string | null { + try { + // decode and remove data:image/svg+xml;utf8, prefix + return decodeURIComponent(uri).split(',').slice(1).join(','); + } catch (error) { + throw new Error(`Decoding ${uri} failed with error: ${error}`); + } +} + +async function fetchUriData(uri: string) { + const response = await fetch(uri); + if (response.ok || (response.status === 0 && uri.startsWith('file://'))) { + return await response.text(); + } + throw new Error(`Fetching ${uri} failed with status ${response.status}`); +} diff --git a/src/xml.tsx b/src/xml.tsx index cb72dd058..091d23330 100644 --- a/src/xml.tsx +++ b/src/xml.tsx @@ -1,6 +1,7 @@ import type { ComponentType, ComponentProps } from 'react'; import * as React from 'react'; import { Component, useEffect, useMemo, useState } from 'react'; +import { fetchText } from './utils/fetchData'; import type { SvgProps } from './elements/Svg'; import { tags } from './xmlTags'; @@ -78,17 +79,6 @@ export function SvgXml(props: XmlProps) { } } -export async function fetchText(uri?: string) { - if (!uri) { - return null; - } - const response = await fetch(uri); - if (response.ok || (response.status === 0 && uri.startsWith('file://'))) { - return await response.text(); - } - throw new Error(`Fetching ${uri} failed with status ${response.status}`); -} - export function SvgUri(props: UriProps) { const { onError = err, uri, onLoad, fallback } = props; const [xml, setXml] = useState(null);