Replacing Handlebarjs's escaper - javascript

I'm working on a setup that runs a bunch of shell commands on a remote system when triggered. Instead of having a bunch of concatenated strings, for maintainability I decided to use a templater.
Handlebarjs has so far proven to be amazing, but by default it html encodes output. I've learned you can add { noEscape: true } to the compile command, or wrap the variable in {{{ }}}, but what I'd like to do is for certain templates, replace the default escaper entirely. Is this doable?
Right now my templates look like:
mkdir \"{{shellEscape directory}}\" with noEscape turned on, but I'd rather default that behaviour.
Failing that, I'd like to know if there is a Util function that translates the variable provided to a string (You can provide handlebar a function, but a helper doesn't evaluate it first)

Related

How do I include untyped-JavaScript, from an adjacent file, in ReasonML bindings?

While trying to get started with Reason, in one JavaScript project, I've got an extremely light file that tries to be a Reason-typed interface to the existing, heavy, library:
/* TheLibrary.re */
type engine
external addEngine : string -> engine -> unit = "" [##bs.val] [##bs.module "../"]
However, when I try to use that library in a ReasonReact project (having added #org/the-library to the bsconfig.json bs-dependencies),
/* AComponent.re */
[#bs.val] [#bs.module "#org/game-engine/dist/game-engine.js"]
external gameEngine : TheLibrary.engine = "default";
/* Further down, a React lifecycle method, */
TheLibrary.addEngine("Game", gameEngine);
I get errors about ../ being not found, relative to that React component:
./src/components/main-menu/AComponent.re
Module not found: Can't resolve '../' in '/Users/ec/Work/reason-reacty/src/components/main-menu'
I've also tried, instead of ../ in TheLibrary.re's external declaration:
#bs.module "./index.js" (the direct, ES6 entry-point for the untyped-JavaScript side of the package in question,)
#bs.module "#org/the-library", the entire name of said library (even though I'm typing inside that library???)
Please help! I'd love to be able to further adopt ML, but I'm having the hardest time wrapping my head around ReasonReact's dependency-resolution!
Additional context:
So, we're trying to build our first ReasonReact project, and we've successfully added baby's-first-opaque-types to one of our internal libraries and include that in the ReasonReact page with something like the following — which works, by the way:
/* Imports.re */
type engine;
[#bs.val] [#bs.module "#org/game-engine/dist/game-engine.js"]
external gameEngine : engine = "default";
[#bs.val] [#bs.module "#org/the-library"] [#bs.scope "default"]
external addEngine : (string, engine) => unit = "";
This yields, when we Imports.(addEngine("Game", gameEngine)), the global setup line we need: TheLibrary.addEngine("Game", GameEngine). I'm in the very first stages of trying to upstream that typing-information into the parent project, and publish that code to npm, so that all consuming projects can start to use Reason.
t sounds like you might be a bit confused about the different tools that make up your toolchain, so let's first go through them one by one to put them in their place:
ReasonReact is a library of opinionated, "thick" bindings to react.js, which despite the name isn't actually all that Reason-specific, except for its integration with Reason's JSX syntax. It would be more accurate to call it a BuckleScript library.
Reason is mostly just the syntax you use, but is often also used more broadly to refer to the ecosystem around it, and usually also imply that BuckleScript is being used.
OCaml is the underlying language. The "semantics" of Reason, if you will.
BuckleScript is the OCaml-to-JavaScript compiler. It compiles ONE source file, which is considered a module, into ONE JavaScript module, but also requires the type information of other OCaml modules as input.
Now, I suspect you already know most of that, but what you do not seem to know is that NONE of these actually do ANY dependency resolution. These next parts of your toolchain are what does that:
The BuckleScript Build System, or bsb, is what finds all the modules in your local project according to what you've specified in src and any BuckleScript libraries you've listed in bs-dependecies in bsconfig.json. It will figure out the dependency order of all these and feed them to the compiler in the correct order to produce one JavaScript module for each OCaml module (along with some other artefacts containing type information and such). But it will not resolve any JavaScript dependencies.
Lastly, webpack, or some other JavaScript bundler, is what you likely use to combine all the JavaScript modules into a single file, and which therefore needs to resolve any JavaScript dependencies. And this is likely where the error message comes from.
Using [#bs.module "some-module"] will make the BuckleScript compiler emit var ... = require('some-module') (or import ... from 'some-module' if es6 is used), but BuckleScript itself will not do anything more with it. The string you pass to #bs.module is the same string you would pass to require if it had been an ordinary CommonJS module (or whatever other module format you have configured).
Also note that the import is not emitted where the external is defined, but where it's used. You can work around, or "ground" it in a module by re-exporting it as an ordinary definition, ie. let addEngine = addEngine.
In order to precisely answer your question I would need to know which bundler you use, where you've configured BuckleScript to output its JavaScript artefacts, where the externals are used, not just defined, and where the external JavaScript module is located. But I hope all this underlying knowledge will make it easy for you and future readers to identify and resolve the problem yourself. If you're still a bit unsure, look at the compiled JavaScript artefacts and just treat them as ordinary JavaScript modules. At this point that's really all they are.

Concatenating raw javascript to a webpack bundle

I'm currently working on a build process that uses webpack. One of the dependencies that I need to include in my bundle is an old third-party library that doesn't follow any module patterns. I wan't to just include it in it's raw form, but it's coded in such a way that the usual techniques don't work.
The offending library is coded a bit like this:
function OldLibrary() {
console.log('What are modules?');
};
var foo = window.OldLibrary;
// Proceeds to use foo without a care in the world
As you can see from the code above, the library assumes that it will always be in the global context, and so it doesn't bother to explicitly set window.OldLibrary.
At first I tried using script-loader, but this wraps the script inside function(module, exports) {}, which means that OldLibrary now belongs to the scope of that function instead of window's and this causes an exception. I also tried using imports loader like imports?this=>window, but this only sets this to window, so it doesn't have effect on functions that are supposed to be global.
Finally, I tried out raw-loader, but this just adds the script as a string, so it's not executed. Is there a way to tell Webpack to just concatenate the script as is without wrapping it inside another function?
Edit
It turns out that script-loader does actually handle this library as expected, I just wasn't matching it properly because it was the only file that didn't have a .min.js extension. I'm still interested in finding a way to concatenate scripts without wrapping them in functions, if possible.

Reverse a Javascript Build

I have a javascript build file, that is unminified; it contains prototype class definitions. Is there any tool i can use to break the build file into separate files, assuming one file per prototype/class definition?
This build file looks like the following, with many objects defined in the following way, all concatenated into the single file. I would like to break this file apart. I don't have access to the original source code, I was basically just given a dump in the form of this build file but its unmanageable in this form as its 10k+ lines of code.
MyClass = function(){
}
MyClass.prototype.foo = function(){
}
I would go with the suggested (in comments) do it manually manner, but if you insist to automate it some way, you can always use javaScript for the job.
One way would be to look up for constructors throw a regex like ([^\.=\s]+[^=]*=[\s]*function[\s]*[(]+[^)]*[)][\s]*[{]*) and extract all 'class'.prototype.'something' from the file, parse the entire file then write each group in separate files after doing any kind of ordering you would prefer.
Another manner would be to use a javaScript parser and group relevant function definitions throw token examination (this one is overkill, but might be interesting for learning purposes).

script tag text/babel variable scope

Firstly, I understand text/babel is not for use in production, but I found it quite useful for development as when I make a change to my .jsx file django's dev webserver will reload without me having to do anything (i.e. compile the JSX to JS after every change).
I am not in control of the build environment (e.g. django) as this is a small plugin for a larger system that I am not developing.
The problem is this:
<script type="text/babel" src="{% static "myapp/js/main.jsx" %}"></script>
<script>
$(function() {
console.log(mything);
}
</script>
Where mything is in main.jsx, something as simple as:
var mything = "hello";
If main.jsx is javascript (and the type of the script tags is changed accordingly) then this will work just fine. As text/babel though, it will not work because mything is not in scope.
Uncaught ReferenceError: mything is not defined
This makes sense to me as I wouldn't expect script tags of different types to share a scope, but I'm wondering if there is some clever way around this to aid development?
I previously had all the code in a single text/babel block, but as it grows, it would be nice to separate it out into several JSX files.
Without diving too deeply into the Babel source (looking at https://github.com/babel/babel/blob/master/packages/babel/src/api/browser.js), I'm going to guess that it reads your JSX source, performs transformation on the source, and then evals the source in some way to execute it. The scope is not shared because babel prepends 'use strict'; to the transformed code (standard in ES6).
If you really need to expose a variable, you can attach it to window (ie use window.mything in your JSX instead of just mything). Ideally, you should make use of modules as you split your code up into multiple files. You can make use of a build step to transform your code through Babel and use browserify/webpack to manage dependencies.

Javascript preprocessor to replace variable reference during build

Is there a way to substitute variables in javascript files, with a preprocessor during build process. I uses grunt, usemin, uglifyjs (part of yeoman stack).
I currently refer to url from a global javascript object. For example,
my.url = {
book: {
get : '/my/book/{id},
new: '/my/book'
}
}
in my program, I may refer the url as my.url.book.get, etc. The intention is
do not want the url string spread across the program, as any change during development make it hard to refactor.
url may generate based on the server API, and don't want to duplicate in client.
Now, once I am happy with the development, I like to preprocess all the javascript file to substitute all these references to actual url string. Intention is to avoid loading an extra file with all the url (may the user only need few of the url).
is there any tool, similar to html templating package, to process the javascript and replace all the variables. I prefer if it works with grunt/yeoman stack.
You can do that with grunt-replace It allows for all kinds of string substitutions in text files. I use it to sync version numbers in bower.json, package.json etc, but obviously you can use it for source file value substitutions as well.
That said, in your case I'd definitely opt for a more dynamic solution with env variables, with for instance grunt-env.
Try #Builder https://github.com/electricimp/Builder
Little example
in config.js:
#set apiEndpoint "https://somesite.com/api/v1"
then:
#include once "config.js"
let url = "#{apiEndpoint}"

Categories