Full Code of 11ty/eleventy-plugin-vite for AI

main 411034f94c71 cached
16 files
21.4 KB
6.6k tokens
10 symbols
1 requests
Download .txt
Repository: 11ty/eleventy-plugin-vite
Branch: main
Commit: 411034f94c71
Files: 16
Total size: 21.4 KB

Directory structure:
gitextract_g145p6_b/

├── .eleventy.js
├── .git-blame-ignore-revs
├── .github/
│   ├── dependabot.yml
│   └── workflows/
│       ├── release.yml
│       └── test.yml
├── .gitignore
├── .prettierrc
├── EleventyVite.js
├── README.md
├── example/
│   ├── .eleventy.js
│   ├── package.json
│   └── src/
│       ├── assets/
│       │   └── main.css
│       └── index.njk
├── package.json
└── test/
    ├── .eleventy.test.js
    └── EleventyVite.test.js

================================================
FILE CONTENTS
================================================

================================================
FILE: .eleventy.js
================================================
import EleventyVite from "./EleventyVite.js";

import path from "node:path";
import { createRequire } from "module";
const require = createRequire(import.meta.url);
const pkg = require("./package.json");

/**
 * Options which can be passed to eleventy-plugin-vite
 * @typedef {Object} EleventyViteOptions
 * @property {string} tempFolderName
 * @property {import("vite").InlineConfig} [viteOptions]
 * @property {Object} [serverOptions]
 */

/**
 * @param {import('@11ty/eleventy/src/UserConfig').default} eleventyConfig
 * @param {EleventyViteOptions} options
 */
export default function (eleventyConfig, options = {}) {
	try {
		eleventyConfig.versionCheck(pkg["11ty"].compatibility);
	} catch (error) {
		eleventyConfig.logger.warn(
			`Warning: Eleventy Plugin (${pkg.name}) Compatibility: ${error.message}`,
		);
	}

	const eleventyVite = new EleventyVite(eleventyConfig, options);

	const publicDir = eleventyVite.options.viteOptions?.publicDir || "public";

	if (!path.relative(eleventyConfig.directories.output, publicDir)) {
		throw new Error(
			`${EleventyVite.LOGGER_PREFIX} Misconfiguration: Can't use the same directory for 11ty output and vite public directory`,
		);
	}

	// Add publicDir to passthrough copy
	eleventyConfig.addPassthroughCopy(publicDir);

	// Add tempFolder to ignores
	eleventyConfig.ignores.add(eleventyVite.getIgnoreDirectory());

	const serverOptions = Object.assign(
		{
			module: "@11ty/eleventy-dev-server",
			domDiff: false,
		},
		options.serverOptions,
	);

	serverOptions.setup = async () => {
		// Use Vite as Middleware
		const viteDevServer = await eleventyVite.getServer();

		process.on("SIGINT", async () => {
			await viteDevServer.close();
		});

		return {
			middleware: [viteDevServer.middlewares],
		};
	};

	eleventyConfig.setServerOptions(serverOptions);

	// Run Vite build
	// TODO use `build.write` option to work with json or ndjson outputs
	eleventyConfig.on("eleventy.after", async ({ dir, runMode, outputMode, results }) => {
		// Skips the Vite build if:
		//   --serve
		//   --to=json
		//   --to=ndjson
		//   or 0 output files from Eleventy build
		// Notably, this *does* run Vite build in --watch mode
		if (
			runMode === "serve" ||
			outputMode === "json" ||
			outputMode === "ndjson" ||
			results.length === 0
		) {
			return;
		}

		await eleventyVite.runBuild(results);
	});
}


================================================
FILE: .git-blame-ignore-revs
================================================
# chore: add prettier
d76b34ffaf428752558b2d99f0e4a4163edda760


================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
  - package-ecosystem: npm
    directory: /
    schedule:
      interval: weekly
    assignees: [KiwiKilian]

  - package-ecosystem: github-actions
    directories: [/, ".github/workflows/**"]
    schedule:
      interval: weekly
    assignees: [KiwiKilian]


