luciopaiva / witchcraft

Inject Javascript and CSS right from your file system. Think GreaseMonkey for more advanced users.
https://luciopaiva.com/witchcraft
MIT License
254 stars 18 forks source link

Possibility to enable/disable scripts #13

Closed schmijos closed 5 years ago

schmijos commented 5 years ago

We at our company would like to manage all our scripts together in one repository. How could we get some individual configuration per user? Now a fork of the repo is the only possibility.

luciopaiva commented 5 years ago

Hey @schmijos, great to know your company is putting Witchcraft to good use.

One easy way I see is to add that functionality to your own scripts, no need to fork Witchcraft at all. Let me give you an example:

function run() {
    let userName = window.localStorage.getItem("user-name");
    if (!userName) {
        userName = window.prompt("Please type in your name");
        window.localStorage.setItem("user-name", userName);
    }
    document.querySelector('input[type="text"]').value = "Hello, " + userName;
}

window.addEventListener("load", run);

Name it google.com.js and then head to google.com to see it working. You should see something like this:

screenshot from 2018-10-19 22-23-17

The idea here is to use the local storage to store your user's configs. The first time the user runs it, they get prompted to type in their name, since the configuration key user-name does not exist yet. The script then stores it and proceeds to use the information.

The next time the page gets loaded, the prompt will not appear anymore, since the information will be found in the local storage.

What do you think?

schmijos commented 5 years ago

Cool! Thank you very much for your input. I already had a similar idea, but rejected it because you would have to include this piece of checking-code in all the scripts, right? Is there a possibility to use partials? Maybe to include a config file loaded from the same web server which is serving the assets anyways?

luciopaiva commented 5 years ago

Actually, it is possible :tada: There's an @include command you can use exactly for that. Say you create a use configuration script named user-config.js:

function loadUserConfiguration() {
    // ToDo get it from local storage
}

You can then include it in your scripts like this:

// @include user-config.js

const userConfig = loadUserConfiguration();

You can use @include anywhere in your code, not just at the beginning. You can also include as many scripts as you want and those scripts can include others recursively. Just remember to always put it in a single line comment.

Alternatively, you could also put it in _global.js, which a special script that gets loaded for every page, but @include probably makes more sense in this case.

schmijos commented 5 years ago

Since our people can use git, I ended up with the following _config.js:

let config = {};

try {
  eval(`
    config =
      // @include .config.json
    ;
  `);
}
catch(err) {
  throw 'There is something wrong with your configuration. Did you create a file called ".config.json"?';
}

function callIfEnabled(configKey, callback) {
  if(config[configKey]) {
    callback();
  }
}

This also enables me to do my own error handling (e.g. sending a report to Sentry).

The config is then used in each file like that:

// @include _config.js
callIfEnabled('sentry.io', function() {
  …
});