astro 2.0.0-beta.3 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/astro.js CHANGED
@@ -4,7 +4,6 @@
4
4
 
5
5
  // ISOMORPHIC FILE: NO TOP-LEVEL IMPORT/REQUIRE() ALLOWED
6
6
  // This file has to run as both ESM and CJS on older Node.js versions
7
- // Assume ESM to start, and then call `require()` below once CJS is confirmed.
8
7
  // Needed for Stackblitz: https://github.com/stackblitz/webcontainer-core/issues/281
9
8
 
10
9
  const CI_INSTRUCTIONS = {
@@ -14,64 +13,41 @@ const CI_INSTRUCTIONS = {
14
13
  VERCEL: 'https://vercel.com/docs/runtimes#official-runtimes/node-js/node-js-version',
15
14
  };
16
15
 
16
+ // Hardcode supported Node.js version so we don't have to read differently in CJS & ESM.
17
+ const engines = '>=16.12.0';
18
+ const skipSemverCheckIfAbove = 16;
19
+
17
20
  /** `astro *` */
18
21
  async function main() {
19
- // Check for ESM support.
20
- // Load the "supports-esm" package in an way that works in both ESM & CJS.
21
- let supportsESM =
22
- typeof require !== 'undefined'
23
- ? require('supports-esm')
24
- : (await import('supports-esm')).default;
25
-
26
- // Check for CJS->ESM named export support.
27
- // "path-to-regexp" is a real-world package that we depend on, that only
28
- // works in later versions of Node with advanced CJS->ESM support.
29
- // If `import {compile} from 'path-to-regexp'` will fail, we need to know.
30
- if (supportsESM) {
31
- const testNamedExportsModule = await import('path-to-regexp');
32
- supportsESM = !!testNamedExportsModule.compile;
33
- }
34
-
35
- // Preflight check complete. Enjoy! ✨
36
- if (supportsESM) {
37
- return import('./dist/cli/index.js')
38
- .then(({ cli }) => cli(process.argv))
39
- .catch((error) => {
40
- console.error(error);
41
- process.exit(1);
42
- });
43
- }
44
-
45
22
  const version = process.versions.node;
46
-
47
- // Not supported (incomplete ESM): It's very difficult (impossible?) to load the
48
- // dependencies below in an unknown module type. If `require` is undefined, then this file
49
- // actually was run as ESM but one of the ESM preflight checks above failed. In that case,
50
- // it's okay to hard-code the valid Node versions here since they will not change over time.
51
- if (typeof require === 'undefined') {
52
- console.error(`\nNode.js v${version} is not supported by Astro!
53
- Please upgrade to a supported version of Node.js: ">=16.12.0"\n`);
23
+ // Fast-path for higher Node.js versions
24
+ if ((parseInt(version) || 0) <= skipSemverCheckIfAbove) {
25
+ try {
26
+ const semver = await import('semver');
27
+ if (!semver.satisfies(version, engines)) {
28
+ await errorNodeUnsupported();
29
+ return;
30
+ }
31
+ } catch {
32
+ await errorNodeUnsupported();
33
+ return;
34
+ }
54
35
  }
55
36
 
56
- // Not supported: Report the most helpful error message possible.
57
- const pkg = require('./package.json');
58
- const ci = require('ci-info');
59
- const semver = require('semver');
60
- const engines = pkg.engines.node;
37
+ return import('./dist/cli/index.js')
38
+ .then(({ cli }) => cli(process.argv))
39
+ .catch((error) => {
40
+ console.error(error);
41
+ process.exit(1);
42
+ });
43
+ }
61
44
 
62
- // TODO: Remove "semver" in Astro v1.0: This is mainly just to check our work. Once run in
63
- // the wild for a bit without error, we can assume our engine range is correct and won't
64
- // change over time.
65
- const isSupported = semver.satisfies(version, engines);
66
- if (isSupported) {
67
- console.error(`\nNode.js v${version} is not supported by Astro!
68
- Supported versions: ${engines}\n
69
- Issue Detected! This Node.js version was expected to work, but failed a system check.
70
- Please file an issue so that we can take a look: https://github.com/withastro/astro/issues/new\n`);
71
- } else {
72
- console.error(`\nNode.js v${version} is not supported by Astro!
45
+ async function errorNodeUnsupported() {
46
+ console.error(`\
47
+ Node.js v${process.versions.node} is not supported by Astro!
73
48
  Please upgrade Node.js to a supported version: "${engines}"\n`);
74
- }
49
+
50
+ const ci = typeof require !== 'undefined' ? require('ci-info') : await import('ci-info');
75
51
 
76
52
  // Special instructions for CI environments, which may have special steps needed.
77
53
  // This is a common issue that we can help users with proactively.
@@ -9,8 +9,10 @@ import { contentFileExts, CONTENT_TYPES_FILE } from "./consts.js";
9
9
  import {
10
10
  getContentPaths,
11
11
  getEntryInfo,
12
+ getEntrySlug,
12
13
  loadContentConfig,
13
- NoCollectionError
14
+ NoCollectionError,
15
+ parseFrontmatter
14
16
  } from "./utils.js";
15
17
  class UnsupportedFileTypeError extends Error {
16
18
  }
@@ -47,6 +49,7 @@ async function createContentTypesGenerator({
47
49
  return { typesGenerated: true };
48
50
  }
49
51
  async function handleEvent(event, opts) {
52
+ var _a, _b;
50
53
  const logLevel = (opts == null ? void 0 : opts.logLevel) ?? "info";
51
54
  if (event.name === "addDir" || event.name === "unlinkDir") {
52
55
  const collection2 = normalizePath(
@@ -115,16 +118,17 @@ async function createContentTypesGenerator({
115
118
  }
116
119
  return { shouldGenerateTypes: false };
117
120
  }
118
- const { id, slug, collection } = entryInfo;
121
+ const { id, collection } = entryInfo;
119
122
  const collectionKey = JSON.stringify(collection);
120
123
  const entryKey = JSON.stringify(id);
121
124
  switch (event.name) {
122
125
  case "add":
126
+ const addedSlug = await parseSlug({ fs, event, entryInfo });
123
127
  if (!(collectionKey in contentTypes)) {
124
128
  addCollection(contentTypes, collectionKey);
125
129
  }
126
130
  if (!(entryKey in contentTypes[collectionKey])) {
127
- addEntry(contentTypes, collectionKey, entryKey, slug);
131
+ setEntry(contentTypes, collectionKey, entryKey, addedSlug);
128
132
  }
129
133
  return { shouldGenerateTypes: true };
130
134
  case "unlink":
@@ -133,6 +137,11 @@ async function createContentTypesGenerator({
133
137
  }
134
138
  return { shouldGenerateTypes: true };
135
139
  case "change":
140
+ const changedSlug = await parseSlug({ fs, event, entryInfo });
141
+ if (((_b = (_a = contentTypes[collectionKey]) == null ? void 0 : _a[entryKey]) == null ? void 0 : _b.slug) !== changedSlug) {
142
+ setEntry(contentTypes, collectionKey, entryKey, changedSlug);
143
+ return { shouldGenerateTypes: true };
144
+ }
136
145
  return { shouldGenerateTypes: false };
137
146
  }
138
147
  }
@@ -196,7 +205,16 @@ function addCollection(contentMap, collectionKey) {
196
205
  function removeCollection(contentMap, collectionKey) {
197
206
  delete contentMap[collectionKey];
198
207
  }
199
- function addEntry(contentTypes, collectionKey, entryKey, slug) {
208
+ async function parseSlug({
209
+ fs,
210
+ event,
211
+ entryInfo
212
+ }) {
213
+ const rawContents = await fs.promises.readFile(event.entry, "utf-8");
214
+ const { data: frontmatter } = parseFrontmatter(rawContents, fileURLToPath(event.entry));
215
+ return getEntrySlug({ ...entryInfo, data: frontmatter });
216
+ }
217
+ function setEntry(contentTypes, collectionKey, entryKey, slug) {
200
218
  contentTypes[collectionKey][entryKey] = { slug };
201
219
  }
202
220
  function removeEntry(contentTypes, collectionKey, entryKey) {
@@ -232,7 +250,7 @@ async function writeContentFiles({
232
250
  for (const entryKey of entryKeys) {
233
251
  const entryMetadata = contentTypes[collectionKey][entryKey];
234
252
  const dataType = (collectionConfig == null ? void 0 : collectionConfig.schema) ? `InferEntrySchema<${collectionKey}>` : "any";
235
- const slugType = (collectionConfig == null ? void 0 : collectionConfig.slug) ? "string" : JSON.stringify(entryMetadata.slug);
253
+ const slugType = JSON.stringify(entryMetadata.slug);
236
254
  contentTypesStr += `${entryKey}: {
237
255
  id: ${entryKey},
238
256
  slug: ${slugType},
@@ -5,43 +5,10 @@ import { z } from 'zod';
5
5
  import { AstroConfig, AstroSettings } from '../@types/astro.js';
6
6
  export declare const collectionConfigParser: z.ZodObject<{
7
7
  schema: z.ZodOptional<z.ZodAny>;
8
- slug: z.ZodOptional<z.ZodFunction<z.ZodTuple<[z.ZodObject<{
9
- id: z.ZodString;
10
- collection: z.ZodString;
11
- defaultSlug: z.ZodString;
12
- body: z.ZodString;
13
- data: z.ZodRecord<z.ZodString, z.ZodAny>;
14
- }, "strip", z.ZodTypeAny, {
15
- id: string;
16
- data: Record<string, any>;
17
- body: string;
18
- collection: string;
19
- defaultSlug: string;
20
- }, {
21
- id: string;
22
- data: Record<string, any>;
23
- body: string;
24
- collection: string;
25
- defaultSlug: string;
26
- }>], z.ZodUnknown>, z.ZodUnion<[z.ZodString, z.ZodPromise<z.ZodString>]>>>;
27
8
  }, "strip", z.ZodTypeAny, {
28
9
  schema?: any;
29
- slug?: ((args_0: {
30
- id: string;
31
- data: Record<string, any>;
32
- body: string;
33
- collection: string;
34
- defaultSlug: string;
35
- }, ...args_1: unknown[]) => string | Promise<string>) | undefined;
36
10
  }, {
37
11
  schema?: any;
38
- slug?: ((args_0: {
39
- id: string;
40
- data: Record<string, any>;
41
- body: string;
42
- collection: string;
43
- defaultSlug: string;
44
- }, ...args_1: unknown[]) => string | Promise<string>) | undefined;
45
12
  }>;
46
13
  export declare function getDotAstroTypeReference({ root, srcDir }: {
47
14
  root: URL;
@@ -50,65 +17,18 @@ export declare function getDotAstroTypeReference({ root, srcDir }: {
50
17
  export declare const contentConfigParser: z.ZodObject<{
51
18
  collections: z.ZodRecord<z.ZodString, z.ZodObject<{
52
19
  schema: z.ZodOptional<z.ZodAny>;
53
- slug: z.ZodOptional<z.ZodFunction<z.ZodTuple<[z.ZodObject<{
54
- id: z.ZodString;
55
- collection: z.ZodString;
56
- defaultSlug: z.ZodString;
57
- body: z.ZodString;
58
- data: z.ZodRecord<z.ZodString, z.ZodAny>;
59
- }, "strip", z.ZodTypeAny, {
60
- id: string;
61
- data: Record<string, any>;
62
- body: string;
63
- collection: string;
64
- defaultSlug: string;
65
- }, {
66
- id: string;
67
- data: Record<string, any>;
68
- body: string;
69
- collection: string;
70
- defaultSlug: string;
71
- }>], z.ZodUnknown>, z.ZodUnion<[z.ZodString, z.ZodPromise<z.ZodString>]>>>;
72
20
  }, "strip", z.ZodTypeAny, {
73
21
  schema?: any;
74
- slug?: ((args_0: {
75
- id: string;
76
- data: Record<string, any>;
77
- body: string;
78
- collection: string;
79
- defaultSlug: string;
80
- }, ...args_1: unknown[]) => string | Promise<string>) | undefined;
81
22
  }, {
82
23
  schema?: any;
83
- slug?: ((args_0: {
84
- id: string;
85
- data: Record<string, any>;
86
- body: string;
87
- collection: string;
88
- defaultSlug: string;
89
- }, ...args_1: unknown[]) => string | Promise<string>) | undefined;
90
24
  }>>;
91
25
  }, "strip", z.ZodTypeAny, {
92
26
  collections: Record<string, {
93
27
  schema?: any;
94
- slug?: ((args_0: {
95
- id: string;
96
- data: Record<string, any>;
97
- body: string;
98
- collection: string;
99
- defaultSlug: string;
100
- }, ...args_1: unknown[]) => string | Promise<string>) | undefined;
101
28
  }>;
102
29
  }, {
103
30
  collections: Record<string, {
104
31
  schema?: any;
105
- slug?: ((args_0: {
106
- id: string;
107
- data: Record<string, any>;
108
- body: string;
109
- collection: string;
110
- defaultSlug: string;
111
- }, ...args_1: unknown[]) => string | Promise<string>) | undefined;
112
32
  }>;
113
33
  }>;
114
34
  export type CollectionConfig = z.infer<typeof collectionConfigParser>;
@@ -132,7 +52,7 @@ export type EntryInfo = {
132
52
  export declare const msg: {
133
53
  collectionConfigMissing: (collection: string) => string;
134
54
  };
135
- export declare function getEntrySlug(entry: Entry, collectionConfig: CollectionConfig): Promise<string>;
55
+ export declare function getEntrySlug({ id, collection, slug, data: unparsedData, }: Pick<Entry, 'id' | 'collection' | 'slug' | 'data'>): string;
136
56
  export declare function getEntryData(entry: Entry, collectionConfig: CollectionConfig): Promise<any>;
137
57
  export declare class NoCollectionError extends Error {
138
58
  }
@@ -8,16 +8,7 @@ import { AstroError, AstroErrorData } from "../core/errors/index.js";
8
8
  import { CONTENT_TYPES_FILE } from "./consts.js";
9
9
  import { astroContentVirtualModPlugin } from "./vite-plugin-content-virtual-mod.js";
10
10
  const collectionConfigParser = z.object({
11
- schema: z.any().optional(),
12
- slug: z.function().args(
13
- z.object({
14
- id: z.string(),
15
- collection: z.string(),
16
- defaultSlug: z.string(),
17
- body: z.string(),
18
- data: z.record(z.any())
19
- })
20
- ).returns(z.union([z.string(), z.promise(z.string())])).optional()
11
+ schema: z.any().optional()
21
12
  });
22
13
  function getDotAstroTypeReference({ root, srcDir }) {
23
14
  const { cacheDir } = getContentPaths({ root, srcDir });
@@ -32,18 +23,23 @@ const contentConfigParser = z.object({
32
23
  const msg = {
33
24
  collectionConfigMissing: (collection) => `${collection} does not have a config. We suggest adding one for type safety!`
34
25
  };
35
- async function getEntrySlug(entry, collectionConfig) {
36
- var _a;
37
- return ((_a = collectionConfig.slug) == null ? void 0 : _a.call(collectionConfig, {
38
- id: entry.id,
39
- data: entry.data,
40
- defaultSlug: entry.slug,
41
- collection: entry.collection,
42
- body: entry.body
43
- })) ?? entry.slug;
26
+ function getEntrySlug({
27
+ id,
28
+ collection,
29
+ slug,
30
+ data: unparsedData
31
+ }) {
32
+ try {
33
+ return z.string().default(slug).parse(unparsedData.slug);
34
+ } catch {
35
+ throw new AstroError({
36
+ ...AstroErrorData.InvalidContentEntrySlugError,
37
+ message: AstroErrorData.InvalidContentEntrySlugError.message(collection, id)
38
+ });
39
+ }
44
40
  }
45
41
  async function getEntryData(entry, collectionConfig) {
46
- let data = entry.data;
42
+ let { slug, ...data } = entry.data;
47
43
  if (collectionConfig.schema) {
48
44
  if (typeof collectionConfig.schema === "object" && !("safeParseAsync" in collectionConfig.schema)) {
49
45
  throw new AstroError({
@@ -53,13 +49,19 @@ async function getEntryData(entry, collectionConfig) {
53
49
  code: 99999
54
50
  });
55
51
  }
52
+ if (typeof collectionConfig.schema === "object" && "shape" in collectionConfig.schema && collectionConfig.schema.shape.slug) {
53
+ throw new AstroError({
54
+ ...AstroErrorData.ContentSchemaContainsSlugError,
55
+ message: AstroErrorData.ContentSchemaContainsSlugError.message(entry.collection)
56
+ });
57
+ }
56
58
  const parsed = await collectionConfig.schema.safeParseAsync(entry.data, { errorMap });
57
59
  if (parsed.success) {
58
60
  data = parsed.data;
59
61
  } else {
60
62
  const formattedError = new AstroError({
61
- ...AstroErrorData.MarkdownContentSchemaValidationError,
62
- message: AstroErrorData.MarkdownContentSchemaValidationError.message(
63
+ ...AstroErrorData.InvalidContentEntryFrontmatterError,
64
+ message: AstroErrorData.InvalidContentEntryFrontmatterError.message(
63
65
  entry.collection,
64
66
  entry.id,
65
67
  parsed.error
@@ -121,9 +121,9 @@ function astroContentServerPlugin({
121
121
  return;
122
122
  const _internal = { filePath: fileId, rawData };
123
123
  const partialEntry = { data: unparsedData, body, _internal, ...entryInfo };
124
+ const slug = getEntrySlug(partialEntry);
124
125
  const collectionConfig = contentConfig == null ? void 0 : contentConfig.collections[entryInfo.collection];
125
126
  const data = collectionConfig ? await getEntryData(partialEntry, collectionConfig) : unparsedData;
126
- const slug = collectionConfig ? await getEntrySlug({ ...partialEntry, data }, collectionConfig) : entryInfo.slug;
127
127
  const code = escapeViteEnvReferences(`
128
128
  export const id = ${JSON.stringify(entryInfo.id)};
129
129
  export const collection = ${JSON.stringify(entryInfo.collection)};
@@ -14,6 +14,7 @@ import { appendForwardSlash, prependForwardSlash } from "../../core/path.js";
14
14
  import { isModeServerWithNoAdapter } from "../../core/util.js";
15
15
  import { runHookBuildSetup } from "../../integrations/index.js";
16
16
  import { PAGE_SCRIPT_ID } from "../../vite-plugin-scripts/index.js";
17
+ import { resolvedPagesVirtualModuleId } from "../app/index.js";
17
18
  import { AstroError, AstroErrorData } from "../errors/index.js";
18
19
  import { info } from "../logger/core.js";
19
20
  import { getOutDirWithinCwd } from "./common.js";
@@ -105,7 +106,13 @@ async function ssrBuild(opts, internals, input) {
105
106
  chunkFileNames: `chunks/[name].[hash].mjs`,
106
107
  assetFileNames: `${settings.config.build.assets}/[name].[hash][extname]`,
107
108
  ...(_c = (_b = viteConfig.build) == null ? void 0 : _b.rollupOptions) == null ? void 0 : _c.output,
108
- entryFileNames: opts.buildConfig.serverEntry
109
+ entryFileNames(chunkInfo) {
110
+ if (chunkInfo.facadeModuleId === resolvedPagesVirtualModuleId) {
111
+ return opts.buildConfig.serverEntry;
112
+ } else {
113
+ return "[name].mjs";
114
+ }
115
+ }
109
116
  }
110
117
  },
111
118
  ssr: true,
@@ -1,4 +1,4 @@
1
- const ASTRO_VERSION = "2.0.0-beta.3";
1
+ const ASTRO_VERSION = "2.0.0";
2
2
  const SUPPORTED_MARKDOWN_FILE_EXTENSIONS = [
3
3
  ".markdown",
4
4
  ".mdown",
@@ -29,7 +29,7 @@ async function dev(settings, options) {
29
29
  isRestart: options.isRestart
30
30
  })
31
31
  );
32
- const currentVersion = "2.0.0-beta.3";
32
+ const currentVersion = "2.0.0";
33
33
  if (currentVersion.includes("-")) {
34
34
  warn(options.logging, null, msg.prerelease({ currentVersion }));
35
35
  }
@@ -437,25 +437,6 @@ export declare const AstroErrorData: {
437
437
  readonly title: "Failed to parse Markdown frontmatter.";
438
438
  readonly code: 6001;
439
439
  };
440
- /**
441
- * @docs
442
- * @message
443
- * **Example error message:**<br/>
444
- * Could not parse frontmatter in **blog** → **post.md**<br/>
445
- * "title" is required.<br/>
446
- * "date" must be a valid date.
447
- * @description
448
- * A Markdown document's frontmatter in `src/content/` does not match its collection schema.
449
- * Make sure that all required fields are present, and that all fields are of the correct type.
450
- * You can check against the collection schema in your `src/content/config.*` file.
451
- * See the [Content collections documentation](https://docs.astro.build/en/guides/content-collections/) for more information.
452
- */
453
- readonly MarkdownContentSchemaValidationError: {
454
- readonly title: "Content collection frontmatter invalid.";
455
- readonly code: 6002;
456
- readonly message: (collection: string, entryId: string, error: ZodError) => string;
457
- readonly hint: "See https://docs.astro.build/en/guides/content-collections/ for more information on content schemas.";
458
- };
459
440
  /**
460
441
  * @docs
461
442
  * @see
@@ -533,6 +514,60 @@ export declare const AstroErrorData: {
533
514
  readonly message: "`astro sync` command failed to generate content collection types.";
534
515
  readonly hint: "Check your `src/content/config.*` file for typos.";
535
516
  };
517
+ /**
518
+ * @docs
519
+ * @kind heading
520
+ * @name Content Collection Errors
521
+ */
522
+ readonly UnknownContentCollectionError: {
523
+ readonly title: "Unknown Content Collection Error.";
524
+ readonly code: 9000;
525
+ };
526
+ /**
527
+ * @docs
528
+ * @message
529
+ * **Example error message:**<br/>
530
+ * **blog** → **post.md** frontmatter does not match collection schema.<br/>
531
+ * "title" is required.<br/>
532
+ * "date" must be a valid date.
533
+ * @description
534
+ * A Markdown or MDX entry in `src/content/` does not match its collection schema.
535
+ * Make sure that all required fields are present, and that all fields are of the correct type.
536
+ * You can check against the collection schema in your `src/content/config.*` file.
537
+ * See the [Content collections documentation](https://docs.astro.build/en/guides/content-collections/) for more information.
538
+ */
539
+ readonly InvalidContentEntryFrontmatterError: {
540
+ readonly title: "Content entry frontmatter does not match schema.";
541
+ readonly code: 9001;
542
+ readonly message: (collection: string, entryId: string, error: ZodError) => string;
543
+ readonly hint: "See https://docs.astro.build/en/guides/content-collections/ for more information on content schemas.";
544
+ };
545
+ /**
546
+ * @docs
547
+ * @see
548
+ * - [The reserved entry `slug` field](https://docs.astro.build/en/guides/content-collections/)
549
+ * @description
550
+ * An entry in `src/content/` has an invalid `slug`. This field is reserved for generating entry slugs, and must be a string when present.
551
+ */
552
+ readonly InvalidContentEntrySlugError: {
553
+ readonly title: "Invalid content entry slug.";
554
+ readonly code: 9002;
555
+ readonly message: (collection: string, entryId: string) => string;
556
+ readonly hint: "See https://docs.astro.build/en/guides/content-collections/ for more on the `slug` field.";
557
+ };
558
+ /**
559
+ * @docs
560
+ * @see
561
+ * - [The reserved entry `slug` field](https://docs.astro.build/en/guides/content-collections/)
562
+ * @description
563
+ * A content collection schema should not contain the `slug` field. This is reserved by Astro for generating entry slugs. Remove the `slug` field from your schema, or choose a different name.
564
+ */
565
+ readonly ContentSchemaContainsSlugError: {
566
+ readonly title: "Content Schema should not contain `slug`.";
567
+ readonly code: 9003;
568
+ readonly message: (collection: string) => string;
569
+ readonly hint: "See https://docs.astro.build/en/guides/content-collections/ for more on the `slug` field.";
570
+ };
536
571
  readonly UnknownError: {
537
572
  readonly title: "Unknown Error.";
538
573
  readonly code: 99999;
@@ -165,17 +165,6 @@ Expected \`true\` value but got \`${suffix}\`.`;
165
165
  title: "Failed to parse Markdown frontmatter.",
166
166
  code: 6001
167
167
  },
168
- MarkdownContentSchemaValidationError: {
169
- title: "Content collection frontmatter invalid.",
170
- code: 6002,
171
- message: (collection, entryId, error) => {
172
- return [
173
- `${String(collection)} \u2192 ${String(entryId)} frontmatter does not match collection schema.`,
174
- ...error.errors.map((zodError) => zodError.message)
175
- ].join("\n");
176
- },
177
- hint: "See https://docs.astro.build/en/guides/content-collections/ for more information on content schemas."
178
- },
179
168
  InvalidFrontmatterInjectionError: {
180
169
  title: "Invalid frontmatter injection.",
181
170
  code: 6003,
@@ -213,6 +202,39 @@ Expected \`true\` value but got \`${suffix}\`.`;
213
202
  message: "`astro sync` command failed to generate content collection types.",
214
203
  hint: "Check your `src/content/config.*` file for typos."
215
204
  },
205
+ UnknownContentCollectionError: {
206
+ title: "Unknown Content Collection Error.",
207
+ code: 9e3
208
+ },
209
+ InvalidContentEntryFrontmatterError: {
210
+ title: "Content entry frontmatter does not match schema.",
211
+ code: 9001,
212
+ message: (collection, entryId, error) => {
213
+ return [
214
+ `${String(collection)} \u2192 ${String(entryId)} frontmatter does not match collection schema.`,
215
+ ...error.errors.map((zodError) => zodError.message)
216
+ ].join("\n");
217
+ },
218
+ hint: "See https://docs.astro.build/en/guides/content-collections/ for more information on content schemas."
219
+ },
220
+ InvalidContentEntrySlugError: {
221
+ title: "Invalid content entry slug.",
222
+ code: 9002,
223
+ message: (collection, entryId) => {
224
+ return `${String(collection)} \u2192 ${String(
225
+ entryId
226
+ )} has an invalid slug. \`slug\` must be a string.`;
227
+ },
228
+ hint: "See https://docs.astro.build/en/guides/content-collections/ for more on the `slug` field."
229
+ },
230
+ ContentSchemaContainsSlugError: {
231
+ title: "Content Schema should not contain `slug`.",
232
+ code: 9003,
233
+ message: (collection) => {
234
+ return `A content collection schema should not contain \`slug\` since it is reserved for slug generation. Remove this from your ${collection} collection schema.`;
235
+ },
236
+ hint: "See https://docs.astro.build/en/guides/content-collections/ for more on the `slug` field."
237
+ },
216
238
  UnknownError: {
217
239
  title: "Unknown Error.",
218
240
  code: 99999
@@ -47,7 +47,7 @@ function serverStart({
47
47
  base,
48
48
  isRestart = false
49
49
  }) {
50
- const version = "2.0.0-beta.3";
50
+ const version = "2.0.0";
51
51
  const localPrefix = `${dim("\u2503")} Local `;
52
52
  const networkPrefix = `${dim("\u2503")} Network `;
53
53
  const emptyPrefix = " ".repeat(11);
@@ -233,7 +233,7 @@ function printHelp({
233
233
  message.push(
234
234
  linebreak(),
235
235
  ` ${bgGreen(black(` ${commandName} `))} ${green(
236
- `v${"2.0.0-beta.3"}`
236
+ `v${"2.0.0"}`
237
237
  )} ${headline}`
238
238
  );
239
239
  }
@@ -2,7 +2,7 @@ import { fileURLToPath } from "url";
2
2
  import { PAGE_SCRIPT_ID } from "../../../vite-plugin-scripts/index.js";
3
3
  import { enhanceViteSSRError } from "../../errors/dev/index.js";
4
4
  import { AggregateError, CSSError, MarkdownError } from "../../errors/index.js";
5
- import { isPage, resolveIdToUrl } from "../../util.js";
5
+ import { isPage, resolveIdToUrl, viteID } from "../../util.js";
6
6
  import { createRenderContext, renderPage as coreRenderPage } from "../index.js";
7
7
  import { filterFoundRenderers, loadRenderer } from "../renderer.js";
8
8
  import { getStylesForURL } from "./css.js";
@@ -78,7 +78,10 @@ async function getScriptsAndStyles({ env, filePath }) {
78
78
  children: ""
79
79
  });
80
80
  styles.add({
81
- props: {},
81
+ props: {
82
+ type: "text/css",
83
+ "data-astro-dev-id": viteID(new URL(`.${url}`, env.settings.config.root))
84
+ },
82
85
  children: content
83
86
  });
84
87
  });
@@ -5,7 +5,7 @@ if (import.meta.hot) {
5
5
  for (const record of records) {
6
6
  for (const node of record.addedNodes) {
7
7
  if (isViteInjectedStyle(node)) {
8
- (_a = injectedStyles.get(node.innerHTML.trim())) == null ? void 0 : _a.remove();
8
+ (_a = injectedStyles.get(node.getAttribute("data-vite-dev-id"))) == null ? void 0 : _a.remove();
9
9
  }
10
10
  }
11
11
  }
@@ -24,8 +24,8 @@ if (import.meta.hot) {
24
24
  }
25
25
  function getInjectedStyles() {
26
26
  const injectedStyles = /* @__PURE__ */ new Map();
27
- document.querySelectorAll("style").forEach((el) => {
28
- injectedStyles.set(el.innerHTML.trim(), el);
27
+ document.querySelectorAll("style[data-astro-dev-id]").forEach((el) => {
28
+ injectedStyles.set(el.getAttribute("data-astro-dev-id"), el);
29
29
  });
30
30
  return injectedStyles;
31
31
  }
@@ -33,5 +33,5 @@ function isStyle(node) {
33
33
  return node.nodeType === node.ELEMENT_NODE && node.tagName.toLowerCase() === "style";
34
34
  }
35
35
  function isViteInjectedStyle(node) {
36
- return isStyle(node) && node.getAttribute("type") === "text/css";
36
+ return isStyle(node) && node.getAttribute("type") === "text/css" && !!node.getAttribute("data-vite-dev-id");
37
37
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "astro",
3
- "version": "2.0.0-beta.3",
3
+ "version": "2.0.0",
4
4
  "description": "Astro is a modern site builder with web best practices, performance, and DX front-of-mind.",
5
5
  "type": "module",
6
6
  "author": "withastro",
@@ -85,11 +85,11 @@
85
85
  "src/content/template"
86
86
  ],
87
87
  "dependencies": {
88
- "@astrojs/compiler": "^1.0.0",
88
+ "@astrojs/compiler": "^1.0.1",
89
89
  "@astrojs/language-server": "^0.28.3",
90
- "@astrojs/markdown-remark": "^2.0.0-beta.2",
91
- "@astrojs/telemetry": "^2.0.0-beta.0",
92
- "@astrojs/webapi": "^2.0.0-beta.0",
90
+ "@astrojs/markdown-remark": "^2.0.0",
91
+ "@astrojs/telemetry": "^2.0.0",
92
+ "@astrojs/webapi": "^2.0.0",
93
93
  "@babel/core": "^7.18.2",
94
94
  "@babel/generator": "^7.18.2",
95
95
  "@babel/parser": "^7.18.4",
@@ -160,7 +160,7 @@
160
160
  "@types/send": "^0.17.1",
161
161
  "@types/server-destroy": "^1.0.1",
162
162
  "@types/unist": "^2.0.6",
163
- "astro-scripts": "0.0.10-beta.0",
163
+ "astro-scripts": "0.0.10",
164
164
  "chai": "^4.3.6",
165
165
  "cheerio": "^1.0.0-rc.11",
166
166
  "eol": "^0.9.1",