rollup.plugins.js 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. /* eslint-env es6 */
  2. const cleancss = require('clean-css');
  3. const path = require('path');
  4. const UMD_WRAPPER_RE = /(\(function \(global, factory\) \{)((?:\s.*?)*)(\}\(this,)/;
  5. const CJS_FACTORY_RE = /(module.exports = )(factory\(.*?\))( :)/;
  6. const AMD_FACTORY_RE = /(define\()(.*?, factory)(\) :)/;
  7. function optional(config = {}) {
  8. return {
  9. name: 'optional',
  10. renderChunk(code, chunk, options) {
  11. if (options.format !== 'umd') {
  12. this.error('only UMD format is currently supported');
  13. }
  14. const wrapper = UMD_WRAPPER_RE.exec(code);
  15. const include = config.include;
  16. if (!wrapper) {
  17. this.error('failed to parse the UMD wrapper');
  18. }
  19. let content = wrapper[2];
  20. let factory = (CJS_FACTORY_RE.exec(content) || [])[2];
  21. let updated = false;
  22. for (let lib of chunk.imports) {
  23. if (!include || include.indexOf(lib) !== -1) {
  24. const regex = new RegExp(`require\\('${lib}'\\)`);
  25. if (!regex.test(factory)) {
  26. this.error(`failed to parse the CJS require for ${lib}`);
  27. }
  28. // We need to write inline try / catch with explicit require
  29. // in order to enable statical extraction of dependencies:
  30. // try { return require('moment'); } catch(e) {}
  31. const loader = `function() { try { return require('${lib}'); } catch(e) { } }()`;
  32. factory = factory.replace(regex, loader);
  33. updated = true;
  34. }
  35. }
  36. if (!updated) {
  37. return;
  38. }
  39. // Replace the CJS factory by our updated one.
  40. content = content.replace(CJS_FACTORY_RE, `$1${factory}$3`);
  41. // Replace the AMD factory by our updated one: we need to use the
  42. // following AMD form in order to be able to try/catch require:
  43. // define(['require'], function(require) { ... require(...); ... })
  44. // https://github.com/amdjs/amdjs-api/wiki/AMD#using-require-and-exports
  45. content = content.replace(AMD_FACTORY_RE, `$1['require'], function(require) { return ${factory}; }$3`);
  46. return code.replace(UMD_WRAPPER_RE, `$1${content}$3`);
  47. }
  48. };
  49. }
  50. // https://github.com/chartjs/Chart.js/issues/5208
  51. function stylesheet(config = {}) {
  52. const minifier = new cleancss();
  53. const styles = [];
  54. return {
  55. name: 'stylesheet',
  56. transform(code, id) {
  57. // Note that 'id' can be mapped to a CJS proxy import, in which case
  58. // 'id' will start with 'commonjs-proxy', so let's first check if we
  59. // are importing an existing css file (i.e. startsWith()).
  60. if (!id.startsWith(path.resolve('.')) || !id.endsWith('.css')) {
  61. return;
  62. }
  63. if (config.minify) {
  64. code = minifier.minify(code).styles;
  65. }
  66. // keep track of all imported stylesheets (already minified)
  67. styles.push(code);
  68. return {
  69. code: 'export default ' + JSON.stringify(code)
  70. };
  71. },
  72. generateBundle(opts, bundle) {
  73. if (!config.extract) {
  74. return;
  75. }
  76. const entry = Object.keys(bundle).find(v => bundle[v].isEntry);
  77. const name = (entry || '').replace(/\.js$/i, '.css');
  78. if (!name) {
  79. this.error('failed to guess the output file name');
  80. }
  81. bundle[name] = {
  82. code: styles.filter(v => !!v).join('')
  83. };
  84. }
  85. };
  86. }
  87. module.exports = {
  88. optional,
  89. stylesheet
  90. };