From 3db05520201a2879c7a26abc54719e6b5c06413a Mon Sep 17 00:00:00 2001 From: khalidabuhakmeh Date: Thu, 24 Apr 2025 13:38:40 -0400 Subject: [PATCH 1/8] Introduce ReHype Plugin to remove .md from links This uses ReHype to remove the `.md` file extension. Also set the content directory to a root path for WebStorm so you get proper path checking and validation when authoring. --- .idea/compiler.xml | 6 ++ .idea/webResources.xml | 14 +++++ astro.config.mjs | 8 ++- package-lock.json | 57 +++++++++++++++++++ package.json | 1 + .../apis/aspnetcore/confirmation.md | 2 +- .../duende-og-image.tsx | 0 src/plugins/remove-markdown-extensions.ts | 37 ++++++++++++ tsconfig.json | 12 +++- 9 files changed, 132 insertions(+), 5 deletions(-) create mode 100644 .idea/compiler.xml create mode 100644 .idea/webResources.xml rename src/{components => plugins}/duende-og-image.tsx (100%) create mode 100644 src/plugins/remove-markdown-extensions.ts diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 000000000..8ca546d7d --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/webResources.xml b/.idea/webResources.xml new file mode 100644 index 000000000..32fcfadc2 --- /dev/null +++ b/.idea/webResources.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/astro.config.mjs b/astro.config.mjs index bf0686174..11076c9ab 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -1,4 +1,3 @@ -// @ts-check import { defineConfig, fontProviders } from "astro/config"; import starlight from "@astrojs/starlight"; import starlightLinksValidator from "starlight-links-validator"; @@ -10,10 +9,14 @@ import starlightHeadingBadges from "starlight-heading-badges"; import starlightLlmsTxt from "starlight-llms-txt"; import rehypeAstroRelativeMarkdownLinks from "astro-rehype-relative-markdown-links"; import opengraphImages from "astro-opengraph-images"; -import { duendeOpenGraphImage } from "./src/components/duende-og-image.js"; import rehypeExternalLinks from "rehype-external-links"; import * as fs from "node:fs"; +// don't convert to path aliases, it doesn't work here +// https://github.com/withastro/astro/issues/9782 +import { duendeOpenGraphImage } from "./src/plugins/duende-og-image.js"; +import removeMarkdownExtensions from "./src/plugins/remove-markdown-extensions.js"; + // https://astro.build/config export default defineConfig({ site: "https://docs.duendesoftware.com", @@ -199,6 +202,7 @@ export default defineConfig({ rel: ["noopener", "noreferrer"], }, ], + [removeMarkdownExtensions, {}], ], }, }); diff --git a/package-lock.json b/package-lock.json index 043f8b60a..227072857 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "dependencies": { "@astrojs/markdown-remark": "^6.3.1", "@astrojs/starlight": "^0.34.0", + "@astrojs/ts-plugin": "^1.10.4", "@fontsource/roboto": "^5.2.5", "@pasqal-io/starlight-client-mermaid": "^0.1.0", "@resvg/resvg-js": "^2.6.2", @@ -234,6 +235,30 @@ "node": "^18.17.1 || ^20.3.0 || >=22.0.0" } }, + "node_modules/@astrojs/ts-plugin": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/@astrojs/ts-plugin/-/ts-plugin-1.10.4.tgz", + "integrity": "sha512-rapryQINgv5VLZF884R/wmgX3mM9eH1PC/I3kkPV9rP6lEWrRN1YClF3bGcDHFrf8EtTLc0Wqxne1Uetpevozg==", + "license": "MIT", + "dependencies": { + "@astrojs/compiler": "^2.10.3", + "@astrojs/yaml2ts": "^0.2.2", + "@jridgewell/sourcemap-codec": "^1.4.15", + "@volar/language-core": "~2.4.7", + "@volar/typescript": "~2.4.7", + "semver": "^7.3.8", + "vscode-languageserver-textdocument": "^1.0.11" + } + }, + "node_modules/@astrojs/yaml2ts": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@astrojs/yaml2ts/-/yaml2ts-0.2.2.tgz", + "integrity": "sha512-GOfvSr5Nqy2z5XiwqTouBBpy5FyI6DEe+/g/Mk5am9SjILN1S5fOEvYK0GuWHg98yS/dobP4m8qyqw/URW35fQ==", + "license": "MIT", + "dependencies": { + "yaml": "^2.5.0" + } + }, "node_modules/@babel/helper-string-parser": { "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", @@ -2637,6 +2662,32 @@ "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", "license": "ISC" }, + "node_modules/@volar/language-core": { + "version": "2.4.12", + "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.12.tgz", + "integrity": "sha512-RLrFdXEaQBWfSnYGVxvR2WrO6Bub0unkdHYIdC31HzIEqATIuuhRRzYu76iGPZ6OtA4Au1SnW0ZwIqPP217YhA==", + "license": "MIT", + "dependencies": { + "@volar/source-map": "2.4.12" + } + }, + "node_modules/@volar/source-map": { + "version": "2.4.12", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.12.tgz", + "integrity": "sha512-bUFIKvn2U0AWojOaqf63ER0N/iHIBYZPpNGogfLPQ68F5Eet6FnLlyho7BS0y2HJ1jFhSif7AcuTx1TqsCzRzw==", + "license": "MIT" + }, + "node_modules/@volar/typescript": { + "version": "2.4.12", + "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.12.tgz", + "integrity": "sha512-HJB73OTJDgPc80K30wxi3if4fSsZZAOScbj2fcicMuOPoOkcf9NNAINb33o+DzhBdF9xTKC1gnPmIRDous5S0g==", + "license": "MIT", + "dependencies": { + "@volar/language-core": "2.4.12", + "path-browserify": "^1.0.1", + "vscode-uri": "^3.0.8" + } + }, "node_modules/@yarnpkg/lockfile": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", @@ -8336,6 +8387,12 @@ "node": ">=6" } }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "license": "MIT" + }, "node_modules/path-data-parser": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/path-data-parser/-/path-data-parser-0.1.0.tgz", diff --git a/package.json b/package.json index 3e9b0e975..5c83d2858 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "dependencies": { "@astrojs/markdown-remark": "^6.3.1", "@astrojs/starlight": "^0.34.0", + "@astrojs/ts-plugin": "^1.10.4", "@fontsource/roboto": "^5.2.5", "@pasqal-io/starlight-client-mermaid": "^0.1.0", "@resvg/resvg-js": "^2.6.2", diff --git a/src/content/docs/identityserver/apis/aspnetcore/confirmation.md b/src/content/docs/identityserver/apis/aspnetcore/confirmation.md index 964e0b0cf..da03a67bf 100644 --- a/src/content/docs/identityserver/apis/aspnetcore/confirmation.md +++ b/src/content/docs/identityserver/apis/aspnetcore/confirmation.md @@ -10,7 +10,7 @@ redirect_from: - /identityserver/v7/apis/aspnetcore/confirmation/ --- -IdentityServer can [bind tokens to clients](/identityserver/tokens/pop#proof-of-possession-styles) using either mTLS or DPoP, creating a `Proof-of-Possession` (PoP) access token. When one of these mechanisms is used, APIs that use those access tokens for authorization need to validate the binding between the client and token. This document describes how to perform such validation, depending on which mechanism was used to produce a PoP token. +IdentityServer can [bind tokens to clients](/identityserver/tokens/pop.md#proof-of-possession-styles) using either mTLS or DPoP, creating a `Proof-of-Possession` (PoP) access token. When one of these mechanisms is used, APIs that use those access tokens for authorization need to validate the binding between the client and token. This document describes how to perform such validation, depending on which mechanism was used to produce a PoP token. ### Validating mTLS diff --git a/src/components/duende-og-image.tsx b/src/plugins/duende-og-image.tsx similarity index 100% rename from src/components/duende-og-image.tsx rename to src/plugins/duende-og-image.tsx diff --git a/src/plugins/remove-markdown-extensions.ts b/src/plugins/remove-markdown-extensions.ts new file mode 100644 index 000000000..9250ae1f9 --- /dev/null +++ b/src/plugins/remove-markdown-extensions.ts @@ -0,0 +1,37 @@ +import { visit } from "unist-util-visit"; +import type { Node, Parent } from "unist"; + +interface Element extends Parent { + type: "element"; + tagName: string; + properties: { + [key: string]: unknown; + }; + content: Node; + children: Node[]; +} + +export default function removeMarkdownExtensions(): (tree: Node) => void { + return (tree: Node) => { + visit(tree, "element", (node: Element) => { + if ( + node.tagName === "a" && + node.properties && + typeof node.properties.href === "string" + ) { + const markdownExtensionRegex = /\.md(#.*)?$/; + if (markdownExtensionRegex.test(node.properties.href)) { + let date = new Date().toLocaleTimeString("en-US", { hour12: false }); + console.log( + `\x1b[90m${date}\x1b[0m \x1b[95m[🔥 *.md]\x1b[0m ${node.properties.href}`, + ); + + node.properties.href = node.properties.href.replace( + markdownExtensionRegex, + "$1", + ); + } + } + }); + }; +} diff --git a/tsconfig.json b/tsconfig.json index 175e17cf6..fd99587e0 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,9 +3,17 @@ "include": [".astro/types.d.ts", "**/*"], "exclude": ["dist"], "compilerOptions": { + "verbatimModuleSyntax": true, "baseUrl": ".", "paths": { - "~/*": ["src/*"] - } + "~/*": ["src/*"], + "@plugins/*": ["src/plugins/*"], + "@components/*": ["src/components/*"] + }, + "plugins": [ + { + "name": "@astrojs/ts-plugin" + } + ] } } From 2d44929a36573502f7888e2e530aec7d76fe82f5 Mon Sep 17 00:00:00 2001 From: khalidabuhakmeh Date: Thu, 24 Apr 2025 14:14:49 -0400 Subject: [PATCH 2/8] Refactor markdown extension removal logic Support for `.md`, `.mdx`, and `index.md(x)` variations. This should make it easier to link things moving forward. --- src/plugins/remove-markdown-extensions.ts | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/plugins/remove-markdown-extensions.ts b/src/plugins/remove-markdown-extensions.ts index 9250ae1f9..b98de44c8 100644 --- a/src/plugins/remove-markdown-extensions.ts +++ b/src/plugins/remove-markdown-extensions.ts @@ -19,17 +19,15 @@ export default function removeMarkdownExtensions(): (tree: Node) => void { node.properties && typeof node.properties.href === "string" ) { - const markdownExtensionRegex = /\.md(#.*)?$/; - if (markdownExtensionRegex.test(node.properties.href)) { + const match = /(?:\/index)?\.(md|mdx)(#.*)?$/; + if (match.test(node.properties.href)) { let date = new Date().toLocaleTimeString("en-US", { hour12: false }); + console.log( - `\x1b[90m${date}\x1b[0m \x1b[95m[🔥 *.md]\x1b[0m ${node.properties.href}`, + `\x1b[90m${date}\x1b[0m \x1b[95m[🔥 *.md(x)]\x1b[0m ${node.properties.href}`, ); - node.properties.href = node.properties.href.replace( - markdownExtensionRegex, - "$1", - ); + node.properties.href = node.properties.href.replace(match, "$2"); } } }); From 94283d84014dfd99789ea84742cefc6829a9b98b Mon Sep 17 00:00:00 2001 From: khalidabuhakmeh Date: Thu, 24 Apr 2025 14:30:58 -0400 Subject: [PATCH 3/8] Out with ReHype and in with ReMark! ReHyper operates on the HTML, while ReMark processes the Markdown, giving us an opportunity to clean up links before they are processed and link checked. --- astro.config.mjs | 2 +- .../docs/identitymodel-oidcclient/manual.md | 2 +- .../docs/identityserver/ui/login/mfa.md | 2 +- src/plugins/remove-markdown-extensions.ts | 37 ++++++++----------- 4 files changed, 18 insertions(+), 25 deletions(-) diff --git a/astro.config.mjs b/astro.config.mjs index 11076c9ab..c1a1776d8 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -183,6 +183,7 @@ export default defineConfig({ }), ], markdown: { + remarkPlugins: [removeMarkdownExtensions], rehypePlugins: [ [ rehypeAstroRelativeMarkdownLinks, @@ -202,7 +203,6 @@ export default defineConfig({ rel: ["noopener", "noreferrer"], }, ], - [removeMarkdownExtensions, {}], ], }, }); diff --git a/src/content/docs/identitymodel-oidcclient/manual.md b/src/content/docs/identitymodel-oidcclient/manual.md index 594c84368..6c999d46a 100644 --- a/src/content/docs/identitymodel-oidcclient/manual.md +++ b/src/content/docs/identitymodel-oidcclient/manual.md @@ -10,7 +10,7 @@ redirect_from: OpenID Connect is a protocol that allows you to authenticate users using a browser and involves browser-based interactions. When using this -library you can choose between two modes: [automatic](./automatic.md) and manual. +library you can choose between two modes: [automatic](/identitymodel-oidcclient/automatic.md) and manual. We recommend using automatic mode when possible, but sometimes you need to use manual mode when you want to handle browser interactions yourself. diff --git a/src/content/docs/identityserver/ui/login/mfa.md b/src/content/docs/identityserver/ui/login/mfa.md index 0a768656a..37f143b15 100644 --- a/src/content/docs/identityserver/ui/login/mfa.md +++ b/src/content/docs/identityserver/ui/login/mfa.md @@ -9,7 +9,7 @@ redirect_from: - /identityserver/v7/ui/login/mfa/ --- -Duende IdentityServer itself doesn't implement multi-factor authentication (MFA). MFA is part of the login process in the user interface which is the [responsibility of the hosting application](../index.md). Microsoft provides some [general guidelines](https://learn.microsoft.com/en-us/aspnet/core/security/authentication/mfa) on how to enable MFA in ASP.NET Core. +Duende IdentityServer itself doesn't implement multi-factor authentication (MFA). MFA is part of the login process in the user interface which is the [responsibility of the hosting application](/identityserver/ui/index.md). Microsoft provides some [general guidelines](https://learn.microsoft.com/en-us/aspnet/core/security/authentication/mfa) on how to enable MFA in ASP.NET Core. ## MFA Hosted In IdentityServer diff --git a/src/plugins/remove-markdown-extensions.ts b/src/plugins/remove-markdown-extensions.ts index b98de44c8..ff25e2d68 100644 --- a/src/plugins/remove-markdown-extensions.ts +++ b/src/plugins/remove-markdown-extensions.ts @@ -1,35 +1,28 @@ import { visit } from "unist-util-visit"; import type { Node, Parent } from "unist"; +import type { Plugin } from "unified"; interface Element extends Parent { - type: "element"; - tagName: string; - properties: { - [key: string]: unknown; - }; - content: Node; + type: "link"; + url: string; children: Node[]; } -export default function removeMarkdownExtensions(): (tree: Node) => void { +const removeMarkdownExtensions: Plugin = function () { return (tree: Node) => { - visit(tree, "element", (node: Element) => { - if ( - node.tagName === "a" && - node.properties && - typeof node.properties.href === "string" - ) { - const match = /(?:\/index)?\.(md|mdx)(#.*)?$/; - if (match.test(node.properties.href)) { - let date = new Date().toLocaleTimeString("en-US", { hour12: false }); + visit(tree, "link", (node: Element) => { + const match = /(?:\/index)?\.(md|mdx)(#.*)?$/; + if (match.test(node.url)) { + let date = new Date().toLocaleTimeString("en-US", { hour12: false }); - console.log( - `\x1b[90m${date}\x1b[0m \x1b[95m[🔥 *.md(x)]\x1b[0m ${node.properties.href}`, - ); + console.log( + `\x1b[90m${date}\x1b[0m \x1b[95m[🔥 *.md(x)]\x1b[0m ${node.url}`, + ); - node.properties.href = node.properties.href.replace(match, "$2"); - } + node.url = node.url.replace(match, "$2"); } }); }; -} +}; + +export default removeMarkdownExtensions; From 5002d79a814fcd9b8be2ec3090b614cc6e9671a5 Mon Sep 17 00:00:00 2001 From: khalidabuhakmeh Date: Thu, 24 Apr 2025 14:46:27 -0400 Subject: [PATCH 4/8] Add option to ignore relative links in removeMarkdownExtensions Introduce the `ignoreRelativeLinks` option to the `removeMarkdownExtensions` plugin, allowing users to bypass processing for relative links. Updated `astro.config.mjs` to enable this option by default. --- astro.config.mjs | 2 +- src/plugins/remove-markdown-extensions.ts | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/astro.config.mjs b/astro.config.mjs index c1a1776d8..ed096e952 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -183,7 +183,7 @@ export default defineConfig({ }), ], markdown: { - remarkPlugins: [removeMarkdownExtensions], + remarkPlugins: [[removeMarkdownExtensions, { ignoreRelativeLinks: true }]], rehypePlugins: [ [ rehypeAstroRelativeMarkdownLinks, diff --git a/src/plugins/remove-markdown-extensions.ts b/src/plugins/remove-markdown-extensions.ts index ff25e2d68..1b450226f 100644 --- a/src/plugins/remove-markdown-extensions.ts +++ b/src/plugins/remove-markdown-extensions.ts @@ -8,10 +8,22 @@ interface Element extends Parent { children: Node[]; } -const removeMarkdownExtensions: Plugin = function () { +interface RemoveMarkdownExtensionsOptions { + ignoreRelativeLinks?: boolean; +} + +const match = /(?:\/index)?\.(md|mdx)(#.*)?$/; + +const removeMarkdownExtensions: Plugin = function ({ + ignoreRelativeLinks = false, +}: RemoveMarkdownExtensionsOptions = {}) { return (tree: Node) => { visit(tree, "link", (node: Element) => { - const match = /(?:\/index)?\.(md|mdx)(#.*)?$/; + // ignore relative links if configured + if (ignoreRelativeLinks && node.url.startsWith("./")) { + return; + } + if (match.test(node.url)) { let date = new Date().toLocaleTimeString("en-US", { hour12: false }); From 2da0af445741391c6259423b80894fea425f40d2 Mon Sep 17 00:00:00 2001 From: Maarten Balliauw Date: Fri, 25 Apr 2025 14:19:30 +0200 Subject: [PATCH 5/8] Oxford comma --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 60ac44fee..714b61734 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ You will need Node 22+ installed on your operating system and in the PATH. * Run `npm install` to restore all dependencies. * Use `npm run dev` to run the documentation site locally. -Alternatively in VS Code, GitHub Codespaces or WebStorm, you can use the devcontainer to get a development environment set up. +Alternatively in VS Code, GitHub Codespaces, or WebStorm, you can use the devcontainer to get a development environment set up. ## Project Structure From 6f4da2e66a88e8d5889f4c378483548315f50012 Mon Sep 17 00:00:00 2001 From: Maarten Balliauw Date: Fri, 25 Apr 2025 14:48:28 +0200 Subject: [PATCH 6/8] Update README with linking rules --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index 714b61734..8850b5b8e 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,16 @@ Content can be authored in Markdown, in a `.md` or `.mdx` file. The Starlight do * [Authoring Content in Markdown](https://starlight.astro.build/guides/authoring-content/) * [Using Components](https://starlight.astro.build/components/using-components/) (only in `.mdx`) +### Linking Rules + +* Always prefer linking internally over linking externally. For example, when you talk about data protection, prefer an internal link over a link to external sites. +* When linking to external content, consider writing one or two sentences about the context and what the reader will learn on the linked page. +* When linking other pages, use a path that starts at the content root, like `/identityserver/troubleshooting.md`. Use the `.md(x)` file extension - Starlight will update the link to the correct format on build. +* When linking to external resources, use the full URL using HTTPS. +* You can link to header anchors using the `#` symbol, for example `[multiple authentication methods](/identityserver/ui/federation.md#multiple-authentication-methods-for-users)`. +* Link relevant text. Prefer `learn more about [improving the sign-in experience]` over `click [here] to learn more`. +* Run `npm run linkchecker` to validate all links (note this will ignore links to GitHub because of rate limits in place). + ## 🧞 Commands All commands are run from the root of the project, from a terminal: From 5118a0b9978c64e48f916ee3bae1086d70a217eb Mon Sep 17 00:00:00 2001 From: Maarten Balliauw Date: Fri, 25 Apr 2025 15:12:19 +0200 Subject: [PATCH 7/8] Update README with authoring guidance/writing style --- README.md | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/README.md b/README.md index 8850b5b8e..22b5cb017 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,20 @@ Content can be authored in Markdown, in a `.md` or `.mdx` file. The Starlight do * [Authoring Content in Markdown](https://starlight.astro.build/guides/authoring-content/) * [Using Components](https://starlight.astro.build/components/using-components/) (only in `.mdx`) +Use a spell checker like [Grazie](https://www.jetbrains.com/grazie/) or [Grammarly](https://www.grammarly.com/) to check your content for spelling and grammar errors. +WebStorm has Grazie as a built-in spell checker and grammar checker, and supports a good default writing style. + +### Writing Style + +* Use the active voice. For example, use "Enable" instead of "Enabled" or "Enabling". +* Use the second person ("you" not "I" or "we"). "You" is the reader of the documentation. "We" is Duende Software. +* Use sentence case in text. Titles use Title Case. +* Use the Oxford comma. +* Avoid words like "very", "simple", "easy", ... +* "As well as" can be written as "and". +* Avoid flowery language. +* When using acronyms, use the full form with parentheses the first time you use it. For example, use "Multi-Factor Authentication (MFA)" instead of "MFA". + ### Linking Rules * Always prefer linking internally over linking externally. For example, when you talk about data protection, prefer an internal link over a link to external sites. @@ -49,6 +63,31 @@ Content can be authored in Markdown, in a `.md` or `.mdx` file. The Starlight do * Link relevant text. Prefer `learn more about [improving the sign-in experience]` over `click [here] to learn more`. * Run `npm run linkchecker` to validate all links (note this will ignore links to GitHub because of rate limits in place). +### Code Block Style + +* Use triple backticks to enclose code blocks. +* Use a language identifier to specify the language (e.g. `csharp`, `bash`, `json`, `html`, `javascript`, `typescript`, `css`, `json`) +* Add a title to the code block. You can do this adding the title as a comment in the first line of the code block (e.g. `// Program.cs`). +* Use [expressive code features](https://starlight.astro.build/guides/authoring-content/#expressive-code-features). +* Readers should not need to scroll horizontally to read a code example. Simplify and condense the code as much as possible. +* If writing C#, use the latest syntax — including top-level statements, collection expressions, ... +* Make sure examples are runnable and complete. The goal is "Copy-paste from docs". Include namespaces, a result, and other prerequisites that are not obvious to someone new to the code. +* Inline comments can be used to explain essential parts of the code. Expressive code can highlight line numbers, show diffs, and more. +* Mention NuGet packages as a `bash` code block showing how to install it (`dotnet add package ...`). Link to the NuGet Gallery. + +### Frontmatter Rules + +* Always have a `title` property to set the page title. +* Always have a `description` property to set the page description. +* Always have a `date` property to set the creation/significant update date for a page. Use the `YYYY-MM-DD` format. +* Add the `sidebar` property and include the `label`. The `label` is used in the menu, and should typically be shorter than the more descriptive `title`. For example: + ```yaml + title: "Using IdentityServer As A Federation Gateway" + sidebar: + label: "Federation" + ``` +* In the `sidebar` property, use `order` to re-order entries in the navigation bar. + ## 🧞 Commands All commands are run from the root of the project, from a terminal: From 7179cf203aed9beefd95f3ed78c3b4d9368ea7c2 Mon Sep 17 00:00:00 2001 From: Maarten Balliauw Date: Fri, 25 Apr 2025 15:13:02 +0200 Subject: [PATCH 8/8] Update logic to ignore additional relative link patterns --- src/plugins/remove-markdown-extensions.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/plugins/remove-markdown-extensions.ts b/src/plugins/remove-markdown-extensions.ts index 1b450226f..07a7db150 100644 --- a/src/plugins/remove-markdown-extensions.ts +++ b/src/plugins/remove-markdown-extensions.ts @@ -20,7 +20,10 @@ const removeMarkdownExtensions: Plugin = function ({ return (tree: Node) => { visit(tree, "link", (node: Element) => { // ignore relative links if configured - if (ignoreRelativeLinks && node.url.startsWith("./")) { + if ( + ignoreRelativeLinks && + (node.url.startsWith("./") || node.url.startsWith("../")) + ) { return; }