mirror of
https://github.com/ppy/osu.git
synced 2025-03-19 05:57:19 +08:00
Merge pull request #12949 from gagahpangeran/main-page-wiki
Add wiki main page
This commit is contained in:
commit
ef937216a9
43
osu.Game.Tests/Visual/Online/TestSceneWikiMainPage.cs
Normal file
43
osu.Game.Tests/Visual/Online/TestSceneWikiMainPage.cs
Normal file
@ -0,0 +1,43 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Wiki;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
public class TestSceneWikiMainPage : OsuTestScene
|
||||
{
|
||||
[Cached]
|
||||
private readonly OverlayColourProvider overlayColour = new OverlayColourProvider(OverlayColourScheme.Orange);
|
||||
|
||||
public TestSceneWikiMainPage()
|
||||
{
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
Colour = overlayColour.Background5,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
new BasicScrollContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Padding = new MarginPadding(20),
|
||||
Child = new WikiMainPage
|
||||
{
|
||||
Markdown = main_page_markdown
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// From https://osu.ppy.sh/api/v2/wiki/en/Main_Page
|
||||
private const string main_page_markdown =
|
||||
"---\nlayout: main_page\n---\n\n<!-- Do not add any empty lines inside this div. -->\n\n<div class=\"wiki-main-page__blurb\">\nWelcome to the osu! wiki, a project containing a wide range of osu! related information.\n</div>\n\n<div class=\"wiki-main-page__panels\">\n<div class=\"wiki-main-page-panel wiki-main-page-panel--full\">\n\n# Getting started\n\n[Welcome](/wiki/Welcome) • [Installation](/wiki/Installation) • [Registration](/wiki/Registration) • [Help Centre](/wiki/Help_Centre) • [FAQ](/wiki/FAQ)\n\n</div>\n<div class=\"wiki-main-page-panel\">\n\n# Game client\n\n[Interface](/wiki/Interface) • [Options](/wiki/Options) • [Visual settings](/wiki/Visual_Settings) • [Shortcut key reference](/wiki/Shortcut_key_reference) • [Configuration file](/wiki/osu!_Program_Files/User_Configuration_File) • [Program files](/wiki/osu!_Program_Files)\n\n[File formats](/wiki/osu!_File_Formats): [.osz](/wiki/osu!_File_Formats/Osz_(file_format)) • [.osk](/wiki/osu!_File_Formats/Osk_(file_format)) • [.osr](/wiki/osu!_File_Formats/Osr_(file_format)) • [.osu](/wiki/osu!_File_Formats/Osu_(file_format)) • [.osb](/wiki/osu!_File_Formats/Osb_(file_format)) • [.db](/wiki/osu!_File_Formats/Db_(file_format))\n\n</div>\n<div class=\"wiki-main-page-panel\">\n\n# Gameplay\n\n[Game modes](/wiki/Game_mode): [osu!](/wiki/Game_mode/osu!) • [osu!taiko](/wiki/Game_mode/osu!taiko) • [osu!catch](/wiki/Game_mode/osu!catch) • [osu!mania](/wiki/Game_mode/osu!mania)\n\n[Beatmap](/wiki/Beatmap) • [Hit object](/wiki/Hit_object) • [Mods](/wiki/Game_modifier) • [Score](/wiki/Score) • [Replay](/wiki/Replay) • [Multi](/wiki/Multi)\n\n</div>\n<div class=\"wiki-main-page-panel\">\n\n# [Beatmap editor](/wiki/Beatmap_Editor)\n\nSections: [Compose](/wiki/Beatmap_Editor/Compose) • [Design](/wiki/Beatmap_Editor/Design) • [Timing](/wiki/Beatmap_Editor/Timing) • [Song setup](/wiki/Beatmap_Editor/Song_Setup)\n\nComponents: [AiMod](/wiki/Beatmap_Editor/AiMod) • [Beat snap divisor](/wiki/Beatmap_Editor/Beat_Snap_Divisor) • [Distance snap](/wiki/Beatmap_Editor/Distance_Snap) • [Menu](/wiki/Beatmap_Editor/Menu) • [SB load](/wiki/Beatmap_Editor/SB_Load) • [Timelines](/wiki/Beatmap_Editor/Timelines)\n\n[Beatmapping](/wiki/Beatmapping) • [Difficulty](/wiki/Beatmap/Difficulty) • [Mapping techniques](/wiki/Mapping_Techniques) • [Storyboarding](/wiki/Storyboarding)\n\n</div>\n<div class=\"wiki-main-page-panel\">\n\n# Beatmap submission and ranking\n\n[Submission](/wiki/Submission) • [Modding](/wiki/Modding) • [Ranking procedure](/wiki/Beatmap_ranking_procedure) • [Mappers' Guild](/wiki/Mappers_Guild) • [Project Loved](/wiki/Project_Loved)\n\n[Ranking criteria](/wiki/Ranking_Criteria): [osu!](/wiki/Ranking_Criteria/osu!) • [osu!taiko](/wiki/Ranking_Criteria/osu!taiko) • [osu!catch](/wiki/Ranking_Criteria/osu!catch) • [osu!mania](/wiki/Ranking_Criteria/osu!mania)\n\n</div>\n<div class=\"wiki-main-page-panel\">\n\n# Community\n\n[Tournaments](/wiki/Tournaments) • [Skinning](/wiki/Skinning) • [Projects](/wiki/Projects) • [Guides](/wiki/Guides) • [osu!dev Discord server](/wiki/osu!dev_Discord_server) • [How you can help](/wiki/How_You_Can_Help!) • [Glossary](/wiki/Glossary)\n\n</div>\n<div class=\"wiki-main-page-panel\">\n\n# People\n\n[The Team](/wiki/People/The_Team): [Developers](/wiki/People/The_Team/Developers) • [Global Moderation Team](/wiki/People/The_Team/Global_Moderation_Team) • [Support Team](/wiki/People/The_Team/Support_Team) • [Nomination Assessment Team](/wiki/People/The_Team/Nomination_Assessment_Team) • [Beatmap Nominators](/wiki/People/The_Team/Beatmap_Nominators) • [osu! Alumni](/wiki/People/The_Team/osu!_Alumni) • [Project Loved Team](/wiki/People/The_Team/Project_Loved_Team)\n\nOrganisations: [osu! UCI](/wiki/Organisations/osu!_UCI)\n\n[Community Contributors](/wiki/People/Community_Contributors) • [Users with unique titles](/wiki/People/Users_with_unique_titles)\n\n</div>\n<div class=\"wiki-main-page-panel\">\n\n# For developers\n\n[API](/wiki/osu!api) • [Bot account](/wiki/Bot_account) • [Brand identity guidelines](/wiki/Brand_identity_guidelines)\n\n</div>\n<div class=\"wiki-main-page-panel\">\n\n# About the wiki\n\n[Sitemap](/wiki/Sitemap) • [Contribution guide](/wiki/osu!_wiki_Contribution_Guide) • [Article styling criteria](/wiki/Article_Styling_Criteria) • [News styling criteria](/wiki/News_Styling_Criteria)\n\n</div>\n</div>\n";
|
||||
}
|
||||
}
|
104
osu.Game/Overlays/Wiki/WikiMainPage.cs
Normal file
104
osu.Game/Overlays/Wiki/WikiMainPage.cs
Normal file
@ -0,0 +1,104 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using HtmlAgilityPack;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
|
||||
namespace osu.Game.Overlays.Wiki
|
||||
{
|
||||
public class WikiMainPage : FillFlowContainer
|
||||
{
|
||||
public string Markdown;
|
||||
|
||||
public WikiMainPage()
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
AutoSizeAxes = Axes.Y;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
var html = new HtmlDocument();
|
||||
html.LoadHtml(Markdown);
|
||||
|
||||
var panels = createPanels(html).ToArray();
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
createBlurb(html),
|
||||
new GridContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
RowDimensions = Enumerable.Repeat(new Dimension(GridSizeMode.AutoSize), panels.Length).ToArray(),
|
||||
Content = panels,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
private Container createBlurb(HtmlDocument html)
|
||||
{
|
||||
var blurbNode = html.DocumentNode.SelectSingleNode("//div[contains(@class, 'wiki-main-page__blurb')]");
|
||||
|
||||
return new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Padding = new MarginPadding
|
||||
{
|
||||
Vertical = 30,
|
||||
},
|
||||
Child = new OsuSpriteText
|
||||
{
|
||||
Text = blurbNode.InnerText,
|
||||
Font = OsuFont.GetFont(size: 12),
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private IEnumerable<Drawable[]> createPanels(HtmlDocument html)
|
||||
{
|
||||
var panelsNode = html.DocumentNode.SelectNodes("//div[contains(@class, 'wiki-main-page-panel')]").ToArray();
|
||||
|
||||
Debug.Assert(panelsNode.Length > 1);
|
||||
|
||||
var i = 0;
|
||||
|
||||
while (i < panelsNode.Length)
|
||||
{
|
||||
var isFullWidth = panelsNode[i].HasClass("wiki-main-page-panel--full");
|
||||
|
||||
if (isFullWidth)
|
||||
{
|
||||
yield return new Drawable[]
|
||||
{
|
||||
new WikiPanelContainer(panelsNode[i++].InnerText, true)
|
||||
{
|
||||
// This is required to fill up the space of "null" drawable below.
|
||||
Width = 2,
|
||||
},
|
||||
null,
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return new Drawable[]
|
||||
{
|
||||
new WikiPanelContainer(panelsNode[i++].InnerText),
|
||||
i < panelsNode.Length ? new WikiPanelContainer(panelsNode[i++].InnerText) : null,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
125
osu.Game/Overlays/Wiki/WikiPanelContainer.cs
Normal file
125
osu.Game/Overlays/Wiki/WikiPanelContainer.cs
Normal file
@ -0,0 +1,125 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using Markdig.Syntax;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Containers.Markdown;
|
||||
using osu.Framework.Graphics.Effects;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers.Markdown;
|
||||
using osu.Game.Overlays.Wiki.Markdown;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Overlays.Wiki
|
||||
{
|
||||
public class WikiPanelContainer : Container
|
||||
{
|
||||
private WikiPanelMarkdownContainer panelContainer;
|
||||
|
||||
private readonly string text;
|
||||
|
||||
private readonly bool isFullWidth;
|
||||
|
||||
public WikiPanelContainer(string text, bool isFullWidth = false)
|
||||
{
|
||||
this.text = text;
|
||||
this.isFullWidth = isFullWidth;
|
||||
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Padding = new MarginPadding(3);
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OverlayColourProvider colourProvider)
|
||||
{
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Masking = true,
|
||||
CornerRadius = 4,
|
||||
EdgeEffect = new EdgeEffectParameters
|
||||
{
|
||||
Type = EdgeEffectType.Shadow,
|
||||
Colour = Color4.Black.Opacity(25),
|
||||
Offset = new Vector2(0, 1),
|
||||
Radius = 3,
|
||||
},
|
||||
Child = new Box
|
||||
{
|
||||
Colour = colourProvider.Background4,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
},
|
||||
panelContainer = new WikiPanelMarkdownContainer(isFullWidth)
|
||||
{
|
||||
Text = text,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
Height = Math.Max(panelContainer.Height, Parent.DrawHeight);
|
||||
}
|
||||
|
||||
private class WikiPanelMarkdownContainer : WikiMarkdownContainer
|
||||
{
|
||||
private readonly bool isFullWidth;
|
||||
|
||||
public WikiPanelMarkdownContainer(bool isFullWidth)
|
||||
{
|
||||
this.isFullWidth = isFullWidth;
|
||||
|
||||
LineSpacing = 0;
|
||||
DocumentPadding = new MarginPadding(30);
|
||||
DocumentMargin = new MarginPadding(0);
|
||||
}
|
||||
|
||||
public override SpriteText CreateSpriteText() => base.CreateSpriteText().With(t => t.Font = t.Font.With(weight: FontWeight.Bold));
|
||||
|
||||
public override MarkdownTextFlowContainer CreateTextFlow() => base.CreateTextFlow().With(f => f.TextAnchor = Anchor.TopCentre);
|
||||
|
||||
protected override MarkdownParagraph CreateParagraph(ParagraphBlock paragraphBlock, int level)
|
||||
=> base.CreateParagraph(paragraphBlock, level).With(p => p.Margin = new MarginPadding { Bottom = 10 });
|
||||
|
||||
protected override MarkdownHeading CreateHeading(HeadingBlock headingBlock) => new WikiPanelHeading(headingBlock)
|
||||
{
|
||||
IsFullWidth = isFullWidth,
|
||||
};
|
||||
}
|
||||
|
||||
private class WikiPanelHeading : OsuMarkdownHeading
|
||||
{
|
||||
public bool IsFullWidth;
|
||||
|
||||
public WikiPanelHeading(HeadingBlock headingBlock)
|
||||
: base(headingBlock)
|
||||
{
|
||||
Margin = new MarginPadding { Bottom = 40 };
|
||||
}
|
||||
|
||||
public override MarkdownTextFlowContainer CreateTextFlow() => base.CreateTextFlow().With(f =>
|
||||
{
|
||||
f.Anchor = Anchor.TopCentre;
|
||||
f.Origin = Anchor.TopCentre;
|
||||
f.TextAnchor = Anchor.TopCentre;
|
||||
});
|
||||
|
||||
protected override FontWeight GetFontWeightByLevel(int level) => FontWeight.Light;
|
||||
|
||||
protected override float GetFontSizeByLevel(int level) => base.GetFontSizeByLevel(IsFullWidth ? level : 3);
|
||||
}
|
||||
}
|
||||
}
|
@ -19,6 +19,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup Label="Package References">
|
||||
<PackageReference Include="DiffPlex" Version="1.7.0" />
|
||||
<PackageReference Include="HtmlAgilityPack" Version="1.11.33" />
|
||||
<PackageReference Include="Humanizer" Version="2.8.26" />
|
||||
<PackageReference Include="MessagePack" Version="2.2.85" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="5.0.5" />
|
||||
|
Loading…
x
Reference in New Issue
Block a user