描述
Loconotion
Loconotion是一个Python脚本,它可以解析一个Notion.so公共页面(以及它的所有子页面),并从中生成一个轻量级的、可定制的静态网站。
为何要如此
Notion是一个网络应用,你可以从内容块中创建你自己的工作空间/个人维基。它使用起来感觉很好,而且结果看起来非常漂亮–开发者做得很好。鉴于它还提供了在网上公开一个页面(及其子页面)的可能性,一些人选择用Notion来管理他们的个人博客、投资组合或某种简单的网站。遗憾的是,Notion不支持自定义域名:你的公共页面被卡在notion.so域名下,在电脑生成的长的URL下。
一些服务,如Super、HostingPotion、HostNotion和Fruition,试图通过依靠使用CloudFlare工作者的黑客入侵来解决这个问题。然而,这种解决方案有一些缺点。
- 不是免费的 -Super、HostingPotion和HostNotion都需要支付月费,因为他们为你管理所有的 “黑客位”;Fruition是开源的,但任何具有相当数量的每日访问量的域名很快就会与CloudFlare的免费层限制发生冲突,并迫使你升级到5美元或更高的计划(另外你需要自己设置Cloudflare)
- 缓慢 –由于页面仍然托管在Notion上,它捆绑了他们所有的分析、编辑/协作javascript、供应商css和更多的臃肿,导致页面的加载速度不完全适合一个简单的博客/网站。在谷歌的PageSpeed Insights上运行的例子页面在移动/桌面上的得分只有24 – 66。
- 丑陋的URLs – 虽然上述服务可以使用自定义域名,但单个页面的URLs却停留在冗长、丑陋、原始的Notion URL上(除了Fruition – 他们想出了自定义URLs,尽管当页面加载时,你总是会看到原始URL闪动)。
Notion免费账户的限制 -最近Notion对其定价模式进行了调整,在免费账户中,公共页面不能被搜索引擎收录(但他们也取消了块数限制,如果你问我,这是一个很好的权衡)。
Loconotion在这方面的做法有点不同。它让Notion渲染页面,然后抓取它并将页面的静态版本保存到磁盘。这提供了以下好处。
- 剥离所有不必要的臃肿,如Notion的分析,供应商的脚本/样式,以及为了实现协作而留下的javascript。
- 缓存所有图片/资产/字体(散列文件名),同时保持链接的完整性。
- 清理页面的URL,如果需要,可以使用自定义的slug。
- 对整个网站或单个页面进行全面的元标签控制。
- 对标题、导航栏、正文和代码块进行细致的自定义Goggle字体控制。
- 让你注入任何自定义样式或脚本,从自定义分析或实时聊天支持到隐藏的加密货币矿工(请不要这么做)。
- 输出静态文件,准备部署在Netlify、GitHub Pages、Vercel、你的Raspberry PI、你用作随机服务器的廉价二手Thinkpad上–你的名字。
其结果是什么?一个更快的,独立的页面版本,保持所有Notion的漂亮的页面布局和眼睛的糖果。作为比较,同样的例子,用Loconotion解析的页面和部署在Netflify的免费层,实现了PageSpeed Insight得分96 – 100!
请记住,由于我们正在有效地解析一个静态版本的页面,与Notion的实时公共页面相比,有一些限制。
- 所有的页面都将在自己的页面中打开,而不是模版(取决于你如何看待它,这可能是一个优点)。
- 数据库将在其初始视图中显示–例如,没有从表格到图库之类的切换视图。
- 所有的编辑功能将被禁用–不能勾选复选框或拖动看板卡片。通常这不是一个问题,因为作为网站的公共页面会锁定更改。
- 动态元素不会自动更新 – 例如,日历不会突出当前日期。
其他一切都应该是好的。Loconotion在客户端重新实现了以下动态元素的逻辑,所以它们仍然可以工作。
- 切换块(也包括嵌套的!)。
- 锚点链接
- 嵌入
- 表上的名称列成为该行的数据库项目的页面链接
除此之外,它还定义了一些额外的CSS规则,以实现整个网站的移动响应性(在某些情况下,看起来甚至比Notion的默认值更好–并不完全是为了移动而思考)。
但是Notion已经有了一个html导出功能?
它有,但我对它的风格不是很满意–页面看起来比在Notion活页上的样子要难看一些。此外,它还不支持上面概述的所有很酷的定制功能
例子
你可以查看一个包含Notion的大部分块/元素的网站实例,它是用Loconotion导出的一个静态网站,并托管在Netlify上:https://loconotion-example.netlify.app/
作为参考,该网站所产生的原始Notion公共页面可以在这里访问。
Installation & Requirements
确保你在你选择的虚拟环境中,然后运行
- poetry install –no-dev 如果你已经安装了Poetry的话
- pip install -r requirements.txt 否则
本脚本使用ChromeDriver来自动运行谷歌浏览器,因此需要安装谷歌浏览器才能工作。
脚本会自动尝试下载并使用适合你的操作系统和Chrome版本的chromedriver发行版。如果这不起作用,请从https://chromedriver.chromium.org/downloads 下载适合你的版本,并在运行时使用-chromedriver参数来指定其路径。
Docker支持
也有一个Docker支持。要建立一个容器并渲染页面,请运行。
# 使用 loconotion 构建容器
$ docker-compose build loconotion
# 运行带有任何参数的loconotion渲染器
$ docker-compose run loconotion PATH_TO_NOTION_FILE [ARGS]
Docker容器是由python:3.8标签构建的,安装了google-chrome-stable和chromedriver。更多信息请见docker/Dockerfile。
简单用法
python loconotion https://www.notion.so/The-perfect-It-s-Always-Sunny-in-Philadelphia-episode-d08aaec2b24946408e8be0e9f2ae857e
在其最简单的形式中,该脚本接收一个公共Notion.so页面的URL,并根据该页面的标题在dist文件夹中生成网站(上面的例子将在dist\The-perfect-It-s-Always-Sunny-in-Philadelphia\中生成网站)。
高级用法
你可以通过向脚本传递一个.toml配置文件来完全配置Loconotion,以满足你的需求。
python loconotion example/example_site.toml
下面是一个完整的.toml配置文件的样子,同时还有每个参数的解释。
## #Loconotion网站配置文件##。
# 完整的.toml配置示例文件展示了所有Loconotion的可用设置
#请查看https://github.com/toml-lang/toml,了解更多关于toml格式的信息。
# 网站将被生成的文件夹的名称
name = “Notion Test Site”
# 正在解析的 notion.so 页面。这个页面将成为生成的站点的index.html
# 生成的网站,并且 loconotion 将解析该页面上的所有子页面。
page = “https://www.notion.so/Loconotion-Example-Page-03c403f4fdc94cc1b315b9469a8950ef”
# 可选择应用notion的黑暗模式,删除下面一行以使用默认的明亮模式
theme = “dark”
##全局网站设置 ##
#这个[site]表定义了整个网站的覆盖设置
#稍后我们将看到如何为单个页面定义设置
[site]
## 自定义元标签 ##
#定义为一个表格阵列(双方括号)。
#表中的每个键都对应于标签中的一个属性
# 以下是添加的标签 <meta name=”title” content=”Loconotion Test Site” />
[[site.meta]]
name = “title”
content = “Loconotion Test Site”
[[site.meta]]
name = “description”
content = “A static site generated from a Notion.so page using Loconotion”
##自定义字体 ##
#你可以指定在网站上使用的谷歌字体的名称–使用字体嵌入名称
#如果有疑问,请在fonts.google.com上选择一个样式,然后导航到 “嵌入 “标签,以便
# 检查CSS规则下的名称
# 下面的表格键控制特定元素的字体。
# site: 改变整个页面的字体(除了代码块之外)
# 但下面的设置会覆盖它
# navbar:页面左上方的网站面包屑。
# title:页面标题(在图标下面)。
# h1:标题块,以及内联数据库的标题
# h2:副标题块
# h3:副标题区块
# body:页面上的非标题文本
# 代码:代码块内的文本
[site.fonts]
site = ‘Nunito’
navbar = ”
title = ‘Montserrat’
h1 = ‘Montserrat’
h2 = ‘Montserrat’
h3 = ‘Montserrat’
body = ”
code = ”
## [Custom Element Injection] [自定义元素注入]。
#定义为一个表格数组[[site.inject]],后面有’head’或’body’来设置
# 注入点,然后是要注入的标签的名称
# 表中的每个键都对应于标签中的一个属性
# 例如,以下是对<head>中这个标签的注入。
# <link href=”favicon-16×16.png” rel=”icon” sizes=”16×16″ type=”image/png” />
[[site.inject.head.link]]
rel=”icon”
sizes=”16×16″
type=”image/png”
href=”/example/favicon-16×16.png”
# 以下是在<body>中注入这个标签。
# <script src=”custom-script.js” type=”text/javascript”></script>
# 注意,所有的href/src文件都会被复制到网站的根目录下
# 无论其原始路径如何
[[site.inject.body.script]]
type=”text/javascript”
src=”/example/custom-script.js”
# 以下是在<head>中注入这个脚本。
<script>console.log(“Hello, world!”)</script>。
[[site.inject.body.script]]
inner_html=”””
console.log(“Hello, world!”)
“””
## [Individual Page Settings] [个别页面设置]
# [pages] 表定义了单个页面的覆盖设置,通过定义
#一个以页面url命名的子表(或url的一部分,但要注意
#不要使用一个出现在多个页面url中的字符串)
[pages]
# 以下设置只适用于这个页面。
# https://www.notion.so/d2fa06f244e64f66880bb0491f58223d
[pages.d2fa06f244e64f66880bb0491f58223d]
## 用户 slugs ##
#在页面设置中,你可以用 “slug “键来改变该页面的URL。
#例如,页面”/d2fa06f244e64f66880bb0491f58223d “现在会映射到”/games-list”
#只为这个页面改变描述元标签
[[pages.d2fa06f244e64f66880bb0491f58223d.meta]]
name = “description”
content = “A fullscreen list database page, now with a pretty slug”
#只为这一页改变标题字体
[pages.d2fa06f244e64f66880bb0491f58223d.fonts]
title = ‘DM Mono’
# 为其他的数据库页面设置漂亮的词条和选项
[pages.54dab6011e604430a21dc477cb8e4e3a]
slug = “film-gallery”
[pages.2604ce45890645c79f67d92833083fee]
slug = “books-table”
# 不跟踪页面上的任何链接,跳过解析从这个页面链接的子页面
# 对大型表格很有用,我们不希望每个项目都有单独的页面
no-links = true
[pages.a28dba2e7a67448da52f2cd2c641407b]
slug = “random-board”
no-links = true
在此基础上,该脚本可以接受这些可选参数。
- -h, –help 显示此帮助信息并退出
- –chromedriver CHROMEDRIVER
使用一个特定的chromedriver可执行文件,而不是
自动安装的那个
- –single-page 只解析第一页,然后停止
- –dark-theme 使用目标Notion.so页面的黑暗主题版本动态元素的时间(默认为5)。如果页面上的内容的内容似乎丢失了,请尝试增加这个值
- –timeout TIMEOUT 等待加载lazy-loaded 动态元素的时间(默认为5)。如果页面上的内容 的内容似乎丢失了,请尝试增加这个值
- –clean 在生成网站之前删除所有先前的缓存文件。生成前,删除该网站以前的所有缓存文件。
- –clean-css 在生成前删除网站以前缓存的.css文件
生成前,删除网站以前缓存的.css文件
- –clean-js 在生成前删除网站以前缓存的.js文件。
生成前删除网站以前缓存的js文件
- –non-headless 在非无头模式下运行chromedriver。
- –v, –verbose 增加输出日志的粗略程度