@lewishowles/cli-style 0.13.0 → 0.14.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/CHANGELOG.md +16 -0
- package/README.md +66 -10
- package/adapters/python/cli_style/__init__.py +73 -0
- package/adapters/python/cli_style/_wrappers.py +503 -0
- package/adapters/python/cli_style/core.py +136 -0
- package/adapters/python/pyproject.toml +15 -0
- package/adapters/swift/Package.swift +16 -0
- package/adapters/swift/Sources/CliStyle/CliStyle.swift +223 -0
- package/adapters/swift/Sources/CliStyle/Wrappers.swift +582 -0
- package/package.json +4 -2
- package/scripts/build-binary.sh +15 -3
- package/scripts/generate-adapters.js +413 -0
- package/scripts/package-binary.sh +4 -1
- package/src/catalogue/renderer-catalogue.js +958 -52
- package/src/cli/adapter-path-command.js +3 -3
- package/src/cli/render-command.js +6 -0
- package/src/gallery/render-gallery.js +40 -0
- package/src/index.js +3 -0
- package/src/patterns/audit-finding.js +4 -4
- package/src/patterns/command-result.js +2 -2
- package/src/patterns/diagnostic-report.js +6 -3
- package/src/patterns/helpers.js +11 -4
- package/src/patterns/next-step-block.js +2 -4
- package/src/patterns/task-summary.js +4 -4
- package/src/primitives/bullet-list.js +150 -0
- package/src/theme/bullets.js +41 -0
- package/adapters/python/cli_style.py +0 -428
- package/adapters/swift/CliStyle.swift +0 -482
|
@@ -2,7 +2,7 @@ import { existsSync } from "node:fs";
|
|
|
2
2
|
import { dirname, join } from "node:path";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
4
|
|
|
5
|
-
// Adapter paths returned for
|
|
5
|
+
// Adapter paths returned for consumer setup.
|
|
6
6
|
const adapterPaths = {
|
|
7
7
|
bash: {
|
|
8
8
|
releasePath: "adapters/bash/cli-style.sh",
|
|
@@ -13,8 +13,8 @@ const adapterPaths = {
|
|
|
13
13
|
sourceUrl: new URL("../../adapters/python", import.meta.url),
|
|
14
14
|
},
|
|
15
15
|
swift: {
|
|
16
|
-
releasePath: "adapters/swift
|
|
17
|
-
sourceUrl: new URL("../../adapters/swift
|
|
16
|
+
releasePath: "adapters/swift",
|
|
17
|
+
sourceUrl: new URL("../../adapters/swift", import.meta.url),
|
|
18
18
|
},
|
|
19
19
|
};
|
|
20
20
|
|
|
@@ -8,6 +8,7 @@ import { diffBlock } from "../patterns/diff-block.js";
|
|
|
8
8
|
import { nextStepBlock } from "../patterns/next-step-block.js";
|
|
9
9
|
import { taskSummary } from "../patterns/task-summary.js";
|
|
10
10
|
import { barChart } from "../primitives/bar-chart.js";
|
|
11
|
+
import { bulletList } from "../primitives/bullet-list.js";
|
|
11
12
|
import { chip } from "../primitives/chip.js";
|
|
12
13
|
import { divider } from "../primitives/divider.js";
|
|
13
14
|
import { emptyState, errorBlock, hint } from "../primitives/feedback.js";
|
|
@@ -33,6 +34,11 @@ const renderers = {
|
|
|
33
34
|
...input,
|
|
34
35
|
...options,
|
|
35
36
|
}),
|
|
37
|
+
"bullet-list": (input, options) =>
|
|
38
|
+
bulletList(input.items, {
|
|
39
|
+
...input,
|
|
40
|
+
...options,
|
|
41
|
+
}),
|
|
36
42
|
chip: (input, options) =>
|
|
37
43
|
chip(input.label, input.tone, {
|
|
38
44
|
...input,
|
|
@@ -10,6 +10,7 @@ import { taskSummary } from "../patterns/task-summary.js";
|
|
|
10
10
|
import { stripAnsi } from "../formatters/ansi.js";
|
|
11
11
|
import { renderSpinnerFrame } from "../interactive/spinner.js";
|
|
12
12
|
import { barChart } from "../primitives/bar-chart.js";
|
|
13
|
+
import { bulletList } from "../primitives/bullet-list.js";
|
|
13
14
|
import { chip } from "../primitives/chip.js";
|
|
14
15
|
import { divider } from "../primitives/divider.js";
|
|
15
16
|
import { emptyState, errorBlock, hint } from "../primitives/feedback.js";
|
|
@@ -776,6 +777,9 @@ function renderPrimitives(options) {
|
|
|
776
777
|
width: 18,
|
|
777
778
|
}),
|
|
778
779
|
"",
|
|
780
|
+
"Bullet lists",
|
|
781
|
+
renderBulletListExamples(options),
|
|
782
|
+
"",
|
|
779
783
|
"Feedback",
|
|
780
784
|
hint(`Run ${span("npm run docs:readme", "info", options)}`, options),
|
|
781
785
|
labelledLine("Notice", "Reusable labelled output", {
|
|
@@ -872,6 +876,42 @@ function renderPrimitives(options) {
|
|
|
872
876
|
].join("\n");
|
|
873
877
|
}
|
|
874
878
|
|
|
879
|
+
/**
|
|
880
|
+
* Render representative flat, wrapped, nested, narrow, and plain bullet lists.
|
|
881
|
+
*
|
|
882
|
+
* @param {object} options
|
|
883
|
+
* Rendering options.
|
|
884
|
+
* @returns {string}
|
|
885
|
+
* Bullet list examples.
|
|
886
|
+
*/
|
|
887
|
+
function renderBulletListExamples(options) {
|
|
888
|
+
return [
|
|
889
|
+
bulletList(["Install dependencies", "Run the unit tests", "Review the output"], options),
|
|
890
|
+
bulletList(["This item wraps so continuation lines stay aligned with the item text."], {
|
|
891
|
+
...options,
|
|
892
|
+
width: 40,
|
|
893
|
+
}),
|
|
894
|
+
bulletList(
|
|
895
|
+
[
|
|
896
|
+
{
|
|
897
|
+
items: ["Use the focused check", "Read the first failure"],
|
|
898
|
+
text: "Verification",
|
|
899
|
+
},
|
|
900
|
+
"Commit the completed chunk",
|
|
901
|
+
],
|
|
902
|
+
options,
|
|
903
|
+
),
|
|
904
|
+
bulletList(["Narrow output keeps the gutter readable."], {
|
|
905
|
+
...options,
|
|
906
|
+
width: 24,
|
|
907
|
+
}),
|
|
908
|
+
bulletList(["ASCII output remains easy to grep."], {
|
|
909
|
+
...options,
|
|
910
|
+
profile: "plain",
|
|
911
|
+
}),
|
|
912
|
+
].join("\n");
|
|
913
|
+
}
|
|
914
|
+
|
|
875
915
|
/**
|
|
876
916
|
* Render wide or narrow table diagnostics.
|
|
877
917
|
*
|
package/src/index.js
CHANGED
|
@@ -40,6 +40,7 @@ export { diffBlock } from "./patterns/diff-block.js";
|
|
|
40
40
|
export { nextStepBlock } from "./patterns/next-step-block.js";
|
|
41
41
|
export { taskSummary } from "./patterns/task-summary.js";
|
|
42
42
|
export { barChart } from "./primitives/bar-chart.js";
|
|
43
|
+
export { bulletList } from "./primitives/bullet-list.js";
|
|
43
44
|
export { chip } from "./primitives/chip.js";
|
|
44
45
|
export { divider } from "./primitives/divider.js";
|
|
45
46
|
export { emptyState, errorBlock, hint } from "./primitives/feedback.js";
|
|
@@ -62,6 +63,8 @@ export {
|
|
|
62
63
|
renderSection,
|
|
63
64
|
} from "./reporters/create-reporter.js";
|
|
64
65
|
|
|
66
|
+
export { bulletTokens, getBulletSymbol } from "./theme/bullets.js";
|
|
67
|
+
|
|
65
68
|
export {
|
|
66
69
|
chartColours,
|
|
67
70
|
chipColours,
|
|
@@ -48,15 +48,15 @@ export function auditFinding(finding, options = {}) {
|
|
|
48
48
|
|
|
49
49
|
const title = isNonEmptyString(finding.title) ? finding.title : defaultTitle;
|
|
50
50
|
const summary = isNonEmptyString(finding.finding) ? finding.finding : "";
|
|
51
|
-
const evidence = normaliseStringList(finding.evidence)
|
|
52
|
-
const references = normaliseStringList(finding.references)
|
|
51
|
+
const evidence = normaliseStringList(finding.evidence);
|
|
52
|
+
const references = normaliseStringList(finding.references);
|
|
53
53
|
|
|
54
54
|
const sections = [
|
|
55
55
|
status(finding.result ?? resultTypes.UNKNOWN, summary, options),
|
|
56
56
|
renderLocation(finding.location, options),
|
|
57
|
-
renderSection("Evidence", evidence, options,
|
|
57
|
+
renderSection("Evidence", evidence, options, true),
|
|
58
58
|
renderTextSection("Recommendation", finding.recommendation, options),
|
|
59
|
-
renderSection("References", references, options,
|
|
59
|
+
renderSection("References", references, options, true),
|
|
60
60
|
].filter((section) => section !== "");
|
|
61
61
|
|
|
62
62
|
return [renderTitle(title, options), ...sections].join("\n\n");
|
|
@@ -48,13 +48,13 @@ export function commandResult(result, options = {}) {
|
|
|
48
48
|
|
|
49
49
|
const title = isNonEmptyString(result.title) ? result.title : defaultTitle;
|
|
50
50
|
const metadata = renderMetadata(result, options);
|
|
51
|
-
const details = normaliseStringList(result.details)
|
|
51
|
+
const details = normaliseStringList(result.details);
|
|
52
52
|
const summary = isNonEmptyString(result.summary) ? result.summary : "";
|
|
53
53
|
|
|
54
54
|
const sections = [
|
|
55
55
|
status(result.result ?? resultTypes.UNKNOWN, summary, options),
|
|
56
56
|
metadata,
|
|
57
|
-
renderSection("Details", details, options,
|
|
57
|
+
renderSection("Details", details, options, true),
|
|
58
58
|
].filter((section) => section !== "");
|
|
59
59
|
|
|
60
60
|
return [renderTitle(title, options), ...sections].join("\n\n");
|
|
@@ -69,7 +69,8 @@ function renderChecks(checks, options) {
|
|
|
69
69
|
status(check.result, formatLabel(check.name, check.detail, options), options),
|
|
70
70
|
);
|
|
71
71
|
|
|
72
|
-
|
|
72
|
+
// Status lines already start with a symbol, so only agent Markdown adds bullets.
|
|
73
|
+
return renderSection("Checks", lines, options, options.profile === profiles.AGENT);
|
|
73
74
|
}
|
|
74
75
|
|
|
75
76
|
/**
|
|
@@ -89,7 +90,8 @@ function renderFindings(findings, options) {
|
|
|
89
90
|
|
|
90
91
|
const lines = validFindings.map((finding) => status(finding.result, finding.message, options));
|
|
91
92
|
|
|
92
|
-
|
|
93
|
+
// Only agent Markdown adds bullets beside the status symbol.
|
|
94
|
+
return renderSection("Findings", lines, options, options.profile === profiles.AGENT);
|
|
93
95
|
}
|
|
94
96
|
|
|
95
97
|
/**
|
|
@@ -111,7 +113,8 @@ function renderSkippedChecks(skippedChecks, options) {
|
|
|
111
113
|
status(resultTypes.SKIPPED, formatLabel(check.name, check.reason, options), options),
|
|
112
114
|
);
|
|
113
115
|
|
|
114
|
-
|
|
116
|
+
// Only agent Markdown adds bullets beside the status symbol.
|
|
117
|
+
return renderSection("Skipped checks", lines, options, options.profile === profiles.AGENT);
|
|
115
118
|
}
|
|
116
119
|
|
|
117
120
|
/**
|
package/src/patterns/helpers.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { bulletList } from "../primitives/bullet-list.js";
|
|
1
2
|
import { profiles } from "../profiles/profiles.js";
|
|
2
3
|
|
|
3
4
|
/**
|
|
@@ -72,7 +73,8 @@ export function normaliseStringList(values) {
|
|
|
72
73
|
* @param {object} options
|
|
73
74
|
* Rendering options.
|
|
74
75
|
* @param {boolean} listItems
|
|
75
|
-
* Whether
|
|
76
|
+
* Whether to show each line as a bullet point, wrapped to the terminal
|
|
77
|
+
* width. Pass false for single values, commands, or numbered lines.
|
|
76
78
|
* @returns {string}
|
|
77
79
|
* Rendered section.
|
|
78
80
|
*/
|
|
@@ -83,10 +85,15 @@ export function renderSection(title, lines, options, listItems = true) {
|
|
|
83
85
|
|
|
84
86
|
const heading = options.profile === profiles.AGENT ? `## ${title}` : title;
|
|
85
87
|
|
|
86
|
-
const content =
|
|
87
|
-
|
|
88
|
+
const content = listItems
|
|
89
|
+
? bulletList(lines, {
|
|
90
|
+
profile: options.profile,
|
|
91
|
+
unicode: options.unicode,
|
|
92
|
+
width: options.width,
|
|
93
|
+
})
|
|
94
|
+
: lines.join("\n");
|
|
88
95
|
|
|
89
|
-
return [heading,
|
|
96
|
+
return [heading, content].join("\n");
|
|
90
97
|
}
|
|
91
98
|
|
|
92
99
|
/**
|
|
@@ -49,15 +49,13 @@ export function nextStepBlock(nextStep, options = {}) {
|
|
|
49
49
|
|
|
50
50
|
const commands = renderCommands(nextStep.commands, options);
|
|
51
51
|
|
|
52
|
-
const alternatives = normaliseStringList(nextStep.alternatives)
|
|
53
|
-
(alternative) => `- ${alternative}`,
|
|
54
|
-
);
|
|
52
|
+
const alternatives = normaliseStringList(nextStep.alternatives);
|
|
55
53
|
|
|
56
54
|
const sections = [
|
|
57
55
|
next,
|
|
58
56
|
reason,
|
|
59
57
|
commands,
|
|
60
|
-
renderSection("Alternatives", alternatives, options,
|
|
58
|
+
renderSection("Alternatives", alternatives, options, true),
|
|
61
59
|
].filter((section) => section !== "");
|
|
62
60
|
|
|
63
61
|
return [renderTitle(title, options), ...sections].join("\n\n");
|
|
@@ -47,13 +47,13 @@ export function taskSummary(summary, options = {}) {
|
|
|
47
47
|
const title = isNonEmptyString(summary.title) ? summary.title : defaultTitle;
|
|
48
48
|
const task = isNonEmptyString(summary.task) ? summary.task : "";
|
|
49
49
|
const detail = formatLabel(task, summary.summary, options);
|
|
50
|
-
const completed = normaliseStringList(summary.completed)
|
|
51
|
-
const remaining = normaliseStringList(summary.remaining)
|
|
50
|
+
const completed = normaliseStringList(summary.completed);
|
|
51
|
+
const remaining = normaliseStringList(summary.remaining);
|
|
52
52
|
|
|
53
53
|
const sections = [
|
|
54
54
|
status(summary.result ?? resultTypes.UNKNOWN, detail, options),
|
|
55
|
-
renderSection("Completed", completed, options,
|
|
56
|
-
renderSection("Remaining", remaining, options,
|
|
55
|
+
renderSection("Completed", completed, options, true),
|
|
56
|
+
renderSection("Remaining", remaining, options, true),
|
|
57
57
|
].filter((section) => section !== "");
|
|
58
58
|
|
|
59
59
|
return [renderTitle(title, options), ...sections].join("\n\n");
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { wrapText } from "../formatters/wrap.js";
|
|
2
|
+
import { getBulletSymbol } from "../theme/bullets.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Render items as a bullet list, wrapping each item's text beside its bullet.
|
|
6
|
+
*
|
|
7
|
+
* @param {object[]} items
|
|
8
|
+
* Item text, or `{ text, items }` for an item with nested items. Empty and
|
|
9
|
+
* malformed items are skipped.
|
|
10
|
+
* @param {object} options
|
|
11
|
+
* Rendering and wrapping options.
|
|
12
|
+
* @param {number} options.width
|
|
13
|
+
* Total line width used to calculate the available item width.
|
|
14
|
+
* @param {number} options.wrapWidth
|
|
15
|
+
* Explicit text width for each item.
|
|
16
|
+
* @returns {string}
|
|
17
|
+
* Rendered bullet list, or an empty string when no usable items exist.
|
|
18
|
+
*/
|
|
19
|
+
export function bulletList(items = [], options = {}) {
|
|
20
|
+
const normalisedItems = normaliseItems(items);
|
|
21
|
+
|
|
22
|
+
if (normalisedItems.length === 0) {
|
|
23
|
+
return "";
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return renderItems(normalisedItems, options, 0).join("\n");
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Render one level of items and its nested children.
|
|
31
|
+
*
|
|
32
|
+
* @param {object[]} items
|
|
33
|
+
* Normalised entries at the current nesting level.
|
|
34
|
+
* @param {object} options
|
|
35
|
+
* Rendering and wrapping options.
|
|
36
|
+
* @param {number} depth
|
|
37
|
+
* Zero-based nesting depth.
|
|
38
|
+
* @returns {string[]}
|
|
39
|
+
* Rendered lines for this level and its children.
|
|
40
|
+
*/
|
|
41
|
+
function renderItems(items, options, depth) {
|
|
42
|
+
const lines = [];
|
|
43
|
+
|
|
44
|
+
for (const entry of items) {
|
|
45
|
+
const prefix = createPrefix(depth, options);
|
|
46
|
+
const itemLines = wrapText(entry.text, resolveWrapWidth(prefix, options));
|
|
47
|
+
|
|
48
|
+
lines.push(
|
|
49
|
+
...itemLines.map((line, index) => {
|
|
50
|
+
if (index === 0) {
|
|
51
|
+
return `${prefix}${line}`;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return `${" ".repeat(prefix.length)}${line}`;
|
|
55
|
+
}),
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
const childItems = normaliseItems(entry.items);
|
|
59
|
+
|
|
60
|
+
if (childItems.length > 0) {
|
|
61
|
+
lines.push(...renderItems(childItems, options, depth + 1));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return lines;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Build the plain-text prefix used for one item and its continuations.
|
|
70
|
+
*
|
|
71
|
+
* @param {number} depth
|
|
72
|
+
* Zero-based nesting depth.
|
|
73
|
+
* @param {object} options
|
|
74
|
+
* Symbol rendering options.
|
|
75
|
+
* @returns {string}
|
|
76
|
+
* Uncoloured indentation, bullet, and trailing space.
|
|
77
|
+
*/
|
|
78
|
+
function createPrefix(depth, options) {
|
|
79
|
+
const symbol = getBulletSymbol(depth, options);
|
|
80
|
+
const gutter = `${symbol} `;
|
|
81
|
+
const indentation = " ".repeat(depth * gutter.length);
|
|
82
|
+
|
|
83
|
+
return `${indentation}${gutter}`;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Resolve the text width available after the item prefix.
|
|
88
|
+
*
|
|
89
|
+
* @param {string} prefix
|
|
90
|
+
* Plain-text item prefix.
|
|
91
|
+
* @param {object} options
|
|
92
|
+
* Rendering and wrapping options.
|
|
93
|
+
* @returns {number|undefined}
|
|
94
|
+
* Explicit text width, derived text width, or undefined for wrapText's default.
|
|
95
|
+
*/
|
|
96
|
+
function resolveWrapWidth(prefix, options) {
|
|
97
|
+
if (options.wrapWidth !== undefined) {
|
|
98
|
+
return options.wrapWidth;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (Number.isFinite(options.width)) {
|
|
102
|
+
return Math.max(1, options.width - prefix.length);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return undefined;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Convert a list value into renderable entries, dropping unusable items.
|
|
110
|
+
*
|
|
111
|
+
* @param {*} items
|
|
112
|
+
* Requested list entries.
|
|
113
|
+
* @returns {object[]}
|
|
114
|
+
* Non-empty strings and valid nested entries.
|
|
115
|
+
*/
|
|
116
|
+
function normaliseItems(items) {
|
|
117
|
+
if (!Array.isArray(items)) {
|
|
118
|
+
return [];
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return items.map(normaliseItem).filter((entry) => entry !== null);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Convert one supported input value into a list entry.
|
|
126
|
+
*
|
|
127
|
+
* @param {*} item
|
|
128
|
+
* Requested list value.
|
|
129
|
+
* @returns {object|null}
|
|
130
|
+
* Original object or a new entry for a string, or null when the value has no usable text.
|
|
131
|
+
*/
|
|
132
|
+
function normaliseItem(item) {
|
|
133
|
+
if (typeof item === "string" && item.trim() !== "") {
|
|
134
|
+
return {
|
|
135
|
+
items: [],
|
|
136
|
+
text: item,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (
|
|
141
|
+
item !== null &&
|
|
142
|
+
typeof item === "object" &&
|
|
143
|
+
typeof item.text === "string" &&
|
|
144
|
+
item.text.trim() !== ""
|
|
145
|
+
) {
|
|
146
|
+
return item;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { profiles } from "../profiles/profiles.js";
|
|
2
|
+
|
|
3
|
+
// Bullet symbols for Unicode, ASCII, and Markdown-compatible agent output.
|
|
4
|
+
export const bulletTokens = {
|
|
5
|
+
agent: "-",
|
|
6
|
+
ascii: "*",
|
|
7
|
+
unicode: {
|
|
8
|
+
nested: "◦",
|
|
9
|
+
root: "•",
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Resolve the display symbol for one bullet depth.
|
|
15
|
+
*
|
|
16
|
+
* @param {number} depth
|
|
17
|
+
* Zero-based nesting depth.
|
|
18
|
+
* @param {object} options
|
|
19
|
+
* Symbol rendering options.
|
|
20
|
+
* @param {string} options.profile
|
|
21
|
+
* Active output profile.
|
|
22
|
+
* @param {boolean} options.unicode
|
|
23
|
+
* Whether to return the Unicode symbol.
|
|
24
|
+
* @returns {string}
|
|
25
|
+
* Display symbol for the requested bullet depth and profile.
|
|
26
|
+
*/
|
|
27
|
+
export function getBulletSymbol(depth = 0, options = {}) {
|
|
28
|
+
if (options.profile === profiles.AGENT) {
|
|
29
|
+
return bulletTokens.agent;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (
|
|
33
|
+
options.profile === profiles.CI ||
|
|
34
|
+
options.profile === profiles.PLAIN ||
|
|
35
|
+
options.unicode === false
|
|
36
|
+
) {
|
|
37
|
+
return bulletTokens.ascii;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return depth === 0 ? bulletTokens.unicode.root : bulletTokens.unicode.nested;
|
|
41
|
+
}
|