diff --git a/.changeset/config.json b/.changeset/config.json index 55f7341e..fa639d7f 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -9,5 +9,9 @@ "linked": [], "access": "public", "baseBranch": "next", - "updateInternalDependencies": "patch" + "updateInternalDependencies": "patch", + "privatePackages": { + "version": false, + "tag": false + } } diff --git a/.changeset/olive-tomatoes-smoke.md b/.changeset/olive-tomatoes-smoke.md new file mode 100644 index 00000000..0e848f71 --- /dev/null +++ b/.changeset/olive-tomatoes-smoke.md @@ -0,0 +1,5 @@ +--- +"@bluecadet/launchpad-content": minor +--- + +Update mediaDownloader and sanityImageUrlTransform defaults diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts index a93024c1..13b36563 100644 --- a/docs/.vitepress/config.mts +++ b/docs/.vitepress/config.mts @@ -97,6 +97,7 @@ export default defineConfig({ { text: "Custom Content Source", link: "/recipes/custom-content-source" }, { text: "Custom Content Plugin", link: "/recipes/custom-content-plugin" }, { text: "Custom Monitor Plugin", link: "/recipes/custom-monitor-plugin" }, + { text: "Transforming Sanity Images", link: "/recipes/transforming-sanity-images" }, ], }, { diff --git a/docs/src/recipes/transforming-sanity-images.md b/docs/src/recipes/transforming-sanity-images.md new file mode 100644 index 00000000..d911ddf7 --- /dev/null +++ b/docs/src/recipes/transforming-sanity-images.md @@ -0,0 +1,119 @@ +# Transforming Sanity Images + +When working with Sanity.io images, you can leverage Sanity's built-in image transformation capabilities instead of using the `sharp` plugin. This is particularly useful for handling Sanity's hotspot and crop features. + +## Fetching Images with GROQ + +First, ensure your GROQ query includes all necessary image fields: + +```typescript{12-17} +import { defineConfig } from '@bluecadet/launchpad-core'; +import { sanitySource } from '@bluecadet/launchpad-content'; + +export default defineConfig({ + content: { + sources: [ + sanitySource({ + id: 'content', + projectId: 'your-project-id', + queries: [{ + id: 'pages', + query: `*[_type == "page"]{ + image { + ..., + asset-> + } + }` + }] + }) + ], + plugins: [ + mediaDownloader() + ] + } +}); +``` + +The `asset->` reference is crucial for accessing the full image data, including hotspot and crop information. + +## Using the Image URL Transform Plugin + +Add the `sanityImageUrlTransform` plugin to transform image references into URLs: + +```typescript{14-22} +import { defineConfig } from '@bluecadet/launchpad-core'; +import { sanityImageUrlTransform, sanitySource } from '@bluecadet/launchpad-content'; + +export default defineConfig({ + content: { + sources: [ + sanitySource({ + id: 'content', + projectId: 'your-project-id', + queries: [/* ... */] + }) + ], + plugins: [ + sanityImageUrlTransform({ + projectId: 'your-project-id', + dataset: 'production', + buildUrl: (builder) => builder + .width(800) + .format('webp') + .fit('crop') + .crop('center') + }), + mediaDownloader() + ] + } +}); +``` + +>[!TIP] +>It's added _before_ the mediaDownloader (unlike the `sharp` plugin) because it modifies + +## Available Transformations + +Sanity's image URL builder supports many transformations: + +```typescript +import { defineConfig } from '@bluecadet/launchpad-core'; +import { sanityImageUrlTransform, sanitySource } from '@bluecadet/launchpad-content'; + +export default defineConfig({ + content: { + sources: [ + sanitySource({ + id: 'content', + projectId: 'your-project-id', + queries: [/* ... */] + }) + ], + plugins: [ + sanityImageUrlTransform({ + projectId: 'your-project-id', + dataset: 'production', + buildUrl: (builder) => builder + .width(800) // Set width + .height(600) // Set height + .format('webp') // Convert format + .quality(80) // Adjust quality + .auto('format') // Auto-select best format + .fit('crop') // Crop fitting + .crop('center') // Crop position + .blur(10) // Apply blur + }), + mediaDownloader() + ] + } +}); +``` + +## Resources + +- [Sanity Image URLs Reference](https://www.sanity.io/docs/image-url) +- [Image Image Presentation Documentation](https://www.sanity.io/docs/presenting-images) +- [sanityImageUrlTransform Plugin](../reference/content/plugins/sanity-image-url-transform.md) +- [Sanity Content Source](../reference/content/sources/sanity-source.md) + +Unlike the `sharp` plugin, Sanity's image transformations are performed on their CDN, reducing your build time and server load. diff --git a/docs/src/reference/content/plugins/media-downloader.md b/docs/src/reference/content/plugins/media-downloader.md index 43a2ae0d..35b0cfa8 100644 --- a/docs/src/reference/content/plugins/media-downloader.md +++ b/docs/src/reference/content/plugins/media-downloader.md @@ -34,7 +34,7 @@ Specifies which data keys to search for media URLs. If not provided, all keys wi ### `mediaPattern` - **Type:** `RegExp` -- **Default:** `/\.(jpe?g|png|webp|avi|mov|mp4|mpg|mpeg|webm)$/i` +- **Default:** `/https?.*\.(jpe?g|png|webp|avi|mov|mp4|mpg|mpeg|webm)$/i` Regex pattern to match URLs for downloading. diff --git a/docs/src/reference/content/plugins/sanity-image-url-transform.md b/docs/src/reference/content/plugins/sanity-image-url-transform.md index 7c51db0e..fb333cc3 100644 --- a/docs/src/reference/content/plugins/sanity-image-url-transform.md +++ b/docs/src/reference/content/plugins/sanity-image-url-transform.md @@ -60,7 +60,7 @@ JSONPath to the content to transform. By default, matches all nodes with `_type` ### `buildUrl` - **Type:** `(builder: ImageUrlBuilder) => ImageUrlBuilder` -- **Required** +- **Default:** `builder => builder` Function to configure image transformations using Sanity's image URL builder. diff --git a/packages/content/src/plugins/sanity-image-url-transform.ts b/packages/content/src/plugins/sanity-image-url-transform.ts index d4db4b97..03a6ecfb 100644 --- a/packages/content/src/plugins/sanity-image-url-transform.ts +++ b/packages/content/src/plugins/sanity-image-url-transform.ts @@ -32,6 +32,7 @@ const sanityImageUrlTransformSchema = z.object({ buildUrl: z .function(z.tuple([z.custom()])) .returns(z.custom()) + .default((bldr) => bldr) .describe("Function to build the image URL"), });