Temporarily added MudBlazor.Markdown to the solution

This is necessary due to issue https://github.com/MyNihongo/MudBlazor.Markdown/issues/247

I created a PR as well: https://github.com/MyNihongo/MudBlazor.Markdown/pull/246
This commit is contained in:
Thorsten Sommer 2024-05-03 22:59:46 +02:00
parent 6f9326a827
commit c84184e5d1
Signed by: tsommer
GPG Key ID: 371BBA77A02C0108
57 changed files with 11216 additions and 1 deletions

View File

@ -0,0 +1,152 @@
using Microsoft.AspNetCore.Components.Web;
namespace MudBlazor;
public partial class MudCodeHighlight : MudComponentBase, IDisposable
{
private ElementReference _ref;
private CodeBlockTheme _theme;
private IMudMarkdownThemeService? _themeService;
private bool _isFirstThemeSet;
/// <summary>
/// Code text to render
/// </summary>
[Parameter]
public string Text { get; set; } = string.Empty;
/// <summary>
/// Language of the <see cref="Text"/>
/// </summary>
[Parameter]
public string Language { get; set; } = string.Empty;
/// <summary>
/// Theme of the code block.<br/>
/// Browse available themes here: https://highlightjs.org/static/demo/ <br/>
/// Default is <see cref="CodeBlockTheme.Default"/>
/// </summary>
#if NET7_0
#pragma warning disable BL0007
#endif
[Parameter]
public CodeBlockTheme Theme
{
get => _theme;
set
{
if (_theme == value)
return;
_theme = value;
Task.Run(SetThemeAsync);
}
}
#if NET7_0
#pragma warning restore BL0007
#endif
[Inject]
private IJSRuntime Js { get; init; } = default!;
[Inject]
private IServiceProvider? ServiceProvider { get; init; }
public void Dispose()
{
if (_themeService != null)
_themeService.CodeBlockThemeChanged -= OnCodeBlockThemeChanged;
GC.SuppressFinalize(this);
}
protected override bool ShouldRender() =>
!string.IsNullOrEmpty(Text);
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
var i = 0;
builder.OpenElement(i++, "div");
builder.AddAttribute(i++, "class", "snippet-clipboard-content overflow-auto");
// Copy button
builder.OpenComponent<MudIconButton>(i++);
builder.AddAttribute(i++, nameof(MudIconButton.Icon), Icons.Material.Rounded.ContentCopy);
builder.AddAttribute(i++, nameof(MudIconButton.Variant), Variant.Filled);
builder.AddAttribute(i++, nameof(MudIconButton.Color), Color.Primary);
builder.AddAttribute(i++, nameof(MudIconButton.Size), Size.Medium);
builder.AddAttribute(i++, nameof(MudIconButton.Class), "snippet-clipboard-copy-icon m-2");
builder.AddAttribute(i++, nameof(MudIconButton.OnClick), EventCallback.Factory.Create<MouseEventArgs>(this, CopyTextToClipboardAsync));
builder.CloseComponent();
// Code block
builder.OpenElement(i++, "pre");
builder.OpenElement(i++, "code");
if (!string.IsNullOrEmpty(Language))
builder.AddAttribute(i++, "class", $"language-{Language}");
builder.AddElementReferenceCapture(i++, x => _ref = x);
builder.AddContent(i++, Text);
builder.CloseElement();
builder.CloseElement();
builder.CloseElement();
}
protected override void OnInitialized()
{
base.OnInitialized();
_themeService = ServiceProvider?.GetService<IMudMarkdownThemeService>();
if (_themeService != null)
_themeService.CodeBlockThemeChanged += OnCodeBlockThemeChanged;
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (!firstRender)
return;
await Js.InvokeVoidAsync("highlightCodeElement", _ref)
.ConfigureAwait(false);
if (!_isFirstThemeSet)
{
await SetThemeAsync()
.ConfigureAwait(false);
}
}
private void OnCodeBlockThemeChanged(object? sender, CodeBlockTheme e) =>
Theme = e;
private async Task SetThemeAsync()
{
var stylesheetPath = Theme.GetStylesheetPath();
await Js.InvokeVoidAsync("setHighlightStylesheet", stylesheetPath)
.ConfigureAwait(false);
_isFirstThemeSet = true;
}
private async Task CopyTextToClipboardAsync(MouseEventArgs args)
{
var ok = await Js.InvokeAsync<bool>("copyTextToClipboard", Text)
.ConfigureAwait(false);
if (ok)
return;
var clipboardService = ServiceProvider?.GetService<IMudMarkdownClipboardService>();
if (clipboardService != null)
{
await clipboardService.CopyToClipboardAsync(Text)
.ConfigureAwait(false);
}
}
}

View File

@ -0,0 +1,76 @@
namespace MudBlazor;
internal sealed class MudLinkButton : MudComponentBase
{
private string Classname =>
new CssBuilder("mud-typography mud-link")
.AddClass($"mud-{Color.ToDescriptionString()}-text")
.AddClass($"mud-link-underline-{Underline.ToDescriptionString()}")
.AddClass($"mud-typography-{Typo.ToDescriptionString()}")
.AddClass("mud-link-disabled", IsDisabled)
.AddClass(Class)
.Build();
/// <summary>
/// The color of the component. It supports the theme colors.
/// </summary>
[Parameter]
public Color Color { get; set; } = Color.Primary;
/// <summary>
/// Typography variant to use.
/// </summary>
[Parameter]
public Typo Typo { get; set; } = Typo.body1;
/// <summary>
/// Controls when the link should have an underline.
/// </summary>
[Parameter]
public Underline Underline { get; set; } = Underline.Hover;
/// <summary>
/// If true, the navlink will be disabled.
/// </summary>
[Parameter]
public bool IsDisabled { get; set; }
/// <summary>
/// Child content of component.
/// </summary>
[Parameter]
public RenderFragment? ChildContent { get; set; }
/// <summary>
/// Command executed on click
/// </summary>
[Parameter]
public ICommand? Command { get; set; }
/// <summary>
/// Parameter passed to the command
/// </summary>
[Parameter]
public object? CommandParameter { get; set; }
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
var i = 0;
builder.OpenElement(i++, "span");
builder.AddAttribute(i++, "class", Classname);
builder.AddAttribute(i++, "style", Style);
builder.AddAttribute(i++, "onclick", EventCallback.Factory.Create(this, OnClick));
builder.AddContent(i++, ChildContent);
builder.CloseElement();
}
private void OnClick()
{
if (IsDisabled)
return;
if (Command?.CanExecute(CommandParameter) ?? false)
Command.Execute(CommandParameter);
}
}

View File

@ -0,0 +1,77 @@
namespace MudBlazor;
/// <summary>
/// For some reason MudExpansionPanels eternally tried to dispose all panels, therefore, RenderFragment was called infinitely<br/>
/// Created this component in order to bypass that weird behaviour
/// </summary>
internal sealed class MudMarkdownDetails : ComponentBase
{
private int _elementIndex;
[Parameter]
public RenderFragment? TitleContent { get; set; }
[Parameter]
public RenderFragment? ChildContent { get; set; }
private bool IsExpanded { get; set; }
private string IconClasses => new CssBuilder("mud-expand-panel-icon")
.AddClass("mud-transform", IsExpanded)
.Build();
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
_elementIndex = 0;
builder.OpenElement(_elementIndex++, "div");
builder.AddAttribute(_elementIndex++, "class", "mud-expand-panel mud-elevation-1 mud-expand-panel-border");
BuildTitle(builder);
BuildContent(builder);
builder.CloseElement();
}
private void BuildTitle(RenderTreeBuilder builder)
{
builder.OpenElement(_elementIndex++, "div");
builder.AddAttribute(_elementIndex++, "class", "mud-expand-panel-header mud-ripple");
builder.AddAttribute(_elementIndex++, "onclick", EventCallback.Factory.Create(this, OnHeaderClick));
// Text
builder.OpenElement(_elementIndex++, "div");
builder.AddAttribute(_elementIndex++, "class", "mud-expand-panel-text");
builder.AddContent(_elementIndex++, TitleContent);
builder.CloseElement();
// Collapse icon
builder.OpenComponent<MudIcon>(_elementIndex++);
builder.AddAttribute(_elementIndex++, nameof(MudIcon.Icon), Icons.Material.Filled.ExpandMore);
builder.AddAttribute(_elementIndex++, "class", IconClasses);
builder.CloseComponent();
builder.CloseElement();
}
private void BuildContent(RenderTreeBuilder builder)
{
builder.OpenComponent<MudCollapse>(_elementIndex++);
builder.AddAttribute(_elementIndex++, nameof(MudCollapse.Expanded), IsExpanded);
builder.AddAttribute(_elementIndex++, nameof(MudCollapse.ChildContent), (RenderFragment)(contentBuilder =>
{
contentBuilder.OpenElement(_elementIndex++, "div");
contentBuilder.AddAttribute(_elementIndex++, "class", "mud-expand-panel-content");
contentBuilder.AddContent(_elementIndex++, ChildContent);
contentBuilder.CloseElement();
}));
builder.CloseComponent();
}
private void OnHeaderClick()
{
IsExpanded = !IsExpanded;
}
}

View File

