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