markdownly.js 1.1.1 → 1.3.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/dist/cli.js +50 -22
- package/dist/index.js +50 -22
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -137,43 +137,57 @@ function parse(markdown) {
|
|
|
137
137
|
function parseList(lines, startIndex) {
|
|
138
138
|
const items = [];
|
|
139
139
|
let i = startIndex;
|
|
140
|
+
const firstMatch = lines[i].match(/^(\s*)/);
|
|
141
|
+
const baseIndent = firstMatch ? firstMatch[1].length : 0;
|
|
140
142
|
while (i < lines.length) {
|
|
141
143
|
const line = lines[i];
|
|
142
|
-
|
|
143
|
-
if (!match && line.trim() === "") {
|
|
144
|
+
if (line.trim() === "") {
|
|
144
145
|
i++;
|
|
145
146
|
continue;
|
|
146
147
|
}
|
|
148
|
+
const match = line.match(/^(\s*)([*+-]|(\d+)\.)\s(.*)$/);
|
|
147
149
|
if (!match)
|
|
148
150
|
break;
|
|
149
|
-
const [,
|
|
151
|
+
const [, indentStr, marker, startNum, content] = match;
|
|
152
|
+
const indent = indentStr.length;
|
|
153
|
+
if (indent < baseIndent)
|
|
154
|
+
break;
|
|
150
155
|
const ordered = /\d+\./.test(marker);
|
|
156
|
+
const start = startNum ? parseInt(startNum, 10) : 1;
|
|
157
|
+
const depth = Math.floor(indent / 2);
|
|
151
158
|
const checked = content.match(/^\[([ xX])\]\s*(.*)$/);
|
|
152
159
|
let itemContent = checked ? checked[2] : content;
|
|
153
160
|
const isChecked = checked ? checked[1].toLowerCase() === "x" : undefined;
|
|
154
161
|
i++;
|
|
162
|
+
const nestedItems = [];
|
|
155
163
|
while (i < lines.length) {
|
|
156
164
|
const nextLine = lines[i];
|
|
157
165
|
if (nextLine.trim() === "") {
|
|
158
166
|
i++;
|
|
159
167
|
continue;
|
|
160
168
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
if (nextLine.match(/^\s{2,}/)) {
|
|
164
|
-
itemContent += `
|
|
165
|
-
` + nextLine.trim();
|
|
166
|
-
i++;
|
|
167
|
-
} else {
|
|
169
|
+
const nextMatch = nextLine.match(/^(\s*)([*+-]|\d+\.)\s/);
|
|
170
|
+
if (!nextMatch)
|
|
168
171
|
break;
|
|
172
|
+
const nextIndent = nextMatch[1].length;
|
|
173
|
+
if (nextIndent > indent) {
|
|
174
|
+
const nested = parseList(lines, i);
|
|
175
|
+
nestedItems.push(...nested.items);
|
|
176
|
+
i = nested.endIndex;
|
|
177
|
+
continue;
|
|
169
178
|
}
|
|
179
|
+
break;
|
|
170
180
|
}
|
|
171
|
-
|
|
181
|
+
const item = {
|
|
172
182
|
type: "list_item",
|
|
173
183
|
content: itemContent,
|
|
174
184
|
children: parseInline(itemContent),
|
|
175
|
-
meta: { ordered, checked: isChecked }
|
|
176
|
-
}
|
|
185
|
+
meta: { ordered, checked: isChecked, depth, start }
|
|
186
|
+
};
|
|
187
|
+
if (nestedItems.length > 0) {
|
|
188
|
+
item.meta.nested = nestedItems;
|
|
189
|
+
}
|
|
190
|
+
items.push(item);
|
|
177
191
|
}
|
|
178
192
|
return { items, endIndex: i };
|
|
179
193
|
}
|
|
@@ -612,28 +626,42 @@ function renderCodeBlock(token, ctx) {
|
|
|
612
626
|
}).join(`
|
|
613
627
|
`);
|
|
614
628
|
}
|
|
615
|
-
function renderList(token, ctx) {
|
|
629
|
+
function renderList(token, ctx, baseDepth = 0) {
|
|
616
630
|
const items = token.children || [];
|
|
617
|
-
|
|
618
|
-
|
|
631
|
+
const markers = ["•", "-", "‣"];
|
|
632
|
+
const result = [];
|
|
633
|
+
for (const item of items) {
|
|
619
634
|
const ordered = item.meta?.ordered;
|
|
620
635
|
const checked = item.meta?.checked;
|
|
636
|
+
const depth = (item.meta?.depth || 0) - baseDepth;
|
|
637
|
+
const start = item.meta?.start || 1;
|
|
638
|
+
const indentStr = " ".repeat(depth * 2);
|
|
621
639
|
let bullet;
|
|
622
640
|
if (checked !== undefined) {
|
|
623
641
|
const check = checked ? green("✓") : " ";
|
|
624
642
|
bullet = grey("[") + check + grey("]");
|
|
625
643
|
} else if (ordered) {
|
|
626
|
-
bullet = blueBright(`${
|
|
644
|
+
bullet = blueBright(`${start}.`);
|
|
627
645
|
} else {
|
|
628
|
-
|
|
646
|
+
const markerIdx = depth % markers.length;
|
|
647
|
+
bullet = redBright(markers[markerIdx]);
|
|
629
648
|
}
|
|
630
649
|
const content = renderInline(item.children || []);
|
|
631
|
-
const wrapped = wrapText(content, ctx.width - 4);
|
|
650
|
+
const wrapped = wrapText(content, ctx.width - 4 - depth * 2);
|
|
632
651
|
const indented = wrapped.split(`
|
|
633
|
-
`).map((line, i) => i === 0 ? `${bullet} ${line}` :
|
|
652
|
+
`).map((line, i) => i === 0 ? `${indentStr}${bullet} ${line}` : `${indentStr} ${line}`).join(`
|
|
634
653
|
`);
|
|
635
|
-
|
|
636
|
-
|
|
654
|
+
result.push(indented);
|
|
655
|
+
if (item.meta?.nested) {
|
|
656
|
+
const nestedToken = {
|
|
657
|
+
type: "list",
|
|
658
|
+
content: "",
|
|
659
|
+
children: item.meta.nested
|
|
660
|
+
};
|
|
661
|
+
result.push(renderList(nestedToken, ctx, baseDepth));
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
return result.join(`
|
|
637
665
|
`);
|
|
638
666
|
}
|
|
639
667
|
function renderTable(token, ctx) {
|
package/dist/index.js
CHANGED
|
@@ -135,43 +135,57 @@ function parse(markdown) {
|
|
|
135
135
|
function parseList(lines, startIndex) {
|
|
136
136
|
const items = [];
|
|
137
137
|
let i = startIndex;
|
|
138
|
+
const firstMatch = lines[i].match(/^(\s*)/);
|
|
139
|
+
const baseIndent = firstMatch ? firstMatch[1].length : 0;
|
|
138
140
|
while (i < lines.length) {
|
|
139
141
|
const line = lines[i];
|
|
140
|
-
|
|
141
|
-
if (!match && line.trim() === "") {
|
|
142
|
+
if (line.trim() === "") {
|
|
142
143
|
i++;
|
|
143
144
|
continue;
|
|
144
145
|
}
|
|
146
|
+
const match = line.match(/^(\s*)([*+-]|(\d+)\.)\s(.*)$/);
|
|
145
147
|
if (!match)
|
|
146
148
|
break;
|
|
147
|
-
const [,
|
|
149
|
+
const [, indentStr, marker, startNum, content] = match;
|
|
150
|
+
const indent = indentStr.length;
|
|
151
|
+
if (indent < baseIndent)
|
|
152
|
+
break;
|
|
148
153
|
const ordered = /\d+\./.test(marker);
|
|
154
|
+
const start = startNum ? parseInt(startNum, 10) : 1;
|
|
155
|
+
const depth = Math.floor(indent / 2);
|
|
149
156
|
const checked = content.match(/^\[([ xX])\]\s*(.*)$/);
|
|
150
157
|
let itemContent = checked ? checked[2] : content;
|
|
151
158
|
const isChecked = checked ? checked[1].toLowerCase() === "x" : undefined;
|
|
152
159
|
i++;
|
|
160
|
+
const nestedItems = [];
|
|
153
161
|
while (i < lines.length) {
|
|
154
162
|
const nextLine = lines[i];
|
|
155
163
|
if (nextLine.trim() === "") {
|
|
156
164
|
i++;
|
|
157
165
|
continue;
|
|
158
166
|
}
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
if (nextLine.match(/^\s{2,}/)) {
|
|
162
|
-
itemContent += `
|
|
163
|
-
` + nextLine.trim();
|
|
164
|
-
i++;
|
|
165
|
-
} else {
|
|
167
|
+
const nextMatch = nextLine.match(/^(\s*)([*+-]|\d+\.)\s/);
|
|
168
|
+
if (!nextMatch)
|
|
166
169
|
break;
|
|
170
|
+
const nextIndent = nextMatch[1].length;
|
|
171
|
+
if (nextIndent > indent) {
|
|
172
|
+
const nested = parseList(lines, i);
|
|
173
|
+
nestedItems.push(...nested.items);
|
|
174
|
+
i = nested.endIndex;
|
|
175
|
+
continue;
|
|
167
176
|
}
|
|
177
|
+
break;
|
|
168
178
|
}
|
|
169
|
-
|
|
179
|
+
const item = {
|
|
170
180
|
type: "list_item",
|
|
171
181
|
content: itemContent,
|
|
172
182
|
children: parseInline(itemContent),
|
|
173
|
-
meta: { ordered, checked: isChecked }
|
|
174
|
-
}
|
|
183
|
+
meta: { ordered, checked: isChecked, depth, start }
|
|
184
|
+
};
|
|
185
|
+
if (nestedItems.length > 0) {
|
|
186
|
+
item.meta.nested = nestedItems;
|
|
187
|
+
}
|
|
188
|
+
items.push(item);
|
|
175
189
|
}
|
|
176
190
|
return { items, endIndex: i };
|
|
177
191
|
}
|
|
@@ -610,28 +624,42 @@ function renderCodeBlock(token, ctx) {
|
|
|
610
624
|
}).join(`
|
|
611
625
|
`);
|
|
612
626
|
}
|
|
613
|
-
function renderList(token, ctx) {
|
|
627
|
+
function renderList(token, ctx, baseDepth = 0) {
|
|
614
628
|
const items = token.children || [];
|
|
615
|
-
|
|
616
|
-
|
|
629
|
+
const markers = ["•", "-", "‣"];
|
|
630
|
+
const result = [];
|
|
631
|
+
for (const item of items) {
|
|
617
632
|
const ordered = item.meta?.ordered;
|
|
618
633
|
const checked = item.meta?.checked;
|
|
634
|
+
const depth = (item.meta?.depth || 0) - baseDepth;
|
|
635
|
+
const start = item.meta?.start || 1;
|
|
636
|
+
const indentStr = " ".repeat(depth * 2);
|
|
619
637
|
let bullet;
|
|
620
638
|
if (checked !== undefined) {
|
|
621
639
|
const check = checked ? green("✓") : " ";
|
|
622
640
|
bullet = grey("[") + check + grey("]");
|
|
623
641
|
} else if (ordered) {
|
|
624
|
-
bullet = blueBright(`${
|
|
642
|
+
bullet = blueBright(`${start}.`);
|
|
625
643
|
} else {
|
|
626
|
-
|
|
644
|
+
const markerIdx = depth % markers.length;
|
|
645
|
+
bullet = redBright(markers[markerIdx]);
|
|
627
646
|
}
|
|
628
647
|
const content = renderInline(item.children || []);
|
|
629
|
-
const wrapped = wrapText(content, ctx.width - 4);
|
|
648
|
+
const wrapped = wrapText(content, ctx.width - 4 - depth * 2);
|
|
630
649
|
const indented = wrapped.split(`
|
|
631
|
-
`).map((line, i) => i === 0 ? `${bullet} ${line}` :
|
|
650
|
+
`).map((line, i) => i === 0 ? `${indentStr}${bullet} ${line}` : `${indentStr} ${line}`).join(`
|
|
632
651
|
`);
|
|
633
|
-
|
|
634
|
-
|
|
652
|
+
result.push(indented);
|
|
653
|
+
if (item.meta?.nested) {
|
|
654
|
+
const nestedToken = {
|
|
655
|
+
type: "list",
|
|
656
|
+
content: "",
|
|
657
|
+
children: item.meta.nested
|
|
658
|
+
};
|
|
659
|
+
result.push(renderList(nestedToken, ctx, baseDepth));
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
return result.join(`
|
|
635
663
|
`);
|
|
636
664
|
}
|
|
637
665
|
function renderTable(token, ctx) {
|