You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

120 lines
3.7 KiB

4 years ago
  1. 'use strict';
  2. var assign = require('lodash.assign'),
  3. defaults = require('lodash.defaults'),
  4. camelcase = require('camelcase');
  5. var debugMessage = require('./debug-message'),
  6. toRegExp = require('./to-reg-exp'),
  7. throwErrors = require('./throw-errors'),
  8. decodeSourcesWith = require('./decode-sources-with'),
  9. locateRootWith = require('./locate-root-with'),
  10. encodeSourcesWith = require('./encode-sources-with'),
  11. testCodec = require('./test-codec');
  12. const CODECS = require('../../codec');
  13. /**
  14. * Process the given source-map per the given options.
  15. * @param {{resourcePath:string, context:string, output:{path:string}}} context A loader or compilation
  16. * @param {{debug:boolean, fail:boolean, format:string|boolean, root:string, codecs:object}} options Options hash
  17. * @param {object|string} sourceMapOrSource An incoming source-map or single source path
  18. * @returns {undefined|object|string} An amended source-map or source path else undefined
  19. */
  20. function process(context, options, sourceMapOrSource) {
  21. // default options
  22. defaults(options, {
  23. sep : '/',
  24. debug : false,
  25. fail : false,
  26. format: false,
  27. root : false,
  28. codecs: CODECS
  29. });
  30. // validate codecs
  31. var codecs = options.codecs
  32. .filter(testCodec);
  33. // determine what is present
  34. var inputMap = !!sourceMapOrSource && (typeof sourceMapOrSource === 'object') && sourceMapOrSource,
  35. inputPath = (typeof sourceMapOrSource === 'string') && sourceMapOrSource,
  36. inputSources = inputMap && inputMap.sources || inputPath && [inputPath];
  37. // what we need to produce
  38. var absoluteSources,
  39. outputSources,
  40. outputRoot,
  41. outputMap;
  42. if (inputSources) {
  43. // decode each source with the first valid codec
  44. absoluteSources = inputSources
  45. .map(decodeSourcesWith.call(context, codecs, options.fail));
  46. // check for decode errors
  47. throwErrors(context.resourcePath, absoluteSources);
  48. // output map is a copy unless absent or we are removing
  49. outputMap = (!inputMap || (options.format === 'remove')) ? undefined : assign({}, inputMap);
  50. // some change in format
  51. if (options.format) {
  52. // find the specified codec in the codecs list
  53. var codec = codecs
  54. .filter(testNamedCodec)
  55. .pop();
  56. if (!codec) {
  57. throw new Error('Specified format "' + options.format + '" does not match any available codec.');
  58. }
  59. // use the encoder where specified in 'format'
  60. outputSources = absoluteSources
  61. .map(encodeSourcesWith.call(context, codec))
  62. .map(insertAbstractSources)
  63. .map(convertPathSep);
  64. outputRoot = !!options.root && locateRootWith.call(context, codec)() || undefined;
  65. // check for encode errors
  66. throwErrors(context.resourcePath, outputSources.concat(outputRoot));
  67. // commit the change
  68. if (outputMap) {
  69. outputMap.sources = outputSources;
  70. outputMap.sourceRoot = outputRoot;
  71. }
  72. }
  73. }
  74. // debugging information
  75. var isDebug = toRegExp(options.debug).test(context.resourcePath);
  76. if (isDebug) {
  77. console.log(debugMessage(context, {
  78. input : inputSources,
  79. absolute: absoluteSources,
  80. output : outputSources,
  81. root : outputRoot
  82. }));
  83. }
  84. // complete
  85. return inputMap ? outputMap : outputSources ? outputSources[0] : undefined;
  86. function testNamedCodec(value) {
  87. return (camelcase(value.name) === options.format);
  88. }
  89. function insertAbstractSources(value, i) {
  90. return value || inputSources[i];
  91. }
  92. function convertPathSep(value) {
  93. return (value instanceof Error) ? value : value.replace(/[\\\/]/g, options.sep);
  94. }
  95. }
  96. module.exports = process;