@ -0,0 +1,64 @@
namespace MudBlazor;
internal sealed class MudMathJax : ComponentBase
{
private const string ScriptId = "mudblazor-markdown-mathjax";
[Parameter]
public string Delimiter { get; set; } = string.Empty;
[Parameter]
public StringSlice Value { get; set; }
[Inject]
private IJSRuntime Js { get; init; } = default!;
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
var elementIndex = 0;
var delimiter = GetDelimiter(Delimiter);
builder.AddContent(elementIndex++, delimiter.Start);
builder.AddContent(elementIndex++, Value);
builder.AddContent(elementIndex, delimiter.End);
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await Js.InvokeVoidAsync("appendMathJaxScript", ScriptId)
.ConfigureAwait(false);
}
await Js.InvokeVoidAsync("refreshMathJaxScript")
.ConfigureAwait(false);
}
private static MathDelimiter GetDelimiter(in string delimiter) =>
delimiter switch
{
"$" => new MathDelimiter("\\(", "\\)"),
"$$" => new MathDelimiter(delimiter),
_ => new MathDelimiter(delimiter)
};
private readonly ref struct MathDelimiter
{
public MathDelimiter(string delimiter)
{
Start = End = delimiter;
}
public MathDelimiter(string start, string end)
{
Start = start;
End = end;
}
public string Start { get; }
public string End { get; }
}
}

View File

@ -0,0 +1,247 @@
namespace MudBlazor;
public enum CodeBlockTheme : ushort
{
Default = 0,
A11yDark,
A11yLight,
Agate,
AnOldHope,
Androidstudio,
ArduinoLight,
Arta,
Ascetic,
AtomOneDarkReasonable,
AtomOneDark,
AtomOneLight,
BrownPaper,
CodepenEmbed,
ColorBrewer,
Dark,
Devibeans,
Docco,
Far,
Foundation,
GithubDarkDimmed,
GithubDark,
Github,
Gml,
Googlecode,
GradientDark,
GradientLight,
Grayscale,
Hybrid,
Idea,
IrBlack,
IsblEditorDark,
IsblEditorLight,
KimbieDark,
KimbieLight,
Lightfair,
Lioshi,
Magula,
MonoBlue,
MonokaiSublime,
Monokai,
NightOwl,
NnfxDark,
NnfxLight,
Nord,
Obsidian,
ParaisoDark,
ParaisoLight,
Pojoaque,
Purebasic,
QtcreatorDark,
QtcreatorLight,
Rainbow,
Routeros,
SchoolBook,
ShadesOfPurple,
Srcery,
StackoverflowDark,
StackoverflowLight,
Sunburst,
TomorrowNightBlue,
TomorrowNightBright,
Vs,
Vs2015,
Xcode,
Xt256,
ApathyBase16,
ApprenticeBase16,
AshesBase16,
AtelierCaveLightBase16,
AtelierCaveBase16,
AtelierDuneLightBase16,
AtelierDuneBase16,
AtelierEstuaryLightBase16,
AtelierEstuaryBase16,
AtelierForestLightBase16,
AtelierForestBase16,
AtelierHeathLightBase16,
AtelierHeathBase16,
AtelierLakesideLightBase16,
AtelierLakesideBase16,
AtelierPlateauLightBase16,
AtelierPlateauBase16,
AtelierSavannaLightBase16,
AtelierSavannaBase16,
AtelierSeasideLightBase16,
AtelierSeasideBase16,
AtelierSulphurpoolLightBase16,
AtelierSulphurpoolBase16,
AtlasBase16,
BespinBase16,
BlackMetalBathoryBase16,
BlackMetalBurzumBase16,
BlackMetalDarkFuneralBase16,
BlackMetalGorgorothBase16,
BlackMetalImmortalBase16,
BlackMetalKholdBase16,
BlackMetalMardukBase16,
BlackMetalMayhemBase16,
BlackMetalNileBase16,
BlackMetalVenomBase16,
BlackMetalBase16,
BrewerBase16,
BrightBase16,
BrogrammerBase16,
BrushTreesDarkBase16,
BrushTreesBase16,
ChalkBase16,
CircusBase16,
ClassicDarkBase16,
ClassicLightBase16,
CodeschoolBase16,
ColorsBase16,
CupcakeBase16,
CupertinoBase16,
DanqingBase16,
DarculaBase16,
DarkVioletBase16,
DarkmossBase16,
DarktoothBase16,
DecafBase16,
DefaultDarkBase16,
DefaultLightBase16,
DirtyseaBase16,
DraculaBase16,
EdgeDarkBase16,
EdgeLightBase16,
EightiesBase16,
EmbersBase16,
EquilibriumDarkBase16,
EquilibriumGrayDarkBase16,
EquilibriumGrayLightBase16,
EquilibriumLightBase16,
EspressoBase16,
EvaDimBase16,
EvaBase16,
FlatBase16,
FramerBase16,
FruitSodaBase16,
GigavoltBase16,
GithubBase16,
GoogleDarkBase16,
GoogleLightBase16,
GrayscaleDarkBase16,
GrayscaleLightBase16,
GreenScreenBase16,
GruvboxDarkHardBase16,
GruvboxDarkMediumBase16,
GruvboxDarkPaleBase16,
GruvboxDarkSoftBase16,
GruvboxLightHardBase16,
GruvboxLightMediumBase16,
GruvboxLightSoftBase16,
HardcoreBase16,
Harmonic16DarkBase16,
Harmonic16LightBase16,
HeetchDarkBase16,
HeetchLightBase16,
HeliosBase16,
HopscotchBase16,
HorizonDarkBase16,
HorizonLightBase16,
HumanoidDarkBase16,
HumanoidLightBase16,
IaDarkBase16,
IaLightBase16,
IcyDarkBase16,
IrBlackBase16,
IsotopeBase16,
KimberBase16,
LondonTubeBase16,
MacintoshBase16,
MarrakeshBase16,
MateriaBase16,
MaterialDarkerBase16,
MaterialLighterBase16,
MaterialPalenightBase16,
MaterialVividBase16,
MaterialBase16,
MellowPurpleBase16,
MexicoLightBase16,
MochaBase16,
MonokaiBase16,
NebulaBase16,
NordBase16,
NovaBase16,
OceanBase16,
OceanicnextBase16,
OneLightBase16,
OnedarkBase16,
OutrunDarkBase16,
PapercolorDarkBase16,
PapercolorLightBase16,
ParaisoBase16,
PasqueBase16,
PhdBase16,
PicoBase16,
PopBase16,
PorpleBase16,
QualiaBase16,
RailscastsBase16,
RebeccaBase16,
RosPineDawnBase16,
RosPineMoonBase16,
RosPineBase16,
SagelightBase16,
SandcastleBase16,
SetiUiBase16,
ShapeshifterBase16,
SilkDarkBase16,
SilkLightBase16,
SnazzyBase16,
SolarFlareLightBase16,
SolarFlareBase16,
SolarizedDarkBase16,
SolarizedLightBase16,
SpacemacsBase16,
SummercampBase16,
SummerfruitDarkBase16,
SummerfruitLightBase16,
SynthMidnightTerminalDarkBase16,
SynthMidnightTerminalLightBase16,
T3024Base16,
TangoBase16,
TenderBase16,
TomorrowNightBase16,
TomorrowBase16,
TwilightBase16,
UnikittyDarkBase16,
UnikittyLightBase16,
VulcanBase16,
Windows10LightBase16,
Windows10Base16,
Windows95LightBase16,
Windows95Base16,
WindowsHighContrastLightBase16,
WindowsHighContrastBase16,
WindowsNtLightBase16,
WindowsNtBase16,
WoodlandBase16,
XcodeDuskBase16,
ZenburnBase16
}

View File

@ -0,0 +1,252 @@
namespace MudBlazor;
internal static class CodeBlockThemeEx
{
public static string GetStylesheetPath(this CodeBlockTheme @this) =>
@this switch
{
CodeBlockTheme.A11yDark => "a11y-dark.min.css",
CodeBlockTheme.A11yLight => "a11y-light.min.css",
CodeBlockTheme.Agate => "agate.min.css",
CodeBlockTheme.AnOldHope => "an-old-hope.min.css",
CodeBlockTheme.Androidstudio => "androidstudio.min.css",
CodeBlockTheme.ArduinoLight => "arduino-light.min.css",
CodeBlockTheme.Arta => "arta.min.css",
CodeBlockTheme.Ascetic => "ascetic.min.css",
CodeBlockTheme.AtomOneDarkReasonable => "atom-one-dark-reasonable.min.css",
CodeBlockTheme.AtomOneDark => "atom-one-dark.min.css",
CodeBlockTheme.AtomOneLight => "atom-one-light.min.css",
CodeBlockTheme.BrownPaper => "brown-paper.min.css",
CodeBlockTheme.CodepenEmbed => "codepen-embed.min.css",
CodeBlockTheme.ColorBrewer => "color-brewer.min.css",
CodeBlockTheme.Dark => "dark.min.css",
CodeBlockTheme.Default => "default.min.css",
CodeBlockTheme.Devibeans => "devibeans.min.css",
CodeBlockTheme.Docco => "docco.min.css",
CodeBlockTheme.Far => "far.min.css",
CodeBlockTheme.Foundation => "foundation.min.css",
CodeBlockTheme.GithubDarkDimmed => "github-dark-dimmed.min.css",
CodeBlockTheme.GithubDark => "github-dark.min.css",
CodeBlockTheme.Github => "github.min.css",
CodeBlockTheme.Gml => "gml.min.css",
CodeBlockTheme.Googlecode => "googlecode.min.css",
CodeBlockTheme.GradientDark => "gradient-dark.min.css",
CodeBlockTheme.GradientLight => "gradient-light.min.css",
CodeBlockTheme.Grayscale => "grayscale.min.css",
CodeBlockTheme.Hybrid => "hybrid.min.css",
CodeBlockTheme.Idea => "idea.min.css",
CodeBlockTheme.IrBlack => "ir-black.min.css",
CodeBlockTheme.IsblEditorDark => "isbl-editor-dark.min.css",
CodeBlockTheme.IsblEditorLight => "isbl-editor-light.min.css",
CodeBlockTheme.KimbieDark => "kimbie-dark.min.css",
CodeBlockTheme.KimbieLight => "kimbie-light.min.css",
CodeBlockTheme.Lightfair => "lightfair.min.css",
CodeBlockTheme.Lioshi => "lioshi.min.css",
CodeBlockTheme.Magula => "magula.min.css",
CodeBlockTheme.MonoBlue => "mono-blue.min.css",
CodeBlockTheme.MonokaiSublime => "monokai-sublime.min.css",
CodeBlockTheme.Monokai => "monokai.min.css",
CodeBlockTheme.NightOwl => "night-owl.min.css",
CodeBlockTheme.NnfxDark => "nnfx-dark.min.css",
CodeBlockTheme.NnfxLight => "nnfx-light.min.css",
CodeBlockTheme.Nord => "nord.min.css",
CodeBlockTheme.Obsidian => "obsidian.min.css",
CodeBlockTheme.ParaisoDark => "paraiso-dark.min.css",
CodeBlockTheme.ParaisoLight => "paraiso-light.min.css",
CodeBlockTheme.Pojoaque => "pojoaque.min.css",
CodeBlockTheme.Purebasic => "purebasic.min.css",
CodeBlockTheme.QtcreatorDark => "qtcreator-dark.min.css",
CodeBlockTheme.QtcreatorLight => "qtcreator-light.min.css",
CodeBlockTheme.Rainbow => "rainbow.min.css",
CodeBlockTheme.Routeros => "routeros.min.css",
CodeBlockTheme.SchoolBook => "school-book.min.css",
CodeBlockTheme.ShadesOfPurple => "shades-of-purple.min.css",
CodeBlockTheme.Srcery => "srcery.min.css",
CodeBlockTheme.StackoverflowDark => "stackoverflow-dark.min.css",
CodeBlockTheme.StackoverflowLight => "stackoverflow-light.min.css",
CodeBlockTheme.Sunburst => "sunburst.min.css",
CodeBlockTheme.TomorrowNightBlue => "tomorrow-night-blue.min.css",
CodeBlockTheme.TomorrowNightBright => "tomorrow-night-bright.min.css",
CodeBlockTheme.Vs => "vs.min.css",
CodeBlockTheme.Vs2015 => "vs2015.min.css",
CodeBlockTheme.Xcode => "xcode.min.css",
CodeBlockTheme.Xt256 => "xt256.min.css",
CodeBlockTheme.ApathyBase16 => "base16/apathy.min.css",
CodeBlockTheme.ApprenticeBase16 => "base16/apprentice.min.css",
CodeBlockTheme.AshesBase16 => "base16/ashes.min.css",
CodeBlockTheme.AtelierCaveLightBase16 => "base16/atelier-cave-light.min.css",
CodeBlockTheme.AtelierCaveBase16 => "base16/atelier-cave.min.css",
CodeBlockTheme.AtelierDuneLightBase16 => "base16/atelier-dune-light.min.css",
CodeBlockTheme.AtelierDuneBase16 => "base16/atelier-dune.min.css",
CodeBlockTheme.AtelierEstuaryLightBase16 => "base16/atelier-estuary-light.min.css",
CodeBlockTheme.AtelierEstuaryBase16 => "base16/atelier-estuary.min.css",
CodeBlockTheme.AtelierForestLightBase16 => "base16/atelier-forest-light.min.css",
CodeBlockTheme.AtelierForestBase16 => "base16/atelier-forest.min.css",
CodeBlockTheme.AtelierHeathLightBase16 => "base16/atelier-heath-light.min.css",
CodeBlockTheme.AtelierHeathBase16 => "base16/atelier-heath.min.css",
CodeBlockTheme.AtelierLakesideLightBase16 => "base16/atelier-lakeside-light.min.css",
CodeBlockTheme.AtelierLakesideBase16 => "base16/atelier-lakeside.min.css",
CodeBlockTheme.AtelierPlateauLightBase16 => "base16/atelier-plateau-light.min.css",
CodeBlockTheme.AtelierPlateauBase16 => "base16/atelier-plateau.min.css",
CodeBlockTheme.AtelierSavannaLightBase16 => "base16/atelier-savanna-light.min.css",
CodeBlockTheme.AtelierSavannaBase16 => "base16/atelier-savanna.min.css",
CodeBlockTheme.AtelierSeasideLightBase16 => "base16/atelier-seaside-light.min.css",
CodeBlockTheme.AtelierSeasideBase16 => "base16/atelier-seaside.min.css",
CodeBlockTheme.AtelierSulphurpoolLightBase16 => "base16/atelier-sulphurpool-light.min.css",
CodeBlockTheme.AtelierSulphurpoolBase16 => "base16/atelier-sulphurpool.min.css",
CodeBlockTheme.AtlasBase16 => "base16/atlas.min.css",
CodeBlockTheme.BespinBase16 => "base16/bespin.min.css",
CodeBlockTheme.BlackMetalBathoryBase16 => "base16/black-metal-bathory.min.css",
CodeBlockTheme.BlackMetalBurzumBase16 => "base16/black-metal-burzum.min.css",
CodeBlockTheme.BlackMetalDarkFuneralBase16 => "base16/black-metal-dark-funeral.min.css",
CodeBlockTheme.BlackMetalGorgorothBase16 => "base16/black-metal-gorgoroth.min.css",
CodeBlockTheme.BlackMetalImmortalBase16 => "base16/black-metal-immortal.min.css",
CodeBlockTheme.BlackMetalKholdBase16 => "base16/black-metal-khold.min.css",
CodeBlockTheme.BlackMetalMardukBase16 => "base16/black-metal-marduk.min.css",
CodeBlockTheme.BlackMetalMayhemBase16 => "base16/black-metal-mayhem.min.css",
CodeBlockTheme.BlackMetalNileBase16 => "base16/black-metal-nile.min.css",
CodeBlockTheme.BlackMetalVenomBase16 => "base16/black-metal-venom.min.css",
CodeBlockTheme.BlackMetalBase16 => "base16/black-metal.min.css",
CodeBlockTheme.BrewerBase16 => "base16/brewer.min.css",
CodeBlockTheme.BrightBase16 => "base16/bright.min.css",
CodeBlockTheme.BrogrammerBase16 => "base16/brogrammer.min.css",
CodeBlockTheme.BrushTreesDarkBase16 => "base16/brush-trees-dark.min.css",
CodeBlockTheme.BrushTreesBase16 => "base16/brush-trees.min.css",
CodeBlockTheme.ChalkBase16 => "base16/chalk.min.css",
CodeBlockTheme.CircusBase16 => "base16/circus.min.css",
CodeBlockTheme.ClassicDarkBase16 => "base16/classic-dark.min.css",
CodeBlockTheme.ClassicLightBase16 => "base16/classic-light.min.css",
CodeBlockTheme.CodeschoolBase16 => "base16/codeschool.min.css",
CodeBlockTheme.ColorsBase16 => "base16/colors.min.css",
CodeBlockTheme.CupcakeBase16 => "base16/cupcake.min.css",
CodeBlockTheme.CupertinoBase16 => "base16/cupertino.min.css",
CodeBlockTheme.DanqingBase16 => "base16/danqing.min.css",
CodeBlockTheme.DarculaBase16 => "base16/darcula.min.css",
CodeBlockTheme.DarkVioletBase16 => "base16/dark-violet.min.css",
CodeBlockTheme.DarkmossBase16 => "base16/darkmoss.min.css",
CodeBlockTheme.DarktoothBase16 => "base16/darktooth.min.css",
CodeBlockTheme.DecafBase16 => "base16/decaf.min.css",
CodeBlockTheme.DefaultDarkBase16 => "base16/default-dark.min.css",
CodeBlockTheme.DefaultLightBase16 => "base16/default-light.min.css",
CodeBlockTheme.DirtyseaBase16 => "base16/dirtysea.min.css",
CodeBlockTheme.DraculaBase16 => "base16/dracula.min.css",
CodeBlockTheme.EdgeDarkBase16 => "base16/edge-dark.min.css",
CodeBlockTheme.EdgeLightBase16 => "base16/edge-light.min.css",
CodeBlockTheme.EightiesBase16 => "base16/eighties.min.css",
CodeBlockTheme.EmbersBase16 => "base16/embers.min.css",
CodeBlockTheme.EquilibriumDarkBase16 => "base16/equilibrium-dark.min.css",
CodeBlockTheme.EquilibriumGrayDarkBase16 => "base16/equilibrium-gray-dark.min.css",
CodeBlockTheme.EquilibriumGrayLightBase16 => "base16/equilibrium-gray-light.min.css",
CodeBlockTheme.EquilibriumLightBase16 => "base16/equilibrium-light.min.css",
CodeBlockTheme.EspressoBase16 => "base16/espresso.min.css",
CodeBlockTheme.EvaDimBase16 => "base16/eva-dim.min.css",
CodeBlockTheme.EvaBase16 => "base16/eva.min.css",
CodeBlockTheme.FlatBase16 => "base16/flat.min.css",
CodeBlockTheme.FramerBase16 => "base16/framer.min.css",
CodeBlockTheme.FruitSodaBase16 => "base16/fruit-soda.min.css",
CodeBlockTheme.GigavoltBase16 => "base16/gigavolt.min.css",
CodeBlockTheme.GithubBase16 => "base16/github.min.css",
CodeBlockTheme.GoogleDarkBase16 => "base16/google-dark.min.css",
CodeBlockTheme.GoogleLightBase16 => "base16/google-light.min.css",
CodeBlockTheme.GrayscaleDarkBase16 => "base16/grayscale-dark.min.css",
CodeBlockTheme.GrayscaleLightBase16 => "base16/grayscale-light.min.css",
CodeBlockTheme.GreenScreenBase16 => "base16/green-screen.min.css",
CodeBlockTheme.GruvboxDarkHardBase16 => "base16/gruvbox-dark-hard.min.css",
CodeBlockTheme.GruvboxDarkMediumBase16 => "base16/gruvbox-dark-medium.min.css",
CodeBlockTheme.GruvboxDarkPaleBase16 => "base16/gruvbox-dark-pale.min.css",
CodeBlockTheme.GruvboxDarkSoftBase16 => "base16/gruvbox-dark-soft.min.css",
CodeBlockTheme.GruvboxLightHardBase16 => "base16/gruvbox-light-hard.min.css",
CodeBlockTheme.GruvboxLightMediumBase16 => "base16/gruvbox-light-medium.min.css",
CodeBlockTheme.GruvboxLightSoftBase16 => "base16/gruvbox-light-soft.min.css",
CodeBlockTheme.HardcoreBase16 => "base16/hardcore.min.css",
CodeBlockTheme.Harmonic16DarkBase16 => "base16/harmonic16-dark.min.css",
CodeBlockTheme.Harmonic16LightBase16 => "base16/harmonic16-light.min.css",
CodeBlockTheme.HeetchDarkBase16 => "base16/heetch-dark.min.css",
CodeBlockTheme.HeetchLightBase16 => "base16/heetch-light.min.css",
CodeBlockTheme.HeliosBase16 => "base16/helios.min.css",
CodeBlockTheme.HopscotchBase16 => "base16/hopscotch.min.css",
CodeBlockTheme.HorizonDarkBase16 => "base16/horizon-dark.min.css",
CodeBlockTheme.HorizonLightBase16 => "base16/horizon-light.min.css",
CodeBlockTheme.HumanoidDarkBase16 => "base16/humanoid-dark.min.css",
CodeBlockTheme.HumanoidLightBase16 => "base16/humanoid-light.min.css",
CodeBlockTheme.IaDarkBase16 => "base16/ia-dark.min.css",
CodeBlockTheme.IaLightBase16 => "base16/ia-light.min.css",
CodeBlockTheme.IcyDarkBase16 => "base16/icy-dark.min.css",
CodeBlockTheme.IrBlackBase16 => "base16/ir-black.min.css",
CodeBlockTheme.IsotopeBase16 => "base16/isotope.min.css",
CodeBlockTheme.KimberBase16 => "base16/kimber.min.css",
CodeBlockTheme.LondonTubeBase16 => "base16/london-tube.min.css",
CodeBlockTheme.MacintoshBase16 => "base16/macintosh.min.css",
CodeBlockTheme.MarrakeshBase16 => "base16/marrakesh.min.css",
CodeBlockTheme.MateriaBase16 => "base16/materia.min.css",
CodeBlockTheme.MaterialDarkerBase16 => "base16/material-darker.min.css",
CodeBlockTheme.MaterialLighterBase16 => "base16/material-lighter.min.css",
CodeBlockTheme.MaterialPalenightBase16 => "base16/material-palenight.min.css",
CodeBlockTheme.MaterialVividBase16 => "base16/material-vivid.min.css",
CodeBlockTheme.MaterialBase16 => "base16/material.min.css",
CodeBlockTheme.MellowPurpleBase16 => "base16/mellow-purple.min.css",
CodeBlockTheme.MexicoLightBase16 => "base16/mexico-light.min.css",
CodeBlockTheme.MochaBase16 => "base16/mocha.min.css",
CodeBlockTheme.MonokaiBase16 => "base16/monokai.min.css",
CodeBlockTheme.NebulaBase16 => "base16/nebula.min.css",
CodeBlockTheme.NordBase16 => "base16/nord.min.css",
CodeBlockTheme.NovaBase16 => "base16/nova.min.css",
CodeBlockTheme.OceanBase16 => "base16/ocean.min.css",
CodeBlockTheme.OceanicnextBase16 => "base16/oceanicnext.min.css",
CodeBlockTheme.OneLightBase16 => "base16/one-light.min.css",
CodeBlockTheme.OnedarkBase16 => "base16/onedark.min.css",
CodeBlockTheme.OutrunDarkBase16 => "base16/outrun-dark.min.css",
CodeBlockTheme.PapercolorDarkBase16 => "base16/papercolor-dark.min.css",
CodeBlockTheme.PapercolorLightBase16 => "base16/papercolor-light.min.css",
CodeBlockTheme.ParaisoBase16 => "base16/paraiso.min.css",
CodeBlockTheme.PasqueBase16 => "base16/pasque.min.css",
CodeBlockTheme.PhdBase16 => "base16/phd.min.css",
CodeBlockTheme.PicoBase16 => "base16/pico.min.css",
CodeBlockTheme.PopBase16 => "base16/pop.min.css",
CodeBlockTheme.PorpleBase16 => "base16/porple.min.css",
CodeBlockTheme.QualiaBase16 => "base16/qualia.min.css",
CodeBlockTheme.RailscastsBase16 => "base16/railscasts.min.css",
CodeBlockTheme.RebeccaBase16 => "base16/rebecca.min.css",
CodeBlockTheme.RosPineDawnBase16 => "base16/ros-pine-dawn.min.css",
CodeBlockTheme.RosPineMoonBase16 => "base16/ros-pine-moon.min.css",
CodeBlockTheme.RosPineBase16 => "base16/ros-pine.min.css",
CodeBlockTheme.SagelightBase16 => "base16/sagelight.min.css",
CodeBlockTheme.SandcastleBase16 => "base16/sandcastle.min.css",
CodeBlockTheme.SetiUiBase16 => "base16/seti-ui.min.css",
CodeBlockTheme.ShapeshifterBase16 => "base16/shapeshifter.min.css",
CodeBlockTheme.SilkDarkBase16 => "base16/silk-dark.min.css",
CodeBlockTheme.SilkLightBase16 => "base16/silk-light.min.css",
CodeBlockTheme.SnazzyBase16 => "base16/snazzy.min.css",
CodeBlockTheme.SolarFlareLightBase16 => "base16/solar-flare-light.min.css",
CodeBlockTheme.SolarFlareBase16 => "base16/solar-flare.min.css",
CodeBlockTheme.SolarizedDarkBase16 => "base16/solarized-dark.min.css",
CodeBlockTheme.SolarizedLightBase16 => "base16/solarized-light.min.css",
CodeBlockTheme.SpacemacsBase16 => "base16/spacemacs.min.css",
CodeBlockTheme.SummercampBase16 => "base16/summercamp.min.css",
CodeBlockTheme.SummerfruitDarkBase16 => "base16/summerfruit-dark.min.css",
CodeBlockTheme.SummerfruitLightBase16 => "base16/summerfruit-light.min.css",
CodeBlockTheme.SynthMidnightTerminalDarkBase16 => "base16/synth-midnight-terminal-dark.min.css",
CodeBlockTheme.SynthMidnightTerminalLightBase16 => "base16/synth-midnight-terminal-light.min.css",
CodeBlockTheme.T3024Base16 => "base16/t3024.min.css",
CodeBlockTheme.TangoBase16 => "base16/tango.min.css",
CodeBlockTheme.TenderBase16 => "base16/tender.min.css",
CodeBlockTheme.TomorrowNightBase16 => "base16/tomorrow-night.min.css",
CodeBlockTheme.TomorrowBase16 => "base16/tomorrow.min.css",
CodeBlockTheme.TwilightBase16 => "base16/twilight.min.css",
CodeBlockTheme.UnikittyDarkBase16 => "base16/unikitty-dark.min.css",
CodeBlockTheme.UnikittyLightBase16 => "base16/unikitty-light.min.css",
CodeBlockTheme.VulcanBase16 => "base16/vulcan.min.css",
CodeBlockTheme.Windows10LightBase16 => "base16/windows-10-light.min.css",
CodeBlockTheme.Windows10Base16 => "base16/windows-10.min.css",
CodeBlockTheme.Windows95LightBase16 => "base16/windows-95-light.min.css",
CodeBlockTheme.Windows95Base16 => "base16/windows-95.min.css",
CodeBlockTheme.WindowsHighContrastLightBase16 => "base16/windows-high-contrast-light.min.css",
CodeBlockTheme.WindowsHighContrastBase16 => "base16/windows-high-contrast.min.css",
CodeBlockTheme.WindowsNtLightBase16 => "base16/windows-nt-light.min.css",
CodeBlockTheme.WindowsNtBase16 => "base16/windows-nt.min.css",
CodeBlockTheme.WoodlandBase16 => "base16/woodland.min.css",
CodeBlockTheme.XcodeDuskBase16 => "base16/xcode-dusk.min.css",
CodeBlockTheme.ZenburnBase16 => "base16/zenburn.min.css",
_ => string.Empty
};
}

