Skip to content

Commit

Permalink
abolish the post-install script and template/plugin copying (jsdoc#519,
Browse files Browse the repository at this point in the history
jsdoc#612)

JSDoc has a few requirements that are somewhat unusual for a Node.js app:

1. We need `require('jsdoc/foo')` to work from any module.
2. We need `require('jsdoc/foo')` to work from external code, such as templates and plugins.

Prior to this commit, JSDoc did two separate things to meet these requirements:

1. Use an npm post-install script to create a symlink from `lib/jsdoc` to `node_modules/jsdoc`.
2. When a user runs JSDoc, copy templates and plugins into the JSDoc directory.

These fixes worked, sort of. But they also caused numerous issues with file permissions, especially on Windows.

We now use the Requizzle module, which hacks the Node.js module system to support JSDoc's use cases. There's no longer a post-install script, and there's no need for a symlink in `node_modules`.
  • Loading branch information
hegemonic committed Jun 10, 2014
1 parent 9555f6c commit fd5ca94
Show file tree
Hide file tree
Showing 15 changed files with 612 additions and 173 deletions.
10 changes: 10 additions & 0 deletions LICENSE.md
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,16 @@ node-browserify is distributed under the MIT license, which is reproduced above.
The source code for node-browserify is available at:
https://github.com/substack/node-browserify

## Requizzle ##

Requizzle is distributed under the MIT license, which is reproduced above.

Copyright (c) 2014 Google Inc. All rights reserved.
Copyright (c) 2012-2013 Johannes Ewald.

The source code for Requizzle is available at:
https://github.com/hegemonic/requizzle

## Rhino ##

Rhino is distributed under the following licenses:
Expand Down
83 changes: 0 additions & 83 deletions cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -247,78 +247,6 @@ function getRandomId() {
return Math.floor(Math.random() * (MAX - MIN + 1) + MIN);
}

// TODO: docs
function createTempDir() {
var fs = require('jsdoc/fs');
var path = require('jsdoc/path');
var wrench = require('wrench');

var isRhino;
var tempDirname;
var tempPath;

// We only need one temp directory
if (props.tmpdir) {
return props.tmpdir;
}

isRhino = require('jsdoc/util/runtime').isRhino();
tempDirname = 'tmp-' + Date.now() + '-' + getRandomId();
tempPath = path.join(env.dirname, tempDirname);

try {
fs.mkdirSync(tempPath);
props.tmpdir = tempPath;
}
catch (e) {
logger.fatal('Unable to create the temp directory %s: %s', tempPath, e.message);
return null;
}

try {
// Delete the temp directory on exit
if (isRhino) {
( new java.io.File(tempPath) ).deleteOnExit();
}
else {
process.on('exit', function() {
wrench.rmdirSyncRecursive(tempPath);
});
}

return tempPath;
}
catch (e) {
logger.error('Cannot automatically delete the temp directory %s on exit: %s', tempPath,
e.message);
return null;
}
}

// TODO: docs
function copyResourceDir(filepath) {
var fs = require('jsdoc/fs');
var path = require('jsdoc/path');
var wrench = require('wrench');

var resourceDir;
var tmpDir;

try {
tmpDir = createTempDir();
resourceDir = path.join( tmpDir, path.basename(filepath) + '-' + getRandomId() );
fs.mkdirSync(resourceDir);

wrench.copyDirSyncRecursive(filepath, resourceDir);
return resourceDir;
}
catch (e) {
logger.fatal('Unable to copy %s to the temp directory %s: %s', filepath, resourceDir,
e.message);
return null;
}
}

// TODO: docs
cli.scanFiles = function() {
var Filter = require('jsdoc/src/filter').Filter;
Expand Down Expand Up @@ -373,10 +301,6 @@ function resolvePluginPaths(paths) {
logger.error('Unable to find the plugin "%s"', plugin);
return;
}
// On Node.js, the plugin needs to be inside the JSDoc directory
else if ( isNode && (pluginPath.indexOf(global.env.dirname) !== 0) ) {
pluginPath = copyResourceDir(pluginPath);
}

pluginPaths.push( path.join(pluginPath, basename) );
});
Expand Down Expand Up @@ -468,13 +392,6 @@ cli.generateDocs = function() {
var publish = env.opts.template || 'templates/default';
var templatePath = path.getResourcePath(publish);

if (templatePath && isNode) {
// On Node.js, the template needs to be inside the JSDoc folder
if (templatePath.indexOf(env.dirname) !== 0) {
templatePath = copyResourceDir(templatePath);
}
}

// if we didn't find the template, keep the user-specified value so the error message is
// useful
return templatePath || env.opts.template;
Expand Down
39 changes: 24 additions & 15 deletions jsdoc.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env node
/*global arguments */
/*global arguments, require: true */
/**
* @project jsdoc
* @author Michael Mathews <[email protected]>
Expand Down Expand Up @@ -86,12 +86,23 @@ global.env = {
(function(args) {
'use strict';

var path;

if (args[0] && typeof args[0] === 'object') {
// we should be on Node.js
args = [__dirname, process.cwd()];
path = require('path');

// Create a custom require method that adds `lib/jsdoc` to the module lookup path.
// This makes it possible to `require('jsdoc/foo')` from external templates and plugins,
// and within JSDoc itself.
require = require('requizzle')({
requirePaths: [path.join(__dirname, 'lib')],
infect: true
});
}

require('jsdoc/util/runtime').initialize(args);
require('./lib/jsdoc/util/runtime').initialize(args);
})( Array.prototype.slice.call(arguments, 0) );

/**
Expand All @@ -102,9 +113,9 @@ global.env = {
*/
global.app = {
jsdoc: {
scanner: new (require('jsdoc/src/scanner').Scanner)(),
name: require('./lib/jsdoc/name'),
parser: null,
name: require('jsdoc/name')
scanner: new (require('./lib/jsdoc/src/scanner').Scanner)()
}
};

Expand All @@ -121,8 +132,8 @@ global.app = {
global.dump = function() {
'use strict';

var doop = require('jsdoc/util/doop').doop;
var _dump = require('jsdoc/util/dumper').dump;
var doop = require('./lib/jsdoc/util/doop').doop;
var _dump = require('./lib/jsdoc/util/dumper').dump;
for (var i = 0, l = arguments.length; i < l; i++) {
console.log( _dump(doop(arguments[i])) );
}
Expand All @@ -131,11 +142,14 @@ global.dump = function() {
(function() {
'use strict';

var logger = require('jsdoc/util/logger');
var path = require('jsdoc/path');
var runtime = require('jsdoc/util/runtime');
var logger = require('./lib/jsdoc/util/logger');
var runtime = require('./lib/jsdoc/util/runtime');
var cli = require('./cli');

var cli = require( path.join(global.env.dirname, 'cli') );
function cb(errorCode) {
cli.logFinish();
cli.exit(errorCode || 0);
}

cli.setVersionInfo()
.loadConfig();
Expand All @@ -146,11 +160,6 @@ global.dump = function() {

cli.logStart();

function cb(errorCode) {
cli.logFinish();
cli.exit(errorCode || 0);
}

// On Rhino, we use a try/catch block so we can log the Java exception (if available)
if ( runtime.isRhino() ) {
try {
Expand Down
72 changes: 0 additions & 72 deletions node/postinstall.js

This file was deleted.

1 change: 0 additions & 1 deletion node_modules/jsdoc

This file was deleted.

22 changes: 22 additions & 0 deletions node_modules/requizzle/LICENSE

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit fd5ca94

Please sign in to comment.