Last active
November 5, 2019 15:43
-
-
Save MihaZupan/51e6e30542f45e73f70e1fc6636a49b7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public const int NewLineWeight = 4; | |
public static void TrimDocument(MarkdownDocument document, int numberOfCharactersToKeep) | |
{ | |
TrimObject(document, ref numberOfCharactersToKeep); | |
} | |
private static void TrimObject(MarkdownObject obj, ref int charactersAvailable) | |
{ | |
if (obj is ContainerBlock containerBlock) | |
{ | |
int i; | |
for (i = 0; i < containerBlock.Count && charactersAvailable > 0; i++) | |
{ | |
TrimObject(containerBlock[i], ref charactersAvailable); | |
} | |
for (int removeIndex = containerBlock.Count - 1; removeIndex >= i; removeIndex--) | |
{ | |
containerBlock.RemoveAt(removeIndex); | |
} | |
} | |
else if (obj is ContainerInline containerInline) | |
{ | |
var inline = containerInline.FirstChild; | |
while (inline != null && charactersAvailable > 0) | |
{ | |
TrimObject(inline, ref charactersAvailable); | |
inline = inline.NextSibling; | |
} | |
if (charactersAvailable <= 0) | |
{ | |
while (inline != null) | |
{ | |
var next = inline.NextSibling; | |
inline.Remove(); | |
inline = next; | |
} | |
} | |
} | |
else if (obj is LeafBlock leafBlock) | |
{ | |
if (leafBlock.Inline != null) | |
{ | |
TrimObject(leafBlock.Inline, ref charactersAvailable); | |
} | |
ref var lines = ref leafBlock.Lines; | |
var stringLines = lines.Lines; | |
if (stringLines != null) | |
{ | |
int i; | |
for (i = 0; i < lines.Count && charactersAvailable > 0; i++) | |
{ | |
TrimStringSlice(ref stringLines[i].Slice, ref charactersAvailable); | |
charactersAvailable -= NewLineWeight; | |
} | |
for (int removeIndex = lines.Count - 1; removeIndex >= i; removeIndex--) | |
{ | |
lines.RemoveAt(removeIndex); | |
} | |
} | |
charactersAvailable -= NewLineWeight; | |
} | |
else if (obj is LeafInline leafInline) | |
{ | |
if (leafInline is LiteralInline literal) | |
{ | |
TrimStringSlice(ref literal.Content, ref charactersAvailable); | |
} | |
else if (leafInline is CodeInline code) | |
{ | |
code.Content = TrimString(code.Content, ref charactersAvailable); | |
} | |
else if (leafInline is AutolinkInline autoLink) | |
{ | |
autoLink.Url = TrimString(autoLink.Url, ref charactersAvailable); | |
} | |
else if (leafInline is LineBreakInline) | |
{ | |
charactersAvailable -= NewLineWeight; | |
} | |
} | |
} | |
private static void TrimStringSlice(ref StringSlice slice, ref int charactersAvailable) | |
{ | |
if (slice.IsEmpty) | |
{ | |
return; | |
} | |
else if (charactersAvailable <= 0) | |
{ | |
slice = new StringSlice(null); | |
} | |
else | |
{ | |
var span = slice.Text.AsSpan(slice.Start, slice.Length); | |
var trimmed = TrimSpan(span, ref charactersAvailable); | |
slice.End = slice.Start + trimmed.Length - 1; | |
} | |
} | |
private static string TrimString(string text, ref int charactersAvailable) | |
{ | |
if (string.IsNullOrEmpty(text)) | |
{ | |
return text; | |
} | |
else if (charactersAvailable <= 0) | |
{ | |
return string.Empty; | |
} | |
else | |
{ | |
var span = TrimSpan(text.AsSpan(), ref charactersAvailable); | |
return span.Length == text.Length ? text : span.ToString(); | |
} | |
} | |
private static ReadOnlySpan<char> TrimSpan(ReadOnlySpan<char> span, ref int charactersAvailable) | |
{ | |
int i = 0; | |
while (i < span.Length && charactersAvailable > 0) | |
{ | |
int nextLine = span.Slice(i).IndexOf('\n'); | |
int lineLength = nextLine == -1 ? span.Length - i : nextLine - i; | |
if (lineLength <= charactersAvailable) | |
{ | |
i += lineLength; | |
charactersAvailable -= lineLength; | |
if (charactersAvailable > NewLineWeight && nextLine != -1) | |
{ | |
i++; | |
charactersAvailable -= NewLineWeight; | |
} | |
else | |
{ | |
if (nextLine != -1) | |
{ | |
charactersAvailable = 0; | |
} | |
break; | |
}; | |
} | |
else | |
{ | |
i += charactersAvailable; | |
charactersAvailable = 0; | |
} | |
} | |
return span.Slice(0, i); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment