refactoring
diff --git a/.gitignore b/.gitignore
index a76bb72..074de94 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,3 @@
node_modules
lib
-
-test/actual
-test/expect/*.js
+test/actual/*.js
\ No newline at end of file
diff --git a/README.md b/README.md
index 073d86a..321c3a2 100644
--- a/README.md
+++ b/README.md
@@ -5,16 +5,16 @@
## Install
```
-npm install weex-loader --save
+npm install weex-loader babel-loader babel-preset-es2015 babel-runtime babel-plugin-transform-runtime --save
```
## Feature
0. Can load `.we` file.
-1. Can load parted files(`.js/.css/.tpl`) instead of one `.we` file.
-2. Can chain any loader you want when write parted files.
-3. Can require a CommonJS module.
-4. Can specify the name of a component.
+1. Can load parted files(`.js/.css/.html`) via a `src` attribute.
+2. Can specify a custom language to chain any loader.
+3. Can specify name when require `.we` file.
+4. Can write es2015 in script.
## Usage
@@ -45,18 +45,17 @@
### How to write parted files
-#### write .js/.css/.tpl anywhere
+#### write .js/.css/.html anywhere
**main.js as script**
```javascript
module.exports = {
- data: {
+ data: function () {
+ return {
text: 'Hello World'
+ }
}
}
-
-module.exports.style = require('./main.css');
-module.exports.template = require('./main.tpl');
```
**main.css as style**
@@ -64,46 +63,40 @@
.h1 {
font-size: 60px;
color: red;
- padding-top: 20px;
- padding-bottom: 20px;
- padding-left: 20px;
- padding-right: 20px;
}
```
-**main.tpl as template**
+**main.html as template**
```html
-<container>
+<div>
<text class="h1">{{text}}</text>
-</container>
+</div>
```
-Then change the entry to `main.js` in `webpack.config.js`
+**main.we**
+```html
+<template src="./main.html"></template>
+<style src="./main.css"></style>
+<script src="./main.js"></script>
+```
-#### add some loader in webpack config
+#### add some custom language for loaders
-**loader for script**
+**append a weex config in webpack config**
```javascript
- {
- test: /\.js(\?[^?]+)?$/,
- loader: 'weex?type=script'
+ weex: {
+ lang: {
+ jade: ['jade-html'] // a jade langauge will chain "jade-html-loader"
+ }
}
```
-**loader for style**
-```javascript
- {
- test: /\.css(\?[^?]+)?$/,
- loader: 'weex?type=style'
- }
+**main.we**
```
-
-**loader for template**
-```javascript
- {
- test: /\.tpl(\?[^?]+)?$/,
- loader: 'weex?type=tpl'
- }
+<template lang="jade">
+div
+ text Hello Weex
+</template>
```
### How to require a CommonJS module
@@ -111,41 +104,45 @@
0. first, require a `path/to/module.js` in `script` like `var _ = require('lodash')`.
1. then use it in `script`.
-### How to embed a composed component
+### How to require `.we` file as component element
-0. first, require a `path/to/component.js` in `script` like `require('./sub.js')`.
-1. second, use it in `template` like `<sub></sub>`.
+0. first, require a `path/to/component.we` in `script` like `require('./foo.we')` or write inline element like `<element name="foo" src="./foo.we"></element>`.
+1. second, use it in `template` like `<foo></foo>`.
+
+```
+<element name="foo" src="./foo.we"></element>
+
+<template>
+ <div>
+ <foo></foo>
+ <bar></bar>
+ </div>
+</template>
+
+<script>
+ require('./bar.we')
+</script>
+```
### How to specify the name of a component
0. By default, the name is the basename without extname of component path.
-1. Give a name query in require request, like `require('./sub.js?name="goto"')`
-2. use the name in `template` like `<goto></goto>`.
+1. Give a name query in require request, like `require('./foo.we?name="fooo"')`. Or specify a name attribute in element, like `<element name="fooo" src="./foo.we" ></element>`
+2. use the name in `template` like `<fooo></fooo>`.
-## Chain your favorite loader
-
-For examples:
-
-### write ES2015
-
-Only your need is chain babel-loader before weex-loader.
-
-```javascript
- {
- test: /\.js(\?[^?]+)?$/,
- loader: 'weex?type=script!babel?presets[]=es2015'
- }
```
+<element name="fooo" src="./foo.we"></element>
-### write SCSS
+<template>
+ <div>
+ <fooo></fooo>
+ <barr></barr>
+ </div>
+</template>
-Only your need is chain scss loader before weex-loader.
-
-```javascript
- {
- test: /\.scss(\?[^?]+)?$/,
- loader: 'weex?type=style!scss'
- }
+<script>
+ require('./bar.we?name=barr')
+</script>
```
## Test
@@ -154,8 +151,3 @@
npm run test
```
will run mocha testing
-
-```bash
-npm run serve
-```
-then open `localhost:12581` on chrome, will run web testing
diff --git a/circle.yml b/circle.yml
index 1bd54b3..fe46540 100644
--- a/circle.yml
+++ b/circle.yml
@@ -1,3 +1,3 @@
machine:
node:
- version: 4.2.1
+ version: 4
diff --git a/index.js b/index.js
index 9615572..18abae3 100644
--- a/index.js
+++ b/index.js
@@ -1 +1 @@
-module.exports = require('./lib/')
+module.exports = require('./lib/loader')
diff --git a/package.json b/package.json
index 2878299..70df19e 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "weex-loader",
- "version": "0.2.0",
+ "version": "0.3.0-alpha",
"description": "a webpack loader for weex",
"main": "index.js",
"author": "terrykingcha <terrykingcha@gmail.com>",
@@ -16,29 +16,30 @@
"transformer"
],
"scripts": {
- "prepublish": "node_modules/babel-cli/bin/babel.js src --out-dir lib",
- "test:lint": "eslint src",
+ "clear": "rm -f lib/* && rm -f test/actual/*",
+ "lint": "eslint --fix src",
+ "build": "node_modules/babel-cli/bin/babel.js src --out-dir lib",
"test:build": "webpack --config test/webpack.config.js",
- "test:transform": "transformer test/expect/*.we -o test/expect",
"test:mocha": "mocha test/test.js",
- "test": "npm run prepublish && npm run test:lint && npm run test:build && npm run test:transform && npm run test:mocha",
- "serve": "serve ./test -p 12581",
- "prebuild": "rm -f lib/* && node_modules/babel-cli/bin/babel.js src --out-dir lib",
- "build": "webpack --config test/webpack.config.js"
+ "pretest": "npm run clear && npm run lint && npm run build",
+ "test": "npm run test:build && npm run test:mocha",
+ "ci": "npm run test",
+ "prepublish": "npm run clear && npm run lint && npm run build"
},
"devDependencies": {
"babel-cli": "^6.10.1",
"babel-core": "^6.10.4",
"babel-loader": "^6.2.4",
+ "babel-plugin-transform-runtime": "^6.9.0",
"babel-preset-es2015": "^6.9.0",
+ "babel-runtime": "^6.9.2",
"chai": "^3.5.0",
"eslint": "^2.13.1",
- "less": "^2.6.1",
- "less-loader": "^2.2.3",
- "memory-fs": "^0.3.0",
+ "jade-html-loader": "0.0.3",
"mocha": "^2.4.5",
"parse5": "^2.1.5",
- "serve": "^1.4.0",
+ "postcss-cssnext": "^2.7.0",
+ "postcss-loader": "^0.9.1",
"sinon": "^1.17.3",
"sinon-chai": "^2.8.0",
"webpack": "~1.13.0"
diff --git a/src/config.js b/src/config.js
index c1e9e30..ded0c99 100644
--- a/src/config.js
+++ b/src/config.js
@@ -1,3 +1 @@
-import pkg from '../package.json'
-export const transformerVersion = pkg.dependencies['weex-transformer'].match(/\d+(?:\.\d+){0,2}/)[0]
export const logLevel = false
diff --git a/src/element.js b/src/element.js
new file mode 100644
index 0000000..378a261
--- /dev/null
+++ b/src/element.js
@@ -0,0 +1,34 @@
+import loaderUtils from 'loader-utils'
+
+import {
+ extractBlocks
+} from './parser'
+
+module.exports = function (source) {
+ this.cacheable && this.cacheable()
+
+ const callback = this.async()
+ const loaderQuery = loaderUtils.parseQuery(this.query)
+ const resourceQuery = loaderUtils.parseQuery(this.resourceQuery)
+ const name = resourceQuery.name
+
+ let contentPromise
+
+ if (loaderQuery.extract) {
+ contentPromise =
+ extractBlocks(source, 'elements')
+ }
+ else {
+ contentPromise = Promise.resolve({ content: source })
+ }
+
+ contentPromise.then(elements => {
+ if (loaderQuery.raw) {
+ return elements[name].content
+ }
+ }).then(result => {
+ callback(null, result)
+ }).catch(e => {
+ callback(e, '')
+ })
+}
diff --git a/src/extract.js b/src/extract.js
new file mode 100644
index 0000000..28485b5
--- /dev/null
+++ b/src/extract.js
@@ -0,0 +1,32 @@
+import loaderUtils from 'loader-utils'
+
+import {
+ extractBlocks
+} from './parser'
+
+module.exports = function (source) {
+ this.cacheable && this.cacheable()
+
+ const callback = this.async()
+ const loaderQuery = loaderUtils.parseQuery(this.query)
+ const type = loaderQuery.type
+ let index = loaderQuery.index
+
+ if (index != null && index.match(/^\d+$/)) {
+ index = parseInt(index)
+ }
+
+ extractBlocks(source, type)
+ .then(result => {
+ if (index != null) {
+ return result[index].content
+ }
+ else {
+ return result.content
+ }
+ }).then(result => {
+ callback(null, result)
+ }).catch(e => {
+ callback(e, '')
+ })
+}
diff --git a/src/html-loader.js b/src/html-loader.js
deleted file mode 100644
index 20ae43f..0000000
--- a/src/html-loader.js
+++ /dev/null
@@ -1,61 +0,0 @@
-import loaderUtils from 'loader-utils'
-import blocker from 'weex-transformer/lib/blocker'
-import templater from 'weex-templater'
-
-import {
- FUNC_START_REG,
- FUNC_END_REG,
- stringifyFunction
-} from './util'
-
-function extrackBlock (source, type) {
- return new Promise((resolve, reject) => {
- blocker.format(source, (err, ret) => {
- if (err) {
- reject(err)
- } else {
- resolve(ret[type])
- }
- })
- })
-}
-
-function parseTemplate (source) {
- return new Promise((resolve, reject) => {
- templater.parse(source, (err, obj) => {
- if (err) {
- reject(err)
- } else {
- // parse json to string and treat function specially
- let target = JSON.stringify(obj.jsonTemplate, stringifyFunction, ' ')
- target = target.replace(FUNC_START_REG, '').replace(FUNC_END_REG, '')
- resolve(target)
- }
- })
- })
-}
-
-module.exports = function(source) {
- this.cacheable && this.cacheable()
- const callback = this.async()
-
- const params = {
- loaderQuery: loaderUtils.parseQuery(this.query),
- resourceQuery: loaderUtils.parseQuery(this.resourceQuery),
- resourcePath: this.resourcePath
- }
-
- extrackBlock(source, 'template')
- .then(template => {
- if (params.loaderQuery.extract) {
- return parseTemplate(template.content)
- } else if (params.loaderQuery.raw) {
- callback(null, template.content)
- }
- }).then(result => {
- result = `module.exports = ${result}\n`
- callback(null, result)
- }).catch(e => {
- callback(e, '')
- })
-}
\ No newline at end of file
diff --git a/src/index.js b/src/index.js
deleted file mode 100644
index fbec04e..0000000
--- a/src/index.js
+++ /dev/null
@@ -1,70 +0,0 @@
-import loaderUtils from 'loader-utils'
-
-import {
- parseScript,
- parseStyle,
- parseTemplate,
- parseWeexFile
-} from './parser'
-import * as config from './config'
-import * as legacy from './legacy'
-
-function partedLoader (type, loader, params, source) {
- let promise
- switch (type) {
- case 'js':
- case 'script':
- const transformerVersion = config.transformerVersion
- promise = parseScript(loader, params, source,
- { config: JSON.stringify({ transformerVersion }) })
- break
- case 'css':
- case 'style':
- promise = parseStyle(loader, params, source)
- break
- case 'html':
- case 'tpl':
- case 'template':
- promise = parseTemplate(loader, params, source)
- break
- case 'we':
- default:
- promise = parseWeexFile(loader, params, source)
- break
- }
- return promise
-}
-
-function loader (source) {
- this.cacheable && this.cacheable()
-
- const callback = this.async()
- const params = {
- loaderQuery: loaderUtils.parseQuery(this.query),
- resourceQuery: loaderUtils.parseQuery(this.resourceQuery),
- resourcePath: this.resourcePath
- }
- const type = params.loaderQuery.type || 'we'
- const promise = partedLoader(type, this, params, source)
-
- promise.then(result => {
- if (type === 'style' || type === 'css' ||
- type === 'html' || type === 'tpl' || type === 'template') {
- result = 'module.exports=' + result
- }
- callback(null, result)
- }).catch(err => {
- this.emitError(err.toString())
- callback(err.toString(), '')
- })
-}
-
-loader.setLogLevel = level => {
- config.logLevel = level
-}
-
-for (const key in legacy) {
- loader[key] = legacy[key]
-}
-
-module.exports = loader
diff --git a/src/json.js b/src/json.js
new file mode 100644
index 0000000..59c2977
--- /dev/null
+++ b/src/json.js
@@ -0,0 +1,5 @@
+module.exports = function (source) {
+ this.cacheable && this.cacheable()
+
+ return `module.exports = ${source}`
+}
diff --git a/src/loader.js b/src/loader.js
index a6f03cf..674cd65 100644
--- a/src/loader.js
+++ b/src/loader.js
@@ -1,120 +1,379 @@
import loaderUtils from 'loader-utils'
import path from 'path'
-import parse5 from 'parse5'
+import fs from 'fs'
import md5 from 'md5'
+import * as config from './config'
+import * as legacy from './legacy'
import {
- getNameByPath
+ parseFragment
+} from './parser'
+import {
+ getNameByPath,
+ getRequireString,
+ stringifyLoaders
} from './util'
const loaderPath = __dirname
-
-function getRequire(loaderContext, loader, filepath) {
- return 'require(' +
- loaderUtils.stringifyRequest(
- loaderContext,
- `!!${loader}!${filepath}`
- ) +
- ')\n'
+const defaultLoaders = {
+ main: path.resolve(loaderPath, 'loader.js'),
+ extract: path.resolve(loaderPath, 'extract.js'),
+ template: path.resolve(loaderPath, 'template.js'),
+ style: path.resolve(loaderPath, 'style.js'),
+ script: path.resolve(loaderPath, 'script.js'),
+ json: path.resolve(loaderPath, 'json.js'),
+ babel: 'babel-loader'
}
-function getAttribute (node, name) {
- if (node.attrs) {
- var i = node.attrs.length
- var attr
- while (i--) {
- attr = node.attrs[i]
- if (attr.name === name) {
- return attr.value
+function getLoaderString (type, config) {
+ config = config || {}
+ let customLoader
+ let loaders
+
+ if (config.lang && config.customLang[config.lang]) {
+ customLoader = config.customLang[config.lang]
+ }
+
+ if (type === 'main') {
+ loaders = [{
+ name: defaultLoaders.main
+ }]
+ return stringifyLoaders(loaders)
+ }
+
+ if (type === 'element') {
+ loaders = [{
+ name: defaultLoaders.main,
+ query: {
+ element: config.source ? undefined : true
+ }
+ }]
+ if (!config.source) {
+ loaders.push({
+ name: defaultLoaders.extract,
+ query: {
+ index: config.name,
+ type: 'elements'
+ }
+ })
+ }
+ return stringifyLoaders(loaders)
+ }
+
+ if (type === 'template') {
+ loaders = [{
+ name: defaultLoaders.template
+ }]
+ if (customLoader) {
+ loaders = loaders.concat(customLoader)
+ }
+ if (!config.source) {
+ loaders.push({
+ name: defaultLoaders.extract,
+ query: {
+ type: 'template'
+ }
+ })
+ }
+ if (config.element) {
+ loaders.push({
+ name: defaultLoaders.extract,
+ query: {
+ index: config.elementName,
+ type: 'elements'
+ }
+ })
+ }
+ return stringifyLoaders(loaders)
+ }
+
+ if (type === 'style') {
+ loaders = [{
+ name: defaultLoaders.style
+ }]
+ if (customLoader) {
+ loaders = loaders.concat(customLoader)
+ }
+ if (!config.source) {
+ loaders.push({
+ name: defaultLoaders.extract,
+ query: {
+ index: 0,
+ type: 'styles'
+ }
+ })
+ }
+ if (config.element) {
+ loaders.push({
+ name: defaultLoaders.extract,
+ query: {
+ index: config.elementName,
+ type: 'elements'
+ }
+ })
+ }
+ return stringifyLoaders(loaders)
+ }
+
+ if (type === 'script') {
+ loaders = [{
+ name: defaultLoaders.script
+ }]
+ if (customLoader) {
+ loaders = loaders.concat(customLoader)
+ }
+ else {
+ loaders.push({
+ name: defaultLoaders.babel,
+ query: {
+ presets: ['es2015'],
+ plugins: ['transform-runtime'],
+ comments: 'false'
+ }
+ })
+ }
+ if (!config.source) {
+ loaders.push({
+ name: defaultLoaders.extract,
+ query: {
+ index: 0,
+ type: 'scripts'
+ }
+ })
+ }
+ if (config.element) {
+ loaders.push({
+ name: defaultLoaders.extract,
+ query: {
+ index: config.elementName,
+ type: 'elements'
+ }
+ })
+ }
+ return stringifyLoaders(loaders)
+ }
+
+ if (type === 'config') {
+ loaders = [{
+ name: defaultLoaders.json
+ }]
+ if (!config.source) {
+ loaders.push({
+ name: defaultLoaders.extract,
+ query: {
+ type: 'config'
+ }
+ })
+ }
+ return stringifyLoaders(loaders)
+ }
+
+ if (type === 'data') {
+ loaders = [{
+ name: defaultLoaders.json
+ }]
+ if (!config.source) {
+ loaders.push({
+ name: defaultLoaders.extract,
+ query: {
+ type: 'data'
+ }
+ })
+ }
+ return stringifyLoaders(loaders)
+ }
+}
+
+function loader (source) {
+ this.cacheable && this.cacheable()
+
+ const options = this.options.weex || {}
+ const customLang = options.lang || {}
+
+ const loaderQuery = loaderUtils.parseQuery(this.query)
+ const resourceQuery = loaderUtils.parseQuery(this.resourceQuery)
+ const resourcePath = this.resourcePath
+ const isElement = loaderQuery.element
+ const isEntry = resourceQuery.entry
+ const name = isEntry ? md5(resourcePath) :
+ (resourceQuery.name ||
+ getNameByPath(resourcePath))
+
+ let output = ''
+
+ const frag = parseFragment(source)
+
+ const elementNames = []
+ if (frag.element.length) {
+ for (let i = 0; i < frag.element.length; i++) {
+ const element = frag.element[i]
+ if (!element.name) {
+ this.emitError('Element block need a name attribute')
+ return ''
+ }
+ elementNames.push(element.name)
+
+ let src = resourcePath
+ if (element.src) {
+ src = element.src
+ }
+
+ output += getRequireString(
+ this,
+ getLoaderString('element', {
+ customLang,
+ name: element.name,
+ source: element.src
+ }),
+ `${src}?name=${element.name}`
+ )
+ }
+ }
+
+ if (frag.deps.length) {
+ for (const dep of frag.deps) {
+ const filepath = path.resolve(path.dirname(resourcePath), `${dep}.we`)
+ if (elementNames.indexOf(dep) < 0
+ && fs.existsSync(filepath)) {
+ output += getRequireString(
+ this,
+ getLoaderString('main'),
+ `./${dep}.we`
+ )
}
}
}
-}
-function parse(source) {
-
- const fragment = parse5.parseFragment(source, {
- locationInfo: true
- })
-
- const output = {
- template: [],
- style: [],
- script: []
+ if (!frag.template.length) {
+ this.emitError('Template block is required')
+ return ''
+ }
+ else {
+ const template = frag.template[0]
+ let src = resourcePath
+ if (template.src) {
+ src = template.src
+ }
+ output += 'var __weex_template__ = ' +
+ getRequireString(
+ this,
+ getLoaderString('template', {
+ customLang,
+ lang: template.lang,
+ element: isElement,
+ elementName: isElement ? name : undefined,
+ source: template.src
+ }),
+ src
+ )
}
- fragment.childNodes.forEach(node => {
- const type = node.tagName
-
- if (!output[type]) {
- return
+ if (frag.style.length) {
+ const style = frag.style[0]
+ let src = resourcePath
+ if (style.src) {
+ src = style.src
}
+ output += 'var __weex_style__ = ' +
+ getRequireString(
+ this,
+ getLoaderString('style', {
+ customLang,
+ lang: style.lang,
+ element: isElement,
+ elementName: isElement ? name : undefined,
+ source: style.src
+ }),
+ src
+ )
+ }
- const lang = getAttribute(node, 'lang')
- const src = getAttribute(node, 'src')
+ if (frag.script.length) {
+ const script = frag.script[0]
+ let src = resourcePath
+ if (script.src) {
+ src = script.src
+ }
+ output += 'var __weex_script__ = ' +
+ getRequireString(
+ this,
+ getLoaderString('script', {
+ customLang,
+ lang: script.lang,
+ element: isElement,
+ elementName: isElement ? name : undefined,
+ source: script.src
+ }),
+ src
+ )
+ }
- output[type].push({
- lang,
- src
- })
- })
+ if (isEntry && frag.data.length) {
+ const data = frag.data[0]
+ let src = resourcePath
+ if (data.src) {
+ src = data.src
+ }
+ output += 'var __weex_data__ = ' +
+ getRequireString(
+ this,
+ getLoaderString('data', {
+ source: data.src
+ }),
+ src
+ )
+ }
+
+ if (isEntry && frag.config.length) {
+ const config = frag.config[0]
+ let src = resourcePath
+ if (config.src) {
+ src = config.src
+ }
+ output += 'var __weex_config__ = ' +
+ getRequireString(
+ this,
+ getLoaderString('config', {
+ source: config.src
+ }),
+ src
+ )
+ }
+
+ output += `
+__weex_define__('@weex-component/${name}', [], function(__weex_require__, __weex_exports__, __weex_module__) {
+` + (
+ frag.script.length > 0 ? `
+ __weex_script__(__weex_require__, __weex_exports__, __weex_module__)
+` : ''
+) +
+`
+ __weex_module__.exports = __weex_module__.exports || {}
+ __weex_module__.exports.template = __weex_template__
+` + (
+ frag.style.length > 0 ? `
+ __weex_module__.exports.style = __weex_style__
+` : ''
+) + `
+})
+`
+ if (isEntry) {
+ output += `
+__weex_bootstrap__('@weex-component/${name}'`
+ + (frag.config.length > 0 ? `,__weex_config__` : ',undefined')
+ + (frag.data.length > 0 ? `,__weex_data__` : ',undefined')
++ `)`
+ }
return output
}
-module.exports = function(source) {
- this.cacheable && this.cacheable()
+loader.setLogLevel = level => {
+ config.logLevel = level
+}
- const defaultLoaders = {
- main: path.resolve(loaderPath, 'loader.js'),
- template: path.resolve(loaderPath, 'html-loader.js?extract'),
- style: path.resolve(loaderPath, 'style-loader.js?extract'),
- script: path.resolve(loaderPath, 'script-loader.js?extract')
- }
- const options = this.options.weex || {}
- const loaders = Object.assign({}, defaultLoaders, options.loaders || {})
- const loaderQuery = loaderUtils.parseQuery(this.query)
- const resourceQuery = loaderUtils.parseQuery(this.resourceQuery)
- const resourcePath = this.resourcePath
- const isEntry = resourceQuery.entry
- const name = isEntry ? md5(resourcePath) :
- resourceQuery.name || getNameByPath(resourcePath)
+for (const key in legacy) {
+ loader[key] = legacy[key]
+}
- let output = '';
-
- const parts = parse(source)
-
- if (parts.template.length) {
- const template = parts.template[0]
- output += 'var __weex_template__ = ' + getRequire(this, loaders['template'], resourcePath)
- }
-
- if (parts.style.length) {
- const style = parts.style[0]
- output += 'var __weex_style__ = ' + getRequire(this, loaders['style'], resourcePath)
- }
-
- if (parts.script.length) {
- const script = parts.script[0]
- output += 'var __weex_script__ = ' + getRequire(this, loaders['script'], resourcePath)
- }
-
-
-
- output += `
-__weex_define__('@weex-component/${name}', [], function(__weex_require__, __weex_exports__, __weex_module__) {
- __weex_module__.exports = Object.assign({}, __weex_script__, {
- template: __weex_template__,
- style: __weex_style__
- })
-})\n
-`
- if (isEntry) {
- output += `
-__weex_bootstrap__('@weex-component/${name}')\n
-`
- }
-
- return output;
-
-}
\ No newline at end of file
+module.exports = loader
diff --git a/src/parser.js b/src/parser.js
index ac1dd76..3b8ad50 100644
--- a/src/parser.js
+++ b/src/parser.js
@@ -1,211 +1,141 @@
+import parse5 from 'parse5'
import blocker from 'weex-transformer/lib/blocker'
import templater from 'weex-templater'
import styler from 'weex-styler'
import scripter from 'weex-scripter'
+import { checkTagName } from 'weex-templater/lib/validator'
-import md5 from 'md5'
-
-import { transformerVersion } from './config'
import {
- MODULE_EXPORTS_REG,
- REQUIRE_REG,
FUNC_START_REG,
FUNC_END_REG,
- getNameByPath,
- checkFileExist,
- depHasRequired,
- stringifyFunction,
- appendToWarn
+ stringifyFunction
} from './util'
-export function parseWeexFile (loader, params, source, deps, elementName) {
- return new Promise(
- // separate source into <element>s, <template>, <style>s and <script>s
- separateBlocks(source, deps || []))
- // pre-parse non-javascript parts
- .then(preParseBlocks(loader, params, elementName))
- // join blocks together and parse as javascript finally
- .then(parseBlocks(loader, params, elementName))
+function getAttribute (node, name) {
+ if (node.attrs) {
+ let i = node.attrs.length
+ let attr
+ while (i--) {
+ attr = node.attrs[i]
+ if (attr.name === name) {
+ return attr.value
+ }
+ }
+ }
}
-function separateBlocks (source, deps) {
- return (resolve, reject) => {
+function extractDependencies (node, deps) {
+ if (node.childNodes) {
+ node.childNodes.forEach(child => {
+ checkTagName(child, {
+ result: {},
+ deps,
+ log: []
+ })
+ extractDependencies(child, deps)
+ })
+ }
+}
+
+export function parseFragment (source) {
+ const fragment = parse5.parseFragment(source, {
+ locationInfo: true
+ })
+
+ const output = {
+ deps: [],
+ element: [],
+ template: [],
+ style: [],
+ script: [],
+ data: [],
+ config: []
+ }
+
+ fragment.childNodes.forEach(node => {
+ let type
+
+ if (node.tagName === 'script') {
+ type = getAttribute(node, 'type')
+ if (type !== 'data' && type !== 'config') {
+ type = 'script'
+ }
+ }
+ else {
+ type = node.tagName
+ }
+
+ if (!output[type]) {
+ return
+ }
+
+ const name = getAttribute(node, 'name')
+ const src = getAttribute(node, 'src')
+ const lang = getAttribute(node, 'lang')
+
+ output[type].push({
+ name,
+ src,
+ lang,
+ node
+ })
+
+ if (type === 'template') {
+ const deps = []
+ extractDependencies(node.content, deps)
+ output.deps = deps
+ }
+ })
+
+ return output
+}
+
+export function extractBlocks (source, type) {
+ return new Promise((resolve, reject) => {
blocker.format(source, (err, ret) => {
if (err) {
reject(err)
}
else {
- ret.deps = deps
- resolve(ret)
+ resolve(ret[type])
}
})
- }
+ })
}
-function preParseBlocks (loader, params) {
- return (blocks) => {
- const { deps, elements, template, styles, scripts, config, data } = blocks
- const promises = [
- Promise.resolve(),
- Promise.resolve(),
- Promise.resolve(),
- Promise.resolve(scripts),
- Promise.resolve(deps),
- Promise.resolve(config),
- Promise.resolve(data)
- ]
- let content
- // pre-parse sub elements
- if (elements) {
- const elPromises = []
- Object.keys(elements).forEach(key => {
- const el = elements[key]
- elPromises.push(parseWeexFile(loader, params, el.content, deps, el.name))
- })
- promises[0] = Promise.all(elPromises)
- }
- // pre-parse template
- if (template) {
- content = template.content
- promises[1] = parseTemplate(loader, params, content, deps)
- }
- // pre-parse styles
- if (styles) {
- content = styles.reduce((pre, cur) => {
- return pre + '\n' + cur.content
- }, '')
- promises[2] = parseStyle(loader, params, content)
- }
- return Promise.all(promises)
- }
-}
-
-function parseBlocks (loader, params, elementName) {
- return (results) => {
- const elements = results[0] || []
- const template = results[1]
- const style = results[2]
- const scripts = results[3]
- const deps = results[4] || []
- const configResult = results[5]
- const dataResult = results[6]
-
- let content = ''
- let config = {}
- let data
-
- if (scripts) {
- content += scripts.reduce((pre, cur) => {
- return pre + '\n;' + cur.content
- }, '')
- }
-
- let requireContent = ''
- if (deps.length) {
- requireContent += deps.map(dep =>
- depHasRequired(content, dep) ? 'require("' + dep + '");' : ''
- ).join('\n')
- content = requireContent + '\n' + content
- }
-
- if (template) {
- content += '\n;module.exports.template = module.exports.template || {}' +
- '\n;Object.assign(module.exports.template, ' + template + ')'
- }
-
- if (style) {
- content += '\n;module.exports.style = module.exports.style || {}' +
- '\n;Object.assign(module.exports.style, ' + style + ')'
- }
-
- if (configResult) {
- config = new Function('return ' + configResult.content.replace(/\n/g, ''))()
- }
- config.transformerVersion = transformerVersion
- config = JSON.stringify(config, null, 2)
-
- if (dataResult) {
- data = new Function('return ' + dataResult.content.replace(/\n/g, ''))()
- data = JSON.stringify(data, null, 2)
- }
-
- return parseScript(loader, params, content, { config, data, elementName, elements })
- }
-}
-
-export function parseTemplate (loader, params, source, deps) {
+export function parseTemplate (source) {
return new Promise((resolve, reject) => {
templater.parse(source, (err, obj) => {
if (err) {
reject(err)
}
else {
- appendToWarn(loader, obj.log)
- // push valid obj.deps to deps
- if (deps && obj.deps) {
- obj.deps.map(
- dep => checkFileExist(dep, params.resourcePath)
- ).forEach(dep => {
- if (dep) {
- deps.push(dep)
- }
- })
- }
// parse json to string and treat function specially
- let target = JSON.stringify(obj.jsonTemplate, stringifyFunction, ' ')
- target = target.replace(FUNC_START_REG, '').replace(FUNC_END_REG, '')
- resolve(target)
+ let parsed = JSON.stringify(obj.jsonTemplate, stringifyFunction, ' ')
+ parsed = parsed.replace(FUNC_START_REG, '').replace(FUNC_END_REG, '')
+ resolve({ parsed, log: obj.log })
}
})
})
}
-export function parseStyle (loader, params, source) {
+export function parseStyle (source) {
return new Promise((resolve, reject) => {
styler.parse(source, (err, obj) => {
if (err) {
reject(err)
}
else {
- appendToWarn(loader, obj.log)
- resolve(JSON.stringify(obj.jsonStyle, null, 2))
+ const parsed = JSON.stringify(obj.jsonStyle, null, 2)
+ resolve({ parsed, log: obj.log })
}
})
})
}
-export function parseScript (loader, params, source, env) {
- const { config, data, elementName, elements } = env
-
- // the entry component has a special resource query and not a sub element tag
- const isEntry = params.resourceQuery.entry === true && !elementName
-
- // resolve component name
- const name = isEntry
- ? md5(source)
- : (elementName || params.resourceQuery.name || getNameByPath(params.resourcePath))
-
- // fix data option from an object to a function
- let target = scripter.fix(source)
-
- // wrap with __weex_define__(name, [], (r, e, m) {...})
- target = target
- .replace(MODULE_EXPORTS_REG, '__weex_module__.exports')
- .replace(REQUIRE_REG, '__weex_require__($1$2$1)')
- target = ';__weex_define__("@weex-component/' + name + '", [], ' +
- 'function(__weex_require__, __weex_exports__, __weex_module__)' +
- '{\n' + target + '\n})'
-
- // append __weex_bootstrap__ for entry component
- if (isEntry) {
- target += '\n;__weex_bootstrap__("@weex-component/' + name + '", ' +
- String(config) + ',' +
- String(data) + ')'
- }
-
- // join with elements deps
- target = (elements || []).concat(target).join(';\n\n')
-
- return Promise.resolve(target)
+export function parseScript (source) {
+ return new Promise((resolve, reject) => {
+ const parsed = scripter.fix(source)
+ resolve({ parsed })
+ })
}
-
diff --git a/src/script-loader.js b/src/script-loader.js
deleted file mode 100644
index 8874f4a..0000000
--- a/src/script-loader.js
+++ /dev/null
@@ -1,51 +0,0 @@
-import loaderUtils from 'loader-utils'
-import blocker from 'weex-transformer/lib/blocker'
-import scripter from 'weex-scripter'
-
-import {
- FUNC_START_REG,
- FUNC_END_REG,
- stringifyFunction
-} from './util'
-
-function extrackBlock (source, type) {
- return new Promise((resolve, reject) => {
- blocker.format(source, (err, ret) => {
- if (err) {
- reject(err)
- } else {
- resolve(ret[type])
- }
- })
- })
-}
-
-function parseScript(source) {
- return new Promise((resolve, reject) => {
- resolve(scripter.fix(source))
- })
-}
-
-module.exports = function(source) {
- this.cacheable && this.cacheable()
- const callback = this.async()
-
- const params = {
- loaderQuery: loaderUtils.parseQuery(this.query),
- resourceQuery: loaderUtils.parseQuery(this.resourceQuery),
- resourcePath: this.resourcePath
- }
-
- extrackBlock(source, 'scripts')
- .then(scripts => {
- if (params.loaderQuery.extract) {
- return parseScript(scripts[0].content)
- } else if (params.loaderQuery.raw) {
- callback(null, scripts[0].content)
- }
- }).then(result => {
- callback(null, result)
- }).catch(e => {
- callback(e, '')
- })
-}
\ No newline at end of file
diff --git a/src/script.js b/src/script.js
new file mode 100644
index 0000000..b0456a5
--- /dev/null
+++ b/src/script.js
@@ -0,0 +1,34 @@
+import {
+ parseScript
+} from './parser'
+
+module.exports = function (source) {
+ this.cacheable && this.cacheable()
+
+ const callback = this.async()
+
+ parseScript(source)
+ .then(({ parsed }) => {
+ let requireList = parsed.match(/require\([^()]+?\)/g)
+
+ if (requireList && requireList.length > 0) {
+ requireList = requireList.filter(str => {
+ if (str.indexOf('@weex-module') < 0) {
+ parsed = parsed.replace(str, '')
+ return true
+ }
+ return false
+ }).join('\n')
+ }
+
+ const result = `
+${requireList || ''}
+module.exports = function(require, exports, module){
+ ${parsed}
+}
+`
+ callback(null, result)
+ }).catch(e => {
+ callback(e, '')
+ })
+}
diff --git a/src/style-loader.js b/src/style-loader.js
deleted file mode 100644
index fb3e4f4..0000000
--- a/src/style-loader.js
+++ /dev/null
@@ -1,58 +0,0 @@
-import loaderUtils from 'loader-utils'
-import blocker from 'weex-transformer/lib/blocker'
-import styler from 'weex-styler'
-
-import {
- FUNC_START_REG,
- FUNC_END_REG,
- stringifyFunction
-} from './util'
-
-function extrackBlock (source, type) {
- return new Promise((resolve, reject) => {
- blocker.format(source, (err, ret) => {
- if (err) {
- reject(err)
- } else {
- resolve(ret[type])
- }
- })
- })
-}
-
-function parseStyle(source) {
- return new Promise((resolve, reject) => {
- styler.parse(source, (err, obj) => {
- if (err) {
- reject(err)
- } else {
- resolve(JSON.stringify(obj.jsonStyle, null, 2))
- }
- })
- })
-}
-
-module.exports = function(source) {
- this.cacheable && this.cacheable()
- const callback = this.async()
-
- const params = {
- loaderQuery: loaderUtils.parseQuery(this.query),
- resourceQuery: loaderUtils.parseQuery(this.resourceQuery),
- resourcePath: this.resourcePath
- }
-
- extrackBlock(source, 'styles')
- .then(styles => {
- if (params.loaderQuery.extract) {
- return parseStyle(styles[0].content)
- } else if (params.loaderQuery.raw) {
- callback(null, styles[0].content)
- }
- }).then(result => {
- result = `module.exports = ${result}\n`
- callback(null, result)
- }).catch(e => {
- callback(e, '')
- })
-}
\ No newline at end of file
diff --git a/src/style.js b/src/style.js
new file mode 100644
index 0000000..01de0ca
--- /dev/null
+++ b/src/style.js
@@ -0,0 +1,25 @@
+import {
+ logWarn
+} from './util'
+
+import {
+ parseStyle
+} from './parser'
+
+module.exports = function (source) {
+ this.cacheable && this.cacheable()
+
+ const callback = this.async()
+
+ parseStyle(source)
+ .then(({ parsed, log }) => {
+ if (log && log.length) {
+ logWarn(this, log)
+ }
+ return `module.exports = ${parsed}\n`
+ }).then(result => {
+ callback(null, result)
+ }).catch(e => {
+ callback(e, '')
+ })
+}
diff --git a/src/template.js b/src/template.js
new file mode 100644
index 0000000..12332cf
--- /dev/null
+++ b/src/template.js
@@ -0,0 +1,25 @@
+import {
+ logWarn
+} from './util'
+
+import {
+ parseTemplate
+} from './parser'
+
+module.exports = function (source) {
+ this.cacheable && this.cacheable()
+
+ const callback = this.async()
+
+ parseTemplate(source)
+ .then(({ parsed, log }) => {
+ if (log && log.length) {
+ logWarn(this, log)
+ }
+ return `module.exports = ${parsed}\n`
+ }).then(result => {
+ callback(null, result)
+ }).catch(e => {
+ callback(e, '')
+ })
+}
diff --git a/src/util.js b/src/util.js
index 3417388..29a7cca 100644
--- a/src/util.js
+++ b/src/util.js
@@ -1,11 +1,8 @@
-import fs from 'fs'
import path from 'path'
+import loaderUtils from 'loader-utils'
import * as config from './config'
-export const MODULE_EXPORTS_REG = /module\.exports/g
-export const REQUIRE_REG = /require\((["'])(@weex\-module\/[^\)\1]+)\1\)/g
-
export function getNameByPath (filepath) {
return path.basename(filepath).replace(/\..*$/, '')
}
@@ -17,12 +14,12 @@
export function stringifyFunction (key, value) {
if (typeof value === 'function') {
- return FUNC_START + value.toString() + '#####FUN_E#####'
+ return FUNC_START + value.toString() + FUNC_END
}
return value
}
-export function appendToWarn (loader, logs) {
+export function logWarn (loader, logs) {
if (config.logLevel && logs && logs.length) {
logs.forEach(log => {
loader.emitWarning(log.reason + '\t@' + log.line + ':' + log.column)
@@ -30,13 +27,40 @@
}
}
-export function checkFileExist (name, resourcePath) {
- const context = path.dirname(resourcePath)
- const filename = './' + name + '.we'
- const filepath = path.resolve(context, filename)
- return fs.existsSync(filepath) ? filename : null
+export function getRequireString (loaderContext, loader, filepath) {
+ return 'require(' +
+ loaderUtils.stringifyRequest(
+ loaderContext,
+ `!!${loader}!${filepath}`
+ ) +
+ ')\n'
}
-export function depHasRequired (content, dep) {
- return !content.match(new RegExp('require\\(["\']./' + path.basename(dep) + '(.we)?["\']\\)', 'g'))
+export function stringifyLoaders (loaders) {
+ return loaders.map(loader => {
+ if (typeof loader === 'string') {
+ return loader
+ }
+ else {
+ const name = loader.name
+ const query = []
+ if (loader.query) {
+ for (const k in loader.query) {
+ const v = loader.query[k]
+ if (v != null) {
+ if (v === true) {
+ query.push(k)
+ }
+ else {
+ if (v instanceof Array) {
+ query.push(`${k}[]=${v.join(',')}`)
+ }
+ query.push(`${k}=${v}`)
+ }
+ }
+ }
+ }
+ return `${name}${query.length ? ('?' + query.join('&')) : ''}`
+ }
+ }).join('!')
}
diff --git a/test/actual/.gitkeeper b/test/actual/.gitkeeper
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/actual/.gitkeeper
diff --git a/test/expect/a.js b/test/expect/a.js
new file mode 100644
index 0000000..0cb3d87
--- /dev/null
+++ b/test/expect/a.js
@@ -0,0 +1,15 @@
+{
+ "@weex-component/14d75138cf7189f2086409e4474268dd": {
+ "template": {
+ "type": "div",
+ "children": [
+ {
+ "type": "text",
+ "attr": {
+ "value": "Hello Weex"
+ }
+ }
+ ]
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/expect/b.js b/test/expect/b.js
new file mode 100644
index 0000000..67292a8
--- /dev/null
+++ b/test/expect/b.js
@@ -0,0 +1,24 @@
+{
+ "@weex-component/2e192c4e656c41953a80de02c8a657a2": {
+ "template": {
+ "type": "div",
+ "children": [
+ {
+ "type": "text",
+ "classList": [
+ "hi"
+ ],
+ "attr": {
+ "value": "Hello Weex"
+ }
+ }
+ ]
+ },
+ "style": {
+ "hi": {
+ "fontSize": 26,
+ "color": "#FF0000"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/expect/c.js b/test/expect/c.js
new file mode 100644
index 0000000..590d5ea
--- /dev/null
+++ b/test/expect/c.js
@@ -0,0 +1,25 @@
+{
+ "@weex-component/5f2196e6aad549d5070457fadf5d4cc0": {
+ "data": "function data() {\n\t return {\n\t name: 'Weex'\n\t };\n\t }",
+ "template": {
+ "type": "div",
+ "children": [
+ {
+ "type": "text",
+ "classList": [
+ "hello"
+ ],
+ "attr": {
+ "value": "function () {return 'Hello ' + (this.name)}"
+ }
+ }
+ ]
+ },
+ "style": {
+ "hello": {
+ "fontSize": 26,
+ "color": "#FF0000"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/expect/d.js b/test/expect/d.js
new file mode 100644
index 0000000..23fee40
--- /dev/null
+++ b/test/expect/d.js
@@ -0,0 +1,57 @@
+{
+ "@weex-component/name": {
+ "data": "function data() {\n\t return {\n\t name: ''\n\t };\n\t }",
+ "template": {
+ "type": "div",
+ "children": [
+ {
+ "type": "text",
+ "classList": [
+ "name"
+ ],
+ "attr": {
+ "value": "function () {return this.name}"
+ }
+ }
+ ]
+ },
+ "style": {
+ "name": {
+ "fontSize": 26,
+ "color": "#FF0000"
+ }
+ }
+ },
+ "@weex-component/b8ad1bad658f6c5956190b94be78d6db": {
+ "data": "function data() {\n\t return {\n\t name: 'Weex'\n\t };\n\t }",
+ "template": {
+ "type": "div",
+ "style": {
+ "flexDirection": "row"
+ },
+ "children": [
+ {
+ "type": "text",
+ "classList": [
+ "hello"
+ ],
+ "attr": {
+ "value": "Hello"
+ }
+ },
+ {
+ "type": "name",
+ "attr": {
+ "name": "function () {return this.name}"
+ }
+ }
+ ]
+ },
+ "style": {
+ "hello": {
+ "fontSize": 26,
+ "color": "#008000"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/expect/e.js b/test/expect/e.js
new file mode 100644
index 0000000..b03ed52
--- /dev/null
+++ b/test/expect/e.js
@@ -0,0 +1,71 @@
+{
+ "@weex-component/hi": {
+ "data": "function data() {\n\t return {\n\t hi: ''\n\t };\n\t }",
+ "template": {
+ "type": "div",
+ "children": [
+ {
+ "type": "text",
+ "classList": [
+ "hi"
+ ],
+ "attr": {
+ "value": "function () {return this.hi}"
+ }
+ }
+ ]
+ },
+ "style": {
+ "hi": {
+ "fontSize": 26,
+ "color": "#008000"
+ }
+ }
+ },
+ "@weex-component/name": {
+ "data": "function data() {\n\t return {\n\t name: ''\n\t };\n\t }",
+ "template": {
+ "type": "div",
+ "children": [
+ {
+ "type": "text",
+ "classList": [
+ "name"
+ ],
+ "attr": {
+ "value": "function () {return this.name}"
+ }
+ }
+ ]
+ },
+ "style": {
+ "name": {
+ "fontSize": 26,
+ "color": "#FF0000"
+ }
+ }
+ },
+ "@weex-component/1fac5618e94c17a7e12486a07120a1c2": {
+ "data": "function data() {\n\t return {\n\t hi: 'Hello',\n\t name: 'Weex'\n\t };\n\t }",
+ "template": {
+ "type": "div",
+ "style": {
+ "flexDirection": "row"
+ },
+ "children": [
+ {
+ "type": "hi",
+ "attr": {
+ "hi": "function () {return this.hi}"
+ }
+ },
+ {
+ "type": "name",
+ "attr": {
+ "name": "function () {return this.name}"
+ }
+ }
+ ]
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/expect/f.js b/test/expect/f.js
new file mode 100644
index 0000000..78e3ba2
--- /dev/null
+++ b/test/expect/f.js
@@ -0,0 +1,76 @@
+{
+ "@weex-component/hi": {
+ "data": "function data() {\n\t return {\n\t hi: ''\n\t };\n\t }",
+ "template": {
+ "type": "div",
+ "children": [
+ {
+ "type": "text",
+ "classList": [
+ "hi"
+ ],
+ "attr": {
+ "value": "function () {return this.hi}"
+ }
+ }
+ ]
+ },
+ "style": {
+ "hi": {
+ "fontSize": 26,
+ "color": "#008000"
+ }
+ }
+ },
+ "@weex-component/name": {
+ "data": "function data() {\n\t return {\n\t name: ''\n\t };\n\t }",
+ "template": {
+ "type": "div",
+ "children": [
+ {
+ "type": "text",
+ "classList": [
+ "name"
+ ],
+ "attr": {
+ "value": "function () {return this.name}"
+ }
+ }
+ ]
+ },
+ "style": {
+ "name": {
+ "fontSize": 26,
+ "color": "#FF0000"
+ }
+ }
+ },
+ "@weex-component/e65e091ca4375a7c5ce7d3dc1dd9648f": {
+ "data": "function data() {\n\t return {\n\t hi: 'Hello',\n\t name: 'Weex'\n\t };\n\t }",
+ "template": {
+ "type": "div",
+ "classList": [
+ "wrap"
+ ],
+ "children": [
+ {
+ "type": "hi",
+ "attr": {
+ "hi": "function () {return this.hi}"
+ }
+ },
+ {
+ "type": "name",
+ "attr": {
+ "name": "function () {return this.name}"
+ }
+ }
+ ]
+ },
+ "style": {
+ "wrap": {
+ "flexDirection": "row"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/expect/g.js b/test/expect/g.js
new file mode 100644
index 0000000..f02f953
--- /dev/null
+++ b/test/expect/g.js
@@ -0,0 +1,76 @@
+{
+ "@weex-component/name1": {
+ "data": "function data() {\n\t return {\n\t name: ''\n\t };\n\t }",
+ "template": {
+ "type": "div",
+ "children": [
+ {
+ "type": "text",
+ "classList": [
+ "name"
+ ],
+ "attr": {
+ "value": "function () {return this.name}"
+ }
+ }
+ ]
+ },
+ "style": {
+ "name": {
+ "fontSize": 26,
+ "color": "#FF0000"
+ }
+ }
+ },
+ "@weex-component/hi1": {
+ "data": "function data() {\n\t return {\n\t hi: ''\n\t };\n\t }",
+ "template": {
+ "type": "div",
+ "children": [
+ {
+ "type": "text",
+ "classList": [
+ "hi"
+ ],
+ "attr": {
+ "value": "function () {return this.hi}"
+ }
+ }
+ ]
+ },
+ "style": {
+ "hi": {
+ "fontSize": 26,
+ "color": "#008000"
+ }
+ }
+ },
+ "@weex-component/ea6e7eb66523432eacea8252752893ce": {
+ "data": "function data() {\n\t return {\n\t hi: 'Hello',\n\t name: 'Weex'\n\t };\n\t }",
+ "template": {
+ "type": "div",
+ "classList": [
+ "wrap"
+ ],
+ "children": [
+ {
+ "type": "hi1",
+ "attr": {
+ "hi": "function () {return this.hi}"
+ }
+ },
+ {
+ "type": "name1",
+ "attr": {
+ "name": "function () {return this.name}"
+ }
+ }
+ ]
+ },
+ "style": {
+ "wrap": {
+ "flexDirection": "row"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/expect/h.js b/test/expect/h.js
new file mode 100644
index 0000000..0107f71
--- /dev/null
+++ b/test/expect/h.js
@@ -0,0 +1,76 @@
+{
+ "@weex-component/hi": {
+ "data": "function data() {\n\t return {\n\t hi: ''\n\t };\n\t }",
+ "template": {
+ "type": "div",
+ "children": [
+ {
+ "type": "text",
+ "classList": [
+ "hi"
+ ],
+ "attr": {
+ "value": "function () {return this.hi}"
+ }
+ }
+ ]
+ },
+ "style": {
+ "hi": {
+ "fontSize": 26,
+ "color": "#008000"
+ }
+ }
+ },
+ "@weex-component/name": {
+ "data": "function data() {\n\t return {\n\t name: ''\n\t };\n\t }",
+ "template": {
+ "type": "div",
+ "children": [
+ {
+ "type": "text",
+ "classList": [
+ "name"
+ ],
+ "attr": {
+ "value": "function () {return this.name}"
+ }
+ }
+ ]
+ },
+ "style": {
+ "name": {
+ "fontSize": 26,
+ "color": "#FF0000"
+ }
+ }
+ },
+ "@weex-component/ee83bc6907b957bce242c32bf2c188f2": {
+ "data": "function data() {\n\t return {\n\t hi: 'Hello',\n\t name: 'Weex'\n\t };\n\t }",
+ "template": {
+ "type": "div",
+ "classList": [
+ "wrap"
+ ],
+ "children": [
+ {
+ "type": "hi",
+ "attr": {
+ "hi": "function () {return this.hi}"
+ }
+ },
+ {
+ "type": "name",
+ "attr": {
+ "name": "function () {return this.name}"
+ }
+ }
+ ]
+ },
+ "style": {
+ "wrap": {
+ "flexDirection": "row"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/expect/i.js b/test/expect/i.js
new file mode 100644
index 0000000..e4cfd6e
--- /dev/null
+++ b/test/expect/i.js
@@ -0,0 +1,24 @@
+{
+ "@weex-component/eebf10d54335bc996c5229787ede33eb": {
+ "template": {
+ "type": "div",
+ "children": [
+ {
+ "type": "text",
+ "classList": [
+ "hello"
+ ],
+ "attr": {
+ "value": "function () {return 'Hello ' + (this.name)}"
+ }
+ }
+ ]
+ },
+ "style": {
+ "hello": {
+ "fontSize": 26,
+ "color": "#FF0000"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/expect/j.js b/test/expect/j.js
new file mode 100644
index 0000000..660882f
--- /dev/null
+++ b/test/expect/j.js
@@ -0,0 +1,31 @@
+{
+ "@weex-component/88780bcf66c93d797a309a82b762e1f9": {
+ "ready": "function ready() {\n\t modal.toast({ 'message': 'ready' });\n\t }",
+ "data": "function data() {\n\t return {\n\t hi: 'Hello',\n\t name: 'Weex'\n\t };\n\t }",
+ "template": {
+ "type": "div",
+ "classList": [
+ "wrap"
+ ],
+ "children": [
+ {
+ "type": "text",
+ "attr": {
+ "value": "function () {return this.hi}"
+ }
+ },
+ {
+ "type": "text",
+ "attr": {
+ "value": "function () {return this.name}"
+ }
+ }
+ ]
+ },
+ "style": {
+ "wrap": {
+ "flexDirection": "row"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/expect/k.js b/test/expect/k.js
new file mode 100644
index 0000000..2676b37
--- /dev/null
+++ b/test/expect/k.js
@@ -0,0 +1,45 @@
+{
+ "@weex-component/215a3c96c2c3802f228bf7ceec470c73": {
+ "ready": "function ready() {\n\t _modal2.default.toast({ 'message': 'ready' });\n\t}",
+ "data": "function data() {\n\t return {\n\t hi: 'Hello',\n\t name: 'Weex'\n\t };\n\t}",
+ "template": {
+ "type": "div",
+ "classList": [
+ "wrap"
+ ],
+ "children": [
+ {
+ "type": "text",
+ "classList": [
+ "text-hi"
+ ],
+ "attr": {
+ "value": "function () {return this.hi}"
+ }
+ },
+ {
+ "type": "text",
+ "classList": [
+ "text-name"
+ ],
+ "attr": {
+ "value": "function () {return this.name}"
+ }
+ }
+ ]
+ },
+ "style": {
+ "wrap": {
+ "flexDirection": "row"
+ },
+ "text-hi": {
+ "color": "#FF0000",
+ "fontSize": 26
+ },
+ "text-name": {
+ "color": "#008000",
+ "fontSize": 26
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/npm-debug.log b/test/npm-debug.log
new file mode 100644
index 0000000..cad643e
--- /dev/null
+++ b/test/npm-debug.log
@@ -0,0 +1,158 @@
+0 info it worked if it ends with ok
+1 verbose cli [ '/Users/terry 1/versions/node/v4.2.2/bin/node',
+1 verbose cli '/Users/terry/versions/node/v4.2.2/bin/npm',
+1 verbose cli 'install',
+1 verbose cli 'weex-loader',
+1 verbose cli 'babel-loader',
+1 verbose cli ' ' ]
+2 info using npm@3.9.6
+3 info using node@v4.2.2
+4 silly loadCurrentTree Starting
+5 silly install loadCurrentTree
+6 silly install readLocalPackageData
+7 silly fetchPackageMetaData weex-loader
+8 silly fetchPackageMetaData babel-loader@^6.2.4
+9 silly fetchPackageMetaData
+10 silly fetchNamedPackageData babel-loader
+11 silly mapToRegistry name babel-loader
+12 silly mapToRegistry using default registry
+13 silly mapToRegistry registry http://registry.npmjs.org/
+14 silly mapToRegistry data Result {
+14 silly mapToRegistry raw: 'babel-loader',
+14 silly mapToRegistry scope: null,
+14 silly mapToRegistry name: 'babel-loader',
+14 silly mapToRegistry rawSpec: '',
+14 silly mapToRegistry spec: 'latest',
+14 silly mapToRegistry type: 'tag' }
+15 silly mapToRegistry uri http://registry.npmjs.org/babel-loader
+16 silly fetchNamedPackageData weex-loader
+17 silly mapToRegistry name weex-loader
+18 silly mapToRegistry using default registry
+19 silly mapToRegistry registry http://registry.npmjs.org/
+20 silly mapToRegistry data Result {
+20 silly mapToRegistry raw: 'weex-loader',
+20 silly mapToRegistry scope: null,
+20 silly mapToRegistry name: 'weex-loader',
+20 silly mapToRegistry rawSpec: '',
+20 silly mapToRegistry spec: 'latest',
+20 silly mapToRegistry type: 'tag' }
+21 silly mapToRegistry uri http://registry.npmjs.org/weex-loader
+22 silly fetchDirectoryPackageData null
+23 verbose request uri http://registry.npmjs.org/weex-loader
+24 verbose request no auth needed
+25 info attempt registry request try #1 at 03:16:37
+26 verbose request using bearer token for auth
+27 verbose request id b05395499c9e154f
+28 http request GET http://registry.npmjs.org/weex-loader
+29 verbose request uri http://registry.npmjs.org/babel-loader
+30 verbose request no auth needed
+31 info attempt registry request try #1 at 03:16:37
+32 verbose request using bearer token for auth
+33 verbose etag "EW23D9MKRNP2807DDKRUKPXG"
+34 http request GET http://registry.npmjs.org/babel-loader
+35 http 200 http://registry.npmjs.org/weex-loader
+36 verbose headers { server: 'CouchDB/1.5.0 (Erlang OTP/R16B03)',
+36 verbose headers etag: '"84NTPFZCZIPAGB6NSL28IXNOE"',
+36 verbose headers 'content-type': 'application/json',
+36 verbose headers 'content-encoding': 'gzip',
+36 verbose headers 'cache-control': 'max-age=300',
+36 verbose headers 'transfer-encoding': 'chunked',
+36 verbose headers 'accept-ranges': 'bytes',
+36 verbose headers date: 'Sat, 09 Jul 2016 19:13:18 GMT',
+36 verbose headers via: '1.1 varnish',
+36 verbose headers connection: 'keep-alive',
+36 verbose headers 'x-served-by': 'cache-lcy1123-LCY',
+36 verbose headers 'x-cache': 'MISS',
+36 verbose headers 'x-cache-hits': '0',
+36 verbose headers 'x-timer': 'S1468091598.000096,VS0,VE356',
+36 verbose headers vary: 'Accept-Encoding' }
+37 silly get cb [ 200,
+37 silly get { server: 'CouchDB/1.5.0 (Erlang OTP/R16B03)',
+37 silly get etag: '"84NTPFZCZIPAGB6NSL28IXNOE"',
+37 silly get 'content-type': 'application/json',
+37 silly get 'content-encoding': 'gzip',
+37 silly get 'cache-control': 'max-age=300',
+37 silly get 'transfer-encoding': 'chunked',
+37 silly get 'accept-ranges': 'bytes',
+37 silly get date: 'Sat, 09 Jul 2016 19:13:18 GMT',
+37 silly get via: '1.1 varnish',
+37 silly get connection: 'keep-alive',
+37 silly get 'x-served-by': 'cache-lcy1123-LCY',
+37 silly get 'x-cache': 'MISS',
+37 silly get 'x-cache-hits': '0',
+37 silly get 'x-timer': 'S1468091598.000096,VS0,VE356',
+37 silly get vary: 'Accept-Encoding' } ]
+38 verbose get saving weex-loader to /Users/terry/.npm/registry.npmjs.org/weex-loader/.cache.json
+39 verbose correctMkdir /Users/terry/.npm correctMkdir not in flight; initializing
+40 http 200 http://registry.npmjs.org/babel-loader
+41 verbose headers { server: 'CouchDB/1.5.0 (Erlang OTP/R16B03)',
+41 verbose headers etag: '"CN9KCPC8USQ6FOZKEY58UCARS"',
+41 verbose headers 'content-type': 'application/json',
+41 verbose headers 'content-encoding': 'gzip',
+41 verbose headers 'cache-control': 'max-age=300',
+41 verbose headers 'transfer-encoding': 'chunked',
+41 verbose headers 'accept-ranges': 'bytes',
+41 verbose headers date: 'Sat, 09 Jul 2016 19:13:18 GMT',
+41 verbose headers via: '1.1 varnish',
+41 verbose headers connection: 'keep-alive',
+41 verbose headers 'x-served-by': 'cache-lcy1129-LCY',
+41 verbose headers 'x-cache': 'MISS',
+41 verbose headers 'x-cache-hits': '0',
+41 verbose headers 'x-timer': 'S1468091597.995738,VS0,VE698',
+41 verbose headers vary: 'Accept-Encoding' }
+42 silly get cb [ 200,
+42 silly get { server: 'CouchDB/1.5.0 (Erlang OTP/R16B03)',
+42 silly get etag: '"CN9KCPC8USQ6FOZKEY58UCARS"',
+42 silly get 'content-type': 'application/json',
+42 silly get 'content-encoding': 'gzip',
+42 silly get 'cache-control': 'max-age=300',
+42 silly get 'transfer-encoding': 'chunked',
+42 silly get 'accept-ranges': 'bytes',
+42 silly get date: 'Sat, 09 Jul 2016 19:13:18 GMT',
+42 silly get via: '1.1 varnish',
+42 silly get connection: 'keep-alive',
+42 silly get 'x-served-by': 'cache-lcy1129-LCY',
+42 silly get 'x-cache': 'MISS',
+42 silly get 'x-cache-hits': '0',
+42 silly get 'x-timer': 'S1468091597.995738,VS0,VE698',
+42 silly get vary: 'Accept-Encoding' } ]
+43 verbose get saving babel-loader to /Users/terry/.npm/registry.npmjs.org/babel-loader/.cache.json
+44 verbose correctMkdir /Users/terry/.npm correctMkdir not in flight; initializing
+45 silly install normalizeTree
+46 silly loadCurrentTree Finishing
+47 silly loadIdealTree Starting
+48 silly install loadIdealTree
+49 silly cloneCurrentTree Starting
+50 silly install cloneCurrentTreeToIdealTree
+51 silly cloneCurrentTree Finishing
+52 silly loadShrinkwrap Starting
+53 silly install loadShrinkwrap
+54 silly loadShrinkwrap Finishing
+55 silly loadAllDepsIntoIdealTree Starting
+56 silly install loadAllDepsIntoIdealTree
+57 silly rollbackFailedOptional Starting
+58 silly rollbackFailedOptional Finishing
+59 silly runTopLevelLifecycles Starting
+60 silly runTopLevelLifecycles Finishing
+61 silly install printInstalled
+62 verbose stack Error: Refusing to install weex-loader as a dependency of itself
+62 verbose stack at checkSelf (/Users/terry 1/versions/node/v4.2.2/lib/node_modules/npm/lib/install/validate-args.js:53:14)
+62 verbose stack at Array.<anonymous> (/Users/terry 1/versions/node/v4.2.2/lib/node_modules/npm/node_modules/slide/lib/bind-actor.js:15:8)
+62 verbose stack at LOOP (/Users/terry 1/versions/node/v4.2.2/lib/node_modules/npm/node_modules/slide/lib/chain.js:15:14)
+62 verbose stack at chain (/Users/terry 1/versions/node/v4.2.2/lib/node_modules/npm/node_modules/slide/lib/chain.js:20:5)
+62 verbose stack at /Users/terry 1/versions/node/v4.2.2/lib/node_modules/npm/lib/install/validate-args.js:16:5
+62 verbose stack at /Users/terry 1/versions/node/v4.2.2/lib/node_modules/npm/node_modules/slide/lib/async-map.js:52:35
+62 verbose stack at Array.forEach (native)
+62 verbose stack at /Users/terry 1/versions/node/v4.2.2/lib/node_modules/npm/node_modules/slide/lib/async-map.js:52:11
+62 verbose stack at Array.forEach (native)
+62 verbose stack at asyncMap (/Users/terry 1/versions/node/v4.2.2/lib/node_modules/npm/node_modules/slide/lib/async-map.js:51:8)
+63 verbose cwd /Users/terry 1/Develop/taobao/weex/toolchain/weex-loader/test
+64 error Darwin 15.0.0
+65 error argv "/Users/terry 1/versions/node/v4.2.2/bin/node" "/Users/terry/versions/node/v4.2.2/bin/npm" "install" "weex-loader" "babel-loader" " "
+66 error node v4.2.2
+67 error npm v3.9.6
+68 error code ENOSELF
+69 error Refusing to install weex-loader as a dependency of itself
+70 error If you need help, you may report this error at:
+70 error <https://github.com/npm/npm/issues>
+71 verbose exit [ 1, true ]
diff --git a/test/spec/a.we b/test/spec/a.we
index 62ac6f9..1335e77 100644
--- a/test/spec/a.we
+++ b/test/spec/a.we
@@ -1,24 +1,3 @@
<template>
- <div>
- <text class="hello">Hello {{name}}</text>
- </div>
-</template>
-
-
-<style>
-.hello {
- font-size: 26px;
- color: red;
-}
-</style>
-
-
-<script>
-module.exports = {
- data: function() {
- return {
- name: 'Weex'
- }
- }
-}
-</script>
\ No newline at end of file
+ <div><text>Hello Weex</text></div>
+</template>
\ No newline at end of file
diff --git a/test/spec/b.we b/test/spec/b.we
new file mode 100644
index 0000000..603ef5c
--- /dev/null
+++ b/test/spec/b.we
@@ -0,0 +1,10 @@
+<template>
+ <div><text class="hi">Hello Weex</text></div>
+</template>
+
+<style>
+.hi {
+ font-size: 26px;
+ color: red;
+}
+</style>
\ No newline at end of file
diff --git a/test/spec/c.we b/test/spec/c.we
new file mode 100644
index 0000000..62ac6f9
--- /dev/null
+++ b/test/spec/c.we
@@ -0,0 +1,24 @@
+<template>
+ <div>
+ <text class="hello">Hello {{name}}</text>
+ </div>
+</template>
+
+
+<style>
+.hello {
+ font-size: 26px;
+ color: red;
+}
+</style>
+
+
+<script>
+module.exports = {
+ data: function() {
+ return {
+ name: 'Weex'
+ }
+ }
+}
+</script>
\ No newline at end of file
diff --git a/test/spec/d.we b/test/spec/d.we
new file mode 100644
index 0000000..37208c2
--- /dev/null
+++ b/test/spec/d.we
@@ -0,0 +1,48 @@
+<element name="name">
+ <template>
+ <div><text class="name">{{name}}</text></div>
+ </template>
+
+ <style>
+ .name {
+ font-size: 26px;
+ color: red;
+ }
+ </style>
+
+ <script>
+ module.exports = {
+ data: function() {
+ return {
+ name: ''
+ }
+ }
+ }
+ </script>
+</element>
+
+<template>
+ <div style="flex-direction: row;">
+ <text class="hello">Hello</text>
+ <name name="{{name}}"></name>
+ </div>
+</template>
+
+
+<style>
+.hello {
+ font-size: 26px;
+ color: green;
+}
+</style>
+
+
+<script>
+module.exports = {
+ data: function() {
+ return {
+ name: 'Weex'
+ }
+ }
+}
+</script>
\ No newline at end of file
diff --git a/test/spec/data.json b/test/spec/data.json
new file mode 100644
index 0000000..b8e9b40
--- /dev/null
+++ b/test/spec/data.json
@@ -0,0 +1,3 @@
+{
+ "name": "Weex"
+}
\ No newline at end of file
diff --git a/test/spec/e.we b/test/spec/e.we
new file mode 100644
index 0000000..06d79d0
--- /dev/null
+++ b/test/spec/e.we
@@ -0,0 +1,63 @@
+<element name="hi">
+ <template>
+ <div><text class="hi">{{hi}}</text></div>
+ </template>
+
+ <style>
+ .hi {
+ font-size: 26px;
+ color: green;
+ }
+ </style>
+
+ <script>
+ module.exports = {
+ data: function() {
+ return {
+ hi: ''
+ }
+ }
+ }
+ </script>
+</element>
+
+<element name="name">
+ <template>
+ <div><text class="name">{{name}}</text></div>
+ </template>
+
+ <style>
+ .name {
+ font-size: 26px;
+ color: red;
+ }
+ </style>
+
+ <script>
+ module.exports = {
+ data: function() {
+ return {
+ name: ''
+ }
+ }
+ }
+ </script>
+</element>
+
+<template>
+ <div style="flex-direction: row;">
+ <hi hi="{{hi}}"></hi>
+ <name name="{{name}}"></name>
+ </div>
+</template>
+
+<script>
+module.exports = {
+ data: function() {
+ return {
+ hi: 'Hello',
+ name: 'Weex'
+ }
+ }
+}
+</script>
\ No newline at end of file
diff --git a/test/spec/f.css b/test/spec/f.css
new file mode 100644
index 0000000..11d03bc
--- /dev/null
+++ b/test/spec/f.css
@@ -0,0 +1,3 @@
+.wrap {
+ flex-direction: row;
+}
\ No newline at end of file
diff --git a/test/spec/f.html b/test/spec/f.html
new file mode 100644
index 0000000..3229bc9
--- /dev/null
+++ b/test/spec/f.html
@@ -0,0 +1,4 @@
+<div class="wrap">
+ <hi hi="{{hi}}"></hi>
+ <name name="{{name}}"></name>
+</div>
\ No newline at end of file
diff --git a/test/spec/f.js b/test/spec/f.js
new file mode 100644
index 0000000..f8879f6
--- /dev/null
+++ b/test/spec/f.js
@@ -0,0 +1,8 @@
+module.exports = {
+ data: function() {
+ return {
+ hi: 'Hello',
+ name: 'Weex'
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/spec/f.we b/test/spec/f.we
new file mode 100644
index 0000000..b955e53
--- /dev/null
+++ b/test/spec/f.we
@@ -0,0 +1,5 @@
+<element name="hi" src="./hi.we"></element>
+<element name="name" src="./name.we"></element>
+<template src="./f.html"></template>
+<style src="./f.css"></style>
+<script src="./f.js"></script>
\ No newline at end of file
diff --git a/test/spec/g.we b/test/spec/g.we
new file mode 100644
index 0000000..84fec79
--- /dev/null
+++ b/test/spec/g.we
@@ -0,0 +1,27 @@
+<element name="name1" src="./name.we"></element>
+
+<template>
+ <div class="wrap">
+ <hi1 hi="{{hi}}"></hi1>
+ <name1 name="{{name}}"></name1>
+ </div>
+</template>
+
+<style>
+ .wrap {
+ flex-direction: row;
+ }
+</style>
+
+<script>
+require('./hi.we?name=hi1')
+
+module.exports = {
+ data: function() {
+ return {
+ hi: 'Hello',
+ name: 'Weex'
+ }
+ }
+}
+</script>
\ No newline at end of file
diff --git a/test/spec/h.we b/test/spec/h.we
new file mode 100644
index 0000000..f8faf4b
--- /dev/null
+++ b/test/spec/h.we
@@ -0,0 +1,23 @@
+<template>
+ <div class="wrap">
+ <hi hi="{{hi}}"></hi>
+ <name name="{{name}}"></name>
+ </div>
+</template>
+
+<style>
+ .wrap {
+ flex-direction: row;
+ }
+</style>
+
+<script>
+module.exports = {
+ data: function() {
+ return {
+ hi: 'Hello',
+ name: 'Weex'
+ }
+ }
+}
+</script>
\ No newline at end of file
diff --git a/test/spec/hi.we b/test/spec/hi.we
new file mode 100644
index 0000000..42ce783
--- /dev/null
+++ b/test/spec/hi.we
@@ -0,0 +1,20 @@
+<template>
+ <div><text class="hi">{{hi}}</text></div>
+</template>
+
+<style>
+.hi {
+ font-size: 26px;
+ color: green;
+}
+</style>
+
+<script>
+module.exports = {
+ data: function() {
+ return {
+ hi: ''
+ }
+ }
+}
+</script>
\ No newline at end of file
diff --git a/test/spec/i.we b/test/spec/i.we
new file mode 100644
index 0000000..f0fc21f
--- /dev/null
+++ b/test/spec/i.we
@@ -0,0 +1,22 @@
+<template>
+ <div>
+ <text class="hello">Hello {{name}}</text>
+ </div>
+</template>
+
+
+<style>
+.hello {
+ font-size: 26px;
+ color: red;
+}
+</style>
+
+
+<script type="config">
+{
+ downgrade: true
+}
+</script>
+
+<script type="data" src="./data.json"></script>
\ No newline at end of file
diff --git a/test/spec/j.we b/test/spec/j.we
new file mode 100644
index 0000000..8d2e8af
--- /dev/null
+++ b/test/spec/j.we
@@ -0,0 +1,28 @@
+<template>
+ <div class="wrap">
+ <text>{{hi}}</text>
+ <text>{{name}}</text>
+ </div>
+</template>
+
+<style>
+ .wrap {
+ flex-direction: row;
+ }
+</style>
+
+<script>
+var modal = require('@weex-module/modal')
+
+module.exports = {
+ ready: function() {
+ modal.toast({'message': 'ready'})
+ },
+ data: function() {
+ return {
+ hi: 'Hello',
+ name: 'Weex'
+ }
+ }
+}
+</script>
\ No newline at end of file
diff --git a/test/spec/k.we b/test/spec/k.we
new file mode 100644
index 0000000..c07c5ba
--- /dev/null
+++ b/test/spec/k.we
@@ -0,0 +1,44 @@
+<template lang="jade">
+.wrap
+ text.text-hi {{hi}}
+ text.text-name {{name}}
+</template>
+
+<style lang="cssnext">
+ :root {
+ --mainColor: red;
+ --subColor: green;
+ --normalFont: {
+ font-size: 26px;
+ };
+ }
+
+ .wrap {
+ flex-direction: row;
+ }
+
+ .text-hi {
+ color: var(--mainColor);
+ @apply --normalFont;
+ }
+
+ .text-name {
+ color: var(--subColor);
+ @apply --normalFont;
+ }
+</style>
+
+<script>
+import modal from '@weex-module/modal'
+
+export function ready() {
+ modal.toast({'message': 'ready'})
+}
+
+export function data() {
+ return {
+ hi: 'Hello',
+ name: 'Weex'
+ }
+}
+</script>
\ No newline at end of file
diff --git a/test/spec/name.css b/test/spec/name.css
new file mode 100644
index 0000000..3c6e476
--- /dev/null
+++ b/test/spec/name.css
@@ -0,0 +1,4 @@
+.name {
+ font-size: 26px;
+ color: red;
+}
\ No newline at end of file
diff --git a/test/spec/name.html b/test/spec/name.html
new file mode 100644
index 0000000..258e5e5
--- /dev/null
+++ b/test/spec/name.html
@@ -0,0 +1 @@
+<div><text class="name">{{name}}</text></div>
diff --git a/test/spec/name.js b/test/spec/name.js
new file mode 100644
index 0000000..d2074a3
--- /dev/null
+++ b/test/spec/name.js
@@ -0,0 +1,7 @@
+module.exports = {
+ data: function() {
+ return {
+ name: ''
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/spec/name.we b/test/spec/name.we
new file mode 100644
index 0000000..efa318e
--- /dev/null
+++ b/test/spec/name.we
@@ -0,0 +1,3 @@
+<template src="./name.html"></template>
+<style src="./name.css"></style>
+<script src="./name.js"></script>
\ No newline at end of file
diff --git a/test/test.js b/test/test.js
index 7f1bafc..4b65f67 100644
--- a/test/test.js
+++ b/test/test.js
@@ -1,5 +1,6 @@
+'use strict';
+
const fs = require('fs');
-const MemoryFS = require("memory-fs");
const path =require('path');
const chai = require('chai');
@@ -8,33 +9,114 @@
const expect = chai.expect;
chai.use(sinonChai);
-const webpackConfig = require('./webpack.config.js');
-const webpack = require('webpack');
+function getActualString(name) {
+ const filepath = path.resolve(__dirname, 'actual', `${name}.js`);
+ const result = fs.readFileSync(filepath, 'utf-8');
+ return result.toString();
+}
-describe('loader', () => {
- it('simple', (done) => {
- const config = Object.assign({}, webpackConfig, {
- entry: {
- a: path.resolve(__dirname, 'spec', 'a.we')
- }
- });
+function getExpectJSON(name) {
+ const filepath = path.resolve(__dirname, 'expect', `${name}.js`);
+ const result = fs.readFileSync(filepath, 'utf-8');
+ return JSON.parse(result.toString());
+}
- const compiler = webpack(config);
- const mfs = new MemoryFS;
- // compiler.outputFileSystem = mfs;
- compiler.run((err, stats) => {
- if (err) {
- return done(err);
- }
+function stringifyActual(json) {
+ return JSON.stringify(json, function(key, value) {
+ if (typeof value === 'function') {
+ value = value.toString();
+ }
+ return value;
+ }, ' ');
+}
- console.log(stats.toString({
- chunks: false,
- color: true
- }))
- // const result = fs.readFileSync(path.resolve(__dirname, 'actual', 'a.we'))
- // console.log(result)
- done()
- })
+describe('build', () => {
+ let __weex_define__;
+ let __weex_bootstrap__;
+ let components;
+ let requireStub;
+ let bootstrapStub;
+
+ function expectActual(name) {
+ const actualStr = getActualString(name);
+ const fn = new Function('__weex_define__', '__weex_bootstrap__', actualStr);
+ fn(__weex_define__, __weex_bootstrap__);
+
+ // const filepath = path.resolve(__dirname, 'expect', `${name}.js`);
+ // fs.writeFileSync(filepath, stringifyActual(components), 'utf-8');
+
+ const expectJSON = getExpectJSON(name);
+ expect(JSON.parse(stringifyActual(components))).eql(expectJSON);
+ expect(components).to.include.keys(__weex_bootstrap__.firstCall.args[0]);
+ }
+
+ beforeEach(() => {
+ components = {};
+ requireStub = sinon.stub();
+ bootstrapStub = sinon.stub();
+
+ __weex_define__ = function(componentName, deps, factory) {
+ var __weex_require__ = requireStub;
+ var __weex_exports__ = {};
+ var __weex_module__ = {exports : __weex_exports__}
+
+ factory(__weex_require__, __weex_exports__, __weex_module__)
+ components[componentName] = __weex_module__.exports
+ }
+
+ __weex_bootstrap__ = bootstrapStub;
+
+ });
+
+ it('single template', () => {
+ expectActual('a');
+ });
+
+ it('template with style', () => {
+ expectActual('b');
+ });
+
+ it('template with style and script', () => {
+ expectActual('c');
+ });
+
+ it('template with single inline element', () => {
+ expectActual('d');
+ });
+
+ it('template with multiple inline elements', () => {
+ expectActual('e');
+ });
+
+ it('template via src', () => {
+ expectActual('f');
+ });
+
+ it('template via requiring src and specifing alias', () => {
+ expectActual('g');
+ expect(requireStub.callCount).eql(0);
+ });
+
+ it('template by finding elements under same folder', () => {
+ expectActual('h');
+ });
+
+ it('template with config and data', () => {
+ expectActual('i');
+ expect(bootstrapStub.firstCall.args[1]).is.not.undefined;
+ expect(bootstrapStub.firstCall.args[2]).is.not.undefined;
+ });
+
+ it('template and require weex modules', () => {
+ expectActual('j');
+ expect(requireStub.callCount).eql(1);
+ expect(requireStub.firstCall.args).eql(['@weex-module/modal']);
+ });
+
+ it('template by using custom language', () => {
+ expectActual('k');
+ expect(requireStub.callCount).eql(1);
+ expect(requireStub.firstCall.args).eql(['@weex-module/modal']);
});
})
diff --git a/test/webpack.config.js b/test/webpack.config.js
index a870a17..e9f9600 100644
--- a/test/webpack.config.js
+++ b/test/webpack.config.js
@@ -1,9 +1,19 @@
var path = require('path')
+var cssnext = require('postcss-cssnext')
+
+var entry = {}
+var start = 'a'
+var end = 'k'
+var count = end.charCodeAt(0) - start.charCodeAt(0)
+
+new Array(count + 1).fill(0)
+ .forEach((n, i) => {
+ var name = String.fromCharCode(i + start.charCodeAt(0))
+ entry[name] = path.resolve(__dirname, 'spec', name + '.we?entry')
+ })
module.exports = {
- entry: {
- a: path.resolve(__dirname, 'spec', 'a.we') + '?entry'
- },
+ entry: entry,
output: {
path: path.resolve(__dirname, 'actual'),
filename: '[name].js'
@@ -19,11 +29,15 @@
resolveLoader: {
modulesDirectories: ['./', './node_modules']
},
+ postcss: function() {
+ return [cssnext({
+ browsers: ['last 1 version']
+ })]
+ },
weex: {
- loaders: {
- es6: ['babel'],
- cssnext: ['postcss-cssnext'],
- jade: ['jade']
+ lang: {
+ cssnext: ['postcss'],
+ jade: ['jade-html']
}
}
}