Compare commits
2 Commits
397aa47217
...
fb5eacea02
| Author | SHA1 | Date | |
|---|---|---|---|
| fb5eacea02 | |||
|
9fd3a55182
|
@@ -1,59 +1,73 @@
|
|||||||
|
using System;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace Slang;
|
namespace Slang;
|
||||||
|
|
||||||
public static class TextMeshProFormatter
|
public static class TextMeshProFormatter
|
||||||
{
|
{
|
||||||
private const string CODE_COLOR = "#FFD700";
|
private const string CODE_COLOR = "#FFD700"; // Gold
|
||||||
|
private const string LINK_COLOR = "#0099FF"; // Blue
|
||||||
|
private const string QUOTE_COLOR = "#90EE90"; // Light Green
|
||||||
|
|
||||||
public static string FromMarkdown(string markdown)
|
public static string FromMarkdown(string markdown)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(markdown))
|
if (string.IsNullOrEmpty(markdown))
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
// 1. Normalize Line Endings
|
// Normalize Line Endings
|
||||||
string text = markdown.Replace("\r\n", "\n");
|
string text = markdown.Replace("\r\n", "\n");
|
||||||
|
|
||||||
// 2. Handle Code Blocks (```)
|
// Process code blocks FIRST (``` ... ```)
|
||||||
text = Regex.Replace(
|
text = Regex.Replace(
|
||||||
text,
|
text,
|
||||||
@"```\s*(.*?)\s*```",
|
@"```[^\n]*\n(.*?)\n```",
|
||||||
match =>
|
match =>
|
||||||
{
|
{
|
||||||
var codeContent = match.Groups[1].Value;
|
var codeContent = match.Groups[1].Value;
|
||||||
return $"<color={CODE_COLOR}>{codeContent}</color>"; // Gold color for code
|
return $"<color={CODE_COLOR}>{codeContent}</color>";
|
||||||
},
|
},
|
||||||
RegexOptions.Singleline
|
RegexOptions.Singleline
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Process headers - check for 1-6 hashes
|
||||||
|
text = Regex.Replace(text, @"^#{1}\s+(.+)$", "<size=120%><b>$1</b></size>", RegexOptions.Multiline);
|
||||||
|
text = Regex.Replace(text, @"^#{2}\s+(.+)$", "<size=110%><b>$1</b></size>", RegexOptions.Multiline);
|
||||||
|
text = Regex.Replace(text, @"^#{3}\s+(.+)$", "<size=100%><b>$1</b></size>", RegexOptions.Multiline);
|
||||||
|
text = Regex.Replace(text, @"^#{4}\s+(.+)$", "<size=90%><b>$1</b></size>", RegexOptions.Multiline);
|
||||||
|
text = Regex.Replace(text, @"^#{5}\s+(.+)$", "<size=80%><b>$1</b></size>", RegexOptions.Multiline);
|
||||||
|
text = Regex.Replace(text, @"^#{6}\s+(.+)$", "<size=70%><b>$1</b></size>", RegexOptions.Multiline);
|
||||||
|
|
||||||
|
// Process markdown links [text](url)
|
||||||
text = Regex.Replace(
|
text = Regex.Replace(
|
||||||
text,
|
text,
|
||||||
@"^\s*##\s+(.+)$",
|
@"\[([^\]]+)\]\(([^\)]+)\)",
|
||||||
"<size=110%><color=#ffffff><b>$1</b></color></size>",
|
$"<color={LINK_COLOR}><u>$1</u></color>"
|
||||||
RegexOptions.Multiline
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// 3. Handle # Headers SECOND (General)
|
// Process inline code (`code`)
|
||||||
text = Regex.Replace(
|
|
||||||
text,
|
|
||||||
@"^\s*#\s+(.+)$",
|
|
||||||
"<size=120%><color=#ffffff><b>$1</b></color></size>",
|
|
||||||
RegexOptions.Multiline
|
|
||||||
);
|
|
||||||
|
|
||||||
// 4. Handle Inline Code (`code`)
|
|
||||||
text = Regex.Replace(text, @"`([^`]+)`", $"<color={CODE_COLOR}>$1</color>");
|
text = Regex.Replace(text, @"`([^`]+)`", $"<color={CODE_COLOR}>$1</color>");
|
||||||
|
|
||||||
// 5. Handle Bold (**text**)
|
// Process bold (**text**)
|
||||||
text = Regex.Replace(text, @"\*\*(.+?)\*\*", "<b>$1</b>");
|
text = Regex.Replace(text, @"\*\*(.+?)\*\*", "<b>$1</b>");
|
||||||
|
|
||||||
// 6. Handle Italics (*text*)
|
// Process italics (*text*)
|
||||||
text = Regex.Replace(text, @"\*(.+?)\*", "<i>$1</i>");
|
text = Regex.Replace(text, @"(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)", "<i>$1</i>");
|
||||||
|
|
||||||
// 7. Convert Newlines to TMP Line Breaks
|
// Process block quotes (> text)
|
||||||
// Stationpedia needs <br> or explicit newlines.
|
text = Regex.Replace(
|
||||||
// Often just ensuring \n is preserved is enough, but <br> is safer for HTML-like parsers.
|
text,
|
||||||
text = text.Replace("\n", "<br>");
|
@"^>\s+(.+)$",
|
||||||
|
$"<color={QUOTE_COLOR}><i>$1</i></color>",
|
||||||
|
RegexOptions.Multiline
|
||||||
|
);
|
||||||
|
|
||||||
|
// Process unordered lists (- items)
|
||||||
|
text = Regex.Replace(
|
||||||
|
text,
|
||||||
|
@"^-\s+(.+)$",
|
||||||
|
" • $1",
|
||||||
|
RegexOptions.Multiline
|
||||||
|
);
|
||||||
|
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use crc32fast::hash as crc32_hash;
|
use crc32fast::hash as crc32_hash;
|
||||||
|
|
||||||
/// This function takes an input which is meant to be hashed via the CRC32 algorithm, but it then
|
/// This function takes an input which is meant to be hashed via the CRC32 algorithm, but it then
|
||||||
/// converts the generated UNSIGNED number into it's SIGNED counterpart.
|
/// converts the generated UNSIGNED number into it's SIGNED counterpart.
|
||||||
pub fn crc_hash_signed(input: &str) -> i128 {
|
pub fn crc_hash_signed(input: &str) -> i128 {
|
||||||
@@ -9,3 +10,38 @@ pub fn crc_hash_signed(input: &str) -> i128 {
|
|||||||
|
|
||||||
hash_value_i32 as i128
|
hash_value_i32 as i128
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Removes common leading whitespace from all lines in a string (dedent).
|
||||||
|
/// This is useful for cleaning up documentation strings that have uniform indentation.
|
||||||
|
pub fn dedent(text: &str) -> String {
|
||||||
|
let lines: Vec<&str> = text.lines().collect();
|
||||||
|
|
||||||
|
// Find minimum indentation (excluding empty lines)
|
||||||
|
let mut min_indent = usize::MAX;
|
||||||
|
for line in &lines {
|
||||||
|
if !line.trim().is_empty() {
|
||||||
|
let indent = line.len() - line.trim_start().len();
|
||||||
|
min_indent = min_indent.min(indent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no lines or all empty, return as-is
|
||||||
|
if min_indent == usize::MAX {
|
||||||
|
return text.to_string();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the common indentation
|
||||||
|
lines
|
||||||
|
.iter()
|
||||||
|
.map(|line| {
|
||||||
|
if line.trim().is_empty() {
|
||||||
|
""
|
||||||
|
} else if line.len() >= min_indent {
|
||||||
|
&line[min_indent..]
|
||||||
|
} else {
|
||||||
|
line
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join("\n")
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
mod helper_funcs;
|
mod helper_funcs;
|
||||||
|
pub use helper_funcs::dedent;
|
||||||
mod macros;
|
mod macros;
|
||||||
mod syscall;
|
mod syscall;
|
||||||
|
|
||||||
|
|||||||
@@ -99,12 +99,12 @@ macro_rules! documented {
|
|||||||
),*
|
),*
|
||||||
];
|
];
|
||||||
|
|
||||||
doc_lines.iter()
|
let combined = doc_lines.iter()
|
||||||
.filter_map(|&d| d)
|
.filter_map(|&d| d)
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join("\n")
|
.join("\n");
|
||||||
.trim()
|
|
||||||
.to_string()
|
$crate::dedent(&combined).trim().to_string()
|
||||||
}
|
}
|
||||||
)*
|
)*
|
||||||
}
|
}
|
||||||
@@ -122,12 +122,13 @@ macro_rules! documented {
|
|||||||
documented!(@doc_filter #[ $($variant_attr)* ])
|
documented!(@doc_filter #[ $($variant_attr)* ])
|
||||||
),*
|
),*
|
||||||
];
|
];
|
||||||
doc_lines.iter()
|
|
||||||
|
let combined = doc_lines.iter()
|
||||||
.filter_map(|&d| d)
|
.filter_map(|&d| d)
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join("\n")
|
.join("\n");
|
||||||
.trim()
|
|
||||||
.to_string()
|
$crate::dedent(&combined).trim().to_string()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
),*
|
),*
|
||||||
@@ -136,4 +137,3 @@ macro_rules! documented {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user