Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[4.3] Template Diff View #2630

Closed
jgerman-bot opened this issue Oct 10, 2022 · 0 comments · Fixed by #2669, #2681 or #2682
Closed

[4.3] Template Diff View #2630

jgerman-bot opened this issue Oct 10, 2022 · 0 comments · Fixed by #2669, #2681 or #2682

Comments

@jgerman-bot
Copy link

New language relevant PR in upstream repo: joomla/joomla-cms#38823 Here are the upstream changes:

Click to expand the diff!
diff --git a/administrator/components/com_admin/sql/updates/mysql/4.3.0-2022-09-23.sql b/administrator/components/com_admin/sql/updates/mysql/4.3.0-2022-09-23.sql
new file mode 100644
index 000000000000..dc11ed153491
--- /dev/null
+++ b/administrator/components/com_admin/sql/updates/mysql/4.3.0-2022-09-23.sql
@@ -0,0 +1,2 @@
+-- Update the com_templates options to add the diff options
+UPDATE `#__extensions` SET `params` = REPLACE(`params`, '}', ',"difference":"SideBySide"}') WHERE `name` = 'com_templates';
diff --git a/administrator/components/com_admin/sql/updates/postgresql/4.3.0-2022-09-23.sql b/administrator/components/com_admin/sql/updates/postgresql/4.3.0-2022-09-23.sql
new file mode 100644
index 000000000000..bf5b5ad7e95e
--- /dev/null
+++ b/administrator/components/com_admin/sql/updates/postgresql/4.3.0-2022-09-23.sql
@@ -0,0 +1,2 @@
+-- Update the com_templates options to add the diff options
+UPDATE "#__extensions" SET "params" = REPLACE("params", '}', ',"difference":"SideBySide"}') WHERE "name" = 'com_templates';
diff --git a/administrator/components/com_templates/config.xml b/administrator/components/com_templates/config.xml
index 529425d9920b..430ebeb57ca2 100644
--- a/administrator/components/com_templates/config.xml
+++ b/administrator/components/com_templates/config.xml
@@ -62,6 +62,24 @@
 			default="zip"
 			extension="com_templates"
 		/>
+
+		<field
+			name="spacer2"
+			type="spacer"
+			hr="true"
+		/>
+
+		<field
+			name="difference"
+			type="radio"
+			label="COM_TEMPLATES_DIFF_OPTIONS"
+			layout="joomla.form.field.radio.switcher"
+			default="SideBySide"
+			>
+			<option value="Inline">COM_TEMPLATES_DIFF_OPTIONS_INLINE</option>
+			<option value="SideBySide">COM_TEMPLATES_DIFF_OPTIONS_SIDE</option>
+		</field>
+
 	</fieldset>
 
 	<fieldset
diff --git a/administrator/components/com_templates/tmpl/template/default.php b/administrator/components/com_templates/tmpl/template/default.php
index 798589607371..ce709617bc2d 100644
--- a/administrator/components/com_templates/tmpl/template/default.php
+++ b/administrator/components/com_templates/tmpl/template/default.php
@@ -11,11 +11,13 @@
 defined('_JEXEC') or die;
 
 use Joomla\CMS\Factory;
+use Joomla\CMS\Component\ComponentHelper;
 use Joomla\CMS\HTML\HTMLHelper;
 use Joomla\CMS\Language\Text;
 use Joomla\CMS\Layout\LayoutHelper;
 use Joomla\CMS\Router\Route;
 use Joomla\CMS\Session\Session;
+use Jfcherng\Diff\DiffHelper;
 
 HTMLHelper::_('behavior.multiselect', 'updateForm');
 HTMLHelper::_('bootstrap.modal');
@@ -27,9 +29,9 @@
 // Enable assets
 $wa->useScript('form.validate')
     ->useScript('keepalive')
-    ->useScript('diff')
-    ->useScript('com_templates.admin-template-compare')
-    ->useScript('com_templates.admin-template-toggle-switch');
+    ->useScript('com_templates.admin-template-toggle-switch')
+    ->useScript('com_templates.admin-templates')
+    ->useStyle('com_templates.admin-templates');
 
 // No access if not global SuperUser
 if (!Factory::getUser()->authorise('core.admin')) {
@@ -40,9 +42,6 @@
     $wa->usePreset('cropperjs');
 }
 
