diff --git a/lib/jsdoc/util/templateHelper.js b/lib/jsdoc/util/templateHelper.js
index 709cd2f6..d86587ae 100644
--- a/lib/jsdoc/util/templateHelper.js
+++ b/lib/jsdoc/util/templateHelper.js
@@ -4,6 +4,7 @@
*/
'use strict';
+var catharsis = require('catharsis');
var dictionary = require('jsdoc/tag/dictionary');
var util = require('util');
@@ -52,20 +53,6 @@ function makeFilenameUnique(filename, str) {
return filename;
}
-function cleanseFilename(str) {
- str = str || '';
-
- // allow for namespace prefix
- // TODO: use prefixes in jsdoc/doclet
- return str.replace(/^(event|module|external|package):/, '$1-')
- // use - instead of ~ to denote 'inner'
- .replace(/~/g, '-')
- // use _ instead of # to denote 'instance'
- .replace(/\#/g, '_')
- // remove the variation, if any
- .replace(/\([\s\S]*\)$/, '');
-}
-
var htmlsafe = exports.htmlsafe = function(str) {
return str.replace(/&/g, '&')
.replace(/]/g, '_')
+ // use - instead of ~ to denote 'inner'
+ .replace(/~/g, '-')
+ // use _ instead of # to denote 'instance'
+ .replace(/\#/g, '_')
+ // use _ instead of / (for example, in module names)
+ .replace(/\//g, '_')
+ // remove the variation, if any
+ .replace(/\([\s\S]*\)$/, '')
+ // make sure we don't create hidden files, or files whose names start with a dash
+ .replace(/^[\.\-]/, '');
- // if the basename includes characters that we can't use in a filepath, remove everything up to
- // and including the last bad character
- var regexp = /[^$a-z0-9._\-](?=[$a-z0-9._\-]*$)/i;
- var result = regexp.exec(basename);
- if (result && result.index) {
- basename = basename.substr(result.index + 1);
- }
-
- // make sure we don't create hidden files on POSIX systems
- basename = basename.replace(/^\./, '');
- // and in case we've now stripped the entire basename (uncommon, but possible):
+ // in case we've now stripped the entire basename (uncommon, but possible):
basename = basename.length ? basename : '_';
return makeFilenameUnique(basename, str) + exports.fileExtension;
@@ -116,7 +107,6 @@ var tutorialLinkMap = {
var longnameToUrl = exports.longnameToUrl = linkMap.longnameToUrl;
function parseType(longname) {
- var catharsis = require('catharsis');
var err;
try {
@@ -146,6 +136,14 @@ function isComplexTypeExpression(expr) {
return expr.search(/[{(|]/) !== -1 || expr.search(/) > 0;
}
+function fragmentHash(fragmentId) {
+ if (!fragmentId) {
+ return '';
+ }
+
+ return '#' + fragmentId;
+}
+
/**
* Build an HTML link to the symbol with the specified longname. If the longname is not
* associated with a URL, this method simply returns the link text, if provided, or the longname.
@@ -171,10 +169,8 @@ function isComplexTypeExpression(expr) {
* @return {string} The HTML link, or the link text if the link is not available.
*/
function buildLink(longname, linkText, options) {
- var catharsis = require('catharsis');
-
var classString = options.cssClass ? util.format(' class="%s"', options.cssClass) : '';
- var fragmentString = options.fragmentId ? '#' + options.fragmentId : '';
+ var fragmentString = fragmentHash(options.fragmentId);
var stripped;
var text;
var url;
@@ -205,7 +201,8 @@ function buildLink(longname, linkText, options) {
return text;
}
else {
- return util.format('%s', url, fragmentString, classString, text);
+ return util.format('%s', encodeURI(url + fragmentString), classString,
+ text);
}
}
@@ -727,7 +724,6 @@ exports.createLink = function(doclet) {
var fakeContainer;
var url = '';
- var INSTANCE = exports.scopeToPunc.instance;
var longname = doclet.longname;
// handle doclets in which doclet.longname implies that the doclet gets its own HTML file, but
@@ -761,7 +757,7 @@ exports.createLink = function(doclet) {
fragment = getNamespace(doclet.kind) + (doclet.name || '');
}
- url = fragment ? (filename + INSTANCE + fragment) : filename;
+ url = encodeURI( filename + fragmentHash(fragment) );
return url;
};
diff --git a/test/specs/jsdoc/util/templateHelper.js b/test/specs/jsdoc/util/templateHelper.js
index c782d22f..28acd015 100644
--- a/test/specs/jsdoc/util/templateHelper.js
+++ b/test/specs/jsdoc/util/templateHelper.js
@@ -177,9 +177,14 @@ describe("jsdoc/util/templateHelper", function() {
expect(filename).toBe('BackusNaur.html');
});
- it('should convert a string with slashes into the text following the last slash plus the default extension', function() {
+ it('should replace slashes with underscores', function() {
var filename = helper.getUniqueFilename('tick/tock');
- expect(filename).toMatch(/^tock\.html$/);
+ expect(filename).toBe('tick_tock.html');
+ });
+
+ it('should replace other problematic characters with underscores', function() {
+ var filename = helper.getUniqueFilename('a very strange \\/?*:|\'"<> filename');
+ expect(filename).toBe('a very strange __________ filename.html');
});
it('should not return the same filename twice', function() {
@@ -1332,7 +1337,7 @@ describe("jsdoc/util/templateHelper", function() {
},
url = helper.createLink(mockDoclet);
- expect(url).toEqual('_.html#"*foo"');
+ expect(url).toEqual('ns1._!_.html#%22*foo%22');
});
it('should create a url for a function that is the only symbol exported by a module.',