modify-url-prefix-transform.js 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. "use strict";
  2. /*
  3. Copyright 2018 Google LLC
  4. Use of this source code is governed by an MIT-style
  5. license that can be found in the LICENSE file or at
  6. https://opensource.org/licenses/MIT.
  7. */
  8. const errors = require('./errors');
  9. /**
  10. * Escaping user input to be treated as a literal string within a regular
  11. * expression can be accomplished by simple replacement.
  12. *
  13. * From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
  14. *
  15. * @private
  16. * @param {string} string The string to be used as part of a regular
  17. * expression
  18. * @return {string} A string that is safe to use in a regular
  19. * expression.
  20. *
  21. * @private
  22. */
  23. const escapeRegExp = string => {
  24. return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
  25. };
  26. module.exports = modifyURLPrefix => {
  27. if (!modifyURLPrefix || typeof modifyURLPrefix !== 'object' || Array.isArray(modifyURLPrefix)) {
  28. throw new Error(errors['modify-url-prefix-bad-prefixes']);
  29. } // If there are no entries in modifyURLPrefix, just return an identity
  30. // function as a shortcut.
  31. if (Object.keys(modifyURLPrefix).length === 0) {
  32. return entry => entry;
  33. }
  34. Object.keys(modifyURLPrefix).forEach(key => {
  35. if (typeof modifyURLPrefix[key] !== 'string') {
  36. throw new Error(errors['modify-url-prefix-bad-prefixes']);
  37. }
  38. }); // Escape the user input so it's safe to use in a regex.
  39. const safeModifyURLPrefixes = Object.keys(modifyURLPrefix).map(escapeRegExp); // Join all the `modifyURLPrefix` keys so a single regex can be used.
  40. const prefixMatchesStrings = safeModifyURLPrefixes.join('|'); // Add `^` to the front the prefix matches so it only matches the start of
  41. // a string.
  42. const modifyRegex = new RegExp(`^(${prefixMatchesStrings})`);
  43. return originalManifest => {
  44. const manifest = originalManifest.map(entry => {
  45. if (typeof entry.url !== 'string') {
  46. throw new Error(errors['manifest-entry-bad-url']);
  47. }
  48. entry.url = entry.url.replace(modifyRegex, match => {
  49. return modifyURLPrefix[match];
  50. });
  51. return entry;
  52. });
  53. return {
  54. manifest
  55. };
  56. };
  57. };