sgkirby / micropublisher
为 Kirby3 设计的可适应的 Micropub 端点
Requires
- firebase/php-jwt: ^5.2
- getkirby/composer-installer: ^1.1
- pixel418/markdownify: ^2.3
This package is auto-updated.
Last update: 2024-09-04 15:43:52 UTC
README
⚠ 此插件处于永久测试版状态,不定期维护;作为一个个人项目,它会随着我的个人需求而变化和发展。我仅仅在这里发布它,以供 Indieweb 社区使用。欢迎您对其进行尝试(使用 Kirby Starterkit 可以轻松开始)并报告任何问题或观察结果,但我不保证提供任何支持。
Kirby3 Micropublisher
概述
为 Kirby3 设计的可适应和可扩展的 Micropub 服务器。
安装
Composer
composer require sgkirby/micropublisher
Git 子模块
git submodule add https://github.com/sebastiangreger/kirby3-micropublisher.git site/plugins/kirby3-micropublisher
下载
下载并将此存储库复制到 /site/plugins/kirby3-micropublisher。
设置
注意。此插件不执行以下步骤将无法正常工作。
1. 设置 IndieAuth
由于 Micropub 使用基于 OAuth 的 IndieAuth 协议进行用户识别,因此除非您的站点已经设置以支持 IndieAuth,否则此插件将无法正常工作。除非您的站点已经设置好 IndieAuth,否则请遵循此 Cookbook 烹饪配方 进行第三方身份验证或使用 kirby3-selfauth 插件 创建完全自托管的 IndieAuth 端点。
IndieAuth 设置页面提供了一个用于测试设置的工具。在 IndieAuth.com 上使用您的站点 URL 成功登录是 Micropub 和此插件正常工作的前提条件。
2. 设置令牌密钥
除了 IndieAuth 身份验证之外,Micropub 工作流程还需要一个所谓的“令牌端点”;它负责为经过身份验证的用户设置允许的操作范围。令牌端点由插件内置,但在 site/config/config.php 中需要设置一个唯一的密钥 - 这必须是一个至少 10 个字符的随机字母数字字符串。
'sgkirby.micropublisher.jwtkey' => '<YOUR-KEY-STRING>',
3. 在模板中链接您的 Micropub 端点
Micropub 软件客户端从您的 HTML 元信息中查找端点的地址。请将以下内容添加到您的 HTML 模板中的 <head> 部分
<?php micropublisherEndpoints() ?>
这会生成所需的标签,以告知 Micropub 客户端如何访问您的服务器
<link rel="token_endpoint" href="https://<SITE-URL>/tokens" /> <link rel="micropub" href="https://<SITE-URL>/micropub" />
注意。在继续之前以及在任何更改配置之后,请记得清空任何服务器端缓存。
4. 设置您的个别处理规则
插件的默认设置与 Kirby Starterkit 一致。对于任何其他设置,可能需要进一步配置;请参阅下面的 配置 部分。
使用
在完成所有三个设置步骤之后,您的站点即可接收来自 Micropub 客户端的内容。
启动 Micropub 客户端,例如 Quill,进行第一步,并通过提供您网站的网址进行登录。客户端将引导您完成 IndieAuth 授权流程。请确保授予应用程序至少“创建”权限 - 否则,它将无法在您的网站上发布。将您的帖子文本输入到客户端中,并选择“发布”。您的帖子应在网站上创建,并自动跳转到已发布帖子的网址。
Indieweb.org 有一个 Micropub 客户端列表。此插件已针对以下客户端进行核心兼容性测试(尽管可能不支持每个客户端的所有功能)
- 浏览器中的 Quill
- 智能手机上的 Indigenous for Android
- Linux 命令行上的 shpub
配置
Micropub 的目的是通过标准化的协议统一向网站发布内容的体验,使用户能够自由选择创建内容的工具。由于没有两个网站是完全相同的,这在服务器端不可避免地需要设置需求 - 虽然从 Micropub 客户端发送的传入内容遵循指定的语法,但像 Kirby 这样的灵活 CMS 意味着无法普遍预配置如何存储内容(除非使用 Starterkit,插件默认设置与此相对应)。
为了确保最佳效用,Micropublisher 插件被设计为高度可配置。这使得它非常灵活,但需要仔细设置。
在设置期间,强烈推荐使用 https://micropub.rocks 上的测试套件。除了提供一种简单测试您实现的方法外,它还会显示服务器响应,在出现错误时可能有助于跟踪问题(激活 Kirby 的 调试模式 非常有帮助)。插件在 site/logs/micropublisher/micropub.log 中的日志文件进一步有助于评估后台的数据流 - 它始终包含最后接收到的 Micropub 内容的完整协议。
选项
您可以通过向您的 site/config/config.php 中添加设置来配置此插件(除非您运行基于 Starterkit 的无插件网站,否则您将必须这样做)。
令牌密钥
内置的令牌端点需要唯一密钥来签署权限令牌 - 这必须是至少 10 个字符的随机字母数字字符串
'sgkirby.micropublisher.jwtkey' => '<YOUR-KEY-STRING>',
注意。以后更改此令牌将使现有的登录无效。
默认值
通过特定的规则集,您可以为 Micropub 端点定义的每种类型的帖子设置不同的模板、页面状态、父页面和 slug 设计。然而,默认值被定义为回退,并且可能需要调整。通过将这些设置为网站上最常用的值,您可以减少以后需要定义的特定规则复杂性;实际上,如果您不需要支持多个格式,您可能只需使用默认设置即可。
默认模板
默认情况下,新帖子使用 Kirby 模板 note 创建(即生成的文本文件为 note.txt;这源于 Starterkit 主题)。如果您的网站使用不同的模板发布帖子,例如 post,请添加以下设置
'sgkirby.micropublisher.default.template' => 'post',
默认状态
由于Micropub的理念是快速发布,通过Micropub端点创建的帖子默认创建为listed(即发布并在您的Kirby网站上列出)。如果您想将默认值更改为创建所有帖子为未发布的草稿,请添加以下行(可能的值有listed、unlisted和draft)
sgkirby.micropublisher.default.status' => 'draft',
默认父级
每个网站的结构都不同。遵循Starterkit的层次结构,默认将新帖子创建为“笔记”页面的子页面。您可能需要更改这一点(注意,当向不存在的父级发布时,插件会抛出错误)。为此,输入页面ID(例如blog或blog/notes)作为设置
sgkirby.micropublisher.default.parent' => 'blog',
默认别名
URL别名默认由提交的别名属性创建;作为最后的手段,使用纪元时间戳。此默认行为可以全局更改。以下示例将默认设置数组添加到配置中(有关语法和如何构建更复杂的别名规则集的详细说明,请参阅以下帖子类型字段定义中的内容,它使用相同的语法)
'sgkirby.micropublisher.default.slug' => 'slug',
默认渲染规则
将Micropub客户端的数据属性转换到Kirby页面字段称为“渲染规则”。语法在以下解释了用于定义特定帖子类型的规则,但在只有一个支持的帖子格式的简单设置中,可能足以调整插件默认的渲染规则集。以下示例定义了一个与Starterkit内置规则相对应的默认规则集
'sgkirby.micropublisher.default.render' => [ 'name' => [ 'title', 'No title' ], 'content' => [ 'text', '' ], 'category' => [ 'tags', null ], 'published' => [ 'date', strftime( '%F %T' ), 'datetime' ], ],
此示例将Micropub的name属性转换为一个假定的Kirby页面字段title,并使用“无标题”作为后备,将来自content属性的内容存储在字段text中,将客户端提交的任何“分类”存储在tags字段中,并将published属性或当前时间戳存储在页面字段date中。
注意。尽管Micropub有效载荷中的Microformat属性由标准定义,但Kirby页面字段名称和数据格式取决于所使用的蓝图。
帖子类型
这是Micropublisher插件最重要的、最强大(并且首先承认,也是最令人生畏)的设置。它使您可以精细控制内容创建。
“帖子类型”是您网站上内容的表示;例如,您可能有一个“文章”帖子类型用于长篇博客帖子,“笔记”用于微博,“checkin”用于发布位置。帖子类型通常通过使用的模板、蓝图字段、文件附件等不同。
从字面上讲,这个数组结构充当一个“翻译器”,它解释传入的Micropub请求(它是Microformats中的内容表示)并组装成Kirby页面(一个字段数组,从中创建新页面)。
以下示例中的每个方面都将用相应的索引号(*1等)进行解释。大多数字段都是可选的(回退到插件中固化的默认值或使用上述设置进行调整),但Micropub端点如果每个帖子类型下没有至少一个设置在fields下,将返回错误。
'sgkirby.micropublisher.posttypes' => [ // internal name of post type (unique) *1 'note' => [ // human-readable name (optional) *2 'name' => 'Note', // Kirby template name (optional) *3 'template' => 'note', // status of the newly created post (optional) *4 'status' => 'listed', // the parent page for new posts of this type (optional) *5 'parent' => 'notes', // the rules to identify incoming posts of this type (optional) *6 'identify' => [ 'unique' => null, 'has' => [ 'content' ], 'hasnot' => null, ], // the rendering rules for this post type *7 'render' => [ 'name' => [ 'title', 'No title' ], 'content' => [ 'text', '', function( $value, $fieldname, $default ) { return $value } ], 'category' => [ 'tags' ], 'published' => [ 'date', strftime( '%F %T' ), 'datetime' ], 'checkin' => [ 'checkin', null, 'yaml' ], ], // handling of uploaded media files (optional) *8 'files' => [ 'photo' => [ 'image', true, false ], ], // slug building rules (optional) *9 'slug' => [ 'slug', 'title', [ 'text', 30 ] ], // target language (optional) *10 'language' => 'en', ], ],
1. 内部名称(唯一)
这必须是一个唯一的名称,不允许有空格或特殊字符;所有字符都建议小写。
2. 名称(可选)
一些Micropub客户端检索支持帖子类型的列表,并在UI中以选择菜单的形式显示它们。因此,每个帖子类型都应该有一个可读的名称。这可以是客户端UI中您认为有意义的任何内容,因为它在程序上不被使用。
如果没有提供名称,则使用上述第1点中的内部名称。
3. Kirby模板名称(可选)
对于每种帖子类型,您可以指定要使用的Kirby内容模板,以覆盖任何全局默认值。
如果没有指定模板名称,将使用全局默认模板('note'),或者如果已定义,则使用从config.php中定义的全局设置sgkirby.micropublisher.default.template。
4. 页面状态(可选)
此设置允许对特定帖子类型的新内容是创建为草稿还是已发布帖子进行细致的控制(可能的值是Kirby的draft、unlisted或listed)。有两种不同的模式可供选择。
允许客户端覆盖
一些Micropub客户端支持设置每个帖子的post-status属性以进行逐帖子控制。由于此属性只了解两种状态(“publish”和“draft”),因此需要将帖子类型数组中的状态属性设置为数组;其第一个值对应于用户选择的“published”(也是如果Micropub客户端未提交此字段时的回退),而第二个值是如果客户端提交了post-status=draft属性,则赋予该帖子的状态。
以下示例将此类型的帖子默认视为listed,但如果在Micropub客户端中选中并传输,则视为draft。
'status' => ['listed', 'draft'],
上述示例也是插件默认设置,如果没有在帖子类型定义中指定status属性;此默认设置可以通过config.php中的全局设置sgkirby.micropublisher.default.status进行更改。
强制状态
仅提供一个字符串作为status属性时,任何此类型的帖子都将强制以该状态发布。这覆盖了Micropub客户端中的用户状态选择以及插件中的所有默认设置。
'status' => 'listed',
5. 父页面(可选)
定义创建此帖子类型新帖子的父页面。这允许为每个帖子类型分别定义特定的“目标”。
如果没有指定父页面,则使用全局默认值('notes'),或者如果已定义,则使用从config.php中定义的全局设置sgkirby.micropublisher.default.parent。
6. 识别规则(可选)
由于Micropub本身没有提供指示不同帖子类型的方法,Micropublisher插件使用一组规则定义 - identify数组,根据Micropub有效负载中提交的Microformat属性来分析和识别要创建哪个帖子类型。
帖子类型按定义数组中出现的顺序处理,并使用满足所有条件的第一个帖子类型。没有或无效的identify数组的类型被视为通配符,用于触发数组中较早的规则未能捕获的任何提交。
如果一个帖子类型结合了多个规则(例如,同时有“has”和“hasnot”规则),则所有条件都必须匹配才能符合此帖子类型。
unique
如果某个Microformat属性的存在唯一表明Micropub帖子为某个帖子类型,则可以在其规则集中将其名称声明为unique。
例如,可以通过声明如果Microformat属性location存在于有效负载中,则使用此帖子类型来检测从传入的Micropub请求中的常见“回复”帖子。
'identify' => [ 'unique' => 'reply-of', ],
注意。unique变量的值是一个字符串
由于unique规则假设唯一条件,因此上述示例将使任何包含位置属性的请求被视为此帖子类型,无论其内容如何。如果多个帖子类型声称相同的Microformat属性作为唯一触发器,则帖子类型数组中的第一个优先。
has/hasnot
has和hasnot值是Microformat属性名称的数组,这有助于进一步检测特定帖子类型。如果请求包含所有声明为“has”的Microformat属性,并且不包含声明为“hasnot”的属性,则认为该帖子类型适用。
例如,一个“checkin”类型的帖子(发布地理位置)可以通过测试Microformat属性content和location的存在来检测,如果已知Micropub客户端始终发送包含GPS坐标和标题字符串的checkins。
'identify' => [ 'has' => ['name', 'location'], ],
这也允许根据附件识别帖子类型:例如,为了定义不匹配包含照片的提交,我们可以定义
'identify' => [ 'hasnot' => ['photo'], ],
注意。对于has和hasnot变量的值是一个字符串数组
7. 渲染规则
数组render中的每个属性代表要从Micropub有效负载中处理的一个值。从发布UI提交的属性取决于客户端和/或帖子类型(例如,一些不太常见的属性包括:摘要、位置、回复、点赞、转发、同步、书签等)。
属性以请求中的microformat属性名称命名;这是要“渲染”的属性。
每个属性的值定义了如何将microformat属性渲染为Kirby页面字段;它是一个包含以下值的数组
- 要将内容存储在此蓝图字段中的蓝图字段名称(字符串);例如,Microformat属性
name的值可能被渲染到名为title的蓝图字段中 - (可选)如果此属性为空(null/字符串),则使用默认字符串;也可以给出一个数组,但将转换为以逗号分隔的字符串
- (可选)对接收到的值进行特殊处理的说明(字符串/函数);在这里,可以给出一个具有预设名称的字符串(目前:'datetime'以返回Kirby格式的日期字符串,'json'将内容转换为JSON字段,或'yaml'将内容转换为YAML结构字段)或匿名回调函数(见下面的示例)。
最小规则
最小要求是将Microformat属性(如Micropub请求中包含的)映射到右边的数组中的Kirby蓝图字段。此规则将简单地保存提交的标签作为category保存到蓝图字段tags中,并将空字符串作为后备值
'render' => [ 'category' => ['tags'],
后备值
此示例将Micropub客户端提交的作为Microformat属性name的值存储到Kirby内容文件的字段title中;如果请求的name值为空,则保存后备字符串“无标题”
'render' => [ 'name' => ['title', 'No title'],
预设:datetime
可能适用于大多数Kirby设置,其中帖子存储创建日期,下一个示例是一个典型情况,其中Micropub和Microformats定义的published值需要存储在名为date的Kirby蓝图字段中(例如,在Starterkit中就是这样)。为了确保始终存储创建日期(即使不是通过Micropub请求提供),默认值被设置为相应的日期/时间字符串。预设datetime作为第三个值触发一个硬编码的例行程序,将几乎任何通过Micropub到达的日期格式转换为Kirby所需的格式 - 否则它将回退到在第二个字段中定义的默认值
'render' => [ 'published' => ['date', strftime('%F %T'), 'datetime'],
注意。published属性通常被Micropub客户端省略(如果缺失,则隐式定义为“现在”),因此仍然为它设置一个渲染规则并将其分配为当前时间作为后备,如果蓝图期望发布日期。
呈现:yaml
某些属性被指定为通过 Micropub 以数据结构的形式发送。例如 "checkins" 或位置数据。除非您希望以更高级的方式处理这些数据(见下文),否则您可以将此类结构存储在 YAML 格式的字段中(使其可以作为面板蓝图中的结构字段进行编辑)。
'render' => [ 'location' => ['checkin', null, 'yaml'],
匿名函数
使用匿名函数作为回调允许对内容进行相当高级的处理。三个(可选)变量是提交字段的值($value)、字段名称($field = 第一个参数)和默认值($default = 第二个参数)。函数可以返回一个字符串,然后将其存储在相应字段的 Kirby 内容文件中,或者返回多个字段值的数组。以下示例中的函数不仅会修改字符串,还会更改标题字段(这里,命令的顺序很重要,因为后来的更改将覆盖早期的更改 - 例如,处理 name 微格式值得到的标题将被函数设置的新值覆盖)。函数必须始终返回一个字符串(然后用作此字段的最终保存值)或一个数组(允许设置要保存的多个字段,包括不在帖子类型字段定义中存在的字段,只要它在 Kirby 蓝图中存在)。
'render' => [ 'content' => ['text', '', function($value, $fieldname, $default) { return [ 'title' => 'Modified', $fieldname => $value . ' and some more text', ]; } ],
对于更高级的功能,可以使用 function($value, $fieldname, $default, $data) {} 调用匿名函数,这将为 $data 提供访问权限,暴露所有通过 Micropub 协议提交的未处理数据(减去一些与认证相关的部分,出于安全考虑)。
8. 接受的文件(可选)
Micropub 规范允许三种类型的文件附件:photo、video 和 audio。此可选设置允许对这些附件进行精细控制。
(可选)的文件变量包含每个 Micropub 附件文件类型的一个数组,包括以下内容:
- 一个字符串,指定上传媒体要存储为的文件蓝图名称(默认为 Micropub 请求的文件类型,即
photo、video或audio) - (可选)一个布尔值,表示是否接受此类型的多个文件(
false限制为每篇帖子只接受一个此类文件) - (仅适用于类型
photo;可选)一个字符串,指定页面蓝图中的字段名称,以将此文件的引用(如果多个,则是第一个)添加到页面数据中;这可以用来保存一张图片作为“封面”图片
要禁止页面类型接受附件类型,可以使用布尔值 false。
例如,限制每篇帖子只能上传一张照片,并使用文件蓝图 image
'files' => [ 'photo' => ['image', false], ],
要仅允许每篇此类帖子上传多张照片,并使用相同的文件蓝图 image,并将对第一张图片的引用添加为字段 cover 到页面数据中
'files' => [ 'photo' => ['image', true, 'cover'], ],
要禁用页面类型的视频和音频上传(照片仍然允许,因为缺失设置数组的默认值为 true)
'files' => [ 'video' => false, 'audio' => false, ],
9. 斜杠设计规则(可选)
对于每个帖子类型,可以定义构建斜杠的单独规则集。它由一个定义规则顺序的数组组成。满足帖子中足够数据的任何规则都被使用。最后的后备(不在规则集中,但硬编码)始终是 UNIX 时间戳。
这是最小定义,等同于硬编码的默认值;它使用由 Micropub 客户端提交的 mp-slug(或已弃用的 slug)属性,如果已提交且不为空。
'slug' => 'slug',
许多用途的共同规则模板是,通过以下顺序补偿缺失/空slug属性:(注意。在这里,必须使用Kirby蓝图中的最终字段名,而不是Micropub请求中的属性名)。以下示例说明了这一点:数组中的三个值按给定顺序处理,并使用第一个规则生成有效的slug - 使用mp-slug属性,将title字段转换为slug,或从text字段的第一个30个字符创建slug
'slug' => ['slug', 'title', ['text', 30]],
如果没有为帖子类型提供slug规则集:如果已定义,则使用config.php中全局定义的规则集sgkirby.micropublisher.default.slug,或全局默认值(即,如果提供了mp-slug属性,则为,否则为epoch时间戳)。
10. 目标语言(可选)
此设置仅适用于多语言网站。
默认情况下,新micropub内容以网站默认语言创建。要覆盖,请提供一个有效的两位字母语言代码,以在特定语言中创建单个帖子类型的内容。
'language' => 'en',
配置客户端UI
micropub客户端可能会查询您的Micropub端点以检索一些设置。如果您想使用标签或分类,并希望它们显示在相应的表单字段中,您可以告诉插件要向客户端传达哪些标签/分类。
目前,这可以通过在config.php中设置一个标签/分类列表来实现(您可以使用一些自定义功能来动态加载此列表)
'sgkirby.micropublisher.categorylist.array' => ['tag1', 'tag2', 'tag3'],
或者,为了向客户端提供现有标签的列表,以下两个配置行指示要轮询以获取现有标签的页面的父级以及要提取的字段名(这期望所有内容文件都是该parent页面的直接子代,并且包含在指示字段中列出的标签)
'sgkirby.micropublisher.categorylist.parent' => 'blog', 'sgkirby.micropublisher.categorylist.taxonomy' => 'tags',
注意。此分类配置选项可能会在即将到来的beta版本中更改。
特定设置
以下是一些可能对大多数用户不相关的特定设置。它们被记录为完整性;如果它们对您没有意义,它们可能是针对您的网站不适用的一些边缘情况。
要更改Micropub端点的URL(默认为https://domain.tld/micropub),请添加以下设置并按需更改字符串
'sgkirby.micropublisher.endpoint' => 'micropub',
某些网站可能使用post.create:after钩子来更改新创建帖子的slug。例如,一个slug为'lorem-ipsum'的帖子可能被存储为'2020-01-lorem-ipsum'。为了避免与现有slug冲突,可以告诉插件在验证其可用性之前向slug添加前缀
'sgkirby.micropublisher.slugprefix' => 'my-prefix-',
...或者,用添加日期的上述示例来说明
'sgkirby.micropublisher.slugprefix' => date('Y') . '-' . date('m') . '-',
待记录
'sgkirby.micropublisher.syndicate-to' => [],
功能
插件功能
以下Micropub功能受支持
- ...
- 将文件上传到Micropub媒体端点
以下Micropub功能目前不在此范围内
- 编辑现有帖子
- 删除帖子
- 源查询
以下Kirby特定功能受支持
- 将传入帖子的HTML转换为Markdown
以下Micropub扩展受支持
- mp-slug(在客户端设置URL slug)
- post-status(在客户端切换草稿/发布)
- 查询支持词汇表
- 查询分类/标签列表
- 媒体端点扩展
要求
Kirby 3.3.2+(https://getkirby.com)
鸣谢
灵感来自
- https://rhiaro.co.uk/2015/04/minimum-viable-micropub
- https://github.com/sebsel/kirby-micropub
- http://p.cweiske.de/363
包含的供应商库
许可
Kirby 3 微出版平台是开源软件,采用MIT 许可协议授权。
版权所有 © 2020 Sebastian Greger
不建议在任何宣传破坏我们地球、种族主义、性别歧视、恐同、动物虐待、暴力或其他任何形式仇恨言论的项目中使用此插件。


