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/README.md b/README.md index 60ac44fee..22b5cb017 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 @@ -39,6 +39,55 @@ 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. +* 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). + +### 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: diff --git a/astro.config.mjs b/astro.config.mjs index bf0686174..ed096e952 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", @@ -180,6 +183,7 @@ export default defineConfig({ }), ], markdown: { + remarkPlugins: [[removeMarkdownExtensions, { ignoreRelativeLinks: true }]], rehypePlugins: [ [ rehypeAstroRelativeMarkdownLinks, 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/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/apis/aspnetcore/confirmation.md b/src/content/docs/identityserver/apis/aspnetcore/confirmation.md index b09452a93..6c8a0ff18 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 +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. 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/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..07a7db150 --- /dev/null +++ b/src/plugins/remove-markdown-extensions.ts @@ -0,0 +1,43 @@ +import { visit } from "unist-util-visit"; +import type { Node, Parent } from "unist"; +import type { Plugin } from "unified"; + +interface Element extends Parent { + type: "link"; + url: string; + children: Node[]; +} + +interface RemoveMarkdownExtensionsOptions { + ignoreRelativeLinks?: boolean; +} + +const match = /(?:\/index)?\.(md|mdx)(#.*)?$/; + +const removeMarkdownExtensions: Plugin = function ({ + ignoreRelativeLinks = false, +}: RemoveMarkdownExtensionsOptions = {}) { + return (tree: Node) => { + visit(tree, "link", (node: Element) => { + // ignore relative links if configured + if ( + ignoreRelativeLinks && + (node.url.startsWith("./") || node.url.startsWith("../")) + ) { + return; + } + + 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.url}`, + ); + + node.url = node.url.replace(match, "$2"); + } + }); + }; +}; + +export default removeMarkdownExtensions; 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" + } + ] } }