Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,11 @@ jobs:
with:
args: |
--root-dir $PWD/dist
--fallback-extensions html
--exclude-path dist/llms.txt
--exclude-path dist/llms/
--exclude-private
--exclude-loopback
--remap "https://expressjs\.com\/((?:[^\/]+\/)*[^\/\.]+)\/?$ file://$PWD/dist/\$1/index.html"
--remap "https://expressjs\.com\/(.*\.html)$ file://$PWD/dist/\$1"
--remap "^https://expressjs\.com\/ file://$PWD/dist/"
dist/
fail: true
2 changes: 1 addition & 1 deletion .lycheeignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
^https://github\.com/

# Exclude 404 pages
dist/(.*/)?404((/index)?\.html|/)$
dist/(.*/)?404((/index)?\.html|/)?$

# Exclude Open Collective links
^https://opencollective\.com/
Expand Down
3 changes: 3 additions & 0 deletions astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ const site = NETLIFY_PREVIEW_SITE || 'https://expressjs.com';
export default defineConfig({
redirects,
site,
build: {
format: 'file',
},
markdown: {
Comment on lines +26 to 29

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, quite a bit of time has passed. Other than the .html extensions, have we run into any additional issues?

To be honest, I feel like we should move forward with the current approach, especially considering the redirects that have already been put in place (which I don't have the ability to remove anyway).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, quite a bit of time has passed. Other than the .html extensions, have we run into any additional issues?

I don't think so. The thing that I found after creating this PR is that it just works with --include-fragments in lychee, which I think that we should enable. Fragment checking should also work with the current directory based version with more remapping.

To be honest, I feel like we should move forward with the current approach, especially considering the redirects that have already been put in place (which I don't have the ability to remove anyway).

The file format works with and without redirects (/page and /page.html just work, /page/ receives a 301 redirect to /page).

I initially wrote that this also lets us avoid 301s that add /, but while most links in menu don't have a trailing / (/api/express/ is the only one ending with /), links in content now have / appended since #2193 was merged (2 days ago).

// Link localization (Markdown links + raw HTML/JSX `<a href>`). Configuration —
// localized sections, versioned sections, default version, and the "global" pages
Expand Down
2 changes: 1 addition & 1 deletion src/components/patterns/Sidebar/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export type SubmenuData = {
};

export function normalizePath(path: string): string {
return path.replace(/\/$/, '');
return path.replace(/(?:\/|\.html)$/, '');
}

export function isVersioned(versioned: VersionPrefix[] | undefined, version: string): boolean {
Expand Down
12 changes: 7 additions & 5 deletions src/i18n/utils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { ui, defaultLang, languages } from './locales';

export function getLangFromUrl(url: URL) {
const [, lang] = url.pathname.split('/');
const strippedPathname = url.pathname.replace(/\.html$/, '');
const [, lang] = strippedPathname.split('/');
if (lang in ui) return lang as keyof typeof ui;
return defaultLang;
}
Expand Down Expand Up @@ -34,7 +35,7 @@ export function getLanguageCodes(): string[] {
*/
export function createLanguagePathRegex(): RegExp {
const codes = getLanguageCodes().join('|');
return new RegExp(`^/(${codes})/`);
return new RegExp(`^/(${codes})(?:/|$)`);
}

/**
Expand All @@ -43,9 +44,10 @@ export function createLanguagePathRegex(): RegExp {
export function replaceLanguageInPath(path: string, newLang: string): string {
const langRegex = createLanguagePathRegex();

if (langRegex.test(path)) {
return path.replace(langRegex, `/${newLang}/`);
const strippedPath = path.replace(/\.html$/, '');
if (langRegex.test(strippedPath)) {
return strippedPath.replace(langRegex, `/${newLang}/`);
} else {
return `/${newLang}${path}`;
return `/${newLang}${strippedPath}`;
}
}
4 changes: 2 additions & 2 deletions src/layouts/Layout.astro
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ const pageTitle = title
? `${title} · Express.js`
: 'Express.js · Node.js web application framework';

const canonicalUrl = new URL(Astro.url.pathname, Astro.site || Astro.url.origin);
const pathname = Astro.url.pathname.replace(/\.html$/, '');
const canonicalUrl = new URL(pathname, Astro.site || Astro.url.origin);

const pathname = Astro.url.pathname.replace(/\/$/, '');
const segments = pathname.split('/').filter(Boolean);
const langSegment = segments[0] || 'en';
const restSegments = segments.slice(1);
Expand Down
2 changes: 1 addition & 1 deletion src/utils/content.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ function resolveLabel(t: (key: string) => string, labelKey?: string, segment?: s
* Build breadcrumbs
*/
export function buildBreadcrumbs(pathname: string, t: (key: string) => string): BreadcrumbItem[] {
const segments = pathname.replace(/^\/|\/$/g, '').split('/');
const segments = pathname.replace(/^\/|\/$|\.html$/g, '').split('/');

// Need at least lang + one content segment
if (segments.length < 2) return [];
Expand Down
Loading