-$wa->useStyle('com_templates.admin-templates')
-    ->useScript('com_templates.admin-templates');
-
 if ($this->type == 'font') {
     $wa->addInlineStyle("
 		@font-face {
@@ -55,7 +54,6 @@
 	");
 }
 ?>
-
 <div class="main-card">
     <?php echo HTMLHelper::_('uitab.startTabSet', 'myTab', ['active' => 'editor', 'recall' => true, 'breakpoint' => 768]); ?>
     <?php echo HTMLHelper::_('uitab.addTab', 'myTab', 'editor', Text::_('COM_TEMPLATES_TAB_EDITOR')); ?>
@@ -141,20 +139,34 @@
                             </form>
                         </div>
                         <?php if (!empty($this->source->coreFile)) : ?>
-                            <?php $coreFileContent = file_get_contents($this->source->coreFile); ?>
-                            <?php $overrideFileContent = file_get_contents($this->source->filePath); ?>
                             <div class="col-md-12" id="core-pane">
                                 <h2><?php echo Text::_('COM_TEMPLATES_FILE_CORE_PANE'); ?></h2>
                                 <div class="editor-border">
                                     <?php echo $this->form->getInput('core'); ?>
                                 </div>
                             </div>
+                            <?php
+                                $difference = DiffHelper::calculateFiles(
+                                    $this->source->coreFile,
+                                    $this->source->filePath,
+                                    ComponentHelper::getParams('com_templates')->get('difference', 'SideByside'),
+                                    ['context' => 1],
+                                    [
+                                        'language' => [
+                                            'old_version' => Text::_('COM_TEMPLATES_DIFF_CORE'),
+                                            'new_version' => Text::_('COM_TEMPLATES_DIFF_OVERRIDE'),
+                                            'differences' => Text::_('COM_TEMPLATES_DIFF_DIFFERENCES'),
+                                        ],
+                                        'resultForIdenticals' => Text::_('COM_TEMPLATES_DIFF_IDENTICAL'),
+                                        'detailLevel' => 'word',
+                                        'spaceToHtmlTag' => true,
+                                    ],
+                                );
+                            ?>
                             <div class="col-md-12" id="diff-main">
                                 <h2><?php echo Text::_('COM_TEMPLATES_FILE_COMPARE_PANE'); ?></h2>
                                 <div class="diff-pane">
-                                    <div class="diffview d-none" id="original"><?php echo htmlspecialchars($coreFileContent, ENT_COMPAT, 'UTF-8'); ?></div>
-                                    <div class="diffview d-none" id="changed"><?php echo htmlspecialchars($overrideFileContent, ENT_COMPAT, 'UTF-8'); ?></div>
-                                    <div id="diff"></div>
+                                    <div id="diff"><?php echo $difference; ?></div>
                                 </div>
                             </div>
                         <?php endif; ?>
diff --git a/administrator/language/en-GB/com_templates.ini b/administrator/language/en-GB/com_templates.ini
index 086c10468b4b..dbe354f46982 100644
--- a/administrator/language/en-GB/com_templates.ini
+++ b/administrator/language/en-GB/com_templates.ini
@@ -32,18 +32,24 @@ COM_TEMPLATES_CHILD_SUCCESS="Child template created."
 COM_TEMPLATES_CLICK_TO_ENLARGE="Select to enlarge."
 COM_TEMPLATES_COMPILE_ERROR="An error occurred. Failed to compile."
 COM_TEMPLATES_COMPILE_LESS="You should compile %s to generate a CSS file."
+COM_TEMPLATES_CONFIGURATION="Template: Options"
 COM_TEMPLATES_CONFIG_FIELDSET_DESC="Global configuration for templates."
 COM_TEMPLATES_CONFIG_FONT_LABEL="Valid Font Formats"
 COM_TEMPLATES_CONFIG_IMAGE_LABEL="Valid Image Formats"
 COM_TEMPLATES_CONFIG_POSITIONS_LABEL="Preview Module Positions"
 COM_TEMPLATES_CONFIG_SOURCE_LABEL="Valid Source Formats"
 COM_TEMPLATES_CONFIG_UPLOAD_LABEL="Max. Upload Size (MB)"
-COM_TEMPLATES_CONFIGURATION="Template: Options"
 COM_TEMPLATES_COPY_CHILD_TEMPLATE_STYLES="%s, copy of %s"
 COM_TEMPLATES_COPY_SUCCESS="New template called %s was installed."
 COM_TEMPLATES_CROP_AREA_ERROR="Crop area not selected."
+COM_TEMPLATES_DIFF_CORE="Original"
+COM_TEMPLATES_DIFF_DIFFERENCES="Differences"
+COM_TEMPLATES_DIFF_IDENTICAL="The two files are identical."
+COM_TEMPLATES_DIFF_OPTIONS="File Diff Display"
+COM_TEMPLATES_DIFF_OPTIONS_INLINE="Inline"
+COM_TEMPLATES_DIFF_OPTIONS_SIDE="Side-by-Side"
+COM_TEMPLATES_DIFF_OVERRIDE="Override"
 COM_TEMPLATES_DIRECTORY_NOT_WRITABLE="The template folder is not writable. Some features may not work."
-COM_TEMPLATES_ERR_XML="Template XML data not available"
 COM_TEMPLATES_ERROR_ASSET_FILE_DELETE="The file joomla.asset.json can't be deleted. Make changes in the editor if you want to change the file."
 COM_TEMPLATES_ERROR_ASSET_FILE_INVALID_JSON="The joomla.asset.json file doesn't contain valid JSON, aborting save."
 COM_TEMPLATES_ERROR_CANNOT_DELETE_LAST_STYLE="Can't delete the last style of a template."
@@ -69,8 +75,8 @@ COM_TEMPLATES_ERROR_INDEX_DELETE="The file index.php can't be deleted. Make chan
 COM_TEMPLATES_ERROR_INVALID_FROM_NAME="Template to copy from can't be found."
 COM_TEMPLATES_ERROR_INVALID_TEMPLATE_NAME="Invalid template name. Please use only letters, numbers and underscores."
 COM_TEMPLATES_ERROR_NO_FILE_SELECTED="No file selected."
-COM_TEMPLATES_ERROR_RENAME_INDEX="The file index.php can't be renamed."
 COM_TEMPLATES_ERROR_RENAME_ASSET_FILE="The file joomla.asset.json can't be renamed."
+COM_TEMPLATES_ERROR_RENAME_INDEX="The file index.php can't be renamed."
 COM_TEMPLATES_ERROR_ROOT_DELETE="The root folder can't be deleted."
 COM_TEMPLATES_ERROR_SAVE_DISABLED_TEMPLATE="Unable to save a style associated to a disabled template."
 COM_TEMPLATES_ERROR_SOURCE_FILE_NOT_FOUND="Source file not found."
@@ -85,6 +91,7 @@ COM_TEMPLATES_ERROR_WARNFILENAME="Invalid file name. Please correct the name of
 COM_TEMPLATES_ERROR_WARNFILETOOLARGE="This file is too large to upload."
 COM_TEMPLATES_ERROR_WARNFILETYPE="File format not supported."
 COM_TEMPLATES_ERROR_WARNIEXSS="Can't be uploaded. Has XSS."
+COM_TEMPLATES_ERR_XML="Template XML data not available"
 COM_TEMPLATES_FIELD_CLIENT_LABEL="Location"
 COM_TEMPLATES_FIELD_HOME_LABEL="Default"
 COM_TEMPLATES_FIELD_SOURCE_LABEL="Source Code"
@@ -153,7 +160,6 @@ COM_TEMPLATES_INVALID_FILE_TYPE="File type not selected."
 COM_TEMPLATES_INVALID_FOLDER_NAME="Invalid folder name. Please choose a folder name with a-z, A-Z, 0-9, - and _."
 COM_TEMPLATES_LAYOUTS_DIFFVIEW_CORE="Show Original File"
 COM_TEMPLATES_LAYOUTS_DIFFVIEW_DIFF="Show Differences"
-COM_TEMPLATES_MANAGE_FOLDERS="Manage Folders"
 COM_TEMPLATES_MANAGER_ADD_STYLE="Templates: Add Style"
 COM_TEMPLATES_MANAGER_EDIT_STYLE="Templates: Edit Style"
 COM_TEMPLATES_MANAGER_STYLES="Templates: Styles"
@@ -164,12 +170,18 @@ COM_TEMPLATES_MANAGER_TEMPLATES="Templates"
 COM_TEMPLATES_MANAGER_TEMPLATES_ADMIN="Templates: Templates (Administrator)"
 COM_TEMPLATES_MANAGER_TEMPLATES_SITE="Templates: Templates (Site)"
 COM_TEMPLATES_MANAGER_VIEW_TEMPLATE="Templates: Customise (%s)"
+COM_TEMPLATES_MANAGE_FOLDERS="Manage Folders"
+COM_TEMPLATES_MENUS_ASSIGNMENT="Menu Assignment"
 COM_TEMPLATES_MENU_CHANGED_1="One menu item has been assigned or unassigned to this style."
 COM_TEMPLATES_MENU_CHANGED_MORE="%d menu items have been assigned or unassigned to this style."
-COM_TEMPLATES_MENUS_ASSIGNMENT="Menu Assignment"
 COM_TEMPLATES_MODAL_FILE_DELETE="The file %s will be deleted."
 COM_TEMPLATES_MSG_MANAGE_NO_STYLES="There are no styles installed matching your query."
 COM_TEMPLATES_MSG_MANAGE_NO_TEMPLATES="There are no templates installed matching your query."
+COM_TEMPLATES_NEW_FILE_HEADER="Create or Upload a new file."
+COM_TEMPLATES_NEW_FILE_NAME="New File Name"
+COM_TEMPLATES_NEW_FILE_SELECT="Select a file type"
+COM_TEMPLATES_NEW_FILE_TYPE="File Type"
+COM_TEMPLATES_NO_TEMPLATE_SELECTED="No template selected."
 COM_TEMPLATES_N_CONFLICT="%d Changes found"
 COM_TEMPLATES_N_CONFLICT_1="Change found"
 COM_TEMPLATES_N_ITEMS_DELETED="%d template styles deleted."
@@ -180,13 +192,13 @@ COM_TEMPLATES_N_OVERRIDE_DELETED="%d records removed."
 COM_TEMPLATES_N_OVERRIDE_DELETED_1="Record removed."
 COM_TEMPLATES_N_OVERRIDE_UNCHECKED="%d records unchecked."
 COM_TEMPLATES_N_OVERRIDE_UNCHECKED_1="Record unchecked."
-COM_TEMPLATES_NEW_FILE_HEADER="Create or Upload a new file."
-COM_TEMPLATES_NEW_FILE_NAME="New File Name"
-COM_TEMPLATES_NEW_FILE_SELECT="Select a file type"
-COM_TEMPLATES_NEW_FILE_TYPE="File Type"
-COM_TEMPLATES_NO_TEMPLATE_SELECTED="No template selected."
 COM_TEMPLATES_OPTION_NONE=":: None ::"
 COM_TEMPLATES_OPTION_SELECT_MENU_ITEM="- Select Menu Item -"
+COM_TEMPLATES_OVERRIDES="Override Files"
+COM_TEMPLATES_OVERRIDES_COMPONENTS="Components"
+COM_TEMPLATES_OVERRIDES_LAYOUTS="Layouts"
+COM_TEMPLATES_OVERRIDES_MODULES="Modules"
+COM_TEMPLATES_OVERRIDES_PLUGINS="Plugins"
 COM_TEMPLATES_OVERRIDE_CHECKED="Checked"
 COM_TEMPLATES_OVERRIDE_CORE_REMOVED="Original file removed"
 COM_TEMPLATES_OVERRIDE_CREATED="Override created in "
@@ -197,25 +209,20 @@ COM_TEMPLATES_OVERRIDE_NOT_UPTODATE="The originals of the template override file
 COM_TEMPLATES_OVERRIDE_SOURCE="Update Source"
 COM_TEMPLATES_OVERRIDE_TEMPLATE_FILE="Template File"
 COM_TEMPLATES_OVERRIDE_UPTODATE="Override files are up to date. Nothing has been changed in the last extension or Joomla update."
-COM_TEMPLATES_OVERRIDES="Override Files"
-COM_TEMPLATES_OVERRIDES_COMPONENTS="Components"
-COM_TEMPLATES_OVERRIDES_LAYOUTS="Layouts"
-COM_TEMPLATES_OVERRIDES_MODULES="Modules"
-COM_TEMPLATES_OVERRIDES_PLUGINS="Plugins"
 COM_TEMPLATES_PREVIEW="Preview"
 COM_TEMPLATES_RENAME_FILE="Rename file %s"
 COM_TEMPLATES_RESIZE_IMAGE="Resize Image"
 COM_TEMPLATES_SCREENSHOT="%s Screenshot"
 COM_TEMPLATES_SOURCE_CODE="Source"
-COM_TEMPLATES_STYLE_CANNOT_DELETE_DEFAULT_STYLE="Can't delete default style."
-COM_TEMPLATES_STYLE_FORM_EDIT="Edit Style"
-COM_TEMPLATES_STYLE_SAVE_SUCCESS="Style saved."
 COM_TEMPLATES_STYLES_FILTER_SEARCH_DESC="Search in style description."
 COM_TEMPLATES_STYLES_PAGES_ALL="Default for all pages"
 COM_TEMPLATES_STYLES_PAGES_ALL_LANGUAGE="Default for %s pages"
 COM_TEMPLATES_STYLES_PAGES_NONE="Not assigned"
 COM_TEMPLATES_STYLES_PAGES_SELECTED="Assigned on %s pages"
 COM_TEMPLATES_STYLES_TABLE_CAPTION="Table of Template Styles"
+COM_TEMPLATES_STYLE_CANNOT_DELETE_DEFAULT_STYLE="Can't delete default style."
+COM_TEMPLATES_STYLE_FORM_EDIT="Edit Style"
+COM_TEMPLATES_STYLE_SAVE_SUCCESS="Style saved."
 COM_TEMPLATES_SUBMENU_TEMPLATES="Templates"
 COM_TEMPLATES_SUCCESS_DUPLICATED="Style duplicated."
 COM_TEMPLATES_SUCCESS_HOME_SET="Default style set."
@@ -224,10 +231,11 @@ COM_TEMPLATES_TAB_DESCRIPTION="Template Description"
 COM_TEMPLATES_TAB_EDITOR="Editor"
 COM_TEMPLATES_TAB_OVERRIDES="Create Overrides"
 COM_TEMPLATES_TAB_UPDATED_FILES="Updated Files"
+COM_TEMPLATES_TEMPLATES_FILTER_SEARCH_DESC="Search in template name or folder name."
+COM_TEMPLATES_TEMPLATES_TABLE_CAPTION="Table of Templates"
 COM_TEMPLATES_TEMPLATE_CHILD="Child Template"
 COM_TEMPLATES_TEMPLATE_CHILD_NAME_LABEL="Child Template Name"
 COM_TEMPLATES_TEMPLATE_CHILD_STYLE_LABEL="Additional Template Styles"
-COM_TEMPLATES_TEMPLATE_NEW_STYLE_DESC="Duplicate existing styles for the new child template."
 COM_TEMPLATES_TEMPLATE_CLOSE="Close"
 COM_TEMPLATES_TEMPLATE_COPY="Copy Template"
 COM_TEMPLATES_TEMPLATE_CORE_FILENAME="Original file &quot;%s&quot;."
@@ -243,11 +251,10 @@ COM_TEMPLATES_TEMPLATE_MEDIA_FOLDER="Media Folder"
 COM_TEMPLATES_TEMPLATE_NEW_NAME_DESC="Letters, numbers and underscore only."
 COM_TEMPLATES_TEMPLATE_NEW_NAME_LABEL="New Template Name"
 COM_TEMPLATES_TEMPLATE_NEW_PREVIEW="Preview %s in new window."
-COM_TEMPLATES_TEMPLATE_NO_PREVIEW="No preview available. You can enable preview in the options."
+COM_TEMPLATES_TEMPLATE_NEW_STYLE_DESC="Duplicate existing styles for the new child template."
 COM_TEMPLATES_TEMPLATE_NOT_SPECIFIED="Template not specified."
+COM_TEMPLATES_TEMPLATE_NO_PREVIEW="No preview available. You can enable preview in the options."
 COM_TEMPLATES_TEMPLATE_PREVIEW="Preview"
-COM_TEMPLATES_TEMPLATES_FILTER_SEARCH_DESC="Search in template name or folder name."
-COM_TEMPLATES_TEMPLATES_TABLE_CAPTION="Table of Templates"
 COM_TEMPLATES_TOOLBAR_SET_HOME="Default"
 COM_TEMPLATES_UPTODATE="Up to date"
 COM_TEMPLATES_WARNING_FORMAT_WILL_NOT_BE_VISIBLE="You have created a new file with the extension '%s'. This is supported but as you did not have that file extension in the list of supported formats this can't be displayed. Please double check the options for Templates and add the format if needed."
diff --git a/build/build.php b/build/build.php
index 5145ced59130..fc07b8b63bfe 100644
--- a/build/build.php
+++ b/build/build.php
@@ -181,6 +181,14 @@ function clean_checkout(string $dir)
     // willdurand/negotiation
     system('rm -rf libraries/vendor/willdurand/negotiation/tests');
 
+    // jfcherng
+    system('rm -rf libraries/vendor/jfcherng/php-color-output/demo.php');
+    system('rm -rf libraries/vendor/jfcherng/php-color-output/UPGRADING_v2.md');
+    system('rm -rf libraries/vendor/jfcherng/php-diff/CHANGELOG');
+    system('rm -rf libraries/vendor/jfcherng/php-diff/example');
+    system('rm -rf libraries/vendor/jfcherng/php-diff/UPGRADING');
+    system('rm -rf libraries/vendor/jfcherng/php-mb-string/CHANGELOG');
+
     echo "Cleanup complete.\n";
 
     chdir($cwd);
diff --git a/build/media_source/com_templates/css/admin-templates-default.css b/build/media_source/com_templates/css/admin-templates-default.css
index a92aa1935c07..fc199a722b84 100644
--- a/build/media_source/com_templates/css/admin-templates-default.css
+++ b/build/media_source/com_templates/css/admin-templates-default.css
@@ -56,30 +56,6 @@
   display: block;
 }
 
-.diffview {
-  white-space: pre-wrap;
-  word-wrap: break-word;
-  display: inline;
-  padding: 4px;
-  border-radius: .2em;
-}
-
-.diff-pane {
-  height: 350px;
-  border: 0.5px solid grey;
-  overflow: auto;
-  padding: 10px;
-  background-color: #FFF;
-}
-
-#diff-main.active {
-  display: block;
-}
-
-#diff-main {
-  display: none;
-}
-
 #core-pane.active {
   display: block;
 }
@@ -96,11 +72,6 @@
   white-space: nowrap;
 }
 
-/* RTL overrides for templates editing*/
-[dir=rtl] .diff-pane {
-  text-align: left;
-}
-
 [dir=rtl] #core-pane textarea,
 #override-pane textarea {
   text-align: left;
@@ -114,3 +85,150 @@
 [dir=rtl] #toggle-buttons {
   text-align: right !important;
 }
+
+.diff-pane {
+  min-height: 100px;
+  max-height: 350px;
+  overflow: auto;
+  border: 1px solid #dfdfdf;
+}
+
+#diff-main.active {
+  display: block;
+}
+
+#diff-main {
+  display: none;
+}
+
+.diff-wrapper.diff {
+  --tab-size: 4;
+  background: repeating-linear-gradient(-45deg, whitesmoke, whitesmoke 0.5em, #e8e8e8 0.5em, #e8e8e8 1em);
+  border-collapse: collapse;
+  border-spacing: 0;
+  color: black;
+  empty-cells: show;
+  font-family: monospace;
+  font-size: 13px;
+  width: 100%;
+}
+.diff-wrapper.diff th {
+  font-weight: 700;
+  cursor: default;
+  -webkit-user-select: none;
+  user-select: none;
+}
+.diff-wrapper.diff td {
+  vertical-align: baseline;
+}
+.diff-wrapper.diff td,
+.diff-wrapper.diff th {
+  border-collapse: separate;
+  border: none;
+  padding: 1px 2px;
+  background: #fff;
+}
+.diff-wrapper.diff td:empty:after,
+.diff-wrapper.diff th:empty:after {
+  content: " ";
+  visibility: hidden;
+}
+.diff-wrapper.diff td a,
+.diff-wrapper.diff th a {
+  color: #000;
+  cursor: inherit;
+  pointer-events: none;
+}
+.diff-wrapper.diff thead th {
+  background: #f7f7f7;
+  border-bottom: 1px solid #ddd;
+  padding: 4px;
+  text-align: left;
+  position: sticky;
+  top: 0;
+}
+.diff-wrapper.diff tbody.skipped {
+  border-top: 1px solid #ddd;
+}
+.diff-wrapper.diff tbody.skipped td,
+.diff-wrapper.diff tbody.skipped th {
+  display: none;
+}
+.diff-wrapper.diff tbody th {
+  color: #999;
+  background: #f7f7f7;
+  border-right: 1px solid #ddd;
+  text-align: right;
+  vertical-align: top;
+  width: 4em;
+  padding-right: 2em;
+  font-weight: 400;
+}
+.diff-wrapper.diff th.n-new {
+  border-left: 1px solid #ddd;
+}
+.diff-wrapper.diff tbody th.sign {
+  background: #fff;
+  border-left: 1px solid #ddd;
+  padding: 1px 0;
+  text-align: center;
+  width: 1em;
+}
+.diff-wrapper.diff tbody th.sign.del {
+  background: #fbe1e1;
+}
+.diff-wrapper.diff tbody th.sign.ins {
+  background: #e1fbe1;
+}
+.diff-wrapper.diff.diff-html {
+  white-space: pre-wrap;
+  tab-size: var(--tab-size);
+}
+.diff-wrapper.diff.diff-html .ch {
+  line-height: 1em;
+  background-clip: border-box;
+  background-repeat: repeat-x;
+  background-position: left center;
+}
+.diff-wrapper.diff.diff-html .ch.sp {
+  background-image: url('data:image/svg+xml,%3Csvg preserveAspectRatio="xMinYMid meet" viewBox="0 0 12 24" xmlns="http://www.w3.org/2000/svg"%3E%3Cpath d="M4.5 11C4.5 10.1716 5.17157 9.5 6 9.5C6.82843 9.5 7.5 10.1716 7.5 11C7.5 11.8284 6.82843 12.5 6 12.5C5.17157 12.5 4.5 11.8284 4.5 11Z" fill="rgba%2860, 60, 60, 50%25%29"/%3E%3C/svg%3E');
+  background-size: 1ch 1.25em;
+}
+.diff-wrapper.diff.diff-html .ch.tab {
+  background-image: url('data:image/svg+xml,%3Csvg preserveAspectRatio="xMinYMid meet" viewBox="0 0 12 24" xmlns="http://www.w3.org/2000/svg"%3E%3Cpath d="M9.5 10.44L6.62 8.12L7.32 7.26L12.04 11V11.44L7.28 14.9L6.62 13.9L9.48 11.78H0V10.44H9.5Z" fill="rgba%2860, 60, 60, 50%25%29"/%3E%3C/svg%3E');
+  background-size: calc(var(--tab-size) * 1ch) 1.25em;
+  background-position: 2px center;
+}
+.diff-wrapper.diff.diff-html.diff-combined .change.change-rep .rep {
+  white-space: normal;
+}
+.diff-wrapper.diff.diff-html .change.change-eq .old,
+.diff-wrapper.diff.diff-html .change.change-eq .new {
+  background: #fff;
+}
+.diff-wrapper.diff.diff-html .change .old {
+  background: #fbe1e1;
+}
+.diff-wrapper.diff.diff-html .change .new {
+  background: #e1fbe1;
+}
+.diff-wrapper.diff.diff-html .change .rep {
+  background: #fef6d9;
+}
+.diff-wrapper.diff.diff-html .change .old.none,
+.diff-wrapper.diff.diff-html .change .new.none,
+.diff-wrapper.diff.diff-html .change .rep.none {
+  background: transparent;
+  cursor: not-allowed;
+}
+.diff-wrapper.diff.diff-html .change ins,
+.diff-wrapper.diff.diff-html .change del {
+  font-weight: bold;
+  text-decoration: none;
+}
+.diff-wrapper.diff.diff-html .change ins {
+  background: #94f094;
+}
+.diff-wrapper.diff.diff-html .change del {
+  background: #f09494;
+}
diff --git a/build/media_source/com_templates/joomla.asset.json b/build/media_source/com_templates/joomla.asset.json
index 3e663870697d..3bba1c93d46f 100644
--- a/build/media_source/com_templates/joomla.asset.json
+++ b/build/media_source/com_templates/joomla.asset.json
@@ -5,30 +5,6 @@
   "description": "Joomla CMS",
   "license": "GPL-2.0-or-later",
   "assets": [
-    {
-      "name": "com_templates.admin-template-compare.es5",
-      "type": "script",
-      "uri": "com_templates/admin-template-compare-es5.min.js",
-      "dependencies": [
-        "core",
-        "diff"
-      ],
-      "attributes": {
-        "nomodule": true,
-        "defer": true
-      }
-    },
-    {
-      "name": "com_templates.admin-template-compare",
-      "type": "script",
-      "uri": "com_templates/admin-template-compare.min.js",
-      "dependencies": [
-        "com_templates.admin-template-compare.es5"
-      ],
-      "attributes": {
-        "type": "module"
-      }
-    },
     {
       "name": "com_templates.admin-template-toggle-assignment.es5",
       "type": "script",
diff --git a/build/media_source/com_templates/js/admin-template-compare.es6.js b/build/media_source/com_templates/js/admin-template-compare.es6.js
deleted file mode 100644
index 7044d9121761..000000000000
--- a/build/media_source/com_templates/js/admin-template-compare.es6.js
+++ /dev/null
@@ -1,61 +0,0 @@
-/**
- * @copyright  (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
- * @license    GNU General Public License version 2 or later; see LICENSE.txt
- */
-(() => {
-  'use strict';
-
-  document.addEventListener('DOMContentLoaded', () => {
-    const decodeHtmlspecialChars = (text) => {
-      const map = {
-        '&amp;': '&',
-        '&#038;': '&',
-        '&lt;': '<',
-        '&gt;': '>',
-        '&quot;': '"',
-        '&#039;': "'",
-        '&#8217;': '’',
-        '&#8216;': '‘',
-        '&#8211;': '–',
-        '&#8212;': '—',
-        '&#8230;': '…',
-        '&#8221;': '”',
-      };
-
-      /* eslint-disable */
-      return text.replace(/\&[\w\d\#]{2,5}\;/g, (m) => { const n = map[m]; return n; });
-    };
-
-    const compare = (original, changed) => {
-      const display = changed.nextElementSibling;
-      let color = '';
-      let pre = null;
-      const diff = Diff.diffLines(original.innerHTML, changed.innerHTML);
-      const fragment = document.createDocumentFragment();
-
-      /* eslint-enable */
-
-      diff.forEach((part) => {
-        if (part.added) {
-          color = '#a6f3a6';
-        } else if (part.removed) {
-          color = '#f8cbcb';
-        } else {
-          color = '';
-        }
-        pre = document.createElement('pre');
-        pre.style.backgroundColor = color;
-        pre.className = 'diffview';
-        pre.appendChild(document.createTextNode(decodeHtmlspecialChars(part.value)));
-        fragment.appendChild(pre);
-      });
-
-      display.appendChild(fragment);
-    };
-
-    const diffs = [].slice.call(document.querySelectorAll('#original'));
-    for (let i = 0, l = diffs.length; i < l; i += 1) {
-      compare(diffs[i], diffs[i].nextElementSibling);
-    }
-  });
-})();
diff --git a/composer.json b/composer.json
index 06fd0b2697ea..937405bb220b 100644
--- a/composer.json
+++ b/composer.json
@@ -97,7 +97,8 @@
         "enshrined/svg-sanitize": "^0.15.4",
         "lcobucci/jwt": "^3.4.6",
         "web-token/signature-pack": "^2.2.11",
-        "phpseclib/bcmath_compat": "^2.0"
+        "phpseclib/bcmath_compat": "^2.0",
+        "jfcherng/php-diff": "^6.10"
     },
     "require-dev": {
         "phpunit/phpunit": "^8.5",
diff --git a/composer.lock b/composer.lock
index 1ff0d3765081..7cd4b27754b0 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "247b8d364f7a520d56a83ae603d724fd",
+    "content-hash": "d9aeb137af8ceaf60f9d57ed6bf4f2fb",
     "packages": [
         {
             "name": "algo26-matthias/idna-convert",
@@ -754,6 +754,236 @@
             },
             "time": "2017-05-01T15:36:40+00:00"
         },
+        {
+            "name": "jfcherng/php-color-output",
+            "version": "2.0.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/jfcherng/php-color-output.git",
+                "reference": "2673074597eca9682d2fdfaee39a22418d4cc2f6"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://github.com/gitapi/repos/jfcherng/php-color-output/zipball/2673074597eca9682d2fdfaee39a22418d4cc2f6",
+                "reference": "2673074597eca9682d2fdfaee39a22418d4cc2f6",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.1.3"
+            },
+            "require-dev": {
+                "friendsofphp/php-cs-fixer": "^2.15",
+                "phan/phan": "^2.2",
+                "phpunit/phpunit": "^7.2 || ^8.2 || ^9",
+                "squizlabs/php_codesniffer": "^3.5"
+            },
+            "type": "library",
+            "autoload": {
+                "files": [
+                    "src/helpers.php"
+                ],
+                "psr-4": {
+                    "Jfcherng\\Utility\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Jack Cherng",
+                    "email": "jfcherng@gmail.com"
+                }
+            ],
+            "description": "Make your PHP command-line application colorful.",
+            "keywords": [
+                "ansi-colors",
+                "color",
+                "command-line",
+                "str-color"
+            ],
+            "support": {
+                "issues": "https://github.com/jfcherng/php-color-output/issues",
+                "source": "https://github.com/jfcherng/php-color-output/tree/2.0.2"
+            },
+            "time": "2020-05-27T19:24:44+00:00"
+        },
+        {
+            "name": "jfcherng/php-diff",
+            "version": "6.10.6",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/jfcherng/php-diff.git",
+                "reference": "8453818a601d3abf68638b72651fac39743fe06f"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://github.com/gitapi/repos/jfcherng/php-diff/zipball/8453818a601d3abf68638b72651fac39743fe06f",
+                "reference": "8453818a601d3abf68638b72651fac39743fe06f",
+                "shasum": ""
+            },
+            "require": {
+                "jfcherng/php-color-output": "^2.0",
+                "jfcherng/php-mb-string": "^1.4.6",
+                "jfcherng/php-sequence-matcher": "^3.2.8",
+                "php": ">=7.1.3"
+            },
+            "require-dev": {
+                "friendsofphp/php-cs-fixer": "^2.19",
+                "liip/rmt": "^1.6",
+                "phan/phan": "^2.5 || ^3 || ^4",
+                "phpunit/phpunit": ">=7 <10",
+                "squizlabs/php_codesniffer": "^3.6"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Jfcherng\\Diff\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Jack Cherng",
+                    "email": "jfcherng@gmail.com"
+                },
+                {
+                    "name": "Chris Boulton",
+                    "email": "chris.boulton@interspire.com"
+                }
+            ],
+            "description": "A comprehensive library for generating differences between two strings in multiple formats (unified, side by side HTML etc).",
+            "keywords": [
+                "diff",
+                "udiff",
+                "unidiff",
+                "unified diff"
+            ],
+            "support": {
+                "issues": "https://github.com/jfcherng/php-diff/issues",
+                "source": "https://github.com/jfcherng/php-diff/tree/6.10.6"
+            },
+            "funding": [
+                {
+                    "url": "https://www.paypal.me/jfcherng/5usd",
+                    "type": "custom"
+                }
+            ],
+            "time": "2022-09-25T14:34:59+00:00"
+        },
+        {
+            "name": "jfcherng/php-mb-string",
+            "version": "1.4.6",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/jfcherng/php-mb-string.git",
+                "reference": "f5b438d348e030961e0b86a04ef2319c31ae8146"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://github.com/gitapi/repos/jfcherng/php-mb-string/zipball/f5b438d348e030961e0b86a04ef2319c31ae8146",
+                "reference": "f5b438d348e030961e0b86a04ef2319c31ae8146",
+                "shasum": ""
+            },
+            "require": {
+                "ext-iconv": "*",
+                "php": ">=7.1.3"
+            },
+            "require-dev": {
+                "friendsofphp/php-cs-fixer": "^2.18",
+                "phan/phan": "^2 || ^3 || ^4",
+                "phpunit/phpunit": "^7.2 || ^8 || ^9"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Jfcherng\\Utility\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Jack Cherng",
+                    "email": "jfcherng@gmail.com"
+                }
+            ],
+            "description": "A high performance multibytes sting implementation for frequently reading/writing operations.",
+            "support": {
+                "issues": "https://github.com/jfcherng/php-mb-string/issues",
+                "source": "https://github.com/jfcherng/php-mb-string/tree/1.4.6"
+            },
+            "funding": [
+                {
+                    "url": "https://www.paypal.me/jfcherng/5usd",
+                    "type": "custom"
+                }
+            ],
+            "time": "2022-04-02T16:32:41+00:00"
+        },
+        {
+            "name": "jfcherng/php-sequence-matcher",
+            "version": "3.2.8",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/jfcherng/php-sequence-matcher.git",
+                "reference": "410519ca07cd7989f450d6e2aa40975dbd1be048"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://github.com/gitapi/repos/jfcherng/php-sequence-matcher/zipball/410519ca07cd7989f450d6e2aa40975dbd1be048",
+                "reference": "410519ca07cd7989f450d6e2aa40975dbd1be048",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.1.3"
+            },
+            "require-dev": {
+                "friendsofphp/php-cs-fixer": "^2.19",
+                "liip/rmt": "^1.6",
+                "phan/phan": "^2.5 || ^3 || ^4 || ^5",
+                "phpunit/phpunit": ">=7 <10",
+                "squizlabs/php_codesniffer": "^3.5"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Jfcherng\\Diff\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Jack Cherng",
+                    "email": "jfcherng@gmail.com"
+                },
+                {
+                    "name": "Chris Boulton",
+                    "email": "chris.boulton@interspire.com"
+                }
+            ],
+            "description": "A longest sequence matcher. The logic is primarily based on the Python difflib package.",
+            "support": {
+                "issues": "https://github.com/jfcherng/php-sequence-matcher/issues",
+                "source": "https://github.com/jfcherng/php-sequence-matcher/tree/3.2.8"
+            },
+            "funding": [
+                {
+                    "url": "https://www.paypal.me/jfcherng/5usd",
+                    "type": "custom"
+                }
+            ],
+            "time": "2021-09-02T04:02:02+00:00"
+        },
         {
             "name": "joomla/application",
             "version": "2.0.3",
@@ -5869,23 +6099,34 @@
         },
         {
             "name": "web-token/jwt-signature-algorithm-eddsa",
-            "version": "v2.2.11",
+            "version": "v2.0.10",
             "source": {
                 "type": "git",
                 "url": "https://github.com/web-token/jwt-signature-algorithm-eddsa.git",
-                "reference": "b805ecca593c56e60e0463bd2cacc9b1341910f6"
+                "reference": "383c0e741d50a4bd5402e00230b3625cb1d489b1"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://github.com/gitapi/repos/web-token/jwt-signature-algorithm-eddsa/zipball/b805ecca593c56e60e0463bd2cacc9b1341910f6",
-                "reference": "b805ecca593c56e60e0463bd2cacc9b1341910f6",
+                "url": "https://github.com/gitapi/repos/web-token/jwt-signature-algorithm-eddsa/zipball/383c0e741d50a4bd5402e00230b3625cb1d489b1",
+                "reference": "383c0e741d50a4bd5402e00230b3625cb1d489b1",
                 "shasum": ""
             },
             "require": {
-                "ext-sodium": "*",
-                "web-token/jwt-signature": "^2.1"
+                "web-token/jwt-signature": "^2.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^8.0"
             },
             "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "v1.0": "1.0.x-dev",
+                    "v1.1": "1.1.x-dev",
+                    "v1.2": "1.2.x-dev",
+                    "v1.3": "1.3.x-dev",
+                    "v2.0": "2.0.x-dev"
+                }
+            },
             "autoload": {
                 "psr-4": {
                     "Jose\\Component\\Signature\\Algorithm\\": ""
@@ -5902,7 +6143,7 @@
                 },
                 {
                     "name": "All contributors",
-                    "homepage": "https://github.com/web-token/jwt-framework/contributors"
+                    "homepage": "https://github.com/web-token/jwt-core/contributors"
                 }
             ],
             "description": "EdDSA Signature Algorithm the JWT Framework.",
