Skip to content

Commit

Permalink
refactor: Model Title explicitly at the symbol level
Browse files Browse the repository at this point in the history
Previously, a level 1 header was implicitly taken as title. This doesn't have to be this way. By having an explicit Title symbol we can make the 'level 1 header = title' interpretation configurable.
  • Loading branch information
artempyanykh committed Nov 20, 2024
1 parent 1a62211 commit c766760
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 75 deletions.
10 changes: 8 additions & 2 deletions Marksman/Ast.fs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,13 @@ module Element =
if Slug.isEmpty id then
None
else
Syms.Sym.Def(Def.Header(level, Slug.toString id)) |> Some
let id = Slug.toString id

// TODO: make this configurable
if level <= 1 then
Syms.Sym.Def(Title(id)) |> Some
else
Syms.Sym.Def(Header(level, id)) |> Some
// Wiki-links mapping
| Element.WL { doc = None; heading = None } -> None
| Element.WL { doc = Some doc; heading = None } ->
Expand Down Expand Up @@ -160,7 +166,7 @@ module Element =
Some(Syms.Sym.Ref(CrossRef(CrossSection(url, Slug.ofString anchor))))
// The rest
| Element.MR mdRef -> Some(Syms.Sym.Ref(IntraRef(IntraLinkDef mdRef.DestLabel)))
| Element.MLD mdLinkDef -> Some(Syms.Sym.Def(Def.LinkDef(mdLinkDef.Label)))
| Element.MLD mdLinkDef -> Some(Syms.Sym.Def(LinkDef(mdLinkDef.Label)))
| Element.T(Tag tag) -> Some(Syms.Sym.Tag(Syms.Tag tag))

type Ast = { elements: Element[] }
2 changes: 1 addition & 1 deletion Marksman/Conn.fs
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ module Conn =

match def with
| Doc
| Header(1, _) ->
| Title _ ->
// Whenever a new title is added, links that were previously pointing at the Doc
// or the other titles need to be invalidated
let affectedDefs =
Expand Down
2 changes: 1 addition & 1 deletion Marksman/Folder.fs
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ module Oracle =
| Ref.IntraRef(IntraSection section) ->
Structure.symbols destStruct
|> Seq.choose Sym.asDef
|> Seq.filter (Def.isHeaderWithId (Slug.toString section))
|> Seq.filter (Def.isHeaderOrTitleWithId (Slug.toString section))
|> Seq.toArray
| Ref.IntraRef(IntraLinkDef label) ->
Structure.symbols destStruct
Expand Down
14 changes: 7 additions & 7 deletions Marksman/Refs.fs
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ module Dest =

match destSym with
| Sym.Def Doc -> Dest.Doc(detectFileLink destDoc)
| Sym.Def(Title _)
| Sym.Def(Header _) ->
let docLink = detectDocLink destDoc

Expand Down Expand Up @@ -238,24 +239,23 @@ module Dest =
Seq.empty

// This logic is a bit involved but the idea is that whenever we invoke 'find references'
// on a level 1 header (aka a title) we should also look for references to the document
// itself
// on a title we should also look for references to the document itself
let defs, filter =
match def with
| LinkDef _ -> Seq.singleton def, konst true
| Header(level, _) when level > 1 -> Seq.singleton def, konst true
| LinkDef _
| Header _ -> Seq.singleton def, konst true
| Doc ->
let headers =
inDoc.Structure.Symbols
|> Seq.choose Sym.asDef
|> Seq.filter Def.isHeader
|> Seq.filter Def.isHeaderOrTitle

Seq.append [ Def.Doc ] headers, Sym.isRefWithExplicitDoc
| Header(_, id) ->
| Title id ->
let headers =
inDoc.Structure.Symbols
|> Seq.choose Sym.asDef
|> Seq.filter Def.isHeader
|> Seq.filter Def.isHeaderOrTitle

let filter sym =
Sym.isRefWithExplicitDoc sym
Expand Down
27 changes: 16 additions & 11 deletions Marksman/Syms.fs
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,14 @@ type Tag =
[<StructuredFormatDisplay("{AsString}")>]
type Def =
| Doc
| Title of string
| Header of level: int * id: string
| LinkDef of LinkLabel

override this.ToString() =
match this with
| Doc -> "Doc"
| Title t -> $"T {{{t}}}"
| Header(l, h) -> $"H{l} {{{h}}}"
| LinkDef ld -> $"[{ld}]:"

Expand All @@ -94,31 +96,34 @@ type Def =
module Def =
let isDoc =
function
| Def.Doc -> true
| Doc -> true
| _ -> false

let isTitle =
function
| Def.Header(level, _) when level <= 1 -> true
| Title _ -> true
| _ -> false

let isHeader =
let isHeaderOrTitle =
function
| Def.Header _ -> true
| Title _
| Header _ -> true
| _ -> false

let isHeaderWithId id =
let isHeaderOrTitleWithId id =
function
| Def.Header(_, id') when id = id' -> true
| Title id'
| Header(_, id') -> id = id'
| _ -> false

let isLinkDefWithLabel label =
function
| Def.LinkDef label' when label = label' -> true
| LinkDef label' when label = label' -> true
| _ -> false

let asHeader =
function
| Title id -> Some(1, id)
| Header(level, id) -> Some(level, id)
| _ -> None

Expand Down Expand Up @@ -172,10 +177,10 @@ module ScopeSlug =

let private ofScopedDefAux (docId: DocId) (def: Def) =
match def with
| Def.LinkDef _ -> None
| Def.Doc -> Some(ofDocId docId)
| Def.Header(1, id) -> Some(ScopeSlug(Slug.ofString id))
| Def.Header _ -> Some(ofDocId docId)
| LinkDef _ -> None
| Doc
| Header _ -> Some(ofDocId docId)
| Title id -> Some(ScopeSlug(Slug.ofString id))

let ofScopedDef (scope: Scope, def: Def) =
match Scope.asDoc scope with
Expand Down
4 changes: 2 additions & 2 deletions Tests/RefsTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ module BasicRefsTests =

let refs = Dest.findElementRefs false folder doc1 wl |> formatRefs

checkInlineSnapshot (fun x -> x.ToString()) refs [
checkInlineSnapshot (_.ToString()) refs [
"(doc1.md, (4,0)-(4,16))"
"(doc2.md, (6,0)-(6,11))"
]
Expand All @@ -409,7 +409,7 @@ module BasicRefsTests =

let refs = Dest.findElementRefs true folder doc1 wl |> formatRefs

checkInlineSnapshot (fun x -> x.ToString()) refs [
checkInlineSnapshot (_.ToString()) refs [
"(doc1.md, (4,0)-(4,16))"
"(doc2.md, (6,0)-(6,11))"
"(doc2.md, (10,0)-(10,9))"
Expand Down
Loading

0 comments on commit c766760

Please sign in to comment.