diff --git a/app/MindWork AI Studio/Tools/FileExportFormatExtensions.cs b/app/MindWork AI Studio/Tools/FileExportFormatExtensions.cs index 6d540797..0e1b552e 100644 --- a/app/MindWork AI Studio/Tools/FileExportFormatExtensions.cs +++ b/app/MindWork AI Studio/Tools/FileExportFormatExtensions.cs @@ -311,6 +311,19 @@ public static class FileExportFormatExtensions _ => true, }; + /// + /// Determines whether Pandoc has to be told the title of a document in the format. + /// + /// + /// A web page shows its title in the browser tab. Without one, Pandoc names the page after its + /// input file, which is a temporary file of ours with a random name. Word and OpenDocument show + /// no such title, and handed one anyway, they keep it as a document property nobody asked for; + /// verified with Pandoc 3.8.3 on 2026-09-23. LaTeX ignores it. + /// + /// The format. + /// True, when a document of this format needs a title besides its content. + public static bool NeedsPageTitle(this FileExportFormat format) => format is FileExportFormat.HTML; + /// /// Returns the name Pandoc knows the format by. /// diff --git a/app/MindWork AI Studio/Tools/PandocExport.cs b/app/MindWork AI Studio/Tools/PandocExport.cs index 1b63fa42..8f94c2cd 100644 --- a/app/MindWork AI Studio/Tools/PandocExport.cs +++ b/app/MindWork AI Studio/Tools/PandocExport.cs @@ -43,14 +43,23 @@ public static class PandocExport await File.WriteAllTextAsync(tempMarkdownFilePath, markdownText, new UTF8Encoding(false), token); // Call Pandoc to create the document: - var pandoc = await PandocProcessBuilder + var pandocBuilder = PandocProcessBuilder .Create() .UseStandaloneMode() .WithInputFormat("gfm+emoji+tex_math_dollars") .WithOutputFormat(format.ToPandocOutputFormat()) .WithOutputFile(targetFilePath) - .WithInputFile(tempMarkdownFilePath) - .BuildAsync(rustService); + .WithInputFile(tempMarkdownFilePath); + + // + // The document is named after the file it is written to. Set as metadata, the name + // reaches the page as a string which Pandoc escapes; only a file named true or false + // is read as a switch and keeps the temporary name. + // + if (format.NeedsPageTitle()) + pandocBuilder.AddArgument("-M").AddArgument($"pagetitle={Path.GetFileNameWithoutExtension(targetFilePath)}"); + + var pandoc = await pandocBuilder.BuildAsync(rustService); using var process = Process.Start(pandoc.StartInfo); if (process is null) diff --git a/app/MindWork AI Studio/wwwroot/changelog/v26.9.1.md b/app/MindWork AI Studio/wwwroot/changelog/v26.9.1.md index ccb4afaa..94e54966 100644 --- a/app/MindWork AI Studio/wwwroot/changelog/v26.9.1.md +++ b/app/MindWork AI Studio/wwwroot/changelog/v26.9.1.md @@ -72,6 +72,7 @@ - Fixed the Visual Briefing assistant (in preview) not scrolling, which put everything below the window edge out of reach and made the assistant unusable. The briefing preview is now shown at its intended size inside its frame, and switching between the desktop, tablet, and mobile view changes its width as it should. - Fixed exported answers losing their sources. When an answer is based on web pages a tool read or on documents of your own, the exported file now lists those sources in every format AI Studio writes. - Fixed the copy button leaving the sources behind. Copy an answer, and its sources come along. +- Fixed exported web pages showing a cryptic string of letters and digits as their title in the browser tab. They now carry the name of their file. - Fixed a tile that opens a chat directly always demanding a workspace. Leave the workspace empty in the Assistant Builder, and the tile opens a disappearing chat instead. - Fixed the same restriction for plugin authors: a direct-chat launcher can now open a chat without naming a workspace. The example assistant plugin shows both ways. - Fixed the security check of an assistant plugin being impossible when no model is set aside for such checks, and you have no app-wide default either. The dialog now lets you pick one, and that choice applies to this one check. Before, the button to start the check was greyed out with nothing saying why, so the plugin could not be enabled at all. diff --git a/app/Tests/Tools/FileExportFormatTests.cs b/app/Tests/Tools/FileExportFormatTests.cs index daa4572d..3c7e0e4a 100644 --- a/app/Tests/Tools/FileExportFormatTests.cs +++ b/app/Tests/Tools/FileExportFormatTests.cs @@ -37,6 +37,18 @@ public sealed class FileExportFormatTests }), "A format was added to or removed from the export menu: say in FollowsPageAnchors whether its reader follows a page in a local link, then name it here."); } + [Test] + public void OnlyAWebPageNeedsAPageTitle() + { + Assert.Multiple(() => + { + Assert.That(FileExportFormat.HTML.NeedsPageTitle(), Is.True, "Without one, the browser tab shows the random name of the temporary file Pandoc read."); + Assert.That(FileExportFormat.MICROSOFT_WORD.NeedsPageTitle(), Is.False, "Word would keep it as a document property nobody asked for."); + Assert.That(FileExportFormat.OPEN_DOCUMENT_TEXT.NeedsPageTitle(), Is.False, "The same goes for an OpenDocument file."); + Assert.That(FileExportFormat.LATEX.NeedsPageTitle(), Is.False); + }); + } + [TestCase("html", FileExportFormat.HTML)] [TestCase("latex", FileExportFormat.LATEX)] [TestCase("tex", FileExportFormat.LATEX)]