Skip to content

Commit 76e4e50

Browse files
committed
feat: add support for LaTeX
1 parent deb222a commit 76e4e50

File tree

12 files changed

+222
-88
lines changed

12 files changed

+222
-88
lines changed

Directory.Packages.props

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
<PackageVersion Include="Markdig" Version="0.43.0"/>
2222
<PackageVersion Include="TextMateSharp" Version="1.0.70"/>
2323
<PackageVersion Include="TextMateSharp.Grammars" Version="1.0.70"/>
24+
<PackageVersion Include="Sylinko.CSharpMath.Avalonia" Version="11.3.0"/>
2425
<!-- NUnit packages -->
2526
<PackageVersion Include="BenchmarkDotNet" Version="0.15.1"/>
2627
<PackageVersion Include="coverlet.collector" Version="6.0.3"/>

LiveMarkdown.Avalonia.sln

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LiveMarkdown.Avalonia.Demo.
3232
EndProject
3333
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LiveMarkdown.Avalonia.Demo.Browser", "src\LiveMarkdown.Avalonia.Demo\LiveMarkdown.Avalonia.Demo.Browser\LiveMarkdown.Avalonia.Demo.Browser.csproj", "{339C1452-35D4-466C-8214-6ED8FE1F9565}"
3434
EndProject
35+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LiveMarkdown.Avalonia.Math", "src\LiveMarkdown.Avalonia.Math\LiveMarkdown.Avalonia.Math.csproj", "{85180282-E6C4-4B75-939A-1705CE99882A}"
36+
EndProject
3537
Global
3638
GlobalSection(SolutionConfigurationPlatforms) = preSolution
3739
Debug|Any CPU = Debug|Any CPU
@@ -66,6 +68,10 @@ Global
6668
{339C1452-35D4-466C-8214-6ED8FE1F9565}.Debug|Any CPU.Build.0 = Debug|Any CPU
6769
{339C1452-35D4-466C-8214-6ED8FE1F9565}.Release|Any CPU.ActiveCfg = Release|Any CPU
6870
{339C1452-35D4-466C-8214-6ED8FE1F9565}.Release|Any CPU.Build.0 = Release|Any CPU
71+
{85180282-E6C4-4B75-939A-1705CE99882A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
72+
{85180282-E6C4-4B75-939A-1705CE99882A}.Debug|Any CPU.Build.0 = Debug|Any CPU
73+
{85180282-E6C4-4B75-939A-1705CE99882A}.Release|Any CPU.ActiveCfg = Release|Any CPU
74+
{85180282-E6C4-4B75-939A-1705CE99882A}.Release|Any CPU.Build.0 = Release|Any CPU
6975
EndGlobalSection
7076
GlobalSection(SolutionProperties) = preSolution
7177
HideSolutionNode = FALSE

README.md

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ It supports **real-time rendering** of Markdown content, so it's ideal for appli
4444
- [x] Local images
4545
- [x] `avares` images
4646
- [x] Selectable text across elements
47-
- [ ] LaTeX support
47+
- [x] LaTeX support
4848
- [ ] HTML rendering
4949

5050
## 🚀 Getting Started
@@ -116,6 +116,23 @@ Avalonia Styling Docs:
116116
- [Avalonia Styles](https://docs.avaloniaui.net/docs/styling)
117117
- [Style selector syntax](https://docs.avaloniaui.net/docs/reference/styles/style-selector-syntax)
118118

119+
### 4. Enable LaTeX rendering
120+
121+
LaTeX is supported via the `LiveMarkdown.Avalonia.Math` package. You can install it via NuGet:
122+
123+
```bash
124+
dotnet add package LiveMarkdown.Avalonia.Math
125+
```
126+
127+
Then register both the `MathInlineNode` and `MathBlockNode` before using LaTeX in your Markdown content:
128+
129+
```csharp
130+
using LiveMarkdown.Avalonia;
131+
132+
MarkdownNode.Register<MathInlineNode>();
133+
MarkdownNode.Register<MathBlockNode>();
134+
```
135+
119136
## 🤔 FAQ
120137

121138
- Q: Why some emojis not rendered correctly (rendered in single color)?
@@ -140,4 +157,6 @@ Distributed under the Apache 2.0 License. See [LICENSE](LICENSE) for more inform
140157
- **TextMateSharp** - [MIT License](https://github.com/danipen/TextMateSharp/blob/master/LICENSE.md)
141158
- Syntax highlighting for code blocks
142159
- Source repo: https://github.com/danipen/TextMateSharp
143-
160+
- **CSharpMath** - [MIT License](https://github.com/verybadcat/CSharpMath/blob/master/License)
161+
- LaTeX rendering support
162+
- Source repo: https://github.com/verybadcat/CSharpMath
Lines changed: 36 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,55 @@
11
using Avalonia;
22
using Avalonia.Controls.ApplicationLifetimes;
3-
using Avalonia.Data.Core;
43
using Avalonia.Data.Core.Plugins;
54
using Avalonia.Markup.Xaml;
65
using LiveMarkdown.Avalonia.Demo.ViewModels;
76
using LiveMarkdown.Avalonia.Demo.Views;
8-
using System.Linq;
97

10-
namespace LiveMarkdown.Avalonia.Demo
8+
namespace LiveMarkdown.Avalonia.Demo;
9+
10+
public class App : Application
1111
{
12-
public partial class App : Application
12+
public override void Initialize()
1313
{
14-
public override void Initialize()
15-
{
16-
AvaloniaXamlLoader.Load(this);
17-
}
14+
MarkdownNode.Register<MathInlineNode>();
15+
MarkdownNode.Register<MathBlockNode>();
16+
17+
AvaloniaXamlLoader.Load(this);
18+
}
1819

19-
public override void OnFrameworkInitializationCompleted()
20+
public override void OnFrameworkInitializationCompleted()
21+
{
22+
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
2023
{
21-
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
24+
// Avoid duplicate validations from both Avalonia and the CommunityToolkit.
25+
// More info: https://docs.avaloniaui.net/docs/guides/development-guides/data-validation#manage-validationplugins
26+
DisableAvaloniaDataAnnotationValidation();
27+
desktop.MainWindow = new MainWindow
2228
{
23-
// Avoid duplicate validations from both Avalonia and the CommunityToolkit.
24-
// More info: https://docs.avaloniaui.net/docs/guides/development-guides/data-validation#manage-validationplugins
25-
DisableAvaloniaDataAnnotationValidation();
26-
desktop.MainWindow = new MainWindow
27-
{
28-
DataContext = new MainViewModel()
29-
};
30-
}
31-
else if (ApplicationLifetime is ISingleViewApplicationLifetime singleViewPlatform)
29+
DataContext = new MainViewModel()
30+
};
31+
}
32+
else if (ApplicationLifetime is ISingleViewApplicationLifetime singleViewPlatform)
33+
{
34+
singleViewPlatform.MainView = new MainView
3235
{
33-
singleViewPlatform.MainView = new MainView
34-
{
35-
DataContext = new MainViewModel()
36-
};
37-
}
38-
39-
base.OnFrameworkInitializationCompleted();
36+
DataContext = new MainViewModel()
37+
};
4038
}
4139

42-
private void DisableAvaloniaDataAnnotationValidation()
43-
{
44-
// Get an array of plugins to remove
45-
var dataValidationPluginsToRemove =
46-
BindingPlugins.DataValidators.OfType<DataAnnotationsValidationPlugin>().ToArray();
40+
base.OnFrameworkInitializationCompleted();
41+
}
4742

48-
// remove each entry found
49-
foreach (var plugin in dataValidationPluginsToRemove)
50-
{
51-
BindingPlugins.DataValidators.Remove(plugin);
52-
}
43+
private static void DisableAvaloniaDataAnnotationValidation()
44+
{
45+
// Get an array of plugins to remove
46+
var dataValidationPluginsToRemove =
47+
BindingPlugins.DataValidators.OfType<DataAnnotationsValidationPlugin>().ToList();
48+
49+
// remove each entry found
50+
foreach (var plugin in dataValidationPluginsToRemove)
51+
{
52+
BindingPlugins.DataValidators.Remove(plugin);
5353
}
5454
}
5555
}

src/LiveMarkdown.Avalonia.Demo/LiveMarkdown.Avalonia.Demo/LiveMarkdown.Avalonia.Demo.csproj

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
3-
<TargetFramework>net9.0</TargetFramework>
3+
<TargetFramework>net10.0</TargetFramework>
44
<Nullable>enable</Nullable>
55
<LangVersion>preview</LangVersion>
66
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
@@ -23,10 +23,7 @@
2323
</ItemGroup>
2424

2525
<ItemGroup>
26-
<EmbeddedResource Include="samples\*.md" />
27-
</ItemGroup>
28-
29-
<ItemGroup>
26+
<ProjectReference Include="..\..\LiveMarkdown.Avalonia.Math\LiveMarkdown.Avalonia.Math.csproj" />
3027
<ProjectReference Include="..\..\LiveMarkdown.Avalonia\LiveMarkdown.Avalonia.csproj" />
3128
</ItemGroup>
3229

@@ -43,5 +40,8 @@
4340
<None Update="samples\Test.md">
4441
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
4542
</None>
43+
<None Update="samples\LaTeX.md">
44+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
45+
</None>
4646
</ItemGroup>
4747
</Project>

src/LiveMarkdown.Avalonia.Demo/LiveMarkdown.Avalonia.Demo/ViewLocator.cs

Lines changed: 0 additions & 31 deletions
This file was deleted.

src/LiveMarkdown.Avalonia.Demo/LiveMarkdown.Avalonia.Demo/ViewModels/MainViewModel.cs

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
using Avalonia;
1+
using System.Collections.ObjectModel;
2+
using Avalonia;
23
using Avalonia.Controls;
34
using Avalonia.Controls.ApplicationLifetimes;
45
using CommunityToolkit.Mvvm.ComponentModel;
56
using CommunityToolkit.Mvvm.Input;
6-
using System.Collections.ObjectModel;
7-
using System.Reflection;
87

98
namespace LiveMarkdown.Avalonia.Demo.ViewModels;
109

@@ -77,16 +76,6 @@ private async Task RenderMarkdownAsync(string? markdownFileName)
7776
cancellationTokenSource = new CancellationTokenSource();
7877
var cancellationToken = cancellationTokenSource.Token;
7978

80-
var assembly = Assembly.GetExecutingAssembly();
81-
var resourceName = assembly.GetManifestResourceNames()
82-
.FirstOrDefault(n => n.EndsWith($"{markdownFileName}.md", StringComparison.OrdinalIgnoreCase));
83-
84-
if (resourceName is null)
85-
{
86-
await Console.Error.WriteLineAsync($"Resource not found: {markdownFileName}.md");
87-
return;
88-
}
89-
9079
async IAsyncEnumerable<string> ReadBlocksAsync()
9180
{
9281
var buffer = Array.Empty<char>();
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
$a,b,c$
2+
3+
$a+b\times c$
4+
5+
$C^a_b+\sqrt{c}$
6+
7+
$$\sum_{i=1}^n a_i$$
8+
9+
$$E=mc^2$$
10+
11+
$$\int_a^b f(x) \, dx$$

src/LiveMarkdown.Avalonia.Demo/LiveMarkdown.Avalonia.Demo/samples/Test.md

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,15 @@ Playwright 框架的主要特点有:
3737
3. Item Three
3838
4. Test long long long long long long long long long long long long long long long long long long text wrapping
3939

40+
Bullet list with different markers:
41+
* Asterisk item
42+
+ Plus item
43+
- Hyphen item
44+
45+
Task list:
46+
- [x] Completed task
47+
- [ ] Incomplete task
48+
4049
Test **bold** and *italic* text, then `inline code` example and [`inline code with backticks`](https://example.com) are here.
4150

4251
---
@@ -166,4 +175,13 @@ Local image example:
166175

167176
Avalonia image example:
168177

169-
![Avalonia Image](avares://LiveMarkdown.Avalonia.Demo/Assets/Antelcat.png)
178+
![Avalonia Image](avares://LiveMarkdown.Avalonia.Demo/Assets/Antelcat.png)
179+
180+
## 5. LaTeX
181+
182+
Inline LaTeX example: $E=mc^2$.
183+
184+
Block LaTeX example:
185+
$$
186+
\int_{a}^{b} x^2 \,dx = \left[ \frac{x^3}{3} \right]_{a}^{b} = \frac{b^3}{3} - \frac{a^3}{3}
187+
$$
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<RootNamespace>LiveMarkdown.Avalonia</RootNamespace>
4+
<TargetFrameworks>netstandard2.0;net8.0;net9.0</TargetFrameworks>
5+
<Title>LiveMarkdown.Avalonia.Math</Title>
6+
<Authors>DearVa</Authors>
7+
<Description>This is a extension package for `LiveMarkdown.Avalonia` that adds support for rendering LaTeX math expressions using CSharpMath.
8+
It leverages the `Sylinko.CSharpMath.Avalonia` library to provide high-quality rendering of mathematical notation within Markdown content.
9+
</Description>
10+
<PackageProjectUrl>https://github.com/DearVa/LiveMarkdown.Avalonia</PackageProjectUrl>
11+
<PackageReadmeFile>README.md</PackageReadmeFile>
12+
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
13+
<RepositoryUrl>https://github.com/DearVa/LiveMarkdown.Avalonia</RepositoryUrl>
14+
</PropertyGroup>
15+
16+
<ItemGroup>
17+
<PackageReference Include="Sylinko.CSharpMath.Avalonia"/>
18+
</ItemGroup>
19+
20+
<ItemGroup>
21+
<ProjectReference Include="..\LiveMarkdown.Avalonia\LiveMarkdown.Avalonia.csproj"/>
22+
</ItemGroup>
23+
24+
<ItemGroup>
25+
<None Include="..\..\README.md" Pack="true" PackagePath="\"/>
26+
</ItemGroup>
27+
</Project>

0 commit comments

Comments
 (0)