Compare commits
17 commits
main
...
mt/client-
Author | SHA1 | Date | |
---|---|---|---|
|
068e618cb9 | ||
|
85cc8daff8 | ||
|
9ed7da1e3b | ||
|
d50aaea36d | ||
|
05833ab44e | ||
|
6bba4efb3f | ||
|
a3ebad84a8 | ||
|
4e2c65c27c | ||
|
9c7cd7c9f6 | ||
|
49cbbf8d23 | ||
|
8eed6cc7ac | ||
|
cb62f02ea1 | ||
|
d125095d09 | ||
|
365adee6f6 | ||
|
20c1b3b0d0 | ||
|
84d1f05964 | ||
|
363f80011b |
50 changed files with 350 additions and 171 deletions
5
.changeset/cuddly-vans-reply.md
Normal file
5
.changeset/cuddly-vans-reply.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'@astrojs/markdown-remark': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Remove `is:raw` from remark Shiki plugin
|
25
.changeset/eleven-buttons-wash.md
Normal file
25
.changeset/eleven-buttons-wash.md
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
---
|
||||||
|
'@astrojs/cloudflare': patch
|
||||||
|
'@astrojs/partytown': patch
|
||||||
|
'@astrojs/alpinejs': patch
|
||||||
|
'@astrojs/prefetch': patch
|
||||||
|
'@astrojs/tailwind': patch
|
||||||
|
'@astrojs/markdoc': patch
|
||||||
|
'@astrojs/sitemap': patch
|
||||||
|
'@astrojs/underscore-redirects': patch
|
||||||
|
'@astrojs/preact': patch
|
||||||
|
'@astrojs/svelte': patch
|
||||||
|
'@astrojs/vercel': patch
|
||||||
|
'@astrojs/react': patch
|
||||||
|
'@astrojs/solid-js': patch
|
||||||
|
'@astrojs/node': patch
|
||||||
|
'@astrojs/lit': patch
|
||||||
|
'@astrojs/mdx': patch
|
||||||
|
'@astrojs/vue': patch
|
||||||
|
'@astrojs/internal-helpers': patch
|
||||||
|
'@astrojs/markdown-remark': patch
|
||||||
|
'@astrojs/telemetry': patch
|
||||||
|
'astro': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Add provenance statement when publishing the library from CI
|
5
.changeset/gentle-hats-dress.md
Normal file
5
.changeset/gentle-hats-dress.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'astro': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fix view transitions with client:only components
|
5
.changeset/green-crabs-breathe.md
Normal file
5
.changeset/green-crabs-breathe.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'@astrojs/telemetry': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Removed an unnecessary dependency.
|
5
.changeset/red-masks-drop.md
Normal file
5
.changeset/red-masks-drop.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'astro': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fix `tsconfig.json` update causing the server to crash
|
5
.changeset/tasty-meals-buy.md
Normal file
5
.changeset/tasty-meals-buy.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'astro': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Remove unused CSS output files when inlined
|
5
.changeset/thirty-ravens-fly.md
Normal file
5
.changeset/thirty-ravens-fly.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'astro': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Node-based adapters now create less server-side javascript
|
5
.changeset/tricky-otters-cross.md
Normal file
5
.changeset/tricky-otters-cross.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'@astrojs/partytown': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Expose types for TypeScript users
|
5
.changeset/witty-fishes-heal.md
Normal file
5
.changeset/witty-fishes-heal.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'astro': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Improve `astro info` copy to clipboard compatability
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
// ISOMORPHIC FILE: NO TOP-LEVEL IMPORT/REQUIRE() ALLOWED
|
// ISOMORPHIC FILE: NO TOP-LEVEL IMPORT/REQUIRE() ALLOWED
|
||||||
// This file has to run as both ESM and CJS on older Node.js versions
|
// This file has to run as both ESM and CJS on older Node.js versions
|
||||||
// Needed for Stackblitz: https://github.com/stackblitz/webcontainer-core/issues/281
|
|
||||||
|
|
||||||
const CI_INSTRUCTIONS = {
|
const CI_INSTRUCTIONS = {
|
||||||
NETLIFY: 'https://docs.netlify.com/configure-builds/manage-dependencies/#node-js-and-javascript',
|
NETLIFY: 'https://docs.netlify.com/configure-builds/manage-dependencies/#node-js-and-javascript',
|
||||||
|
@ -16,15 +15,11 @@ const CI_INSTRUCTIONS = {
|
||||||
const engines = '>=18.14.1';
|
const engines = '>=18.14.1';
|
||||||
const skipSemverCheckIfAbove = 19;
|
const skipSemverCheckIfAbove = 19;
|
||||||
|
|
||||||
// HACK (2023-08-18) Stackblitz does not support Node 18 yet, so we'll fake Node 16 support for some time until it's supported
|
|
||||||
// TODO: Remove when Node 18 is supported on Stackblitz
|
|
||||||
const isStackblitz = process.env.SHELL === '/bin/jsh' && process.versions.webcontainer != null;
|
|
||||||
|
|
||||||
/** `astro *` */
|
/** `astro *` */
|
||||||
async function main() {
|
async function main() {
|
||||||
const version = process.versions.node;
|
const version = process.versions.node;
|
||||||
// Fast-path for higher Node.js versions
|
// Fast-path for higher Node.js versions
|
||||||
if (!isStackblitz && (parseInt(version) || 0) <= skipSemverCheckIfAbove) {
|
if ((parseInt(version) || 0) <= skipSemverCheckIfAbove) {
|
||||||
try {
|
try {
|
||||||
const semver = await import('semver');
|
const semver = await import('semver');
|
||||||
if (!semver.satisfies(version, engines)) {
|
if (!semver.satisfies(version, engines)) {
|
||||||
|
|
|
@ -3,6 +3,7 @@ import Layout from '../components/Layout.astro';
|
||||||
import Island from '../components/Island';
|
import Island from '../components/Island';
|
||||||
---
|
---
|
||||||
<Layout>
|
<Layout>
|
||||||
|
<p id="page-one">Page 1</p>
|
||||||
<a id="click-two" href="/client-only-two">go to page 2</a>
|
<a id="click-two" href="/client-only-two">go to page 2</a>
|
||||||
<div transition:persist="island">
|
<div transition:persist="island">
|
||||||
<Island client:only count={5}>message here</Island>
|
<Island client:only count={5}>message here</Island>
|
||||||
|
|
|
@ -4,6 +4,7 @@ import Island from '../components/Island';
|
||||||
---
|
---
|
||||||
<Layout>
|
<Layout>
|
||||||
<p id="page-two">Page 2</p>
|
<p id="page-two">Page 2</p>
|
||||||
|
<a id="click-one" href="/client-only-one">go to page 1</a>
|
||||||
<div transition:persist="island">
|
<div transition:persist="island">
|
||||||
<Island client:only count={5}>message here</Island>
|
<Island client:only count={5}>message here</Island>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -649,9 +649,14 @@ test.describe('View Transitions', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('client:only styles are retained on transition', async ({ page, astro }) => {
|
test('client:only styles are retained on transition', async ({ page, astro }) => {
|
||||||
|
const loads = [];
|
||||||
|
page.addListener('load', async (p) => {
|
||||||
|
loads.push(p);
|
||||||
|
});
|
||||||
|
|
||||||
const totalExpectedStyles = 7;
|
const totalExpectedStyles = 7;
|
||||||
|
|
||||||
// Go to page 1
|
// Go to page 1 (normal load)
|
||||||
await page.goto(astro.resolveUrl('/client-only-one'));
|
await page.goto(astro.resolveUrl('/client-only-one'));
|
||||||
let msg = page.locator('.counter-message');
|
let msg = page.locator('.counter-message');
|
||||||
await expect(msg).toHaveText('message here');
|
await expect(msg).toHaveText('message here');
|
||||||
|
@ -659,13 +664,24 @@ test.describe('View Transitions', () => {
|
||||||
let styles = await page.locator('style').all();
|
let styles = await page.locator('style').all();
|
||||||
expect(styles.length).toEqual(totalExpectedStyles);
|
expect(styles.length).toEqual(totalExpectedStyles);
|
||||||
|
|
||||||
|
// Transition to page 2 (will do a full load)
|
||||||
await page.click('#click-two');
|
await page.click('#click-two');
|
||||||
|
|
||||||
let pageTwo = page.locator('#page-two');
|
let pageTwo = page.locator('#page-two');
|
||||||
await expect(pageTwo, 'should have content').toHaveText('Page 2');
|
await expect(pageTwo, 'should have content').toHaveText('Page 2');
|
||||||
|
|
||||||
|
// Transition to page 1 (will do a full load)
|
||||||
|
await page.click('#click-one');
|
||||||
|
|
||||||
|
let pageOne = page.locator('#page-one');
|
||||||
|
await expect(pageOne, 'should have content').toHaveText('Page 1');
|
||||||
|
|
||||||
|
// Transition to page 1 (real transition, no full load)
|
||||||
|
await page.click('#click-two');
|
||||||
|
|
||||||
styles = await page.locator('style').all();
|
styles = await page.locator('style').all();
|
||||||
expect(styles.length).toEqual(totalExpectedStyles, 'style count has not changed');
|
expect(styles.length).toEqual(totalExpectedStyles, 'style count has not changed');
|
||||||
|
expect(loads.length, 'There should only be 1 page load').toEqual(3);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Horizontal scroll position restored on back button', async ({ page, astro }) => {
|
test('Horizontal scroll position restored on back button', async ({ page, astro }) => {
|
||||||
|
|
|
@ -168,7 +168,6 @@
|
||||||
"string-width": "^6.1.0",
|
"string-width": "^6.1.0",
|
||||||
"strip-ansi": "^7.1.0",
|
"strip-ansi": "^7.1.0",
|
||||||
"tsconfig-resolver": "^3.0.1",
|
"tsconfig-resolver": "^3.0.1",
|
||||||
"undici": "^5.23.0",
|
|
||||||
"unist-util-visit": "^4.1.2",
|
"unist-util-visit": "^4.1.2",
|
||||||
"vfile": "^5.3.7",
|
"vfile": "^5.3.7",
|
||||||
"vite": "^4.4.9",
|
"vite": "^4.4.9",
|
||||||
|
@ -226,5 +225,8 @@
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.14.1",
|
"node": ">=18.14.1",
|
||||||
"npm": ">=6.14.0"
|
"npm": ">=6.14.0"
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"provenance": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1168,10 +1168,10 @@ export interface AstroUserConfig {
|
||||||
* Pass [rehype plugins](https://github.com/remarkjs/remark-rehype) to customize how your Markdown's output HTML is processed. You can import and apply the plugin function (recommended), or pass the plugin name as a string.
|
* Pass [rehype plugins](https://github.com/remarkjs/remark-rehype) to customize how your Markdown's output HTML is processed. You can import and apply the plugin function (recommended), or pass the plugin name as a string.
|
||||||
*
|
*
|
||||||
* ```js
|
* ```js
|
||||||
* import rehypeMinifyHtml from 'rehype-minify';
|
* import { rehypeAccessibleEmojis } from 'rehype-accessible-emojis';
|
||||||
* {
|
* {
|
||||||
* markdown: {
|
* markdown: {
|
||||||
* rehypePlugins: [rehypeMinifyHtml]
|
* rehypePlugins: [rehypeAccessibleEmojis]
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
* ```
|
* ```
|
||||||
|
|
|
@ -41,10 +41,22 @@ export async function printInfo({ flags }: InfoOptions) {
|
||||||
await copyToClipboard(output.trim());
|
await copyToClipboard(output.trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
const SUPPORTED_SYSTEM = new Set(['darwin', 'win32']);
|
|
||||||
async function copyToClipboard(text: string) {
|
async function copyToClipboard(text: string) {
|
||||||
const system = platform();
|
const system = platform();
|
||||||
if (!SUPPORTED_SYSTEM.has(system)) return;
|
let command = '';
|
||||||
|
if (system === 'darwin') {
|
||||||
|
command = 'pbcopy';
|
||||||
|
} else if (system === 'win32') {
|
||||||
|
command = 'clip';
|
||||||
|
} else {
|
||||||
|
// Unix: check if `xclip` is installed
|
||||||
|
const output = execSync('which xclip', { encoding: 'utf8' });
|
||||||
|
if (output[0] !== '/') {
|
||||||
|
// Did not find a path for xclip, bail out!
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
command = 'xclip -sel clipboard -l 1';
|
||||||
|
}
|
||||||
|
|
||||||
console.log();
|
console.log();
|
||||||
const { shouldCopy } = await prompts({
|
const { shouldCopy } = await prompts({
|
||||||
|
@ -54,11 +66,11 @@ async function copyToClipboard(text: string) {
|
||||||
initial: true,
|
initial: true,
|
||||||
});
|
});
|
||||||
if (!shouldCopy) return;
|
if (!shouldCopy) return;
|
||||||
const command = system === 'darwin' ? 'pbcopy' : 'clip';
|
|
||||||
try {
|
try {
|
||||||
execSync(`echo ${JSON.stringify(text.trim())} | ${command}`, {
|
execSync(command, {
|
||||||
|
input: text.trim(),
|
||||||
encoding: 'utf8',
|
encoding: 'utf8',
|
||||||
stdio: 'ignore',
|
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(
|
console.error(
|
||||||
|
|
|
@ -148,9 +148,15 @@ export const _internal = {
|
||||||
hasContentFlag(modUrl, DATA_FLAG) ||
|
hasContentFlag(modUrl, DATA_FLAG) ||
|
||||||
Boolean(getContentRendererByViteId(modUrl, settings))
|
Boolean(getContentRendererByViteId(modUrl, settings))
|
||||||
) {
|
) {
|
||||||
const mod = await viteServer.moduleGraph.getModuleByUrl(modUrl);
|
try {
|
||||||
if (mod) {
|
const mod = await viteServer.moduleGraph.getModuleByUrl(modUrl);
|
||||||
viteServer.moduleGraph.invalidateModule(mod);
|
if (mod) {
|
||||||
|
viteServer.moduleGraph.invalidateModule(mod);
|
||||||
|
}
|
||||||
|
} catch (e: any) {
|
||||||
|
// The server may be closed due to a restart caused by this file change
|
||||||
|
if (e.code === 'ERR_CLOSED_SERVER') break;
|
||||||
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -200,7 +200,7 @@ function rollupPluginAstroBuildCSS(options: PluginOptions): VitePlugin[] {
|
||||||
const inlineConfig = settings.config.build.inlineStylesheets;
|
const inlineConfig = settings.config.build.inlineStylesheets;
|
||||||
const { assetsInlineLimit = 4096 } = settings.config.vite?.build ?? {};
|
const { assetsInlineLimit = 4096 } = settings.config.vite?.build ?? {};
|
||||||
|
|
||||||
Object.entries(bundle).forEach(([_, stylesheet]) => {
|
Object.entries(bundle).forEach(([id, stylesheet]) => {
|
||||||
if (
|
if (
|
||||||
stylesheet.type !== 'asset' ||
|
stylesheet.type !== 'asset' ||
|
||||||
stylesheet.name?.endsWith('.css') !== true ||
|
stylesheet.name?.endsWith('.css') !== true ||
|
||||||
|
@ -224,10 +224,15 @@ function rollupPluginAstroBuildCSS(options: PluginOptions): VitePlugin[] {
|
||||||
: { type: 'external', src: stylesheet.fileName };
|
: { type: 'external', src: stylesheet.fileName };
|
||||||
|
|
||||||
const pages = Array.from(eachPageData(internals));
|
const pages = Array.from(eachPageData(internals));
|
||||||
|
let sheetAddedToPage = false;
|
||||||
|
|
||||||
pages.forEach((pageData) => {
|
pages.forEach((pageData) => {
|
||||||
const orderingInfo = pagesToCss[pageData.moduleSpecifier]?.[stylesheet.fileName];
|
const orderingInfo = pagesToCss[pageData.moduleSpecifier]?.[stylesheet.fileName];
|
||||||
if (orderingInfo !== undefined) return pageData.styles.push({ ...orderingInfo, sheet });
|
if (orderingInfo !== undefined) {
|
||||||
|
pageData.styles.push({ ...orderingInfo, sheet });
|
||||||
|
sheetAddedToPage = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const propagatedPaths = pagesToPropagatedCss[pageData.moduleSpecifier];
|
const propagatedPaths = pagesToPropagatedCss[pageData.moduleSpecifier];
|
||||||
if (propagatedPaths === undefined) return;
|
if (propagatedPaths === undefined) return;
|
||||||
|
@ -243,8 +248,21 @@ function rollupPluginAstroBuildCSS(options: PluginOptions): VitePlugin[] {
|
||||||
pageData.propagatedStyles.set(pageInfoId, new Set()).get(pageInfoId)!;
|
pageData.propagatedStyles.set(pageInfoId, new Set()).get(pageInfoId)!;
|
||||||
|
|
||||||
propagatedStyles.add(sheet);
|
propagatedStyles.add(sheet);
|
||||||
|
sheetAddedToPage = true;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (toBeInlined && sheetAddedToPage) {
|
||||||
|
// CSS is already added to all used pages, we can delete it from the bundle
|
||||||
|
// and make sure no chunks reference it via `importedCss` (for Vite preloading)
|
||||||
|
// to avoid duplicate CSS.
|
||||||
|
delete bundle[id];
|
||||||
|
for (const chunk of Object.values(bundle)) {
|
||||||
|
if (chunk.type === 'chunk') {
|
||||||
|
chunk.viteMetadata?.importedCss?.delete(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -39,7 +39,6 @@ export function createAPIContext({
|
||||||
props,
|
props,
|
||||||
adapterName,
|
adapterName,
|
||||||
}: CreateAPIContext): APIContext {
|
}: CreateAPIContext): APIContext {
|
||||||
initResponseWithEncoding();
|
|
||||||
const context = {
|
const context = {
|
||||||
cookies: new AstroCookies(request),
|
cookies: new AstroCookies(request),
|
||||||
request,
|
request,
|
||||||
|
@ -92,44 +91,28 @@ export function createAPIContext({
|
||||||
|
|
||||||
type ResponseParameters = ConstructorParameters<typeof Response>;
|
type ResponseParameters = ConstructorParameters<typeof Response>;
|
||||||
|
|
||||||
export let ResponseWithEncoding: ReturnType<typeof initResponseWithEncoding>;
|
export class ResponseWithEncoding extends Response {
|
||||||
// TODO Remove this after StackBlitz supports Node 18.
|
constructor(body: ResponseParameters[0], init: ResponseParameters[1], encoding?: BufferEncoding) {
|
||||||
let initResponseWithEncoding = () => {
|
// If a body string is given, try to encode it to preserve the behaviour as simple objects.
|
||||||
class LocalResponseWithEncoding extends Response {
|
// We don't do the full handling as simple objects so users can control how headers are set instead.
|
||||||
constructor(
|
if (typeof body === 'string') {
|
||||||
body: ResponseParameters[0],
|
// In NodeJS, we can use Buffer.from which supports all BufferEncoding
|
||||||
init: ResponseParameters[1],
|
if (typeof Buffer !== 'undefined' && Buffer.from) {
|
||||||
encoding?: BufferEncoding
|
body = Buffer.from(body, encoding);
|
||||||
) {
|
|
||||||
// If a body string is given, try to encode it to preserve the behaviour as simple objects.
|
|
||||||
// We don't do the full handling as simple objects so users can control how headers are set instead.
|
|
||||||
if (typeof body === 'string') {
|
|
||||||
// In NodeJS, we can use Buffer.from which supports all BufferEncoding
|
|
||||||
if (typeof Buffer !== 'undefined' && Buffer.from) {
|
|
||||||
body = Buffer.from(body, encoding);
|
|
||||||
}
|
|
||||||
// In non-NodeJS, use the web-standard TextEncoder for utf-8 strings
|
|
||||||
else if (encoding == null || encoding === 'utf8' || encoding === 'utf-8') {
|
|
||||||
body = encoder.encode(body);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// In non-NodeJS, use the web-standard TextEncoder for utf-8 strings
|
||||||
super(body, init);
|
else if (encoding == null || encoding === 'utf8' || encoding === 'utf-8') {
|
||||||
|
body = encoder.encode(body);
|
||||||
if (encoding) {
|
|
||||||
this.headers.set('X-Astro-Encoding', encoding);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
super(body, init);
|
||||||
|
|
||||||
|
if (encoding) {
|
||||||
|
this.headers.set('X-Astro-Encoding', encoding);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Set the module scoped variable.
|
|
||||||
ResponseWithEncoding = LocalResponseWithEncoding;
|
|
||||||
|
|
||||||
// Turn this into a noop.
|
|
||||||
initResponseWithEncoding = (() => {}) as any;
|
|
||||||
|
|
||||||
return LocalResponseWithEncoding;
|
|
||||||
};
|
|
||||||
|
|
||||||
export async function callEndpoint<MiddlewareResult = Response | EndpointOutput>(
|
export async function callEndpoint<MiddlewareResult = Response | EndpointOutput>(
|
||||||
mod: EndpointHandler,
|
mod: EndpointHandler,
|
||||||
|
|
|
@ -1158,7 +1158,7 @@ export const ContentSchemaContainsSlugError = {
|
||||||
/**
|
/**
|
||||||
* @docs
|
* @docs
|
||||||
* @message A collection queried via `getCollection()` does not exist.
|
* @message A collection queried via `getCollection()` does not exist.
|
||||||
* @deprecated Collections that do not exist no longer result in an error. A warning is omitted instead.
|
* @deprecated Collections that do not exist no longer result in an error. A warning is given instead.
|
||||||
* @description
|
* @description
|
||||||
* When querying a collection, ensure a collection directory with the requested name exists under `src/content/`.
|
* When querying a collection, ensure a collection directory with the requested name exists under `src/content/`.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,19 +1,52 @@
|
||||||
import { EventEmitter } from 'node:events';
|
import { EventEmitter } from 'node:events';
|
||||||
|
import path from 'node:path';
|
||||||
import type * as vite from 'vite';
|
import type * as vite from 'vite';
|
||||||
import type { ModuleLoader, ModuleLoaderEventEmitter } from './loader.js';
|
import type { ModuleLoader, ModuleLoaderEventEmitter } from './loader.js';
|
||||||
|
|
||||||
export function createViteLoader(viteServer: vite.ViteDevServer): ModuleLoader {
|
export function createViteLoader(viteServer: vite.ViteDevServer): ModuleLoader {
|
||||||
const events = new EventEmitter() as ModuleLoaderEventEmitter;
|
const events = new EventEmitter() as ModuleLoaderEventEmitter;
|
||||||
|
|
||||||
viteServer.watcher.on('add', (...args) => events.emit('file-add', args));
|
let isTsconfigUpdated = false;
|
||||||
viteServer.watcher.on('unlink', (...args) => events.emit('file-unlink', args));
|
function isTsconfigUpdate(filePath: string) {
|
||||||
viteServer.watcher.on('change', (...args) => events.emit('file-change', args));
|
const result = path.basename(filePath) === 'tsconfig.json';
|
||||||
|
if (result) isTsconfigUpdated = true;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
wrapMethod(viteServer.ws, 'send', (msg) => {
|
// Skip event emit on tsconfig change as Vite restarts the server, and we don't
|
||||||
|
// want to trigger unnecessary work that will be invalidated shortly.
|
||||||
|
viteServer.watcher.on('add', (...args) => {
|
||||||
|
if (!isTsconfigUpdate(args[0])) {
|
||||||
|
events.emit('file-add', args);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
viteServer.watcher.on('unlink', (...args) => {
|
||||||
|
if (!isTsconfigUpdate(args[0])) {
|
||||||
|
events.emit('file-unlink', args);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
viteServer.watcher.on('change', (...args) => {
|
||||||
|
if (!isTsconfigUpdate(args[0])) {
|
||||||
|
events.emit('file-change', args);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const _wsSend = viteServer.ws.send;
|
||||||
|
viteServer.ws.send = function (...args: any) {
|
||||||
|
// If the tsconfig changed, Vite will trigger a reload as it invalidates the module.
|
||||||
|
// However in Astro, the whole server is restarted when the tsconfig changes. If we
|
||||||
|
// do a restart and reload at the same time, the browser will refetch and the server
|
||||||
|
// is not ready yet, causing a blank page. Here we block that reload from happening.
|
||||||
|
if (isTsconfigUpdated) {
|
||||||
|
isTsconfigUpdated = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const msg = args[0] as vite.HMRPayload;
|
||||||
if (msg?.type === 'error') {
|
if (msg?.type === 'error') {
|
||||||
events.emit('hmr-error', msg);
|
events.emit('hmr-error', msg);
|
||||||
}
|
}
|
||||||
});
|
_wsSend.apply(this, args);
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
import(src) {
|
import(src) {
|
||||||
|
@ -56,11 +89,3 @@ export function createViteLoader(viteServer: vite.ViteDevServer): ModuleLoader {
|
||||||
events,
|
events,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function wrapMethod(object: any, method: string, newFn: (...args: any[]) => void) {
|
|
||||||
const orig = object[method];
|
|
||||||
object[method] = function (...args: any[]) {
|
|
||||||
newFn.apply(this, args);
|
|
||||||
return orig.apply(this, args);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,63 +1,7 @@
|
||||||
|
import buffer from 'node:buffer';
|
||||||
import crypto from 'node:crypto';
|
import crypto from 'node:crypto';
|
||||||
import {
|
|
||||||
ByteLengthQueuingStrategy,
|
|
||||||
CountQueuingStrategy,
|
|
||||||
ReadableByteStreamController,
|
|
||||||
ReadableStream,
|
|
||||||
ReadableStreamBYOBReader,
|
|
||||||
ReadableStreamBYOBRequest,
|
|
||||||
ReadableStreamDefaultController,
|
|
||||||
ReadableStreamDefaultReader,
|
|
||||||
TransformStream,
|
|
||||||
WritableStream,
|
|
||||||
WritableStreamDefaultController,
|
|
||||||
WritableStreamDefaultWriter,
|
|
||||||
} from 'node:stream/web';
|
|
||||||
import { File, FormData, Headers, Request, Response, fetch } from 'undici';
|
|
||||||
|
|
||||||
// NOTE: This file does not intend to polyfill everything that exists, its main goal is to make life easier
|
|
||||||
// for users deploying to runtime that do support these features. In the future, we hope for this file to disappear.
|
|
||||||
|
|
||||||
// HACK (2023-08-18) Stackblitz does not support Node 18 yet, so we'll fake Node 16 support for some time until it's supported
|
|
||||||
// TODO: Remove when Node 18 is supported on Stackblitz. File should get imported from `node:buffer` instead of `undici` once this is removed
|
|
||||||
const isStackblitz = process.env.SHELL === '/bin/jsh' && process.versions.webcontainer != null;
|
|
||||||
|
|
||||||
export function apply() {
|
export function apply() {
|
||||||
if (isStackblitz) {
|
|
||||||
const neededPolyfills = {
|
|
||||||
ByteLengthQueuingStrategy,
|
|
||||||
CountQueuingStrategy,
|
|
||||||
ReadableByteStreamController,
|
|
||||||
ReadableStream,
|
|
||||||
ReadableStreamBYOBReader,
|
|
||||||
ReadableStreamBYOBRequest,
|
|
||||||
ReadableStreamDefaultController,
|
|
||||||
ReadableStreamDefaultReader,
|
|
||||||
TransformStream,
|
|
||||||
WritableStream,
|
|
||||||
WritableStreamDefaultController,
|
|
||||||
WritableStreamDefaultWriter,
|
|
||||||
File,
|
|
||||||
FormData,
|
|
||||||
Headers,
|
|
||||||
Request,
|
|
||||||
Response,
|
|
||||||
fetch,
|
|
||||||
};
|
|
||||||
|
|
||||||
for (let polyfillName of Object.keys(neededPolyfills)) {
|
|
||||||
if (Object.hasOwnProperty.call(globalThis, polyfillName)) continue;
|
|
||||||
|
|
||||||
// Add polyfill to globalThis
|
|
||||||
Object.defineProperty(globalThis, polyfillName, {
|
|
||||||
configurable: true,
|
|
||||||
enumerable: true,
|
|
||||||
writable: true,
|
|
||||||
value: neededPolyfills[polyfillName as keyof typeof neededPolyfills],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove when Node 18 is dropped for Node 20
|
// Remove when Node 18 is dropped for Node 20
|
||||||
if (!globalThis.crypto) {
|
if (!globalThis.crypto) {
|
||||||
Object.defineProperty(globalThis, 'crypto', {
|
Object.defineProperty(globalThis, 'crypto', {
|
||||||
|
@ -68,7 +12,7 @@ export function apply() {
|
||||||
// Remove when Node 18 is dropped for Node 20
|
// Remove when Node 18 is dropped for Node 20
|
||||||
if (!globalThis.File) {
|
if (!globalThis.File) {
|
||||||
Object.defineProperty(globalThis, 'File', {
|
Object.defineProperty(globalThis, 'File', {
|
||||||
value: File,
|
value: buffer.File,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,15 @@ type State = {
|
||||||
};
|
};
|
||||||
type Events = 'astro:page-load' | 'astro:after-swap';
|
type Events = 'astro:page-load' | 'astro:after-swap';
|
||||||
|
|
||||||
|
let viteDevIds: { static: Record<string, string[]>; dynamic: Record<string, string[]> };
|
||||||
|
if (import.meta.env.DEV) {
|
||||||
|
// viteDevIds on a page
|
||||||
|
viteDevIds = JSON.parse(
|
||||||
|
sessionStorage.getItem('astro:viteDevIds') || '{"static":{},"dynamic":{}}'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const page = (url: { origin: string; pathname: string }) => url.origin + url.pathname;
|
||||||
|
|
||||||
// only update history entries that are managed by us
|
// only update history entries that are managed by us
|
||||||
// leave other entries alone and do not accidently add state.
|
// leave other entries alone and do not accidently add state.
|
||||||
const persistState = (state: State) => history.state && history.replaceState(state, '');
|
const persistState = (state: State) => history.state && history.replaceState(state, '');
|
||||||
|
@ -44,8 +53,10 @@ const PERSIST_ATTR = 'data-astro-transition-persist';
|
||||||
const parser = new DOMParser();
|
const parser = new DOMParser();
|
||||||
// explained at its usage
|
// explained at its usage
|
||||||
let noopEl: HTMLDivElement;
|
let noopEl: HTMLDivElement;
|
||||||
|
let reloadEl: HTMLDivElement;
|
||||||
if (import.meta.env.DEV) {
|
if (import.meta.env.DEV) {
|
||||||
noopEl = document.createElement('div');
|
noopEl = document.createElement('div');
|
||||||
|
reloadEl = document.createElement('div');
|
||||||
}
|
}
|
||||||
|
|
||||||
// The History API does not tell you if navigation is forward or back, so
|
// The History API does not tell you if navigation is forward or back, so
|
||||||
|
@ -198,20 +209,40 @@ async function updateDOM(
|
||||||
const href = el.getAttribute('href');
|
const href = el.getAttribute('href');
|
||||||
return newDocument.head.querySelector(`link[rel=stylesheet][href="${href}"]`);
|
return newDocument.head.querySelector(`link[rel=stylesheet][href="${href}"]`);
|
||||||
}
|
}
|
||||||
// What follows is a fix for an issue (#8472) with missing client:only styles after transition.
|
|
||||||
// That problem exists only in dev mode where styles are injected into the page by Vite.
|
|
||||||
// Returning a noop element ensures that the styles are not removed from the old document.
|
|
||||||
// Guarding the code below with the dev mode check
|
|
||||||
// allows tree shaking to remove this code in production.
|
|
||||||
if (import.meta.env.DEV) {
|
if (import.meta.env.DEV) {
|
||||||
if (el.tagName === 'STYLE' && el.dataset.viteDevId) {
|
const viteDevId = el.getAttribute('data-vite-dev-id');
|
||||||
const devId = el.dataset.viteDevId;
|
if (!viteDevId) {
|
||||||
// If this same style tag exists, remove it from the new page
|
return null;
|
||||||
return (
|
}
|
||||||
newDocument.querySelector(`style[data-vite-dev-id="${devId}"]`) ||
|
const newDevEl = newDocument.head.querySelector(`[data-vite-dev-id="${viteDevId}"]`);
|
||||||
// Otherwise, keep it anyways. This is client:only styles.
|
if (newDevEl) {
|
||||||
noopEl
|
return newDevEl;
|
||||||
);
|
}
|
||||||
|
// What follows is a fix for an issue (#8472) with missing client:only styles after transition.
|
||||||
|
// That problem exists only in dev mode where styles are injected into the page by Vite.
|
||||||
|
// Returning a noop element ensures that the styles are not removed from the old document.
|
||||||
|
// Guarding the code below with the dev mode check
|
||||||
|
// allows tree shaking to remove this code in production.
|
||||||
|
if (
|
||||||
|
document.querySelector(
|
||||||
|
`[${PERSIST_ATTR}] astro-island[client="only"], astro-island[client="only"][${PERSIST_ATTR}]`
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
const here = page(toLocation);
|
||||||
|
const dynamicViteDevIds = viteDevIds.dynamic[here];
|
||||||
|
if (!dynamicViteDevIds) {
|
||||||
|
console.info(`
|
||||||
|
${toLocation.pathname}
|
||||||
|
Development mode only: This page uses view transitions with persisted client:only Astro islands.
|
||||||
|
On the first transition to this page, Astro did a full page reload to capture the dynamic effects of the client only code.
|
||||||
|
`);
|
||||||
|
location.href = toLocation.href;
|
||||||
|
return reloadEl;
|
||||||
|
}
|
||||||
|
if (dynamicViteDevIds?.includes(viteDevId)) {
|
||||||
|
return noopEl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -249,12 +280,16 @@ async function updateDOM(
|
||||||
// Swap head
|
// Swap head
|
||||||
for (const el of Array.from(document.head.children)) {
|
for (const el of Array.from(document.head.children)) {
|
||||||
const newEl = persistedHeadElement(el as HTMLElement);
|
const newEl = persistedHeadElement(el as HTMLElement);
|
||||||
|
if (newEl === reloadEl) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
// If the element exists in the document already, remove it
|
// If the element exists in the document already, remove it
|
||||||
// from the new document and leave the current node alone
|
// from the new document and leave the current node alone
|
||||||
if (newEl) {
|
if (newEl) {
|
||||||
newEl.remove();
|
newEl.remove();
|
||||||
} else {
|
} else {
|
||||||
// Otherwise remove the element in the head. It doesn't exist in the new page.
|
// Otherwise remove the element from the head.
|
||||||
|
// It doesn't exist in the new page or will be re-inserted after this loop
|
||||||
el.remove();
|
el.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -336,6 +371,20 @@ async function transition(
|
||||||
options: Options,
|
options: Options,
|
||||||
popState?: State
|
popState?: State
|
||||||
) {
|
) {
|
||||||
|
if (import.meta.env.DEV) {
|
||||||
|
const thisPageStaticViteDevIds = viteDevIds.static[page(location)];
|
||||||
|
if (thisPageStaticViteDevIds) {
|
||||||
|
const allViteDevIds = new Set<string>();
|
||||||
|
document.head
|
||||||
|
.querySelectorAll('[data-vite-dev-id]')
|
||||||
|
.forEach((el) => allViteDevIds.add(el.getAttribute('data-vite-dev-id')!));
|
||||||
|
viteDevIds.dynamic[page(location)] = [...allViteDevIds].filter(
|
||||||
|
(x) => !thisPageStaticViteDevIds.includes(x)
|
||||||
|
);
|
||||||
|
sessionStorage.setItem('astro:viteDevIds', JSON.stringify(viteDevIds, null, 2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let finished: Promise<void>;
|
let finished: Promise<void>;
|
||||||
const href = toLocation.href;
|
const href = toLocation.href;
|
||||||
const response = await fetchHTML(href);
|
const response = await fetchHTML(href);
|
||||||
|
@ -360,6 +409,14 @@ async function transition(
|
||||||
location.href = href;
|
location.href = href;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (import.meta.env.DEV) {
|
||||||
|
const staticViteDevIds = new Set<string>();
|
||||||
|
newDocument.querySelectorAll('head > [data-vite-dev-id]').forEach((el) => {
|
||||||
|
staticViteDevIds.add(el.getAttribute('data-vite-dev-id')!);
|
||||||
|
});
|
||||||
|
viteDevIds.static[page(toLocation)] = [...staticViteDevIds];
|
||||||
|
sessionStorage.setItem('astro:viteDevIds', JSON.stringify(viteDevIds, null, 2));
|
||||||
|
}
|
||||||
|
|
||||||
if (!popState) {
|
if (!popState) {
|
||||||
// save the current scroll position before we change the DOM and transition to the new page
|
// save the current scroll position before we change the DOM and transition to the new page
|
||||||
|
|
|
@ -170,7 +170,7 @@ export async function loadFixture(inlineConfig) {
|
||||||
try {
|
try {
|
||||||
return await fetch(resolvedUrl, init);
|
return await fetch(resolvedUrl, init);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// undici throws a vague error when it fails, so we log the url here to easily debug it
|
// node fetch throws a vague error when it fails, so we log the url here to easily debug it
|
||||||
if (err.message?.includes('fetch failed')) {
|
if (err.message?.includes('fetch failed')) {
|
||||||
console.error(`[astro test] failed to fetch ${resolvedUrl}`);
|
console.error(`[astro test] failed to fetch ${resolvedUrl}`);
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
|
|
@ -39,5 +39,8 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"astro": "workspace:*",
|
"astro": "workspace:*",
|
||||||
"astro-scripts": "workspace:*"
|
"astro-scripts": "workspace:*"
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"provenance": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,5 +58,8 @@
|
||||||
"cheerio": "1.0.0-rc.12",
|
"cheerio": "1.0.0-rc.12",
|
||||||
"mocha": "^10.2.0",
|
"mocha": "^10.2.0",
|
||||||
"wrangler": "^3.5.1"
|
"wrangler": "^3.5.1"
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"provenance": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,5 +59,8 @@
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@webcomponents/template-shadowroot": "^0.2.1",
|
"@webcomponents/template-shadowroot": "^0.2.1",
|
||||||
"lit": "^2.7.0"
|
"lit": "^2.7.0"
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"provenance": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,5 +94,8 @@
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.14.1"
|
"node": ">=18.14.1"
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"provenance": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,5 +79,8 @@
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.14.1"
|
"node": ">=18.14.1"
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"provenance": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,9 @@
|
||||||
"cheerio": "1.0.0-rc.12",
|
"cheerio": "1.0.0-rc.12",
|
||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
"mocha": "^10.2.0",
|
"mocha": "^10.2.0",
|
||||||
"node-mocks-http": "^1.13.0",
|
"node-mocks-http": "^1.13.0"
|
||||||
"undici": "^5.23.0"
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"provenance": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,15 +8,12 @@ import type { OutgoingHttpHeaders } from 'node:http';
|
||||||
* @returns NodeJS OutgoingHttpHeaders object with multiple set-cookie handled as an array of values
|
* @returns NodeJS OutgoingHttpHeaders object with multiple set-cookie handled as an array of values
|
||||||
*/
|
*/
|
||||||
export const createOutgoingHttpHeaders = (
|
export const createOutgoingHttpHeaders = (
|
||||||
webHeaders: Headers | undefined | null
|
headers: Headers | undefined | null
|
||||||
): OutgoingHttpHeaders | undefined => {
|
): OutgoingHttpHeaders | undefined => {
|
||||||
if (!webHeaders) {
|
if (!headers) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
// re-type to access Header.getSetCookie()
|
|
||||||
const headers = webHeaders as HeadersWithGetSetCookie;
|
|
||||||
|
|
||||||
// at this point, a multi-value'd set-cookie header is invalid (it was concatenated as a single CSV, which is not valid for set-cookie)
|
// at this point, a multi-value'd set-cookie header is invalid (it was concatenated as a single CSV, which is not valid for set-cookie)
|
||||||
const nodeHeaders: OutgoingHttpHeaders = Object.fromEntries(headers.entries());
|
const nodeHeaders: OutgoingHttpHeaders = Object.fromEntries(headers.entries());
|
||||||
|
|
||||||
|
@ -26,7 +23,8 @@ export const createOutgoingHttpHeaders = (
|
||||||
|
|
||||||
// if there is > 1 set-cookie header, we have to fix it to be an array of values
|
// if there is > 1 set-cookie header, we have to fix it to be an array of values
|
||||||
if (headers.has('set-cookie')) {
|
if (headers.has('set-cookie')) {
|
||||||
const cookieHeaders = headers.getSetCookie();
|
// @ts-expect-error
|
||||||
|
const cookieHeaders = headers.getSetCookie() as string[];
|
||||||
if (cookieHeaders.length > 1) {
|
if (cookieHeaders.length > 1) {
|
||||||
// the Headers.entries() API already normalized all header names to lower case so we can safely index this as 'set-cookie'
|
// the Headers.entries() API already normalized all header names to lower case so we can safely index this as 'set-cookie'
|
||||||
nodeHeaders['set-cookie'] = cookieHeaders;
|
nodeHeaders['set-cookie'] = cookieHeaders;
|
||||||
|
@ -35,8 +33,3 @@ export const createOutgoingHttpHeaders = (
|
||||||
|
|
||||||
return nodeHeaders;
|
return nodeHeaders;
|
||||||
};
|
};
|
||||||
|
|
||||||
interface HeadersWithGetSetCookie extends Headers {
|
|
||||||
// the @astrojs/webapi polyfill makes this available (as of undici@5.19.0), but tsc doesn't pick it up on the built-in Headers type from DOM lib
|
|
||||||
getSetCookie(): string[];
|
|
||||||
}
|
|
||||||
|
|
|
@ -38,5 +38,8 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"astro": "workspace:*",
|
"astro": "workspace:*",
|
||||||
"astro-scripts": "workspace:*"
|
"astro-scripts": "workspace:*"
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"provenance": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import { fileURLToPath } from 'node:url';
|
||||||
import sirv from './sirv.js';
|
import sirv from './sirv.js';
|
||||||
const resolve = createRequire(import.meta.url).resolve;
|
const resolve = createRequire(import.meta.url).resolve;
|
||||||
|
|
||||||
type PartytownOptions = {
|
export type PartytownOptions = {
|
||||||
config?: PartytownConfig;
|
config?: PartytownConfig;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -52,5 +52,8 @@
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.14.1"
|
"node": ">=18.14.1"
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"provenance": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,5 +40,8 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"throttles": "^1.0.1"
|
"throttles": "^1.0.1"
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"provenance": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,5 +67,8 @@
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.14.1"
|
"node": ">=18.14.1"
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"provenance": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,5 +43,8 @@
|
||||||
"chai": "^4.3.7",
|
"chai": "^4.3.7",
|
||||||
"mocha": "^10.2.0",
|
"mocha": "^10.2.0",
|
||||||
"xml2js": "0.6.2"
|
"xml2js": "0.6.2"
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"provenance": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,5 +47,8 @@
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.14.1"
|
"node": ">=18.14.1"
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"provenance": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,5 +53,8 @@
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.14.1"
|
"node": ">=18.14.1"
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"provenance": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,5 +45,8 @@
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"astro": "workspace:^3.2.2",
|
"astro": "workspace:^3.2.2",
|
||||||
"tailwindcss": "^3.0.24"
|
"tailwindcss": "^3.0.24"
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"provenance": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,5 +72,8 @@
|
||||||
"chai-jest-snapshot": "^2.0.0",
|
"chai-jest-snapshot": "^2.0.0",
|
||||||
"cheerio": "1.0.0-rc.12",
|
"cheerio": "1.0.0-rc.12",
|
||||||
"mocha": "^10.2.0"
|
"mocha": "^10.2.0"
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"provenance": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,5 +61,8 @@
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.14.1"
|
"node": ">=18.14.1"
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"provenance": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,5 +37,8 @@
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"astro",
|
"astro",
|
||||||
"astro-component"
|
"astro-component"
|
||||||
]
|
],
|
||||||
|
"publishConfig": {
|
||||||
|
"provenance": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,5 +57,8 @@
|
||||||
"chai": "^4.3.7",
|
"chai": "^4.3.7",
|
||||||
"mdast-util-mdx-expression": "^1.3.2",
|
"mdast-util-mdx-expression": "^1.3.2",
|
||||||
"mocha": "^10.2.0"
|
"mocha": "^10.2.0"
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"provenance": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,8 +76,8 @@ export function remarkShiki({
|
||||||
// It would become this before hitting our regexes:
|
// It would become this before hitting our regexes:
|
||||||
// <span class="line"
|
// <span class="line"
|
||||||
|
|
||||||
// Replace "shiki" class naming with "astro" and add "is:raw".
|
// Replace "shiki" class naming with "astro".
|
||||||
html = html.replace(/<pre class="(.*?)shiki(.*?)"/, `<pre is:raw class="$1astro-code$2"`);
|
html = html.replace(/<pre class="(.*?)shiki(.*?)"/, `<pre class="$1astro-code$2"`);
|
||||||
// Add "user-select: none;" for "+"/"-" diff symbols
|
// Add "user-select: none;" for "+"/"-" diff symbols
|
||||||
if (node.lang === 'diff') {
|
if (node.lang === 'diff') {
|
||||||
html = html.replace(
|
html = html.replace(
|
||||||
|
|
12
packages/markdown/remark/test/shiki.js
Normal file
12
packages/markdown/remark/test/shiki.js
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import { createMarkdownProcessor } from '../dist/index.js';
|
||||||
|
import chai from 'chai';
|
||||||
|
|
||||||
|
describe('shiki syntax highlighting', async () => {
|
||||||
|
const processor = await createMarkdownProcessor();
|
||||||
|
|
||||||
|
it('does not add is:raw to the output', async () => {
|
||||||
|
const { code } = await processor.render('```\ntest\n```');
|
||||||
|
|
||||||
|
chai.expect(code).not.to.contain('is:raw');
|
||||||
|
});
|
||||||
|
});
|
|
@ -35,7 +35,6 @@
|
||||||
"dset": "^3.1.2",
|
"dset": "^3.1.2",
|
||||||
"is-docker": "^3.0.0",
|
"is-docker": "^3.0.0",
|
||||||
"is-wsl": "^3.0.0",
|
"is-wsl": "^3.0.0",
|
||||||
"undici": "^5.23.0",
|
|
||||||
"which-pm-runs": "^1.1.0"
|
"which-pm-runs": "^1.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -49,5 +48,8 @@
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.14.1"
|
"node": ">=18.14.1"
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"provenance": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
const ASTRO_TELEMETRY_ENDPOINT = `https://telemetry.astro.build/api/v1/record`;
|
const ASTRO_TELEMETRY_ENDPOINT = `https://telemetry.astro.build/api/v1/record`;
|
||||||
import { fetch } from 'undici';
|
|
||||||
|
|
||||||
export function post(body: Record<string, any>): Promise<any> {
|
export function post(body: Record<string, any>): Promise<any> {
|
||||||
return fetch(ASTRO_TELEMETRY_ENDPOINT, {
|
return fetch(ASTRO_TELEMETRY_ENDPOINT, {
|
||||||
|
|
|
@ -38,5 +38,8 @@
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"astro",
|
"astro",
|
||||||
"astro-component"
|
"astro-component"
|
||||||
]
|
],
|
||||||
|
"publishConfig": {
|
||||||
|
"provenance": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -628,9 +628,6 @@ importers:
|
||||||
tsconfig-resolver:
|
tsconfig-resolver:
|
||||||
specifier: ^3.0.1
|
specifier: ^3.0.1
|
||||||
version: 3.0.1
|
version: 3.0.1
|
||||||
undici:
|
|
||||||
specifier: ^5.23.0
|
|
||||||
version: 5.23.0
|
|
||||||
unist-util-visit:
|
unist-util-visit:
|
||||||
specifier: ^4.1.2
|
specifier: ^4.1.2
|
||||||
version: 4.1.2
|
version: 4.1.2
|
||||||
|
@ -4307,9 +4304,6 @@ importers:
|
||||||
node-mocks-http:
|
node-mocks-http:
|
||||||
specifier: ^1.13.0
|
specifier: ^1.13.0
|
||||||
version: 1.13.0
|
version: 1.13.0
|
||||||
undici:
|
|
||||||
specifier: ^5.23.0
|
|
||||||
version: 5.23.0
|
|
||||||
|
|
||||||
packages/integrations/node/test/fixtures/api-route:
|
packages/integrations/node/test/fixtures/api-route:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -5005,9 +4999,6 @@ importers:
|
||||||
is-wsl:
|
is-wsl:
|
||||||
specifier: ^3.0.0
|
specifier: ^3.0.0
|
||||||
version: 3.0.0
|
version: 3.0.0
|
||||||
undici:
|
|
||||||
specifier: ^5.23.0
|
|
||||||
version: 5.23.0
|
|
||||||
which-pm-runs:
|
which-pm-runs:
|
||||||
specifier: ^1.1.0
|
specifier: ^1.1.0
|
||||||
version: 1.1.0
|
version: 1.1.0
|
||||||
|
@ -17276,6 +17267,7 @@ packages:
|
||||||
engines: {node: '>=14.0'}
|
engines: {node: '>=14.0'}
|
||||||
dependencies:
|
dependencies:
|
||||||
busboy: 1.6.0
|
busboy: 1.6.0
|
||||||
|
dev: true
|
||||||
|
|
||||||
/unherit@3.0.1:
|
/unherit@3.0.1:
|
||||||
resolution: {integrity: sha512-akOOQ/Yln8a2sgcLj4U0Jmx0R5jpIg2IUyRrWOzmEbjBtGzBdHtSeFKgoEcoH4KYIG/Pb8GQ/BwtYm0GCq1Sqg==}
|
resolution: {integrity: sha512-akOOQ/Yln8a2sgcLj4U0Jmx0R5jpIg2IUyRrWOzmEbjBtGzBdHtSeFKgoEcoH4KYIG/Pb8GQ/BwtYm0GCq1Sqg==}
|
||||||
|
|
Loading…
Reference in a new issue