Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/git/src/hover.ts
4772 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { Command, l10n, MarkdownString, Uri } from 'vscode';
7
import { fromNow, getCommitShortHash } from './util';
8
import { emojify } from './emoji';
9
import { CommitShortStat } from './git';
10
11
export const AVATAR_SIZE = 20;
12
13
export function getCommitHover(authorAvatar: string | undefined, authorName: string | undefined, authorEmail: string | undefined, authorDate: Date | number | undefined, message: string, shortStats: CommitShortStat | undefined, commands: Command[][] | undefined): MarkdownString {
14
const markdownString = new MarkdownString('', true);
15
markdownString.isTrusted = {
16
enabledCommands: commands?.flat().map(c => c.command) ?? []
17
};
18
19
// Author, Subject | Message (escape image syntax)
20
appendContent(markdownString, authorAvatar, authorName, authorEmail, authorDate, message);
21
22
// Short stats
23
if (shortStats) {
24
appendShortStats(markdownString, shortStats);
25
}
26
27
// Commands
28
if (commands && commands.length > 0) {
29
appendCommands(markdownString, commands);
30
}
31
32
return markdownString;
33
}
34
35
export function getHistoryItemHover(authorAvatar: string | undefined, authorName: string | undefined, authorEmail: string | undefined, authorDate: Date | number | undefined, message: string, shortStats: CommitShortStat | undefined, commands: Command[][] | undefined): MarkdownString[] {
36
const hoverContent: MarkdownString[] = [];
37
38
// Author, Subject | Message (escape image syntax)
39
const authorMarkdownString = new MarkdownString('', true);
40
appendContent(authorMarkdownString, authorAvatar, authorName, authorEmail, authorDate, message);
41
hoverContent.push(authorMarkdownString);
42
43
// Short stats
44
if (shortStats) {
45
const shortStatsMarkdownString = new MarkdownString('', true);
46
shortStatsMarkdownString.supportHtml = true;
47
appendShortStats(shortStatsMarkdownString, shortStats);
48
hoverContent.push(shortStatsMarkdownString);
49
}
50
51
// Commands
52
if (commands && commands.length > 0) {
53
const commandsMarkdownString = new MarkdownString('', true);
54
commandsMarkdownString.isTrusted = {
55
enabledCommands: commands?.flat().map(c => c.command) ?? []
56
};
57
appendCommands(commandsMarkdownString, commands);
58
hoverContent.push(commandsMarkdownString);
59
}
60
61
return hoverContent;
62
}
63
64
function appendContent(markdownString: MarkdownString, authorAvatar: string | undefined, authorName: string | undefined, authorEmail: string | undefined, authorDate: Date | number | undefined, message: string): void {
65
// Author
66
if (authorName) {
67
// Avatar
68
if (authorAvatar) {
69
markdownString.appendMarkdown('![');
70
markdownString.appendText(authorName);
71
markdownString.appendMarkdown('](');
72
markdownString.appendText(authorAvatar);
73
markdownString.appendMarkdown(`|width=${AVATAR_SIZE},height=${AVATAR_SIZE})`);
74
} else {
75
markdownString.appendMarkdown('$(account)');
76
}
77
78
// Email
79
if (authorEmail) {
80
markdownString.appendMarkdown(' [**');
81
markdownString.appendText(authorName);
82
markdownString.appendMarkdown('**](mailto:');
83
markdownString.appendText(authorEmail);
84
markdownString.appendMarkdown(')');
85
} else {
86
markdownString.appendMarkdown(' **');
87
markdownString.appendText(authorName);
88
markdownString.appendMarkdown('**');
89
}
90
91
// Date
92
if (authorDate && !isNaN(new Date(authorDate).getTime())) {
93
const dateString = new Date(authorDate).toLocaleString(undefined, {
94
year: 'numeric', month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric'
95
});
96
97
markdownString.appendMarkdown(', $(history)');
98
markdownString.appendText(` ${fromNow(authorDate, true, true)} (${dateString})`);
99
}
100
101
markdownString.appendMarkdown('\n\n');
102
}
103
104
// Subject | Message (escape image syntax)
105
markdownString.appendMarkdown(`${emojify(message.replace(/!\[/g, '![').replace(/\r\n|\r|\n/g, '\n\n'))}`);
106
markdownString.appendMarkdown(`\n\n---\n\n`);
107
}
108
109
function appendShortStats(markdownString: MarkdownString, shortStats: { files: number; insertions: number; deletions: number }): void {
110
// Short stats
111
markdownString.appendMarkdown(`<span>${shortStats.files === 1 ?
112
l10n.t('{0} file changed', shortStats.files) :
113
l10n.t('{0} files changed', shortStats.files)}</span>`);
114
115
if (shortStats.insertions) {
116
markdownString.appendMarkdown(`,&nbsp;<span style="color:var(--vscode-scmGraph-historyItemHoverAdditionsForeground);">${shortStats.insertions === 1 ?
117
l10n.t('{0} insertion{1}', shortStats.insertions, '(+)') :
118
l10n.t('{0} insertions{1}', shortStats.insertions, '(+)')}</span>`);
119
}
120
121
if (shortStats.deletions) {
122
markdownString.appendMarkdown(`,&nbsp;<span style="color:var(--vscode-scmGraph-historyItemHoverDeletionsForeground);">${shortStats.deletions === 1 ?
123
l10n.t('{0} deletion{1}', shortStats.deletions, '(-)') :
124
l10n.t('{0} deletions{1}', shortStats.deletions, '(-)')}</span>`);
125
}
126
127
markdownString.appendMarkdown(`\n\n---\n\n`);
128
}
129
130
function appendCommands(markdownString: MarkdownString, commands: Command[][]): void {
131
for (let index = 0; index < commands.length; index++) {
132
if (index !== 0) {
133
markdownString.appendMarkdown('&nbsp;&nbsp;|&nbsp;&nbsp;');
134
}
135
136
const commandsMarkdown = commands[index]
137
.map(command => `[${command.title}](command:${command.command}?${encodeURIComponent(JSON.stringify(command.arguments))} "${command.tooltip}")`);
138
markdownString.appendMarkdown(commandsMarkdown.join('&nbsp;'));
139
}
140
}
141
142
export function getHoverCommitHashCommands(documentUri: Uri, hash: string): Command[] {
143
return [{
144
title: `$(git-commit) ${getCommitShortHash(documentUri, hash)}`,
145
tooltip: l10n.t('Open Commit'),
146
command: 'git.viewCommit',
147
arguments: [documentUri, hash, documentUri]
148
}, {
149
title: `$(copy)`,
150
tooltip: l10n.t('Copy Commit Hash'),
151
command: 'git.copyContentToClipboard',
152
arguments: [hash]
153
}] satisfies Command[];
154
}
155
156
export function processHoverRemoteCommands(commands: Command[], hash: string): Command[] {
157
return commands.map(command => ({
158
...command,
159
arguments: [...command.arguments ?? [], hash]
160
} satisfies Command));
161
}
162
163