From 8e6431924e2cce69f26f9a7c47b45ce493069d85 Mon Sep 17 00:00:00 2001 From: Kevin Schneider Date: Fri, 17 Nov 2023 10:14:20 +0100 Subject: [PATCH 1/6] add minimal seo tags for open graph and twitter cards to default template --- docs/_template.html | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docs/_template.html b/docs/_template.html index 3baf0ece5..fa43747df 100644 --- a/docs/_template.html +++ b/docs/_template.html @@ -7,6 +7,18 @@ + + + + + + + + + + + + From 3014d1b2d409cceacb0df380640e798060a25f4a Mon Sep 17 00:00:00 2001 From: nojaf Date: Thu, 30 Nov 2023 09:53:15 +0100 Subject: [PATCH 2/6] Update Twitter meta tags. --- docs/_template.html | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/_template.html b/docs/_template.html index d1aced88d..98a0c725b 100644 --- a/docs/_template.html +++ b/docs/_template.html @@ -10,10 +10,9 @@ - + - - + {{fsdocs-page-title}} | {{fsdocs-collection-name}} From ec9d162bd09ae252a8989d5dc3df81986b483f21 Mon Sep 17 00:00:00 2001 From: nojaf Date: Thu, 30 Nov 2023 12:07:30 +0100 Subject: [PATCH 3/6] Add {{fsdocs-meta-tags}} substitution. --- docs/_template.html | 1 + docs/content.fsx | 9 +++- src/FSharp.Formatting.Common/Templating.fs | 5 ++ src/FSharp.Formatting.Literate/Formatting.fs | 18 +++++++ .../FSharp.Literate.Tests/DocContentTests.fs | 49 ++++++++++++++++++- .../FSharp.Literate.Tests.fsproj | 1 + tests/FSharp.Literate.Tests/files/seo-page.md | 34 +++++++++++++ 7 files changed, 115 insertions(+), 2 deletions(-) create mode 100644 tests/FSharp.Literate.Tests/files/seo-page.md diff --git a/docs/_template.html b/docs/_template.html index 98a0c725b..2f1910216 100644 --- a/docs/_template.html +++ b/docs/_template.html @@ -14,6 +14,7 @@ + {{fsdocs-meta-tags}} {{fsdocs-page-title}} | {{fsdocs-collection-name}} diff --git a/docs/content.fsx b/docs/content.fsx index b686c6566..4f454de27 100644 --- a/docs/content.fsx +++ b/docs/content.fsx @@ -70,7 +70,7 @@ Any file or directory beginning with `.` is ignored. ## Front matter -Each content file can have optional frontmatter. This determines the navigation bar title, categorization and ordering. +Each content file can have optional frontmatter. This determines the navigation bar title, categorization ordering and meta tags. For markdown, the format is: ``` @@ -79,6 +79,8 @@ title: Some Title category: Some Category categoryindex: 2 index: 3 +description: Some description +keywords: tag1, tag2, tag3 --- ``` For F# scripts the frontmatter is in this form: @@ -89,6 +91,8 @@ For F# scripts the frontmatter is in this form: category: Examples categoryindex: 2 index: 1 + description: Some description + keywords: tag1, tag2, tag3 --- *) @@ -96,6 +100,8 @@ All entries are optional. The `categoryindex` determines the ordering of categories. The `index` determines the ordering of within each category. The `title` is used in the navigation bar instead of any title inferred from the document. +The `description` is used in ` Option.bind mkValidIndex let index = findInFrontMatter "index" |> Option.bind mkValidIndex let titleFromFrontMatter = findInFrontMatter "title" + let description = findInFrontMatter "description" + let tags = findInFrontMatter "keywords" // If we want to include the source code of the script, then process // the entire source and generate replacement {source} => ...some html... @@ -229,10 +231,26 @@ module internal Formatting = getLinksFromCurrentPageIdx currentPageIdx + let meta = + let mkDescription description = + $""" + +""" + + let mkKeywords keywords = + $"""""" + + match description, tags with + | Some description, Some tags -> String.Concat(mkDescription description, "\n", mkKeywords tags) + | Some description, None -> mkDescription description + | None, Some keywords -> mkKeywords keywords + | None, None -> String.Empty + let substitutions0 = [ yield ParamKeys.``fsdocs-page-title``, pageTitle yield ParamKeys.``fsdocs-page-source``, doc.SourceFile yield ParamKeys.``fsdocs-body-class``, "content" + yield ParamKeys.``fsdocs-meta-tags``, meta yield! ctx.Substitutions yield! sourceSubstitutions yield! nextPreviousPageSubstitutions ] diff --git a/tests/FSharp.Literate.Tests/DocContentTests.fs b/tests/FSharp.Literate.Tests/DocContentTests.fs index 6cf6cf842..fac1e244e 100644 --- a/tests/FSharp.Literate.Tests/DocContentTests.fs +++ b/tests/FSharp.Literate.Tests/DocContentTests.fs @@ -1,6 +1,7 @@ module FSharp.Literate.Tests.DocContent open System.IO +open FSharp.Formatting.Templating open fsdocs open NUnit.Framework open FsUnitTyped @@ -255,6 +256,52 @@ let ``Parses frontmatter correctly `` () = twoTowersHtml |> shouldContainText "Next" returnHtml |> shouldContainText "Previous" +[] +let ``Parses description and keywords from frontmatter `` () = + let rootOutputFolderAsGiven = __SOURCE_DIRECTORY__ "output1" + + let relativeInputFolderAsGiven = + Path.GetRelativePath(System.Environment.CurrentDirectory, __SOURCE_DIRECTORY__ "files") + + if Directory.Exists(rootOutputFolderAsGiven) then + Directory.Delete(rootOutputFolderAsGiven, true) + + let content = + DocContent( + rootOutputFolderAsGiven, + Map.empty, + lineNumbers = None, + evaluate = false, + substitutions = [], + saveImages = None, + watch = false, + root = "https://github.com", + crefResolver = (fun _ -> None), + onError = failwith + ) + + let docModels = content.Convert(relativeInputFolderAsGiven, None, []) + + let seoPageDocModel = + docModels + |> List.pick (fun (docInfo, _substitutions) -> + match docInfo with + | Some(_, _, docModel) when docModel.Title = "StringAnalyzer" -> Some(docModel) + | _ -> None) + + let globals = [] + + for _thing, action in docModels do + action globals + + let meta = + seoPageDocModel.Substitutions + |> List.find (fst >> ((=) ParamKeys.``fsdocs-meta-tags``)) + |> snd + + StringAssert.Contains("] @@ -283,7 +330,7 @@ let ``ipynb notebook evaluates`` () = let globals = [] for (_thing, action) in docModels do - action globals + action globals let ipynbOut = rootOutputFolderAsGiven "eval.html" |> File.ReadAllText diff --git a/tests/FSharp.Literate.Tests/FSharp.Literate.Tests.fsproj b/tests/FSharp.Literate.Tests/FSharp.Literate.Tests.fsproj index b5e3ca698..a931eff92 100644 --- a/tests/FSharp.Literate.Tests/FSharp.Literate.Tests.fsproj +++ b/tests/FSharp.Literate.Tests/FSharp.Literate.Tests.fsproj @@ -10,6 +10,7 @@ + Common\MarkdownUnit.fs diff --git a/tests/FSharp.Literate.Tests/files/seo-page.md b/tests/FSharp.Literate.Tests/files/seo-page.md new file mode 100644 index 000000000..f281ec181 --- /dev/null +++ b/tests/FSharp.Literate.Tests/files/seo-page.md @@ -0,0 +1,34 @@ +--- +title: StringAnalyzer +category: analyzers +categoryindex: 1 +index: 3 +description: Great description about StringAnalyzer! +keywords: fsharp, analyzers, tooling +--- + +# StringAnalyzer + +There are multiple analyzers for various string comparison functions: + +- String.EndsWith Analyzer +- String.StartsWith Analyzer +- String.IndexOf Analyzer + +## Problem + +The [recommendations for string usage](https://learn.microsoft.com/en-us/dotnet/standard/base-types/best-practices-strings#recommendations-for-string-usage) mention calling the overloads using `StringComparison` to increase performance. + +```fsharp +"foo".EndsWith("p") +``` + +## Fix + +Signal your intention explicitly by calling an overload. + +```fsharp +open System + +"foo".EndsWith("p", StringComparison.Ordinal) +``` \ No newline at end of file From 88d2ce8f99fe5db1c6a7a4541e9af238d847024f Mon Sep 17 00:00:00 2001 From: nojaf Date: Wed, 6 Dec 2023 11:20:46 +0100 Subject: [PATCH 4/6] Enable strict indentation. --- Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Build.props b/Directory.Build.props index 013df25cb..b6f66d5fa 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -6,7 +6,7 @@ true true - $(OtherFlags) /warnon:1182 --test:GraphBasedChecking --test:ParallelOptimization --test:ParallelIlxGen + $(OtherFlags) /warnon:1182 --test:GraphBasedChecking --test:ParallelOptimization --test:ParallelIlxGen --strict-indentation+ From 6c814071b5d24f0f09b74e4a4bc69a5307ee9ed0 Mon Sep 17 00:00:00 2001 From: nojaf Date: Wed, 6 Dec 2023 11:30:38 +0100 Subject: [PATCH 5/6] Add hint for separator. --- docs/content.fsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content.fsx b/docs/content.fsx index 4f454de27..7ec8acd66 100644 --- a/docs/content.fsx +++ b/docs/content.fsx @@ -101,7 +101,7 @@ The `categoryindex` determines the ordering of categories. The `index` determines the ordering of within each category. The `title` is used in the navigation bar instead of any title inferred from the document. The `description` is used in ` Date: Wed, 6 Dec 2023 11:34:05 +0100 Subject: [PATCH 6/6] Add release note. --- RELEASE_NOTES.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 6bb45119c..5ae753cc9 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,10 +1,13 @@ # Changelog -## Unreleased +## 20.0.0-alpha-015 - 2023-12-06 ### Fixed * Namespace description overflows content box. [#886](https://github.com/fsprojects/FSharp.Formatting/issues/886) +### Added +* SEO-optimization for new theme. Allow `description` and `keywords` in frontmatter. Introduce `{{fsdocs-meta-tags}}`. [#869](https://github.com/fsprojects/FSharp.Formatting/issues/869) + ## 20.0.0-alpha-014 - 2023-11-22 ### Added