Skip to content

Commit 06d7467

Browse files
authored
Merge pull request #1089 from fsprojects/repo-assist/fix-issue-924-watch-root-override-c4e35a7b2fb520aa
[Repo Assist] Add --root option to fsdocs watch for remote/proxy hosting
2 parents 2d8a1b8 + 018fa94 commit 06d7467

2 files changed

Lines changed: 27 additions & 10 deletions

File tree

RELEASE_NOTES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
## [22.0.0-alpha.2] - 2026-03-13
2424

2525
### Added
26+
* Add `--root` option to `fsdocs watch` to override the root URL for generated pages. Useful for serving docs via GitHub Codespaces, reverse proxies, or other remote hosting where `localhost` URLs are inaccessible. E.g. `fsdocs watch --root /` or `fsdocs watch --root https://example.com/docs/`. When not set, defaults to `http://localhost:<port>/` as before. [#924](https://github.com/fsprojects/FSharp.Formatting/issues/924)
27+
* Fix `fsdocs watch` hot-reload WebSocket to connect using the page's actual host (`window.location.host`) instead of a hardcoded `localhost:<port>`, so hot-reload works correctly in GitHub Codespaces, behind reverse proxies, and over HTTPS. [#924](https://github.com/fsprojects/FSharp.Formatting/issues/924)
2628
* Search dialog now auto-focuses the search input when opened, clears on close, and can be triggered with `Ctrl+K` / `Cmd+K` in addition to `/`.
2729
* Add `dotnet fsdocs convert` command to convert a single `.md`, `.fsx`, or `.ipynb` file to HTML (or another output format) without building a full documentation site. [#811](https://github.com/fsprojects/FSharp.Formatting/issues/811)
2830
* `fsdocs convert` now accepts the input file as a positional argument (e.g. `fsdocs convert notebook.ipynb -o notebook.html`). [#1019](https://github.com/fsprojects/FSharp.Formatting/pull/1019)

src/fsdocs-tool/BuildCommand.fs

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -827,11 +827,10 @@ module Serve =
827827
let refreshEvent = FSharp.Control.Event<string>()
828828

829829
/// generate the script to inject into html to enable hot reload during development
830-
let generateWatchScript (port: int) =
831-
let tag =
832-
"""
830+
let generateWatchScript () =
831+
"""
833832
<script type="text/javascript">
834-
var wsUri = "ws://localhost:{{PORT}}/websocket";
833+
var wsUri = "ws://" + window.location.host + "/websocket";
835834
function init()
836835
{
837836
websocket = new WebSocket(wsUri);
@@ -858,8 +857,6 @@ module Serve =
858857
</script>
859858
"""
860859

861-
tag.Replace("{{PORT}}", string<int> port)
862-
863860
let connectedClients = ConcurrentDictionary<WebSocket, unit>()
864861

865862
let socketHandler (webSocket: WebSocket) (context: HttpContext) =
@@ -1568,9 +1565,15 @@ type CoreBuildOptions(watch) =
15681565
// Adjust the user substitutions for 'watch' mode root
15691566
let userRoot, userParameters =
15701567
if watch then
1571-
let userRoot = sprintf "http://localhost:%d/" this.port_option
1572-
1573-
if userParametersDict.ContainsKey(ParamKeys.root) then
1568+
let userRoot =
1569+
match this.root_override_option with
1570+
| Some r -> r
1571+
| None -> sprintf "http://localhost:%d/" this.port_option
1572+
1573+
if
1574+
userParametersDict.ContainsKey(ParamKeys.root)
1575+
&& this.root_override_option.IsNone
1576+
then
15741577
printfn "ignoring user-specified root since in watch mode, root = %s" userRoot
15751578

15761579
let userParameters =
@@ -1881,7 +1884,7 @@ type CoreBuildOptions(watch) =
18811884
let getLatestWatchScript () =
18821885
if watch then
18831886
// if running in watch mode, inject hot reload script
1884-
[ ParamKeys.``fsdocs-watch-script``, Serve.generateWatchScript this.port_option ]
1887+
[ ParamKeys.``fsdocs-watch-script``, Serve.generateWatchScript () ]
18851888
else
18861889
// otherwise, inject empty replacement string
18871890
[ ParamKeys.``fsdocs-watch-script``, "" ]
@@ -2330,6 +2333,9 @@ type CoreBuildOptions(watch) =
23302333
abstract port_option: int
23312334
default x.port_option = 0
23322335

2336+
abstract root_override_option: string option
2337+
default x.root_override_option = None
2338+
23332339
/// Helpers for the <c>fsdocs convert</c> command.
23342340
module private ConvertHelpers =
23352341

@@ -2746,3 +2752,12 @@ type WatchCommand() =
27462752

27472753
[<Option("port", Required = false, Default = 8901, HelpText = "Port to serve content for http://localhost serving.")>]
27482754
member val port = 8901 with get, set
2755+
2756+
override x.root_override_option = if x.root = "" then None else Some x.root
2757+
2758+
[<Option("root",
2759+
Required = false,
2760+
Default = "",
2761+
HelpText =
2762+
"Override the root URL for generated pages. Useful for reverse proxies or GitHub Codespaces. E.g. --root / or --root https://example.com/docs/. When not set, defaults to http://localhost:<port>/.")>]
2763+
member val root = "" with get, set

0 commit comments

Comments
 (0)