diff --git a/.gitignore b/.gitignore index d5e87be21a..f76c5c2282 100644 --- a/.gitignore +++ b/.gitignore @@ -40,3 +40,4 @@ launchSettings.json # Test development user appdata files dev-appdata/ +c-sharp/**/*.BAK diff --git a/c-sharp/NetworkObjects/UsfmDataProvider.cs b/c-sharp/NetworkObjects/UsfmDataProvider.cs index 865ec0f612..d1072a64c3 100644 --- a/c-sharp/NetworkObjects/UsfmDataProvider.cs +++ b/c-sharp/NetworkObjects/UsfmDataProvider.cs @@ -1,6 +1,7 @@ using System.Text.Json; using System.Text.Json.Nodes; using System.Xml; +using System.Xml.XPath; using Paranext.DataProvider.JsonUtils; using Paranext.DataProvider.MessageHandlers; using Paranext.DataProvider.MessageTransports; @@ -43,6 +44,7 @@ protected override ResponseToRequest HandleRequest(string functionName, JsonArra "getBookNames" => GetBookNames(), "getChapter" => GetChapter(args[0]!.ToJsonString()), "getChapterUsx" => GetChapterUsx(args[0]!.ToJsonString()), + "setChapterUsx" => SetChapterUsx(args[0]!.ToJsonString(), args[1]!.ToString()), "getVerse" => GetVerse(args[0]!.ToJsonString()), _ => ResponseToRequest.Failed($"Unexpected function: {functionName}") }; @@ -73,6 +75,13 @@ private ResponseToRequest GetChapterUsx(string args) : ResponseToRequest.Failed(errorMsg); } + private ResponseToRequest SetChapterUsx(string argVref, string argNewUsx) + { + return VerseRefConverter.TryCreateVerseRef(argVref, out var verseRef, out string errorMsg) + ? SetUsx(verseRef, argNewUsx) + : ResponseToRequest.Failed(errorMsg); + } + private ResponseToRequest GetVerse(string args) { return VerseRefConverter.TryCreateVerseRef(args, out var verseRef, out string errorMsg) @@ -87,6 +96,34 @@ public string GetUsx(VerseRef vref) return contents; } + public ResponseToRequest SetUsx(VerseRef vref, string newUsx) + { + try + { + XmlDocument doc = new() { PreserveWhitespace = true }; + doc.LoadXml(newUsx); + if (doc.FirstChild?.Name != "usx") + return ResponseToRequest.Failed("Invalid USX"); + + UsxFragmenter.FindFragments( + _scrText!.ScrStylesheet(vref.BookNum), + doc.CreateNavigator(), + XPathExpression.Compile("*[false()]"), + out string usfm + ); + + usfm = UsfmToken.NormalizeUsfm(_scrText, vref.BookNum, usfm); + _scrText.PutText(vref.BookNum, vref.ChapterNum, false, usfm, null); + SendDataUpdateEvent("*"); + } + catch (Exception e) + { + return ResponseToRequest.Failed(e.Message); + } + + return ResponseToRequest.Succeeded(); + } + private XmlDocument GetUsxForChapter(int bookNum, int chapterNum) { return ConvertUsfmToUsx(GetUsfmForChapter(bookNum, chapterNum), bookNum); diff --git a/c-sharp/ParatextUtils/ParatextGlobals.cs b/c-sharp/ParatextUtils/ParatextGlobals.cs index 1a93744631..240cba4342 100644 --- a/c-sharp/ParatextUtils/ParatextGlobals.cs +++ b/c-sharp/ParatextUtils/ParatextGlobals.cs @@ -34,6 +34,7 @@ public static void Initialize(string dataFolderPath) ICUDllLocator.Initialize(false, false); // Now tell Paratext.Data to use the specified folder + dataFolderPath = Path.GetFullPath(dataFolderPath); // Make sure path is rooted ParatextData.Initialize(dataFolderPath, false); s_initialized = true; } diff --git a/extensions/src/resource-viewer/resource-viewer.web-view.tsx b/extensions/src/resource-viewer/resource-viewer.web-view.tsx index 38a2b93d1e..897cdd7cba 100644 --- a/extensions/src/resource-viewer/resource-viewer.web-view.tsx +++ b/extensions/src/resource-viewer/resource-viewer.web-view.tsx @@ -123,6 +123,7 @@ const usxEditorCharMap = Object.fromEntries( interface ScriptureTextPanelUsxProps { usx: string; + onChanged?: (newUsx: string) => void; } const defaultScrRef: ScriptureReference = { @@ -135,7 +136,7 @@ const defaultScrRef: ScriptureReference = { * Scripture text panel that displays a read only version of a usx editor that displays the current * chapter */ -function ScriptureTextPanelUsxEditor({ usx }: ScriptureTextPanelUsxProps) { +function ScriptureTextPanelUsxEditor({ usx, onChanged }: ScriptureTextPanelUsxProps) { return ( // eslint-disable-next-line jsx-a11y/no-static-element-interactions