================================================
FILE: .github/workflows/release.yml
================================================
name: Publish Release to npm
on:
  release:
    types: [published]
permissions: read-all
jobs:
  build:
    runs-on: ubuntu-latest
    environment: GitHub Publish
    permissions:
      contents: read
      id-token: write
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # 6.0.2
      - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # 6.4.0
        with:
          node-version: "24"
          registry-url: "https://registry.npmjs.org"
      - run: npm install -g npm@latest
      - run: npm ci
      - if: ${{ github.event.release.tag_name != '' && env.NPM_PUBLISH_TAG != '' }}
        run: npm publish --provenance --access=public --tag=${{ env.NPM_PUBLISH_TAG }}
        env:
          NPM_PUBLISH_TAG: ${{ contains(github.event.release.tag_name, '-alpha.') && 'alpha' || 'latest' }}


================================================
FILE: .github/workflows/test.yml
================================================
name: Run Tests
on:
  push:
    branches: [main, alpha]
  pull_request:
    branches: [main, alpha]
  merge_group:
    branches: [main, alpha]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # 4.2.2
      - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # 4.4.0
        with:
          node-version: "24"
      - run: npm ci
      - run: npm test


================================================
FILE: .gitignore
================================================
# Build results
_site

# IDEs
/.idea/
/.vscode/

# Package managers
node_modules
.npm

# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Artefacts
.DS_Store


================================================
FILE: .prettierrc
================================================
{
	"useTabs": true,
	"singleQuote": false,
	"semi": true,
	"endOfLine": "lf",
	"arrowParens": "always",
	"printWidth": 100
}


================================================
FILE: EleventyVite.js
================================================
import { promises as fsp } from "node:fs";
import path from "node:path";
import { DeepCopy, Merge } from "@11ty/eleventy-utils";
import { build, createServer } from "vite";

/** @type {Required<import(".eleventy.js").EleventyViteOptions>} */
const DEFAULT_OPTIONS = {
	tempFolderName: ".11ty-vite",
	viteOptions: {
		clearScreen: false,
		appType: "mpa",
		server: {
			middlewareMode: true,
		},
		build: {
			emptyOutDir: true,
			rolldownOptions: {
				// HTML files will be injected and merged into `input` for MPA
			},
		},
		resolve: {
			alias: {
				// Allow references to `node_modules` directly for bundling.
				"/node_modules": path.resolve(".", "node_modules"),
				// Note that bare module specifiers are also supported
			},
		},
	},
};

export default class EleventyVite {
	static LOGGER_PREFIX = "[11ty/eleventy-plugin-vite]";

	/** @type {import("@11ty/eleventy/src/Util/ProjectDirectories.js").default} */
	directories;

	/** @type {import("@11ty/eleventy/src/Util/ConsoleLogger.js").default} */
	logger;

	/** @type {Required<import(".eleventy.js").EleventyViteOptions>} */
	options;

	constructor(eleventyConfig, pluginOptions = {}) {
		this.directories = eleventyConfig.directories;
		this.logger = eleventyConfig.logger;

		// Relevant until `rollupOptions` are removed
		pluginOptions = DeepCopy({}, pluginOptions);
		const userBuildOptions = pluginOptions.viteOptions?.build;
		if (userBuildOptions?.rollupOptions && !userBuildOptions?.rolldownOptions) {
			this.logger.logWithOptions({
				prefix: EleventyVite.LOGGER_PREFIX,
				message: "Usage of `rollupOptions` is deprecated, use `rolldownOptions` instead",
				type: "info",
			});

			userBuildOptions.rolldownOptions = userBuildOptions.rollupOptions;
			delete userBuildOptions.rollupOptions;
		}

		this.options = Merge({}, DEFAULT_OPTIONS, pluginOptions);
	}

