Turned getter-like extension methods into extension properties (#1157)

This commit is contained in:
Thorsten Sommer authored and GitHub committed 2026-11-04 13:00:56 +01:00
1 parent 0375318b1b
commit f649febf88
286 files changed
+1379 -1109

No files matched your search

@@ -23,43 +23,49 @@ public static class FileExportFormatExtensions
private static readonly Encoding WITH_BYTE_ORDER_MARK = new UTF8Encoding(true);
private static readonly Encoding WITHOUT_BYTE_ORDER_MARK = new UTF8Encoding(false);
/// <summary>
/// The formats which lay the text out as a document you would hand to somebody, in the order
/// the export menu shows them.
/// </summary>
public static readonly IReadOnlyList<FileExportFormat> DOCUMENT_FORMATS =
private static readonly IReadOnlyList<FileExportFormat> DOCUMENT_FORMATS =
[
FileExportFormat.MICROSOFT_WORD,
FileExportFormat.OPEN_DOCUMENT_TEXT,
FileExportFormat.LATEX,
];
/// <summary>
/// The formats which keep the text as text, in the order the export menu shows them.
/// </summary>
public static readonly IReadOnlyList<FileExportFormat> TEXT_FORMATS =
private static readonly IReadOnlyList<FileExportFormat> TEXT_FORMATS =
[
FileExportFormat.MARKDOWN,
FileExportFormat.HTML,
];
/// <summary>
/// Every format an entire answer can be written as.
/// </summary>
/// <remarks>
/// The tabular formats are missing on purpose: they hold one table out of an answer, never the
/// answer itself. Whoever offers a table adds them.
/// </remarks>
public static readonly IReadOnlyList<FileExportFormat> ANSWER_FORMATS = [..DOCUMENT_FORMATS, ..TEXT_FORMATS];
private static readonly IReadOnlyList<FileExportFormat> ANSWER_FORMATS = [..DOCUMENT_FORMATS, ..TEXT_FORMATS];
/// <param name="format">The format.</param>
extension(FileExportFormat format)
{
/// <summary>
/// The formats which lay the text out as a document you would hand to somebody, in the order
/// the export menu shows them.
/// </summary>
public static IReadOnlyList<FileExportFormat> DocumentFormats => DOCUMENT_FORMATS;
/// <summary>
/// The formats which keep the text as text, in the order the export menu shows them.
/// </summary>
public static IReadOnlyList<FileExportFormat> TextFormats => TEXT_FORMATS;
/// <summary>
/// Every format an entire answer can be written as.
/// </summary>
/// <remarks>
/// The tabular formats are missing on purpose: they hold one table out of an answer, never the
/// answer itself. Whoever offers a table adds them.
/// </remarks>
public static IReadOnlyList<FileExportFormat> AnswerFormats => ANSWER_FORMATS;
/// <summary>
/// Returns the name of the format as shown to the user.
/// </summary>
/// <returns>The name of the format.</returns>
public string ToName() => format switch
/// <value>The name of the format.</value>
public string Name => format switch
{
FileExportFormat.MICROSOFT_WORD => TB("Microsoft Word (.docx)"),
FileExportFormat.OPEN_DOCUMENT_TEXT => TB("OpenDocument Text (.odt), e.g. LibreOffice"),
@@ -76,8 +82,8 @@ public static class FileExportFormatExtensions
/// <summary>
/// Returns the icon of the format.
/// </summary>
/// <returns>The icon of the format.</returns>
public string ToIcon() => format switch
/// <value>The icon of the format.</value>
public string Icon => format switch
{
FileExportFormat.MICROSOFT_WORD => Icons.Custom.FileFormats.FileWord,
FileExportFormat.OPEN_DOCUMENT_TEXT => Icons.Custom.FileFormats.FileDocument,
@@ -93,9 +99,9 @@ public static class FileExportFormatExtensions
/// <summary>
/// Returns the file extension of the format, including the leading dot.
/// </summary>
/// <returns>The file extension, or an empty string when the format writes no file or, as code
/// does, takes the extension from its language.</returns>
public string ToFileExtension() => format switch
/// <value>The file extension, or an empty string when the format writes no file or, as code
/// does, takes the extension from its language.</value>
public string FileExtension => format switch
{
FileExportFormat.MICROSOFT_WORD => ".docx",
FileExportFormat.OPEN_DOCUMENT_TEXT => ".odt",
@@ -111,8 +117,8 @@ public static class FileExportFormatExtensions
/// <summary>
/// Determines whether the format holds a table rather than a text.
/// </summary>
/// <returns>True for the formats a spreadsheet opens.</returns>
public bool IsTabular() => format is FileExportFormat.CSV or FileExportFormat.TSV;
/// <value>True for the formats a spreadsheet opens.</value>
public bool IsTabular => format is FileExportFormat.CSV or FileExportFormat.TSV;
/// <summary>
/// Determines whether a file of the format is plain text, which AI Studio writes as it is.
@@ -124,8 +130,8 @@ public static class FileExportFormatExtensions
/// list is spelled out on purpose, so a format added later counts as plain text only once
/// somebody says so.
/// </remarks>
/// <returns>True, when a text written as it is makes a valid file of the format.</returns>
public bool IsPlainText() => format is FileExportFormat.LATEX or FileExportFormat.MARKDOWN or FileExportFormat.HTML or FileExportFormat.CSV or FileExportFormat.TSV or FileExportFormat.SOURCE_CODE;
/// <value>True, when a text written as it is makes a valid file of the format.</value>
public bool IsPlainText => format is FileExportFormat.LATEX or FileExportFormat.MARKDOWN or FileExportFormat.HTML or FileExportFormat.CSV or FileExportFormat.TSV or FileExportFormat.SOURCE_CODE;
/// <summary>
/// Returns the file name the save dialog starts with.
@@ -138,14 +144,14 @@ public static class FileExportFormatExtensions
/// <param name="name">What the file is about, for example the heading above a table. Anything
/// a file name cannot hold is removed. Null or blank falls back to a generic name.</param>
/// <returns>The suggested file name, including its extension.</returns>
public string ToSuggestedFileName(string? name = null) => SuggestFileName(name, format.ToFileExtension());
public string ToSuggestedFileName(string? name = null) => SuggestFileName(name, format.FileExtension);
/// <summary>
/// Returns the filter which the save dialog offers for the format.
/// </summary>
/// <returns>The filter, or null when the format cannot be written or, as code does, takes the
/// filter from its language.</returns>
public FileTypeFilter? ToFileTypeFilter() => format switch
/// <value>The filter, or null when the format cannot be written or, as code does, takes the
/// filter from its language.</value>
public FileTypeFilter? FileTypeFilter => format switch
{
FileExportFormat.MICROSOFT_WORD => FileTypes.MS_WORD,
FileExportFormat.OPEN_DOCUMENT_TEXT => FileTypes.ODT,
@@ -167,8 +173,8 @@ public static class FileExportFormatExtensions
/// turns every umlaut into garbage. Text files get none: editors, compilers, and LaTeX have
/// no use for it and some of them stumble over it.
/// </remarks>
/// <returns>The encoding to write the file with.</returns>
public Encoding ToFileEncoding() => format switch
/// <value>The encoding to write the file with.</value>
public Encoding FileEncoding => format switch
{
FileExportFormat.CSV or FileExportFormat.TSV => WITH_BYTE_ORDER_MARK,
@@ -221,8 +227,8 @@ public static class FileExportFormatExtensions
/// which page it was stays in the title of the source. Verified on 2026-09-15 with LibreOffice
/// on an exported .odt. A format added later keeps the page unless it is known to stumble too.
/// </remarks>
/// <returns>True, when a reader of this format follows such a link.</returns>
public bool FollowsPageAnchors() => format switch
/// <value>True, when a reader of this format follows such a link.</value>
public bool FollowsPageAnchors => format switch
{
FileExportFormat.MICROSOFT_WORD or FileExportFormat.OPEN_DOCUMENT_TEXT => false,
@@ -238,14 +244,14 @@ public static class FileExportFormatExtensions
/// 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.
/// </remarks>
/// <returns>True, when a document of this format needs a title besides its content.</returns>
public bool NeedsPageTitle() => format is FileExportFormat.HTML;
/// <value>True, when a document of this format needs a title besides its content.</value>
public bool NeedsPageTitle => format is FileExportFormat.HTML;
/// <summary>
/// Returns the name Pandoc knows the format by.
/// </summary>
/// <returns>The Pandoc output format, or an empty string when AI Studio writes the file itself.</returns>
public string ToPandocOutputFormat() => format switch
/// <value>The Pandoc output format, or an empty string when AI Studio writes the file itself.</value>
public string PandocOutputFormat => format switch
{
FileExportFormat.MICROSOFT_WORD => "docx",
FileExportFormat.OPEN_DOCUMENT_TEXT => "odt",
@@ -258,39 +264,39 @@ public static class FileExportFormatExtensions
/// <summary>
/// Determines whether writing the format needs Pandoc.
/// </summary>
/// <returns>True, when Pandoc converts the message; false, when AI Studio writes the file itself.</returns>
public bool UsesPandoc() => !string.IsNullOrWhiteSpace(format.ToPandocOutputFormat());
}
/// <value>True, when Pandoc converts the message; false, when AI Studio writes the file itself.</value>
public bool UsesPandoc => !string.IsNullOrWhiteSpace(format.PandocOutputFormat);
/// <summary>
/// Reads which format a model means when it names a language behind the opening fence of a
/// code block.
/// </summary>
/// <remarks>
/// A model which answers with a finished file puts it into a code block and names its language,
/// as in ```html. Models do not agree on the spelling, so we accept the usual names of a format
/// in any case. Only formats which are plain text appear here: a code block holds text, never
/// a Word document. A block in any other language, or in none, is code, see
/// SourceCodeLanguages.FromCodeFenceLanguage.
/// </remarks>
/// <param name="language">The language behind the opening fence, as Markdig reads it into
/// FencedCodeBlock.Info.</param>
/// <param name="format">The format the language names, or NONE when it names none of ours.</param>
/// <returns>True, when the language names a format AI Studio writes.</returns>
public static bool TryFromCodeFenceLanguage(string? language, out FileExportFormat format)
{
format = language?.Trim().ToLowerInvariant() switch
/// <summary>
/// Reads which format a model means when it names a language behind the opening fence of a
/// code block.
/// </summary>
/// <remarks>
/// A model which answers with a finished file puts it into a code block and names its language,
/// as in ```html. Models do not agree on the spelling, so we accept the usual names of a format
/// in any case. Only formats which are plain text appear here: a code block holds text, never
/// a Word document. A block in any other language, or in none, is code, see
/// SourceCodeLanguages.FromCodeFenceLanguage.
/// </remarks>
/// <param name="language">The language behind the opening fence, as Markdig reads it into
/// FencedCodeBlock.Info.</param>
/// <param name="namedFormat">The format the language names, or NONE when it names none of ours.</param>
/// <returns>True, when the language names a format AI Studio writes.</returns>
public static bool TryFromCodeFenceLanguage(string? language, out FileExportFormat namedFormat)
{
"html" => FileExportFormat.HTML,
"latex" or "tex" => FileExportFormat.LATEX,
"markdown" or "md" => FileExportFormat.MARKDOWN,
"csv" => FileExportFormat.CSV,
"tsv" => FileExportFormat.TSV,
namedFormat = language?.Trim().ToLowerInvariant() switch
{
"html" => FileExportFormat.HTML,
"latex" or "tex" => FileExportFormat.LATEX,
"markdown" or "md" => FileExportFormat.MARKDOWN,
"csv" => FileExportFormat.CSV,
"tsv" => FileExportFormat.TSV,
_ => FileExportFormat.NONE,
};
_ => FileExportFormat.NONE,
};
return format is not FileExportFormat.NONE;
return namedFormat is not FileExportFormat.NONE;
}
}
/// <summary>