UNPKG

atom-nuclide

Version:

A unified developer experience for web and mobile development, built as a suite of features on top of Atom to provide hackability and the support of an active community.

168 lines (137 loc) 4.82 kB
Object.defineProperty(exports, '__esModule', { value: true }); /* * Copyright (c) 2015-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the license found in the LICENSE file in * the root directory of this source tree. */ exports.getNPMHyperclickProvider = getNPMHyperclickProvider; exports.getPackageUrlForRange = getPackageUrlForRange; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } var _semver2; function _semver() { return _semver2 = _interopRequireDefault(require('semver')); } var _commonsNodeNuclideUri2; function _commonsNodeNuclideUri() { return _commonsNodeNuclideUri2 = _interopRequireDefault(require('../../commons-node/nuclideUri')); } var _electron2; function _electron() { return _electron2 = require('electron'); } var _parsing2; function _parsing() { return _parsing2 = require('./parsing'); } var DEPENDENCY_PROPERTIES = new Set(['dependencies', 'devDependencies', 'optionalDependencies']); function getNPMHyperclickProvider() { return npmHyperclickProvider; } var npmHyperclickProvider = { priority: 1, providerName: 'npm-package-json', getSuggestionForWord: getSuggestionForWord, // Capture just text in quotes wordRegExp: /"[^"]*"/g }; function getSuggestionForWord(textEditor, text, range) { if (text === '' || !isPackageJson(textEditor)) { return Promise.resolve(null); } var packageUrl = getPackageUrlForRange(textEditor.getText(), text, range); if (packageUrl == null) { return Promise.resolve(null); } var suggestion = { range: range, callback: function callback() { (_electron2 || _electron()).shell.openExternal(packageUrl); } }; return Promise.resolve(suggestion); } // Exported for testing. We could derive the token from the json text and the range, but since // hyperclick provides it we may as well use it. function getPackageUrlForRange(json, token, range) { var version = getDependencyVersion(json, range); if (version == null) { return null; } // Strip off the quotes var packageName = token.substring(1, token.length - 1); return getPackageUrl(packageName, version); } function isPackageJson(textEditor) { var scopeName = textEditor.getGrammar().scopeName; var filePath = textEditor.getPath(); return scopeName === 'source.json' && filePath != null && (_commonsNodeNuclideUri2 || _commonsNodeNuclideUri()).default.basename(filePath) === 'package.json'; } function getPackageUrl(packageName, version) { if ((_semver2 || _semver()).default.valid(version)) { return 'https://www.npmjs.com/package/' + packageName + '/'; } // - optionally prefixed with 'github:' (but don't capture that) // - all captured together: // - username: alphanumeric characters, plus underscores and dashes // - slash // - repo name: same as username // - optionally followed by a revision: // - starts with a hash (not captured) // - then alphanumeric characters, underscores, dashes, periods (captured) var githubRegex = /^(?:github:)?([\w-]+\/[\w-]+)(?:#([\w-.]+))?$/; var githubMatch = version.match(githubRegex); if (githubMatch != null) { var commit = githubMatch[2]; var commitSuffix = commit == null ? '' : '/tree/' + commit; return 'https://github.com/' + githubMatch[1] + commitSuffix; } return null; } // Return the version string, if it exists function getDependencyVersion(json, range) { var ast = (0, (_parsing2 || _parsing()).parseJSON)(json); if (ast == null) { // parse error return null; } var pathToNode = getPathToNodeForRange(ast, range); if (pathToNode != null && pathToNode.length === 2 && DEPENDENCY_PROPERTIES.has(pathToNode[0].key.value) && isValidVersion(pathToNode[1].value)) { var valueNode = pathToNode[1].value; if (isValidVersion(valueNode)) { return valueNode.value; } else { return null; } } return null; } function isValidVersion(valueASTNode) { return valueASTNode.type === 'Literal' && typeof valueASTNode.value === 'string'; } // return an array of property AST nodes function getPathToNodeForRange(objectExpression, range) { var properties = objectExpression.properties; if (properties == null) { return null; } for (var property of properties) { var propertyRange = (0, (_parsing2 || _parsing()).babelLocToRange)(property.loc); if (propertyRange.containsRange(range)) { var keyRange = (0, (_parsing2 || _parsing()).babelLocToRange)(property.key.loc); if (keyRange.isEqual(range)) { return [property]; } var subPath = getPathToNodeForRange(property.value, range); if (subPath == null) { return null; } subPath.unshift(property); return subPath; } } return null; }