mirror of
https://github.com/stablyai/orca.git
synced 2026-10-06 16:02:25 +00:00
fix(editor): recognize Ruby task and configuration files
Add Ruby task/configuration filenames to the existing generated language associations. Co-authored-by: ggbdpq <ggbdpq@gmail.com> Co-authored-by: Neil <neil@stably.ai>
This commit is contained in:
@@ -10,6 +10,12 @@ export const associationsPath = fileURLToPath(
|
||||
new URL('../../src/renderer/src/lib/monaco-language-associations.json', import.meta.url)
|
||||
)
|
||||
|
||||
// Monaco omits common Ruby task, template and configuration files.
|
||||
const rubyAssociations = {
|
||||
extensions: ['.rake', '.ru', '.jbuilder', '.thor'],
|
||||
filenames: ['Guardfile', 'Capfile', 'Podfile', 'Brewfile', 'Vagrantfile']
|
||||
}
|
||||
|
||||
// Read registration metadata without importing Monaco or executing its grammar loaders.
|
||||
export function readMonacoAssociations() {
|
||||
const entry = ts.createSourceFile(
|
||||
@@ -62,6 +68,12 @@ export function readMonacoAssociations() {
|
||||
if (!metadata.id) {
|
||||
throw new Error(`Missing language id in ${file}`)
|
||||
}
|
||||
if (metadata.id === 'ruby') {
|
||||
metadata.extensions = [
|
||||
...new Set([...metadata.extensions, ...rubyAssociations.extensions])
|
||||
]
|
||||
metadata.filenames = [...new Set([...metadata.filenames, ...rubyAssociations.filenames])]
|
||||
}
|
||||
registrations.push(metadata)
|
||||
}
|
||||
ts.forEachChild(node, visit)
|
||||
|
||||
@@ -3,10 +3,36 @@ import { describe, expect, it } from 'vitest'
|
||||
import { associationsPath, readMonacoAssociations } from './generate-monaco-associations.mjs'
|
||||
|
||||
describe('Monaco filename associations', () => {
|
||||
it('matches every registration shipped by the installed editor entry point', () => {
|
||||
it('matches the installed editor registrations and curated Orca associations', () => {
|
||||
expect(
|
||||
JSON.parse(readFileSync(associationsPath, 'utf8')),
|
||||
'Run node config/scripts/generate-monaco-associations.mjs after upgrading Monaco'
|
||||
'Run node config/scripts/generate-monaco-associations.mjs after changing associations or Monaco'
|
||||
).toEqual(readMonacoAssociations())
|
||||
})
|
||||
|
||||
it('keeps built-in Ruby aliases alongside the curated Ruby associations', () => {
|
||||
expect(readMonacoAssociations().find((language) => language.id === 'ruby')).toEqual({
|
||||
id: 'ruby',
|
||||
extensions: expect.arrayContaining([
|
||||
'.rb',
|
||||
'.rbx',
|
||||
'.rjs',
|
||||
'.gemspec',
|
||||
'.pp',
|
||||
'.rake',
|
||||
'.ru',
|
||||
'.jbuilder',
|
||||
'.thor'
|
||||
]),
|
||||
filenames: expect.arrayContaining([
|
||||
'rakefile',
|
||||
'Gemfile',
|
||||
'Guardfile',
|
||||
'Capfile',
|
||||
'Podfile',
|
||||
'Brewfile',
|
||||
'Vagrantfile'
|
||||
])
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -5,7 +5,11 @@ languages and loads their grammars on demand. Filename detection must not load t
|
||||
editor itself: it also runs during session restoration and before the editor mounts.
|
||||
|
||||
`monaco-language-associations.json` contains the registration metadata from the
|
||||
installed package's entry point. Regenerate it after upgrading Monaco:
|
||||
installed package's entry point, plus curated Ruby associations in the generator.
|
||||
Those add `.rake`, `.ru`, `.jbuilder`, `.thor`, `Guardfile`, `Capfile`, `Podfile`,
|
||||
`Brewfile` and `Vagrantfile` to the existing Ruby grammar. Change these in
|
||||
`config/scripts/generate-monaco-associations.mjs`, not the generated JSON.
|
||||
Regenerate after changing the curated associations or upgrading Monaco:
|
||||
|
||||
```sh
|
||||
node config/scripts/generate-monaco-associations.mjs
|
||||
@@ -13,7 +17,7 @@ pnpm exec oxfmt --write src/renderer/src/lib/monaco-language-associations.json
|
||||
```
|
||||
|
||||
The generator reads syntax trees without executing contributions or grammar loaders.
|
||||
Its test compares the checked-in metadata to the installed package. The original
|
||||
Its test compares the checked-in metadata to the installed package and curated associations. The original
|
||||
list was verified against a clone of `microsoft/monaco-editor`, tag `v0.55.1`, commit
|
||||
`516f350bdaf7a82f6731bd128a9ec86a6e5fa47d` (`src/basic-languages` and `src/language`).
|
||||
|
||||
|
||||
@@ -124,6 +124,27 @@ describe('detectLanguage', () => {
|
||||
expect(detectLanguage('C:\\repo\\force-app\\classes\\ACCOUNTSERVICE.CLS')).toBe('apex')
|
||||
})
|
||||
|
||||
it('maps Ruby DSL extensions to the ruby language id (case-insensitive)', () => {
|
||||
expect(detectLanguage('lib/tasks/devise.rake')).toBe('ruby')
|
||||
expect(detectLanguage('config.ru')).toBe('ruby')
|
||||
expect(detectLanguage('app/views/posts/index.json.jbuilder')).toBe('ruby')
|
||||
expect(detectLanguage('lib/tasks/install.thor')).toBe('ruby')
|
||||
expect(detectLanguage('C:\\repo\\lib\\tasks\\DEVISE.RAKE')).toBe('ruby')
|
||||
})
|
||||
|
||||
it('maps Ruby DSL filenames to the ruby language id', () => {
|
||||
expect(detectLanguage('rails/Guardfile')).toBe('ruby')
|
||||
expect(detectLanguage('deploy/Capfile')).toBe('ruby')
|
||||
expect(detectLanguage('ios/Podfile')).toBe('ruby')
|
||||
expect(detectLanguage('homebrew/Brewfile')).toBe('ruby')
|
||||
expect(detectLanguage('C:\\vms\\Vagrantfile')).toBe('ruby')
|
||||
})
|
||||
|
||||
it('keeps near-miss Ruby DSL names off the ruby language id', () => {
|
||||
expect(detectLanguage('report.rake.bak')).toBe('plaintext')
|
||||
expect(detectLanguage('ruby.rakex')).toBe('plaintext')
|
||||
})
|
||||
|
||||
it.each([
|
||||
'templates/base.twig',
|
||||
'templates/node--article.html.twig',
|
||||
|
||||
@@ -24,6 +24,45 @@ describe('Monaco filename detection', () => {
|
||||
expect(detectLanguage(path)).toBe(language)
|
||||
})
|
||||
|
||||
it.each([
|
||||
'lib/tasks/devise.rake',
|
||||
'config.ru',
|
||||
'app/views/posts/index.json.jbuilder',
|
||||
'lib/tasks/install.thor',
|
||||
'rails/Guardfile',
|
||||
'deploy/Capfile',
|
||||
'ios/Podfile',
|
||||
'homebrew/Brewfile',
|
||||
'vms/Vagrantfile',
|
||||
'C:\\repo\\lib\\tasks\\DEVISE.RAKE',
|
||||
'C:\\repo\\CONFIG.RU',
|
||||
'C:\\repo\\INDEX.JSON.JBUILDER',
|
||||
'C:\\repo\\INSTALL.THOR',
|
||||
'C:\\vms\\VAGRANTFILE',
|
||||
'/home/user/folder workspace/tasks/Daily.RaKe',
|
||||
'main.rb',
|
||||
'main.rbx',
|
||||
'main.rjs',
|
||||
'package.gemspec',
|
||||
'script.pp',
|
||||
'Rakefile',
|
||||
'Gemfile'
|
||||
])('recognizes Ruby source %s', (path) => {
|
||||
expect(detectLanguage(path)).toBe('ruby')
|
||||
expect(detectMonacoFilenameLanguage(path.split(/[\\/]/).at(-1)!)).toBe('ruby')
|
||||
})
|
||||
|
||||
it.each([
|
||||
'report.rake.bak',
|
||||
'ruby.rakex',
|
||||
'Guardfile.bak',
|
||||
'Guardfilex',
|
||||
'tasks.rake/README',
|
||||
'tasks.rake\\README'
|
||||
])('keeps non-Ruby file %s on plaintext', (path) => {
|
||||
expect(detectLanguage(path)).toBe('plaintext')
|
||||
})
|
||||
|
||||
it('recognizes every unambiguous upstream extension and filename', () => {
|
||||
for (const language of associations) {
|
||||
for (const extension of language.extensions) {
|
||||
|
||||
@@ -336,8 +336,16 @@
|
||||
},
|
||||
{
|
||||
"id": "ruby",
|
||||
"extensions": [".rb", ".rbx", ".rjs", ".gemspec", ".pp"],
|
||||
"filenames": ["rakefile", "Gemfile"]
|
||||
"extensions": [".rb", ".rbx", ".rjs", ".gemspec", ".pp", ".rake", ".ru", ".jbuilder", ".thor"],
|
||||
"filenames": [
|
||||
"rakefile",
|
||||
"Gemfile",
|
||||
"Guardfile",
|
||||
"Capfile",
|
||||
"Podfile",
|
||||
"Brewfile",
|
||||
"Vagrantfile"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "rust",
|
||||
|
||||
Reference in New Issue
Block a user