SteamPress 是一个 Swift 博客引擎,可与 Vapor 框架结合使用,将博客部署到运行在 Vapor 之上的网站。它使用 Fluent,因此可以与任何具有 Fluent 驱动程序的数据库一起使用。它还包含一个 Markdown Provider,允许您以 Markdown 格式编写文章,然后使用 Leaf 渲染 Markdown。
该博客既可以用作您网站的根目录(即出现在 https://www.acme.org),也可以用作子路径(即 https://www.acme.org/blog/)。
在 https://github.com/brokenhandsio/SteamPressExample 中,有一个示例展示了它如何在网站中工作(以及它在 Leaf 模板方面需要什么,以及传递给它们的参数)。
SteamPress 很容易与您的应用程序集成。 有两个提供程序为 PostgreSQL 或 MySQL 提供实现。您也可以自由编写自己的集成。通常,您会选择其中一个实现,因为它提供了数据库的存储库集成。在此示例中,我们使用 Postgres。
首先,将提供程序添加到您的 Package.swift
依赖项中
dependencies: [
// ...
.package(name: "SteampressFluentPostgres", url: "https://github.com/brokenhandsio/steampress-fluent-postgres.git", from: "1.0.0"),
],
然后将其作为依赖项添加到您的应用程序目标
.target(name: "App",
dependencies: [
// ...
"SteampressFluentPostgres"
])
在 configure.swift
中,导入提供程序
import SteampressFluentPostgres
接下来,在您的服务中注册提供程序
try services.register(SteamPressFluentPostgresProvider())
提供程序要求您将 SteamPress 的模型添加到您的迁移中
/// Configure migrations
var migrations = MigrationConfig()
// ...
migrations.add(model: BlogTag.self, database: .psql)
migrations.add(model: BlogUser.self, database: .psql)
migrations.add(model: BlogPost.self, database: .psql)
migrations.add(model: BlogPostTagPivot.self, database: .psql)
// Optional but recommended - this will create an admin user for you to login with
migrations.add(migration: BlogAdminUser.self, database: .psql)
services.register(migrations)
首先将 SteamPress 添加到您的 Package.swift
依赖项中
dependencies: [
// ...,
.package(name: "SteamPress", url: "https://github.com/brokenhandsio/SteamPress", from: "1.0.0")
]
然后作为依赖项添加到您的目标中
.target(name: "App",
dependencies: [
// ...
"SteamPress"
])
这将为您注册路由。 您必须为您的服务提供不同存储库类型的实现
services.register(MyTagRepository(), as: BlogTagRepository.self)
services.register(MyUserRepository(), as: BlogUserRepository.self)
services.register(MyPostRepository(), as: BlogPostRepository.self)
然后您可以将 SteamPress 提供程序注册到您的服务中
let steampressProvider = SteamPress.Provider()
try services.register(steampressProvider)
SteamPress 在登录时提供“记住我”功能,以延长会话的持续时间。 为了使它工作,您必须注册中间件
var middlewares = MiddlewareConfig()
// ...
middlewares.use(BlogRememberMeMiddleware.self)
middlewares.use(SessionsMiddleware.self)
services.register(middlewares)
注意: 必须在注册 SessionsMiddleware
之前注册此中间件。
SteamPress 使用 PasswordVerifier
协议来检查密码。 Vapor 没有为此提供默认的 BCrypt 实现,因此您必须自己注册
config.prefer(BCryptDigest.self, for: PasswordVerifier.self)
最后,如果您希望在您的博客 Leaf 模板中使用 #markdown()
标签,您必须注册它。 还有一个分页标签,使分页变得容易
var tags = LeafTagConfig.default()
tags.use(Markdown(), as: "markdown")
let paginatorTag = PaginatorTag(paginationLabel: "Blog Posts")
tags.use(paginatorTag, as: PaginatorTag.name)
services.register(tags)
您可以将许多配置选项传递给提供程序以配置 SteamPress
blogPath
:将博客添加到的路径。 默认情况下,博客路由将注册到您网站的根目录,但您可能希望将博客注册到 /blog
。 因此,如果您传入 "blog"
,则博客将在 https://www.mysite.com/blog
上可用。feedInformation
:提供给 RSS 和 Atom feed 的信息。postsPerPage
:在博客主索引页面上每页显示的帖子数。 默认为 10。enableAuthorsPages
:用于确定是否公开作者端点的标志。 默认为 true。enableTagsPages
:用于确定是否公开标签端点的标志。 默认为 true。要配置这些,您可以将它们传递给提供程序。 例如
let feedInformation = FeedInformation(
title: "The SteamPress Blog",
description: "SteamPress is an open-source blogging engine written for Vapor in Swift",
copyright: "Released under the MIT licence",
imageURL: "https://user-images.githubusercontent.com/9938337/29742058-ed41dcc0-8a6f-11e7-9cfc-680501cdfb97.png")
try services.register(SteamPressFluentPostgresProvider(blogPath: "blog", feedInformation: feedInformation, postsPerPage: 5))
此外,您应该将 WEBSITE_URL
环境变量设置为您网站的根地址,例如 https://www.steampress.io
。 这用于在整个 SteamPress 中设置各种参数。
首次启动 SteamPress 时,如果您启用了 BlogAdminUser
迁移,则会在数据库中创建一个管理员用户。 用户名是 admin
,密码将打印到您应用程序的日志中。 建议您在网站启动并运行后首次登录时立即重置密码。
SteamPress 当前支持使用 Disqus 作为评论引擎。 要使用 Disqus,请启动应用程序,并将环境变量 BLOG_DISQUS_NAME
设置为您的 Disqus 站点的名称。 (您可以从您的 Disqus 管理面板获取您的 Disqus 站点的名称)
这会将其传递给博客索引(blog.leaf
)、博客文章(blogpost.leaf
)、作者页面(profile.leaf
)和标签页面(tag.leaf
)的 Leaf 模板,以便您可以在需要时包含它。 如果您想手动设置评论,您可以自己完成,只需包含您的提供程序所需的文件。 这主要是为 示例网站 提供简单的配置。
SteamPress 支持 Open Graph 和 Twitter Card。 博客文章页面上下文将以 ISO 8601 格式传递创建日期和上次编辑日期(如果适用),以支持 Open Graph 文章,参数为 createdDateNumeric
和 lastEditedDateNumeric
。
博客文章页面还将传递许多其他有用的参数,用于 Open Graph 和 Twitter Card。 请参阅下面的 blogpost.leaf
部分。
站点的 Twitter 句柄可以通过 BLOG_SITE_TWITTER_HANDLE
环境变量进行配置(站点的 Twitter 句柄不带 @
)。 如果设置,这将按照如下所述注入到公共页面中。 这是用于 Twitter Card 的 twitter:site
标签
SteamPress 使您可以轻松地将 Google Analytics 集成到您的博客中。 只需启动应用程序,并将 BLOG_GOOGLE_ANALYTICS_IDENTIFIER
环境变量设置为您的 Google Analytics 标识符。 (您可以从 Google Analytics 控制台获取您的标识符,它看起来类似于 UA-12345678-1)
这会将 googleAnalyticsIdentifier
参数传递给 pageInformation
变量中的所有公共页面,您可以包含它,然后使用 示例网站的 javascript 进行集成。
SteamPress 自动提供用于注册 RSS 阅读器的端点,可以使用 RSS 2.0 或 Atom 1.0。 这些端点可以在博客的 atom.xml
和 rss.xml
路径中找到; 例如,如果您的博客位于 https://www.example.com/blog
,则 atom feed 将显示在 https://wwww.example.com/blog/atom.xml
。 这些默认情况下有效,但您可能需要配置一些字段。 这些字段通过传递给提供程序的 FeedInformation
参数进行配置。 配置选项为
title
- 博客的标题 - 否则将提供默认的“SteamPress Blog”description
- 博客的描述(或 Atom 中的副标题) - 否则将提供默认的“SteamPress 是一个用 Swift 编写的 Vapor 开源博客引擎”copyright
- 添加到 feed 的可选版权信息imageURL
- 添加到 feed 的可选图像/徽标。 请注意,对于 Atom,这应该是一个 2:1 横向缩放图像SteamPress 内置了博客搜索。 它将在您的博客路径下注册一个路由 /search
,您可以通过该路由发送一个查询,使用键 term
来搜索博客。
SteamPress 期望在 Resources/Views
中的正确位置有许多 Leaf 模板文件。 所有这些文件都应该位于 blog
目录中,管理模板文件位于 admin
目录中。 有关 SteamPress 如何与 Leaf 模板配合使用的示例,请参阅 示例 SteamPress 网站。
对于每个公共 Leaf 模板,将传入一个带有以下信息的 pageInformation
参数
disqusName
:站点 Disqus 名称,如上所述siteTwitterHandle
:站点 twitter 句柄,如上所述googleAnalyticsIdentifier
:Google Analytics 标识符,如上所述loggedInUser
:当前登录的用户(如果用户已登录)。 这对于在登录时显示“创建文章”链接等很有用。websiteURL
:网站的 URLcurrentPageURL
:当前页面的 URLcurrentPageEncodedURL
:当前页面的 URL 编码表示对于管理页面,pageInformation
参数具有以下信息
loggedInUser
:当前登录的用户(如果用户已登录)。 这对于在登录时显示“创建文章”链接等很有用。websiteURL
:网站的 URLcurrentPageURL
:当前页面的 URL您的 Resources/View
目录的基本结构应为
blog
blog.leaf
- 主索引页blogpost.leaf
- 单个博客文章的页面tag.leaf
- 标签的页面profile.leaf
- 用户配置文件的页面tags.leaf
- 用于显示所有标签的页面authors.leaf
- 用于显示所有作者的页面search.leaf
- 用于显示搜索结果的页面admin
createPost.leaf
- 用于创建和编辑博客文章的页面createUser.leaf
- 用于创建和编辑用户的页面index.leaf
- 管理站点的索引页login.leaf
- 管理站点的登录页resetPassword.leaf
- 用于重置密码的页面这是博客的索引页。 它将收到的参数是
posts
- 包含 ViewBlogPost
的数组。 这包含所有文章信息和有用的额外内容,例如其他日期格式和摘要。tags
- 如果有任何 ViewBlogTag
的数组authors
- 如果有任何作者的数组pageInformation
- 常规页面信息(见上文)title
- 页面的标题blogIndexPage
- 一个布尔值,表示我们位于博客的索引页上 - 用于导航栏paginationTagInformation
- 用于在页面上启用分页的信息。 有关更多详细信息,请参阅 PaginationTagInformation
。这是用于查看单个完整博客文章的页面。 设置的参数为
title
- 博客文章的标题post
- 作为 ViewBlogPost
的博客文章author
- 文章的作者blogPostPage
- 一个布尔值,表示我们位于博客文章页面上pageInformation
- 常规页面信息(见上文)postImage
- 如果存在,则博客文章中的第一个图像。 用于 OpenGraph 和 Twitter CardpostImageAlt
- 如果存在,则第一个图像的 alt 文本。 用于 Twitter CardshortSnippet
:文章短摘要的 HTML,位于一行上,并剥离所有 HTML 标签以用于 description
标签这是标签页面。一篇博客文章可以标记多个标签,一个标签也可以被标记在多篇博客文章上。此页面通常用于查看该标签下的所有文章。参数如下:
tag
- 标签posts
- 包含此标签的 ViewBlogPost
对象数组。请注意,由于分页,这可能不是全部文章。tagPage
- 一个布尔值,表示我们是否在标签页面上。postCount
- 具有此标签的文章总数。pageInformation
- 常规页面信息(见上文)paginationTagInformation
- 用于在页面上启用分页的信息。 有关更多详细信息,请参阅 PaginationTagInformation
。这是用户个人资料页面。通常用于查看用户撰写的所有文章以及关于用户的一些信息。可以设置的参数如下:
author
- 页面所属的用户posts
- 由该用户撰写的 ViewBlogPost
对象数组。请注意,由于分页,这可能不是全部文章。profilePage
- 一个布尔值,如果我们在查看个人资料页面,则设置为 true。myProfile
- 如果当前登录的用户正在查看他们自己的个人资料页面,则设置为 true 的布尔值。postCount
- 具有此标签的文章总数。pageInformation
- 常规页面信息(见上文)paginationTagInformation
- 用于在页面上启用分页的信息。 有关更多详细信息,请参阅 PaginationTagInformation
。这是用于查看博客上所有标签的页面。它为博客提供更多导航点,并且在用户从标签的 URL 中删除标签时提供一个页面。可以传递给它的参数是:
title
- 页面的标题tags
- BlogTagWithPostCount
对象数组。这是标签以及标记了该标签的文章数量。pageInformation
- 常规页面信息(见上文)这是用于查看博客上所有作者的页面。它为用户提供了一个有用的页面,可以查看所有为该站点做出贡献的人员。
authors
- 博客上所有 ViewBlogAuthor
对象数组pageInformation
- 常规页面信息(见上文)这是将显示搜索结果的页面。除了标准参数之外,它还有许多参数:
title
- 页面的标题searchTerm
- 如果提供了搜索词totalResults
- 从搜索返回的结果数posts
- 搜索返回的 ViewBlogPost
对象数组。请注意,由于分页,这可能不是全部文章。pageInformation
- 常规页面信息(见上文)paginationTagInformation
- 用于在页面上启用分页的信息。 有关更多详细信息,请参阅 PaginationTagInformation
。这是用于登录到博客管理部分的页面。参数如下:
title
- 页面的标题errors
- 如果登录时出现任何错误,则为错误消息数组loginWarning
- 如果用户尝试访问受保护的页面并被重定向到登录页面,则设置此标志username
- 最初提交登录表单时提供的用户名(如果有)(有助于预先填充表单)usernameError
- 如果用户名有问题,则设置为 true 的布尔值passwordError
- 如果密码出现错误,则设置为 true 的布尔值(请注意,出于安全原因,如果出现错误,我们不会将任何提交的密码传递回任何页面)rememberMe
- 如果选中了“记住我”复选框并且出现错误,则设置,有助于预先填充pageInformation
- 常规页面信息(见上文)这是博客的主要管理页面,您可以在其中创建和编辑用户和文章。此页面的参数是:
users
- 网站的所有用户publishedPosts
- 所有已发布的文章(如果有),作为 ViewBlogPostWithoutTags
draftPosts
- 所有已保存但未发布的草稿文章(如果有),作为 ViewBlogPostWithoutTags
errors
- 尝试删除文章或用户时发生的任何错误消息(例如,尝试删除您自己或最后一个用户)blogAdminPage
- 设置为 true 的布尔值,有助于导航title
- 页面的标题pageInformation
- 常规页面信息,作为 BlogAdminPageInformation
- 请参见上文如果您需要重置密码,将被重定向到此页面。参数如下:
errors
- 如果重置密码时出现任何错误,则为错误数组passwordError
- 如果密码出现错误(例如,为空),则设置为 true 的布尔值confirmPasswordError
- 如果密码确认出现错误(例如,为空),则设置为 true 的布尔值pageInformation
- 常规页面信息,作为 BlogAdminPageInformation
- 请参见上文这是用于创建新博客文章或编辑现有博客文章的页面。此页面的参数是:
title
- 页面的标题editing
- 如果我们当前正在编辑博客文章而不是创建新文章,则设置为 true 的布尔值post
- 我们当前正在编辑的文章对象draft
- 在文章保存为草稿时设置的标志errors
- 如果创建或编辑博客文章时出现任何错误,则为错误消息数组titleSupplied
- 要编辑的博客文章的标题,或创建失败的文章的标题contentsSupplied
- 要编辑的博客文章的内容,或创建失败的文章的内容tagsSupplied
- 为博客文章指定的所有标签数组slugURLSupplied
- 要编辑的博客文章的 Slug URL,或创建失败的文章的 Slug URLtitleError
- 如果标题出现错误,则设置为 true 的布尔值contentsError
- 如果博客内容出现错误,则设置为 true 的布尔值 let postPathPrefix: StringpostPathPrefix
- 将要创建或我们正在编辑的文章页面的路径pageInformation
- 常规页面信息,作为 BlogAdminPageInformation
- 请参见上文这是用于创建新用户或编辑现有用户的页面。参数如下:
title
- 页面的标题editing
- 如果我们正在编辑用户,则设置为 true 的布尔值errors
- 如果编辑或创建用户时出现任何错误,则为错误消息数组nameSupplied
- 我们正在编辑的用户名称或创建失败的用户名称nameError
- 如果名称出现错误,则设置为 true 的布尔值usernameSupplied
- 我们正在编辑的用户用户名或创建失败的用户名usernameError
- 如果用户名出现错误,则设置为 true 的布尔值passwordError
- 如果密码出现错误,则设置为 true 的布尔值confirmPasswordError
- 如果密码确认出现错误,则设置为 true 的布尔值resetPasswordOnLoginSupplied
- 如果编辑/创建提交要求在下次登录时重置用户密码,则设置为 true 的布尔值(仅在错误中提供,因此您可以预先填充表单以供用户更正,而不会丢失任何信息)userID
- 如果我们正在编辑用户,则这是用户的 ID。这允许您将编辑用户 POST
发送回正确的路由twitterHandleSupplied
- 我们正在编辑的用户 Twitter handle 或创建失败的 Twitter handleprofilePictureSupplied
- 我们正在编辑的用户个人资料图片 URL 或创建失败的个人资料图片 URLbiographySupplied
- 我们正在编辑的用户的个人简介或创建失败的个人简介taglineSupplied
- 我们正在编辑的用户的标语或创建失败的标语pageInformation
- 常规页面信息,作为 BlogAdminPageInformation
- 请参见上文管理站点有许多 POST
路由用于创建和编辑用户等,否则您将收到错误。
本节需要填写,但您可以查看代码中的控制器以了解它们应该是什么,或参阅 示例站点。
Markdown 标签允许您在 Leaf 文件中将 Markdown 呈现为 HTML。 要使用,只需简单地使用
#markdown(myObject.markdownContent)
这将把对象 myObject
的 markdownContent
转换为 HTML(您将 myObject
作为参数传递给您的 Leaf 视图)。 它在底层使用 Github Flavoured Markdown,但有关更多详细信息,请参见 Leaf Markdown repo。
SteamPress 还包含一个 API,用于访问某些可能有用的内容。 当前端点为:
/<blog-path>/api/tags/
- 以 JSON 格式返回所有已保存的标签