Expose file
and url
for Astro files (#3385)
* feat: update test * feat: return `file` and `url` for astro files * chore: add changeset * fix: use private names $$file and $$url * test: update markdown test * chore: update fileId logic to strip query params
This commit is contained in:
parent
a7480452b1
commit
d34859d750
8 changed files with 61 additions and 14 deletions
5
.changeset/quiet-pumpkins-hunt.md
Normal file
5
.changeset/quiet-pumpkins-hunt.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'astro': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Expose `file` and `url` properties when fetching `.astro` files with `Astro.glob()`
|
|
@ -216,7 +216,7 @@ export interface AstroGlobalPartial {
|
||||||
*
|
*
|
||||||
* [Astro reference](https://docs.astro.build/en/reference/api-reference/#astroglob)
|
* [Astro reference](https://docs.astro.build/en/reference/api-reference/#astroglob)
|
||||||
*/
|
*/
|
||||||
glob(globStr: `${any}.astro`): Promise<ComponentInstance[]>;
|
glob(globStr: `${any}.astro`): Promise<AstroInstance[]>;
|
||||||
glob<T extends Record<string, any>>(globStr: `${any}.md`): Promise<MarkdownInstance<T>[]>;
|
glob<T extends Record<string, any>>(globStr: `${any}.md`): Promise<MarkdownInstance<T>[]>;
|
||||||
glob<T extends Record<string, any>>(globStr: string): Promise<T[]>;
|
glob<T extends Record<string, any>>(globStr: string): Promise<T[]>;
|
||||||
/**
|
/**
|
||||||
|
@ -752,6 +752,12 @@ export interface ComponentInstance {
|
||||||
getStaticPaths?: (options: GetStaticPathsOptions) => GetStaticPathsResult;
|
getStaticPaths?: (options: GetStaticPathsOptions) => GetStaticPathsResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface AstroInstance {
|
||||||
|
file: string;
|
||||||
|
url: string | undefined;
|
||||||
|
default: AstroComponentFactory;
|
||||||
|
}
|
||||||
|
|
||||||
export interface MarkdownInstance<T extends Record<string, any>> {
|
export interface MarkdownInstance<T extends Record<string, any>> {
|
||||||
frontmatter: T;
|
frontmatter: T;
|
||||||
file: string;
|
file: string;
|
||||||
|
|
|
@ -14,6 +14,7 @@ import ancestor from 'common-ancestor-path';
|
||||||
import { trackCSSDependencies, handleHotUpdate } from './hmr.js';
|
import { trackCSSDependencies, handleHotUpdate } from './hmr.js';
|
||||||
import { isRelativePath, startsWithForwardSlash } from '../core/path.js';
|
import { isRelativePath, startsWithForwardSlash } from '../core/path.js';
|
||||||
import { PAGE_SCRIPT_ID, PAGE_SSR_SCRIPT_ID } from '../vite-plugin-scripts/index.js';
|
import { PAGE_SCRIPT_ID, PAGE_SSR_SCRIPT_ID } from '../vite-plugin-scripts/index.js';
|
||||||
|
import { getFileInfo } from '../vite-plugin-utils/index.js';
|
||||||
import { resolvePages } from '../core/util.js';
|
import { resolvePages } from '../core/util.js';
|
||||||
|
|
||||||
const FRONTMATTER_PARSE_REGEXP = /^\-\-\-(.*)^\-\-\-/ms;
|
const FRONTMATTER_PARSE_REGEXP = /^\-\-\-(.*)^\-\-\-/ms;
|
||||||
|
@ -168,6 +169,7 @@ export default function astro({ config, logging }: AstroPluginOptions): vite.Plu
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const transformResult = await cachedCompilation(compileProps);
|
const transformResult = await cachedCompilation(compileProps);
|
||||||
|
const { fileId: file, fileUrl: url } = getFileInfo(id, config);
|
||||||
|
|
||||||
// Compile all TypeScript to JavaScript.
|
// Compile all TypeScript to JavaScript.
|
||||||
// Also, catches invalid JS/TS in the compiled output before returning.
|
// Also, catches invalid JS/TS in the compiled output before returning.
|
||||||
|
@ -180,6 +182,7 @@ export default function astro({ config, logging }: AstroPluginOptions): vite.Plu
|
||||||
});
|
});
|
||||||
|
|
||||||
let SUFFIX = '';
|
let SUFFIX = '';
|
||||||
|
SUFFIX += `\nconst $$file = ${JSON.stringify(file)};\nconst $$url = ${JSON.stringify(url)};export { $$file as file, $$url as url };\n`;
|
||||||
// Add HMR handling in dev mode.
|
// Add HMR handling in dev mode.
|
||||||
if (!resolvedConfig.isProduction) {
|
if (!resolvedConfig.isProduction) {
|
||||||
// HACK: extract dependencies from metadata until compiler static extraction handles them
|
// HACK: extract dependencies from metadata until compiler static extraction handles them
|
||||||
|
|
|
@ -9,8 +9,9 @@ import type { Plugin } from 'vite';
|
||||||
import type { AstroConfig } from '../@types/astro';
|
import type { AstroConfig } from '../@types/astro';
|
||||||
import { PAGE_SSR_SCRIPT_ID } from '../vite-plugin-scripts/index.js';
|
import { PAGE_SSR_SCRIPT_ID } from '../vite-plugin-scripts/index.js';
|
||||||
import { pagesVirtualModuleId } from '../core/app/index.js';
|
import { pagesVirtualModuleId } from '../core/app/index.js';
|
||||||
import { appendForwardSlash, prependForwardSlash } from '../core/path.js';
|
import { prependForwardSlash } from '../core/path.js';
|
||||||
import { resolvePages, viteID } from '../core/util.js';
|
import { resolvePages, viteID } from '../core/util.js';
|
||||||
|
import { getFileInfo } from '../vite-plugin-utils/index.js';
|
||||||
|
|
||||||
interface AstroPluginOptions {
|
interface AstroPluginOptions {
|
||||||
config: AstroConfig;
|
config: AstroConfig;
|
||||||
|
@ -78,17 +79,7 @@ export default function markdown({ config }: AstroPluginOptions): Plugin {
|
||||||
// Return the file's JS representation, including all Markdown
|
// Return the file's JS representation, including all Markdown
|
||||||
// frontmatter and a deferred `import() of the compiled markdown content.
|
// frontmatter and a deferred `import() of the compiled markdown content.
|
||||||
if (id.endsWith(`.md${MARKDOWN_IMPORT_FLAG}`)) {
|
if (id.endsWith(`.md${MARKDOWN_IMPORT_FLAG}`)) {
|
||||||
const sitePathname = appendForwardSlash(
|
const { fileId, fileUrl } = getFileInfo(id, config);
|
||||||
config.site ? new URL(config.base, config.site).pathname : config.base
|
|
||||||
);
|
|
||||||
|
|
||||||
const fileId = id.replace(MARKDOWN_IMPORT_FLAG, '');
|
|
||||||
let fileUrl = fileId.includes('/pages/')
|
|
||||||
? fileId.replace(/^.*?\/pages\//, sitePathname).replace(/(\/index)?\.md$/, '')
|
|
||||||
: undefined;
|
|
||||||
if (fileUrl && config.trailingSlash === 'always') {
|
|
||||||
fileUrl = appendForwardSlash(fileUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
const source = await fs.promises.readFile(fileId, 'utf8');
|
const source = await fs.promises.readFile(fileId, 'utf8');
|
||||||
const { data: frontmatter } = matter(source);
|
const { data: frontmatter } = matter(source);
|
||||||
|
|
17
packages/astro/src/vite-plugin-utils/index.ts
Normal file
17
packages/astro/src/vite-plugin-utils/index.ts
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import type { AstroConfig } from '../@types/astro';
|
||||||
|
import { appendForwardSlash } from '../core/path.js';
|
||||||
|
|
||||||
|
export function getFileInfo(id: string, config: AstroConfig) {
|
||||||
|
const sitePathname = appendForwardSlash(
|
||||||
|
config.site ? new URL(config.base, config.site).pathname : config.base
|
||||||
|
);
|
||||||
|
|
||||||
|
const fileId = id.split('?')[0];
|
||||||
|
let fileUrl = fileId.includes('/pages/')
|
||||||
|
? fileId.replace(/^.*?\/pages\//, sitePathname).replace(/(\/index)?\.(md|astro)$/, '')
|
||||||
|
: undefined;
|
||||||
|
if (fileUrl && config.trailingSlash === 'always') {
|
||||||
|
fileUrl = appendForwardSlash(fileUrl);
|
||||||
|
}
|
||||||
|
return { fileId, fileUrl };
|
||||||
|
}
|
|
@ -2,7 +2,7 @@ import { expect } from 'chai';
|
||||||
import * as cheerio from 'cheerio';
|
import * as cheerio from 'cheerio';
|
||||||
import { loadFixture } from './test-utils.js';
|
import { loadFixture } from './test-utils.js';
|
||||||
|
|
||||||
describe('Astro.*', () => {
|
describe('Astro Global', () => {
|
||||||
let fixture;
|
let fixture;
|
||||||
|
|
||||||
before(async () => {
|
before(async () => {
|
||||||
|
@ -76,5 +76,12 @@ describe('Astro.*', () => {
|
||||||
const $ = cheerio.load(html);
|
const $ = cheerio.load(html);
|
||||||
expect($('.post-url').attr('href')).to.equal('/blog/post/post-2');
|
expect($('.post-url').attr('href')).to.equal('/blog/post/post-2');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Astro.glob() correctly returns meta info for MD and Astro files', async () => {
|
||||||
|
const html = await fixture.readFile('/glob/index.html');
|
||||||
|
const $ = cheerio.load(html);
|
||||||
|
expect($('[data-file]').length).to.equal(3);
|
||||||
|
expect($('.post-url[href]').length).to.equal(3);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
17
packages/astro/test/fixtures/astro-global/src/pages/glob.astro
vendored
Normal file
17
packages/astro/test/fixtures/astro-global/src/pages/glob.astro
vendored
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
---
|
||||||
|
const data = await Astro.glob('./post/**/*');
|
||||||
|
---
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>All Posts</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
{data.map((page: any) => (
|
||||||
|
<div>
|
||||||
|
<h1 data-file={page.file} />Title</h1>
|
||||||
|
<a class="post-url" href={page.url}>Read</a>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</body>
|
||||||
|
</html>
|
1
packages/astro/test/fixtures/astro-global/src/pages/post/post-3.astro
vendored
Normal file
1
packages/astro/test/fixtures/astro-global/src/pages/post/post-3.astro
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<h1>Post 3</h1>
|
Loading…
Reference in a new issue