Skip to content

Commit

Permalink
feat(pages): make terms page render statically
Browse files Browse the repository at this point in the history
  • Loading branch information
MrOrz committed Jan 16, 2024
1 parent 2b7f44f commit ef6630a
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 78 deletions.
17 changes: 17 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
"js-cookie": "^3.0.1",
"json-url": "^2.6.0",
"lodash": "^4.17.19",
"marked": "^4.1.1",
"next": "^9.3.2",
"next-apollo": "^3.1.5",
"pm2": "^4.2.3",
Expand Down
10 changes: 9 additions & 1 deletion pages/_document.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,15 @@ MyDocument.getInitialProps = async ctx => {
),
});

const initialProps = await Document.getInitialProps(ctx);
let initialProps = {};

try {
initialProps = await Document.getInitialProps(ctx);
} catch (e) {
// May be getInitialProps don't exist, etc.
// Just ignore.
console.error(e);
}

return {
...initialProps,
Expand Down
100 changes: 23 additions & 77 deletions pages/terms.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { useState, useEffect } from 'react';
import fs from 'fs/promises';
import path from 'path';
import { t, jt } from 'ttag';
import Head from 'next/head';

import { marked } from 'marked';
import { styled } from '@material-ui/core/styles';

import AppLayout from 'components/AppLayout';
Expand All @@ -11,31 +14,6 @@ import withData from 'lib/apollo';
const TERMS_REVISIONS_URL =
'https://github.com/cofacts/rumors-site/commits/master/LEGAL.md';

// URL to the raw Markdown version of the user agreement
//
const TERMS_MARKDOWN_URL =
'https://raw.githubusercontent.com/cofacts/rumors-site/master/LEGAL.md';

const TERMS_FALLBACK_URL =
'https://github.com/cofacts/rumors-site/blob/master/LEGAL.md';

// cdn.js URL and checksum from cdn.js website
//
const JS_LIBS = [
[
'https://cdnjs.cloudflare.com/ajax/libs/marked/4.1.1/marked.min.js',
'sha512-+mCmSlBpa1bF0npQzdpxFWIyJaFbVdEcuyET6FtmHmlXIacQjN/vQs1paCsMlVHHZ2ltD2VTHy3fLFhXQu0AMA==',
],
[
'https://cdnjs.cloudflare.com/ajax/libs/dompurify/2.4.0/purify.min.js',
'sha512-/hVAZO5POxCKdZMSLefw30xEVwjm94PAV9ynjskGbIpBvHO9EBplEcdUlBdCKutpZsF+La8Ag4gNrG0gAOn3Ig==',
],
];

function getScriptId(idx) {
return `_terms_script_${idx}`;
}

const TermArticle = styled('article')(({ theme }) => ({
margin: '0 auto 36px',
maxWidth: '70em',
Expand Down Expand Up @@ -68,73 +46,41 @@ const TermArticle = styled('article')(({ theme }) => ({
},
}));

function Terms() {
const [termsHtml, setTermsHtml] = useState(null);

useEffect(() => {
const markdownPromise = fetch(TERMS_MARKDOWN_URL)
.then(resp => {
if (resp.status !== 200) throw resp.statusText;
return resp.text();
})
.catch(error => {
console.error('Failed to fetch terms markdown', error);
window.rollbar.error('Failed to fetch terms markdown', error);
return `Cannot load terms content due to "${error}"; please view the terms [here](${TERMS_FALLBACK_URL}) instead.`;
});

const scriptPromises = JS_LIBS.map(([src, integrity], idx) => {
// Don't insert the same script when visit this page the second time
//
if (document.getElementById(getScriptId(idx)) !== null)
return Promise.resolve();

return new Promise(resolve => {
/**
* <script src="..." integrity="..." crossorigin="anonymous" referrerpolicy="no-referrer"></script>
*/
const scriptElem = document.createElement('script');
scriptElem.id = getScriptId(idx);
scriptElem.onload = resolve;
scriptElem.integrity = integrity;
scriptElem.crossOrigin = 'anonymous';
scriptElem.referrerPolicy = 'no-referrer';
scriptElem.src = src;
window.document.body.appendChild(scriptElem);
});
});
export async function getStaticProps() {
const markdown = await fs.readFile(
path.resolve(process.cwd(), './LEGAL.md'),
'utf8'
);
const termsHtml = marked.parse(markdown);

Promise.all([markdownPromise, ...scriptPromises]).then(([markdown]) => {
// All stuff is ready!
const { marked, DOMPurify } = window;
setTermsHtml({ __html: DOMPurify.sanitize(marked.parse(markdown)) });
});
}, []);
return {
props: { termsHtml },
};
}

function Terms({ termsHtml }) {
const revisionLink = (
<a key="revision" href={TERMS_REVISIONS_URL}>{t`Github`}</a>
);

const termFallbackLink = (
<a key="fallback" href={TERMS_FALLBACK_URL}>{t`User Agreement`}</a>
);

return (
<AppLayout>
<Head>
<title>{t`User Agreement`}</title>
</Head>
<TermArticle>
{termsHtml ? (
<div dangerouslySetInnerHTML={termsHtml} />
) : (
jt`Loading ${termFallbackLink}...`
)}
<div dangerouslySetInnerHTML={{ __html: termsHtml }} />
<hr />
<p>{jt`See ${revisionLink} for other revisions of the user agreement.`}</p>
</TermArticle>
</AppLayout>
);
}

export default withData(Terms);
// FIXME: this page don't need SSR, but we need to use `withData` for AppLayout to work.
// Migrate to server components to get rid of Apollo client alltogether.
//
const TermsWithData = withData(Terms);
delete TermsWithData.getInitialProps;

export default TermsWithData;

0 comments on commit ef6630a

Please sign in to comment.