Skip to content

Commit 8da4915

Browse files
authored
Merge branch 'main' into repo-assist/feature-811-fsdocs-convert-2cf2c2973fcbd211
2 parents 0231407 + fa2d46d commit 8da4915

13 files changed

Lines changed: 292 additions & 41 deletions

File tree

.github/workflows/pull-requests.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ on:
88
branches:
99
- main
1010

11+
concurrency:
12+
group: ${{ github.workflow }}-${{ github.ref }}
13+
cancel-in-progress: true
14+
1115
permissions:
1216
contents: read
1317
id-token: write
@@ -24,6 +28,13 @@ jobs:
2428

2529
steps:
2630
- uses: actions/checkout@v6
31+
- name: Cache .NET SDK
32+
uses: actions/cache@v4
33+
with:
34+
path: ~/.dotnet
35+
key: ${{ runner.os }}-dotnet-sdk-${{ hashFiles('global.json') }}
36+
restore-keys: |
37+
${{ runner.os }}-dotnet-sdk-
2738
- name: Cache NuGet packages
2839
uses: actions/cache@v4
2940
with:

.github/workflows/push-main.yml

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@ on:
55
branches:
66
- main
77

8+
concurrency:
9+
group: ${{ github.workflow }}-${{ github.ref }}
10+
cancel-in-progress: true
11+
permissions:
12+
id-token: write
13+
contents: write
14+
815
jobs:
916
build:
1017

@@ -16,6 +23,13 @@ jobs:
1623

1724
steps:
1825
- uses: actions/checkout@v6
26+
- name: Cache .NET SDK
27+
uses: actions/cache@v4
28+
with:
29+
path: ~/.dotnet
30+
key: ${{ runner.os }}-dotnet-sdk-${{ hashFiles('global.json') }}
31+
restore-keys: |
32+
${{ runner.os }}-dotnet-sdk-
1933
- name: Cache NuGet packages
2034
uses: actions/cache@v4
2135
with:
@@ -34,5 +48,11 @@ jobs:
3448
publish_dir: ./output
3549
publish_branch: gh-pages
3650
force_orphan: true
37-
- name: Publish NuGets (if main version changed)
38-
run: dotnet nuget push "artifacts/*.nupkg" -s https://api.nuget.org/v3/index.json -k ${{ secrets.FSHARP_FORMATTING_TOKEN_2020 }} --skip-duplicate
51+
- name: Obtain NuGet key
52+
# this hash is v1.1.0
53+
uses: NuGet/login@d22cc5f58ff5b88bf9bd452535b4335137e24544
54+
id: login
55+
with:
56+
user: dsyme
57+
- name: Publish NuGets (if this version not published before)
58+
run: dotnet nuget push "artifacts/*.nupkg" -s https://www.nuget.org/api/v2/package -k ${{ steps.login.outputs.NUGET_API_KEY }} --skip-duplicate

.github/workflows/repo-assist.lock.yml

Lines changed: 15 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.github/workflows/repo-assist.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ tools:
7171
bash: true
7272
repo-memory: true
7373

74-
source: githubnext/agentics/workflows/repo-assist.md@b87234850bf9664d198f28a02df0f937d0447295
74+
source: githubnext/agentics/workflows/repo-assist.md@f2c5cf1e4af58e09a93ba0703c6bf084711b265f
7575
---
7676

7777
# Repo Assist
@@ -115,6 +115,8 @@ Read memory at the **start** of every run; update it at the **end**.
115115

116116
Use a **round-robin strategy**: each run, work on a different subset of tasks, rotating through them across runs so that all tasks get attention over time. Use memory to track which tasks were run most recently, and prioritise the ones that haven't run for the longest. Aim to do 2–4 tasks per run (plus the mandatory Task 11).
117117

