@crustjs/style 0.0.1

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 ADDED
@@ -0,0 +1,227 @@
1
+ # @crustjs/style
2
+
3
+ Terminal styling foundation for the [Crust](https://crustjs.com) CLI framework.
4
+
5
+ `@crustjs/style` provides ANSI-safe styling primitives, terminal capability awareness, layout helpers, and a semantic markdown theme — so CLI output remains readable, aligned, and consistent across color and no-color environments.
6
+
7
+ Zero runtime dependencies.
8
+
9
+ ## Install
10
+
11
+ ```sh
12
+ bun add @crustjs/style
13
+ ```
14
+
15
+ ## Quick Start
16
+
17
+ ```ts
18
+ import { style } from "@crustjs/style";
19
+
20
+ // The default `style` instance auto-detects color support
21
+ console.log(style.bold("Build succeeded"));
22
+ console.log(style.red("Error: missing argument"));
23
+ console.log(style.dim("hint: use --help for usage"));
24
+ ```
25
+
26
+ ## Primitive Styling
27
+
28
+ Direct styling functions that always emit ANSI codes (useful when you control output directly):
29
+
30
+ ```ts
31
+ import { bold, red, italic, bgYellow } from "@crustjs/style";
32
+
33
+ console.log(bold("important"));
34
+ console.log(red("error"));
35
+ console.log(italic("note"));
36
+ console.log(bgYellow("highlighted"));
37
+ ```
38
+
39
+ ### Available Modifiers
40
+
41
+ `bold`, `dim`, `italic`, `underline`, `inverse`, `hidden`, `strikethrough`
42
+
43
+ ### Available Colors
44
+
45
+ **Foreground:** `black`, `red`, `green`, `yellow`, `blue`, `magenta`, `cyan`, `white`, `gray`, `brightRed`, `brightGreen`, `brightYellow`, `brightBlue`, `brightMagenta`, `brightCyan`, `brightWhite`
46
+
47
+ **Background:** `bgBlack`, `bgRed`, `bgGreen`, `bgYellow`, `bgBlue`, `bgMagenta`, `bgCyan`, `bgWhite`, `bgBrightBlack`, `bgBrightRed`, `bgBrightGreen`, `bgBrightYellow`, `bgBrightBlue`, `bgBrightMagenta`, `bgBrightCyan`, `bgBrightWhite`
48
+
49
+ ### Composing Styles
50
+
51
+ ```ts
52
+ import { applyStyle, composeStyles, boldCode, redCode } from "@crustjs/style";
53
+
54
+ const boldRed = composeStyles(boldCode, redCode);
55
+ console.log(applyStyle("critical error", boldRed));
56
+ ```
57
+
58
+ Nested styles are handled safely — no style bleed across boundaries.
59
+
60
+ ## Color Modes
61
+
62
+ Control when ANSI codes are emitted using `createStyle`:
63
+
64
+ ```ts
65
+ import { createStyle } from "@crustjs/style";
66
+
67
+ // Auto-detect (default) — respects NO_COLOR and TTY status
68
+ const auto = createStyle({ mode: "auto" });
69
+
70
+ // Always emit ANSI codes
71
+ const color = createStyle({ mode: "always" });
72
+ console.log(color.red("always red"));
73
+
74
+ // Never emit ANSI codes — returns plain text
75
+ const plain = createStyle({ mode: "never" });
76
+ console.log(plain.red("just text")); // "just text"
77
+ ```
78
+
79
+ The default `style` export uses `"auto"` mode:
80
+
81
+ - Emits ANSI when stdout is a TTY and `NO_COLOR` is not set
82
+ - Returns plain text otherwise
83
+
84
+ ### Deterministic Testing
85
+
86
+ Inject capability overrides for predictable test output:
87
+
88
+ ```ts
89
+ const testStyle = createStyle({
90
+ mode: "auto",
91
+ overrides: { isTTY: true, noColor: undefined },
92
+ });
93
+ ```
94
+
95
+ ## Text Utilities
96
+
97
+ ANSI-aware text measurement and layout:
98
+
99
+ ```ts
100
+ import {
101
+ stripAnsi,
102
+ visibleWidth,
103
+ wrapText,
104
+ padStart,
105
+ padEnd,
106
+ center,
107
+ } from "@crustjs/style";
108
+
109
+ // Strip ANSI escape sequences
110
+ stripAnsi("\x1b[1mhello\x1b[22m"); // "hello"
111
+
112
+ // Measure visible width (ignores ANSI codes, counts CJK as 2)
113
+ visibleWidth("\x1b[31mhello\x1b[39m"); // 5
114
+
115
+ // Wrap text to a visible width, preserving active styles across breaks
116
+ wrapText("a long line of styled text", 20);
117
+ wrapText("force break mode", 10, { wordBreak: false });
118
+
119
+ // ANSI-safe padding and alignment
120
+ padStart("42", 6); // " 42"
121
+ padEnd("name", 10); // "name "
122
+ center("title", 20); // " title "
123
+ ```
124
+
125
+ ## Block Helpers
126
+
127
+ Format structured blocks for terminal output:
128
+
129
+ ### Lists
130
+
131
+ ```ts
132
+ import { unorderedList, orderedList, taskList } from "@crustjs/style";
133
+
134
+ unorderedList(["apples", "bananas", "cherries"]);
135
+ // • apples
136
+ // • bananas
137
+ // • cherries
138
+
139
+ orderedList(["first", "second", "third"]);
140
+ // 1. first
141
+ // 2. second
142
+ // 3. third
143
+
144
+ taskList([
145
+ { text: "Write tests", checked: true },
146
+ { text: "Update docs", checked: false },
147
+ ]);
148
+ // [x] Write tests
149
+ // [ ] Update docs
150
+ ```
151
+
152
+ Lists support `indent` for nesting and custom markers.
153
+
154
+ ### Tables
155
+
156
+ ```ts
157
+ import { table } from "@crustjs/style";
158
+
159
+ table(
160
+ ["Name", "Version", "Status"],
161
+ [
162
+ ["core", "1.2.0", "stable"],
163
+ ["style", "0.1.0", "new"],
164
+ ],
165
+ );
166
+ // | Name | Version | Status |
167
+ // | ----- | ------- | ------ |
168
+ // | core | 1.2.0 | stable |
169
+ // | style | 0.1.0 | new |
170
+ ```
171
+
172
+ Tables support per-column alignment (`"left"`, `"right"`, `"center"`), custom padding, and ANSI-styled cell content with correct alignment.
173
+
174
+ ## Markdown Theme
175
+
176
+ Semantic theme slots for styling GFM (GitHub Flavored Markdown) constructs:
177
+
178
+ ```ts
179
+ import { defaultTheme } from "@crustjs/style";
180
+
181
+ // Apply theme slots to extracted markdown content
182
+ console.log(defaultTheme.heading1("Getting Started"));
183
+ console.log(defaultTheme.strong("important"));
184
+ console.log(defaultTheme.inlineCode("npm install"));
185
+ console.log(defaultTheme.linkText("docs") + " " + defaultTheme.linkUrl("https://crustjs.com"));
186
+ ```
187
+
188
+ ### Custom Themes
189
+
190
+ Override specific slots while inheriting defaults:
191
+
192
+ ```ts
193
+ import { createTheme } from "@crustjs/style";
194
+
195
+ const theme = createTheme({
196
+ style: { mode: "always" },
197
+ overrides: {
198
+ heading1: (text) => `>>> ${text.toUpperCase()} <<<`,
199
+ strong: (text) => `**${text}**`,
200
+ },
201
+ });
202
+ ```
203
+
204
+ ### Theme Slots
205
+
206
+ The `MarkdownTheme` interface covers 30 GFM slots:
207
+
208
+ | Category | Slots |
209
+ | --- | --- |
210
+ | Headings | `heading1` through `heading6` |
211
+ | Text | `text`, `emphasis`, `strong`, `strongEmphasis`, `strikethrough` |
212
+ | Code | `inlineCode`, `codeFence`, `codeInfo`, `codeText` |
213
+ | Links | `linkText`, `linkUrl`, `autolink` |
214
+ | Lists | `listMarker`, `orderedListMarker`, `taskChecked`, `taskUnchecked` |
215
+ | Blockquotes | `blockquoteMarker`, `blockquoteText` |
216
+ | Tables | `tableHeader`, `tableCell`, `tableBorder` |
217
+ | Other | `thematicBreak`, `imageAltText`, `imageUrl` |
218
+
219
+ Theme slots are parser-agnostic `string => string` functions. Markdown parsing and AST handling belong to a separate consumer package — `@crustjs/style` provides the presentation layer only.
220
+
221
+ ## Documentation
222
+
223
+ See the full docs at [crustjs.com](https://crustjs.com).
224
+
225
+ ## License
226
+
227
+ MIT