View File

@ -0,0 +1,25 @@
using Markdig.Syntax.Inlines;
namespace MudBlazor;
internal static class EmphasisInlineEx
{
public static bool TryGetEmphasisElement(this EmphasisInline emphasis, out string value)
{
const string italics = "i", bold = "b";
value = emphasis.DelimiterChar switch
{
'*' => emphasis.DelimiterCount switch
{
1 => italics,
2 => bold,
_ => string.Empty
},
'_' => italics,
_ => string.Empty
};
return !string.IsNullOrEmpty(value);
}
}

View File

@ -0,0 +1,30 @@
using System.Text;
using Markdig.Syntax;
namespace MudBlazor;
internal static class FencedCodeBlockEx
{
public static string CreateCodeBlockText(this FencedCodeBlock @this)
{
if (@this.Lines.Count == 0)
return string.Empty;
var sb = new StringBuilder();
foreach (var line in @this.Lines)
{
var str = line.ToString();
if (string.IsNullOrEmpty(str))
continue;
if (sb.Length != 0)
sb.AppendLine();
sb.Append(str);
}
return sb.ToString();
}
}

View File

@ -0,0 +1,45 @@
using Markdig.Helpers;
using Markdig.Syntax;
using Markdig.Syntax.Inlines;
namespace MudBlazor;
internal static class HeadingBlockEx
{
private const char JoinChar = '-';
private static readonly string[] EscapeChars = { "+", ":", "&" };
public static string? BuildIdString(this HeadingBlock @this)
{
if (@this.Inline == null)
return null;
var slices = @this.Inline
.Select(static x => x.GetStringContent())
.Where(static x => x.Length > 0);
return string.Join(JoinChar, slices);
}
private static string GetStringContent(this Inline @this)
{
var slice = @this switch
{
LiteralInline x => x.Content,
_ => StringSlice.Empty
};
return PrepareStringContent(slice.ToString());
}
private static string PrepareStringContent(this string @this)
{
var words = @this.Split(' ', StringSplitOptions.RemoveEmptyEntries);
var str = string.Join(JoinChar, words).ToLower();
for (var i = 0; i < EscapeChars.Length; i++)
str = str.Replace(EscapeChars[i], string.Empty);
return str;
}
}

