diff --git a/CHANGELOG.md b/CHANGELOG.md index dc57259e5..8a9b1f422 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ - `c-select` `open-on-clear` prop once again functions as expected. - `c-select` now closes when changing focus to other elements on the page +- Multi-line strings now emit correctly into generated metadata (e.g. a multi-line description for a property) # 5.2.1 diff --git a/src/IntelliTect.Coalesce.Tests/TargetClasses/TestDbContext/ComplexModel.cs b/src/IntelliTect.Coalesce.Tests/TargetClasses/TestDbContext/ComplexModel.cs index 1b8095f01..fd059befe 100644 --- a/src/IntelliTect.Coalesce.Tests/TargetClasses/TestDbContext/ComplexModel.cs +++ b/src/IntelliTect.Coalesce.Tests/TargetClasses/TestDbContext/ComplexModel.cs @@ -70,9 +70,14 @@ public class ComplexModel public string AdminReadableString { get; set; } [Restrict] + [Display(Description = """ + This is a multiline string in an attribute. + This is a second line in the string. + """)] public string RestrictedString { get; set; } [Restrict] + [Display(Description = "This is a multiline string\n via explicit escaped newline")] public string RestrictInit { get; init; } [Read(RoleNames.Admin)] diff --git a/src/IntelliTect.Coalesce/Utilities/StringExtensions.cs b/src/IntelliTect.Coalesce/Utilities/StringExtensions.cs index b3904f1ab..43afc78bc 100644 --- a/src/IntelliTect.Coalesce/Utilities/StringExtensions.cs +++ b/src/IntelliTect.Coalesce/Utilities/StringExtensions.cs @@ -131,6 +131,8 @@ public static string ToCamelCase(this string s) [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("str")] public static string? EscapeStringLiteralForTypeScript(this string? str) => str? .Replace(@"\", @"\\") + .Replace("\r", @"\r") + .Replace("\n", @"\n") .Replace("\"", "\\\""); [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("str")] diff --git a/src/test-targets/metadata.g.ts b/src/test-targets/metadata.g.ts index 0967794c5..cb10f5712 100644 --- a/src/test-targets/metadata.g.ts +++ b/src/test-targets/metadata.g.ts @@ -715,12 +715,14 @@ export const ComplexModel = domain.types.ComplexModel = { restrictedString: { name: "restrictedString", displayName: "Restricted String", + description: "This is a multiline string in an attribute.\r\nThis is a second line in the string.", type: "string", role: "value", }, restrictInit: { name: "restrictInit", displayName: "Restrict Init", + description: "This is a multiline string\n via explicit escaped newline", type: "string", role: "value", createOnly: true, diff --git a/src/test-targets/models.g.ts b/src/test-targets/models.g.ts index 8daf7f123..b78094432 100644 --- a/src/test-targets/models.g.ts +++ b/src/test-targets/models.g.ts @@ -258,7 +258,17 @@ export interface ComplexModel extends Model { dateOnlyViaAttribute: Date | null unmappedSettableString: string | null adminReadableString: string | null + + /** + This is a multiline string in an attribute. + This is a second line in the string. + */ restrictedString: string | null + + /** + This is a multiline string + via explicit escaped newline + */ restrictInit: string | null adminReadableReferenceNavigationId: number | null adminReadableReferenceNavigation: ComplexModel | null diff --git a/src/test-targets/viewmodels.g.ts b/src/test-targets/viewmodels.g.ts index dfe29229e..05fe6d3a1 100644 --- a/src/test-targets/viewmodels.g.ts +++ b/src/test-targets/viewmodels.g.ts @@ -199,7 +199,17 @@ export interface ComplexModelViewModel extends $models.ComplexModel { dateOnlyViaAttribute: Date | null; unmappedSettableString: string | null; adminReadableString: string | null; + + /** + This is a multiline string in an attribute. + This is a second line in the string. + */ restrictedString: string | null; + + /** + This is a multiline string + via explicit escaped newline + */ restrictInit: string | null; adminReadableReferenceNavigationId: number | null; get adminReadableReferenceNavigation(): ComplexModelViewModel | null;