From 5cc8a28a74f9087dbdd9e39a91517cd3214fae70 Mon Sep 17 00:00:00 2001 From: Altinok Darici Date: Mon, 24 Mar 2025 14:13:13 -0700 Subject: [PATCH] Add extensions option to load JSON files with custom extensions --- packages/json/README.md | 6 ++++++ packages/json/src/index.js | 6 +++++- .../custom-file-extension/config.customjson | 3 +++ .../fixtures/custom-file-extension/main.js | 3 +++ packages/json/test/test.js | 21 +++++++++++++++++++ packages/json/types/index.d.ts | 5 +++++ 6 files changed, 43 insertions(+), 1 deletion(-) create mode 100755 packages/json/test/fixtures/custom-file-extension/config.customjson create mode 100755 packages/json/test/fixtures/custom-file-extension/main.js diff --git a/packages/json/README.md b/packages/json/README.md index 1b1c9cd0f..c0b900a2e 100644 --- a/packages/json/README.md +++ b/packages/json/README.md @@ -103,6 +103,12 @@ Default: `false` If `true`, instructs the plugin to declare properties as variables, using either `var` or `const`. This pertains to tree-shaking. +### `extensions` + +Type: `Array[...String]`
+Default: `['.json']` +A list of file extensions to be handled by the plugin. By default, only `.json` files are handled. + ## Meta [CONTRIBUTING](/.github/CONTRIBUTING.md) diff --git a/packages/json/src/index.js b/packages/json/src/index.js index dcb8f3333..ac597fa4e 100755 --- a/packages/json/src/index.js +++ b/packages/json/src/index.js @@ -1,15 +1,19 @@ import { createFilter, dataToEsm } from '@rollup/pluginutils'; +import { extname } from 'path'; export default function json(options = {}) { const filter = createFilter(options.include, options.exclude); const indent = 'indent' in options ? options.indent : '\t'; + const extensions = new Set('extensions' in options ? options.extensions : ['.json']); return { name: 'json', // eslint-disable-next-line no-shadow transform(code, id) { - if (id.slice(-5) !== '.json' || !filter(id)) return null; + const extension = extname(id); + + if (!extensions.has(extension) || !filter(id)) return null; try { const parsed = JSON.parse(code); diff --git a/packages/json/test/fixtures/custom-file-extension/config.customjson b/packages/json/test/fixtures/custom-file-extension/config.customjson new file mode 100755 index 000000000..0a6e8769b --- /dev/null +++ b/packages/json/test/fixtures/custom-file-extension/config.customjson @@ -0,0 +1,3 @@ +{ + "answer": 42 +} diff --git a/packages/json/test/fixtures/custom-file-extension/main.js b/packages/json/test/fixtures/custom-file-extension/main.js new file mode 100755 index 000000000..fb5eee1f1 --- /dev/null +++ b/packages/json/test/fixtures/custom-file-extension/main.js @@ -0,0 +1,3 @@ +import config from './config.customjson'; + +t.is(config.answer, 42); diff --git a/packages/json/test/test.js b/packages/json/test/test.js index 9aec69089..ba074ea72 100755 --- a/packages/json/test/test.js +++ b/packages/json/test/test.js @@ -164,3 +164,24 @@ test('handles empty keys', async (t) => { 'export var b = "c";\nexport default {\n\t"": "a",\n\tb: b\n};\n' ); }); + +test('uses extensions option', async (t) => { + const bundle = await rollup({ + input: 'fixtures/custom-file-extension/main.js', + plugins: [ + json({ + extensions: ['.customjson'] + }) + ] + }); + t.plan(1); + return testBundle(t, bundle); +}); + +test('does not process non-custom extensions', async (t) => { + const content = 'some content'; + const id = 'testfile.json'; + const plugin = json({ extensions: ['.custom'] }); + const output = plugin.transform(content, id); + t.is(output, null, 'Should return null for files without custom extensions'); +}); diff --git a/packages/json/types/index.d.ts b/packages/json/types/index.d.ts index 6ef037a23..da90b05a8 100755 --- a/packages/json/types/index.d.ts +++ b/packages/json/types/index.d.ts @@ -33,6 +33,11 @@ export interface RollupJsonOptions { * @default true */ namedExports?: boolean; + /** + * Specify the file extensions to be parsed as JSON + * @default ['.json'] + */ + extensions?: string[]; } /**