Replace/Rename Astro.canonicalURL with new Astro.url helper (#3959)

* add Astro.url

* Add examples of how to create the canonicalURL

Co-authored-by: Matthew Phillips <matthew@skypack.dev>
This commit is contained in:
Fred K. Schott 2022-07-21 10:45:59 -07:00 committed by GitHub
parent d503c5bf3d
commit ddefb172f6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
35 changed files with 101 additions and 117 deletions

View file

@ -0,0 +1,5 @@
---
'astro': patch
---
Deprecate Astro.canonicalURL, in favor of Astro.url instead.

View file

@ -0,0 +1,5 @@
---
'astro': patch
---
Add Astro.url helper for getting the request URL

View file

@ -5,4 +5,5 @@ import preact from '@astrojs/preact';
export default defineConfig({ export default defineConfig({
// Enable the Preact integration to support Preact JSX components. // Enable the Preact integration to support Preact JSX components.
integrations: [preact()], integrations: [preact()],
site: `http://astro.build`
}); });

View file

@ -1,10 +1,9 @@
--- ---
import MainHead from "../components/MainHead.astro"; import MainHead from "../components/MainHead.astro";
import Nav from "../components/Nav.astro"; import Nav from "../components/Nav.astro";
import authorData from "../data/authors.json";
const { content } = Astro.props; const { content } = Astro.props;
let canonicalURL = Astro.canonicalURL; const canonicalURL = new URL(Astro.url.pathname, Astro.site);
--- ---
<html lang={content.lang || "en"}> <html lang={content.lang || "en"}>

View file

@ -4,7 +4,7 @@ import Nav from "../components/Nav.astro";
let title = "About"; let title = "About";
let description = "About page of an example blog on Astro"; let description = "About page of an example blog on Astro";
let canonicalURL = Astro.canonicalURL; const canonicalURL = new URL(Astro.url.pathname, Astro.site);
--- ---
<html lang="en"> <html lang="en">

View file

@ -13,6 +13,7 @@ export async function getStaticPaths() {
const { allPosts } = Astro.props; const { allPosts } = Astro.props;
const title = "Dons Blog"; const title = "Dons Blog";
const description = "An example blog on Astro"; const description = "An example blog on Astro";
const canonicalURL = new URL(Astro.url.pathname, Astro.site);
/** filter posts by author, sort by date */ /** filter posts by author, sort by date */
const posts = allPosts const posts = allPosts
@ -28,7 +29,7 @@ const author = authorData[posts[0].frontmatter.author];
{title} {title}
{description} {description}
image={posts[0].frontmatter.image} image={posts[0].frontmatter.image}
canonicalURL={Astro.canonicalURL.toString()} canonicalURL={canonicalURL.toString()}
/> />
<style lang="scss"> <style lang="scss">

View file

@ -12,7 +12,7 @@ import authorData from "../data/authors.json";
// All variables are available to use in the HTML template below. // All variables are available to use in the HTML template below.
let title = "Dons Blog"; let title = "Dons Blog";
let description = "An example blog on Astro"; let description = "An example blog on Astro";
let canonicalURL = Astro.canonicalURL; const canonicalURL = new URL(Astro.url.pathname, Astro.site);
// Data Fetching: List all Markdown posts in the repo. // Data Fetching: List all Markdown posts in the repo.
let allPosts = await Astro.glob("./post/*.md"); let allPosts = await Astro.glob("./post/*.md");

View file

@ -32,7 +32,7 @@ export async function getStaticPaths({ paginate, rss }) {
// page // page
const title = "Dons Blog"; const title = "Dons Blog";
const description = "An example blog on Astro"; const description = "An example blog on Astro";
const { canonicalURL } = Astro; const canonicalURL = new URL(Astro.url.pathname, Astro.site);
const { page } = Astro.props; const { page } = Astro.props;
--- ---

View file

@ -4,4 +4,5 @@ import preact from '@astrojs/preact';
// https://astro.build/config // https://astro.build/config
export default defineConfig({ export default defineConfig({
integrations: [preact()], integrations: [preact()],
site: `http://astro.build`
}); });

View file

@ -6,6 +6,7 @@ export interface Props {
description: string; description: string;
} }
const canonicalURL = new URL(Astro.url.pathname, Astro.site);
const { title, description } = Astro.props; const { title, description } = Astro.props;
--- ---
@ -21,14 +22,14 @@ const { title, description } = Astro.props;
<!-- Open Graph / Facebook --> <!-- Open Graph / Facebook -->
<meta property="og:type" content="website" /> <meta property="og:type" content="website" />
<meta property="og:url" content={Astro.canonicalURL} /> <meta property="og:url" content={canonicalURL} />
<meta property="og:title" content={title} /> <meta property="og:title" content={title} />
<meta property="og:description" content={description} /> <meta property="og:description" content={description} />
<meta property="og:image" content="https://astro.build/social.png" /> <meta property="og:image" content="https://astro.build/social.png" />
<!-- Twitter --> <!-- Twitter -->
<meta property="twitter:card" content="summary_large_image" /> <meta property="twitter:card" content="summary_large_image" />
<meta property="twitter:url" content={Astro.canonicalURL} /> <meta property="twitter:url" content={canonicalURL} />
<meta property="twitter:title" content={title} /> <meta property="twitter:title" content={title} />
<meta property="twitter:description" content={description} /> <meta property="twitter:description" content={description} />
<meta property="twitter:image" content="https://astro.build/social.png" /> <meta property="twitter:image" content="https://astro.build/social.png" />

View file

@ -10,4 +10,5 @@ export default defineConfig({
// Enable React for the Algolia search component. // Enable React for the Algolia search component.
react(), react(),
], ],
site: `http://astro.build`
}); });

