-
-
Save mayneyao/b9fefc9625b76f70488e5d8c2a99315d to your computer and use it in GitHub Desktop.
const MY_DOMAIN = "agodrich.com" | |
const START_PAGE = "https://www.notion.so/gatsby-starter-notion-2c5e3d685aa341088d4cd8daca52fcc2" | |
const DISQUS_SHORTNAME = "agodrich" | |
addEventListener('fetch', event => { | |
event.respondWith(fetchAndApply(event.request)) | |
}) | |
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) | |
let response | |
if (url.pathname.startsWith("/app") && url.pathname.endsWith("js")) { | |
// skip validation in app.js | |
response = await fetch(`https://www.notion.so${url.pathname}`) | |
let body = await response.text() | |
try { | |
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") | |
console.log("get rewrite app.js") | |
} catch (err) { | |
console.log(err) | |
} | |
} else if ((url.pathname.startsWith("/api"))) { | |
// Forward API | |
response = await fetch(`https://www.notion.so${url.pathname}`, { | |
body: request.body, // must match 'Content-Type' header | |
headers: { | |
'content-type': 'application/json;charset=UTF-8', | |
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36' | |
}, | |
method: "POST", // *GET, POST, PUT, DELETE, etc. | |
}) | |
response = new Response(response.body, response) | |
response.headers.set('Access-Control-Allow-Origin', "*") | |
} else if (url.pathname === `/`) { | |
// 301 redrict | |
let pageUrlList = START_PAGE.split("/") | |
let redrictUrl = `https://${MY_DOMAIN}/${pageUrlList[pageUrlList.length - 1]}` | |
return Response.redirect(redrictUrl, 301) | |
} else { | |
response = await fetch(`https://www.notion.so${url.pathname}`, { | |
body: request.body, // must match 'Content-Type' header | |
headers: request.headers, | |
method: request.method, // *GET, POST, PUT, DELETE, etc. | |
}) | |
response = new Response(response.body, response) | |
if (DISQUS_SHORTNAME) { | |
// Delete CSP to load disqus content | |
response.headers.delete("Content-Security-Policy") | |
// add disqus comment component for every notion page | |
return new HTMLRewriter().on('body', new ElementHandler()).transform(response) | |
} | |
} | |
return response | |
} | |
class ElementHandler { | |
element(element) { | |
// An incoming element, such as `div` | |
element.append(` | |
<script> | |
let disqus = document.createElement("div") | |
disqus.id = "disqus_thread" | |
disqus.style.width = "100%" | |
var disqus_config = function () { | |
let pathList = window.location.pathname.split("-") | |
let pageID = pathList[pathList.length - 1] | |
this.page.url = window.location.href; | |
if (/^[\w]{32}$/.test(pageID)) { | |
this.page.identifier = pageID; | |
}else{ | |
this.page.identifier = undefined; | |
} | |
}; | |
(function () { | |
var d = document, s = d.createElement('script'); | |
s.src = 'https://${DISQUS_SHORTNAME}.disqus.com/embed.js'; | |
s.setAttribute('data-timestamp', +new Date()); | |
(d.head || d.body).appendChild(s); | |
})(); | |
// if you want to hide some element, add the selector to hideEle Array | |
const hideEle = [ | |
"#notion-app > div > div.notion-cursor-listener > div > div:nth-child(1) > div.notion-topbar > div > div:nth-child(6)", | |
"#notion-app > div > div.notion-cursor-listener > div > div:nth-child(1) > div.notion-topbar > div > div:nth-child(5)", | |
"#notion-app > div > div.notion-cursor-listener > div > div:nth-child(1) > div.notion-topbar > div > div:nth-child(4)", | |
] | |
// if you want to replace some element, add the selector and innerHTML to replaceEle Object | |
const replaceEle = { | |
"#notion-app > div > div.notion-cursor-listener > div > div:nth-child(1) > div.notion-topbar > div > div:nth-child(6)": "<span>agodrich<span>" | |
} | |
function hideElement(qs) { | |
let eles = document.querySelectorAll(qs) | |
eles && eles.forEach(ele => ele.style.display = "none") | |
} | |
function replaceElement(qs, _html) { | |
let ele = document.querySelector(qs) | |
if (ele) { | |
ele.innerHTML = _html | |
} | |
} | |
let MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver; | |
let body = document.querySelector('body'); | |
let observer = new MutationObserver(function (mutations) { | |
mutations.forEach(function (mutation) { | |
let pageContent = document.querySelector("#notion-app div.notion-page-content") | |
if (pageContent) { | |
if (pageContent.lastChild && pageContent.lastChild.id !== "disqus_thread") { | |
pageContent.append(disqus) | |
DISQUS.reset({ reload: true }) | |
console.log(+new Date()) | |
} | |
} | |
hideEle.forEach( hideE => hideElement(hideE) ) | |
Object.entries(replaceEle).forEach( item => { | |
let [qs,_html] = item; | |
replaceEle(qs,_html) | |
}) | |
}); | |
}); | |
observer.observe(body, { subtree: true, childList: true }); | |
</script> | |
<noscript>Please enable JavaScript to view the <a href="https://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript> | |
`, { html: Boolean }) | |
console.log(`Incoming element: ${element.tagName}`) | |
} | |
comments(comment) { | |
// An incoming comment | |
} | |
text(text) { | |
// An incoming piece of text | |
} | |
} |
Make sure to set both routes "www.yourdomain.com/" and "yourdomain.com/".
you can achieve the same result by having one single rule using an asterisk, like I mentioned in this past comment:
https://gist.github.com/mayneyao/b9fefc9625b76f70488e5d8c2a99315d#gistcomment-3095515
In my case, it didn't work out.
Only after I have separated into two routes, I could get rid of 520 Error. I'm not too sure why.
Yeah with one, did not work for me either, that's why I put two. I never have any other *.mycomain.com case anyways.
Hey, guys! I just moved my 2 domains to Porkbun and my site stopped working! Any ideas why? www.edgaras.com
VM42 0d54f02a6f8941648c9bf2a6c5fd8ba0:64 Uncaught TypeError: replaceEle is not a function
at VM42 0d54f02a6f8941648c9bf2a6c5fd8ba0:64
at Array.forEach (<anonymous>)
at VM42 0d54f02a6f8941648c9bf2a6c5fd8ba0:62
at Array.forEach (<anonymous>)
at MutationObserver.<anonymous> (VM42 0d54f02a6f8941648c9bf2a6c5fd8ba0:52)
Please support disqus loading on demand, thanks
In case someone is facing 4xx errors on their images, you can try appending the query search params on the url on Line 69
Example:
Old
response = await fetch(`https://www.notion.so${url.pathname}`, {
body: request.body, // must match 'Content-Type' header
headers: request.headers,
method: request.method, // *GET, POST, PUT, DELETE, etc.
})
New
response = await fetch(`https://www.notion.so${url.pathname}${url.search}`, {
body: request.body, // must match 'Content-Type' header
headers: request.headers,
method: request.method, // *GET, POST, PUT, DELETE, etc.
})
This was helpful, thanks @naman1-gupta
An alternative is to set url.host = 'www.notion.so
and use url.toString()
for all the URLs. This guarantees not only search params but also fragments are included: https://github.com/stephenou/fruitionsite/blob/master/worker.js#L87
In case someone is facing 4xx errors on their images, you can try appending the query search params on the url on Line 69
Example:
Oldresponse = await fetch(`https://www.notion.so${url.pathname}`, { body: request.body, // must match 'Content-Type' header headers: request.headers, method: request.method, // *GET, POST, PUT, DELETE, etc. })
New
response = await fetch(`https://www.notion.so${url.pathname}${url.search}`, { body: request.body, // must match 'Content-Type' header headers: request.headers, method: request.method, // *GET, POST, PUT, DELETE, etc. })
This really solves the problem that pictures uploaded in notion cannot be opened, thx a lot!
Need working example for subdomain! getting DNS_PROBE_FINISHED_NXDOMAIN
If you are facing issues, you can refer this ->> https://fruitionsite.com/
Hello,
I am facing a problem.
I would like to redirect the domain I have acquired on google domains to a notion page.
I have set up the worker, a A record, and the DNS but somehow it does not redict it.
I have an : ERR_NAME_NOT_RESOLVED error
telling me : impossible to find IP adresse
Do you have any chere it can come from ?
Cheers,
In case someone is facing 4xx errors on their images, you can try appending the query search params on the url on Line 69
Example:
Oldresponse = await fetch(`https://www.notion.so${url.pathname}`, { body: request.body, // must match 'Content-Type' header headers: request.headers, method: request.method, // *GET, POST, PUT, DELETE, etc. })
New
response = await fetch(`https://www.notion.so${url.pathname}${url.search}`, { body: request.body, // must match 'Content-Type' header headers: request.headers, method: request.method, // *GET, POST, PUT, DELETE, etc. })
amazing. thanks
Thanks, perfect work!
Try NotionDog if you have no custom domain and no money. 😉
I believe it's the easiest way to build simple, powerful websites with nothing but Notion.
https://github.com/notiondog/notion.dog
showcases:
Hey there, Really appreciate this script, I am struggling with changing it with how Notion has changed their public site link options. I've used the FruitionSite Script could anyone help with this?
Notion errors out with "Mismatch between origin and baseUrl (dev)." during the worker preview. Any thoughts?
Generate again the worker script from the fruition site and paste into the Cloudflare worker script.
It worked for me.
you can achieve the same result by having one single rule using an asterisk, like I mentioned in this past comment:
https://gist.github.com/mayneyao/b9fefc9625b76f70488e5d8c2a99315d#gistcomment-3095515