Skip to content

Commit c65cdeb

Browse files
committed
tmp
1 parent fcf2be1 commit c65cdeb

File tree

12 files changed

+204
-162
lines changed

12 files changed

+204
-162
lines changed

.github/dependabot.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,12 @@ updates:
4747
- '@shikijs/*'
4848
- '@mdx-js/*'
4949
- hast-util-*
50+
- estree-util-*
5051
- rehype-*
5152
- remark-*
5253
- shiki
5354
- sval
5455
- unist-util-*
55-
- vfile
56-
- vfile-*
5756
- reading-time
5857
- twoslash
5958
orama:
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ title: Run JavaScript Everywhere
33
layout: home
44
---
55

6+
{
7+
// The `/en/page.mdx` file has to exist for localization (See https://github.com/vercel/next.js/discussions/87976)
8+
// TODO(@avivkeller): Create a minimal reproduction
9+
}
10+
611
<section>
712
<WithBadgeGroup section="index" />
813

apps/site/app/sitemap.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@ import { availableLocaleCodes, defaultLocale } from '@node-core/website-i18n';
33
import { BASE_PATH } from '#site/next.constants.mjs';
44
import { BASE_URL } from '#site/next.constants.mjs';
55
import { EXTERNAL_LINKS_SITEMAP } from '#site/next.constants.mjs';
6-
import { BLOG_DYNAMIC_ROUTES } from '#site/next.dynamic.constants.mjs';
7-
import { dynamicRouter } from '#site/next.dynamic.mjs';
6+
import { getBlogSitemapData } from '#site/util/blog';
87

98
import type { MetadataRoute } from 'next';
109

10+
import { getAllRoutes } from '#site/util/router';
11+
1112
// This is the combination of the Application Base URL and Base PATH
1213
const baseUrlAndPath = `${BASE_URL}${BASE_PATH}`;
1314

@@ -21,20 +22,19 @@ const getAlternatePath = (r: string, locales: Array<string>) =>
2122

