Giter VIP home page Giter VIP logo

typescript-template-language-service-decorator's Introduction

TypeScript Template Language Service Decorator

Framework for decorating a TypeScript language service with additional support for languages embedded inside of template strings.

Build Status

Usage

This framework helps you to extend TypeScript's editor support for languages embedded inside of template strings. It hides most of the details of dealing with template strings so that you only have to worry about working with the template string contents themselves.

Support for embedded template languages is implemented using the TemplateLanguageService interface. Here's a simple TemplateLanguageService that adds completions that repeat the prior characters in a template string

import { TemplateLanguageService, TemplateContext } from 'typescript-template-language-service-decorator';

class EchoTemplateLanguageService implements TemplateLanguageService {
    getCompletionsAtPosition(
        context: TemplateContext,
        position: ts.LineAndCharacter
    ): ts.CompletionInfo {
        const line = context.text.split(/\n/g)[position.line];
        return {
            isGlobalCompletion: false,
            isMemberCompletion: false,
            isNewIdentifierLocation: false,
            entries: [
                {
                    name: line.slice(0, position.character),
                    kind: '',
                    kindModifiers: 'echo',
                    sortText: 'echo'
                }
            ]
        };
    }
}

The TemplateLanguageService operates on the contents of template nodes. context.text for example returns the text content of the template string, and the position passed to getCompletionsAtPosition is relative to the template string body.

The decorateWithTemplateLanguageService method takes a existing TypeScript language service and decorates it with a TemplateLanguageService. Here's how you would use this method to create a simple TypeScript server plugin for the EchoTemplateLanguageService

import * as ts from 'typescript/lib/tsserverlibrary';
import { decorateWithTemplateLanguageService } from 'typescript-template-language-service-decorator';

export = (mod: { typescript: typeof ts }) => {
    return {
        create(info: ts.server.PluginCreateInfo): ts.LanguageService {
            return decorateWithTemplateLanguageService(
                mod.typescript,
                info.languageService,
                info.project,
                new EchoTemplateLanguageService(),
                { tags: ['echo'] });
        }
    };
};

This plugin will now add echo completions to all template strings tagged with echo.

Examples

For more advanced examples of using this library:

Contributing

To build, you'll need Git and Node.js.

First, fork the typescript-template-language-service-decorator repo and clone your fork:

git clone https://github.com/YOUR_GITHUB_ACCOUNT_NAME/typescript-template-language-service-decorator.git
cd typescript-template-language-service-decorator

Then install dev dependencies:

npm install

The plugin is written in TypeScript. The source code is in the src/ directory with the compiled JavaScript output to the lib/ directory. Kick off a build using the compile script:

npm run compile

And then run the end to end tests with the e2e script:

(cd e2e && npm install)
npm run e2e

You can submit bug fixes and features through pull requests. To get started, first checkout a new feature branch on your local repo:

git checkout -b my-awesome-new-feature-branch

Make the desired code changes, commit them, and then push the changes up to your forked repository:

git push origin my-awesome-new-feature-branch

Then submit a pull request against the Microsoft typescript-template-language-service-decorator repository.

Please also see our Code of Conduct.

Credits

Code originally forked from: https://github.com/Quramy/ts-graphql-plugin

typescript-template-language-service-decorator's People

Contributors

barik avatar dependabot[bot] avatar microsoft-github-policy-service[bot] avatar mjbvz avatar yesmeck avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

typescript-template-language-service-decorator's Issues

getCompletionsAtPosition not triggering after emmet modifiers

I am trying to implement emmet functionality inside typescript template literals however there's a strange behavior regarding getCompletionsAtPosition. with the following code from the demo completions aren't triggered if the position is after the number

            div*5
            div*5>li
    public getCompletionsAtPosition(context: TemplateContext, position: LineAndCharacter):
        CompletionInfo {
        const line = context.text.split(/\n/g)[position.line]
        return {
            isGlobalCompletion: false,
            isMemberCompletion: false,
            isNewIdentifierLocation: false,
            entries: [
                {
                    name: line,
                    kind: '',
                    kindModifiers: 'echo',
                    sortText: 'echo'
                }
            ]
        } as CompletionInfo
    }

To replicate, just use the demo EchoServer and test with emmet abbreviations above.

Expose `standard-template-source-helper` to get `TemplateContext` for unit tests

Hi. I am currently working on building a language server plugin for custom elements for microsoft FAST . I have a basic example working when running the plugin, but I would like to write unit tests for it so I can work TDD, and more easily spot regressions.

I have functions I would like to test which take the TemplateContext and LineAndCharacter to return CompletionInfo but I need a way to get a TemplateContext from my test tagged templates.

  1. For now I can just manually set up the interface from a raw string as best I as I can during the test, using jest.mock for typescript itself as well as the AST node
  2. Is it possible to change this library to get an instance of StandardTemplateSourceHelper so I can get the TemplateContext myself, or would this not be possible during the unit tests anyway as we are running in jest via node rather than the typescript runtime?
  3. Is there a different way to approach this problem that I am not seeing?

Do not take a runtime dependency on typescript

This library currently imports tsserverlibrary. This causes a number of problems:

  • Possibly mismatch in the version of TypeScript used between the host and the plugin
  • Duplicate versions of TypeScript being loaded
  • Does not work in environments like VS Code's bundled typescript where we strip out tsserverlibrary

