返回提交历史

XFEstudio/MyFirstRespo

修复部分已知问题,新增折叠块消息

d04590d
X
XFEstudio <mail@xfegzs.com>
提交于

代码差异

11 个文件 +174 -222
Modified XFEToolBox/App.xaml.cs +2 -2
@@ -28,7 +28,7 @@ public partial class App : Application
28 28 void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
29 29 {
30 30 // 处理 UI 线程未处理的异常
31 MessageBox.Show("UI线程未处理异常:" + e.Exception.Message, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
31 //MessageBox.Show("UI线程未处理异常:" + e.Exception.Message, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
32 32 e.Handled = true; // 设置为 true 表示异常已处理,防止应用程序退出
33 33 }
34 34
@@ -42,7 +42,7 @@ public partial class App : Application
42 42 void TaskScheduler_UnobservedTaskException(object? sender, UnobservedTaskExceptionEventArgs e)
43 43 {
44 44 // 处理任务调度程序未观察到的任务异常
45 MessageBox.Show("非主线程未处理异常:" + e.Exception.Message, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
45 //MessageBox.Show("非主线程未处理异常:" + e.Exception.Message, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
46 46 e.SetObserved(); // 防止程序崩溃
47 47 }
48 48 }
Modified XFEToolBox/Resources/Style/MainStyle.xaml +30 -4
@@ -295,7 +295,7 @@
295 295 <Setter Property="Template">
296 296 <Setter.Value>
297 297 <ControlTemplate TargetType="Button">
298 <Grid>
298 <Grid x:Name="grid">
299 299 <Border x:Name="border" CornerRadius="5" Background="White" Opacity="0.1">
300 300 </Border>
301 301 <ContentPresenter Margin="5,3"/>
@@ -315,17 +315,43 @@
315 315 </Storyboard>
316 316 </BeginStoryboard>
317 317 </EventTrigger>
318 <EventTrigger RoutedEvent="MouseLeftButtonDown">
318 <EventTrigger RoutedEvent="MouseLeftButtonDown" SourceName="grid">
319 319 <BeginStoryboard>
320 320 <Storyboard>
321 321 <DoubleAnimation Storyboard.TargetName="border" Storyboard.TargetProperty="Opacity" To="0.3" Duration="0:0:0.1"/>
322 322 </Storyboard>
323 323 </BeginStoryboard>
324 324 </EventTrigger>
325 <EventTrigger RoutedEvent="MouseLeftButtonUp">
325 </ControlTemplate.Triggers>
326 </ControlTemplate>
327 </Setter.Value>
328 </Setter>
329 </Style.Setters>
330 <Style.Triggers>
331 <Trigger Property="IsEnabled" Value="False">
332 <Setter Property="Opacity" Value="0.5"/>
333 </Trigger>
334 </Style.Triggers>
335 </Style>
336 <Style x:Key="FoldButton" TargetType="Button">
337 <Style.Setters>
338 <Setter Property="Opacity" Value="1"/>
339 <Setter Property="Template">
340 <Setter.Value>
341 <ControlTemplate TargetType="Button">
342 <ContentPresenter x:Name="content" Margin="5,3"/>
343 <ControlTemplate.Triggers>
344 <EventTrigger RoutedEvent="MouseEnter">
326 345 <BeginStoryboard>
327 346 <Storyboard>
328 <DoubleAnimation Storyboard.TargetName="border" Storyboard.TargetProperty="Opacity" To="0.5" Duration="0:0:0.1"/>
347 <DoubleAnimation Storyboard.TargetProperty="Opacity" To="0.8" Duration="0:0:0.1"/>
348 </Storyboard>
349 </BeginStoryboard>
350 </EventTrigger>
351 <EventTrigger RoutedEvent="MouseLeave">
352 <BeginStoryboard>
353 <Storyboard>
354 <DoubleAnimation Storyboard.TargetProperty="Opacity" To="0.8" Duration="0:0:0.1"/>
329 355 </Storyboard>
330 356 </BeginStoryboard>
331 357 </EventTrigger>
Modified XFEToolBox/Utilities/DecTextSpan.cs +4 -23
@@ -2,28 +2,9 @@
2 2
3 3 namespace XFEToolBox.Utilities;
4 4
5 public class DecTextSpan
5 public class DecTextSpan(string text, Color color, Color backgroundColor)
6 6 {
7 public bool IsHyperLink { get; set; }
8 public string Text { get; set; }
9 public string? Link { get; set; }
10 public Color Color { get; set; }
11 public Color BackgroundColor { get; set; }
12
13 public DecTextSpan(string text, Color color, Color backgroundColor)
14 {
15 IsHyperLink = false;
16 Text = text;
17 Color = color;
18 BackgroundColor = backgroundColor;
19 }
20
21 public DecTextSpan(string text, string link, Color color, Color backgroundColor)
22 {
23 IsHyperLink= true;
24 Text = text;
25 Link = link;
26 Color = color;
27 BackgroundColor = backgroundColor;
28 }
7 public string Text { get; set; } = text;
8 public Color Color { get; set; } = color;
9 public Color BackgroundColor { get; set; } = backgroundColor;
29 10 }
Modified XFEToolBox/Utilities/DecoratedTextConverter.cs +116 -10
@@ -1,5 +1,6 @@
1 1 using System.Diagnostics;
2 2 using System.Text.RegularExpressions;
3 using System.Windows;
3 4 using System.Windows.Controls;
4 5 using System.Windows.Documents;
5 6 using System.Windows.Media;
@@ -8,31 +9,37 @@ namespace XFEToolBox.Utilities;
8 9
9 10 public partial class DecoratedTextConverter
10 11 {
11 [GeneratedRegex(@"\[(?:(?:(?<type>color)\s+(?<color>\#[0-9a-fA-F]{6}|\w+)(?:\s+(?<background>\#[0-9a-fA-F]{6}|\w+))?)|(?:(?<type>hyperlink)\s+(?:color:\s*(?<color>\#[0-9a-fA-F]{6}|\w+)(?<background>\s+\#[0-9a-fA-F]{6}|\w+)?(?:\s+))?link:\s*(?<link>.+)\s+text:\s*(?<text>.+)))\]")]
12 [GeneratedRegex(@"\[(?:(?:(?<type>color)\s+(?<color>\#[0-9a-fA-F]{6}|\w+)(?:\s+(?<background>\#[0-9a-fA-F]{6}|\w+))?)|(?:(?<type>hyperlink)\s+(?:color:\s*(?<color>\#[0-9a-fA-F]{6}|\w+)(?<background>\s+\#[0-9a-fA-F]{6}|\w+)?(?:\s+))?link:\s*(?<link>.+)\s+text:\s*(?<text>.+))|(?:(?<type>foldblock)\s+(?:color:\s*(?<color>\#[0-9a-fA-F]{6}|\w+)\s+(?<background>\#[0-9a-fA-F]{6}|\w+))\s+title:\s*(?<title>.+)\s+text:\s*(?<text>(?s).+)))\]")]
12 13 public static partial Regex DecorationRegex();
13 14
14 15 public static TextBlock ConvertToTextBlock(string decoratedText, Color defaultColor)
15 16 {
16 17 var results = ConvertToInlineList(decoratedText, defaultColor);
17 18 var textBlock = new TextBlock();
18 textBlock.Inlines.AddRange(results);
19 foreach (var result in results)
20 {
21 if (result is Inline inline)
22 textBlock.Inlines.Add(inline);
23 else
24 textBlock.Inlines.Add((UIElement)result);
25 }
19 26 return textBlock;
20 27 }
21 public static List<Inline> ConvertToInlineList(string decoratedText, Color defaultColor)
28 public static List<object> ConvertToInlineList(string decoratedText, Color defaultColor)
22 29 {
23 30 var results = ConvertText(decoratedText, defaultColor);
24 var inLineList = new List<Inline>();
31 var inLineList = new List<object>();
25 32 if (results.Count > 0)
26 33 {
27 34 foreach (var result in results)
28 35 {
29 if (result.IsHyperLink)
36 if (result is HyperLinkDecSpan hyperLinkDecSpan)
30 37 {
31 var hyperLink = new Hyperlink(new Run(result.Text))
38 var hyperLink = new Hyperlink(new Run(hyperLinkDecSpan.Text))
32 39 {
33 Foreground = new SolidColorBrush(result.Color),
34 NavigateUri = new Uri(result.Link!),
35 Background = new SolidColorBrush(result.BackgroundColor)
40 Foreground = new SolidColorBrush(hyperLinkDecSpan.Color),
41 NavigateUri = new Uri(hyperLinkDecSpan.Link),
42 Background = new SolidColorBrush(hyperLinkDecSpan.BackgroundColor)
36 43 };
37 44 hyperLink.RequestNavigate += (sender, e) =>
38 45 {
@@ -40,6 +47,100 @@ public partial class DecoratedTextConverter
40 47 };
41 48 inLineList.Add(hyperLink);
42 49 }
50 else if (result is FoldBlockDecSpan foldBlockDecSpan)
51 {
52 var foldGrid = new Grid
53 {
54 Margin = new Thickness(3)
55 };
56 foldGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new(220) });
57 foldGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new(20) });
58 foldGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new(1, GridUnitType.Star) });
59 foldGrid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
60 foldGrid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
61 var titleTextBlock = new TextBlock
62 {
63 Margin = new Thickness(5, 2, 5, 2),
64 Text = foldBlockDecSpan.Title,
65 TextTrimming = TextTrimming.CharacterEllipsis,
66 Foreground = new SolidColorBrush(foldBlockDecSpan.Color),
67 VerticalAlignment = VerticalAlignment.Center,
68 HorizontalAlignment = HorizontalAlignment.Center
69 };
70 var titleBorder = new Border
71 {
72 Background = new SolidColorBrush(foldBlockDecSpan.BackgroundColor),
73 CornerRadius = new CornerRadius(5, 0, 0, 5),
74 Child = titleTextBlock
75 };
76 foldGrid.Children.Add(titleBorder);
77 var buttonText = new TextBlock
78 {
79 Foreground = new SolidColorBrush(foldBlockDecSpan.BackgroundColor),
80 Background = new SolidColorBrush(foldBlockDecSpan.Color),
81 Text = "▼",
82 FontSize = 18
83 };
84 var button = new Button
85 {
86 Style = (Style)Application.Current.FindResource("FoldButton"),
87 Background = new SolidColorBrush(foldBlockDecSpan.Color),
88 Content = buttonText
89 };
90 var foldButtonBorder = new Border
91 {
92 Background = new SolidColorBrush(foldBlockDecSpan.Color),
93 CornerRadius = new CornerRadius(0, 5, 5, 0),
94 Child = button
95 };
96 Grid.SetColumn(foldButtonBorder, 1);
97 foldGrid.Children.Add(foldButtonBorder);
98 var contentTextBlock = new TextBlock
99 {
100 TextWrapping = TextWrapping.Wrap,
101 Foreground = new SolidColorBrush(foldBlockDecSpan.Color),
102 };
103 if (foldBlockDecSpan.DecTextList.Count > 0)
104 contentTextBlock.Inlines.AddRange(foldBlockDecSpan.DecTextList.Select(x => new Span(new Run(x.Text))
105 {
106 Foreground = new SolidColorBrush(x.Color),
107 Background = new SolidColorBrush(x.BackgroundColor)
108 }));
109 else
110 contentTextBlock.Text = foldBlockDecSpan.Text;
111 var contentBorder = new Border
112 {
113 Visibility = Visibility.Collapsed,
114 CornerRadius = new CornerRadius(0, 5, 5, 5),
115 Background = Brushes.Transparent,
116 BorderBrush = new SolidColorBrush(foldBlockDecSpan.BackgroundColor),
117 BorderThickness = new Thickness(3),
118 Padding = new Thickness(3),
119 Child = contentTextBlock
120 };
121 button.Click += (sender, e) =>
122 {
123 if (contentBorder.Visibility == Visibility.Visible)
124 {
125 contentBorder.Visibility = Visibility.Collapsed;
126 titleBorder.CornerRadius = new(5, 0, 0, 5);
127 buttonText.Text = "▼";
128 }
129 else
130 {
131 contentBorder.Visibility = Visibility.Visible;
132 titleBorder.CornerRadius = new(5, 0, 0, 0);
133 buttonText.Text = "▲";
134 }
135 };
136 Grid.SetColumnSpan(contentBorder, 3);
137 Grid.SetRow(contentBorder, 1);
138 Grid.SetRow(contentBorder, 1);
139 Grid.SetColumnSpan(contentBorder, 3);
140 foldGrid.Children.Add(contentBorder);
141 inLineList.Add(new Span(new Run("\n")));
142 inLineList.Add(foldGrid);
143 }
43 144 else
44 145 {
45 146 inLineList.Add(new Span(new Run(result.Text))
@@ -75,6 +176,7 @@ public partial class DecoratedTextConverter
75 176 Color backgroundColor = (Color)ColorConverter.ConvertFromString(backgroundColorText);
76 177 var link = match.Groups["link"].Value;
77 178 var text = match.Groups["text"].Value;
179 var title = match.Groups["title"].Value;
78 180 var unMatchString = "";
79 181 if (i == 0 && match.Index != 0)
80 182 {
@@ -97,7 +199,11 @@ public partial class DecoratedTextConverter
97 199 continue;
98 200 case "hyperlink":
99 201 var color = ColorConverter.ConvertFromString(colorText);
100 textSpanList.Add(new(text, link, color is null ? defaultColor : (Color)color, backgroundColor));
202 textSpanList.Add(new HyperLinkDecSpan(text, link, color is null ? defaultColor : (Color)color, backgroundColor));
203 textSpanList.Add(new(unMatchString, defaultColor, Colors.Transparent));
204 continue;
205 case "foldblock":
206 textSpanList.Add(new FoldBlockDecSpan(text, title, ConvertText(text, defaultColor), (Color)ColorConverter.ConvertFromString(colorText), backgroundColor));
101 207 textSpanList.Add(new(unMatchString, defaultColor, Colors.Transparent));
102 208 continue;
103 209 default:
Added XFEToolBox/Utilities/FoldBlockDecSpan.cs +9 -0
@@ -0,0 +1,9 @@
1 using System.Windows.Media;
2
3 namespace XFEToolBox.Utilities;
4
5 public class FoldBlockDecSpan(string text, string title, List<DecTextSpan> decTextList, Color color, Color backgroundColor) : DecTextSpan(text, color, backgroundColor)
6 {
7 public string Title { get; set; } = title;
8 public List<DecTextSpan> DecTextList { get; set; } = decTextList;
9 }
Added XFEToolBox/Utilities/HyperLinkDecSpan.cs +8 -0
@@ -0,0 +1,8 @@
1 using System.Windows.Media;
2
3 namespace XFEToolBox.Utilities;
4
5 public class HyperLinkDecSpan(string text, string link, Color color, Color backgroundColor) : DecTextSpan(text, color, backgroundColor)
6 {
7 public string Link { get; set; } = link;
8 }
Deleted XFEToolBox/Utilities/XFEConsoleClientInfo.cs +0 -30
@@ -1,30 +0,0 @@
1 using XFEExtension.NetCore.CyberComm;
2
3 namespace XFEExtension.NetCore.XFEConsole;
4
5 /// <summary>
6 /// XFE控制台客户端信息
7 /// </summary>
8 /// <param name="clientName">客户端名称</param>
9 /// <param name="clientUUID">客户端唯一标识符</param>
10 /// <param name="password">客户端连接时密码</param>
11 /// <param name="eventArgs">事件参数</param>
12 public class XFEConsoleClientInfo(string clientName, string clientUUID, string password, CyberCommServerEventArgs eventArgs)
13 {
14 /// <summary>
15 /// 客户端名称
16 /// </summary>
17 public string ClientName { get; set; } = clientName;
18 /// <summary>
19 /// 客户端唯一标识符
20 /// </summary>
21 public string ClientUUID { get; set; } = clientUUID;
22 /// <summary>
23 /// 客户端密码
24 /// </summary>
25 public string Password { get; set; } = password;
26 /// <summary>
27 /// 事件参数
28 /// </summary>
29 public CyberCommServerEventArgs EventArgs { get; set; } = eventArgs;
30 }
Deleted XFEToolBox/Utilities/XFEConsoleTerminalServer.cs +0 -149
@@ -1,149 +0,0 @@
1 using System.Net.WebSockets;
2 using XFEExtension.NetCore.CyberComm;
3 using XFEExtension.NetCore.DelegateExtension;
4
5 namespace XFEExtension.NetCore.XFEConsole;
6
7 /// <summary>
8 /// XFE控制台终端服务器
9 /// </summary>
10 public class XFEConsoleTerminalServer
11 {
12 /// <summary>
13 /// 服务器
14 /// </summary>
15 public CyberCommServer Server { get; set; }
16 /// <summary>
17 /// 密码
18 /// </summary>
19 public string Password { get; set; }
20 /// <summary>
21 /// Socket客户端-客户端信息字典
22 /// </summary>
23 public Dictionary<WebSocket, XFEConsoleClientInfo> ClientInfoDictionary { get; set; } = [];
24 /// <summary>
25 /// 客户端连接事件
26 /// </summary>
27 public event XFEEventHandler<XFEConsoleTerminalServer, XFEConsoleClientInfo>? Connected;
28 /// <summary>
29 /// 客户端断开连接事件
30 /// </summary>
31 public event XFEEventHandler<XFEConsoleTerminalServer, XFEConsoleClientInfo>? Disconnected;
32 /// <summary>
33 /// 接收到客户端消息触发
34 /// </summary>
35 public event XFEEventHandler<XFEConsoleClientInfo, string>? MessageReceived;
36 /// <summary>
37 /// 发生错误
38 /// </summary>
39 public event XFEEventHandler<XFEConsoleClientInfo, Exception>? ErrorOccurred;
40 /// <summary>
41 /// 服务器启动事件
42 /// </summary>
43 public event XFEEventHandler<XFEConsoleTerminalServer>? ServerStarted;
44 /// <summary>
45 /// XFE控制台终端服务器
46 /// </summary>
47 /// <param name="port">端口号</param>
48 /// <param name="localOnly">是否只在本地开启</param>
49 /// <param name="password">密码(默认为空)</param>
50 public XFEConsoleTerminalServer(int port, bool localOnly = true, string password = "")
51 {
52 Password = password;
53 if (localOnly)
54 Server = new CyberCommServer($"http://localhost:{port}/");
55 else
56 Server = new CyberCommServer(port);
57 Server.ServerStarted += Server_ServerStarted;
58 Server.ClientConnected += Server_ClientConnected;
59 Server.ConnectionClosed += Server_ConnectionClosed;
60 Server.MessageReceived += Server_MessageReceived;
61 }
62 /// <summary>
63 /// XFE控制台终端服务器
64 /// </summary>
65 /// <param name="ipAddress">IP地址</param>
66 /// <param name="password">密码(默认为空)</param>
67 public XFEConsoleTerminalServer(string[] ipAddress, string password = "")
68 {
69 Password = password;
70 Server = new CyberCommServer(ipAddress);
71 Server.ServerStarted += Server_ServerStarted;
72 Server.ClientConnected += Server_ClientConnected;
73 Server.ConnectionClosed += Server_ConnectionClosed;
74 Server.MessageReceived += Server_MessageReceived;
75 }
76
77 private void Server_MessageReceived(object? sender, CyberCommServerEventArgs e)
78 {
79 switch (e.MessageType)
80 {
81 case BackMessageType.Text:
82 MessageReceived?.Invoke(ClientInfoDictionary[e.CurrentWebSocket], e.TextMessage!);
83 break;
84 case BackMessageType.Binary:
85 break;
86 case BackMessageType.Error:
87 ErrorOccurred?.Invoke(ClientInfoDictionary[e.CurrentWebSocket], e.Exception!);
88 break;
89 default:
90 break;
91 }
92 }
93
94 private void Server_ConnectionClosed(object? sender, CyberCommServerEventArgs e)
95 {
96 if (ClientInfoDictionary.TryGetValue(e.CurrentWebSocket, out XFEConsoleClientInfo? clientInfo))
97 {
98 ClientInfoDictionary.Remove(e.CurrentWebSocket);
99 Disconnected?.Invoke(this, clientInfo);
100 }
101 }
102
103 private async void Server_ClientConnected(object? sender, CyberCommServerEventArgs e)
104 {
105 try
106 {
107 if (e.WSHeader["ClientName"] is not null && e.WSHeader["ClientID"] is not null && e.WSHeader["Password"] is not null)
108 {
109 var password = e.WSHeader["Password"]!;
110 var clientName = e.WSHeader["ClientName"]!;
111 var clientUUID = e.WSHeader["ClientID"]!;
112 if (password == Password)
113 {
114 var clientInfo = new XFEConsoleClientInfo(clientName, clientUUID, password, e);
115 ClientInfoDictionary.Add(e.CurrentWebSocket, clientInfo);
116 Connected?.Invoke(this, clientInfo);
117 }
118 return;
119 }
120 }
121 catch { }
122 try
123 {
124 await e.Close();
125 }
126 catch
127 {
128 try
129 {
130 e.ForceClose();
131 }
132 catch { }
133 }
134 }
135
136 private void Server_ServerStarted(object? sender, EventArgs e)
137 {
138 ClientInfoDictionary = [];
139 ServerStarted?.Invoke(this);
140 }
141 /// <summary>
142 /// 启动服务器
143 /// </summary>
144 /// <returns></returns>
145 public async Task StartServer()
146 {
147 await Server.StartCyberCommServer();
148 }
149 }
Modified XFEToolBox/ViewModel/ConsolePageViewModel.cs +1 -1
@@ -52,7 +52,7 @@ public partial class ConsolePageViewModel(ConsolePage viewPage) : ObservableObje
52 52 {
53 53 var code = e.InnerException?.InnerException is HttpListenerException ? (e.InnerException.InnerException as HttpListenerException)!.ErrorCode : 0;
54 54 if (code != 995)
55 ShowMessageWithTimeLine($"[color Red]发生错误:{e.Message}");
55 ShowMessageWithTimeLine($"[foldblock color: white #ff0000 title: 错误:{e.Message} text: {e}]");
56 56 }
57 57
58 58 private void TerminalServer_MessageReceived(XFEConsoleClientInfo sender, string e)
Modified XFEToolBox/Views/Windows/MainWindow.xaml +2 -2
@@ -8,9 +8,9 @@
8 8 xmlns:local="clr-namespace:XFEToolBox.Views.Windows"
9 9 mc:Ignorable="d"
10 10 d:DataContext="{d:DesignInstance Type=viewmodel:MainWindowViewModel}"
11 Title="XFE工具箱" Height="450" Width="720" MinHeight="450" MinWidth="720" Background="Transparent" WindowStyle="None" AllowsTransparency="True" WindowStartupLocation="CenterScreen" Icon="/Resources/Icon/XFEToolBoxIcon.ico" Loaded="Window_Loaded">
11 Title="XFE工具箱" Height="460" Width="730" MinHeight="450" MinWidth="720" Background="Transparent" WindowStyle="None" AllowsTransparency="True" WindowStartupLocation="CenterScreen" Icon="/Resources/Icon/XFEToolBoxIcon.ico" Loaded="Window_Loaded">
12 12
13 <Border CornerRadius="19" Background="#9898e7">
13 <Border CornerRadius="19" Background="#9898e7" Margin="5">
14 14 <Grid>
15 15 <Grid.ColumnDefinitions>
16 16 <ColumnDefinition Width="180"/>
Modified XFEToolBox/XFEToolBox.csproj +2 -1
@@ -32,11 +32,12 @@
32 32
33 33 <ItemGroup>
34 34 <PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" />
35 <PackageReference Include="XFEExtension.NetCore" Version="3.0.1" />
35 <PackageReference Include="XFEExtension.NetCore" Version="3.0.2" />
36 36 <PackageReference Include="XFEExtension.NetCore.AutoConfig" Version="1.1.1" />
37 37 <PackageReference Include="XFEExtension.NetCore.AutoPath" Version="1.0.1" />
38 38 <PackageReference Include="XFEExtension.NetCore.InputSimulator" Version="2.2.0" />
39 39 <PackageReference Include="XFEExtension.NetCore.TodoHighLight" Version="1.0.0" />
40 <PackageReference Include="XFEExtension.NetCore.XFEConsole" Version="1.0.0" />
40 41 </ItemGroup>
41 42
42 43 <ItemGroup>