diff --git a/.changeset/five-toes-swim.md b/.changeset/five-toes-swim.md new file mode 100644 index 000000000000..ac8d04b7a6d3 --- /dev/null +++ b/.changeset/five-toes-swim.md @@ -0,0 +1,5 @@ +--- +"astro": minor +--- + +in this release we can support .toml file as data entry for in the /src/content folder diff --git a/examples/with-data/.codesandbox/Dockerfile b/examples/with-data/.codesandbox/Dockerfile new file mode 100644 index 000000000000..c3b5c81a121d --- /dev/null +++ b/examples/with-data/.codesandbox/Dockerfile @@ -0,0 +1 @@ +FROM node:18-bullseye diff --git a/examples/with-data/.gitignore b/examples/with-data/.gitignore new file mode 100644 index 000000000000..016b59ea143d --- /dev/null +++ b/examples/with-data/.gitignore @@ -0,0 +1,24 @@ +# build output +dist/ + +# generated types +.astro/ + +# dependencies +node_modules/ + +# logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# environment variables +.env +.env.production + +# macOS-specific files +.DS_Store + +# jetbrains setting folder +.idea/ diff --git a/examples/with-data/.vscode/extensions.json b/examples/with-data/.vscode/extensions.json new file mode 100644 index 000000000000..22a15055d638 --- /dev/null +++ b/examples/with-data/.vscode/extensions.json @@ -0,0 +1,4 @@ +{ + "recommendations": ["astro-build.astro-vscode"], + "unwantedRecommendations": [] +} diff --git a/examples/with-data/.vscode/launch.json b/examples/with-data/.vscode/launch.json new file mode 100644 index 000000000000..d6422097621f --- /dev/null +++ b/examples/with-data/.vscode/launch.json @@ -0,0 +1,11 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "command": "./node_modules/.bin/astro dev", + "name": "Development server", + "request": "launch", + "type": "node-terminal" + } + ] +} diff --git a/examples/with-data/README.md b/examples/with-data/README.md new file mode 100644 index 000000000000..1db3fb3991a8 --- /dev/null +++ b/examples/with-data/README.md @@ -0,0 +1,54 @@ +# Astro Starter Kit: Basics + +```sh +npm create astro@latest -- --template basics +``` + +[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/basics) +[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/basics) +[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/withastro/astro?devcontainer_path=.devcontainer/basics/devcontainer.json) + +> 🧑‍🚀 **Seasoned astronaut?** Delete this file. Have fun! + +![just-the-basics](https://github.com/withastro/astro/assets/2244813/a0a5533c-a856-4198-8470-2d67b1d7c554) + +## 🚀 Project Structure + +Inside of your Astro project, you'll see the following folders and files: + +```text +/ +├── public/ +│ └── favicon.svg +├── src/ +│ ├── components/ +│ │ └── Card.astro +│ ├── layouts/ +│ │ └── Layout.astro +│ └── pages/ +│ └── index.astro +└── package.json +``` + +Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name. + +There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components. + +Any static assets, like images, can be placed in the `public/` directory. + +## 🧞 Commands + +All commands are run from the root of the project, from a terminal: + +| Command | Action | +| :------------------------ | :----------------------------------------------- | +| `npm install` | Installs dependencies | +| `npm run dev` | Starts local dev server at `localhost:4321` | +| `npm run build` | Build your production site to `./dist/` | +| `npm run preview` | Preview your build locally, before deploying | +| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` | +| `npm run astro -- --help` | Get help using the Astro CLI | + +## 👀 Want to learn more? + +Feel free to check [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat). diff --git a/examples/with-data/astro.config.mjs b/examples/with-data/astro.config.mjs new file mode 100644 index 000000000000..882e6515a67e --- /dev/null +++ b/examples/with-data/astro.config.mjs @@ -0,0 +1,4 @@ +import { defineConfig } from 'astro/config'; + +// https://astro.build/config +export default defineConfig({}); diff --git a/examples/with-data/package.json b/examples/with-data/package.json new file mode 100644 index 000000000000..4fd5d4fb15c9 --- /dev/null +++ b/examples/with-data/package.json @@ -0,0 +1,16 @@ +{ + "name": "@example/with-data", + "type": "module", + "version": "0.0.1", + "private": true, + "scripts": { + "dev": "astro dev", + "start": "astro dev", + "build": "astro build", + "preview": "astro preview", + "astro": "astro" + }, + "dependencies": { + "astro": "^4.8.2" + } +} diff --git a/examples/with-data/public/favicon.svg b/examples/with-data/public/favicon.svg new file mode 100644 index 000000000000..f157bd1c5e28 --- /dev/null +++ b/examples/with-data/public/favicon.svg @@ -0,0 +1,9 @@ + + + + diff --git a/examples/with-data/src/components/Card.astro b/examples/with-data/src/components/Card.astro new file mode 100644 index 000000000000..bd6d5971ebf3 --- /dev/null +++ b/examples/with-data/src/components/Card.astro @@ -0,0 +1,61 @@ +--- +interface Props { + title: string; + body: string; + href: string; +} + +const { href, title, body } = Astro.props; +--- + + + diff --git a/examples/with-data/src/content/config.ts b/examples/with-data/src/content/config.ts new file mode 100644 index 000000000000..1762cc064ccf --- /dev/null +++ b/examples/with-data/src/content/config.ts @@ -0,0 +1,13 @@ +import { defineCollection, z } from 'astro:content'; + +const siteCollection = defineCollection({ + type: 'data', + schema: z.object({ + title: z.string(), + description: z.string(), + }) +}); + +export const collections = { + 'site': siteCollection, +}; \ No newline at end of file diff --git a/examples/with-data/src/content/site/about.toml b/examples/with-data/src/content/site/about.toml new file mode 100644 index 000000000000..308df43a569e --- /dev/null +++ b/examples/with-data/src/content/site/about.toml @@ -0,0 +1,2 @@ +title = "About Us" +description = "Welcome to our website! Learn more about our company and what we do." \ No newline at end of file diff --git a/examples/with-data/src/content/site/home.yaml b/examples/with-data/src/content/site/home.yaml new file mode 100644 index 000000000000..0133c0cb6c27 --- /dev/null +++ b/examples/with-data/src/content/site/home.yaml @@ -0,0 +1,3 @@ +title: Home Page +description: description of website +slug: home \ No newline at end of file diff --git a/examples/with-data/src/layouts/Layout.astro b/examples/with-data/src/layouts/Layout.astro new file mode 100644 index 000000000000..98c71bb54449 --- /dev/null +++ b/examples/with-data/src/layouts/Layout.astro @@ -0,0 +1,52 @@ +--- +interface Props { + title: string; + description?: string; +} + +const { title, description = "Astro description" } = Astro.props; +--- + + + + + + + + + + {title} + + + + + + diff --git a/examples/with-data/src/pages/about.astro b/examples/with-data/src/pages/about.astro new file mode 100644 index 000000000000..2a3e729fc61a --- /dev/null +++ b/examples/with-data/src/pages/about.astro @@ -0,0 +1,102 @@ +--- +import Layout from '../layouts/Layout.astro'; +import { getEntry } from "astro:content"; + +const aboutpage = await getEntry('site', 'about'); +console.log(aboutpage) +--- + + +
+ +