@@ -5926,15 +6167,9 @@
                 "symfony"
             ],
             "support": {
-                "source": "https://github.com/web-token/jwt-signature-algorithm-eddsa/tree/v2.2.11"
+                "source": "https://github.com/web-token/jwt-signature-algorithm-eddsa/tree/v2.0"
             },
-            "funding": [
-                {
-                    "url": "https://www.patreon.com/FlorentMorselli",
-                    "type": "patreon"
-                }
-            ],
-            "time": "2021-01-21T19:18:03+00:00"
+            "time": "2019-06-22T12:34:09+00:00"
         },
         {
             "name": "web-token/jwt-signature-algorithm-experimental",
diff --git a/installation/sql/mysql/base.sql b/installation/sql/mysql/base.sql
index b76250873f39..8c195d21691c 100644
--- a/installation/sql/mysql/base.sql
+++ b/installation/sql/mysql/base.sql
@@ -165,7 +165,7 @@ INSERT INTO `#__extensions` (`package_id`, `name`, `type`, `element`, `folder`,
 (0, 'com_modules', 'component', 'com_modules', '', 1, 1, 1, 1, 1, '', '', ''),
 (0, 'com_newsfeeds', 'component', 'com_newsfeeds', '', 1, 1, 1, 0, 1, '', '{"newsfeed_layout":"_:default","save_history":"1","history_limit":5,"show_feed_image":"1","show_feed_description":"1","show_item_description":"1","feed_character_count":"0","feed_display_order":"des","float_first":"right","float_second":"right","show_tags":"1","category_layout":"_:default","show_category_title":"1","show_description":"1","show_description_image":"1","maxLevel":"-1","show_empty_categories":"0","show_subcat_desc":"1","show_cat_items":"1","show_cat_tags":"1","show_base_description":"1","maxLevelcat":"-1","show_empty_categories_cat":"0","show_subcat_desc_cat":"1","show_cat_items_cat":"1","filter_field":"1","show_pagination_limit":"1","show_headings":"1","show_articles":"0","show_link":"1","show_pagination":"1","show_pagination_results":"1","sef_ids":1}', ''),
 (0, 'com_plugins', 'component', 'com_plugins', '', 1, 1, 1, 1, 1, '', '', ''),
-(0, 'com_templates', 'component', 'com_templates', '', 1, 1, 1, 1, 1, '', '{"template_positions_display":"0","upload_limit":"10","image_formats":"gif,bmp,jpg,jpeg,png,webp","source_formats":"txt,less,ini,xml,js,php,css,scss,sass,json","font_formats":"woff,woff2,ttf,otf","compressed_formats":"zip"}', ''),
+(0, 'com_templates', 'component', 'com_templates', '', 1, 1, 1, 1, 1, '', '{"template_positions_display":"0","upload_limit":"10","image_formats":"gif,bmp,jpg,jpeg,png,webp","source_formats":"txt,less,ini,xml,js,php,css,scss,sass,json","font_formats":"woff,woff2,ttf,otf","compressed_formats":"zip","difference":"SideBySide"}', ''),
 (0, 'com_content', 'component', 'com_content', '', 1, 1, 0, 1, 1, '', '{"article_layout":"_:default","show_title":"1","link_titles":"1","show_intro":"1","info_block_position":"0","info_block_show_title":"1","show_category":"1","link_category":"1","show_parent_category":"0","link_parent_category":"0","show_associations":"0","flags":"1","show_author":"1","link_author":"0","show_create_date":"0","show_modify_date":"0","show_publish_date":"1","show_item_navigation":"1","show_readmore":"1","show_readmore_title":"1","readmore_limit":100,"show_tags":"1","record_hits":"1","show_hits":"1","show_noauth":"0","urls_position":0,"captcha":"","show_publishing_options":"1","show_article_options":"1","show_configure_edit_options":"1","show_permissions":"1","show_associations_edit":"1","save_history":"1","history_limit":10,"show_urls_images_frontend":"0","show_urls_images_backend":"1","targeta":0,"targetb":0,"targetc":0,"float_intro":"left","float_fulltext":"left","category_layout":"_:blog","show_category_title":"0","show_description":"0","show_description_image":"0","maxLevel":"1","show_empty_categories":"0","show_no_articles":"1","show_category_heading_title_text":"1","show_subcat_desc":"1","show_cat_num_articles":"0","show_cat_tags":"1","show_base_description":"1","maxLevelcat":"-1","show_empty_categories_cat":"0","show_subcat_desc_cat":"1","show_cat_num_articles_cat":"1","num_leading_articles":1,"blog_class_leading":"","num_intro_articles":4,"blog_class":"","num_columns":1,"multi_column_order":"0","num_links":4,"show_subcategory_content":"0","link_intro_image":"0","show_pagination_limit":"1","filter_field":"hide","show_headings":"1","list_show_date":"0","date_format":"","list_show_hits":"1","list_show_author":"1","display_num":"10","orderby_pri":"order","orderby_sec":"rdate","order_date":"published","show_pagination":"2","show_pagination_results":"1","show_featured":"show","show_feed_link":"1","feed_summary":"0","feed_show_readmore":"0","sef_ids":1,"custom_fields_enable":"1","workflow_enabled":"0"}', ''),
 (0, 'com_config', 'component', 'com_config', '', 1, 1, 0, 1, 1, '', '{"filters":{"1":{"filter_type":"NH","filter_tags":"","filter_attributes":""},"9":{"filter_type":"NH","filter_tags":"","filter_attributes":""},"6":{"filter_type":"BL","filter_tags":"","filter_attributes":""},"7":{"filter_type":"BL","filter_tags":"","filter_attributes":""},"2":{"filter_type":"NH","filter_tags":"","filter_attributes":""},"3":{"filter_type":"BL","filter_tags":"","filter_attributes":""},"4":{"filter_type":"BL","filter_tags":"","filter_attributes":""},"5":{"filter_type":"BL","filter_tags":"","filter_attributes":""},"8":{"filter_type":"NONE","filter_tags":"","filter_attributes":""}}}', ''),
 (0, 'com_redirect', 'component', 'com_redirect', '', 1, 1, 0, 0, 1, '', '', ''),
diff --git a/installation/sql/postgresql/base.sql b/installation/sql/postgresql/base.sql
index 418cb533bad6..6fb2ae5c7550 100644
--- a/installation/sql/postgresql/base.sql
+++ b/installation/sql/postgresql/base.sql
@@ -171,7 +171,7 @@ INSERT INTO "#__extensions" ("package_id", "name", "type", "element", "folder",
 (0, 'com_modules', 'component', 'com_modules', '', 1, 1, 1, 1, 1, '', '', '', 0, 0),
 (0, 'com_newsfeeds', 'component', 'com_newsfeeds', '', 1, 1, 1, 0, 1, '', '{"newsfeed_layout":"_:default","save_history":"1","history_limit":5,"show_feed_image":"1","show_feed_description":"1","show_item_description":"1","feed_character_count":"0","feed_display_order":"des","float_first":"right","float_second":"right","show_tags":"1","category_layout":"_:default","show_category_title":"1","show_description":"1","show_description_image":"1","maxLevel":"-1","show_empty_categories":"0","show_subcat_desc":"1","show_cat_items":"1","show_cat_tags":"1","show_base_description":"1","maxLevelcat":"-1","show_empty_categories_cat":"0","show_subcat_desc_cat":"1","show_cat_items_cat":"1","filter_field":"1","show_pagination_limit":"1","show_headings":"1","show_articles":"0","show_link":"1","show_pagination":"1","show_pagination_results":"1","sef_ids":1}', '', 0, 0),
 (0, 'com_plugins', 'component', 'com_plugins', '', 1, 1, 1, 1, 1, '', '', '', 0, 0),
-(0, 'com_templates', 'component', 'com_templates', '', 1, 1, 1, 1, 1, '', '{"template_positions_display":"0","upload_limit":"10","image_formats":"gif,bmp,jpg,jpeg,png,webp","source_formats":"txt,less,ini,xml,js,php,css,scss,sass,json","font_formats":"woff,woff2,ttf,otf","compressed_formats":"zip"}', '', 0, 0),
+(0, 'com_templates', 'component', 'com_templates', '', 1, 1, 1, 1, 1, '', '{"template_positions_display":"0","upload_limit":"10","image_formats":"gif,bmp,jpg,jpeg,png,webp","source_formats":"txt,less,ini,xml,js,php,css,scss,sass,json","font_formats":"woff,woff2,ttf,otf","compressed_formats":"zip","difference":"SideBySide"}', '', 0, 0),
 (0, 'com_content', 'component', 'com_content', '', 1, 1, 0, 1, 1, '', '{"article_layout":"_:default","show_title":"1","link_titles":"1","show_intro":"1","info_block_position":"0","info_block_show_title":"1","show_category":"1","link_category":"1","show_parent_category":"0","link_parent_category":"0","show_associations":"0","flags":"1","show_author":"1","link_author":"0","show_create_date":"0","show_modify_date":"0","show_publish_date":"1","show_item_navigation":"1","show_readmore":"1","show_readmore_title":"1","readmore_limit":100,"show_tags":"1","record_hits":"1","show_hits":"1","show_noauth":"0","urls_position":0,"captcha":"","show_publishing_options":"1","show_article_options":"1","show_configure_edit_options":"1","show_permissions":"1","show_associations_edit":"1","save_history":"1","history_limit":10,"show_urls_images_frontend":"0","show_urls_images_backend":"1","targeta":0,"targetb":0,"targetc":0,"float_intro":"left","float_fulltext":"left","category_layout":"_:blog","show_category_title":"0","show_description":"0","show_description_image":"0","maxLevel":"1","show_empty_categories":"0","show_no_articles":"1","show_category_heading_title_text":"1","show_subcat_desc":"1","show_cat_num_articles":"0","show_cat_tags":"1","show_base_description":"1","maxLevelcat":"-1","show_empty_categories_cat":"0","show_subcat_desc_cat":"1","show_cat_num_articles_cat":"1","num_leading_articles":1,"blog_class_leading":"","num_intro_articles":4,"blog_class":"","num_columns":1,"multi_column_order":"0","num_links":4,"show_subcategory_content":"0","link_intro_image":"0","show_pagination_limit":"1","filter_field":"hide","show_headings":"1","list_show_date":"0","date_format":"","list_show_hits":"1","list_show_author":"1","display_num":"10","orderby_pri":"order","orderby_sec":"rdate","order_date":"published","show_pagination":"2","show_pagination_results":"1","show_featured":"show","show_feed_link":"1","feed_summary":"0","feed_show_readmore":"0","sef_ids":1,"custom_fields_enable":"1","workflow_enabled":"0"}', '', 0, 0),
 (0, 'com_config', 'component', 'com_config', '', 1, 1, 0, 1, 1, '', '{"filters":{"1":{"filter_type":"NH","filter_tags":"","filter_attributes":""},"9":{"filter_type":"NH","filter_tags":"","filter_attributes":""},"6":{"filter_type":"BL","filter_tags":"","filter_attributes":""},"7":{"filter_type":"BL","filter_tags":"","filter_attributes":""},"2":{"filter_type":"NH","filter_tags":"","filter_attributes":""},"3":{"filter_type":"BL","filter_tags":"","filter_attributes":""},"4":{"filter_type":"BL","filter_tags":"","filter_attributes":""},"5":{"filter_type":"BL","filter_tags":"","filter_attributes":""},"8":{"filter_type":"NONE","filter_tags":"","filter_attributes":""}}}', '', 0, 0),
 (0, 'com_redirect', 'component', 'com_redirect', '', 1, 1, 0, 0, 1, '', '', '', 0, 0),
diff --git a/libraries/src/Version.php b/libraries/src/Version.php
index b23d9324d976..db9d74308186 100644
--- a/libraries/src/Version.php
+++ b/libraries/src/Version.php
@@ -66,7 +66,7 @@ final class Version
      * @var    string
      * @since  3.8.0
      */
-    public const EXTRA_VERSION = 'dev';
+    public const EXTRA_VERSION = 'rc2-dev';
 
     /**
      * Development status.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment