How do I add extra syntax highlighting to an existing language? - visual-studio-code

I want to add some extra language features, such as liquid language support inside JavaScript:
var firstName = "<% User.firstName %>";
var lastName = "<% User.firstName %>";
I browsed around a bit and I found this folder in the vscode repository: https://github.com/microsoft/vscode/tree/main/extensions/javascript
It's basically the JavaScript tmLanguage grammar rules, so I had this idea to create a new javascript file format (.pjs) and apply the same tmLanguage file as well as add these new rules:
"pk-liquid-expression": {
"begin": "<%",
"beginCaptures": {
"0": {
"name": "storage.type.primitive.java"
}
},
"end": "%>",
"endCaptures": {
"0": {
"name": "storage.type.primitive.java"
}
},
"name": "storage.type.primitive.java"
},
And this worked, however now my pjs files don't have any of the language features such as errors and warnings.
I think my solution is not very forward-thinking however, so is it possible to just edit the current JavaScript tmLanguage rules and add these new tokens?
Thank you.

One solution is to inject the "liquid language" into the Javascript language definition. Main steps for that is to define a grammar to inject and creating a selector which defines when to inject your grammar:
{
"contributes": {
"grammars": [
{
"path": "./syntaxes/injection.json",
"scopeName": "todo-comment.injection",
"injectTo": ["source.js"]
}
]
}
}
See also: How to properly inject grammar extension in vscode (so it works)?

Related

Is there a way to stop Autorest.Powershell from flattening response objects?

