diff --git a/README.md b/README.md index 1a6126d..9a3f9bc 100644 --- a/README.md +++ b/README.md @@ -103,6 +103,30 @@ makeLegalIdentifier( 'foo-bar' ); // 'foo_bar' makeLegalIdentifier( 'typeof' ); // '_typeof' ``` +### dataToEsm + +Helper for treeshakable data imports + +```js +import { dataToEsm } from 'rollup-pluginutils'; + +const esModuleSource = dataToEsm({ + custom: 'data', + to: ['treeshake'] +}, options = { + compact: false, + indent: '\t', + preferConst: false, + objectShorthand: false +}); +/* +Outputs the string ES module source: + export const custom = 'data'; + export const to = ['treeshake']; + export default { custom, to }; +*/ +``` + ## License diff --git a/package.json b/package.json index edc5b09..75967fa 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,8 @@ }, "dependencies": { "estree-walker": "^0.3.0", - "micromatch": "^2.3.11" + "micromatch": "^2.3.11", + "tosource": "^1.0.0" }, "repository": "rollup/rollup-pluginutils", "keywords": [ diff --git a/rollup.config.js b/rollup.config.js index a2685c7..be95a67 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -4,7 +4,7 @@ import buble from 'rollup-plugin-buble'; export default { entry: 'src/index.js', plugins: [ buble() ], - external: [ 'path', 'estree-walker', 'micromatch' ], + external: [ 'path', 'estree-walker', 'micromatch', 'tosource' ], targets: [ { diff --git a/src/dataToEsm.js b/src/dataToEsm.js new file mode 100644 index 0000000..5ac1d25 --- /dev/null +++ b/src/dataToEsm.js @@ -0,0 +1,27 @@ +import makeLegalIdentifier from './makeLegalIdentifier'; +import tosource from 'tosource'; + +// convert data object into separate named exports (and default) +export default function dataToNamedExports ( data, options = {} ) { + const t = options.compact ? '' : 'indent' in options ? options.indent : '\t'; + const _ = options.compact ? '' : ' '; + const n = options.compact ? '' : '\n'; + const declarationType = options.preferConst ? 'const' : 'var'; + + let namedExportCode = ''; + const defaultExportRows = []; + const dataKeys = Object.keys( data ); + for (let i = 0; i < dataKeys.length; i++) { + const key = dataKeys[i]; + if (key === makeLegalIdentifier( key )) { + if ( options.objectShorthand ) + defaultExportRows.push(key); + else + defaultExportRows.push( `${ key }:${ _ }${ key }` ); + namedExportCode += `export ${declarationType} ${key}${ _ }=${ _ }${ tosource( data[key], null, options.compact ? false : t ) };${ n }`; + } else { + defaultExportRows.push( `${ JSON.stringify(key) }: ${ tosource( data[key], null, options.compact ? false : t )}` ); + } + } + return namedExportCode + `export default${ _ }{${ n }${ t }${ defaultExportRows.join(`,${ n }${ t }`) }${ n }};${ n }`; +}; \ No newline at end of file diff --git a/src/index.js b/src/index.js index fdce1bb..b783da9 100644 --- a/src/index.js +++ b/src/index.js @@ -2,3 +2,4 @@ export { default as addExtension } from './addExtension'; export { default as attachScopes } from './attachScopes'; export { default as createFilter } from './createFilter'; export { default as makeLegalIdentifier } from './makeLegalIdentifier'; +export { default as dataToEsm } from './dataToEsm'; \ No newline at end of file diff --git a/test/test.js b/test/test.js index bebb113..ce6f93a 100644 --- a/test/test.js +++ b/test/test.js @@ -442,4 +442,26 @@ describe( 'rollup-pluginutils', function () { assert.equal( makeLegalIdentifier( 'arguments' ), '_arguments' ); }); }); + + describe( 'dataToEsm', function () { + var dataToEsm = utils.dataToEsm; + + it( 'outputs treeshakable data', function () { + assert.equal( dataToEsm( { some: 'data', another: 'data' } ), 'export var some = "data";\nexport var another = "data";\nexport default {\n\tsome: some,\n\tanother: another\n};\n' ); + }); + + it( 'handles illegal identifiers, object shorthand, preferConst', function () { + assert.equal( dataToEsm( { '1': 'data', 'default': 'data' }, { objectShorthand: true, preferConst: true } ), 'export default {\n\t"1": "data",\n\t"default": "data"\n};\n' ); + }); + + it( 'supports non-JSON data', function () { + const date = new Date(); + assert.equal( dataToEsm( { inf: Infinity, date: date } ), 'export var inf = Infinity;\nexport var date = new Date(' + date.getTime() + ');\nexport default {\n\tinf: inf,\n\tdate: date\n};\n' ); + }); + + it( 'supports a compact argument', function () { + assert.equal( dataToEsm( { some: 'data', another: 'data' }, { compact: true, objectShorthand: true } ), 'export var some="data";export var another="data";export default{some,another};' ); + assert.equal( dataToEsm( { some: { deep: { object: 'definition', here: 'here' } }, another: 'data' }, { compact: true, objectShorthand: false } ), 'export var some={deep:{object:"definition",here:"here"}};export var another="data";export default{some:some,another:another};' ); + }); + }); });