diff --git a/BSIPA-ModList/BSIPA-ModList.csproj b/BSIPA-ModList/BSIPA-ModList.csproj
index 2cffd2e6..8ba37248 100644
--- a/BSIPA-ModList/BSIPA-ModList.csproj
+++ b/BSIPA-ModList/BSIPA-ModList.csproj
@@ -78,6 +78,7 @@
+
@@ -94,6 +95,9 @@
+
+ 0.15.1
+
1.2.0
@@ -112,12 +116,15 @@
-
+
+
+
+
\ No newline at end of file
diff --git a/BSIPA-ModList/Plugin.cs b/BSIPA-ModList/Plugin.cs
index 51ee7c63..d9e7c24e 100644
--- a/BSIPA-ModList/Plugin.cs
+++ b/BSIPA-ModList/Plugin.cs
@@ -3,12 +3,15 @@ using UnityEngine.SceneManagement;
using IPALogger = IPA.Logging.Logger;
using BSIPA_ModList.UI;
using UnityEngine;
+using IPA.Logging;
namespace BSIPA_ModList
{
internal static class Logger
{
internal static IPALogger log { get; set; }
+
+ internal static IPALogger md => log.GetChildLogger("MarkDown");
}
public class Plugin : IBeatSaberPlugin
diff --git a/BSIPA-ModList/PostBuild.msbuild b/BSIPA-ModList/PostBuild.msbuild
new file mode 100644
index 00000000..d2016a49
--- /dev/null
+++ b/BSIPA-ModList/PostBuild.msbuild
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/BSIPA-ModList/UI/ViewControllers/MarkdownView.cs b/BSIPA-ModList/UI/ViewControllers/MarkdownView.cs
new file mode 100644
index 00000000..8b27e520
--- /dev/null
+++ b/BSIPA-ModList/UI/ViewControllers/MarkdownView.cs
@@ -0,0 +1,204 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using UnityEngine;
+using CommonMark;
+using CommonMark.Syntax;
+using UnityEngine.UI;
+using TMPro;
+using CustomUI.BeatSaber;
+
+namespace BSIPA_ModList.UI.ViewControllers
+{
+ [RequireComponent(/*typeof(ScrollRect),*/ typeof(RectTransform))]
+ public class MarkdownView : MonoBehaviour
+ {
+ private class TagTypeComponent : MonoBehaviour
+ {
+ internal BlockTag Tag;
+ }
+
+ private string markdown = "";
+ public string Markdown
+ {
+ get => markdown;
+ set
+ {
+ markdown = value;
+ UpdateMd();
+ }
+ }
+
+ public RectTransform rectTransform => GetComponent();
+
+ //private ScrollRect view;
+ private RectTransform content;
+
+ private CommonMarkSettings settings;
+ public MarkdownView()
+ {
+ settings = CommonMarkSettings.Default.Clone();
+ settings.AdditionalFeatures = CommonMarkAdditionalFeatures.All;
+ settings.RenderSoftLineBreaksAsLineBreaks = false;
+ settings.UriResolver = ResolveUri;
+ }
+
+ public Func HasEmbeddedImage;
+
+ private string ResolveUri(string arg)
+ {
+ var name = arg.Substring(3);
+ if (!arg.StartsWith("!::") && !arg.StartsWith("w::"))
+ { // !:: means embedded, w:: means web
+ // this block is for when neither is specified
+
+ // check if its embedded
+ if (HasEmbeddedImage != null && HasEmbeddedImage(arg))
+ return "!::" + arg;
+ else
+ return "w::" + arg;
+ }
+
+ return arg;
+ }
+
+ protected void Awake()
+ {
+ content = new GameObject("Content Wrapper").AddComponent();
+ content.SetParent(transform);
+ var contentLayout = content.gameObject.AddComponent();
+ var contentFitter = content.gameObject.AddComponent();
+ contentFitter.horizontalFit = ContentSizeFitter.FitMode.PreferredSize;
+ contentFitter.verticalFit = ContentSizeFitter.FitMode.Unconstrained;
+ contentLayout.preferredWidth = 100f; // to be adjusted
+ content.sizeDelta = new Vector2(100f,100f);
+
+ /*view = GetComponent();
+ view.content = content;
+ view.vertical = true;
+ view.horizontal = false;
+ view.verticalScrollbarVisibility = ScrollRect.ScrollbarVisibility.AutoHide;
+ view.horizontalScrollbarVisibility = ScrollRect.ScrollbarVisibility.AutoHide;*/
+ }
+
+ private void UpdateMd()
+ {
+ Clear();
+
+ var doc = CommonMarkConverter.Parse(markdown, settings);
+
+ Stack layout = new Stack();
+ layout.Push(content);
+ TextMeshProUGUI currentText = null;
+ foreach (var node in doc.AsEnumerable())
+ {
+ Logger.md.Debug($"node {node}");
+
+ if (node.Block != null)
+ {
+ var block = node.Block;
+
+ void BlockNode(string name, float spacing, bool isVertical)
+ {
+ var type = isVertical ? typeof(VerticalLayoutGroup) : typeof(HorizontalLayoutGroup);
+ if (node.IsOpening)
+ {
+ Logger.md.Debug($"Creating block container {name}");
+
+ currentText = null;
+ var go = new GameObject(name, typeof(RectTransform), type);
+ var vlayout = go.GetComponent();
+ vlayout.SetParent(layout.Peek());
+ go.AddComponent().Tag = block.Tag;
+ layout.Push(vlayout);
+
+ if (isVertical)
+ {
+ var vl = go.GetComponent();
+ vl.childControlHeight = vl.childControlWidth =
+ vl.childForceExpandHeight = vl.childForceExpandWidth = false;
+ vl.spacing = spacing;
+ }
+ else
+ {
+ var hl = go.GetComponent();
+ hl.childControlHeight = hl.childControlWidth =
+ hl.childForceExpandHeight = hl.childForceExpandWidth = false;
+ hl.spacing = spacing;
+ }
+ }
+ else if (node.IsClosing)
+ {
+ currentText = null;
+ layout.Pop();
+ }
+ }
+
+ switch (block.Tag)
+ {
+ case BlockTag.Document:
+ BlockNode("DocumentRoot", 10f, true);
+ break;
+ case BlockTag.SetextHeading:
+ BlockNode("Heading1", .1f, false);
+ break;
+ case BlockTag.AtxHeading:
+ BlockNode("Heading2", .1f, false);
+ break;
+ case BlockTag.Paragraph:
+ BlockNode("Paragraph", .1f, false);
+ break;
+ // TODO: add the rest of the tag types
+ }
+ }
+ else if (node.Inline != null)
+ { // inline element
+ var inl = node.Inline;
+
+ switch (inl.Tag)
+ {
+ case InlineTag.String:
+ if (currentText == null)
+ {
+ Logger.md.Debug($"Adding new text element");
+
+ var btt = layout.Peek().gameObject.GetComponent().Tag;
+ currentText = BeatSaberUI.CreateText(layout.Peek(), "", Vector2.zero);
+ //var le = currentText.gameObject.AddComponent();
+
+ switch (btt)
+ {
+ case BlockTag.List:
+ case BlockTag.ListItem:
+ case BlockTag.Paragraph:
+ currentText.fontSize = 3.5f;
+ currentText.enableWordWrapping = true;
+ break;
+ case BlockTag.AtxHeading:
+ currentText.fontSize = 4f;
+ currentText.enableWordWrapping = true;
+ break;
+ case BlockTag.SetextHeading:
+ currentText.fontSize = 4.5f;
+ currentText.enableWordWrapping = true;
+ break;
+ // TODO: add other relevant types
+ }
+ }
+ Logger.md.Debug($"Appending '{inl.LiteralContent}' to current element");
+ currentText.text += inl.LiteralContent;
+ break;
+ }
+ }
+ }
+ }
+
+ private void Clear()
+ {
+ foreach (Transform child in content)
+ Destroy(child.gameObject);
+ }
+ }
+}
diff --git a/BSIPA-ModList/UI/ViewControllers/ModInfoViewController.cs b/BSIPA-ModList/UI/ViewControllers/ModInfoViewController.cs
index e7f764d4..1ba01716 100644
--- a/BSIPA-ModList/UI/ViewControllers/ModInfoViewController.cs
+++ b/BSIPA-ModList/UI/ViewControllers/ModInfoViewController.cs
@@ -1,4 +1,5 @@
-using CustomUI.BeatSaber;
+using BSIPA_ModList.UI.ViewControllers;
+using CustomUI.BeatSaber;
using CustomUI.MenuButton;
using IPA.Loader;
using IPA.Updating.BeatMods;
@@ -182,10 +183,17 @@ namespace BSIPA_ModList.UI
titleText.fontSize = 6f;
authorText = BeatSaberUI.CreateText(rectTransform, controller.Author, new Vector2(11f, 22f));
authorText.fontSize = 4.5f;
+
+ /*
descText = BeatSaberUI.CreateText(rectTransform, controller.Description, new Vector2(-4.5f, 12f));
descText.fontSize = 3.5f;
descText.enableWordWrapping = true;
- descText.overflowMode = TextOverflowModes.ScrollRect;
+ descText.overflowMode = TextOverflowModes.ScrollRect;*/
+
+ var mdv = new GameObject("MarkDown Desc").AddComponent();
+ mdv.rectTransform.anchoredPosition = new Vector2(-4.5f, 12f);
+ mdv.rectTransform.SetParent(rectTransform);
+ mdv.Markdown = controller.Description;
icon = new GameObject("Mod Info View Icon", typeof(RectTransform)).AddComponent();
icon.gameObject.SetActive(false);
@@ -328,5 +336,5 @@ namespace BSIPA_ModList.UI
#endif
}
#endif
- }
+ }
}
diff --git a/BSIPA-ModList/manifest.json b/BSIPA-ModList/manifest.json
index 689ae4c7..c1a1f3ef 100644
--- a/BSIPA-ModList/manifest.json
+++ b/BSIPA-ModList/manifest.json
@@ -1,7 +1,13 @@
{
"$schema": "https://raw.githubusercontent.com/nike4613/ModSaber-MetadataFileSchema/master/Schema.json",
"author": "DaNike",
- "description": "An in-game interface client for BSIPA.",
+ "description": [
+ "## An in-game interface client for BSIPA.",
+ "",
+ "***",
+ "",
+ "Look, ma! Markdown! Its **[CommonMark](w::https://commonmark.org/)**!"
+ ],
"gameVersion": "0.13.2",
"id": "BSIPA Mod List",
"name": "BSIPA Mod List",