{aboutpage.data.title}

+

+ {aboutpage.data.description} +

+
+
+ + diff --git a/examples/with-data/src/pages/index.astro b/examples/with-data/src/pages/index.astro new file mode 100644 index 000000000000..6fdba65ba944 --- /dev/null +++ b/examples/with-data/src/pages/index.astro @@ -0,0 +1,127 @@ +--- +import Layout from '../layouts/Layout.astro'; +import Card from '../components/Card.astro'; +import { getEntry } from "astro:content"; + +const homepage = await getEntry('site', 'home'); +console.log(homepage) +--- + + +
+ +

Welcome to Astro

+

+ To get started, open the directory src/pages in your project.
+ Code Challenge: Tweak the "Welcome to Astro" message above. +

+ +
+
+ + diff --git a/examples/with-data/tsconfig.json b/examples/with-data/tsconfig.json new file mode 100644 index 000000000000..d78f81ec4e8e --- /dev/null +++ b/examples/with-data/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "astro/tsconfigs/base" +} diff --git a/packages/astro/package.json b/packages/astro/package.json index 6f416a61e1e4..a8e02ec462ea 100644 --- a/packages/astro/package.json +++ b/packages/astro/package.json @@ -158,6 +158,7 @@ "html-escaper": "^3.0.3", "http-cache-semantics": "^4.1.1", "js-yaml": "^4.1.0", + "js-toml": "^1.0.0", "kleur": "^4.1.5", "magic-string": "^0.30.10", "mrmime": "^2.0.0", diff --git a/packages/astro/src/core/config/settings.ts b/packages/astro/src/core/config/settings.ts index d01e4299c42a..487f5722f314 100644 --- a/packages/astro/src/core/config/settings.ts +++ b/packages/astro/src/core/config/settings.ts @@ -1,6 +1,7 @@ import path from 'node:path'; import { fileURLToPath, pathToFileURL } from 'node:url'; import yaml from 'js-yaml'; +import { load as tomlParse } from 'js-toml'; import type { AstroConfig, AstroSettings } from '../../@types/astro.js'; import { getContentPaths } from '../../content/index.js'; import createPreferences from '../../preferences/index.js'; @@ -96,6 +97,44 @@ export function createBaseSettings(config: AstroConfig): AstroSettings { } }, }, + { + extensions: ['.toml'], + getEntryInfo({ contents, fileUrl }) { + if (contents === undefined || contents === '') return { data: {} }; + + const pathRelToContentDir = path.relative( + fileURLToPath(contentDir), + fileURLToPath(fileUrl) + ); + let data; + try { + data = tomlParse(contents); + } catch (e) { + throw new AstroError({ + ...AstroErrorData.DataCollectionEntryParseError, + message: AstroErrorData.DataCollectionEntryParseError.message( + pathRelToContentDir, + e instanceof Error ? e.message : 'contains invalid TOML.' + ), + location: { file: fileUrl.pathname }, + stack: e instanceof Error ? e.stack : undefined, + }); + } + + if (data == null || typeof data !== 'object') { + throw new AstroError({ + ...AstroErrorData.DataCollectionEntryParseError, + message: AstroErrorData.DataCollectionEntryParseError.message( + pathRelToContentDir, + 'data is not an object.' + ), + location: { file: fileUrl.pathname }, + }); + } + + return { data }; + }, + }, ], renderers: [], scripts: [], diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d2ec86c1f0d1..01ecc9e5815e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -393,6 +393,12 @@ importers: specifier: ^4.8.6 version: link:../../packages/astro + examples/with-data: + dependencies: + astro: + specifier: ^4.8.2 + version: link:../../packages/astro + examples/with-markdoc: dependencies: '@astrojs/markdoc': @@ -617,6 +623,9 @@ importers: http-cache-semantics: specifier: ^4.1.1 version: 4.1.1 + js-toml: + specifier: ^1.0.0 + version: 1.0.0 js-yaml: specifier: ^4.1.0 version: 4.1.0 @@ -6227,6 +6236,14 @@ packages: '@babel/plugin-syntax-typescript': 7.24.1(@babel/core@7.24.5) dev: false + /@babel/runtime-corejs3@7.24.5: + resolution: {integrity: sha512-GWO0mgzNMLWaSYM4z4NVIuY0Cd1fl8cPnuetuddu5w/qGuvt5Y7oUi/kvvQGK9xgOkFJDQX2heIvTRn/OQ1XTg==} + engines: {node: '>=6.9.0'} + dependencies: + core-js-pure: 3.37.0 + regenerator-runtime: 0.14.1 + dev: false + /@babel/runtime@7.24.4: resolution: {integrity: sha512-dkxf7+hn8mFBwKjs9bvBlArzLVxVbS8usaPUDd5p2a9JCL9tB8OaOVN1isD4+Xyk4ns89/xeOmbQvgdK7IIVdA==} engines: {node: '>=6.9.0'} @@ -6565,6 +6582,33 @@ packages: prettier: 2.8.8 dev: true + /@chevrotain/cst-dts-gen@11.0.3: + resolution: {integrity: sha512-BvIKpRLeS/8UbfxXxgC33xOumsacaeCKAjAeLyOn7Pcp95HiRbrpl14S+9vaZLolnbssPIUuiUd8IvgkRyt6NQ==} + dependencies: + '@chevrotain/gast': 11.0.3 + '@chevrotain/types': 11.0.3 + lodash-es: 4.17.21 + dev: false + + /@chevrotain/gast@11.0.3: + resolution: {integrity: sha512-+qNfcoNk70PyS/uxmj3li5NiECO+2YKZZQMbmjTqRI3Qchu8Hig/Q9vgkHpI3alNjr7M+a2St5pw5w5F6NL5/Q==} + dependencies: + '@chevrotain/types': 11.0.3 + lodash-es: 4.17.21 + dev: false + + /@chevrotain/regexp-to-ast@11.0.3: + resolution: {integrity: sha512-1fMHaBZxLFvWI067AVbGJav1eRY7N8DDvYCTwGBiE/ytKBgP8azTdgyrKyWZ9Mfh09eHWb5PgTSO8wi7U824RA==} + dev: false + + /@chevrotain/types@11.0.3: + resolution: {integrity: sha512-gsiM3G8b58kZC2HaWR50gu6Y1440cHiJ+i3JUvcp/35JchYejb2+5MVeJK0iKThYpAa/P2PYFV4hoi44HD+aHQ==} + dev: false + + /@chevrotain/utils@11.0.3: + resolution: {integrity: sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ==} + dev: false + /@clack/core@0.3.4: resolution: {integrity: sha512-H4hxZDXgHtWTwV3RAVenqcC4VbJZNegbBjlPvzOzCouXtS2y3sDvlO3IsbrPNWuLWPPlYVYPghQdSF64683Ldw==} dependencies: @@ -10033,6 +10077,17 @@ packages: parse5-htmlparser2-tree-adapter: 7.0.0 dev: true + /chevrotain@11.0.3: + resolution: {integrity: sha512-ci2iJH6LeIkvP9eJW6gpueU8cnZhv85ELY8w8WiFtNjMHA5ad6pQLaJo9mEly/9qUyCpvqX8/POVUTf18/HFdw==} + dependencies: + '@chevrotain/cst-dts-gen': 11.0.3 + '@chevrotain/gast': 11.0.3 + '@chevrotain/regexp-to-ast': 11.0.3 + '@chevrotain/types': 11.0.3 + '@chevrotain/utils': 11.0.3 + lodash-es: 4.17.21 + dev: false + /chokidar@3.5.3: resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} engines: {node: '>= 8.10.0'} @@ -10295,6 +10350,11 @@ packages: resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} engines: {node: '>= 0.6'} + /core-js-pure@3.37.0: + resolution: {integrity: sha512-d3BrpyFr5eD4KcbRvQ3FTUx/KWmaDesr7+a3+1+P46IUnNoEt+oiLijPINZMEon7w9oGkIINWxrBAU9DEciwFQ==} + requiresBuild: true + dev: false + /cross-argv@2.0.0: resolution: {integrity: sha512-YIaY9TR5Nxeb8SMdtrU8asWVM4jqJDNDYlKV21LxtYcfNJhp1kEsgSa6qXwXgzN0WQWGODps0+TlGp2xQSHwOg==} dev: false @@ -12543,6 +12603,13 @@ packages: resolution: {integrity: sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==} dev: false + /js-toml@1.0.0: + resolution: {integrity: sha512-G757004huuG5Cjg8KUoVTS4zNRR4449KG8kjtFQS0yyQnceq3KfxcArThcqUV2cwdpd0C9I+e1WciK3Xm4cWJw==} + dependencies: + chevrotain: 11.0.3 + xregexp: 5.1.1 + dev: false + /js-yaml@3.14.1: resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} hasBin: true @@ -12787,6 +12854,10 @@ packages: dependencies: p-locate: 5.0.0 + /lodash-es@4.17.21: + resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} + dev: false + /lodash.chunk@4.2.0: resolution: {integrity: sha512-ZzydJKfUHJwHa+hF5X66zLFCBrWn5GeF28OHEr4WVWtNDXlQ/IjWKPBiikqKo2ne0+v6JgCgJ0GzJp8k8bHC7w==} dev: false @@ -15014,7 +15085,6 @@ packages: /regenerator-runtime@0.14.1: resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} - dev: true /regexp-ast-analysis@0.7.1: resolution: {integrity: sha512-sZuz1dYW/ZsfG17WSAG7eS85r5a0dDsvg+7BiiYR5o6lKCAtUrEwdmRmaGF6rwVj3LcmAeYkOWKEPlbPzN3Y3A==} @@ -17470,6 +17540,12 @@ packages: engines: {node: '>=0.1'} dev: true + /xregexp@5.1.1: + resolution: {integrity: sha512-fKXeVorD+CzWvFs7VBuKTYIW63YD1e1osxwQ8caZ6o1jg6pDAbABDG54LCIq0j5cy7PjRvGIq6sef9DYPXpncg==} + dependencies: + '@babel/runtime-corejs3': 7.24.5 + dev: false + /y18n@4.0.3: resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} dev: true