CmdPal: Restore content viewer spec and regenerate IDL (#50210)

## Summary of the Pull Request

Restore the image and plain-text content documentation that was omitted
from merged PR #43964. Preserve the original documentation while fixing
its frontmatter typo and trailing whitespace.

Reconcile older grid, filter, ContentSize, and fallback definitions in
the Markdown with the existing SDK before regenerating the IDL. All 76
current SDK declarations, including members, UUIDs, and contracts, are
preserved.

Mark the IDL as generated, reject missing or failed Markdown parsers,
normalize generated whitespace, and correct the regeneration
instructions.

Restored-from: 6c5a415fd4
This commit is contained in:
Jiří Polášek
2026-08-28 21:56:52 +02:00
committed by GitHub
parent 338bfd1bbb
commit 428044b477
3 changed files with 202 additions and 100 deletions

View File

@@ -1,8 +1,15 @@
# The spec is next to this script:
$pathToSpec = Join-Path (Split-Path -parent $MyInvocation.MyCommand.Definition) initial-sdk-spec.md
# First, use the mistletoe library to parse the markdown file to json
if (-not (Get-Command mistletoe -ErrorAction SilentlyContinue)) {
throw 'The generator requires mistletoe. Install it with python -m pip install mistletoe and add its scripts directory to PATH.'
}
$jsonText = mistletoe $pathToSpec --renderer mistletoe.ast_renderer.AstRenderer
$json = $jsonText | ConvertFrom-Json
if ($LASTEXITCODE -ne 0) {
throw "mistletoe failed with exit code $LASTEXITCODE"
}
$json = $jsonText | ConvertFrom-Json -ErrorAction Stop
$sdkContents = ""
foreach ($item in $json.children) {
@@ -55,7 +62,11 @@ foreach ($item in $json.children) {
}
# now, write the fully formatted interface with headers and all:
Write-Output @"
$interface = @"
// <auto-generated>
// Generated from doc/initial-sdk-spec/initial-sdk-spec.md by generate-interface.ps1.
// Edit the Markdown spec, then regenerate this file.
// </auto-generated>
namespace Microsoft.CommandPalette.Extensions
{
[contractversion(1)]
@@ -115,3 +126,8 @@ namespace Microsoft.CommandPalette.Extensions
$sdkContents
}
"@
# Keep generated output free of trailing whitespace and use consistent line endings.
$interface = $interface -replace "\r\n?", "`n"
$interface = $interface -replace "(?m)[\t ]+$", ""
Write-Output ($interface.TrimEnd("`n") -replace "`n", [Environment]::NewLine)

View File

@@ -1,7 +1,7 @@
---
author: Mike Griese
created on: 2024-07-19
last updated: 2026-02-05
last updated: 2026-08-28
issue id: n/a
---
@@ -85,6 +85,9 @@ functionality.
- [Nov 2025 status](#nov-2025-status)
- [Addenda IV: Dock bands](#addenda-iv-dock-bands)
- [Pinning nested commands to the dock (and top level)](#pinning-nested-commands-to-the-dock-and-top-level)
- [Addenda V: Extra content types](#addenda-v-extra-content-types)
- [Image content](#image-content)
- [Plain text content](#plain-text-content)
- [Class diagram](#class-diagram)
- [Future considerations](#future-considerations)
- [Arbitrary parameters and arguments](#arbitrary-parameters-and-arguments)
@@ -819,8 +822,21 @@ interface IListItem requires ICommandItem {
String TextToSuggest { get; };
}
interface IGridProperties {
Windows.Foundation.Size TileSize { get; };
[uuid("50C6F080-1CBE-4CE4-B92F-DA2F116ED524")]
interface IGridProperties requires INotifyPropChanged { }
[uuid("05914D59-6ECB-4992-9CF2-5982B5120A26")]
interface ISmallGridLayout requires IGridProperties { }
interface IMediumGridLayout requires IGridProperties
{
Boolean ShowTitle { get; };
}
interface IGalleryGridLayout requires IGridProperties
{
Boolean ShowTitle { get; };
Boolean ShowSubtitle { get; };
}
interface IListPage requires IPage, INotifyItemsChanged {
@@ -942,9 +958,10 @@ of grouped results, they're free to have as many sections as they like.
When the `GridProperties` property is set to null, DevPal will display the items
as a simple list, grouping them by section. When the `GridProperties` property
is set to a non-null value, DevPal will display the items as a grid, with each
item in the grid being a `TileSize` square. Grids are useful for showing items
that are more visual in nature, like images or icons.
is set to a non-null value, DevPal uses the implemented layout interface:
`ISmallGridLayout`, `IMediumGridLayout`, or `IGalleryGridLayout`. Medium and
gallery layouts can show titles, and gallery layouts can also show subtitles.
Grids are useful for visual content such as images or icons.
Each item in the list may also include an optional `Details` property. This
allows the extension to provide additional information about the item, like a
@@ -1125,7 +1142,7 @@ interface IFilterItem {}
[uuid("0a923c7f-5b7b-431d-9898-3c8c841d02ed")]
interface ISeparatorFilterItem requires IFilterItem {}
interface IFilter requires IFilterItem {
interface IFilter requires INotifyPropChanged, IFilterItem {
String Id { get; };
String Name { get; };
IIconInfo Icon { get; };
@@ -1133,7 +1150,7 @@ interface IFilter requires IFilterItem {
interface IFilters {
String CurrentFilterId { get; set; };
IFilterItem[] Filters();
IFilterItem[] GetFilters();
}
```
@@ -1416,6 +1433,15 @@ interface ITag {
[uuid("6a6dd345-37a3-4a1e-914d-4f658a4d583d")]
interface IDetailsData {}
[contract(Microsoft.CommandPalette.Extensions.ExtensionsContract, 1)]
enum ContentSize
{
Small = 0,
Medium = 1,
Large = 2,
};
interface IDetailsElement {
String Key { get; };
IDetailsData Data { get; };
@@ -1487,6 +1513,10 @@ interface IFallbackCommandItem requires ICommandItem {
String DisplayTitle { get; };
};
interface IFallbackCommandItem2 requires IFallbackCommandItem {
String Id { get; };
};
interface ICommandProvider requires Windows.Foundation.IClosable, INotifyItemsChanged
{
String Id { get; };
@@ -2355,6 +2385,45 @@ because that method is was designed for two main purposes:
In neither of those scenarios was the full "display" of the item needed. In
pinning scenarios, however, we need everything that the user would see in the UI
for that item, which is all in the `ICommandItem`.
## Addenda V: Extra content types
Extra content types for [Content Pages](#content-pages) views so we can provide extra functionality to the user.
### Image content
Image content is dedicated to displaying a single image. The host will attempt to display the entire
image in the UI or a scaled down preview, while respecting the max width and height. If possible, the host will
provide UI controls to display the image 1:1, save it or copy it to the clipboard.
```csharp
interface IImageContent requires IContent {
IIconInfo Image { get; };
Int32 MaxWidth { get; };
Int32 MaxHeight { get; };
}
```
### Plain text content
Developers can declare that the content is unformatted plain text and provide
hints about how to render it, such as what font to use and whether to
wrap words or not. Users can control the view settings.
```csharp
enum FontFamily
{
UserInterface,
Monospace,
};
interface IPlainTextContent requires IContent {
String Text { get; };
FontFamily FontFamily { get; };
Boolean WrapWords { get; };
}
```
## Class diagram
This is a diagram attempting to show the relationships between the various types we've defined for the SDK. Some elements are omitted for clarity. (Notably, `IconData` and `IPropChanged`, which are used in many places.)
@@ -2447,8 +2516,17 @@ classDiagram
ITag "*" *-- IListItem
IFallbackHandler "?" *-- IListItem
class IGridProperties {
Windows.Foundation.Size TileSize
IGridProperties --|> INotifyPropChanged
class IGridProperties
ISmallGridLayout --|> IGridProperties
IMediumGridLayout --|> IGridProperties
IGalleryGridLayout --|> IGridProperties
class IMediumGridLayout {
Boolean ShowTitle
}
class IGalleryGridLayout {
Boolean ShowTitle
Boolean ShowSubtitle
}
IListPage --|> IPage
@@ -2607,19 +2685,22 @@ Is that just a `Details` object? A markdown body?
### Generating the `.idl`
The `.idl` for this SDK can be generated directly from this file. To do so, run the following command:
This Markdown file is the source for the SDK definitions. Do not edit
`extensionsdk/Microsoft.CommandPalette.Extensions/Microsoft.CommandPalette.Extensions.idl`
directly. API declarations use `csharp` or `c#` fences; implementation examples use
`cs` fences and are not emitted by the generator.
Install the generator dependency with `python -m pip install mistletoe`, and ensure
its `mistletoe` command is on `PATH`. From `src/modules/cmdpal`, regenerate with:
```ps1
.\generate-interface.ps1 > .\Microsoft.DevPalette.Extensions.idl
.\doc\initial-sdk-spec\generate-interface.ps1 |
Set-Content -Encoding utf8 .\extensionsdk\Microsoft.CommandPalette.Extensions\Microsoft.CommandPalette.Extensions.idl
```
(After a `pip3 install mistletoe`)
Or, to generate straight to the place I'm consuming it from:
```ps1
.\doc\initial-sdk-spec\generate-interface.ps1 > .\extensionsdk\Microsoft.CommandPalette.Extensions\Microsoft.CommandPalette.Extensions.Toolkit.idl
```
Review the generated diff along with the Markdown changes. Existing interface
members, UUIDs and `requires` declarations must be preserved when reconciling old
source drift. Regenerating a second time should produce no further changes.
### Adding APIs

View File

@@ -1,3 +1,7 @@
// <auto-generated>
// Generated from doc/initial-sdk-spec/initial-sdk-spec.md by generate-interface.ps1.
// Edit the Markdown spec, then regenerate this file.
// </auto-generated>
namespace Microsoft.CommandPalette.Extensions
{
[contractversion(1)]
@@ -354,26 +358,6 @@ namespace Microsoft.CommandPalette.Extensions
IContent[] GetChildren();
}
enum FontFamily
{
UserInterface,
Monospace,
};
[contract(Microsoft.CommandPalette.Extensions.ExtensionsContract, 1)]
interface IPlainTextContent requires IContent {
String Text { get; };
FontFamily FontFamily { get; };
Boolean WrapWords { get; };
}
[contract(Microsoft.CommandPalette.Extensions.ExtensionsContract, 1)]
interface IImageContent requires IContent {
IIconInfo Image { get; };
Int32 MaxWidth { get; };
Int32 MaxHeight { get; };
}
[contract(Microsoft.CommandPalette.Extensions.ExtensionsContract, 1)]
interface IContentPage requires IPage, INotifyItemsChanged {
IContent[] GetContent();
@@ -431,23 +415,10 @@ namespace Microsoft.CommandPalette.Extensions
Object[] GetApiExtensionStubs();
};
[contract(Microsoft.CommandPalette.Extensions.ExtensionsContract, 1)]
interface ICommandProvider3 requires ICommandProvider2
{
ICommandItem[] GetDockBands();
};
[contract(Microsoft.CommandPalette.Extensions.ExtensionsContract, 1)]
interface ICommandProvider4 requires ICommandProvider3
{
ICommandItem GetCommandItem(String id);
};
[contract(Microsoft.CommandPalette.Extensions.ExtensionsContract, 1)]
[uuid("a2590cc9-510c-4af7-b562-a6b56fe37f55")]
[contract(Microsoft.CommandPalette.Extensions.ExtensionsContract, 1)]
interface IParameterRun requires INotifyPropChanged
{
};
[contract(Microsoft.CommandPalette.Extensions.ExtensionsContract, 1)]
@@ -486,4 +457,38 @@ namespace Microsoft.CommandPalette.Extensions
IParameterRun[] Parameters{ get; };
IListItem Command{ get; };
};
[contract(Microsoft.CommandPalette.Extensions.ExtensionsContract, 1)]
interface ICommandProvider3 requires ICommandProvider2
{
ICommandItem[] GetDockBands();
};
[contract(Microsoft.CommandPalette.Extensions.ExtensionsContract, 1)]
interface ICommandProvider4 requires ICommandProvider3
{
ICommandItem GetCommandItem(String id);
};
[contract(Microsoft.CommandPalette.Extensions.ExtensionsContract, 1)]
interface IImageContent requires IContent {
IIconInfo Image { get; };
Int32 MaxWidth { get; };
Int32 MaxHeight { get; };
}
enum FontFamily
{
UserInterface,
Monospace,
};
[contract(Microsoft.CommandPalette.Extensions.ExtensionsContract, 1)]
interface IPlainTextContent requires IContent {
String Text { get; };
FontFamily FontFamily { get; };
Boolean WrapWords { get; };
}
}