Skip to content

社区集市

在思源中, 开发者希望把自己开发的作品上架到集市 (bazaar),除了核心的代码文件之外, 还必须提交如下内容

  • 清单文件 (不同类型资源的清单文件文件名不同)
    • icon.json
    • plugin.json
    • template.json
    • theme.json
    • widget.json
  • 说明文件
    • README.md
  • 图标图片
    • icon.png
  • 预览图片
    • preview.png

清单文件

bazaar 读取特定 json 文件来获悉社区资源的具体配置。

  • 图标资源: icon.json
  • 插件资源: plugin.json
  • 模板资源: template.json
  • 主题资源: theme.json
  • 挂件资源: widget.json

基本字段

不同类型的社区资源有不同的清单文件,但是他们有一些共同的字段。

json
{
    "$schema": "https://docs.siyuan-note.club/schemas/manifest/base.schema.json",
    "name": "example-name",
    "author": "Author Name Example",
    "url": "https://github.com/example-username/example-repository-name",
    "version": "0.1.0",
    "minAppVersion": "2.8.8",
    "keywords": [
        "example",
        "示例"
    ],
    "displayName": {
        "default": "Example Name",
        "zh_CHT": "示例名稱",
        "zh_CN": "示例名称"
    },
    "description": {
        "default": "Descriptive information about this example",
        "zh_CHT": "關於本示例的描述信息",
        "zh_CN": "关于本示例的描述信息"
    },
    "readme": {
        "default": "README.md",
        "en_US": "README_en_US.md",
        "zh_CN": "README_zh_CN.md"
    },
    "funding": {
        "openCollective": "siyuan",
        "patreon": "",
        "github": "88250",
        "custom": [
            "https://ld246.com/sponsor"
        ]
    }
}
ts
/**
 * Basic definition of community resource manifest file
 */
export interface IBase {
    /**
     * The name of the author
     */
    readonly author: string;
    /**
     * The description of the resource
     */
    readonly description?: ILocalizedText;
    /**
     * The display name of the resource
     */
    readonly displayName?: ILocalizedText;
    /**
     * The funding of the resource
     */
    readonly funding?: IFunding;
    /**
     * The keywords of the resource used for search
     */
    readonly keywords?: string[];
    /**
     * The minimum version of SiYuan that the resource is compatible with
     */
    readonly minAppVersion?: string;
    /**
     * The name of the resource
     */
    readonly name: string;
    /**
     * The readme file name of the resource
     */
    readonly readme?: ILocalizedText;
    /**
     * The GitHub repository URL of the resource
     */
    readonly url: string;
    /**
     * The version of the resource
     */
    readonly version: string;
    [property: string]: any;
}

/**
 * The description of the resource
 *
 * Localize text fields
 *
 * The display name of the resource
 *
 * The readme file name of the resource
 */
export interface ILocalizedText {
    /**
     * The default text
     */
    readonly default: string;
    /**
     * The English text
     */
    readonly en_US?: string;
    /**
     * The Traditional Chinese text
     */
    readonly zh_CHT?: string;
    /**
     * The Simplified Chinese text
     */
    readonly zh_CN?: string;
    [property: string]: any;
}

/**
 * The funding of the resource
 */
