RequestShortener.js 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const path = require("path");
  7. const NORMALIZE_SLASH_DIRECTION_REGEXP = /\\/g;
  8. const PATH_CHARS_REGEXP = /[-[\]{}()*+?.,\\^$|#\s]/g;
  9. const SEPARATOR_REGEXP = /[/\\]$/;
  10. const FRONT_OR_BACK_BANG_REGEXP = /^!|!$/g;
  11. const INDEX_JS_REGEXP = /\/index.js(!|\?|\(query\))/g;
  12. const MATCH_RESOURCE_REGEXP = /!=!/;
  13. const normalizeBackSlashDirection = request => {
  14. return request.replace(NORMALIZE_SLASH_DIRECTION_REGEXP, "/");
  15. };
  16. const createRegExpForPath = path => {
  17. const regexpTypePartial = path.replace(PATH_CHARS_REGEXP, "\\$&");
  18. return new RegExp(`(^|!)${regexpTypePartial}`, "g");
  19. };
  20. class RequestShortener {
  21. constructor(directory) {
  22. directory = normalizeBackSlashDirection(directory);
  23. if (SEPARATOR_REGEXP.test(directory)) {
  24. directory = directory.substr(0, directory.length - 1);
  25. }
  26. if (directory) {
  27. this.currentDirectoryRegExp = createRegExpForPath(directory);
  28. }
  29. const dirname = path.dirname(directory);
  30. const endsWithSeparator = SEPARATOR_REGEXP.test(dirname);
  31. const parentDirectory = endsWithSeparator
  32. ? dirname.substr(0, dirname.length - 1)
  33. : dirname;
  34. if (parentDirectory && parentDirectory !== directory) {
  35. this.parentDirectoryRegExp = createRegExpForPath(`${parentDirectory}/`);
  36. }
  37. if (__dirname.length >= 2) {
  38. const buildins = normalizeBackSlashDirection(path.join(__dirname, ".."));
  39. const buildinsAsModule =
  40. this.currentDirectoryRegExp &&
  41. this.currentDirectoryRegExp.test(buildins);
  42. this.buildinsAsModule = buildinsAsModule;
  43. this.buildinsRegExp = createRegExpForPath(buildins);
  44. }
  45. this.cache = new Map();
  46. }
  47. shorten(request) {
  48. if (!request) return request;
  49. const cacheEntry = this.cache.get(request);
  50. if (cacheEntry !== undefined) {
  51. return cacheEntry;
  52. }
  53. let result = normalizeBackSlashDirection(request);
  54. if (this.buildinsAsModule && this.buildinsRegExp) {
  55. result = result.replace(this.buildinsRegExp, "!(webpack)");
  56. }
  57. if (this.currentDirectoryRegExp) {
  58. result = result.replace(this.currentDirectoryRegExp, "!.");
  59. }
  60. if (this.parentDirectoryRegExp) {
  61. result = result.replace(this.parentDirectoryRegExp, "!../");
  62. }
  63. if (!this.buildinsAsModule && this.buildinsRegExp) {
  64. result = result.replace(this.buildinsRegExp, "!(webpack)");
  65. }
  66. result = result.replace(INDEX_JS_REGEXP, "$1");
  67. result = result.replace(FRONT_OR_BACK_BANG_REGEXP, "");
  68. result = result.replace(MATCH_RESOURCE_REGEXP, " = ");
  69. this.cache.set(request, result);
  70. return result;
  71. }
  72. }
  73. module.exports = RequestShortener;