Я пытаюсь выделить синтаксис фрагментов кода на веб-сайте моей библиотеки. Я пробовал Highlight.js и Prism, но ни один из них не использовал токенизированный код правильно (это Ruby), поэтому в итоге код не выделен синтаксисом должным образом. Это потому, что они оба реализуют свои собственные регулярные выражения токенизации, что является подходом, который обязательно имеет недостатки.
Затем я обнаружил, что GitHub , Atom и VSCode все используют TextMate грамматики для их токенизации. Для меня это звучит как правильный подход - хранить языковые грамматики в одном месте, чтобы другие инструменты могли затем использовать их вместо того, чтобы определять свои собственные.
Мой вопрос таков: как токенизироватьстрока кода, использующая грамматику TextMate в Node? Моя цель - получить что-то вроде:
const codeSnippet = `
class Foo
def bar
puts "baz"
end
end
`
const tokenized = tokenizeCode(codeSnippet, 'ruby')
tokenized // some kind of array of tokens, e.g:
// [
// ['keyword', 'class'],
// ['whitespace', ' '],
// ['class', 'Foo'],
// ...
// ]
Я пробовал vscode-textmate , что, как кажется, VSCodeиспользовать для собственной подсветки синтаксиса. Однако я не мог понять, как использовать его для достижения вышеуказанной функциональности.
В конечном итоге я хочу закончить с HTML, который я могу выделить синтаксисом:
<pre>
<code>
<span class="token kewyord">class</span> <span class="token class">Foo</span>
<!-- ... -->
Опять же, я попробовал highlight.js и Prism, но они оба неправильно маркируют даже самый простой код Ruby.
Edit
Вот несколько примеров, где Prism и Highlight.jsнеправильно токенизировать код Ruby:
Highlight.js - не токенизировать Post
как "константу"
const hljs = require("highlight.js/lib/highlight.js");
hljs.registerLanguage('ruby', require('highlight.js/lib/languages/ruby'));
const rubyCode = `Post.create(params[:post])`
const html = hljs.highlight('ruby', rubyCode).value
console.log(html)
// Post.create(params[<span class="hljs-symbol">:post</span>])
Prism -не маркирует foo:
как "символ"
const Prism = require('prismjs');
const loadLanguages = require('prismjs/components/');
loadLanguages(['ruby']);
const rubyCode = `{ foo: "bar" }`
const html = Prism.highlight(rubyCode, Prism.languages.ruby, 'ruby')
console.log(html)
// <span class="token punctuation">{</span> foo<span class="token punctuation">:</span> <span class="token string">"bar"</span> <span class="token punctuation">}</span>