mirror of
https://github.com/jsdoc/jsdoc.git
synced 2025-12-08 19:46:11 +00:00
improve filename creation (#677)
We now allow a much larger range of characters in filenames. We also URL-encode HTML links when necessary, so that everything still works when you upload the files to a web server.
This commit is contained in:
parent
da7911bcf8
commit
873480a3ed
@ -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, '<');
|
||||
@ -83,20 +70,24 @@ var htmlsafe = exports.htmlsafe = function(str) {
|
||||
* @return {string} The filename to use for the string.
|
||||
*/
|
||||
var getUniqueFilename = exports.getUniqueFilename = function(str) {
|
||||
// allow for namespace prefix
|
||||
var basename = cleanseFilename(str);
|
||||
var basename = (str || '')
|
||||
// allow for namespace prefix
|
||||
// TODO: use prefixes in jsdoc/doclet
|
||||
.replace(/^(event|module|external|package):/, '$1-')
|
||||
// replace characters that can cause problems on some filesystems
|
||||
.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('<a href="%s%s"%s>%s</a>', url, fragmentString, classString, text);
|
||||
return util.format('<a href="%s"%s>%s</a>', 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;
|
||||
};
|
||||
|
||||
@ -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.',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user