Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,35 @@ console.log(myCode);
// Outputs the content of 'example.js' as a string.
```

### Good News:

With the latest update, you no longer need to specify the file extension explicitly.

```js
import myCode from "./example?raw";
```

This works seamlessly! Additionally, if you're exporting from files like `index.tsx`, `index.jsx`, etc., you can simplify imports. For example, if your file path is `my-lib/index.ts`, you can import the raw content like this:

```js
import myCode from "./my-lib?raw";
```

### Extension Options (Optional)

```ts
export interface RawPluginOptions {
/**
* Extensions to check in order if the file does not exist.
* If it's a directory, the plugin will look for `dir/index.[ext]`.
* @defaultValue ["tsx", "ts", "jsx", "js", "mjs", "mts", "module.css", "module.scss", "css", "scss"]
*
* You can provide your own extensions to optimize build performance or extend the list based on your use case.
*/
ext?: string[];
}
```

### Supported File Types

You can use `?raw` with any file type, including:
Expand Down
7 changes: 7 additions & 0 deletions lib/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# esbuild-raw-plugin

## 0.1.0

### Minor Changes

- 8a7e550: Autocomplete extensions if not added in import statement.
46 changes: 32 additions & 14 deletions lib/__tests__/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,45 @@
import { beforeAll, describe, test } from "vitest";
import esbuild from "esbuild";
import esbuild, { BuildOptions } from "esbuild";
import path from "node:path";
import { raw } from "../src";
import fs from "node:fs";

const buildOptions: BuildOptions = {
format: "cjs",
target: "es2019",
sourcemap: false,
bundle: true,
minify: true,
entryPoints: [path.resolve(__dirname, "test.ts")],
outdir: "__tests__/dist",
treeShaking: true,
plugins: [raw()],
};

describe("WebGL plugins", () => {
beforeAll(async () => {
await esbuild.build({
format: "cjs",
target: "es2019",
sourcemap: false,
bundle: true,
minify: true,
entryPoints: [path.resolve(__dirname, "test.ts")],
outdir: "__tests__/dist",
treeShaking: true,
plugins: [raw()],
});
});
test("test raw import", async ({ expect }) => {
await esbuild.build(buildOptions);
const fileContent = fs.readFileSync(path.resolve(__dirname, "../src/index.ts"), "utf-8");
// @ts-ignore
const generatedCodeContent = (await import("./dist/test.js")).getText();
expect(fileContent).toBe(generatedCodeContent);
});

test("test raw import with auto ext", async ({ expect }) => {
await esbuild.build({ ...buildOptions, entryPoints: [path.resolve(__dirname, "test1.ts")] });
const fileContent = fs.readFileSync(path.resolve(__dirname, "../src/index.ts"), "utf-8");
// @ts-ignore
const generatedCodeContent = (await import("./dist/test1.js")).getText();
expect(fileContent).toBe(generatedCodeContent);
});

test("throws error if no file is found", async ({ expect }) => {
let didThrow = false;
try {
await esbuild.build({ ...buildOptions, entryPoints: [path.resolve(__dirname, "test2.ts")] });
} catch (e) {
didThrow = true;
}
expect(didThrow).toBe(true);
});
});
5 changes: 5 additions & 0 deletions lib/__tests__/test1.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// test auto complete

import text from "../src?raw";

export const getText = () => text;
5 changes: 5 additions & 0 deletions lib/__tests__/test2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// test auto error

import text from "../src/my-file?raw";

export const getText = () => text;
2 changes: 1 addition & 1 deletion lib/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "esbuild-raw-plugin",
"author": "Mayank Kumar Chaudhari <https://mayank-chaudhari.vercel.app>",
"private": false,
"version": "0.0.0",
"version": "0.1.0",
"description": "An ESBuild and TSUP plugin that allows importing files as raw text. Useful for loading code files in documentation, interactive demos, or tools like react-live.",
"license": "MPL-2.0",
"main": "./dist/index.js",
Expand Down
43 changes: 40 additions & 3 deletions lib/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,34 @@ import type { Plugin, PluginBuild } from "esbuild";
import fs from "node:fs";
import path from "node:path";

export interface RawPluginOptions {
/**
* Extensions to check in order if the file does not exist.
* If it's a directory, the plugin will look for `dir/index.[ext]`.
* @defaultValue ["tsx", "ts", "jsx", "js", "mjs", "mts", "module.css", "module.scss", "css", "scss"]
*
* You can provide your own extensions to optimize build performance or extend the list based on your use case.
*/
ext?: string[];
}

/** Plugin to load `.glsl` files as minified strings */
export const raw: () => Plugin = () => ({
export const raw: (options?: RawPluginOptions) => Plugin = options => ({
/** generate randmo name to avoid collision among the plugins */
name: `raw-${(Date.now() * Math.random()).toString(36).slice(0, 8)}`,
setup(build: PluginBuild) {
const ext = options?.ext ?? [
"tsx",
"ts",
"jsx",
"js",
"mjs",
"mts",
"module.css",
"module.scss",
"css",
"scss",
];
build.onResolve({ filter: /\?raw$/ }, args => {
const filePath = args.path;
return {
Expand All @@ -15,9 +38,23 @@ export const raw: () => Plugin = () => ({
namespace: "raw",
};
});
build.onLoad({ filter: /\?raw$/, namespace: "raw" }, async args => {
build.onLoad({ filter: /\?raw$/, namespace: "raw" }, args => {
let filePath = args.pluginData;
if (fs.lstatSync(filePath).isDirectory()) filePath += path.sep + "index";
if (!fs.existsSync(filePath))
for (const e of ext)
if (fs.existsSync(filePath + "." + e)) {
filePath += "." + e;
break;
}
if (!fs.existsSync(filePath))
throw new Error(
/* v8 ignore next */
`File not found: ${args.pluginData}\nWe checked for following extensions: ${ext.join(", ")}. You can customise by passing {ext: [...]} to raw({ext:[...]})`,
/* v8 ignore next */
);
return {
contents: fs.readFileSync(args.pluginData, "utf8"),
contents: fs.readFileSync(filePath, "utf8"),
loader: "text",
};
});
Expand Down
8 changes: 8 additions & 0 deletions packages/shared/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# @repo/shared

## 0.0.1

### Patch Changes

- Updated dependencies [8a7e550]
- [email protected]
2 changes: 1 addition & 1 deletion packages/shared/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@repo/shared",
"version": "0.0.0",
"version": "0.0.1",
"private": true,
"sideEffects": false,
"main": "./dist/index.js",
Expand Down
Loading