From cb6dd0d8e5f07aa7741a7e7a8cc6f4bb49236f55 Mon Sep 17 00:00:00 2001 From: Anairkoen Schno Date: Mon, 13 May 2019 19:36:21 -0500 Subject: [PATCH] Added code block support Added list support, but that is a bit scuffed --- .../UI/ViewControllers/MarkdownView.cs | 160 +++++++++++++++--- 1 file changed, 135 insertions(+), 25 deletions(-) diff --git a/BSIPA-ModList/UI/ViewControllers/MarkdownView.cs b/BSIPA-ModList/UI/ViewControllers/MarkdownView.cs index 02649e3e..d7607c25 100644 --- a/BSIPA-ModList/UI/ViewControllers/MarkdownView.cs +++ b/BSIPA-ModList/UI/ViewControllers/MarkdownView.cs @@ -22,6 +22,9 @@ namespace BSIPA_ModList.UI.ViewControllers { internal BlockTag Tag; internal HeadingData hData; + internal ListData lData; + internal int listCount; + internal int listIndex; } private string markdown = ""; @@ -217,18 +220,8 @@ namespace BSIPA_ModList.UI.ViewControllers } } - private static Sprite blockQuoteSidebar; - private static Sprite BlockQuoteSidebar - { - get - { - if (blockQuoteSidebar == null) - blockQuoteSidebar = Resources.FindObjectsOfTypeAll().First(s => s.name == "BackButtonBG"); - return blockQuoteSidebar; - } - } - - private static readonly Color BlockQuoteColor = new Color(30f/255, 109f/255, 178f/255, .25f); + private static readonly Color BlockQuoteColor = new Color( 30f / 255, 109f / 255, 178f / 255, .25f); + private static readonly Color BlockCodeColor = new Color(135f / 255, 135f / 255, 135f / 255, .5f); #if DEBUG #if UI_CONFIGURE_MARKDOWN_THEMATIC_BREAK @@ -258,6 +251,11 @@ namespace BSIPA_ModList.UI.ViewControllers private const string LinkDefaultColor = "#0061ff"; private const string LinkHoverColor = "#009dff"; + const float PSize = 3.5f; + const float BlockCodeSize = PSize - .5f; + const float H1Size = 5.5f; + const float HLevelDecrease = 0.5f; + private IEnumerator UpdateMd() { mdDirty = false; @@ -284,6 +282,8 @@ namespace BSIPA_ModList.UI.ViewControllers const float BreakHeight = .5f; const int TextInset = 1; const int BlockQuoteInset = TextInset * 2; + const int BlockCodeInset = BlockQuoteInset; + const int ListInset = TextInset; void Spacer(float size = 1.5f) { @@ -442,24 +442,127 @@ namespace BSIPA_ModList.UI.ViewControllers l.childForceExpandWidth = true; l.padding = new RectOffset(BlockQuoteInset, BlockQuoteInset, BlockQuoteInset, 0); var go = l.gameObject; - var rt = go.GetComponent(); var im = go.AddComponent(); im.material = CustomUI.Utilities.UIUtilities.NoGlowMaterial; im.type = Image.Type.Sliced; im.sprite = Instantiate(BlockQuoteBackground); im.color = BlockQuoteColor; + } + break; + case BlockTag.IndentedCode: + case BlockTag.FencedCode: + { + currentText = null; + var go = new GameObject("CodeBlock", typeof(RectTransform)); + var vlayout = go.GetComponent(); + vlayout.SetParent(layout.Peek()); + + vlayout.anchorMin = new Vector2(.5f, .5f); + vlayout.anchorMax = new Vector2(.5f, .5f); + vlayout.localScale = Vector3.one; + vlayout.localPosition = Vector3.zero; + vlayout.sizeDelta = new Vector2(layout.Peek().rect.width - BlockCodeInset * 2, 0f); + + var tt = go.AddComponent(); + tt.Tag = block.Tag; + + l = go.AddComponent(); + + l.childControlHeight = l.childControlWidth = true; + l.childForceExpandHeight = false; + l.childForceExpandWidth = true; + l.spacing = 1.5f; + l.padding = new RectOffset(BlockCodeInset, BlockCodeInset, BlockCodeInset, BlockCodeInset); + + var im = go.AddComponent(); + im.material = CustomUI.Utilities.UIUtilities.NoGlowMaterial; + im.type = Image.Type.Sliced; + im.sprite = Instantiate(BlockQuoteBackground); + im.color = BlockCodeColor; + + var text = BeatSaberUI.CreateText(vlayout, $"{block.StringContent}", Vector2.zero); + text.fontSize = BlockCodeSize; + text.font = Consolas; + } + break; + + case BlockTag.List: + l = BlockNode("List", .05f, true, t => t.lData = block.ListData, matchWidth: true, matchWidthDiff: ListInset * 2, spacer: 1.5f); + if (l) + { + l.childForceExpandWidth = true; + l.padding = new RectOffset(ListInset, ListInset, 0, 0); + var go = l.gameObject; + var tt = go.GetComponent(); - /*var im2 = go.AddComponent(); - im2.material = CustomUI.Utilities.UIUtilities.NoGlowMaterial; - im2.type = Image.Type.Sliced; - im2.sprite = Instantiate(BlockQuoteSidebar);*/ - //im2.color = BlockQuoteColor; + // count up children + var count = 0; + for (var c = block.FirstChild; c != null; c = c.NextSibling) count++; + tt.listCount = count; + tt.listIndex = 0; } break; + case BlockTag.ListItem: + l = BlockNode("ListItem", .05f, false, matchWidth: true, spacer: null); + if (l) + { // TODO: this is mega scuffed + l.childForceExpandWidth = true; + var go = l.gameObject; + var rt = go.GetComponent(); + var tt = go.GetComponent(); + var ptt = rt.parent.gameObject.GetComponent(); + + var index = ptt.listIndex++; + + var listCount = ptt.listCount; + var maxNum = listCount + ptt.lData.Start; + var numChars = (int)Math.Floor(Math.Log10(maxNum) + 1); + + var cNum = index + ptt.lData.Start; + + var lt = ptt.lData.ListType; + + var id = lt == ListType.Bullet ? ptt.lData.BulletChar.ToString() : (cNum + (ptt.lData.Delimiter == ListDelimiter.Parenthesis ? ")" : ".")); + var ident = BeatSaberUI.CreateText(rt, $"{id} \n", Vector2.zero); + if (lt == ListType.Ordered) // pad it out to fill space + ident.text += $"{new string(' ', numChars + 1)}"; + + var contGo = new GameObject("Content", typeof(RectTransform)); + var vlayout = contGo.GetComponent(); + vlayout.SetParent(rt); + + vlayout.anchorMin = new Vector2(.5f, .5f); + vlayout.anchorMax = new Vector2(.5f, .5f); + vlayout.localScale = Vector3.one; + vlayout.localPosition = Vector3.zero; + //vlayout.sizeDelta = new Vector2(rt.rect.width, 0f); + + var tt2 = contGo.AddComponent(); + tt2.Tag = block.Tag; + + var csf = contGo.AddComponent(); + csf.horizontalFit = ContentSizeFitter.FitMode.PreferredSize; + csf.verticalFit = ContentSizeFitter.FitMode.Unconstrained; + + l = contGo.AddComponent(); + l.childAlignment = TextAnchor.UpperLeft; + l.childControlHeight = l.childControlWidth = true; + l.childForceExpandHeight = false; + l.childForceExpandWidth = true; + l.spacing = .5f; + + layout.Push(vlayout); + } + else + layout.Pop(); // pop one more to clear content rect from stack + break; + + case BlockTag.HtmlBlock: + break; case BlockTag.ReferenceDefinition: // i have no idea what the state looks like here - block.DebugPrintTo(Logger.md.Info, 5); + //block.DebugPrintTo(Logger.md.Info, 5); break; } } @@ -475,9 +578,6 @@ namespace BSIPA_ModList.UI.ViewControllers textFlags &= ~flag; } - const float PSize = 3.5f; - const float H1Size = 5.5f; - const float HLevelDecrease = 0.5f; void EnsureText() { if (currentText == null) @@ -488,25 +588,24 @@ namespace BSIPA_ModList.UI.ViewControllers currentText = BeatSaberUI.CreateText(layout.Peek(), "", Vector2.zero); currentText.gameObject.AddComponent(); + currentText.enableWordWrapping = true; + switch (tt.Tag) { case BlockTag.List: case BlockTag.ListItem: case BlockTag.Paragraph: currentText.fontSize = PSize; - currentText.enableWordWrapping = true; break; case BlockTag.AtxHeading: var size = H1Size; size -= HLevelDecrease * (tt.hData.Level - 1); currentText.fontSize = size; - currentText.enableWordWrapping = true; if (tt.hData.Level == 1) currentText.alignment = TextAlignmentOptions.Center; break; case BlockTag.SetextHeading: currentText.fontSize = H1Size; - currentText.enableWordWrapping = true; currentText.alignment = TextAlignmentOptions.Center; break; // TODO: add other relevant types @@ -549,6 +648,10 @@ namespace BSIPA_ModList.UI.ViewControllers EnsureText(); currentText.text += " "; // soft breaks translate to a space break; + case InlineTag.LineBreak: + EnsureText(); + currentText.text += "\n"; // line breaks translate to a new line + break; case InlineTag.Link: EnsureText(); Flag(CurrentTextFlags.Underline); @@ -557,6 +660,13 @@ namespace BSIPA_ModList.UI.ViewControllers else if (node.IsClosing) currentText.text += ""; break; + case InlineTag.RawHtml: + EnsureText(); + currentText.text += inl.LiteralContent; + break; + case InlineTag.Placeholder: + + break; } } }