rollup.examples.config.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. import babel from '@rollup/plugin-babel';
  2. import path from 'path';
  3. import os from 'os';
  4. import glob from 'glob';
  5. import babelrc from './.babelrc.json';
  6. const EOL = os.EOL;
  7. function babelCleanup() {
  8. return {
  9. transform( code ) {
  10. // remove comments messed up by babel that break eslint
  11. // example:
  12. // setSize: function ()
  13. // /* width, height */
  14. // {
  15. // ↓
  16. // setSize: function () {
  17. code = code.replace( new RegExp( `\\(\\)${EOL}\\s*\\/\\*([a-zA-Z0-9_, ]+)\\*\\/${EOL}\\s*{`, 'g' ), '( ) {' );
  18. return {
  19. code: code,
  20. map: null
  21. };
  22. }
  23. };
  24. }
  25. function unmodularize() {
  26. return {
  27. renderChunk( code, { fileName } ) {
  28. // Namespace the modules that end with Utils
  29. const fileNameNoExtension = fileName.slice( 0, fileName.indexOf( '.' ) );
  30. const namespace = fileNameNoExtension.endsWith( 'Utils' ) ? fileNameNoExtension : undefined;
  31. // export { Example };
  32. // ↓
  33. // THREE.Example = Example;
  34. code = code.replace( /export { ([a-zA-Z0-9_, ]+) };/g, ( match, p1 ) => {
  35. const exps = p1.split( ', ' );
  36. let output = '';
  37. if ( namespace ) {
  38. output += `THREE.${namespace} = {};${ EOL }`;
  39. output += exps.map( exp => `THREE.${namespace}.${exp} = ${exp};` ).join( EOL );
  40. } else {
  41. output += exps.map( exp => `THREE.${exp} = ${exp};` ).join( EOL );
  42. }
  43. return output;
  44. } );
  45. // import { Example } from '...';
  46. // but excluding imports importing from the libs/ folder
  47. const imports = [];
  48. code = code.replace( /import { ([a-zA-Z0-9_, ]+) } from '((?!libs).)*';/g, ( match, p1 ) => {
  49. const imps = p1.split( ', ' );
  50. imps.reverse();
  51. imports.push( ...imps );
  52. return '';
  53. } );
  54. // import * as Example from '...';
  55. // but excluding imports importing from the libs/ folder
  56. code = code.replace( /import \* as ([a-zA-Z0-9_, ]+) from '((?!libs).)*';/g, ( match, p1 ) => {
  57. const imp = p1;
  58. if ( imp !== 'THREE' ) {
  59. imports.push( imp );
  60. }
  61. return '';
  62. } );
  63. // new Example()
  64. // (Example)
  65. // [Example]
  66. // Example2
  67. // ↓
  68. // new THREE.Example()
  69. // (THREE.Example)
  70. // [THREE.Example]
  71. // Example2
  72. function prefixThree( word ) {
  73. code = code.replace( new RegExp( `([\\s([!])${word}([^a-zA-Z0-9_])`, 'g' ), ( match, p1, p2 ) => {
  74. return `${p1}THREE.${word}${p2}`;
  75. } );
  76. }
  77. imports.forEach( prefixThree );
  78. // Do it again for this particular example
  79. // new Example(Example)
  80. // ↓
  81. // new THREE.Example(THREE.Example)
  82. imports.forEach( prefixThree );
  83. // fix for BasisTextureLoader.js
  84. imports.forEach( imp => {
  85. code = code.replace( new RegExp( `${EOL}(\\s)*THREE\\.${imp}:`, 'g' ), ( match, p1 ) => {
  86. return `${EOL}${p1}${imp}:`;
  87. } );
  88. } );
  89. // import * as THREE from '...';
  90. code = code.replace( /import \* as THREE from '(.*)';/g, '' );
  91. // Remove library imports that are exposed as
  92. // global variables in the non-module world
  93. code = code.replace( /import (.*) from '(.*)\/libs\/(.*)';/g, '' );
  94. // remove newline at the start of file
  95. code = code.trimStart();
  96. code = `( function () {${EOL}${code}${EOL}} )();`;
  97. return {
  98. code: code,
  99. map: null
  100. };
  101. }
  102. };
  103. }
  104. const jsFolder = path.resolve( __dirname, '../../examples/js' );
  105. const jsmFolder = path.resolve( __dirname, '../../examples/jsm' );
  106. // list of all .js file nested in the examples/jsm folder
  107. const files = glob.sync( '**/*.js', { cwd: jsmFolder, ignore: [
  108. // don't convert libs
  109. 'capabilities/*',
  110. 'libs/**/*',
  111. 'loaders/ifc/**/*',
  112. // no non-module library
  113. // https://unpkg.com/browse/@webxr-input-profiles/[email protected]/dist/
  114. 'webxr/**/*',
  115. // no non-module library
  116. // https://unpkg.com/browse/[email protected]/
  117. 'loaders/IFCLoader.js',
  118. 'loaders/USDZLoader.js',
  119. 'node-editor/**/*',
  120. 'renderers/webgl/**/*',
  121. 'renderers/webgpu/**/*',
  122. 'renderers/nodes/**/*',
  123. 'nodes/**/*',
  124. 'loaders/NodeMaterialLoader.js',
  125. 'offscreen/**/*',
  126. // dont convert new files
  127. 'exporters/KTX2Exporter.js',
  128. 'loaders/KTX2Loader.js',
  129. 'loaders/MaterialXLoader.js'
  130. ] } );
  131. // Create a rollup config for each .js file
  132. export default files.map( file => {
  133. const inputPath = path.join( 'examples/jsm', file );
  134. const outputPath = path.resolve( jsFolder, file );
  135. return {
  136. input: inputPath,
  137. treeshake: false,
  138. external: () => true, // don't bundle anything
  139. plugins: [
  140. babel( {
  141. babelHelpers: 'bundled',
  142. babelrc: false,
  143. ...babelrc
  144. } ),
  145. babelCleanup(),
  146. unmodularize(),
  147. ],
  148. output: {
  149. format: 'esm',
  150. file: outputPath,
  151. }
  152. };
  153. } );