You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@weex.apache.org by so...@apache.org on 2017/04/13 02:31:56 UTC

[02/23] incubator-weex git commit: * [html5] change viewport adapter, add unit tests for new adapting methods.

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/38f1a971/html5/render/vue/utils/style.js
----------------------------------------------------------------------
diff --git a/html5/render/vue/utils/style.js b/html5/render/vue/utils/style.js
index c7b5fe6..0dc1879 100644
--- a/html5/render/vue/utils/style.js
+++ b/html5/render/vue/utils/style.js
@@ -1,5 +1,16 @@
 // @flow
 
+import { getViewportInfo } from '../env/viewport'
+import addPrefix from 'inline-style-prefixer/static/index'
+
+const noUnitsNumberKeys = [
+  'flex',
+  'opacity',
+  'zIndex',
+  'fontWeight',
+  'lines'
+]
+
 /**
  * remove comments from a cssText.
  */
@@ -19,3 +30,102 @@ export function supportSticky (): boolean {
   support = elementStyle.position.indexOf('sticky') !== -1
   return support
 }
+
+const regPercentage = /^[+-]?\d+(\.\d+)?%$/
+export function isPercentage (val: string) {
+  return regPercentage.test(val)
+}
+
+const regUnitsNum = /^([+-]?\d+(?:\.\d+)?)([p,w]x)?$/ // support units: px, wx.
+export function normalizeUnitsNum (val: string): string {
+  const match = val.match(regUnitsNum)
+  if (!match) { return '' }
+  let unit = 'px' // px by default.
+  if (match[2]) {
+    unit = match[2]
+  }
+  return parseScale(parseFloat(match[1]), unit)
+}
+
+function parseScale (val: number, unit: string): string {
+  const { scale, dpr } = getViewportInfo()
+  const unitScaleMap = {
+    px: scale,
+    wx: scale * dpr
+  }
+  return val * unitScaleMap[unit] + 'px'
+}
+
+export function normalizeString (styleKey: string, styleVal: string): string {
+  if (isPercentage(styleVal)) {
+    return styleVal
+  }
+
+  // 1. test if is a regular scale css. e.g. `width: 100px;`
+  const unitsNum = normalizeUnitsNum(styleVal)
+  if (unitsNum) { return unitsNum }
+
+  // 2. test if is a translate scale. e.g. `transform: translate2d(1px, 2px);`
+  const regTranslateString = /translate[^(]*\([\d ,.pwx]+\)/i // unit support: wx, px.
+  if (styleKey.match(/transform/i) && regTranslateString.test(styleVal)) {
+    const val = styleVal.replace(regTranslateString, function (translate) {
+      const reg = /([+-]?\d+(?:\.\d+)?)([p,w]x)?(?![dD])/g
+      return translate.replace(reg, function (m, $1, $2) {
+        const unit = $2 || 'px'
+        return parseScale($1, unit)
+      })
+    })
+    return val
+  }
+
+  // 3. test if is a border style. e.g. `border: 1px solid red;`
+  const regBorderKey = /^border(?:-(?:top|bottom|left|right))?$/
+  const regBorderVal = /^([+-]?\d+(?:\.\d+)?)([p ,w]x)?\s+/
+  if (regBorderKey.test(styleKey) && regBorderVal.test(styleVal)) {
+    const reg = /^([+-]?\d+(?:\.\d+)?)([p,w]x)?/
+    const val = styleVal.replace(reg, function (m, $1, $2) {
+      const unit = $2 || 'px'
+      return parseScale($1, unit)
+    })
+    return val
+  }
+
+  // otherwise
+  return styleVal
+}
+
+export function autoPrefix (style: {}): {} {
+  return addPrefix(style)
+}
+
+export function normalizeNumber (styleKey: string, styleVal: number): string {
+  const { scale } = getViewportInfo()
+  return styleVal * scale + 'px'
+}
+
+/**
+ * normalize style to adapte to current viewport by multiply current scale.
+ * @param  {object} style: should be camelCase.
+ */
+export function normalizeStyle (style: {}) {
+  const res = {}
+  for (const key in style) {
+    const val = style[key]
+    if (noUnitsNumberKeys.indexOf(key) > -1) {
+      res[key] = val
+      continue
+    }
+    switch (typeof val) {
+      case 'string':
+        res[key] = normalizeString(key, val)
+        break
+      case 'number':
+        res[key] = normalizeNumber(key, val)
+        break
+      default:
+        res[key] = val
+        break
+    }
+  }
+  return res
+}

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/38f1a971/html5/test/render/vue/components/image.js
----------------------------------------------------------------------
diff --git a/html5/test/render/vue/components/image.js b/html5/test/render/vue/components/image.js
index 241696a..cfe10e3 100644
--- a/html5/test/render/vue/components/image.js
+++ b/html5/test/render/vue/components/image.js
@@ -41,11 +41,11 @@ init('<image> component', (Vue, helper) => {
 
   it('<image> resize="stretch"', () => {
     const vm = compile(`<image resize="stretch"></image>`)
-    expect(vm.$el.style.backgroundSize).to.be.equal('100%')
+    expect(vm.$el.style.backgroundSize).to.contain('100%')
   })
 
   it('<image> unknown resize', () => {
     const vm = compile(`<image resize="unknown"></image>`)
-    expect(vm.$el.style.backgroundSize).to.be.equal('100%')
+    expect(vm.$el.style.backgroundSize).to.be.contain('100%')
   })
 })

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/38f1a971/html5/test/render/vue/core/scope-style-map.js
----------------------------------------------------------------------
diff --git a/html5/test/render/vue/core/scope-style-map.js b/html5/test/render/vue/core/scope-style-map.js
new file mode 100644
index 0000000..2ead7e8
--- /dev/null
+++ b/html5/test/render/vue/core/scope-style-map.js
@@ -0,0 +1,16 @@
+import {
+  getHeadStyleMap
+} from '../../../../render/vue/core/style'
+import '../data/head-css'
+import headMap from '../data/head-map'
+
+describe('style map', (Vue, helper) => {
+  it('should get head style map.', () => {
+    const styleMap = getHeadStyleMap()
+    for (const key in headMap) {
+      const expected = headMap[key]
+      const result = styleMap[key]
+      expect(expected).be.deep.equal(result)
+    }
+  })
+})

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/38f1a971/html5/test/render/vue/core/style.js
----------------------------------------------------------------------
diff --git a/html5/test/render/vue/core/style.js b/html5/test/render/vue/core/style.js
new file mode 100644
index 0000000..4b6b88f
--- /dev/null
+++ b/html5/test/render/vue/core/style.js
@@ -0,0 +1,59 @@
+import { init } from '../helper/runtime'
+import {
+  getScopeIds,
+  getScopeStyle,
+  getComponentStyle,
+  getSize
+} from '../../../../render/vue/core/style'
+import div from '../../../../render/vue/components/div'
+import image from '../../../../render/vue/components/image'
+import { init as initViewport, resetViewport } from '../../../../render/vue/env/viewport'
+
+import scopedStyleBundle from '../data/build/dotvue/scoped-style'
+
+init('core style', (Vue, helper) => {
+  const { compile, utils } = helper
+  const { scale } = initViewport()
+
+  before(() => {
+    helper.register('div', div)
+    helper.register('image', image)
+  })
+
+  it('should get normalized merged styles.', function () {
+    const vm = helper.createVm(scopedStyleBundle)
+    const el = vm.$refs.foo.$el
+    expect(el).to.be.ok
+
+    const expectedMap = {
+      width: 200 * scale + 'px',
+      height: 200 * scale + 'px',
+      backgroundColor: 'red'
+    }
+    const expectedDirection = {
+      WebkitBoxDirection: 'normal',
+      WebkitBoxOrient: 'horizontal',
+      WebkitFlexDirection: 'row',
+      flexDirection: 'row'
+    }
+    const expectedTransform = {
+      WebkitTransform: `translate3d(${100 * scale + 'px'}, ${100 * scale + 'px'}, 0px)`,
+      transform: `translate3d(${100 * scale + 'px'}, ${100 * scale + 'px'}, 0px)`
+    }
+
+   for (const k in expectedMap) {
+    expect(el.style[k]).to.equal(expectedMap[k])
+   }
+   const directionRes = []
+   for (const k in expectedDirection) {
+    directionRes.push(el.style[k] === expectedDirection[k])
+   }
+   expect(directionRes).to.include(true)
+
+   const transformRes = []
+   for (const k in expectedTransform) {
+    transformRes.push(el.style[k] === expectedTransform[k])
+   }
+   expect(transformRes).to.include(true)
+  })
+})

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/38f1a971/html5/test/render/vue/data/build/dotvue/scoped-style.js
----------------------------------------------------------------------
diff --git a/html5/test/render/vue/data/build/dotvue/scoped-style.js b/html5/test/render/vue/data/build/dotvue/scoped-style.js
new file mode 100644
index 0000000..b87ba8a
--- /dev/null
+++ b/html5/test/render/vue/data/build/dotvue/scoped-style.js
@@ -0,0 +1,525 @@
+(function webpackUniversalModuleDefinition(root, factory) {
+	if(typeof exports === 'object' && typeof module === 'object')
+		module.exports = factory();
+	else if(typeof define === 'function' && define.amd)
+		define([], factory);
+	else {
+		var a = factory();
+		for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
+	}
+})(this, function() {
+return /******/ (function(modules) { // webpackBootstrap
+/******/ 	// The module cache
+/******/ 	var installedModules = {};
+
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+
+/******/ 		// Check if module is in cache
+/******/ 		if(installedModules[moduleId])
+/******/ 			return installedModules[moduleId].exports;
+
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = installedModules[moduleId] = {
+/******/ 			exports: {},
+/******/ 			id: moduleId,
+/******/ 			loaded: false
+/******/ 		};
+
+/******/ 		// Execute the module function
+/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+
+/******/ 		// Flag the module as loaded
+/******/ 		module.loaded = true;
+
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+
+
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = modules;
+
+/******/ 	// expose the module cache
+/******/ 	__webpack_require__.c = installedModules;
+
+/******/ 	// __webpack_public_path__
+/******/ 	__webpack_require__.p = "";
+
+/******/ 	// Load entry module and return exports
+/******/ 	return __webpack_require__(0);
+/******/ })
+/************************************************************************/
+/******/ ([
+/* 0 */
+/***/ function(module, exports, __webpack_require__) {
+
+	
+	/* styles */
+	__webpack_require__(1)
+
+	var Component = __webpack_require__(6)(
+	  /* script */
+	  null,
+	  /* template */
+	  __webpack_require__(7),
+	  /* scopeId */
+	  "data-v-0776c87b",
+	  /* cssModules */
+	  null
+	)
+	Component.options.__file = "/Users/rdp/www/rdp/github/MrRaindrop/weex/html5/test/render/vue/data/dotvue/scoped-style.vue"
+	if (Component.esModule && Object.keys(Component.esModule).some(function (key) {return key !== "default" && key !== "__esModule"})) {console.error("named exports are not supported in *.vue files.")}
+	if (Component.options.functional) {console.error("[vue-loader] scoped-style.vue: functional components are not supported with templates, they should use render functions.")}
+
+	/* hot reload */
+	if (false) {(function () {
+	  var hotAPI = require("vue-loader/node_modules/vue-hot-reload-api")
+	  hotAPI.install(require("vue"), false)
+	  if (!hotAPI.compatible) return
+	  module.hot.accept()
+	  if (!module.hot.data) {
+	    hotAPI.createRecord("data-v-0776c87b", Component.options)
+	  } else {
+	    hotAPI.reload("data-v-0776c87b", Component.options)
+	  }
+	})()}
+
+	module.exports = Component.exports
+
+
+/***/ },
+/* 1 */
+/***/ function(module, exports, __webpack_require__) {
+
+	// style-loader: Adds some css to the DOM by adding a <style> tag
+
+	// load the styles
+	var content = __webpack_require__(2);
+	if(typeof content === 'string') content = [[module.id, content, '']];
+	if(content.locals) module.exports = content.locals;
+	// add the styles to the DOM
+	var update = __webpack_require__(4)("27230129", content, false);
+	// Hot Module Replacement
+	if(false) {
+	 // When the styles change, update the <style> tags
+	 if(!content.locals) {
+	   module.hot.accept("!!../../../../../../node_modules/.0.26.1@css-loader/index.js!../../../../../../node_modules/vue-loader/lib/style-compiler/index.js?{\"id\":\"data-v-0776c87b\",\"scoped\":true,\"hasInlineConfig\":false}!../../../../../../node_modules/vue-loader/lib/selector.js?type=styles&index=0!./scoped-style.vue", function() {
+	     var newContent = require("!!../../../../../../node_modules/.0.26.1@css-loader/index.js!../../../../../../node_modules/vue-loader/lib/style-compiler/index.js?{\"id\":\"data-v-0776c87b\",\"scoped\":true,\"hasInlineConfig\":false}!../../../../../../node_modules/vue-loader/lib/selector.js?type=styles&index=0!./scoped-style.vue");
+	     if(typeof newContent === 'string') newContent = [[module.id, newContent, '']];
+	     update(newContent);
+	   });
+	 }
+	 // When the module is disposed, remove the <style> tags
+	 module.hot.dispose(function() { update(); });
+	}
+
+/***/ },
+/* 2 */
+/***/ function(module, exports, __webpack_require__) {
+
+	exports = module.exports = __webpack_require__(3)();
+	// imports
+
+
+	// module
+	exports.push([module.id, "\n.ct[data-v-0776c87b] {\n  width: 200px;\n  flex-direction: row;\n  transform: translate3d(100px, 100px, 0);\n}\n", ""]);
+
+	// exports
+
+
+/***/ },
+/* 3 */
+/***/ function(module, exports) {
+
+	/*
+		MIT License http://www.opensource.org/licenses/mit-license.php
+		Author Tobias Koppers @sokra
+	*/
+	// css base code, injected by the css-loader
+	module.exports = function() {
+		var list = [];
+
+		// return the list of modules as css string
+		list.toString = function toString() {
+			var result = [];
+			for(var i = 0; i < this.length; i++) {
+				var item = this[i];
+				if(item[2]) {
+					result.push("@media " + item[2] + "{" + item[1] + "}");
+				} else {
+					result.push(item[1]);
+				}
+			}
+			return result.join("");
+		};
+
+		// import a list of modules into the list
+		list.i = function(modules, mediaQuery) {
+			if(typeof modules === "string")
+				modules = [[null, modules, ""]];
+			var alreadyImportedModules = {};
+			for(var i = 0; i < this.length; i++) {
+				var id = this[i][0];
+				if(typeof id === "number")
+					alreadyImportedModules[id] = true;
+			}
+			for(i = 0; i < modules.length; i++) {
+				var item = modules[i];
+				// skip already imported module
+				// this implementation is not 100% perfect for weird media query combinations
+				//  when a module is imported multiple times with different media queries.
+				//  I hope this will never occur (Hey this way we have smaller bundles)
+				if(typeof item[0] !== "number" || !alreadyImportedModules[item[0]]) {
+					if(mediaQuery && !item[2]) {
+						item[2] = mediaQuery;
+					} else if(mediaQuery) {
+						item[2] = "(" + item[2] + ") and (" + mediaQuery + ")";
+					}
+					list.push(item);
+				}
+			}
+		};
+		return list;
+	};
+
+
+/***/ },
+/* 4 */
+/***/ function(module, exports, __webpack_require__) {
+
+	/*
+	  MIT License http://www.opensource.org/licenses/mit-license.php
+	  Author Tobias Koppers @sokra
+	  Modified by Evan You @yyx990803
+	*/
+
+	var hasDocument = typeof document !== 'undefined'
+
+	if (false) {
+	  if (!hasDocument) {
+	    throw new Error(
+	    'vue-style-loader cannot be used in a non-browser environment. ' +
+	    "Use { target: 'node' } in your Webpack config to indicate a server-rendering environment."
+	  ) }
+	}
+
+	var listToStyles = __webpack_require__(5)
+
+	/*
+	type StyleObject = {
+	  id: number;
+	  parts: Array<StyleObjectPart>
+	}
+
+	type StyleObjectPart = {
+	  css: string;
+	  media: string;
+	  sourceMap: ?string
+	}
+	*/
+
+	var stylesInDom = {/*
+	  [id: number]: {
+	    id: number,
+	    refs: number,
+	    parts: Array<(obj?: StyleObjectPart) => void>
+	  }
+	*/}
+
+	var head = hasDocument && (document.head || document.getElementsByTagName('head')[0])
+	var singletonElement = null
+	var singletonCounter = 0
+	var isProduction = false
+	var noop = function () {}
+
+	// Force single-tag solution on IE6-9, which has a hard limit on the # of <style>
+	// tags it will allow on a page
+	var isOldIE = typeof navigator !== 'undefined' && /msie [6-9]\b/.test(navigator.userAgent.toLowerCase())
+
+	module.exports = function (parentId, list, _isProduction) {
+	  isProduction = _isProduction
+
+	  var styles = listToStyles(parentId, list)
+	  addStylesToDom(styles)
+
+	  return function update (newList) {
+	    var mayRemove = []
+	    for (var i = 0; i < styles.length; i++) {
+	      var item = styles[i]
+	      var domStyle = stylesInDom[item.id]
+	      domStyle.refs--
+	      mayRemove.push(domStyle)
+	    }
+	    if (newList) {
+	      styles = listToStyles(parentId, newList)
+	      addStylesToDom(styles)
+	    } else {
+	      styles = []
+	    }
+	    for (var i = 0; i < mayRemove.length; i++) {
+	      var domStyle = mayRemove[i]
+	      if (domStyle.refs === 0) {
+	        for (var j = 0; j < domStyle.parts.length; j++) {
+	          domStyle.parts[j]()
+	        }
+	        delete stylesInDom[domStyle.id]
+	      }
+	    }
+	  }
+	}
+
+	function addStylesToDom (styles /* Array<StyleObject> */) {
+	  for (var i = 0; i < styles.length; i++) {
+	    var item = styles[i]
+	    var domStyle = stylesInDom[item.id]
+	    if (domStyle) {
+	      domStyle.refs++
+	      for (var j = 0; j < domStyle.parts.length; j++) {
+	        domStyle.parts[j](item.parts[j])
+	      }
+	      for (; j < item.parts.length; j++) {
+	        domStyle.parts.push(addStyle(item.parts[j]))
+	      }
+	      if (domStyle.parts.length > item.parts.length) {
+	        domStyle.parts.length = item.parts.length
+	      }
+	    } else {
+	      var parts = []
+	      for (var j = 0; j < item.parts.length; j++) {
+	        parts.push(addStyle(item.parts[j]))
+	      }
+	      stylesInDom[item.id] = { id: item.id, refs: 1, parts: parts }
+	    }
+	  }
+	}
+
+	function createStyleElement () {
+	  var styleElement = document.createElement('style')
+	  styleElement.type = 'text/css'
+	  head.appendChild(styleElement)
+	  return styleElement
+	}
+
+	function addStyle (obj /* StyleObjectPart */) {
+	  var update, remove
+	  var styleElement = document.querySelector('style[data-vue-ssr-id~="' + obj.id + '"]')
+
+	  if (styleElement) {
+	    if (isProduction) {
+	      // has SSR styles and in production mode.
+	      // simply do nothing.
+	      return noop
+	    } else {
+	      // has SSR styles but in dev mode.
+	      // for some reason Chrome can't handle source map in server-rendered
+	      // style tags - source maps in <style> only works if the style tag is
+	      // created and inserted dynamically. So we remove the server rendered
+	      // styles and inject new ones.
+	      styleElement.parentNode.removeChild(styleElement)
+	    }
+	  }
+
+	  if (isOldIE) {
+	    // use singleton mode for IE9.
+	    var styleIndex = singletonCounter++
+	    styleElement = singletonElement || (singletonElement = createStyleElement())
+	    update = applyToSingletonTag.bind(null, styleElement, styleIndex, false)
+	    remove = applyToSingletonTag.bind(null, styleElement, styleIndex, true)
+	  } else {
+	    // use multi-style-tag mode in all other cases
+	    styleElement = createStyleElement()
+	    update = applyToTag.bind(null, styleElement)
+	    remove = function () {
+	      styleElement.parentNode.removeChild(styleElement)
+	    }
+	  }
+
+	  update(obj)
+
+	  return function updateStyle (newObj /* StyleObjectPart */) {
+	    if (newObj) {
+	      if (newObj.css === obj.css &&
+	          newObj.media === obj.media &&
+	          newObj.sourceMap === obj.sourceMap) {
+	        return
+	      }
+	      update(obj = newObj)
+	    } else {
+	      remove()
+	    }
+	  }
+	}
+
+	var replaceText = (function () {
+	  var textStore = []
+
+	  return function (index, replacement) {
+	    textStore[index] = replacement
+	    return textStore.filter(Boolean).join('\n')
+	  }
+	})()
+
+	function applyToSingletonTag (styleElement, index, remove, obj) {
+	  var css = remove ? '' : obj.css
+
+	  if (styleElement.styleSheet) {
+	    styleElement.styleSheet.cssText = replaceText(index, css)
+	  } else {
+	    var cssNode = document.createTextNode(css)
+	    var childNodes = styleElement.childNodes
+	    if (childNodes[index]) styleElement.removeChild(childNodes[index])
+	    if (childNodes.length) {
+	      styleElement.insertBefore(cssNode, childNodes[index])
+	    } else {
+	      styleElement.appendChild(cssNode)
+	    }
+	  }
+	}
+
+	function applyToTag (styleElement, obj) {
+	  var css = obj.css
+	  var media = obj.media
+	  var sourceMap = obj.sourceMap
+
+	  if (media) {
+	    styleElement.setAttribute('media', media)
+	  }
+
+	  if (sourceMap) {
+	    // https://developer.chrome.com/devtools/docs/javascript-debugging
+	    // this makes source maps inside style tags work properly in Chrome
+	    css += '\n/*# sourceURL=' + sourceMap.sources[0] + ' */'
+	    // http://stackoverflow.com/a/26603875
+	    css += '\n/*# sourceMappingURL=data:application/json;base64,' + btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))) + ' */'
+	  }
+
+	  if (styleElement.styleSheet) {
+	    styleElement.styleSheet.cssText = css
+	  } else {
+	    while (styleElement.firstChild) {
+	      styleElement.removeChild(styleElement.firstChild)
+	    }
+	    styleElement.appendChild(document.createTextNode(css))
+	  }
+	}
+
+
+/***/ },
+/* 5 */
+/***/ function(module, exports) {
+
+	/**
+	 * Translates the list format produced by css-loader into something
+	 * easier to manipulate.
+	 */
+	module.exports = function listToStyles (parentId, list) {
+	  var styles = []
+	  var newStyles = {}
+	  for (var i = 0; i < list.length; i++) {
+	    var item = list[i]
+	    var id = item[0]
+	    var css = item[1]
+	    var media = item[2]
+	    var sourceMap = item[3]
+	    var part = {
+	      id: parentId + ':' + i,
+	      css: css,
+	      media: media,
+	      sourceMap: sourceMap
+	    }
+	    if (!newStyles[id]) {
+	      styles.push(newStyles[id] = { id: id, parts: [part] })
+	    } else {
+	      newStyles[id].parts.push(part)
+	    }
+	  }
+	  return styles
+	}
+
+
+/***/ },
+/* 6 */
+/***/ function(module, exports) {
+
+	// this module is a runtime utility for cleaner component module output and will
+	// be included in the final webpack user bundle
+
+	module.exports = function normalizeComponent (
+	  rawScriptExports,
+	  compiledTemplate,
+	  scopeId,
+	  cssModules
+	) {
+	  var esModule
+	  var scriptExports = rawScriptExports = rawScriptExports || {}
+
+	  // ES6 modules interop
+	  var type = typeof rawScriptExports.default
+	  if (type === 'object' || type === 'function') {
+	    esModule = rawScriptExports
+	    scriptExports = rawScriptExports.default
+	  }
+
+	  // Vue.extend constructor export interop
+	  var options = typeof scriptExports === 'function'
+	    ? scriptExports.options
+	    : scriptExports
+
+	  // render functions
+	  if (compiledTemplate) {
+	    options.render = compiledTemplate.render
+	    options.staticRenderFns = compiledTemplate.staticRenderFns
+	  }
+
+	  // scopedId
+	  if (scopeId) {
+	    options._scopeId = scopeId
+	  }
+
+	  // inject cssModules
+	  if (cssModules) {
+	    var computed = Object.create(options.computed || null)
+	    Object.keys(cssModules).forEach(function (key) {
+	      var module = cssModules[key]
+	      computed[key] = function () { return module }
+	    })
+	    options.computed = computed
+	  }
+
+	  return {
+	    esModule: esModule,
+	    exports: scriptExports,
+	    options: options
+	  }
+	}
+
+
+/***/ },
+/* 7 */
+/***/ function(module, exports, __webpack_require__) {
+
+	module.exports={render:function (){var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;
+	  return _c('div', [_c('div', {
+	    ref: "foo",
+	    staticClass: "ct",
+	    staticStyle: {
+	      "height": "200px"
+	    },
+	    style: ({
+	      backgroundColor: 'red'
+	    })
+	  })])
+	},staticRenderFns: []}
+	module.exports.render._withStripped = true
+	if (false) {
+	  module.hot.accept()
+	  if (module.hot.data) {
+	     require("vue-loader/node_modules/vue-hot-reload-api").rerender("data-v-0776c87b", module.exports)
+	  }
+	}
+
+/***/ }
+/******/ ])
+});
+;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/38f1a971/html5/test/render/vue/data/css/head1.css
----------------------------------------------------------------------
diff --git a/html5/test/render/vue/data/css/head1.css b/html5/test/render/vue/data/css/head1.css
new file mode 100644
index 0000000..f6a818a
--- /dev/null
+++ b/html5/test/render/vue/data/css/head1.css
@@ -0,0 +1,38 @@
+/*/////////////////////////////////////////////////////////////*/
+
+/* \u9ed8\u8ba4\u80cc\u666f\u8272\u4e3a #FFFFFF */
+.wrapper[data-v-67763bae] {
+    width: 375px;
+    /*background-color: #586C5D;*/
+    overflow: hidden;
+}
+.module-warning[data-v-67763bae]{
+    text-align: center;
+    font-size: 25px;
+    color: red;
+    font-weight: bold;
+}
+.video[data-v-67763bae]{
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 375px;
+}
+.first-frame[data-v-67763bae]{
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 375px;
+}
+.final-image[data-v-67763bae]{
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 375px;
+}
+.deco-img[data-v-67763bae]{
+    width: 375px;
+    position: absolute;
+    left: 0;
+    bottom: 0;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/38f1a971/html5/test/render/vue/data/css/head10.css
----------------------------------------------------------------------
diff --git a/html5/test/render/vue/data/css/head10.css b/html5/test/render/vue/data/css/head10.css
new file mode 100644
index 0000000..06dce95
--- /dev/null
+++ b/html5/test/render/vue/data/css/head10.css
@@ -0,0 +1,14 @@
+/*/////////////////////////////////////////////////////////////*/
+/* Copyright 2014 Evernote Corporation. All rights reserved. */
+.en-markup-crop-options {
+    top: 18px !important;
+    left: 50% !important;
+    margin-left: -100px !important;
+    width: 200px !important;
+    border: 2px rgba(255,255,255,.38) solid !important;
+    border-radius: 4px !important;
+}
+
+.en-markup-crop-options div div:first-of-type {
+    margin-left: 0px !important;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/38f1a971/html5/test/render/vue/data/css/head11.css
----------------------------------------------------------------------
diff --git a/html5/test/render/vue/data/css/head11.css b/html5/test/render/vue/data/css/head11.css
new file mode 100644
index 0000000..dbefea4
--- /dev/null
+++ b/html5/test/render/vue/data/css/head11.css
@@ -0,0 +1,2 @@
+/*/////////////////////////////////////////////////////////////*/
+#J_6820099468 .act-module-title-m {padding-bottom:0;background-color:#34110b}#J_6820099468 .act-module-title-m h3{margin:0 auto 0}#J_6820099468 .act-module-title-m .item-title{color:#333}#J_6820099468 .act-module-title-m .item-title:before,#J_6820099468 .act-module-title-m .item-title:after{background:#333}#J_6820099468 .act-module-title-m .is-img{padding-top:28.26666667%}#J_6820099468 .act-module-title-m .banner-img{height:212}#J_3487624305 .act-module-title-m{padding-bottom:0;background-color:#34110b}#J_3487624305 .act-module-title-m h3{margin:0 auto 0}#J_3487624305 .act-module-title-m .item-title{color:#333}#J_3487624305 .act-module-title-m .item-title:before,#J_3487624305 .act-module-title-m .item-title:after{background:#333}#J_3487624305 .act-module-title-m .is-img{padding-top:28.26666667%}#J_3487624305 .act-module-title-m .banner-img{height:212}#J_1043444990 .zebra-basis-slider{background-color:#4e351f;box-sizing:border-box;-webkit-box-sizing:border-box;-moz-box-sizing:border-
 box;-o-box-sizing:border-box;-ms-box-sizing:border-box;padding-left:0;padding-right:0}#J_1043444990 .zebra-basis-slider .icons i{background-color:#e6e6e6}#J_1043444990 .zebra-basis-slider .icons i.current{background-color:#DF3434}#J_1043444990 .zebra-basis-slider .slider{min-height:136.17021277px}#J_5774361206 .act-module-title-m{padding-bottom:0;background-color:#34110b}#J_5774361206 .act-module-title-m h3{margin:0 auto 0}#J_5774361206 .act-module-title-m .item-title{color:#333}#J_5774361206 .act-module-title-m .item-title:before,#J_5774361206 .act-module-title-m .item-title:after{background:#333}#J_5774361206 .act-module-title-m .is-img{padding-top:28.26666667%}#J_5774361206 .act-module-title-m .banner-img{height:212}#J_4710936714 .act-module-title-m{padding-bottom:0;background-color:#34110b}#J_4710936714 .act-module-title-m h3{margin:0 auto 0}#J_4710936714 .act-module-title-m .item-title{color:#333}#J_4710936714 .act-module-title-m .item-title:before,#J_4710936714 .act-module-tit
 le-m .item-title:after{background:#333}#J_4710936714 .act-module-title-m .is-img{padding-top:28.26666667%}#J_4710936714 .act-module-title-m .banner-img{height:212}

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/38f1a971/html5/test/render/vue/data/css/head12.css
----------------------------------------------------------------------
diff --git a/html5/test/render/vue/data/css/head12.css b/html5/test/render/vue/data/css/head12.css
new file mode 100644
index 0000000..8cc067b
--- /dev/null
+++ b/html5/test/render/vue/data/css/head12.css
@@ -0,0 +1,2 @@
+/*/////////////////////////////////////////////////////////////*/
+.inner-feedback-m{        width: 40px;        height: 40px;        background-size: 50px;        background-image: url(//img.alicdn.com/tps/i3/T1JDlEFg4cXXcu8V6l-64-64.png);        display: block;        position: fixed;        left: 10px;        bottom: 100px;        overflow: hidden;        text-indent: -9999em;        z-index: 9999;        background-color: rgba(0, 0, 0, 0.2);        border-radius: 20px;        background-position: center;    }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/38f1a971/html5/test/render/vue/data/css/head2.css
----------------------------------------------------------------------
diff --git a/html5/test/render/vue/data/css/head2.css b/html5/test/render/vue/data/css/head2.css
new file mode 100644
index 0000000..50c718f
--- /dev/null
+++ b/html5/test/render/vue/data/css/head2.css
@@ -0,0 +1,11 @@
+/*/////////////////////////////////////////////////////////////*/
+
+.wrapper[data-v-16194ed9] {
+    color: #353535;
+}
+.point[data-v-16194ed9] {
+  position: absolute;
+}
+.banner[data-v-16194ed9]{
+  width: 375px;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/38f1a971/html5/test/render/vue/data/css/head3.css
----------------------------------------------------------------------
diff --git a/html5/test/render/vue/data/css/head3.css b/html5/test/render/vue/data/css/head3.css
new file mode 100644
index 0000000..f8bf724
--- /dev/null
+++ b/html5/test/render/vue/data/css/head3.css
@@ -0,0 +1,25 @@
+/*/////////////////////////////////////////////////////////////*/
+
+/* \u9ed8\u8ba4\u80cc\u666f\u8272\u4e3a #FFFFFF */
+.wrapper[data-v-6acf469e] {
+    background-color: transparent;
+    -webkit-box-pack: center;
+    -webkit-justify-content: center;
+        -ms-flex-pack: center;
+            justify-content: center;
+    -webkit-box-align: center;
+    -webkit-align-items: center;
+        -ms-flex-align: center;
+            align-items: center;
+    padding-bottom: 9px;
+}
+.items-wrapper[data-v-6acf469e] {
+    width: 357.5px;
+}
+.row[data-v-6acf469e] {
+    -webkit-box-orient: horizontal;
+    -webkit-box-direction: normal;
+    -webkit-flex-direction: row;
+        -ms-flex-direction: row;
+            flex-direction: row;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/38f1a971/html5/test/render/vue/data/css/head4.css
----------------------------------------------------------------------
diff --git a/html5/test/render/vue/data/css/head4.css b/html5/test/render/vue/data/css/head4.css
new file mode 100644
index 0000000..dfde2dc
--- /dev/null
+++ b/html5/test/render/vue/data/css/head4.css
@@ -0,0 +1,56 @@
+/*/////////////////////////////////////////////////////////////*/
+
+.item[data-v-553d6ea0] {
+    width: 178px;
+    height: 118px;
+    background-color: #ffffff;
+    margin-bottom: 1px;
+}
+.bgImage[data-v-553d6ea0] {
+    position: absolute;
+    width: 178px;
+    height: 118px;
+}
+.img[data-v-553d6ea0] {
+    position: absolute;
+    width: 90px;
+    height: 90px;
+    top: 14px;
+    left: 3px;
+}
+.right-panel[data-v-553d6ea0] {
+    position: absolute;
+    left: 98px;
+    width: 75px;
+    lines: 1;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+    display: inline-block;
+    overflow: hidden;
+}
+.title[data-v-553d6ea0] {
+    font-weight: bold;
+    font-size: 12px;
+}
+.title-goods[data-v-553d6ea0] {
+    top: 22px;
+}
+.title-shop[data-v-553d6ea0] {
+    top: 40px;
+}
+.subtitle[data-v-553d6ea0] {
+    font-weight: lighter;
+    font-size: 12px;
+    color: #4A4A4A;
+}
+.subtitle-goods[data-v-553d6ea0] {
+    top: 43px;
+}
+.subtitle-shop[data-v-553d6ea0] {
+    top: 61px;
+}
+.price[data-v-553d6ea0] {
+    font-weight: lighter;
+    font-size: 14px;
+    top: 76px;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/38f1a971/html5/test/render/vue/data/css/head5.css
----------------------------------------------------------------------
diff --git a/html5/test/render/vue/data/css/head5.css b/html5/test/render/vue/data/css/head5.css
new file mode 100644
index 0000000..a0adb55
--- /dev/null
+++ b/html5/test/render/vue/data/css/head5.css
@@ -0,0 +1,153 @@
+/*/////////////////////////////////////////////////////////////*/
+
+/* \u9ed8\u8ba4\u80cc\u666f\u8272\u4e3a #FFFFFF */
+.wrapper[data-v-2c9fb3eb] {
+    background-color: transparent;
+}
+.cell-wrap[data-v-2c9fb3eb]{
+}
+.like-row[data-v-2c9fb3eb]{
+    width: 375px;
+    padding-left: 9px;
+    padding-right: 9px;
+    margin-bottom: 9px;
+    box-sizing: border-box;
+    -webkit-box-orient: horizontal;
+    -webkit-box-direction: normal;
+    -webkit-flex-direction: row;
+        -ms-flex-direction: row;
+            flex-direction: row;
+    -webkit-box-pack: justify;
+    -webkit-justify-content: space-between;
+        -ms-flex-pack: justify;
+            justify-content: space-between;
+        }
+.like-item[data-v-2c9fb3eb]{
+    box-sizing: border-box;
+    width: 174px;
+    height: 250px;
+    /*margin-bottom: 18;*/
+    padding-left: 7px;
+    padding-right: 7px;
+    /*padding-top: 348px;*/
+    background-color: #ffffff;
+}
+.item-img[data-v-2c9fb3eb]{
+    /*position: absolute;*/
+    /*top: 0;*/
+    /*left: 0;*/
+    margin-left: -7px;
+    width: 174px;
+    height: 174px;
+}
+.title-ctn[data-v-2c9fb3eb]{
+    margin-top: 12px;
+    /* 348 - 14 * 2 */
+    width: 162px;
+    /*background-color: #eee;*/
+}
+.badge[data-v-2c9fb3eb]{
+    position: absolute;
+    top: 2px;
+    left: 0px;
+    width: 26px;
+    height: 13px;
+    margin-right: 4px;
+}
+.title[data-v-2c9fb3eb]{
+    width: 162px;
+    font-size: 12px;
+    line-height: 15px;
+    /*padding-top: 3;*/
+    color: #333333;
+    /*background-color: #ccc;*/
+
+    overflow: hidden;
+    text-overflow: ellipsis;
+    lines: 2;
+}
+.sub-title[data-v-2c9fb3eb]{
+    position: absolute;
+    /* 348 - 40(own-height)*/
+    bottom: 11px;
+    right: 6px;
+    /*width: 312;*/
+
+    /* totally hack, do not change */
+    font-size: 10px;
+    line-height: 9px;
+    height: 14px;
+    padding-top: 1.5px;
+
+    padding-left: 3px;
+    padding-right: 3px;
+    text-align: center;
+
+    color: #F70E50;
+    text-align: center;
+    border-radius: 3px;
+    border-width: 1px;
+
+    overflow: hidden;
+    text-overflow: ellipsis;
+    lines: 1;
+}
+.sub-title-bg[data-v-2c9fb3eb]{
+    position: absolute;
+    bottom: 11px;
+    right: 6px;
+
+    /* totally hack, do not change */
+    font-size: 10px;
+    line-height: 9px;
+    height: 14px;
+    padding-left: 3px;
+    padding-right: 3px;
+    text-align: center;
+
+    text-align: center;
+    border-radius: 3px;
+    border-width: 1px;
+
+    overflow: hidden;
+    text-overflow: ellipsis;
+    lines: 1;
+
+    border-color: transparent;
+    color: transparent;
+    opacity: 0.15;
+}
+.price-ctn[data-v-2c9fb3eb]{
+    position: absolute;
+    bottom: 11px;
+    left: 6px;
+    -webkit-box-orient: horizontal;
+    -webkit-box-direction: normal;
+    -webkit-flex-direction: row;
+        -ms-flex-direction: row;
+            flex-direction: row;
+    -webkit-box-align: center;
+    -webkit-align-items: center;
+        -ms-flex-align: center;
+            align-items: center;
+    /*background-color: #ccc;*/
+}
+.price-title[data-v-2c9fb3eb]{
+    font-size: 12px;
+    /*margin-top: 4px;*/
+}
+.price-unit[data-v-2c9fb3eb]{
+    /*margin-top: 5px;*/
+    font-size: 12px;
+    /*line-height: 26px;*/
+    color: #E71A17;
+    /*background-color: #ccc;*/
+}
+.price-num[data-v-2c9fb3eb]{
+    margin-left: -1px;
+    color: #E71A17;
+    font-size: 15px;
+    /*line-height: 36px;*/
+    font-weight: bold;
+    /*background-color: #ccc;*/
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/38f1a971/html5/test/render/vue/data/css/head6.css
----------------------------------------------------------------------
diff --git a/html5/test/render/vue/data/css/head6.css b/html5/test/render/vue/data/css/head6.css
new file mode 100644
index 0000000..38eb47d
--- /dev/null
+++ b/html5/test/render/vue/data/css/head6.css
@@ -0,0 +1,4 @@
+/*/////////////////////////////////////////////////////////////*/
+.mui-zebra-page{
+  background:#192905
+}

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/38f1a971/html5/test/render/vue/data/css/head7.css
----------------------------------------------------------------------
diff --git a/html5/test/render/vue/data/css/head7.css b/html5/test/render/vue/data/css/head7.css
new file mode 100644
index 0000000..aab323b
--- /dev/null
+++ b/html5/test/render/vue/data/css/head7.css
@@ -0,0 +1,61 @@
+/*/////////////////////////////////////////////////////////////*/
+.weex-root,
+.weex-root * {
+  color: initial;
+  cursor: initial;
+  direction: initial;
+  font: initial;
+  font-family: initial;
+  font-size: initial;
+  font-style: initial;
+  font-variant: initial;
+  font-weight: initial;
+  line-height: initial;
+  text-align: initial;
+  text-indent: initial;
+  visibility: initial;
+  white-space: initial;
+  word-spacing: initial;
+  font-family: BlinkMacSystemFont, 'Source Sans Pro', 'Helvetica Neue', Helvetica, Arial, sans-serif;
+}
+
+.weex-root,
+.weex-root *,
+.weex-root *::before,
+.weex-root *::after {
+  box-sizing: border-box;
+  -webkit-text-size-adjust: none;
+      -ms-text-size-adjust: none;
+          text-size-adjust: none;
+      }
+
+.weex-root a,
+.weex-root button,
+.weex-root [role="button"],
+.weex-root input,
+.weex-root label,
+.weex-root select,
+.weex-root textarea {
+  -ms-touch-action: manipulation;
+      touch-action: manipulation;
+  }
+
+.weex-root p,
+.weex-root ol,
+.weex-root ul,
+.weex-root dl {
+  margin: 0;
+  padding: 0;
+}
+
+.weex-root li {
+  list-style: none;
+}
+
+.weex-root figure {
+  margin: 0;
+}
+
+.weex-root textarea {
+  resize: none;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/38f1a971/html5/test/render/vue/data/css/head8.css
----------------------------------------------------------------------
diff --git a/html5/test/render/vue/data/css/head8.css b/html5/test/render/vue/data/css/head8.css
new file mode 100644
index 0000000..8f25208
--- /dev/null
+++ b/html5/test/render/vue/data/css/head8.css
@@ -0,0 +1,507 @@
+/*/////////////////////////////////////////////////////////////*/
+.weex-root * {
+  border-width: 0;
+  border-color: inherit;
+  border-style: solid;
+}
+
+.weex-ct {
+  box-sizing: border-box;
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: flex;
+  position: relative;
+  -webkit-box-orient: vertical;
+  -webkit-flex-direction: column;
+  flex-direction: column;
+  -webkit-flex-shrink: 0;
+  -ms-flex-negative: 0;
+  flex-shrink: 0;
+  -webkit-flex-grow: 0;
+  -ms-flex-grow: 0;
+  flex-grow: 0;
+  -webkit-flex-basis: auto;
+  flex-basis: auto;
+  -webkit-box-align: stretch;
+  -webkit-align-items: stretch;
+  -ms-flex-align: stretch;
+  align-items: stretch;
+  -webkit-align-content: flex-start;
+  -ms-flex-line-pack: start;
+  align-content: flex-start;
+  border: 0 solid black;
+  margin: 0;
+  padding: 0;
+  min-width: 0;
+}
+
+.weex-ct.horizontal {
+  -webkit-box-orient: horizontal;
+  -webkit-flex-direction: row;
+  flex-direction: row;
+}
+
+.weex-el {
+  display: block;
+  box-sizing: border-box;
+  position: relative;
+  -webkit-flex-shrink: 0;
+  -ms-flex-negative: 0;
+  flex-shrink: 0;
+  -webkit-flex-grow: 0;
+  -ms-flex-grow: 0;
+  flex-grow: 0;
+  -webkit-flex-basis: auto;
+  flex-basis: auto;
+  border: 0 solid black;
+  margin: 0;
+  padding: 0;
+  min-width: 0;
+}
+
+.weex-a {
+  text-decoration: none;
+}
+
+body > .weex-div {
+  min-height: 100%;
+}
+
+.weex-input, .weex-textarea {
+  font-size: 0.426667rem;
+}
+.weex-input:focus, .weex-textarea:focus {
+  outline: none;
+}
+
+.weex-image, .weex-img {
+  background-repeat: no-repeat;
+  background-position: 50% 50%;
+}
+
+.weex-toast {
+  font-size: 0.426667rem;
+  line-height: 0.426667rem;
+  position: fixed;
+  z-index: 1999999999;
+  box-sizing: border-box;
+  max-width: 80%;
+  bottom: 50%;
+  left: 50%;
+  padding: 0.213333rem;
+  background-color: #000;
+  color: #fff;
+  text-align: center;
+  opacity: 0.6;
+  -webkit-transition: all 0.4s ease-in-out;
+          transition: all 0.4s ease-in-out;
+  border-radius: 0.066667rem;
+  -webkit-transform: translateX(-50%);
+  -ms-transform: translateX(-50%);
+      transform: translateX(-50%);
+  }
+
+.weex-toast.hide {
+  opacity: 0;
+}
+
+.weex-alert .weex-alert-ok {
+  width: 100%;
+}
+
+.weex-confirm .btn-group .btn {
+  float: left;
+  width: 50%;
+}
+
+.weex-confirm .btn-group .btn.btn-ok {
+  border-right: 0.013333rem solid #ddd;
+}
+
+.weex-modal-wrap {
+  display: none;
+  position: fixed;
+  z-index: 999999999;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  background-color: #000;
+  opacity: 0.5;
+}
+
+.weex-modal-node {
+  position: fixed;
+  z-index: 9999999999;
+  top: 50%;
+  left: 50%;
+  width: 6.666667rem;
+  min-height: 2.666667rem;
+  border-radius: 0.066667rem;
+  -webkit-transform: translate(-50%, -50%);
+  -ms-transform: translate(-50%, -50%);
+      transform: translate(-50%, -50%);
+  background-color: #fff;
+}
+
+.weex-modal-node.hide {
+  display: none;
+}
+
+.weex-modal-node .content {
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: -ms-flexbox;
+  display: flex;
+  -webkit-box-orient: vertical;
+  -webkit-flex-direction: column;
+  -ms-flex-direction: column;
+      flex-direction: column;
+  -webkit-box-align: center;
+  -webkit-align-items: center;
+  -ms-flex-align: center;
+      align-items: center;
+  -webkit-box-pack: center;
+  -webkit-justify-content: center;
+  -ms-flex-pack: center;
+      justify-content: center;
+  width: 100%;
+  min-height: 1.866667rem;
+  box-sizing: border-box;
+  font-size: 0.426667rem;
+  line-height: 0.426667rem;
+  padding: 0.213333rem;
+  border-bottom: 0.013333rem solid #ddd;
+}
+
+.weex-modal-node .btn-group {
+  width: 100%;
+  height: 0.8rem;
+  font-size: 0.373333rem;
+  text-align: center;
+  margin: 0;
+  padding: 0;
+  border: none;
+}
+
+.amfe-modal-node .btn-group .btn {
+  text-align: center;
+}
+
+.weex-modal-node .btn-group .btn {
+  box-sizing: border-box;
+  height: 0.8rem;
+  line-height: 0.8rem;
+  margin: 0;
+  padding: 0;
+  border: none;
+  background: none;
+  text-align: center;
+}
+
+.weex-prompt .input-wrap {
+  box-sizing: border-box;
+  width: 100%;
+  margin-top: 0.133333rem;
+  height: 0.96rem;
+}
+
+.weex-prompt .input-wrap .input {
+  box-sizing: border-box;
+  width: 100%;
+  height: 0.56rem;
+  line-height: 0.56rem;
+  font-size: 0.426667rem;
+  border: 0.013333rem solid #999;
+}
+
+.weex-prompt .btn-group .btn {
+  float: left;
+  width: 50%;
+}
+
+.weex-prompt .btn-group .btn.btn-ok {
+  border-right: 0.013333rem solid #ddd;
+}
+
+body > .weex-list,
+body > .weex-scroller {
+  max-height: 100%;
+}
+
+.weex-list-wrapper,
+.weex-scroller-wrapper {
+  -webkit-overflow-scrolling: touch;
+}
+
+.weex-list-wrapper {
+  overflow-y: scroll !important;
+}
+
+.weex-list-inner,
+.weex-scroller-inner {
+  -webkit-overflow-scrolling: touch;
+  width: 100%;
+}
+
+.weex-scroller-inner::-webkit-scrollbar {
+    width: 0;
+}
+
+.weex-scroller-wrapper.weex-scroller-vertical {
+  overflow-y: scroll;
+}
+
+.weex-scroller-wrapper.weex-scroller-horizontal {
+  overflow-x: scroll;
+}
+
+.weex-scroller-horizontal .weex-scroller-inner {
+  -webkit-flex-direction: row;
+      -ms-flex-direction: row;
+          flex-direction: row;
+  -webkit-box-orient: horizontal;
+  height: 100%;
+}
+
+.iossticky {
+  position: -webkit-sticky !important;
+  position: sticky !important;
+  z-index: 9999;
+  top: 0;
+}
+
+.sticky {
+  position: fixed;
+  top: 0;
+  z-index: 9999;
+}
+
+.weex-cell {
+  width: 100%;
+}
+
+.weex-refresh,
+.weex-loading {
+  -webkit-box-align: center;
+  -webkit-align-items: center;
+      -ms-flex-align: center;
+          align-items: center;
+  -webkit-box-pack: center;
+  -webkit-justify-content: center;
+      -ms-flex-pack: center;
+          justify-content: center;
+  width: 100%;
+  overflow: hidden;
+}
+
+.weex-slider-wrapper {
+  overflow: hidden;
+}
+
+.weex-slider-inner {
+  position: absolute;
+  height: 100%;
+  top: 0;
+  left: 0;
+}
+
+.weex-slider-cell {
+  display: block;
+  position: absolute;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  margin: 0;
+  padding: 0;
+  height: 100%;
+  overflow: hidden;
+}
+
+.weex-indicator {
+  position: absolute;
+  -webkit-flex-direction: row;
+  -ms-flex-direction: row;
+  flex-direction: row;
+  -webkit-box-orient: horizontal;
+  margin: 0;
+  padding: 0;
+}
+
+.weex-indicator-item {
+  display: inline-block;
+  position: relative;
+  border-radius: 50%;
+  width: 0.266667rem;
+  height: 0.266667rem;
+  background-color: #BBBBBB;
+}
+.weex-indicator-item + .weex-indicator-item {
+  margin-left: 0.133333rem;
+}
+
+.weex-indicator-item-active {
+  background-color: blue;
+}
+
+.weex-refresh-indicator,
+.weex-loading-indicator {
+  width: 1.0rem;
+  height: 1.0rem;
+  -webkit-box-align: center;
+  -webkit-align-items: center;
+      -ms-flex-align: center;
+          align-items: center;
+  -webkit-box-pack: center;
+  -webkit-justify-content: center;
+      -ms-flex-pack: center;
+          justify-content: center;
+  overflow: visible;
+  background: none;
+}
+.weex-refresh-indicator:before,
+.weex-loading-indicator:before {
+  display: block;
+  content: '';
+  font-size: 0.16rem;
+  width: 1em;
+  height: 1em;
+  left: -60%;
+  top: 40%;
+  border-radius: 50%;
+  position: relative;
+  text-indent: -9999em;
+  -webkit-animation: weex-spinner 1.1s infinite ease;
+          animation: weex-spinner 1.1s infinite ease;
+  -webkit-transform: translate3d(1.0rem, 0, 0);
+          transform: translate3d(1.0rem, 0, 0);
+}
+
+@-webkit-keyframes weex-spinner {
+  0%,
+  100% {
+    box-shadow: 0em -2.6em 0em 0em #ffffff, 1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2), 2.5em 0em 0 0em rgba(255, 255, 255, 0.2), 1.75em 1.75em 0 0em rgba(255, 255, 255, 0.2), 0em 2.5em 0 0em rgba(255, 255, 255, 0.2), -1.8em 1.8em 0 0em rgba(255, 255, 255, 0.2), -2.6em 0em 0 0em rgba(255, 255, 255, 0.5), -1.8em -1.8em 0 0em rgba(255, 255, 255, 0.7);
+  }
+  12.5% {
+    box-shadow: 0em -2.6em 0em 0em rgba(255, 255, 255, 0.7), 1.8em -1.8em 0 0em #ffffff, 2.5em 0em 0 0em rgba(255, 255, 255, 0.2), 1.75em 1.75em 0 0em rgba(255, 255, 255, 0.2), 0em 2.5em 0 0em rgba(255, 255, 255, 0.2), -1.8em 1.8em 0 0em rgba(255, 255, 255, 0.2), -2.6em 0em 0 0em rgba(255, 255, 255, 0.2), -1.8em -1.8em 0 0em rgba(255, 255, 255, 0.5);
+  }
+  25% {
+    box-shadow: 0em -2.6em 0em 0em rgba(255, 255, 255, 0.5), 1.8em -1.8em 0 0em rgba(255, 255, 255, 0.7), 2.5em 0em 0 0em #ffffff, 1.75em 1.75em 0 0em rgba(255, 255, 255, 0.2), 0em 2.5em 0 0em rgba(255, 255, 255, 0.2), -1.8em 1.8em 0 0em rgba(255, 255, 255, 0.2), -2.6em 0em 0 0em rgba(255, 255, 255, 0.2), -1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2);
+  }
+  37.5% {
+    box-shadow: 0em -2.6em 0em 0em rgba(255, 255, 255, 0.2), 1.8em -1.8em 0 0em rgba(255, 255, 255, 0.5), 2.5em 0em 0 0em rgba(255, 255, 255, 0.7), 1.75em 1.75em 0 0em #ffffff, 0em 2.5em 0 0em rgba(255, 255, 255, 0.2), -1.8em 1.8em 0 0em rgba(255, 255, 255, 0.2), -2.6em 0em 0 0em rgba(255, 255, 255, 0.2), -1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2);
+  }
+  50% {
+    box-shadow: 0em -2.6em 0em 0em rgba(255, 255, 255, 0.2), 1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2), 2.5em 0em 0 0em rgba(255, 255, 255, 0.5), 1.75em 1.75em 0 0em rgba(255, 255, 255, 0.7), 0em 2.5em 0 0em #ffffff, -1.8em 1.8em 0 0em rgba(255, 255, 255, 0.2), -2.6em 0em 0 0em rgba(255, 255, 255, 0.2), -1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2);
+  }
+  62.5% {
+    box-shadow: 0em -2.6em 0em 0em rgba(255, 255, 255, 0.2), 1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2), 2.5em 0em 0 0em rgba(255, 255, 255, 0.2), 1.75em 1.75em 0 0em rgba(255, 255, 255, 0.5), 0em 2.5em 0 0em rgba(255, 255, 255, 0.7), -1.8em 1.8em 0 0em #ffffff, -2.6em 0em 0 0em rgba(255, 255, 255, 0.2), -1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2);
+  }
+  75% {
+    box-shadow: 0em -2.6em 0em 0em rgba(255, 255, 255, 0.2), 1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2), 2.5em 0em 0 0em rgba(255, 255, 255, 0.2), 1.75em 1.75em 0 0em rgba(255, 255, 255, 0.2), 0em 2.5em 0 0em rgba(255, 255, 255, 0.5), -1.8em 1.8em 0 0em rgba(255, 255, 255, 0.7), -2.6em 0em 0 0em #ffffff, -1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2);
+  }
+  87.5% {
+    box-shadow: 0em -2.6em 0em 0em rgba(255, 255, 255, 0.2), 1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2), 2.5em 0em 0 0em rgba(255, 255, 255, 0.2), 1.75em 1.75em 0 0em rgba(255, 255, 255, 0.2), 0em 2.5em 0 0em rgba(255, 255, 255, 0.2), -1.8em 1.8em 0 0em rgba(255, 255, 255, 0.5), -2.6em 0em 0 0em rgba(255, 255, 255, 0.7), -1.8em -1.8em 0 0em #ffffff;
+  }
+}
+
+@keyframes weex-spinner {
+  0%,
+  100% {
+    box-shadow: 0em -2.6em 0em 0em #ffffff, 1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2), 2.5em 0em 0 0em rgba(255, 255, 255, 0.2), 1.75em 1.75em 0 0em rgba(255, 255, 255, 0.2), 0em 2.5em 0 0em rgba(255, 255, 255, 0.2), -1.8em 1.8em 0 0em rgba(255, 255, 255, 0.2), -2.6em 0em 0 0em rgba(255, 255, 255, 0.5), -1.8em -1.8em 0 0em rgba(255, 255, 255, 0.7);
+  }
+  12.5% {
+    box-shadow: 0em -2.6em 0em 0em rgba(255, 255, 255, 0.7), 1.8em -1.8em 0 0em #ffffff, 2.5em 0em 0 0em rgba(255, 255, 255, 0.2), 1.75em 1.75em 0 0em rgba(255, 255, 255, 0.2), 0em 2.5em 0 0em rgba(255, 255, 255, 0.2), -1.8em 1.8em 0 0em rgba(255, 255, 255, 0.2), -2.6em 0em 0 0em rgba(255, 255, 255, 0.2), -1.8em -1.8em 0 0em rgba(255, 255, 255, 0.5);
+  }
+  25% {
+    box-shadow: 0em -2.6em 0em 0em rgba(255, 255, 255, 0.5), 1.8em -1.8em 0 0em rgba(255, 255, 255, 0.7), 2.5em 0em 0 0em #ffffff, 1.75em 1.75em 0 0em rgba(255, 255, 255, 0.2), 0em 2.5em 0 0em rgba(255, 255, 255, 0.2), -1.8em 1.8em 0 0em rgba(255, 255, 255, 0.2), -2.6em 0em 0 0em rgba(255, 255, 255, 0.2), -1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2);
+  }
+  37.5% {
+    box-shadow: 0em -2.6em 0em 0em rgba(255, 255, 255, 0.2), 1.8em -1.8em 0 0em rgba(255, 255, 255, 0.5), 2.5em 0em 0 0em rgba(255, 255, 255, 0.7), 1.75em 1.75em 0 0em #ffffff, 0em 2.5em 0 0em rgba(255, 255, 255, 0.2), -1.8em 1.8em 0 0em rgba(255, 255, 255, 0.2), -2.6em 0em 0 0em rgba(255, 255, 255, 0.2), -1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2);
+  }
+  50% {
+    box-shadow: 0em -2.6em 0em 0em rgba(255, 255, 255, 0.2), 1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2), 2.5em 0em 0 0em rgba(255, 255, 255, 0.5), 1.75em 1.75em 0 0em rgba(255, 255, 255, 0.7), 0em 2.5em 0 0em #ffffff, -1.8em 1.8em 0 0em rgba(255, 255, 255, 0.2), -2.6em 0em 0 0em rgba(255, 255, 255, 0.2), -1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2);
+  }
+  62.5% {
+    box-shadow: 0em -2.6em 0em 0em rgba(255, 255, 255, 0.2), 1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2), 2.5em 0em 0 0em rgba(255, 255, 255, 0.2), 1.75em 1.75em 0 0em rgba(255, 255, 255, 0.5), 0em 2.5em 0 0em rgba(255, 255, 255, 0.7), -1.8em 1.8em 0 0em #ffffff, -2.6em 0em 0 0em rgba(255, 255, 255, 0.2), -1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2);
+  }
+  75% {
+    box-shadow: 0em -2.6em 0em 0em rgba(255, 255, 255, 0.2), 1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2), 2.5em 0em 0 0em rgba(255, 255, 255, 0.2), 1.75em 1.75em 0 0em rgba(255, 255, 255, 0.2), 0em 2.5em 0 0em rgba(255, 255, 255, 0.5), -1.8em 1.8em 0 0em rgba(255, 255, 255, 0.7), -2.6em 0em 0 0em #ffffff, -1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2);
+  }
+  87.5% {
+    box-shadow: 0em -2.6em 0em 0em rgba(255, 255, 255, 0.2), 1.8em -1.8em 0 0em rgba(255, 255, 255, 0.2), 2.5em 0em 0 0em rgba(255, 255, 255, 0.2), 1.75em 1.75em 0 0em rgba(255, 255, 255, 0.2), 0em 2.5em 0 0em rgba(255, 255, 255, 0.2), -1.8em 1.8em 0 0em rgba(255, 255, 255, 0.5), -2.6em 0em 0 0em rgba(255, 255, 255, 0.7), -1.8em -1.8em 0 0em #ffffff;
+  }
+}
+.weex-switch {
+  border: 0.013333rem solid #dfdfdf;
+  cursor: pointer;
+  display: inline-block;
+  position: relative;
+  vertical-align: middle;
+  -webkit-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+          user-select: none;
+  box-sizing: content-box;
+  background-clip: content-box;
+  color: #64bd63;
+  width: 1.333333rem;
+  height: 0.8rem;
+  background-color: white;
+  border-color: #dfdfdf;
+  box-shadow: #dfdfdf 0 0 0 0 inset;
+  border-radius: 0.8rem;
+  -webkit-transition: border 0.4s, box-shadow 0.4s, background-color 1.2s;
+          transition: border 0.4s, box-shadow 0.4s, background-color 1.2s;
+      }
+
+.weex-switch-checked {
+  background-color: #64bd63;
+  border-color: #64bd63;
+  box-shadow: #64bd63 0 0 0 0.533333rem inset;
+}
+
+.weex-switch-checked.weex-switch-disabled {
+  background-color: #A0CCA0;
+  box-shadow: #A0CCA0 0 0 0 0.533333rem inset;
+}
+
+.weex-switch-disabled {
+  background-color: #EEEEEE;
+}
+
+.weex-switch-inner {
+  width: 0.8rem;
+  height: 0.8rem;
+  background: #fff;
+  border-radius: 100%;
+  box-shadow: 0 0.013333rem 0.04rem rgba(0, 0, 0, 0.4);
+  position: absolute;
+  top: 0;
+  left: 0;
+  -webkit-transition: background-color 0.4s, left 0.2s;
+          transition: background-color 0.4s, left 0.2s;
+      }
+
+.weex-switch-checked > .weex-switch-inner {
+  left: 0.533333rem;
+}
+
+.weex-text {
+  display: -webkit-box;
+  -webkit-box-orient: vertical;
+  position: relative;
+  white-space: pre-wrap;  /* not using 'pre': support auto line feed. */
+  font-size: 0.426667rem;
+  word-wrap: break-word;
+  overflow: hidden; /* it'll be clipped if the height is not high enough. */
+}
+
+.weex-web {
+  position: relative;
+  width: 100%;
+  height: 100%;
+  border: none;
+  box-sizing: border-box;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/38f1a971/html5/test/render/vue/data/css/head9.css
----------------------------------------------------------------------
diff --git a/html5/test/render/vue/data/css/head9.css b/html5/test/render/vue/data/css/head9.css
new file mode 100644
index 0000000..ce38a66
--- /dev/null
+++ b/html5/test/render/vue/data/css/head9.css
@@ -0,0 +1,173 @@
+/*/////////////////////////////////////////////////////////////*/
+@font-face {
+  font-family: "iconfont";
+  src: url("data:application/x-font-ttf;charset=utf-8;base64,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
 bA6LLEJBCVCsAAWsAQlsAQlIC5HI0cjYSCwBCNCsAZFKyCwYFBYILBAUVizAiADIBuzAiYDGllCQiMgR7AEQ7CAYmAgsAArIIqKYSCwAkNgZCOwA0NhZFBYsAJDYRuwA0NgWbADJbCAYmGwAiVGYTgjIDwjOBshICBGI0ewACsjYTghWbEkARQrLbA7LLAuKy6xJAEUKy2wPCywLyshIyAgPLAEI0IjOLEkARQrsARDLrAkKy2wPSywABUgR7AAI0KyAAEBFRQTLrAqKi2wPiywABUgR7AAI0KyAAEBFRQTLrAqKi2wPyyxAAEUE7ArKi2wQCywLSotsEEssAAWRSMgLiBGiiNhOLEkARQrLbBCLLAJI0KwQSstsEMssgAAOistsEQssgABOistsEUssgEAOistsEYssgEBOistsEcssgAAOystsEgssgABOystsEkssgEAOystsEossgEBOystsEsssgAANystsEwssgABNystsE0ssgEANystsE4ssgEBNystsE8ssgAAOSstsFAssgABOSstsFEssgEAOSstsFIssgEBOSstsFMssgAAPCstsFQssgABPCstsFUssgEAPCstsFYssgEBPCstsFcssgAAOCstsFgssgABOCstsFkssgEAOCstsFossgEBOCstsFsssDArLrEkARQrLbBcLLAwK7A0Ky2wXSywMCuwNSstsF4ssAAWsDArsDYrLbBfLLAxKy6xJAEUKy2wYCywMSuwNCstsGEssDErsDUrLbBiLLAxK7A2Ky2wYyywMisusSQBFCstsGQssDIrsDQrLbBlLLAyK7A1Ky2wZiywMiuwNistsGcssDMrLrEkARQrLbBoLLAzK7A0Ky2waSywMyuwNSstsGossDMrsDYrLbBrLCuwCGWwAyRQeLABFTAtAABLuADIUlixAQGOWbkIAAgAYyCwASNEILADI3CwDkUgIEu4AA5RS7AGU1pYsDQbsChZYGYgilVYsA
 IlYbABRWMjYrACI0SzCgkFBCuzCgsFBCuzDg8FBCtZsgQoCUVSRLMKDQYEK7EGAUSxJAGIUViwQIhYsQYDRLEmAYhRWLgEAIhYsQYBRFlZWVm4Af+FsASNsQUARAAAAA==") format("truetype");
+}
+
+.iconfont {
+  font-family: iconfont !important;
+  font-size: 0.213333rem;
+  font-style: normal;
+  -webkit-font-smoothing: antialiased;
+  -webkit-text-stroke-width: 0.0.002667rem;
+  -moz-osx-font-smoothing: grayscale;
+}
+
+.weex-tabheader {
+  position: relative;
+  -webkit-box-align: center;
+  -webkit-align-items: center;
+  -ms-flex-align: center;
+  align-items: center;
+  left: 0;
+  top: 0;
+  width: 10rem;
+  height: 1.6rem;
+  color: #333;
+  overflow: hidden;
+}
+
+.weex-tabheader,
+.weex-tabheader * {
+  color: inherit;
+  cursor: inherit;
+  direction: inherit;
+  font: inherit;
+  font-family: inherit;
+  font-size: inherit;
+  font-style: inherit;
+  font-variant: inherit;
+  font-weight: inherit;
+  line-height: inherit;
+  text-align: inherit;
+  text-indent: inherit;
+  visibility: inherit;
+  white-space: inherit;
+  word-spacing: inherit;
+}
+
+.weex-tabheader .header-bar {
+  display: none;
+  position: absolute;
+  top: 0;
+  left: 0;
+  font-size: 0.373333rem;
+  height: 1.17rem;
+  line-height: 1.17rem;
+  color: #999;
+  padding-left: 0.4rem;
+}
+.weex-tabheader .header-body {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 9rem;
+  overflow-x: scroll;
+  overflow-y: hidden;
+  white-space: nowrap;
+}
+.weex-tabheader .header-body::-webkit-scrollbar {
+  width: 0;
+  height: 0;
+  overflow: hidden;
+}
+.weex-tabheader .fold-toggle {
+  position: absolute;
+  top: 0.6rem;
+  right: 0;
+  width: 1rem;
+  height: 1.17rem;
+  line-height: 1.17rem;
+  text-align: center;
+  z-index: 999;
+  font-size: 0.426667rem;
+  -webkit-transform: translateY(-50%);
+  transform: translateY(-50%);
+}
+.weex-tabheader.unfold-header {
+  position: fixed !important;
+  top: 0;
+  left: 0;
+  overflow: visible;
+}
+
+.weex-tabheader {
+  list-style: none;
+  white-space: nowrap;
+  height: 1.17rem;
+  line-height: 1.17rem;
+}
+.weex-tabheader .th-item {
+  padding-left: 0.72rem;
+  font-size: 0.373333rem;
+  position: relative;
+  display: inline-block;
+}
+.weex-tabheader .th-item.active {
+  color: #ff0000;
+}
+.weex-tabheader .hl-icon {
+  width: 0.4rem;
+  height: 0.4rem;
+  line-height: 0.4rem;
+  text-align: center;
+  position: absolute;
+  top: 50%;
+  left: 0.24rem;
+  font-size: 0.373333rem;
+  -webkit-transform: translateY(-50%);
+  transform: translateY(-50%);
+}
+
+.weex-tabheader .hl-icon.active {
+  color: #ff0000;
+}
+
+.unfold-header .header-bar {
+  display: block;
+}
+.unfold-header .fold-toggle {
+  -webkit-transform: translateY(-50%) rotate(180deg);
+  transform: translateY(-50%) rotate(180deg);
+}
+.unfold-header .header-body {
+  display: block;
+  height: auto;
+  position: relative;
+  margin-top: 1.17rem;
+  padding: 0.133333rem;
+  margin-right: 0;
+  white-space: normal;
+}
+.unfold-header.weex-tabheader {
+  display: block;
+  height: auto;
+}
+.unfold-header .th-item {
+  box-sizing: border-box;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  float: left;
+  width: 33.3333%;
+  height: 1.01rem;
+  line-height: 1.01rem;
+}
+.unfold-header .hl-icon {
+  margin-right: 0;
+  font-size: 0.373333rem;
+  position: absolute;
+}
+.unfold-header.tabheader-mask {
+  display: block;
+  width: 100%;
+  height: 100%;
+  background-color: rgba(0, 0, 0, 0.6);
+}
+
+.tabheader-mask {
+  display: none;
+  position: fixed;
+  left: 0;
+  top: 0;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/38f1a971/html5/test/render/vue/data/dotvue/scoped-style.vue
----------------------------------------------------------------------
diff --git a/html5/test/render/vue/data/dotvue/scoped-style.vue b/html5/test/render/vue/data/dotvue/scoped-style.vue
new file mode 100644
index 0000000..67c1bb8
--- /dev/null
+++ b/html5/test/render/vue/data/dotvue/scoped-style.vue
@@ -0,0 +1,13 @@
+<template>
+  <div>
+    <div ref="foo" style="height:200px;" :style="{ backgroundColor: 'red' }" class="ct"></div>
+  </div>
+</template>
+
+<style scoped>
+.ct {
+  width: 200px;
+  flex-direction: row;
+  transform: translate3d(100px, 100px, 0);
+}
+</style>

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/38f1a971/html5/test/render/vue/data/head-css.js
----------------------------------------------------------------------
diff --git a/html5/test/render/vue/data/head-css.js b/html5/test/render/vue/data/head-css.js
new file mode 100644
index 0000000..ca4aca6
--- /dev/null
+++ b/html5/test/render/vue/data/head-css.js
@@ -0,0 +1,12 @@
+import './css/head1.css'
+import './css/head2.css'
+import './css/head3.css'
+import './css/head4.css'
+import './css/head5.css'
+import './css/head6.css'
+import './css/head7.css'
+import './css/head8.css'
+import './css/head9.css'
+import './css/head10.css'
+import './css/head11.css'
+import './css/head12.css'

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/38f1a971/html5/test/render/vue/data/head-map.js
----------------------------------------------------------------------
diff --git a/html5/test/render/vue/data/head-map.js b/html5/test/render/vue/data/head-map.js
new file mode 100644
index 0000000..cde66c9
--- /dev/null
+++ b/html5/test/render/vue/data/head-map.js
@@ -0,0 +1,247 @@
+export default {
+  /*// 1 /////////////////////////////////////////////////*/
+  ".wrapper[data-v-67763bae]": {
+    "width": "375px",
+    "overflow": "hidden"
+  },
+  ".module-warning[data-v-67763bae]": {
+    "text-align": "center",
+    "font-size": "25px",
+    "color": "red",
+    "font-weight": "bold"
+  },
+  ".video[data-v-67763bae]": {
+    "position": "absolute",
+    "top": "0",
+    "left": "0",
+    "width": "375px"
+  },
+  ".first-frame[data-v-67763bae]": {
+    "position": "absolute",
+    "top": "0",
+    "left": "0",
+    "width": "375px"
+  },
+  ".final-image[data-v-67763bae]": {
+    "position": "absolute",
+    "top": "0",
+    "left": "0",
+    "width": "375px"
+  },
+  ".deco-img[data-v-67763bae]": {
+    "width": "375px",
+    "position": "absolute",
+    "left": "0",
+    "bottom": "0"
+  },
+
+  /*// 2 /////////////////////////////////////////////////*/
+  ".wrapper[data-v-16194ed9]": {
+    "color": "#353535"
+  },
+  ".point[data-v-16194ed9]": {
+    "position": "absolute"
+  },
+  ".banner[data-v-16194ed9]": {
+    "width": "375px"
+  },
+
+  /*// 3 /////////////////////////////////////////////////*/
+  ".wrapper[data-v-6acf469e]": {
+    "background-color": "transparent",
+    "-webkit-box-pack": "center",
+    "-webkit-justify-content": "center",
+    "-ms-flex-pack": "center",
+    "justify-content": "center",
+    "-webkit-box-align": "center",
+    "-webkit-align-items": "center",
+    "-ms-flex-align": "center",
+    "align-items": "center",
+    "padding-bottom": "9px"
+  },
+  ".items-wrapper[data-v-6acf469e]": {
+    "width": "357.5px"
+  },
+  ".row[data-v-6acf469e]": {
+    "-webkit-box-orient": "horizontal",
+    "-webkit-box-direction": "normal",
+    "-webkit-flex-direction": "row",
+    "-ms-flex-direction": "row",
+    "flex-direction": "row"
+  },
+
+  /*// 4 /////////////////////////////////////////////////*/
+  ".item[data-v-553d6ea0]": {
+    "width": "178px",
+    "height": "118px",
+    "background-color": "#ffffff",
+    "margin-bottom": "1px"
+  },
+  ".bgImage[data-v-553d6ea0]": {
+    "position": "absolute",
+    "width": "178px",
+    "height": "118px"
+  },
+  ".img[data-v-553d6ea0]": {
+    "position": "absolute",
+    "width": "90px",
+    "height": "90px",
+    "top": "14px",
+    "left": "3px"
+  },
+  ".right-panel[data-v-553d6ea0]": {
+    "position": "absolute",
+    "left": "98px",
+    "width": "75px",
+    "lines": "1",
+    "text-overflow": "ellipsis",
+    "white-space": "nowrap",
+    "display": "inline-block",
+    "overflow": "hidden"
+  },
+  ".title[data-v-553d6ea0]": {
+    "font-weight": "bold",
+    "font-size": "12px"
+  },
+  ".title-goods[data-v-553d6ea0]": {
+    "top": "22px"
+  },
+  ".title-shop[data-v-553d6ea0]": {
+    "top": "40px"
+  },
+  ".subtitle[data-v-553d6ea0]": {
+    "font-weight": "lighter",
+    "font-size": "12px",
+    "color": "#4A4A4A"
+  },
+  ".subtitle-goods[data-v-553d6ea0]": {
+    "top": "43px"
+  },
+  ".subtitle-shop[data-v-553d6ea0]": {
+    "top": "61px"
+  },
+  ".price[data-v-553d6ea0]": {
+    "font-weight": "lighter",
+    "font-size": "14px",
+    "top": "76px"
+  },
+
+  /*// 5 /////////////////////////////////////////////////*/
+  ".wrapper[data-v-2c9fb3eb]": {
+    "background-color": "transparent"
+  },
+  ".cell-wrap[data-v-2c9fb3eb]": {},
+  ".like-row[data-v-2c9fb3eb]": {
+    "width": "375px",
+    "padding-left": "9px",
+    "padding-right": "9px",
+    "margin-bottom": "9px",
+    "box-sizing": "border-box",
+    "-webkit-box-orient": "horizontal",
+    "-webkit-box-direction": "normal",
+    "-webkit-flex-direction": "row",
+    "-ms-flex-direction": "row",
+    "flex-direction": "row",
+    "-webkit-box-pack": "justify",
+    "-webkit-justify-content": "space-between",
+    "-ms-flex-pack": "justify",
+    "justify-content": "space-between"
+  },
+  ".like-item[data-v-2c9fb3eb]": {
+    "box-sizing": "border-box",
+    "width": "174px",
+    "height": "250px",
+    "padding-left": "7px",
+    "padding-right": "7px",
+    "background-color": "#ffffff"
+  },
+  ".item-img[data-v-2c9fb3eb]": {
+    "margin-left": "-7px",
+    "width": "174px",
+    "height": "174px"
+  },
+  ".title-ctn[data-v-2c9fb3eb]": {
+    "margin-top": "12px"
+  },
+  ".badge[data-v-2c9fb3eb]": {
+    "position": "absolute",
+    "top": "2px",
+    "left": "0px",
+    "width": "26px",
+    "height": "13px",
+    "margin-right": "4px"
+  },
+  ".title[data-v-2c9fb3eb]": {
+    "width": "162px",
+    "font-size": "12px",
+    "line-height": "15px",
+    "color": "#333333",
+    "overflow": "hidden",
+    "text-overflow": "ellipsis",
+    "lines": "2"
+  },
+  ".sub-title[data-v-2c9fb3eb]": {
+    "position": "absolute",
+    "bottom": "11px",
+    "right": "6px",
+    "font-size": "10px",
+    "line-height": "9px",
+    "height": "14px",
+    "padding-top": "1.5px",
+    "padding-left": "3px",
+    "padding-right": "3px",
+    "text-align": "center",
+    "color": "#F70E50",
+    "border-radius": "3px",
+    "border-width": "1px",
+    "overflow": "hidden",
+    "text-overflow": "ellipsis",
+    "lines": "1"
+  },
+  ".sub-title-bg[data-v-2c9fb3eb]": {
+    "position": "absolute",
+    "bottom": "11px",
+    "right": "6px",
+    "font-size": "10px",
+    "line-height": "9px",
+    "height": "14px",
+    "padding-left": "3px",
+    "padding-right": "3px",
+    "text-align": "center",
+    "border-radius": "3px",
+    "border-width": "1px",
+    "overflow": "hidden",
+    "text-overflow": "ellipsis",
+    "lines": "1",
+    "border-color": "transparent",
+    "color": "transparent",
+    "opacity": "0.15"
+  },
+  ".price-ctn[data-v-2c9fb3eb]": {
+    "position": "absolute",
+    "bottom": "11px",
+    "left": "6px",
+    "-webkit-box-orient": "horizontal",
+    "-webkit-box-direction": "normal",
+    "-webkit-flex-direction": "row",
+    "-ms-flex-direction": "row",
+    "flex-direction": "row",
+    "-webkit-box-align": "center",
+    "-webkit-align-items": "center",
+    "-ms-flex-align": "center",
+    "align-items": "center"
+  },
+  ".price-title[data-v-2c9fb3eb]": {
+    "font-size": "12px"
+  },
+  ".price-unit[data-v-2c9fb3eb]": {
+    "font-size": "12px",
+    "color": "#E71A17"
+  },
+  ".price-num[data-v-2c9fb3eb]": {
+    "margin-left": "-1px",
+    "color": "#E71A17",
+    "font-size": "15px",
+    "font-weight": "bold"
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/38f1a971/html5/test/render/vue/helper.js
----------------------------------------------------------------------
diff --git a/html5/test/render/vue/helper.js b/html5/test/render/vue/helper.js
deleted file mode 100644
index 26daac0..0000000
--- a/html5/test/render/vue/helper.js
+++ /dev/null
@@ -1,140 +0,0 @@
-import '../../../render/vue/styles/reset.css'
-import '../../../render/vue/styles/components.css'
-
-import '../../../render/browser/render/gesture'
-
-/* istanbul ignore next */
-import '../../../shared/arrayFrom'
-/* istanbul ignore next */
-import '../../../shared/objectAssign'
-/* istanbul ignore next */
-import '../../../shared/objectSetPrototypeOf'
-
-/* istanbul ignore next */
-import 'core-js/modules/es6.object.to-string'
-/* istanbul ignore next */
-import 'core-js/modules/es6.string.iterator'
-/* istanbul ignore next */
-import 'core-js/modules/web.dom.iterable'
-/* istanbul ignore next */
-import 'core-js/modules/es6.promise'
-
-/* istanbul ignore next */
-import Vue from 'vue/dist/vue.esm.js'
-// import { base, scrollable, style, inputCommon } from '../../../render/vue/mixins'
-import { base, style } from '../../../render/vue/mixins'
-import weex from '../../../render/vue/env/weex'
-
-/**
- * functional tools exported by helper.utils.
- */
-const utils = {
-  toArray (list) {
-    if (!list) return []
-    return Array.prototype.slice.call(list)
-  }
-}
-
-/**
- * Describe tests for current versions of Vue.
- */
-export function init (title, fn) {
-  return describe(title, () => {
-    let components = {}
-
-    before(function () {
-      const htmlRegex = /^html:/i
-      Vue.config.isReservedTag = tag => htmlRegex.test(tag)
-      Vue.config.parsePlatformTagName = tag => tag.replace(htmlRegex, '')
-
-      Vue.mixin(base)
-      Vue.mixin(style)
-
-      window.global = window
-      global.weex = weex
-    })
-
-    const helper = {
-
-      utils,
-      /**
-       * register a component.
-       * @param  {string} name,
-       * @param  {object} component.
-       */
-      register (name, component) {
-        components[name] = component
-      },
-
-      /**
-       * reset registered components with empty object.
-       */
-      reset () {
-        components = {}
-      },
-
-      /**
-       * create a vm instance of Vue.
-       * @param  {Object} options.
-       * @return {Vue} vue instance.
-       */
-      createVm (options = {}) {
-        options.components = components
-        return new Vue(options).$mount()
-      },
-
-      /**
-       * [compile description]
-       * @param  {[type]} template [description]
-       * @return {[type]}          [description]
-       */
-      compile (template) {
-        return helper.createVm({ template })
-      }
-    }
-
-    /**
-     * describe a vue-render test for certain vue verson.
-     */
-    describe(`Vue ${Vue.version}`, () => {
-      after(function () {
-        helper.reset()
-      })
-
-      fn(Vue, helper)
-    })
-  })
-}
-
-// import vue200 from './vender/vue-2.0.0.js'
-// import vue210 from './vender/vue-2.1.0.js'
-// const Vues = [
-//   vue200,
-//   vue210
-// ]
-/**
- * Describe tests for multiple versions of Vue.
- */
-// export function multiDescribe (title, fn) {
-//   return describe(title, () => {
-//     Vues.forEach(Vue => {
-//       let components = {}
-//       Vue.config.isReservedTag = function () { return false }
-//       describe(`Vue ${Vue.version}`, () => fn(Vue, {
-//         register (name, component) {
-//           components[name] = component
-//         },
-//         reset () {
-//           components = {}
-//         },
-//         createVm (options = {}) {
-//           options.components = components
-//           return new Vue(options).$mount()
-//         },
-//         compile (template) {
-//           return this.createVm({ template })
-//         }
-//       }))
-//     })
-//   })
-// }

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/38f1a971/html5/test/render/vue/helper/env.js
----------------------------------------------------------------------
diff --git a/html5/test/render/vue/helper/env.js b/html5/test/render/vue/helper/env.js
new file mode 100644
index 0000000..d972c0e
--- /dev/null
+++ b/html5/test/render/vue/helper/env.js
@@ -0,0 +1,20 @@
+import '../../../../render/vue/styles/reset.css'
+import '../../../../render/vue/styles/base.css'
+
+import '../../../../render/browser/render/gesture'
+
+/* istanbul ignore next */
+import '../../../../shared/arrayFrom'
+/* istanbul ignore next */
+import '../../../../shared/objectAssign'
+/* istanbul ignore next */
+import '../../../../shared/objectSetPrototypeOf'
+
+/* istanbul ignore next */
+import 'core-js/modules/es6.object.to-string'
+/* istanbul ignore next */
+import 'core-js/modules/es6.string.iterator'
+/* istanbul ignore next */
+import 'core-js/modules/web.dom.iterable'
+/* istanbul ignore next */
+import 'core-js/modules/es6.promise'

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/38f1a971/html5/test/render/vue/helper/index.js
----------------------------------------------------------------------
diff --git a/html5/test/render/vue/helper/index.js b/html5/test/render/vue/helper/index.js
new file mode 100644
index 0000000..425aa5c
--- /dev/null
+++ b/html5/test/render/vue/helper/index.js
@@ -0,0 +1,113 @@
+import './env'
+
+/* istanbul ignore next */
+import Vue from 'vue/dist/vue.esm.js'
+// import { base, scrollable, style, inputCommon } from '../../../render/vue/mixins'
+import { base, style } from '../../../../render/vue/mixins'
+import weex from '../../../../render/vue/env/weex'
+
+import * as utils from './utils'
+
+/**
+ * Describe tests for current versions of Vue.
+ */
+export function init (title, fn) {
+  return describe(title, () => {
+    let components = {}
+
+    before(function () {
+      const htmlRegex = /^html:/i
+      Vue.config.isReservedTag = tag => htmlRegex.test(tag)
+      Vue.config.parsePlatformTagName = tag => tag.replace(htmlRegex, '')
+
+      Vue.mixin(base)
+      Vue.mixin(style)
+
+      window.global = window
+      global.weex = weex
+    })
+
+    const helper = {
+
+      utils,
+      /**
+       * register a component.
+       * @param  {string} name,
+       * @param  {object} component.
+       */
+      register (name, component) {
+        components[name] = component
+      },
+
+      /**
+       * reset registered components with empty object.
+       */
+      reset () {
+        components = {}
+      },
+
+      /**
+       * create a vm instance of Vue.
+       * @param  {Object} options.
+       * @return {Vue} vue instance.
+       */
+      createVm (options = {}) {
+        options.components = components
+        return new Vue(options).$mount()
+      },
+
+      /**
+       * [compile description]
+       * @param  {[type]} template [description]
+       * @return {[type]}          [description]
+       */
+      compile (template) {
+        return helper.createVm({ template })
+      }
+    }
+
+    /**
+     * describe a vue-render test for certain vue verson.
+     */
+    describe(`Vue ${Vue.version}`, () => {
+      after(function () {
+        helper.reset()
+      })
+
+      fn(Vue, helper)
+    })
+  })
+}
+
+// import vue200 from './vender/vue-2.0.0.js'
+// import vue210 from './vender/vue-2.1.0.js'
+// const Vues = [
+//   vue200,
+//   vue210
+// ]
+/**
+ * Describe tests for multiple versions of Vue.
+ */
+// export function multiDescribe (title, fn) {
+//   return describe(title, () => {
+//     Vues.forEach(Vue => {
+//       let components = {}
+//       Vue.config.isReservedTag = function () { return false }
+//       describe(`Vue ${Vue.version}`, () => fn(Vue, {
+//         register (name, component) {
+//           components[name] = component
+//         },
+//         reset () {
+//           components = {}
+//         },
+//         createVm (options = {}) {
+//           options.components = components
+//           return new Vue(options).$mount()
+//         },
+//         compile (template) {
+//           return this.createVm({ template })
+//         }
+//       }))
+//     })
+//   })
+// }

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/38f1a971/html5/test/render/vue/helper/runtime.js
----------------------------------------------------------------------
diff --git a/html5/test/render/vue/helper/runtime.js b/html5/test/render/vue/helper/runtime.js
new file mode 100644
index 0000000..6f5ea17
--- /dev/null
+++ b/html5/test/render/vue/helper/runtime.js
@@ -0,0 +1,80 @@
+import './env'
+
+/* istanbul ignore next */
+import Vue from 'vue/dist/vue.runtime.esm.js'
+// import { base, scrollable, style, inputCommon } from '../../../render/vue/mixins'
+import { base, style } from '../../../../render/vue/mixins'
+import weex from '../../../../render/vue/env/weex'
+
+import * as utils from './utils'
+
+/**
+ * Describe tests for current versions of Vue.
+ */
+export function init (title, fn) {
+  return describe(title, () => {
+    let components = {}
+
+    before(function () {
+      const htmlRegex = /^html:/i
+      Vue.config.isReservedTag = tag => htmlRegex.test(tag)
+      Vue.config.parsePlatformTagName = tag => tag.replace(htmlRegex, '')
+
+      Vue.mixin(base)
+      Vue.mixin(style)
+
+      window.global = window
+      global.weex = weex
+    })
+
+    const helper = {
+
+      utils,
+      /**
+       * register a component.
+       * @param  {string} name,
+       * @param  {object} component.
+       */
+      register (name, component) {
+        components[name] = component
+      },
+
+      /**
+       * reset registered components with empty object.
+       */
+      reset () {
+        components = {}
+      },
+
+      /**
+       * create a vm instance of Vue.
+       * @param  {Object} options.
+       * @return {Vue} vue instance.
+       */
+      createVm (options = {}) {
+        options.components = components
+        return new Vue(options).$mount()
+      },
+
+      /**
+       * [compile description]
+       * @param  {[type]} template [description]
+       * @return {[type]}          [description]
+       */
+      compile (template) {
+        return helper.createVm({ template })
+      }
+    }
+
+    /**
+     * describe a vue-render test for certain vue verson.
+     */
+    describe(`Vue ${Vue.version}`, () => {
+      after(function () {
+        helper.reset()
+      })
+
+      fn(Vue, helper)
+    })
+  })
+}

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/38f1a971/html5/test/render/vue/helper/utils.js
----------------------------------------------------------------------
diff --git a/html5/test/render/vue/helper/utils.js b/html5/test/render/vue/helper/utils.js
new file mode 100644
index 0000000..11b2319
--- /dev/null
+++ b/html5/test/render/vue/helper/utils.js
@@ -0,0 +1,8 @@
+/**
+ * @fileOverview utils for tests.
+ */
+
+export function toArray (list) {
+  if (!list) return []
+  return Array.prototype.slice.call(list)
+}

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/38f1a971/html5/test/render/vue/utils.js
----------------------------------------------------------------------
diff --git a/html5/test/render/vue/utils.js b/html5/test/render/vue/utils.js
deleted file mode 100644
index 0a38e32..0000000
--- a/html5/test/render/vue/utils.js
+++ /dev/null
@@ -1,47 +0,0 @@
-import * as utils from '../../../render/vue/utils'
-
-describe('utils', function () {
-  it('cached', () => {
-    expect(utils.cached).to.be.a('function')
-  })
-
-  it('camelize', () => {
-    const { camelize } = utils
-    expect(camelize).to.be.a('function')
-    expect(camelize('')).to.be.equal('')
-    expect(camelize('dispaly')).to.be.equal('dispaly')
-    expect(camelize('-webkit-transform')).to.be.equal('WebkitTransform')
-    expect(camelize('text-overflow')).to.be.equal('textOverflow')
-    expect(camelize('a-b-c-d')).to.be.equal('aBCD')
-  })
-
-  it('capitalize', () => {
-    const { capitalize } = utils
-    expect(capitalize).to.be.a('function')
-    expect(capitalize('')).to.be.equal('')
-    expect(capitalize('string')).to.be.equal('String')
-    expect(capitalize('string object')).to.be.equal('String object')
-    expect(capitalize('[string object]')).to.be.equal('[string object]')
-    expect(capitalize('I have an apple')).to.be.equal('I have an apple')
-  })
-
-  it('hyphenate', () => {
-    const { hyphenate } = utils
-    expect(hyphenate).to.be.a('function')
-    expect(hyphenate('')).to.be.equal('')
-    expect(hyphenate('dispaly')).to.be.equal('dispaly')
-    expect(hyphenate('WebkitTransform')).to.be.equal('webkit-transform')
-    expect(hyphenate('textOverflow')).to.be.equal('text-overflow')
-    expect(hyphenate('aBCD')).to.be.equal('a-b-c-d')
-  })
-
-  it('extend', () => {
-    const { extend } = utils
-    expect(extend).to.be.a('function')
-
-    const abc = { name: 'abc' }
-    expect(extend(abc)).to.deep.equal(abc)
-    expect(extend(abc, { name: 'x' }) === abc).to.be.true
-    expect(abc).to.deep.equal({ name: 'x' })
-  })
-})

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/38f1a971/html5/test/render/vue/utils/func.js
----------------------------------------------------------------------
diff --git a/html5/test/render/vue/utils/func.js b/html5/test/render/vue/utils/func.js
new file mode 100644
index 0000000..17341f6
--- /dev/null
+++ b/html5/test/render/vue/utils/func.js
@@ -0,0 +1,50 @@
+import * as utils from '../../../../render/vue/utils'
+
+describe('utils', function () {
+  describe('function', function () {
+    it('cached', function () {
+      expect(utils.cached).to.be.a('function')
+    })
+
+    it('camelize', function () {
+      const { camelize } = utils
+      expect(camelize).to.be.a('function')
+      expect(camelize('')).to.be.equal('')
+      expect(camelize('dispaly')).to.be.equal('dispaly')
+      expect(camelize('-webkit-transform')).to.be.equal('WebkitTransform')
+      expect(camelize('text-overflow')).to.be.equal('textOverflow')
+      expect(camelize('a-b-c-d')).to.be.equal('aBCD')
+    })
+
+    it('capitalize', function () {
+      const { capitalize } = utils
+      expect(capitalize).to.be.a('function')
+      expect(capitalize('')).to.be.equal('')
+      expect(capitalize('string')).to.be.equal('String')
+      expect(capitalize('string object')).to.be.equal('String object')
+      expect(capitalize('[string object]')).to.be.equal('[string object]')
+      expect(capitalize('I have an apple')).to.be.equal('I have an apple')
+    })
+
+    it('hyphenate', function () {
+      const { hyphenate } = utils
+      expect(hyphenate).to.be.a('function')
+      expect(hyphenate('')).to.be.equal('')
+      expect(hyphenate('dispaly')).to.be.equal('dispaly')
+      expect(hyphenate('WebkitTransform')).to.be.equal('webkit-transform')
+      expect(hyphenate('textOverflow')).to.be.equal('text-overflow')
+      expect(hyphenate('aBCD')).to.be.equal('a-b-c-d')
+    })
+
+    it('extend', function () {
+      const { extend } = utils
+      expect(extend).to.be.a('function')
+
+      const abc = { name: 'abc' }
+      expect(extend(abc)).to.deep.equal(abc)
+      expect(extend(abc, { name: 'x' }) === abc).to.be.true
+      expect(abc).to.deep.equal({ name: 'x' })
+    })
+  })
+
+})