Fix title JS string escaping bug #1498

Reimplement as a single recursive template.