export interface IFunding {
    /**
     * The custom funding URLs
     */
    readonly custom?: string[];
    /**
     * The GitHub sponsors username, such as https://github.com/sponsors/<username>
     */
    readonly github?: string;
    /**
     * The Open Collective username, such as https://opencollective.com/<username>
     */
    readonly openCollective?: string;
    /**
     * The Patreon username, such as https://www.patreon.com/<username>
     */
    readonly patreon?: string;
}
json5
/**
 * 基础属性
 */
{
    $schema: 'https://json-schema.org/draft/2020-12/schema',
    $id: 'https://github.com/siyuan-community/siyuan-sdk/raw/main/schemas/manifest/base.schema.json5',
    $comment: 'v1.0.1',
    $ref: '#/$defs/root',
    $defs: {
        root: {
            // 社区资源清单文件基本定义
            title: 'IBase',
            description: 'Basic definition of community resource manifest file',
            $ref: '#/$defs/base',
        },
        base: {
            type: 'object',
            additionalProperties: true,
            required: [
                'author',
                'name',
                'url',
                'version',
            ],
            properties: {
                author: {
                    // 作者名
                    type: 'string',
                    description: 'The name of the author',
                },
                description: {
                    // 资源描述
                    description: 'The description of the resource',
                    $ref: '#/$defs/_localized_text_',
                },
                displayName: {
                    // 显示名称
                    description: 'The display name of the resource',
                    $ref: '#/$defs/_localized_text_',
                },
                funding: {
                    // 资助途径
                    type: 'object',
                    title: 'IFunding',
                    description: 'The funding of the resource',

                    additionalProperties: false,
                    required: [],
                    properties: {
                        custom: {
                            // 自定义捐助途径 URL
                            type: 'array',
                            description: 'The custom funding URLs',
                            items: {
                                type: 'string',
                                description: 'The custom funding URL',
                                format: 'uri',
                                examples: [
                                    'https://afdian.net/a/<username>', // 爱发电
                                    'https://ko-fi.com/<username>', // Ko-fi
                                    'https://tidelift.com/subscription/<platform-name>/<package-name>', // Tidelift
                                    'https://funding.communitybridge.org/projects/<project-name>', // Community Bridge
                                    'https://liberapay.com/<username>', // Liberapay
                                    'https://issuehunt.io/r/<username>', // IssueHunt
                                    'https://crowdfunding.lfx.linuxfoundation.org/projects/<project-name>', // LFX Crowdfunding
                                ],
                            },
                        },
                        github: {
                            // GitHub sponsors 用户名
                            type: 'string',
                            description: 'The GitHub sponsors username, such as https://github.com/sponsors/<username>',
                            examples: [
                                '88250',
                            ],
                        },
                        openCollective: {
                            // Open Collective 用户名
                            type: 'string',
                            description: 'The Open Collective username, such as https://opencollective.com/<username>',
                            examples: [
                                'siyuan',
                            ],
                        },
                        patreon: {
                            // Patreon 用户名
                            type: 'string',
                            description: 'The Patreon username, such as https://www.patreon.com/<username>',
                        },
                    },
                },
                keywords: {
                    // 用于搜索的关键词
                    type: 'array',
                    description: 'The keywords of the resource used for search',
                    items: {
                        type: 'string',
                        description: 'The keyword used for search',
                    },
                },
                minAppVersion: {
                    // 兼容的最低思源版本
                    type: 'string',
                    description: 'The minimum version of SiYuan that the resource is compatible with',
                    pattern: '^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$',
                },
                name: {
                    // 资源名称
                    type: 'string',
                    description: 'The name of the resource',
                    pattern: '^[^\\\\/:*?"<>|. ][^\\\\/:*?"<>|]*[^\\\\/:*?"<>|. ]$',
                },
                readme: {
                    // 资源说明文档名称
                    description: 'The readme file name of the resource',
                    $ref: '#/$defs/_localized_text_',
                },
                url: {
                    // 资源仓库地址
                    type: 'string',
                    description: 'The GitHub repository URL of the resource',
                    format: 'uri',
                    examples: [
                        'https://github.com/siyuan-note/icon-sample',
                        'https://github.com/siyuan-note/plugin-sample',
                        'https://github.com/siyuan-note/template-sample',
                        'https://github.com/siyuan-note/theme-sample',
                        'https://github.com/siyuan-note/widget-sample',
                    ],
                },
                version: {
                    // 资源版本号
                    type: 'string',
                    description: 'The version of the resource',
                    // REF: https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string
                    pattern: '^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$',
                },
            },
        },
        _localized_text_: {
            // 本地化文本
            type: 'object',
            title: 'ILocalizedText',
            description: 'Localize text fields',

            additionalProperties: true,
            required: [
                'default',
            ],
            properties: {
                default: {
                    // 默认文本
                    type: 'string',
                    description: 'The default text',
                },
                en_US: {
                    // 英文文本
                    type: 'string',
                    description: 'The English text',
                },
                zh_CHT: {
                    // 繁体中文文本
                    type: 'string',
                    description: 'The Traditional Chinese text',
                },
                zh_CN: {
                    // 简体中文文本
                    type: 'string',
                    description: 'The Simplified Chinese text',
                },
            },
        },
    },
}
json
{
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "$id": "https://github.com/siyuan-community/siyuan-sdk/raw/main/schemas/manifest/base.schema.json",
    "$comment": "v1.0.1",
    "$ref": "#/$defs/root",
    "$defs": {
        "root": {
            "title": "IBase",
            "description": "Basic definition of community resource manifest file",
            "$ref": "#/$defs/base"
        },
        "base": {
            "type": "object",
            "additionalProperties": true,
            "required": [
                "author",
                "name",
                "url",
                "version"
            ],
            "properties": {
                "author": {
                    "type": "string",
                    "description": "The name of the author"
                },
                "description": {
                    "description": "The description of the resource",
                    "$ref": "#/$defs/_localized_text_"
                },
                "displayName": {
                    "description": "The display name of the resource",
                    "$ref": "#/$defs/_localized_text_"
                },
                "funding": {
                    "type": "object",
                    "title": "IFunding",
                    "description": "The funding of the resource",
                    "additionalProperties": false,
                    "required": [],
                    "properties": {
                        "custom": {
                            "type": "array",
                            "description": "The custom funding URLs",
                            "items": {
                                "type": "string",
                                "description": "The custom funding URL",
                                "format": "uri",
                                "examples": [
                                    "https://afdian.net/a/<username>",
                                    "https://ko-fi.com/<username>",
                                    "https://tidelift.com/subscription/<platform-name>/<package-name>",
                                    "https://funding.communitybridge.org/projects/<project-name>",
                                    "https://liberapay.com/<username>",
                                    "https://issuehunt.io/r/<username>",
                                    "https://crowdfunding.lfx.linuxfoundation.org/projects/<project-name>"
                                ]
                            }
                        },
                        "github": {
                            "type": "string",
                            "description": "The GitHub sponsors username, such as https://github.com/sponsors/<username>",
                            "examples": [
                                "88250"
                            ]
                        },
                        "openCollective": {
                            "type": "string",
                            "description": "The Open Collective username, such as https://opencollective.com/<username>",
                            "examples": [
                                "siyuan"
                            ]
                        },
                        "patreon": {
                            "type": "string",
                            "description": "The Patreon username, such as https://www.patreon.com/<username>"
                        }
                    }
                },
                "keywords": {
                    "type": "array",
                    "description": "The keywords of the resource used for search",
                    "items": {
                        "type": "string",
                        "description": "The keyword used for search"
                    }
                },
                "minAppVersion": {
                    "type": "string",
                    "description": "The minimum version of SiYuan that the resource is compatible with",
                    "pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$"
                },
                "name": {
                    "type": "string",
                    "description": "The name of the resource",
                    "pattern": "^[^\\\\/:*?\"<>|. ][^\\\\/:*?\"<>|]*[^\\\\/:*?\"<>|. ]$"
                },
                "readme": {
                    "description": "The readme file name of the resource",
                    "$ref": "#/$defs/_localized_text_"
                },
                "url": {
                    "type": "string",
                    "description": "The GitHub repository URL of the resource",
                    "format": "uri",
                    "examples": [
                        "https://github.com/siyuan-note/icon-sample",
                        "https://github.com/siyuan-note/plugin-sample",
                        "https://github.com/siyuan-note/template-sample",
                        "https://github.com/siyuan-note/theme-sample",
                        "https://github.com/siyuan-note/widget-sample"
                    ]
                },
                "version": {
                    "type": "string",
                    "description": "The version of the resource",
                    "pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$"
                }
            }
        },
        "_localized_text_": {
            "type": "object",
            "title": "ILocalizedText",
            "description": "Localize text fields",
            "additionalProperties": true,
            "required": [
                "default"
            ],
            "properties": {
                "default": {
                    "type": "string",
                    "description": "The default text"
                },
                "en_US": {
                    "type": "string",
                    "description": "The English text"
                },
                "zh_CHT": {
                    "type": "string",
                    "description": "The Traditional Chinese text"
                },
                "zh_CN": {
                    "type": "string",
                    "description": "The Simplified Chinese text"
                }
            }
        }
    }
}
  • 基础字段
    • name: 资源名称,必须全局唯一(集市中不能有同名图标)
    • author: 资源作者名
    • url: 资源 GitHub 仓库 URL
    • version: 资源版本号,建议遵循 semver 规范
    • minAppVersion: 资源兼容的最低思源笔记版本号
    • keywords: 用于在集市中搜索的关键词列表
    • displayName: 资源显示名称,主要用于集市列表中显示,支持多语言
      • default: 默认语言,必须存在
      • zh_CNen_US 等其他语言: 可选,建议至少提供中文和英文
    • description: 资源描述,主要用于资源集市列表中显示,支持多语言
      • default: 默认语言,必须存在
      • zh_CNen_US 等其他语言: 可选,建议至少提供中文和英文
    • readme: 自述文件名,主要用于资源集市详情页中显示,支持多语言
      • default: 默认语言,必须存在
      • zh_CNen_US 等其他语言: 可选,建议至少提供中文和英文
    • funding: 项目赞助渠道
      • openCollective: Open Collective 名称
      • patreon: Patreon 名称
      • github: GitHub 用户名
      • custom: 自定义赞助链接列表

