2using System.Collections.Generic;
5using System.Threading.Tasks;
17 private string caption;
19 private int nrColumns;
20 private int nrHeaderRows;
21 private int nrCellRows;
22 private readonly Dictionary<string, int> columnIndices =
new Dictionary<string, int>();
23 private readonly Dictionary<long, MarkdownElement> headers =
new Dictionary<long, MarkdownElement>();
24 private readonly Dictionary<long, MarkdownElement> cells =
new Dictionary<long, MarkdownElement>();
25 private readonly Dictionary<long, TextAlignment?> headerAlignments =
new Dictionary<long, TextAlignment?>();
26 private readonly Dictionary<long, TextAlignment?> cellAlignments =
new Dictionary<long, TextAlignment?>();
27 private readonly Dictionary<int, TextAlignment> columnAlignments =
new Dictionary<int, TextAlignment>();
28 private readonly Dictionary<int, string> sources =
new Dictionary<int, string>();
29 private readonly SemaphoreSlim synchObj =
new SemaphoreSlim(1);
37 this.nrColumns = MarkdownTable.
Columns;
38 this.nrHeaderRows = MarkdownTable.
Headers.Length;
39 this.nrCellRows = MarkdownTable.
Rows.Length;
40 this.caption = MarkdownTable.
Caption;
41 this.id = MarkdownTable.
Id;
50 public static async Task<ConsolidatedTable>
CreateAsync(
string Source,
Table MarkdownTable)
59 for (ColumnIndex = 0; ColumnIndex <
NrColumns; ColumnIndex++)
61 Result.columnIndices[await Result.GetHeaderKey(MarkdownTable.
Headers, ColumnIndex)] = ColumnIndex;
62 Result.columnAlignments[ColumnIndex] = MarkdownTable.
ColumnAlignments[ColumnIndex];
65 for (RowIndex = 0, NrRows = MarkdownTable.
Headers.Length; RowIndex < NrRows; RowIndex++)
67 Row = MarkdownTable.
Headers[RowIndex];
70 for (ColumnIndex = 0; ColumnIndex <
NrColumns; ColumnIndex++)
72 l = (((long)RowIndex) << 32) + ColumnIndex;
73 Result.headers[l] = Row[ColumnIndex];
74 Result.headerAlignments[l] = CellAlignments[ColumnIndex];
78 for (RowIndex = 0, NrRows = MarkdownTable.
Headers.Length; RowIndex < NrRows; RowIndex++)
80 Row = MarkdownTable.
Rows[RowIndex];
83 for (ColumnIndex = 0; ColumnIndex <
NrColumns; ColumnIndex++)
85 l = (((long)RowIndex) << 32) + ColumnIndex;
86 Result.cells[l] = Row[ColumnIndex];
87 Result.cellAlignments[l] = CellAlignments[ColumnIndex];
90 Result.sources[ColumnIndex] = Source;
96 private async Task<string> GetHeaderKey(
MarkdownElement[][] Headers,
int ColumnIndex)
98 StringBuilder sb =
new StringBuilder();
108 if (ColumnIndex < Row.Length)
109 await Row[ColumnIndex].GenerateMarkdown(sb);
126 await this.synchObj.WaitAsync();
129 return this.nrColumns;
133 this.synchObj.Release();
148 await this.synchObj.WaitAsync();
151 return this.nrHeaderRows;
155 this.synchObj.Release();
170 await this.synchObj.WaitAsync();
173 return this.nrCellRows;
177 this.synchObj.Release();
188 await this.synchObj.WaitAsync();
191 if (Column < 0 || Column > this.nrColumns)
192 throw new ArgumentOutOfRangeException(
"Invalid column.", nameof(Column));
198 this.synchObj.Release();
207 public async Task
Add(
string Source,
Table MarkdownTable)
209 await this.synchObj.WaitAsync();
212 if (this.caption != MarkdownTable.
Caption)
213 this.caption =
string.Empty;
215 if (this.
id != MarkdownTable.
Id)
216 this.id =
string.Empty;
218 if (MarkdownTable.
Headers.Length >
this.nrHeaderRows)
219 this.nrHeaderRows = MarkdownTable.
Headers.Length;
223 int[] Indices =
new int[MarkdownTable.
Columns];
225 int RowIndex, NrRows;
232 Key = await this.GetHeaderKey(MarkdownTable.
Headers, i);
234 if (!this.columnIndices.TryGetValue(Key, out i2))
236 i2 = this.nrColumns++;
237 this.columnIndices[Key] = i2;
238 this.columnAlignments[i2] = Alignment;
240 for (RowIndex = 0, NrRows = MarkdownTable.
Headers.Length; RowIndex < NrRows; RowIndex++)
242 Row = MarkdownTable.
Headers[RowIndex];
245 l = (((long)RowIndex) << 32) + i2;
246 this.headers[l] = Row[i];
247 this.headerAlignments[l] = CellAlignments[i];
255 i2 = this.nrCellRows;
257 this.nrCellRows += MarkdownTable.
Rows.Length;
259 for (RowIndex = 0, NrRows = MarkdownTable.
Rows.Length; RowIndex < NrRows; RowIndex++)
261 Row = MarkdownTable.
Rows[RowIndex];
268 l = (((long)i2) << 32) + j2;
269 this.cells[l] = Element;
270 this.cellAlignments[l] = CellAlignments[j];
275 this.sources[i2++] = Source;
280 this.synchObj.Release();
288 public async Task
Export(StringBuilder Markdown)
290 await this.synchObj.WaitAsync();
297 for (i = 0; i < this.nrHeaderRows; i++)
299 Markdown.Append(
"| Nr | Source |");
301 for (j = 0; j < this.nrColumns; j++)
303 l = (((long)i) << 32) + j;
305 if (!this.headerAlignments.TryGetValue(l, out CellAlignment))
306 CellAlignment =
null;
311 Markdown.Append(
'|');
314 Markdown.Append(
' ');
316 if (CellAlignment.HasValue)
318 switch (CellAlignment.Value)
321 Markdown.Append(
"<<");
322 await E.GenerateMarkdown(Markdown);
326 Markdown.Append(
">>");
327 await E.GenerateMarkdown(Markdown);
328 Markdown.Append(
"<<");
332 await E.GenerateMarkdown(Markdown);
333 Markdown.Append(
">>");
337 await E.GenerateMarkdown(Markdown);
342 await E.GenerateMarkdown(Markdown);
344 Markdown.Append(
" |");
348 Markdown.Append(
" |");
351 Markdown.AppendLine();
354 Markdown.Append(
"|--:|:--|");
356 for (j = 0; j < this.nrColumns; j++)
358 if (!this.columnAlignments.TryGetValue(j, out
TextAlignment Alignment))
364 Markdown.Append(
":--|");
368 Markdown.Append(
"--:|");
372 Markdown.Append(
":-:|");
376 Markdown.Append(
"---|");
381 Markdown.AppendLine();
383 for (i = 0; i < this.nrCellRows; i++)
385 Markdown.Append(
"| ");
386 Markdown.Append((i + 1).ToString());
387 Markdown.Append(
" | `");
389 if (this.sources.TryGetValue(i, out
string Source))
390 Markdown.Append(Source);
392 Markdown.Append(
"` |");
394 for (j = 0; j < this.nrColumns; j++)
396 l = (((long)i) << 32) + j;
398 if (!this.cellAlignments.TryGetValue(l, out CellAlignment))
399 CellAlignment =
null;
404 Markdown.Append(
'|');
407 Markdown.Append(
' ');
409 if (CellAlignment.HasValue)
411 switch (CellAlignment.Value)
414 Markdown.Append(
"<<");
415 await E.GenerateMarkdown(Markdown);
419 Markdown.Append(
">>");
420 await E.GenerateMarkdown(Markdown);
421 Markdown.Append(
"<<");
425 await E.GenerateMarkdown(Markdown);
426 Markdown.Append(
">>");
430 await E.GenerateMarkdown(Markdown);
435 await E.GenerateMarkdown(Markdown);
437 Markdown.Append(
" |");
441 Markdown.Append(
" |");
444 Markdown.AppendLine();
449 this.synchObj.Release();
Represents a consolidated table.
Task< int > NrCellRows
Number of cell rows.
async Task Export(StringBuilder Markdown)
Exports the consolidated table to Markdown.
async Task< TextAlignment > GetAlignment(int Column)
Gets the alignment of a column.
async Task< int > GetNrColumns()
Gets the number of columns.
Task< int > NrHeaderRows
Number of header rows.
async Task< int > GetNrCellRows()
Gets the number of cell rows.
async Task Add(string Source, Table MarkdownTable)
Adds data from a Markdown table to the consolidated table.
static async Task< ConsolidatedTable > CreateAsync(string Source, Table MarkdownTable)
Creates a consolidated table.
Task< int > NrColumns
Number of columns.
async Task< int > GetNrHeaderRows()
Gets the number of header rows.
Represents a table in a markdown document.
TextAlignment[] ColumnAlignments
Table column alignments.
string Caption
Table caption.
MarkdownElement[][] Headers
Headers in table.
int Columns
Number of columns.
TextAlignment?[][] RowCellAlignments
Row cell alignments in table.
TextAlignment?[][] HeaderCellAlignments
Header cell alignments in table.
MarkdownElement[][] Rows
Rows in table.
Abstract base class for all markdown elements.
override string ToString()
TextAlignment
Text alignment of contents.