naming.js 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. /**
  2. * @fileoverview Common helpers for naming of plugins, formatters and configs
  3. */
  4. const NAMESPACE_REGEX = /^@.*\//iu;
  5. /**
  6. * Brings package name to correct format based on prefix
  7. * @param {string} name The name of the package.
  8. * @param {string} prefix Can be either "eslint-plugin", "eslint-config" or "eslint-formatter"
  9. * @returns {string} Normalized name of the package
  10. * @private
  11. */
  12. function normalizePackageName(name, prefix) {
  13. let normalizedName = name;
  14. /**
  15. * On Windows, name can come in with Windows slashes instead of Unix slashes.
  16. * Normalize to Unix first to avoid errors later on.
  17. * https://github.com/eslint/eslint/issues/5644
  18. */
  19. if (normalizedName.includes("\\")) {
  20. normalizedName = normalizedName.replace(/\\/gu, "/");
  21. }
  22. if (normalizedName.charAt(0) === "@") {
  23. /**
  24. * it's a scoped package
  25. * package name is the prefix, or just a username
  26. */
  27. const scopedPackageShortcutRegex = new RegExp(`^(@[^/]+)(?:/(?:${prefix})?)?$`, "u"),
  28. scopedPackageNameRegex = new RegExp(`^${prefix}(-|$)`, "u");
  29. if (scopedPackageShortcutRegex.test(normalizedName)) {
  30. normalizedName = normalizedName.replace(scopedPackageShortcutRegex, `$1/${prefix}`);
  31. } else if (!scopedPackageNameRegex.test(normalizedName.split("/")[1])) {
  32. /**
  33. * for scoped packages, insert the prefix after the first / unless
  34. * the path is already @scope/eslint or @scope/eslint-xxx-yyy
  35. */
  36. normalizedName = normalizedName.replace(/^@([^/]+)\/(.*)$/u, `@$1/${prefix}-$2`);
  37. }
  38. } else if (!normalizedName.startsWith(`${prefix}-`)) {
  39. normalizedName = `${prefix}-${normalizedName}`;
  40. }
  41. return normalizedName;
  42. }
  43. /**
  44. * Removes the prefix from a fullname.
  45. * @param {string} fullname The term which may have the prefix.
  46. * @param {string} prefix The prefix to remove.
  47. * @returns {string} The term without prefix.
  48. */
  49. function getShorthandName(fullname, prefix) {
  50. if (fullname[0] === "@") {
  51. let matchResult = new RegExp(`^(@[^/]+)/${prefix}$`, "u").exec(fullname);
  52. if (matchResult) {
  53. return matchResult[1];
  54. }
  55. matchResult = new RegExp(`^(@[^/]+)/${prefix}-(.+)$`, "u").exec(fullname);
  56. if (matchResult) {
  57. return `${matchResult[1]}/${matchResult[2]}`;
  58. }
  59. } else if (fullname.startsWith(`${prefix}-`)) {
  60. return fullname.slice(prefix.length + 1);
  61. }
  62. return fullname;
  63. }
  64. /**
  65. * Gets the scope (namespace) of a term.
  66. * @param {string} term The term which may have the namespace.
  67. * @returns {string} The namespace of the term if it has one.
  68. */
  69. function getNamespaceFromTerm(term) {
  70. const match = term.match(NAMESPACE_REGEX);
  71. return match ? match[0] : "";
  72. }
  73. //------------------------------------------------------------------------------
  74. // Public Interface
  75. //------------------------------------------------------------------------------
  76. export {
  77. normalizePackageName,
  78. getShorthandName,
  79. getNamespaceFromTerm
  80. };