The fix is to ensure that all imports from typescript only are used in type positions instead of value positions. All values must come from a version of typescript provided to the adapter

Please consider removing tag regex escaping

Due to this line it's impossible to use regular expression to define tags to match. Also identifiers can't have these special regex symbols anyway, and you can always escape them by self if you need.

Use case:

const A = styled<Props>("button") `color: red;`

Ideally i want to define tags in typescript-styled-plugin as:

{
                "tags": [
                    "styled",
                    "styled<.*>\\(.*\\)"
                ]
}

Typescript code as a result

Hi!
Sorry for such a simple question. I'm looking for a template language that targets typescript code as a return value. I'm using basic string interpolation and looking for something more convenient. Is it possible to use this tool for this case?

Issue with autocompletion when string contians characters (e.g. `@`)

Hi

I am currently working on a LSP plugin for Custom Elements (and https://www.fast.design/) and I am basing it off this language server decorator.

All is workng well until I have tried to add autocompletion functionlity for events, which in fast are written in a html tagged template literal with the following syntax @event="${x => x.doSomething()}"

I am returning an array of CompletionEntry with the events starting with the @ symbol. This works perfectly in NeoVim, but VSCode is appearing to ignore the @ but also filter out all of the events from the array of CompletionEntry

I raised an issue with VSCode here - microsoft/vscode#183200. I thought it was possible that I was doing something wrong, but either way I should get an answer. I received an answer which sounds like I need to manually set the filterText parameter, and to set a span which contains the whole token to replace with the suggestion (e.g. @cli).

I have set these values, but I am having issues with both of them.

Here is an example of a CompletionEntry that I am returning

{
  "name": "@waiting",
  "insertText": "@waiting=\"${(x,c) => $1}\"$0",
  "kind": "parameter",
  "kindModifiers": "event-attribute",
  "sortText": "z",
  "labelDetails": {
    "description": "[attr] Event"
  },
  "isSnippet": true,
  "replacementSpan": {
    "start": -2,
    "length": 1
  },
  "filterText": "waiting"
}

Corresponding section in the response when I look in the vscode tsserver.log

{
  "name": "@waiting",
  "kind": "parameter",
  "kindModifiers": "event-attribute",
  "sortText": "z",
  "insertText": "@waiting=\"${(x,c) => $1}\"$0",
  "replacementSpan": {
    "start": {
      "line": 9,
      "offset": 25
    },
    "end": {
      "line": 9,
      "offset": 26
    }
  }
}
  1. As you can see the filterText is just being completely removed by the time it gets to the LSP itself. That somewhat makes sense as it isn't specified on the CompletionItem definition which comes with tsserver.d.ts, but it is specified on the LSP specification here.
  2. My implementation of replacementSpan is not working. Now VSCode doesn't even suggest the @event attributes even if I haven't started typing, suggesting to me that they are somewhat malformed or invalid. I am returning -2 and 1 because in this case we have typed @c<cursor> where <cursor> is reprenting the cursor, so we need to move backwards two positions in order to capture the @c characters. I see somewhere this is being converted to a line and offset but I am unsure how that is working. I couldn't find anything helpful looking through documentation except it saying that the span needs to include the position of the cursor - so perhaps that is why I am not seeing those suggestions anymore

any help would be appriciated

Allow using predicate function to determine which template nodes should have language service enable

Problem

Some consumers of this library would like more advanced ways to control when the language service is enabled inside a template. Examples:

Proposal

Rather than attempting to provide configuration options to support additional types of tagging, I think we should delegate this back to the users of this library. This would override tags. The function should take a ts.TemplateLiteral and return true if the language service should be enabled for it

Error - Cannot find name 'AsyncIterator'

When I clone the project and run tsc I get this error.
Solution is to add lib = ["es2015", "esnext"] to tsconfig.json

Can we add it be default or extract AsyncIterator and keep it inline with the codebase?

CodeLens support

I am planning to take up CodeLens implementation in the interface.

I will use this feature to further augment GraphQL Language Service into TypeScript language service, mainly for VSCode GraphQL extension.

I suppose this is the right place implement that as the extension already relies on this package.

example

Hi,
I'm just started to learn the typescript language service plugin and I'm trying to understand your example and I don't understand the sentence "This plugin will now add echo completions to all template strings tagged with echo.", could you please provide more examples?
and where can I get documentation about it, because here Writing-a-Language-Service-Plugin not enough.

Last question:
I got typescript-plugin-example from git and that's plugin works into Atom IDE but into Intellij IDE doesn't, do you know why ?

Inject the tags option dynamically

Hey! we are using this in context of GraphQL for providing language features and an interesting use case is that in one TS/JS file you can have gql tags belonging to different schemas.

So, we might want to have something like

gql1 or gql2 that might changing at runtime in context of the VSCode plugin.

Or even something like

gql.app1 or gql.app2 (can we already specify a tag that has a "." in it?)

Do you think that something like this is possible in context of this project?

This idea is still in early stage but I am opening this issue to

  1. Make you aware of the approach we are thinking of - maybe you ran into this before
  2. Seeking your view on the issue

Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.