textmate-utilities
This package exposes several utilities that help with TextMate Scopes.
interface Position {
line: number;
start: number;
length: number;
}
interface CodeDocument {
getTextAtPosition(position: Position): string;
getLines(): string[];
getRaw(): string;
}
interface TextMateNode extends Position {
scopes: Scope[];
}
interface TextMateParserResult {
code: CodeDocument;
tokens: TextMateNode[];
}
Usage
First copy the following files into your applications static folder (which should be accessable via window.fetch
):
- all the wanted grammar files from
./node_modules/@anche/textmate-utilities/grammar
(or add your own, can be json or plist) onigasm.wasm
(https://github.com/NeekSandhu/onigasm), also in ./node_modules/lib/onigasm.wasm
Before you can use the helper, you should bootstrap your app with the initialize module
import { initialize } from '@anche/textmate-utilities';
const ONIGASM_URL = '/public/static/onigasm.wasm';
(async () => {
await initialize(ONIGASM_URL);
App.start();
})();
TextMateScopesParser setup
import { TextMateScopesParser } from '@anche/textmate-utilities';
const service = new TextMateScopesParser({
filePaths: {
'source.tsx': '/grammar/TypeScriptReact.tmLanguage.json',
},
});
const rawCode = `
import React from 'react';
interface Props {
onClick: () => void;
};
const Button: React.FC<Props> = ({ onClick, children }) => {
return (
<button type="button" onClick={onClick}>
{children}
</button>
);
};
export default Button;
`;
const code = service.parse(rawCode, 'source.tsx' );
Rule/Scope matching
This utility helps by getting the applicable rule for a given scope
import { match } from '@anche/textmate-utilities';
interface TextMateRule {
scopes: string[];
}
type MatchFn = <T extends TextMateRule>(nodeScopes: string | string[], rules: T[]) => T | null;
const rawCode = `import React from 'react';`;
const parsed: { code: CodeDocument; tokens: TextMateNode[] } = service.parse(rawCode, 'source.tsx');
const firstNode = parsed.tokens[0];
const textMateRules = [
{ scopes: ['source.tsx', 'keyword.control.import.tsx'], color: '#000000' },
{ scopes: ['meta.var.expr.tsx', 'meta.block.tsx'], color: '#ffffff' },
{ scopes: ['meta.tag entity'], color: '#ff00ff' },
];
const rule = match(firstNode.scopes, textMateRules);