diff --git a/src/libraries/Microsoft.PowerFx.Core/Localization/Strings.cs b/src/libraries/Microsoft.PowerFx.Core/Localization/Strings.cs index 58a12a4474..a5740ad3e7 100644 --- a/src/libraries/Microsoft.PowerFx.Core/Localization/Strings.cs +++ b/src/libraries/Microsoft.PowerFx.Core/Localization/Strings.cs @@ -518,8 +518,8 @@ internal static class TexlStrings public static StringGetter AboutEncodeUrl = (b) => StringResources.Get("AboutEncodeUrl", b); public static StringGetter EncodeUrlArg1 = (b) => StringResources.Get("EncodeUrlArg1", b); - public static StringGetter AboutEscapeHtml = (b) => StringResources.Get("AboutEscapeHtml", b); - public static StringGetter EscapeHtmlArg1 = (b) => StringResources.Get("EscapeHtmlArg1", b); + public static StringGetter AboutEncodeHTML = (b) => StringResources.Get("AboutEncodeHTML", b); + public static StringGetter EncodeHTMLArg1 = (b) => StringResources.Get("EncodeHTMLArg1", b); public static StringGetter AboutPlainText = (b) => StringResources.Get("AboutPlainText", b); public static StringGetter PlainTextArg1 = (b) => StringResources.Get("PlainTextArg1", b); diff --git a/src/libraries/Microsoft.PowerFx.Core/Texl/BuiltinFunctionsCore.cs b/src/libraries/Microsoft.PowerFx.Core/Texl/BuiltinFunctionsCore.cs index 30025f099a..e3fc14e414 100644 --- a/src/libraries/Microsoft.PowerFx.Core/Texl/BuiltinFunctionsCore.cs +++ b/src/libraries/Microsoft.PowerFx.Core/Texl/BuiltinFunctionsCore.cs @@ -94,10 +94,10 @@ internal class BuiltinFunctionsCore public static readonly TexlFunction DropColumns = _library.Add(new DropColumnsFunction()); public static readonly TexlFunction EDate = _library.Add(new EDateFunction()); public static readonly TexlFunction EOMonth = _library.Add(new EOMonthFunction()); + public static readonly TexlFunction EncodeHTML = _library.Add(new EncodeHTMLFunction()); public static readonly TexlFunction EncodeUrl = _library.Add(new EncodeUrlFunction()); public static readonly TexlFunction EndsWith = _library.Add(new EndsWithFunction()); public static readonly TexlFunction Error = _library.Add(new ErrorFunction()); - public static readonly TexlFunction EscapeHtml = _library.Add(new EscapeHtmlFunction()); public static readonly TexlFunction Exp = _library.Add(new ExpFunction()); public static readonly TexlFunction ExpT = _library.Add(new ExpTableFunction()); public static readonly TexlFunction Filter = _library.Add(new FilterFunction()); diff --git a/src/libraries/Microsoft.PowerFx.Core/Texl/Builtins/EncodeHTML.cs b/src/libraries/Microsoft.PowerFx.Core/Texl/Builtins/EncodeHTML.cs new file mode 100644 index 0000000000..8678b61326 --- /dev/null +++ b/src/libraries/Microsoft.PowerFx.Core/Texl/Builtins/EncodeHTML.cs @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +using System.Collections.Generic; +using Microsoft.PowerFx.Core.Localization; +using Microsoft.PowerFx.Core.Texl.Builtins; +using Microsoft.PowerFx.Core.Types; + +namespace Microsoft.PowerFx.Core.Texl +{ + internal sealed class EncodeHTMLFunction : StringOneArgFunction + { + public EncodeHTMLFunction() + : base("EncodeHTML", TexlStrings.AboutEncodeHTML, FunctionCategories.Text) + { + } + + public override IEnumerable GetSignatures() + { + yield return new[] { TexlStrings.EncodeHTMLArg1 }; + } + } +} diff --git a/src/libraries/Microsoft.PowerFx.Core/Texl/Builtins/EscapeHtml.cs b/src/libraries/Microsoft.PowerFx.Core/Texl/Builtins/EscapeHtml.cs deleted file mode 100644 index 527448c1d8..0000000000 --- a/src/libraries/Microsoft.PowerFx.Core/Texl/Builtins/EscapeHtml.cs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. - -using System.Collections.Generic; -using Microsoft.PowerFx.Core.Localization; -using Microsoft.PowerFx.Core.Texl.Builtins; -using Microsoft.PowerFx.Core.Types; - -namespace Microsoft.PowerFx.Core.Texl -{ - internal sealed class EscapeHtmlFunction : StringOneArgFunction - { - public EscapeHtmlFunction() - : base("EscapeHtml", TexlStrings.AboutEscapeHtml, FunctionCategories.Text) - { - } - - public override IEnumerable GetSignatures() - { - yield return new[] { TexlStrings.EscapeHtmlArg1 }; - } - } -} diff --git a/src/libraries/Microsoft.PowerFx.Interpreter/Functions/Library.cs b/src/libraries/Microsoft.PowerFx.Interpreter/Functions/Library.cs index e7dddf459d..dff3ef1914 100644 --- a/src/libraries/Microsoft.PowerFx.Interpreter/Functions/Library.cs +++ b/src/libraries/Microsoft.PowerFx.Interpreter/Functions/Library.cs @@ -641,6 +641,17 @@ static Library() returnBehavior: ReturnBehavior.AlwaysEvaluateAndReturnResult, targetFunction: EOMonth) }, + { + BuiltinFunctionsCore.EncodeHTML, + StandardErrorHandling( + BuiltinFunctionsCore.EncodeUrl.Name, + expandArguments: NoArgExpansion, + replaceBlankValues: NoOpAlreadyHandledByIR, + checkRuntimeTypes: ExactValueType, + checkRuntimeValues: DeferRuntimeValueChecking, + returnBehavior: ReturnBehavior.AlwaysEvaluateAndReturnResult, + targetFunction: EncodeHTML) + }, { BuiltinFunctionsCore.EncodeUrl, StandardErrorHandling( @@ -674,17 +685,6 @@ static Library() returnBehavior: ReturnBehavior.ReturnFalseIfAnyArgIsBlank, targetFunction: Error) }, - { - BuiltinFunctionsCore.EscapeHtml, - StandardErrorHandling( - BuiltinFunctionsCore.EncodeUrl.Name, - expandArguments: NoArgExpansion, - replaceBlankValues: NoOpAlreadyHandledByIR, - checkRuntimeTypes: ExactValueType, - checkRuntimeValues: DeferRuntimeValueChecking, - returnBehavior: ReturnBehavior.AlwaysEvaluateAndReturnResult, - targetFunction: EscapeHtml) - }, { BuiltinFunctionsCore.Exp, StandardErrorHandling( diff --git a/src/libraries/Microsoft.PowerFx.Interpreter/Functions/LibraryText.cs b/src/libraries/Microsoft.PowerFx.Interpreter/Functions/LibraryText.cs index 891fb83f1c..e589161fc0 100644 --- a/src/libraries/Microsoft.PowerFx.Interpreter/Functions/LibraryText.cs +++ b/src/libraries/Microsoft.PowerFx.Interpreter/Functions/LibraryText.cs @@ -802,7 +802,7 @@ public static FormulaValue EncodeUrl(IRContext irContext, StringValue[] args) return new StringValue(irContext, Uri.EscapeDataString(args[0].Value)); } - public static FormulaValue EscapeHtml(IRContext irContext, StringValue[] args) + public static FormulaValue EncodeHTML(IRContext irContext, StringValue[] args) { var encoded = HttpUtility.HtmlEncode(args[0].Value); return new StringValue(irContext, encoded); diff --git a/src/strings/PowerFxResources.en-US.resx b/src/strings/PowerFxResources.en-US.resx index 65a90595a9..2cbd2a85be 100644 --- a/src/strings/PowerFxResources.en-US.resx +++ b/src/strings/PowerFxResources.en-US.resx @@ -4092,16 +4092,16 @@ A url to be encoded. - + Converts a text to an HTML-encoded text. - Description of 'EncodeUrl' function. + Description of 'EncodeHTML' function. - + value - Function_parameter - First parameter for the EscapeHtml function - the value (string) to escape. + Function_parameter - First parameter for the EncodeHTML function - the value (string) to encode. - - A text to be escaped. + + A text to be encoded. '{0}' is a recognized but not supported function. diff --git a/src/tests/Microsoft.PowerFx.Core.Tests/ExpressionTestCases/EscapeHtml.txt b/src/tests/Microsoft.PowerFx.Core.Tests/ExpressionTestCases/EncodeHTML.txt similarity index 57% rename from src/tests/Microsoft.PowerFx.Core.Tests/ExpressionTestCases/EscapeHtml.txt rename to src/tests/Microsoft.PowerFx.Core.Tests/ExpressionTestCases/EncodeHTML.txt index 462d359faf..57fcb458b6 100644 --- a/src/tests/Microsoft.PowerFx.Core.Tests/ExpressionTestCases/EscapeHtml.txt +++ b/src/tests/Microsoft.PowerFx.Core.Tests/ExpressionTestCases/EncodeHTML.txt @@ -1,42 +1,49 @@ // Escaping ->> EscapeHtml("

A paragraph

") +>> EncodeHTML("

A paragraph

") "<p>A paragraph</p>" // Multiple encodings ->> EscapeHtml("

Mac & cheese

") +>> EncodeHTML("

Mac & cheese

") "<h1>Mac & cheese</h1>" // Quotes ->> EscapeHtml("A value with ""double"" and 'single' quotes") +>> EncodeHTML("A value with ""double"" and 'single' quotes") "A value with "double" and 'single' quotes" // \u00A0 to \u00af - escaped ->> EscapeHtml(Concat(Sequence(16, 160), UniChar(Value))) +>> EncodeHTML(Concat(Sequence(16, 160), UniChar(Value))) " ¡¢£¤¥¦§¨©ª«¬­®¯" // \u0090 to \u009f - not escaped ->> With({str:Concat(Sequence(16, 144), UniChar(Value))}, str = EscapeHtml(str)) +>> With({str:Concat(Sequence(16, 144), UniChar(Value))}, str = EncodeHTML(str)) true // \u00A0 to \u00ff - escaped ->> With({str:EscapeHtml(Concat(Sequence(96, 160), UniChar(Value))), expectedEscaped:Concat(Sequence(96, 160), $"&#{Value};")}, str = expectedEscaped) +>> With({str:EncodeHTML(Concat(Sequence(96, 160), UniChar(Value))), expectedEscaped:Concat(Sequence(96, 160), $"&#{Value};")}, str = expectedEscaped) true // \u0100... not escaped ->> EscapeHtml("ĀāĂă") +>> EncodeHTML("ĀāĂă") "<b>ĀāĂă</b>" // Blanks ->> EscapeHtml(Blank()) +>> EncodeHTML(Blank()) +"" + +>> EncodeHTML("") "" // Errors ->> EscapeHtml(Char(-1)) +>> EncodeHTML(Char(-1)) Error({Kind:ErrorKind.InvalidArgument}) // Escaping surrogate pairs ->> EscapeHtml("
  • not a pair: ❤
  • a surrogate pair: 💩
") +>> EncodeHTML("
  • not a pair: ❤
  • a surrogate pair: 💩
") "<ul><li>not a pair: ❤</li><li>a surrogate pair: 💩</li></ul>" ->> EscapeHtml("Osage alphabet (start): 𐒰𐒱𐒲𐒳𐒴𐒵𐒶") +>> EncodeHTML("Osage alphabet (start): 𐒰𐒱𐒲𐒳𐒴𐒵𐒶") "Osage alphabet (start): 𐒰𐒱𐒲𐒳𐒴𐒵𐒶" + +// Unpaired surrogate characters become the replacement character U+FFFD +>> EncodeHTML($"Unpaired: {UniChar(Hex2Dec("df32"))} {UniChar(Hex2Dec("d823"))}")) +"Unpaired: � �" diff --git a/src/tests/Microsoft.PowerFx.Interpreter.Tests/Docs/InterpreterBase.json b/src/tests/Microsoft.PowerFx.Interpreter.Tests/Docs/InterpreterBase.json index 22dbbbc223..bb877d2a83 100644 --- a/src/tests/Microsoft.PowerFx.Interpreter.Tests/Docs/InterpreterBase.json +++ b/src/tests/Microsoft.PowerFx.Interpreter.Tests/Docs/InterpreterBase.json @@ -46,11 +46,11 @@ "Distinct", "DropColumns", "EDate", + "EncodeHTML", "EncodeUrl", "EndsWith", "EOMonth", "Error", - "EscapeHtml", "Exp", "Filter", "Find",