Glavin001/atom-preview

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 {}.

Blocked by #22 and #36.

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
}

Gorgeous! I am very excited for this one. Will be extremely helpful for building packages! :D

image

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 requires no longer work.

image

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! 😉

@ddavison have you had a chance to try the SpacePen preview? :)

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.