-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add support for defining card messages with XML (#9)
* feat: add card message XSD definition * feat: add card message XML deserializer * fix: handle multiline text correctly * chore: include XSD in nuget package * doc: add XML namespace docs * fix: XSD element documentation * fix: set project IsPackable to false * feat: add sync overload and try methods * feat: add sample * fix: type error in schema * fix: sample error * doc: add documentation for xml card message * fix: should use XML 1.0 as XmlReader does not support XML 1.1 * Update samples/Kook.Net.Samples.CardMarkup/Cards/big-card.xml * Apply suggestions from code review * fix: card markup doc typo --------- Co-authored-by: Ge <[email protected]>
- Loading branch information
1 parent
9fd2547
commit 76aa2f6
Showing
52 changed files
with
2,393 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
--- | ||
uid: Guides.CardMarkup.Card | ||
title: 卡片 | ||
--- | ||
|
||
# 卡片 | ||
|
||
## 属性 | ||
|
||
| 属性 | 类型| 默认值 | 必需 | 说明 | | ||
| --- | --- | --- | --- | --- | | ||
| theme | string | null | | 卡片主题,可选值为 `primary` `success` `danger` `warning` `info` `secondary` `none` | | ||
| size | string | null | | 卡片尺寸,可选值为 `small` `large` | | ||
| color | string | null | | 卡片颜色,十六进制 RGB 色彩,以 `#` 开头 | | ||
|
||
## 元素 | ||
|
||
每一个卡片需要包含一个 `<modules>` 元素,`<modules>` 元素包含卡片的[组件](modules.md)。 | ||
|
||
```xml | ||
<card> | ||
<modules> | ||
<!-- 卡片组件 --> | ||
</modules> | ||
</card> | ||
``` | ||
|
||
## 示例 1 | ||
|
||
使用默认主题、尺寸、颜色的卡片,并包含一个 [标题模块](modules.md#标题-header)。 | ||
|
||
[!code-xml[Card 01](samples/card/sample-01.xml)] | ||
|
||
## 示例 2 | ||
|
||
使用 `warning` 主题、`small` 尺寸、`#aaaaaa` 颜色的卡片,并包含一个 [标题模块](modules.md#标题-header)、一个 [图片组模块](modules.md#图片组-images)。 | ||
|
||
[!code-xml[Card 02](samples/card/sample-02.xml)] | ||
|
||
## 示例 3 | ||
|
||
KOOK 消息编辑器中的投票消息模版。 | ||
|
||
[!code-xml[Card 03](samples/card/sample-03.xml)] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
--- | ||
uid: Guides.CardMarkup.Elements | ||
title: 元素 | ||
--- | ||
|
||
# 元素 | ||
|
||
[KOOK 开发者文档 - 卡片消息 - 元素](https://developer.kookapp.cn/doc/cardmessage#%E5%85%83%E7%B4%A0) | ||
|
||
## 普通文本 `plain` | ||
|
||
| 属性 | 类型 | 默认值 | 必需 | 说明 | | ||
| --- | --- | --- | --- | --- | | ||
| emoji | bool | true | | 如果为 true,会把 emoji 的 shortcut 转为 emoji | | ||
|
||
[!code-xml[Plain](samples/definitions/element-plain.xml)] | ||
|
||
## KMarkdown `kmarkdown` | ||
|
||
[!code-xml[KMarkdown](samples/definitions/element-kmarkdown.xml)] | ||
|
||
## 图片 `image` | ||
|
||
| 属性 | 类型 | 默认值 | 必需 | 说明 | | ||
| --- | --- | --- | --- | --- | | ||
| src | anyURI | null | ✅ | 图片 URL,必须以 `https://` 开头 | | ||
| alt | string | null | | 图片的替代文本 | | ||
| size | string | null | | 图片的尺寸,可选值为 `small` `large` | | ||
| circle | bool | false | | 是否显示为圆形 | | ||
|
||
[!code-xml[Image](samples/definitions/element-image.xml)] | ||
|
||
## 按钮 `button` | ||
|
||
| 属性 | 类型 | 默认值 | 必需 | 说明 | | ||
| --- | --- | --- | --- | --- | | ||
| theme | string | null | | 按钮主题,可选值为 `primary` `success` `danger` `warning` `info` `secondary` | | ||
| value | string | null | | 按钮需要传递的 value | | ||
| click | string | null | | 按钮事件类型,可选值为 `link` `return-val` | | ||
|
||
| 元素 | 数量 | 说明 | | ||
| --- | --- | --- | | ||
| [plain](#普通文本-plain) | 1,与 kmarkdown 互斥 | 按钮文本 | | ||
| [kmarkdown](#kmarkdown-kmarkdown) | 1,与 plain 互斥 | 按钮文本 | | ||
|
||
[!code-xml[Button](samples/definitions/element-button.xml)] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
--- | ||
uid: Guides.CardMarkup.Intro | ||
title: XML 卡片消息入门 | ||
--- | ||
|
||
# XML 卡片消息 | ||
|
||
[Kook.CardMarkup](xref:Kook.CardMarkup) 命名空间提供了将使用 XML 标记语言定义的卡片消息反序列化为 [ICard](xref:Kook.ICard) 对象的方法。 | ||
|
||
## 入门 | ||
|
||
下面的示例中,我们创建一个简单的,由标题、分割线和 9 张图片组成的一个卡片消息。 | ||
|
||
### XML 标记 | ||
|
||
创建一个 XML 文件,定义卡片消息的内容: | ||
|
||
[!code-xml[Sample Card](samples/intro/sample-card.xml)] | ||
|
||
#### XML 声明 | ||
|
||
文件第一行为 XML 声明,指定 XML 版本和字符编码: | ||
|
||
> [!WARNING] | ||
> 字符编码必须是 `UTF-8`。 | ||
> XML 版本必须是 `1.0`。 | ||
[!code-xml[Sample Card - XML Declaration](samples/intro/sample-card.xml#L1)] | ||
|
||
#### 卡片消息 | ||
|
||
XML 根元素为 `<card-message>`,代表一个卡片消息,每一个 `<card-message>` 元素可以包含多个 `<card>` 元素。 | ||
|
||
`<card-message>` 元素上需要指定 XML 命名空间,以及 XML Schema 文件的位置: | ||
|
||
[!code-xml[Sample Card - Root Element](samples/intro/sample-card.xml#L3-L5)] | ||
|
||
- `xmlns=https://kooknet.dev` 指定了默认 XML 命名空间,卡片消息所有的元素均在该命名空间下。 | ||
- `xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"` 指定了 XML Schema 实例命名空间,并设置命名空间前缀为 `xsi`。 | ||
- `xsi:schemaLocation="https://kooknet.dev https://kooknet.dev/card-message.xsd"` 调用了 `xsi` 命名空间下的 `schemaLocation` 属性,指定了 `https://kooknet.dev` 命名空间下的 XML Schema 文件位置在 `https://kooknet.dev/card-message.xsd`。 | ||
|
||
#### 卡片 | ||
|
||
`<card>` 元素代表一个卡片,每一个 `<card>` 元素包含一个 `<modules>` 元素,用于包含卡片的组件。 | ||
|
||
关于卡片,请参阅 [卡片](card.md)。 | ||
|
||
### 反序列化 | ||
|
||
使用 [Kook.CardMarkup.CardMarkupSerializer](xref:Kook.CardMarkup.CardMarkupSerializer) 将 XML 卡片消息反序列化为 [ICard](xref:Kook.ICard) 对象: | ||
|
||
> [!WARNING] | ||
> `Try...` 方法只适用于同步调用。 | ||
> [!NOTE] | ||
> 此示例传入参数为 XML 文件的 `FileInfo` 类实例。 | ||
> 所有方法均有传入参数为 `Stream` 或 `string` 的重载。 | ||
> 传出参数的类型均为 `IEnumerable<ICard>` 或 `Task<IEnumerable<ICard>>`。 | ||
[!code-csharp[Deserialize Card](samples/intro/deserialize-sample-card.cs)] | ||
|
||
### 渲染效果 | ||
|
||
该 XML 卡片消息等效于以下 JSON 格式的卡片消息: | ||
|
||
[!code-json[Sample Card](samples/intro/sample-card.json)] | ||
|
||
渲染效果如下: | ||
|
||
![Sample Card](samples/intro/sample-card.png) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
--- | ||
uid: Guides.CardMarkup.Modules | ||
title: 模块 | ||
--- | ||
|
||
# 模块 | ||
|
||
[KOOK 开发者文档 - 卡片消息 - 模块](https://developer.kookapp.cn/doc/cardmessage#%E6%A8%A1%E5%9D%97) | ||
|
||
## 标题 `header` | ||
|
||
| 元素 | 数量 | 说明 | | ||
| --- | --- | --- | | ||
| [plain](elements.md#普通文本-plain) | 1 | 标题文本 | | ||
|
||
[!code-xml[Header](samples/definitions/module-header.xml)] | ||
|
||
## 内容 `section` | ||
|
||
| 属性 | 类型 | 默认值 | 必需 | 说明 | | ||
| --- | --- | --- | --- | --- | | ||
| mode | string | right | | 其它元素的放置位置 | | ||
|
||
| 元素 | 数量 | 说明 | | ||
| --- | --- | --- | | ||
| text | 1 | 内容模块的文本元素 | | ||
| text/[plain](elements.md#普通文本-plain) | 1,与 `text/markdown` 互斥 | 内容模块的文本元素(纯文本) | | ||
| text/[kmarkdown](elements.md#kmarkdown-kmarkdown) | 1,与 `text/plain` 互斥 | 内容模块的文本元素(KMarkdown) | | ||
| accessory | 0-1 | 内容模块的其它元素 | | ||
| accessory/[image](elements.md#图片-image) | 1,与 `accessory/button` 互斥 | 内容模块的其它元素(图片) | | ||
| accessory/[button](elements.md#按钮-button) | 1,与 `accessory/image` 互斥 | 内容模块的其它元素(按钮) | | ||
|
||
[!code-xml[Section](samples/definitions/module-section.xml)] | ||
|
||
## 图片组 `images` | ||
|
||
| 元素 | 数量 | 说明 | | ||
| --- | --- | --- | | ||
| [image](elements.md#图片-image) | 1-9 | 图片 | | ||
|
||
[!code-xml[Images](samples/definitions/module-images.xml)] | ||
|
||
## 容器 `container` | ||
|
||
| 元素 | 数量 | 说明 | | ||
| --- | --- | --- | | ||
| [image](elements.md#图片-image) | 1-9 | 图片 | | ||
|
||
[!code-xml[Container](samples/definitions/module-container.xml)] | ||
|
||
## 交互 `actions` | ||
|
||
| 元素 | 数量 | 说明 | | ||
| --- | --- | --- | | ||
| [button](elements.md#按钮-button) | 1-4 | 按钮 | | ||
|
||
[!code-xml[Actions](samples/definitions/module-actions.xml)] | ||
|
||
## 备注 `context` | ||
|
||
| 元素 | 数量 | 说明 | | ||
| --- | --- | --- | | ||
| [plain](elements.md#普通文本-plain) | 与 `kmarkdown` `image` 合计至多 10,至少 1 | 纯文本 | | ||
| [kmarkdown](elements.md#kmarkdown-kmarkdown) | 与 `plain` `image` 合计至多 10,至少 1 | KMarkdown | | ||
| [image](elements.md#图片-image) | 与 `plain` `kmarkdown` 合计至多 10,至少 1 | 图片 | | ||
|
||
[!code-xml[Context](samples/definitions/module-context.xml)] | ||
|
||
## 分割线 `divider` | ||
|
||
[!code-xml[Divider](samples/definitions/module-divider.xml)] | ||
|
||
## 文件 (文件/视频) `file` `video` | ||
|
||
| 属性 | 类型 | 默认值 | 必需 | 说明 | | ||
| --- | --- | --- | --- | --- | | ||
| src | anyURI | null | ✅ | 文件 URL,必须以 `https://` 开头 | | ||
| title | string | null | | 文件标题 | | ||
|
||
[!code-xml[File](samples/definitions/module-file.xml)] | ||
[!code-xml[Video](samples/definitions/module-video.xml)] | ||
|
||
## 文件 (音频) `audio` | ||
|
||
| 属性 | 类型 | 默认值 | 必需 | 说明 | | ||
| --- | --- | --- | --- | --- | | ||
| src | anyURI | null | ✅ | 文件 URL,必须以 `https://` 开头 | | ||
| title | string | null | | 文件标题 | | ||
| cover | anyURI | null | | 封面 URL,必须以 `https://` 开头 | | ||
|
||
[!code-xml[Audio](samples/definitions/module-audio.xml)] | ||
|
||
## 倒计时 `countdown` | ||
|
||
| 属性 | 类型 | 默认值 | 必需 | 说明 | | ||
| --- | --- | --- | --- | --- | | ||
| start | ulong | null | ⚠️ | 起始的毫秒时间戳,仅 `mode="second"` 时需要 | | ||
| end | ulong | null | ✅ | 到期的毫秒时间戳 | | ||
| mode | string | null | ✅ | 显示模式,可选值为 `day` `hour` `second` | | ||
|
||
[!code-xml[Countdown](samples/definitions/module-countdown.xml)] | ||
|
||
## 邀请 `invite` | ||
|
||
| 属性 | 类型 | 默认值 | 必需 | 说明 | | ||
| --- | --- | --- | --- | --- | | ||
| code | string | null | ✅ | 邀请链接或者邀请码 | | ||
|
||
[!code-xml[Invite](samples/definitions/module-invite.xml)] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<card> | ||
<modules> | ||
<header> | ||
<plain>测试卡片</plain> | ||
</header> | ||
</modules> | ||
</card> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<card theme="warning" color="#aaaaaa" size="small"> | ||
<modules> | ||
|
||
<header> | ||
<plain>测试卡片</plain> | ||
</header> | ||
|
||
<images> | ||
<image src="https://img.kaiheila.cn/assets/2021-01/pWsmcLsPJq08c08c.jpeg" /> | ||
<image src="https://img.kaiheila.cn/assets/2021-01/YIfHfnvxaV0dw0dw.jpg" /> | ||
<image src="https://img.kaiheila.cn/assets/2021-01/YevTY6eGJa0fk0f2.jpeg" /> | ||
<image src="https://img.kaiheila.cn/assets/2021-01/r2K9RjHZ4s0xc0xc.jpeg" /> | ||
<image src="https://img.kaiheila.cn/assets/2021-01/klosFRTVy90jz0k0.jpg" /> | ||
<image src="https://img.kaiheila.cn/assets/2021-01/veHnEhzu6c0dw0dv.jpg" /> | ||
<image src="https://img.kaiheila.cn/assets/2021-01/tiVWPIuTrf0dw0dw.jpg" /> | ||
<image src="https://img.kaiheila.cn/assets/2021-01/wExzRIrTeR0j60j7.jpeg" /> | ||
<image src="https://img.kaiheila.cn/assets/2021-01/AybvLWYQgA0dw0dw.jpg" /> | ||
</images> | ||
|
||
</modules> | ||
</card> |
Oops, something went wrong.