From a10461c6cb5a58ab6d673088d6ccdab9d45d7e86 Mon Sep 17 00:00:00 2001 From: Nicolas Brugneaux Date: Tue, 19 Sep 2023 15:28:12 +0200 Subject: [PATCH 1/2] fix: prevent app from crashing in dev mode when yaml has undefined values Also replace the handcrafted yaml parser [Closes #176] --- package.json | 1 + src/features/governance/data/getProposals.ts | 1 + src/utils/proposals.ts | 41 ++++++------ yarn.lock | 65 ++++++++++++++++++++ 4 files changed, 89 insertions(+), 19 deletions(-) diff --git a/package.json b/package.json index 7e2ae25a..fda71ac6 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "dayjs": "^1.11.4", "graphql": "^16.6.0", "graphql-request": "^5.2.0", + "gray-matter": "^4.0.3", "next": "^13.4.19", "react": "18.2.0", "react-dom": "18.2.0", diff --git a/src/features/governance/data/getProposals.ts b/src/features/governance/data/getProposals.ts index 16f39908..0fca93f7 100644 --- a/src/features/governance/data/getProposals.ts +++ b/src/features/governance/data/getProposals.ts @@ -142,6 +142,7 @@ export async function getYamlForProposal(proposal: MiniProposal) { if (!parsed) { throw new Error("Couldn't parse markdown"); } + console.log(parsed); return parsed; } catch { console.warn(`Failed to fetch proposal markdown at url ${proposal.metadata.descriptionURL}`); diff --git a/src/utils/proposals.ts b/src/utils/proposals.ts index dd73490f..a0d0d5ba 100644 --- a/src/utils/proposals.ts +++ b/src/utils/proposals.ts @@ -1,3 +1,5 @@ +import matter from 'gray-matter'; + export function camelCasesify(str: string): string { const words = str.split(/\W/g); @@ -16,27 +18,28 @@ export type ParsedYAML = { }; export function parsedYAMLFromMarkdown(markdown: string): ParsedYAML | null { - const parsed = markdown.match(/---(.*?)---/s); - if (!parsed) { + try { + // Note: the typings seem out of date and don't reference the existing `isEmpty` prop + // which is true if the front-matter couldn't be parsed + const parsed = matter(markdown) as matter.GrayMatterFile & { isEmpty: boolean }; + + if (parsed.isEmpty) return null; + + const data = {} as ParsedYAML; + Object.keys(parsed.data).forEach((key) => { + const newKey = camelCasesify(key) as keyof ParsedYAML; + + data[newKey] = parsed.data[key] ?? ''; + if (typeof data[newKey] === 'object') { + data[newKey] = parsed.data[newKey].toString(); + } + }); + + return data; + } catch (error) { + console.error('Couldnt parse YAML', error); return null; } - const rows = parsed[1].split('\n'); - const keyValues = rows - .map((x) => - x - .split(/(.*?):(.*)/) - .map((x) => x.trim()) - .filter(Boolean) - ) - .filter((x) => x.length); - - return keyValues.reduce( - (acc, [key, value]) => ({ - ...acc, - [camelCasesify(key)]: value, - }), - {} as ParsedYAML - ); } export function getRawGithubUrl(descriptionURL: string) { diff --git a/yarn.lock b/yarn.lock index e0687797..a200c6db 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1943,6 +1943,13 @@ arg@^5.0.2: resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c" integrity sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg== +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + argparse@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" @@ -3257,6 +3264,11 @@ espree@^9.3.2: acorn-jsx "^5.3.2" eslint-visitor-keys "^3.3.0" +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + esquery@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" @@ -3518,6 +3530,13 @@ ext@^1.1.2: dependencies: type "^2.5.0" +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug== + dependencies: + is-extendable "^0.1.0" + extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" @@ -3956,6 +3975,16 @@ graphql@^16.6.0: resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.6.0.tgz#c2dcffa4649db149f6282af726c8c83f1c7c5fdb" integrity sha512-KPIBPDlW7NxrbT/eh4qPXz5FiFdL5UbaA0XUNz2Rp3Z3hqBSkbj0GVjwFDztsWVauZUWsbKHgMg++sk8UX0bkw== +gray-matter@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/gray-matter/-/gray-matter-4.0.3.tgz#e893c064825de73ea1f5f7d88c7a9f7274288798" + integrity sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q== + dependencies: + js-yaml "^3.13.1" + kind-of "^6.0.2" + section-matter "^1.0.0" + strip-bom-string "^1.0.0" + gzip-size@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462" @@ -4222,6 +4251,11 @@ is-date-object@^1.0.1: dependencies: has-tostringtag "^1.0.0" +is-extendable@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + integrity sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw== + is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" @@ -4415,6 +4449,14 @@ js-sha3@^0.5.7: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== +js-yaml@^3.13.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + js-yaml@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" @@ -4537,6 +4579,11 @@ keyvaluestorage-interface@^1.0.0: resolved "https://registry.yarnpkg.com/keyvaluestorage-interface/-/keyvaluestorage-interface-1.0.0.tgz#13ebdf71f5284ad54be94bd1ad9ed79adad515ff" integrity sha512-8t6Q3TclQ4uZynJY9IGr2+SsIGwK9JHcO6ootkHCGA0CrQCRy+VkouYNO2xicET6b9al7QKzpebNow+gkpCL8g== +kind-of@^6.0.0, kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + language-subtag-registry@~0.3.2: version "0.3.22" resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz#2e1500861b2e457eba7e7ae86877cbd08fa1fd1d" @@ -5898,6 +5945,14 @@ secp256k1@^4.0.1: node-addon-api "^2.0.0" node-gyp-build "^4.2.0" +section-matter@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/section-matter/-/section-matter-1.0.0.tgz#e9041953506780ec01d59f292a19c7b850b84167" + integrity sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA== + dependencies: + extend-shallow "^2.0.1" + kind-of "^6.0.0" + semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" @@ -6071,6 +6126,11 @@ split2@^4.0.0: resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4" integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg== +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== + sshpk@^1.7.0: version "1.17.0" resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.17.0.tgz#578082d92d4fe612b13007496e543fa0fbcbe4c5" @@ -6174,6 +6234,11 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: dependencies: ansi-regex "^5.0.1" +strip-bom-string@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-bom-string/-/strip-bom-string-1.0.0.tgz#e5211e9224369fbb81d633a2f00044dc8cedad92" + integrity sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g== + strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" From 5be455818dbf092c694b28f5667d57b43bd57c63 Mon Sep 17 00:00:00 2001 From: Nicolas Brugneaux Date: Wed, 20 Sep 2023 11:40:52 +0200 Subject: [PATCH 2/2] Update src/features/governance/data/getProposals.ts --- src/features/governance/data/getProposals.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/features/governance/data/getProposals.ts b/src/features/governance/data/getProposals.ts index 0fca93f7..16f39908 100644 --- a/src/features/governance/data/getProposals.ts +++ b/src/features/governance/data/getProposals.ts @@ -142,7 +142,6 @@ export async function getYamlForProposal(proposal: MiniProposal) { if (!parsed) { throw new Error("Couldn't parse markdown"); } - console.log(parsed); return parsed; } catch { console.warn(`Failed to fetch proposal markdown at url ${proposal.metadata.descriptionURL}`);