parent
ecf31568c8
commit
430ab2b50e
|
@ -0,0 +1,14 @@
|
||||||
|
using System.Text.Json;
|
||||||
|
using Markdig.Renderers;
|
||||||
|
using Markdig.Syntax;
|
||||||
|
|
||||||
|
namespace OliverBooth.Markdown.Renderers.EditorJs;
|
||||||
|
|
||||||
|
public class JsonRenderer : RendererBase
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override object Render(MarkdownObject markdownObject)
|
||||||
|
{
|
||||||
|
return JsonDocument.Parse("""{"blocks": []}""");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
using Markdig.Renderers;
|
||||||
|
using Markdig.Syntax;
|
||||||
|
|
||||||
|
namespace OliverBooth.Markdown.Renderers.EditorJs.ObjectRenderers;
|
||||||
|
|
||||||
|
public class HeadingObjectRenderer : IMarkdownObjectRenderer
|
||||||
|
{
|
||||||
|
public bool Accept(RendererBase renderer, Type objectType)
|
||||||
|
{
|
||||||
|
return renderer.GetType() == typeof(JsonRenderer) && objectType == typeof(HeadingBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Write(RendererBase renderer, MarkdownObject objectToRender)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Nodes;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using Markdig.Helpers;
|
||||||
|
using Markdig.Syntax;
|
||||||
|
using Markdig.Syntax.Inlines;
|
||||||
|
|
||||||
|
namespace OliverBooth.Markdown.Renderers.JsonConverters;
|
||||||
|
|
||||||
|
public sealed class HeadingBlockConverter : JsonConverter<HeadingBlock>
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override HeadingBlock? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
var node = JsonNode.Parse(reader.ValueSpan);
|
||||||
|
if (node is not JsonObject jsonObject)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new HeadingBlock(null!)
|
||||||
|
{
|
||||||
|
Level = jsonObject["level"]?.GetValue<int>() ?? 1,
|
||||||
|
Lines = new StringLineGroup(jsonObject["text"]?.GetValue<string>() ?? string.Empty)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Write(Utf8JsonWriter writer, HeadingBlock value, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
if (value.Inline is not { } containerInline)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.WriteStartObject();
|
||||||
|
writer.WriteString("type", "header");
|
||||||
|
writer.WriteNumber("level", value.Level);
|
||||||
|
writer.WritePropertyName("text");
|
||||||
|
|
||||||
|
foreach (Inline inline in containerInline)
|
||||||
|
{
|
||||||
|
if (inline is LiteralInline literal)
|
||||||
|
{
|
||||||
|
var converter = (JsonConverter<LiteralInline>)options.GetConverter(typeof(LiteralInline));
|
||||||
|
writer.WriteStringValue(literal.Content.Text);
|
||||||
|
converter.Write(writer, literal, options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.WriteEndObject();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using Markdig.Syntax.Inlines;
|
||||||
|
|
||||||
|
namespace OliverBooth.Markdown.Renderers.JsonConverters;
|
||||||
|
|
||||||
|
public class LiteralInlineConverter : JsonConverter<LiteralInline>
|
||||||
|
{
|
||||||
|
public override LiteralInline? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
ReadOnlySpan<byte> bytes = reader.ValueSpan;
|
||||||
|
Span<char> chars = stackalloc char[bytes.Length];
|
||||||
|
Encoding.UTF8.GetChars(bytes, chars);
|
||||||
|
return new LiteralInline(chars.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(Utf8JsonWriter writer, LiteralInline value, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
writer.WriteStringValue(value.Content.Text);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using Markdig.Syntax;
|
||||||
|
|
||||||
|
namespace OliverBooth.Markdown.Renderers.JsonConverters;
|
||||||
|
|
||||||
|
public sealed class MarkdownDocumentConverter : JsonConverter<MarkdownDocument>
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override MarkdownDocument Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
var document = new MarkdownDocument();
|
||||||
|
var blocks = JsonSerializer.Deserialize<Block[]>(ref reader, options) ?? Array.Empty<Block>();
|
||||||
|
|
||||||
|
foreach (Block block in blocks)
|
||||||
|
{
|
||||||
|
document.Add(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
return document;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Write(Utf8JsonWriter writer, MarkdownDocument value, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
writer.WriteStartObject();
|
||||||
|
writer.WriteStartArray("blocks");
|
||||||
|
|
||||||
|
foreach (Block block in value)
|
||||||
|
{
|
||||||
|
WriteBlock(writer, options, block);
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.WriteEndArray();
|
||||||
|
writer.WriteEndObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void WriteBlock(Utf8JsonWriter writer, JsonSerializerOptions options, Block block)
|
||||||
|
{
|
||||||
|
switch (block)
|
||||||
|
{
|
||||||
|
case ParagraphBlock paragraphBlock:
|
||||||
|
{
|
||||||
|
var converter = (JsonConverter<ParagraphBlock>)options.GetConverter(typeof(ParagraphBlock));
|
||||||
|
converter.Write(writer, paragraphBlock, options);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case HeadingBlock headingBlock:
|
||||||
|
{
|
||||||
|
var converter = (JsonConverter<HeadingBlock>)options.GetConverter(typeof(HeadingBlock));
|
||||||
|
converter.Write(writer, headingBlock, options);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Nodes;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using Markdig.Helpers;
|
||||||
|
using Markdig.Syntax;
|
||||||
|
|
||||||
|
namespace OliverBooth.Markdown.Renderers.JsonConverters;
|
||||||
|
|
||||||
|
public sealed class ParagraphBlockConverter : JsonConverter<ParagraphBlock>
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override ParagraphBlock? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
var node = JsonNode.Parse(reader.ValueSpan);
|
||||||
|
if (node is not JsonObject jsonObject)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ParagraphBlock
|
||||||
|
{
|
||||||
|
Lines = new StringLineGroup(jsonObject["text"]?.GetValue<string>() ?? string.Empty)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Write(Utf8JsonWriter writer, ParagraphBlock value, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
string text = string.Join('\n', value.Inline);
|
||||||
|
writer.WriteStartObject();
|
||||||
|
writer.WriteString("type", "paragraph");
|
||||||
|
writer.WriteString("text", text);
|
||||||
|
writer.WriteEndObject();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
|
@using System.Text.Json
|
||||||
@using OliverBooth.Common.Data.Blog
|
@using OliverBooth.Common.Data.Blog
|
||||||
@using OliverBooth.Common.Services
|
@using OliverBooth.Common.Services
|
||||||
@implements IDisposable
|
@implements IDisposable
|
||||||
|
@ -7,6 +8,17 @@
|
||||||
@code {
|
@code {
|
||||||
private DotNetObjectReference<MarkdownEditor>? _dotNetHelper;
|
private DotNetObjectReference<MarkdownEditor>? _dotNetHelper;
|
||||||
|
|
||||||
|
[JSInvokable]
|
||||||
|
public string GetEditorObject(Guid id)
|
||||||
|
{
|
||||||
|
if (!BlogPostService.TryGetPost(id, out IBlogPost? post))
|
||||||
|
{
|
||||||
|
return JsonSerializer.Serialize(new { blocks = Array.Empty<object>() });
|
||||||
|
}
|
||||||
|
|
||||||
|
return BlogPostService.GetBlogPostEditorObject(post);
|
||||||
|
}
|
||||||
|
|
||||||
[JSInvokable]
|
[JSInvokable]
|
||||||
public void Save(Guid id, string content)
|
public void Save(Guid id, string content)
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,13 +7,18 @@ import SaveButtonMode from "./MarkdownEditor/SaveButtonMode";
|
||||||
import EditorJS from "@editorjs/editorjs";
|
import EditorJS from "@editorjs/editorjs";
|
||||||
import Header from "@editorjs/header";
|
import Header from "@editorjs/header";
|
||||||
import SimpleImage from "./BlockTools/SimpleImage";
|
import SimpleImage from "./BlockTools/SimpleImage";
|
||||||
|
import Utility from "../app/Utility";
|
||||||
|
|
||||||
(() => {
|
(() => {
|
||||||
getCurrentBlogPost().then(post => {
|
getCurrentBlogPost().then(async post => {
|
||||||
if (!post) {
|
if (!post) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await Utility.delay(1000); // hack to wait for setDotNetHelper invocation. TODO fix this shit
|
||||||
|
const blocks = JSON.parse(await Interop.invoke<string>("GetEditorObject", post.id));
|
||||||
|
console.log("JSON object is", blocks);
|
||||||
|
|
||||||
// UI.init();
|
// UI.init();
|
||||||
// UI.addSaveButtonListener(savePost);
|
// UI.addSaveButtonListener(savePost);
|
||||||
|
|
||||||
|
@ -29,7 +34,8 @@ import SimpleImage from "./BlockTools/SimpleImage";
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
image: SimpleImage
|
image: SimpleImage
|
||||||
}
|
},
|
||||||
|
data: blocks
|
||||||
});
|
});
|
||||||
|
|
||||||
/*const editor = new MarkdownEditor(UI.markdownInput);
|
/*const editor = new MarkdownEditor(UI.markdownInput);
|
||||||
|
|
|
@ -16,6 +16,7 @@ class BlogPost {
|
||||||
private readonly _formattedPublishDate: string;
|
private readonly _formattedPublishDate: string;
|
||||||
private readonly _formattedUpdateDate: string;
|
private readonly _formattedUpdateDate: string;
|
||||||
private readonly _tags: string[];
|
private readonly _tags: string[];
|
||||||
|
private readonly _blockData: [{ id: string, type: string, data: any }];
|
||||||
|
|
||||||
constructor(json: any) {
|
constructor(json: any) {
|
||||||
this._id = json.id;
|
this._id = json.id;
|
||||||
|
@ -33,6 +34,11 @@ class BlogPost {
|
||||||
this._formattedPublishDate = json.formattedPublishDate;
|
this._formattedPublishDate = json.formattedPublishDate;
|
||||||
this._formattedUpdateDate = json.formattedUpdateDate;
|
this._formattedUpdateDate = json.formattedUpdateDate;
|
||||||
this._tags = json.tags;
|
this._tags = json.tags;
|
||||||
|
this._blockData = json.blockData;
|
||||||
|
}
|
||||||
|
|
||||||
|
get blockData(): [{ id: string, type: string, data: any }] {
|
||||||
|
return this._blockData;
|
||||||
}
|
}
|
||||||
|
|
||||||
get id(): string {
|
get id(): string {
|
||||||
|
@ -70,7 +76,7 @@ class BlogPost {
|
||||||
get url(): BlogUrl {
|
get url(): BlogUrl {
|
||||||
return this._url;
|
return this._url;
|
||||||
}
|
}
|
||||||
|
|
||||||
get tags(): string[] {
|
get tags(): string[] {
|
||||||
return this._tags;
|
return this._tags;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
class Utility {
|
||||||
|
public static delay(timeout: number): Promise<void> {
|
||||||
|
return new Promise(resolve => setTimeout(resolve, timeout));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Utility;
|
Loading…
Reference in New Issue