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:
Bohdan Artiukhov
2024-09-24 10:23:14 +02:00
committed by GitHub
parent 712201a19e
commit 14a131c5d8
3 changed files with 35 additions and 0 deletions

View File

@@ -17,6 +17,7 @@ import Test2071 from './src/Test2071';
import Test2080 from './src/Test2080'; import Test2080 from './src/Test2080';
import Test2086 from './src/Test2086'; import Test2086 from './src/Test2086';
import Test2089 from './src/Test2089'; import Test2089 from './src/Test2089';
import Test2142 from './src/Test2142';
import Test2148 from './src/Test2148'; import Test2148 from './src/Test2148';
import Test2196 from './src/Test2196'; import Test2196 from './src/Test2196';
import Test2248 from './src/Test2248'; import Test2248 from './src/Test2248';

View 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=`}
/>
</>
);
}

View File

@@ -1,4 +1,5 @@
import { Platform } from 'react-native'; import { Platform } from 'react-native';
import { Buffer } from 'buffer';
export async function fetchText(uri?: string): Promise<string | null> { export async function fetchText(uri?: string): Promise<string | null> {
if (!uri) { 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') { if (uri.startsWith('data:image/svg+xml;utf8') && Platform.OS === 'android') {
return dataUriToXml(uri); return dataUriToXml(uri);
} else if (uri.startsWith('data:image/svg+xml;base64')) {
return decodeBase64Image(uri);
} else { } else {
return fetchUriData(uri); 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 { function dataUriToXml(uri: string): string | null {
try { try {
// decode and remove data:image/svg+xml;utf8, prefix // decode and remove data:image/svg+xml;utf8, prefix