View File

@ -0,0 +1,25 @@
using Markdig.Syntax;
namespace MudBlazor;
internal static class HtmlBlockEx
{
public static bool TryGetDetails(this HtmlBlock @this, out HtmlDetailsData htmlDetailsData)
{
htmlDetailsData = new HtmlDetailsData();
// Closing `>` for <details> is missing because there might be attributes for this tag
if (!@this.Lines.StartsAndEndsWith("<details", "</details>", out var range))
return false;
// Closing `>` for <summary> is missing because there might be attributes for this tag
var summaryEndIndex = @this.Lines.TryGetContent("<summary", "</summary>", range.Start, out var headerContent);
if (summaryEndIndex.Line == -1)
return false;
var dataContent = @this.Lines.GetContent(summaryEndIndex, range.End);
htmlDetailsData = new HtmlDetailsData(headerContent, dataContent);
return true;
}
}

View File

@ -0,0 +1,13 @@
using Markdig.Extensions.Mathematics;
namespace MudBlazor;
internal static class MathInlineEx
{
public static string GetDelimiter(this MathInline @this) =>
string.Create(@this.DelimiterCount, @this.Delimiter, static (span, c) =>
{
for (var i = 0; i < span.Length; i++)
span[i] = c;
});
}

View File

@ -0,0 +1,28 @@
namespace MudBlazor;
internal static class StringEx
{
public static bool IsExternalUri(this string? @this, string? baseUri)
{
if (string.IsNullOrEmpty(@this) || string.IsNullOrEmpty(baseUri))
return false;
try
{
var uri = new Uri(@this, UriKind.RelativeOrAbsolute);
return uri.IsAbsoluteUri && !@this.StartsWith(baseUri);
}
catch
{
return false;
}
}
public static int ParseOrDefault(this string? @this)
{
if (!int.TryParse(@this, out var intValue))
intValue = 0;
return intValue;
}
}

View File

@ -0,0 +1,27 @@
namespace MudBlazor;
internal static class StringLineEx
{
public static int IndexOf(this StringLine @this, string value, int startIndex = 0)
{
const int notFoundIndex = -1;
if (@this.Slice.Length < value.Length)
return notFoundIndex;
for (var i = startIndex; i <= @this.Slice.Length - value.Length; i++)
{
var j = 0;
for (; j < value.Length; j++)
{
if (@this.Slice[@this.Position + i + j] != value[j])
break;
}
if (j == value.Length)
return i;
}
return notFoundIndex;
}
}

View File

@ -0,0 +1,131 @@
using System.Text;
namespace MudBlazor;
internal static class StringLineGroupEx
{
public static bool StartsAndEndsWith(this StringLineGroup @this, in string startsWith, in string endsWith, out StringLineGroupRange range)
{
range = new StringLineGroupRange();
if (@this.Count == 0)
return false;
const int firstLineIndex = 0;
var lastLineIndex = @this.Count - 1;
// Starts with
var firstLine = @this.Lines[firstLineIndex];
if (firstLine.Slice.Length < startsWith.Length)
return false;
var startIndex = 0;
for (;startIndex < startsWith.Length; startIndex++)
if (firstLine.Slice[firstLine.Position + startIndex] != startsWith[startIndex])
return false;
// Ends with
var lastLine = @this.Lines[lastLineIndex];
if (lastLine.Slice.Length < endsWith.Length)
return false;
var endIndex = lastLine.Slice.Length - 1;
for (var i = endsWith.Length - 1; i >= 0; i--, endIndex--)
if (endsWith[i] != lastLine.Slice[lastLine.Position + endIndex])
return false;
range = new StringLineGroupRange(
new StringLineGroupIndex(firstLineIndex, startIndex),
new StringLineGroupIndex(lastLineIndex, endIndex));
return true;
}
public static StringLineGroupIndex TryGetContent(this StringLineGroup @this, in string startsWith, in string endsWith, in StringLineGroupIndex startIndex, out string content)
{
var endIndex = new StringLineGroupIndex(-1, -1);
var isFound = false;
var stringBuilder = new StringBuilder();
for (var i = startIndex.Line; i < @this.Count; i++)
{
for (var j = i == startIndex.Line ? startIndex.Index : 0; j < @this.Lines[i].Slice.Length; j++)
{
if (!isFound)
{
var start = @this.Lines[i].IndexOf(startsWith);
if (start == -1)
continue;
isFound = true;
j = @this.Lines[i].IndexOf(">", start);
}
else
{
var end = @this.Lines[i].IndexOf(endsWith);
if (end == -1)
{
var strValue = @this.Lines[i].ToString().Trim();
stringBuilder.Append(strValue);
break;
}
else
{
var strValue = @this.Lines[i].Slice.AsSpan()[j..end].ToString().Trim();
stringBuilder.Append(strValue);
endIndex = new StringLineGroupIndex(i, end + endsWith.Length);
goto Return;
}
}
}
}
Return:
content = stringBuilder.ToString();
return endIndex;
}
public static string GetContent(this StringLineGroup @this, in StringLineGroupIndex startIndex, in StringLineGroupIndex endIndex)
{
var stringBuilder = new StringBuilder();
for (var i = startIndex.Line; i <= endIndex.Line; i++)
{
if (i == startIndex.Line)
{
if (i == endIndex.Line)
{
var strValue = @this.Lines[i].Slice.AsSpan()[startIndex.Index..endIndex.Index].ToString().Trim();
stringBuilder.Append(strValue);
break;
}
else
{
var strValue = @this.Lines[i].Slice.AsSpan()[startIndex.Index..].ToString().Trim();
stringBuilder.Append(strValue);
}
}
else if (i == endIndex.Line)
{
if (endIndex.Index == -1)
break;
var strValue = @this.Lines[i].Slice.AsSpan()[..endIndex.Index].ToString().Trim();
stringBuilder.Append(strValue);
}
else
{
if (stringBuilder.Length != 0)
stringBuilder.AppendLine();
var strValue = @this.Lines[i].ToString().Trim();
stringBuilder.Append(strValue);
}
}
return stringBuilder.ToString();
}
}

View File

@ -0,0 +1,24 @@
namespace MudBlazor;
public sealed class MudMarkdownStyling
{
public TableStyling Table { get; } = new();
public sealed class TableStyling
{
/// <summary>
/// If true, striped table rows will be used.
/// </summary>
public bool IsStriped { get; set; } = true;
/// <summary>
/// If true, table's cells will have left/right borders.
/// </summary>
public bool IsBordered { get; set; } = true;
/// <summary>
/// Child content of component.
/// </summary>
public int Elevation { set; get; } = 1;
}
}

View File

@ -0,0 +1,14 @@
namespace MudBlazor;
internal readonly ref struct HtmlDetailsData
{
public HtmlDetailsData(string header, string content)
{
Header = header;
Content = content;
}
public string Header { get; }
public string Content { get; }
}

View File

@ -0,0 +1,14 @@
namespace MudBlazor;
internal readonly ref struct StringLineGroupIndex
{
public StringLineGroupIndex(int line, int index)
{
Line = line;
Index = index;
}
public int Line { get; }
public int Index { get; }
}

View File

@ -0,0 +1,14 @@
namespace MudBlazor;
internal readonly ref struct StringLineGroupRange
{
public StringLineGroupRange(StringLineGroupIndex start, StringLineGroupIndex end)
{
Start = start;
End = end;
}
public StringLineGroupIndex Start { get; }
public StringLineGroupIndex End { get; }
}

