/// <summary> /// Creates the manifest document from the provided intermediates. Discards a previous /// manifest document if present. /// </summary> /// <param name="intermediates">Intermediates to process into the AppX manifest.</param> public void ProcessIntermediates(IEnumerable <Intermediate> intermediates) { this.document = null; this.Files = new List <PackageFile>(); Package package = null; Version minNetfx = null; Version maxNetfx = null; SortedSet <string> supportedProducts = new SortedSet <string>(StringComparer.OrdinalIgnoreCase); XElement xContent = new XElement(VsixNamespace + "Content"); XElement xReferences = new XElement(VsixNamespace + "References"); foreach (Intermediate intermediate in intermediates) { foreach (PackageItem item in intermediate.Items) { if (item.System) { continue; } // Files are processed differently since we need to go search for them on disk and such. if (item is File) { PackageFile packageFile; if (PackageFile.TryCreate(backend, (File)item, out packageFile)) { this.Files.Add(packageFile); } } else if (item is Package) { if (package == null) { package = (Package)item; } else { this.backend.OnMessage(new CompilerMessageEventArgs(CompilerMessage.HighlanderElement("Package"), item)); } } else if (item is Prerequisite) { Prerequisite prereq = (Prerequisite)item; switch (prereq.On.ToLowerInvariant()) { case "netfx": if (null == minNetfx) { if (prereq.Version == null) { this.backend.OnMessage(new CompilerMessageEventArgs(CompilerMessage.RequiredAttribute("Prerequisite", "Version"), prereq)); } else { minNetfx = prereq.Version; } if (prereq.MaxVersion != null) { maxNetfx = prereq.MaxVersion; } } else { this.backend.OnMessage(new CompilerMessageEventArgs(CompilerMessage.HighlanderElementWithAttributeValue("Prerequisite", "On", prereq.On), prereq)); } break; case "vs": if (prereq.Version == null) { this.backend.OnMessage(new CompilerMessageEventArgs(CompilerMessage.RequiredAttribute("Prerequisite", "Version"), prereq)); } else { string edition = Product.GetEdition(prereq); if (String.IsNullOrEmpty(edition)) { this.backend.OnMessage(new CompilerMessageEventArgs(CompilerMessage.RequiredAttribute("Vsix", "Product.Edition"), prereq)); } else { // Ensure that if the edition matches one of the well known values that it has the appropriate casing. string[] editionMatches = new string[] { "IntegratedShell", "Pro", "Premium", "Ultimate", "VWDExpress", "VCSExpress", "VBExpress", "VCExpress", "Express_All" }; foreach (string editionMatch in editionMatches) { if (edition.Equals(editionMatch, StringComparison.OrdinalIgnoreCase)) { edition = editionMatch; break; } } supportedProducts.Add(String.Concat(prereq.Version.ToString(), "\\", edition)); } } break; default: this.backend.OnMessage(new CompilerMessageEventArgs(CompilerMessage.InvalidAttributeValue("Prerequisite", "On", prereq.On), prereq)); break; } } else if (item is Dependency) { Dependency dependency = (Dependency)item; XElement reference = new XElement(VsixNamespace + "Reference", new XAttribute("Id", dependency.Name), new XElement(VsixNamespace + "Name", dependency.Publisher) ); if (dependency.Version != null) { reference.Add(new XAttribute("MinVersion", dependency.Version.ToString())); } if (dependency.MaxVersion != null) { reference.Add(new XAttribute("MaxVersion", dependency.MaxVersion.ToString())); } xReferences.Add(reference); } else if (item is Vspackage) { Vspackage vspackage = (Vspackage)item; // TODO: verify file specified string pkgdef = VsixManifest.StripRootFolderReference(vspackage.File.Path); // TODO: warn if file extension not .pkgdef. xContent.Add(new XElement(VsixNamespace + "VsPackage", pkgdef)); } } } if (package != null) { // TODO: verify DisplayName <= 50 chars // TODO: verify Description <= 1000 chars // TODO: verify Manufacturer // TODO: verify Version // TODO: verify Languages[0] only one. XElement xIdentifier = new XElement(VsixNamespace + "Identifier", new XAttribute("Id", package.Name), new XElement(VsixNamespace + "Name", package.DisplayName), new XElement(VsixNamespace + "Author", package.Manufacturer), new XElement(VsixNamespace + "Version", package.Version.ToString()), new XElement(VsixNamespace + "Description", package.Description), new XElement(VsixNamespace + "Locale", this.backend.Languages[0].LCID) ); string image = (package.Image == null) ? null : package.Image.NonqualifiedName; if (!string.IsNullOrEmpty(image)) { xIdentifier.Add(VsixNamespace + "Icon", image); } xIdentifier.Add(new XElement(VsixNamespace + "InstalledByMsi", "false")); XElement xSupportedProducts = new XElement(VsixNamespace + "SupportedProducts"); xIdentifier.Add(xSupportedProducts); string previonsVersion = null; XElement xVisualStudio = null; foreach (string supported in supportedProducts) { string[] versionEdition = supported.Split(new char[] { '\\' }, 2); if (!versionEdition[0].Equals(previonsVersion)) { xVisualStudio = new XElement(VsixNamespace + "VisualStudio", new XAttribute("Version", versionEdition[0])); xSupportedProducts.Add(xVisualStudio); previonsVersion = versionEdition[0]; } xVisualStudio.Add(new XElement(VsixNamespace + "Edition", versionEdition[1])); } if (null != minNetfx) { XElement xSupportedFrameworkRuntime = new XElement(VsixNamespace + "SupportedFrameworkRuntimeEdition", new XAttribute("MinVersion", minNetfx.ToString()) ); if (null != maxNetfx) { xSupportedFrameworkRuntime.Add(new XAttribute("MaxVersion", maxNetfx.ToString())); } xIdentifier.Add(xSupportedFrameworkRuntime); } if (package.Framework) { xIdentifier.Add(VsixNamespace + "SystemComponent", "true"); } // Now put the manifest together. XElement xRoot = new XElement(VsixNamespace + "Vsix", new XAttribute("Version", "1.0"), xIdentifier ); if (xReferences.HasElements) { xRoot.Add(xReferences); } if (xContent.HasElements) { xRoot.Add(xContent); } this.document = new XDocument(xRoot); } }
/// <summary> /// Finishes the manifest applcation XML. /// </summary> /// <param name="backend">Compiler backend used for sending messages.</param> public void Finish(BackendCompiler backend) { // Visual elements is required. XElement xVisualElements = new XElement(AppxManifest.AppxNamespace + "VisualElements"); this.Xml.Add(xVisualElements); if (this.Tile != null) { Application application = (Application)this.Item; AppxLexicon.Tile tile = (AppxLexicon.Tile) this.Tile.Item; // Display name is required. if (!String.IsNullOrEmpty(application.DisplayName)) { xVisualElements.Add(new XAttribute("DisplayName", application.DisplayName)); } else { backend.OnMessage(new CompilerMessageEventArgs(CompilerMessage.RequiredAttribute("Application", "DisplayName"), this.Item)); } // Description is required. if (!String.IsNullOrEmpty(application.Description)) { xVisualElements.Add(new XAttribute("Description", application.Description)); } else { backend.OnMessage(new CompilerMessageEventArgs(CompilerMessage.RequiredAttribute("Application", "Description"), this.Item)); } // Image is required. string logo = tile.Image == null ? null : tile.Image.NonqualifiedName; if (!String.IsNullOrEmpty(logo)) { xVisualElements.Add(new XAttribute("Logo", logo)); } else { backend.OnMessage(new CompilerMessageEventArgs(CompilerMessage.RequiredAttribute("Tile", "Image"), this.Item)); } // Small image is required. string smallLogo = tile.SmallImage == null ? null : tile.SmallImage.NonqualifiedName; if (!String.IsNullOrEmpty(smallLogo)) { xVisualElements.Add(new XAttribute("SmallLogo", smallLogo)); } else { backend.OnMessage(new CompilerMessageEventArgs(CompilerMessage.RequiredAttribute("Tile", "SmallImage"), this.Item)); } // Foreground is required. xVisualElements.Add(new XAttribute("ForegroundText", tile.Foreground)); // Background is required. string color = AppxManifest.GetColor(tile.Background); if (!String.IsNullOrEmpty(color)) { xVisualElements.Add(new XAttribute("BackgroundColor", color)); } else { backend.OnMessage(new CompilerMessageEventArgs(CompilerMessage.InvalidAttributeValue("Tile", "Background", tile.Background), tile)); } // Toast capable is optional. bool?toast = AppxLexicon.Application.GetToastCapable(application); if (toast.HasValue && toast.Value) { xVisualElements.Add(new XAttribute("ToastCapable", true)); } // Default tile is optional. string wideLogo = (tile.WideImage == null) ? null : tile.WideImage.NonqualifiedName; if (!String.IsNullOrEmpty(wideLogo) || !String.IsNullOrEmpty(tile.ShortName) || tile.ShowName != AppxLexicon.TileShowName.Invalid) { XElement xDefautTile = new XElement(AppxManifest.AppxNamespace + "DefaultTile"); if (!String.IsNullOrEmpty(tile.ShortName)) { xDefautTile.Add(new XAttribute("ShortName", tile.ShortName)); } if (tile.ShowName != AppxLexicon.TileShowName.Invalid) { if (tile.ShowName != AppxLexicon.TileShowName.Invalid) { xDefautTile.Add(new XAttribute("ShowName", tile.ShowName)); } } if (!String.IsNullOrEmpty(wideLogo)) { xDefautTile.Add(new XAttribute("WideLogo", wideLogo)); } xVisualElements.Add(xDefautTile); } } else { backend.OnMessage(new CompilerMessageEventArgs(CompilerMessage.RequiredElement("Application", "Tile"), this.Item)); } // Lock screen is optional. if (this.LockScreen != null && this.LockScreen.Xml != null && this.LockScreen.Xml.HasAttributes) { xVisualElements.Add(this.LockScreen.Xml); } // Splash screen is required. if (this.SplashScreen != null && this.SplashScreen.Xml != null && this.SplashScreen.Xml.HasAttributes) { xVisualElements.Add(this.SplashScreen.Xml); } else { backend.OnMessage(new CompilerMessageEventArgs(CompilerMessage.RequiredElement("Application", "SplashScreen"), this.Item)); } // Orientation preferences are optional. if (this.initialRotationPreferences != null && this.initialRotationPreferences.HasElements) { xVisualElements.Add(initialRotationPreferences); } // Extensions are optional. if (this.extensions != null && this.extensions.HasElements) { this.Xml.Add(this.extensions); } // Content URI rules are optional. if (this.contentUriRules != null && this.contentUriRules.HasElements) { this.Xml.Add(this.contentUriRules); } }
/// <summary> /// Creates the manifest document from the provided intermediates. Discards a previous /// manifest document if present. /// </summary> /// <param name="intermediates">Intermediates to process into the .nuspec file.</param> public void ProcessIntermediates(IEnumerable <Intermediate> intermediates) { this.document = null; this.Files = new List <PackageFile>(); Package package = null; Metadata metadata = null; Version minNuget = null; Dictionary <string, List <XElement> > groupedDependencies = new Dictionary <string, List <XElement> >(); Dictionary <string, List <XElement> > groupedFrameworks = new Dictionary <string, List <XElement> >(); Dictionary <string, List <XElement> > groupedReferences = new Dictionary <string, List <XElement> >(); foreach (Intermediate intermediate in intermediates) { foreach (PackageItem item in intermediate.Items) { if (item.System) { continue; } // Files are processed differently since we need to go search for them on disk and such. if (item is File) { PackageFile packageFile; if (PackageFile.TryCreate(backend, (File)item, out packageFile)) { this.Files.Add(packageFile); } } else if (item is Package) { if (package == null) { package = (Package)item; } else { this.backend.OnMessage(new CompilerMessageEventArgs(CompilerMessage.HighlanderElement("Package"), item)); } } else if (item is Prerequisite) { Prerequisite prereq = (Prerequisite)item; switch (prereq.On.ToLowerInvariant()) { case "nuget": if (null == minNuget) { if (prereq.Version == null) { this.backend.OnMessage(new CompilerMessageEventArgs(CompilerMessage.RequiredAttribute("Prerequisite", "Version"), prereq)); } else { minNuget = prereq.Version; } if (prereq.MaxVersion != null) { this.backend.OnMessage(new CompilerMessageEventArgs(CompilerMessage.InvalidAttributeValue("Prerequisite", "MaxVersion", prereq.MaxVersion.ToString()), prereq)); } } else { this.backend.OnMessage(new CompilerMessageEventArgs(CompilerMessage.HighlanderElementWithAttributeValue("Prerequisite", "On", prereq.On), prereq)); } break; default: // TODO: handle this correctly //xFrameworkAssemblies.Add(new XElement(NugetNamespace + "frameworkAssembly", // new XAttribute("assemblyName", prereq.On))); break; } } // TODO: handle dependencies and references correctly. //else if (item is Dependency) //{ // Dependency dependency = (Dependency)item; // XElement reference = new XElement(NugetNamespace + "reference", // new XAttribute("Id", dependency.Name), // new XElement(NugetNamespace + "Name", dependency.Publisher) // ); // string targetFramework = String.Empty; // if (dependency.Version != null) // { // reference.Add(new XAttribute("MinVersion", dependency.Version.ToString())); // } // if (dependency.MaxVersion != null) // { // reference.Add(new XAttribute("MaxVersion", dependency.MaxVersion.ToString())); // } // List<XElement> dependencies; // if (!groupedDependencies.TryGetValue(targetFramework, out dependencies)) // { // dependencies = new List<XElement>(); // groupedDependencies.Add(targetFramework, dependencies); // } // dependencies.Add(reference); //} //else if (item is Reference) //{ // Reference reference = (Reference)item; // string targetFramework = reference.TargetFramework ?? String.Empty; // List<XElement> references; // if (!groupedReferences.TryGetValue(targetFramework, out references)) // { // references = new List<XElement>(); // groupedReferences.Add(targetFramework, references); // } // references.Add(new XElement(NugetNamespace + "reference", // new XAttribute("file", IO.Path.GetFileName(reference.File)))); // references.Add(reference); //} else if (item is Metadata) { if (metadata == null) { metadata = (Metadata)item; } else { this.backend.OnMessage(new CompilerMessageEventArgs(CompilerMessage.HighlanderElement("Metadata"), item)); } } } } if (package != null) { this.Description = package.Description; this.Name = package.Name; this.Language = (null == backend.Languages || backend.Languages.Length == 0 || backend.Languages[0] == DefaultLanguage) ? null : backend.Languages[0].ToString(); this.Tags = metadata.Tags; this.DisplayName = package.DisplayName; this.Version = package.Version.ToString(); XElement xMetadata = new XElement(NugetNamespace + "metadata"); if (null != minNuget) { xMetadata.Add(new XAttribute("minClientVersion", minNuget.ToString())); } xMetadata.Add( new XElement(NugetNamespace + "id", package.Name), new XElement(NugetNamespace + "version", this.Version), String.IsNullOrEmpty(package.DisplayName) ? null : new XElement(NugetNamespace + "title", package.DisplayName), new XElement(NugetNamespace + "authors", package.Manufacturer), // TODO: Consider whether owner is useful enough to bring back. NuGet Gallery ignores it so no one will ever see this optional data. //String.IsNullOrEmpty(metadata.Owner) ? null : new XElement(NugetNamespace + "owners", metadata.Owner), String.IsNullOrEmpty(package.License) ? null : new XElement(NugetNamespace + "licenseUrl", package.License), String.IsNullOrEmpty(package.About) ? null : new XElement(NugetNamespace + "projectUrl", package.About), null == package.Image ? null : new XElement(NugetNamespace + "iconUrl", package.Image), metadata.DevelopmentDependency ? null : new XElement(NugetNamespace + "developmentDependency", "true"), new XElement(NugetNamespace + "requireLicenseAcceptance", metadata.RequireLicenseAcceptance ? "true" : "false"), new XElement(NugetNamespace + "description", package.Description), String.IsNullOrEmpty(metadata.Summary) ? null : new XElement(NugetNamespace + "summary", metadata.Summary), String.IsNullOrEmpty(metadata.ReleaseNotes) ? null : new XElement(NugetNamespace + "releaseNotes", metadata.ReleaseNotes), String.IsNullOrEmpty(package.Copyright) ? null : new XElement(NugetNamespace + "copyright", package.Copyright), this.Language == null ? null : new XElement(NugetNamespace + "language", this.Language), String.IsNullOrEmpty(metadata.Tags) ? null : new XElement(NugetNamespace + "tags", metadata.Tags) ); // Now put the manifest together. if (groupedDependencies != null) { XElement xDependencies = new XElement(NugetNamespace + "dependencies"); this.AddGroupedElements(xDependencies, groupedDependencies); xMetadata.Add(xDependencies); } if (groupedFrameworks != null) { XElement xFrameworkAssemblies = new XElement(NugetNamespace + "frameworkAssemblies"); this.AddGroupedElements(xFrameworkAssemblies, groupedFrameworks); xMetadata.Add(xFrameworkAssemblies); } if (groupedReferences != null) { XElement xReferences = new XElement(NugetNamespace + "references"); this.AddGroupedElements(xReferences, groupedReferences); xMetadata.Add(xReferences); } this.document = new XDocument(new XElement(NugetNamespace + "package", xMetadata)); } }