Nominally Patriotic Meathead
Learn about our RFC process, Open RFC meetings & more.Join in the discussion! »

@anche/textmate-utilities

0.0.2 • Public • Published

textmate-utilities

This package exposes several utilities that help with TextMate Scopes.

// types
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: {
        // [languageScope]: 'path to your static grammar file'
        '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' /* key of filePaths: languageScope */);

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');
 
/**
 * the node of `import`, object will look like this:
 * {
 *   line: 0,
 *   start: 0,
 *   length: 6
 *   scopes: [
 *      'keyword.control.import.tsx',
 *      'meta.import.tsx',
 *      'source.tsx',
 *   ],
 * }
 */
const firstNode = parsed.tokens[0];
 
// Defined TextMate Rules
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' },
];
 
// Now you want to know which color the `import` text should be based on your rules, so you need to find out if a rule applies and which one that is:
const rule = match(firstNode.scopes, textMateRules);
 
// rule = textMateRules[0];

Install

npm i @anche/textmate-utilities

DownloadsWeekly Downloads

0

Version

0.0.2

License

MIT

Unpacked Size

40.7 kB

Total Files

21

Last publish

Collaborators

  • avatar