2223
// This allows us to generate a `sitemap.xml` file dynamically based on the needs of the Node.js Website
2324
const sitemap = async (): Promise<MetadataRoute.Sitemap> => {
24-
// Gets a list of all statically available routes
25-
const routes = await dynamicRouter.getAllRoutes();
25+
const routes = await getAllRoutes();
2626

2727
const currentDate = new Date().toISOString();
2828

2929
const getSitemapEntry = (r: string, locales: Array<string> = []) => ({
30-
url: `${baseUrlAndPath}/${defaultLocale.code}/${r}`,
30+
url: `${baseUrlAndPath}/${defaultLocale.code}${r}`,
3131
lastModified: currentDate,
3232
changeFrequency: 'always' as const,
3333
alternates: { languages: getAlternatePath(r, locales) },
3434
});
3535

3636
const staticPaths = routes.map(r => getSitemapEntry(r, nonDefaultLocales));
37-
const blogPaths = BLOG_DYNAMIC_ROUTES.map(r => getSitemapEntry(`blog/${r}`));
37+
const blogPaths = getBlogSitemapData().map(r => getSitemapEntry(`blog/${r}`));
3838
const externalPaths = EXTERNAL_LINKS_SITEMAP.map(r => getSitemapEntry(r));
3939

4040
return [...staticPaths, ...blogPaths, ...externalPaths];

apps/site/mdx/plugins/layout.mjs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
import { relative, sep, join } from 'node:path';
1+
import { relative, sep } from 'node:path';
22
import { join as posixJoin } from 'node:path/posix';
33

44
import { valueToEstree } from 'estree-util-value-to-estree';
55

6+
import { APP_ROOT } from '#site/util/router.mjs';
7+
68
const createAttribute = (name, value) => ({
79
type: 'JSXAttribute',
810
name: {
@@ -15,10 +17,8 @@ const createAttribute = (name, value) => ({
1517
},
1618
});
1719

18-
const root = join(process.cwd(), 'app');
19-
2020
const getAdditionalAttributes = ({ history: [fullPath], data }) => {
21-
const rel = relative(root, fullPath).replaceAll(sep, '/');
21+
const rel = relative(APP_ROOT, fullPath).replaceAll(sep, '/');
2222

2323
// Filename is the locale-less filepath
2424
const filename = rel.substring(rel.indexOf('/'));

apps/site/next-env.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/// <reference types="next" />
22
/// <reference types="next/image-types/global" />
3-
import './.next/dev/types/routes.d.ts';
3+
import './.next/types/routes.d.ts';
44

55
// NOTE: This file should not be edited
66
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.

apps/site/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161
"github-slugger": "~2.0.0",
6262
"gray-matter": "~4.0.3",
6363
"mdast-util-to-string": "^4.0.0",
64-
"next": "16.0.10",
64+
"next": "16.1.1",
6565
"next-intl": "~4.5.3",
6666
"next-themes": "~0.4.6",
6767
"postcss-calc": "~10.1.1",
@@ -79,7 +79,7 @@
7979
"unist-util-visit": "^5.0.0"
8080
},
8181
"devDependencies": {
82-
"@next/eslint-plugin-next": "16.0.7",
82+
"@next/eslint-plugin-next": "16.1.1",
8383
"@node-core/remark-lint": "workspace:*",
8484
"@opennextjs/cloudflare": "^1.14.7",
8585
"@playwright/test": "^1.57.0",

apps/site/scripts/blog-data/generate.mjs

Lines changed: 59 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,28 @@
1-
// TODO
21
'use strict';
32

43
import { createReadStream } from 'node:fs';
5-
import { basename, extname, join } from 'node:path';
4+
import { basename, join } from 'node:path';
65
import readline from 'node:readline';
76

87
import graymatter from 'gray-matter';
98

10-
import { getMarkdownFiles } from '#site/next.helpers.mjs';
9+
import {
10+
DEFAULT_LOCALE_ROOT,
11+
getAllPages,
12+
pathToRoute,
13+
} from '#site/util/router.mjs';
1114

1215
// gets the current blog path based on local module path
13-
const blogPath = join(process.cwd(), 'pages/en/blog');
16+
const blogPath = join(DEFAULT_LOCALE_ROOT, 'blog');
1417

1518
/**
1619
* This method parses the source (raw) Markdown content into Frontmatter
1720
* and returns basic information for blog posts
1821
*
19-
* @param {string} filename the filename related to the blogpost
22+
* @param {string} route the filename related to the blogpost
2023
* @param {string} source the source markdown content of the blog post
2124
*/
22-
const getFrontMatter = (filename, source) => {
25+
const getFrontMatter = (route, source) => {
2326
const {
2427
title = 'Untitled',
2528
author = 'The Node.js Project',
@@ -36,7 +39,7 @@ const getFrontMatter = (filename, source) => {
3639
const categories = [category, `year-${publishYear}`, 'all'];
3740

3841
// this is the url used for the blog post it based on the category and filename
39-
const slug = `/blog/${category}/${basename(filename, extname(filename))}`;
42+
const slug = `/blog/${category}/${basename(route)}`;
4043

4144
return {
4245
title,
@@ -56,59 +59,64 @@ const getFrontMatter = (filename, source) => {
5659
*/
5760
const generateBlogData = async () => {
5861
// We retrieve the full pathnames of all Blog Posts to read each file individually
59-
const filenames = await getMarkdownFiles(process.cwd(), 'pages/en/blog', [
60-
'**/index.md',
61-
]);
62+
const filenames = await getAllPages({
63+
cwd: blogPath,
64+
});
6265

6366
/**
6467
* This contains the metadata of all available blog categories
6568
*/
6669
const blogCategories = new Set(['all']);
6770

6871
const posts = await Promise.all(
69-
filenames.map(
70-
filename =>
71-
new Promise(resolve => {
72-
// We create a stream for reading a file instead of reading the files
73-
const _stream = createReadStream(join(blogPath, filename));
74-
75-
// We create a readline interface to read the file line-by-line
76-
const _readLine = readline.createInterface({ input: _stream });
77-
78-
let rawFrontmatter = '';
79-
let frontmatterSeparatorsEncountered = 0;
80-
81-
// We read line by line
82-
_readLine.on('line', line => {
83-
rawFrontmatter += `${line}\n`;
84-
85-
// We observe the frontmatter separators
86-
if (line === '---') {
87-
frontmatterSeparatorsEncountered++;
88-
}
89-
90-
// Once we have two separators we close the readLine and the stream
91-
if (frontmatterSeparatorsEncountered === 2) {
92-
_readLine.close();
93-
_stream.close();
94-
}
95-
});
96-
97-
// Then we parse gray-matter on the frontmatter
98-
// This allows us to only read the frontmatter part of each file
99-
// and optimise the read-process as we have thousands of markdown files
100-
_readLine.on('close', () => {
101-
const frontMatterData = getFrontMatter(filename, rawFrontmatter);
102-
103-
frontMatterData.categories.forEach(category => {
104-
// we add the category to the categories set
105-
blogCategories.add(category);
72+
filenames
73+
.filter(n => n !== 'page.md')
74+
.map(
75+
filename =>
76+
new Promise(resolve => {
77+
// We create a stream for reading a file instead of reading the files
78+
const _stream = createReadStream(join(blogPath, filename));
79+
80+
// We create a readline interface to read the file line-by-line
81+
const _readLine = readline.createInterface({ input: _stream });
82+
83+
let rawFrontmatter = '';
84+
let frontmatterSeparatorsEncountered = 0;
85+
86+
// We read line by line
87+
_readLine.on('line', line => {
88+
rawFrontmatter += `${line}\n`;
89+
90+
// We observe the frontmatter separators
91+
if (line === '---') {
92+
frontmatterSeparatorsEncountered++;
93+
}
94+
95+
// Once we have two separators we close the readLine and the stream
96+
if (frontmatterSeparatorsEncountered === 2) {
97+
_readLine.close();
98+
_stream.close();
99+
}
106100
});
107101

108-
resolve(frontMatterData);
109-
});
110-
})
111-
)
102+
// Then we parse gray-matter on the frontmatter
103+
// This allows us to only read the frontmatter part of each file
104+
// and optimise the read-process as we have thousands of markdown files
105+
_readLine.on('close', () => {
106+
const frontMatterData = getFrontMatter(
107+
pathToRoute(filename),
108+
rawFrontmatter
109+
);
110+
111+
frontMatterData.categories.forEach(category => {
112+
// we add the category to the categories set
113+
blogCategories.add(category);
114+
});
115+
116+
resolve(frontMatterData);
117+
});
118+
})
119+
)
112120
);
113121

114122
return {

apps/site/scripts/orama-search/get-documents.mjs

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1-
// TODO
2-
import { readFile, glob } from 'node:fs/promises';
3-
import { join, basename, posix, win32 } from 'node:path';
1+
import { readFile } from 'node:fs/promises';
2+
import { join, basename } from 'node:path';
43

54
import generateReleaseData from '#site/next-data/generators/releaseData.mjs';
6-
import { getRelativePath } from '#site/next.helpers.mjs';
5+
import {
6+
DEFAULT_LOCALE_ROOT,
7+
getAllPages,
8+
pathToRoute,
9+
} from '#site/util/router.mjs';
710

811
import { processDocument } from './process-documents.mjs';
912

@@ -52,23 +55,16 @@ export const getAPIDocs = async () => {
5255
* excluding blog content.
5356
*/
5457
export const getArticles = async () => {
55-
const relativePath = getRelativePath(import.meta.url);
56-
const root = join(relativePath, '..', '..', 'pages', 'en');
57-
5858
// Find all markdown files (excluding blog)
59-
const files = await Array.fromAsync(glob('**/*.{md,mdx}', { cwd: root }));
59+
const files = getAllPages();
6060

6161
// Read content + metadata
6262
return Promise.all(
6363
files
6464
.filter(path => !path.startsWith('blog'))
6565
.map(async path => ({
66-
content: await readFile(join(root, path), 'utf8'),
67-
pathname: path
68-
// Strip the extension
69-
.replace(/\.mdx?$/, '')
70-
// Normalize to a POSIX path
71-
.replaceAll(win32.sep, posix.sep),
66+
content: await readFile(join(DEFAULT_LOCALE_ROOT, path), 'utf8'),
67+
pathname: pathToRoute(path),
7268
}))
7369
);
7470
};

apps/site/util/blog.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,17 @@ export const getBlogData = (cat: BlogCategory, page?: number): BlogPostsRSC => {
7878

7979
return page && page >= 1 ? paginateBlogPosts(posts, page) : posts;
8080
};
81+
82+
export const getBlogSitemapData = () => [
83+
// Provides Routes for all Blog Categories
84+
...blogData.categories,
85+
// Provides Routes for all Blog Categories w/ Pagination
86+
...blogData.categories
87+
// retrieves the amount of pages for each blog category
88+
.map(c => [c, getBlogPosts(c).pagination.pages])
89+
// creates a numeric array for each page and define a pathname for
90+
// each page for a category (i.e. blog/all/page/1)
91+
.map(([c, t]) => [...Array(t).keys()].map(p => `${c}/page/${p + 1}`))
92+
// flattens the array since we have a .map inside another .map
93+
.flat(),
94+
];

apps/site/util/router.mjs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { glob } from 'node:fs/promises';
2+
import { join, relative, sep } from 'node:path';
3+
import { join as posixJoin } from 'node:path/posix';
4+
5+
import { defaultLocale } from '@node-core/website-i18n/index.mjs';
6+
7+
export const APP_ROOT = join(process.cwd(), 'app');
8+
export const DEFAULT_LOCALE_ROOT = join(APP_ROOT, `[${defaultLocale.code}]`);
9+
10+
export const getAllPages = (options = {}) =>
11+
Array.fromAsync(
12+
glob('**/page.{md,mdx}', {
13+
cwd: DEFAULT_LOCALE_ROOT,
14+
...options,
15+
})
16+
);
17+
18+
export const getAllRoutes = async () => (await getAllPages()).map(pathToRoute);
19+
20+
export const pathToRoute = path => {
21+
const rel = relative(APP_ROOT, path).replaceAll(sep, '/');
22+
23+
// Filename is the locale-less filepath
24+
const filename = rel.substring(rel.indexOf('/'));
25+
26+
// Derive a URL-like pathnam
27+
return posixJoin(filename, '..');
28+
};

0 commit comments

Comments
 (0)