Skip to content

Commit

Permalink
Add a Markdown text editor (#114)
Browse files Browse the repository at this point in the history
* Added Link and script for SimpleMDE

* Created SimpleMDE.js file. Got rich text editor to appear using custom <textarea>

* updated js. should effect all textarea elements on page

* added .js code to all(?) pages with textarea. changed icon color

* removed fullscreen option, added markdig package

* Markdown.cs to take markdown string and convert to html. RTE Functionaly and now displays Markdown correctly

* Fix bug in Work Entry edit page

* commit

* Uninstalled Markdig everywhere except "WebApp"

* Re-installed Markdig for AppServices

* SimpleMDE files -> EasyMDE. Attempted using @Sections opposed to <head> tags for the scripts and stylesheet. Non functional as of now

* Added textarea-to-MDE.js

* EasyMDE works on textareas. Removed all instances of "SimpleMDE." Working on styling with dark mode and options for EasyMDE

* Changes to toolbar

* css changes for Dark Mode EasyMDE

* removed overlapping label for textarea

* Created new additionalViewData for EasyMDE. Added MDE to Edit.cshtml

* Added the HtmlSanitizer package to AppServices. Sanitized rendered Markdown on the backend.

* Added .UseBootstrap() to MarkdownPiplineBuilder(),
Moved Markdown.cs to WebApp from AppServices,
Uninstalled HtmlSanitizer from AppServices and reinstalled in WebApp

* Used libman for DOMPurify

* Installed EasyMDE via libman

* Fixed references in Details.cshtml. Deleted EasyMDE.css and incorporated changes into libman file

* Added easymde.darkmode.css to overwrite some css in easymde

* added DOMpurify to textarea-to-MDE. added correct styles to Details.cshtml

* Removed EasyMDE from Details and added to Edit

* Changed Notes section in Details.cshtml. Border now surrounds generated Markdown HTML

* Several CSS changes: Fullscreen background, fullscreen taskbar, cursor color, etc.

* Removed Preview

* Removed unnecessary EasyMDE references in Close.cshtml. Removed Label for Textarea's using MDE

* Commented out preview button

* Remade Close page. Text is bigger overall and Notes has its own section with rendered HTML

* Fix EasyMDE preview button

* Fix rendering of Bootstrap classes in Markdown output

* Fix label on non-MDE textareas

* Add Markdown table example

* Make code quality fixes

* Add MDE side-by-side toolbar button

---------

Co-authored-by: Caleb Nguyen <[email protected]>
Co-authored-by: Doug Waldron <[email protected]>
  • Loading branch information
3 people authored Aug 8, 2024
1 parent 03695de commit adc4c39
Show file tree
Hide file tree
Showing 14 changed files with 172 additions and 17 deletions.
3 changes: 3 additions & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@
<PackageVersion Include="FluentValidation.AspNetCore" Version="11.3.0" />
<PackageVersion Include="GaEpd.AppLibrary" Version="5.2.1" />
<PackageVersion Include="GaEpd.FileService" Version="3.1.1" />
<PackageVersion Include="HtmlSanitizer" Version="8.0.865" />
<PackageVersion Include="JetBrains.Annotations" Version="2023.3.0" />
<PackageVersion Include="LigerShark.WebOptimizer.Core" Version="3.0.405" />
<PackageVersion Include="MailKit" Version="4.5.0" />
<PackageVersion Include="Markdig" Version="0.37.0" />
<PackageVersion Include="Markdig.Signed" Version="0.37.0" />
<PackageVersion Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.4" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.4">
<PrivateAssets>all</PrivateAssets>
Expand Down
23 changes: 20 additions & 3 deletions src/TestData/Constants/TextData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ public static class TextData
Environment.NewLine +
"Pudding ice cream chocolate sweet roll jelly.";

public const string Paragraph = "Oat cake gummi bears danish I love tart muffin bonbon I love. Danish tiramisu " +
public const string Paragraph = "**Oat cake gummi** bears danish I *love* tart muffin bonbon I love. Danish tiramisu " +
"tootsie roll tart marshmallow icing tootsie roll. Shortbread tiramisu tiramisu chocolate bar biscuit. " +
"Liquorice I love biscuit bonbon jujubes croissant.";
"~~Liquorice I love biscuit bonbon jujubes croissant.~~";

public static readonly string MultipleParagraphs = "Dessert cheesecake ice cream fruitcake chocolate bar cookie." +
Environment.NewLine +
Expand All @@ -44,6 +44,23 @@ public static class TextData
"candy. Oat cake muffin tart bear claw bonbon lollipop. Marshmallow donut icing chocolate bar dessert." +
Environment.NewLine +
Environment.NewLine +
"## Oat cake muffin" +
Environment.NewLine +
Environment.NewLine +
"Dessert cheesecake ice cream fruitcake chocolate bar pie cookie. Croissant marzipan jelly cupcake cupcake " +
"lemon drops jelly-o. Shortbread donut pie.";
"lemon drops jelly-o. Shortbread donut pie." +
Environment.NewLine +
Environment.NewLine +
"| Dessert | Topping |" +
Environment.NewLine +
"| --- | --: |" +
Environment.NewLine +
"| lemon drops | jelly |" +
Environment.NewLine +
"| brownie | chocolate |" +
Environment.NewLine +
"| Croissant | Marshmallow |" +
Environment.NewLine +
Environment.NewLine +
"Lemon drops jelly-o. Shortbread donut pie.";
}
1 change: 1 addition & 0 deletions src/TestData/WorkEntryData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ internal static class WorkEntryData
ReceivedBy = UserData.GetUsers.ElementAt(1),
ReceivedDate = DateTimeOffset.Now.AddMinutes(30),
EntryType = EntryTypeData.GetData.ElementAt(0),
Notes = TextData.MultipleParagraphs,
},
new(new Guid("10000000-0000-0000-0000-000000000002")) // 2
{
Expand Down
15 changes: 12 additions & 3 deletions src/WebApp/Pages/Shared/EditorTemplates/Textarea.cshtml
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
@model string
@{
var rows = (int?)ViewData["Rows"] ?? 2;
var mde = (bool?)ViewData["MDE"] ?? false;
var classMde = mde ? (string?)ViewData["ClassMDE"] ?? "EasyMDE" : "";
}

<div class="form-floating">
<textarea asp-for="@__model" class="form-control" rows="@rows.ToString()"></textarea>
<label asp-for="@__model" class="form-label"></label>
<div class="@(mde ? "" : "form-floating")">
@if (mde)
{
<label asp-for="@__model" class="form-label"></label>
}
<textarea asp-for="@__model" class="form-control markdown @classMde" rows="@rows.ToString()"></textarea>
@if (!mde)
{
<label asp-for="@__model" class="form-label"></label>
}
<span asp-validation-for="@__model" class="invalid-feedback"></span>
</div>
1 change: 1 addition & 0 deletions src/WebApp/Pages/Shared/_Layout.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<link rel="stylesheet" href="~/css/site.css" />
<partial name="_RaygunScriptsPartial" />
<script src="~/js/color-modes.js"></script>
@await RenderSectionAsync("Styles", false)
</head>

<body id="top" class="d-flex flex-column vh-100">
Expand Down
10 changes: 9 additions & 1 deletion src/WebApp/Pages/Staff/WorkEntries/Add.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,20 @@
</div>

<h2>Details</h2>

<div class="row">
<div class="col-md">
<div class="mb-3">
@Html.EditorFor(model => model.Item.Notes, EditorTemplate.Textarea,
additionalViewData: new { Rows = 5 })
additionalViewData: new { Rows = 5, MDE = true })
</div>
</div>
<div class="col-md">
<div class="mb-3">
@Html.EditorFor(model => model.Item.EntryTypeId, EditorTemplate.Select,
additionalViewData: new { Items = Model.EntryTypesSelectList, Placeholder = string.Empty })
</div>

