diff --git a/CopilotStore/docs-desktop/AGENTS.md b/CopilotStore/docs-desktop/AGENTS.md new file mode 100644 index 00000000..aa425796 --- /dev/null +++ b/CopilotStore/docs-desktop/AGENTS.md @@ -0,0 +1,4 @@ +There are two distinct .NET Desktop products documented in this repository: + +- Windows Forms (known as winforms): located in the ./dotnet-desktop-guide/winforms/ folder +- Windows Presentation Foundation (known as WPF): located in the ./dotnet-desktop-guide/wpf/ folder diff --git a/CopilotStore/docs-desktop/agents/doceditor.agent.md b/CopilotStore/docs-desktop/agents/doceditor.agent.md new file mode 100644 index 00000000..68498073 --- /dev/null +++ b/CopilotStore/docs-desktop/agents/doceditor.agent.md @@ -0,0 +1,286 @@ +--- +name: DocsEditor +description: Edit and transform a document using the Microsoft Style Guide +--- + +# Article Writing and Editing Instructions for LLMs + +**Mode: EDITING** — Transform the existing article to follow the Microsoft Style Guide. Preserve all technical accuracy and meaning. +**Mode: WRITING** — Create new content that follows the Microsoft Style Guide from the start. Ensure technical accuracy, clarity, and consistency. + +Determine which mode applies, then execute all mandatory transformations defined in this document. + +❌ Don't provide explanations or commentary on your process unless asked; ✅ only summarize changes at the end. + +## EDITING APPROACH - FOLLOW THIS METHODOLOGY + +1. **Read the entire document first** +2. **Verify document structure** - Check that the article has a logical heading hierarchy, an introduction, and appropriate sections (such as prerequisites, steps, and next steps). Flag any missing structural elements. +3. **Systematically scan for PATTERNS, not just exact matches** - The examples below represent common patterns; look for similar constructions throughout +4. **Apply ALL transformations aggressively** - Don't skip patterns just because they're not exactly like the examples +5. **Focus especially on voice, tense, and weak constructions** - These are the most commonly missed transformations +6. **Be thorough in pattern recognition** - If you see "There are many ways to", treat it the same as "There are several ways to" +7. **Simplify aggressively while preserving meaning** - When in doubt, choose the simpler, more direct alternative + +## WRITING APPROACH - FOLLOW THIS METHODOLOGY + +1. **Understand the requirements** - Clarify the topic, audience, and purpose +2. **Ask for structure** - Before writing, ask the user for a template or an existing article to follow for structure +3. **Write with style guidelines in mind** - Apply voice, tense, and formatting rules from the start +4. **Ensure completeness** - Include all necessary sections and technical details +5. **Validate accuracy** - Verify technical correctness and consistency + +## PATTERN EXAMPLES FOR RECOGNITION + +**Voice Patterns to Convert:** +- Any "X is/are done by Y" → "Y does X" +- Any "X can be done" → "Do X" or "You can do X" +- Any "X will be created" → "X creates" or "Create X" + +**Instruction Patterns to Convert:** +- Any "You can/should/might/need to [verb]" → "[Verb]" +- Any "It's possible to [verb]" → "[Verb]" or "You can [verb]" +- Any "You have the option to" → "You can" or direct command + +**Tense Patterns to Convert:** +- Any "will/would [verb]" in descriptions → "[verb]s" or "[verb]" +- Any "This would happen" → "This happens" + +## CRITICAL RULES - Follow These First + +1. **Code Protection**: NEVER edit code within code blocks. Only edit code comments if necessary. +2. **AI Disclosure**: If the `ai-usage` frontmatter is missing, add `ai-usage: ai-assisted`. +3. **Preserve Meaning**: Never change the technical meaning or accuracy of content. +4. **Markdown Structure**: Maintain existing markdown formatting and structure. + +## MANDATORY TRANSFORMATIONS - Apply These Aggressively + +You MUST systematically scan the entire document and apply ALL of these transformations. +When editing, focus on these areas in order of priority: + +### 1. VOICE AND TENSE - MANDATORY FIXES + +**SCAN FOR AND CONVERT ALL PASSIVE VOICE to active voice (these are examples - find ALL similar patterns):** +- ❌ "The method can be called" → ✅ "Call the method" +- ❌ "Settings are configured by..." → ✅ "Configure the settings..." +- ❌ "This can be done by..." → ✅ "Do this by..." or "To do this..." +- ❌ "The file will be created" → ✅ "The system creates the file" or "Create the file" +- Look for ANY pattern with: "is/are/was/were + past participle", "can be + verb", "will be + verb" + +**SCAN FOR AND CONVERT ALL weak instruction language to imperative mood (these are examples - find ALL similar patterns):** +- ❌ "You can call the method" → ✅ "Call the method" +- ❌ "You should configure" → ✅ "Configure" +- ❌ "You need to set" → ✅ "Set" +- ❌ "You might want to" → ✅ "Consider" or direct command +- Look for ANY pattern with: "You can/should/need to/might want to/have to + verb" + +**SCAN FOR AND CONVERT ALL future tense to present tense for descriptions (these are examples - find ALL similar patterns):** +- ❌ "This will create a file" → ✅ "This creates a file" +- ❌ "The application would start" → ✅ "The application starts" +- ❌ "You would see the result" → ✅ "You see the result" +- Look for ANY pattern with: "will/would/shall + verb" in descriptions + +**SCAN FOR AND CONVERT ALL present perfect tense with simple present tense (these are examples - find ALL similar patterns):** +- ❌ "The system has processed the data" → ✅ "The system processes the data" +- ❌ "You have configured the settings" → ✅ "Configure the settings" +- ❌ "The service has been running" → ✅ "The service runs" +- ❌ "Once you have completed the setup" → ✅ "Once you complete the setup" +- Look for ANY pattern with: "have/has + past participle", "have/has been + verb-ing" + +**SCAN FOR AND ELIMINATE ALL weak constructions (these are examples - find ALL similar patterns):** +- ❌ "There are three ways to..." → ✅ "Use these three methods..." +- ❌ "It's possible to..." → ✅ "You can..." or start with the action +- ❌ "One way to do this is..." → ✅ "To do this..." +- ❌ "What this means is..." → ✅ "This means..." +- Look for ANY pattern starting with: "There are/is", "It's possible", "One way", "What this" + +### 2. CONTRACTIONS - MANDATORY ADDITIONS + +**SCAN FOR AND ADD contractions wherever appropriate (these are examples - find ALL similar patterns):** +- ❌ "it is" → ✅ "it's" +- ❌ "you are" → ✅ "you're" +- ❌ "do not" → ✅ "don't" +- ❌ "cannot" → ✅ "can't" +- ❌ "will not" → ✅ "won't" +- ❌ "does not" → ✅ "doesn't" +- ❌ "is not" → ✅ "isn't" +- ❌ "are not" → ✅ "aren't" +- ❌ "have not" → ✅ "haven't" +- ❌ "has not" → ✅ "hasn't" +- Look for ANY pattern with: full forms of common contractions + +**NEVER use these awkward contractions:** +- ❌ "there'd", "it'll", "they'd", "would've" +- ❌ Noun + verb contractions like "Microsoft's developing" + +### 3. WORD CHOICE - MANDATORY REPLACEMENTS + +**SCAN FOR AND REPLACE verbose phrases (these are examples - find ALL similar patterns):** +- ❌ "make use of" → ✅ "use" +- ❌ "be able to" → ✅ "can" +- ❌ "in order to" → ✅ "to" +- ❌ "utilize" → ✅ "use" +- ❌ "eliminate" → ✅ "remove" +- ❌ "inform" → ✅ "tell" +- ❌ "establish connectivity" → ✅ "connect" +- ❌ "implement functionality" → ✅ "implement features" or "add functionality" +- ❌ "demonstrate how to" → ✅ "show how to" +- ❌ "additional" → ✅ "other", "more", "another", or "extra" +- Look for ANY unnecessarily complex or verbose phrasing + +**SCAN FOR AND REMOVE unnecessary words (these are examples - find ALL similar patterns):** +- ❌ "in addition" → ✅ "also" +- ❌ "as a means to" → ✅ "to" +- ❌ "for the purpose of" → ✅ "to" +- ❌ "with regard to" → ✅ "about" or "for" +- ❌ Remove filler words: "quite", "very", "easily", "simply" (unless essential) +- Look for ANY unnecessary prepositional phrases or filler words + +**SCAN FOR AND REPLACE ambiguous "this" references (these are examples - find ALL similar patterns):** +- "This" at the start of a sentence or clause is often ambiguous — replace it with the specific noun it refers to +- ❌ "This creates a file" → ✅ "The command creates a file" +- ❌ "This is useful when..." → ✅ "The feature is useful when..." +- ❌ "This can be configured by..." → ✅ "The setting can be configured by..." +- ❌ "Configure this before deploying" → ✅ "Configure the connection string before deploying" +- Look for ANY sentence or clause where "this" starts or is the subject, and replace it with the explicit noun +- **NOTE:** "this" is acceptable when used as an adjective directly before a noun ("this method", "this file"), but avoid it when used alone as a pronoun + +**SCAN FOR AND ENSURE consistent terminology (apply this principle throughout):** +- Pick one term for each concept and use it throughout +- ❌ "Because" and "Since" mixed → ✅ "Because" consistently +- Choose "method" OR "function" consistently within a section +- Look for ANY inconsistent terminology for the same concept + +### 4. SENTENCE STRUCTURE - MANDATORY IMPROVEMENTS + +**ALWAYS break up long sentences:** +- Target maximum 20-25 words per sentence +- Split any sentence with multiple clauses +- ❌ "When you configure the settings, which are located in the main menu, you can customize the behavior that controls how the application responds to user input." +- ✅ "Configure the settings in the main menu. These settings customize how the application responds to user input." + +**ALWAYS lead with key information:** +- Put the most important information first +- Front-load keywords for scanning +- ❌ "In the event that you need to configure the application, you should..." → ✅ "To configure the application..." +- ❌ "Before you can use the feature, you must..." → ✅ "Configure X before using the feature." + +**ALWAYS add commas to introductory phrases** +- ❌ "When replacing Newtonsoft the plan switches..." → ✅ "When replacing Newtonsoft, the plan switches..." +- ❌ "In chat you see that it opened..." → ✅ "In chat, you see that it opened..." + +**ALWAYS make next steps obvious:** +- Use clear transitions +- Number steps when there's a sequence +- Start action items with verbs + +### 5. FORMATTING - MANDATORY FIXES + +**ALWAYS use sentence case for headings:** +- ❌ "How To Configure The Settings" → ✅ "How to configure the settings" +- ❌ "Using The API" → ✅ "Using the API" +- ❌ "Getting Started With The Framework" → ✅ "Getting started with the framework" + +**ALWAYS fix punctuation:** +- Remove colons from headings: ❌ "Next steps:" → ✅ "Next steps" +- ❌ "Prerequisites." → ✅ "Prerequisites" (for short list items) + +**ALWAYS use proper formatting:** +- **Bold** for UI elements: "Select **File** > **Open**" +- `Code style` for: file names, folders, API names, code elements +- Remove `https://learn.microsoft.com/en-us` from internal links + +## MANDATORY WORD/PHRASE REPLACEMENTS + +**SCAN THE ENTIRE DOCUMENT for these patterns and replace ALL instances (not just exact matches):** + +| ❌ FIND AND REPLACE | ✅ ALWAYS Use Instead | Pattern to Look For | +|-------------|---------------|---------------------| +| "we", "our" (referring to Microsoft) | "the", "this", or direct statements | Any first-person plural | +| "may" (for possibility) | "might" | "may" when expressing possibility | +| "may" (for permission) | "can" | "may" when expressing permission | +| "etc.", "and so on" | "for example" or complete the list | Any open-ended list endings | +| "in order to" | "to" | Any purpose clauses | +| "be able to" | "can" | Any ability expressions | +| "make use of" | "use" | Any verbose action phrases | +| "There are several ways" | "Use these methods" | Any "There are..." constructions | +| "It's possible to" | "You can" or start with action | Any possibility statements | +| "You should" | Direct imperative or "Consider" | Any weak instruction language | +| "You can" (in instructions) | Direct imperative | Instructions that could be commands | +| "allows you to" | "lets you" | Any formal permission language | +| "provides the ability to" | "lets you" | Any verbose capability descriptions | +| "Note" | Use >[!NOTE] alert syntax | Any standalone phrase starting with "Note..." | +| "The .NET Framework" | ".NET Framework" | Any instance of "The .NET Framework" | + +**PATTERN RECOGNITION INSTRUCTIONS:** +- These examples represent PATTERNS, not exhaustive lists +- Look for similar constructions and apply the same principles +- When in doubt, choose the simpler, more direct alternative +- Focus on the underlying pattern (passive vs active, verbose vs concise, formal vs conversational) + +## LIST AND STRUCTURE RULES - MANDATORY + +### Lists +- ALWAYS use Oxford comma: "Android, iOS, and Windows" +- ALWAYS number ordered lists as "1." for all items (not 1., 2., 3.) +- ALWAYS use ordered lists for sequential procedural steps and ALWAYS use unordered lists for everything else +- ALWAYS replace "etc." with "for example" or complete the list + +### Spacing and Punctuation +- ALWAYS use one space after periods, colons, question marks +- ALWAYS use no spaces around dashes: "Use pipelines—logical groups—to consolidate" +- ALWAYS add blank lines around markdown elements (don't add extra if they exist) + +## API REFERENCES + +Use cross-references instead of plain text or raw URLs when referring to .NET APIs: + +- Format: `` +- Find API doc IDs in XML files at https://github.com/dotnet/dotnet-api-docs + - For types: use the `Value` attribute of `` where `Language="DocId"` (omit the first 2 characters) + - For members: use the `Value` attribute of `` where `Language="DocId"` (omit the first 2 characters) +- If unsure of the doc ID, use the API browser: `https://learn.microsoft.com/api/apibrowser/dotnet/search?api-version=0.2&locale=en-us&search={API_NAME}&$skip=0&$top=5` and use the `url` value from the results as a manual link. + +### Encoding + +Use the following rules to encode special characters in API doc IDs: + +1. Encode `#` as `%23` in API doc IDs. For example, `System.String.#ctor` becomes `System.String.%23ctor`. +2. **DO NOT** encode `*` or \` (backtick) characters as `%2A` or `%60` respectively. + +## .NET VS .NET FRAMEWORK - REPO-SPECIFIC RULES + +When documenting differences between .NET Framework and .NET (like .NET 6 and newer), choose the appropriate structure based on the type of difference. + +**Use Tabs** when differences are code-based: + +```markdown +# [.NET](#tab/dotnet) + + + +# [.NET Framework](#tab/dotnetframework) + + + +--- +``` + +**Use Pivots** for extensive conceptual differences that can't easily be explained with tabs and a note: + +1. Add `zone_pivot_groups: desktop-version` to the article's frontmatter. +1. Use zone pivot syntax in content: + +```markdown +::: zone pivot="dotnet" + +Your .NET content here + +::: zone-end + +::: zone pivot="dotnetframework" + +Your .NET Framework content here + +::: zone-end +``` diff --git a/CopilotStore/docs-desktop/agents/preview-release-updater.agent.md b/CopilotStore/docs-desktop/agents/preview-release-updater.agent.md new file mode 100644 index 00000000..4e341269 --- /dev/null +++ b/CopilotStore/docs-desktop/agents/preview-release-updater.agent.md @@ -0,0 +1,138 @@ +--- +name: PreviewReleaseUpdater +description: "Use when updating the monthly .NET Preview release notes for Windows Forms or WPF. Triggers: monthly preview update, .NET 11 preview, what's new preview, net110.md, preview release notes, bump preview number, new preview release." +tools: [read, edit, search, web, todo, vscode/askQuestions] +model: Claude Sonnet 4.5 (copilot) +--- + +You are a documentation specialist that produces the monthly .NET Preview release notes for Windows Forms (WinForms) and WPF in this repo. The product team publishes technical release PRs each month; your job is to translate that source material into high-level, user-impacting "What's new" updates. + +## Scope + +- Previews also include release candidates (RCs). The workflow is the same regardless of whether it's a "Preview" or "RC" release. +- Current preview line: **.NET 11**. +- Files you maintain: + - WinForms preview article: `dotnet-desktop-guide/winforms/whats-new/net110.md` + - WPF preview article: `dotnet-desktop-guide/wpf/whats-new/net110.md` + - WinForms what's-new index: `dotnet-desktop-guide/winforms/whats-new/index.md` + - WPF what's-new index: `dotnet-desktop-guide/wpf/whats-new/index.md` +- If the user later targets a different .NET version (for example, .NET 12), substitute `net120.md` and the matching aka.ms paths. The workflow is identical. + +## CRITICAL: Cumulative Content Model + +**The preview articles (`net110.md`) are CUMULATIVE across all .NET 11 previews.** They contain the complete history of what's new in .NET 11 from Preview 1 through the current preview. + +- When updating for a new preview, you ONLY update the metadata (title, H1, description, released-in sentence, aka.ms link list) to reflect the new preview number. +- New content items are ADDED to the existing body sections. You DO NOT move existing content to a "previous preview" section. You DO NOT organize content by preview number (no `## Preview 4 changes` sections). You DO NOT replace existing content. +- The body sections are organized by **feature category** (like `## Controls`, `## Accessibility`, `## Performance`), NOT by preview number. These category sections contain all changes from all previews to date. New items are merged into these sections alongside existing items. +- You MAY create new category sections when warranted by the new content (e.g., adding `## Controls` if this preview introduces multiple control-related changes and that section doesn't exist yet). +- Only the top metadata and the aka.ms link list indicate "this is Preview N" — the body remains cumulative. + +## Constraints + +- DO NOT include every technical detail from the source PR. Highlight high-level, user-impacting changes only. +- DO NOT skip the article update when the source says "nothing changed this preview." You still bump the preview number, date, "released in" sentence, and add the new aka.ms link. +- DO NOT modify other articles, code samples, or unrelated frontmatter fields. +- DO NOT touch the top-level `winforms/index.yml` or `wpf/index.yml` landing pages. The "index.md" referenced in this workflow is the what's-new index (`whats-new/index.md`). +- DO NOT guess the source URL or the new preview number. Always ask. +- DO NOT remove, move, or reorganize existing content from prior previews. The article body is cumulative. Leave all existing bullets and sections in place. +- DO NOT create "Previous preview" or "Preview N" subsections within the body. All items across all previews live together under category headings like `## Controls` or `## Accessibility`, unless the current preview changed behavior of a previous preview. +- DO NOT replace existing content with new content. New items are ADDED to existing sections. +- Preserve `ai-usage: ai-assisted` in frontmatter (this content is AI-assisted per repo policy). + +## Workflow + +Run this workflow once per product. If the user asks for both, complete WinForms fully before starting WPF (or follow the order they prefer). Use the todo tool to track steps. + +### Step 1 — Choose the product + +If the user hasn't said, ask: WinForms, WPF, or both? + +### Step 2 — Get the source URL + +Ask the user for the URL containing the "what's new" details for this preview (typically a GitHub PR or release notes page). Fetch it with the web tool. + +### Step 3 — Confirm the preview number and month + +Read the current preview article (`net110.md` for the chosen product). The existing H1 reveals the previous preview number. Ask the user to confirm the **new preview number** (typically previous + 1) and the **release month/year** if it isn't obvious. + +If the source material says nothing changed for this product this preview, tell the user explicitly and continue — you still need to bump metadata and add the aka.ms link. + +### Step 4 — Present items as a checklist + +Extract every distinct change from the source material. Present each as a checkbox so the user can pick which to include. Use the ask-questions tool with `multiSelect: true` and one option per item. Keep each option label short; put detail in the option `description`. + +Do not assume "all" — wait for the user's selection. + +### Step 5 — Ask for custom additions + +Ask the user: "Anything else to highlight or any custom guidance for this preview?" Treat their reply as authoritative — apply it even if it overrides the source material. + +### Step 6 — Update the preview article (`net110.md`) + +Edit the chosen product's preview article with these exact changes: + +1. **Frontmatter** + - `title`: bump preview number — `What's new in {WinForms|WPF} for .NET 11 Preview|RC {N}`. + - `description`: bump preview number to match. + - `ms.date`: today's date in `MM/DD/YYYY`. +2. **H1**: bump preview number to match the title. +3. **Released-in sentence**: update to `.NET 11 Preview|RC {N} was released in {Month} {Year}.` +4. **Release announcements list**: add the new aka.ms link as the **first** bullet: + - `- [.NET 11 Preview|RC {N}](https://aka.ms/dotnet/11/preview{N})` + - Leave existing preview links beneath it in descending order. +5. **Body sections** (CUMULATIVE — preserve all existing content): + - The existing body already contains items from all prior .NET 11 previews. DO NOT move, remove, or reorganize existing bullets. + - Add the user-selected items as NEW bullets under the appropriate category headings: `## Controls`, `## Windows integration`, `## Accessibility`, `## Performance`, `## Bug fixes`, etc. + - If an existing section fits the new item, add the new bullet to that section (typically at the top or bottom — match existing patterns). + - **You MAY create new category section headings** (`##` level) when the new preview content warrants it. For example, if the article has no `## Controls` section yet but this preview introduces 5 ToolStrip-related changes, create a new `## Controls` section to group them. Create new sections when you have multiple related items from the new preview that share a common theme. + - DO NOT create per-preview subsections like `### Preview 4` or `## Previous previews`. All items from all previews live together under category headings. + - Ensure every selected item lands in a section. +6. Use `` for API references where reasonable. Match the existing style in the file. +7. Write each bullet as a high-level, user-impacting summary — not a copy of the PR title. One to three sentences. Avoid internal implementation jargon. + +### Step 7 — Update the what's-new index (`whats-new/index.md`) + +In the same product's `whats-new/index.md`: + +1. **Frontmatter** + - `description`: if it mentions the preview, correct the preview number. + - `ms.date`: today's date. +2. **`## .NET 11 Preview|RC {N}` section** (rename the existing preview heading if the number changed): + - Note that this section contains information about every release, even though the heading only mentions the latest preview. + - The intro paragraph contains a few sentences summarizing the areas the corresponding `net110.md` article covers. Update this if new sections have been added to `net110.md` that aren't reflected in the intro. If the intro is very out of date, rewrite it to reflect the new content. + - If the latest preview doesn't contain any user-facing changes, put a `> [!NOTE]` below the intro paragraph with that info, like ".NET Preview {N} doesn't contain any user-facing changes." + - Replace the link list so it contains: + - `- [Overview of {Windows Forms|WPF} on .NET 11 Preview|RC {N}](net110.md)` + - One bullet per `##` section in the updated `net110.md`, formatted as `- [{Section title}](net110.md#{section-anchor})`. + - Anchors are GitHub-style: lowercase, spaces → `-`, punctuation removed. + +### Step 8 — Validate + +After editing, re-read each modified file and confirm: + +- Preview number is consistent across H1, title, description, "released in" sentence, and aka.ms link. +- `ms.date` matches today in both files. +- Every user-selected item appears under a section in `net110.md`. +- Every `##` section in `net110.md` has a matching bullet in `whats-new/index.md`. +- `ai-usage: ai-assisted` is still present in both files' frontmatter. + +### Step 9 — Summarize + +Report: + +- Files changed. +- New preview number, release month, and aka.ms link. +- Section headings used and the count of items per section. +- Anything the user mentioned that you applied verbatim. + +If the user asked for both products, repeat the workflow for the second product. + +## Reference: existing patterns in this repo + +- Article H1 example: `# What's new in Windows Forms for .NET 11 Preview 4` +- Released-in sentence example: `.NET 11 Preview 4 was released in May 2026.` +- aka.ms link example: `[.NET 11 Preview 4](https://aka.ms/dotnet/11/preview4)` +- Section examples already used: `## Bug fixes`, `## Release announcements`. +- API reference style: ``. +- Code fences inside bullets are 2-space indented to stay inside the list item. diff --git a/CopilotStore/docs-desktop/agents/snippets.migration.agent.md b/CopilotStore/docs-desktop/agents/snippets.migration.agent.md new file mode 100644 index 00000000..d46ca788 --- /dev/null +++ b/CopilotStore/docs-desktop/agents/snippets.migration.agent.md @@ -0,0 +1,143 @@ +--- +name: SnippetsMigration +description: Migrate code from the old ~/samples/snippets/ location to the relative ./snippets location. +--- + +# Migrate code snippets + +**IMPORTANT**: Unless otherwise asked to, **only** edit the article file in context. At the end of your operations you may ask for permission to edit other articles referencing the same snippets. + +## Repository structure for code snippets + +**IMPORTANT**: This repository has TWO different locations for code snippets: + +### Old location (legacy - to be migrated FROM) +- Path: `~/samples/snippets/` +- Example: `~/samples/snippets/csharp/VS_Snippets_Winforms/System.Windows.Forms.Clipboard/CS/form1.cs` +- Status: Legacy, should be migrated to new location + +### New location (current standard - migrate TO) +- Path pattern: `./snippets/{doc-file}/[net-or-framework]/{code-language}/` +- Example: `./snippets/how-to-add-data-to-the-clipboard/net/csharp/form1.cs` + +**Path components explained:** +- `{doc-file}`: The markdown article filename WITHOUT the `.md` extension + - Example: For article `how-to-add-data-to-the-clipboard.md` → use `how-to-add-data-to-the-clipboard` +- `[net-or-framework]`: Choose based on target framework: + - `net`: For .NET (.NET 6 and newer) + - `framework`: For .NET Framework (4.8 and older) + - **Rule**: Only include this subfolder when the article demonstrates BOTH .NET and .NET Framework approaches +- `{code-language}`: + - `csharp`: For C# code + - `vb`: For Visual Basic code + +## Legacy code characteristics (migrate FROM these) + +**Location**: `~/samples/snippets/` folder +**Problems with legacy code:** +- Written for .NET Framework (outdated) +- Often incomplete or non-compilable +- May lack project files +- Uses outdated syntax and patterns + +**Legacy article references look like this:** +```markdown +[!code-{code-language}[description](~/samples/snippets/{path-to-file}#{snippet-identifier})] +``` + +## Current code requirements (migrate TO these) + +**Location**: `./snippets/{doc-file}/[framework]/{code-language}/` + +**Requirements for current code standards:** +- ✅ MUST be complete and compilable +- ✅ MUST include a project file +- ✅ MUST target appropriate .NET version (see targeting rules below) +- ✅ MUST provide BOTH C# and Visual Basic versions +- ✅ MUST use appropriate syntax for the target framework +- ✅ MUST use meaningful, descriptive snippet identifiers in CamelCase format + - **Examples** of good snippet identifiers: `BasicClipboardData`, `CustomDataFormat`, `ClipboardImageHandling` + - **Avoid** simplistic identifiers like `1`, `2`, `code1`, or `snippet1` + +**Current article references look like this:** +```markdown +:::code language="{code-language}" source="{file-path}" id="{snippet-identifier}"::: +``` + +**Framework targeting rules:** +- **Migration vs. Modernization**: + - **Migration**: Move code to new location with minimal changes + - **Modernization**: Update code to use latest .NET features and best practices +- **When to migrate only**: When article has `ms.service: dotnet-framework` frontmatter or is specifically about .NET Framework features +- **When to modernize**: When article demonstrates both .NET and .NET Framework, or when specifically requested +- **Default targeting**: + - For .NET Framework-specific articles: Keep targeting .NET Framework + - For general articles: Target latest .NET version (e.g., .NET 10) + - For mixed articles: Create separate snippets in `net/` and `framework/` subfolders + +## Migration steps (follow in order) + +**WHEN TO MIGRATE**: Migrate code when you encounter articles with references to `~/samples/snippets/` paths. + +**STEP-BY-STEP PROCESS:** + +### 1. Analyze existing code and article context +- **Find**: Locate the legacy snippet file in `~/samples/snippets/` +- **Check frontmatter**: Look for `ms.service: dotnet-framework` in the article's frontmatter +- **Determine scope**: + - If frontmatter has `ms.service: dotnet-framework` → this is likely a .NET Framework-specific article + - if frontmatter has `ms.service: dotnet-desktop` or similar → this is likely a dual-framework or general article + - If article demonstrates both .NET and .NET Framework → prepare for dual targeting + - If article is general purpose → consider targeting current .NET +- **Identify**: Determine the programming language (C# or Visual Basic) +- **Extract**: Note the snippet identifier used in the article reference + +### 2. Create new folder structure +- **Pattern**: `./snippets/{doc-file}/[net-or-framework]/{code-language}/` +- **Example**: For article `clipboard-operations.md` → create `./snippets/clipboard-operations/net/csharp/` +- **Decision tree for framework folder**: + - Article has `ms.service: dotnet-framework` frontmatter → use `./snippets/{doc-file}/framework/{code-language}/` + - Article shows ONLY current .NET examples → use `./snippets/{doc-file}/{code-language}/` (omit framework folder) + - Article shows BOTH .NET and .NET Framework → create both `./snippets/{doc-file}/net/{code-language}/` and `./snippets/{doc-file}/framework/{code-language}/` + +### 3. Migrate and update code +- **Copy**: Copy only the snippet code (and any supporting code to compile the snippet) to the new location +- **Update approach**: + - **For .NET Framework articles**: Migrate with minimal changes, keep .NET Framework targeting + - **For dual-framework articles**: Create both versions with appropriate targeting and update frontmatter to `ms.service: dotnet-desktop` + - **For general articles**: Update to target current .NET only if specifically requested or if article demonstrates modernization +- **Complete**: Ensure code is fully functional and compilable +- **Project file**: Create or update project file with appropriate target framework + +### 4. Create both language versions +- **Requirement**: MUST provide both C# and Visual Basic versions +- **C# path**: `./snippets/{doc-file}/[framework]/csharp/` +- **VB path**: `./snippets/{doc-file}/[framework]/vb/` + +### 5. Update article references +- **Replace**: Change from legacy `[!code-...]` format to modern `:::code...:::` format +- **Before**: `[!code-csharp[description](~/samples/snippets/path/file.cs#snippet1)]` +- **After**: `:::code language="csharp" source="./snippets/doc-name/net/csharp/file.cs" id="BasicClipboardData":::` +- **Note**: Use meaningful CamelCase identifiers instead of simple numbers + +### 6. Validate +- **Build**: Ensure all code compiles successfully +- **Test**: Verify snippet references work in the article +- **Clean**: Remove unused legacy files (if no other articles reference them) + +### 7. Delete +- **Identify**: + - Check if the old snippet file is used by any other articles + - Some articles may use a relative path to the `samples` folder, so simply search for links to `samples/snippets/...` + - Be confident that all legacy snippets use a `samples/snippets` folder structure +- **Delete**: If old snippet is no longer used by any article, delete it. + +## Common mistakes to avoid + +- ❌ **Don't** assume all code needs to be modernized - check article context first +- ❌ **Don't** modernize .NET Framework-specific articles unless specifically requested +- ❌ **Don't** ignore the `ms.service: dotnet-framework` frontmatter indicator +- ❌ **Don't** forget to create both C# and VB versions +- ❌ **Don't** mix up the framework targeting (net vs framework) +- ❌ **Don't** forget to update ALL article references to the migrated code +- ❌ **Don't** leave incomplete or non-compilable code diff --git a/CopilotStore/docs-desktop/copilot-instructions.md b/CopilotStore/docs-desktop/copilot-instructions.md new file mode 100644 index 00000000..b631a565 --- /dev/null +++ b/CopilotStore/docs-desktop/copilot-instructions.md @@ -0,0 +1,129 @@ +# .NET Documentation Guidelines + +## Disclosure + +IMPORTANT: For any Markdown files generated by AI, always disclose that they were created with the assistance of AI. If missing, add the `ai-usage` frontmatter key/value pair: + +- When reviewing a PR not created by AI: + + ```markdown + ai-usage: ai-assisted + ``` + +- When Copilot generates the article through GitHub without the use of a human: + + ```markdown + ai-usage: ai-generated + ``` + +- When using an IDE with a human guiding AI: + + ```markdown + ai-usage: ai-assisted + ``` + +## New articles + +- New articles must follow a template in the /.github/projects/article-templates/ folder. +- If you don't know which template to use, ask. + +## Terminology + +- Unless otherwise specified, all .NET content refers to modern .NET (not .NET Framework). + +## API References + +Use cross-references: ``. + +To find API doc IDs: +1. Check XML files in https://github.com/dotnet/dotnet-api-docs. +2. For types: `Value` attribute of `` where `Language="DocId"` (omit first 2 characters). +3. For members: `Value` attribute of `` where `Language="DocId"` (omit first 2 characters). + +If unsure, use API browser: `https://learn.microsoft.com/api/apibrowser/dotnet/search?api-version=0.2&locale=en-us&search={API_NAME}&$skip=0&$top=5` and then use the `url` value from the results as a manual link. + +### Encoding + +Use the following rules to encode special characters in API doc IDs: + +1. Encode `#` as `%23` in API doc IDs. For example, `System.String.#ctor` becomes `System.String.%23ctor`. +2. **DO NOT** encode `*` or \` (backtick) characters as `%2A` or `%60` respectively. + +## Code Snippets + +For snippets >6 lines: +1. Create `./snippets/my-doc/language` folder in same directory as document (for a document named `my-doc.md`) where language is either vb (for visual basic) or csharp (for c#). Omit the `language` component when the document is in the `docs/visual-basic`, `docs/csharp`, or `docs/fsharp` folders. +1. Add snippet as separate code file. +1. Include simple project file targeting latest .NET. +1. All code should use the latest stable versions/features. +1. Create examples in both C# and Visual Basic unless the article referencing the snippet resides in the in the `csharp`, `fsharp`, and `visual-basic` language folders. +1. When you add code, use code comments sparingly because they don't get localized. You can use them to briefly clarify code-specific details (such as logic, parameters, or edge cases). Put any critical information and context in the markdown text of the referencing article. +1. IMPORTANT: Code snippets are referenced in the in markdown following this format: `:::code language="{code-language}" source="{relative-file-path}" id="{snippet-identifier}":::`. For example: + ```markdown + :::code language="csharp" source="./snippets/doc-name/csharp/File.cs" id="ButtonClick"::: + :::code language="vb" source="./snippets/doc-name/vb/File.vb" id="ButtonClick"::: + ``` + +## .NET Framework vs .NET differences + +When documenting differences between .NET Framework and .NET (like .NET 6 and newer), choose the appropriate system: + +### Use Tabs +Use tabbed content when the differences are code-based: + +```markdown +# [.NET](#tab/dotnet) + + + +# [.NET Framework](#tab/dotnetframework) + + + +--- +``` + +### Use Pivots +Use zone pivots when there are many conceptual differences that can't easily be explained with tabs and a note. Pivots allow for more comprehensive explanations of different approaches or methodologies. + +To use zone pivots: + +1. Add `zone_pivot_groups: desktop-version` to the article's frontmatter +2. Use zone pivot syntax in content: + +```markdown +::: zone pivot="dotnet" + +Your .NET content here + +::: zone-end + +::: zone pivot="dotnetframework" + +Your .NET Framework content here + +::: zone-end +``` + +## File Naming + +New Markdown files: lowercase with hyphens, omit filler words (the, a, etc.). + +Examples: +- ✅ Good: `getting-started-with-entity-framework.md` +- ✅ Good: `configure-logging.md` +- ✅ Good: `dependency-injection-guidelines.md` +- ❌ Bad: `Getting-Started-With-The-Entity-Framework.md` +- ❌ Bad: `configure_logging.md` +- ❌ Bad: `DependencyInjectionGuidelines.md` + +## Special Cases + +### GitHub Issue Assignment (AI Workflow) +When assigned an issue in GitHub: +1. Complete your work +2. Wait for workflows (status checks) to run +3. Check for build warnings in the OpenPublishing.Build status check +4. If warnings exist: + - Click "View Details" to open the build report + - Resolve any build warnings you introduced diff --git a/CopilotStore/docs-desktop/instructions/Markdown.WritingStyle.instructions.md b/CopilotStore/docs-desktop/instructions/Markdown.WritingStyle.instructions.md new file mode 100644 index 00000000..eb72f1e3 --- /dev/null +++ b/CopilotStore/docs-desktop/instructions/Markdown.WritingStyle.instructions.md @@ -0,0 +1,83 @@ +--- +applyTo: 'dotnet-desktop-guide/**/*.md' +description: 'Follow these comprehensive writing style guidelines when creating or editing Markdown documentation. Apply active voice, conversational tone, Oxford commas, and specific formatting rules to ensure consistency and readability across all documentation.' +--- + +# Markdown Writing Style Instructions + +When writing or editing Markdown documentation, follow these style guidelines: + +## Voice and Tone Requirements + +ALWAYS write using: +- Active voice with second person ("you") +- Conversational tone with contractions +- Present tense for instructions and descriptions +- Imperative mood for instructions (write "Call the method" NOT "You should call the method") +- "might" for possibility (NOT "may") +- "can" for permissible actions (NOT "may") + +NEVER use: +- "we" or "our" when referring to documentation authors or product teams +- Jargon or overly complex technical language +- Weak phrases like "you can" or "there is/are/were" unless they add value + +ALWAYS: +- Write like you speak using everyday words +- Create a friendly, informal tone +- Start statements with verbs when possible + +## Structure and Format Rules + +### Headings and Content +- Use sentence case headings (capitalize only first word and proper nouns) +- Never use gerunds in titles +- Never place consecutive headings without content between them +- Lead with the most important information first +- Front-load keywords for scanning + +### Lists and Punctuation +- **CRITICAL: Use Oxford comma in ALL lists (item1, item2, and item3) - NO EXCEPTIONS** +- **MANDATORY: Number ordered lists using "1." for every item (NOT 1., 2., 3.) - ALWAYS USE "1."** +- **REQUIRED: Use bullets for unordered lists - NEVER use numbers for unordered content** +- **ESSENTIAL: Write complete sentences in lists with proper punctuation** +- **MUST: End list items with periods if more than three words - THIS IS NON-NEGOTIABLE** +- Skip end punctuation on titles, headings, and UI elements (3 words or fewer) + +### Spacing and Layout +- Add blank lines around Markdown elements (but don't add extra if they exist) +- Use only one space after periods, question marks, and colons +- Use no spaces around dashes (word—word) +- Break up long sentences for clarity + +### Prohibited Terms +- Never write "etc." or "and so on" - provide complete lists or use "for example" +- Use "for example" instead of "e.g." +- Use "that is" instead of "i.e." + +## Formatting Conventions + +Apply these formatting rules: +- **Bold text** for UI elements +- `Code style` for file names, folders, custom types, and non-localizable text +- Raw URLs in angle brackets +- Relative links for files in this repository +- Remove `https://learn.microsoft.com/en-us` from Microsoft Learn links + +## Word Choice Requirements + +### Verb Selection +- Choose simple verbs without modifiers +- Avoid weak verbs: "be," "have," "make," "do" +- Use precise verbs (write "tell" NOT "inform") + +### Conciseness Rules +- Use one word instead of multiple when possible (write "to" NOT "in order to") +- Choose words with one clear meaning (write "because" NOT "since" for causation) +- Omit unnecessary adverbs unless critical to meaning +- Use one term consistently for each concept + +### Contraction Guidelines +- Use common contractions: "it's," "you're," "that's," "don't" +- Avoid ambiguous contractions: "there'd," "it'll," "they'd" +- Never form contractions from noun + verb (avoid "Microsoft's developing") \ No newline at end of file diff --git a/CopilotStore/docs-desktop/prompts/Clean.ControlTemplate.Ref.prompt.md b/CopilotStore/docs-desktop/prompts/Clean.ControlTemplate.Ref.prompt.md new file mode 100644 index 00000000..72823f2e --- /dev/null +++ b/CopilotStore/docs-desktop/prompts/Clean.ControlTemplate.Ref.prompt.md @@ -0,0 +1,97 @@ +--- +name: Clean WPF Control Reference Articles +agent: agent +description: "Clean up and reorganize WPF control reference articles for consistent structure and improved readability." +--- + +You are tasked with cleaning up and reorganizing WPF control reference articles in the `dotnet-desktop-guide/wpf/controls/` directory to ensure consistent structure and improved documentation quality. + +**ALWAYS** write content according to `.github/instructions/Markdown.WritingStyle.instructions.md` + +## Primary Tasks + +### 1. Consolidate Reference Sections +Merge all scattered reference sections into a single `## See also` section at the end of the article: +- Combine content from: "See also", "Related sections", "Related articles", "Related topics", "Related links", "Reference", and similar sections +- Remove duplicate links and organize alphabetically +- Use proper link formatting with descriptive text + +### 2. Remove Navigation Sections +Delete "In this section" or "In this article" sections entirely as they're auto-generated by the TOC. + +### 3. Merge Overview Articles +When both `controlname.md` and `controlname-overview.md` exist: +- Merge the overview content into the main control article (`controlname.md`) +- Preserve ALL unique content from both articles +- Replace brief content with comprehensive overview content +- Delete the separate overview file after merging +- Update any internal links that referenced the overview file + +### 4. Standardize Image Syntax +Convert all control images to modern markdown syntax: +```markdown +:::image type="content" source="./media/filename.png" alt-text="Descriptive alt text"::: +``` +- Ensure alt-text is descriptive and helpful for screen readers +- Use relative paths starting with `./media/` + +### 5. Organize Content Structure +Arrange article content in this specific order: +1. **Introductory area** - This includes all of the following as part of the introduction, not as separate sections: + - Brief description of the control and its purpose + - Control image (if present) - Visual representation using modern image syntax + - Related articles table (if applicable) - Table with "Title" and "Description" columns for control-specific how-to articles. Don't put them in a section, just add them under the intro +2. **Styles and templates** - XAML styling information. Cross reference `.github/projects/xaml/control-reference/` for a control article. +3. **Key concepts** - Important concepts specific to this control +4. **Examples** - Code examples and usage scenarios +5. **See also** - Consolidated reference links + +#### 5.1 Styles and Templates Section +- The `## Styles and templates` section should always appear in the article. If not merging from another location, create it and add a brief introduction sentence. +- There should be a control reference file in `.github/projects/xaml/control-reference/` that contains the information about the control +- If the control reference file says there is no parts or visual states, include a brief note about that under the section. +- If template parts or visual states exist, include them as subsections under `## Styles and templates`: + - `### Content property` and detail what content property is used and its purpose. If none, state "This control does not define a content property." + - `### Parts` for template parts (sort table and add xref links) + - `### Visual states` for visual states + - If there are subcontrols, such as a data grid row, continue to include those as subsections under `## Styles and templates` + +### 6. Clean Up Duplicate Content +- Ensure only ONE `## Styles and templates` section exists per article +- Consolidate all styling-related content into this single section +- Remove redundant explanations or repeated information + +### 7. Create a Redirect Entry +- For any merged overview articles, add a redirect entry in `.openpublishing.redirection.wpf.json` to point from the old overview file to the main control file. +- Find any links to deleted files and change them. + +### 8. Edit metadata + +- Remove `f1_keywords` and `ms.assetid` metadata from the front matter +- Keep `helpviewer_keywords` if it exists +- Ensure `ai-usage: ai-assisted` is present in the front matter +- Update `ms.date` to the current date in `MM/DD/YYYY` format. + +## Quality Standards + +- **Preserve content**: Never delete unique information during reorganization +- **Consistent headings**: Use sentence case for all headings +- **Complete sentences**: Ensure all list items are complete sentences with proper punctuation +- **Logical flow**: Information should progress from basic to advanced concepts +- **Cross-references**: Update any broken internal links after merging articles + +## Success Criteria + +After completion, each control article should: +- Follow the exact content structure outlined above +- Have consolidated reference sections +- Include modern image syntax +- Be free of duplicate or redundant sections +- Maintain all original unique content in a more organized format + +## Quality Requirements + +- Ensure introductory content appears before technical sections +- Preserve all unique content during article merges +- Maintain consistent section ordering across all control articles + diff --git a/CopilotStore/docs-desktop/prompts/Editing.FullPass.prompt.md b/CopilotStore/docs-desktop/prompts/Editing.FullPass.prompt.md new file mode 100644 index 00000000..c6875df7 --- /dev/null +++ b/CopilotStore/docs-desktop/prompts/Editing.FullPass.prompt.md @@ -0,0 +1,26 @@ +--- +model: Claude Sonnet 4.6 (copilot) +agent: DocsEditor +description: "Performs comprehensive editing pass following Microsoft Style Guide" +--- + +# Article Editing Instructions + +Examine and edit the entire article, including front matter, for clarity, conciseness, grammar, spelling, and adherence to Microsoft Style Guide standards. + +## EDITING - FINAL VALIDATION - MANDATORY CHECKS + +After editing, you MUST verify: +- [ ] ALL passive voice converted to active voice +- [ ] ALL "you can/should" converted to imperative mood +- [ ] ALL future tense converted to present tense for descriptions +- [ ] ALL contractions added where appropriate +- [ ] ALL verbose phrases simplified +- [ ] ALL weak constructions eliminated +- [ ] ALL ambiguous "this" pronoun uses replaced with explicit nouns +- [ ] Content maintains technical accuracy +- [ ] Tone is conversational and helpful +- [ ] Sentences are concise and scannable +- [ ] Formatting follows conventions +- [ ] No consecutive headings without content +- [ ] Code blocks are unchanged (except comments if needed) diff --git a/CopilotStore/docs-desktop/prompts/Merge.Article.prompt.md b/CopilotStore/docs-desktop/prompts/Merge.Article.prompt.md new file mode 100644 index 00000000..21d5818e --- /dev/null +++ b/CopilotStore/docs-desktop/prompts/Merge.Article.prompt.md @@ -0,0 +1,16 @@ +--- +name: Merge an article +agent: agent +description: "Copy the content from one article into another." +--- + +Migrate the content in one article to another. + +Pay attention to the following pieces of information when merging the articles: + +- Copy all sections and their content from the source article to the destination article. +- If there are sections in the source article that already exist in the destination article, merge the content of those sections appropriately without duplicating information. +- Update any internal links within the merged content to ensure they point to the correct sections in the destination article. +- Ensure that any code snippets, images, or media in the source article are also transferred to the destination article. + +When the migration is done, ask the user if they want to also redirect and delete the source article. If they do, invoke the `redirect-article` skill. diff --git a/CopilotStore/docs-desktop/prompts/Move.ControlTemplate.Ref.prompt.md b/CopilotStore/docs-desktop/prompts/Move.ControlTemplate.Ref.prompt.md new file mode 100644 index 00000000..736c2029 --- /dev/null +++ b/CopilotStore/docs-desktop/prompts/Move.ControlTemplate.Ref.prompt.md @@ -0,0 +1,29 @@ +--- +name: Move Control Template Reference +agent: agent +description: "Move control template information from type-styles-and-templates.md files into the main control markdown file." +--- + +Most control articles don't have any templating information, or they do, but it's in a different file named in the following pattern `type-styles-and-templates.md`. I want to move the content of that file into the main control file, so all information about the control is in one place. + +Using the button control as an example, the main control file is `dotnet-desktop-guide/wpf/controls/button.md` and the styles and templates file is `dotnet-desktop-guide/wpf/controls/button-styles-and-templates.md`. + +The content and headings from the styles and templates file should be moved into the main control file under a new heading named `Styles and templates`. The content should be appended to the end of the main control file, after any existing content, but before any reference or link section. + +After that, add an entry to the `.openpublishing.redirection.wpf.json` file to redirect from the old styles and templates file to the main control file. + +The structure of the edits should look like the following: + +``` +## Styles and templates + +Introduction about styles and templates for the control, include an xref link of the control. Finish with this clause: For more information, see [What are styles and templates?](styles-templates-overview.md) and [How to create a template for a control](how-to-create-apply-template.md). + +### Parts + +List and describe the named parts of the control template, if any exist. + +### Visual states + +List and describe the visual states of the control, if any exist. +``` \ No newline at end of file diff --git a/CopilotStore/docs-desktop/prompts/NewArticle.ExpandComments.prompt.md b/CopilotStore/docs-desktop/prompts/NewArticle.ExpandComments.prompt.md new file mode 100644 index 00000000..9ae8f029 --- /dev/null +++ b/CopilotStore/docs-desktop/prompts/NewArticle.ExpandComments.prompt.md @@ -0,0 +1,40 @@ +--- +model: Claude Sonnet 4.6 (copilot) +agent: DocsEditor +description: "Expand selected areas with more details" +--- + +Expand selected high-level bullet points into detailed, narrative documentation content. + +## Step 1 — Validate selection + +If the user hasn't selected any content, stop and ask them to select the bullet points or notes they want expanded. Do not proceed without a selection. + +## Step 2 — Read the article's reference material + +Before writing anything, find and read the XML comment near the top of the article (after the frontmatter and H1). It is typically named `REFERENCE MATERIAL AND RULES` and contains: + +- Target audience +- Key points to cover +- Links to reference material + +Fetch every linked reference and read it thoroughly. The expanded content must be grounded in that material. + +## Step 3 — Identify context + +Note the parent heading of the selected content. The heading defines the topic scope — use it to stay focused and avoid introducing unrelated information. + +## Step 4 — Write the expanded content + +Replace the selected content using this structure: + +1. Move the original source bullet points into an XML comment directly above the expanded content (skip this if they're already in an XML comment). +2. Write the expanded content immediately after the comment. + +**Writing rules:** + +- Write in a narrative style — connected prose, not a list of facts. +- Be detailed but not verbose. Cover every source point without padding. +- Maintain logical flow. Each idea should lead naturally to the next. +- Link to source material or related articles when relevant. +- Balance breadth (covering all scenarios) with depth (actionable guidance). diff --git a/CopilotStore/docs-desktop/prompts/NewArticle.Outline.prompt.md b/CopilotStore/docs-desktop/prompts/NewArticle.Outline.prompt.md new file mode 100644 index 00000000..aea5a50a --- /dev/null +++ b/CopilotStore/docs-desktop/prompts/NewArticle.Outline.prompt.md @@ -0,0 +1,86 @@ +--- +model: Claude Sonnet 4.6 (copilot) +agent: agent +description: "Create a new article outline based on a specific template and user-provided facts" +tools: [vscode/askQuestions, read, edit, search, web, 'github/*', 'microsoft.docs.mcp/*'] +--- + +Your goal is to gather information from the user and produce a structured article outline. Do **not** write article content — only produce an outline. + +## Phase 1: Gather information + +Use the `vscode/askQuestions` tool to collect the following information in a single interaction where possible: + +1. **File path** — Ask whether this is a new file or an existing file. + - If new: ask which folder it should be placed in. + - If existing: get the path to the file. +2. **Template** — Ask the user to choose a template. Templates are located in `.github/projects/article-templates/`. Present a short list of the most common templates as options. Always include two additional options at the end of the list: "None of the above" and "Show me all templates". If the user selects "Show me all templates", list every file in that folder and let the user pick one. +3. **Topic** — Ask what the article is going to be about. +4. **Audience** — Ask who the target audience is (for example: beginner developers, administrators, architects). +5. **Additional notes** — Ask if there is anything else you should know when writing the outline. + +After those questions are answered, ask in a **regular chat message** (not using `vscode/askQuestions`): "Please share links to any relevant documentation or resources that should inform this article." Wait for the user's response before proceeding. + +## Phase 2: Build the outline + +Once all information is gathered, perform these steps in order: + +1. **Set up the file** — Copy the selected template to the destination path. If the destination file already exists, replace its content with the template content. +2. **Fill in frontmatter** — Populate the template's metadata (title, description, author, date, etc.) using the information collected. +3. **Read reference material** — For each link or resource the user provided, fetch and read the content to understand the context and key points. +4. **Store the reference material and custom instructions** — Put the reference material in an XML comment above the first heading of the article for future reference. Use the name `REFERENCE MATERIAL AND RULES`. Include any custom instructions or notes from the user in that comment. + - Example format: + ```markdown + + ``` +5. **Read the template structure** — Review the template's headings and sections. Use them to guide the outline structure. +6. **Write the outline** — Produce a detailed outline using the template's headings and subheadings. Follow these rules: + - **Do not write article prose or sentences intended for readers.** + - Under each heading, insert an XML comment containing markdown bullet points. Each bullet point is a concise statement describing what that section will cover. Include any referenced source material. + - Example format: + ```markdown + ## Section heading + + + ``` diff --git a/CopilotStore/docs-desktop/prompts/RefreshLinks.prompt.md b/CopilotStore/docs-desktop/prompts/RefreshLinks.prompt.md new file mode 100644 index 00000000..fda8400c --- /dev/null +++ b/CopilotStore/docs-desktop/prompts/RefreshLinks.prompt.md @@ -0,0 +1,107 @@ +--- +name: RefreshLinks +agent: agent +description: "Updates link text to match target content headings" +model: GPT-4.1 (copilot) +--- + +# Refresh Links Prompt + +You are tasked with checking and updating all links in the current file to ensure their link text accurately reflects the target content's H1 heading or title. + +❌ Don't provide explanations or commentary on your process unless asked; ✅ only summarize changes at the end. + +## ⚠️ CRITICAL CONSTRAINT ⚠️ + +**NO OTHER EDITS OR ALTERATIONS** should be made to the file beyond updating link text. This means: +- Do NOT modify any other content in the file +- Do NOT change formatting, structure, or layout +- Do NOT add, remove, or alter any text outside of link text updates +- Do NOT modify code blocks, headings, or any other markdown elements +- Do NOT use the **title** specified in front matter as the H1 heading for local markdown articles - only use explicitly defined H1 headings in the markdown content (`# Heading Text`) +- ONLY update the display text portion of markdown links `[THIS PART](url)` + +The file content must remain completely unchanged except for link text updates. + +## Link Types and Processing Rules + +### 1. Relative Links (e.g., `./folder/file.md`, `../folder/file.md`) +- **Target**: Files within this repository, relative to the current file's location +- **Action**: Read the target file and extract the H1 heading (should be within the first 30 lines) +- **Update**: Replace the link text with the extracted H1 heading + +### 2. Root-Relative Links (e.g., `/dotnet-desktop-guide/wpf/overview`) +- **Target**: Published pages on https://learn.microsoft.com/ +- **Action**: Fetch the page from `https://learn.microsoft.com{link-path}` and extract the H1 heading +- **Update**: Replace the link text with the extracted H1 heading + +### 3. Repository Root Links (e.g., `~/dotnet-desktop-guide/winforms/overview.md`) +- **Target**: Files within this repository, relative to the repository root +- **Action**: Convert `~/` to the repository root path, read the target file, and extract the H1 heading +- **Update**: Replace the link text with the extracted H1 heading + +### 4. Full URLs (e.g., `https://example.com/page`) +- **Target**: External web pages +- **Action**: Fetch the page and extract the H1 heading or page title +- **Update**: Replace the link text with the extracted heading/title + +### 5. XREF links (e.g., `[link text](xref:api-doc-id)`) +- **Target**: API documentation links +- **Action**: Do not change the link text, ignore this type of item. + +## Processing Instructions + +1. **Scan the file**: Identify all markdown links in the format `[link text](url)` + +2. **For each link**: + - Determine the link type based on the URL pattern + - Follow the appropriate processing rule above + - Extract the H1 heading or title from the target + - Compare with current link text + - Update if different + +3. **Check for bookmark**: + - If the link contains a bookmark (e.g., `file.md#section`), use the markdown heading instead of H1 as the link text + +4. **H1 Extraction Rules**: + - Look for markdown H1 headers (`# Heading Text`) + - For repository files, check within the first 30 lines + - For web pages, extract the `

