naming.js 3.1 KB

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