Coder Social home page Coder Social logo

nodsoft / moltenobsidian Goto Github PK

View Code? Open in Web Editor NEW
60.0 4.0 2.0 2.86 MB

Obsidian-flavoured Markdown parsing library for .NET 6+, with support for Obsidian Vaults navigation.

Home Page: https://moltenobsidian.dev

License: MIT License

HTML 5.82% C# 80.34% TypeScript 4.02% JavaScript 0.11% Astro 4.47% SCSS 5.24%
aspnetcore blazor dotnet extensions html library markdown obsidian obsidian-md obsidian-vault

moltenobsidian's Introduction

logo

MoltenObsidian

.NET 6+ Library for Obsidian-flavoured Markdown parsing, with support for vault mapping and Blazor.


GitHub Actions Workflow Status NuGet Core Version NuGet Core Preversion NuGet Downloads
โ€‹

Premise

Molten Obsidian is a high-performance library designed as an easily integrated and lightweight FOSS alternative to Obsidian Publish. With extensibility and integration-oriented conception, this library makes it perfect for integrating Obsidian-flavoured markdown notes on your Blazor App, but also importing entire vaults as a navigation-ready area, with full routing support.

Furthermore, Molten Obisidian extends past the original Obsidian specifications, aiming to supercharge your documentation/wiki applications and websites needs, using a customizable data source interface, and supercharged YAML frontmatter capabilities.

Example

Converting an Obsidian-flavoured Markdown note to HTML is as simple as this :

using Nodsoft.MoltenObsidian;

