@citron-systems/citron-ds 1.0.0 → 1.0.2
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 +218 -149
- package/cli/citron-mascot.mjs +117 -0
- package/dist/ai/inkblot-ai-reference.json +582 -570
- package/dist/ai/inkblot-tokens-resolved.json +25 -0
- package/dist/ai/inkblot-tokens-schema.json +54 -54
- package/dist/brand/citron-mascot-mono.svg +17 -0
- package/dist/brand/citron-mascot.svg +21 -0
- package/dist/brand/readme-hero.svg +61 -0
- package/dist/bundle/README.md +28 -0
- package/dist/bundle/ai-reference.json +582 -0
- package/dist/bundle/brand/citron-mascot-mono.svg +17 -0
- package/dist/bundle/brand/citron-mascot.svg +21 -0
- package/dist/bundle/brand/readme-hero.svg +61 -0
- package/dist/bundle/preview/mascot.html +72 -0
- package/dist/bundle/system/ai.json +168 -0
- package/dist/bundle/system/cli.json +340 -0
- package/dist/bundle/system/components.json +304 -0
- package/dist/bundle/system/content.json +168 -0
- package/dist/bundle/system/devtools.json +95 -0
- package/dist/bundle/system/foundations.json +121 -0
- package/dist/bundle/system/grid.json +101 -0
- package/dist/bundle/system/icons.json +507 -0
- package/dist/bundle/system/index.json +57 -0
- package/dist/bundle/system/inkblot-ai-reference.json +582 -0
- package/dist/bundle/system/motion.json +159 -0
- package/dist/bundle/tokens/primitive/breakpoint.tokens.json +14 -0
- package/dist/bundle/tokens/primitive/color.tokens.json +71 -0
- package/dist/bundle/tokens/primitive/devtools.palette.tokens.json +55 -0
- package/dist/bundle/tokens/primitive/duration.tokens.json +38 -0
- package/dist/bundle/tokens/primitive/grid.tokens.json +34 -0
- package/dist/bundle/tokens/primitive/radius.tokens.json +26 -0
- package/dist/bundle/tokens/primitive/shadow.tokens.json +41 -0
- package/dist/bundle/tokens/primitive/spacing.tokens.json +38 -0
- package/dist/bundle/tokens/primitive/typography.tokens.json +60 -0
- package/dist/bundle/tokens/primitive/zindex.tokens.json +19 -0
- package/dist/bundle/tokens/semantic/dark.tokens.json +43 -0
- package/dist/bundle/tokens/semantic/devtools.semantic.tokens.json +79 -0
- package/dist/bundle/tokens/semantic/inkblot.semantic.tokens.json +140 -0
- package/dist/bundle/tokens-schema.json +54 -0
- package/dist/bundle/tokens.flat.json +224 -0
- package/dist/bundle/tokens.resolved.json +224 -0
- package/dist/bundle/variables.css +228 -0
- package/dist/bundle/variables.scss +225 -0
- package/dist/css/inkblot-variables.css +25 -0
- package/dist/index.html +956 -0
- package/dist/js/inkblot-tokens.js +25 -0
- package/dist/js/inkblot-tokens.json +25 -0
- package/dist/preview/mascot.html +72 -0
- package/dist/scss/_inkblot-variables.scss +25 -0
- package/package.json +73 -61
- package/tokens/primitive/breakpoint.tokens.json +14 -14
- package/tokens/primitive/color.tokens.json +71 -71
- package/tokens/primitive/devtools.palette.tokens.json +55 -0
- package/tokens/primitive/duration.tokens.json +38 -38
- package/tokens/primitive/grid.tokens.json +34 -34
- package/tokens/primitive/radius.tokens.json +26 -26
- package/tokens/primitive/shadow.tokens.json +41 -41
- package/tokens/primitive/spacing.tokens.json +38 -38
- package/tokens/primitive/typography.tokens.json +60 -60
- package/tokens/primitive/zindex.tokens.json +19 -19
- package/tokens/semantic/dark.tokens.json +43 -43
- package/tokens/semantic/devtools.semantic.tokens.json +79 -0
- package/tokens/semantic/inkblot.semantic.tokens.json +140 -140
package/README.md
CHANGED
|
@@ -1,149 +1,218 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
npm
|
|
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
|
-
|
|
130
|
-
|
|
131
|
-
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
<img src="assets/brand/readme-hero.svg" width="100%" alt="Citron Design System — mascot and wordmark on citron-toned dark background" />
|
|
4
|
+
|
|
5
|
+
<br />
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/@citron-systems/citron-ds)
|
|
8
|
+
[](https://opensource.org/licenses/MIT)
|
|
9
|
+
[](https://github.com/Inkblot-Studio/citron-ds)
|
|
10
|
+
|
|
11
|
+
**Citron** — Apple-inspired, accessible, AI-ready design tokens. Warmly minimal, quietly distinctive.
|
|
12
|
+
|
|
13
|
+
[Repository](https://github.com/Inkblot-Studio/citron-ds) · [npm package](https://www.npmjs.com/package/@citron-systems/citron-ds)
|
|
14
|
+
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Install
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install @citron-systems/citron-ds
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### CDN (no build step)
|
|
26
|
+
|
|
27
|
+
```html
|
|
28
|
+
<link rel="stylesheet" href="https://unpkg.com/@citron-systems/citron-ds/dist/css/inkblot-variables.css">
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Quick Start
|
|
34
|
+
|
|
35
|
+
### CSS (recommended)
|
|
36
|
+
|
|
37
|
+
```css
|
|
38
|
+
@import '@citron-systems/citron-ds/css';
|
|
39
|
+
|
|
40
|
+
.button {
|
|
41
|
+
background: var(--inkblot-semantic-color-interactive-primary);
|
|
42
|
+
color: var(--inkblot-semantic-color-text-inverse);
|
|
43
|
+
padding: var(--inkblot-spacing-3) var(--inkblot-spacing-6);
|
|
44
|
+
border-radius: var(--inkblot-radius-lg);
|
|
45
|
+
font-weight: var(--inkblot-typography-font-weight-medium);
|
|
46
|
+
min-height: var(--inkblot-size-touch-target-min);
|
|
47
|
+
transition: all var(--inkblot-duration-fast) var(--inkblot-easing-default);
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### SCSS
|
|
52
|
+
|
|
53
|
+
```scss
|
|
54
|
+
@use '@citron-systems/citron-ds/scss' as *;
|
|
55
|
+
|
|
56
|
+
.card {
|
|
57
|
+
background: var(--inkblot-semantic-color-background-secondary);
|
|
58
|
+
border: 1px solid var(--inkblot-semantic-color-border-default);
|
|
59
|
+
border-radius: var(--inkblot-radius-xl);
|
|
60
|
+
padding: var(--inkblot-spacing-6);
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### JavaScript / ESM
|
|
65
|
+
|
|
66
|
+
```javascript
|
|
67
|
+
import {
|
|
68
|
+
InkblotColorAccentCitron500,
|
|
69
|
+
InkblotSpacing4,
|
|
70
|
+
InkblotRadiusLg,
|
|
71
|
+
} from '@citron-systems/citron-ds';
|
|
72
|
+
|
|
73
|
+
// Use in JS-driven styling (e.g. React inline, Canvas, etc.)
|
|
74
|
+
const styles = {
|
|
75
|
+
backgroundColor: InkblotColorAccentCitron500,
|
|
76
|
+
padding: InkblotSpacing4,
|
|
77
|
+
borderRadius: InkblotRadiusLg,
|
|
78
|
+
};
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### JSON (for tooling, build scripts, AI)
|
|
82
|
+
|
|
83
|
+
```javascript
|
|
84
|
+
import tokens from '@citron-systems/citron-ds/tokens';
|
|
85
|
+
// Flat resolved values: { "inkblot.color.accent.citron.500": "#c4a030", ... }
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Package exports
|
|
91
|
+
|
|
92
|
+
| Import path | Contents |
|
|
93
|
+
|-------------|----------|
|
|
94
|
+
| `@citron-systems/citron-ds` | ESM JS tokens (default) |
|
|
95
|
+
| `@citron-systems/citron-ds/css` | CSS variables (`:root`) |
|
|
96
|
+
| `@citron-systems/citron-ds/scss` | SCSS variables |
|
|
97
|
+
| `@citron-systems/citron-ds/tokens` | Flat JSON (resolved values) |
|
|
98
|
+
| `@citron-systems/citron-ds/ai-reference` | AI agent reference (token map, patterns, rules) |
|
|
99
|
+
| `@citron-systems/citron-ds/brand/citron-mascot.svg` | Citron mascot (full color; optional `--citron-mascot-fill`) |
|
|
100
|
+
| `@citron-systems/citron-ds/brand/citron-mascot-mono.svg` | Mascot lockup (`currentColor`) |
|
|
101
|
+
| `@citron-systems/citron-ds/bundle` | Bundle entry (`dist/bundle/README.md`) |
|
|
102
|
+
| `@citron-systems/citron-ds/bundle/*` | Resolved tokens, CSS/SCSS bundles, system JSON, etc. |
|
|
103
|
+
| `@citron-systems/citron-ds/preview/mascot.html` | Static mascot preview page |
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## Brand assets
|
|
108
|
+
|
|
109
|
+
Source SVGs live in `assets/brand/`; `npm run build` copies them into `dist/brand/` for publishing. Import from the package as in the table above, or copy from `dist/brand/` in a checkout.
|
|
110
|
+
|
|
111
|
+
| File | Use |
|
|
112
|
+
|------|-----|
|
|
113
|
+
| `citron-mascot.svg` | Full-color mark (`#c4a030` citron **500**) |
|
|
114
|
+
| `citron-mascot-mono.svg` | Single-color / `currentColor` lockups |
|
|
115
|
+
| `readme-hero.svg` | README banner (warm dark + citron accent **900→950**) |
|
|
116
|
+
|
|
117
|
+
**GitHub (maintainers):** Set the repository **Social preview** (Settings → General) to a **1280×640** image exported from `readme-hero.svg` (or a wider crop). Use `citron-mascot-mono.svg` for the repo or org avatar so the mark stays clear at small sizes.
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## CLI
|
|
122
|
+
|
|
123
|
+
The **citron-mascot** binary prints the ASCII Citron mascot (with a short color animation in supported terminals).
|
|
124
|
+
|
|
125
|
+
From a project that already depends on this package:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
npx citron-mascot
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
One-off without adding a dependency:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
npx --package=@citron-systems/citron-ds citron-mascot
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## Principles
|
|
140
|
+
|
|
141
|
+
- **Radical Clarity** — One correct interpretation per rule. No ambiguity.
|
|
142
|
+
- **Composable Independence** — Every component is self-contained and works in isolation.
|
|
143
|
+
- **Universal Access** — WCAG AAA. 7:1 contrast. 44px touch targets. Full keyboard nav.
|
|
144
|
+
- **AI-First** — Every token, component, and rule is machine-parseable JSON.
|
|
145
|
+
- **Deliberate Restraint** — Minimum visual complexity. Every element earns its place.
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## Color modes
|
|
150
|
+
|
|
151
|
+
Light mode is default. Dark mode activates via:
|
|
152
|
+
|
|
153
|
+
- `[data-theme="dark"]` on a parent element, or
|
|
154
|
+
- `prefers-color-scheme: dark` (system preference)
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## For AI agents
|
|
159
|
+
|
|
160
|
+
**Primary reference** (include in context): `@citron-systems/citron-ds/ai-reference`
|
|
161
|
+
|
|
162
|
+
- CSS variable map for all semantic tokens
|
|
163
|
+
- Composite patterns (form, card, modal, table, list item)
|
|
164
|
+
- Breakpoints, grid, easing (in CSS format)
|
|
165
|
+
- Icon semantics, CSS snippets, component spacing
|
|
166
|
+
- Validation and ARIA patterns
|
|
167
|
+
|
|
168
|
+
**Rule**: Always use semantic tokens (`var(--inkblot-semantic-color-*)`), never primitives.
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## Standards
|
|
173
|
+
|
|
174
|
+
- **Tokens**: [W3C Design Tokens Community Group](https://www.designtokens.org/)
|
|
175
|
+
- **Build**: [Style Dictionary](https://styledictionary.com/) v4
|
|
176
|
+
- **Accessibility**: WCAG 2.2 AAA
|
|
177
|
+
- **Contrast**: 7:1 normal text, 4.5:1 large text, 3:1 UI components
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## Development
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
git clone https://github.com/Inkblot-Studio/citron-ds.git
|
|
185
|
+
cd citron-ds
|
|
186
|
+
npm install
|
|
187
|
+
npm run build
|
|
188
|
+
npm run dev # Live preview at localhost:5173
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
- **`npm run build`** — Style Dictionary outputs plus copy steps for brand assets, mascot preview, and desktop bundle (`dist/`).
|
|
192
|
+
- **`prepublishOnly`** runs `npm run build` before `npm publish`.
|
|
193
|
+
|
|
194
|
+
### Publish note (maintainers)
|
|
195
|
+
|
|
196
|
+
If you publish with **npm provenance** from GitHub Actions, `package.json` **`repository.url`** must point at the **same** GitHub repository as the workflow (otherwise the registry returns `422` provenance validation errors). Run `npm pkg fix` if npm warns about normalized fields during publish.
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## Deploy preview to Vercel
|
|
201
|
+
|
|
202
|
+
1. Push to GitHub and [import the repo](https://vercel.com/new) in Vercel.
|
|
203
|
+
2. Vercel will auto-detect the build from `vercel.json`.
|
|
204
|
+
3. Deploy — the preview site will be live.
|
|
205
|
+
|
|
206
|
+
Or deploy from the CLI:
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
npm install -g vercel
|
|
210
|
+
npm run build:deploy
|
|
211
|
+
vercel --prod
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## License
|
|
217
|
+
|
|
218
|
+
MIT © Inkblot Studio
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
3
|
+
import { dirname, join } from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
|
|
6
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
const pkgPath = join(__dirname, '..', 'package.json');
|
|
8
|
+
const version = JSON.parse(readFileSync(pkgPath, 'utf8')).version ?? '0.0.0';
|
|
9
|
+
|
|
10
|
+
const CITRON = '\x1b[38;2;196;160;48m';
|
|
11
|
+
const DIM = '\x1b[2m';
|
|
12
|
+
const RESET = '\x1b[0m';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Compact ASCII: small pause eyes + stepped block smile (diagonal “wings”, solid base only).
|
|
16
|
+
* No extra rows that cross the mouth — avoids a busy / intersecting look. All lines = CANVAS_W.
|
|
17
|
+
*/
|
|
18
|
+
export const MASCOT_CANVAS_W = 28;
|
|
19
|
+
|
|
20
|
+
export const SMILE_FRAMES = [
|
|
21
|
+
[
|
|
22
|
+
'',
|
|
23
|
+
'',
|
|
24
|
+
'',
|
|
25
|
+
' ██ ██ ',
|
|
26
|
+
' ██ ██ ',
|
|
27
|
+
' ██ ██ ',
|
|
28
|
+
' ██ ██ ',
|
|
29
|
+
' ██████████ ',
|
|
30
|
+
'',
|
|
31
|
+
' Citron ',
|
|
32
|
+
'',
|
|
33
|
+
],
|
|
34
|
+
[
|
|
35
|
+
'',
|
|
36
|
+
'',
|
|
37
|
+
'',
|
|
38
|
+
' ██ ██ ',
|
|
39
|
+
' ██ ██ ',
|
|
40
|
+
'',
|
|
41
|
+
' ██ ██ ',
|
|
42
|
+
' ██ ██ ',
|
|
43
|
+
' ██████████ ',
|
|
44
|
+
'',
|
|
45
|
+
' Citron ',
|
|
46
|
+
'',
|
|
47
|
+
],
|
|
48
|
+
];
|
|
49
|
+
|
|
50
|
+
const ASCII = SMILE_FRAMES[0];
|
|
51
|
+
|
|
52
|
+
function usage() {
|
|
53
|
+
return `citron-mascot — Citron mascot in the terminal (${version})
|
|
54
|
+
|
|
55
|
+
Usage:
|
|
56
|
+
citron-mascot [options]
|
|
57
|
+
npm run mascot (in this repo)
|
|
58
|
+
npx --package @citron-systems/citron-ds citron-mascot
|
|
59
|
+
|
|
60
|
+
Options:
|
|
61
|
+
--animate Alternate smile frames a few times (TTY: clears screen between frames)
|
|
62
|
+
--no-color Plain text (also respects NO_COLOR=1)
|
|
63
|
+
--help, -h Show this message
|
|
64
|
+
|
|
65
|
+
Browser preview (no terminal): open dist/preview/mascot.html, or after npm install:
|
|
66
|
+
node_modules/@citron-systems/citron-ds/dist/preview/mascot.html
|
|
67
|
+
`;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function printMascot(lines, noColor) {
|
|
71
|
+
for (const line of lines) {
|
|
72
|
+
if (line === '' || noColor) {
|
|
73
|
+
process.stdout.write(line + '\n');
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
if (line.includes('Citron')) {
|
|
77
|
+
process.stdout.write(DIM + line + RESET + '\n');
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
process.stdout.write(CITRON + line + RESET + '\n');
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async function main() {
|
|
85
|
+
const argv = process.argv.slice(2);
|
|
86
|
+
if (argv.includes('--help') || argv.includes('-h')) {
|
|
87
|
+
process.stdout.write(usage());
|
|
88
|
+
process.exit(0);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const noColor =
|
|
92
|
+
argv.includes('--no-color') ||
|
|
93
|
+
process.env.NO_COLOR === '1' ||
|
|
94
|
+
process.env.NO_COLOR === 'true' ||
|
|
95
|
+
!process.stdout.isTTY;
|
|
96
|
+
|
|
97
|
+
if (argv.includes('--animate')) {
|
|
98
|
+
const cycles = SMILE_FRAMES.length * 5;
|
|
99
|
+
for (let i = 0; i < cycles; i++) {
|
|
100
|
+
if (process.stdout.isTTY && !noColor) {
|
|
101
|
+
process.stdout.write('\x1b[2J\x1b[H');
|
|
102
|
+
}
|
|
103
|
+
printMascot(SMILE_FRAMES[i % SMILE_FRAMES.length], noColor);
|
|
104
|
+
if (i < cycles - 1) {
|
|
105
|
+
await new Promise((r) => setTimeout(r, 380));
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
printMascot(ASCII, noColor);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
main().catch((err) => {
|
|
115
|
+
process.stderr.write(String(err) + '\n');
|
|
116
|
+
process.exit(1);
|
|
117
|
+
});
|