mirror of
https://github.com/zoriya/react-native-svg.git
synced 2025-12-05 22:56:11 +00:00
feat: add support base64 uri type in SvgUri component (#2444)
# Summary Feature #2142 Add support for data: image/svg+XML; Base64 format. ## Test Plan TestExample app -> src -> Test2142 ## Compatibility | OS | Implemented | | ------- | :---------: | | iOS | ✅ | | MacOS | ✅ | | Android | ✅ | | Web | ✅ | --------- Co-authored-by: Jakub Grzywacz <jakub.grzywacz@swmansion.com>
This commit is contained in:
@@ -17,6 +17,7 @@ import Test2071 from './src/Test2071';
|
||||
import Test2080 from './src/Test2080';
|
||||
import Test2086 from './src/Test2086';
|
||||
import Test2089 from './src/Test2089';
|
||||
import Test2142 from './src/Test2142';
|
||||
import Test2148 from './src/Test2148';
|
||||
import Test2196 from './src/Test2196';
|
||||
import Test2248 from './src/Test2248';
|
||||
|
||||
22
apps/test-examples/src/Test2142.tsx
Normal file
22
apps/test-examples/src/Test2142.tsx
Normal file
@@ -0,0 +1,22 @@
|
||||
import {SvgUri} from 'react-native-svg';
|
||||
|
||||
export default function App() {
|
||||
return (
|
||||
<>
|
||||
<SvgUri
|
||||
uri={`data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMDAiIGhlaWdodD0iMTAwIj4KICA8cmVjdCB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgZmlsbD0iYmx1ZSIgLz48L3N2Zz4=`}
|
||||
/>
|
||||
<SvgUri
|
||||
uri={`data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgdmlld0JveD0iMCAwIDEwMCAxMDAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPHRpdGxlPkNpcmNsZTwvdGl0bGU+CiAgPGNpcmNsZSBjeD0iNTAiIGN5PSI1MCIgcj0iNDIiIHN0eWxlPSJmaWxsOnJlZDsiIC8+Cjwvc3ZnPg==`}
|
||||
/>
|
||||
<SvgUri
|
||||
uri={`data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgdmlld0JveD0iMCAwIDEwMCAxMDAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPHBvbHlnb24gcG9pbnRzPSI1MCwxMCAxMCw5MCA5MCw5MCIgc3R5bGU9ImZpbGw6Z3JlZW47IiAvPgo8L3N2Zz4=`}
|
||||
/>
|
||||
<SvgUri
|
||||
width={100}
|
||||
height={100}
|
||||
uri={`data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48IS0tIFVwbG9hZGVkIHRvOiBTVkcgUmVwbywgd3d3LnN2Z3JlcG8uY29tLCBHZW5lcmF0b3I6IFNWRyBSZXBvIE1peGVyIFRvb2xzIC0tPgo8c3ZnIGZpbGw9IiMwMDAwMDAiIHdpZHRoPSI4MDBweCIgaGVpZ2h0PSI4MDBweCIgdmlld0JveD0iMCAwIDI1NiAyNTYiIGlkPSJGbGF0IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgogIDxwYXRoIGQ9Ik0zNi44NzUsNzQuNDkwMjNhMy45OTU4MiwzLjk5NTgyLDAsMCwxLC42MjYtNS42MTMyOEE3Ny4zNjg1Niw3Ny4zNjg1NiwwLDAsMSw2NS4wMjk3OSw1Ni4xMTkxNGMxNS4zODEzNC0zLjg0Mzc1LDM5LjE3Njc1LTQuNzg5MDYsNjUuMTg5LDEyLjU1Mjc0LDE4LjgyMjI3LDEyLjU0Nzg1LDM4LjUsMTYuNDI3NzMsNTguNDg2ODIsMTEuNTI3MzRhNzAuNzc5MDYsNzAuNzc5MDYsMCwwLDAsMjQuODAxNzUtMTEuMzI3MTUsMy45OTk3NSwzLjk5OTc1LDAsMCwxLDQuOTkxNyw2LjI1MSw3Ny4zNjg1Niw3Ny4zNjg1NiwwLDAsMS0yNy41Mjg4MSwxMi43NTc4MSw3Ny4yNDgwNiw3Ny4yNDgwNiwwLDAsMS0xOC43MTUzMywyLjMxMTUyYy0xMy4zODU3NC4wMDEtMjkuNDU0MS0zLjUxNzU4LTQ2LjQ3MzYzLTE0Ljg2NDI2QzEwNi45NTksNjIuNzc5Myw4Ny4yODA3Niw1OC44OTk0MSw2Ny4yOTQ0Myw2My44MDA3OEE3MC43NzkwNiw3MC43NzkwNiwwLDAsMCw0Mi40OTI2OCw3NS4xMjc5Myw0LjAwMzg2LDQuMDAzODYsMCwwLDEsMzYuODc1LDc0LjQ5MDIzWm0xNzYuNjMyMzIsNTAuMzgxODRhNzAuNzc5MDYsNzAuNzc5MDYsMCwwLDEtMjQuODAxNzUsMTEuMzI3MTVjLTE5Ljk4NjgyLDQuODk5NDEtMzkuNjY0NTUsMS4wMjA1MS01OC40ODY4Mi0xMS41MjczNC0yNi4wMTIyMS0xNy4zNDA4My00OS44MDc2Mi0xNi4zOTY0OS02NS4xODktMTIuNTUyNzRBNzcuMzY4NTYsNzcuMzY4NTYsMCwwLDAsMzcuNTAxLDEyNC44NzdhMy45OTk3NSwzLjk5OTc1LDAsMCwwLDQuOTkxNyw2LjI1MSw3MC43NzkwNiw3MC43NzkwNiwwLDAsMSwyNC44MDE3NS0xMS4zMjcxNWMxOS45ODYzMy00LjkwMjM0LDM5LjY2NDU1LTEuMDIwNTEsNTguNDg2ODIsMTEuNTI3MzQsMTcuMDE5NTMsMTEuMzQ2NjgsMzMuMDg3ODksMTQuODY1MjQsNDYuNDczNjMsMTQuODY0MjZBNzkuNDQ5NzIsNzkuNDQ5NzIsMCwwLDAsMjE4LjQ5OSwxMzEuMTIzMDVhMy45OTk3NSwzLjk5OTc1LDAsMCwwLTQuOTkxNy02LjI1MVptMCw1NmE3MC43NzkwNiw3MC43NzkwNiwwLDAsMS0yNC44MDE3NSwxMS4zMjcxNWMtMTkuOTg2ODIsNC44OTk0MS0zOS42NjQ1NSwxLjAxOTUzLTU4LjQ4NjgyLTExLjUyNzM0LTI2LjAxMjIxLTE3LjM0MDgzLTQ5LjgwNzYyLTE2LjM5NjQ5LTY1LjE4OS0xMi41NTI3NEE3Ny4zNjg1Niw3Ny4zNjg1NiwwLDAsMCwzNy41MDEsMTgwLjg3N2EzLjk5OTc1LDMuOTk5NzUsMCwwLDAsNC45OTE3LDYuMjUxLDcwLjc3OTA2LDcwLjc3OTA2LDAsMCwxLDI0LjgwMTc1LTExLjMyNzE1YzE5Ljk4NjMzLTQuOTAzMzIsMzkuNjY0NTUtMS4wMjA1MSw1OC40ODY4MiwxMS41MjczNCwxNy4wMTk1MywxMS4zNDY2OCwzMy4wODc4OSwxNC44NjUyNCw0Ni40NzM2MywxNC44NjQyNkE3OS40NDk3Miw3OS40NDk3MiwwLDAsMCwyMTguNDk5LDE4Ny4xMjMwNWEzLjk5OTc1LDMuOTk5NzUsMCwwLDAtNC45OTE3LTYuMjUxWiIvPgo8L3N2Zz4=`}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Platform } from 'react-native';
|
||||
import { Buffer } from 'buffer';
|
||||
|
||||
export async function fetchText(uri?: string): Promise<string | null> {
|
||||
if (!uri) {
|
||||
@@ -6,11 +7,22 @@ export async function fetchText(uri?: string): Promise<string | null> {
|
||||
}
|
||||
if (uri.startsWith('data:image/svg+xml;utf8') && Platform.OS === 'android') {
|
||||
return dataUriToXml(uri);
|
||||
} else if (uri.startsWith('data:image/svg+xml;base64')) {
|
||||
return decodeBase64Image(uri);
|
||||
} else {
|
||||
return fetchUriData(uri);
|
||||
}
|
||||
}
|
||||
|
||||
const decodeBase64Image = (uri: string) => {
|
||||
const decoded = decodeURIComponent(uri);
|
||||
const splitContent = decoded.split(';')[1].split(',');
|
||||
const dataType = splitContent[0] as BufferEncoding;
|
||||
const content = splitContent.slice(1).join(',');
|
||||
|
||||
return Buffer.from(content, dataType).toString('utf-8');
|
||||
};
|
||||
|
||||
function dataUriToXml(uri: string): string | null {
|
||||
try {
|
||||
// decode and remove data:image/svg+xml;utf8, prefix
|
||||
|
||||
Reference in New Issue
Block a user