summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/SMAPI.Web/ViewModels/ModCompatibilityModel.cs12
-rw-r--r--src/SMAPI.Web/ViewModels/ModModel.cs12
-rw-r--r--src/SMAPI.Web/Views/Mods/Index.cshtml2
-rw-r--r--src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/ModExtendedMetadataModel.cs2
-rw-r--r--src/StardewModdingAPI.Toolkit/Framework/Clients/Wiki/WikiClient.cs112
-rw-r--r--src/StardewModdingAPI.Toolkit/Framework/Clients/Wiki/WikiCompatibilityInfo.cs3
-rw-r--r--src/StardewModdingAPI.Toolkit/Framework/Clients/Wiki/WikiModEntry.cs22
7 files changed, 92 insertions, 73 deletions
diff --git a/src/SMAPI.Web/ViewModels/ModCompatibilityModel.cs b/src/SMAPI.Web/ViewModels/ModCompatibilityModel.cs
index d331c093..61756176 100644
--- a/src/SMAPI.Web/ViewModels/ModCompatibilityModel.cs
+++ b/src/SMAPI.Web/ViewModels/ModCompatibilityModel.cs
@@ -11,12 +11,15 @@ namespace StardewModdingAPI.Web.ViewModels
/// <summary>The compatibility status, as a string like <c>"Broken"</c>.</summary>
public string Status { get; set; }
- /// <summary>A link to the unofficial version which fixes compatibility, if any.</summary>
- public ModLinkModel UnofficialVersion { get; set; }
-
/// <summary>The human-readable summary, as an HTML block.</summary>
public string Summary { get; set; }
+ /// <summary>The game or SMAPI version which broke this mod (if applicable).</summary>
+ public string BrokeIn { get; set; }
+
+ /// <summary>A link to the unofficial version which fixes compatibility, if any.</summary>
+ public ModLinkModel UnofficialVersion { get; set; }
+
/*********
** Public methods
@@ -26,9 +29,10 @@ namespace StardewModdingAPI.Web.ViewModels
public ModCompatibilityModel(WikiCompatibilityInfo info)
{
this.Status = info.Status.ToString();
+ this.Summary = info.Summary;
+ this.BrokeIn = info.BrokeIn;
if (info.UnofficialVersion != null)
this.UnofficialVersion = new ModLinkModel(info.UnofficialUrl, info.UnofficialVersion.ToString());
- this.Summary = info.Summary;
}
}
}
diff --git a/src/SMAPI.Web/ViewModels/ModModel.cs b/src/SMAPI.Web/ViewModels/ModModel.cs
index 4fb9d5b5..1199fe20 100644
--- a/src/SMAPI.Web/ViewModels/ModModel.cs
+++ b/src/SMAPI.Web/ViewModels/ModModel.cs
@@ -34,9 +34,6 @@ namespace StardewModdingAPI.Web.ViewModels
/// <summary>Links to the available mod pages.</summary>
public ModLinkModel[] ModPages { get; set; }
- /// <summary>The game or SMAPI version which broke this mod (if applicable).</summary>
- public string BrokeIn { get; set; }
-
/// <summary>A unique identifier for the mod that can be used in an anchor URL.</summary>
public string Slug { get; set; }
@@ -49,15 +46,14 @@ namespace StardewModdingAPI.Web.ViewModels
public ModModel(WikiModEntry entry)
{
// basic info
- this.Name = entry.Name;
- this.AlternateNames = entry.AlternateNames;
- this.Author = entry.Author;
- this.AlternateAuthors = entry.AlternateAuthors;
+ this.Name = entry.Name.FirstOrDefault();
+ this.AlternateNames = string.Join(", ", entry.Name.Skip(1).ToArray());
+ this.Author = entry.Author.FirstOrDefault();
+ this.AlternateAuthors = string.Join(", ", entry.Author.Skip(1).ToArray());
this.SourceUrl = this.GetSourceUrl(entry);
this.Compatibility = new ModCompatibilityModel(entry.Compatibility);
this.BetaCompatibility = entry.BetaCompatibility != null ? new ModCompatibilityModel(entry.BetaCompatibility) : null;
this.ModPages = this.GetModPageUrls(entry).ToArray();
- this.BrokeIn = entry.BrokeIn;
this.Slug = entry.Anchor;
}
diff --git a/src/SMAPI.Web/Views/Mods/Index.cshtml b/src/SMAPI.Web/Views/Mods/Index.cshtml
index b2ab61d7..b2e20c7a 100644
--- a/src/SMAPI.Web/Views/Mods/Index.cshtml
+++ b/src/SMAPI.Web/Views/Mods/Index.cshtml
@@ -71,7 +71,7 @@
<span v-html="mod.BetaCompatibility.Summary"></span>
</div>
</td>
- <td class="mod-broke-in" v-html="mod.BrokeIn" v-show="showAllFields"></td>
+ <td class="mod-broke-in" v-html="mod.BetaCompatibility ? mod.BetaCompatibility.BrokeIn : mod.Compatibility.BrokeIn" v-show="showAllFields"></td>
<td v-show="showAllFields">
<span v-if="mod.SourceUrl"><a v-bind:href="mod.SourceUrl">source</a></span>
<span v-else class="mod-closed-source">no source</span>
diff --git a/src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/ModExtendedMetadataModel.cs b/src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/ModExtendedMetadataModel.cs
index e6f2e4b4..247730d7 100644
--- a/src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/ModExtendedMetadataModel.cs
+++ b/src/StardewModdingAPI.Toolkit/Framework/Clients/WebApi/ModExtendedMetadataModel.cs
@@ -74,7 +74,7 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.WebApi
if (wiki != null)
{
this.ID = wiki.ID;
- this.Name = wiki.Name;
+ this.Name = wiki.Name.FirstOrDefault();
this.NexusID = wiki.NexusID;
this.ChucklefishID = wiki.ChucklefishID;
this.GitHubRepo = wiki.GitHubRepo;
diff --git a/src/StardewModdingAPI.Toolkit/Framework/Clients/Wiki/WikiClient.cs b/src/StardewModdingAPI.Toolkit/Framework/Clients/Wiki/WikiClient.cs
index 9be760f8..7197bf2c 100644
--- a/src/StardewModdingAPI.Toolkit/Framework/Clients/Wiki/WikiClient.cs
+++ b/src/StardewModdingAPI.Toolkit/Framework/Clients/Wiki/WikiClient.cs
@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
+using System.Net;
using System.Threading.Tasks;
using HtmlAgilityPack;
using Pathoschild.Http.Client;
@@ -84,40 +85,40 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki
foreach (HtmlNode node in nodes)
{
// extract fields
- string name = this.GetMetadataField(node, "mod-name");
- string alternateNames = this.GetMetadataField(node, "mod-name2");
- string author = this.GetMetadataField(node, "mod-author");
- string alternateAuthors = this.GetMetadataField(node, "mod-author2");
- string[] ids = this.GetMetadataField(node, "mod-id")?.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(p => p.Trim()).ToArray() ?? new string[0];
- int? nexusID = this.GetNullableIntField(node, "mod-nexus-id");
- int? chucklefishID = this.GetNullableIntField(node, "mod-cf-id");
- string githubRepo = this.GetMetadataField(node, "mod-github");
- string customSourceUrl = this.GetMetadataField(node, "mod-custom-source");
- string customUrl = this.GetMetadataField(node, "mod-url");
- string brokeIn = this.GetMetadataField(node, "mod-broke-in");
- string anchor = this.GetMetadataField(node, "mod-anchor");
+ string[] names = this.GetAttributeAsCsv(node, "data-name");
+ string[] authors = this.GetAttributeAsCsv(node, "data-author");
+ string[] ids = this.GetAttributeAsCsv(node, "data-id");
+ string[] warnings = this.GetAttributeAsCsv(node, "data-warnings");
+ int? nexusID = this.GetAttributeAsNullableInt(node, "data-nexus-id");
+ int? chucklefishID = this.GetAttributeAsNullableInt(node, "data-cf-id");
+ string githubRepo = this.GetAttribute(node, "data-github");
+ string customSourceUrl = this.GetAttribute(node, "data-custom-source");
+ string customUrl = this.GetAttribute(node, "data-url");
+ string anchor = this.GetAttribute(node, "id");
// parse stable compatibility
WikiCompatibilityInfo compatibility = new WikiCompatibilityInfo
{
- Status = this.GetStatusField(node, "mod-status") ?? WikiCompatibilityStatus.Ok,
- UnofficialVersion = this.GetSemanticVersionField(node, "mod-unofficial-version"),
- UnofficialUrl = this.GetMetadataField(node, "mod-unofficial-url"),
- Summary = this.GetMetadataField(node, "mod-summary")?.Trim()
+ Status = this.GetAttributeAsStatus(node, "data-status") ?? WikiCompatibilityStatus.Ok,
+ BrokeIn = this.GetAttribute(node, "data-broke-in"),
+ UnofficialVersion = this.GetAttributeAsSemanticVersion(node, "data-unofficial-version"),
+ UnofficialUrl = this.GetAttribute(node, "data-unofficial-url"),
+ Summary = this.GetInnerHtml(node, "mod-summary")?.Trim()
};
// parse beta compatibility
WikiCompatibilityInfo betaCompatibility = null;
{
- WikiCompatibilityStatus? betaStatus = this.GetStatusField(node, "mod-beta-status");
+ WikiCompatibilityStatus? betaStatus = this.GetAttributeAsStatus(node, "data-beta-status");
if (betaStatus.HasValue)
{
betaCompatibility = new WikiCompatibilityInfo
{
Status = betaStatus.Value,
- UnofficialVersion = this.GetSemanticVersionField(node, "mod-beta-unofficial-version"),
- UnofficialUrl = this.GetMetadataField(node, "mod-beta-unofficial-url"),
- Summary = this.GetMetadataField(node, "mod-beta-summary")
+ BrokeIn = this.GetAttribute(node, "data-beta-broke-in"),
+ UnofficialVersion = this.GetAttributeAsSemanticVersion(node, "data-beta-unofficial-version"),
+ UnofficialUrl = this.GetAttribute(node, "data-beta-unofficial-url"),
+ Summary = this.GetInnerHtml(node, "mod-beta-summary")
};
}
}
@@ -126,37 +127,50 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki
yield return new WikiModEntry
{
ID = ids,
- Name = name,
- AlternateNames = alternateNames,
- Author = author,
- AlternateAuthors = alternateAuthors,
+ Name = names,
+ Author = authors,
NexusID = nexusID,
ChucklefishID = chucklefishID,
GitHubRepo = githubRepo,
CustomSourceUrl = customSourceUrl,
CustomUrl = customUrl,
- BrokeIn = brokeIn,
Compatibility = compatibility,
BetaCompatibility = betaCompatibility,
+ Warnings = warnings,
Anchor = anchor
};
}
}
- /// <summary>Get the value of a metadata field.</summary>
- /// <param name="container">The metadata container.</param>
- /// <param name="name">The field name.</param>
- private string GetMetadataField(HtmlNode container, string name)
+ /// <summary>Get an attribute value.</summary>
+ /// <param name="element">The element whose attributes to read.</param>
+ /// <param name="name">The attribute name.</param>
+ private string GetAttribute(HtmlNode element, string name)
{
- return container.Descendants().FirstOrDefault(p => p.HasClass(name))?.InnerHtml;
+ string value = element.GetAttributeValue(name, null);
+ if (string.IsNullOrWhiteSpace(value))
+ return null;
+
+ return WebUtility.HtmlDecode(value);
}
- /// <summary>Get the value of a metadata field as a compatibility status.</summary>
- /// <param name="container">The metadata container.</param>
- /// <param name="name">The field name.</param>
- private WikiCompatibilityStatus? GetStatusField(HtmlNode container, string name)
+ /// <summary>Get an attribute value and parse it as a comma-delimited list of strings.</summary>
+ /// <param name="element">The element whose attributes to read.</param>
+ /// <param name="name">The attribute name.</param>
+ private string[] GetAttributeAsCsv(HtmlNode element, string name)
+ {
+ string raw = this.GetAttribute(element, name);
+ return !string.IsNullOrWhiteSpace(raw)
+ ? raw.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(p => p.Trim()).ToArray()
+ : new string[0];
+ }
+
+ /// <summary>Get an attribute value and parse it as a compatibility status.</summary>
+ /// <param name="element">The element whose attributes to read.</param>
+ /// <param name="name">The attribute name.</param>
+ private WikiCompatibilityStatus? GetAttributeAsStatus(HtmlNode element, string name)
{
- string raw = this.GetMetadataField(container, name);
+ string raw = this.GetAttribute(element, name);
if (raw == null)
return null;
if (!Enum.TryParse(raw, true, out WikiCompatibilityStatus status))
@@ -164,28 +178,36 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki
return status;
}
- /// <summary>Get the value of a metadata field as a semantic version.</summary>
- /// <param name="container">The metadata container.</param>
- /// <param name="name">The field name.</param>
- private ISemanticVersion GetSemanticVersionField(HtmlNode container, string name)
+ /// <summary>Get an attribute value and parse it as a semantic version.</summary>
+ /// <param name="element">The element whose attributes to read.</param>
+ /// <param name="name">The attribute name.</param>
+ private ISemanticVersion GetAttributeAsSemanticVersion(HtmlNode element, string name)
{
- string raw = this.GetMetadataField(container, name);
+ string raw = this.GetAttribute(element, name);
return SemanticVersion.TryParse(raw, out ISemanticVersion version)
? version
: null;
}
- /// <summary>Get the value of a metadata field as a nullable integer.</summary>
- /// <param name="container">The metadata container.</param>
- /// <param name="name">The field name.</param>
- private int? GetNullableIntField(HtmlNode container, string name)
+ /// <summary>Get an attribute value and parse it as a nullable int.</summary>
+ /// <param name="element">The element whose attributes to read.</param>
+ /// <param name="name">The attribute name.</param>
+ private int? GetAttributeAsNullableInt(HtmlNode element, string name)
{
- string raw = this.GetMetadataField(container, name);
+ string raw = this.GetAttribute(element, name);
if (raw != null && int.TryParse(raw, out int value))
return value;
return null;
}
+ /// <summary>Get the text of an element with the given class name.</summary>
+ /// <param name="container">The metadata container.</param>
+ /// <param name="className">The field name.</param>
+ private string GetInnerHtml(HtmlNode container, string className)
+ {
+ return container.Descendants().FirstOrDefault(p => p.HasClass(className))?.InnerHtml;
+ }
+
/// <summary>The response model for the MediaWiki parse API.</summary>
[SuppressMessage("ReSharper", "ClassNeverInstantiated.Local")]
[SuppressMessage("ReSharper", "UnusedAutoPropertyAccessor.Local")]
diff --git a/src/StardewModdingAPI.Toolkit/Framework/Clients/Wiki/WikiCompatibilityInfo.cs b/src/StardewModdingAPI.Toolkit/Framework/Clients/Wiki/WikiCompatibilityInfo.cs
index 2725df1a..204acd2b 100644
--- a/src/StardewModdingAPI.Toolkit/Framework/Clients/Wiki/WikiCompatibilityInfo.cs
+++ b/src/StardewModdingAPI.Toolkit/Framework/Clients/Wiki/WikiCompatibilityInfo.cs
@@ -12,6 +12,9 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki
/// <summary>The human-readable summary of the compatibility status or workaround, without HTML formatting.</summary>
public string Summary { get; set; }
+ /// <summary>The game or SMAPI version which broke this mod (if applicable).</summary>
+ public string BrokeIn { get; set; }
+
/// <summary>The version of the latest unofficial update, if applicable.</summary>
public ISemanticVersion UnofficialVersion { get; set; }
diff --git a/src/StardewModdingAPI.Toolkit/Framework/Clients/Wiki/WikiModEntry.cs b/src/StardewModdingAPI.Toolkit/Framework/Clients/Wiki/WikiModEntry.cs
index 752b526c..ce8d6c5f 100644
--- a/src/StardewModdingAPI.Toolkit/Framework/Clients/Wiki/WikiModEntry.cs
+++ b/src/StardewModdingAPI.Toolkit/Framework/Clients/Wiki/WikiModEntry.cs
@@ -6,20 +6,14 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki
/*********
** Accessors
*********/
- /// <summary>The mod's unique ID. A mod may have multiple current IDs in rare cases (e.g. due to parallel releases or unofficial updates).</summary>
+ /// <summary>The mod's unique ID. If the mod has alternate/old IDs, they're listed in latest to newest order.</summary>
public string[] ID { get; set; }
- /// <summary>The mod's display name.</summary>
- public string Name { get; set; }
+ /// <summary>The mod's display name. If the mod has multiple names, the first one is the most canonical name.</summary>
+ public string[] Name { get; set; }
- /// <summary>The mod's alternative names, if any.</summary>
- public string AlternateNames { get; set; }
-
- /// <summary>The mod's author name.</summary>
- public string Author { get; set; }
-
- /// <summary>The mod's alternative author names, if any.</summary>
- public string AlternateAuthors { get; set; }
+ /// <summary>The mod's author name. If the author has multiple names, the first one is the most canonical name.</summary>
+ public string[] Author { get; set; }
/// <summary>The mod ID on Nexus.</summary>
public int? NexusID { get; set; }
@@ -36,9 +30,6 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki
/// <summary>The custom mod page URL (if applicable).</summary>
public string CustomUrl { get; set; }
- /// <summary>The game or SMAPI version which broke this mod (if applicable).</summary>
- public string BrokeIn { get; set; }
-
/// <summary>The mod's compatibility with the latest stable version of the game.</summary>
public WikiCompatibilityInfo Compatibility { get; set; }
@@ -48,6 +39,9 @@ namespace StardewModdingAPI.Toolkit.Framework.Clients.Wiki
/// <summary>Whether a Stardew Valley or SMAPI beta which affects mod compatibility is in progress. If this is true, <see cref="BetaCompatibility"/> should be used for beta versions of SMAPI instead of <see cref="Compatibility"/>.</summary>
public bool HasBetaInfo => this.BetaCompatibility != null;
+ /// <summary>The human-readable warnings for players about this mod.</summary>
+ public string[] Warnings { get; set; }
+
/// <summary>The link anchor for the mod entry in the wiki compatibility list.</summary>
public string Anchor { get; set; }
}