feat: render a table given a definition
This commit is contained in:
parent
21714ee614
commit
db599fa123
@ -10,7 +10,8 @@
|
||||
}
|
||||
|
||||
.App {
|
||||
background-color: #282c34;
|
||||
background-color: #1E1E1E;
|
||||
color: #CAD6DC;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
37
src/App.tsx
37
src/App.tsx
@ -1,15 +1,16 @@
|
||||
import React, { useState } from 'react';
|
||||
import './App.css';
|
||||
import TableMethodCode from './TableMethodCode';
|
||||
|
||||
export interface TableDefinition {
|
||||
names?: string[]
|
||||
fields?: (string|undefined)[]
|
||||
widths?: (number|undefined)[]
|
||||
alighments?: ("left"|"right")[]
|
||||
}
|
||||
import TableMethodCodeBlock from './TableMethodCodeBlock';
|
||||
import { TableDefinition } from './TableMethodGenerator';
|
||||
import TableRenderer from './TableRenderer';
|
||||
|
||||
function App() {
|
||||
let definition: TableDefinition = {
|
||||
names: ["Miestas", "Atsakingas", "Vardas", "Adresas", "Metai"],
|
||||
fields: ["City", "Manager", "Name", "Address", "Year"],
|
||||
widths: [10, 20, 18, 15, 5],
|
||||
alignments: ["left", "left", "left", "left", "right"]
|
||||
}
|
||||
|
||||
let data = {
|
||||
method_name: "PrintLocations",
|
||||
empty_message: "Nėra",
|
||||
@ -18,17 +19,23 @@ function App() {
|
||||
entry_name: "l",
|
||||
entry_type: "Location",
|
||||
|
||||
definition: {
|
||||
names: ["Miestas", "Atsakingas", "Vardas", "Adresas", "Metai"],
|
||||
fields: ["City", "Manager", "Name", "Address", "Year"],
|
||||
widths: [10, 20, 18, 15, 5]
|
||||
}
|
||||
definition
|
||||
};
|
||||
|
||||
let test_entries = [
|
||||
["Alytus", "AlytausMuziejusA", "Jonas Jonaitis", "GatveA", "1999"],
|
||||
["Alytus", "AlytausMuziejusB", "Ona Onaite", "GatveB", "2018"],
|
||||
["Kaunas", "KaunasMuziejusC", "Jonas Jonaitis", "GatveC", "2004"],
|
||||
["Klaipėda", "KlaipėdaMuziejusD", "Ona Onaite", "GatveD", "1988"],
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="App">
|
||||
{TableMethodCode(data)}
|
||||
<main>
|
||||
<hr />
|
||||
{TableMethodCodeBlock(data)}
|
||||
<hr />
|
||||
<TableRenderer definition={definition} entries={test_entries} />
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
|
@ -1,103 +0,0 @@
|
||||
import SyntaxHighlighter from 'react-syntax-highlighter';
|
||||
import { docco } from 'react-syntax-highlighter/dist/esm/styles/hljs';
|
||||
import { TableDefinition } from './App';
|
||||
|
||||
export interface TableMethodGeneratorProps {
|
||||
definition: TableDefinition
|
||||
|
||||
method_name?: string
|
||||
empty_message?: string
|
||||
|
||||
container_type?: string
|
||||
container_name?: string
|
||||
entry_type?: string
|
||||
entry_name?: string
|
||||
}
|
||||
|
||||
function generateTableMethod(props: TableMethodGeneratorProps): string {
|
||||
const section_names = props.definition.names || []
|
||||
const method_name = props.method_name || "PrintTable"
|
||||
if (section_names.length == 0) {
|
||||
return `static void ${method_name}()\n{\n}`;
|
||||
}
|
||||
|
||||
const empty_message = props.empty_message || "Empty"
|
||||
const container_name = props.container_name || "container"
|
||||
const container_type = props.container_type || "Container"
|
||||
const entry_name = props.entry_name || "e"
|
||||
const entry_type = props.entry_type || "Entry"
|
||||
const section_widths = props.definition.widths || []
|
||||
const section_alignments = props.definition.alighments || []
|
||||
const section_fields = props.definition.fields || []
|
||||
|
||||
// Total width
|
||||
let total_width = 0
|
||||
for (let i = 0; i < section_names.length; i++) {
|
||||
const section = section_names[i]
|
||||
total_width += section_widths[i] || section.length
|
||||
}
|
||||
total_width += 2 + 2;
|
||||
total_width += 3*(section_names.length-1);
|
||||
|
||||
// Table row
|
||||
let row_components: string[] = []
|
||||
for (let i = 0; i < section_names.length; i++) {
|
||||
const section = section_names[i]
|
||||
const width = section_widths[i] || section.length
|
||||
const alighment = section_alignments[i] || "right"
|
||||
if (alighment == "left") {
|
||||
row_components.push(`{${i},-${width}}`)
|
||||
} else {
|
||||
row_components.push(`{${i},${width}}`)
|
||||
}
|
||||
}
|
||||
|
||||
let table_row = "";
|
||||
if (row_components.length > 0) {
|
||||
table_row = "| " + row_components.join(" | ") + " |"
|
||||
}
|
||||
|
||||
// Section names
|
||||
const joined_names = section_names.map((n) => `"${n}"`).join(", ")
|
||||
|
||||
// Section fields
|
||||
const formatted_fields = []
|
||||
for (let i = 0; i < section_names.length; i++) {
|
||||
if (section_fields[i]) {
|
||||
formatted_fields.push(`${entry_name}.${section_fields[i]}`)
|
||||
} else {
|
||||
formatted_fields.push(`"-"`)
|
||||
}
|
||||
}
|
||||
const joined_fields = formatted_fields.join(", ")
|
||||
|
||||
// Final code string
|
||||
return `static void ${method_name}(${container_type} ${container_name})\n{
|
||||
if (${container_name}.Count == 0)
|
||||
{
|
||||
Console.WriteLine("${empty_message}");
|
||||
return;
|
||||
}
|
||||
|
||||
Console.WriteLine(new string('-', ${total_width}));
|
||||
Console.WriteLine("${table_row}", ${joined_names});
|
||||
Console.WriteLine(new string('-', ${total_width}));
|
||||
for (int i = 0; i < ${container_name}.Count; i++)
|
||||
{
|
||||
${entry_type} ${entry_name} = ${container_name}.Get(i);
|
||||
Console.WriteLine("${table_row}", ${joined_fields});
|
||||
}
|
||||
Console.WriteLine(new string('-', ${total_width}));\n}`;
|
||||
}
|
||||
|
||||
function TableMethodCode(props: TableMethodGeneratorProps) {
|
||||
return (
|
||||
<div>
|
||||
<SyntaxHighlighter language="csharp" style={docco}>
|
||||
{generateTableMethod(props)}
|
||||
</SyntaxHighlighter>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default TableMethodCode
|
16
src/TableMethodCodeBlock.tsx
Normal file
16
src/TableMethodCodeBlock.tsx
Normal file
@ -0,0 +1,16 @@
|
||||
import { Light as SyntaxHighlighter } from 'react-syntax-highlighter';
|
||||
import csharp from 'react-syntax-highlighter/dist/esm/languages/hljs/csharp';
|
||||
import { vs2015 } from 'react-syntax-highlighter/dist/esm/styles/hljs';
|
||||
import { generate, TableMethodGeneratorOptions } from './TableMethodGenerator';
|
||||
|
||||
SyntaxHighlighter.registerLanguage('csharp', csharp);
|
||||
|
||||
function TableMethodCodeBlock(props: TableMethodGeneratorOptions) {
|
||||
return (
|
||||
<SyntaxHighlighter language="csharp" style={vs2015}>
|
||||
{generate(props)}
|
||||
</SyntaxHighlighter>
|
||||
)
|
||||
}
|
||||
|
||||
export default TableMethodCodeBlock
|
146
src/TableMethodGenerator.ts
Normal file
146
src/TableMethodGenerator.ts
Normal file
@ -0,0 +1,146 @@
|
||||
type Alignment = "left"|"right"
|
||||
|
||||
export interface TableDefinition {
|
||||
names?: string[]
|
||||
fields?: (string|undefined)[]
|
||||
widths?: (number|undefined)[]
|
||||
alignments?: (Alignment|undefined)[]
|
||||
}
|
||||
|
||||
export interface TableMethodGeneratorOptions {
|
||||
definition: TableDefinition
|
||||
|
||||
method_name?: string
|
||||
empty_message?: string
|
||||
|
||||
container_type?: string
|
||||
container_name?: string
|
||||
entry_type?: string
|
||||
entry_name?: string
|
||||
}
|
||||
|
||||
function get_total_width(definition: TableDefinition): number {
|
||||
let names = definition.names || []
|
||||
if (names.length == 0) { return 0; }
|
||||
|
||||
let total_width = 0
|
||||
let widths = definition.widths || []
|
||||
for (let i = 0; i < names.length; i++) {
|
||||
const name = names[i]
|
||||
total_width += widths[i] || name.length
|
||||
}
|
||||
total_width += 2 + 2;
|
||||
total_width += 3*(names.length-1);
|
||||
|
||||
return total_width;
|
||||
}
|
||||
|
||||
export function generate(options: TableMethodGeneratorOptions): string {
|
||||
const section_names = options.definition.names || []
|
||||
const method_name = options.method_name || "PrintTable"
|
||||
if (section_names.length == 0) {
|
||||
return `static void ${method_name}()\n{\n}`;
|
||||
}
|
||||
|
||||
const empty_message = options.empty_message || "Empty"
|
||||
const container_name = options.container_name || "container"
|
||||
const container_type = options.container_type || "Container"
|
||||
const entry_name = options.entry_name || "e"
|
||||
const entry_type = options.entry_type || "Entry"
|
||||
const section_widths = options.definition.widths || []
|
||||
const section_alignments = options.definition.alignments || []
|
||||
const section_fields = options.definition.fields || []
|
||||
|
||||
// Total width
|
||||
const total_width = get_total_width(options.definition)
|
||||
|
||||
// Table row
|
||||
let row_components: string[] = []
|
||||
for (let i = 0; i < section_names.length; i++) {
|
||||
const section = section_names[i]
|
||||
const width = section_widths[i] || section.length
|
||||
const alighment = section_alignments[i] || "right"
|
||||
if (alighment == "left") {
|
||||
row_components.push(`{${i},-${width}}`)
|
||||
} else {
|
||||
row_components.push(`{${i},${width}}`)
|
||||
}
|
||||
}
|
||||
|
||||
let table_row = "";
|
||||
if (row_components.length > 0) {
|
||||
table_row = "| " + row_components.join(" | ") + " |"
|
||||
}
|
||||
|
||||
// Section names
|
||||
const joined_names = section_names.map((n) => `"${n}"`).join(", ")
|
||||
|
||||
// Section fields
|
||||
const formatted_fields = []
|
||||
for (let i = 0; i < section_names.length; i++) {
|
||||
if (section_fields[i]) {
|
||||
formatted_fields.push(`${entry_name}.${section_fields[i]}`)
|
||||
} else {
|
||||
formatted_fields.push(`"-"`)
|
||||
}
|
||||
}
|
||||
const joined_fields = formatted_fields.join(", ")
|
||||
|
||||
// Final code string
|
||||
return `static void ${method_name}(${container_type} ${container_name})\n{
|
||||
if (${container_name}.Count == 0)
|
||||
{
|
||||
Console.WriteLine("${empty_message}");
|
||||
return;
|
||||
}
|
||||
|
||||
Console.WriteLine(new string('-', ${total_width}));
|
||||
Console.WriteLine("${table_row}", ${joined_names});
|
||||
Console.WriteLine(new string('-', ${total_width}));
|
||||
for (int i = 0; i < ${container_name}.Count; i++)
|
||||
{
|
||||
${entry_type} ${entry_name} = ${container_name}.Get(i);
|
||||
Console.WriteLine("${table_row}", ${joined_fields});
|
||||
}
|
||||
Console.WriteLine(new string('-', ${total_width}));\n}`;
|
||||
}
|
||||
|
||||
function render_table_row(definition: TableDefinition, entry: string[]): string {
|
||||
let names = definition.names || []
|
||||
if (names.length == 0) { return ""; }
|
||||
|
||||
const columns: string[] = []
|
||||
const alighments = definition.alignments || []
|
||||
const widths = definition.widths || []
|
||||
for (let i = 0; i < names.length; i++) {
|
||||
const value = entry[i] || "";
|
||||
const alighment = alighments[i] || "right"
|
||||
const width = widths[i] || names[i].length
|
||||
|
||||
const filler = " ".repeat(Math.max(width - value.length, 0));
|
||||
if (alighment == "left") {
|
||||
columns.push(value + filler);
|
||||
} else {
|
||||
columns.push(filler + value);
|
||||
}
|
||||
}
|
||||
return "| " + columns.join(" | ") + " |"
|
||||
}
|
||||
|
||||
export function render_table(definition: TableDefinition, entries: string[][]): string {
|
||||
if (!definition.names) {return ""; }
|
||||
|
||||
const total_width = get_total_width(definition)
|
||||
const seperator = "-".repeat(total_width)
|
||||
|
||||
const lines = []
|
||||
lines.push(seperator)
|
||||
lines.push(render_table_row(definition, definition.names))
|
||||
lines.push(seperator)
|
||||
for (let i = 0; i < entries.length; i++) {
|
||||
lines.push(render_table_row(definition, entries[i]))
|
||||
}
|
||||
lines.push(seperator)
|
||||
|
||||
return lines.join("\n")
|
||||
}
|
16
src/TableRenderer.tsx
Normal file
16
src/TableRenderer.tsx
Normal file
@ -0,0 +1,16 @@
|
||||
import { render_table, TableDefinition } from "./TableMethodGenerator"
|
||||
|
||||
export interface TableRendererProps {
|
||||
definition: TableDefinition,
|
||||
entries: string[][]
|
||||
}
|
||||
|
||||
function TableRenderer(props: TableRendererProps) {
|
||||
return (
|
||||
<pre>
|
||||
{render_table(props.definition, props.entries)}
|
||||
</pre>
|
||||
)
|
||||
}
|
||||
|
||||
export default TableRenderer
|
Loading…
Reference in New Issue
Block a user