public/New-TriliumNote.ps1

function New-TriliumNote {
    <#
    .SYNOPSIS
        Creates a new note in Trilium Notes.
 
    .DESCRIPTION
        Creates a new note in Trilium Notes with the specified content, title, type, and formatting options. Supports a wide range of note types, including text, markdown, code, and special types like book, canvas, mermaid, and more. When using `-Markdown`, the function converts markdown to HTML before sending to Trilium, with optional MathJax support via `-Math`. HTML content is beautified before sending. Requires authentication via `Connect-TriliumAuth`.
 
    .PARAMETER ParentNoteId
        The ID of the parent note under which the new note will be created. Defaults to 'root'.
        Use `Get-TriliumNotes` to find IDs of existing notes.
 
        Required? false
        Position? 0
        Default value 'root'
        Accept pipeline input? false
        Accept wildcard characters? false
 
    .PARAMETER Title
        The title of the new note. Displayed in the Trilium Notes UI.
 
        Required? false
        Position? 1
        Default value None
        Accept pipeline input? false
        Accept wildcard characters? false
 
    .PARAMETER Content
        The content of the new note. This is required.
        For code notes, provide the code as plain text. For markdown notes, provide markdown-formatted text.
 
        Required? true
        Position? 2
        Default value None
        Accept pipeline input? false
        Accept wildcard characters? false
 
    .PARAMETER NoteType
        The type of note to create. Tab completion is available for common types.
        Supported values:
        image, file, text, book, canvas, mermaid, geoMap, mindMap, relationMap, renderNote, webview, PlainText, CSS, html, http, JSbackend, JSfrontend, json, markdown, powershell, python, ruby, shellBash, sql, sqliteTrilium, xml, yaml
        See Trilium documentation for more details.
 
        Required? false
        Position? 3
        Default value None
        Accept pipeline input? false
        Accept wildcard characters? false
 
    .PARAMETER Mime
        The MIME type of the note content. If not specified, it will be determined based on NoteType. Only specify this if you need to override the default MIME type.
 
        Required? false
        Position? 4
        Default value None
        Accept pipeline input? false
        Accept wildcard characters? false
 
    .PARAMETER SkipCertCheck
        If specified, certificate validation will be skipped when connecting to Trilium (useful for self-signed certificates).
 
        Required? false
        Position? named
        Default value false
        Accept pipeline input? false
        Accept wildcard characters? false
 
    .PARAMETER Markdown
        If specified, the Content will be treated as markdown and converted to HTML. When this parameter is used, NoteType must be 'text' or not specified. Enables advanced markdown rendering including tables, task lists, and code blocks.
 
        Required? false
        Position? named
        Default value false
        Accept pipeline input? false
        Accept wildcard characters? false
 
    .PARAMETER Math
        If specified, adds support for mathematical expressions in markdown using MathJax. Only used with the -Markdown parameter. Math expressions can be included inline using $expression$ syntax or as blocks with $$ syntax.
 
        Required? false
        Position? named
        Default value false
        Accept pipeline input? false
        Accept wildcard characters? false
 
    .INPUTS
        None. You cannot pipe objects to New-TriliumNote.
 
    .OUTPUTS
        System.Management.Automation.PSCustomObject
        Returns the API response from Trilium, including information about the created note.
 
    .EXAMPLE
        New-TriliumNote -Title "My Note" -Content "This is the content of my note"
        Creates a new text note with the specified title and content under the root.
 
    .EXAMPLE
        New-TriliumNote -Title "Code Sample" -Content "Get-Process" -NoteType "powershell"
        Creates a new PowerShell code note with syntax highlighting.
 
    .EXAMPLE
        New-TriliumNote -Title "Markdown Note" -Content "# Header`n`nThis is *markdown* content" -Markdown
        Creates a new note by converting the markdown content to HTML.
 
    .EXAMPLE
        New-TriliumNote -Title "Math Example" -Content "When $a \ne 0$, there are two solutions to $ax^2 + bx + c = 0$" -Markdown -Math
        Creates a note with markdown content that includes mathematical expressions.
 
    .EXAMPLE
        $parentId = (Get-TriliumNotes -Title "My Folder").noteId
        New-TriliumNote -ParentNoteId $parentId -Title "Nested Note" -Content "This is a nested note"
        Creates a new note inside an existing note folder by specifying its ID.
 
    .LINK
        Online version: https://github.com/ptmorris1/TriliumNext-Powershell-Module
    .LINK
        Connect-TriliumAuth
    .LINK
        Get-TriliumNotes
 
    .NOTES
        Requires authentication via Connect-TriliumAuth before use.
        Author: P. Morris
        Module: TriliumNext-Powershell-Module
    #>

    [CmdletBinding(SupportsShouldProcess = $true)]
    param (
        [Parameter()] [string]$ParentNoteId = 'root',
        [Parameter()] [string]$Title,
        [Parameter(Mandatory = $true)] [string]$Content,
        [Parameter()]
        [ArgumentCompleter({
            param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters)
            $noteTypes = @('image','file','text','book','canvas','mermaid','geoMap','mindMap','relationMap','renderNote','webview',
            'PlainText','CSS','html','http','JSbackend','JSfrontend','json','markdown','powershell','python','ruby','shellBash','sql','sqliteTrilium','xml','yaml')
            
            return $noteTypes | Where-Object { $_ -like "$wordToComplete*" }
        })]
        [string]$NoteType,
        [Parameter()] [string]$Mime,        [Parameter()] [switch]$SkipCertCheck,
        [Parameter()] [switch]$Markdown,
        [Parameter()] [switch]$Math
    )    begin {
        if (!$global:TriliumCreds) { Write-Error -Message 'Need to run: Connect-TriliumAuth'; exit }
        
        # Load the MimeTypeMap JSON directly
        $moduleRoot = $MyInvocation.MyCommand.Module.ModuleBase
        $mimeTypeMapPath = Join-Path -Path $moduleRoot -ChildPath 'data\MimeTypeMap.json'
        
        if (Test-Path -Path $mimeTypeMapPath) {
            $mimeTypeMap = Get-Content -Path $mimeTypeMapPath -Raw | ConvertFrom-Json
        } else {
            Write-Error "MimeTypeMap.json not found at path: $mimeTypeMapPath"
            exit
        }

        if ($Markdown) {
            if ($NoteType -and $NoteType -ne 'text') {
                Write-Error -Message 'If -Markdown is specified, -NoteType must be "text".'
                exit
            }
            $NoteType = 'text'
            $moduleRoot = $MyInvocation.MyCommand.Module.ModuleBase
            $dllPath = Join-Path -Path $moduleRoot -ChildPath 'lib\Markdig.dll'
            if (-not ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.Location -eq (Resolve-Path $dllPath) })) {
                Add-Type -Path $dllPath
            }            $builder = [Markdig.MarkdownPipelineBuilder]::new()
            [Markdig.MarkdownExtensions]::UseAdvancedExtensions($builder) | Out-Null
            if ($Math) {
                [Markdig.MarkdownExtensions]::UseMathematics($builder) | Out-Null
            }
            $pipeline = $builder.Build()
            $html = [Markdig.Markdown]::ToHtml($Content, $pipeline)
            if ($Math) {
                $html = $html.Replace('<span class="math"', '<span class="math-tex"')
                $html = $html.Replace('<div class="math"', '<span class="math-tex"')
            }            # Format code blocks with proper mime types using our unified mapping
            $html = [regex]::Replace($html, '(?i)<pre><code class="language-([a-z0-9+\-]+)">', {
                param($match)
                $lang = $match.Groups[1].Value.ToLower()
                $mimeType = ($mimeTypeMap | Where-Object { $_.Note -eq $lang })?.Mime
                if ($mimeType) {
                    # Use the found mime type from our mapping
                    $formattedMime = $mimeType.Replace('/', '-')
                } elseif ($lang -match '^(html|xml|json|markdown|sql|text|plaintext)$') {
                    $formattedMime = "text-$lang"
                } elseif ($lang -match '^(c|cpp|csharp|java|go|sh|bash|powershell)$') {
                    $formattedMime = "text-x-$lang"
                } else {
                    $formattedMime = "application-x-$lang"
                }                
                "<pre><code class=`"language-$formattedMime`">"
            })
            
            $Content = $html
            # Beautify the HTML content before sending to Trilium
            $Content = Format-TriliumHtml -Content $Content
        }
    }
    process {
        try {
            if ($SkipCertCheck) {
                $PSDefaultParameterValues = @{'Invoke-RestMethod:SkipCertificateCheck' = $true }
            }            $TriliumHeaders = @{ Authorization = "$($TriliumCreds.Authorization)" }
            $uri = "$($TriliumCreds.URL)/create-note"

            $body = @{ parentNoteId = $ParentNoteId }
            if ($Title) { $body.title = $Title }
            if ($Content) { $body.content = $Content }
            if ($Mime) { $body.mime = $Mime }            if ($NoteType) {
                $mimeObj = $mimeTypeMap | Where-Object { $_.Note -eq $NoteType }
                if ($mimeObj) {
                    $body.type = $mimeObj.Type
                    if ($null -ne $mimeObj.Mime -and -not $Mime) {
                        $body.mime = $mimeObj.Mime
                    }
                } else {
                    $body.type = $NoteType
                }
            } elseif (-not $body.ContainsKey('type')) {
                $body.type = 'text'
                if (-not $body.ContainsKey('mime')) { $body.mime = 'text/html' }
            }

            $json = $body | ConvertTo-Json -Depth 5
            if ($PSCmdlet.ShouldProcess($uri, 'Create new note')) {
                Invoke-RestMethod -Uri $uri -Headers $TriliumHeaders -SkipHeaderValidation -ContentType 'application/json' -Body $json -Method Post
            }
        } catch {
            $_.Exception.Response
        }
    }
    end { return }
}