Browse Source

Scripting extensions.

pull/544/head
Sebastian 6 years ago
parent
commit
93607b03ae
  1. 105
      backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/Extensions/StringJintExtension.cs
  2. 77
      backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/Extensions/StringWordsJintExtension.cs
  3. 2
      backend/src/Squidex.Domain.Apps.Core.Operations/Squidex.Domain.Apps.Core.Operations.csproj
  4. 3
      backend/src/Squidex/Config/Domain/InfrastructureServices.cs
  5. 3
      backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleEventFormatterCompareTests.cs
  6. 3
      backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleEventFormatterTests.cs
  7. 71
      backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/Scripting/JintScriptEngineHelperTests.cs
  8. 3
      backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/Scripting/JintScriptEngineTests.cs

105
backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/Extensions/StringJintExtension.cs

@ -6,8 +6,12 @@
// ========================================================================== // ==========================================================================
using System; using System;
using System.IO;
using System.Text;
using HtmlAgilityPack;
using Jint; using Jint;
using Jint.Native; using Jint.Native;
using Markdig;
using Squidex.Infrastructure; using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Core.Scripting.Extensions namespace Squidex.Domain.Apps.Core.Scripting.Extensions
@ -52,12 +56,113 @@ namespace Squidex.Domain.Apps.Core.Scripting.Extensions
} }
}; };
private readonly Func<string, JsValue> html2Text = text =>
{
try
{
var document = LoadHtml(text);
var sb = new StringBuilder();
WriteTextTo(document.DocumentNode, sb);
return sb.ToString().Trim(' ', '\n', '\r');
}
catch
{
return JsValue.Undefined;
}
};
private static HtmlDocument LoadHtml(string text)
{
var document = new HtmlDocument();
document.LoadHtml(text);
return document;
}
private static void WriteTextTo(HtmlNode node, StringBuilder sb)
{
switch (node.NodeType)
{
case HtmlNodeType.Comment:
break;
case HtmlNodeType.Document:
WriteChildrenTextTo(node, sb);
break;
case HtmlNodeType.Text:
var html = ((HtmlTextNode)node).Text;
if (HtmlNode.IsOverlappedClosingElement(html))
{
break;
}
if (!string.IsNullOrWhiteSpace(html))
{
sb.Append(HtmlEntity.DeEntitize(html));
}
break;
case HtmlNodeType.Element:
switch (node.Name)
{
case "p":
sb.AppendLine();
break;
case "br":
sb.AppendLine();
break;
case "style":
return;
case "script":
return;
}
if (node.HasChildNodes)
{
WriteChildrenTextTo(node, sb);
}
break;
}
}
private static void WriteChildrenTextTo(HtmlNode node, StringBuilder sb)
{
foreach (var child in node.ChildNodes)
{
WriteTextTo(child, sb);
}
}
private readonly Func<string, JsValue> markdown2Text = text =>
{
try
{
return Markdown.ToPlainText(text).Trim(' ', '\n', '\r');
}
catch
{
return JsValue.Undefined;
}
};
public Func<string, JsValue> Html2Text => html2Text;
public void Extend(Engine engine) public void Extend(Engine engine)
{ {
engine.SetValue("slugify", slugify); engine.SetValue("slugify", slugify);
engine.SetValue("toCamelCase", toCamelCase); engine.SetValue("toCamelCase", toCamelCase);
engine.SetValue("toPascalCase", toPascalCase); engine.SetValue("toPascalCase", toPascalCase);
engine.SetValue("html2Text", Html2Text);
engine.SetValue("markdown2Text", markdown2Text);
} }
} }
} }

77
backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/Extensions/StringWordsJintExtension.cs

@ -0,0 +1,77 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
using Jint;
using Jint.Native;
namespace Squidex.Domain.Apps.Core.Scripting.Extensions
{
public sealed class StringWordsJintExtension : IJintExtension
{
private readonly Func<string, JsValue> wordCount = text =>
{
try
{
var numWords = 0;
for (int i = 1; i < text.Length; i++)
{
if (char.IsWhiteSpace(text[i - 1]))
{
var character = text[i];
if (char.IsLetterOrDigit(character) || char.IsPunctuation(character))
{
numWords++;
}
}
}
if (text.Length > 2)
{
numWords++;
}
return numWords;
}
catch
{
return JsValue.Undefined;
}
};
private readonly Func<string, JsValue> characterCount = text =>
{
try
{
var characterCount = 0;
for (int i = 0; i < text.Length; i++)
{
if (char.IsLetter(text[i]))
{
characterCount++;
}
}
return characterCount;
}
catch
{
return JsValue.Undefined;
}
};
public void Extend(Engine engine)
{
engine.SetValue("wordCount", wordCount);
engine.SetValue("characterCount", characterCount);
}
}
}

2
backend/src/Squidex.Domain.Apps.Core.Operations/Squidex.Domain.Apps.Core.Operations.csproj

