markdown-it-adv-table 0.1.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,18 +1,26 @@
1
1
 
2
2
  # markdown-it-adv-table
3
3
 
4
- A [markdown-it](https://www.npmjs.com/package/markdown-it) plugin to enable advanced table rendering in Markdown. The custom syntax allows to create complex tables supporting:
4
+ A [markdown-it](https://www.npmjs.com/package/markdown-it) plugin for advanced table rendering.
5
5
 
6
- - Rowspan and colspan for merged cells
7
- - Custom column widths
8
- - Horizontal cell alignment
9
- - Table styling with css classes
10
- - Header rows and columns (using `<th>`)
11
- - Multiple blocks and nested markdown within cells
6
+ This plugin adds custom table syntaxes to render complex tables easier.
12
7
 
13
- ## Install
8
+ - "flat-table" syntax
9
+ - "csv-table" syntax
10
+ - "tsv-table" syntax
14
11
 
15
- ```bash
12
+ The "flat-table" syntax allows to:
13
+
14
+ - Set Rowspan and colspan for spanning cells
15
+ - Set column width
16
+ - Set horizontal text alignment
17
+ - Set css classes for table styling
18
+ - Define Header rows and columns
19
+ - Allow writing markdown inside the cells (nested document)
20
+
21
+ ## Installation
22
+
23
+ ```sh
16
24
  npm install markdown-it-adv-table
17
25
  ```
18
26
 
@@ -25,11 +33,37 @@ md.use(advTable);
25
33
  const html = md.render("text...");
26
34
  ```
27
35
 
28
- ## Documentation
36
+ <table>
37
+ <tr>
38
+ <th>Plugin</th>
39
+ <th>LangName</th>
40
+ <th>Behavior</th>
41
+ </tr>
42
+ <tr>
43
+ <td><code>advTable</code></td>
44
+ <td>table*</td>
45
+ <td>Installs an all-unified plugin</td>
46
+ </tr>
47
+ <tr>
48
+ <td><code>flatTable</code></td>
49
+ <td>flat-table</td>
50
+ <td>parse flat-table syntax</td>
51
+ </tr>
52
+ <tr>
53
+ <td><code>csvTable</code></td>
54
+ <td>csv-table</td>
55
+ <td>render csv as table</td>
56
+ </tr>
57
+ <tr>
58
+ <td><code>tsvTable</code></td>
59
+ <td>tsv-table</td>
60
+ <td>render tsv as table</td>
61
+ </tr>
62
+ </table>
29
63
 
30
- To Be Documented
64
+ ## Usage
31
65
 
32
- ## Examples
66
+ Use fenced code block for the table data.
33
67
 
34
68
  ``````
35
69
  ```table cols=4 header-rows=2 header-cols=1
@@ -54,6 +88,7 @@ c3| Q1 Sales
54
88
  | $3,500
55
89
  | $4,000
56
90
  | $4,200
91
+ ```
57
92
  ``````
58
93
 
59
94
  <table>
@@ -90,7 +125,134 @@ c3| Q1 Sales
90
125
  </tbody>
91
126
  </table>
92
127
 
128
+ ## Documentation
129
+
130
+ The table is expressed in a fenced code block.
131
+
132
+ - A line that starts with `|` starts a new cell.
133
+ - The cell content is parsed as Markdown.
134
+ - The cell content spans until the next cell marker.
135
+
136
+ A cell marker can include directives that control the cell’s properties.
137
+
138
+
139
+ ### TableSpec (Table Definition)
140
+
141
+ The [info-string](https://spec.commonmark.org/0.31.2/#info-string) of the fenced code block is parsed as TableSpec.
142
+
143
+ <table>
144
+ <tr>
145
+ <th>Key</th>
146
+ <th>Type</th>
147
+ <th>Value</th>
148
+ </tr>
149
+ <tr>
150
+ <td>cols</td>
151
+ <td>number | string</td>
152
+ <td>
153
+ <p>Define number of columns.</p>
154
+ <p>If the value is a string literal, it is a <a href="#colspec"><code>ColSpec</code></a>.</p>
155
+ <pre>cols=3 // 3 columns
156
+ cols="1,1,2" // 3 columns, 1:1:2 ratio</pre>
157
+ </td>
158
+ </tr>
159
+ <tr>
160
+ <td>header-cols</td>
161
+ <td>number</td>
162
+ <td>Number of header columns (rendered as &lt;th&gt;)</td>
163
+ </tr>
164
+ <tr>
165
+ <td>header-rows</td>
166
+ <td>number</td>
167
+ <td>Number of header rows (rendered as &lt;thead&gt; with &lt;th&gt;)</td>
168
+ </tr>
169
+ <tr>
170
+ <td>class</td>
171
+ <td>string</td>
172
+ <td>Table class names (space- or comma-separated)</td>
173
+ </tr>
174
+ <tr>
175
+ <td>width</td>
176
+ <td>number | string</td>
177
+ <td>Table width.</td>
178
+ </tr>
179
+ <tr>
180
+ <td>format</td>
181
+ <td>string</td>
182
+ <td>
183
+ <p>Use alternative table syntax. </p>
184
+ <ul>
185
+ <li><code>csv</code> : parse text as csv</li>
186
+ <li><code>tsv</code> : parse text as tsv</li>
187
+ </ul>
188
+ </td>
189
+ </tr>
190
+ </table>
191
+
192
+ <h3 id="colspec">ColSpec (Column Definition)</h3>
193
+
194
+ <code>ColSpec</code> is a comma-separated set-of-directives to control the column's properties.
195
+
196
+ "1,1,1" 3 columns, 1:1:1 ratio
197
+ "30%,15,30,60" 4 columns, 3:1:2:4 ratio
198
+ "<100px,,>25%" 3 columns, 100px-auto-25% with alignment directives
199
+
200
+ <table>
201
+ <tr>
202
+ <th>Directive</th>
203
+ <th>Description</th>
204
+ </tr>
205
+ <tr>
206
+ <td>size[unit]</td>
207
+ <td>
208
+ <p>Set column width. Any css units can be used.</p>
209
+ <p>If the unit is omitted, the value represents the weight of the column. The plugin calculates the column width by dividing up the remaining space, based on its weight.</p>
210
+ <pre>"1,1,2" = "25%,25%,50%" (Eq = calc(100% * x / 4))
211
+ "20%,1,1,2" = "20%,20%,20%,40%" (Eq = calc( 80% * x / 4))</pre>
212
+ <p>If the size is empty or invalid, the width is unset. The weight of the unsized(auto) column defaults to 1.</p>
213
+ <p><small>NOTE: The actual width is calculated by the HTML engine, respecting the column's minimum content width.</small></p>
214
+ </td>
215
+ </tr>
216
+ <tr>
217
+ <td>&lt;<br>^<br>&gt;</td>
218
+ <td>
219
+ Left-aligned<br>
220
+ Center-aligned<br>
221
+ Right-aligned<br>
222
+ </td>
223
+ </tr>
224
+ </table>
225
+
226
+
227
+
228
+ ### Cell Directives (Cell Definition)
229
+
230
+ <table>
231
+ <tr>
232
+ <th>Syntax</th>
233
+ <th>Description</th>
234
+ </tr>
235
+ <tr>
236
+ <td>c2, c{\d+}</td>
237
+ <td>Set colspan</td>
238
+ </tr>
239
+ <tr>
240
+ <td>r2, r{\d+}</td>
241
+ <td>Set rowspan</td>
242
+ </tr>
243
+ <tr>
244
+ <td>&lt;<br>^<br>&gt;</td>
245
+ <td>Left align<br>Center align<br>Right align</td>
246
+ </tr>
247
+ <tr>
248
+ <td>h</td>
249
+ <td>Use &lt;th&gt; instead of &lt;td&gt;</td>
250
+ </tr>
251
+ </table>
252
+
253
+
93
254
 
255
+ ## More Examples
94
256
 
95
257
 
96
258
  ``````
package/lib/fence.js CHANGED
@@ -65,15 +65,23 @@ export function fence_custom(names, parser) {
65
65
  }
66
66
  len = state.sCount[startLine];
67
67
  state.line = nextLine + (haveEndMarker ? 1 : 0);
68
- if (parser !== undefined) {
69
- parser(params, state, startLine, nextLine);
70
- }
71
- else {
68
+ const parseDefault = () => {
72
69
  const token = state.push("fence", "code", 0);
73
70
  token.info = params;
74
71
  token.content = state.getLines(startLine + 1, nextLine, len, true);
75
72
  token.markup = markup;
76
73
  token.map = [startLine, state.line];
74
+ };
75
+ if (parser !== undefined) {
76
+ try {
77
+ parser(params, state, startLine, nextLine);
78
+ }
79
+ catch {
80
+ parseDefault();
81
+ }
82
+ }
83
+ else {
84
+ parseDefault();
77
85
  }
78
86
  return true;
79
87
  };
package/lib/flat-table.js CHANGED
@@ -14,7 +14,8 @@ export class FlatTableParser {
14
14
  return new FlatTableParser(tableSpec);
15
15
  }
16
16
  parse(state, startLine, endLine) {
17
- const builder = new TableBuilder(state, this._tableSpec);
17
+ const md = state.md;
18
+ const builder = TableBuilder.newLocal(state, this._tableSpec);
18
19
  builder.startTable();
19
20
  let currentLine = startLine;
20
21
  while (currentLine < endLine) {
@@ -29,7 +30,6 @@ export class FlatTableParser {
29
30
  currentLine++;
30
31
  }
31
32
  const cellEnd = currentLine;
32
- const md = state.md;
33
33
  const cellIndent = FlatTableParser.getCellIndent(state, line);
34
34
  const cellSpec = FlatTableParser.cellspec(line);
35
35
  const cellAttr = FlatTableParser.parseCellspec(cellSpec);
@@ -54,6 +54,7 @@ export class FlatTableParser {
54
54
  }
55
55
  }
56
56
  builder.endTable();
57
+ state.tokens.push(...builder.state.tokens);
57
58
  }
58
59
  getline(state, lineNumber) {
59
60
  return state.getLines(lineNumber, lineNumber + 1, state.blkIndent, false);
package/lib/index.d.ts CHANGED
@@ -1,19 +1,11 @@
1
- import { PluginWithOptions } from "markdown-it";
1
+ import { PluginSimple, PluginWithOptions } from "markdown-it";
2
2
  import { Parser } from "./fence.js";
3
3
  export interface PluginOption {
4
- names: {
5
- adv: string;
6
- flat: string;
7
- csv: string;
8
- tsv: string;
9
- };
10
- }
11
- export interface PluginOptionSingle {
12
4
  name: string;
13
5
  }
14
- export declare function createParser(option: PluginOption): Parser;
6
+ export declare function unifiedParser(option: PluginOption): Parser;
15
7
  export declare const advTable: PluginWithOptions<PluginOption>;
16
- export declare const flatTable: PluginWithOptions<PluginOptionSingle>;
17
- export declare const csvTable: PluginWithOptions<PluginOptionSingle>;
18
- export declare const tsvTable: PluginWithOptions<PluginOptionSingle>;
8
+ export declare const flatTable: PluginSimple;
9
+ export declare const csvTable: PluginSimple;
10
+ export declare const tsvTable: PluginSimple;
19
11
  export default advTable;
package/lib/index.js CHANGED
@@ -4,29 +4,16 @@ import { debug } from "./debug.js";
4
4
  import { fence_custom } from "./fence.js";
5
5
  import { FlatTableParser } from "./flat-table.js";
6
6
  import { merge } from "./merge.js";
7
- const defaultOptions = {
8
- names: {
9
- adv: "table",
10
- flat: "flat-table",
11
- csv: "csv-table",
12
- tsv: "tsv-table"
13
- }
7
+ const langNames = {
8
+ adv: "table",
9
+ flat: "flat-table",
10
+ csv: "csv-table",
11
+ tsv: "tsv-table",
14
12
  };
15
- const plainNames = {
16
- adv: "",
17
- flat: "",
18
- csv: "",
19
- tsv: "",
13
+ const defaultOption = {
14
+ name: langNames.adv,
20
15
  };
21
- function getAllNames(option) {
22
- return [
23
- option.names.adv,
24
- option.names.flat,
25
- option.names.csv,
26
- option.names.tsv
27
- ];
28
- }
29
- export function createParser(option) {
16
+ export function unifiedParser(option) {
30
17
  return (info, state, startLine, endLine) => {
31
18
  if (debug.isEnabled()) {
32
19
  debug(">> table parse start");
@@ -49,52 +36,49 @@ export function createParser(option) {
49
36
  }
50
37
  const lang = info.slice(0, info.search(/\s|$/));
51
38
  const params = info.slice(lang.length + 1);
52
- if (lang === option.names.adv) {
39
+ if (lang === option.name) {
53
40
  const parser = new AdvTableParser(params);
54
41
  parser.parse(state, startLine + 1, endLine);
55
42
  }
56
- else if (lang === option.names.flat) {
57
- const parser = FlatTableParser.new(info, state, startLine + 1, endLine);
43
+ else if (lang === langNames.flat) {
44
+ const parser = FlatTableParser.new(params, state, startLine + 1, endLine);
58
45
  parser.parse(state, startLine + 1, endLine);
59
46
  }
60
- else if (lang === option.names.csv) {
47
+ else if (lang === langNames.csv) {
61
48
  const parser = CsvTableParser.new(params, ",");
62
49
  parser.parse(state, startLine + 1, endLine);
63
50
  }
64
- else if (lang === option.names.tsv) {
51
+ else if (lang === langNames.tsv) {
65
52
  const parser = CsvTableParser.new(params, "\t");
66
53
  parser.parse(state, startLine + 1, endLine);
67
54
  }
68
55
  };
69
56
  }
70
57
  export const advTable = (md, option) => {
71
- const opts = merge(defaultOptions, option);
72
- const parser = createParser(opts);
73
- const rule = fence_custom(getAllNames(opts), parser);
58
+ const opts = merge(defaultOption, option);
59
+ const awareNames = [
60
+ option?.name ?? langNames.adv,
61
+ langNames.flat,
62
+ langNames.csv,
63
+ langNames.tsv
64
+ ];
65
+ const parser = unifiedParser(opts);
66
+ const rule = fence_custom(awareNames, parser);
74
67
  md.block.ruler.before("fence", "adv_table", rule);
75
68
  };
76
- export const flatTable = (md, option) => {
77
- const defaultNames = merge(plainNames, { flat: defaultOptions.names.flat });
78
- const names = merge(defaultNames, { flat: option?.name });
79
- const opts = merge(defaultOptions, { names });
80
- const parser = createParser(opts);
81
- const rule = fence_custom(getAllNames(opts), parser);
82
- md.block.ruler.before("fence", "csv_table", rule);
69
+ export const flatTable = (md) => {
70
+ const parser = unifiedParser(defaultOption);
71
+ const rule = fence_custom(langNames.flat, parser);
72
+ md.block.ruler.before("fence", "flat_table", rule);
83
73
  };
84
- export const csvTable = (md, option) => {
85
- const defaultNames = merge(plainNames, { csv: defaultOptions.names.csv });
86
- const names = merge(defaultNames, { csv: option?.name });
87
- const opts = merge(defaultOptions, { names });
88
- const parser = createParser(opts);
89
- const rule = fence_custom(getAllNames(opts), parser);
74
+ export const csvTable = (md) => {
75
+ const parser = unifiedParser(defaultOption);
76
+ const rule = fence_custom(langNames.csv, parser);
90
77
  md.block.ruler.before("fence", "csv_table", rule);
91
78
  };
92
- export const tsvTable = (md, option) => {
93
- const defaultNames = merge(plainNames, { tsv: defaultOptions.names.csv });
94
- const names = merge(defaultNames, { tsv: option?.name });
95
- const opts = merge(defaultOptions, { names });
96
- const parser = createParser(opts);
97
- const rule = fence_custom(getAllNames(opts), parser);
98
- md.block.ruler.before("fence", "csv_table", rule);
79
+ export const tsvTable = (md) => {
80
+ const parser = unifiedParser(defaultOption);
81
+ const rule = fence_custom(langNames.tsv, parser);
82
+ md.block.ruler.before("fence", "tsv_table", rule);
99
83
  };
100
84
  export default advTable;
@@ -11,6 +11,7 @@ export declare class TableBuilder implements ITableBuilder {
11
11
  readonly tableSpec: TableSpec;
12
12
  readonly _cells: CellState;
13
13
  constructor(state: StateBlock, tableSpec: TableSpec);
14
+ static newLocal(state: StateBlock, tableSpec: TableSpec): TableBuilder;
14
15
  private get useColgroup();
15
16
  private get useTHead();
16
17
  private get useTBody();
@@ -9,6 +9,9 @@ export class TableBuilder {
9
9
  this.tableSpec = tableSpec;
10
10
  this._cells = new CellState(tableSpec);
11
11
  }
12
+ static newLocal(state, tableSpec) {
13
+ return new TableBuilder(new state.md.block.State("", state.md, state.env, []), tableSpec);
14
+ }
12
15
  get useColgroup() {
13
16
  return this.tableSpec.attr.cols?.startsWith("\"");
14
17
  }
@@ -23,6 +26,15 @@ export class TableBuilder {
23
26
  this.tableSpec.classes.forEach(name => {
24
27
  token.attrJoin("class", name);
25
28
  });
29
+ if (this.tableSpec.attr["width"] !== undefined) {
30
+ const width = this.tableSpec.attr["width"];
31
+ if (/^\d+$/.test(width)) {
32
+ token.attrSet("width", width);
33
+ }
34
+ else {
35
+ token.attrSet("style", `width: ${width}`);
36
+ }
37
+ }
26
38
  if (this.tableSpec.attr["caption"] !== undefined) {
27
39
  this.setCaption(this.tableSpec.attr["caption"]);
28
40
  }
@@ -86,10 +98,9 @@ export class TableBuilder {
86
98
  setColgroup(numCols) {
87
99
  this.state.push("colgroup_open", "colgroup", 1);
88
100
  for (let c = 0; c < numCols; c++) {
89
- const colWidthRatio = this.tableSpec.colspecs.colWidthRatio(c);
90
- const colWidth = `${Math.round(colWidthRatio * 100).toFixed(0)}%`;
101
+ const widthProp = this.tableSpec.colspecs.colWidthPropValue(c);
91
102
  const token = this.state.push("col", "col", 0);
92
- token.attrSet("style", `width: ${colWidth}`);
103
+ token.attrSet("style", `width: ${widthProp}`);
93
104
  }
94
105
  this.state.push("colgroup_close", "colgroup", -1);
95
106
  }
package/lib/table.d.ts CHANGED
@@ -7,7 +7,7 @@ export type TableAttr = {
7
7
  };
8
8
  export interface ColumnAttr {
9
9
  align?: HAlign;
10
- width?: string;
10
+ width?: ColWidth;
11
11
  }
12
12
  export type CellAttr = {
13
13
  align?: HAlign;
@@ -15,6 +15,13 @@ export type CellAttr = {
15
15
  rowspan?: number;
16
16
  header?: boolean;
17
17
  };
18
+ export declare class ColWidth {
19
+ text: string;
20
+ constructor(text: string);
21
+ get hasUnit(): boolean;
22
+ get relSize(): number;
23
+ static widthPropertyValue(c: ColWidth, all: ColWidth[]): string;
24
+ }
18
25
  export declare class TableSpec {
19
26
  readonly attr: TableAttr;
20
27
  readonly classes: string[];
@@ -32,8 +39,8 @@ export declare class ColSpecs {
32
39
  readonly specs: readonly ColumnAttr[];
33
40
  constructor(colspec: string);
34
41
  colSpec(col: number): ColumnAttr;
35
- colWidth(col: number): number;
36
- colWidthRatio(col: number): number;
42
+ colWidth(col: number): ColWidth;
43
+ colWidthPropValue(col: number): string;
37
44
  lazyInit(cols: number): void;
38
45
  static parseColSpec(spec: string): ColumnAttr;
39
46
  }
package/lib/table.js CHANGED
@@ -1,4 +1,43 @@
1
1
  import { Lexer, unwrapLiteral } from "./lexer.js";
2
+ const cssUnits = [
3
+ "px", "%", "em", "rem",
4
+ "ex", "rex", "cap", "rcap",
5
+ "cm", "mm", "Q", "in", "pt", "pc",
6
+ "ch", "rch", "ic", "ric", "lh", "rlh",
7
+ "vw", "vh", "vi", "vb", "vmin", "vmax",
8
+ "svw", "svh", "svi", "svb", "svmin", "svmax",
9
+ "lvw", "lvh", "lvi", "lvb", "lvmin", "lvmax",
10
+ "dvw", "dvh", "dvi", "dvb", "dvmin", "dvmax",
11
+ "cqw", "cqh", "cqi", "cqb", "cqmin", "cqmax"
12
+ ];
13
+ export class ColWidth {
14
+ text;
15
+ constructor(text) {
16
+ this.text = text;
17
+ }
18
+ get hasUnit() {
19
+ return !/^\d+$/.test(this.text);
20
+ }
21
+ get relSize() {
22
+ return this.hasUnit ? 0 : parseInt(this.text, 10);
23
+ }
24
+ static widthPropertyValue(c, all) {
25
+ if (c.hasUnit) {
26
+ return c.text;
27
+ }
28
+ const total = all
29
+ .filter(cw => !cw.hasUnit)
30
+ .reduce((sum, cw) => sum + cw.relSize, 0);
31
+ const exclude = all.filter(cw => cw.hasUnit);
32
+ if (exclude.length === 0) {
33
+ return `calc(100% * ${c.relSize} / ${total})`;
34
+ }
35
+ else {
36
+ const sum = exclude.map(cw => cw.text).join(" + ");
37
+ return `calc((100% - (${sum})) * ${c.relSize} / ${total})`;
38
+ }
39
+ }
40
+ }
2
41
  export class TableSpec {
3
42
  attr;
4
43
  classes;
@@ -16,8 +55,8 @@ export class TableSpec {
16
55
  return this.colspecs.numCols;
17
56
  }
18
57
  static parseClass(classnames) {
19
- return classnames
20
- .split(",")
58
+ return unwrapLiteral(classnames, "\"")
59
+ .split(/[\s,]/)
21
60
  .map((s) => s.trim())
22
61
  .filter(s => s.length > 0)
23
62
  .filter((s, i, arr) => arr.indexOf(s) === i);
@@ -79,6 +118,7 @@ export class TableSpec {
79
118
  "header-cols": "",
80
119
  "header-rows": "",
81
120
  class: "",
121
+ width: "",
82
122
  format: ""
83
123
  };
84
124
  return Object.keys(k);
@@ -108,16 +148,14 @@ export class ColSpecs {
108
148
  colWidth(col) {
109
149
  const spec = this.colSpec(col);
110
150
  if (spec.width) {
111
- return parseInt(spec.width, 10);
151
+ return spec.width;
112
152
  }
113
- return 1;
153
+ return new ColWidth("1");
114
154
  }
115
- colWidthRatio(col) {
116
- let totalWidth = 0;
117
- for (let c = 0; c < this.numCols; c++) {
118
- totalWidth += this.colWidth(c);
119
- }
120
- return this.colWidth(col) / totalWidth;
155
+ colWidthPropValue(col) {
156
+ const c = this.colWidth(col);
157
+ const all = this.specs.map(s => s.width || new ColWidth("1"));
158
+ return ColWidth.widthPropertyValue(c, all);
121
159
  }
122
160
  lazyInit(cols) {
123
161
  this.numCols = cols;
@@ -141,7 +179,7 @@ export class ColSpecs {
141
179
  attr.align = "right";
142
180
  }
143
181
  else if (char >= "0" && char <= "9") {
144
- attr.width = consumeNumber();
182
+ attr.width = consumeColWidth();
145
183
  break;
146
184
  }
147
185
  else {
@@ -152,11 +190,13 @@ export class ColSpecs {
152
190
  function consume() {
153
191
  return spec[pos++];
154
192
  }
155
- function consumeNumber() {
156
- const match = spec.slice(pos).match(/^\d+/);
193
+ function consumeColWidth() {
194
+ const regex = new RegExp(`^\\d+(${cssUnits.join("|")})?`);
195
+ const match = spec.slice(pos).match(regex);
157
196
  if (!match)
158
- throw new Error("cannot consume number");
159
- return match[0];
197
+ throw new Error("cannot consume col width");
198
+ pos += match[0].length;
199
+ return new ColWidth(match[0]);
160
200
  }
161
201
  }
162
202
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "markdown-it-adv-table",
3
- "version": "0.1.2",
3
+ "version": "0.2.0",
4
4
  "description": "Markdown syntax extension for better table support",
5
5
  "keywords": [
6
6
  "markdown",
@@ -34,13 +34,13 @@
34
34
  "lint:fix": "eslint src --fix"
35
35
  },
36
36
  "devDependencies": {
37
- "@cobapen/eslint-config": "^0.4.0",
37
+ "@cobapen/eslint-config": "^0.5.0",
38
38
  "@types/markdown-it": "^14.1.2",
39
- "@types/node": "^22.14.1",
40
- "@vitest/coverage-v8": "^3.1.1",
41
- "eslint": "^9.24.0",
39
+ "@types/node": "^25.2.1",
40
+ "@vitest/coverage-v8": "^4.0.18",
41
+ "eslint": "^9.39.2",
42
42
  "markdown-it": "^14.1.0",
43
- "typescript": "^5.8.3",
44
- "vitest": "^3.1.1"
43
+ "typescript": "^5.9.3",
44
+ "vitest": "^4.0.18"
45
45
  }
46
46
  }