Compare commits
2 Commits
main
...
wan92hen-p
Author | SHA1 | Date |
---|---|---|
|
479682dc03 | 8 months ago |
|
41416c7d47 | 8 months ago |
@ -1,72 +0,0 @@
|
|||||||
---
|
|
||||||
title: 获取扩展
|
|
||||||
description: 了解如何在插件中使用 `ExtensionGetter` 获取扩展
|
|
||||||
---
|
|
||||||
|
|
||||||
`ExtensionGetter` 用于获取和管理 Halo 或其他插件提供的扩展。它提供了多种方法来根据扩展点获取扩展,确保插件能够灵活地集成和使用各种扩展功能。
|
|
||||||
|
|
||||||
`ExtensionGetter` 接口的定义如下:
|
|
||||||
|
|
||||||
```java
|
|
||||||
public interface ExtensionGetter {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get only one enabled extension from system configuration.
|
|
||||||
*
|
|
||||||
* @param extensionPoint is extension point class.
|
|
||||||
* @return implementation of the corresponding extension point. If no configuration is found,
|
|
||||||
* we will use the default implementation from application context instead.
|
|
||||||
*/
|
|
||||||
<T extends ExtensionPoint> Mono<T> getEnabledExtension(Class<T> extensionPoint);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the extension(s) according to the {@link ExtensionPointDefinition} queried
|
|
||||||
* by incoming extension point class.
|
|
||||||
*
|
|
||||||
* @param extensionPoint extension point class
|
|
||||||
* @return implementations of the corresponding extension point.
|
|
||||||
* @throws IllegalArgumentException if the incoming extension point class does not have
|
|
||||||
* the {@link ExtensionPointDefinition}.
|
|
||||||
*/
|
|
||||||
<T extends ExtensionPoint> Flux<T> getEnabledExtensions(Class<T> extensionPoint);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all extensions according to extension point class.
|
|
||||||
*
|
|
||||||
* @param extensionPointClass extension point class
|
|
||||||
* @param <T> type of extension point
|
|
||||||
* @return a bunch of extension points.
|
|
||||||
*/
|
|
||||||
<T extends ExtensionPoint> Flux<T> getExtensions(Class<T> extensionPointClass);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
包含以下方法:
|
|
||||||
|
|
||||||
1. `getEnabledExtension(Class<T> extensionPoint)`: 获取一个在扩展设置中已启用的扩展。如果没有找到对应配置,将使用 Halo 中的默认扩展,如果 Halo 没有提供默认实现则找到一个由**已启用插件**提供的可用扩展。
|
|
||||||
2. `getEnabledExtensions(Class<T> extensionPoint)`: 根据传入的扩展点类获取所有已启用扩展。如果没有在扩展设置页面配置过则会返回所有可用的扩展。
|
|
||||||
3. `getExtensions(Class<T> extensionPointClass)`: 获取所有与扩展点类相关的扩展,无论是否在扩展设置中启用它。
|
|
||||||
|
|
||||||
:::tip Note
|
|
||||||
使用 `getEnabledExtension` 方法或者 `getEnabledExtensions` 方法取决于扩展点声明的 `type` 是 `SINGLETON` 还是 `MULTI_INSTANCE`。
|
|
||||||
|
|
||||||
通过使用 `ExtensionGetter`,开发者可以轻松地在插件中访问和管理各种扩展点,提升插件的功能和灵活性。
|
|
||||||
|
|
||||||
如果想了解 Halo 提供的扩展点请参考:[扩展点](./extension-points/index.md)。
|
|
||||||
:::
|
|
||||||
|
|
||||||
### 示例
|
|
||||||
|
|
||||||
如果你想在插件中获取已启用的搜索引擎扩展,可以使用 `ExtensionGetter` 来获取:
|
|
||||||
|
|
||||||
```java
|
|
||||||
@Service
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class SearchService {
|
|
||||||
private final ExtensionGetter extensionGetter;
|
|
||||||
|
|
||||||
Mono<SearchEngine> getSearchEngine() {
|
|
||||||
return extensionGetter.getEnabledExtension(SearchEngine.class)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
@ -1,81 +0,0 @@
|
|||||||
---
|
|
||||||
title: 评论数据列表操作菜单
|
|
||||||
description: 扩展评论数据列表操作菜单 - comment:list-item:operation:create
|
|
||||||
---
|
|
||||||
|
|
||||||
此扩展点用于扩展评论数据列表的操作菜单项。
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## 定义方式
|
|
||||||
|
|
||||||
```ts
|
|
||||||
export default definePlugin({
|
|
||||||
extensionPoints: {
|
|
||||||
"comment:list-item:operation:create": (
|
|
||||||
comment: Ref<ListedComment>
|
|
||||||
): OperationItem<ListedComment>[] | Promise<OperationItem<ListedComment>[]> => {
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
priority: 10,
|
|
||||||
component: markRaw(VDropdownItem),
|
|
||||||
props: {},
|
|
||||||
action: (item?: ListedComment) => {
|
|
||||||
// do something
|
|
||||||
},
|
|
||||||
label: "foo",
|
|
||||||
hidden: false,
|
|
||||||
permissions: [],
|
|
||||||
children: [],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
```mdx-code-block
|
|
||||||
import OperationItem from "./interface/OperationItem.md";
|
|
||||||
|
|
||||||
<OperationItem />
|
|
||||||
```
|
|
||||||
|
|
||||||
## 示例
|
|
||||||
|
|
||||||
此示例将实现一个操作菜单项。
|
|
||||||
|
|
||||||
```ts
|
|
||||||
import type { ListedComment } from "@halo-dev/api-client";
|
|
||||||
import { VDropdownItem } from "@halo-dev/components";
|
|
||||||
import { definePlugin } from "@halo-dev/console-shared";
|
|
||||||
import { markRaw } from "vue";
|
|
||||||
|
|
||||||
export default definePlugin({
|
|
||||||
extensionPoints: {
|
|
||||||
"comment:list-item:operation:create": () => {
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
priority: 21,
|
|
||||||
component: markRaw(VDropdownItem),
|
|
||||||
label: "测试评论菜单",
|
|
||||||
visible: true,
|
|
||||||
permissions: [],
|
|
||||||
action: async (comment: ListedComment) => {
|
|
||||||
console.log(comment)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
## 类型定义
|
|
||||||
|
|
||||||
### ListedComment
|
|
||||||
|
|
||||||
```mdx-code-block
|
|
||||||
import ListedComment from "./interface/ListedComment.md";
|
|
||||||
|
|
||||||
<ListedComment />
|
|
||||||
```
|
|
@ -1,64 +0,0 @@
|
|||||||
```ts
|
|
||||||
export interface ListedComment {
|
|
||||||
comment:{
|
|
||||||
apiVersion: "content.halo.run/v1alpha1"
|
|
||||||
kind: "Comment"
|
|
||||||
metadata: {
|
|
||||||
annotations: {}
|
|
||||||
creationTimestamp: string
|
|
||||||
labels: {}
|
|
||||||
name: string // 评论的唯一标识
|
|
||||||
version: number
|
|
||||||
}
|
|
||||||
spec: {
|
|
||||||
allowNotification: boolean; // 是否允许通知
|
|
||||||
approved: boolean;
|
|
||||||
approvedTime: string;
|
|
||||||
content: string; // 最终渲染的文本
|
|
||||||
creationTime: string; // 创建时间
|
|
||||||
hidden: boolean;
|
|
||||||
ipAddress: string; // 评论者 IP 地址
|
|
||||||
lastReadTime: string;
|
|
||||||
owner: { // 创建者信息
|
|
||||||
annotations: {};
|
|
||||||
displayName: string;
|
|
||||||
kind: string;
|
|
||||||
name: string;
|
|
||||||
};
|
|
||||||
priority: number; // 排序字段
|
|
||||||
raw: string; // 原始文本,一般用于给编辑器使用
|
|
||||||
subjectRef: { // 引用关联,比如文章、自定义页面
|
|
||||||
group: string;
|
|
||||||
kind: string;
|
|
||||||
name: string;
|
|
||||||
version: string;
|
|
||||||
};
|
|
||||||
top: boolean; // 是否置顶
|
|
||||||
userAgent: string; // 评论者 UserAgent 信息
|
|
||||||
}
|
|
||||||
status: {
|
|
||||||
hasNewReply: boolean; // 是否有新回复
|
|
||||||
lastReplyTime: string;
|
|
||||||
observedVersion: number;
|
|
||||||
replyCount: number; // 回复数量
|
|
||||||
unreadReplyCount: number;
|
|
||||||
visibleReplyCount: number;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
owner: { // 创建者信息
|
|
||||||
avatar: string; // 头像
|
|
||||||
displayName: string; // 描述
|
|
||||||
email: string; // 邮箱
|
|
||||||
kind: string;
|
|
||||||
name: string; // 创建者的唯一标识
|
|
||||||
}
|
|
||||||
stats: {
|
|
||||||
upvote: number;
|
|
||||||
}
|
|
||||||
subject: {
|
|
||||||
apiVersion: string;
|
|
||||||
kind: string;
|
|
||||||
metadata: Metadata;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
@ -1,49 +0,0 @@
|
|||||||
```ts
|
|
||||||
export interface ListedReply {
|
|
||||||
owner: { // 创建者信息
|
|
||||||
avatar: string; // 头像
|
|
||||||
displayName: string; // 描述
|
|
||||||
email: string; // 邮箱
|
|
||||||
kind: string;
|
|
||||||
name: string; // 创建者的唯一标识
|
|
||||||
}
|
|
||||||
reply:{
|
|
||||||
apiVersion: "content.halo.run/v1alpha1"
|
|
||||||
kind: "Reply"
|
|
||||||
metadata: {
|
|
||||||
annotations: {}
|
|
||||||
creationTimestamp: string
|
|
||||||
labels: {}
|
|
||||||
name: string // 评论的唯一标识
|
|
||||||
version: number
|
|
||||||
}
|
|
||||||
spec: {
|
|
||||||
allowNotification: boolean; // 是否允许通知
|
|
||||||
approved: boolean;
|
|
||||||
approvedTime: string;
|
|
||||||
commentName: string; // 被回复的评论名称,即 Comment 的 metadata.name
|
|
||||||
content: string; // 最终渲染的文本
|
|
||||||
creationTime: string; // 创建时间
|
|
||||||
hidden: boolean;
|
|
||||||
ipAddress: string; // 评论者 IP 地址
|
|
||||||
owner: { // 创建者信息
|
|
||||||
annotations: {};
|
|
||||||
displayName: string;
|
|
||||||
kind: string;
|
|
||||||
name: string;
|
|
||||||
};
|
|
||||||
priority: number; // 排序字段
|
|
||||||
quoteReply: string; // 被回复的回复名称,即 Reply 的 metadata.name
|
|
||||||
raw: string; // 原始文本,一般用于给编辑器使用
|
|
||||||
top: boolean; // 是否置顶
|
|
||||||
userAgent: string; // 评论者 UserAgent 信息
|
|
||||||
}
|
|
||||||
status: {
|
|
||||||
observedVersion: number;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stats: {
|
|
||||||
upvote: number;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
@ -1,81 +0,0 @@
|
|||||||
---
|
|
||||||
title: 回复数据列表操作菜单
|
|
||||||
description: 扩展回复数据列表操作菜单 - reply:list-item:operation:create
|
|
||||||
---
|
|
||||||
|
|
||||||
此扩展点用于扩展回复数据列表的操作菜单项。
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## 定义方式
|
|
||||||
|
|
||||||
```ts
|
|
||||||
export default definePlugin({
|
|
||||||
extensionPoints: {
|
|
||||||
"reply:list-item:operation:create": (
|
|
||||||
reply: Ref<ListedReply>
|
|
||||||
): OperationItem<ListedReply>[] | Promise<OperationItem<ListedReply>[]> => {
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
priority: 10,
|
|
||||||
component: markRaw(VDropdownItem),
|
|
||||||
props: {},
|
|
||||||
action: (item?: ListedReply) => {
|
|
||||||
// do something
|
|
||||||
},
|
|
||||||
label: "foo",
|
|
||||||
hidden: false,
|
|
||||||
permissions: [],
|
|
||||||
children: [],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
```mdx-code-block
|
|
||||||
import OperationItem from "./interface/OperationItem.md";
|
|
||||||
|
|
||||||
<OperationItem />
|
|
||||||
```
|
|
||||||
|
|
||||||
## 示例
|
|
||||||
|
|
||||||
此示例将实现一个操作菜单项。
|
|
||||||
|
|
||||||
```ts
|
|
||||||
import type { ListedReply } from "@halo-dev/api-client";
|
|
||||||
import { VDropdownItem } from "@halo-dev/components";
|
|
||||||
import { definePlugin } from "@halo-dev/console-shared";
|
|
||||||
import { markRaw } from "vue";
|
|
||||||
|
|
||||||
export default definePlugin({
|
|
||||||
extensionPoints: {
|
|
||||||
"reply:list-item:operation:create": () => {
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
priority: 21,
|
|
||||||
component: markRaw(VDropdownItem),
|
|
||||||
label: "测试回复菜单",
|
|
||||||
visible: true,
|
|
||||||
permissions: [],
|
|
||||||
action: async (reply: ListedReply) => {
|
|
||||||
console.log(reply)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
## 类型定义
|
|
||||||
|
|
||||||
### ListedReply
|
|
||||||
|
|
||||||
```mdx-code-block
|
|
||||||
import ListedReply from "./interface/ListedReply.md";
|
|
||||||
|
|
||||||
<ListedReply />
|
|
||||||
```
|
|
@ -1,78 +0,0 @@
|
|||||||
{
|
|
||||||
"version.label": {
|
|
||||||
"message": "2.18",
|
|
||||||
"description": "The label for version 2.18"
|
|
||||||
},
|
|
||||||
"sidebar.tutorial.category.入门": {
|
|
||||||
"message": "入门",
|
|
||||||
"description": "The label for category 入门 in sidebar tutorial"
|
|
||||||
},
|
|
||||||
"sidebar.tutorial.category.安装指南": {
|
|
||||||
"message": "安装指南",
|
|
||||||
"description": "The label for category 安装指南 in sidebar tutorial"
|
|
||||||
},
|
|
||||||
"sidebar.tutorial.category.云平台": {
|
|
||||||
"message": "云平台",
|
|
||||||
"description": "The label for category 云平台 in sidebar tutorial"
|
|
||||||
},
|
|
||||||
"sidebar.tutorial.category.其他指南": {
|
|
||||||
"message": "其他指南",
|
|
||||||
"description": "The label for category 其他指南 in sidebar tutorial"
|
|
||||||
},
|
|
||||||
"sidebar.tutorial.category.用户指南": {
|
|
||||||
"message": "用户指南",
|
|
||||||
"description": "The label for category 用户指南 in sidebar tutorial"
|
|
||||||
},
|
|
||||||
"sidebar.tutorial.category.参与贡献": {
|
|
||||||
"message": "参与贡献",
|
|
||||||
"description": "The label for category 参与贡献 in sidebar tutorial"
|
|
||||||
},
|
|
||||||
"sidebar.developer.category.系统开发": {
|
|
||||||
"message": "系统开发",
|
|
||||||
"description": "The label for category 系统开发 in sidebar developer"
|
|
||||||
},
|
|
||||||
"sidebar.developer.category.插件开发": {
|
|
||||||
"message": "插件开发",
|
|
||||||
"description": "The label for category 插件开发 in sidebar developer"
|
|
||||||
},
|
|
||||||
"sidebar.developer.category.基础": {
|
|
||||||
"message": "基础",
|
|
||||||
"description": "The label for category 基础 in sidebar developer"
|
|
||||||
},
|
|
||||||
"sidebar.developer.category.服务端": {
|
|
||||||
"message": "服务端",
|
|
||||||
"description": "The label for category 服务端 in sidebar developer"
|
|
||||||
},
|
|
||||||
"sidebar.developer.category.UI": {
|
|
||||||
"message": "UI",
|
|
||||||
"description": "The label for category UI in sidebar developer"
|
|
||||||
},
|
|
||||||
"sidebar.developer.category.API 参考": {
|
|
||||||
"message": "API 参考",
|
|
||||||
"description": "The label for category API 参考 in sidebar developer"
|
|
||||||
},
|
|
||||||
"sidebar.developer.category.扩展点": {
|
|
||||||
"message": "扩展点",
|
|
||||||
"description": "The label for category 扩展点 in sidebar developer"
|
|
||||||
},
|
|
||||||
"sidebar.developer.category.组件": {
|
|
||||||
"message": "组件",
|
|
||||||
"description": "The label for category 组件 in sidebar developer"
|
|
||||||
},
|
|
||||||
"sidebar.developer.category.案例和最佳实践": {
|
|
||||||
"message": "案例和最佳实践",
|
|
||||||
"description": "The label for category 案例和最佳实践 in sidebar developer"
|
|
||||||
},
|
|
||||||
"sidebar.developer.category.主题开发": {
|
|
||||||
"message": "主题开发",
|
|
||||||
"description": "The label for category 主题开发 in sidebar developer"
|
|
||||||
},
|
|
||||||
"sidebar.developer.category.模板变量": {
|
|
||||||
"message": "模板变量",
|
|
||||||
"description": "The label for category 模板变量 in sidebar developer"
|
|
||||||
},
|
|
||||||
"sidebar.developer.category.Finder API": {
|
|
||||||
"message": "Finder API",
|
|
||||||
"description": "The label for category Finder API in sidebar developer"
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,57 +0,0 @@
|
|||||||
const fs = require('fs');
|
|
||||||
const path = require('path');
|
|
||||||
|
|
||||||
// 指定要扫描的目录
|
|
||||||
const directoryPath = './docs';
|
|
||||||
|
|
||||||
// 递归读取目录中的所有 Markdown 文件
|
|
||||||
function readDirectory(directory) {
|
|
||||||
fs.readdir(directory, (err, files) => {
|
|
||||||
if (err) {
|
|
||||||
return console.log('无法扫描目录: ' + err);
|
|
||||||
}
|
|
||||||
|
|
||||||
files.forEach(file => {
|
|
||||||
const filePath = path.join(directory, file);
|
|
||||||
fs.stat(filePath, (err, stats) => {
|
|
||||||
if (err) {
|
|
||||||
return console.log('无法获取文件信息: ' + err);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stats.isDirectory()) {
|
|
||||||
// 如果是目录,递归读取
|
|
||||||
readDirectory(filePath);
|
|
||||||
} else if (path.extname(file) === '.md') {
|
|
||||||
// 如果是 Markdown 文件,处理文件内容
|
|
||||||
processMarkdownFile(filePath);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理 Markdown 文件内容
|
|
||||||
function processMarkdownFile(filePath) {
|
|
||||||
fs.readFile(filePath, 'utf8', (err, data) => {
|
|
||||||
if (err) {
|
|
||||||
return console.log('无法读取文件: ' + err);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 使用正则表达式匹配 <https://ryanc.cc> 形式的链接
|
|
||||||
const updatedData = data.replace(/<https:\/\/[^\s]+>/g, match => {
|
|
||||||
const url = match.slice(1, -1); // 去掉尖括号
|
|
||||||
return `[${url}](${url})`;
|
|
||||||
});
|
|
||||||
|
|
||||||
// 将更新后的内容写回文件
|
|
||||||
fs.writeFile(filePath, updatedData, 'utf8', err => {
|
|
||||||
if (err) {
|
|
||||||
return console.log('无法写入文件: ' + err);
|
|
||||||
}
|
|
||||||
console.log(`已处理文件: ${filePath}`);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 开始扫描目录
|
|
||||||
readDirectory(directoryPath);
|
|
File diff suppressed because it is too large
Load Diff
Before Width: | Height: | Size: 74 KiB |
Before Width: | Height: | Size: 77 KiB |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue