Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .github/workflows/dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,20 @@ jobs:
uses: actions/[email protected]

- name: Prepare - Setup dotnet
id: dotnet
uses: actions/[email protected]
with:
dotnet-version: 8.0.x

# Note: Unless a concrete version is specified in the `global.json` file,
# the latest .NET version installed on the runner (including preinstalled
# versions) will be used by default. To control this behavior, you may want
# to use temporary `global.json` files.
# https://github.com/actions/setup-dotnet/blob/main/README.md#matrix-testing
- name: Create `global.json`
run: |
echo '{"sdk":{"version": "${{ steps.dotnet.outputs.dotnet-version }}"}}' > ./global.json

- name: Test - TestContainers
run: dotnet test backend/Squidex.sln --filter Category=TestContainer

Expand Down
13 changes: 13 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,23 @@ jobs:
uses: actions/[email protected]

- name: Prepare - Setup dotnet
id: dotnet
uses: actions/[email protected]
with:
dotnet-version: 8.0.x

# Note: Unless a concrete version is specified in the `global.json` file,
# the latest .NET version installed on the runner (including preinstalled
# versions) will be used by default. To control this behavior, you may want
# to use temporary `global.json` files.
# https://github.com/actions/setup-dotnet/blob/main/README.md#matrix-testing
- name: Create `global.json`
run: |
echo '{"sdk":{"version": "${{ steps.dotnet.outputs.dotnet-version }}"}}' > ./global.json

- name: Test - TestContainers
run: dotnet test backend/Squidex.sln --filter Category=TestContainer

- name: Test - TestContainers
run: dotnet test backend/Squidex.sln --filter Category=TestContainer

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace Squidex.Extensions.Text.ElasticSearch;

