File: GetMauiAssetPath.cs
Web Access
Project: src\src\SingleProject\Resizetizer\src\Resizetizer.csproj (Microsoft.Maui.Resizetizer)
using System;
using System.IO;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
 
namespace Microsoft.Maui.Resizetizer
{
	/// <summary>
	/// Takes the incoming @(MauiAsset) item group, and returns the proper metadata to include it in the app.
	/// The main reason we need a task for this is to preserve directory structure.
	/// 
	/// Some examples:
	/// Resources\foo.mp3 -> Resources\foo.mp3
	/// C:\src\code\MyProject\Resources\foo.mp3 -> Resources\foo.mp3
	/// C:\some\random\path\foo.mp3 -> foo.mp3
	/// </summary>
	public class GetMauiAssetPath : Task
	{
		/// <summary>
		/// The value for $(MSBuildProjectDirectory) in the current project
		/// </summary>
		[Required]
		public string ProjectDirectory { get; set; }
 
		/// <summary>
		/// The name of any folders to prefix with
		/// </summary>
		public string FolderName { get; set; }
 
		/// <summary>
		/// On Windows, %(TargetPath) is passed in, %(Link) by default for other platforms
		/// </summary>
		public string ItemMetadata { get; set; } = "Link";
 
		public ITaskItem[] Input { get; set; }
 
		[Output]
		public ITaskItem[] Output { get; set; }
 
		public override bool Execute()
		{
			if (Input != null && Input.Length > 0)
			{
				foreach (var item in Input)
				{
					var link = item.GetMetadata("Link");
					var path = string.IsNullOrEmpty(link)
						? Normalize(item.ItemSpec)
						: Normalize(link);
					if (Path.IsPathRooted(path))
					{
						path = Path.GetFullPath(path);
						var project = Normalize(item.GetMetadata("ProjectDirectory"));
						if (!MakeRelative(project, ref path) && !MakeRelative(ProjectDirectory, ref path))
						{
							// If this is a random path, the best we can do is use the file name
							path = Path.GetFileName(path);
						}
					}
					// Prepend FolderName if not blank
					if (!string.IsNullOrEmpty(FolderName))
					{
						path = Path.Combine(FolderName, path);
					}
					item.SetMetadata(ItemMetadata, path);
				}
				Output = Input;
			}
 
			return !Log.HasLoggedErrors;
		}
 
		static string Normalize(string path) =>
			path?.Replace('\\', Path.DirectorySeparatorChar)?.Replace('/', Path.DirectorySeparatorChar);
 
		static bool MakeRelative(string projectDirectory, ref string path)
		{
			if (string.IsNullOrEmpty(projectDirectory))
				return false;
 
			projectDirectory = Path.GetFullPath(projectDirectory);
			if (!projectDirectory.EndsWith(Path.DirectorySeparatorChar.ToString()))
			{
				projectDirectory += Path.DirectorySeparatorChar;
			}
			if (path.StartsWith(projectDirectory, StringComparison.OrdinalIgnoreCase))
			{
				path = path.Substring(projectDirectory.Length);
				return true;
			}
			return false;
		}
	}
}