diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml new file mode 100644 index 0000000..17fe8be --- /dev/null +++ b/.github/workflows/nodejs.yml @@ -0,0 +1,65 @@ +name: Node CI + +on: [push, pull_request] + +jobs: + build: + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + node-version: [22.x] + astro-version: ["3", "4", "5", "6"] + include: + - astro-version: "3" + node-adapter: "@astrojs/node@^6" + - astro-version: "4" + node-adapter: "@astrojs/node@^8" + - astro-version: "5" + node-adapter: "@astrojs/node@^9" + - astro-version: "6" + node-adapter: "@astrojs/node@^10" + + steps: + - uses: actions/checkout@v4 + + - name: Install pnpm + uses: pnpm/action-setup@v4 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + cache: 'pnpm' + + - name: Install dependencies + run: pnpm install + + - name: Build + run: pnpm build + + - name: Pack the package + run: | + cd imagekit-astro + pnpm pack + + - name: Setup test-app with packed package and target Astro version + run: | + cd test-app + pnpm remove @imagekit/astro || true + pnpm add ../imagekit-astro/imagekit-astro-*.tgz + pnpm add astro@${{ matrix.astro-version }} + pnpm add ${{ matrix.node-adapter }} + + - name: Install Playwright + run: | + cd test-app + pnpm exec playwright install --with-deps + + - name: Run E2E tests + run: | + cd test-app + pnpm test:e2e + env: + CI: true + ASTRO_VERSION: ${{ matrix.astro-version }} diff --git a/.github/workflows/npmpublish.yml b/.github/workflows/npmpublish.yml new file mode 100644 index 0000000..f6ec097 --- /dev/null +++ b/.github/workflows/npmpublish.yml @@ -0,0 +1,94 @@ +name: Publish + +on: + release: + types: [published] + +jobs: + build: + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [20.x] + + steps: + - uses: actions/checkout@v4 + + - name: Install pnpm + uses: pnpm/action-setup@v4 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + cache: 'pnpm' + + - name: Install dependencies + run: pnpm install + + - name: Build + run: pnpm build + + - name: Pack the package + run: | + cd imagekit-astro + pnpm pack + + - name: Setup test-app with packed package + run: | + cd test-app + pnpm remove @imagekit/astro || true + pnpm add ../imagekit-astro/imagekit-astro-*.tgz + + - name: Install Playwright + run: | + cd test-app + npx playwright install --with-deps + + - name: Run E2E tests + run: | + cd test-app + pnpm test:e2e + env: + CI: true + + publish: + needs: build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install pnpm + uses: pnpm/action-setup@v4 + with: + version: 9 + + - uses: actions/setup-node@v4 + with: + node-version: 20 + registry-url: https://registry.npmjs.org/ + cache: 'pnpm' + + - name: Install and Build + run: | + pnpm install + pnpm build + + - name: NPM Publish + run: | + cd imagekit-astro + npm config set //registry.npmjs.org/:_authToken=$NODE_AUTH_TOKEN + # print the NPM user name for validation + npm whoami + VERSION=$(node -p "require('./package.json').version") + # Only publish stable versions to the latest tag + if [[ "$VERSION" =~ ^[^-]+$ ]]; then + NPM_TAG="latest" + else + NPM_TAG="beta" + fi + echo "Publishing $VERSION with $NPM_TAG tag." + npm publish --tag $NPM_TAG --access public + env: + NODE_AUTH_TOKEN: ${{secrets.npm_token}} + CI: true diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0952345 --- /dev/null +++ b/.gitignore @@ -0,0 +1,29 @@ +# Dependencies +node_modules/ + +# Build output +dist/ + +# IDE +.vscode/ +.idea/ +*.swp +*.swo + +# OS +.DS_Store +Thumbs.db + +# Environment +.env +.env.local +.env.*.local + +# Astro +.astro/ + +# Test artifacts +test-results/ +playwright-report/ +coverage/ +imagekit-astro/imagekit-astro-*.tgz diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..cf04042 --- /dev/null +++ b/.npmrc @@ -0,0 +1,2 @@ +shamefully-hoist=true +strict-peer-dependencies=false diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..3007f73 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) ImageKit Private Limited 2025 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index e8c6ce5..594572d 100644 --- a/README.md +++ b/README.md @@ -1 +1,609 @@ -Imagekit Astro +# @imagekit/astro + +Astro SDK for [ImageKit.io](https://imagekit.io) — optimized image & video delivery with real-time transformations, responsive images, and automatic format optimization. + +[![npm version](https://img.shields.io/npm/v/@imagekit/astro)](https://www.npmjs.com/package/@imagekit/astro) +[![license](https://img.shields.io/npm/l/@imagekit/astro)](./LICENSE) + +## Quick Start + +### 1. Install + +```bash +npm install @imagekit/astro +# or +pnpm add @imagekit/astro +# or +yarn add @imagekit/astro +``` + +### 2. Configure + +Add your ImageKit URL endpoint to your `.env` file: + +```env +# Preferred when endpoint may be used in client-side code +PUBLIC_IMAGEKIT_URL_ENDPOINT=https://ik.imagekit.io/your_imagekit_id + +# Server-only fallback +IMAGEKIT_URL_ENDPOINT=https://ik.imagekit.io/your_imagekit_id +``` + +> Get your URL endpoint from the [ImageKit dashboard](https://imagekit.io/dashboard/url-endpoints). + +Add the ImageKit integration to your Astro config: + +```js +// astro.config.mjs +import { defineConfig } from 'astro/config'; +import imagekit from '@imagekit/astro/integration'; + +export default defineConfig({ + integrations: [imagekit()], +}); +``` + +By default, the integration automatically configures: + +- `image.service` with `@imagekit/astro/image-service` +- `image.domains` allowlisting for ImageKit hosts +- `image.remotePatterns` with secure (`https`) ImageKit patterns + +You can also pass options when needed: + +```js +export default defineConfig({ + integrations: [ + imagekit({ + urlEndpoint: import.meta.env.PUBLIC_IMAGEKIT_URL_ENDPOINT, + transformationPosition: 'query', + domains: ['assets.example.com'], + remotePatterns: [{ protocol: 'https', hostname: 'assets.example.com', pathname: '/**' }], + }), + ], +}); +``` + +### Standalone image service + +If you want to control Astro's image config yourself, you can use the ImageKit image service directly. This is useful when you already manage `image.domains`, `image.remotePatterns`, or have a custom setup. + +```js +// astro.config.mjs +import { defineConfig } from 'astro/config'; + +export default defineConfig({ + image: { + service: { + entrypoint: '@imagekit/astro/image-service', + config: { + urlEndpoint: import.meta.env.PUBLIC_IMAGEKIT_URL_ENDPOINT, + transformationPosition: 'query', + }, + }, + domains: ['ik.imagekit.io'], + remotePatterns: [{ protocol: 'https', hostname: 'ik.imagekit.io', pathname: '/**' }], + }, +}); +``` + +Notes: + +- If you omit `urlEndpoint`, the service falls back to `PUBLIC_IMAGEKIT_URL_ENDPOINT` or `IMAGEKIT_URL_ENDPOINT`. +- You are responsible for keeping `domains` and `remotePatterns` in sync with your ImageKit URL endpoint. + +### 3. Use + +```astro +--- +import { Image } from '@imagekit/astro'; +--- + +A beautiful image +``` + +--- + +## Components + +### `` +Uses Astro's built-in `` component with ImageKit transformations. This provides Astro's native image optimization features while leveraging ImageKit's URL-based transformations. + +```astro +--- +import { Image } from '@imagekit/astro'; +--- + + +Hero image + + +Cropped hero + + +Optimized hero +``` + +#### Props + +| Prop | Type | Default | Description | +|------|------|---------|-------------| +| `src` | `string` | *required* | Relative path or absolute ImageKit URL | +| `alt` | `string` | *required* | Alt text for accessibility | +| `urlEndpoint` | `string` | env var | Overrides `PUBLIC_IMAGEKIT_URL_ENDPOINT` / `IMAGEKIT_URL_ENDPOINT` | +| `transformation` | `Transformation[]` | `[]` | Array of ImageKit transformations | +| `queryParameters` | `Record` | — | Additional URL query parameters | +| `transformationPosition` | `'path' \| 'query'` | `'query'` | Where to place transformations in the URL | +| `responsive` | `boolean` | `true` | Generate responsive `srcSet` and `sizes` | +| `sizes` | `string` | — | HTML `sizes` attribute for responsive images | +| `deviceBreakpoints` | `number[]` | `[640,750,828,1080,1200,1920,2048,3840]` | Custom device-width breakpoints | +| `imageBreakpoints` | `number[]` | `[16,32,48,64,96,128,256,384]` | Custom image-specific breakpoints | +| `width` | `number \| string` | — | Image width | +| `height` | `number \| string` | — | Image height | +| `format` | `string` | — | Image format (webp, avif, jpg, png, etc.) | +| `quality` | `number` | — | Image quality (1-100) | +| `loading` | `'lazy' \| 'eager'` | `'lazy'` | Image loading strategy | +| `class` | `string` | — | CSS class(es) to add | + +All standard Astro `` props are also supported. + +--- + +### `