为 Notion 公开网页免费自定义域名

同步来源:树洞剪藏 源站剪藏 ID:570 原文地址:https://www.ppanda.com/posts/tech/notion%E8%87%AA%E5%AE%9A%E4%B9%89%E5%9F%9F%E5%90%8D/
为 Notion 公开网页免费自定义域名
黑夜给了我黑色的眼睛,我却用它戴黑框眼镜
🏠 首页 • 🗃 归档 • 📖 读书破万卷 • 🐼 关于
为 Notion 公开网页免费自定义域名
Posted on
2024-12-09
网络技术
cloudflare
| 共 2510 字,阅读约 6 分钟 ,浏览了 次
0
上次搞了个 微信读书笔记自动同步到 Notion ,现在我已经把读书笔记的内容都迁移到 Notion上了 微信读书笔记 。
如果直接使用 Notion,生成的公开地址就是 Notion 自己的服务器,比如: 微信读书笔记 https://zhuxiaojian.notion.site/80580de1183c45ecb8efc8b2eabee30a ,这样的地址显然不够美观,而且别人看到这个地址也不一定愿意点进去。
于是根据网上的方案,我也改造成了 https://weread.ppanda.com/ 的方式。
具体方案如下,原文来自于 免费为Notion绑定域名 ,这里只是搬运留存。
域名注册
可以选择在腾讯云或者阿里云上或者其他平台上购买域名。
腾讯云购买地址:https://buy.cloud.tencent.com/domain/。
阿里云购买地址:https://wanwang.aliyun.com/
修改DNS信息
注册cloudflare: https://dash.cloudflare.com/ ,登录成功之后添加点击添加域。
输入我们购买的域名,然后点击继续。
进入下一个页面,选择免费计划。这里免费计划在最下面,如果屏幕小的可能会看不到。
然后点击继续,会看到我们需要配置的DNS服务器。
打开购买域名的网站,将你购买的域名的DNS修改为cloudflare的DNS服务器。
腾讯云修改DNS教程:https://cloud.tencent.com/document/product/302/5518#id.3Aserveraddress 阿里云修改DNS教程:https://help.aliyun.com/zh/dws/user-guide/change-dns-servers-for-a-domain-name#6a5c8962350ho
生成代码
打开网站:https://site.notionhub.app/
输入我们的域名和要绑定域名的Notion链接,请确保你的Notion已经发布到网络上。
如果你需要配置多个页面,比如https://malinkang.com/book,https://malinkang.com/podcast这种,点击 ADD A PRETTY LINK 添加对应的路径和NOTION链接即可。
最后可以点击 TOGGLE STYLE AND SCRIPT SETTINGS 来设置网站标题描述和字体。
全部设置完成点击复制代码。
配置Cloudflare Worker
打开Cloudflare:https://dash.cloudflare.com/,选中Workers和Pages,然后点击创建按钮
输入名字,然后点击部署
点击编辑代码
将我们上一步生成的代码,粘贴到箭头所指的地方,然后点击部署。部署完成后点返回按钮返回。
选中设置->域和路由,点击添加,输入我们的域名然后点击添加域即可。
这里贴一下我生成后的代码
/* CONFIGURATION STARTS HERE */
/* Step 1: enter your domain name like fruitionsite.com */ const MY_DOMAIN = 'weread.ppanda.com' ;
/*
- Step 2: enter your URL slug to page ID mapping
- The key on the left is the slug (without the slash)
- The value on the right is the Notion page ID */ const SLUG_TO_PAGE = { '' : '80580de1183c45ecb8efc8b2eabee30a' , };
/* Step 3: enter your page title and description for SEO purposes */ const PAGE_TITLE = '朱小贱的读书笔记' ; const PAGE_DESCRIPTION = '朱小贱的读书笔记' ;
/* Step 4: enter a Google Font name, you can choose from https://fonts.google.com */ const GOOGLE_FONT = '' ;
/* Step 5: enter any custom scripts you'd like */
const CUSTOM_SCRIPT = 朱小贱的读书笔记 ;
/* CONFIGURATION ENDS HERE */
const PAGE_TO_SLUG = {}; const slugs = []; const pages = []; Object .keys(SLUG_TO_PAGE).forEach(slug => { const page = SLUG_TO_PAGE[slug]; slugs.push(slug); pages.push(page); PAGE_TO_SLUG[page] = slug; });
addEventListener( 'fetch' , event => { event.respondWith(fetchAndApply(event.request)); });
function generateSitemap() { let sitemap = '' ; slugs.forEach( (slug) => (sitemap += 'https://' + MY_DOMAIN + '/' + slug + '' ) ); sitemap += '' ; return sitemap; }
const corsHeaders = { 'Access-Control-Allow-Origin' : '*' , 'Access-Control-Allow-Methods' : 'GET, HEAD, POST, PUT, OPTIONS' , 'Access-Control-Allow-Headers' : 'Content-Type' , };
function handleOptions(request) { if (request.headers.get( 'Origin' ) !== null && request.headers.get( 'Access-Control-Request-Method' ) !== null && request.headers.get( 'Access-Control-Request-Headers' ) !== null ) { // Handle CORS pre-flight request. return new Response( null , { headers : corsHeaders }); } else { // Handle standard OPTIONS request. return new Response( null , { headers : { 'Allow' : 'GET, HEAD, POST, PUT, OPTIONS' , } }); } }
async function fetchAndApply(request) { if (request.method === 'OPTIONS' ) { return handleOptions(request); } let url = new URL(request.url); url.hostname = 'www.notion.so' ; if (url.pathname === '/robots.txt' ) { return new Response( 'Sitemap: https://' + MY_DOMAIN + '/sitemap.xml' ); } if (url.pathname === '/sitemap.xml' ) { let response = new Response(generateSitemap()); response.headers.set( 'content-type' , 'application/xml' ); return response; } let response; if (url.pathname.startsWith( '/app' ) && url.pathname.endsWith( 'js' )) { response = await fetch(url.toString()); let body = await response.text(); response = new Response(body.replace( /www.notion.so/g , MY_DOMAIN).replace( /notion.so/g , MY_DOMAIN), response); response.headers.set( 'Content-Type' , 'application/x-javascript' ); return response; } else if ((url.pathname.startsWith( '/api' ))) { // Forward API response = await fetch(url.toString(), { body : url.pathname.startsWith( '/api/v3/getPublicPageData' ) ? null : request.body, headers : { 'content-type' : 'application/json;charset=UTF-8' , 'user-agent' : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36' }, method : 'POST' , }); response = new Response(response.body, response); response.headers.set( 'Access-Control-Allow-Origin' , '*' ); return response; } else if (url.pathname.endsWith( ".js" )){ response = await fetch(url.toString()); let body = await response.text(); response = new Response( body, response ); response.headers.set( "Content-Type" , "application/x-javascript" ); return response; } else if (slugs.indexOf(url.pathname.slice( 1 )) > - 1 ) { const pageId = SLUG_TO_PAGE[url.pathname.slice( 1 )]; return Response.redirect( 'https://' + MY_DOMAIN + '/' + pageId, 301 ); } else { response = await fetch(url.toString(), { body : request.body, headers : request.headers, method : request.method, }); response = new Response(response.body, response); response.headers. delete ( 'Content-Security-Policy' ); response.headers. delete ( 'X-Content-Security-Policy' ); }
return appendJavascript(response, SLUG_TO_PAGE); }
class MetaRewriter { element(element) { if (PAGE_TITLE !== '' ) { if (element.getAttribute( 'property' ) === 'og:title' || element.getAttribute( 'name' ) === 'twitter:title' ) { element.setAttribute( 'content' , PAGE_TITLE); } if (element.tagName === 'title' ) { element.setInnerContent(PAGE_TITLE); } } if (PAGE_DESCRIPTION !== '' ) { if (element.getAttribute( 'name' ) === 'description' || element.getAttribute( 'property' ) === 'og:description' || element.getAttribute( 'name' ) === 'twitter:description' ) { element.setAttribute( 'content' , PAGE_DESCRIPTION); } } if (element.getAttribute( 'property' ) === 'og:url' || element.getAttribute( 'name' ) === 'twitter:url' ) { element.setAttribute( 'content' , MY_DOMAIN); } if (element.getAttribute( 'name' ) === 'apple-itunes-app' ) { element.remove(); } } }
class HeadRewriter { element(element) { if (GOOGLE_FONT !== '' ) { element.append( `
html : true }); } element.append( ` div.notion-topbar > div > div:nth-child(3) { display: none !important; } div.notion-topbar > div > div:nth-child(4) { display: none !important; } div.notion-topbar > div > div:nth-child(5) { display: none !important; } div.notion-topbar > div > div:nth-child(6) { display: none !important; } div.notion-topbar > div > div:nth-child(7) { display: none !important; } div.notion-topbar-mobile > div:nth-child(3) { display: none !important; } div.notion-topbar-mobile > div:nth-child(4) { display: none !important; } div.notion-topbar > div > div:nth-child(1n).toggle-mode { display: block !important; } div.notion-topbar-mobile > div:nth-child(1n).toggle-mode { display: block !important; }
html : true }) } }
class BodyRewriter { constructor(SLUG_TO_PAGE) { this .SLUG_TO_PAGE = SLUG_TO_PAGE; } element(element) { element.append( `Powered by Fruition
html : true }); } }
async function appendJavascript(res, SLUG_TO_PAGE) { return new HTMLRewriter() .on( 'title' , new MetaRewriter()) .on( 'meta' , new MetaRewriter()) .on( 'head' , new HeadRewriter()) .on( 'body' , new BodyRewriter(SLUG_TO_PAGE)) .transform(res); }
原理是用当前域名替换了真实的 notion api 服务,效果还不错。
📝 评论
评论区加载中,请稍等
« Prev
Next »
相关页面
Mac mini 利用 ClashX Pro 开启网关模式
Cloudflare Workers 生成占位图服务
年度总结-词云版
为 Notion 公开网页免费自定义域名
域名注册
修改DNS信息
生成代码
配置Cloudflare Worker
• 探索世界的好奇心万岁 •
访问量 次 • 访客数 次