From 3d22b5b6ef94a4db0b06eaf1d331d1da2f0b05af Mon Sep 17 00:00:00 2001 From: juanchax Date: Sun, 20 Apr 2025 15:22:09 -0300 Subject: [PATCH 1/3] Update .env.example --- .env.example | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.env.example b/.env.example index 857ccdf6790..9b5d84327e0 100644 --- a/.env.example +++ b/.env.example @@ -22,8 +22,8 @@ # DUNE_API_KEY= # Matomo environment (URL and site ID required for analytics) -NEXT_PUBLIC_MATOMO_URL= -NEXT_PUBLIC_MATOMO_SITE_ID= +# NEXT_PUBLIC_MATOMO_URL= +# NEXT_PUBLIC_MATOMO_SITE_ID= # Used to avoid loading Matomo in our preview deploys IS_PREVIEW_DEPLOY=false @@ -31,15 +31,15 @@ IS_PREVIEW_DEPLOY=false # Build pages only for the specified langs. Leave it empty to build all the langs # e.g. `en,fr` will only build English and French pages # Note: always include `en` as it is the default lang of the site -NEXT_PUBLIC_BUILD_LOCALES= +NEXT_PUBLIC_BUILD_LOCALES=en,es # If resource constraints are being hit during builds, change LIMIT_CPUS to a # fixed number of CPUs (e.g. 2) to limit the demand during build time -LIMIT_CPUS= +# LIMIT_CPUS= # Enables the bundle analyzer ANALYZE=false # Use mock data for development. Set to "false" to use live data but you must have the # environment variables set to make api requests -USE_MOCK_DATA=true \ No newline at end of file +USE_MOCK_DATA=true From 06067e714514c133d183d5ff50a00bbafd4c4d3c Mon Sep 17 00:00:00 2001 From: juanchax <2845759+juanchax@users.noreply.github.com> Date: Sun, 20 Apr 2025 16:14:25 -0300 Subject: [PATCH 2/3] Added variables.ts Populated variables.ts with external url references contained in /public/content/contributing/index.md Added preprocess.ts with the markdown preprocessing logic Removed preprocessMarkdown() from compile.ts imported preprocessMarkdown() from preprocess.ts --- public/content/contributing/index.md | 29 ++++--- src/lib/md/compile.ts | 11 +-- src/lib/md/preprocess.ts | 108 +++++++++++++++++++++++++++ src/lib/variables.ts | 68 +++++++++++++++++ 4 files changed, 193 insertions(+), 23 deletions(-) create mode 100644 src/lib/md/preprocess.ts create mode 100644 src/lib/variables.ts diff --git a/public/content/contributing/index.md b/public/content/contributing/index.md index 8b010222b33..24b7b9f7687 100644 --- a/public/content/contributing/index.md +++ b/public/content/contributing/index.md @@ -16,7 +16,7 @@ We are a welcoming community that will help you grow and educate in the Ethereum - [Join the translation program](/contributing/translation-program/) – Help us bring ethereum.org to new languages **Development** -- [Work on an open issue](https://github.com/ethereum/ethereum-org-website/issues) – Work we've identified that needs doing +- [Work on an open issue]({EXT_GITHUB_ISSUES}) – Work we've identified that needs doing **Design** - [Help design the website](/contributing/design/) – Designers of all levels can contribute to improve the website @@ -28,7 +28,7 @@ We are a welcoming community that will help you grow and educate in the Ethereum - [Quizzes](/contributing/quizzes/) – Add, update, and delete quiz question banks for a relevant page **Feature ideas** -- [Request a feature](https://github.com/ethereum/ethereum-org-website/issues/new?assignees=&labels=Type%3A+Feature&template=feature_request.yaml&title=) – Let us know about any ideas you have for a new feature or design +- [Request a feature]({EXT_GITHUB_FEATURE_REQUEST}) – Let us know about any ideas you have for a new feature or design **Product listings** - [Add an exchange](/contributing/adding-exchanges/) – Add an exchange to our [exchange finder](/get-eth/#country-picker) @@ -39,7 +39,7 @@ We are a welcoming community that will help you grow and educate in the Ethereum - [Add a wallet](/contributing/adding-wallets/) – Add a wallet for the [find wallets page](/wallets/find-wallet/) - [Suggest a project for our DeSci page](/contributing/adding-desci-projects/) – Add a project built on Ethereum that contributes to decentralized science -Any questions? 🤔 Join our [Discord server](https://discord.gg/ethereum-org) +Any questions? 🤔 Join our [Discord server]({EXT_DISCORD}) ## Good first tasks to start contributing @@ -51,14 +51,14 @@ These are few current tasks that you could help us solve and take responsibility ## How to work on ethereum.org {#how-to-update-content} -If you wish to contribute in the [Translation Program](/contributing/translation-program/), we ask you to create an account on [Crowdin](https://crowdin.com/project/ethereum-org). For everything else – adding or editing content or visuals to the website, fixing bugs, working on open tasks – you will need a [GitHub](https://github.com/) account. +If you wish to contribute in the [Translation Program](/contributing/translation-program/), we ask you to create an account on [Crowdin]({CROWDIN_PROJECT}). For everything else – adding or editing content or visuals to the website, fixing bugs, working on open tasks – you will need a [GitHub](https://github.com/) account. -All updates are made via the GitHub PR process. This means you create a local copy of the website, make your changes and request to merge your changes. If you've never done this before, follow the instructions at the bottom of our [GitHub repository](https://github.com/ethereum/ethereum-org-website). +All updates are made via the GitHub PR process. This means you create a local copy of the website, make your changes and request to merge your changes. If you've never done this before, follow the instructions at the bottom of our [GitHub repository]({GITHUB_REPO}). You don't need permission to work on anything, but it's always best to let us know what you're planning to do. You can do this by: -- Commenting on an issue or PR in [GitHub](https://github.com/ethereum/ethereum-org-website) -- Messaging on our [Discord server](https://discord.gg/ethereum-org) +- Commenting on an issue or PR in [GitHub]({GITHUB_REPO}) +- Messaging on our [Discord server]({EXT_DISCORD}) Before contributing, make sure you're familiar with: @@ -74,8 +74,8 @@ Before contributing, make sure you're familiar with: Decisions about individual PRs, design evolution and major upgrades are made by a team from across the Ethereum ecosystem. This team includes project managers, developers, designers, marketing and communications, and subject matter experts. Community input informs every decision: so please raise questions in issues, submit PRs, or contact the team: - [website@ethereum.org](mailto:website@ethereum.org) -- [@ethdotorg](https://twitter.com/ethdotorg) -- [Discord server](https://discord.gg/ethereum-org) +- [@ethdotorg]({EXT_X}) +- [Discord server]({EXT_DISCORD}) ### A note on plagiarism {#plagiarism} @@ -83,16 +83,16 @@ Only use your original work or content that you have permission to use when cont ## New to open-source? {#new-to-open-source} -We have low barrier to entry issues on our GitHub repository specifically designed for developers who are new to open-source labelled [good first issue](https://github.com/ethereum/ethereum-org-website/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22). +We have low barrier to entry issues on our GitHub repository specifically designed for developers who are new to open-source labelled [good first issue]({EXT_GITHUB_ISSUES_GFI}). ## Claim your Onchain Achievement Token (OAT) {#oat} -If your contribution gets merged into ethereum.org, you will have a chance to claim a special badge on [Galxe](https://app.galxe.com/quest/ethereumorg). An Onchain Achievement Token (OAT) is a proof that you helped make the ecosystem a little more awesome. +If your contribution gets merged into ethereum.org, you will have a chance to claim a special badge on [Galxe]({EXT_GALXE}). An Onchain Achievement Token (OAT) is a proof that you helped make the ecosystem a little more awesome. -[More on OATs](https://help.galxe.com/en/articles/9645630-create-quest-rewards#h_1c5d63ba03) +[More on OATs]({EXT_GALXE_OATS}) ### How to claim -1. Join our [Discord server](https://discord.gg/ethereum-org). +1. Join our [Discord server]({EXT_DISCORD}). 2. Paste a link to your contribution in the `#🥇 | proof-of-contribution` channel. 3. Wait for a member of our team to send you a link to your OAT. 4. Claim your OAT! @@ -103,10 +103,9 @@ You should only use self-custody wallets to claim OATs. Do not use exchange acco GitPOAP will also automatically recognize your merged contribution and let you mint a separate unique contributors POAP on their platform itself! - ### How to claim {#how-to-claim} -1. Visit [GitPOAP](https://www.gitpoap.io). +1. Visit [GitPOAP]({EXT_GITPOAP}). 2. Connect with your wallet or even with your email through sign in option. 3. Search for your GitHub username, ETH address, ENS names or any GitPOAP to check if you're eligible. 4. If your GitHub account is eligible, then you would be able to mint a GitPOAP! diff --git a/src/lib/md/compile.ts b/src/lib/md/compile.ts index 6aa64f5ea74..99706ca579c 100644 --- a/src/lib/md/compile.ts +++ b/src/lib/md/compile.ts @@ -11,17 +11,12 @@ import remarkHeadingId from "remark-heading-id" import { CONTENT_DIR, CONTENT_PATH } from "../constants" import { Frontmatter, TocNodeType } from "../types" +import { preprocessMarkdown } from "./preprocess" + import rehypeImg from "@/lib/md/rehypeImg" import remarkInferToc from "@/lib/md/remarkInferToc" import { remarkPreserveJsx } from "@/lib/md/remarkPreserveJsx" -// Preprocess the markdown content -function preprocessMarkdown(content: string) { - // Replace heading IDs without escaping to escaped version - // TODO: move to a separate file and test it more - return content.replace(/^(#{1,6}.*?)\{(#[\w-]+)\}/gm, "$1\\{$2\\}") -} - export const compile = async ({ markdown, slugArray, @@ -54,7 +49,7 @@ export const compile = async ({ rehypePlugins: [[rehypeImg, { dir: mdDir, srcPath: mdPath, locale }]], } satisfies SerializeOptions["mdxOptions"] - const source = preprocessMarkdown(markdown) + const source = await preprocessMarkdown(markdown) const { content, frontmatter } = await compileMDX({ source, diff --git a/src/lib/md/preprocess.ts b/src/lib/md/preprocess.ts new file mode 100644 index 00000000000..2ef4d24fa75 --- /dev/null +++ b/src/lib/md/preprocess.ts @@ -0,0 +1,108 @@ +import { EXT_URLS } from "../variables" + +const extUrlRefs = EXT_URLS + +type RegexSearchAndReplace = { + search: RegExp + replace: RegExp +} + +// Match {myVar} styled placeholders +// ignore Markdown anchors, e.g. {#myVar} +const rgxCurlyIgnoreAnchor = { + search: /\{(?!#).*\}/g, + replace: /(\{?)(\}?)/g, +} + +// Match Markdown Headings & Excape anchors' curly braces +const rgxCurlyEscapeIncludeAnchor = { + //REVIEW: Named capturing groups are only available when targeting 'ES2018' or later.ts(1503) + // search: /^(?#{1,6}.*?)\{(?#[\w-]+)\}/gm, + // replace: `$\\{$\\}` + search: /^(#{1,6}.*?)\{(#[\w-]+)\}/gm, + replace: "$1\\{$2\\}", +} + +const getVarValue = (varName: string, refsObj: object) => { + const varValue = refsObj[varName] + if (!varValue) { + return + } + return varValue +} + +const extractVars = (content: string, regex: RegExp) => { + return content.match(regex) +} + +const resolveVars = ( + markdown: string, + regex: RegexSearchAndReplace, + refsObj: object +) => { + let content = markdown + + // Catch empty markdown content + if (!content) { + return content + } + + const varsExtracted = extractVars(markdown, regex.search) + + // Catch empty array of extracted variables + if (!varsExtracted || !varsExtracted.length) { + return content + } + + for (const i in varsExtracted) { + const varExtracted = varsExtracted[i] + const varName = varExtracted.replace(regex.replace, "") + const varValue = getVarValue(varName, refsObj) + + if (varValue) { + content = content.replace(varExtracted, varValue) + } + } + + return content +} + +//NOTE: not using deifned Type due to commend in line: 19 +const escapeAnchorChars = ( + markdown: string, + regex: { search: RegExp; replace: string } +) => { + let content = markdown + + // Catch empty markdown content + if (!content) { + return content + } + content = content.replace(regex.search, regex.replace) + + return content +} + +export async function preprocessMarkdown(markdown: string) { + let content = markdown + // Inject external URLs into placeholders + content = resolveVars(markdown, rgxCurlyIgnoreAnchor, extUrlRefs) + + // Excape curly braces in Heading Anchors + content = escapeAnchorChars(content, rgxCurlyEscapeIncludeAnchor) + + return content +} + +/*NOTE - Additional RegEx options for url variables +// Match ${myVar} styled placeholders +/* const rgxDollaCurly = { + search: /\$\{.*\}/g, + replace: /(\$\{)(\})/g +} */ + +// Match{{myVar}} styled placeholders +/* const rgxDoubleCurly = { + search: /\{\{(?!#).*\}\}/g, + replace: /(\{\{?)(\}\}?)/g +} */ diff --git a/src/lib/variables.ts b/src/lib/variables.ts new file mode 100644 index 00000000000..e789aa52880 --- /dev/null +++ b/src/lib/variables.ts @@ -0,0 +1,68 @@ +import { CROWDIN_PROJECT_URL, GITHUB_REPO_URL } from "./constants" + +/*NOTE: External URLs Reference + * 1. Add/edit as needed + * 2. add newly added vars to the exported obj 'EXT_URLS' at the bottom + */ + +// Contributing urls +const GITHUB_REPO = GITHUB_REPO_URL +const CROWDIN_PROJECT = CROWDIN_PROJECT_URL + +const EXT_GITHUB_ISSUES = GITHUB_REPO + "/issues" +const EXT_GITHUB_ISSUES_GFI = + EXT_GITHUB_ISSUES + "?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22" +const EXT_GITHUB_FEATURE_REQUEST = + EXT_GITHUB_ISSUES + + "/new?assignees=&labels=Type%3A+Feature&template=feature_request.yaml&title=" +const EXT_DISCORD = "https://discord.gg/ethereum-org" +const EXT_CROWDIN_DOCS = "https://support.crowdin.com/online-editor" +const EXT_X = "https://x.com/ethdotorg" + +// Translation-guide +const EXT_ISO_LANG_CODE = + "https://www.andiamo.co.uk/resources/iso-language-codes" + +// Translation Tools +const EXT_MS_LANG_PORTAL = "https://www.microsoft.com/en-us/language" +const EXT_LINGUEE = "https://www.linguee.com" +const EXT_PROZ_SEARCH = "https://www.proz.com/search" +const EXT_EURO_TERMBANK = "https://www.eurotermbank.com" + +// Translation Communities +const EXT_TRANSLATORS_CH = + "https://www.notion.so/Ethereum-org-05375fe0a94c4214acaf90f42ba40171" + +// Contributing Rewards +const EXT_GALXE = "https://app.galxe.com/quest/ethereumorg" +const EXT_GALXE_DOCS = "https://help.galxe.com" +const EXT_GALXE_OATS = + EXT_GALXE_DOCS + "/en/articles/9645630-create-quest-rewards#h_1c5d63ba03" +// const EXT_GALXE_OATS = 'https://medium.com/galxe-news/introducing-galaxy-oat-on-chain-achievement-token-7e89779242b4' +const EXT_GITPOAP = "https://www.gitpoap.io" +const EXT_DEVCON = "https://devcon.org" +const EXT_DEVCONNECT = "https://devconnect.org" + +// External URLs -- Exported vars as an obj +export const EXT_URLS = { + GITHUB_REPO, + CROWDIN_PROJECT, + EXT_GITHUB_ISSUES, + EXT_GITHUB_ISSUES_GFI, + EXT_GITHUB_FEATURE_REQUEST, + EXT_DISCORD, + EXT_X, + EXT_CROWDIN_DOCS, + EXT_ISO_LANG_CODE, + EXT_MS_LANG_PORTAL, + EXT_LINGUEE, + EXT_PROZ_SEARCH, + EXT_EURO_TERMBANK, + EXT_TRANSLATORS_CH, + EXT_GALXE, + EXT_GALXE_DOCS, + EXT_GALXE_OATS, + EXT_GITPOAP, + EXT_DEVCON, + EXT_DEVCONNECT, +} From 47d013c554aeadd6db695c41634968081927b6b4 Mon Sep 17 00:00:00 2001 From: juanchax <2845759+juanchax@users.noreply.github.com> Date: Mon, 21 Apr 2025 13:38:33 -0300 Subject: [PATCH 3/3] added type guard for current escapeAnchorChars() implementation --- src/lib/md/preprocess.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/lib/md/preprocess.ts b/src/lib/md/preprocess.ts index 2ef4d24fa75..e0525ede432 100644 --- a/src/lib/md/preprocess.ts +++ b/src/lib/md/preprocess.ts @@ -4,7 +4,8 @@ const extUrlRefs = EXT_URLS type RegexSearchAndReplace = { search: RegExp - replace: RegExp + // type union for current 'escapeAnchorChars()' implementation + replace: RegExp | string } // Match {myVar} styled placeholders @@ -78,7 +79,11 @@ const escapeAnchorChars = ( if (!content) { return content } - content = content.replace(regex.search, regex.replace) + + //type guard for current implementation + if (typeof regex.replace === "string") { + content = content.replace(regex.search, regex.replace) + } return content }