Skip to content

Commit

Permalink
Fix Gov Proposals (#170)
Browse files Browse the repository at this point in the history
* github locked down fetching raw content from web browers so we need to go thru the server

* woops
  • Loading branch information
aaronmgdr authored Feb 25, 2025
1 parent 58fbd9f commit fe9af3c
Show file tree
Hide file tree
Showing 5 changed files with 514 additions and 32 deletions.
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
"@vercel/analytics": "^1.3.0",
"bignumber.js": "^9.1.2",
"clsx": "^2.1.1",
"dompurify": "^3.1.4",
"formik": "2.4.6",
"isomorphic-dompurify": "^2.22.0",
"micromark": "^4.0.0",
"micromark-extension-gfm-table": "^2.0.0",
"next": "14.2.21",
Expand All @@ -49,7 +49,6 @@
"@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.1.0",
"@types/dompurify": "^3",
"@types/node": "^20.11.30",
"@types/react": "^18.2.73",
"@types/react-dom": "^18.2.22",
Expand Down
16 changes: 16 additions & 0 deletions src/app/governance/[id]/markdown-api/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export const revalidate = 60 * 2;

const URL_BASE = 'https://raw.githubusercontent.com/celo-org/governance/main/CGPs/cgp-';

export async function GET(request: Request, { params }: { params: Promise<{ id: string }> }) {
const { id } = await params;
const url = URL_BASE + zeroPad(id) + '.md';
console.info('Fetching markdown for proposal', url);
const data = await fetch(url);
const yaml = await data.text();
return Response.json({ yaml });
}

function zeroPad(cgpDashid: string) {
return cgpDashid.padStart(4, '0');
}
18 changes: 9 additions & 9 deletions src/features/governance/fetchFromRepository.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { sanitize } from 'dompurify';
import DOMPurify from 'isomorphic-dompurify';
import { micromark } from 'micromark';
import { gfmTable, gfmTableHtml } from 'micromark-extension-gfm-table';
import {
Expand Down Expand Up @@ -94,20 +94,20 @@ export async function fetchProposalsFromRepo(
return validProposals;
}

export async function fetchProposalContent(url: string) {
const content = await fetchGithubFile(url);
if (!content) throw new Error('Failed to fetch proposal content');
const fileParts = separateYamlFrontMatter(content);
export async function fetchProposalContent(cgpNumber: number) {
const response = await fetch(`/governance/${cgpNumber}/markdown-api`);
const { yaml } = await response.json();
if (!yaml) throw new Error('Failed to fetch proposal content');
const fileParts = separateYamlFrontMatter(yaml);
if (!fileParts) throw new Error('Failed to parse proposal content');
const markup = markdownToHtml(fileParts.body);
if (isNullish(markup)) throw new Error('Failed to convert markdown to html');
if (!markup) {
logger.warn('Content is empty for:', url);
logger.warn('Content is empty for:', cgpNumber);
return '';
}
// Client-side only due to issue with DomPurify in SSR
if (typeof window !== 'undefined') return sanitize(markup);
else return '';
// return markup;
return DOMPurify.sanitize(markup);
}

interface GithubFile {
Expand Down
12 changes: 6 additions & 6 deletions src/features/governance/hooks/useProposalContent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@ import { ProposalMetadata } from 'src/features/governance/types';
import { logger } from 'src/utils/logger';

export function useProposalContent(metadata?: ProposalMetadata) {
const url = metadata?.cgpUrlRaw;
const cgpNumber = metadata?.cgp;
const { isLoading, isError, error, data } = useQuery({
queryKey: ['useProposalContent', url],
queryKey: ['useProposalContent', cgpNumber],
queryFn: () => {
if (!url) return null;
logger.debug('Fetching proposal content', url);
return fetchProposalContent(url);
if (!cgpNumber) return null;
logger.debug('Fetching proposal content', cgpNumber);
return fetchProposalContent(cgpNumber);
},
gcTime: Infinity,
staleTime: 60 * 60 * 1000, // 1 hour
staleTime: 5 * 60 * 1000, // 5 min // TODO 1 hour is too long while its active
});

useToastError(error, 'Error fetching proposal content');
Expand Down
Loading

0 comments on commit fe9af3c

Please sign in to comment.