Skip to content

Commit aa31d97

Browse files
committed
fix: map shebang executables and resolve lint error
1 parent 57254b1 commit aa31d97

File tree

4 files changed

+78
-4
lines changed

4 files changed

+78
-4
lines changed

packages/cli/test/cli.test.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,4 +174,34 @@ describe('run', () => {
174174
expect(output).toContain('javascript')
175175
expect(output).toContain('python')
176176
})
177+
178+
describe('stdin', () => {
179+
it('reads from stdin and guesses language', async () => {
180+
const output: string[] = []
181+
const content = '#!/usr/bin/env node\nconsole.log("hi")'
182+
183+
const mockStdin = {
184+
isTTY: false,
185+
on: vi.fn((event, handler) => {
186+
if (event === 'data')
187+
handler(new TextEncoder().encode(content))
188+
if (event === 'end')
189+
handler()
190+
return mockStdin
191+
}),
192+
}
193+
194+
const originalStdin = process.stdin
195+
Object.defineProperty(process, 'stdin', { value: mockStdin, configurable: true })
196+
197+
await run(['node', 'shiki'], msg => output.push(msg))
198+
199+
expect(output.length).toBe(1)
200+
expect(output[0]).toContain('console') // Should be highlighted
201+
// Since we can't easily check for colors in this test environment without more setup,
202+
// we at least verify it didn't throw and produced output.
203+
204+
Object.defineProperty(process, 'stdin', { value: originalStdin, configurable: true })
205+
})
206+
})
177207
})

packages/core/src/utils/strings.test.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,15 +199,22 @@ print("hello")
199199
})
200200

201201
it('detects languages from shebangs', () => {
202-
expect(guessEmbeddedLanguages('#!/usr/bin/node', undefined)).toContain('node')
202+
expect(guessEmbeddedLanguages('#!/usr/bin/node', undefined)).toContain('javascript')
203203
expect(guessEmbeddedLanguages('#!/bin/bash', undefined)).toContain('bash')
204-
expect(guessEmbeddedLanguages('#!/usr/bin/env python3', undefined)).toContain('python3')
204+
expect(guessEmbeddedLanguages('#!/usr/bin/env python3', undefined)).toContain('python')
205205
expect(guessEmbeddedLanguages('#!/usr/bin/env -S ts-node --foo', undefined)).toContain('ts-node')
206+
expect(guessEmbeddedLanguages('#!/usr/bin/env -S node --inspect', undefined)).toContain('javascript')
207+
expect(guessEmbeddedLanguages('#!/usr/bin/env', undefined)).toEqual([])
208+
expect(guessEmbeddedLanguages('#!', undefined)).toEqual([])
209+
expect(guessEmbeddedLanguages(' #!/bin/bash', undefined)).toEqual([]) // Must be at start
206210
})
207211

208212
it('detects languages from comments', () => {
209213
expect(guessEmbeddedLanguages('<!-- language: lang-js -->', undefined)).toContain('js')
210214
expect(guessEmbeddedLanguages('// @lang typescript', undefined)).toContain('typescript')
211215
expect(guessEmbeddedLanguages('/** @lang python */', undefined)).toContain('python')
216+
expect(guessEmbeddedLanguages('<!-- language: lang- -->', undefined)).toEqual([])
217+
expect(guessEmbeddedLanguages('// @lang ', undefined)).toEqual([])
218+
expect(guessEmbeddedLanguages('<!-- language: lang-JS-variant -->', undefined)).toContain('js-variant')
212219
})
213220
})

packages/core/src/utils/strings.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ export function guessEmbeddedLanguages(
118118
if (parts.length > 0) {
119119
let lang = parts[0].split('/').pop()
120120
if (lang === 'env') {
121+
lang = undefined
121122
// Find first part that doesn't start with '-'
122123
for (let i = 1; i < parts.length; i++) {
123124
if (parts[i] && !parts[i].startsWith('-')) {
@@ -126,8 +127,21 @@ export function guessEmbeddedLanguages(
126127
}
127128
}
128129
}
129-
if (lang)
130-
langs.add(lang.toLowerCase())
130+
131+
if (lang) {
132+
lang = lang.toLowerCase()
133+
// Map common executable names to Shiki aliases
134+
if (lang === 'node')
135+
lang = 'javascript'
136+
else if (lang === 'python3')
137+
lang = 'python'
138+
else if (lang === 'rb')
139+
lang = 'ruby'
140+
else if (lang === 'sh' || lang === 'zsh')
141+
lang = 'shell'
142+
143+
langs.add(lang)
144+
}
131145
}
132146
}
133147

packages/core/test/tokens.test.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,3 +197,26 @@ it('colorsRendering none', async () => {
197197
}),
198198
).toMatchSnapshot('colorsRendering none')
199199
})
200+
201+
it('ansi with multiple themes', async () => {
202+
using engine = await createShikiPrimitiveAsync({
203+
themes: [
204+
import('@shikijs/themes/vitesse-light'),
205+
import('@shikijs/themes/vitesse-dark'),
206+
],
207+
langs: [],
208+
engine: createJavaScriptRegexEngine(),
209+
})
210+
211+
const code = '\x1B[31mred\x1B[0m'
212+
const html = codeToHtml(engine, code, {
213+
lang: 'ansi',
214+
themes: {
215+
light: 'vitesse-light',
216+
dark: 'vitesse-dark',
217+
},
218+
})
219+
220+
expect(html).toContain('<span style="color:#')
221+
expect(html).toContain('--shiki-dark:#')
222+
})

0 commit comments

Comments
 (0)