From efd95ec54ebe3669203bdbc0f8e4008fd5ce868f Mon Sep 17 00:00:00 2001 From: Dimitri POSTOLOV Date: Fri, 22 Jul 2022 16:06:10 +0200 Subject: [PATCH] fix(nextra): allow to contain dots in page filenames (#546) * fix(nextra): allow to contain dots in page filenames * add changeset --- .changeset/two-dots-play.md | 5 + examples/swr-site/next.config.js | 3 +- .../advanced/file-name.with.DOTS.en-US.mdx | 1 + .../advanced/file-name.with.DOTS.es-ES.mdx | 1 + .../docs/advanced/file-name.with.DOTS.ja.mdx | 1 + .../docs/advanced/file-name.with.DOTS.ko.mdx | 1 + .../docs/advanced/file-name.with.DOTS.ru.mdx | 1 + .../advanced/file-name.with.DOTS.zh-CN.mdx | 1 + .../pages/docs/advanced/meta.en-US.json | 3 +- .../pages/docs/advanced/meta.es-ES.json | 3 +- .../swr-site/pages/docs/advanced/meta.ja.json | 3 +- .../swr-site/pages/docs/advanced/meta.ko.json | 3 +- .../swr-site/pages/docs/advanced/meta.ru.json | 3 +- .../pages/docs/advanced/meta.zh-CN.json | 3 +- ...map.spec.ts.snap => page-map.test.ts.snap} | 12 ++ .../{page-map.spec.ts => page-map.test.ts} | 0 packages/nextra/__test__/utils.test.ts | 108 ++++++++++++++++++ packages/nextra/src/constants.ts | 5 + packages/nextra/src/index.js | 4 +- packages/nextra/src/loader.ts | 18 ++- packages/nextra/src/locales.ts | 7 +- packages/nextra/src/page-map.ts | 28 +++-- packages/nextra/src/plugin.ts | 56 ++++----- packages/nextra/src/utils.ts | 33 +++--- 24 files changed, 216 insertions(+), 87 deletions(-) create mode 100644 .changeset/two-dots-play.md create mode 100644 examples/swr-site/pages/docs/advanced/file-name.with.DOTS.en-US.mdx create mode 100644 examples/swr-site/pages/docs/advanced/file-name.with.DOTS.es-ES.mdx create mode 100644 examples/swr-site/pages/docs/advanced/file-name.with.DOTS.ja.mdx create mode 100644 examples/swr-site/pages/docs/advanced/file-name.with.DOTS.ko.mdx create mode 100644 examples/swr-site/pages/docs/advanced/file-name.with.DOTS.ru.mdx create mode 100644 examples/swr-site/pages/docs/advanced/file-name.with.DOTS.zh-CN.mdx rename packages/nextra/__test__/__snapshots__/{page-map.spec.ts.snap => page-map.test.ts.snap} (97%) rename packages/nextra/__test__/{page-map.spec.ts => page-map.test.ts} (100%) create mode 100644 packages/nextra/__test__/utils.test.ts create mode 100644 packages/nextra/src/constants.ts diff --git a/.changeset/two-dots-play.md b/.changeset/two-dots-play.md new file mode 100644 index 0000000000..9ca118a32b --- /dev/null +++ b/.changeset/two-dots-play.md @@ -0,0 +1,5 @@ +--- +'nextra': patch +--- + +fix(nextra): allow to contain dots in page filenames diff --git a/examples/swr-site/next.config.js b/examples/swr-site/next.config.js index 75172c6b25..1ffbece53c 100644 --- a/examples/swr-site/next.config.js +++ b/examples/swr-site/next.config.js @@ -9,8 +9,7 @@ const withNextra = require("nextra")({ module.exports = withNextra({ i18n: { - // locales: ["en-US", "zh-CN", "es-ES", "ja", "ko", "ru"], - locales: ["en-US", "zh-CN"], + locales: ["en-US", "es-ES", "ja", "ko", "ru", "zh-CN"], defaultLocale: "en-US", }, redirects: () => { diff --git a/examples/swr-site/pages/docs/advanced/file-name.with.DOTS.en-US.mdx b/examples/swr-site/pages/docs/advanced/file-name.with.DOTS.en-US.mdx new file mode 100644 index 0000000000..1a5ad30352 --- /dev/null +++ b/examples/swr-site/pages/docs/advanced/file-name.with.DOTS.en-US.mdx @@ -0,0 +1 @@ +# You can add dots in your file names diff --git a/examples/swr-site/pages/docs/advanced/file-name.with.DOTS.es-ES.mdx b/examples/swr-site/pages/docs/advanced/file-name.with.DOTS.es-ES.mdx new file mode 100644 index 0000000000..6d14fa5942 --- /dev/null +++ b/examples/swr-site/pages/docs/advanced/file-name.with.DOTS.es-ES.mdx @@ -0,0 +1 @@ +# Puede agregar puntos en los nombres de sus archivos diff --git a/examples/swr-site/pages/docs/advanced/file-name.with.DOTS.ja.mdx b/examples/swr-site/pages/docs/advanced/file-name.with.DOTS.ja.mdx new file mode 100644 index 0000000000..b3d4e5b63f --- /dev/null +++ b/examples/swr-site/pages/docs/advanced/file-name.with.DOTS.ja.mdx @@ -0,0 +1 @@ +# ファイル名にドットを追加できます diff --git a/examples/swr-site/pages/docs/advanced/file-name.with.DOTS.ko.mdx b/examples/swr-site/pages/docs/advanced/file-name.with.DOTS.ko.mdx new file mode 100644 index 0000000000..df3d5cac2a --- /dev/null +++ b/examples/swr-site/pages/docs/advanced/file-name.with.DOTS.ko.mdx @@ -0,0 +1 @@ +# 파일 이름에 점을 추가할 수 있습니다. diff --git a/examples/swr-site/pages/docs/advanced/file-name.with.DOTS.ru.mdx b/examples/swr-site/pages/docs/advanced/file-name.with.DOTS.ru.mdx new file mode 100644 index 0000000000..75acc21de6 --- /dev/null +++ b/examples/swr-site/pages/docs/advanced/file-name.with.DOTS.ru.mdx @@ -0,0 +1 @@ +# Вы можете добавить точки в имя своих файлов diff --git a/examples/swr-site/pages/docs/advanced/file-name.with.DOTS.zh-CN.mdx b/examples/swr-site/pages/docs/advanced/file-name.with.DOTS.zh-CN.mdx new file mode 100644 index 0000000000..020b40603c --- /dev/null +++ b/examples/swr-site/pages/docs/advanced/file-name.with.DOTS.zh-CN.mdx @@ -0,0 +1 @@ +# 您可以在文件名中添加点 diff --git a/examples/swr-site/pages/docs/advanced/meta.en-US.json b/examples/swr-site/pages/docs/advanced/meta.en-US.json index 2fe803d04e..f46023fe70 100644 --- a/examples/swr-site/pages/docs/advanced/meta.en-US.json +++ b/examples/swr-site/pages/docs/advanced/meta.en-US.json @@ -11,5 +11,6 @@ "cache": "Cache", "performance": "Performance", "react-native": "React Native", - "more": "More: A Super Super Super Super Long Directory" + "more": "More: A Super Super Super Super Long Directory", + "file-name.with.DOTS": "Filenames with dots" } diff --git a/examples/swr-site/pages/docs/advanced/meta.es-ES.json b/examples/swr-site/pages/docs/advanced/meta.es-ES.json index 210f6d38e6..6908490107 100644 --- a/examples/swr-site/pages/docs/advanced/meta.es-ES.json +++ b/examples/swr-site/pages/docs/advanced/meta.es-ES.json @@ -1,5 +1,6 @@ { "cache": "Cache", "performance": "Rendimiento", - "react-native": "React Native" + "react-native": "React Native", + "file-name.with.DOTS": "Nombres de archivos con puntos" } diff --git a/examples/swr-site/pages/docs/advanced/meta.ja.json b/examples/swr-site/pages/docs/advanced/meta.ja.json index d7537302ef..5c3373df88 100644 --- a/examples/swr-site/pages/docs/advanced/meta.ja.json +++ b/examples/swr-site/pages/docs/advanced/meta.ja.json @@ -1,5 +1,6 @@ { "cache": "キャッシュ", "performance": "パフォーマンス", - "react-native": "React Native" + "react-native": "React Native", + "file-name.with.DOTS": "ドット付きのファイル名" } diff --git a/examples/swr-site/pages/docs/advanced/meta.ko.json b/examples/swr-site/pages/docs/advanced/meta.ko.json index b513a463e4..0b97abb4a0 100644 --- a/examples/swr-site/pages/docs/advanced/meta.ko.json +++ b/examples/swr-site/pages/docs/advanced/meta.ko.json @@ -1,5 +1,6 @@ { "cache": "캐시", "performance": "성능", - "react-native": "React Native" + "react-native": "React Native", + "file-name.with.DOTS": "점이 있는 파일 이름" } diff --git a/examples/swr-site/pages/docs/advanced/meta.ru.json b/examples/swr-site/pages/docs/advanced/meta.ru.json index b76fa6172f..885cc59e95 100644 --- a/examples/swr-site/pages/docs/advanced/meta.ru.json +++ b/examples/swr-site/pages/docs/advanced/meta.ru.json @@ -1,5 +1,6 @@ { "cache": "Кеш", "performance": "Производительность", - "react-native": "React Native" + "react-native": "React Native", + "file-name.with.DOTS": "Имя файла может содержать точки" } diff --git a/examples/swr-site/pages/docs/advanced/meta.zh-CN.json b/examples/swr-site/pages/docs/advanced/meta.zh-CN.json index ece5ba4576..0130d21838 100644 --- a/examples/swr-site/pages/docs/advanced/meta.zh-CN.json +++ b/examples/swr-site/pages/docs/advanced/meta.zh-CN.json @@ -1,5 +1,6 @@ { "cache": "缓存", "performance": "性能", - "react-native": "React Native" + "react-native": "React Native", + "file-name.with.DOTS": "带点的文件名" } diff --git a/packages/nextra/__test__/__snapshots__/page-map.spec.ts.snap b/packages/nextra/__test__/__snapshots__/page-map.test.ts.snap similarity index 97% rename from packages/nextra/__test__/__snapshots__/page-map.spec.ts.snap rename to packages/nextra/__test__/__snapshots__/page-map.test.ts.snap index 78843e1b86..0ac2d3799c 100644 --- a/packages/nextra/__test__/__snapshots__/page-map.spec.ts.snap +++ b/packages/nextra/__test__/__snapshots__/page-map.test.ts.snap @@ -47,6 +47,11 @@ exports[`Page Process > pageMap en-US 1`] = ` "name": "cache", "route": "/docs/advanced/cache", }, + { + "locale": "en-US", + "name": "file-name.with.DOTS", + "route": "/docs/advanced/file-name.with.DOTS", + }, { "locale": "en-US", "meta": { @@ -60,6 +65,7 @@ exports[`Page Process > pageMap en-US 1`] = ` "type": "separator", }, "cache": "Cache", + "file-name.with.DOTS": "Filenames with dots", "more": "More: A Super Super Super Super Long Directory", "performance": "Performance", "react-native": "React Native", @@ -392,10 +398,16 @@ exports[`Page Process > pageMap zh-CN 1`] = ` "name": "cache", "route": "/docs/advanced/cache", }, + { + "locale": "zh-CN", + "name": "file-name.with.DOTS", + "route": "/docs/advanced/file-name.with.DOTS", + }, { "locale": "zh-CN", "meta": { "cache": "缓存", + "file-name.with.DOTS": "带点的文件名", "performance": "性能", "react-native": "React Native", }, diff --git a/packages/nextra/__test__/page-map.spec.ts b/packages/nextra/__test__/page-map.test.ts similarity index 100% rename from packages/nextra/__test__/page-map.spec.ts rename to packages/nextra/__test__/page-map.test.ts diff --git a/packages/nextra/__test__/utils.test.ts b/packages/nextra/__test__/utils.test.ts new file mode 100644 index 0000000000..9fd1d28761 --- /dev/null +++ b/packages/nextra/__test__/utils.test.ts @@ -0,0 +1,108 @@ +import { describe, it, expect } from 'vitest' +import { parseFileName } from '../src/utils' + +describe('Utils', () => { + describe('parseFileName()', () => { + describe('extension', () => { + it('parse different extensions', () => { + expect(parseFileName('./foo.bar.baz-qux.zh-CN.js')).toEqual({ + name: 'foo.bar.baz-qux', + locale: 'zh-CN', + ext: '.js' + }) + expect(parseFileName('MY_FOLDER/foo.bar.qux.mtsx')).toEqual({ + name: 'foo.bar.qux', + locale: '', + ext: '.mtsx' + }) + expect(parseFileName('docs-folder/foo.bar.ba-qu.zh-CN.json5')).toEqual({ + name: 'foo.bar.ba-qu', + locale: 'zh-CN', + ext: '.json5' + }) + expect(parseFileName('hello/foo.bar.ba-qu.txt')).toEqual({ + name: 'foo.bar.ba-qu', + locale: '', + ext: '.txt' + }) + }) + + it('parse no extension', () => { + expect(parseFileName('bazru-RU')).toEqual({ + name: 'bazru-RU', + locale: '', + ext: '' + }) + }) + }) + + describe('locale', () => { + it('with 2 letters', () => { + expect(parseFileName('foo.ru.mdx')).toEqual({ + name: 'foo', + locale: 'ru', + ext: '.mdx' + }) + }) + + it('with 4 letters', () => { + expect(parseFileName('foo.en-US.jsx')).toEqual({ + name: 'foo', + locale: 'en-US', + ext: '.jsx' + }) + }) + + it('not with incorrect case', () => { + const fileNames = [ + 'foo.Ru.mdx', + 'foo.rU.mdx', + 'foo.RU.mdx', + + 'foo.Ru-ru.mdx', + 'foo.Ru-Ru.mdx', + 'foo.Ru-rU.mdx', + 'foo.Ru-RU.mdx', + + 'foo.rU-ru.mdx', + 'foo.rU-Ru.mdx', + 'foo.rU-rU.mdx', + 'foo.rU-RU.mdx', + + 'foo.RU-ru.mdx', + 'foo.RU-Ru.mdx', + 'foo.RU-rU.mdx', + 'foo.RU-RU.mdx', + + 'foo.ru-ru.mdx', + 'foo.ru-Ru.mdx', + 'foo.ru-rU.mdx' + ] + + for (const fileName of fileNames) { + expect(parseFileName(fileName).locale).toBe('') + } + }) + + it('not without leading dot', () => { + expect(parseFileName('fooen-US.mdx')).toEqual({ + name: 'fooen-US', + locale: '', + ext: '.mdx' + }) + }) + + it('not with underscore', () => { + expect(parseFileName('foo.en_US.mdx').locale).toBe('') + }) + + it('not for 5 letters', () => { + expect(parseFileName('foo.en-USZ.json')).toEqual({ + name: 'foo.en-USZ', + locale: '', + ext: '.json' + }) + }) + }) + }) +}) diff --git a/packages/nextra/src/constants.ts b/packages/nextra/src/constants.ts new file mode 100644 index 0000000000..1054286461 --- /dev/null +++ b/packages/nextra/src/constants.ts @@ -0,0 +1,5 @@ +export const MARKDOWN_EXTENSION_REGEX = /\.mdx?$/ + +export const IS_PRODUCTION = process.env.NODE_ENV === 'production' + +export const LOCALE_REGEX = /\.([a-z]{2}(-[A-Z]{2})?)$/ diff --git a/packages/nextra/src/index.js b/packages/nextra/src/index.js index be3618c3cb..6275159ee2 100644 --- a/packages/nextra/src/index.js +++ b/packages/nextra/src/index.js @@ -1,8 +1,8 @@ import { NextraPlugin, pageMapCache } from './plugin' +import { MARKDOWN_EXTENSION_REGEX } from './constants' const defaultExtensions = ['js', 'jsx', 'ts', 'tsx'] const markdownExtensions = ['md', 'mdx'] -const markdownExtensionTest = /\.mdx?$/ module.exports = (...args) => @@ -38,7 +38,7 @@ module.exports = } config.module.rules.push({ - test: markdownExtensionTest, + test: MARKDOWN_EXTENSION_REGEX, use: [ options.defaultLoaders.babel, { diff --git a/packages/nextra/src/loader.ts b/packages/nextra/src/loader.ts index 060c289346..2da3d393cb 100644 --- a/packages/nextra/src/loader.ts +++ b/packages/nextra/src/loader.ts @@ -7,13 +7,11 @@ import { LoaderContext } from 'webpack' import { Repository } from '@napi-rs/simple-git' import { addPage } from './content-dump' -import { getLocaleFromFilename } from './utils' +import { parseFileName } from './utils' import { compileMdx } from './compile' import { getPageMap, findPagesDir } from './page-map' import { collectFiles } from './plugin' - -const extension = /\.mdx?$/ -const isProductionBuild = process.env.NODE_ENV === 'production' +import { MARKDOWN_EXTENSION_REGEX, IS_PRODUCTION } from './constants' // TODO: create this as a webpack plugin. const indexContentEmitted = new Set() @@ -55,15 +53,15 @@ async function loader( return '' } - const filename = resourcePath.slice(resourcePath.lastIndexOf('/') + 1) - const fileLocale = getLocaleFromFilename(filename) + const filename = path.basename(resourcePath) + const fileLocale = parseFileName(filename).locale // Check if there's a theme provided if (!theme) { throw new Error('No Nextra theme found!') } - const { items: pageMapResult, fileMap } = isProductionBuild + const { items: pageMapResult, fileMap } = IS_PRODUCTION ? pageMapCache.get()! : await collectFiles(pagesDir, '/') @@ -74,7 +72,7 @@ async function loader( defaultLocale ) - if (!isProductionBuild) { + if (!IS_PRODUCTION) { // Add the entire directory `pages` as the dependency // so we can generate the correct page map. context.addContextDependency(pagesDir) @@ -106,7 +104,7 @@ async function loader( layoutConfig = slash(path.resolve(layoutConfig)) } - if (isProductionBuild && indexContentEmitted.has(filename)) { + if (IS_PRODUCTION && indexContentEmitted.has(filename)) { unstable_flexsearch = false } @@ -124,7 +122,7 @@ async function loader( if (unstable_flexsearch) { // We only add .MD and .MDX contents - if (extension.test(filename) && data.searchable !== false) { + if (MARKDOWN_EXTENSION_REGEX.test(filename) && data.searchable !== false) { addPage({ fileLocale: fileLocale || 'default', route, diff --git a/packages/nextra/src/locales.ts b/packages/nextra/src/locales.ts index 6b3808f5bd..0750481551 100644 --- a/packages/nextra/src/locales.ts +++ b/packages/nextra/src/locales.ts @@ -1,8 +1,6 @@ import { NextResponse } from 'next/server' import type { NextRequest } from 'next/server' -const PUBLIC_FILE = /\.(.*)$/ - type LegacyMiddlewareCookies = { [key: string]: string } type StableMiddlewareCookies = Map @@ -20,9 +18,8 @@ export function locales(request: NextRequest) { const { nextUrl } = request const shouldHandleLocale = - !PUBLIC_FILE.test(nextUrl.pathname) && - !nextUrl.pathname.includes('/api/') && - !nextUrl.pathname.includes('/_next/') && + !/^\/(api|_next)\//.test(nextUrl.pathname) && + !/\.(jpe?g|svg|png|webmanifest)$/.test(nextUrl.pathname) && nextUrl.locale !== '' if (!shouldHandleLocale) return diff --git a/packages/nextra/src/page-map.ts b/packages/nextra/src/page-map.ts index 60e57a0bc9..2ae4c8bc82 100644 --- a/packages/nextra/src/page-map.ts +++ b/packages/nextra/src/page-map.ts @@ -1,11 +1,9 @@ import { PageMapItem } from './types' -import { getLocaleFromFilename, existsSync } from './utils' +import { parseFileName, existsSync } from './utils' import path from 'path' import filterRouteLocale from './filter-route-locale' -export const extension = /\.mdx?$/ -export const metaExtension = /meta\.?([a-zA-Z-]+)?\.json/ -export function findPagesDir(dir: string = process.cwd()): string { +export function findPagesDir(dir = process.cwd()): string { // prioritize ./pages over ./src/pages if (existsSync(path.join(dir, 'pages'))) return 'pages' if (existsSync(path.join(dir, 'src/pages'))) return 'src/pages' @@ -17,11 +15,11 @@ export function findPagesDir(dir: string = process.cwd()): string { export function getPageMap( currentResourcePath: string, - pageMaps: PageMapItem[], + pageMap: PageMapItem[], fileMap: Record, defaultLocale: string -) { - const activeRouteLocale = getLocaleFromFilename(currentResourcePath) +): [PageMapItem[], string, string] { + const activeRouteLocale = parseFileName(currentResourcePath).locale const pageItem = fileMap[currentResourcePath] const metaPath = path.dirname(currentResourcePath) const metaExtension = activeRouteLocale ? `${activeRouteLocale}.json` : `json` @@ -29,12 +27,12 @@ export function getPageMap( fileMap[`${metaPath}/meta.${metaExtension}`]?.meta?.[pageItem.name] const title = (typeof pageMeta === 'string' ? pageMeta : pageMeta?.title) || pageItem.name - if (activeRouteLocale) { - return [ - filterRouteLocale(pageMaps, activeRouteLocale, defaultLocale), - fileMap[currentResourcePath].route, - title - ] - } - return [pageMaps, fileMap[currentResourcePath].route, title] + + return [ + activeRouteLocale + ? filterRouteLocale(pageMap, activeRouteLocale, defaultLocale) + : pageMap, + pageItem.route, + title + ] } diff --git a/packages/nextra/src/plugin.ts b/packages/nextra/src/plugin.ts index 23a2db046d..149de985fc 100644 --- a/packages/nextra/src/plugin.ts +++ b/packages/nextra/src/plugin.ts @@ -1,29 +1,31 @@ import { NextraConfig, PageMapItem } from './types' import fs from 'graceful-fs' -import util from 'util' -import { getLocaleFromFilename, parseJsonFile, removeExtension } from './utils' +import { promisify } from 'util' +import { parseFileName, parseJsonFile } from './utils' import path from 'path' import slash from 'slash' import grayMatter from 'gray-matter' -import { extension, findPagesDir, metaExtension } from './page-map' +import { findPagesDir } from './page-map' import { Compiler } from 'webpack' import { restoreCache } from './content-dump' -const { readdir, readFile } = fs +import { MARKDOWN_EXTENSION_REGEX } from './constants' + +const readdir = promisify(fs.readdir) +const readFile = promisify(fs.readFile) export async function collectFiles( dir: string, - route: string = '/', + route = '/', fileMap: Record = {} ): Promise<{ items: PageMapItem[]; fileMap: Record }> { - const files = await util.promisify(readdir)(dir, { withFileTypes: true }) + const files = await readdir(dir, { withFileTypes: true }) const items = ( await Promise.all( files.map(async f => { const filePath = path.resolve(dir, f.name) - const fileRoute = slash( - path.join(route, removeExtension(f.name).replace(/^index$/, '')) - ) + const { name, locale, ext } = parseFileName(f.name) + const fileRoute = slash(path.join(route, name.replace(/^index$/, ''))) if (f.isDirectory()) { if (fileRoute === '/api') return null @@ -38,34 +40,22 @@ export async function collectFiles( children, route: fileRoute } - } else if (extension.test(f.name)) { - const locale = getLocaleFromFilename(f.name) - const fileContents = await util.promisify(readFile)(filePath, 'utf-8') - const { data } = grayMatter(fileContents) - if (Object.keys(data).length) { - fileMap[filePath] = { - name: removeExtension(f.name), - route: fileRoute, - frontMatter: data, - locale - } - return fileMap[filePath] - } + } else if (MARKDOWN_EXTENSION_REGEX.test(ext)) { + const content = await readFile(filePath, 'utf8') + const { data } = grayMatter(content) fileMap[filePath] = { - name: removeExtension(f.name), + name, route: fileRoute, - locale + locale, + ...(Object.keys(data).length && { frontMatter: data }) } return fileMap[filePath] - } else if (metaExtension.test(f.name)) { - const content = await util.promisify(readFile)(filePath, 'utf-8') - const meta = parseJsonFile(content, filePath) - // @ts-expect-error since metaExtension.test(f.name) === true - const locale = f.name.match(metaExtension)[1] + } else if (ext === '.json' && name === 'meta') { + const content = await readFile(filePath, 'utf8') fileMap[filePath] = { name: 'meta.json', - meta, - locale + locale, + meta: parseJsonFile(content, filePath) } return fileMap[filePath] } @@ -81,16 +71,20 @@ export async function collectFiles( export class PageMapCache { public cache: { items: PageMapItem[]; fileMap: Record } | null + constructor() { this.cache = { items: [], fileMap: {} } } + set(data: { items: PageMapItem[]; fileMap: Record }) { this.cache!.items = data.items this.cache!.fileMap = data.fileMap } + clear() { this.cache = null } + get() { return this.cache } diff --git a/packages/nextra/src/utils.ts b/packages/nextra/src/utils.ts index 36de082202..18605c7409 100644 --- a/packages/nextra/src/utils.ts +++ b/packages/nextra/src/utils.ts @@ -1,25 +1,26 @@ -import fs from 'fs'; +import fs from 'fs' import path from 'path' +import { LOCALE_REGEX } from './constants' -export function getLocaleFromFilename(name: string): string | void { - const localeRegex = /\.([a-zA-Z-]+)?\.(mdx?|jsx?|json)$/ - const match = name.match(localeRegex) - if (match) return match[1] -} - -export function removeExtension(name: string): string { - const match = name.match(/^([^.]+)/) - return match !== null ? match[1] : '' -} - -export function getFileName(resourcePath: string): string { - return removeExtension(path.basename(resourcePath)) +export function parseFileName(filePath: string): { + name: string + locale: string + ext: string +} { + // Get file name and extension from file path + const { name, ext } = path.parse(filePath) + const locale = name.match(LOCALE_REGEX)?.[1] || '' + return { + name: locale ? name.replace(LOCALE_REGEX, '') : name, + locale, + ext + } } -export const parseJsonFile: ( +export const parseJsonFile = ( content: string, path: string -) => Record = (content: string, path: string) => { +): Record => { try { return JSON.parse(content) } catch (err) {