diff --git a/src/git/formatters/commitFormatter.ts b/src/git/formatters/commitFormatter.ts index 34f59bc..df109cd 100644 --- a/src/git/formatters/commitFormatter.ts +++ b/src/git/formatters/commitFormatter.ts @@ -631,9 +631,11 @@ export class CommitFormatter extends Formatter { return this._padOrTruncate(message, this._options.tokenOptions.message); } - let message = this._options.messageTruncateAtNewLine - ? this._item.summary - : this._item.message ?? this._item.summary; + let message = ( + this._options.messageTruncateAtNewLine ? this._item.summary : this._item.message ?? this._item.summary + ) + .trim() + .replace(/\r?\n/g, '\n'); message = emojify(message); message = this._padOrTruncate(message, this._options.tokenOptions.message); diff --git a/src/system/string.ts b/src/system/string.ts index 734f50d..f600afb 100644 --- a/src/system/string.ts +++ b/src/system/string.ts @@ -116,7 +116,7 @@ export function encodeHtmlWeak(s: string | undefined): string | undefined { const escapeMarkdownRegex = /[\\`*_{}[\]()#+\-.!]/g; const escapeMarkdownHeaderRegex = /^===/gm; // const sampleMarkdown = '## message `not code` *not important* _no underline_ \n> don\'t quote me \n- don\'t list me \n+ don\'t list me \n1. don\'t list me \nnot h1 \n=== \nnot h2 \n---\n***\n---\n___'; -const markdownQuotedRegex = /\n/g; +const markdownQuotedRegex = /\r?\n/g; export function escapeMarkdown(s: string, options: { quoted?: boolean } = {}): string { s = s @@ -128,7 +128,7 @@ export function escapeMarkdown(s: string, options: { quoted?: boolean } = {}): s if (!options.quoted) return s; // Keep under the same block-quote but with line breaks - return s.replace(markdownQuotedRegex, '\t\\\n> '); + return s.trim().replace(markdownQuotedRegex, '\t\\\n> '); } export function escapeRegex(s: string) { diff --git a/src/webviews/apps/commitDetails/commitDetails.scss b/src/webviews/apps/commitDetails/commitDetails.scss index c2144a7..1dda73f 100644 --- a/src/webviews/apps/commitDetails/commitDetails.scss +++ b/src/webviews/apps/commitDetails/commitDetails.scss @@ -254,6 +254,7 @@ ul { overflow-y: auto; overflow-x: hidden; max-height: 9rem; + white-space: break-spaces; strong { font-weight: 600; diff --git a/src/webviews/apps/commitDetails/commitDetails.ts b/src/webviews/apps/commitDetails/commitDetails.ts index 4177ab7..af9d34e 100644 --- a/src/webviews/apps/commitDetails/commitDetails.ts +++ b/src/webviews/apps/commitDetails/commitDetails.ts @@ -10,6 +10,7 @@ import { CommitActionsCommandType, DidChangeNotificationType, FileActionsCommandType, + messageHeadlineSplitterToken, OpenFileCommandType, OpenFileComparePreviousCommandType, OpenFileCompareWorkingCommandType, @@ -482,11 +483,14 @@ export class CommitDetailsApp extends App> { const $el = document.querySelector('[data-region="message"]'); if ($el == null) return; - const [headline, ...lines] = state.selected.message.split('
'); - if (lines.length > 0) { - $el.innerHTML = /*html*/ `${headline}
${lines.join('
')}`; + const index = state.selected.message.indexOf(messageHeadlineSplitterToken); + if (index === -1) { + $el.innerHTML = /*html*/ `${state.selected.message}`; } else { - $el.innerHTML = /*html*/ `${headline}`; + $el.innerHTML = /*html*/ `${state.selected.message.substring( + 0, + index, + )}
${state.selected.message.substring(index + 3)}`; } } diff --git a/src/webviews/commitDetails/commitDetailsWebviewView.ts b/src/webviews/commitDetails/commitDetailsWebviewView.ts index d7178a6..816dee9 100644 --- a/src/webviews/commitDetails/commitDetailsWebviewView.ts +++ b/src/webviews/commitDetails/commitDetailsWebviewView.ts @@ -10,6 +10,7 @@ import { configuration } from '../../configuration'; import { Commands, ContextKeys, CoreCommands } from '../../constants'; import type { Container } from '../../container'; import { getContext } from '../../context'; +import { CommitFormatter } from '../../git/formatters/commitFormatter'; import type { GitCommit } from '../../git/models/commit'; import { isCommit } from '../../git/models/commit'; import type { GitFileChange } from '../../git/models/file'; @@ -20,6 +21,7 @@ import type { PullRequest } from '../../git/models/pullRequest'; import { serializePullRequest } from '../../git/models/pullRequest'; import type { GitRevisionReference } from '../../git/models/reference'; import { GitReference } from '../../git/models/reference'; +import type { GitRemote } from '../../git/models/remote'; import { Logger } from '../../logger'; import type { ShowInCommitGraphCommandArgs } from '../../plus/webviews/graph/graphWebview'; import { executeCommand, executeCoreCommand } from '../../system/command'; @@ -27,6 +29,7 @@ import type { DateTimeFormat } from '../../system/date'; import { debug, getLogScope } from '../../system/decorators/log'; import type { Deferrable } from '../../system/function'; import { debounce } from '../../system/function'; +import type { PromiseCancelledError } from '../../system/promise'; import { getSettledValue } from '../../system/promise'; import type { Serialized } from '../../system/serialize'; import { serialize } from '../../system/serialize'; @@ -46,6 +49,7 @@ import { CommitActionsCommandType, DidChangeNotificationType, FileActionsCommandType, + messageHeadlineSplitterToken, OpenFileCommandType, OpenFileComparePreviousCommandType, OpenFileCompareWorkingCommandType, @@ -376,11 +380,9 @@ export class CommitDetailsWebviewView extends WebviewViewBase'), - 'html', - remote != null ? [remote] : undefined, - autolinkedIssuesOrPullRequests, - ); + const formattedMessage = this.getFormattedMessage(commit, remote, autolinkedIssuesOrPullRequests); // Remove possible duplicate pull request if (pr != null) { @@ -623,11 +620,7 @@ export class CommitDetailsWebviewView extends WebviewViewBase'), - 'html', - remote != null ? [remote] : undefined, - ); + formattedMessage = this.getFormattedMessage(commit, remote); } return { @@ -658,6 +651,24 @@ export class CommitDetailsWebviewView extends WebviewViewBase, + ) { + let message = CommitFormatter.fromTemplate(`\${message}`, commit); + const index = message.indexOf('\n'); + if (index !== -1) { + message = `${message.substring(0, index)}${messageHeadlineSplitterToken}${message.substring(index + 1)}`; + } + return this.container.autolinks.linkify( + message, + 'html', + remote != null ? [remote] : undefined, + issuesOrPullRequests, + ); + } + private async getFileCommitFromParams( params: FileActionParams, ): Promise<[commit: GitCommit, file: GitFileChange] | undefined> { diff --git a/src/webviews/commitDetails/protocol.ts b/src/webviews/commitDetails/protocol.ts index 1661ce6..d7beea3 100644 --- a/src/webviews/commitDetails/protocol.ts +++ b/src/webviews/commitDetails/protocol.ts @@ -6,6 +6,8 @@ import type { PullRequestShape } from '../../git/models/pullRequest'; import type { Serialized } from '../../system/serialize'; import { IpcCommandType, IpcNotificationType } from '../protocol'; +export const messageHeadlineSplitterToken = '\x00\n\x00'; + export type FileShowOptions = TextDocumentShowOptions; export type CommitSummary = {