Merge branch 'v13/dev' into release/13.6

This commit is contained in:
Jacob Overgaard
2024-12-13 10:07:46 +01:00
17 changed files with 8063 additions and 25 deletions

View File

@@ -8,7 +8,7 @@ namespace Umbraco.Cms.Core.Configuration.Models;
public class RichTextEditorSettings
{
internal const string StaticValidElements =
"+a[id|style|rel|data-id|data-udi|rev|charset|hreflang|dir|lang|tabindex|accesskey|type|name|href|target|title|class|onfocus|onblur|onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup],-strong/-b[class|style],-em/-i[class|style],-strike[class|style],-s[class|style],-u[class|style],#p[id|style|dir|class|align],-ol[class|reversed|start|style|type],-ul[class|style],-li[class|style],br[class],img[id|dir|lang|longdesc|usemap|style|class|src|onmouseover|onmouseout|border|alt=|title|hspace|vspace|width|height|align|umbracoorgwidth|umbracoorgheight|onresize|onresizestart|onresizeend|rel|data-id],-sub[style|class],-sup[style|class],-blockquote[dir|style|class],-table[border=0|cellspacing|cellpadding|width|height|class|align|summary|style|dir|id|lang|bgcolor|background|bordercolor],-tr[id|lang|dir|class|rowspan|width|height|align|valign|style|bgcolor|background|bordercolor],tbody[id|class],thead[id|class],tfoot[id|class],#td[id|lang|dir|class|colspan|rowspan|width|height|align|valign|style|bgcolor|background|bordercolor|scope],-th[id|lang|dir|class|colspan|rowspan|width|height|align|valign|style|scope],caption[id|lang|dir|class|style],-div[id|dir|class|align|style],-span[class|align|style],-pre[class|align|style],address[class|align|style],-h1[id|dir|class|align|style],-h2[id|dir|class|align|style],-h3[id|dir|class|align|style],-h4[id|dir|class|align|style],-h5[id|dir|class|align|style],-h6[id|style|dir|class|align|style],hr[class|style],small[class|style],dd[id|class|title|style|dir|lang],dl[id|class|title|style|dir|lang],dt[id|class|title|style|dir|lang],object[class|id|width|height|codebase|*],param[name|value|_value|class],embed[type|width|height|src|class|*],map[name|class],area[shape|coords|href|alt|target|class],bdo[class],button[class],iframe[*],figure,figcaption,cite,video[*],audio[*],picture[*],source[*],canvas[*]";
"+a[id|style|rel|data-id|data-udi|rev|charset|hreflang|dir|lang|tabindex|accesskey|type|name|href|target|title|class|onfocus|onblur|onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup],-strong/-b[class|style],-em/-i[class|style],-strike[class|style],-s[class|style],-u[class|style],#p[id|style|dir|class|align],-ol[class|reversed|start|style|type],-ul[class|style],-li[class|style],br[class],img[id|dir|lang|longdesc|usemap|style|class|src|onmouseover|onmouseout|border|alt=|title|hspace|vspace|width|height|align|umbracoorgwidth|umbracoorgheight|onresize|onresizestart|onresizeend|rel|data-id],-sub[style|class],-sup[style|class],-blockquote[dir|style|class],-table[border=0|cellspacing|cellpadding|width|height|class|align|summary|style|dir|id|lang|bgcolor|background|bordercolor],-tr[id|lang|dir|class|rowspan|width|height|align|valign|style|bgcolor|background|bordercolor],tbody[id|class],thead[id|class],tfoot[id|class],#td[id|lang|dir|class|colspan|rowspan|width|height|align|valign|style|bgcolor|background|bordercolor|scope],-th[id|lang|dir|class|colspan|rowspan|width|height|align|valign|style|scope],caption[id|lang|dir|class|style],-div[id|dir|class|align|style],-span[class|align|style],-pre[class|align|style],address[class|align|style],-h1[id|dir|class|align|style],-h2[id|dir|class|align|style],-h3[id|dir|class|align|style],-h4[id|dir|class|align|style],-h5[id|dir|class|align|style],-h6[id|style|dir|class|align|style],hr[class|style],small[class|style],dd[id|class|title|style|dir|lang],dl[id|class|title|style|dir|lang],dt[id|class|title|style|dir|lang],object[class|id|width|height|codebase|*],param[name|value|_value|class],embed[type|width|height|src|class|*],map[name|class],area[shape|coords|href|alt|target|class],bdo[class],button[class],iframe[*],figure,figcaption,cite,video[*],audio[*],picture[*],source[*],canvas[*],code";
internal const string StaticInvalidElements = "font";

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -330,7 +330,10 @@ public static class ClaimsIdentityExtensions
var firstValue = identity.FindFirstValue(ClaimTypes.NameIdentifier);
if (firstValue is not null)
{
return int.Parse(firstValue, CultureInfo.InvariantCulture);
if (int.TryParse(firstValue, CultureInfo.InvariantCulture, out var id))
{
return id;
}
}
return null;

View File

@@ -187,8 +187,7 @@ public class ExamineIndexRebuilder : IIndexRebuilder
{
// If an index exists but it has zero docs we'll consider it empty and rebuild
IIndex[] indexes = (onlyEmptyIndexes
? _examineManager.Indexes.Where(x =>
!x.IndexExists() || (x is IIndexStats stats && stats.GetDocumentCount() == 0))
? _examineManager.Indexes.Where(ShouldRebuild)
: _examineManager.Indexes).ToArray();
if (indexes.Length == 0)
@@ -228,4 +227,17 @@ public class ExamineIndexRebuilder : IIndexRebuilder
}
}
}
private bool ShouldRebuild(IIndex index)
{
try
{
return !index.IndexExists() || (index is IIndexStats stats && stats.GetDocumentCount() == 0);
}
catch (Exception e)
{
_logger.LogError(e, "An error occured trying to get determine index shouldRebuild status for index {IndexName}. The index will NOT be considered for rebuilding", index.Name);
return false;
}
}
}

