Add external command support

This commit is contained in:
Thomas Reynolds 2014-07-11 14:24:22 -07:00
parent bb0b4e7992
commit feef2bf71c
42 changed files with 484 additions and 8 deletions

View file

@ -0,0 +1,5 @@
activate :external_pipeline,
name: :ember,
command: "cd test-app/ && ember #{build? ? :build : :serve} --environment #{config[:environment]}",
source: "test-app/dist",
latency: 2

View file

@ -0,0 +1,3 @@
{
"directory": "vendor"
}

View file

@ -0,0 +1,17 @@
# See http://help.github.com/ignore-files/ for more about ignoring files.
# compiled output
/dist
/tmp
# dependencies
/node_modules
/vendor/*
# misc
/.sass-cache
/connect.lock
/coverage/*
/libpeerconnection.log
npm-debug.log
testem.log

View file

@ -0,0 +1,32 @@
{
"predef": {
"document": true,
"window": true,
"TestAppENV": true
},
"browser" : true,
"boss" : true,
"curly": true,
"debug": false,
"devel": true,
"eqeqeq": true,
"evil": true,
"forin": false,
"immed": false,
"laxbreak": false,
"newcap": true,
"noarg": true,
"noempty": false,
"nonew": false,
"nomen": false,
"onevar": false,
"plusplus": false,
"regexp": false,
"undef": true,
"sub": true,
"strict": false,
"white": false,
"eqnull": true,
"esnext": true,
"unused": true
}

View file

@ -0,0 +1,20 @@
/* global require, module */
var EmberApp = require('ember-cli/lib/broccoli/ember-app');
var app = new EmberApp();
// Use `app.import` to add additional libraries to the generated
// output files.
//
// If you need to use different assets in different
// environments, specify an object as the first parameter. That
// object's keys should be the environment name and the values
// should be the asset to use in that environment.
//
// If the library that you are including contains AMD or ES6
// modules that you would like to import into your application
// please specify an object with the list of modules as keys
// along with the exports of each module as its value.
module.exports = app.toTree();

View file

