resources/src/mediawiki.diff.styles/diff.less
/*!
 * Diff rendering
 *
 * Stable for use on any page where a diff is rendered.
 * The early-loaded part of the mediawiki.diff module.
 * Usually added via DifferenceEngine::showDiffStyle() and loaded for all diffs generated by DifferenceEngine
 * IMPORTANT: This stylesheet is loaded on various pages.
 * This includes (but is not limited to):
 * diff pages, undo workflow, edit preview, edit conflict workflow.
 */

@import 'mediawiki.skin.variables.less';
@import 'mediawiki.mixins.less';

/* stylelint-disable selector-class-pattern */

.diff {
	border: 0;
	border-spacing: 4px;
	margin: 0;
	width: 100%;
	/* Ensure that columns are of equal width */
	table-layout: fixed;

	td {
		padding: 0.33em 0.5em;

		&.diff-marker {
			/* Compensate padding for increased font-size */
			padding: 0.25em;
			text-align: right;
			font-weight: bold;
			font-size: 1.25em;
			line-height: 1.2;

			&::before {
				content: attr( data-marker );
			}
		}

		div {
			/* Force-wrap very long lines such as URLs or page-widening char strings */
			word-wrap: break-word;
		}
	}

	col.diff-marker {
		width: 2%;
	}

	.diff-content {
		width: 48%;
	}
}

.diff-title {
	vertical-align: top;
}

.diff-notice,
.diff-multi,
.diff-otitle,
.diff-ntitle {
	text-align: center;
}

.diff-lineno {
	font-weight: bold;
	.user-select( none );
}

.mw-diff-inline-added,
.mw-diff-inline-changed,
.mw-diff-inline-moved,
.mw-diff-inline-deleted {
	ins,
	del {
		padding: 0.3em 1px;
		text-decoration: none;
		white-space: break-spaces;
		// When JS is enabled, deleted and added content will show a popup explaining what the colors mean.
		// Show a cursor pointer to make it clear it's clickable.
		.client-js & {
			// Note: This currently only happens at low resolutions.
			@media only screen and ( max-width: @max-width-breakpoint-tablet ) {
				cursor: pointer;
			}
		}
	}
}

.mw-diff-inline-added ins,
.mw-diff-inline-changed ins,
.mw-diff-inline-moved ins {
	background: @background-color-content-added;
}

.mw-diff-inline-deleted del,
.mw-diff-inline-changed del,
.mw-diff-inline-moved del {
	background: @background-color-content-removed;
}

.mw-diff-table-prefix {
	display: flex;
	justify-content: flex-end;
	align-items: center;
	margin: 1em 0;

	.mw-diff-inline-legend {
		margin-right: auto;

		.mw-diff-inline-legend-ins,
		.mw-diff-inline-legend-del {
			display: inline-block;
			padding: 4px 6px;
		}

		.mw-diff-inline-legend-ins {
			background: @background-color-content-added;
		}

		.mw-diff-inline-legend-del {
			background: @background-color-content-removed;
		}
	}

	.mw-diffPage-inlineToggle-container {
		margin-left: 1em;
	}
}

.diff-addedline,
.diff-deletedline,
.diff-context {
	vertical-align: top;
	border-style: solid;
	border-width: 1px 1px 1px 4px;
	border-radius: 0.33em;
}

.diff-addedline,
.diff-deletedline,
.diff-context,
.mw-diff-inline-added,
.mw-diff-inline-deleted,
.mw-diff-inline-moved,
.mw-diff-inline-changed,
.mw-diff-inline-context {
	// TODO: Re-evaluate we can use Codex design token like @font-size-small, which would mean to
	// bump the size up by equal to 14px in Vector 2022 and MinervaNeue.
	font-size: 0.8125rem;
	/* Standardize tab width */
	-moz-tab-size: 4;
	tab-size: 4;
	line-height: 1.6;
	// Support Chrome <= 75, Firefox <= 68: Fallback for browsers that don't support `break-spaces`.
	white-space: pre-wrap;
	white-space: break-spaces;

	// Allow editfont to be set on container while only
	// affecting wikitext content.
	// These classes match mw-editfont-*
	.diff-editfont-monospace & {
		font-family: monospace, monospace;
	}

	.diff-editfont-sans-serif & {
		font-family: sans-serif;
	}

	.diff-editfont-serif & {
		font-family: serif;
	}
}