View File

@ -0,0 +1,47 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<RootNamespace>MudBlazor</RootNamespace>
<Version>0.1.3</Version>
<Authors>MyNihongo</Authors>
<Description>Markdown component for MudBlazor (https://mudblazor.com/)</Description>
<Copyright>Copyright © 2023 MyNihongo</Copyright>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<RepositoryUrl>https://github.com/MyNihongo/MudBlazor.Markdown</RepositoryUrl>
<PackageProjectUrl>https://mudblazor.com/</PackageProjectUrl>
<PackageIcon>favico.png</PackageIcon>
<PackageTags>mudblazor, blazor, markdown</PackageTags>
<GeneratePackageOnBuild Condition="'$(Configuration)'=='Release'">true</GeneratePackageOnBuild>
<PackageReleaseNotes>https://github.com/MyNihongo/MudBlazor.Markdown/releases</PackageReleaseNotes>
<Title>MudBlazor Markdown</Title>
<PackageReadmeFile>README.md</PackageReadmeFile>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Markdig" Version="0.33.0" />
<PackageReference Include="MudBlazor" Version="6.11.1" />
</ItemGroup>
<ItemGroup>
<SupportedPlatform Include="browser" />
</ItemGroup>
<Target Name="PreBuild" BeforeTargets="PreBuildEvent" Condition="'$(Configuration)'=='Release'">
<Exec Command="npm run build" />
</Target>
<ItemGroup>
<None Include="..\..\favico.png" Pack="true" PackagePath="\" />
<None Include="..\..\README.md" Pack="true" PackagePath="\" />
<Content Remove="**\package*.json" />
<None Remove="*.csproj.DotSettings" />
</ItemGroup>
<ItemGroup>
<Folder Include="wwwroot\" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,10 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=components/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=enums/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=extensions/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=helpers/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=services/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=services_005Cinterfaces/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=services_005Cregistration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=utils/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

View File

@ -0,0 +1,500 @@
using Markdig.Extensions.Mathematics;
using Markdig.Extensions.Tables;
using Markdig.Syntax;
using Markdig.Syntax.Inlines;
using Microsoft.AspNetCore.Components.Routing;
using Microsoft.AspNetCore.Components.Web;
// ReSharper disable MemberCanBePrivate.Global
namespace MudBlazor;
public class MudMarkdown : ComponentBase, IDisposable
{
protected IMudMarkdownThemeService? ThemeService;
protected MarkdownPipeline? Pipeline;
protected bool EnableLinkNavigation;
protected int ElementIndex;
/// <summary>
/// Markdown text to be rendered in the component.
/// </summary>
[Parameter]
public string Value { get; set; } = string.Empty;
/// <summary>
/// Minimum width (in pixels) for a table cell.<br/>
/// If <see langword="null" /> or negative the minimum width is not applied.
/// </summary>
[Parameter]
public int? TableCellMinWidth { get; set; }
/// <summary>
/// Command which is invoked when a link is clicked.<br/>
/// If <see langword="null" /> a link is opened in the browser.
/// </summary>
[Parameter]
public ICommand? LinkCommand { get; set; }
/// <summary>
/// Theme of the code block.<br/>
/// Browse available themes here: https://highlightjs.org/static/demo/
/// </summary>
[Parameter]
public CodeBlockTheme CodeBlockTheme { get; set; }
/// <summary>
/// Override the original URL address of the <see cref="LinkInline"/>.<br/>
/// If a function is not provided <see cref="LinkInline.Url"/> is used
/// </summary>
[Parameter]
public Func<LinkInline, string?>? OverrideLinkUrl { get; set; }
/// <summary>
/// Typography variant to use for Heading Level 1-6.<br/>
/// If a function is not provided a default typo for each level is set (e.g. for &lt;h1&gt; it will be <see cref="Typo.h1"/>, etc.)
/// </summary>
[Parameter]
public Func<Typo, Typo>? OverrideHeaderTypo { get; set; }
/// <summary>
/// Override default styling of the markdown component
/// </summary>
[Parameter]
public MudMarkdownStyling Styling { get; set; } = new();
[Parameter]
public MarkdownPipeline? MarkdownPipeline { get; set; }
[Inject]
protected NavigationManager? NavigationManager { get; init; }
[Inject]
protected IJSRuntime JsRuntime { get; init; } = default!;
[Inject]
protected IServiceProvider? ServiceProvider { get; init; }
public virtual void Dispose()
{
if (NavigationManager != null)
NavigationManager.LocationChanged -= NavigationManagerOnLocationChanged;
if (ThemeService != null)
ThemeService.CodeBlockThemeChanged -= OnCodeBlockThemeChanged;
GC.SuppressFinalize(this);
}
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
if (string.IsNullOrEmpty(Value))
return;
ElementIndex = 0;
var pipeline = GetMarkdownPipeLine();
var parsedText = Markdown.Parse(Value, pipeline);
if (parsedText.Count == 0)
return;
builder.OpenElement(ElementIndex++, "article");
builder.AddAttribute(ElementIndex++, "class", "mud-markdown-body");
RenderMarkdown(parsedText, builder);
builder.CloseElement();
}
protected override void OnInitialized()
{
base.OnInitialized();
ThemeService = ServiceProvider?.GetService<IMudMarkdownThemeService>();
if (ThemeService != null)
ThemeService.CodeBlockThemeChanged += OnCodeBlockThemeChanged;
}
protected override void OnAfterRender(bool firstRender)
{
if (!firstRender || !EnableLinkNavigation || NavigationManager == null)
return;
var args = new LocationChangedEventArgs(NavigationManager.Uri, true);
NavigationManagerOnLocationChanged(NavigationManager, args);
NavigationManager.LocationChanged += NavigationManagerOnLocationChanged;
}
protected virtual void RenderMarkdown(ContainerBlock container, RenderTreeBuilder builder)
{
for (var i = 0; i < container.Count; i++)
{
switch (container[i])
{
case ParagraphBlock paragraph:
{
RenderParagraphBlock(paragraph, builder);
break;
}
case HeadingBlock heading:
{
var typo = (Typo)heading.Level;
typo = OverrideHeaderTypo?.Invoke(typo) ?? typo;
EnableLinkNavigation = true;
var id = heading.BuildIdString();
RenderParagraphBlock(heading, builder, typo, id);
break;
}
case QuoteBlock quote:
{
builder.OpenElement(ElementIndex++, "blockquote");
RenderMarkdown(quote, builder);
builder.CloseElement();
break;
}
case Table table:
{
RenderTable(table, builder);
break;
}
case ListBlock list:
{
RenderList(list, builder);
break;
}
case ThematicBreakBlock:
{
builder.OpenComponent<MudDivider>(ElementIndex++);
builder.CloseComponent();
break;
}
case FencedCodeBlock code:
{
var text = code.CreateCodeBlockText();
// Necessary to prevent Blazor from crashing when the code block is empty.
// It seems that Blazor does not like empty attributes.
if(string.IsNullOrWhiteSpace(text))
break;
builder.OpenComponent<MudCodeHighlight>(ElementIndex++);
builder.AddAttribute(ElementIndex++, nameof(MudCodeHighlight.Text), text);
builder.AddAttribute(ElementIndex++, nameof(MudCodeHighlight.Language), code.Info ?? string.Empty);
builder.AddAttribute(ElementIndex++, nameof(MudCodeHighlight.Theme), CodeBlockTheme);
builder.CloseComponent();
break;
}
case HtmlBlock html:
{
if (html.TryGetDetails(out var detailsData))
RenderDetailsHtml(builder, detailsData.Header, detailsData.Content);
else
RenderHtml(builder, html.Lines);
break;
}
default:
{
OnRenderMarkdownBlockDefault(container[i]);
break;
}
}
}
}
/// <summary>
/// Renders a markdown block which is not covered by the switch-case block in <see cref="RenderMarkdown"/>
/// </summary>
protected virtual void OnRenderMarkdownBlockDefault(Markdig.Syntax.Block block)
{
}
protected virtual void RenderParagraphBlock(LeafBlock paragraph, RenderTreeBuilder builder, Typo typo = Typo.body1, string? id = null)
{
if (paragraph.Inline == null)
return;
builder.OpenComponent<MudText>(ElementIndex++);
if (!string.IsNullOrEmpty(id))
builder.AddAttribute(ElementIndex++, "id", id);
builder.AddAttribute(ElementIndex++, nameof(MudText.Typo), typo);
builder.AddAttribute(ElementIndex++, nameof(MudText.ChildContent), (RenderFragment)(contentBuilder => RenderInlines(paragraph.Inline, contentBuilder)));
builder.CloseComponent();
}
protected virtual void RenderInlines(ContainerInline inlines, RenderTreeBuilder builder)
{
foreach (var inline in inlines)
{
switch (inline)
{
case LiteralInline x:
{
builder.AddContent(ElementIndex++, x.Content);
break;
}
case HtmlInline x:
{
builder.AddMarkupContent(ElementIndex++, x.Tag);
break;
}
case LineBreakInline:
{
builder.OpenElement(ElementIndex++, "br");
builder.CloseElement();
break;
}
case CodeInline x:
{
builder.OpenElement(ElementIndex++, "code");
builder.AddContent(ElementIndex++, x.Content);
builder.CloseElement();
break;
}
case EmphasisInline x:
{
if (!x.TryGetEmphasisElement(out var elementName))
continue;
builder.OpenElement(ElementIndex++, elementName);
RenderInlines(x, builder);
builder.CloseElement();
break;
}
case LinkInline x:
{
var url = OverrideLinkUrl?.Invoke(x) ?? x.Url;
if (x.IsImage)
{
var alt = x
.OfType<LiteralInline>()
.Select(static x => x.Content);
builder.OpenComponent<MudImage>(ElementIndex++);
builder.AddAttribute(ElementIndex++, nameof(MudImage.Class), "rounded-lg");
builder.AddAttribute(ElementIndex++, nameof(MudImage.Src), url);
builder.AddAttribute(ElementIndex++, nameof(MudImage.Alt), string.Join(null, alt));
builder.AddAttribute(ElementIndex++, nameof(MudImage.Elevation), 25);
builder.CloseComponent();
}
else if (LinkCommand == null)
{
builder.OpenComponent<MudLink>(ElementIndex++);
builder.AddAttribute(ElementIndex++, nameof(MudLink.Href), url);
builder.AddAttribute(ElementIndex++, nameof(MudLink.ChildContent), (RenderFragment)(linkBuilder => RenderInlines(x, linkBuilder)));
if (url.IsExternalUri(NavigationManager?.BaseUri))
{
builder.AddAttribute(ElementIndex++, nameof(MudLink.Target), "_blank");
builder.AddAttribute(ElementIndex++, "rel", "noopener noreferrer");
}
// (prevent scrolling to the top of the page)
// custom implementation only for links on the same page
else if (url?.StartsWith('#') ?? false)
{
builder.AddEventPreventDefaultAttribute(ElementIndex++, "onclick", true);
builder.AddAttribute(ElementIndex++, "onclick", EventCallback.Factory.Create<MouseEventArgs>(this, () =>
{
if (NavigationManager == null)
return;
var uriBuilder = new UriBuilder(NavigationManager.Uri)
{
Fragment = url,
};
var args = new LocationChangedEventArgs(uriBuilder.Uri.AbsoluteUri, true);
NavigationManagerOnLocationChanged(NavigationManager, args);
}));
}
builder.CloseComponent();
}
else
{
builder.OpenComponent<MudLinkButton>(ElementIndex++);
builder.AddAttribute(ElementIndex++, nameof(MudLinkButton.Command), LinkCommand);
builder.AddAttribute(ElementIndex++, nameof(MudLinkButton.CommandParameter), url);
builder.AddAttribute(ElementIndex++, nameof(MudLinkButton.ChildContent), (RenderFragment)(linkBuilder => RenderInlines(x, linkBuilder)));
builder.CloseComponent();
}
break;
}
case MathInline x:
{
builder.OpenComponent<MudMathJax>(ElementIndex++);
builder.AddAttribute(ElementIndex++, nameof(MudMathJax.Delimiter), x.GetDelimiter());
builder.AddAttribute(ElementIndex++, nameof(MudMathJax.Value), x.Content);
builder.CloseComponent();
break;
}
default:
{
OnRenderInlinesDefault(inline, builder);
break;
}
}
}
}
/// <summary>
/// Renders inline block which is not covered by the switch-case block in <see cref="RenderInlines"/>
/// </summary>
protected virtual void OnRenderInlinesDefault(Inline inline, RenderTreeBuilder builder)
{
}
protected virtual void RenderTable(Table table, RenderTreeBuilder builder)
{
// First child is columns
if (table.Count < 2)
return;
builder.OpenComponent<MudSimpleTable>(ElementIndex++);
builder.AddAttribute(ElementIndex++, nameof(MudSimpleTable.Style), "overflow-x: auto;");
builder.AddAttribute(ElementIndex++, nameof(MudSimpleTable.Striped), Styling.Table.IsStriped);
builder.AddAttribute(ElementIndex++, nameof(MudSimpleTable.Bordered), Styling.Table.IsBordered);
builder.AddAttribute(ElementIndex++, nameof(MudSimpleTable.Elevation), Styling.Table.Elevation);
builder.AddAttribute(ElementIndex++, nameof(MudSimpleTable.ChildContent), (RenderFragment)(contentBuilder =>
{
// thread
contentBuilder.OpenElement(ElementIndex++, "thead");
RenderTableRow((TableRow)table[0], "th", contentBuilder, TableCellMinWidth);
contentBuilder.CloseElement();
// tbody
contentBuilder.OpenElement(ElementIndex++, "tbody");
for (var j = 1; j < table.Count; j++)
{
RenderTableRow((TableRow)table[j], "td", contentBuilder);
}
contentBuilder.CloseElement();
}));
builder.CloseComponent();
}
protected virtual void RenderTableRow(TableRow row, string cellElementName, RenderTreeBuilder builder, int? minWidth = null)
{
builder.OpenElement(ElementIndex++, "tr");
for (var j = 0; j < row.Count; j++)
{
var cell = (TableCell)row[j];
builder.OpenElement(ElementIndex++, cellElementName);
if (minWidth is > 0)
builder.AddAttribute(ElementIndex++, "style", $"min-width:{minWidth}px");
if (cell.Count != 0 && cell[0] is ParagraphBlock paragraphBlock)
RenderParagraphBlock(paragraphBlock, builder);
builder.CloseElement();
}
builder.CloseElement();
}
protected virtual void RenderList(ListBlock list, RenderTreeBuilder builder)
{
if (list.Count == 0)
return;
var elementName = list.IsOrdered ? "ol" : "ul";
var orderStart = list.OrderedStart.ParseOrDefault();
builder.OpenElement(ElementIndex++, elementName);
if (orderStart > 1)
{
builder.AddAttribute(ElementIndex++, "start", orderStart);
}
for (var i = 0; i < list.Count; i++)
{
var block = (ListItemBlock)list[i];
for (var j = 0; j < block.Count; j++)
{
switch (block[j])
{
case ListBlock x:
{
RenderList(x, builder);
break;
}
case ParagraphBlock x:
{
builder.OpenElement(ElementIndex++, "li");
RenderParagraphBlock(x, builder);
builder.CloseElement();
break;
}
default:
{
OnRenderListDefault(block[j], builder);
break;
}
}
}
}
builder.CloseElement();
}
/// <summary>
/// Renders a markdown block which is not covered by the switch-case block in <see cref="RenderList"/>
/// </summary>
protected virtual void OnRenderListDefault(Markdig.Syntax.Block block, RenderTreeBuilder builder)
{
}
protected virtual void RenderDetailsHtml(in RenderTreeBuilder builder, in string header, in string content)
{
var headerHtml = Markdown.Parse(header, Pipeline);
var contentHtml = Markdown.Parse(content);
builder.OpenComponent<MudMarkdownDetails>(ElementIndex++);
builder.AddAttribute(ElementIndex++, nameof(MudMarkdownDetails.TitleContent), (RenderFragment)(titleBuilder => RenderMarkdown(headerHtml, titleBuilder)));
builder.AddAttribute(ElementIndex++, nameof(MudMarkdownDetails.ChildContent), (RenderFragment)(contentBuilder => RenderMarkdown(contentHtml, contentBuilder)));
builder.CloseComponent();
}
protected virtual void RenderHtml(in RenderTreeBuilder builder, in StringLineGroup lines)
{
var markupString = new MarkupString(lines.ToString());
builder.AddContent(ElementIndex, markupString);
}
private async void NavigationManagerOnLocationChanged(object? sender, LocationChangedEventArgs e)
{
var idFragment = new Uri(e.Location, UriKind.Absolute).Fragment;
if (!idFragment.StartsWith('#') || idFragment.Length < 2)
return;
idFragment = idFragment[1..];
await JsRuntime.InvokeVoidAsync("scrollToElementId", idFragment)
.ConfigureAwait(false);
}
private void OnCodeBlockThemeChanged(object? sender, CodeBlockTheme e) =>
CodeBlockTheme = e;
private MarkdownPipeline GetMarkdownPipeLine()
{
if (MarkdownPipeline != null)
return MarkdownPipeline;
return Pipeline ??= new MarkdownPipelineBuilder()
.UseAdvancedExtensions()
.Build();
}
}

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,110 @@
/* Code */
.mud-markdown-body code:not(.hljs) {
background: var(--mud-palette-overlay-dark);
color: var(--mud-palette-text-primary) !important;
padding: 2.5px 7.5px;
border-radius: 5px;
}
/* This component is public, so apply styling in all places, not only within mud-markdown-body */
pre code.hljs {
display: block !important;
overflow-x: auto;
padding: 1em;
}
.mud-markdown-body .snippet-clipboard-content {
position: relative !important;
}
.mud-markdown-body .snippet-clipboard-content:hover > .snippet-clipboard-copy-icon {
display: block !important;
}
.mud-markdown-body .snippet-clipboard-content .snippet-clipboard-copy-icon {
position: absolute;
display: none;
top: 0;
right: 0;
}
/* Quote */
.mud-markdown-body blockquote {
border-left: .25em solid var(--mud-palette-text-disabled);
color: var(--mud-palette-text-secondary);
background-color: var(--mud-palette-drawer-background);
padding: 0.25em 1em;
margin: 0.5em 0 1.25em;
}
.mud-markdown-body blockquote p {
margin-bottom: 0 !important;
}
/* Table */
.mud-markdown-body table {
margin: 1.25em 0;
}
/* Link */
.mud-markdown-body .mud-link:hover {
cursor: pointer !important;
}
/* List */
.mud-markdown-body ul {
list-style-type: disc;
}
.mud-markdown-body ul, .mud-markdown-body ol {
padding-left: 2em;
margin-bottom: 1.25em !important;
}
.mud-markdown-body ul ul {
list-style-type: circle;
margin-bottom: 0 !important;
}
.mud-markdown-body ul ul ul {
list-style-type: square;
margin-bottom: 0 !important;
}
.mud-markdown-body li {
display: list-item !important;
text-align: -webkit-match-parent;
}
/* Headers */
.mud-markdown-body h1, .mud-markdown-body h2 {
border-bottom: 1px solid var(--mud-palette-text-disabled);
padding-bottom: 0.125em;
margin-bottom: 0.4em;
}
.mud-markdown-body h1, .mud-markdown-body h2, .mud-markdown-body h3, .mud-markdown-body h4, .mud-markdown-body h5, .mud-markdown-body h6 {
scroll-margin-top: 5rem;
margin-top: 0.25em;
word-wrap: break-word;
margin-bottom: 0.3em !important;
}
.mud-markdown-body .mud-divider {
margin: 0.5em 0;
height: 0.25em;
}
/* Paragraphs */
.mud-markdown-body p {
margin-bottom: 1.25em !important;
}
.mud-markdown-body li p, .mud-markdown-body .mud-expand-panel p {
margin-bottom: 0 !important;
}
/* Images */
.mud-markdown-body img {
max-width: 100%;
}

