starlight-cli 1.1.4 → 1.1.6

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "starlight-cli",
3
- "version": "1.1.4",
3
+ "version": "1.1.6",
4
4
  "description": "Starlight Programming Language CLI",
5
5
  "bin": {
6
6
  "starlight": "index.js"
@@ -13,6 +13,9 @@
13
13
  "license": "MIT",
14
14
  "dependencies": {
15
15
  "blessed": "^0.1.81",
16
+ "markdown-it": "^14.1.0",
17
+ "markdown-it-footnote": "^4.0.0",
18
+ "markdown-it-task-lists": "^2.1.1",
16
19
  "readline-sync": "^1.4.10",
17
20
  "starlight-color": "^1.0.4"
18
21
  },
package/src/evaluator.js CHANGED
@@ -107,7 +107,6 @@ suggest(name, env) {
107
107
 
108
108
  return best;
109
109
  }
110
-
111
110
  formatValue(value, seen = new Set()) {
112
111
  const color = require('starlight-color');
113
112
 
@@ -152,7 +151,7 @@ formatValue(value, seen = new Set()) {
152
151
  } catch {
153
152
  return color.red('[Unprintable]');
154
153
  }
155
- }
154
+ }
156
155
 
157
156
 
158
157
  setupBuiltins() {
@@ -167,6 +166,64 @@ formatValue(value, seen = new Set()) {
167
166
  if (Array.isArray(arg)) return 'array';
168
167
  return typeof arg;
169
168
  });
169
+ this.global.define('map', async (array, fn) => {
170
+ if (!Array.isArray(array)) {
171
+ throw new RuntimeError('map() expects an array', null, this.source);
172
+ }
173
+ if (typeof fn !== 'function') {
174
+ throw new RuntimeError('map() expects a function', null, this.source);
175
+ }
176
+
177
+ const result = [];
178
+ for (let i = 0; i < array.length; i++) {
179
+ result.push(await fn(array[i], i, array));
180
+ }
181
+ return result;
182
+ });
183
+ this.global.define('filter', async (array, fn) => {
184
+ if (!Array.isArray(array)) {
185
+ throw new RuntimeError('filter() expects an array', null, this.source);
186
+ }
187
+ if (typeof fn !== 'function') {
188
+ throw new RuntimeError('filter() expects a function', null, this.source);
189
+ }
190
+
191
+ const result = [];
192
+ for (let i = 0; i < array.length; i++) {
193
+ if (await fn(array[i], i, array)) {
194
+ result.push(array[i]);
195
+ }
196
+ }
197
+ return result;
198
+ });
199
+ this.global.define('reduce', async (array, fn, initial) => {
200
+ if (!Array.isArray(array)) {
201
+ throw new RuntimeError('reduce() expects an array', null, this.source);
202
+ }
203
+ if (typeof fn !== 'function') {
204
+ throw new RuntimeError('reduce() expects a function', null, this.source);
205
+ }
206
+
207
+ let acc;
208
+ let startIndex = 0;
209
+
210
+ if (initial !== undefined) {
211
+ acc = initial;
212
+ } else {
213
+ if (array.length === 0) {
214
+ throw new RuntimeError('reduce() of empty array with no initial value', null, this.source);
215
+ }
216
+ acc = array[0];
217
+ startIndex = 1;
218
+ }
219
+
220
+ for (let i = startIndex; i < array.length; i++) {
221
+ acc = await fn(acc, array[i], i, array);
222
+ }
223
+
224
+ return acc;
225
+ });
226
+
170
227
  this.global.define('keys', arg => arg && typeof arg === 'object' ? Object.keys(arg) : []);
171
228
  this.global.define('values', arg => arg && typeof arg === 'object' ? Object.values(arg) : []);
