Fun.fun.ps1


# Fun Website
if (-not $ExecutionContext.SessionState.InvokeCommand.GetCommand('layout', 'Alias')) {
    function Layout {
        @(
        "<html>"    
            "<head>"
                '<meta charset="utf-8">'
                "<title>$([Web.HttpUtility]::HtmlEncode("$title"))</title>"
                "<style>"
                    
                    "body { max-width:80vw; height: 100vh; margin-left: auto; margin-right: auto; }"

                    "h1 { text-align: center }"

                    "h2 { text-align: center }"

                "</style>"
            "</head>"
            "<body>"
                $args -join "`n"
                $input -join "`n"
            "</body>"
        "</html>"
        ) -join "`n"
    }

}

function / {
<#
.SYNOPSIS
    Fun Server
.DESCRIPTION
    A Fun PowerShell Server
#>

[OutputType('text/html')]
param()

$title = "Fun Server $(Get-Module Fun | Select-Object -ExpandProperty Version)"

@"

<h1>Fun</h1>

<h2>A Fun PowerShell Server</h2>

<p>
Fun is a fun functional interactive PowerShell server.
</p>

<p>
It maps a url to a PowerShell function.
</p>

<p>
For example, the current request to <a href='$(
    $request.url.LocalPath
)'>$(
    $request.Url.LocalPath
)</a> is handled by:
</p>

<pre>
    <code class='language-powershell'>
$([Web.HttpUtility]::HtmlEncode($MyInvocation.MyCommand.ScriptBlock))
    </code>
</pre>

<p>
Fun is defined in a single PowerShell script:
</p>

<details>

    <summary>Fun.ps1</summary>

        <pre>

            <code class='language-powershell'>
$([Web.HttpUtility]::HtmlEncode(
    $ExecutionContext.SessionState.InvokeCommand.GetCommand('Fun','Function').ScriptBlock
))
            </code>

        </pre>
</details>
"@
 | . Layout
}

function /get/command {
    $title = "Fun Commands"
    @(
    "<h1>$title</h1>"    
    "<ul>"
    "<li>Functions</li>"
    "<ul>"
    foreach ($func in Get-Command /* -CommandType Function) {
        "<li><a href='$($func.Name)'>$([Web.HttpUtility]::HtmlEncode($func.Name))</a></li>"
    }
    "</ul>"
    "<li>Aliases</li>"
    "<ul>"
    foreach ($func in Get-Command /* -CommandType Alias) {
        "<li><a href='$($func.Name)'>$([Web.HttpUtility]::HtmlEncode($func.Name))</a></li>"
    }
    "</ul>"
    "</ul>"
    ) | Layout
}

Set-Alias /index.html /

function /fun/state {
 
    param()

    "<h1>Fun State</h1>"
    "<p>Fun functions are run in their original context. This can be very fun.</p>"
}

function /fun/website {
    "<h1>"
    "Fun Websites"
    "</h1>"
    "<h2>"
    "Static Websites with Fun"
    "</h2>"

    "<p>"
    "In a dynamic site, we run our functions on demand"    
    "</p>"

    "<p>"
    "To make a static site, we can just run our fun once and save it to a file"
    "</p>"

    "<pre>"
    "<code class='language-powershell'>"
    [Web.HttpUtility]::HtmlEncode("/ > ./index.html")
    "</code>"
    "</pre>"
    
    "<p>"
    "To make this easier, fun includes a <pre>.Build()</pre> method"
    "</p>"

    "<pre>"
        "<code class='language-powershell'>"
            [Web.HttpUtility]::HtmlEncode("(fun).Build()")
        "</code>"
    "</pre>"
}

function /fun/experiment {
    "<h1>Fun Experiment</h1>",
    "<h3>Fun is an experiment</h3>",
    "<p>Fun is a fun server, and it is experimental and subject to change</p>" |
        Layout    
}

function /fun/security {
    "$((ConvertFrom-Markdown -LiteralPath (
        Get-Module Fun | Split-Path | Join-Path -ChildPath "security.md"
    )).Html)"
 | Layout
}

Set-Alias /fun/security/index.html /fun/security

function /fun/contributing {
    "$((ConvertFrom-Markdown -LiteralPath (
        Get-Module Fun | Split-Path | Join-Path -ChildPath "contributing.md"
    )).Html)"
|
    Layout
}

Set-Alias /fun/contributing/index.html /fun/contributing

function /fun/code-of-conduct {
    ConvertFrom-Markdown -LiteralPath (
        Get-Module Fun | Split-Path | Join-Path -ChildPath "code_of_conduct.md"
    ) |
    Select-Object -ExpandProperty Html |
    Layout
}

Set-Alias /fun/code-of-conduct/index.html /fun/code-of-conduct
function /get/fun {
    [OutputType('text/plain')]
    param()
    Get-Command Get-Fun | 
        Select-Object -ExpandProperty ScriptBlock
}

Set-Alias /get/fun.ps1 /get/fun
function /404 {
    @(
        "<h1>404</h1>"
        "<h2><img src='https://media1.tenor.com/m/_OXEOGoxedQAAAAC/hal9000-hal.gif' /></h2>"
    ) | Layout
}


# $fun
# $fun = 1..10 | ./fun.ps1 some fun args
# $fun.Start(3)