interpolateName.js 2.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. "use strict";
  2. const path = require("path");
  3. const emojisList = require("emojis-list");
  4. const getHashDigest = require("./getHashDigest");
  5. const emojiRegex = /[\uD800-\uDFFF]./;
  6. const emojiList = emojisList.filter(emoji => emojiRegex.test(emoji));
  7. const emojiCache = {};
  8. function encodeStringToEmoji(content, length) {
  9. if(emojiCache[content]) return emojiCache[content];
  10. length = length || 1;
  11. const emojis = [];
  12. do {
  13. const index = Math.floor(Math.random() * emojiList.length);
  14. emojis.push(emojiList[index]);
  15. emojiList.splice(index, 1);
  16. } while(--length > 0);
  17. const emojiEncoding = emojis.join("");
  18. emojiCache[content] = emojiEncoding;
  19. return emojiEncoding;
  20. }
  21. function interpolateName(loaderContext, name, options) {
  22. let filename;
  23. if(typeof name === "function") {
  24. filename = name(loaderContext.resourcePath);
  25. } else {
  26. filename = name || "[hash].[ext]";
  27. }
  28. const context = options.context;
  29. const content = options.content;
  30. const regExp = options.regExp;
  31. let ext = "bin";
  32. let basename = "file";
  33. let directory = "";
  34. let folder = "";
  35. if(loaderContext.resourcePath) {
  36. const parsed = path.parse(loaderContext.resourcePath);
  37. let resourcePath = loaderContext.resourcePath;
  38. if(parsed.ext) {
  39. ext = parsed.ext.substr(1);
  40. }
  41. if(parsed.dir) {
  42. basename = parsed.name;
  43. resourcePath = parsed.dir + path.sep;
  44. }
  45. if(typeof context !== "undefined") {
  46. directory = path.relative(context, resourcePath + "_").replace(/\\/g, "/").replace(/\.\.(\/)?/g, "_$1");
  47. directory = directory.substr(0, directory.length - 1);
  48. } else {
  49. directory = resourcePath.replace(/\\/g, "/").replace(/\.\.(\/)?/g, "_$1");
  50. }
  51. if(directory.length === 1) {
  52. directory = "";
  53. } else if(directory.length > 1) {
  54. folder = path.basename(directory);
  55. }
  56. }
  57. let url = filename;
  58. if(content) {
  59. // Match hash template
  60. url = url
  61. .replace(
  62. /\[(?:(\w+):)?hash(?::([a-z]+\d*))?(?::(\d+))?\]/ig,
  63. (all, hashType, digestType, maxLength) => getHashDigest(content, hashType, digestType, parseInt(maxLength, 10))
  64. )
  65. .replace(
  66. /\[emoji(?::(\d+))?\]/ig,
  67. (all, length) => encodeStringToEmoji(content, length)
  68. );
  69. }
  70. url = url
  71. .replace(/\[ext\]/ig, () => ext)
  72. .replace(/\[name\]/ig, () => basename)
  73. .replace(/\[path\]/ig, () => directory)
  74. .replace(/\[folder\]/ig, () => folder);
  75. if(regExp && loaderContext.resourcePath) {
  76. const match = loaderContext.resourcePath.match(new RegExp(regExp));
  77. match && match.forEach((matched, i) => {
  78. url = url.replace(
  79. new RegExp("\\[" + i + "\\]", "ig"),
  80. matched
  81. );
  82. });
  83. }
  84. if(typeof loaderContext.options === "object" && typeof loaderContext.options.customInterpolateName === "function") {
  85. url = loaderContext.options.customInterpolateName.call(loaderContext, url, name, options);
  86. }
  87. return url;
  88. }
  89. module.exports = interpolateName;