I have a response object in my swagger.json file that includes a nested object as one of its fields. When I use Autorest.Powershell to generate a client for this API, it flattens the nested object. So when the service returns the following response:
{
"code": 200,
"status": "OK",
"data": {
"FileName": "gameserver.zip",
"AssetUploadUrl": "https://example.com"
}
}
my Autorest.Powershell client returns a flattened object like this:
{
"code": 200,
"status": "OK",
"dataFileName": "gameserver.zip",
"dataAssetUploadUrl": "https://example.com"
}
Is there some sort of configuration setting I can use to disable this behavior?
Here are the relevant portions of my swagger.json file, if it helps:
"definitions": {
"GetAssetUploadUrlResponse": {
"type": "object",
"properties": {
"AssetUploadUrl": {
"description": "The asset's upload URL.",
"type": "string"
},
"FileName": {
"description": "The asset's file name to get the upload URL for.",
"type": "string"
}
},
"example": {
"FileName": "gameserver.zip",
"AssetUploadUrl": "https://example.com"
}
}
},
"responses": {
"GetAssetUploadUrlResponse": {
"description": "",
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "The Http status code. If X-ReportErrorAsSuccess header is set to true, this will report the actual http error code."
},
"status": {
"type": "string",
"description": "The Http status code as a string."
},
"data": {
"$ref": "#/definitions/GetAssetUploadUrlResponse"
}
},
"example": {
"code": 200,
"status": "OK",
"data": {
"FileName": "gameserver.zip",
"AssetUploadUrl": "https://example.com"
}
}
}
}
}
There are several ways, none of which is really straightforward (as, I'm starting to believe, is the case with most things AutoRest-related; sorry, couldn't resist :-P ).
There are three semi-official ways. Semi-official here means they are based on public AutoRest mechanism but are not themselves documented. Being semi-official, they might only work with certain versions of AutoRest components, so, here are the ones I used
(from autorest --info):
#autorest/core (3.0.6369)
#autorest/modelerfour (4.15.414)
#autorest/powershell (3.0.421)
Finally, here are the relevant parts of AutoRest's code base: inline properties plug-in and configuration directive definition
inlining-threshold setting
This setting control the maximum number of properties an inner object could have for it to be considered eligible for inlining. You can set it either on the command line or in the "literate config" .md file.
```yaml
inlining-threshold: 0
```
In theory, setting this to 0 should prevent any inner member's properties from being inlined, however the plug-in has a hard-coded exception that if the inner object is in a property that's itself named properties then the limit is ignored and it's still flattened.
definitions:
SomeSchema:
type: "object"
properties:
detail_info: # <-- threshold honored
$ref: "#/definitions/InfoSchema"
properties: # <-- this is always flattened because of its special name
$ref: "#/definitions/OtherSchema"
no-inline directive
The PowerShell AutoRest plug-in also defines a custom directive that is used to specify that certain schemas should never be inlined. Using "literate config", it goes like
```yaml
directive:
- no-inline:
- OtherSchema
- ThirdSchema
```
The pros of this approach are that the no-inline directive overrides the "always inline properties in a property named properties" exception mentioned above, so it can be used to alleviate the problem.
The cons are that all schema names should be listed explicitly. (It seems the directive should also support Rx name expression but I couldn't get no-inline: ".*" to work)
Low-level transform
This is approach disables inlining unconditionally in all cases, however it is coupled to the specific internal code model used by AutoRest. (In principle, the model should be stable, at least within major versions). It also relies on the PowerShell plug-in using a specific (non-contractual) property to flag schemas excluded from inlining.
```yaml
directive:
- from: code-model-v4-no-tags
where: $.schemas.objects.*
transform: |
$.language.default['skip-inline'] = true;
```

VS Code Spell Checker

I enabled the VS Code extension, "Code Spell Checker," and it works great. However, I wanted to include words from my custom dictionary file so the words in it aren't flagged as incorrect. I tried the following in my settings.json:
"cSpell.customUserDictionaries": [
"name": "Custom",
"description": "These are words from my custom dictionary.",
"path": "C:\\Users\\Joe\\Documents\\Custom.txt",
"addWords": false
],
But the words in Custom.txt are still marked as incorrect.
How can I configure Code Spell Checker so that it's able to load all the words in Custom.txt and ignore them?
According to their package.json that configuration is expecting a typeof array of objects, so the following should work:
"cSpell.customUserDictionaries": [
{
"name": "Custom",
"description": "My desc",
"path": "C:\\Users\\Joe\\Documents\\Custom.txt",
"addWords": false
}
],
And per their description:
File Format: Each line in the file is considered a dictionary entry

Create Entities and training phrases for values in functions for google action

I have created a trivia game using the SDK, it takes user input and then compares it to a value in my DB to see if its correct.
At the moment, I am just passing a raw input variable through my conversation, this means that it regularly fails when it mishears the user since the exact string which was picked up is rarely == to the value in the DB.
Specifically I would like it to only pick up numbers, and for example realise that it must extract '10' , from a speech input of 'my answer is 10'.
{
"actions": [
{
"description": "Default Welcome Intent",
"name": "MAIN",
"fulfillment": {
"conversationName": "welcome"
},
"intent": {
"name": "actions.intent.MAIN"
}
},
{
"description": "response",
"name": "Raw input",
"fulfillment": {
"conversationName": "rawInput"
},
"intent": {
"name": "raw.input",
"parameters": [{
"name": "number",
"type": "org.schema.type.Number"
}],
"trigger": {
"queryPatterns":[
"$org.schema.type.Number:number is the answer",
"$org.schema.type.Number:number",
"My answer is $org.schema.type.Number:number"
]
}
}
}
],
"conversations": {
"welcome": {
"name": "welcome",
"url": "https://us-central1-triviagame",
"fulfillmentApiVersion": 2
},
"rawInput": {
"name": "rawInput",
"url": "https://us-central1-triviagame",
"fulfillmentApiVersion": 2
}
}
}
app.intent('actions.intent.MAIN', (conv) => {
conv.data.answers = answersArr;
conv.data.questions = questionsArr;
conv.data.counter = answersArr.length;
var thisQuestion = conv.data.questions;
conv.ask((conv.data.answers)[0]));
});
app.intent('raw.input', (conv, input) => {
if(input == ((conv.data.answers)[0])){
conv.ask(nextQuestion());
}
app.intent('actions.intent.TEXT', (conv,input) => {
//verifying if input and db value are equal
// at the moment input is equal to 'my number is 10' (for example) instead of '10'
//therefore the string verification never works
conv.ask(nextQuestion());
});
In a previous project i used the dialogflow UI and I used this #system.entities number parameter along with creating some training phrases so it understands different speech patterns.
This input parameter I am passing through my conv , is only a raw string where I'd like it to be filtered using some sort of entity schema.
How do I create the same effect of training phrases/entities using the JSON file?
You can't do this using just the Action SDK. You need a Natural Language Processing system (such as Dialogflow) to handle this as well. The Action SDK, by itself, will do speech-to-text, and will use the actions.json configuration to help shape how to interpret the text. But it will only return the entire text from the user - it will not try to determine how it might match an Intent, nor what parameters may exist in it.
To do that, you need an NLP/NLU system. You don't need to use Dialogflow, but you will need something that does the parsing. Trying to do it with simple pattern matching or regular expressions will lead to nightmares - find a good system to do it.
If you want to stick to things you can edit yourself, Dialogflow does allow you to download its configuration files (they're just JSON), edit them, and update or replace the configuration through the UI or an API.

RESTful master/detail

Having 3 dropdown pickers in a web application. The web application uses a Restful service to populate pickers data.
The two first pickers get their values from something like /years and /colors. The third one should get its values depending on the settings of the two.
So it could be something like /models?year=1&color=red.
The question is, how to make this HATEOAS-compliant (so that the dev does not have to know the way he should create an url to get the models).
The root / gets me a number of links, such as:
{
"_links": {
"colors": "/colors",
"years": "/years",
"models": "???" }
}
What should be instead of ???? If there was some kind of template /models?color={color}&year={year}, the dev would have to create the url. Is this OK?
Or there could be a link to list of years on each color got from /colors and then a link to list of models on each year got from /years?color=red, but i'd have to first choose color, then populate years and then populate models. Any idea if i want to have the model dependent on both color and year, not just the year populated from color?
Is it even possible in this situation to make it hateoas-compliant?
I have not heard of HATEOAS before, but based on what I just read about it, it seems that it supposed to return links to where the consumer of the service can go forward in the "state machine".
In your case that would translate to the links being "function calls". The first two (/colors and /years) are functions that take no parameters (and return "something" at this point), while the third is a function call that takes two parameters: one that is a representation of a color, the other a year. For the first two having a simple URL will suffice for the link, but for the third, you need to include the parameter name/type information as well. Something like:
{
"_links": {
"colors": "/colors",
"years": "/years",
"models": {
"url": "/models",
"param1": {"color"}
"param2": {"year"}
}
}
}
Note: you can use the same layout as "models" for "colors" and "years" as well.
At this point the client knows what the URL to access the functions are and what the parameter (if any) names are to be passed to the function.
One more thing is missing: types. Although you could just use "string", it will not be obvious that the "color" parameter is actually a value from what "/colors" returns. You can be introducing a "type" Color that describes a color (and any functions that operate on a color: give a displayable name, HTML color code, etc.)
The "beefed up" signature becomes:
{
"_links": {
"colors": {
"url": "/colors",
"return": "/type/List?type=/type/Color"
},
"years": {
"url": "/years",
"return": "/type/List?type=/type/Integer"
},
"models": {
"url": "/models",
"param1": {
"name": "color",
"type": "/type/Color"
},
"param2": {
"name": "year",
"type": "/type/Integer"
}
"return": "/type/List?type=/type/Model"
}
}
}
Note: the path "/type" is used just to separate the types from functions, but is not necessary.
This will interchangeably and discoverably describe the functions, what parameters they take, and what values they are returning, so you can use the right value at the right place.
Of course implementing this on the service end will not be easy (especially with parameterized types, like "/type/List" -- think Generics in Java or templates in C++), but this is the most "safe" and "portable" way you can describe your interface to your clients.

Chrome Extension - Content Script unable to find elements by class name

I am attempting to access elements with a specific class name from a page using a content script of a Chrome extension. So far the content script can successfully find an element with a specific id using document.getElementById(), but using document.getElementsByClassName() or jQuery's $(".className") yields no results. For the sake of testing, I used 'header' as my class name and every website I ran the extension on resulted in an array length of 0. Any ideas what I might be missing? Here's what I have been testing with:
manifest.json
=================
{
"name": "Sample Extension",
"version": "0.0.1",
"description": "Sample extension",
"icons": {"128": "icon.png"},
"permissions": [
"tabs", "<all_urls>"
],
"browser_action": {
"default_icon": "browseraction.png",
"default_title": "Sample",
"popup": "popup.html"
},
"content_scripts": [
{
"matches": [ "<all_urls>" ],
"js": ["scripts/contentscript.js"],
"run_at": "document_end"
}
]
}
contentscript.js
===================
var elems = document.getElementsByClassName("header");
alert( elems.length );
Your code is very basic and straightforward, it can't be a cause of problem. In fact, I just used your exact code (with "says" class and website you provided) and alert() says every and each time 1 (which is correct).
My best guess is that you haven't reloaded your extension after making changes in contentscript.js OR some other extension is interfering and causing this strange behavior. Try disabling other extensions before testing your extension.