.mw-diff-inline-header {
	font-weight: bold;
	margin: 1em 0;
}

.diff-context {
	background: @background-color-neutral-subtle;
	color: @color-base;
	border-color: @border-color-muted;
}

.diff-addedline {
	border-color: @background-color-content-added;
}

.diff-deletedline {
	border-color: @background-color-content-removed;
}

.diffchange {
	font-weight: bold;
	text-decoration: none;

	.diff-addedline &,
	.diff-deletedline & {
		border-radius: 0.33em;
		padding: 0.25em 0;
	}

	.diff-addedline & {
		background: @background-color-content-added;
	}

	.diff-deletedline & {
		background: @background-color-content-removed;
	}
}

/* Correct user & content directionality when viewing a diff */
.diff-currentversion-title,
.diff {
	direction: ltr;
	unicode-bidi: embed;
}

.diff-contentalign-right td {
	/* @noflip */
	direction: rtl;
	unicode-bidi: embed;
}

.diff-contentalign-left td {
	/* @noflip */
	direction: ltr;
	unicode-bidi: embed;
}

.diff-multi,
.diff-otitle,
.diff-ntitle,
.diff-lineno {
	direction: ltr !important; /* stylelint-disable-line declaration-no-important */
	unicode-bidi: embed;
}

.mw-diff-slot-header {
	text-align: center;
}

.mw-diff-slot-error {
	text-align: center;
	color: @color-error;
}

/*!
 * Wikidiff2 rendering for moved paragraphs
 */

.mw-diff-movedpara-left,
.mw-diff-movedpara-right {
	&,
	&:visited,
	&:active {
		display: block;
		color: transparent;
		.user-select( none );
	}

	&:hover {
		text-decoration: none;
		color: transparent;
	}

	&::after {
		display: block;
		color: @color-base;
		margin-top: -1.25em;
	}
}

.mw-diff-movedpara-left::after,
.rtl .mw-diff-movedpara-right::after {
	content: '↪';
}

.mw-diff-movedpara-right::after,
.rtl .mw-diff-movedpara-left::after {
	content: '↩';
}

#mw-inlinediff-header {
	#mw-diff-otitle1,
	#mw-diff-otitle2,
	#mw-diff-otitle3,
	#mw-diff-otitle5 {
		display: none;
	}
}

/* Lock selection to a single side */
.diff[ data-selected-side='deleted' ] .diff-side-added,
.diff[ data-selected-side='added' ] .diff-side-deleted {
	.user-select( none );
	cursor: text;
}

/*!
 * Wikidiff2 rendering for new lines and deleted lines
 */
.mw-diff-inline-added.mw-diff-empty-line,
.mw-diff-inline-deleted.mw-diff-empty-line,
.mw-inline-diff-newline {
	&::after {
		font-family: @font-family-monospace;
		font-size: 87.5%;
		padding: 0 3px;
		display: inline-block;
		color: @color-subtle;
	}
}

.mw-diff-inline-added.mw-diff-empty-line,
.mw-inline-diff-newline {
	&::after {
		content: '@{msg-diff-newline}';
		background: @background-color-content-added;
	}
}

.mw-diff-inline-deleted.mw-diff-empty-line {
	&::after {
		content: '@{msg-diff-line-deleted}';
		background: @background-color-content-removed;
	}
}

.mw-diffPage-inlineToggle-container .oo-ui-fieldLayout-body {
	align-items: center;
	white-space: nowrap;
}

.mw-diff-empty-line {
	ins,
	del {
		display: none;
	}
}

// Hidden by default, but can be used to adapt layout to mobile devices.
// This content may be useful on desktop skins too, however initially this
// is hidden by default as communities have not yet been consulted about this.
.mw-diff-usermetadata,
.mw-diff-revision-history-links {
	display: none;
}

// Hide the diff legend at lower resolutions.
@media only screen and ( max-width: @max-width-breakpoint-tablet ) {
	.mw-diff-inline-legend {
		display: none;
	}
}
