Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: RichTextEdit based on roosterjs #4693

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion Blazorise.sln
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
.runsettings = .runsettings
DotnetWatchRunAll.bat = DotnetWatchRunAll.bat
CREDITS.md = CREDITS.md
DotnetWatchRunAll.bat = DotnetWatchRunAll.bat
README.md = README.md
EndProjectSection
EndProject
Expand Down Expand Up @@ -153,6 +153,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Blazorise.Captcha", "Source
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Blazorise.Captcha.ReCaptcha", "Source\Extensions\Blazorise.Captcha.ReCaptcha\Blazorise.Captcha.ReCaptcha.csproj", "{2B4FD79A-42E2-4B81-828B-0799E4744ADA}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Blazorise.RichTextEdit.Rooster", "Source\Extensions\Blazorise.RichTextEdit.Rooster\Blazorise.RichTextEdit.Rooster.csproj", "{D03708E9-0E38-4AD1-87DF-DA349E7DC271}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -399,6 +401,10 @@ Global
{2B4FD79A-42E2-4B81-828B-0799E4744ADA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2B4FD79A-42E2-4B81-828B-0799E4744ADA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2B4FD79A-42E2-4B81-828B-0799E4744ADA}.Release|Any CPU.Build.0 = Release|Any CPU
{D03708E9-0E38-4AD1-87DF-DA349E7DC271}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D03708E9-0E38-4AD1-87DF-DA349E7DC271}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D03708E9-0E38-4AD1-87DF-DA349E7DC271}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D03708E9-0E38-4AD1-87DF-DA349E7DC271}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -467,6 +473,7 @@ Global
{FE5BCD94-0215-4BF1-8CF7-0F97C20B0054} = {9731051E-0AA7-411E-A76A-987854F034DA}
{D24EA4EF-0AEC-43B2-BCDC-56229D60C285} = {9731051E-0AA7-411E-A76A-987854F034DA}
{2B4FD79A-42E2-4B81-828B-0799E4744ADA} = {9731051E-0AA7-411E-A76A-987854F034DA}
{D03708E9-0E38-4AD1-87DF-DA349E7DC271} = {9731051E-0AA7-411E-A76A-987854F034DA}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {205B3EA4-470F-45DA-911E-346AF7D0A9A5}
Expand Down
2 changes: 1 addition & 1 deletion Build/Blazorise.props
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<Company>Megabit</Company>
<Copyright>Copyright 2018-2024 Megabit</Copyright>

<TargetFrameworks>net6.0;net7.0;net8.0</TargetFrameworks>
<TargetFramework>net8.0</TargetFramework>
<OutputType>Library</OutputType>
<IsPackable>true</IsPackable>
<LangVersion>10.0</LangVersion>
Expand Down
5 changes: 4 additions & 1 deletion Demos/Blazorise.Demo.Bootstrap.Server/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ public void ConfigureServices( IServiceCollection services )
.AddFontAwesomeIcons();

services.AddRazorPages();
services.AddServerSideBlazor();
services.AddServerSideBlazor( options =>
{
options.DetailedErrors = true;
} );