	getServer() {
		/** @type {import("vite").InlineConfig} */
		const viteOptions = DeepCopy({}, this.options.viteOptions);
		viteOptions.root = this.directories.output;

		return createServer(viteOptions);
	}

	getIgnoreDirectory() {
		return path.join(this.options.tempFolderName, "**");
	}

	get tempFolderPath() {
		return path.resolve(this.options.tempFolderName);
	}

	static getEntryPointName(filePath) {
		return path
			.join(path.dirname(filePath), path.basename(filePath, path.extname(filePath)))
			.replace(/^\/+/, "");
	}

	getEleventyRolldownOptionsInput(input) {
		return (
			input
				// Filter out `false` serverless routes
				.filter((entry) => !!entry.outputPath)
				// Only HTML output
				.filter((entry) => (entry.outputPath ?? "").endsWith(".html"))
				.reduce((result, entry) => {
					if (!entry.outputPath.startsWith(this.directories.output)) {
						throw new Error(
							`Unexpected output path (was not in output directory ${this.directories.output}): ${entry.outputPath}`,
						);
					}

					const filePath = entry.outputPath.substring(this.directories.output.length);
					result[EleventyVite.getEntryPointName(filePath)] = path.resolve(
						this.tempFolderPath,
						filePath,
					);

					return result;
				}, {})
		);
	}

	getUserRolldownOptionsInput(input) {
		let userInput = {};

		if (input) {
			if (Array.isArray(input)) {
				input.forEach((file) => {
					userInput[EleventyVite.getEntryPointName(file)] = file;
				});
			} else if (typeof input === "object") {
				userInput = input;
			} else if (typeof input === "string") {
				userInput[EleventyVite.getEntryPointName(input)] = input;
			}
		}

		return userInput;
	}

	async runBuild(input) {
		await fsp.rename(this.directories.output, this.tempFolderPath);

		try {
			/** @type {import("vite").InlineConfig} */
			const viteOptions = DeepCopy({}, this.options.viteOptions);
			viteOptions.root = this.tempFolderPath;
			viteOptions.build.outDir = path.resolve(".", this.directories.output);
			viteOptions.build.rolldownOptions.input = {
				...this.getEleventyRolldownOptionsInput(input),
				...this.getUserRolldownOptionsInput(viteOptions.build.rolldownOptions.input),
			};

			this.logger.logWithOptions({
				prefix: EleventyVite.LOGGER_PREFIX,
				message: "Starting Vite build",
				type: "info",
			});

			await build(viteOptions);

			this.logger.logWithOptions({
				prefix: EleventyVite.LOGGER_PREFIX,
				message: "Finished Vite build",
				type: "info",
			});
		} catch (error) {
			this.logger.logWithOptions({
				prefix: EleventyVite.LOGGER_PREFIX,
				message: `Encountered a Vite build error, restoring original Eleventy output to ${this.directories.output}`,
				type: "error",
				color: "red",
			});
			this.logger.logWithOptions({
				prefix: EleventyVite.LOGGER_PREFIX,
				message: "Vite error:",
				type: "error",
			});
			this.logger.logWithOptions({
				prefix: EleventyVite.LOGGER_PREFIX,
				message: JSON.stringify(error, null, 2),
				type: "error",
				color: "cyan",
			});

			await fsp.rename(this.tempFolderPath, this.directories.output);

			throw error;
		} finally {
			await fsp.rm(this.tempFolderPath, { force: true, recursive: true });
		}
	}
}


================================================
FILE: README.md
================================================
<p align="center"><img src="https://www.11ty.dev/img/logo-github.svg" width="200" height="200" alt="11ty Logo">&#160;&#160;<img src="https://v1.image.11ty.dev/https%3A%2F%2Fvitejs.dev%2Flogo.svg/png/200x200/" alt="Vite logo" width="200" height="200"></p>

# eleventy-plugin-vite 🕚⚡️🎈🐀