@ -17,7 +17,9 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Fluid.Core.Squidex" Version="1.0.0-beta" /> <PackageReference Include="Fluid.Core.Squidex" Version="1.0.0-beta" />
<PackageReference Include="HtmlAgilityPack" Version="1.11.24" />
<PackageReference Include="Jint" Version="3.0.0-beta-1580" /> <PackageReference Include="Jint" Version="3.0.0-beta-1580" />
<PackageReference Include="Markdig" Version="0.20.0" />
<PackageReference Include="Microsoft.Extensions.Http" Version="3.1.4" /> <PackageReference Include="Microsoft.Extensions.Http" Version="3.1.4" />
<PackageReference Include="Microsoft.OData.Core" Version="7.6.4" /> <PackageReference Include="Microsoft.OData.Core" Version="7.6.4" />
<PackageReference Include="NJsonSchema" Version="10.1.18" /> <PackageReference Include="NJsonSchema" Version="10.1.18" />

3
backend/src/Squidex/Config/Domain/InfrastructureServices.cs

@ -71,6 +71,9 @@ namespace Squidex.Config.Domain
services.AddSingletonAs<StringJintExtension>() services.AddSingletonAs<StringJintExtension>()
.As<IJintExtension>(); .As<IJintExtension>();
services.AddSingletonAs<StringWordsJintExtension>()
.As<IJintExtension>();
services.AddSingletonAs<HttpJintExtension>() services.AddSingletonAs<HttpJintExtension>()
.As<IJintExtension>(); .As<IJintExtension>();

3
backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleEventFormatterCompareTests.cs

@ -109,7 +109,8 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules
{ {
new DateTimeJintExtension(), new DateTimeJintExtension(),
new EventJintExtension(urlGenerator), new EventJintExtension(urlGenerator),
new StringJintExtension() new StringJintExtension(),
new StringWordsJintExtension()
}; };
var cache = new MemoryCache(Options.Create(new MemoryCacheOptions())); var cache = new MemoryCache(Options.Create(new MemoryCacheOptions()));

3
backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleEventFormatterTests.cs

@ -103,7 +103,8 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules
{ {
new DateTimeJintExtension(), new DateTimeJintExtension(),
new EventJintExtension(urlGenerator), new EventJintExtension(urlGenerator),
new StringJintExtension() new StringJintExtension(),
new StringWordsJintExtension()
}; };
var cache = new MemoryCache(Options.Create(new MemoryCacheOptions())); var cache = new MemoryCache(Options.Create(new MemoryCacheOptions()));

71
backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/Scripting/JintScriptEngineHelperTests.cs

@ -33,7 +33,8 @@ namespace Squidex.Domain.Apps.Core.Operations.Scripting
{ {
new DateTimeJintExtension(), new DateTimeJintExtension(),
new HttpJintExtension(httpClientFactory), new HttpJintExtension(httpClientFactory),
new StringJintExtension() new StringJintExtension(),
new StringWordsJintExtension()
}; };
var cache = new MemoryCache(Options.Create(new MemoryCacheOptions())); var cache = new MemoryCache(Options.Create(new MemoryCacheOptions()));
@ -44,6 +45,74 @@ namespace Squidex.Domain.Apps.Core.Operations.Scripting
}; };
} }
[Fact]
public void Should_convert_html_to_text()
{
const string script = @"
return html2Text(value);
";
var vars = new ScriptVars
{
["value"] = "<script>Invalid</script><STYLE>Invalid</STYLE><p>Hello World</p>"
};
var result = sut.Execute(vars, script).ToString();
Assert.Equal("Hello World", result);
}
[Fact]
public void Should_convert_markdown_to_text()
{
const string script = @"
return markdown2Text(value);
";
var vars = new ScriptVars
{
["value"] = "## Hello World"
};
var result = sut.Execute(vars, script).ToString();
Assert.Equal("Hello World", result);
}
[Fact]
public void Should_count_words()
{
const string script = @"
return wordCount(value);
";
var vars = new ScriptVars
{
["value"] = "Hello, World"
};
var result = ((JsonNumber)sut.Execute(vars, script)).Value;
Assert.Equal(2, result);
}
[Fact]
public void Should_count_characters()
{
const string script = @"
return characterCount(value);
";
var vars = new ScriptVars
{
["value"] = "Hello, World"
};
var result = ((JsonNumber)sut.Execute(vars, script)).Value;
Assert.Equal(10, result);
}
[Fact] [Fact]
public void Should_camel_case_value() public void Should_camel_case_value()
{ {

3
backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/Scripting/JintScriptEngineTests.cs

@ -40,7 +40,8 @@ namespace Squidex.Domain.Apps.Core.Operations.Scripting
{ {
new DateTimeJintExtension(), new DateTimeJintExtension(),
new HttpJintExtension(httpClientFactory), new HttpJintExtension(httpClientFactory),
new StringJintExtension() new StringJintExtension(),
new StringWordsJintExtension()
}; };
var httpResponse = new HttpResponseMessage(HttpStatusCode.OK) var httpResponse = new HttpResponseMessage(HttpStatusCode.OK)

Loading…
Cancel
Save