Skip to content

Commit

Permalink
feat: add support base64 uri type in SvgUri component (#2444)
Browse files Browse the repository at this point in the history
# 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 <[email protected]>
  • Loading branch information
bohdanprog and jakex7 authored Sep 24, 2024
1 parent 712201a commit 14a131c
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 0 deletions.
1 change: 1 addition & 0 deletions apps/test-examples/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
22 changes: 22 additions & 0 deletions apps/test-examples/src/Test2142.tsx
Original file line number Diff line number Diff line change
@@ -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=`}
/>
</>
);
}
12 changes: 12 additions & 0 deletions src/utils/fetchData.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,28 @@
import { Platform } from 'react-native';
import { Buffer } from 'buffer';

export async function fetchText(uri?: string): Promise<string | null> {
if (!uri) {
return 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
Expand Down

0 comments on commit 14a131c

Please sign in to comment.