!2829 feat: add cherry-markdown

* chore: 更新依赖包
* refactor: 更新组件到 0.7.3
* 升级cherrymarkdown版本到0.7.3
* doc: 更新示例文档
* doc: 更新参数注释
* doc: 更新菜单
* chore: 更新资源文件
* refactor: 更新组件 logo
* Merge branch 'main' into dev-CherryMarkdown
* chore: 更新打包文件
* feat: 增加客户端文件键值防止大文件并行上传键值覆盖问题
* chore: 格式化脚本更改缓存键值
* fix: 增加 using 释放文件流
* refactor: 重构代码增加兼容 NET5 代码
* chore: 更新项目配置文件
* chore: 更新打包文件
* Merge branch 'main' into dev-CherryMarkdown
* update
* update
* update
* update
* update
* update
* update
This commit is contained in:
j4587698
2022-05-28 01:59:33 +00:00
committed by Argo
parent b2d528fced
commit 22a4216416
27 changed files with 887 additions and 0 deletions

View File

@@ -120,6 +120,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BootstrapBlazor.AzureSpeech
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BootstrapBlazor.BaiduSpeech", "src\Extensions\Components\BootstrapBlazor.BaiduSpeech\BootstrapBlazor.BaiduSpeech.csproj", "{4ED606D8-D252-4573-8F0F-B69502ADB7ED}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BootstrapBlazor.CherryMarkdown", "src\Extensions\Components\BootstrapBlazor.CherryMarkdown\BootstrapBlazor.CherryMarkdown.csproj", "{018091B3-1E3A-41F3-87B2-5F285C2C3B73}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BootstrapBlazor.SummerNote", "src\Extensions\Components\BootstrapBlazor.SummerNote\BootstrapBlazor.SummerNote.csproj", "{2FFC1564-EF75-454B-9D8E-A437A1737CEC}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTestEditor", "test\UnitTestEditor\UnitTestEditor.csproj", "{9552B649-17E2-4BCA-8774-664C83A960CB}"
@@ -200,6 +202,10 @@ Global
{4ED606D8-D252-4573-8F0F-B69502ADB7ED}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4ED606D8-D252-4573-8F0F-B69502ADB7ED}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4ED606D8-D252-4573-8F0F-B69502ADB7ED}.Release|Any CPU.Build.0 = Release|Any CPU
{018091B3-1E3A-41F3-87B2-5F285C2C3B73}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{018091B3-1E3A-41F3-87B2-5F285C2C3B73}.Debug|Any CPU.Build.0 = Debug|Any CPU
{018091B3-1E3A-41F3-87B2-5F285C2C3B73}.Release|Any CPU.ActiveCfg = Release|Any CPU
{018091B3-1E3A-41F3-87B2-5F285C2C3B73}.Release|Any CPU.Build.0 = Release|Any CPU
{2FFC1564-EF75-454B-9D8E-A437A1737CEC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2FFC1564-EF75-454B-9D8E-A437A1737CEC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2FFC1564-EF75-454B-9D8E-A437A1737CEC}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -244,6 +250,7 @@ Global
{C28717F8-9D2B-4296-9CC4-94882338F370} = {CD062AB6-244D-402A-8F33-C37DAC5856CC}
{42108A8A-C773-4F35-A870-3673BDD383E4} = {CD062AB6-244D-402A-8F33-C37DAC5856CC}
{4ED606D8-D252-4573-8F0F-B69502ADB7ED} = {CD062AB6-244D-402A-8F33-C37DAC5856CC}
{018091B3-1E3A-41F3-87B2-5F285C2C3B73} = {CD062AB6-244D-402A-8F33-C37DAC5856CC}
{2FFC1564-EF75-454B-9D8E-A437A1737CEC} = {CD062AB6-244D-402A-8F33-C37DAC5856CC}
{9552B649-17E2-4BCA-8774-664C83A960CB} = {7C1D79F1-87BC-42C1-BD5A-CDE4044AC1BD}
{6312863E-771D-4EFE-9B9D-071A01222E7A} = {CD062AB6-244D-402A-8F33-C37DAC5856CC}

View File

@@ -20,6 +20,7 @@
<ItemGroup>
<PackageReference Include="BootstrapBlazor.BaiduSpeech" Version="6.*" />
<PackageReference Include="BootstrapBlazor.Chart" Version="6.*" />
<PackageReference Include="BootstrapBlazor.CherryMarkdown" Version="6.*" />
<PackageReference Include="BootstrapBlazor.Markdown" Version="6.*" />
<PackageReference Include="BootstrapBlazor.OnScreenKeyboard" Version="6.*" />
<PackageReference Include="BootstrapBlazor.SignaturePad" Version="6.*" />

View File

@@ -2735,6 +2735,7 @@
"InputNumber": "InputNumber",
"Ip": "IpAddress",
"Markdown": "Markdown",
"CherryMarkdown": "Cherry-Markdown",
"MultiSelect": "MultiSelect",
"Radio": "Radio",
"Rate": "Rate",

View File

@@ -2744,6 +2744,7 @@
"InputGroup": "输入组 InputGroup",
"Ip": "IP 地址 IpAddress",
"Markdown": "富文本框 Markdown",
"CherryMarkdown": "腾讯文本框 Markdown",
"MultiSelect": "多项选择器 MultiSelect",
"Radio": "单选框 Radio",
"Rate": "评分 Rate",

View File

@@ -0,0 +1,39 @@
@page "/cherry-markdowns"
<h3>CherryMarkdown 腾讯富文本框</h3>
<h4>基于 CherryMarkdown 的富文本框组件</h4>
<DemoBlock Title="基础用法" Introduction="使用双向绑定获取对应的 <code>html</code> 和 <code>markdown</code> 内容">
<CherryMarkdown @bind-Value="MarkdownString" @bind-Html="HtmlString" style="height: 400px"></CherryMarkdown>
<div class="mt-3">
<textarea class="form-control" rows="6" disabled="disabled">
@MarkdownString
</textarea>
</div>
<div class="mt-3">
<textarea class="form-control" rows="6" disabled="disabled">
@HtmlString
</textarea>
</div>
</DemoBlock>
<DemoBlock Title="自行处理文件上传事件" Introduction="使用<code>OnFileUpload</code>事件处理文件上传事件,支持直接粘贴图片到浏览器">
<CherryMarkdown OnFileUpload="OnFileUpload"></CherryMarkdown>
</DemoBlock>
<DemoBlock Title="自定义内容" Introduction="通过<code>ToolbarSettings</code>自定义工具栏,通过<code>EditorSettings</code>自定义编辑器样式">
<CherryMarkdown ToolbarSettings="@ToolbarSettings" EditorSettings="@EditorSettings"></CherryMarkdown>
</DemoBlock>
<DemoBlock Title="浏览模式" Introduction="纯浏览模式,没有编辑器">
<CherryMarkdown @bind-Value="MarkdownString" @bind-Html="HtmlString" style="height: 400px" IsViewer="true"></CherryMarkdown>
</DemoBlock>
<DemoBlock Title="外部控制组件" Introduction="使用CherryMarkdown的Api在外部控制内容">
<CherryMarkdown @ref="@MarkdownElement"></CherryMarkdown>
<Button OnClick="@(async () => { await MarkdownElement.DoMethodAsync("toolbar.toolbarHandlers.insert", "checklist");})">插入一个CheckList</Button>
<Button OnClick="@(async () => { await MarkdownElement.DoMethodAsync("insert", "![一张图片](https://i.niupic.com/images/2022/04/01/9Y6T.jpg)", false, false, true);})">插入一张图片</Button>
</DemoBlock>
<AttributeTable Items="GetAttributes()"></AttributeTable>

View File

@@ -0,0 +1,96 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
// Website: https://www.blazor.zone or https://argozhang.github.io/
using BootstrapBlazor.Components;
using BootstrapBlazor.Shared.Common;
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Options;
namespace BootstrapBlazor.Shared.Samples;
/// <summary>
///
/// </summary>
public partial class CherryMarkdowns
{
private string? MarkdownString { get; set; }
private string? HtmlString { get; set; }
[NotNull]
private CherryMarkdown? MarkdownElement { get; set; }
private EditorSettings EditorSettings { get; set; } = new EditorSettings() { DefaultModel = "editOnly" };
private ToolbarSettings ToolbarSettings { get; set; } =
new ToolbarSettings() { Toolbar = new List<object> { "italic", new { insert = new List<string>() { "image" } } }, Bubble = new List<string>() { "bold" }, Float = new List<string>() { "h1" } };
[Inject]
[NotNull]
private IOptionsMonitor<WebsiteOptions>? SiteOptions { get; set; }
/// <summary>
/// OnInitialized
/// </summary>
protected override void OnInitialized()
{
base.OnInitialized();
MarkdownString = "# test";
}
private async Task<string> OnFileUpload(CherryMarkdownUploadFile arg)
{
var url = Path.Combine("images", "uploader",
$"{Path.GetFileNameWithoutExtension(arg.FileName)}-{DateTimeOffset.Now:yyyyMMddHHmmss}{Path.GetExtension(arg.FileName)}");
var fileName = Path.Combine(SiteOptions.CurrentValue.WebRootPath, url);
var ret = await arg.SaveToFile(fileName);
return ret ? url : "";
}
private IEnumerable<AttributeItem> GetAttributes() => new AttributeItem[]
{
new AttributeItem(){
Name = "EditorSettings",
Description = "编辑器设置",
Type = "EditorSettings",
ValueList = " — ",
DefaultValue = " — "
},
new AttributeItem(){
Name = "ToolbarSettings",
Description = "工具栏设置",
Type = "ToolbarSettings",
ValueList = " — ",
DefaultValue = " — "
},
new AttributeItem(){
Name = "Value",
Description = "组件值",
Type = "string",
ValueList = " — ",
DefaultValue = " — "
},
new AttributeItem(){
Name = "Html",
Description = "组件 Html 代码",
Type = "string",
ValueList = " — ",
DefaultValue = " — "
},
new AttributeItem(){
Name = "OnFileUpload",
Description = "文件上传回调方法",
Type = "Func<CherryMarkdownUploadFile, Task<string>>",
ValueList = " — ",
DefaultValue = " — "
},
new AttributeItem(){
Name = "IsViewer",
Description = "组件是否为浏览器模式",
Type = "bool",
ValueList = "true/false",
DefaultValue = "false"
}
};
}

View File

@@ -346,6 +346,12 @@ public sealed partial class NavMenu
Url = "markdowns"
},
new()
{
IsNew = true,
Text = Localizer["CherryMarkdown"],
Url = "cherry-markdowns"
},
new()
{
Text = Localizer["MultiSelect"],
Url = "multiselects"

View File

@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">
<Import Project="..\..\..\bundleconfig.props" />
<PropertyGroup>
<Version>6.0.1</Version>
</PropertyGroup>
<ItemGroup>
<Content Remove="wwwroot\css\cherry-markdown.min.css" />
<Content Remove="wwwroot\js\cherry-markdown.min.js" />
<None Include="wwwroot\css\cherry-markdown.min.css" />
<None Include="wwwroot\js\cherry-markdown.min.js" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\..\..\BootstrapBlazor\Extensions\JSRuntimeExtensions.cs" Link="JSRuntimeExtensions.cs" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,79 @@
export function bb_cherry_markdown(el, value, method, obj) {
BootstrapBlazorModules.addLink('_content/BootstrapBlazor.CherryMarkdown/css/bootstrap.blazor.cherrymarkdown.min.css');
var $el = $(el);
if (method === "init") {
if (value.toolbars.toolbar === null) {
delete value.toolbars.toolbar;
}
if (value.toolbars.bubble === null) {
delete value.toolbars.bubble;
}
if (value.toolbars.float === null) {
delete value.toolbars.float;
}
var handler = window.setInterval(function () {
if ($el.is(':visible')) {
window.clearInterval(handler);
var editor = new Cherry({
el: el,
value: value.value,
fileUpload(file, callback) {
var id = $.getUID('md');
if (window.cherryMarkdownUploadFiles === undefined) {
window.cherryMarkdownUploadFiles = {};
}
window.cherryMarkdownUploadFiles[id] = file;
obj.invokeMethodAsync('Upload', id, {
fileName: file.name,
fileSize: file.size,
contentType: file.type,
lastModified: new Date(file.lastModified).toISOString(),
}).then(data => {
if (data !== "") {
callback(data);
}
})
},
editor: value.editor,
toolbars: value.toolbars,
callback: {
afterChange: function (markdown, html) {
obj.invokeMethodAsync('Update', [markdown, html]);
}
}
});
$.data(el, 'bb_cherry_md_editor', editor);
}
}, 100);
} else if (method === 'setMarkdown') {
var editor = $.data(el, 'bb_cherry_md_editor');
editor.setMarkdown(value, true);
}
}
export function bb_cherry_markdown_file(id) {
var file = window.cherryMarkdownUploadFiles[id];
delete window.cherryMarkdownUploadFiles[id];
return file
}
export function bb_cherry_markdown_method(el, method, parameter, obj) {
var md = $.data(el, 'bb_cherry_md_editor');
if (md) {
if (method.indexOf('.') < 0) {
md[method](...parameter)
} else {
var methods = method.split('.');
var m = md[methods[0]];
for (let i = 1; i < methods.length; i++) {
m = m[methods[i]]
}
m(...parameter);
}
var val = md.getMarkdown();
var html = md.getHtml();
obj.invokeMethodAsync('Update', [val, html]);
}
}

View File

@@ -0,0 +1 @@
export function bb_cherry_markdown(n,t,i,r){var u,f,e;BootstrapBlazorModules.addLink("_content/BootstrapBlazor.CherryMarkdown/css/bootstrap.blazor.cherrymarkdown.min.css");u=$(n);i==="init"?(t.toolbars.toolbar===null&&delete t.toolbars.toolbar,t.toolbars.bubble===null&&delete t.toolbars.bubble,t.toolbars.float===null&&delete t.toolbars.float,f=window.setInterval(function(){if(u.is(":visible")){window.clearInterval(f);var i=new Cherry({el:n,value:t.value,fileUpload(n,t){var i=$.getUID("md");window.cherryMarkdownUploadFiles===undefined&&(window.cherryMarkdownUploadFiles={});window.cherryMarkdownUploadFiles[i]=n;r.invokeMethodAsync("Upload",i,{fileName:n.name,fileSize:n.size,contentType:n.type,lastModified:new Date(n.lastModified).toISOString()}).then(n=>{n!==""&&t(n)})},editor:t.editor,toolbars:t.toolbars,callback:{afterChange:function(n,t){r.invokeMethodAsync("Update",[n,t])}}});$.data(n,"bb_cherry_md_editor",i)}},100)):i==="setMarkdown"&&(e=$.data(n,"bb_cherry_md_editor"),e.setMarkdown(t,!0))}export function bb_cherry_markdown_file(n){var t=window.cherryMarkdownUploadFiles[n];return delete window.cherryMarkdownUploadFiles[n],t}export function bb_cherry_markdown_method(n,t,i,r){var u=$.data(n,"bb_cherry_md_editor"),f,e,o,s;if(u){if(t.indexOf(".")<0)u[t](...i);else{f=t.split(".");e=u[f[0]];for(let n=1;n<f.length;n++)e=e[f[n]];e(...i)}o=u.getMarkdown();s=u.getHtml();r.invokeMethodAsync("Update",[o,s])}}

View File

@@ -0,0 +1,6 @@
@namespace BootstrapBlazor.Components
@inherits BootstrapComponentBase
<div @attributes="@AdditionalAttributes" @ref="MarkdownElement">
</div>

View File

@@ -0,0 +1,212 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
// Website: https://www.blazor.zone or https://argozhang.github.io/
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.JSInterop;
namespace BootstrapBlazor.Components;
/// <summary>
///
/// </summary>
public partial class CherryMarkdown : IAsyncDisposable
{
private readonly CherryMarkdownOption _option = new();
/// <summary>
/// 获得/设置 编辑器设置
/// </summary>
[Parameter]
public EditorSettings? EditorSettings { get; set; }
/// <summary>
/// 获得/设置 工具栏设置
/// </summary>
[Parameter]
public ToolbarSettings? ToolbarSettings { get; set; }
private string? _value;
/// <summary>
/// 获得/设置 组件值
/// </summary>
[Parameter]
public string? Value
{
get => _value;
set
{
if (_value != value)
{
_value = value;
IsRender = true;
}
}
}
/// <summary>
/// 获得/设置 组件值回调
/// </summary>
[Parameter]
public EventCallback<string?> ValueChanged { get; set; }
/// <summary>
/// 获得/设置 组件 Html 代码
/// </summary>
[Parameter]
public string? Html { get; set; }
/// <summary>
/// 获得/设置 组件 Html 代码回调
/// </summary>
[Parameter]
public EventCallback<string?> HtmlChanged { get; set; }
/// <summary>
/// 获得/设置 Markdown组件内上传文件时回调此方法
/// </summary>
[Parameter]
public Func<CherryMarkdownUploadFile, Task<string>>? OnFileUpload { get; set; }
/// <summary>
/// 获取/设置 组件是否为浏览器模式
/// </summary>
[Parameter]
public bool? IsViewer { get; set; }
/// <summary>
/// 获得/设置 DOM 元素实例
/// </summary>
private ElementReference MarkdownElement { get; set; }
private bool IsRender { get; set; }
[NotNull]
private JSModule<CherryMarkdown>? Module { get; set; }
/// <summary>
/// OnInitialized 方法
/// </summary>
protected override void OnInitialized()
{
base.OnInitialized();
_option.Value = _value;
_option.Editor = EditorSettings ?? new EditorSettings();
_option.Toolbars = ToolbarSettings ?? new ToolbarSettings();
if (IsViewer == true)
{
_option.Editor.DefaultModel = "previewOnly";
_option.Toolbars.Toolbar = false;
}
}
/// <summary>
/// OnAfterRenderAsync 方法
/// </summary>
/// <param name="firstRender"></param>
/// <returns></returns>
protected override async Task OnAfterRenderAsync(bool firstRender)
{
await base.OnAfterRenderAsync(firstRender);
if (firstRender)
{
IsRender = false;
Module = await JSRuntime.LoadModule<CherryMarkdown>("./_content/BootstrapBlazor.CherryMarkdown/js/bootstrap.blazor.cherrymarkdown.min.js", this, false);
await Module.InvokeVoidAsync("bb_cherry_markdown", MarkdownElement, _option, "init");
}
if (IsRender)
{
await Module.InvokeVoidAsync("bb_cherry_markdown", MarkdownElement, Value ?? "", "setMarkdown");
}
}
/// <summary>
/// 文件上传回调
/// </summary>
/// <param name="id"></param>
/// <param name="uploadFile"></param>
[JSInvokable]
public async Task<string> Upload(string id, CherryMarkdownUploadFile uploadFile)
{
#if NET6_0_OR_GREATER
var stream = await Module.InvokeAsync<IJSStreamReference>("bb_cherry_markdown_file", id);
using var data = await stream.OpenReadStreamAsync();
uploadFile.UploadStream = data;
var ret = "";
if (OnFileUpload != null)
{
ret = await OnFileUpload.Invoke(uploadFile);
}
return ret;
#else
await Task.Yield();
throw new NotSupportedException();
#endif
}
/// <summary>
/// 更新组件值方法
/// </summary>
/// <param name="vals"></param>
/// <returns></returns>
[JSInvokable]
public async Task Update(string[] vals)
{
if (vals.Length == 2)
{
var hasChanged = !EqualityComparer<string>.Default.Equals(vals[0], Value);
if (hasChanged)
{
_value = vals[0];
if (ValueChanged.HasDelegate)
{
await ValueChanged.InvokeAsync(Value);
}
}
hasChanged = !EqualityComparer<string>.Default.Equals(vals[1], Html);
if (hasChanged)
{
Html = vals[1];
if (HtmlChanged.HasDelegate)
{
await HtmlChanged.InvokeAsync(Html);
}
}
}
}
/// <summary>
/// 执行方法
/// </summary>
/// <param name="method"></param>
/// <param name="parameters"></param>
/// <returns></returns>
public ValueTask DoMethodAsync(string method, params object[] parameters) => Module.InvokeVoidAsync("bb_cherry_markdown_method", MarkdownElement, method, parameters);
/// <summary>
/// Dispose 方法
/// </summary>
/// <param name="disposing"></param>
protected virtual async ValueTask DisposeAsync(bool disposing)
{
if (disposing)
{
if (Module != null)
{
await Module.DisposeAsync();
}
}
}
/// <summary>
/// Dispose 方法
/// </summary>
public async ValueTask DisposeAsync()
{
await DisposeAsync(true);
GC.SuppressFinalize(this);
}
}

View File

@@ -0,0 +1,26 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
// Website: https://www.blazor.zone or https://argozhang.github.io/
namespace BootstrapBlazor.Components;
/// <summary>
/// 配置信息
/// </summary>
internal class CherryMarkdownOption
{
/// <summary>
/// 初始值
/// </summary>
public string? Value { get; set; }
/// <summary>
/// 编辑器选项
/// </summary>
public EditorSettings? Editor { get; set; }
/// <summary>
/// 工具栏选项
/// </summary>
public ToolbarSettings? Toolbars { get; set; }
}

View File

@@ -0,0 +1,108 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
// Website: https://www.blazor.zone or https://argozhang.github.io/
namespace BootstrapBlazor.Components;
/// <summary>
/// 文件信息
/// </summary>
public class CherryMarkdownUploadFile
{
/// <summary>
/// 文件名
/// </summary>
public string? FileName { get; set; }
/// <summary>
/// 文件大小
/// </summary>
public long FileSize { get; set; }
/// <summary>
/// 最后修改日期
/// </summary>
public string? LastModified { get; set; }
/// <summary>
/// 文件类型
/// </summary>
public string? ContentType { get; set; }
/// <summary>
/// 上传的文件流
/// </summary>
public Stream? UploadStream { get; set; }
/// <summary>
/// 返回码0为成功非0失败
/// </summary>
public int Code { get; set; }
/// <summary>
/// 错误信息
/// </summary>
public string? Error { get; set; }
/// <summary>
/// 保存到文件
/// </summary>
/// <param name="fileName"></param>
/// <param name="token"></param>
/// <returns></returns>
public async Task<bool> SaveToFile(string fileName, CancellationToken token = default)
{
var ret = false;
if (UploadStream != null)
{
// 文件保护,如果文件存在则先删除
if (System.IO.File.Exists(fileName))
{
try
{
System.IO.File.Delete(fileName);
}
catch (Exception ex)
{
Code = 1002;
Error = ex.Message;
}
}
var folder = Path.GetDirectoryName(fileName);
if (!string.IsNullOrEmpty(folder) && !Directory.Exists(folder))
{
Directory.CreateDirectory(folder);
}
if (Code == 0)
{
using var uploadFile = File.OpenWrite(fileName);
try
{
// 打开文件流
var stream = UploadStream;
var buffer = new byte[4 * 1096];
int bytesRead = 0;
// 开始读取文件
while ((bytesRead = await stream.ReadAsync(buffer, token)) > 0)
{
await uploadFile.WriteAsync(buffer.AsMemory(0, bytesRead), token);
}
ret = true;
}
catch (Exception ex)
{
Code = 1003;
Error = ex.Message;
}
}
}
return ret;
}
}

View File

@@ -0,0 +1,34 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
// Website: https://www.blazor.zone or https://argozhang.github.io/
namespace BootstrapBlazor.Components;
/// <summary>
/// 编辑器设置
/// </summary>
public class EditorSettings
{
/// <summary>
/// CodeMirror主题默认为 default
/// </summary>
public string Theme { get; set; } = "default";
/// <summary>
/// 编辑器高度默认为100%
/// </summary>
public string Height { get; set; } = "100%";
/// <summary>
/// 编辑器显示模式
/// edit&amp;preview: 双栏编辑预览模式,默认值
/// editOnly: 只显示编辑器
/// previewOnly: 预览模式
/// </summary>
public string DefaultModel { get; set; } = "edit&preview";
/// <summary>
/// 粘贴Html时自动转换为Markdown格式
/// </summary>
public bool ConvertWhenPaste { get; set; } = true;
}

View File

@@ -0,0 +1,31 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
// Website: https://www.blazor.zone or https://argozhang.github.io/
namespace BootstrapBlazor.Components;
/// <summary>
/// 状态栏设置
/// </summary>
public class ToolbarSettings
{
/// <summary>
/// 主题light 、dark默认值
/// </summary>
public string Theme { get; set; } = "dark";
/// <summary>
/// 自定义工具栏按钮null则为默认工具栏false则不显示工具栏
/// </summary>
public object? Toolbar { get; set; }
/// <summary>
/// 选中后的悬浮菜单null为默认悬浮菜单false则不显示悬浮菜单
/// </summary>
public object? Bubble { get; set; }
/// <summary>
/// 新行的悬浮菜单null为默认悬浮菜单false则不显示悬浮菜单
/// </summary>
public object? Float { get; set; }
}

View File

@@ -0,0 +1,31 @@
[
{
"outputFileName": "wwwroot/css/bootstrap.blazor.cherrymarkdown.min.css",
"inputFiles": [
"wwwroot/css/cherry-markdown.min.css",
"Components/**/*.css"
]
},
{
"outputFileName": "Components/CherryMarkdown/CherryMarkdown.min.js",
"inputFiles": [
"Components/CherryMarkdown/CherryMarkdown.js"
],
"minify": {
"enabled": true,
"renameLocals": true
}
},
{
"outputFileName": "wwwroot/js/bootstrap.blazor.cherrymarkdown.min.js",
"inputFiles": [
"wwwroot/js/cherry-markdown.min.js",
"Components/**/*.min.js"
],
"minify": {
"enabled": false,
"renameLocals": true
},
"sourceMap": false
}
]

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 197 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long