118+
**Repeat-run mode**: When invoked via `gh aw run repo-assist --repeat`, runs occur every 5–10 minutes. Even in this mode, **actively look for useful work to do** on every run. Do not skip a run just because the last one was recent or because open PRs are awaiting CI — there is always a task to advance: label issues, scan the backlog, study the codebase, prepare a fix, push an update, or work on Task 10. Treat a "nothing to do" conclusion as a sign you haven't looked hard enough, unless there really is, like, literally nothing to do. And be careful not to do duplicate work across runs — check memory to see if you've already tried a fix or commented on an issue before doing it again.
119+
118120
Always do Task 11 (Update Monthly Activity Summary Issue) every run. In all comments and PR descriptions, identify yourself as "Repo Assist".
119121

120122
### Task 1: Triage and Comment on Open Issues

RELEASE_NOTES.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,18 @@
1111
* Add `{{fsdocs-logo-alt}}` substitution (configurable via `<FsDocsLogoAlt>` MSBuild property, defaults to `Logo`) for accessible alt text on the header logo image. [#626](https://github.com/fsprojects/FSharp.Formatting/issues/626)
1212

1313
### Fixed
14+
* Fix `_menu_template.html` and `_menu-item_template.html` being copied to the output directory. [#803](https://github.com/fsprojects/FSharp.Formatting/issues/803)
15+
* Fix `ApiDocMember.Details.ReturnInfo.ReturnType` returning `None` for properties that have both a getter and a setter. [#734](https://github.com/fsprojects/FSharp.Formatting/issues/734)
1416
* Improve error message when a named code snippet is not found (e.g. `(*** include:name ***)` with undefined name now reports the missing name clearly). [#982](https://github.com/fsprojects/FSharp.Formatting/pull/982)
1517
* HTML-encode XML doc text nodes and unresolved `<see cref>` values to prevent HTML injection and fix broken output when docs contain characters like `<`, `>`, or backticks in generic type notation. [#748](https://github.com/fsprojects/FSharp.Formatting/issues/748)
1618
* Add uppercase output kind extension (e.g. `HTML`, `IPYNB`) to `ConditionalDefines` so that `#if HTML` and `(*** condition: HTML ***)` work alongside their lowercase variants. [#693](https://github.com/fsprojects/FSharp.Formatting/issues/693)
1719
* Strip `#if SYMBOL` / `#endif // SYMBOL` marker lines from `LiterateCode` source before syntax-highlighting so they do not appear in formatted output. [#693](https://github.com/fsprojects/FSharp.Formatting/issues/693)
20+
* Fix incorrect column ranges for inline spans (links, images, inline code) in the Markdown parser — spans and subsequent literals now report correct `StartColumn`/`EndColumn` values. [#744](https://github.com/fsprojects/FSharp.Formatting/issues/744)
21+
* Normalize `--projects` paths to absolute paths before passing to the project cracker, fixing failures when relative paths are supplied. [#793](https://github.com/fsprojects/FSharp.Formatting/issues/793)
1822

1923
### Changed
2024
* Update FCS to 43.10.100. [#935](https://github.com/fsprojects/FSharp.Formatting/pull/966)
25+
* Reduce dark mode header border contrast to match the visual subtlety of light mode borders. [#885](https://github.com/fsprojects/FSharp.Formatting/issues/885)
2126

2227
## 21.0.0 - 2025-11-12
2328

docs/content/fsdocs-default.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@
135135
--code-background: #28282D;
136136
--code-color: #f5f5f6;
137137
--header-background: #0c1318;
138-
--header-border: #9b9b9b;
138+
--header-border: #3a3a42;
139139
--menu-item-hover-background: #2c2624;
140140
--doc-tip-background: #2e293a;
141141
--link-color: #c5eff7;

src/FSharp.Formatting.ApiDocs/GenerateModel.fs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1538,6 +1538,7 @@ module internal SymbolReader =
15381538
let argInfos, retType =
15391539
match argInfos, v.HasGetterMethod, v.HasSetterMethod with
15401540
| [ AllAndLast(args, last) ], _, true -> [ args ], Some last.Type
1541+
| [ [] ], _, true -> [], Some retType
15411542
| _, _, true -> argInfos, None
15421543
| [ [] ], true, _ -> [], Some retType
15431544
| _, _, _ -> argInfos, Some retType

src/FSharp.Formatting.Markdown/MarkdownParser.fs

Lines changed: 45 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,23 @@ type ParsingContext =
324324

325325
member x.AllowYamlFrontMatter = (x.ParseOptions &&& MarkdownParseOptions.AllowYamlFrontMatter) <> enum 0
326326

327+
/// Advances the StartColumn of the current range in ctx by n characters.
328+
let private advanceCtxBy n ctx =
329+
{ ctx with
330+
CurrentRange =
331+
match ctx.CurrentRange with
332+
| Some r ->
333+
Some
334+
{ r with
335+
StartColumn = r.StartColumn + n }
336+
| None -> None }
337+
338+
/// Computes a span range starting at ctx.StartColumn and spanning n characters.
339+
let private spanRange n ctx =
340+
match ctx.CurrentRange with
341+
| Some r -> Some { r with EndColumn = r.StartColumn + n }
342+
| None -> None
343+
327344
/// Parses a body of a paragraph and recognizes all inline tags.
328345
let rec parseChars acc input (ctx: ParsingContext) =
329346
seq {
@@ -390,11 +407,11 @@ let rec parseChars acc input (ctx: ParsingContext) =
390407
Some
391408
{ n with
392409
StartColumn = n.StartColumn + s
393-
EndColumn = n.EndColumn - e }
410+
EndColumn = n.StartColumn + s + body.Length }
394411
| None -> None
395412

396413
yield InlineCode(String(Array.ofList body).Trim(), rng)
397-
yield! parseChars [] rest ctx
414+
yield! parseChars [] rest (advanceCtxBy (s + body.Length + e) ctx)
398415

399416
// Display Latex inline math mode
400417
| DelimitedLatexDisplayMath [ '$'; '$' ] (body, rest) ->
@@ -442,60 +459,70 @@ let rec parseChars acc input (ctx: ParsingContext) =
442459
->
443460
let (value, ctx) = accLiterals.Value
444461
yield! value
445-
yield DirectLink([ Literal(link, ctx.CurrentRange) ], link, None, ctx.CurrentRange)
446-
yield! parseChars [] rest ctx
462+
let consumed = 1 + link.Length + 1
463+
yield DirectLink([ Literal(link, spanRange consumed ctx) ], link, None, spanRange consumed ctx)
464+
yield! parseChars [] rest (advanceCtxBy consumed ctx)
447465
// Not an inline link - leave as an inline HTML tag
448466
| List.DelimitedWith [ '<' ] [ '>' ] (tag, rest, _s, _e) ->
449467
yield! parseChars ('>' :: (List.rev tag) @ '<' :: acc) rest ctx
450468

451469
// Recognize direct link [foo](http://bar) or indirect link [foo][bar] or auto link http://bar
452-
| DirectLink(body, link, rest) ->
470+
| DirectLink(body, linkChars, rest) ->
453471
let (value, ctx) = accLiterals.Value
454472
yield! value
455473

456-
let link, title = getLinkAndTitle (String(Array.ofList link), MarkdownRange.zero)
474+
let consumed = 2 + body.Length + 2 + linkChars.Length
475+
let link, title = getLinkAndTitle (String(Array.ofList linkChars), MarkdownRange.zero)
476+
let bodyCtx = advanceCtxBy 1 ctx // advance past opening '['
457477

458-
yield DirectLink(parseChars [] body ctx |> List.ofSeq, link, title, ctx.CurrentRange)
459-
yield! parseChars [] rest ctx
478+
yield DirectLink(parseChars [] body bodyCtx |> List.ofSeq, link, title, spanRange consumed ctx)
479+
yield! parseChars [] rest (advanceCtxBy consumed ctx)
460480
| IndirectLink(body, link, original, rest) ->
461481
let (value, ctx) = accLiterals.Value
462482
yield! value
463483

484+
let consumed = 2 + body.Length + original.Length
485+
let bodyCtx = advanceCtxBy 1 ctx // advance past opening '['
486+
464487
let key =
465488
if String.IsNullOrEmpty(link) then
466489
String(body |> Array.ofSeq)
467490
else
468491
link
469492

470-
yield IndirectLink(parseChars [] body ctx |> List.ofSeq, original, key, ctx.CurrentRange)
471-
yield! parseChars [] rest ctx
493+
yield IndirectLink(parseChars [] body bodyCtx |> List.ofSeq, original, key, spanRange consumed ctx)
494+
yield! parseChars [] rest (advanceCtxBy consumed ctx)
472495
| AutoLink(link, rest) ->
473496
let (value, ctx) = accLiterals.Value
474497
yield! value
475-
yield DirectLink([ Literal(link, ctx.CurrentRange) ], link, None, ctx.CurrentRange)
476-
yield! parseChars [] rest ctx
498+
let consumed = link.Length
499+
yield DirectLink([ Literal(link, spanRange consumed ctx) ], link, None, spanRange consumed ctx)
500+
yield! parseChars [] rest (advanceCtxBy consumed ctx)
477501

478502
// Recognize image - this is a link prefixed with the '!' symbol
479-
| '!' :: DirectLink(body, link, rest) ->
503+
| '!' :: DirectLink(body, linkChars, rest) ->
480504
let (value, ctx) = accLiterals.Value
481505
yield! value
482506

483-
let link, title = getLinkAndTitle (String(Array.ofList link), MarkdownRange.zero)
507+
let consumed = 1 + 2 + body.Length + 2 + linkChars.Length
508+
let link, title = getLinkAndTitle (String(Array.ofList linkChars), MarkdownRange.zero)
484509

485-
yield DirectImage(String(Array.ofList body), link, title, ctx.CurrentRange)
486-
yield! parseChars [] rest ctx
510+
yield DirectImage(String(Array.ofList body), link, title, spanRange consumed ctx)
511+
yield! parseChars [] rest (advanceCtxBy consumed ctx)
487512
| '!' :: IndirectLink(body, link, original, rest) ->
488513
let (value, ctx) = accLiterals.Value
489514
yield! value
490515

516+
let consumed = 1 + 2 + body.Length + original.Length
517+
491518
let key =
492519
if String.IsNullOrEmpty(link) then
493520
String(body |> Array.ofSeq)
494521
else
495522
link
496523

497-
yield IndirectImage(String(Array.ofList body), original, key, ctx.CurrentRange)
498-
yield! parseChars [] rest ctx
524+
yield IndirectImage(String(Array.ofList body), original, key, spanRange consumed ctx)
525+
yield! parseChars [] rest (advanceCtxBy consumed ctx)
499526

500527
// Handle Emphasis
501528
| CannotOpenEmphasis(revPre, post) -> yield! parseChars (revPre @ acc) post ctx

src/fsdocs-tool/BuildCommand.fs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,10 @@ type internal DocContent
141141
if
142142
not (inputFileName.StartsWith('.'))
143143
&& not (inputFileName.StartsWith("_template", StringComparison.Ordinal))
144+
&& not (
145+
inputFileName.StartsWith("_menu", StringComparison.Ordinal)
146+
&& inputFileName.EndsWith("_template.html", StringComparison.Ordinal)
147+
)
144148
then
145149
let inputFileFullPath = Path.GetFullPath(inputFileFullPath)
146150

@@ -186,7 +190,13 @@ type internal DocContent
186190

187191
if name.StartsWith('.') then
188192
printfn "skipping file %s" inputFileFullPath
189-
elif not (name.StartsWith("_template", StringComparison.Ordinal)) then
193+
elif
194+
not (name.StartsWith("_template", StringComparison.Ordinal))
195+
&& not (
196+
name.StartsWith("_menu", StringComparison.Ordinal)
197+
&& name.EndsWith("_template.html", StringComparison.Ordinal)
198+
)
199+
then
190200
let isFsx = inputFileFullPath.EndsWith(".fsx", StringComparison.OrdinalIgnoreCase)
191201

192202
let isMd = inputFileFullPath.EndsWith(".md", StringComparison.OrdinalIgnoreCase)

0 commit comments

Comments
 (0)