Their paid tier offers the possibility to access it through HTTP – a good candidate for Gulp automation. Since there’s no ready-made plugin available on the internet, I’ve ventured into building one; which I’m going to share with you in this post. Before going into the technical details of Gulp plugins, let me recap very briefly my point of view on code privacy.
- HTML Panels should protect both JS and JSX, and JSX is known to be particularly resistant to aggressive minification and/or obfuscation.
- To my experience, free obfuscation services are not that much reliable: even the apparently ugliest result can be automatically beautified in such a way that at least part of the code logic is exposed. Moreover, some of them are known to inject malicious code in the process.
- I’ve evaluated two or three different options, and I’ve finally chosen the one I’ll talk about. I’m not sponsored in any way – alas :-)
- No, JSXBIN isn’t as secure as it was in the past.
proj object is created, and some properties assigned: your API data, the project name, and a series of parameters that will drive the obfuscation process. In this case,
ReplaceName set to
true (line 6). In the same call, you can send for processing more that one single file: they must be wrapped with an object (here
item1), which actual code is found in the
FileCode property (lines 11-17).
Then they’re both stored into an array that is assigned to the
proj.Items property. Next, a standard
XMLHttpRequest of type
POST is sent, passing the stringified
proj object (line 26). The response is then showed in a couple of
div elements in the page. Enough for this example. The kind of API that I’d like to consume in my real code is as follows – this comes directly, yet slightly simplified, from my
I’m passing two files in the source array – the ones I’m interested in deep obfuscating: the main application JS, and the only JSX of the Panel. The processed result is going to be saved in the
dist folder, keeping the same directories structure. As you see, I’m requiring
'./jsobfuscator': this means that I’ve created in the root folder a
jsobfuscator.js file, which contains my actual Gulp plugin. The entire code is as follows, read along for a walkthrough.
Before going any further, check this Writing a Gulp Plugin documentation page as a way to orient yourself: I’ll point out the main problems I’ve run into as a total Gulp plugins beginner, that I’ve been able to solve after a good deal of head scratching time. First, you need to require some modules: the native
vinyl – install them:
I’m exporting a single function, that returns (line 84) the
transform function passed through the
through.obj() method: this is the way a Gulp plugin works.
transform function (line 10) is exactly where everything happens. I’ve recreated there the
proj object you’ve seen in the demo file, passing a lot more parameters. These ones (lines 21-29, like
That’s what you’re allowed to set with a Basic membership ($19 per month). I’m not 100% sure I’ve been able to replicate everything: if you have a better understanding of the parameters, please let me know in the comments. Next, I’ve created the wrapper object (
appJS, line 31) that will contain the plain code to be obfuscated: please note that the
FileCode property this time can’t be just equal to
file, which is a peculiar object called Vinyl File – what your Plugin should receive and, eventually, return. Instead, you’re interested into the
contents prop of the Vinyl File, which happens to be a Buffer: so you need to stringify it, passing the correct encoding (
At line 35,
appJS is inserted in the
proj.Items array; I’m then creating a
proj object. Line 41-49, the
options object will be needed in the request at line 80: I have to specify the host (no prepended https), path, method, and headers. Without
'Content-Length' (see this StackOverflow thread for the
Buffer.byteLength() method used to calculate the latter) the request will fail. Line 49,
postCallback is called when the request is dispatched.
As soon as data is coming, i.e.
response.on('data'), a string is formed. When the response is terminated, i.e.
response.on('end'), I’m parsing the received JSON string into an object (line 62). If you want to log it – or log anything to debug your code – use the
gutil.log() function, that you can find in the code comments here and there. The horribly, properly obfuscated string is found in the
resObj.Items.FileCode prop, hurray! The only problem is, as I’ve mentioned earlier, that your Gulp plugin needs to return a Vinyl File. Hence, a brand new Vinyl File called
jsFile is created (line 66) using current working directory, base, and path from the original
file. What about the
contents? You cannot stick in there the
resObj.Items.FileCode String, because contents must be a Stream. Thanks to the holy StackOverflow, I’ve learned that a
Readable (line 64) can turn String into Stream, and I’m a happy camper now.
Last but not least, this Vinyl file must be pushed down the line, for the Gulp Plugin to work. Was I not into a callback, nested in a function, which in turn is nested into the main
transform function, I would have used
this.push(jsFile). But I happen to be at a location where
this is not what it used to be: that’s the why I’ve stored it (line 15) into the
that variable. So
that.push(jsFile), line 75. At the very end, you need to run the
transform’s callback (line 76), and you can call quit.
The above took me more than a full day of work to figure out… It’s been a self-taught crash course on Gulp Plugins – worth sharing to you and my future self when I’ll have forgotten every juicy detail of it; in about… a couple of months maybe? There is plenty of room for improvement – I would have liked to merge multiple source files not into a single file, but into a single http request: splitting the various input files into several elements of the
proj.Items array. Yet, I have no idea how to do so (suggestions in the comments are welcome!). Error checking is completely missing, and so on and so forth. Rough as it is, it works; and every second saved from manual labor is worth the effort, isn’t it?
The Photoshop HTML Panels Development Course
If you’re reading here, you might be interested in my Photoshop Panels development – so let me inform you that I’ve authored a full course:
- 300 pages PDF
- 3 hours of HD screencasts
- 28 custom Panels with commented code
Check it out! Please help me spread the news – I’ll be able to keep producing more exclusive content on this blog. Thank you!