</div>
</div>

Expand All @@ -42,4 +44,10 @@

@section Scripts {
<partial name="_ValidationScriptsPartial" />
<script src="~/lib/easymde/dist/easymde.min.js"></script>
<script src="~/js/textarea-to-MDE.js" defer></script>
}
@section Styles {
<link rel="stylesheet" href="~/lib/easymde/dist/easymde.min.css" />
<link rel="stylesheet" href="~/css/easymde.darkmode.css"/>
}
15 changes: 12 additions & 3 deletions src/WebApp/Pages/Staff/WorkEntries/Close.cshtml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
@page "{id:Guid?}"
@using MyApp.WebApp.Pages.Shared.EditorTemplates
@using MyApp.WebApp.Platform.Rendering
@model CloseModel

@{
Expand All @@ -9,9 +10,17 @@

<h1>@ViewData["Title"]</h1>

<div class="p-3 border rounded-3">
<partial name="Shared/_WorkEntrySummaryPartial" model="Model.ItemView" />

<div class="p-3 bg-light-subtle border rounded-3">
<h2 class="h4">Status</h2>
<p>@Model.ItemView.Status</p>
<h2 class="h4">Entry Type</h2>
<p>@Model.ItemView.EntryTypeName</p>
<h2 class="h4">Date Received</h2>
<p>@Model.ItemView.ReceivedDate</p>
<h2 class="h4">Notes</h2>
<section class="border border-info p-4 rounded mb-3">
@Html.Raw(MarkdownHelper.MarkdownToHtml(Model.ItemView.Notes))
</section>
<form method="post">
<div class="mb-3">
@Html.EditorFor(model => model.EntryDto.Comments, EditorTemplate.Textarea, new { Rows = 3 })
Expand Down
10 changes: 6 additions & 4 deletions src/WebApp/Pages/Staff/WorkEntries/Details.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
@using MyApp.AppServices.WorkEntries.Permissions
@using MyApp.WebApp.Pages.Shared.DisplayTemplates
@using MyApp.WebApp.Pages.Shared.EditorTemplates
@using MyApp.WebApp.Platform.Rendering
@model DetailsModel
@{
ViewData["Title"] = $"WorkEntry ID {Model.ItemView.Id.ToString()}";
Expand Down Expand Up @@ -85,8 +86,10 @@
</div>

<h2 class="h3">Notes</h2>
<section class="border border-info p-4 rounded mb-3 bg-light-subtle">
@Html.Raw(MarkdownHelper.MarkdownToHtml(Model.ItemView.Notes))
</section>

<p class="container text-break text-pre-line">@Html.DisplayFor(_ => Model.ItemView.Notes, DisplayTemplate.StringOrPlaceholder)</p>

<div class="container">
<dl class="row">
Expand Down Expand Up @@ -197,7 +200,6 @@
</div>
}

@section Scripts
{
@section Scripts {
<partial name="_ValidationScriptsPartial" />
}
}
13 changes: 10 additions & 3 deletions src/WebApp/Pages/Staff/WorkEntries/Edit.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<div class="col-md">
<div class="mb-3">
@Html.EditorFor(model => model.Item.Notes, EditorTemplate.Textarea,
additionalViewData: new { Rows = 5 })
additionalViewData: new { Rows = 5, MDE = true })
</div>
</div>
<div class="col-md">
Expand All @@ -41,7 +41,14 @@
</form>
</div>

