interpolateName.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. "use strict";
  2. const path = require("path");
  3. const getHashDigest = require("./getHashDigest");
  4. function interpolateName(loaderContext, name, options = {}) {
  5. let filename;
  6. const hasQuery =
  7. loaderContext.resourceQuery && loaderContext.resourceQuery.length > 1;
  8. if (typeof name === "function") {
  9. filename = name(
  10. loaderContext.resourcePath,
  11. hasQuery ? loaderContext.resourceQuery : undefined
  12. );
  13. } else {
  14. filename = name || "[hash].[ext]";
  15. }
  16. const context = options.context;
  17. const content = options.content;
  18. const regExp = options.regExp;
  19. let ext = "bin";
  20. let basename = "file";
  21. let directory = "";
  22. let folder = "";
  23. let query = "";
  24. if (loaderContext.resourcePath) {
  25. const parsed = path.parse(loaderContext.resourcePath);
  26. let resourcePath = loaderContext.resourcePath;
  27. if (parsed.ext) {
  28. ext = parsed.ext.substr(1);
  29. }
  30. if (parsed.dir) {
  31. basename = parsed.name;
  32. resourcePath = parsed.dir + path.sep;
  33. }
  34. if (typeof context !== "undefined") {
  35. directory = path
  36. .relative(context, resourcePath + "_")
  37. .replace(/\\/g, "/")
  38. .replace(/\.\.(\/)?/g, "_$1");
  39. directory = directory.substr(0, directory.length - 1);
  40. } else {
  41. directory = resourcePath.replace(/\\/g, "/").replace(/\.\.(\/)?/g, "_$1");
  42. }
  43. if (directory.length <= 1) {
  44. directory = "";
  45. } else {
  46. // directory.length > 1
  47. folder = path.basename(directory);
  48. }
  49. }
  50. if (loaderContext.resourceQuery && loaderContext.resourceQuery.length > 1) {
  51. query = loaderContext.resourceQuery;
  52. const hashIdx = query.indexOf("#");
  53. if (hashIdx >= 0) {
  54. query = query.substr(0, hashIdx);
  55. }
  56. }
  57. let url = filename;
  58. if (content) {
  59. // Match hash template
  60. url = url
  61. // `hash` and `contenthash` are same in `loader-utils` context
  62. // let's keep `hash` for backward compatibility
  63. .replace(
  64. /\[(?:([^[:\]]+):)?(?:hash|contenthash)(?::([a-z]+\d*(?:safe)?))?(?::(\d+))?\]/gi,
  65. (all, hashType, digestType, maxLength) =>
  66. getHashDigest(content, hashType, digestType, parseInt(maxLength, 10))
  67. );
  68. }
  69. url = url
  70. .replace(/\[ext\]/gi, () => ext)
  71. .replace(/\[name\]/gi, () => basename)
  72. .replace(/\[path\]/gi, () => directory)
  73. .replace(/\[folder\]/gi, () => folder)
  74. .replace(/\[query\]/gi, () => query);
  75. if (regExp && loaderContext.resourcePath) {
  76. const match = loaderContext.resourcePath.match(new RegExp(regExp));
  77. match &&
  78. match.forEach((matched, i) => {
  79. url = url.replace(new RegExp("\\[" + i + "\\]", "ig"), matched);
  80. });
  81. }
  82. if (
  83. typeof loaderContext.options === "object" &&
  84. typeof loaderContext.options.customInterpolateName === "function"
  85. ) {
  86. url = loaderContext.options.customInterpolateName.call(
  87. loaderContext,
  88. url,
  89. name,
  90. options
  91. );
  92. }
  93. return url;
  94. }
  95. module.exports = interpolateName;