Browse Source

Merge pull request #92 from transloadit/new-build

New build, npm-run-all and yo-yo rendering experiments
Artur Paikin 9 years ago
parent
commit
5eb35b8c34

+ 3 - 3
CHANGELOG.md

@@ -58,12 +58,12 @@ Theme: The aim low release
 
 Released: June 03, 2016
 
-- [ ] build: minification of the bundle (@arturi)
+- [x] build: minification of the bundle (@arturi)
 - [ ] build: supply pre-built bundle in npm (@arturi)
-- [ ] build: switch to https://www.npmjs.com/package/npm-run-all instead of parallelshell (@kvz)
+- [x] build: switch to https://www.npmjs.com/package/npm-run-all instead of parallelshell (@kvz)
 - [ ] drive: Make sure uppy-server does not explode on special file types: https://dl.dropboxusercontent.com/s/d4dbxitjt8clo50/2016-05-06%20at%2022.41.png (@hedgerh)
 - [ ] modal: accessibility. focus on the first input field / button in tab panel (@arturi)
-- [ ] progressdrawer: figure out crazy rerendering of previews by yoyo (@arturi)
+- [ ] progressdrawer: figure out crazy rerendering of previews by yoyo/bel: https://github.com/shama/bel/issues/26 (@arturi)
 - [ ] progressdrawer: improve styles, add preview icons for all (@arturi)
 - [ ] server: Start implementing the `SERVER-PLAN.md` so that Google Drive files are actually uploaded to the endpoint (@hedgerh)
 - [ ] test: Get IE4 on windows 3.11 to run Uppy and see it fall back to regular form upload (`api2.transloadit.com`) (@arturi)

+ 26 - 0
bin/build-css.js

@@ -0,0 +1,26 @@
+var sass = require('node-sass')
+var postcss = require('postcss')
+var autoprefixer = require('autoprefixer')
+var cssnano = require('cssnano')
+var chalk = require('chalk')
+var fs = require('fs')
+var mkdirp = require('mkdirp')
+
+mkdirp.sync('./dist/')
+
+function handleErr (err) {
+  console.error(chalk.red('✗ Error:'), chalk.red(err.message))
+}
+
+sass.render({file: './src/scss/uppy.scss'}, function (err, sassResult) {
+  if (err) handleErr(err)
+  postcss([ cssnano, autoprefixer ])
+    .process(sassResult.css)
+    .then(function (postCSSResult) {
+      postCSSResult.warnings().forEach(function (warn) {
+        console.warn(warn.toString())
+      })
+      fs.writeFileSync('./dist/uppy.min.css', postCSSResult.css)
+      console.info(chalk.green('✓ Built Uppy CSS:'), chalk.magenta('uppy.min.css'))
+    })
+})

+ 59 - 0
bin/build-js.js

@@ -0,0 +1,59 @@
+var path = require('path')
+var fs = require('fs')
+var babelify = require('babelify')
+var chalk = require('chalk')
+var mkdirp = require('mkdirp')
+var glob = require('glob')
+var browserify = require('browserify')
+// var rollupify = require('rollupify')
+
+mkdirp.sync('./dist/')
+
+function handleErr (err) {
+  console.error(chalk.red('✗ Error:'), chalk.red(err.message))
+}
+
+function buildUppyBundle () {
+  browserify('./src/index.js', { debug: true, standalone: 'Uppy' })
+    .plugin('minifyify', {
+      map: 'uppy.js.map',
+      output: './dist/uppy.js.map'
+    })
+    // .transform(rollupify)
+    .transform(babelify)
+    .on('error', handleErr)
+    .bundle()
+    // .pipe(exorcist('./dist/uppy.js.map'))
+    .pipe(fs.createWriteStream('./dist/uppy.min.js', 'utf8'))
+    .on('error', handleErr)
+    .on('finish', function () {
+      console.info(chalk.green('✓ Built Uppy bundle:'), chalk.magenta('uppy.min.js'))
+    })
+}
+
+function buildUppyLocales () {
+  mkdirp.sync('./dist/locales')
+  glob('./src/locales/*.js', function (err, files) {
+    if (err) console.log(err)
+    files.forEach(function (file) {
+      var fileName = path.basename(file, '.js')
+      browserify(file, { debug: true })
+        .plugin('minifyify', {
+          map: fileName + '.min.js.map',
+          output: './dist/locales/' + fileName + '.min.js.map'
+        })
+        // .transform(rollupify)
+        .transform(babelify)
+        .on('error', handleErr)
+        .bundle()
+        .pipe(fs.createWriteStream('./dist/locales/' + fileName + '.min.js', 'utf8'))
+        .on('error', handleErr)
+        .on('finish', function () {
+          console.info(chalk.green('✓ Built Uppy locale:'), chalk.magenta(fileName + '.min.js'))
+        })
+    })
+  })
+}
+
+buildUppyBundle()
+buildUppyLocales()

+ 24 - 0
example/index.html

@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>uppy</title>
+  </head>
+  <body>
+    <h1>Uppy is here</h1>
+    <button id="uppyModalOpener">Open Modal</button>
+    <link href="../dist/uppy.min.css" rel="stylesheet">
+    <script src="../dist/uppy.min.js"></script>
+    <script src="../dist/locales/ru_RU.min.js"></script>
+    <script>
+      var uppy = new Uppy.Core({locales: Uppy.locales.ru_RU, debug: true})
+        .use(Uppy.plugins.Modal, {trigger: '#uppyModalOpener'})
+        .use(Uppy.plugins.Dummy, {target: Uppy.plugins.Modal})
+        .run();
+    </script>
+
+    <script>
+      document.querySelector('#uppyModalOpener').click()
+    </script>
+  </body>
+</html>

+ 23 - 15
package.json

@@ -4,13 +4,13 @@
   "description": "Almost as cute as a Puppy :dog:",
   "main": "src/index.js",
   "scripts": {
+    "build:bundle": "node ./bin/build-js.js",
+    "build:css": "node ./bin/build-css.js",
+    "size": "echo 'JS Size:' && cat ./dist/uppy.min.js | gzip | wc -c && echo 'CSS Size:' && cat ./dist/uppy.min.css | gzip | wc -c",
     "build:bundle:fullpath": "env OUT=uppy-fp.js ./bin/build-bundle --full-paths",
-    "build:bundle:min": "./bin/build-bundle",
-    "build:bundle": "./bin/build-bundle && ./bin/build-bundle-locales",
-    "build:css": "bin/build-css",
-    "build:js": "npm run build:lib && npm run build:bundle && npm run build:bundle:min",
+    "build:js": "npm-run-all --parallel build:bundle build:lib",
     "build:lib": "babel --version && babel src -d lib",
-    "build": "npm run build:lib && npm run build:bundle && npm run build:bundle:min && npm run build:css",
+    "build": "npm-run-all --parallel build:js build:css",
     "clean": "rm -rf lib && rm -rf dist",
     "docs": "cd website && node node_modules/documentation/bin/documentation.js readme ../src/index.js --readme-file=src/api/docs.md --section 'Uppy Core & Plugins' -q --github -c doc-order.json",
     "install": "npm run web:install",
@@ -28,9 +28,9 @@
     "test": "npm run lint && npm run test:unit",
     "travis:deletecache": "travis cache --delete",
     "watch:css": "nodemon --watch src --ext scss -x 'npm run build:css && node website/update.js'",
-    "watch:fast": "parallelshell 'npm run watch:css' 'npm run web:preview'",
+    "watch:fast": "npm-run-all --parallel watch:css web:preview",
     "watch:js": "nodemon --watch src --ext js -x 'npm run build:bundle && node website/update.js'",
-    "watch": "parallelshell 'npm run watch:js' 'npm run watch:css' && node website/update.js",
+    "watch": "npm-run-all --parallel watch:js watch:css && node website/update.js",
     "web:build": "cd website && node update.js && ./node_modules/.bin/hexo generate --silent && node build-examples.js",
     "web:clean": "cd website && ./node_modules/.bin/hexo clean",
     "web:deploy": "npm run web:install && npm run web:disc && npm run docs && npm run web:build && ./bin/web-deploy",
@@ -38,7 +38,8 @@
     "web:install": "cd website && npm install",
     "web:preview": "cd website && parallelshell 'node build-examples.js watch' './node_modules/.bin/hexo server'",
     "web:update:frontpage:code:sample": "cd website && ./node_modules/.bin/hexo generate && cp -f public/frontpage-code-sample.html ./themes/uppy/layout/partials/frontpage-code-sample.html",
-    "web": "npm run web:clean && npm run web:build"
+    "web": "npm run web:clean && npm run web:build",
+    "prepublish": ""
   },
   "repository": {
     "type": "git",
@@ -51,21 +52,23 @@
   },
   "homepage": "https://github.com/transloadit/uppy#readme",
   "devDependencies": {
-    "babel-cli": "6.6.5",
-    "babel-core": "6.7.4",
+    "autoprefixer": "6.3.6",
+    "babel-cli": "6.9.0",
+    "babel-core": "6.7.7",
     "babel-eslint": "6.0.2",
     "babel-loader": "6.2.4",
     "babel-plugin-es6-promise": "1.0.0",
     "babel-plugin-transform-object-assign": "6.5.0",
     "babel-plugin-transform-proto-to-assign": "6.8.0",
     "babel-polyfill": "6.7.4",
-    "babel-preset-es2015": "6.6.0",
+    "babel-preset-es2015": "6.9.0",
     "babel-preset-es2015-loose": "7.0.0",
     "babel-register": "6.7.2",
     "babelify": "7.2.0",
     "browser-sync": "2.10.0",
     "browserify": "12.0.1",
     "chalk": "1.1.1",
+    "cssnano": "3.6.2",
     "disc": "1.3.2",
     "es6-promise": "3.1.2",
     "eslint": "2.7.0",
@@ -73,16 +76,21 @@
     "eslint-plugin-promise": "1.1.0",
     "eslint-plugin-standard": "1.3.2",
     "fakefile": "0.0.5",
+    "glob": "7.0.3",
     "isomorphic-fetch": "2.2.1",
+    "minifyify": "7.3.3",
+    "mkdirp": "0.5.1",
     "multi-glob": "1.0.1",
-    "nock": "^8.0.0",
-    "node-fetch": "^1.5.0",
+    "nock": "8.0.0",
+    "node-fetch": "1.5.0",
     "node-notifier": "4.4.0",
     "node-sass": "3.4.2",
     "nodemon": "1.8.1",
+    "npm-run-all": "2.1.1",
     "parallelshell": "2.0.0",
+    "postcss": "5.0.21",
     "selenium-webdriver": "2.52.0",
-    "tap-spec": "^4.1.1",
+    "tap-spec": "4.1.1",
     "tape": "4.4.0",
     "uppy-server": "0.0.7",
     "watchify": "3.6.1"
@@ -91,6 +99,6 @@
     "drag-drop": "2.11.0",
     "tus-js-client": "1.1.3",
     "whatwg-fetch": "1.0.0",
-    "yo-yo": "1.1.1"
+    "yo-yo": "1.2.0"
   }
 }