// Create a new ObsidianText instance with the content to convert
ObsidianText obsidianMarkdown = new(@"
# Hello, world!   

This is a sample Markdown document.    
And a paragraph with **bold** and *italic* text.
");

// This is the HTML string you can then call in Blazor components as `@htmlText`.
MarkupString htmlText = obsidianMarkdown.ToHtml();

But that's just the basics. Under the hood, Markdig is what makes it happen. Easy!

Now let's open an Obsidian vault on the Filesystem, and wire it to a routable Blazor component :

Startup.cs

using Nodsoft.MoltenObsidian.Blazor;
using Nodsoft.MoltenObsidian.Vault;
using Nodsoft.MoltenObsidian.Vaults.FileSystem;

// First deal with the DI, by adding a Filesystem vault and the Blazor integration:
public void ConfigureServices(IServiceCollection services)
{
	services.AddMoltenObsidianFileSystemVault(new DirectoryInfo("/path/to/vault"));
	services.AddMoltenObsidianBlazorIntegration();
}

_Imports.razor

@using Nodsoft.MoltenObsidian.Blazor
@using Nodsoft.MoltenObsidian.Blazor.Helpers;
@using Nodsoft.MoltenObsidian.Vault;

VaultPage.razor

@page "/vault/{*VaultPath}"  
@inject IVault Vault   
  
<ObsidianVaultDisplay BasePath="@this.GetCallingBaseVaultPath()" CurrentPath="@VaultPath" />  
  
@code {  
   [Parameter]  
   public string VaultPath { get; set; }
}

In a matter of minutes, you've just created a web app integration for your own Obsidian Vault, for all to see. Congratulations!

Now, let's take it further.

Customizations

Vault sources (see: Vaults)

Molten Obsidian is designed with extensibility at its core, and allows you to implement your own Vault source. Should the existing reference Vault providers not be suitable for your Vault storage needs, you can provide your own implementation.

A few examples of additional stores you can implement:

  • Database store (xSQL, MongoDB, etc...)
  • Over-the-wire/Network-based (NFS, etc...)
  • VCS-based (Git repo)

If you're finding yourself implementing any of these, feel free to PR! We'll be more than happy to support new vault providers.

Layouts

Molten Obsidian is meant to tailor itself to your app. As such, you can provide within the Blazor Component a series of RenderFragment delegates responsible for organizing the Vault display.

You can provide them in cascade, as such :

<ObsidianVaultDisplay BasePath="@this.GetCallingBaseVaultPath()" CurrentPath="@VaultPath">  
   <FoundFile Context="file">  
      <h1>Vault note: @file.NoteName</h1>  
      <a class="lead text-muted" href="@file.Parent?.Path">Return to @(file.Parent?.Name ?? "Root")</a>  
  
      <hr />  
  
      @(new MarkupString(file.ReadDocument().ToHtml()))  
   </FoundFile>  
  
   <NotFound>  
      <h3 class="text-warning">Sorry, there is nothing here.</h3>  
   </NotFound>  
</ObsidianVaultDisplay>

Alternatively, you can provide delegates, like so :

<ObsidianVaultDisplay BasePath="@this.GetCallingBaseVaultPath()" CurrentPath="@VaultPath"  
   FoundFile="OnFoundFile"  
   NotFound="OnNotFound"  
/>  

@code {  
   public static RenderFragment OnFoundFile(IVaultNote file) => __builder =>  
   {  
      <h1>Vault note: @file.NoteName</h1>  
      <a class="lead text-muted" href="@file.Parent?.Path">Return to @(file.Parent?.Name ?? "Root")</a>  

      <hr />  

      @(new MarkupString(file.ReadDocument().ToHtml()))  
   };  
     
   public static RenderFragment OnNotFound(string _) => static __builder =>  
   {  
      <h3 class="text-warning">Sorry, there's nothing here.</h3>  
   }; 
}

CLI Tool

Our CLI tool aims at cutting down the menial tasks associated with implementing more advanced features of Molten Obsidian, allowing you to better focus on what matters, but also automating any of those integration tasks within you workflow.

moltenobsidian's People

Contributors

sakuraisayeki avatar spencernaugler7 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

moltenobsidian's Issues

Git Hooks / GH Actions integrations for MoltenObsidian

Context

During updates of a MoltenObsidian vault, the integration of changes should be streamlined as much as possible.

Problem

Updates to a MoltenObsidian manifest are currently not automatable outside of manually trigerring a command, prior to committing.

Solution

The integration of a Git commit hook or a GitHub Actions CI step allows some automation to take place.
Further research should be lead into this subject, to determine pros & cons of each method.

`IWritableVault`: Support for renaming entities

Problem

As a downstream developer, I have no key-in-hand solution to rename a vault entity. I must implement my own solution.

Solution

Implement three new methods to IWritableVault:

/// <summary>
/// Moves a folder to a new location.
/// </summary>
/// <param name="sourcePath">The path of the folder to move.</param>
/// <param name="destinationPath">The path to move the folder to.</param>
/// <returns>A task containing the moved folder as its result.</returns>
/// <exception cref="ArgumentException">Thrown if the specified path is invalid.</exception>
/// <exception cref="InvalidOperationException">Thrown if a folder with the specified path already exists.</exception>
/// <exception cref="IOException">Thrown if an I/O error occurs.</exception>
ValueTask<IVaultFolder> MoveFolderAsync(string sourcePath, string destinationPath);

/// <summary>
/// Moves a file to a new location.
/// </summary>
/// <param name="sourcePath">The path of the file to move.</param>
/// <param name="destinationPath">The path to move the file to.</param>
/// <returns>A task containing the moved file as its result.</returns>
/// <exception cref="ArgumentException">Thrown if the specified path is invalid.</exception>
/// <exception cref="InvalidOperationException">Thrown if a file with the specified path already exists.</exception>
/// <exception cref="IOException">Thrown if an I/O error occurs.</exception>
ValueTask<IVaultFile> MoveFileAsync(string sourcePath, string destinationPath);

/// <summary>
/// Moves a note to a new location.
/// </summary>
/// <param name="sourcePath">The path of the note to move.</param>
/// <param name="destinationPath">The path to move the note to.</param>
/// <returns>A task containing the moved note as its result.</returns>
/// <exception cref="ArgumentException">Thrown if the specified path is invalid.</exception>
/// <exception cref="InvalidOperationException">Thrown if a note with the specified path already exists.</exception>
/// <exception cref="IOException">Thrown if an I/O error occurs.</exception>
ValueTask<IVaultNote> MoveNoteAsync(string sourcePath, string destinationPath);

Notes

Given the complexity in propagating changes, and the as of yet limited utility in entity renaming, we deliberately omitted the implementation of rename operations. This issue aims at implementing this feature as needed, at a later time.

Support for Tags

Premise

To fully support Obsidian-flavoured Markdown, we need to implement support for Tags, as defined in #2.

Solution

Overview

Adding a new extension/converter to the current Markdig rendering pipeline solutions this issue in the best manner possible.

Requirements

  • Tags should follow the exact specification as defined in Obsidian's documentation.
  • Support for Bootstrap being contingent for now to this feature (using their Badge component), this feature is dependent on usage of Bootstrap, and should be reflected and guarded as such in the pipeline builder.

Support Vault exporting to archive file

Premise

As an editor, I would like to be able to download a copy of my vault, so that I can edit it locally on Obsidian.

Implementation

  • A new project should be created (Name TBA), to keep the core implementation focused on the essentials.
  • An extension method, extending from IVault, should provide the implementing party with a Blob/Buffer output, containing the full Obisidian vault.
  • Export method(s?) should provide GZIP / BZIP compressions.

Support for canvases

Context

Starting from v1.1, Obsidian is releasing a Canvas feature.

Here is a preview of the feature, with sample elements from the SocialGuard vault :

Image

A preview of the .canvas file reveals this JSON syntax :

{
    "nodes": [
        {
            "id": "6e9325b8d75b7110",
            "x": 120,
            "y": -460,
            "width": 400,
            "height": 500,
            "color": "124, 77, 255",
            "type": "file",
            "file": "Concepts/Emitter.md"
        },
        {
            "id": "8570b6b21fa4c1c0",
            "x": -400,
            "y": -460,
            "width": 400,
            "height": 500,
            "color": "",
            "type": "file",
            "file": "Concepts/Entry.md"
        },
        {
            "id": "c990621969033edb",
            "x": -120,
            "y": 160,
            "width": 360,
            "height": 100,
            "color": "0, 184, 212",
            "type": "text",
            "text": "This is sample text with links to both cards above."
        }
    ],
    "edges": [
        {
            "id": "773c0f6b99e52f39",
            "fromNode": "6e9325b8d75b7110",
            "fromSide": "left",
            "toNode": "8570b6b21fa4c1c0",
            "toSide": "right",
            "color": "255, 214, 0",
            "label": ""
        },
        {
            "id": "66b5420eac1b0c44",
            "fromNode": "c990621969033edb",
            "fromSide": "left",
            "toNode": "8570b6b21fa4c1c0",
            "toSide": "bottom",
            "color": "",
            "label": ""
        },
        {
            "id": "90f32a0f7543f592",
            "fromNode": "c990621969033edb",
            "fromSide": "right",
            "toNode": "6e9325b8d75b7110",
            "toSide": "bottom",
            "color": "255, 23, 68",
            "label": ""
        }
    ]
}

Problem

No support of Canvases exist within Molten Obsidian.
As such, and depending on the needs, development for supporting such a feature should be considered for the Blazor package.

Support for Callouts

Premise

To fully support Obsidian-flavoured Markdown, we need to implement support for Callouts, as defined in #2.

Solution

Overview

Adding a new extension/converter to the current Markdig rendering pipeline solutions this issue in the best manner possible.

Requirements

  • Callouts should follow the exact specification as defined in Obsidian's documentation.
  • Support for callout icons should be left up to the user to toggle and switch, from a list of well-known providers (Bootstrap Icons, Font Awesome, etc)
  • Support for Bootstrap being contingent for now to this feature (using their Alerts), this feature is dependent on usage of Bootstrap, and should be reflected and guarded as such in the pipeline builder.

Support for Embedded resource Vaults

Premise

During development, a developer may choose to embed their Molten Obsidian vault within their software's assembly. This is particularly useful for plugin architectures that rely on an assembly discovery pattern.

Implementation

  • New vault provider : Nodsoft.MoltenObsidian.Vaults.Embedded
  • Embedded vaults should be discoverable in an easy manner, such as providing an assembly-scoped attribute that specifies the path of the Vault root (Name TBA)
  • Should we create a provider interface like IVaultProvider or IVaultFactory for multiple vaults scenario?

Support for SSG-style vault exports

Context

As a web developer using other technologies outside of the .NET ecosystem, I should be able to export a MoltenObsidian vault into static HTML files, for use in my non-ASP.NET apps.

Solution

Overview

We should implement a CLI tool (or more exactly integrate with the existing one) that allows a MO Vault to HTML output.

Requirements

  • The core pipeline consists of first instantiating a vault, through FS or HTTP, then rendering ahead-of-time all vault notes and bundling related assets (like media attachments, etc), and perhaps manifest.
  • The tool command should be invoked as either :
    • moltenobsidian ssg generate --from-folder "/path/to/vault/"
    • moltenobsidian ssg generate --from-url "https://path.to/vault/moltenobsidian.manifest.json"
  • Support for render options, such as Bootstrap support and Dark Mode support, should be supported.
  • Support for YAML Frontmatter export should be supported, through a separate export to a .yaml file.
  • Support for output packing/bundling to Gzip/Bzip should be supported, at term (see #4).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.