@@ -135,6 +135,46 @@ function Get-WebSocket {
135135 [string ]
136136 $HTML ,
137137
138+ # The name of the palette to use. This will include the [4bitcss](https://4bitcss.com) stylesheet.
139+ [Alias (' Palette' , ' ColorScheme' , ' ColorPalette' )]
140+ [ArgumentCompleter ({
141+ param ($commandName , $parameterName , $wordToComplete , $commandAst , $fakeBoundParameters )
142+ if (-not $script :4bitcssPaletteList ) {
143+ $script :4bitcssPaletteList = Invoke-RestMethod - Uri https:// cdn.jsdelivr.net/ gh/ 2bitdesigns/ 4bitcss@latest / docs/ Palette- List.json
144+ }
145+ if ($wordToComplete ) {
146+ $script :4bitcssPaletteList -match " $ ( [Regex ]::Escape($wordToComplete ) -replace ' \\\*' , ' .{0,}' ) "
147+ } else {
148+ $script :4bitcssPaletteList
149+ }
150+ })]
151+ [string ]
152+ $PaletteName ,
153+
154+ # The [Google Font](https://fonts.google.com/) name.
155+ [Parameter (ValueFromPipelineByPropertyName )]
156+ [Alias (' FontName' )]
157+ [string ]
158+ $GoogleFont ,
159+
160+ # The Google Font name to use for code blocks.
161+ # (this should be a [monospace font](https://fonts.google.com/?classification=Monospace))
162+ [Parameter (ValueFromPipelineByPropertyName )]
163+ [Alias (' PreFont' , ' CodeFontName' , ' PreFontName' )]
164+ [string ]
165+ $CodeFont ,
166+
167+ # A list of javascript files or urls to include in the content.
168+ [Parameter (ValueFromPipelineByPropertyName )]
169+ [string []]
170+ $JavaScript ,
171+
172+ # A javascript import map. This allows you to import javascript modules.
173+ [Parameter (ValueFromPipelineByPropertyName )]
174+ [Alias (' ImportsJavaScript' , ' JavaScriptImports' , ' JavaScriptImportMap' )]
175+ [Collections.IDictionary ]
176+ $ImportMap ,
177+
138178 # A collection of query parameters.
139179 # These will be appended onto the `-WebSocketUri`.
140180 [Collections.IDictionary ]
@@ -488,6 +528,63 @@ function Get-WebSocket {
488528
489529 # If the listener isn't listening, start it.
490530 if (-not $httpListener.IsListening ) { $httpListener.Start () }
531+
532+ $variable [' SiteHeader' ] = $siteHeader = @ (
533+
534+ if ($Javascript ) {
535+ # as well as any javascript files provided.
536+ foreach ($js in $Javascript ) {
537+ if ($js -match ' .js$' ) {
538+ " <script src='$javascript '></script>"
539+ } else {
540+ " <script type='text/javascript'>$js </script>"
541+ }
542+ }
543+ }
544+
545+ # If an import map was provided, we will include it.
546+ if ($ImportMap ) {
547+ $variable [' ImportMap' ] = @ (
548+ " <script type='importmap'>"
549+ [Ordered ]@ {
550+ imports = $ImportMap
551+ } | ConvertTo-Json - Depth 3
552+ " </script>"
553+ ) -join [Environment ]::NewLine
554+ }
555+
556+ # If a palette name was provided, we will include the 4bitcss stylesheet.
557+ if ($PaletteName ) {
558+ if ($PaletteName -match ' /.+?\.css$' ) {
559+ " <link type='text/css' rel='stylesheet' href='$PaletteName ' id='4bitcss' />"
560+
561+ } else {
562+ ' <link type="text/css" rel="stylesheet" href="https://cdn.jsdelivr.net/gh/2bitdesigns/4bitcss@latest/css/.css" id="4bitcss" />' -replace ' \.css' , " $PaletteName .css"
563+ }
564+ }
565+
566+ # If a font name was provided, we will include the font stylesheet.
567+ if ($GoogleFont ) {
568+ " <link type='text/css' rel='stylesheet' href='https://fonts.googleapis.com/css?family=$GoogleFont ' id='fontname' />"
569+ " <style type='text/css'>body { font-family: '$GoogleFont '; }</style>"
570+ }
571+
572+ # If a code font was provided, we will include the code font stylesheet.
573+ if ($CodeFont ) {
574+ " <link type='text/css' rel='stylesheet' href='https://fonts.googleapis.com/css?family=$CodeFont ' id='codefont' />"
575+ " <style type='text/css'>pre, code { font-family: '$CodeFont '; }</style>"
576+ }
577+
578+ # and if any stylesheets were provided, we will include them.
579+ foreach ($css in $variable.StyleSheet ) {
580+ if ($css -match ' .css$' ) {
581+ " <link rel='stylesheet' href='$css ' />"
582+ } else {
583+ " <style type='text/css'>$css </style>"
584+ }
585+ }
586+ )
587+
491588 $httpListener.psobject.properties.add ([psnoteproperty ]::new(' JobVariable' , $Variable ), $true )
492589
493590 # While the listener is listening,
@@ -497,6 +594,24 @@ function Get-WebSocket {
497594 # and wait for it to complete.
498595 while (-not ($contextAsync.IsCompleted -or $contextAsync.IsFaulted -or $contextAsync.IsCanceled )) {
499596 # while this is going on, other events can be processed, and CTRL-C can exit.
597+ # also, we can go ahead and check for any socket requests, and get ready for the next one if we find one.
598+ foreach ($socketRequest in @ ($httpListener.SocketRequests.GetEnumerator ())) {
599+ if ($socketRequest.Value.Receiving.IsCompleted ) {
600+ $socketRequest.Value.MessageCount ++
601+ $jsonMessage = ConvertFrom-Json - InputObject ($OutputEncoding.GetString ($socketRequest.Value.ClientBuffer -gt 0 ))
602+ $socketRequest.Value.ClientBuffer.Clear ()
603+ if ($MainRunspace.Events.GenerateEvent ) {
604+ $MainRunspace.Events.GenerateEvent.Invoke (@ (
605+ " $ ( $request.Url.Scheme -replace ' ^http' , ' ws' ) ://" ,
606+ $httpListener ,
607+ @ ($socketRequest.Value.Context , $socketRequest.Value.WebSocketContet , $socketRequest.Key , $socketRequest.Value ),
608+ $jsonMessage
609+ ))
610+ }
611+ $socketRequest.Value.Receiving =
612+ $socketRequest.Value.WebSocket.ReceiveAsync ($socketRequest.Value.ClientBuffer , [Threading.CancellationToken ]::None)
613+ }
614+ }
500615 }
501616 # If async method fails,
502617 if ($contextAsync.IsFaulted ) {
@@ -553,7 +668,18 @@ function Get-WebSocket {
553668 $Protocol = $requestedUrl.Scheme -replace ' ^http' , ' ws'
554669
555670 # Now add the result it to the SocketRequests lookup table, using the request trace identifier as the key.
556- $httpListener.SocketRequests [$context.Request.RequestTraceIdentifier ] = $webSocketResult
671+ $clientBuffer = $webSocketResult.WebSocket ::CreateClientBuffer($BufferSize , $BufferSize )
672+ $httpListener.SocketRequests [$context.Request.RequestTraceIdentifier ] = [Ordered ]@ {
673+ Context = $context
674+ WebSocketContext = $webSocketResult
675+ WebSocket = $webSocketResult.WebSocket
676+ ClientBuffer = $clientBuffer
677+ Created = [DateTime ]::UtcNow
678+ LastMessageTime = $null
679+ Receiving = $webSocketResult.WebSocket.ReceiveAsync ($clientBuffer , [Threading.CancellationToken ]::None)
680+ MessageQueue = [Collections.Queue ]::new()
681+ MessageCount = [long ]0
682+ }
557683 # and add the websocketcontext result to the message data.
558684 $messageData [" WebSocketContext" ] = $webSocketResult
559685 # also add the websocket result to the message data,
@@ -612,7 +738,7 @@ function Get-WebSocket {
612738 " <html>"
613739 " <head>"
614740 # and apply the site header.
615- $SiteHeader
741+ $SiteHeader -join [ Environment ]::NewLine
616742 " </head>"
617743 " <body>"
618744 $html
@@ -742,6 +868,9 @@ function Get-WebSocket {
742868 }
743869
744870 $Variable [' MainRunspace' ] = [Runspace ]::DefaultRunspace
871+ if (-not $variable [' BufferSize' ]) {
872+ $variable [' BufferSize' ] = $BufferSize
873+ }
745874 $StartThreadJobSplat = [Ordered ]@ {
746875 InitializationScript = $InitializationScript
747876 ThrottleLimit = $ThrottleLimit
0 commit comments