View File

@@ -205,7 +205,7 @@ public class ExamineManagementController : UmbracoAuthorizedJsonController
documentCount = indexDiag.GetDocumentCount();
fieldCount = indexDiag.GetFieldNames().Count();
}
catch (FileNotFoundException ex)
catch (Exception ex)
{
// Safe catch that will allow to rebuild a corrupted index
documentCount = 0;

View File

@@ -93,7 +93,7 @@ Use this directive to render a button with a dropdown of alternative actions.
function ButtonGroupDirective() {
function controller($scope) {
function controller($scope, localizationService) {
$scope.toggleStyle = null;
$scope.blockElement = false;
@@ -121,6 +121,31 @@ Use this directive to render a button with a dropdown of alternative actions.
}
}
}
// As the <localize /> directive doesn't support Angular expressions as fallback, we instead listen for changes
// to the label key of the default button, and if detected, we update the button label with the localized value
// received from the localization service
$scope.$watch("defaultButton.labelKey", function () {
if (!$scope.defaultButton.labelKey) return;
localizationService.localize($scope.defaultButton.labelKey).then(value => {
if (value && value.indexOf("[") === 0) return;
$scope.defaultButton.label = value;
});
});
// In a similar way, we must listen for changes to the sub buttons (or their label keys), and if detected, update
// the label with the localized value received from the localization service
$scope.$watch("defaultButton.subButtons", function () {
if (!Array.isArray($scope.subButtons)) return;
$scope.subButtons.forEach(function (sub) {
if (!sub.labelKey) return;
localizationService.localize(sub.labelKey).then(value => {
if (value && value.indexOf("[") === 0) return;
sub.label = value;
});
});
}, true);
}
function link(scope) {

View File

@@ -513,7 +513,7 @@
init();
//needs to be manually set for infinite editing mode
$scope.page.isNew = false;
$scope.isNew = false;
syncTreeNode($scope.content, data.path, false, args.reloadChildren);

View File

@@ -11,8 +11,8 @@ angular.module("umbraco.filters").filter('simpleMarkdown', function () {
}
return text
.replace(/\*\*(.*)\*\*/gim, '<b>$1</b>')
.replace(/\*(.*)\*/gim, '<i>$1</i>')
.replace(/\*\*(.+?)\*\*/gim, '<b>$1</b>')
.replace(/\*(.+?)\*/gim, '<i>$1</i>')
.replace(/!\[(.*?)\]\((.*?)\)/gim, "<img alt='$1' src='$2' />")
.replace(/\[(.*?)\]\((.*?)\)/gim, "<a href='$2' target='_blank' rel='noopener' class='underline'>$1</a>")
.replace(/\n/g, '<br />').trim();

View File

@@ -11,8 +11,8 @@ angular.module("umbraco.filters").filter('simpleMarkdown', function () {
}
return text
.replace(/\*\*(.*)\*\*/gim, '<b>$1</b>')
.replace(/\*(.*)\*/gim, '<i>$1</i>')
.replace(/\*\*(.+?)\*\*/gim, '<b>$1</b>')
.replace(/\*(.+?)\*/gim, '<i>$1</i>')
.replace(/!\[(.*?)\]\((.*?)\)/gim, "<img alt='$1' src='$2' />")
.replace(/\[(.*?)\]\((.*?)\)/gim, "<a href='$2' target='_blank' class='underline'>$1</a>")
.replace(/\n/g, '<br />').trim();

View File

@@ -37,6 +37,7 @@
.umb-media-entry-editor__crops {
background-color: white;
overflow: auto;
flex-shrink: 0;
> button {
display: flex;

View File

@@ -8,7 +8,7 @@
href-target="{{defaultButton.hrefTarget}}"
button-style="{{buttonStyle}}"
state="state"
label="{{defaultButton.labelKey}}"
label="{{defaultButton.label}}"
label-key="{{defaultButton.labelKey}}"
shortcut="{{defaultButton.hotKey}}"
shortcut-when-hidden="{{defaultButton.hotKeyWhenHidden}}"
@@ -29,7 +29,7 @@
ng-disabled="disabled">
<span class="caret">
<span class="sr-only">
<localize key="{{labelKey}}">{{label}}</localize>
{{defaultButton.label}}
</span>
</span>
</button>
@@ -48,8 +48,7 @@
hotkey="{{subButton.hotKey}}"
hotkey-when-hidden="{{subButton.hotKeyWhenHidden}}"
ng-disabled="disabled">
<localize ng-if="subButton.labelKey" key="{{subButton.labelKey}}">{{subButton.labelKey}}</localize>
<span ng-if="subButton.label">{{subButton.label}}</span>
<span>{{subButton.label}}</span>
<span ng-if="subButton.addEllipsis === 'true'">...</span>
</button>
</umb-dropdown-item>

View File

@@ -77,7 +77,7 @@
vm.elementTypes = elementTypes;
vm.contentPreview = vm.getElementTypeByKey(vm.block.contentElementTypeKey);
vm.settingsPreview = vm.getElementTypeByKey(vm.block.settingsElementTypeKey);
vm.settingsPreview = vm.getElementTypeByKey(vm.block.settingsElementTypeKey) || { icon: "icon-science", name: "(Unavailable ElementType)" };
});
}
@@ -170,7 +170,7 @@
vm.requestRemoveSettingsForBlock = function(block) {
localizationService.localizeMany(["general_remove", "defaultdialogs_confirmremoveusageof"]).then(function (data) {
var settingsElementType = vm.getElementTypeByKey(block.settingsElementTypeKey);
const settingsElementType = vm.getElementTypeByKey(block.settingsElementTypeKey);
overlayService.confirmRemove({
title: data[0],

View File

@@ -41,7 +41,11 @@
<label class="control-label"><localize key="blockEditor_labelContentElementType">Content ElementType</localize></label>
<div class="controls">
<div class="__settings-input --hasValue" ng-if="vm.block.contentElementTypeKey !== null" >
<umb-node-preview icon="vm.contentPreview.icon" name="vm.contentPreview.name" alias="vm.contentPreview.alias"></umb-node-preview>
<umb-node-preview
icon="vm.contentPreview.icon"
name="vm.contentPreview.name"
alias="vm.contentPreview.alias">
</umb-node-preview>
<div class="__control-actions">
<button type="button" class="btn-reset __control-actions-btn --open umb-outline" ng-click="vm.openElementType(vm.block.contentElementTypeKey)">
<umb-icon icon="icon-edit" class="icon"></umb-icon>
@@ -58,9 +62,13 @@
<label class="control-label"><localize key="blockEditor_labelSettingsElementType">Settings Element Type</localize></label>
<div class="controls">
<div class="__settings-input --hasValue" ng-if="vm.block.settingsElementTypeKey !== null">
<umb-node-preview icon="vm.settingsPreview.icon" name="vm.settingsPreview.name" alias="vm.settingsPreview.alias"></umb-node-preview>
<umb-node-preview
icon="vm.settingsPreview.icon"
name="vm.settingsPreview.name"
alias="vm.settingsPreview.alias">
</umb-node-preview>
<div class="__control-actions">
<button type="button" class="btn-reset __control-actions-btn --open umb-outline" ng-click="vm.openElementType(vm.block.settingsElementTypeKey)">
<button type="button" class="btn-reset __control-actions-btn --open umb-outline" ng-click="vm.openElementType(vm.block.settingsElementTypeKey)" ng-if="vm.settingsPreview && vm.settingsPreview.alias">
<umb-icon icon="icon-edit" class="icon"></umb-icon>
</button>
<button type="button" class="btn-reset __control-actions-btn --remove umb-outline" ng-click="vm.requestRemoveSettingsForBlock(vm.block)">

View File

@@ -30,7 +30,7 @@
vm.elementTypes = elementTypes;
vm.contentPreview = vm.getElementTypeByKey(vm.block.contentElementTypeKey);
vm.settingsPreview = vm.getElementTypeByKey(vm.block.settingsElementTypeKey);
vm.settingsPreview = vm.getElementTypeByKey(vm.block.settingsElementTypeKey) || { icon: "icon-science", name: "(Unavailable ElementType)" };
});
}
@@ -123,7 +123,7 @@
vm.requestRemoveSettingsForBlock = function(block) {
localizationService.localizeMany(["general_remove", "defaultdialogs_confirmremoveusageof"]).then(function (data) {
var settingsElementType = vm.getElementTypeByKey(block.settingsElementTypeKey);
const settingsElementType = vm.getElementTypeByKey(block.settingsElementTypeKey);
overlayService.confirmRemove({
title: data[0],

View File

@@ -110,7 +110,11 @@
<label class="control-label" for="blockContentElemenType"><localize key="blockEditor_labelContentElementType">Content ElementType</localize></label>
<div class="controls">
<div class="__settings-input --hasValue" ng-if="vm.block.contentElementTypeKey !== null" >
<umb-node-preview icon="vm.contentPreview.icon" name="vm.contentPreview.name" alias="vm.contentPreview.alias"></umb-node-preview>
<umb-node-preview
icon="vm.contentPreview.icon"
name="vm.contentPreview.name"
alias="vm.contentPreview.alias">
</umb-node-preview>
<div class="__control-actions">
<button type="button" id="blockContentElemenType" class="btn-reset __control-actions-btn --open umb-outline" ng-click="vm.openElementType(vm.block.contentElementTypeKey)">
<umb-icon icon="icon-edit" class="icon"></umb-icon>
@@ -127,9 +131,13 @@
<label class="control-label" for="blockSettingsElemenType"><localize key="blockEditor_labelSettingsElementType">Settings Element Type</localize></label>
<div class="controls">
<div class="__settings-input --hasValue" ng-if="vm.block.settingsElementTypeKey !== null">
<umb-node-preview icon="vm.settingsPreview.icon" name="vm.settingsPreview.name" alias="vm.settingsPreview.alias"></umb-node-preview>
<umb-node-preview
icon="vm.settingsPreview.icon"
name="vm.settingsPreview.name"
alias="vm.settingsPreview.alias">
</umb-node-preview>
<div class="__control-actions">
<button type="button" class="btn-reset __control-actions-btn --open umb-outline" ng-click="vm.openElementType(vm.block.settingsElementTypeKey)">
<button type="button" class="btn-reset __control-actions-btn --open umb-outline" ng-click="vm.openElementType(vm.block.settingsElementTypeKey)" ng-if="vm.settingsPreview && vm.settingsPreview.alias">
<umb-icon icon="icon-edit" class="icon"></umb-icon>
</button>
<button type="button" class="btn-reset __control-actions-btn --remove umb-outline" ng-click="vm.requestRemoveSettingsForBlock(vm.block)">