Files
react-native/packages/assets/path-support.js
T
Peter AbbondanzoandFacebook GitHub Bot 2e80f5acf1 Load XML files on disk by default (#46371)
Summary:
X-link: https://github.com/facebook/metro/pull/1348

Pull Request resolved: https://github.com/facebook/react-native/pull/46371

## Internal

Vector drawable image support was added in D59530172 but importing vector drawable asset types was not supported out of the box. It required custom source transformers like the one added in D60021474. This is because Android cannot load vector drawable XML over the network. Vector drawables are compiled by AAPT as part of the build process. Even though Metro can serve XML, it would never load.

## Summary

This adds some minor checks in the `AssetSourceResolver` to only attempt loading XML asset types from disk on the Android platform. XML assets like vector drawables are precompiled and cannot be served over the network by Metro.

## Changelog

[Android] [Added] - Adds support for importing XML assets as images

Reviewed By: javache

Differential Revision: D62302929

fbshipit-source-id: 01e49ac5b0429d291318984128dfca2dc058149d
2024-09-09 10:18:10 -07:00

94 lines
2.4 KiB
JavaScript

/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
* @flow strict
*/
'use strict';
import type {PackagerAsset} from './registry.js';
const androidScaleSuffix = {
'0.75': 'ldpi',
'1': 'mdpi',
'1.5': 'hdpi',
'2': 'xhdpi',
'3': 'xxhdpi',
'4': 'xxxhdpi',
};
const ANDROID_BASE_DENSITY = 160;
/**
* FIXME: using number to represent discrete scale numbers is fragile in essence because of
* floating point numbers imprecision.
*/
function getAndroidAssetSuffix(scale: number): string {
if (scale.toString() in androidScaleSuffix) {
// $FlowFixMe[invalid-computed-prop]
return androidScaleSuffix[scale.toString()];
}
// NOTE: Android Gradle Plugin does not fully support the nnndpi format.
// See https://issuetracker.google.com/issues/72884435
if (Number.isFinite(scale) && scale > 0) {
return Math.round(scale * ANDROID_BASE_DENSITY) + 'dpi';
}
throw new Error('no such scale ' + scale.toString());
}
// See https://developer.android.com/guide/topics/resources/drawable-resource.html
const drawableFileTypes = new Set([
'gif',
'jpeg',
'jpg',
'ktx',
'png',
'svg',
'webp',
'xml',
]);
function getAndroidResourceFolderName(
asset: PackagerAsset,
scale: number,
): string | $TEMPORARY$string<'raw'> {
if (!drawableFileTypes.has(asset.type)) {
return 'raw';
}
const suffix = getAndroidAssetSuffix(scale);
if (!suffix) {
throw new Error(
"Don't know which android drawable suffix to use for scale: " +
scale +
'\nAsset: ' +
JSON.stringify(asset, null, '\t') +
'\nPossible scales are:' +
JSON.stringify(androidScaleSuffix, null, '\t'),
);
}
return 'drawable-' + suffix;
}
function getAndroidResourceIdentifier(asset: PackagerAsset): string {
return (getBasePath(asset) + '/' + asset.name)
.toLowerCase()
.replace(/\//g, '_') // Encode folder structure in file name
.replace(/([^a-z0-9_])/g, '') // Remove illegal chars
.replace(/^(?:assets|assetsunstable_path)_/, ''); // Remove "assets_" or "assetsunstable_path_" prefix
}
function getBasePath(asset: PackagerAsset): string {
const basePath = asset.httpServerLocation;
return basePath.startsWith('/') ? basePath.slice(1) : basePath;
}
module.exports = {
getAndroidResourceFolderName,
getAndroidResourceIdentifier,
getBasePath,
};