@ -0,0 +1,25 @@
# Test-app
This README outlines the details of collaborating on this Ember application.
## Installation
* `git clone` this repository
* `npm install`
* `bower install`
## Running
* `ember server`
* Visit your app at http://localhost:4200.
## Running Tests
* `ember test`
* `ember test --server`
## Building
* `ember build`
For more information on using ember-cli, visit [http://iamstef.net/ember-cli/](http://iamstef.net/ember-cli/).

View file

@ -0,0 +1,14 @@
import Ember from 'ember';
import Resolver from 'ember/resolver';
import loadInitializers from 'ember/load-initializers';
Ember.MODEL_FACTORY_INJECTIONS = true;
var App = Ember.Application.extend({
modulePrefix: 'test-app', // TODO: loaded via config
Resolver: Resolver
});
loadInitializers(App, 'test-app');
export default App;

View file

@ -0,0 +1,26 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>TestApp</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
{{BASE_TAG}}
<link rel="stylesheet" href="assets/vendor.css">
<link rel="stylesheet" href="assets/test-app.css">
</head>
<body>
<script>
window.TestAppENV = {{ENV}};
window.EmberENV = window.TestAppENV.EmberENV;
</script>
<script src="assets/vendor.js"></script>
<script src="assets/test-app.js"></script>
<script>
window.TestApp = require('test-app/app')['default'].create(TestAppENV.APP);
</script>
</body>
</html>

View file

@ -0,0 +1,10 @@
import Ember from 'ember';
var Router = Ember.Router.extend({
location: TestAppENV.locationType
});
Router.map(function() {
});
export default Router;

View file

@ -0,0 +1,3 @@
html, body {
margin: 20px;
}

View file

@ -0,0 +1,3 @@
<h2 id='title'>Welcome to Ember.js</h2>
{{outlet}}

View file

@ -0,0 +1,16 @@
{
"name": "test-app",
"dependencies": {
"handlebars": "~1.3.0",
"jquery": "^1.11.1",
"qunit": "~1.12.0",
"ember-qunit": "~0.1.5",
"ember": "1.5.1",
"ember-resolver": "~0.1.1",
"loader": "stefanpenner/loader.js#1.0.0",
"ember-cli-shims": "stefanpenner/ember-cli-shims#0.0.2",
"ember-load-initializers": "stefanpenner/ember-load-initializers#0.0.2",
"ember-qunit-notifications": "^0.0.3",
"ember-cli-test-loader": "rjackson/ember-cli-test-loader#0.0.2"
}
}

View file

@ -0,0 +1,38 @@
/* jshint node: true */
module.exports = function(environment) {
var ENV = {
environment: environment,
baseURL: '/',
locationType: 'auto',
EmberENV: {
FEATURES: {
// Here you can enable experimental features on an ember canary build
// e.g. 'with-controller': true
}
},
APP: {
// Here you can pass flags/options to your application instance
// when it is created
}
};
if (environment === 'development') {
// LOG_MODULE_RESOLVER is needed for pre-1.6.0
ENV.LOG_MODULE_RESOLVER = true;
ENV.APP.LOG_RESOLVER = true;
ENV.APP.LOG_ACTIVE_GENERATION = true;
ENV.APP.LOG_MODULE_RESOLVER = true;
// ENV.APP.LOG_TRANSITIONS = true;
// ENV.APP.LOG_TRANSITIONS_INTERNAL = true;
ENV.APP.LOG_VIEW_LOOKUPS = true;
}
if (environment === 'production') {
}
return ENV;
};

View file

@ -0,0 +1,31 @@
{
"name": "test-app",
"version": "0.0.0",
"private": true,
"directories": {
"doc": "doc",
"test": "test"
},
"scripts": {
"start": "ember server",
"build": "ember build",
"test": "ember test"
},
"repository": "https://github.com/stefanpenner/ember-cli",
"engines": {
"node": ">= 0.10.0"
},
"author": "",
"license": "MIT",
"devDependencies": {
"ember-cli": "0.0.39",
"originate": "0.1.5",
"broccoli-ember-hbs-template-compiler": "^1.5.0",
"express": "^4.1.1",
"body-parser": "^1.2.0",
"glob": "^3.2.9",
"ember-cli-ic-ajax": "0.1.1",
"ember-cli-ember-data": "0.1.0",
"broccoli-asset-rev": "0.0.11"
}
}

View file

@ -0,0 +1,6 @@
{
"framework": "qunit",
"test_page": "tests/index.html",
"launch_in_ci": ["PhantomJS"],
"launch_in_dev": ["PhantomJS", "Chrome"]
}

View file

@ -0,0 +1,73 @@
{
"predef": [
"document",
"window",
"location",
"setTimeout",
"$",
"QUnit",
"define",
"console",
"equal",
"notEqual",
"notStrictEqual",
"test",
"asyncTest",
"testBoth",
"testWithDefault",
"raises",
"throws",
"deepEqual",
"start",
"stop",
"ok",
"strictEqual",
"module",
"moduleFor",
"moduleForComponent",
"moduleForModel",
"process",
"expect",
"visit",
"exists",
"fillIn",
"click",
"keyEvent",
"find",
"findWithAssert",
"wait",
"DS",
"keyEvent",
"isolatedContainer",
"startApp",
"andThen",
"currentURL",
"currentPath",
"currentRouteName"
],
"node": false,
"browser": false,
"boss": true,
"curly": false,
"debug": false,
"devel": false,
"eqeqeq": true,
"evil": true,
"forin": false,
"immed": false,
"laxbreak": false,
"newcap": true,
"noarg": true,
"noempty": false,
"nonew": false,
"nomen": false,
"onevar": false,
"plusplus": false,
"regexp": false,
"undef": true,
"sub": true,
"strict": false,
"white": false,
"eqnull": true,
"esnext": true
}

View file

@ -0,0 +1,9 @@
import Resolver from 'ember/resolver';
var resolver = Resolver.create();
resolver.namespace = {
modulePrefix: 'test-app'
};
export default resolver;

View file

@ -0,0 +1,30 @@
/* global require */
var Application = require('test-app/app')['default'];
var Router = require('test-app/router')['default'];
import Ember from 'ember';
export default function startApp(attrs) {
var App;
var attributes = Ember.merge({
// useful Test defaults
rootElement: '#ember-testing',
LOG_ACTIVE_GENERATION:false,
LOG_VIEW_LOOKUPS: false
}, attrs); // but you can override;
Router.reopen({
location: 'none'
});
Ember.run(function(){
App = Application.create(attributes);
App.setupForTesting();
App.injectTestHelpers();
});
App.reset(); // this shouldn't be needed, i want to be able to "start an app at a specific URL"
return App;
}

View file

@ -0,0 +1,50 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>TestApp Tests</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
{{BASE_TAG}}
<link rel="stylesheet" href="assets/vendor.css">
<link rel="stylesheet" href="assets/test-app.css">
<link rel="stylesheet" href="assets/qunit.css">
<style>
#ember-testing-container {
position: absolute;
background: white;
bottom: 0;
right: 0;
width: 640px;
height: 384px;
overflow: auto;
z-index: 9999;
border: 1px solid #ccc;
}
#ember-testing {
zoom: 50%;
}
</style>
</head>
<body>
<div id="qunit"></div>
<div id="qunit-fixture"></div>
<script>
window.TestAppENV = {{ENV}};
window.EmberENV = window.TestAppENV.EmberENV;
</script>
<script src="assets/qunit.js"></script>
<script src="assets/qunit-notifications.js"></script>
<script src="assets/vendor.js"></script>
<script src="assets/test-app.js"></script>
<script src="testem.js"></script>
<script>
require('test-app/tests/test-helper');
</script>
<script src="assets/test-loader.js"></script>
</body>
</html>

View file

@ -0,0 +1,6 @@
import resolver from './helpers/resolver';
import { setResolver } from 'ember-qunit';
setResolver(resolver);
document.write('<div id="ember-testing-container"><div id="ember-testing"></div></div>');

View file

@ -1 +1 @@
title: Data Default
title: Data Default

View file

@ -1 +1 @@
title: Opposite 2
title: Opposite 2

View file

@ -1 +1 @@
title: Opposite 1
title: Opposite 1

View file

@ -1,5 +1,10 @@
Default: <%= data.data.title %>
Data 1: <%= data.data1.title %>
Data 2: <%= data.data2.title %>
<<<<<<< HEAD
Override in Two: <%= data.two.title %>
Override in One: <%= data.one.title %>
Override in One: <%= data.one.title %>
=======
Override in One: <%= data.one.title %>
Override in Two: <%= data.two.title %>
>>>>>>> Add external command support

View file

@ -7,7 +7,7 @@ module Middleman
attr_reader :app
# Whitelist methods that can reach out.
def_delegators :@app, :config, :logger, :use, :map, :mime_type, :data, :files, :root
def_delegators :@app, :config, :logger, :use, :map, :mime_type, :data, :files, :root, :build?, :server?, :environment?
def_delegator :"@app.extensions", :activate
def initialize(app, template_context_class)

View file

@ -128,3 +128,8 @@ Middleman::Extensions.register :automatic_alt_tags do
require 'middleman-core/extensions/automatic_alt_tags'
Middleman::Extensions::AutomaticAltTags
end
Middleman::Extensions.register :external_pipeline do
require 'middleman-core/extensions/external_pipeline'
Middleman::Extensions::ExternalPipeline
end

View file

@ -7,8 +7,6 @@ class Middleman::CoreExtensions::Internationalization < ::Middleman::Extension
option :mount_at_root, nil, 'Mount a specific language at the root of the site'
option :data, 'locales', 'The directory holding your locale configurations'
def_delegator :@app, :logger
def after_configuration
# See https://github.com/svenfuchs/i18n/wiki/Fallbacks
unless options[:no_fallbacks]

View file

@ -67,6 +67,8 @@ module Middleman
extend Forwardable
include Contracts
def_delegator :@app, :logger
# @!attribute supports_multiple_instances
# @!scope class
# @return [Boolean] whether or not an extension can be activated multiple times, generating multiple instances of the extension.

View file

@ -0,0 +1,49 @@
class Middleman::Extensions::ExternalPipeline < ::Middleman::Extension
self.supports_multiple_instances = true
option :name, nil, 'The name of the pipeline'
option :command, nil, 'The command to initialize'
option :source, nil, 'Path to merge into sitemap'
option :latency, 0.25, 'Latency between refreshes of source'
def initialize(app, config={}, &block)
super
if options[:name].nil?
throw "Name is required"
end
if options[:command].nil?
throw "Command is required"
end
if options[:source].nil?
throw "Source is required"
end
require 'thread'
app.files.watch :source,
path: File.expand_path(options[:source], app.root),
latency: options[:latency]
end
def after_configuration
if app.build?
logger.info "== Executing: `#{options[:command]}`"
watch_command!
else
logger.debug "== Executing: `#{options[:command]}`"
::Thread.new { watch_command! }
end
end
def watch_command!
::IO.popen(options[:command], 'r') do |pipe|
while buf = pipe.gets
without_newline = buf.sub(/\n$/,'')
logger.info "== External: #{without_newline}" if without_newline.length > 0
end
end
end
end

View file

@ -176,7 +176,7 @@ module Middleman
end
end
Contract IsA['Middleman::Application'], Or[Symbol, String], Hash => Maybe[IsA['Middleman::SourceFile']]
Contract IsA['Middleman::Application'], String, Hash => Maybe[IsA['Middleman::SourceFile']]
def self.uncached_resolve_template(app, relative_path, options)
# By default, any engine will do
preferred_engines = []