Types/Turtle/set_Style.ps1

<#
.SYNOPSIS
    Sets a Turtle's Style
.DESCRIPTION
    Sets any CSS styles associated with the Turtle.

    These styles will be declared in a `<style>` element, just beneath a Turtle's `<svg>`
.EXAMPLE
    turtle style '.myClass { color: #4488ff}' style
.EXAMPLE
    turtle style abc
.EXAMPLE
    turtle style "@import url('https://fonts.googleapis.com/css?family=Abel')" text 'Hello World' textattribute @{'font-family'='Abel';'font-size'='3em'} fill 'red' save ./t.png show
#>

param(
[PSObject[]]
$Style
)

filter toCss {
    # Capture the input,
    $in = $_    
    # know myself,
    $mySelf = $MyInvocation.MyCommand.ScriptBlock
    # and determine our depth
    $depth = 0
    # (with a little callstack peeking).
    foreach ($frame in Get-PSCallStack) {
        if ($frame.InvocationInfo.MyCommand.ScriptBlock -eq $mySelf) {
            $depth++
        }
    }
    # Always substract one so we don't indent the root.
    $depth--
    
    if ($in -is [string]) {
        $in # Directly output strings
    } elseif ($in -is [Collections.IDictionary]) {
        # Join dictionaries by semicolons and indentation
        ($in.GetEnumerator() | & $mySelf) -join (
            ';' + [Environment]::NewLine + (' ' * 2 * $depth)
        )
    } elseif ($in.Key -and $in.Value) {
        # Key/value pairs containing dictionaries
        if ($in.Value -is [Collections.IDictionary]) {
            # become `selector { rules }`
            (
                "$($in.Key) {", (
                    (' ' * 2) + ($in.Value | & $mySelf)
                ) -join (
                    [Environment]::NewLine + (' ' * 2 * $depth)
                )
            ) + (
                    [Environment]::NewLine + (' ' * 2 * ($depth - 1))
            ) + '}'
        } 
        elseif ($in.Value -is [TimeSpan]) {
            "$($in.Key):$($in.Value.TotalSeconds)s"
        }
        else {
            # Other key/value pairs are placed inline
            "$($in.Key):$($in.Value)"
        }
    }     
    elseif ($in -is [PSObject]) {
        # turn non-dictionaries into dictionaries
        $inDictionary = [Ordered]@{}
        foreach ($property in $in.psobject.properties) {
            $inDictionary[$property.Name] = $in.($property.Name)
        }
        if ($inDictionary.Count) {
            # and recurse.
            $inDictionary | & $mySelf
        }
    }
}

if (-not $this.'.style') {
    $this | Add-Member NoteProperty '.style' @() -Force 
}
$this.'.style' += $style |toCss