Space-pen support
Glavin001 opened this issue · 20 comments
See https://github.com/atom/space-pen
Render from Spacepen source (JavaScript and CoffeeScript support) to an HTML preview of what it will look like.
Use the JSON editor (#36) as the @content
params for rendering, defaulting to {}
.
We could either eval
(read: evil) the source code or write the contents to a temporary file (since the saved file will be different than the file content buffer we are actually evaluating) and then require
the temporary file.
If we are going to use require
then we should also use https://www.npmjs.org/package/clear-require
- Check if the module is a space-pen view (jQuery element).
$ = require('atom').$;
var clearRequire = require('clear-require');
var p = '/absolute/path/to/temp/file.coffee'; // Temp file path
clearRequire(p); // Clear from Node require cache
var dv = require(p); // Get the View module
var d = new dv(); // Create new View
// Check if it is an instance of a Space-pen View
if (d instanceof $) {
// Is Space-pen view
}
Instead of using clearRequire
, as long as the require
is on a temporary file it will always be unique! 👍 Use node-temp.
The issue with requiring the module from a temp directory is that the relative require
s no longer work.
Apparently you can set $NODE_PATH
and require
will look in that directory! See http://stackoverflow.com/a/10861719 and http://www.bennadel.com/blog/2169-where-does-node-js-and-require-look-for-modules.htm
NODE_PATH
environment variable should work, as confirmed by Node.js docs: http://nodejs.org/api/modules.html#modules_loading_from_the_global_folders
Setting an environment variable is easy:
process.env.ENV_VARIABLE
However, we should revert afterwards. So be sure to store the previous NODE_PATH
.
You can append to an existing NODE_PATH
because it is a semicolon-delimited string.
Note: On Windows, NODE_PATH is delimited by semicolons instead of colons.
See http://nodejs.org/api/modules.html#modules_loading_from_the_global_folders
So NODE_PATH is not working.
# Patch the NODE_PATH
cd = path.dirname(filepath)
nodePath = process.env.NODE_PATH
deli = ":"
newNodePath = "#{nodePath}#{deli}#{cd}"
console.log newNodePath
process.env.NODE_PATH = newNodePath
View = null
try
View = require(info.path) # Get the View module
catch e
# Revert NODE_PATH
process.env.NODE_PATH = nodePath
return cb(e, null)
Still cannot find modules.
Going to try and play with module.paths
. See http://stackoverflow.com/a/9745308
module.paths
did not work either.
Found out why NODE_PATH
was not working! See https://gist.github.com/branneman/8048520#6-the-hack
NODE_PATH
must have been cached, and there is a way to reload it!
require('module').Module._initPaths();
So that works if it is not a relative require
...
> process.env.NODE_PATH = "/Applications/Atom.app/Contents/Resources/app/exports:/Users/glavin/Documents/Project Dev/atom-preview/lib"
"/Applications/Atom.app/Contents/Resources/app/exports:/Users/glavin/Documents/Project Dev/atom-preview/lib"
> require('module').Module._initPaths();
> require('preview-view')
function PreviewView() {
this.hideViewPreview = __bind(this.hideViewPreview, this);
this.renderViewForPreview = __bind(this.renderViewForPreview, this);
this.renderPreviewWithRenderer = __bind(this.renderPreviewWithRenderer, this);
this.renderPreview = __bind(this.renderPreview, this);
this.handleTabChanges = __bind(this.handleTabChanges, this);
this.changeHandler = __bind(this.changeHandler, this);
var Analytics, buffer, editor, uuid;
buffer = new TextBuffer;
editor = new Editor({
buffer: buffer
});
PreviewView.__super__.constructor.call(this, editor);
this.addClass('preview-container');
editor.setText('');
this.editorContents = $('.editor-contents', this.element);
this.messageView = new PreviewMessageView();
this.showLoading();
this.optionsView = new OptionsView(this);
this.selectRendererView = new SelectRendererView(this);
this.htmlPreviewContainer = $$(function() {
return this.div((function(_this) {
return function() {
return _this.div("THIS IS A TEST");
};
})(this));
});
this.append(this.htmlPreviewContainer);
atom.workspaceView.on('pane-container:active-pane-item-changed', this.handleTabChanges);
atom.config.observe('preview.refreshDebouncePeriod', (function(_this) {
return function(wait) {
return _this.debouncedRenderPreview = _.debounce(_this.renderPreview.bind(_this), wait);
};
})(this));
Analytics = require('analytics-node');
this.analytics = new Analytics(analyticsWriteKey);
if (!atom.config.get('preview._analyticsUserId')) {
uuid = require('node-uuid');
atom.config.set('preview._analyticsUserId', uuid.v4());
}
atom.config.observe('preview._analyticsUserId', {}, (function(_this) {
return function(userId) {
return _this.analytics.identify({
userId: userId
});
};
})(this));
this.renderPreview();
} preview-view.coffee:27
> require('./preview-view')
Error: Cannot find module './preview-view'
Still not working.
Also tried editing the module.filename
.
How about creating a temporary file in the same directory!? I'll try that now..
To try out SpacePen
rendering support, open your preview and load up a JavaScript or CoffeeScript file that exports (module.exports =
) a class that extends View
(class MyClass extends View
).
Preview
will load the file and create an instance to preview and render over top of the previewer.
Live updating still applies! 😉
No I hadn't yet.. i still can't get it to trigger :P I opened up options-view.coffee
and Toggled Preview
but it was simply the coffeescript transpilation
Oh sorry, I forgot to say in the above instructions:
To change your Preview renderer, right-click and Select Preview Renderer
(or preview:select-renderer
command in command pallete) and scroll down to SpacePen
.