+ 3 - 3
src/core/Core.js

@@ -244,7 +244,7 @@ export default class Core {
   use (Plugin, opts) {
     // Instantiate
     const plugin = new Plugin(this, opts)
-    const pluginName = Utils.getFnName(plugin.constructor)
+    const pluginName = plugin.id
     this.plugins[plugin.type] = this.plugins[plugin.type] || []
 
     if (!pluginName) {
@@ -258,7 +258,7 @@ export default class Core {
     let existsPluginAlready = this.getPlugin(pluginName)
     if (existsPluginAlready) {
       let msg = `Already found a plugin named '${existsPluginAlready.name}'.
-        Tried to use: '${plugin.constructor.name}'.
+        Tried to use: '${pluginName}'.
         Uppy is currently limited to running one of every plugin.
         Share your use case with us over at
         https://github.com/transloadit/uppy/issues/
@@ -279,7 +279,7 @@ export default class Core {
   getPlugin (name) {
     let foundPlugin = false
     this.iteratePlugins((plugin) => {
-      const pluginName = Utils.getFnName(plugin.constructor)
+      const pluginName = plugin.id
       if (pluginName === name) {
         foundPlugin = plugin
         return false

+ 9 - 5
src/plugins/Dummy.js

@@ -17,13 +17,17 @@ export default class Dummy extends Plugin {
 
     // merge default options with the ones set by user
     this.opts = Object.assign({}, defaultOptions, opts)
+
+    this.strange = yo`<h1>this is strange 1</h1>`
   }
 
-  render (state) {
+  render () {
+    const bla = yo`<h1>this is strange 2</h1>`
     return yo`
       <div class="wow-this-works">
         <input type="text" value="hello">
-        I am a dummy plugin, look at me, I was rendered in a modal! That’s crazy, I know.
+        ${this.strange}
+        ${bla}
       </div>
     `
   }
@@ -33,8 +37,8 @@ export default class Dummy extends Plugin {
     firstInput.focus()
   }
 
-  install (state) {
-    this.el = this.render(this.core.state)
-    this.target = this.getTarget(this.opts.target, this, this.el, this.render.bind(this))
+  install () {
+    this.el = this.render()
+    this.target = this.getTarget(this.opts.target, this, this.el, this.render)
   }
 }

+ 74 - 0
src/plugins/IndependentDummy.js

@@ -0,0 +1,74 @@
+import Utils from '../core/Utils'
+import yo from 'yo-yo'
+
+/**
+ * Independent Dummy
+ *
+ */
+export default class Dummy {
+  constructor (core, opts) {
+    // super(core, opts)
+    this.type = 'acquirer'
+    this.id = 'Dummy'
+    this.title = 'Dummy'
+    this.core = core
+
+    // set default options
+    const defaultOptions = {}
+
+    this.strange = yo`<h1>this is strange 1</h1>`
+
+    // merge default options with the ones set by user
+    this.opts = Object.assign({}, defaultOptions, opts)
+  }
+
+  getTarget (target, caller, el, render) {
+    const callerPluginName = Utils.getFnName(caller.constructor)
+
+    if (typeof target === 'string') {
+      this.core.log(`Installing ${callerPluginName} to ${target}`)
+
+      // clear everything inside the target selector
+      // if (replaceTargetContent) {
+      //   document.querySelector(target).innerHTML = ''
+      // }
+      document.querySelector(target).appendChild(el)
+
+      return target
+    } else {
+      const targetPluginName = Utils.getFnName(target)
+      this.core.log(`Installing ${callerPluginName} to ${targetPluginName}`)
+      let targetPlugin = this.core.getPlugin(targetPluginName)
+      let selectorTarget = targetPlugin.addTarget(caller, render)
+
+      return selectorTarget
+    }
+  }
+
+  update () {
+
+  }
+
+  render () {
+    const bla = yo`<h2>this is strange 2</h2>`
+    return yo`
+      <div class="wow-this-works">
+        <input type="text" value="hello">
+        I am a dummy plugin, look at me, I was rendered in a modal! That’s crazy, I know.
+        ${this.strange}
+        ${bla}
+      </div>
+    `
+  }
+
+  focus () {
+    const firstInput = document.querySelector(`${this.target} *:input[type!=hidden]:first`)
+    firstInput.focus()
+  }
+
+  install () {
+    this.el = this.render()
+    document.body.appendChild(this.el)
+    this.target = this.getTarget(this.opts.target, this, this.el, this.render.bind(this))
+  }
+}

+ 1 - 1
src/plugins/Modal.js

@@ -32,7 +32,7 @@ export default class Modal extends Plugin {
 
   addTarget (callerPlugin, render) {
     const callerPluginId = callerPlugin.constructor.name
-    const callerPluginName = callerPlugin.name || callerPluginId
+    const callerPluginName = callerPlugin.title || callerPluginId
     const callerPluginIcon = callerPlugin.icon || this.opts.defaultTabIcon
     const callerPluginType = callerPlugin.type
 

+ 4 - 3
src/plugins/Plugin.js

@@ -1,5 +1,4 @@
 import yo from 'yo-yo'
-import Utils from '../core/Utils'
 
 /**
  * Boilerplate that all Plugins share - and should not be used
@@ -37,7 +36,7 @@ export default class Plugin {
    *
    */
   getTarget (target, caller, el, render) {
-    const callerPluginName = Utils.getFnName(caller.constructor)
+    const callerPluginName = caller.id
 
     if (typeof target === 'string') {
       this.core.log(`Installing ${callerPluginName} to ${target}`)
@@ -50,7 +49,9 @@ export default class Plugin {
 
       return target
     } else {
-      const targetPluginName = Utils.getFnName(target)
+      // TODO: is this the way to roll just to get the plugin name?
+      const Target = target
+      const targetPluginName = new Target().id
       this.core.log(`Installing ${callerPluginName} to ${targetPluginName}`)
       let targetPlugin = this.core.getPlugin(targetPluginName)
       let selectorTarget = targetPlugin.addTarget(caller, render)

+ 7 - 3
test/acceptance/dummy.spec.js

@@ -1,16 +1,20 @@
 var test = require('tape')
-var Driver = require('./Browser')
+var webdriver = require('selenium-webdriver')
+
+var driver = new webdriver
+  .Builder()
+  .forBrowser('firefox')
+  .build()
 
 test('open a page, create a variable and get its value', function (t) {
   t.plan(1)
 
-  var driver = Driver.setDriver()
-
   driver.get('http://ya.ru')
   driver.executeScript('window.a = "blabla";')
   driver.sleep(2000)
   driver.executeScript('return a').then(function (val) {
     console.log(val)
+    t.equal(val, 'blabla')
   })
   driver.sleep(5000)
   driver.quit()

+ 27 - 0
website/src/uppy.ejs

@@ -0,0 +1,27 @@
+---
+layout: false
+title: Uppy
+permalink: uppy/
+---
+
+<!doctype html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>uppy</title>
+  </head>
+  <body>
+    <h1>Uppy is here</h1>
+    <button id="uppyModalOpener">Open Modal</button>
+    <link href="uppy.min.css" rel="stylesheet">
+    <script src="uppy.min.js"></script>
+    <script src="locales/ru_RU.min.js"></script>
+    <script>
+      var uppy = new Uppy.Core({locales: Uppy.locales.ru_RU, debug: true})
+      // uppy.use(Uppy.plugins.DragDrop, {target: 'body'});
+        .use(Uppy.plugins.Modal, {trigger: '#uppyModalOpener'})
+        .use(Uppy.plugins.Dummy, {target: Uppy.plugins.Modal})
+        .run();
+    </script>
+  </body>
+</html>