附加字段

以下是各清单文件详细定义说明,不同类型的社区资源的清单文件可能存在一些额外的字段。

说明文件

README 说明文件会被解析为集市中项目的介绍文档。思源支持 i18n 国际化,所以一个项目中可能不止有一个 README 文件,需要配置 json 文件中 readme 字段。

json
"readme": {
    "default": "README.md",
    "zh_CN": "README_zh_CN.md"
},

README 文件中的图片

思源在解析 README 的时候遇到相对链接的图片,不会在本地查找,而是会通过网络访问远程仓库中的图片资源。

由于众所周知的原因, 中国大陆内访问 github 仓库会出现波动情况。所以思源会根据 json 文件 url 配置把本地图片资源解析成 cdn 链接。xx.png 会被处理为 https://cdn.jsdelivr.net/gh/<author>/<repo>/xx.png

所以大部分情况下,我们只需要在 README 里使用相对路径引用图片即可。

不过 jsdeliver cdn 本身也存在波动,你也可以选择在 zh_CN 的文档中使用自建图床的链接地址,来提供更加文档的访问。

需要注意的是,思源的集市里的介绍文档是访问 cdn 托管的网络资源。但是「已下载」当中的介绍文档则是访问本地下载下来的 README.md 文件,所以如果你不是很在乎在集市里的显示的话,还有一种方案, 是把所有的 asset 图片打包到发布包当中,然后指定思源内部网络访问的 uri,这样用户下载了集市中的产品后可以在本地看到完整的介绍文档。

例如以下的 url:

/appearance/themes/<ThemeX>/preview-light.png`

会访问思源工作空间目录下, 主题 ThemeX 的安装路径 /appearance/themes/<ThemeX>/ 下属的图片 preview-light.png

图标图片

图标图片用于在社区资源集市列表与详情页中展示你的项目。

图标图片需要满足如下要求:

  • 文件名称: icon.png
  • 图片格式: image/png
  • 图片尺寸: 160×160 (推荐)

预览图片

预览图片用于在社区资源集市详情页面中展示你的项目。

预览图片需要满足如下定要求:

  • 文件名称: preview.png
  • 图片格式: image/png
  • 图片尺寸: 1024×768 (推荐)

集市详情页

Tips: 一次性制作符合要求尺寸的图片可能比较麻烦,你可以试着分别制作两个 1:1 和 4:3 的图片,然后使用图片编辑软件 (比如 windows 自带的画图) 缩放到指定尺寸。