View File

@ -0,0 +1,87 @@
import hljs from "highlight.js";
const codeStylesDir = "code-styles";
const codeStylesSegment = `/MudBlazor.Markdown/${codeStylesDir}/`;
window.highlightCodeElement = function (element) {
hljs.highlightElement(element);
}
window.setHighlightStylesheet = function (stylesheetPath) {
let isFound = false;
const stylesheets = document.querySelectorAll("link[rel='stylesheet']");
for (let i = 0; i < stylesheets.length; i++) {
const href = stylesheets[i].getAttribute("href");
if (!href) {
continue;
}
const index = href.indexOf(codeStylesSegment);
if (index !== -1) {
if (!isFound) {
isFound = true;
const newHref = href.substring(0, index + codeStylesSegment.length) + stylesheetPath;
stylesheets[i].setAttribute("href", newHref);
} else {
stylesheets[i].remove();
}
}
}
if (!isFound) {
const link = document.createElement("link");
link.rel = "stylesheet";
link.href = `_content/MudBlazor.Markdown/${codeStylesDir}/${stylesheetPath}`;
document.head.appendChild(link);
}
}
window.scrollToElementId = function (elementId) {
const element = document.getElementById(elementId);
if (element) {
const elementIdHref = `#${elementId}`;
if (!window.location.pathname.endsWith(elementIdHref)) {
history.replaceState(null, "", window.location.pathname + elementIdHref);
}
element.scrollIntoView({
behavior: "smooth",
block: "start",
inline: "nearest"
});
}
}
window.appendMathJaxScript = function (scriptId) {
if (document.getElementById(scriptId)) {
return;
}
const script = document.createElement("script");
script.id = scriptId;
script.type = "text/javascript";
script.src = "_content/MudBlazor.Markdown/MudBlazor.Markdown.MathJax.min.js";
document.head.appendChild(script);
}
window.refreshMathJaxScript = function () {
try {
MathJax.typeset();
} catch (e) {
// swallow since in some cases MathJax might not be initialized
}
}
window.copyTextToClipboard = async function (text) {
try {
await navigator.clipboard.writeText(text);
return true;
} catch (e) {
return false;
}
}

View File

@ -0,0 +1,6 @@
namespace MudBlazor;
public interface IMudMarkdownClipboardService
{
ValueTask CopyToClipboardAsync(string text);
}

View File

@ -0,0 +1,8 @@
namespace MudBlazor;
public interface IMudMarkdownThemeService
{
event EventHandler<CodeBlockTheme> CodeBlockThemeChanged;
void SetCodeBlockTheme(CodeBlockTheme theme);
}

View File

@ -0,0 +1,9 @@
namespace MudBlazor;
internal sealed class MudMarkdownThemeService : IMudMarkdownThemeService
{
public event EventHandler<CodeBlockTheme>? CodeBlockThemeChanged;
public void SetCodeBlockTheme(CodeBlockTheme theme) =>
CodeBlockThemeChanged?.Invoke(this, theme);
}

View File

@ -0,0 +1,15 @@
namespace MudBlazor;
public static class ServiceCollectionEx
{
public static IServiceCollection AddMudMarkdownServices(this IServiceCollection @this)
{
return @this.AddScoped<IMudMarkdownThemeService, MudMarkdownThemeService>();
}
public static IServiceCollection AddMudMarkdownClipboardService<T>(this IServiceCollection @this)
where T : class, IMudMarkdownClipboardService
{
return @this.AddScoped<IMudMarkdownClipboardService, T>();
}
}

View File

@ -0,0 +1,12 @@
global using System.Windows.Input;
global using Markdig;
global using Markdig.Helpers;
global using Microsoft.AspNetCore.Components;
global using Microsoft.AspNetCore.Components.Rendering;
global using Microsoft.Extensions.DependencyInjection;
global using Microsoft.JSInterop;
global using MudBlazor.Extensions;
global using MudBlazor.Utilities;
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("MudBlazor.Markdown.Tests")]

View File

@ -0,0 +1,47 @@
const { src, dest, series } = require("gulp");
const webpack = require("webpack-stream");
const rename = require("gulp-rename");
const minifyCss = require("gulp-clean-css");
const changeCase = require("change-case");
const all = require("gulp-all");
function fonts() {
return src("Resources/Fonts/*.woff")
.pipe(dest("wwwroot/output/chtml/fonts/woff-v2"));
}
function cssMain() {
return src("Resources/*.css")
.pipe(minifyCss())
.pipe(rename({ extname: ".min.css" }))
.pipe(dest("wwwroot"));
}
function cssCodeStyles() {
return src("Resources/CodeStyles/src/**/*.css")
.pipe(minifyCss({ level: { 1: { specialComments: "0" } } }))
.pipe(rename(function (path) {
path.dirname = changeCase.camelCase(path.dirname);
path.extname = ".min.css";
}))
.pipe(dest("wwwroot/code-styles"));
}
function img() {
return src("Resources/CodeStyles/src/**/*.{png,jpg}")
.pipe(dest("wwwroot/code-styles"));
}
function jsMain() {
const mainJs = src("Resources/MudBlazor.Markdown.js")
.pipe(webpack({ mode: "production" }))
.pipe(rename({ basename: "MudBlazor.Markdown", extname: ".min.js" }))
.pipe(dest("wwwroot"));
const mathJax = src("Resources/MudBlazor.Markdown.MathJax.min.js")
.pipe(dest("wwwroot"));
return all(mainJs, mathJax);
}
exports.default = series(fonts, cssMain, cssCodeStyles, img, jsMain);

9070
MudBlazor.Markdown/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,27 @@
{
"name": "mudblazor.markdown",
"version": "1.0.0",
"description": "Markdown component for MudBlazor (https://mudblazor.com/)",
"keywords": [
"mudblazor",
"markdown",
"blazor"
],
"scripts": {
"build": "gulp"
},
"author": "MyNihongo",
"license": "MIT",
"devDependencies": {
"change-case": "^4.1.2",
"gulp": "^4.0.2",
"gulp-all": "^1.1.0",
"gulp-clean-css": "^4.3.0",
"gulp-rename": "^2.0.0",
"webpack": "^5.89.0",
"webpack-stream": "^7.0.0"
},
"dependencies": {
"highlight.js": "^11.9.0"
}
}

View File

@ -2,6 +2,8 @@
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MindWork AI Studio", "MindWork AI Studio\MindWork AI Studio.csproj", "{059FDFCC-7D0B-474E-9F20-B9C437DF1CDD}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MindWork AI Studio", "MindWork AI Studio\MindWork AI Studio.csproj", "{059FDFCC-7D0B-474E-9F20-B9C437DF1CDD}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MudBlazor.Markdown", "..\MudBlazor.Markdown\MudBlazor.Markdown.csproj", "{9402C391-AFEE-431B-BDD4-107890772036}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -12,5 +14,9 @@ Global
{059FDFCC-7D0B-474E-9F20-B9C437DF1CDD}.Debug|Any CPU.Build.0 = Debug|Any CPU {059FDFCC-7D0B-474E-9F20-B9C437DF1CDD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{059FDFCC-7D0B-474E-9F20-B9C437DF1CDD}.Release|Any CPU.ActiveCfg = Release|Any CPU {059FDFCC-7D0B-474E-9F20-B9C437DF1CDD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{059FDFCC-7D0B-474E-9F20-B9C437DF1CDD}.Release|Any CPU.Build.0 = Release|Any CPU {059FDFCC-7D0B-474E-9F20-B9C437DF1CDD}.Release|Any CPU.Build.0 = Release|Any CPU
{9402C391-AFEE-431B-BDD4-107890772036}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9402C391-AFEE-431B-BDD4-107890772036}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9402C391-AFEE-431B-BDD4-107890772036}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9402C391-AFEE-431B-BDD4-107890772036}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal

View File

@ -14,7 +14,9 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="MudBlazor" Version="6.19.1" /> <PackageReference Include="MudBlazor" Version="6.19.1" />
<PackageReference Include="MudBlazor.Markdown" Version="0.1.3" /> </ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\MudBlazor.Markdown\MudBlazor.Markdown.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>