How do I access context key values in vscode extension? - javascript

Description
I am setting a configPath context variable using...
const configPath = '/some/file/path.yml';
vscode.commands.executeCommand(
'setContext',
'ext.configPath',
configPath
);
... which can be used within when properties in package.json. For example, "when": "ext.configPath".
Problem
I cannot seem to obtain the value for string interpolation, or programmatically.
Ask
I would like to know...
How to interpolate the context variable value within a string in the package.json file. For example, for tree data title...
{
"id": "ext.treedata.accounts",
"name": "Accounts - ${context:ext.configPath}",
"when": "ext.configPath"
}
... I would expect the title to read Accounts - /some/file/path.yml.
How to obtain the context variable value programmatically. For example...
const configPath = vscode.getContext('ext.configPath');
console.log(configPath); // Outputs: /some/file/path.yml
I've tried using ${context:ext.configPath} to interpolate, and I've tried looking for getContext methods. I've also tried searching the vscode extension development docs.

There is no getContext API/command, unfortunately. There is however, an open issue (https://github.com/microsoft/vscode/issues/10471), but no ETA.
So, in your case, you will have to store that value somewhere. Depending on your scenarios, maybe you could take advantage of workspaceState or globalState Mementos.
Hope this helps

Related

Is there a way to access global vars from the target website via cypress?

I've got a website that I want to test with cypress. This website is working with coordinates, which are stored in a global var.
I want to write a test that accesses these coordinates and checks if they are right.
Is there any way to do this with cypress?
I mean, there is a way to access the vars in the DevTools (Chrome) via the Console, so it should also be possible with cypress, right...?
Thanks for helping! <3
I searched on the web but did not find anything about this.
I tried (like in the chrome DevTools) to access the vars directly but it did not work...
Edit:
WAIT! im dumb...
I did not realised that my "global" var is the same as the "window" var....
So, i now accessing it with the solution from #Nichola Walker
If by global var you mean const coordinates = or let coordinates = or var coordinates = , then you can expose a reference to the variable on window, which is a global context that is common to both the app and the test.
In the app
const coordinates = {x:1, y:2}
if (window.Cypress) { // if window.Cypress is defined then we are testing
window.coordinates = coordinates
}
In the test
cy.window().then(window => {
expect(window.coordinates).to.deep.eq({x:1, y:2}) // passes
})
If I understood you correctly, the answer is no, You cannot access the global variables of the website.
You could expose any value through the window object or through the different storages like cookies, sessions, and local storage.
Then you can access them easily through cypress.

Unable to access GeoJSON properties with ":" using JS variable

I am currently following the tutorial on Mapbox to build a store locator with a map.
I'm having problems displaying data from my GeoJSON file that I got from Turbo Overpass. Example of the GeoJSON being used :
"properties": {
"#id": "node/5750820619",
"addr:city": "Caissargues",
"addr:housenumber": "180",
"addr:postcode": "30132",
"addr:street": "Avenue de la Vistrenque",
"description:covid19": "horaires légèrement réduits",
"name": "Bio Marché",
},
In my Javascript file I can access properties such as name using this code :
var details = listing.appendChild(document.createElement('div'));
details.innerHTML = prop.addr:city;
...but am unable to figure out how to access the addr:city or addr:postcode field as I either get an unexpected identified in vs code or it returns a undefined value in the website. I've tried using prop.addr:city;, prop.addr/':city'/; and other ways proposed on websites.
If someone could point me in the right direction or propose the solution I would be very grateful.
Thanks !
You should access these properties like this:
details.innerHTML = prop['addr:city'];
This works because in Javascript object properties can always be accessed using these brackets.
For example this:
const a = prop.a;
is equal to
const a = prop['a'];
However using the last syntax Javascript is a lot more relaxed. You could even do this:
const property = prop['some property with lots of spaces'];

How to edit an object within a very simple JS file using Node.js

Whilst this question is related to Workbox and Webpack, it does not require any prior knowledge of either library.
Background (skip if not familiar with Workbox)
I am currently utilising the InjectManifest plugin from Workbox 4.3.1 (workbox-webpack-plugin). This version of the library offers an option called manifestTransforms, but unfortunately, the transformations are not applied to assets within the webpack compilation (this is a known issue).
Whilst this has been fixed in Workbox v5+, I am unable to upgrade due to another library in my build process requiring webpack v3 (Dynamic Importing in Laravel Mix)
The reason I mention the above is because unforunately the solution is not to upgrade to workbox v5+.
The Problem
I have an auto-generated file that looks like this:
self.__precacheManifest = (self.__precacheManifest || []).concat([
{
"revision": "68cd3870a6400d76a16c",
"url": "//css/app.css"
},
// etc...
]);
I need to somehow extract the the contents of the object stored within self.__precacheManifest, apply my own transformations, and then save it back to the file.
What I have Tried...
This is as far as I have got:
// As the precached filename is hashed, we need to read the
// directory in order to find the filename. Assuming there
// are no other files called `precache-manifest`, we can assume
// it is the first value in the filtered array. There is no
// need to test if [0] has a value because if it doesn't
// this needs to throw an error
let manifest = fs
.readdirSync(path.normalize(`${__dirname}/dist/js`))
.filter(filename => filename.startsWith('precache-manifest'))[0];
require('./dist/js/' + manifest);
// This does not fire because of thrown error...
console.log(self.__precacheManifest);
This throws the following error:
self is not defined
I understand why it is throwing the error, but I have no idea how I am going to get around this because I need to somehow read the contents of the file in order to extract the object. Can anyone advise me here?
Bear in mind that once I have applied the transformations to the object, I then need to save the updated object to the file...
Since self refers to window and window does not exist in node.js a way around is needed.
One thing that should work is to define the variable self in Node's global scope and let the require statement populate the content of the variable, like this:
global['self'] = {};
require('./dist/js/' + manifest);
console.log(self.__precacheManifest);
To save the modified contents back to the file
const newPrecacheManifest = JSON.stringify(updatedArray);
fs.writeFileSync('./dist/js/' + manifest, `self.__precacheManifest = (self.__precacheManifest || []).concat(${newPrecachedManifes});`, 'utf8');

How do I get a list of all GlobalEventHandlers?

https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers
How do I get a list of all the properties of GlobalEventHandlers?
Specifically, I want to test if a passed string is a property of GlobalEventHandlers, something like:
console.log(GlobalEventHandlers.includes('onClick')); // true
console.log(GlobalEventHandlers.includes('fizzBuzz')); // false
The only real way to get all of them is to build the list yourself, but you can loop over the keys in the window object and look for keys that start with on
Object.keys(window).filter(k => !k.indexOf('on'))
BUT that is not going to return just the built in ones. If someone set a custom event listener like
window.onfoobar = function () {}
than that will also show up in the result.
I wrote an npm package that does that for you.
Full usage and installation: global-event-handlers-map.
it extracts every global event handler under every object that exists under window (including window).
for example, by calling:
const getGlobalEventsHandlersMap = require('global-event-handlers-map');
const gehsMap = getGlobalEventsHandlersMap('WebSocket');
you will get the following result (gehsMap would be):
{
"WebSocket": [
"onopen",
"onerror",
"onclose",
"onmessage"
]
}
by calling getGlobalEventsHandlersMap() with no arguments, you will receive ALL global event handlers.
the README file should be very indicative and should help you understand how to get everything you need from that package.
you can either:
execute the code once in the browser, get the results, and use that map statically in your code.
integrate the library in your code and by that dynamically create the map every time your code runs in the browser.
the best way depends on your needs, and should be your call. i can help you understand which way is best for you depends on your needs.
hope that helps!

Redefining a RequireJS module -- is it possible?

Basically, there is a page that I visit that uses RequireJS. I want to make adjustments to this page, so I went the route of a userscript. While looking at the client-side code I see that there is a module defined as so:
define("settings", [], function() {
return {
SETTINGA: "100",
SETTINGB: "200",
etc.
}
})
I want to add my own item to the settings array, as well as change some settings without having to redefine the module in my userscript (with the changes) and then removing/readding it. Is it possible to just make adjustments to this module?
P.S. I'm using the Script Injection technique to get my userscript to interact with other javascript in the original page.
Also, doing require("settings") in the Javascript console returns an object (not an array), so I can't do things like require("settings")[0] or require("settings").push(...), however I can access the settings by doing require("settings").SETTINGA. So, I'm not sure how to add/redefine settings to this since it is not an array?
Use this:
require('settings').new_property = 'new value';
The reason you can't retrieve or add settings to "the settings array" is that you aren't creating an array to begin with. {foo:bar} is an object literal, not an array literal ([foo,bar]).

Categories

Resources