services.AddServerSideBlazor().AddHubOptions( ( o ) =>
{
Expand Down
1 change: 1 addition & 0 deletions Demos/Blazorise.Demo/Blazorise.Demo.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
<ProjectReference Include="..\..\Source\Extensions\Blazorise.LottieAnimation\Blazorise.LottieAnimation.csproj" />
<ProjectReference Include="..\..\Source\Extensions\Blazorise.Markdown\Blazorise.Markdown.csproj" />
<ProjectReference Include="..\..\Source\Extensions\Blazorise.QRCode\Blazorise.QRCode.csproj" />
<ProjectReference Include="..\..\Source\Extensions\Blazorise.RichTextEdit.Rooster\Blazorise.RichTextEdit.Rooster.csproj" />
<ProjectReference Include="..\..\Source\Extensions\Blazorise.RichTextEdit\Blazorise.RichTextEdit.csproj" />
<ProjectReference Include="..\..\Source\Extensions\Blazorise.Sidebar\Blazorise.Sidebar.csproj" />
<ProjectReference Include="..\..\Source\Extensions\Blazorise.Snackbar\Blazorise.Snackbar.csproj" />
Expand Down
3 changes: 3 additions & 0 deletions Demos/Blazorise.Demo/Components/SideMenu.razor
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,9 @@
<BarDropdownItem To="tests/richtextedit">
RichTextEdit
</BarDropdownItem>
<BarDropdownItem To="tests/rooster">
Rooster RichTextEdit
</BarDropdownItem>
<BarDropdownItem To="tests/selectlist">
Select List
</BarDropdownItem>
Expand Down
150 changes: 150 additions & 0 deletions Demos/Blazorise.Demo/Pages/Tests/RoosterPage.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
@page "/tests/rooster"
@using Blazorise.RichTextEdit.Rooster
@using Markdig.Extensions.SmartyPants
@using System.Text.Json
@using System.Text.Json.Serialization

<Row>
<Column>
<Card Margin="Margin.Is4.OnY">
<CardHeader>
<CardTitle>RichTextEdit based on rooster.js</CardTitle>
</CardHeader>
<CardBody>
<Buttons Role="ButtonsRole.Toolbar">
<Buttons Margin="Margin.Is2.FromEnd">
<Button Command="editor.Editor.Undo"><Icon Name="IconName.Undo" /></Button>
<Button Command="editor.Editor.Redo"><Icon Name="IconName.Redo" /></Button>
</Buttons>
<Buttons Margin="Margin.Is2.FromEnd">
<Button Command="editor.Format.ToggleBold" Active="@(editor.FormatState.IsBold ?? false)"><Icon Name="IconName.Bold"/></Button>
<Button Command="editor.Format.ToggleItalic" Active="@(editor.FormatState.IsItalic ?? false)"><Icon Name="IconName.Italic" /></Button>
<Button Command="editor.Format.ToggleUnderline" Active="@(editor.FormatState.IsUnderline ?? false)"><Icon Name="IconName.Underline" /></Button>
<Button Command="editor.Format.ChangeFontSize" CommandParameter="FontSizeChange.Increase">A⁺</Button>
<Button Command="editor.Format.ChangeFontSize" CommandParameter="FontSizeChange.Decrease">A⁻</Button>
<Button Command="editor.Format.SetIndentation" CommandParameter="Indentation.Decrease">←</Button>
<Button Command="editor.Format.SetIndentation" CommandParameter="Indentation.Increase">→</Button>
Text: <ColorPicker Width="Width.Px(40)" Color="@editor.FormatState.TextColor" ColorChanged="editor.Format.SetTextColor"/>
Bg: <ColorPicker Width="Width.Px(40)" Color="@editor.FormatState.BackgroundColor" ColorChanged="editor.Format.SetBackgroundColor"/>
<Dropdown>
<DropdownToggle>@GetFontLabel()</DropdownToggle>
<DropdownMenu>
<DropdownItem Clicked="editor.Format.SetFontName" Value="@("Arial")">Arial</DropdownItem>
<DropdownItem Clicked="editor.Format.SetFontName" Value="@("Calibri")">Calibri</DropdownItem>
<DropdownItem Clicked="editor.Format.SetFontName" Value="@("Comic Sans MS")">Comic Sans MS</DropdownItem>
<DropdownItem Clicked="editor.Format.SetFontName" Value="@("Courier New")">Courier New</DropdownItem>
<DropdownItem Clicked="editor.Format.SetFontName" Value="@("Times New Roman")">Times New Roman</DropdownItem>
<DropdownItem Clicked="editor.Format.SetFontName" Value="@("Verdana")">Verdana</DropdownItem>
</DropdownMenu>
</Dropdown>
<Dropdown>
<DropdownToggle>Size</DropdownToggle>
<DropdownMenu>
<DropdownItem Clicked="editor.Format.SetFontSize" Value="8">8</DropdownItem>
<DropdownItem Clicked="editor.Format.SetFontSize" Value="9">9</DropdownItem>
<DropdownItem Clicked="editor.Format.SetFontSize" Value="10">10</DropdownItem>
<DropdownItem Clicked="editor.Format.SetFontSize" Value="11">11</DropdownItem>
<DropdownItem Clicked="editor.Format.SetFontSize" Value="12">12</DropdownItem>
<DropdownItem Clicked="editor.Format.SetFontSize" Value="20">20</DropdownItem>
<DropdownItem Clicked="editor.Format.SetFontSize" Value="36">36</DropdownItem>
<DropdownItem Clicked="editor.Format.SetFontSize" Value="48">48</DropdownItem>
<DropdownItem Clicked="editor.Format.SetFontSize" Value="72">72</DropdownItem>
<Divider/>
<DropdownItem Clicked="editor.Format.SetFontSize" Value="@("1rem")">1rem</DropdownItem>
<DropdownItem Clicked="editor.Format.SetFontSize" Value="@("2rem")">2rem</DropdownItem>
<DropdownItem Clicked="editor.Format.SetFontSize" Value="@("4rem")">4rem</DropdownItem>
<Divider/>
<DropdownItem Clicked="editor.Format.SetFontSize">Default</DropdownItem>
</DropdownMenu>
</Dropdown>
<Dropdown>
<DropdownToggle>H1</DropdownToggle>
<DropdownMenu>
<DropdownItem Clicked="editor.Format.SetHeadingLevel" Value="HeadingSize.Is1">Heading 1</DropdownItem>
<DropdownItem Clicked="editor.Format.SetHeadingLevel" Value="HeadingSize.Is2">Heading 2</DropdownItem>
<DropdownItem Clicked="editor.Format.SetHeadingLevel" Value="HeadingSize.Is3">Heading 3</DropdownItem>
<DropdownItem Clicked="editor.Format.SetHeadingLevel" Value="HeadingSize.Is4">Heading 4</DropdownItem>
<DropdownItem Clicked="editor.Format.SetHeadingLevel" Value="HeadingSize.Is5">Heading 5</DropdownItem>
<DropdownItem Clicked="editor.Format.SetHeadingLevel" Value="HeadingSize.Is6">Heading 6</DropdownItem>
<Divider/>
<DropdownItem Clicked="editor.Format.SetHeadingLevel">No heading</DropdownItem>
</DropdownMenu>
</Dropdown>
</Buttons>
</Buttons>

<Blazorise.RichTextEdit.Rooster.RichTextEdit @ref="editor"
@bind-Content="contentAsHtml"
FormatStateChanged="OnFormatStateChanged" />
</CardBody>
</Card>
</Column>
</Row>
<Row>
<Column ColumnSize="ColumnSize.Is4">
<Card>
<CardHeader>
<CardTitle>Content Preview</CardTitle>
</CardHeader>
<CardBody>
@((MarkupString)contentAsHtml)
</CardBody>
</Card>
</Column>
<Column ColumnSize="ColumnSize.Is4">
<Card>
<CardHeader>
<CardTitle>State Preview</CardTitle>
</CardHeader>
<CardBody>
<pre><code>@formatStateJson</code></pre>
</CardBody>
</Card>
</Column>
<Column ColumnSize="ColumnSize.Is4">
<Card>
<CardHeader>
<CardTitle>Actions</CardTitle>
</CardHeader>
<CardBody>
<Button Command="editor.Editor.Focus">Focus</Button>
<Button Command="editor.Editor.Clear">Clear</Button>
<Button Clicked="SetContent">Set content</Button>
</CardBody>
</Card>
</Column>
</Row>

@code {
private Blazorise.RichTextEdit.Rooster.RichTextEdit editor;
private string contentAsHtml = "<p>Welcome to the <b>Rooster.js</b> RichTextEdit!</p>";
private string formatStateJson;

private static readonly JsonSerializerOptions SerializerOptions = new(JsonSerializerDefaults.Web)
{
WriteIndented = true,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
};

private void SetContent()
{
contentAsHtml = $"Content from code <b>{DateTime.Now:g}</b>";
InvokeAsync(StateHasChanged);
}

private void OnFormatStateChanged(FormatState state)
{
formatStateJson = JsonSerializer.Serialize(state, SerializerOptions);
InvokeAsync(StateHasChanged);
}

private string GetFontLabel()
{
if (string.IsNullOrWhiteSpace(editor.FormatState.FontName)) return "Select Font";

return editor.FormatState.FontName
.Split(',')
.Select(x => x.Trim('"'))
.FirstOrDefault();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">

<Import Project="..\..\..\Build\Blazorise.props" />

<PropertyGroup>
<PackageTags>blazorise blazor components richtextedit roosterjs</PackageTags>
</PropertyGroup>

<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\Blazorise\Blazorise.csproj" />
</ItemGroup>

<ItemGroup>
<None Include="..\..\..\LICENSE.md" Pack="true" Visible="false" PackagePath="" />
<None Include="..\..\..\NuGet\Blazorise.png" Pack="true" Visible="false" PackagePath="" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace Blazorise.RichTextEdit.Rooster.Commands;

///<summary>
/// Change the capitalization of text in the selection
/// </summary>
public class ChangeCapitalizationCommand : RichTextEditCommand<Capitalization>
{
internal ChangeCapitalizationCommand( RichTextEdit editor ) : base( editor, "changeCapitalization" )
{
}

/// <inheritdoc />
protected override object Transform( Capitalization argument )
=> argument.Value;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace Blazorise.RichTextEdit.Rooster.Commands;

///<summary>
/// Increase or decrease font size in selection
/// </summary>
public class ChangeFontSizeCommand : RichTextEditCommand<FontSizeChange?>
{
internal ChangeFontSizeCommand( RichTextEdit editor ) : base( editor, "changeFontSize" )
{
}

/// <inheritdoc />
protected override object Transform( FontSizeChange? argument )
=> argument.HasValue ? (int)argument : null;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace Blazorise.RichTextEdit.Rooster.Commands;

/// <summary>
/// Clear the format in current selection, after cleaning, the format will be changed to default format.
/// </summary>
public class ClearFormatCommand : RichTextEditCommand<ClearFormatMode?>
{
internal ClearFormatCommand( RichTextEdit editor ) : base( editor, "clearFormat" )
{
}

/// <inheritdoc />
protected override object Transform( ClearFormatMode? argument )
=> argument.HasValue ? (int)argument : null;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
namespace Blazorise.RichTextEdit.Rooster.Commands;

/// <summary>
/// Rooster format commands.
/// </summary>
/// <see href="https://microsoft.github.io/roosterjs/docs/interfaces/roosterjs_editor_types.ieditor.html"/>
public class Editor
{
internal Editor( RichTextEdit editor )
{
Undo = new( editor, "undo", x => x.FormatState.CanUndo );
Redo = new( editor, "redo", x => x.FormatState.CanRedo );
Focus = new( editor, "focus" );
DeleteSelectedContent = new( editor, "deleteSelectedContent" );
SetZoomScale = new( editor, "setZoomScale" );
Clear = new( editor, "setContent" );
}

/// <summary>
/// Undo last edit operation.
/// </summary>
public RichTextEditCommand Undo { get; }
/// <summary>
/// Redo next edit operation.
/// </summary>
public RichTextEditCommand Redo { get; }
/// <summary>
/// Focus to this editor, the selection was restored to where it was before, no unexpected scroll.
/// </summary>
public RichTextEditCommand Focus { get; }
/// <summary>
/// Delete selected content
/// </summary>
public RichTextEditCommand DeleteSelectedContent { get; }
/// <summary>
/// Set current zoom scale, default value is 1.
/// </summary>
public RichTextEditCommand SetZoomScale { get; }
/// <summary>
/// Clears the editor.
/// </summary>
public RichTextEditCommand Clear { get; }
}
Loading
Loading