` tag content or `` tag as fallback + - Clean up the extracted text (remove extra whitespace, HTML entities) + +5. **Preserve Link Functionality**: + - Keep the original URL intact + - Only update the display text portion + - Maintain any additional link attributes if present + +6. **Error Handling**: + - If a target cannot be reached or read, leave the link unchanged + - If no H1 is found, try alternative heading levels (H2, H3) or page title + - Log any issues encountered during processing + +## Example Transformations + +```markdown +Before: [Old Link Text](../core/install/windows.md) +After: [Install .NET on Windows](../core/install/windows.md) + +Before: [Old Link Text](../core/install/linux.md#system-requirements) +After: [System requirements](../core/install/linux.md#system-requirements) + +Before: [Click here](/dotnet/fundamentals/networking/overview) +After: [Networking in .NET](/dotnet/fundamentals/networking/overview) + +Before: [Link](~/docs/csharp/fundamentals/types/index.md) +After: [C# Type System](~/docs/csharp/fundamentals/types/index.md) + +Before: [External](https://example.com/some-page) +After: [Example Page](https://example.com/some-page) +``` + +## Output + +Provide a summary of: +- Total links processed +- Number of links updated +- Any errors or warnings encountered +- List of updated links with before/after text diff --git a/CopilotStore/docs-desktop/prompts/Snippets.Migrate.prompt.md b/CopilotStore/docs-desktop/prompts/Snippets.Migrate.prompt.md new file mode 100644 index 00000000..b4ec957d --- /dev/null +++ b/CopilotStore/docs-desktop/prompts/Snippets.Migrate.prompt.md @@ -0,0 +1,126 @@ +--- +agent: agent +model: Claude Sonnet 4.6 (copilot) +description: Migrate code from the old ~/samples/snippets/ location to the relative ./snippets location. +--- + +# Migrate code snippets + +We no longer use the `~/samples/snippets/` location for code snippets. All code snippets must be migrated to the new `./snippets/` location, which is relative to the article using the snippet. Generally, snippets in the old location are outdated, incomplete, and often can't compile. The new location requires that all snippets be complete, compilable, and include project files. Additionally, the new location requires both C# and Visual Basic versions of each snippet. + +**IMPORTANT**: Unless otherwise asked to, **only** edit the article file in context. At the end of your operations you may ask for permission to edit other articles referencing the same snippets. + +## Repository structure for code snippets + +**IMPORTANT**: This repository has TWO different locations for code snippets: + +### Old location (legacy - to be migrated FROM) +- Path: `~/samples/snippets/` +- Example: `~/samples/snippets/csharp/VS_Snippets_Winforms/System.Windows.Forms.Clipboard/CS/form1.cs` + +**Problems with legacy code:** +- Written for .NET Framework (outdated) +- Often incomplete and can't compile +- May lack project files +- Uses outdated syntax and patterns + +**Legacy article references generally use old syntax:** +```markdown +[!code-{code-language}[description](~/samples/snippets/{path-to-file}#{snippet-identifier})] +``` +### New location (current standard - migrate TO) +- Path pattern: `./snippets/{article-filename-using-snippet}/[net-or-framework]/[optional-sub-subject]/{code-language}/` +- Example C# (standard): `./snippets/anchors-in-regular-expressions/csharp/Form1.cs` +- Example VB (standard): `./snippets/anchors-in-regular-expressions/vb/Form1.vb` +- Example C# (.NET, dual-framework article): `./snippets/clipboard-operations/net/csharp/Form1.cs` +- Example C# (.NET Framework, dual-framework article): `./snippets/clipboard-operations/framework/csharp/Form1.cs` +- Example C# (clash avoidance): `./snippets/program-structure/AsyncProgram/csharp/Program.cs` +- Example (language guide, no code-language subfolder): `./snippets/pattern-matching/Program.cs` + +**Path components explained:** +- `./`: Current folder of the article being edited +- `snippets/`: Root folder for all snippets +- `{article-filename-using-snippet}`: The markdown article filename WITHOUT the `.md` extension + - Example: For article `anchors-in-regular-expressions.md` → use `anchors-in-regular-expressions` +- `[net-or-framework]`: An optional subfolder used only when the article demonstrates BOTH .NET and .NET Framework approaches: + - `net/`: For .NET (.NET 6 and newer) snippets + - `framework/`: For .NET Framework snippets + - Omit this subfolder entirely when the article targets only one framework +- `[optional-sub-subject]`: An optional subfolder to avoid clashes when snippets can't be merged with existing ones. For example, if two snippets both need a `Program.cs` file, use descriptive subfolders like `AsyncProgram/` and `SyncProgram/`. +- `{code-language}`: + - `csharp`: For C# code + - `vb`: For Visual Basic code + +**IMPORTANT**: Exception to the rules about having multiple code languages: For language guide articles, only the guide's language is required — do not create a version in the other language. The C# Language guide only contains CS code snippets, and the VB Language guide only contains VB code snippets. All other articles should follow the full path pattern including the `{code-language}/` subfolder. For example, you wouldn't use the `./snippets/article-name/csharp/` or `./snippets/article-name/vb/` folder structures for an article in the C# language guide, the folder would simply be `./snippets/article-name/` and the code in C#. The same applies to the VB language guide. + +**Requirements for current code standards:** +- ✅ MUST be complete and compilable +- ✅ MUST include a project file +- ✅ MUST target the latest .NET or .NET Framework version as appropriate based on article context +- ✅ MUST provide BOTH C# and Visual Basic versions +- ✅ MUST use appropriate syntax for the target framework +- ✅ MUST use meaningful, descriptive snippet identifiers in CamelCase format + - **Examples** of good snippet identifiers: `BasicClipboardData`, `CustomDataFormat`, `ClipboardImageHandling` + - **Avoid** simplistic identifiers like `1`, `2`, `code1`, or `snippet1` + +**Current article references look like this:** +```markdown +:::code language="{code-language}" source="{relative-file-path}" id="{snippet-identifier}"::: +``` + +## Migration steps (follow in order) + +**STEP-BY-STEP PROCESS:** + +### 1. Analyze existing code and article context +- **Find**: Locate the legacy snippet file references to `~/samples/snippets/` (path may be relative, navigating back to the root `samples` folder) +- **Check frontmatter**: Look for `ms.service` in the article's frontmatter to determine the article's scope: + - `ms.service: dotnet-framework` → .NET Framework-specific article; migrate with minimal changes, keep .NET Framework targeting + - `ms.service: dotnet-desktop` or similar → general or dual-framework article; target latest .NET, or create both `net/` and `framework/` versions if the article demonstrates both +- **Identify**: Determine the programming language (C# or Visual Basic) +- **Extract**: Note the snippet identifier used in the article reference + +### 2. Create new or reuse existing folder structure +- **Pattern**: `./snippets/{article-filename-using-snippet}/[optional-sub-subject]/{code-language}/` +- **Example**: For article `clipboard-operations.md` → create `./snippets/clipboard-operations/csharp/` +- **Reuse**: If the article already has snippets in the new location, reuse the existing folder structure and try to merge the code into the existing snippets if possible. Use new classes and code files as needed. Code **ONLY** needs to compile, it doesn't have to run from the program main. +- **Create**: If no existing folder structure exists for the article, create a new one following the pattern above. +- **New projects**: **NEVER** create project files manually. Always use the `dotnet` CLI to ensure correct formatting and structure of new code. Projects should be console apps unless otherwise required (such as a Windows Forms-related snippet) + - Specify a meaningful project name with the `-n` parameter. + - Example 1: An article about clipboard handling, use `dotnet new console -n ClipboardExample` + - Example 2: An article about events would be `dotnet new console -n EventsOverview` + +### 3. Migrate and update code +- **Copy**: Copy only the snippet code (and any supporting code to compile the snippet) to the new location +- **Complete**: Ensure code is fully functional and compilable + +### 4. Create both language versions +- **Requirement**: MUST provide both C# and Visual Basic versions, except for language guide articles (C# or VB guide), where only the guide's language is required. +- **Standard articles** (both languages required): + - **C# path**: `./snippets/{article-filename-using-snippet}/csharp/` + - **VB path**: `./snippets/{article-filename-using-snippet}/vb/` +- **Language guide articles** (single language, no `{code-language}` subfolder): + - **C# guide path**: `./snippets/{article-filename-using-snippet}/` + - **VB guide path**: `./snippets/{article-filename-using-snippet}/` + +### 5. Update article references +- **Replace**: Change from legacy `[!code-...]` format to modern `:::code...:::` format +- **Before**: `[!code-csharp[description](~/samples/snippets/path/file.cs#snippet1)]` +- **After**: `:::code language="csharp" source="./snippets/article-name/csharp/file.cs" id="BasicClipboardData":::` +- **Note**: Use meaningful CamelCase identifiers instead of simple numbers + +### 6. Validate +- **Build**: Ensure all code compiles successfully + +### 7. Delete +- **Identify**: + - Check if the old snippet file is used by any other articles. Search for the old snippet path across the repository to find any references. This can be done by searching for links to `samples/snippets/...` (the file path used in the snippet reference) since some articles may use a relative path to the `samples` folder instead of absolute paths. +- **Delete**: If old snippet was migrated and is no longer used by any other article, delete it. + +## Common mistakes to avoid + +- ❌ **Don't** assume all code needs to be modernized - check article context first; .NET Framework-specific articles (`ms.service: dotnet-framework`) should be migrated with minimal changes, not modernized +- ❌ **Don't** forget to create both C# and VB versions +- ❌ **Don't** mix up the framework targeting (`net/` vs `framework/` subfolders) for dual-framework articles +- ❌ **Don't** forget to update ALL article references to the migrated code +- ❌ **Don't** leave incomplete or non-compilable code diff --git a/CopilotStore/docs-desktop/prompts/Snippets.Push.prompt.md b/CopilotStore/docs-desktop/prompts/Snippets.Push.prompt.md new file mode 100644 index 00000000..14965dad --- /dev/null +++ b/CopilotStore/docs-desktop/prompts/Snippets.Push.prompt.md @@ -0,0 +1,122 @@ +--- +agent: agent +model: Claude Sonnet 4.6 (copilot) +description: Push inline code block snippets out of articles into standalone files with proper project structure. +--- + +# Push inline code snippets to files + +**IMPORTANT**: Unless otherwise asked to, **only** extract snippets from the article file in context. At the end of your operations you may ask for permission to edit other articles that might benefit from the same snippet extraction. + +**IMPORTANT**: Don't share code across multiple articles. Each article should have its own copy of the snippet in its own folder structure. + +**IMPORTANT**: If only XAML snippets are present, only create C# projects to hold the XAML. Do not create VB projects for XAML-only snippets. + +## When to push snippets out of articles + +**PUSH SNIPPETS WHEN:** +- Code blocks are longer than 6 lines +- Code demonstrates complete, compilable examples +- Code represents a complete application or significant functionality +- User specifically requests snippet extraction + +**KEEP INLINE WHEN:** +- Code blocks are 6 lines or shorter +- Code is pseudo-code or conceptual examples + +## Target folder structure +- Path pattern: `./snippets/{article-name}/[net-or-framework]/[optional-sub-subject]/{code-language}/` +- Example C# (standard): `./snippets/create-app/csharp/` +- Example VB (standard): `./snippets/create-app/vb/` +- Example C# (.NET, dual-framework article): `./snippets/create-app/net/csharp/` +- Example C# (.NET Framework, dual-framework article): `./snippets/create-app/framework/csharp/` +- Example C# (clash avoidance): `./snippets/create-app/AsyncProgram/csharp/` + +**Path components explained:** +- `./`: Current folder of the article being edited +- `snippets/`: Root folder for all snippets +- `{article-name}`: The markdown article filename WITHOUT the `.md` extension + - Example: For article `create-app.md` → use `create-app` +- `[net-or-framework]`: An optional subfolder used only when the article demonstrates BOTH .NET and .NET Framework approaches: + - `net/`: For .NET (.NET 6 and newer) snippets + - `framework/`: For .NET Framework snippets + - Omit this subfolder entirely when the article targets only one framework +- `[optional-sub-subject]`: An optional subfolder to avoid clashes. Used when snippets in the same article can't be merged — for example, two snippets that both require a `Program.cs` file but demonstrate different things. Use descriptive subfolder names like `AsyncProgram/` and `SyncProgram/`. +- `{code-language}`: + - `csharp`: For C# code (also use for XAML snippets) + - `vb`: For Visual Basic code + +**Language guide exception**: For articles in the C# or VB language guides, only the guide's language is required — do not create a version in the other language, and omit the `{code-language}/` subfolder: +- C# guide path: `./snippets/{article-name}/` +- VB guide path: `./snippets/{article-name}/` + +## Push process + +### 1. Analyze and prepare +- Locate code blocks >6 lines or complete examples (unless overridden by user request) +- Identify the programming language(s) used +- Determine if the article is in a language guide (C# or VB) to apply the language exception + +### 2. Decide how code will be placed +- If the article talks about single-file apps, **STOP** and ask the user if they want to use a single-file app or a traditional project-based app +- If the article doesn't talk about single-file apps, assume the code samples must be put into a project-based app + +### 2.1 Project-based apps +- This is the default for moving code snippets from an article +- **NEVER** create project files manually. +- **ALWAYS** use the `dotnet` CLI. Default to console apps (`dotnet new console`) unless the snippet requires a different project type (for example, `dotnet new winforms` for a Windows Forms snippet). Don't specify an output folder with `-o`. Specify a meaningful project name with `-n` if possible. + +### 2.2 Single-file apps +- This is not the default. You must have a good reason to use this mode, such as the user requested it or the article itself references single-file apps along with the snippets +- Only C# is supported +- VB snippets must use a project-based app approach +- Multiple single-file apps can share the same folder for the article +- Instead of `Program.cs`, they can be named anything +- They are compiled with `dotnet run file.cs` +- Folder must not have a project file + +### 3. Extract code +- Copy and complete code to make it compilable. Code only needs to compile — it doesn't have to run from `Main`. +- Add missing using statements, namespaces, and class declarations as needed. +- Build to verify compilation with `dotnet build`. + +### 4. Add snippet markers and update article references +- Add CamelCase region markers around each snippet. Snippet markers are added as comments in the language of the code file: + - C#: `// <SnippetId>` and `// </SnippetId>` + - VB: `' <SnippetId>` and `' </SnippetId>` +- The angle brackets (`<` and `>`) are part of the comment markers only. The snippet identifier itself is the bare CamelCase name (for example, `SnippetId`), which is what you use in the `id` attribute. +- Use the same identifiers across C# and VB versions. +- Use meaningful, descriptive identifiers — avoid `1`, `2`, `code1`, or `snippet1`. +- Replace each inline code block with a `:::code:::` reference: + ```markdown + :::code language="csharp" source="./snippets/doc-name/csharp/File.cs" id="ButtonClick"::: + :::code language="vb" source="./snippets/doc-name/vb/File.vb" id="ButtonClick"::: + ``` +- DO NOT use language tabs in the article — place references side-by-side, like so: + ```markdown + :::code language="csharp" source="./snippets/doc-name/csharp/File.cs" id="ButtonClick"::: + + :::code language="vb" source="./snippets/doc-name/vb/File.vb" id="ButtonClick"::: + ``` +- Verify all paths and identifiers are correct. + +### 5. Update article frontmatter +If both C# and VB examples are provided, ensure the following frontmatter is present at the top of the article: + +```yml +dev_langs: + - "csharp" + - "vb" +``` + +If a single language is used (like in the language guides), omit the `dev_langs` section. + +## Common mistakes to avoid + +- ❌ Extracting short snippets (≤6 lines) without being asked +- ❌ Creating project files manually instead of using `dotnet new` (when using project-based apps) +- ❌ Missing C# or VB versions for standard articles +- ❌ Creating VB projects for XAML-only snippets +- ❌ Using language tabs instead of side-by-side references +- ❌ Missing or inconsistent snippet region identifiers +- ❌ Code that doesn't compile diff --git a/CopilotStore/docs-desktop/prompts/Snippets.Upgrade.prompt.md b/CopilotStore/docs-desktop/prompts/Snippets.Upgrade.prompt.md new file mode 100644 index 00000000..1edc6718 --- /dev/null +++ b/CopilotStore/docs-desktop/prompts/Snippets.Upgrade.prompt.md @@ -0,0 +1,113 @@ +--- +agent: agent +model: Claude Sonnet 4.6 (copilot) +description: Upgrade snippets to the latest .NET and possibly migrate from .NET Framework +--- + +# Code Snippet Upgrade Instructions + +## When to Apply These Instructions + +Apply these instructions when working with code snippets that need modernization, especially when: +- Improving snippet quality and completeness +- Upgrading .NET Framework code to modern .NET +- Adding missing language versions (C# or VB) + +## Snippet Structure Requirements + +All snippets must follow this folder structure relative to the referencing article: + +``` +./snippets/{article-name}/[net-or-framework]/[optional-sub-subject]/{code-language}/ +``` + +**Path components explained:** +- `./`: Current folder of the article being edited +- `snippets/`: Root folder for all snippets +- `{article-name}`: The markdown article filename WITHOUT the `.md` extension +- `[net-or-framework]`: An optional subfolder used only when the article demonstrates BOTH .NET and .NET Framework approaches: + - `net/`: For .NET (.NET 6 and newer) snippets + - `framework/`: For .NET Framework snippets + - Omit this subfolder entirely when the article targets only one framework +- `[optional-sub-subject]`: An optional subfolder to avoid clashes — use when two snippets in the same article can't be merged (for example, both require a `Program.cs` file). Use descriptive names like `AsyncProgram/` and `SyncProgram/`. +- `{code-language}`: `csharp` for C#, `vb` for Visual Basic + +**Examples:** +- `./snippets/how-to-add-data-to-the-clipboard/csharp/MainForm.cs` +- `./snippets/how-to-add-data-to-the-clipboard/vb/MainForm.vb` +- `./snippets/clipboard-operations/net/csharp/Form1.cs` (dual-framework, .NET) +- `./snippets/clipboard-operations/framework/csharp/Form1.cs` (dual-framework, .NET Framework) +- `./snippets/program-structure/AsyncProgram/csharp/Program.cs` (clash avoidance) + +**Language guide exception**: For articles in the C# or VB language guides, only the guide's language is required — do not create a version in the other language, and omit the `{code-language}/` subfolder. The path is simply `./snippets/{article-name}/`. + +## Required Upgrade Actions + +### 1. File Naming and Organization +- Use PascalCase for class names and file names (e.g., `MainForm.cs`, `DataProcessor.cs`) +- Organize files logically within the language folder + +### 2. Snippet Identifiers and Naming +- Use meaningful, descriptive snippet identifiers in CamelCase format +- Replace simplistic identifiers (like single numbers) with descriptive names +- Good examples: `BasicClipboardData`, `CustomDataFormat`, `ClipboardImageHandling` +- Avoid: `1`, `2`, `code1`, `snippet1` +- Identifiers should clearly describe the code's purpose or functionality + +### 3. Syntax Modernization +- Target the latest stable .NET version +- Use modern C# features: + - File-scoped namespaces + - Top-level statements where appropriate + - Pattern matching + - String interpolation + - `var` where type is obvious + - Modern `using` statements + +### 4. Project File Requirements +- **NEVER** create project files manually. Always use the `dotnet` CLI. Default to console apps (`dotnet new console`) unless the snippet requires a different project type. Don't specify an output folder with `-o`. +- Specify a meaningful project name with the `-n` parameter. + - Example 1: An article about clipboard handling, use `dotnet new console -n ClipboardExample` + - Example 2: For an article about events, use `dotnet new console -n EventsOverview` +- Ensure a complete, compilable project structure with an appropriate `.csproj` or `.vbproj` file +- Code only needs to compile — it doesn't have to run from `Main` +- Verify compilation with `dotnet build` + +### 5. Code Quality Standards +- Ensure code compiles without errors +- Follow .NET naming conventions +- Use appropriate access modifiers +- Include necessary `using`/`import` statements + +### 6. Language Parity +- Create both C# and VB.NET versions for standard articles +- For language guide articles (C# or VB guide), only the guide's language is required +- Maintain functional equivalence between language versions +- Adapt language-specific idioms appropriately + +## Example Transformation + +**Before (outdated structure):** +``` +~/samples/snippets/csharp/clipboard/code.cs +``` + +**After (current structure):** +``` +./snippets/how-to-add-data-to-the-clipboard/csharp/ +├── ClipboardExample.csproj +├── MainForm.cs +└── Program.cs + +./snippets/how-to-add-data-to-the-clipboard/vb/ +├── ClipboardExample.vbproj +├── MainForm.vb +└── Program.vb +``` + +## Common mistakes to avoid + +- ❌ Creating project files manually instead of using `dotnet new` +- ❌ Missing C# or VB versions for standard articles +- ❌ Using simplistic or non-descriptive snippet identifiers +- ❌ Code that doesn't compile \ No newline at end of file diff --git a/CopilotStore/docs-desktop/prompts/Target.Desktop.prompt.md b/CopilotStore/docs-desktop/prompts/Target.Desktop.prompt.md new file mode 100644 index 00000000..b7226d44 --- /dev/null +++ b/CopilotStore/docs-desktop/prompts/Target.Desktop.prompt.md @@ -0,0 +1,13 @@ +--- +model: Claude Haiku 4.5 (copilot) +agent: agent +description: "Migrate metadata service from dotnet-framework to dotnet-desktop for article." +--- + +There are two lifecycles for articles: dotnet-framework and dotnet-desktop: + +Articles that are dotnet-desktop should have the `ms.service` metadata set to `dotnet-desktop` and the `ms.update-cycle` set to `365-days`. + +Articles that are dotnet-framework should have the `ms.service` metadata set to `dotnet-framework` and the `ms.update-cycle` set to `1825-days`. + +Change this article to `dotnet-desktop` and update the metadata accordingly. diff --git a/CopilotStore/docs-desktop/prompts/Target.Framework.prompt.md b/CopilotStore/docs-desktop/prompts/Target.Framework.prompt.md new file mode 100644 index 00000000..0d742214 --- /dev/null +++ b/CopilotStore/docs-desktop/prompts/Target.Framework.prompt.md @@ -0,0 +1,13 @@ +--- +model: Claude Haiku 4.5 (copilot) +agent: agent +description: "Migrate metadata service from dotnet-desktop to dotnet-framework for article." +--- + +There are two lifecycles for articles: dotnet-framework and dotnet-desktop: + +Articles that are dotnet-desktop should have the `ms.service` metadata set to `dotnet-desktop` and the `ms.update-cycle` set to `365-days`. + +Articles that are dotnet-framework should have the `ms.service` metadata set to `dotnet-framework` and the `ms.update-cycle` set to `1825-days`. + +Change this article to `dotnet-framework` and update the metadata accordingly. diff --git a/CopilotStore/docs-desktop/prompts/ValidateTemplate.prompt.md b/CopilotStore/docs-desktop/prompts/ValidateTemplate.prompt.md new file mode 100644 index 00000000..e0f99b1b --- /dev/null +++ b/CopilotStore/docs-desktop/prompts/ValidateTemplate.prompt.md @@ -0,0 +1,97 @@ +--- +model: Claude Haiku 4.5 (copilot) +agent: agent +description: "Validates article structure against appropriate templates" +--- + +# Template Validation Prompt + +You are tasked with validating that the current Markdown documentation file conforms to the appropriate article template from `/.github/projects/article-templates/`. + +- **IMPORTANT**: Template files contain XML comments (`<!-- ... -->`) that provide crucial instructions. You must read and apply these instructions during validation. + +## Validation Workflow + +### Step 1: Identify Article Type +Analyze the current article to determine its type: +- Examine `ms.topic` frontmatter value +- Review content structure and purpose +- Consider file naming conventions +- Assess target audience and use case + +### Step 2: Select and Read Template +- Map the article type to the corresponding template file: + - `how-to` → `template-how-to-guide.md` + - `quickstart` → `template-quickstart.md` + - `tutorial` → `template-tutorial.md` + - `concept` → `template-concept.md` + - `overview` → `template-overview.md` + - `troubleshooting` → `general-troubleshoot.md` + - Other types as defined in the templates directory +- Read the complete template file from `/.github/projects/article-templates/` +- Extract all template requirements and guidelines + +### Step 3: Systematic Validation +Compare the current article against the template across all dimensions: + +#### Frontmatter Analysis +- Check all required frontmatter fields +- Validate field values and formats +- Verify template-specific frontmatter requirements + +#### Structure Validation +- Compare section presence and organization +- Verify heading hierarchy and naming +- Check for required content blocks + +#### Content Pattern Compliance +- Analyze all headers format per template specifications +- Validate introduction patterns +- Check for template-mandated content elements + +#### Consistency Verification +- Ensure title frontmatter aligns with H1 heading +- Verify internal consistency throughout the article +- Check template-specific formatting requirements + +### Step 4: Generate Corrections +For any violations found: +- Reference the specific template requirement +- Provide the exact corrected version +- Explain the rationale based on template guidance +- Preserve the article's core content and intent + +### Step 5: Next Steps and Related Content +- Validate if the article includes a **Next step** or **Related content** section at the end, as per the updated template style. +- If the article contains a **See also** section, ensure it is updated to **Related content** to align with the new guidelines. + +## Execution Instructions + +1. **Read the current article** completely +2. **Determine the article type** using the criteria above +3. **Load the appropriate template** from the templates directory +4. **Extract all template requirements** systematically +5. **Perform comprehensive comparison** across all elements +6. **Document violations** with specific template references +7. **Apply corrections** while maintaining content value + +## Output Requirements + +Provide a structured report including: +- **Article type identified** and reasoning +- **Template file used** for validation +- **Comprehensive violation list** with template citations +- **Specific corrections applied** with before/after examples +- **Summary of structural changes** made + +## Validation Scope + +This process should cover: +- All frontmatter requirements +- Complete structural conformance +- Heading and title formatting +- Required section presence +- Template-specific content patterns +- Internal consistency requirements + +Focus on template fidelity while preserving the article's informational value and purpose. \ No newline at end of file diff --git a/CopilotStore/docs-desktop/skills/redirect-article/SKILL.md b/CopilotStore/docs-desktop/skills/redirect-article/SKILL.md new file mode 100644 index 00000000..549d4c8a --- /dev/null +++ b/CopilotStore/docs-desktop/skills/redirect-article/SKILL.md @@ -0,0 +1,108 @@ +--- +name: redirect-article +description: Deletes a markdown article and creates a redirect entry pointing to a different article. Use when consolidating articles, renaming or moving content, removing outdated documentation, or reorganizing the docs structure while preserving existing URLs. +--- + +# Redirect Article + +Delete a markdown article from the repository and create a redirect entry that points users to a different article. This ensures existing links and bookmarks continue to work after content is reorganized. + +## When to Use + +- Deleting an article that should redirect to another existing article +- Consolidating multiple articles into a single article +- Renaming or moving an article to a new location +- Removing outdated content while preserving URL functionality + +## Important Notes + +- Redirect entries are sorted **alphabetically** by path (ignoring the leading `/` for `source_path_from_root`) +- Always determine the correct redirection file by searching for existing entries with similar paths before running the script +- Always search the repository for links to the old article and update them +- The `redirect_url` shouldn't include the file extension or domain—just the URL path + +## Steps + +### 1. Required: Use the provided script + +**DO NOT manually edit a redirection JSON file.** Use the `create-redirect-entry.ps1` script to handle the redirect creation automatically. + +1. **Delete the source article** - Remove the original markdown file from the repository using `Remove-Item` +2. **Create a redirect entry** - **REQUIRED:** Use the `create-redirect-entry.ps1` script (see below) to add the redirect entry to the appropriate JSON file. Do not manually edit the JSON file +3. **Update internal links** - Search the repository for links to the old article and update them to point to the new article + +### 2. Update the internal links + +1. Build a list of files that reference the deleted article + - Search for `**/*.md` files that reference the redirected file + - Search for `**/*.yml` files that reference the redirected file +2. Update the links to point to the new article + +## Redirection File Selection + +To determine the correct redirection file for an article: + +1. **Search for existing redirects** - Search the `.openpublishing.redirection.*.json` files for entries with paths similar to your source article (same folder or parent folder) +2. **Match by path prefix** - Use the redirection file that contains entries with the longest matching path prefix to your source article +3. **Use the reference table** - If no existing entries match, consult the table below based on the content area + +**Reference table:** + +| Product Area | Redirection File | +|--------------|------------------| +| AI | `.openpublishing.redirection.ai.json` | +| Architecture | `.openpublishing.redirection.architecture.json` | +| .NET Aspire | `.openpublishing.redirection.aspire.json` | +| Azure | `.openpublishing.redirection.azure.json` | +| .NET Core | `.openpublishing.redirection.core.json` | +| C# | `.openpublishing.redirection.csharp.json` | +| Desktop WPF | `.openpublishing.redirection.desktop-wpf.json` | +| .NET Framework | `.openpublishing.redirection.framework.json` | +| .NET Framework WinForms | `.openpublishing.redirection.framework-winforms.json` | +| .NET Framework WPF | `.openpublishing.redirection.framework-wpf.json` | +| F# | `.openpublishing.redirection.fsharp.json` | +| .NET Fundamentals | `.openpublishing.redirection.fundamentals.json` | +| Machine Learning | `.openpublishing.redirection.machine-learning.json` | +| Navigate | `.openpublishing.redirection.navigate.json` | +| Orleans | `.openpublishing.redirection.orleans.json` | +| .NET Standard | `.openpublishing.redirection.standard.json` | +| Visual Basic | `.openpublishing.redirection.visual-basic.json` | +| Default/General | `.openpublishing.redirection.json` | + +## Scripts + +### create-redirect-entry.ps1 + +**ALWAYS use this script to add redirect entries.** This script adds the entry in alphabetical order and handles formatting. It supports both `source_path_from_root` and `source_path` properties when reading existing entries. + +Location (relative to this skill file): `./scripts/create-redirect-entry.ps1` + +| Parameter | Required | Description | +|-----------|----------|-------------| +| `RedirectionFile` | Yes | The redirection JSON file name (e.g., `.openpublishing.redirection.csharp.json`) | +| `SourcePath` | Yes | Repository path of the deleted article (with or without leading `/`) | +| `RedirectUrl` | Yes | Destination URL to redirect to | + +**Example:** + +```powershell +.\scripts\create-redirect-entry.ps1 ` + -RedirectionFile ".openpublishing.redirection.csharp.json" ` + -SourcePath "docs/csharp/fundamentals/old-article.md" ` + -RedirectUrl "/dotnet/csharp/fundamentals/new-article" +``` + +## Redirect Entry Format + +```json +{ + "source_path_from_root": "/docs/csharp/fundamentals/old-article.md", + "redirect_url": "/dotnet/csharp/fundamentals/new-article" +} +``` + +- **source_path_from_root**: File path from the repository root, starting with `/` (preferred property) +- **source_path**: Legacy property without leading `/` (some older files use this) +- **redirect_url**: URL path to redirect to (starts with `/dotnet/`) + +> **Note:** The script handles both `source_path_from_root` and `source_path` when reading existing entries, but always writes new entries using `source_path_from_root`. diff --git a/CopilotStore/docs-desktop/skills/redirect-article/scripts/create-redirect-entry.ps1 b/CopilotStore/docs-desktop/skills/redirect-article/scripts/create-redirect-entry.ps1 new file mode 100644 index 00000000..4ff2361b --- /dev/null +++ b/CopilotStore/docs-desktop/skills/redirect-article/scripts/create-redirect-entry.ps1 @@ -0,0 +1,268 @@ +<# +.SYNOPSIS + Adds a new redirection entry to an Open Publishing redirection JSON file. + +.DESCRIPTION + This script adds a new redirection entry to the specified JSON file. The entry + is inserted alphabetically by path. The script handles both 'source_path_from_root' + (preferred) and 'source_path' properties when reading existing entries. + +.PARAMETER RedirectionFile + The name of the redirection JSON file (e.g., '.openpublishing.redirection.csharp.json'). + +.PARAMETER SourcePath + The source path of the article being redirected (relative to repo root). + Example: 'docs/csharp/fundamentals/old-article.md' + +.PARAMETER RedirectUrl + The destination URL to redirect to. + Example: '/dotnet/csharp/fundamentals/new-article' + +.EXAMPLE + .\create-redirect-entry.ps1 -RedirectionFile ".openpublishing.redirection.csharp.json" -SourcePath "docs/csharp/fundamentals/old-article.md" -RedirectUrl "/dotnet/csharp/fundamentals/new-article" +#> + +[CmdletBinding()] +param( + [Parameter(Mandatory = $true)] + [string]$RedirectionFile, + + [Parameter(Mandatory = $true)] + [string]$SourcePath, + + [Parameter(Mandatory = $true)] + [string]$RedirectUrl +) + +# Find the root of the git repository +function Get-GitRepoRoot { + $currentPath = (Get-Location).Path + while ($currentPath -ne $null) { + if (Test-Path (Join-Path $currentPath ".git")) { + return $currentPath + } + $parentPath = Split-Path $currentPath -Parent + if ($parentPath -eq $currentPath) { + break + } + $currentPath = $parentPath + } + return $null +} + +# Get the source path from a redirection entry (handles both properties) +function Get-EntrySourcePath { + param($Entry) + if ($Entry.source_path_from_root) { + return $Entry.source_path_from_root + } + return $Entry.source_path +} + +# Normalize a path for comparison (strip leading /) +function Get-NormalizedPath { + param([string]$Path) + return $Path.TrimStart('/') +} + +# Main script logic +try { + # Normalize SourcePath (remove leading / if present for consistent handling) + $normalizedSourcePath = Get-NormalizedPath -Path $SourcePath + + # Determine the redirection file path + if ([System.IO.Path]::IsPathRooted($RedirectionFile)) { + # Absolute path provided + $redirectionFilePath = $RedirectionFile + } + else { + # Relative path - find repo root and join + $repoRoot = Get-GitRepoRoot + if (-not $repoRoot) { + Write-Error "Could not find git repository root. Make sure you're running this script from within a git repository." + exit 1 + } + Write-Host "Repository root: $repoRoot" -ForegroundColor Cyan + $redirectionFilePath = Join-Path $repoRoot $RedirectionFile + } + + if (-not (Test-Path $redirectionFilePath)) { + Write-Error "Redirection file not found: $redirectionFilePath" + exit 1 + } + + Write-Host "Redirection file: $redirectionFilePath" -ForegroundColor Cyan + + # Read and parse the JSON file + $rawFileContent = Get-Content -Path $redirectionFilePath -Raw + $originalLineEnding = if ($rawFileContent -match '\r\n') { "`r`n" } else { "`n" } + $jsonContent = $rawFileContent | ConvertFrom-Json + + # Check if redirections array exists + if (-not $jsonContent.redirections) { + Write-Error "Invalid redirection file format. Expected 'redirections' array not found." + exit 1 + } + + # Check if entry already exists (check both source_path_from_root and source_path) + $sourcePathWithRoot = "/$normalizedSourcePath" + $existingEntry = $jsonContent.redirections | Where-Object { + (Get-NormalizedPath -Path (Get-EntrySourcePath -Entry $_)) -eq $normalizedSourcePath + } + if ($existingEntry) { + $existingPath = Get-EntrySourcePath -Entry $existingEntry + Write-Warning "A redirection entry for '$existingPath' already exists." + Write-Warning "Existing redirect_url: $($existingEntry.redirect_url)" + exit 1 + } + + # Convert redirections to a list for easier manipulation + $redirectionsList = [System.Collections.ArrayList]@($jsonContent.redirections) + + # Find the correct position to insert (alphabetically by normalized path) + $insertIndex = 0 + for ($i = 0; $i -lt $redirectionsList.Count; $i++) { + $existingNormalizedPath = Get-NormalizedPath -Path (Get-EntrySourcePath -Entry $redirectionsList[$i]) + if ($existingNormalizedPath -gt $normalizedSourcePath) { + $insertIndex = $i + break + } + $insertIndex = $i + 1 + } + + # --------------------------------------------------------------------------- + # NOTE: The block below (commented out) used ConvertTo-Json to rebuild the + # entire file. This caused indentation reformatting because ConvertTo-Json + # always outputs 2-space indentation regardless of the original file style. + # Kept here for reference only. + # --------------------------------------------------------------------------- + # $newEntry = [PSCustomObject]@{ + # source_path_from_root = $sourcePathWithRoot + # redirect_url = $RedirectUrl + # } + # $redirectionsList.Insert($insertIndex, $newEntry) + # $jsonContent.redirections = $redirectionsList.ToArray() + # $jsonOutput = $jsonContent | ConvertTo-Json -Depth 10 + # $jsonOutput = $jsonOutput -replace '\r\n', "`n" + # if ($originalLineEnding -eq "`r`n") { $jsonOutput = $jsonOutput -replace "`n", "`r`n" } + # [System.IO.File]::WriteAllText($redirectionFilePath, $jsonOutput, (New-Object System.Text.UTF8Encoding $false)) + # --------------------------------------------------------------------------- + + # Raw text injection - splices the new entry into the file without touching + # any other lines, preserving original indentation and formatting exactly. + + $lines = if ($originalLineEnding -eq "`r`n") { + $rawFileContent -split '\r\n' + } else { + $rawFileContent -split '\n' + } + + # Detect indentation from a sample source_path line and the entry { line above it + $sampleFieldLineIdx = -1 + for ($i = 0; $i -lt $lines.Count; $i++) { + if ($lines[$i] -match '^\s+"source_path') { + $sampleFieldLineIdx = $i + break + } + } + $fieldIndent = if ($sampleFieldLineIdx -ge 0 -and $lines[$sampleFieldLineIdx] -match '^(\s+)') { $Matches[1] } else { " " } + # Walk back from the field line to find the entry's opening { and use its indentation + $entryIndent = "" + if ($sampleFieldLineIdx -ge 1) { + for ($i = $sampleFieldLineIdx - 1; $i -ge 0; $i--) { + if ($lines[$i] -match '^(\s*)\{\s*$') { + $entryIndent = $Matches[1] + break + } + } + } + + # Core lines of the new entry (closing brace has no comma yet - added below per context) + $newEntryCore = @( + "$entryIndent{", + "$fieldIndent`"source_path_from_root`": `"$sourcePathWithRoot`",", + "$fieldIndent`"redirect_url`": `"$RedirectUrl`"", + "$entryIndent}" + ) + + $outputLines = [System.Collections.ArrayList]@() + + if ($insertIndex -lt $redirectionsList.Count) { + # Middle or beginning: insert before the entry currently at $insertIndex. + # Find that entry's source path in the raw lines to locate its opening {. + $targetPath = Get-EntrySourcePath -Entry $redirectionsList[$insertIndex] + $targetLineIdx = -1 + for ($i = 0; $i -lt $lines.Count; $i++) { + if ($lines[$i] -match [regex]::Escape($targetPath)) { + $targetLineIdx = $i + break + } + } + if ($targetLineIdx -lt 0) { + Write-Error "Could not locate insertion point in file for: $targetPath" + exit 1 + } + # Walk back to find the opening { of that entry + $entryStartIdx = $targetLineIdx + for ($i = $targetLineIdx - 1; $i -ge 0; $i--) { + if ($lines[$i].Trim() -eq '{') { + $entryStartIdx = $i + break + } + } + # Emit: lines before insertion point, new entry with trailing comma, then rest + for ($i = 0; $i -lt $entryStartIdx; $i++) { $null = $outputLines.Add($lines[$i]) } + for ($i = 0; $i -lt ($newEntryCore.Length - 1); $i++) { $null = $outputLines.Add($newEntryCore[$i]) } + $null = $outputLines.Add("$entryIndent},") # closing brace with comma (next entry follows) + for ($i = $entryStartIdx; $i -lt $lines.Count; $i++) { $null = $outputLines.Add($lines[$i]) } + } else { + # Append at end: the current last entry has no trailing comma; add one, then + # insert the new entry (no trailing comma) before the closing ]. + $closingBracketIdx = -1 + for ($i = $lines.Count - 1; $i -ge 0; $i--) { + if ($lines[$i].TrimStart() -match '^\]\s*$') { + $closingBracketIdx = $i + break + } + } + if ($closingBracketIdx -lt 0) { + Write-Error "Could not find closing ] of redirections array" + exit 1 + } + # Find the closing } of the last entry (immediately before the ]) + $lastCloserIdx = -1 + for ($i = $closingBracketIdx - 1; $i -ge 0; $i--) { + $trimmed = $lines[$i].Trim() + if ($trimmed -eq '}' -or $trimmed -eq '},') { + $lastCloserIdx = $i + break + } + } + if ($lastCloserIdx -lt 0) { + Write-Error "Could not find last entry closing brace" + exit 1 + } + # Emit: all lines up to (not including) last }, then last } with comma, + # then new entry (no trailing comma), then closing ] onward + for ($i = 0; $i -lt $lastCloserIdx; $i++) { $null = $outputLines.Add($lines[$i]) } + $null = $outputLines.Add("$entryIndent},") # previous last entry now has a comma + foreach ($l in $newEntryCore) { $null = $outputLines.Add($l) } # new entry, no trailing comma + for ($i = $closingBracketIdx; $i -lt $lines.Count; $i++) { $null = $outputLines.Add($lines[$i]) } + } + + $outputContent = $outputLines -join $originalLineEnding + [System.IO.File]::WriteAllText($redirectionFilePath, $outputContent, (New-Object System.Text.UTF8Encoding $false)) + + Write-Host "" + Write-Host "Successfully added redirection entry:" -ForegroundColor Green + Write-Host " Source: $sourcePathWithRoot" -ForegroundColor White + Write-Host " Redirect to: $RedirectUrl" -ForegroundColor White + Write-Host " Inserted at index: $insertIndex" -ForegroundColor Gray + Write-Host "" + Write-Host "File updated: $redirectionFilePath" -ForegroundColor Green + +} +catch { + Write-Error "An error occurred: $_" + exit 1 +} diff --git a/CopilotStore/docs-desktop/skills/sort-redirects/SKILL.md b/CopilotStore/docs-desktop/skills/sort-redirects/SKILL.md new file mode 100644 index 00000000..0729d012 --- /dev/null +++ b/CopilotStore/docs-desktop/skills/sort-redirects/SKILL.md @@ -0,0 +1,42 @@ +--- +name: sort-redirects +description: Sorts redirect entries in Open Publishing redirection JSON files alphabetically by path. Use after adding redirects or when the file becomes unsorted. +--- + +# Sort Redirects + +Sort redirect entries in Open Publishing redirection JSON files alphabetically by path. This ensures consistency and makes the redirect files easier to maintain. + +## When to Use + +- After adding redirect entries to a JSON file +- When the redirect file has become unsorted +- After merging branches that may have caused unsorted entries + +## Steps + +1. **Identify the redirection file** - Determine which `.openpublishing.redirection.*.json` file needs sorting. +2. **Run the sort script** - Use the `sort-redirects.ps1` script with the file path. + +## Scripts + +### sort-redirects.ps1 + +Sorts all entries in the JSON file alphabetically by path (ignoring leading `/` for `source_path_from_root`). Handles both `source_path_from_root` and `source_path` properties. + +Location (relative to this skill file): `./scripts/sort-redirects.ps1` + +| Parameter | Required | Description | +|-----------|----------|-------------| +| `RedirectionFile` | Yes | The path to a redirection JSON file (e.g., `.openpublishing.redirection.csharp.json`) | + +**Example:** + +```powershell +.\scripts\sort-redirects.ps1 -RedirectionFile ".openpublishing.redirection.csharp.json" +``` + +## Important Notes + +- The script preserves all existing redirect entries, only changing their order. +- Sorting is case-sensitive and alphabetical by the normalized path (without leading `/`). diff --git a/CopilotStore/docs-desktop/skills/sort-redirects/scripts/sort-redirects.ps1 b/CopilotStore/docs-desktop/skills/sort-redirects/scripts/sort-redirects.ps1 new file mode 100644 index 00000000..8e424a25 --- /dev/null +++ b/CopilotStore/docs-desktop/skills/sort-redirects/scripts/sort-redirects.ps1 @@ -0,0 +1,112 @@ +<# +.SYNOPSIS + Sorts an Open Publishing redirection JSON file alphabetically by path. + +.DESCRIPTION + This script sorts all redirection entries in a JSON file alphabetically by path. + It handles both 'source_path_from_root' and 'source_path' properties, normalizing + paths by stripping leading '/' for consistent sorting. + +.PARAMETER RedirectionFile + The name of the redirection JSON file (e.g., '.openpublishing.redirection.csharp.json'). + +.EXAMPLE + .\sort-redirects.ps1 -RedirectionFile ".openpublishing.redirection.csharp.json" +#> + +[CmdletBinding()] +param( + [Parameter(Mandatory = $true)] + [string]$RedirectionFile +) + +# Find the root of the git repository +function Get-GitRepoRoot { + $currentPath = (Get-Location).Path + while ($currentPath -ne $null) { + if (Test-Path (Join-Path $currentPath ".git")) { + return $currentPath + } + $parentPath = Split-Path $currentPath -Parent + if ($parentPath -eq $currentPath) { + break + } + $currentPath = $parentPath + } + return $null +} + +# Get the source path from a redirection entry (handles both properties) +function Get-EntrySourcePath { + param($Entry) + if ($Entry.source_path_from_root) { + return $Entry.source_path_from_root + } + return $Entry.source_path +} + +# Normalize a path for comparison (strip leading /) +function Get-NormalizedPath { + param([string]$Path) + return $Path.TrimStart('/') +} + +# Main script logic +try { + # Determine the redirection file path + if ([System.IO.Path]::IsPathRooted($RedirectionFile)) { + # Absolute path provided + $redirectionFilePath = $RedirectionFile + } + else { + # Relative path - find repo root and join + $repoRoot = Get-GitRepoRoot + if (-not $repoRoot) { + Write-Error "Could not find git repository root. Make sure you're running this script from within a git repository." + exit 1 + } + Write-Host "Repository root: $repoRoot" -ForegroundColor Cyan + $redirectionFilePath = Join-Path $repoRoot $RedirectionFile + } + + # Check if file exists + if (-not (Test-Path $redirectionFilePath)) { + Write-Error "Redirection file not found: $redirectionFilePath" + exit 1 + } + + Write-Host "Redirection file: $redirectionFilePath" -ForegroundColor Cyan + + # Read and parse the JSON file + $jsonContent = Get-Content -Path $redirectionFilePath -Raw | ConvertFrom-Json + + # Check if redirections array exists + if (-not $jsonContent.redirections) { + Write-Error "Invalid redirection file format. Expected 'redirections' array not found." + exit 1 + } + + $originalCount = $jsonContent.redirections.Count + Write-Host "Total redirections found: $originalCount" -ForegroundColor Cyan + + # Sort the redirections alphabetically by normalized path + $sortedRedirections = $jsonContent.redirections | Sort-Object -Property { Get-NormalizedPath -Path (Get-EntrySourcePath -Entry $_) } + + # Update the JSON object with sorted redirections + $jsonContent.redirections = $sortedRedirections + + # Convert back to JSON with proper formatting + $jsonOutput = $jsonContent | ConvertTo-Json -Depth 10 + + # Write the updated JSON back to the file + $jsonOutput | Set-Content -Path $redirectionFilePath -Encoding UTF8 + + Write-Host "" + Write-Host "Successfully sorted $originalCount redirection entries alphabetically" -ForegroundColor Green + Write-Host "File updated: $redirectionFilePath" -ForegroundColor Green + +} +catch { + Write-Error "An error occurred: $_" + exit 1 +}