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.',