@section Scripts
{
@section Scripts {
<partial name="_ValidationScriptsPartial" />
<script src="~/lib/easymde/dist/easymde.min.js"></script>
<script src="~/lib/dompurify/purify.min.js"></script>
<script src="~/js/textarea-to-MDE.js" defer></script>
}

@section Styles {
<link rel="stylesheet" href="~/lib/easymde/dist/easymde.min.css" />
<link rel="stylesheet" href="~/css/easymde.darkmode.css" />
}
16 changes: 16 additions & 0 deletions src/WebApp/Platform/Rendering/Markdown.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using Ganss.Xss;
using Markdig;

namespace MyApp.WebApp.Platform.Rendering
{
public static class MarkdownHelper
{
public static string MarkdownToHtml(string markdown)
{
var pipeline = new MarkdownPipelineBuilder().UseBootstrap().UseAdvancedExtensions().Build();
var sanitizer = new HtmlSanitizer();
sanitizer.AllowedAttributes.Add("class");
return sanitizer.Sanitize(Markdown.ToHtml(markdown, pipeline));
}
}
}
2 changes: 2 additions & 0 deletions src/WebApp/WebApp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="HtmlSanitizer" />
<PackageReference Include="LigerShark.WebOptimizer.Core" />
<PackageReference Include="Markdig" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" />
<PackageReference Include="Microsoft.Identity.Web" />
Expand Down
14 changes: 14 additions & 0 deletions src/WebApp/libman.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,20 @@
"files": [
"anchor.min.js"
]
},
{
"provider": "cdnjs",
"library": "[email protected]",
"destination": "wwwroot/lib/dompurify/"
},
{
"provider": "jsdelivr",
"library": "[email protected]",
"destination": "wwwroot/lib/easymde/",
"files": [
"dist/easymde.min.css",
"dist/easymde.min.js"
]
}
]
}
35 changes: 35 additions & 0 deletions src/WebApp/wwwroot/css/easymde.darkmode.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*Dark Mode color changes*/

[data-bs-theme="dark"] .CodeMirror {
background-color: #212529 !important;
}

[data-bs-theme="dark"] .CodeMirror-placeholder {
color: #f1f1f1 !important;
}

[data-bs-theme="dark"] .CodeMirror-line {
color: white !important;
}
[data-bs-theme="dark"] .CodeMirror-fullscreen.CodeMirror {
background-color: #212529 !important;
}
[data-bs-theme="dark"] .editor-toolbar button:hover {
background: none !important;
}

[data-bs-theme="dark"] .editor-toolbar.fullscreen {
background-color: #343a40 !important;
}

[data-bs-theme="dark"] .editor-toolbar button.active {
background-color: #ffffff20 !important;
}

[data-bs-theme="dark"] .CodeMirror-cursor {
border-left: 2px solid white;
}

[data-bs-theme="dark"] .editor-preview {
background-color: #2d3338 !important;
}
31 changes: 31 additions & 0 deletions src/WebApp/wwwroot/js/textarea-to-MDE.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
const textareaList = document.querySelectorAll("textarea.EasyMDE");
textareaList.forEach((area) => {
new EasyMDE({
renderingConfig: {
sanitizerFunction: (renderedHTML) => {
return DOMPurify.sanitize(renderedHTML, { USE_PROFILES: { html: true } });
},
},
element: area,
placeholder: "Type here...",
toolbar: [
"bold",
"italic",
"|",
"heading-1",
"heading-2",
"heading-3",
"|",
"quote",
"unordered-list",
"ordered-list",
"table",
"|",
"preview",
"side-by-side",
"fullscreen",
"guide",
],
toolbarButtonClassPrefix: "mde",
});
});

0 comments on commit adc4c39

Please sign in to comment.