public sealed class ElasticSearchClient : IElasticSearchClient
{
private readonly IElasticLowLevelClient elasticSearch;
private readonly ElasticLowLevelClient elasticSearch;

public ElasticSearchClient(string configurationString)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,13 @@
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql.Json.Microsoft" Version="8.0.3" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql.NetTopologySuite" Version="8.0.3" />
<PackageReference Include="RefactoringEssentials" Version="5.6.0" PrivateAssets="all" />
<PackageReference Include="Squidex.AI.EntityFramework" Version="7.30.0" />
<PackageReference Include="Squidex.Assets.EntityFramework" Version="7.30.0" />
<PackageReference Include="Squidex.Assets.TusAdapter" Version="7.30.0" />
<PackageReference Include="Squidex.Events.EntityFramework" Version="7.30.0" />
<PackageReference Include="Squidex.Flows.EntityFramework" Version="7.30.0" />
<PackageReference Include="Squidex.Hosting" Version="7.30.0" />
<PackageReference Include="Squidex.Messaging.EntityFramework" Version="7.30.0" />
<PackageReference Include="Squidex.AI.EntityFramework" Version="7.33.0" />
<PackageReference Include="Squidex.Assets.EntityFramework" Version="7.33.0" />
<PackageReference Include="Squidex.Assets.TusAdapter" Version="7.33.0" />
<PackageReference Include="Squidex.Events.EntityFramework" Version="7.33.0" />
<PackageReference Include="Squidex.Flows.EntityFramework" Version="7.33.0" />
<PackageReference Include="Squidex.Hosting" Version="7.33.0" />
<PackageReference Include="Squidex.Messaging.EntityFramework" Version="7.33.0" />
<PackageReference Include="Squidex.OpenIdDict.EntityFramework" Version="5.8.4" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="all" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,7 @@ public async Task InitializeAsync(
{
var databaseName = Database.DatabaseNamespace.DatabaseName;

var error = new ConfigurationError($"MongoDb connection failed to connect to database {databaseName}.");

var error = new ConfigurationError($"MongoDb connection failed to connect to database {databaseName}: {ex.Message}.");
throw new ConfigurationException(error, ex);
}
}
Expand Down
12 changes: 6 additions & 6 deletions backend/src/Squidex.Data.MongoDb/Squidex.Data.MongoDb.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@
<PackageReference Include="MongoDB.Driver.GridFS" Version="2.30.0" />
<PackageReference Include="NodaTime.Serialization.SystemTextJson" Version="1.3.0" />
<PackageReference Include="RefactoringEssentials" Version="5.6.0" PrivateAssets="all" />
<PackageReference Include="Squidex.AI.Mongo" Version="7.30.0" />
<PackageReference Include="Squidex.Assets.Mongo" Version="7.30.0" />
<PackageReference Include="Squidex.Events.Mongo" Version="7.30.0" />
<PackageReference Include="Squidex.Flows.Mongo" Version="7.30.0" />
<PackageReference Include="Squidex.Hosting" Version="7.30.0" />
<PackageReference Include="Squidex.Messaging.Mongo" Version="7.30.0" />
<PackageReference Include="Squidex.AI.Mongo" Version="7.33.0" />
<PackageReference Include="Squidex.Assets.Mongo" Version="7.33.0" />
<PackageReference Include="Squidex.Events.Mongo" Version="7.33.0" />
<PackageReference Include="Squidex.Flows.Mongo" Version="7.33.0" />
<PackageReference Include="Squidex.Hosting" Version="7.33.0" />
<PackageReference Include="Squidex.Messaging.Mongo" Version="7.33.0" />
<PackageReference Include="Squidex.OpenIddict.MongoDb" Version="5.8.4" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="all" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,6 @@ namespace Squidex.Domain.Apps.Core.Contents;

public static class RichTextExtensions
{
public static bool TryGetEnum<T>(this JsonValue value, out T enumValue) where T : struct
{
enumValue = default;

return value.Value is string text && Enum.TryParse(text, true, out enumValue);
}

public static int GetIntAttr(this JsonObject? attrs, string name, int defaultValue = 0)
{
if (attrs?.TryGetValue(name, out var value) == true && value.Value is double attr)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,10 @@ internal sealed class RichTextMark : IMark
{
private JsonObject? attrs;

public MarkType Type { get; private set; }
public string Type { get; private set; } = string.Empty;

public bool TryUse(JsonValue source)
public bool TryUse(JsonValue source, RichTextOptions options)
{
Type = MarkType.Undefined;

attrs = null;

if (source.Value is not JsonObject obj)
Expand All @@ -32,7 +30,7 @@ public bool TryUse(JsonValue source)
{
switch (key)
{
case "type" when value.TryGetEnum<MarkType>(out var type):
case "type" when value.Value is string type && options.IsSupportedMarkType(type):
Type = type;
break;
case "attrs" when value.Value is JsonObject attrs:
Expand All @@ -41,8 +39,7 @@ public bool TryUse(JsonValue source)
}
}

isValid &= Type != MarkType.Undefined;

isValid &= !string.IsNullOrWhiteSpace(Type);
return isValid;
}

Expand Down
34 changes: 16 additions & 18 deletions backend/src/Squidex.Domain.Apps.Core.Model/Contents/RichTextNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@ public sealed class RichTextNode : INode
internal struct State
{
public JsonObject? Root;
public NodeType Type;
public string Type;
public JsonArray? Marks;
public JsonObject? Attrs;
public JsonArray? Content;
public string? Text;
public int MarkIndex;
}

public NodeType Type
public string Type
{
get => currentState.Type;
}
Expand All @@ -43,11 +43,11 @@ public string? Text
get => currentState.Text;
}

public static bool TryCreate(JsonValue source, out RichTextNode node)
public static bool TryCreate(JsonValue source, RichTextOptions options, out RichTextNode node)
{
var candidate = new RichTextNode();

if (candidate.TryUse(source, true))
if (candidate.TryUse(source, true, options))
{
node = candidate;
return true;
Expand All @@ -57,17 +57,17 @@ public static bool TryCreate(JsonValue source, out RichTextNode node)
return false;
}

public static RichTextNode Create(JsonValue source)
public static RichTextNode Create(JsonValue source, RichTextOptions options)
{
var node = new RichTextNode();

// We assume that we have made the validation before.
node.TryUse(source, false);
node.TryUse(source, false, options);

return node;
}

public bool TryUse(JsonValue source, bool recursive = false)
public bool TryUse(JsonValue source, bool recursive, RichTextOptions options)
{
State state = default;

Expand All @@ -84,7 +84,7 @@ public bool TryUse(JsonValue source, bool recursive = false)
{
switch (key)
{
case "type" when value.TryGetEnum<NodeType>(out var type):
case "type" when value.Value is string type && options.IsSupportedNodeType(type):
state.Type = type;
break;
case "attrs" when value.Value is JsonObject attrs:
Expand All @@ -103,17 +103,16 @@ public bool TryUse(JsonValue source, bool recursive = false)
}

currentState = state;

isValid &= Type != NodeType.Undefined;
isValid &= !string.IsNullOrWhiteSpace(Type);

if (isValid && recursive)
{
if (state.Content != null)
{
foreach (var content in state.Content)
foreach (var contentObj in state.Content)
{
// We have already validated this before.
isValid &= TryUse((JsonObject)content.Value!, recursive);
isValid &= TryUse((JsonObject)contentObj.Value!, recursive, options);
}
}

Expand All @@ -122,13 +121,12 @@ public bool TryUse(JsonValue source, bool recursive = false)
foreach (var markObj in state.Marks)
{
// We have already validated this before.
isValid &= mark.TryUse((JsonObject)markObj.Value!);
isValid &= mark.TryUse((JsonObject)markObj.Value!, options);
}
}
}

currentState = state;

return isValid;
}

Expand All @@ -142,19 +140,19 @@ public string GetStringAttr(string name, string defaultValue = "")
return currentState.Attrs.GetStringAttr(name, defaultValue);
}

public IMark? GetNextMark()
public IMark? GetNextMark(RichTextOptions options)
{
if (currentState.Marks == null || currentState.MarkIndex >= currentState.Marks.Count)
{
return null;
}

// We have already validated this before.
mark.TryUse((JsonObject)currentState.Marks[currentState.MarkIndex++].Value!);
mark.TryUse((JsonObject)currentState.Marks[currentState.MarkIndex++].Value!, options);
return mark;
}

public void IterateContent<T>(T state, Action<INode, T, bool, bool> action)
public void IterateContent<T>(T state, RichTextOptions options, Action<INode, T, bool, bool> action)
{
var prevState = currentState;

Expand All @@ -170,7 +168,7 @@ public void IterateContent<T>(T state, Action<INode, T, bool, bool> action)
var isLast = i == prevState.Content.Count - 1;

// We have already validated this before.
TryUse((JsonObject)item.Value!, false);
TryUse((JsonObject)item.Value!, false, options);
action(this, state, isFirst, isLast);
i++;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================

using Squidex.Text.RichText.Model;

namespace Squidex.Domain.Apps.Core.Contents;

public static class SquidexRichText
{
public static class NodeTypes
{
public const string ContentLink = "contentLink";
}

private class ExtendedOptions : RichTextOptions
{
public override bool IsSupportedMarkType(string type)
{
return base.IsSupportedMarkType(type) || IsExtension(type);
}

public override bool IsSupportedNodeType(string type)
{
return base.IsSupportedNodeType(type) || IsExtension(type);
}

private static bool IsExtension(string type)
{
return type.StartsWith("x-", StringComparison.OrdinalIgnoreCase);
}
}

public static readonly RichTextOptions Options = new ExtendedOptions
{
NodeTypes =
[
..RichTextOptions.Default.NodeTypes,
NodeTypes.ContentLink,
],
MarkTypes = RichTextOptions.Default.MarkTypes,
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<PackageReference Include="NetTopologySuite" Version="2.5.0" />
<PackageReference Include="NodaTime.Serialization.SystemTextJson" Version="1.3.0" />
<PackageReference Include="RefactoringEssentials" Version="5.6.0" PrivateAssets="all" />
<PackageReference Include="Squidex.Flows" Version="7.30.0" />
<PackageReference Include="Squidex.Flows" Version="7.33.0" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="all" />
<PackageReference Include="System.Collections.Immutable" Version="8.0.0" />
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ public string Visit(ReferencesFieldProperties properties, Args args)

public string Visit(RichTextFieldProperties properties, Args args)
{
return RichTextNode.Create(args.Value).ToText(100);
return RichTextNode.Create(args.Value, SquidexRichText.Options).ToText(100);
}

public string Visit(StringFieldProperties properties, Args args)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
// ==========================================================================

using System.Text.RegularExpressions;
using Squidex.Domain.Apps.Core.Contents;
using Squidex.Infrastructure;
using Squidex.Text.RichText.Model;

Expand Down Expand Up @@ -81,7 +82,7 @@ static void Visit(INode node, List<DomainId> result, List<Regex> patterns)
if (node.Type == NodeType.Text)
{
IMark? mark = null;
while ((mark = node.GetNextMark()) != null)
while ((mark = node.GetNextMark(SquidexRichText.Options)) != null)
{
if (mark.Type == MarkType.Link)
{
Expand All @@ -91,8 +92,19 @@ static void Visit(INode node, List<DomainId> result, List<Regex> patterns)
}
}
}
else if (node.Type == SquidexRichText.NodeTypes.ContentLink)
{
var contentId = node.GetStringAttr("contentId");
if (!string.IsNullOrWhiteSpace(contentId))
{
result.Add(DomainId.Create(contentId));
}
}

node.IterateContent((result, patterns), static (node, s, _, _) => Visit(node, s.result, s.patterns));
node.IterateContent(
(result, patterns),
SquidexRichText.Options,
static (node, s, _, _) => Visit(node, s.result, s.patterns));
}

Visit(node, result, contentsPatterns);
Expand All @@ -117,7 +129,10 @@ static void Visit(INode node, List<DomainId> result, List<Regex> patterns)
result.AddRange(GetEmbeddedIds(src, patterns));
}

node.IterateContent((result, patterns), static (node, s, _, _) => Visit(node, s.result, s.patterns));
node.IterateContent(
(result, patterns),
SquidexRichText.Options,
static (node, s, _, _) => Visit(node, s.result, s.patterns));
}

Visit(node, result, assetsPatterns);
Expand Down
Loading
Loading