-
-
Notifications
You must be signed in to change notification settings - Fork 5.4k
Expand file tree
/
Copy pathmarkdown-table-generator.vue
More file actions
129 lines (117 loc) · 3.89 KB
/
Copy pathmarkdown-table-generator.vue
File metadata and controls
129 lines (117 loc) · 3.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
<script setup lang="ts">
import {
type MarkdownTableAlignment,
createMarkdownTable,
generateMarkdownTable,
} from './markdown-table-generator.service';
import TextareaCopyable from '@/components/TextareaCopyable.vue';
const table = ref(createMarkdownTable());
const alignmentOptions: { label: string; value: MarkdownTableAlignment }[] = [
{ label: 'Left', value: 'left' },
{ label: 'Center', value: 'center' },
{ label: 'Right', value: 'right' },
];
const output = computed(() => generateMarkdownTable(table.value));
function addColumn() {
const columnNumber = table.value.headers.length + 1;
table.value.headers.push(`Column ${columnNumber}`);
table.value.alignments.push('left');
table.value.rows.forEach(row => row.push(''));
}
function removeColumn(index: number) {
if (table.value.headers.length <= 1) {
return;
}
table.value.headers.splice(index, 1);
table.value.alignments.splice(index, 1);
table.value.rows.forEach(row => row.splice(index, 1));
}
function addRow() {
table.value.rows.push(Array.from({ length: table.value.headers.length }, () => ''));
}
function removeRow(index: number) {
if (table.value.rows.length <= 1) {
return;
}
table.value.rows.splice(index, 1);
}
</script>
<template>
<div>
<c-card>
<div mb-4 flex flex-wrap items-center gap-2>
<c-button @click="addRow">
Add row
</c-button>
<c-button @click="addColumn">
Add column
</c-button>
</div>
<n-scrollbar x-scrollable>
<n-table :bordered="false" :single-line="false" min-w-700px>
<thead>
<tr>
<th v-for="(_, columnIndex) of table.headers" :key="columnIndex" scope="col" min-w-170px>
<div flex flex-col gap-2>
<c-input-text
v-model:value="table.headers[columnIndex]"
raw-text
:placeholder="`Column ${columnIndex + 1}`"
:test-id="`header-${columnIndex}`"
/>
<div flex items-center gap-2>
<c-select
v-model:value="table.alignments[columnIndex]"
:options="alignmentOptions"
size="small"
flex-1
/>
<c-button
circle
size="small"
variant="text"
:disabled="table.headers.length <= 1"
@click="removeColumn(columnIndex)"
>
<icon-mdi-delete-outline />
</c-button>
</div>
</div>
</th>
<th scope="col" w-45px />
</tr>
</thead>
<tbody>
<tr v-for="(row, rowIndex) of table.rows" :key="rowIndex">
<td v-for="(_, columnIndex) of table.headers" :key="columnIndex">
<c-input-text
v-model:value="row[columnIndex]"
raw-text
multiline
rows="2"
:placeholder="`Row ${rowIndex + 1}, column ${columnIndex + 1}`"
:test-id="`cell-${rowIndex}-${columnIndex}`"
/>
</td>
<td text-center>
<c-button
circle
size="small"
variant="text"
:disabled="table.rows.length <= 1"
@click="removeRow(rowIndex)"
>
<icon-mdi-delete-outline />
</c-button>
</td>
</tr>
</tbody>
</n-table>
</n-scrollbar>
</c-card>
<n-divider />
<n-form-item label="Generated Markdown table:">
<TextareaCopyable :value="output" language="markdown" copy-placement="outside" />
</n-form-item>
</div>
</template>