Skip to content

Commit 374a13b

Browse files
authored
Merge pull request #15179 from ethereum/dev
2 parents 2acc7f9 + bd9f6c3 commit 374a13b

File tree

779 files changed

+20969
-4722
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

779 files changed

+20969
-4722
lines changed

.github/CODEOWNERS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@
88
* @wackerow @corwintines @pettinarip @minimalsm
99

1010
# Owners of specific files
11-
/src/data/consensus-bounty-hunters.json @djrtwo @asanso @fredriksvantes
11+
/src/data/consensus-bounty-hunters.json @asanso @fredriksvantes
1212
/src/data/wallets/new-to-crypto.ts @konopkja @minimalsm
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
name: Suggest a resource
2+
description: Suggest a new resource to list on ethereum.org/resources
3+
title: Suggest a resource
4+
labels: ["resource 📚"]
5+
body:
6+
- type: markdown
7+
attributes:
8+
value: |
9+
Before suggesting a resource, make sure you've read [our listing policy](https://www.ethereum.org/en/contributing/adding-resources/).
10+
- type: markdown
11+
attributes:
12+
value: Only continue with the issue if your resource meets the criteria listed there.
13+
- type: markdown
14+
attributes:
15+
value: If it does, complete the following information which we need to accurately list the resource.
16+
- type: markdown
17+
id: resource_info
18+
attributes:
19+
value: "## Resource info"
20+
- type: input
21+
id: resource_name
22+
attributes:
23+
label: Name
24+
description: Please provide the official name of the resource
25+
validations:
26+
required: true
27+
- type: input
28+
id: resource_url
29+
attributes:
30+
label: Resource URL
31+
description: Please provide a URL to the resource
32+
validations:
33+
required: true
34+
- type: textarea
35+
id: resource_description
36+
attributes:
37+
label: Description
38+
description: Please provide a short 1-2 sentence description of the resource
39+
validations:
40+
required: true
41+
- type: textarea
42+
id: resource_logo
43+
attributes:
44+
label: Logo
45+
description: |
46+
Please provide an SVG or transparent PNG
47+
Tip: You can attach images by clicking this area to highlight it and then dragging files in.
48+
- type: input
49+
id: resource_category
50+
attributes:
51+
label: Category
52+
description: Please specify a best fit to categorize the resource (e.g., DeFi, NFT, Scaling, etc.)
53+
- type: checkboxes
54+
id: resource_work_on
55+
attributes:
56+
label: Would you like to work on this issue?
57+
options:
58+
- label: "Yes"
59+
required: false
60+
- label: "No"
61+
required: false
62+
validations:
63+
required: true

