Trick to use CoffeeScript in Hexo

Hexo has a scripts folder, and the files under which are loaded by Hexo when start. I usually uses this folder as the development folder for my plug-in scripts. And extract them into independent package after polished it into package-ready quality.

Usually, the files under scripts should be javascripts. But as I’m a fan of Coffee Script, so I wish to use coffee-script to write the plug-ins. For the formal package, I compile the coffee scripts into javascripts before release. But for development, I wish to use coffee script directly.

In node.js, it is possible to require coffee-script directly, if you registered the coffee-script runtime compiler:

1
require('coffee-script/register');

And as how node.js require function is implemented, you cannot register coffee-script runtime compiler in .coffee file. Or the compiler will complain:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[error] HexoError: Script load failed: plugin.coffee
SyntaxError: Unexpected string
at Module._compile (module.js:439:25)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Module.require (module.js:364:17)
at require (module.js:380:17)
at /usr/local/lib/node_modules/hexo/lib/loaders/scripts.js:17:11
at Array.forEach (native)
at /usr/local/lib/node_modules/hexo/lib/loaders/scripts.js:15:13
at /usr/local/lib/node_modules/hexo/lib/util/file2.js:339:7
at done (/usr/local/lib/node_modules/hexo/node_modules/async/lib/async.js:135:19)
at /usr/local/lib/node_modules/hexo/node_modules/async/lib/async.js:32:16
at /usr/local/lib/node_modules/hexo/lib/util/file2.js:335:11
at Object.oncomplete (evalmachine.<anonymous>:107:15)

Theoretically, it is possible to put the coffee-script registration code in a javascript file and also put it under /scripts folder. SO Hexo will load it when start-up.

Well, this approach doesn’t really work. If you try it, it is very likely to get the exactly same error as before. The reason is related to Hexo implementation. Hexo uses Scripts Loader to require files under /scripts. The loader doesn’t really provide an explicit way to specify which file is loaded before another. So the registration file is guaranteed to be loaded before any .coffee.

So far, it seems that there is no cure to this problem! But actually it does. There is undocumented feature will help to solve this issue.

Hexo uses [Script Loader] to load the scripts. In Scripts Loader use hexo.util.file2 to populate the source files under /scripts. And hexo.util.file2 use fs.readdir to actully populate the file system entries. For fs.readdir, there is a undocumented feature, that the populated entries are actually sorted alphabetically, which means a.js is loaded before b.coffee.

With this feature, we can put our coffee-script registration in a file with lower alphabetic-order name. Personally, I’d like called ___register_coffeescript.js, since _ is smaller than any letter or number.

⚠️WARNING: fs.readdir yielding sorted files is an undocumented behavior, which means it is not guaranteed either to work across platforms or not get changed in the future. So for, it works on Mac, and I expect it behaves similar on Linux. But not sure about Windows, since fs uses a different native binding on Windows.

Some tricky ways to calculate integer in javascript

Javascript is famous for its lack of preciseness, so it always surprises and make joke with the developers by breaking the common sense or instinct.

Javascript doesn’t provide integer type, but in daily life, integer sometimes is necessary, then how can we convert a trim a float number into integer in Javascript?
Some very common answers might be Math.floor, Math.round or even parseInt. But besides calling Math functions, is there any other answer?

The answer is bitwise operations. Amazing? Yes. Because bitwise operations are usually only applied to integers, so Javascript will try to convert the number into "integer" internally when a bitwise operation is applied, even it is still represented in type of number

Suppose value = 3.1415926, and we want integer is the trimmed value of value, then we can have:

Trim Float Number
1
2
3
4
5
6
7
8
9
10
11
12
var value = 3.1415926;
var integer = Math.floor(value);
integer = Math.round(value);
integer = parseInt(value);
integer = ~~value; // Bitwise NOT
integer = value | 0; // Bitwise OR
integer = value << 0; // Left Shift
integer = value >> 0; // Sign-propagating Right Shift
integer = value >>> 0; // Zero-fill Right Shift

For more detail information about bitwise operation in javascript, please check out the MDN document

All approaches listed before are working, but with different performance. And according to the result from JsPerf, I sort the algorithms by performance from good to bad:

  1. integer = ~~value;
  2. integer = value >>> 0; and integer = value << 0;
  3. integer = Math.floor(value);
  4. integer = value >> 0;
  5. integer = value | 0;
  6. integer = Math.round(value);
  7. integer = parseInt(value);

NOTE: The test cases are running in Chrome 24.0.1312.57 on Mac OS X 10.8.2

Inject jQuery to current page

Now I’m hacking some web sites to try to grab the interesting informations from the page. But for some reason, all the sites I’m working on now, doesn’t included jQuery, they uses YUI or extJS, which makes me feel super inconvenient when trying hacking the page pattern.

Do I need to find a way to inject jQuery into the current page that I’m browsing.
Thanks to the browser address bar which allow us to execute javascript directly on current session. And also thanks to bookmark, which allow us to persists the script into bookmark, and invoke it with only one mouse click.

So I wrote this:

With this, we can quickly inject jQuery into current session in no time.

You can drag the following link to your browser favorites bar to:
Inject jQuery