A plugin to use [Vite](https://vitejs.dev/) with Eleventy.

This plugin:

- Runs Vite as Middleware in Eleventy Dev Server (try with Eleventy’s `--incremental`)
- Runs Vite build to postprocess your Eleventy build output

## Eleventy Housekeeping

- Please star [Eleventy on GitHub](https://github.com/11ty/eleventy/)!
- Follow us on Mastodon [@eleventy@fosstodon.org](https://fosstodon.org/@eleventy) or Twitter [@eleven_ty](https://twitter.com/eleven_ty)
- Join us on [Discord](https://www.11ty.dev/blog/discord/)
- Support [11ty on Open Collective](https://opencollective.com/11ty)
- [11ty on npm](https://www.npmjs.com/org/11ty)
- [11ty on GitHub](https://github.com/11ty)

[![npm Version](https://img.shields.io/npm/v/@11ty/eleventy-plugin-vite.svg?style=for-the-badge)](https://www.npmjs.com/package/@11ty/eleventy-plugin-vite)

## Installation

```
npm install @11ty/eleventy-plugin-vite@alpha --save-dev
```

### ESM `.eleventy.js` Config

```js
import EleventyVitePlugin from "@11ty/eleventy-plugin-vite";

export default function (eleventyConfig) {
	eleventyConfig.addPlugin(EleventyVitePlugin);
}
```

### CommonJS `.eleventy.js` Config

> [!NOTE]
> This plugin is written in ESM, therefore `require` is not possible. If your .eleventy.js config uses CommonJS, make it async and create a dynamic import as shown below.

```js
module.exports = async function (eleventyConfig) {
	const EleventyPluginVite = (await import("@11ty/eleventy-plugin-vite")).default;

	eleventyConfig.addPlugin(EleventyPluginVite);
};
```

Read more about ESM vs CommonJS on the [Eleventy documentation](https://www.11ty.dev/docs/cjs-esm/).

### Options

These are the default options of the plugin. There's no need to specify them unless you want to change them.

```js
import EleventyVitePlugin from "@11ty/eleventy-plugin-vite";

export default function (eleventyConfig) {
	eleventyConfig.addPlugin(EleventyVitePlugin, {
        // Default name of the temp folder
		tempFolderName: ".11ty-vite",

		// Eleventy Dev Server Options
		serverOptions: {
			module: "@11ty/eleventy-dev-server",
			domDiff: false,
		},

		// Vite Config
		viteOptions: {
			clearScreen: false,
			appType: "mpa",
			server: {
				middlewareMode: true,
			},
			build: {
				emptyOutDir: true,
				rolldownOptions: {
					input: {
						// HTML entry points will be injected automatically
						// Custom input will be merged
					},
				},
			},
			resolve: {
				alias: {
					// Allow references to `node_modules` directly for bundling.
					"/node_modules": path.resolve(".", "node_modules"),
					// Note that bare module specifiers are also supported
				},
			},
		},
	});
}
```

View the [full list of Vite configuration options](https://vitejs.dev/config/). Custom viteOptions will be deeply merged with the defaults.

## Related Projects

- [`eleventy-plus-vite`](https://github.com/matthiasott/eleventy-plus-vite) by @matthiasott: A starter template using this plugin
- Currently unmaintained:
  - [`slinkity`](https://slinkity.dev/) by @Holben888: A much deeper and more comprehensive integration with Vite! Offers partial hydration and can use shortcodes to render framework components in Eleventy!
  - [`vite-plugin-eleventy`](https://www.npmjs.com/package/vite-plugin-eleventy) by @Snugug: Uses Eleventy as Middleware in Vite (instead of the post-processing approach used here)


================================================
FILE: example/.eleventy.js
================================================
import EleventyVitePlugin from "../.eleventy.js";

export default function (eleventyConfig) {
	eleventyConfig.addPassthroughCopy("src/assets");

	eleventyConfig.addPlugin(EleventyVitePlugin);
}

export const config = {
	dir: {
		input: "src",
	},
};


================================================
FILE: example/package.json
================================================
{
	"name": "eleventy-plugin-vite-example",
	"private": true,
	"type": "module"
}


================================================
FILE: example/src/assets/main.css
================================================
body {
	background-color: black;
	color: white;
	font-family: sans-serif;
}


================================================
FILE: example/src/index.njk
================================================
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>Eleventy Plugin Vite</title>
    <meta name="viewport" content="width=device-width, initial-scale=1" />

    <link rel="stylesheet" href="{{ '/assets/main.css' | url }}" />
  </head>

  <body>
    <h1>Eleventy Plugin Vite</h1>
  </body>
</html>


================================================
FILE: package.json
================================================
{
	"name": "@11ty/eleventy-plugin-vite",
	"version": "8.0.0",
	"description": "A plugin to use Vite as a development server and run Vite to postprocess your Eleventy build.",
	"license": "MIT",
	"engines": {
		"node": "^20.19.0 || >=22.12.0"
	},
	"funding": {
		"type": "opencollective",
		"url": "https://opencollective.com/11ty"
	},
	"keywords": [
		"eleventy",
		"server"
	],
	"11ty": {
		"compatibility": ">=3.0.0"
	},
	"publishConfig": {
		"access": "public"
	},
	"contributors": [
		{
			"name": "Zach Leatherman",
			"email": "zachleatherman@gmail.com",
			"url": "https://zachleat.com/"
		},
		{
			"name": "Kilian Finger",
			"email": "npm@kilianfinger.com",
			"url": "https://www.kilianfinger.com/"
		}
	],
	"repository": {
		"type": "git",
		"url": "git://github.com/11ty/eleventy-plugin-vite.git"
	},
	"bugs": "https://github.com/11ty/eleventy-plugin-vite/issues",
	"homepage": "https://github.com/11ty/eleventy-plugin-vite/",
	"main": "./.eleventy.js",
	"type": "module",
	"exports": {
		".": "./.eleventy.js",
		"./EleventyVite": "./EleventyVite.js",
		"./package.json": "./package.json"
	},
	"files": [
		".eleventy.js",
		"EleventyVite.js"
	],
	"scripts": {
		"test": "vitest",
		"format": "prettier . --write",
		"example": "cd example && eleventy",
		"example:start": "npm run example -- --serve",
		"example:build": "npm run example",
		"example:clean": "rimraf ./example/_site"
	},
	"dependencies": {
		"@11ty/eleventy-utils": "^2.0.7",
		"vite": "^8.0.9"
	},
	"devDependencies": {
		"@11ty/eleventy": "3.1.5",
		"prettier": "3.8.3",
		"vitest": "3.2.4"
	}
}


================================================
FILE: test/.eleventy.test.js
================================================
import { describe, it, expect, vi } from "vitest";
import eleventyPlugin from "../.eleventy.js";

describe(".eleventy.js", () => {
	it("sets up passthrough, ignores, and server options", () => {
		const ignores = new Set();

		const eleventyConfig = {
			directories: { output: "dist" },
			addPassthroughCopy: vi.fn(),
			ignores,
			setServerOptions: vi.fn(),
			on: vi.fn(),
			logger: { warn: vi.fn() },
			versionCheck: vi.fn(),
		};

		eleventyPlugin(eleventyConfig, { tempFolderName: ".test-11ty-vite" });

		expect(eleventyConfig.addPassthroughCopy).toHaveBeenCalled();
		expect([...ignores].some((i) => i.includes(".test-11ty-vite"))).toBe(true);
		expect(eleventyConfig.setServerOptions).toHaveBeenCalled();
		expect(typeof eleventyConfig.setServerOptions.mock.calls[0][0].setup).toBe("function");
		expect(eleventyConfig.on).toHaveBeenCalled();
	});
});


================================================
FILE: test/EleventyVite.test.js
================================================
import { describe, it, beforeEach, afterEach, expect } from "vitest";
import fs from "node:fs/promises";
import path from "node:path";
import EleventyVite from "../EleventyVite.js";

const outputPath = ".test-output";
const htmlFilePath = path.join(outputPath, "index.html");
const tempFolderName = ".test-11ty-vite";

const mockEleventyConfig = {
	directories: { output: outputPath },
	logger: {
		logWithOptions: () => {},
	},
};
const pluginOptions = {
	tempFolderName,
	viteOptions: {
		logLevel: "silent",
	},
};

describe("EleventyVite", () => {
	beforeEach(async () => {
		await fs.rm(outputPath, { recursive: true, force: true }).catch(() => {});
		await fs.mkdir(outputPath, { recursive: true });
		await fs.writeFile(path.join(outputPath, "style.css"), "body { color: red; }");
		await fs.writeFile(
			htmlFilePath,
			`<html><head><link rel="stylesheet" href="style.css"></head><body></body></html>`,
		);
	});

	afterEach(async () => {
		await fs.rm(outputPath, { recursive: true, force: true }).catch(() => {});
		await fs.rm(tempFolderName, { recursive: true, force: true }).catch(() => {});
	});

	it("constructor merges options", () => {
		const plugin = new EleventyVite(mockEleventyConfig, pluginOptions);
		expect(plugin.options.tempFolderName).toBe(tempFolderName);
		expect(plugin.options.viteOptions).toBeTruthy();
		expect(plugin.options.viteOptions.appType).toBe("mpa");
	});

	it("getServer returns a Vite dev server", async () => {
		const plugin = new EleventyVite(mockEleventyConfig, pluginOptions);
		const server = await plugin.getServer();
		expect(server.middlewares).toBeTruthy();
		await server.close();
	});

	it("getIgnoreDirectory returns correct path", () => {
		const plugin = new EleventyVite(mockEleventyConfig, pluginOptions);
		expect(plugin.getIgnoreDirectory()).toBe(path.join(tempFolderName, "**"));
	});

	it("outputs HTML file to output path during build", async () => {
		const plugin = new EleventyVite(mockEleventyConfig, pluginOptions);
		const input = [{ outputPath: htmlFilePath }];

		await plugin.runBuild(input);

		const stat = await fs.stat(htmlFilePath);
		expect(stat.isFile()).toBe(true);
	});

	it("runBuild runs Vite build and cleans up", async () => {
		const plugin = new EleventyVite(mockEleventyConfig, pluginOptions);
		const input = [{ outputPath: htmlFilePath }];
		await expect(plugin.runBuild(input)).resolves.not.toThrow();

		const exists = await fs.stat(tempFolderName).then(
			() => true,
			() => false,
		);
		expect(exists).toBe(false);
	});

	it("references CSS file with hash in HTML after build", async () => {
		const plugin = new EleventyVite(mockEleventyConfig, pluginOptions);
		const input = [{ outputPath: htmlFilePath }];

		await plugin.runBuild(input);

		const html = await fs.readFile(htmlFilePath, "utf8");
		const match = html.match(
			/<link[^>]+href=["']([^"']*assets\/index-[a-zA-Z0-9]+\.css)["'][^>]*>/,
		);
		expect(match).toBeTruthy();

		const cssPath = match[1];
		const cssFile = path.join(outputPath, cssPath);
		const stat = await fs.stat(cssFile);
		expect(stat.isFile()).toBe(true);
	});

	it("getEleventyRolldownOptionsInput returns correct input object", () => {
		const entries = [
			{ outputPath: `${outputPath}index.html` },
			{ outputPath: `${outputPath}posts/index.html` },
			{ outputPath: `${outputPath}posts/hello/index.html` },
			{ outputPath: `${outputPath}robots.txt` },
			{ outputPath: false },
		];

		const plugin = new EleventyVite(mockEleventyConfig, pluginOptions);

		const result = plugin.getEleventyRolldownOptionsInput(entries);

		expect(result).toEqual({
			index: path.resolve(`${tempFolderName}/index.html`),
			"posts/index": path.resolve(`${tempFolderName}/posts/index.html`),
			"posts/hello/index": path.resolve(`${tempFolderName}/posts/hello/index.html`),
		});
	});

	it("getUserRolldownOptionsInput handles array input", () => {
		const plugin = new EleventyVite(mockEleventyConfig, pluginOptions);
		const result = plugin.getUserRolldownOptionsInput(["script.js", "styles/main.css"]);

		expect(result).toEqual({
			script: "script.js",
			"styles/main": "styles/main.css",
		});
	});

	it("getUserRolldownOptionsInput handles object input", () => {
		const plugin = new EleventyVite(mockEleventyConfig, pluginOptions);
		const result = plugin.getUserRolldownOptionsInput({
			script: "script.js",
			"styles/main": "styles/main.css",
		});

		expect(result).toEqual({
			script: "script.js",
			"styles/main": "styles/main.css",
		});
	});

	it("maps rollupOptions to rolldownOptions and logs a deprecation warning", () => {
		const logCalls = [];
		const mockConfigWithLogger = {
			...mockEleventyConfig,
			logger: {
				logWithOptions: (opts) => logCalls.push(opts),
			},
		};

		const rollupInput = { main: "src/main.js" };
		const options = {
			tempFolderName,
			viteOptions: {
				build: {
					rollupOptions: { input: rollupInput },
				},
			},
		};

		const plugin = new EleventyVite(mockConfigWithLogger, options);

		expect(plugin.options.viteOptions.build.rolldownOptions.input).toEqual(rollupInput);
		expect(plugin.options.viteOptions.build.rollupOptions).toBeUndefined();

		const warning = logCalls.find((c) => c.message.includes("rollupOptions"));
		expect(warning).toBeTruthy();
		expect(warning.type).toBe("info");

		// original pluginOptions object must not be mutated
		expect(options.viteOptions.build.rollupOptions).toEqual({ input: rollupInput });
		expect(options.viteOptions.build.rolldownOptions).toBeUndefined();
	});

	it("getUserRolldownOptionsInput handles string input", () => {
		const plugin = new EleventyVite(mockEleventyConfig, pluginOptions);
		const result = plugin.getUserRolldownOptionsInput("styles/main.css");

		expect(result).toEqual({
			"styles/main": "styles/main.css",
		});
	});
});
Download .txt
gitextract_g145p6_b/

├── .eleventy.js
├── .git-blame-ignore-revs
├── .github/
│   ├── dependabot.yml
│   └── workflows/
│       ├── release.yml
│       └── test.yml
├── .gitignore
├── .prettierrc
├── EleventyVite.js
├── README.md
├── example/
│   ├── .eleventy.js
│   ├── package.json
│   └── src/
│       ├── assets/
│       │   └── main.css
│       └── index.njk
├── package.json
└── test/
    ├── .eleventy.test.js
    └── EleventyVite.test.js
Download .txt
SYMBOL INDEX (10 symbols across 1 files)

FILE: EleventyVite.js
  constant DEFAULT_OPTIONS (line 7) | const DEFAULT_OPTIONS = {
  class EleventyVite (line 31) | class EleventyVite {
    method constructor (line 43) | constructor(eleventyConfig, pluginOptions = {}) {
    method getServer (line 64) | getServer() {
    method getIgnoreDirectory (line 72) | getIgnoreDirectory() {
    method tempFolderPath (line 76) | get tempFolderPath() {
    method getEntryPointName (line 80) | static getEntryPointName(filePath) {
    method getEleventyRolldownOptionsInput (line 86) | getEleventyRolldownOptionsInput(input) {
    method getUserRolldownOptionsInput (line 111) | getUserRolldownOptionsInput(input) {
    method runBuild (line 129) | async runBuild(input) {
Condensed preview — 16 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (25K chars).
[
  {
    "path": ".eleventy.js",
    "chars": 2361,
    "preview": "import EleventyVite from \"./EleventyVite.js\";\n\nimport path from \"node:path\";\nimport { createRequire } from \"module\";\ncon"
  },
  {
    "path": ".git-blame-ignore-revs",
    "chars": 63,
    "preview": "# chore: add prettier\nd76b34ffaf428752558b2d99f0e4a4163edda760\n"
  },
  {
    "path": ".github/dependabot.yml",
    "chars": 278,
    "preview": "version: 2\nupdates:\n  - package-ecosystem: npm\n    directory: /\n    schedule:\n      interval: weekly\n    assignees: [Kiw"
  },
  {
    "path": ".github/workflows/release.yml",
    "chars": 843,
    "preview": "name: Publish Release to npm\non:\n  release:\n    types: [published]\npermissions: read-all\njobs:\n  build:\n    runs-on: ubu"
  },
  {
    "path": ".github/workflows/test.yml",
    "chars": 442,
    "preview": "name: Run Tests\non:\n  push:\n    branches: [main, alpha]\n  pull_request:\n    branches: [main, alpha]\n  merge_group:\n    b"
  },
  {
    "path": ".gitignore",
    "chars": 175,
    "preview": "# Build results\n_site\n\n# IDEs\n/.idea/\n/.vscode/\n\n# Package managers\nnode_modules\n.npm\n\n# Logs\nlogs\n*.log\nnpm-debug.log*\n"
  },
  {
    "path": ".prettierrc",
    "chars": 125,
    "preview": "{\n\t\"useTabs\": true,\n\t\"singleQuote\": false,\n\t\"semi\": true,\n\t\"endOfLine\": \"lf\",\n\t\"arrowParens\": \"always\",\n\t\"printWidth\": 1"
  },
  {
    "path": "EleventyVite.js",
    "chars": 5054,
    "preview": "import { promises as fsp } from \"node:fs\";\nimport path from \"node:path\";\nimport { DeepCopy, Merge } from \"@11ty/eleventy"
  },
  {
    "path": "README.md",
    "chars": 3644,
    "preview": "<p align=\"center\"><img src=\"https://www.11ty.dev/img/logo-github.svg\" width=\"200\" height=\"200\" alt=\"11ty Logo\">&#160;&#1"
  },
  {
    "path": "example/.eleventy.js",
    "chars": 250,
    "preview": "import EleventyVitePlugin from \"../.eleventy.js\";\n\nexport default function (eleventyConfig) {\n\televentyConfig.addPassthr"
  },
  {
    "path": "example/package.json",
    "chars": 81,
    "preview": "{\n\t\"name\": \"eleventy-plugin-vite-example\",\n\t\"private\": true,\n\t\"type\": \"module\"\n}\n"
  },
  {
    "path": "example/src/assets/main.css",
    "chars": 76,
    "preview": "body {\n\tbackground-color: black;\n\tcolor: white;\n\tfont-family: sans-serif;\n}\n"
  },
  {
    "path": "example/src/index.njk",
    "chars": 327,
    "preview": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <title>Eleventy Plugin Vite</title>\n    <meta"
  },
  {
    "path": "package.json",
    "chars": 1580,
    "preview": "{\n\t\"name\": \"@11ty/eleventy-plugin-vite\",\n\t\"version\": \"8.0.0\",\n\t\"description\": \"A plugin to use Vite as a development ser"
  },
  {
    "path": "test/.eleventy.test.js",
    "chars": 865,
    "preview": "import { describe, it, expect, vi } from \"vitest\";\nimport eleventyPlugin from \"../.eleventy.js\";\n\ndescribe(\".eleventy.js"
  },
  {
    "path": "test/EleventyVite.test.js",
    "chars": 5791,
    "preview": "import { describe, it, beforeEach, afterEach, expect } from \"vitest\";\nimport fs from \"node:fs/promises\";\nimport path fro"
  }
]

About this extraction

This page contains the full source code of the 11ty/eleventy-plugin-vite GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 16 files (21.4 KB), approximately 6.6k tokens, and a symbol index with 10 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!