app/[locale]/[...slug]/page.tsx

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import pick from "lodash.pick"
2+
import { notFound } from "next/navigation"
3+
import { getMessages, setRequestLocale } from "next-intl/server"
4+
5+
import I18nProvider from "@/components/I18nProvider"
6+
import mdComponents from "@/components/MdComponents"
7+
8+
import { dataLoader } from "@/lib/utils/data/dataLoader"
9+
import { getPostSlugs } from "@/lib/utils/md"
10+
import { getRequiredNamespacesForPage } from "@/lib/utils/translations"
11+
12+
import { LOCALES_CODES } from "@/lib/constants"
13+
14+
import { componentsMapping, layoutMapping } from "@/layouts"
15+
import { fetchGFIs } from "@/lib/api/fetchGFIs"
16+
import { getPageData } from "@/lib/md/data"
17+
import { getMdMetadata } from "@/lib/md/metadata"
18+
19+
const loadData = dataLoader([["gfissues", fetchGFIs]])
20+
21+
export default async function Page({
22+
params,
23+
}: {
24+
params: Promise<{ locale: string; slug: string[] }>
25+
}) {
26+
const { locale, slug: slugArray } = await params
27+
28+
// Check if this specific path is in our valid paths
29+
const validPaths = await generateStaticParams()
30+
const isValidPath = validPaths.some(
31+
(path) =>
32+
path.locale === locale && path.slug.join("/") === slugArray.join("/")
33+
)
34+
35+
if (!isValidPath) {
36+
notFound()
37+
}
38+
39+
// Enable static rendering
40+
setRequestLocale(locale)
41+
42+
const [gfissues] = await loadData()
43+
44+
const slug = slugArray.join("/")
45+
46+
const {
47+
content,
48+
frontmatter,
49+
tocItems,
50+
lastEditLocaleTimestamp,
51+
isTranslated,
52+
} = await getPageData({
53+
locale,
54+
slug,
55+
// TODO: Address component typing error here (flip `FC` types to prop object types)
56+
// @ts-expect-error Incompatible component function signatures
57+
components: { ...mdComponents, ...componentsMapping },
58+
scope: {
59+
gfissues,
60+
},
61+
})
62+
63+
// Determine the actual layout after we have the frontmatter
64+
const layout = frontmatter.template || "static"
65+
const Layout = layoutMapping[layout]
66+
67+
// Get i18n messages
68+
const allMessages = await getMessages({ locale })
69+
const requiredNamespaces = getRequiredNamespacesForPage(slug, layout)
70+
const messages = pick(allMessages, requiredNamespaces)
71+
72+
return (
73+
<I18nProvider locale={locale} messages={messages}>
74+
<Layout
75+
slug={slug}
76+
frontmatter={frontmatter}
77+
tocItems={tocItems}
78+
lastEditLocaleTimestamp={lastEditLocaleTimestamp}
79+
contentNotTranslated={!isTranslated}
80+
>
81+
{content}
82+
</Layout>
83+
</I18nProvider>
84+
)
85+
}
86+
87+
export async function generateStaticParams() {
88+
const slugs = await getPostSlugs("/", /\/developers/)
89+
90+
return LOCALES_CODES.flatMap((locale) =>
91+
slugs.map((slug) => ({
92+
slug: slug.split("/").slice(1),
93+
locale,
94+
}))
95+
)
96+
}
97+
98+
export async function generateMetadata({
99+
params,
100+
}: {
101+
params: Promise<{ locale: string; slug: string[] }>
102+
}) {
103+
const { locale, slug } = await params
104+
105+
return await getMdMetadata({
106+
locale,
107+
slug,
108+
})
109+
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import { join } from "path"
2+
3+
import pick from "lodash.pick"
4+
import { getMessages, setRequestLocale } from "next-intl/server"
5+
6+
import I18nProvider from "@/components/I18nProvider"
7+
import mdComponents from "@/components/MdComponents"
8+
9+
import { getPostSlugs } from "@/lib/utils/md"
10+
import { getRequiredNamespacesForPage } from "@/lib/utils/translations"
11+
12+
import { LOCALES_CODES } from "@/lib/constants"
13+
14+
import { docsComponents, DocsLayout } from "@/layouts"
15+
import { getPageData } from "@/lib/md/data"
16+
import { getMdMetadata } from "@/lib/md/metadata"
17+
18+
export default async function Page({
19+
params,
20+
}: {
21+
params: Promise<{ locale: string; doc?: string[] }>
22+
}) {
23+
const { locale, doc: docArray } = await params
24+
25+
// Enable static rendering
26+
setRequestLocale(locale)
27+
28+
const slug = join("developers/docs", ...(docArray || []))
29+
30+
const layout = "docs"
31+
32+
const {
33+
content,
34+
frontmatter,
35+
tocItems,
36+
lastEditLocaleTimestamp,
37+
contributors,
38+
isTranslated,
39+
} = await getPageData({
40+
locale,
41+
slug,
42+
// TODO: Address component typing error here (flip `FC` types to prop object types)
43+
// @ts-expect-error Incompatible component function signatures
44+
components: { ...mdComponents, ...docsComponents },
45+
layout,
46+
})
47+
48+
// Get i18n messages
49+
const allMessages = await getMessages({ locale })
50+
const requiredNamespaces = getRequiredNamespacesForPage(slug, layout)
51+
const messages = pick(allMessages, requiredNamespaces)
52+
53+
return (
54+
<I18nProvider locale={locale} messages={messages}>
55+
<DocsLayout
56+
slug={slug}
57+
frontmatter={frontmatter}
58+
tocItems={tocItems}
59+
lastEditLocaleTimestamp={lastEditLocaleTimestamp}
60+
contributors={contributors}
61+
contentNotTranslated={!isTranslated}
62+
>
63+
{content}
64+
</DocsLayout>
65+
</I18nProvider>
66+
)
67+
}
68+
69+
export async function generateStaticParams() {
70+
const slugs = await getPostSlugs("/developers/docs")
71+
72+
// Generate page paths for each supported locale
73+
return LOCALES_CODES.flatMap((locale) =>
74+
slugs.map((slug) => {
75+
return {
76+
// Splitting nested paths to generate proper slug
77+
doc: slug.replace("/developers/docs", "").split("/").slice(1),
78+
locale,
79+
}
80+
})
81+
)
82+
}
83+
84+
export async function generateMetadata({
85+
params,
86+
}: {
87+
params: Promise<{ locale: string; doc: string[] }>
88+
}) {
89+
const { locale, doc } = await params
90+
const slug = ["developers/docs", ...(doc || [])]
91+
92+
return await getMdMetadata({
93+
locale,
94+
slug,
95+
})
96+
}
97+
98+
export const dynamicParams = false
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
import { join } from "path"
2+
3+
import pick from "lodash.pick"
4+
import { getMessages, setRequestLocale } from "next-intl/server"
5+
6+
import I18nProvider from "@/components/I18nProvider"
7+
import mdComponents from "@/components/MdComponents"
8+
9+
import { dateToString } from "@/lib/utils/date"
10+
import { getPostSlugs } from "@/lib/utils/md"
11+
import { getRequiredNamespacesForPage } from "@/lib/utils/translations"
12+
13+
import { LOCALES_CODES } from "@/lib/constants"
14+
15+
import { TutorialLayout, tutorialsComponents } from "@/layouts"
16+
import { getPageData } from "@/lib/md/data"
17+
import { getMdMetadata } from "@/lib/md/metadata"
18+
19+
export default async function Page({
20+
params,
21+
}: {
22+
params: Promise<{ locale: string; tutorial: string[] }>
23+
}) {
24+
const { locale, tutorial: tutorialArray } = await params
25+
26+
// Enable static rendering
27+
setRequestLocale(locale)
28+
29+
const slug = join("developers/tutorials", ...tutorialArray)
30+
31+
const layout = "tutorial"
32+
33+
const {
34+
content,
35+
frontmatter,
36+
tocItems,
37+
lastEditLocaleTimestamp,
38+
contributors,
39+
isTranslated,
40+
} = await getPageData({
41+
locale,
42+
slug,
43+
// TODO: Address component typing error here (flip `FC` types to prop object types)
44+
// @ts-expect-error Incompatible component function signatures
45+
components: { ...mdComponents, ...tutorialsComponents },
46+
layout,
47+
})
48+
49+
// If the page has a published date, format it
50+
if ("published" in frontmatter) {
51+
frontmatter.published = dateToString(frontmatter.published)
52+
}
53+
54+
// Get i18n messages
55+
const allMessages = await getMessages({ locale })
56+
const requiredNamespaces = getRequiredNamespacesForPage(slug, layout)
57+
const messages = pick(allMessages, requiredNamespaces)
58+
59+
return (
60+
<I18nProvider locale={locale} messages={messages}>
61+
<TutorialLayout
62+
slug={slug}
63+
frontmatter={frontmatter}
64+
tocItems={tocItems}
65+
lastEditLocaleTimestamp={lastEditLocaleTimestamp}
66+
contributors={contributors}
67+
contentNotTranslated={!isTranslated}
68+
timeToRead={2}
69+
>
70+
{content}
71+
</TutorialLayout>
72+
</I18nProvider>
73+
)
74+
}
75+
76+
export async function generateStaticParams() {
77+
const slugs = await getPostSlugs("/developers/tutorials")
78+
79+
return LOCALES_CODES.flatMap((locale) =>
80+
slugs.map((slug) => ({
81+
tutorial: slug.replace("/developers/tutorials", "").split("/").slice(1),
82+
locale,
83+
}))
84+
)
85+
}
86+
87+
export async function generateMetadata({
88+
params,
89+
}: {
90+
params: Promise<{ locale: string; tutorial: string[] }>
91+
}) {
92+
const { locale, tutorial } = await params
93+
const slug = ["developers/tutorials", ...(tutorial || [])]
94+
95+
return await getMdMetadata({
96+
locale,
97+
slug,
98+
})
99+
}
100+
101+
export const dynamicParams = false

0 commit comments

Comments
 (0)