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:
parent
d503c5bf3d
commit
ddefb172f6
35 changed files with 101 additions and 117 deletions
5
.changeset/unlucky-panthers-yawn.md
Normal file
5
.changeset/unlucky-panthers-yawn.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'astro': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Deprecate Astro.canonicalURL, in favor of Astro.url instead.
|
5
.changeset/yellow-drinks-judge.md
Normal file
5
.changeset/yellow-drinks-judge.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'astro': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Add Astro.url helper for getting the request URL
|
|
@ -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`
|
||||||
});
|
});
|
||||||
|
|
|
@ -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"}>
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -13,6 +13,7 @@ export async function getStaticPaths() {
|
||||||
const { allPosts } = Astro.props;
|
const { allPosts } = Astro.props;
|
||||||
const title = "Don’s Blog";
|
const title = "Don’s 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">
|
||||||
|
|
|
@ -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 = "Don’s Blog";
|
let title = "Don’s 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");
|
||||||
|
|
|
@ -32,7 +32,7 @@ export async function getStaticPaths({ paginate, rss }) {
|
||||||
// page
|
// page
|
||||||
const title = "Don’s Blog";
|
const title = "Don’s 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;
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
@ -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`
|
||||||
});
|
});
|
||||||
|
|
|
@ -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" />
|
||||||
|
|
|
@ -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`
|
||||||
});
|
});
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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 = {
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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 there’s no extension
|
|
||||||
pathname = pathname.replace(/\/+/g, '/'); // remove duplicate slashes (URL() won’t)
|
|
||||||
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 {
|
||||||
|
|
|
@ -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`);
|
||||||
|
|
|
@ -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)) {
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -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);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -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');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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 />
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
<div id="nested-child-pathname">{new URL(Astro.request.url).pathname}</div>
|
<div id="nested-child-pathname">{Astro.url.pathname}</div>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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 />
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
---
|
---
|
||||||
const origin = new URL(Astro.request.url).origin;
|
const origin = Astro.url.origin;
|
||||||
---
|
---
|
||||||
|
|
||||||
<html>
|
<html>
|
||||||
|
|
Loading…
Add table
Reference in a new issue