View file

@ -5,7 +5,9 @@ export interface Props {
site: any; site: any;
canonicalURL: URL | string; canonicalURL: URL | string;
} }
const { content = {}, canonicalURL } = Astro.props;
const canonicalURL = new URL(Astro.url.pathname, Astro.site);
const { content = {} } = Astro.props;
const formattedContentTitle = content.title ? `${content.title} 🚀 ${SITE.title}` : SITE.title; const formattedContentTitle = content.title ? `${content.title} 🚀 ${SITE.title}` : SITE.title;
const imageSrc = content?.image?.src ?? OPEN_GRAPH.image.src; const imageSrc = content?.image?.src ?? OPEN_GRAPH.image.src;
const canonicalImageSrc = new URL(imageSrc, Astro.site); const canonicalImageSrc = new URL(imageSrc, Astro.site);

View file

@ -9,7 +9,8 @@ import RightSidebar from "../components/RightSidebar/RightSidebar.astro";
import * as CONFIG from "../config"; import * as CONFIG from "../config";
const { content = {} } = Astro.props; const { content = {} } = Astro.props;
const currentPage = new URL(Astro.request.url).pathname; const canonicalURL = new URL(Astro.url.pathname, Astro.site);
const currentPage = Astro.url.pathname;
const currentFile = `src/pages${currentPage.replace(/\/$/, "")}.md`; const currentFile = `src/pages${currentPage.replace(/\/$/, "")}.md`;
const githubEditUrl = CONFIG.GITHUB_EDIT_URL && CONFIG.GITHUB_EDIT_URL + currentFile; const githubEditUrl = CONFIG.GITHUB_EDIT_URL && CONFIG.GITHUB_EDIT_URL + currentFile;
--- ---
@ -17,7 +18,7 @@ const githubEditUrl = CONFIG.GITHUB_EDIT_URL && CONFIG.GITHUB_EDIT_URL + current
<html dir={content.dir ?? "ltr"} lang={content.lang ?? "en-us"} class="initial"> <html dir={content.dir ?? "ltr"} lang={content.lang ?? "en-us"} class="initial">
<head> <head>
<HeadCommon /> <HeadCommon />
<HeadSEO {content} canonicalURL={Astro.canonicalURL} /> <HeadSEO {content} canonicalURL={canonicalURL} />
<title>{content.title ? `${content.title} 🚀 ${CONFIG.SITE.title}` : CONFIG.SITE.title}</title> <title>{content.title ? `${content.title} 🚀 ${CONFIG.SITE.title}` : CONFIG.SITE.title}</title>
<style> <style>
body { body {

View file

@ -85,15 +85,29 @@ export interface BuildConfig {
* [Astro reference](https://docs.astro.build/reference/api-reference/#astro-global) * [Astro reference](https://docs.astro.build/reference/api-reference/#astro-global)
*/ */
export interface AstroGlobal extends AstroGlobalPartial { export interface AstroGlobal extends AstroGlobalPartial {
/** Canonical URL of the current page. If the [site](https://docs.astro.build/en/reference/configuration-reference/#site) config option is set, its origin will be the origin of this URL. /**
* * Canonical URL of the current page.
* [Astro reference](https://docs.astro.build/en/reference/api-reference/#astrocanonicalurl) * @deprecated Use `Astro.url` instead.
*
* Example:
* ```astro
* ---
* const canonicalURL = new URL(Astro.url.pathname, Astro.site);
* ---
* ```
*/ */
canonicalURL: URL; canonicalURL: URL;
/** The address (usually IP address) of the user. Used with SSR only. /** The address (usually IP address) of the user. Used with SSR only.
* *
*/ */
clientAddress: string; clientAddress: string;
/**
* A full URL object of the request URL.
* Equivalent to: `new URL(Astro.request.url)`
*
* [Astro reference](https://docs.astro.build/en/reference/api-reference/#url)
*/
url: URL;
/** Parameters passed to a dynamic page generated using [getStaticPaths](https://docs.astro.build/en/reference/api-reference/#getstaticpaths) /** Parameters passed to a dynamic page generated using [getStaticPaths](https://docs.astro.build/en/reference/api-reference/#getstaticpaths)
* *
* Example usage: * Example usage:
@ -224,11 +238,9 @@ export interface AstroGlobalPartial {
/** /**
* Returns a [URL](https://developer.mozilla.org/en-US/docs/Web/API/URL) object built from the [site](https://docs.astro.build/en/reference/configuration-reference/#site) config option * Returns a [URL](https://developer.mozilla.org/en-US/docs/Web/API/URL) object built from the [site](https://docs.astro.build/en/reference/configuration-reference/#site) config option
* *
* If `site` is undefined, the URL object will instead be built from `localhost`
*
* [Astro reference](https://docs.astro.build/en/reference/api-reference/#astrosite) * [Astro reference](https://docs.astro.build/en/reference/api-reference/#astrosite)
*/ */
site: URL; site: URL | undefined;
} }
type ServerConfig = { type ServerConfig = {

View file

@ -114,11 +114,7 @@ export const AstroConfigSchema = z.object({
.string() .string()
.url() .url()
.optional() .optional()
.transform((val) => (val ? appendForwardSlash(val) : val)) .transform((val) => (val ? appendForwardSlash(val) : val)),
.refine((val) => !val || new URL(val).pathname.length <= 1, {
message:
'"site" must be a valid URL origin (ex: "https://example.com") but cannot contain a URL path (ex: "https://example.com/blog"). Use "base" to configure your deployed URL path',
}),
base: z base: z
.string() .string()
.optional() .optional()

View file

@ -14,7 +14,7 @@ import type {
import { renderSlot } from '../../runtime/server/index.js'; import { renderSlot } from '../../runtime/server/index.js';
import { LogOptions, warn } from '../logger/core.js'; import { LogOptions, warn } from '../logger/core.js';
import { isScriptRequest } from './script.js'; import { isScriptRequest } from './script.js';
import { createCanonicalURL, isCSSRequest } from './util.js'; import { isCSSRequest } from './util.js';
const clientAddressSymbol = Symbol.for('astro.clientAddress'); const clientAddressSymbol = Symbol.for('astro.clientAddress');
@ -109,16 +109,10 @@ class Slots {
let renderMarkdown: any = null; let renderMarkdown: any = null;
function isPaginatedRoute({ page }: { page?: Page }) {
return page && 'currentPage' in page;
}
export function createResult(args: CreateResultArgs): SSRResult { export function createResult(args: CreateResultArgs): SSRResult {
const { markdown, params, pathname, props: pageProps, renderers, request, resolve, site } = args; const { markdown, params, pathname, props: pageProps, renderers, request, resolve } = args;
const paginated = isPaginatedRoute(pageProps);
const url = new URL(request.url); const url = new URL(request.url);
const canonicalURL = createCanonicalURL('.' + pathname, site ?? url.origin, paginated);
const headers = new Headers(); const headers = new Headers();
if (args.streaming) { if (args.streaming) {
headers.set('Transfer-Encoding', 'chunked'); headers.set('Transfer-Encoding', 'chunked');
@ -155,7 +149,6 @@ export function createResult(args: CreateResultArgs): SSRResult {
const Astro = { const Astro = {
__proto__: astroGlobal, __proto__: astroGlobal,
canonicalURL,
get clientAddress() { get clientAddress() {
if (!(clientAddressSymbol in request)) { if (!(clientAddressSymbol in request)) {
if (args.adapterName) { if (args.adapterName) {
@ -174,6 +167,7 @@ export function createResult(args: CreateResultArgs): SSRResult {
params, params,
props, props,
request, request,
url,
redirect: args.ssr redirect: args.ssr
? (path: string) => { ? (path: string) => {
return new Response(null, { return new Response(null, {
@ -220,6 +214,24 @@ ${extra}`
slots: astroSlots, slots: astroSlots,
} as unknown as AstroGlobal; } as unknown as AstroGlobal;
Object.defineProperty(Astro, 'canonicalURL', {
get: function() {
warn(args.logging,
'deprecation',
`${bold(
'Astro.canonicalURL'
)} is deprecated! Use \`Astro.url\` instead.
Example:
---
const canonicalURL = new URL(Astro.url.pathname, Astro.site);
---
`
);
return new URL(this.request.url.pathname, this.site);
},
});
Object.defineProperty(Astro, '__renderMarkdown', { Object.defineProperty(Astro, '__renderMarkdown', {
// Ensure this API is not exposed to users // Ensure this API is not exposed to users
enumerable: false, enumerable: false,

View file

@ -2,18 +2,6 @@ import npath from 'path-browserify';
import type { ModuleNode, ViteDevServer } from 'vite'; import type { ModuleNode, ViteDevServer } from 'vite';
import type { Metadata } from '../../runtime/server/metadata.js'; import type { Metadata } from '../../runtime/server/metadata.js';
/** Normalize URL to its canonical form */
export function createCanonicalURL(url: string, base?: string, paginated?: boolean): URL {
let pathname = url.replace(/\/index.html$/, ''); // index.html is not canonical
// Only trim the first page's /1 param if Astro's paginated() was used
if (paginated) {
pathname = pathname.replace(/\/1\/?$/, ''); // neither is a trailing /1/ (impl. detail of collections)
}
if (!npath.extname(pathname)) pathname = pathname.replace(/(\/+)?$/, '/'); // add trailing slash if theres no extension
pathname = pathname.replace(/\/+/g, '/'); // remove duplicate slashes (URL() wont)
return new URL(pathname, base);
}
/** Check if a URL is already valid */ /** Check if a URL is already valid */
export function isValidURL(url: string): boolean { export function isValidURL(url: string): boolean {
try { try {

View file

@ -38,16 +38,6 @@ export function createRequest({
}); });
Object.defineProperties(request, { Object.defineProperties(request, {
canonicalURL: {
get() {
warn(
logging,
'deprecation',
`Astro.request.canonicalURL has been moved to Astro.canonicalURL`
);
return undefined;
},
},
params: { params: {
get() { get() {
warn(logging, 'deprecation', `Astro.request.params has been moved to Astro.params`); warn(logging, 'deprecation', `Astro.request.params has been moved to Astro.params`);

View file

@ -516,11 +516,11 @@ function createAstroGlobFn() {
// Inside of getStaticPaths. // Inside of getStaticPaths.
export function createAstro( export function createAstro(
filePathname: string, filePathname: string,
_site: string, _site: string | undefined,
projectRootStr: string projectRootStr: string
): AstroGlobalPartial { ): AstroGlobalPartial {
const site = new URL(_site); const site = _site ? new URL(_site) : undefined;
const url = new URL(filePathname, site); const referenceURL = new URL(filePathname, `http://localhost`);
const projectRoot = new URL(projectRootStr); const projectRoot = new URL(projectRootStr);
return { return {
site, site,
@ -528,7 +528,7 @@ export function createAstro(
glob: createAstroGlobFn(), glob: createAstroGlobFn(),
// INVESTIGATE is there a use-case for multi args? // INVESTIGATE is there a use-case for multi args?
resolve(...segments: string[]) { resolve(...segments: string[]) {
let resolved = segments.reduce((u, segment) => new URL(segment, u), url).pathname; let resolved = segments.reduce((u, segment) => new URL(segment, u), referenceURL).pathname;
// When inside of project root, remove the leading path so you are // When inside of project root, remove the leading path so you are
// left with only `/src/images/tower.png` // left with only `/src/images/tower.png`
if (resolved.startsWith(projectRoot.pathname)) { if (resolved.startsWith(projectRoot.pathname)) {

View file

@ -77,9 +77,7 @@ async function compile({
// For Windows compat, prepend the module ID with `/@fs` // For Windows compat, prepend the module ID with `/@fs`
pathname: `/@fs${prependForwardSlash(moduleId)}`, pathname: `/@fs${prependForwardSlash(moduleId)}`,
projectRoot: config.root.toString(), projectRoot: config.root.toString(),
site: config.site site: config.site?.toString(),
? new URL(config.base, config.site).toString()
: `http://localhost:${config.server.port}/`,
sourcefile: filename, sourcefile: filename,
sourcemap: 'both', sourcemap: 'both',
internalURL: `/@fs${prependForwardSlash( internalURL: `/@fs${prependForwardSlash(

View file

@ -100,8 +100,8 @@ describe('getStaticPaths - numeric route params', () => {
const canonical = $('link[rel=canonical]'); const canonical = $('link[rel=canonical]');
expect(canonical.attr('href')).to.equal( expect(canonical.attr('href')).to.equal(
`https://mysite.dev/posts/${page}/`, `https://mysite.dev/posts/${page}`,
`doesn't trim the /${page}/ route param` `doesn't trim the /${page} route param`
); );
} }
}); });

View file

@ -8,7 +8,7 @@ describe('Astro Global', () => {
before(async () => { before(async () => {
fixture = await loadFixture({ fixture = await loadFixture({
root: './fixtures/astro-global/', root: './fixtures/astro-global/',
site: 'https://mysite.dev/', site: 'https://mysite.dev/blog/',
base: '/blog', base: '/blog',
}); });
}); });
@ -50,23 +50,6 @@ describe('Astro Global', () => {
expect($('#nested-child-pathname').text()).to.equal('/blog/'); expect($('#nested-child-pathname').text()).to.equal('/blog/');
}); });
it('Astro.canonicalURL', async () => {
// given a URL, expect the following canonical URL
const canonicalURLs = {
'/index.html': 'https://mysite.dev/blog/',
'/post/post/index.html': 'https://mysite.dev/blog/post/post/',
'/posts/1/index.html': 'https://mysite.dev/blog/posts/',
'/posts/2/index.html': 'https://mysite.dev/blog/posts/2/',
};
for (const [url, canonicalURL] of Object.entries(canonicalURLs)) {
const html = await fixture.readFile(url);
const $ = cheerio.load(html);
expect($('link[rel="canonical"]').attr('href')).to.equal(canonicalURL);
}
});
it('Astro.site', async () => { it('Astro.site', async () => {
const html = await fixture.readFile('/index.html'); const html = await fixture.readFile('/index.html');
const $ = cheerio.load(html); const $ = cheerio.load(html);
@ -134,27 +117,10 @@ describe('Astro Global Defaults', () => {
expect($('#nested-child-pathname').text()).to.equal('/'); expect($('#nested-child-pathname').text()).to.equal('/');
}); });
it('Astro.canonicalURL', async () => {
// given a URL, expect the following canonical URL
const canonicalURLs = {
'/index.html': /http:\/\/localhost:\d+\//,
'/post/post/index.html': /http:\/\/localhost:\d+\/post\/post\//,
'/posts/1/index.html': /http:\/\/localhost:\d+\/posts\//,
'/posts/2/index.html': /http:\/\/localhost:\d+\/posts\/2\//,
};
for (const [url, canonicalURL] of Object.entries(canonicalURLs)) {
const html = await fixture.readFile(url);
const $ = cheerio.load(html);
expect($('link[rel="canonical"]').attr('href')).to.match(canonicalURL);
}
});
it('Astro.site', async () => { it('Astro.site', async () => {
const html = await fixture.readFile('/index.html'); const html = await fixture.readFile('/index.html');
const $ = cheerio.load(html); const $ = cheerio.load(html);
expect($('#site').attr('href')).to.match(/http:\/\/localhost:\d+\//); expect($('#site').attr('href')).to.equal(undefined);
}); });
}); });
}); });

View file

@ -8,6 +8,7 @@ describe('Custom 404', () => {
before(async () => { before(async () => {
fixture = await loadFixture({ fixture = await loadFixture({
root: './fixtures/custom-404/', root: './fixtures/custom-404/',
site: 'http://example.com',
}); });
}); });
@ -35,7 +36,7 @@ describe('Custom 404', () => {
$ = cheerio.load(html); $ = cheerio.load(html);
expect($('h1').text()).to.equal('Page not found'); expect($('h1').text()).to.equal('Page not found');
expect($('p').text()).to.equal('/a/'); expect($('p').text()).to.equal('/a');
}); });
}); });
}); });

View file

@ -14,6 +14,7 @@ export async function getStaticPaths() {
}; };
const { page } = Astro.params const { page } = Astro.params
const canonicalURL = new URL(Astro.url.pathname, Astro.site);
--- ---
<html lang="en"> <html lang="en">
@ -21,7 +22,7 @@ const { page } = Astro.params
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width" /> <meta name="viewport" content="width=device-width" />
<title>Posts Page {page}</title> <title>Posts Page {page}</title>
<link rel="canonical" href={Astro.canonicalURL.href}> <link rel="canonical" href={canonicalURL.href}>
</head> </head>
<body> <body>
<h1>Welcome to page {page}</h1> <h1>Welcome to page {page}</h1>

View file

@ -1,5 +1,5 @@
--- ---
import NestedChild from './NestedChild.astro'; import NestedChild from './NestedChild.astro';
--- ---
<div id="child-pathname">{new URL(Astro.request.url).pathname}</div> <div id="child-pathname">{Astro.url.pathname}</div>
<NestedChild /> <NestedChild />

View file

@ -1 +1 @@
<div id="nested-child-pathname">{new URL(Astro.request.url).pathname}</div> <div id="nested-child-pathname">{Astro.url.pathname}</div>

View file

@ -1,10 +1,11 @@
--- ---
const { content } = Astro.props; const { content } = Astro.props;
const canonicalURL = new URL(Astro.url.pathname, Astro.site ?? `http://example.com`);
--- ---
<html> <html>
<head> <head>
<title>{content.title}</title> <title>{content.title}</title>
<link rel="canonical" href={Astro.canonicalURL.href}> <link rel="canonical" href={canonicalURL.href}>
</head> </head>
<body> <body>
<slot></slot> <slot></slot>

View file

@ -1,14 +1,15 @@
--- ---
import Child from '../components/Child.astro'; import Child from '../components/Child.astro';
const canonicalURL = new URL(Astro.url.pathname, Astro.site ?? `http://example.com`);
--- ---
<html> <html>
<head> <head>
<title>Test</title> <title>Test</title>
<link rel="canonical" href={Astro.canonicalURL.href}> <link rel="canonical" href={canonicalURL.href}>
</head> </head>
<body> <body>
<div id="pathname">{new URL(Astro.request.url).pathname}</div> <div id="pathname">{Astro.url.pathname}</div>
<div id="searchparams">{JSON.stringify(new URL(Astro.request.url).searchParams)}</div> <div id="searchparams">{JSON.stringify(Astro.url.searchParams)}</div>
<a id="site" href={Astro.site}>Home</a> <a id="site" href={Astro.site}>Home</a>
<Child /> <Child />

View file

@ -4,7 +4,7 @@ export async function getStaticPaths({paginate}) {
return paginate(data, {pageSize: 1}); return paginate(data, {pageSize: 1});
} }
const { page } = Astro.props; const { page } = Astro.props;
const { params, canonicalURL } = Astro; const canonicalURL = new URL(Astro.url.pathname, Astro.site ?? `http://example.com`);
--- ---
<html> <html>
@ -13,7 +13,7 @@ const { params, canonicalURL } = Astro;
<link rel="canonical" href={canonicalURL.href} /> <link rel="canonical" href={canonicalURL.href} />
</head> </head>
<body> <body>
{page.data.map((data) => ( {page.data.map((data: any) => (
<div> <div>
<h1>{data.frontmatter.title}</h1> <h1>{data.frontmatter.title}</h1>
<a class="post-url" href={data.url}>Read</a> <a class="post-url" href={data.url}>Read</a>

View file

@ -1,12 +1,13 @@
--- ---
const canonicalURL = new URL(Astro.url.pathname, Astro.site);
--- ---
<html> <html>
<head> <head>
<title>Test</title> <title>Test</title>
<link rel="canonical" href={Astro.canonicalURL.href}> <link rel="canonical" href={canonicalURL.href}>
</head> </head>
<body> <body>
<div id="pathname">{new URL(Astro.request.url).pathname}</div> <div id="pathname">{Astro.url.pathname}</div>
<a id="site" href={Astro.site}>Home</a> <a id="site" href={Astro.site}>Home</a>
</body> </body>
</html> </html>

View file

@ -11,7 +11,8 @@ export async function getStaticPaths({paginate}) {
}); });
} }
const { page, filter } = Astro.props; const { page, filter } = Astro.props;
const { params, canonicalURL} = Astro; const { params } = Astro;
const canonicalURL = new URL(Astro.url.pathname, Astro.site);
--- ---
<html> <html>

View file

@ -3,8 +3,7 @@ export async function getStaticPaths({paginate}) {
const data = await Astro.glob('../../post/*.md'); const data = await Astro.glob('../../post/*.md');
return paginate(data, {pageSize: 1}); return paginate(data, {pageSize: 1});
} }
const { page } = Astro.props; const canonicalURL = new URL(Astro.url.pathname, Astro.site);
const { params, canonicalURL} = Astro;
--- ---
<html> <html>

View file

@ -3,8 +3,7 @@ export async function getStaticPaths({paginate}) {
const data = await Astro.glob('../../post/*.md'); const data = await Astro.glob('../../post/*.md');
return paginate(data, {pageSize: 1}); return paginate(data, {pageSize: 1});
} }
const { page } = Astro.props; const canonicalURL = new URL(Astro.url.pathname, Astro.site);
const { params, canonicalURL} = Astro;
--- ---
<html> <html>

View file

@ -1,4 +1,5 @@
--- ---
const canonicalURL = new URL(Astro.url.pathname, Astro.site);
--- ---
<html lang="en"> <html lang="en">
@ -7,6 +8,6 @@
</head> </head>
<body> <body>
<h1>Page not found</h1> <h1>Page not found</h1>
<p>{Astro.canonicalURL.pathname}</p> <p>{canonicalURL.pathname}</p>
</body> </body>
</html> </html>

View file

@ -1,5 +1,5 @@
--- ---
const origin = new URL(Astro.request.url).origin; const origin = Astro.url.origin;
--- ---
<html> <html>