172
229
  this.global.define('range', (...args) => {
package/src/starlight.js CHANGED
@@ -4,12 +4,15 @@ const os = require('os');
4
4
  const { exec } = require('child_process');
5
5
  const readline = require('readline');
6
6
  const readlineSync = require('readline-sync');
7
+ const MarkdownIt = require('markdown-it');
8
+ const mdTaskLists = require('markdown-it-task-lists');
9
+ const mdFootnote = require('markdown-it-footnote');
7
10
 
8
11
  const Lexer = require('./lexer');
9
12
  const Parser = require('./parser');
10
13
  const Evaluator = require('./evaluator');
11
14
 
12
- const VERSION = '1.1.4';
15
+ const VERSION = '1.1.6';
13
16
 
14
17
  const COLOR = {
15
18
  reset: '\x1b[0m',
@@ -35,6 +38,99 @@ function fatal(msg) {
35
38
  console.error(COLOR.white + msg + COLOR.reset);
36
39
  waitAndExit(1);
37
40
  }
41
+ function renderMarkdown(mdPath) {
42
+ let markdown;
43
+ try {
44
+ markdown = fs.readFileSync(mdPath, 'utf8');
45
+ } catch (e) {
46
+ console.error(COLOR.white + `Failed to read markdown: ${e.message}` + COLOR.reset);
47
+ return waitAndExit(1);
48
+ }
49
+
50
+ const md = new MarkdownIt({
51
+ html: true,
52
+ linkify: true,
53
+ typographer: true
54
+ })
55
+ .use(mdTaskLists, { enabled: true })
56
+ .use(mdFootnote);
57
+
58
+ const html = `<!DOCTYPE html>
59
+ <html lang="en">
60
+ <head>
61
+ <meta charset="UTF-8">
62
+ <title>${path.basename(mdPath)}</title>
63
+ <style>
64
+ body {
65
+ font-family: system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
66
+ padding: 40px;
67
+ max-width: 900px;
68
+ margin: auto;
69
+ background: #0e0e11;
70
+ color: #eaeaea;
71
+ line-height: 1.6;
72
+ }
73
+ h1, h2, h3, h4 {
74
+ border-bottom: 1px solid #2a2a35;
75
+ padding-bottom: 6px;
76
+ }
77
+ pre {
78
+ background: #1e1e2e;
79
+ padding: 16px;
80
+ overflow-x: auto;
81
+ border-radius: 8px;
82
+ }
83
+ code {
84
+ background: #1e1e2e;
85
+ padding: 2px 6px;
86
+ border-radius: 4px;
87
+ color: #f8f8f2;
88
+ }
89
+ table {
90
+ border-collapse: collapse;
91
+ width: 100%;
92
+ margin: 20px 0;
93
+ }
94
+ th, td {
95
+ border: 1px solid #2a2a35;
96
+ padding: 8px;
97
+ }
98
+ th {
99
+ background: #1b1b25;
100
+ }
101
+ a {
102
+ color: #7aa2f7;
103
+ text-decoration: none;
104
+ }
105
+ a:hover {
106
+ text-decoration: underline;
107
+ }
108
+ blockquote {
109
+ border-left: 4px solid #7aa2f7;
110
+ padding-left: 16px;
111
+ color: #c0caf5;
112
+ margin: 20px 0;
113
+ }
114
+ </style>
115
+ </head>
116
+ <body>
117
+ ${md.render(markdown)}
118
+ </body>
119
+ </html>`;
120
+
121
+ const tempHtml = path.join(
122
+ os.tmpdir(),
123
+ `starlight-md-${Date.now()}.html`
124
+ );
125
+
126
+ fs.writeFileSync(tempHtml, html, 'utf8');
127
+
128
+ openURL(`file://${tempHtml}`);
129
+
130
+ setTimeout(() => {
131
+ try { fs.unlinkSync(tempHtml); } catch {}
132
+ }, 3000);
133
+ }
38
134
 
39
135
  function highlightCode(line) {
40
136
  return line
@@ -216,5 +312,12 @@ async function runFile(filePath, isTemp = false, callback) {
216
312
 
217
313
 
218
314
  if (!args[0].startsWith('--')) {
219
- runFile(path.resolve(args[0]));
315
+ const file = path.resolve(args[0]);
316
+ const ext = path.extname(file).toLowerCase();
317
+
318
+ if (ext === '.md') {
319
+ renderMarkdown(file);
320
+ } else {
321
+ runFile(file);
322
+ }
220
323
  }