@microsoft/compose-language-service
Version:
Language service for Docker Compose documents
83 lines • 4.86 kB
JavaScript
;
/*!--------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE in the project root for license information.
*--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.ImageLinkProvider = void 0;
const vscode_languageserver_1 = require("vscode-languageserver");
const yaml_1 = require("yaml");
const ActionContext_1 = require("../utils/ActionContext");
const yamlRangeToLspRange_1 = require("../utils/yamlRangeToLspRange");
const ProviderBase_1 = require("./ProviderBase");
const dockerHubImageRegex = /^(?<imageName>[.\w-]+)(?<tag>:[.\w-]+)?$/i;
const dockerHubNamespacedImageRegex = /^(?<namespace>[a-z0-9]+)\/(?<imageName>[.\w-]+)(?<tag>:[.\w-]+)?$/i;
const mcrImageRegex = /^mcr.microsoft.com\/(?<namespace>([a-z0-9]+\/)+)(?<imageName>[.\w-]+)(?<tag>:[.\w-]+)?$/i;
class ImageLinkProvider extends ProviderBase_1.ProviderBase {
on(params, token) {
const ctx = (0, ActionContext_1.getCurrentContext)();
ctx.telemetry.properties.isActivationEvent = 'true'; // This happens automatically so we'll treat it as isActivationEvent === true
const results = [];
const imageTypes = new Set();
const serviceMap = params.document.yamlDocument.value.getIn(['services']);
if ((0, yaml_1.isMap)(serviceMap)) {
for (const service of serviceMap.items) {
// Within each loop we'll check for cancellation (though this is expected to be very fast)
if (token.isCancellationRequested) {
return undefined;
}
if ((0, yaml_1.isMap)(service.value)) {
const image = service.value.getIn(['image'], true);
const hasBuild = service.value.has('build');
if (!hasBuild && (0, yaml_1.isScalar)(image) && typeof image.value === 'string') {
const quoteOffset = (image.type === yaml_1.Scalar.QUOTE_SINGLE || image.type === yaml_1.Scalar.QUOTE_DOUBLE) ? 1 : 0; // Offset if the scalar is quoted
const link = ImageLinkProvider.getLinkForImage(image.value, imageTypes);
if (link && image.range) {
results.push(vscode_languageserver_1.DocumentLink.create((0, yamlRangeToLspRange_1.yamlRangeToLspRange)(params.document.textDocument, [quoteOffset + image.range[0] + link.start, quoteOffset + image.range[0] + link.start + link.length]), link.uri));
}
}
}
}
}
ctx.telemetry.properties.imageTypes = Array.from(imageTypes.values()).sort().join(',');
return results;
}
static getLinkForImage(image, imageTypes) {
var _a, _b, _c, _d, _e, _f;
let match;
let namespace;
let imageName;
if ((match = dockerHubImageRegex.exec(image)) &&
(imageName = (_a = match.groups) === null || _a === void 0 ? void 0 : _a['imageName'])) {
imageTypes.add('dockerHub');
return {
uri: `https://hub.docker.com/_/${imageName}`,
start: match.index,
length: imageName.length
};
}
else if ((match = dockerHubNamespacedImageRegex.exec(image)) &&
(namespace = (_b = match.groups) === null || _b === void 0 ? void 0 : _b['namespace']) &&
(imageName = (_c = match.groups) === null || _c === void 0 ? void 0 : _c['imageName'])) {
imageTypes.add('dockerHubNamespaced');
return {
uri: `https://hub.docker.com/r/${namespace}/${imageName}`,
start: match.index,
length: namespace.length + 1 + imageName.length // 1 is the length of the '/' after namespace
};
}
else if ((match = mcrImageRegex.exec(image)) &&
(namespace = (_e = (_d = match.groups) === null || _d === void 0 ? void 0 : _d['namespace']) === null || _e === void 0 ? void 0 : _e.replace(/\/$/, '')) &&
(imageName = (_f = match.groups) === null || _f === void 0 ? void 0 : _f['imageName'])) {
imageTypes.add('mcr');
return {
uri: `https://hub.docker.com/_/microsoft-${namespace.replace('/', '-')}-${imageName}`,
start: match.index,
length: 18 + namespace.length + 1 + imageName.length // 18 is the length of 'mcr.microsoft.com/', 1 is the length of the '/' after namespace
};
}
return undefined;
}
}
exports.ImageLinkProvider = ImageLinkProvider;
//# sourceMappingURL=ImageLinkProvider.js.map