Skip to content

Commit a879ec0

Browse files
committed
init
0 parents  commit a879ec0

35 files changed

Lines changed: 3671 additions & 0 deletions

.babelrc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"env": {
3+
"development": {
4+
"presets": ["es2015", "stage-2"]
5+
},
6+
"production": {
7+
"presets": ["es2015-rollup", "stage-2"]
8+
}
9+
}
10+
}

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
.DS_Store
2+
node_modules
3+
npm-debug.log
4+
explorations
5+
TODOs.md

build/build.js

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
var fs = require('fs')
2+
var zlib = require('zlib')
3+
var rollup = require('rollup')
4+
var uglify = require('uglify-js')
5+
var babel = require('rollup-plugin-babel')
6+
var node = require('rollup-plugin-node-resolve')
7+
var commonjs = require('rollup-plugin-commonjs')
8+
var replace = require('rollup-plugin-replace')
9+
var version = process.env.VERSION || require('../package.json').version
10+
11+
var banner =
12+
'/*!\n' +
13+
' * Vue.js v' + version + '\n' +
14+
' * (c) ' + new Date().getFullYear() + ' Evan You\n' +
15+
' * Released under the MIT License.\n' +
16+
' */'
17+
18+
// update main file
19+
var main = fs
20+
.readFileSync('src/index.js', 'utf-8')
21+
.replace(/Vue\.version = '[\d\.]+'/, "Vue.version = '" + version + "'")
22+
fs.writeFileSync('src/index.js', main)
23+
24+
var plugins = [
25+
node(),
26+
commonjs({
27+
include: 'node_modules/**'
28+
}),
29+
babel({
30+
exclude: 'node_modules/**'
31+
})
32+
]
33+
34+
// CommonJS build.
35+
// this is used as the "main" field in package.json
36+
// and used by bundlers like Webpack and Browserify.
37+
rollup.rollup({
38+
entry: 'src/index.js',
39+
plugins: plugins
40+
})
41+
.then(function (bundle) {
42+
return write('dist/vue.common.js', bundle.generate({
43+
format: 'cjs',
44+
banner: banner
45+
}).code)
46+
})
47+
// Standalone Dev Build
48+
.then(function () {
49+
return rollup.rollup({
50+
entry: 'src/index.js',
51+
plugins: [
52+
replace({
53+
'process.env.NODE_ENV': "'development'"
54+
})
55+
].concat(plugins)
56+
})
57+
.then(function (bundle) {
58+
return write('dist/vue.js', bundle.generate({
59+
format: 'umd',
60+
banner: banner,
61+
moduleName: 'Vue'
62+
}).code)
63+
})
64+
})
65+
.then(function () {
66+
// Standalone Production Build
67+
return rollup.rollup({
68+
entry: 'src/index.js',
69+
plugins: [
70+
replace({
71+
'process.env.NODE_ENV': "'production'"
72+
})
73+
].concat(plugins)
74+
})
75+
.then(function (bundle) {
76+
var code = bundle.generate({
77+
format: 'umd',
78+
moduleName: 'Vue'
79+
}).code
80+
var minified = banner + '\n' + uglify.minify(code, {
81+
fromString: true,
82+
output: {
83+
ascii_only: true
84+
}
85+
}).code
86+
return write('dist/vue.min.js', minified)
87+
})
88+
.then(zip)
89+
})
90+
.catch(logError)
91+
92+
function write (dest, code) {
93+
return new Promise(function (resolve, reject) {
94+
fs.writeFile(dest, code, function (err) {
95+
if (err) return reject(err)
96+
console.log(blue(dest) + ' ' + getSize(code))
97+
resolve()
98+
})
99+
})
100+
}
101+
102+
function zip () {
103+
return new Promise(function (resolve, reject) {
104+
fs.readFile('dist/vue.min.js', function (err, buf) {
105+
if (err) return reject(err)
106+
zlib.gzip(buf, function (err, buf) {
107+
if (err) return reject(err)
108+
write('dist/vue.min.js.gz', buf).then(resolve)
109+
})
110+
})
111+
})
112+
}
113+
114+
function getSize (code) {
115+
return (code.length / 1024).toFixed(2) + 'kb'
116+
}
117+
118+
function logError (e) {
119+
console.log(e)
120+
}
121+
122+
function blue (str) {
123+
return '\x1b[1m\x1b[34m' + str + '\x1b[39m\x1b[22m'
124+
}

package.json

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
{
2+
"name": "vue-lite",
3+
"version": "1.0.0",
4+
"description": "Lighter-weight Vue on virtual dom",
5+
"main": "index.js",
6+
"scripts": {
7+
"dev": "webpack --watch",
8+
"test": "mocha",
9+
"build": "NODE_ENV=production node build/build.js"
10+
},
11+
"repository": {
12+
"type": "git",
13+
"url": "git+https://github.com/vuejs/vue-lite.git"
14+
},
15+
"keywords": [
16+
"vue"
17+
],
18+
"author": "Evan You",
19+
"license": "MIT",
20+
"bugs": {
21+
"url": "https://github.com/vuejs/vue-lite/issues"
22+
},
23+
"homepage": "https://github.com/vuejs/vue-lite#readme",
24+
"devDependencies": {
25+
"babel-core": "^6.0.0",
26+
"babel-loader": "^6.0.0",
27+
"babel-preset-es2015": "^6.0.0",
28+
"babel-preset-es2015-rollup": "^1.1.1",
29+
"babel-preset-stage-2": "^6.0.0",
30+
"rollup": "^0.25.8",
31+
"rollup-plugin-babel": "^2.4.0",
32+
"rollup-plugin-commonjs": "^2.2.1",
33+
"rollup-plugin-node-resolve": "^1.5.0",
34+
"rollup-plugin-replace": "^1.1.0",
35+
"uglify-js": "^2.6.2",
36+
"webpack": "^1.12.14"
37+
}
38+
}

src/compiler/codegen.js

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
import { parseText } from './text-parser'
2+
3+
const bindRE = /^:|^v-bind:/
4+
const onRE = /^@|^v-on:/
5+
const mustUsePropsRE = /^(value|selected|checked|muted)$/
6+
7+
export function generate (ast) {
8+
const code = genElement(ast)
9+
return new Function (`with (this) { return ${code}}`)
10+
}
11+
12+
function genElement (el, key) {
13+
let exp
14+
if (exp = getAttr(el, 'v-for')) {
15+
return genFor(el, exp)
16+
} else if (exp = getAttr(el, 'v-if')) {
17+
return genIf(el, exp)
18+
} else if (el.tag === 'template') {
19+
return genChildren(el)
20+
} else {
21+
return `__h__('${ el.tag }', ${ genData(el, key) }, ${ genChildren(el) })`
22+
}
23+
}
24+
25+
function genIf (el, exp) {
26+
return `(${ exp }) ? ${ genElement(el) } : ''`
27+
}
28+
29+
function genFor (el, exp) {
30+
const inMatch = exp.match(/([a-zA-Z_][\w]*)\s+(?:in|of)\s+(.*)/)
31+
if (!inMatch) {
32+
throw new Error('Invalid v-for expression: '+ exp)
33+
}
34+
const alias = inMatch[1].trim()
35+
exp = inMatch[2].trim()
36+
const key = el.attrsMap['track-by'] || 'undefined'
37+
return `(${ exp }).map(function (${ alias }, $index) {return ${ genElement(el, key) }})`
38+
}
39+
40+
function genData (el, key) {
41+
if (!el.attrs.length) {
42+
return '{}'
43+
}
44+
let data = key ? `{key:${ key },` : `{`
45+
if (el.attrsMap[':class'] || el.attrsMap['class']) {
46+
data += `class: _renderClass(${ el.attrsMap[':class'] }, "${ el.attrsMap['class'] || '' }"),`
47+
}
48+
let attrs = `attrs:{`
49+
let props = `props:{`
50+
let hasAttrs = false
51+
let hasProps = false
52+
for (let i = 0, l = el.attrs.length; i < l; i++) {
53+
let attr = el.attrs[i]
54+
let name = attr.name
55+
if (bindRE.test(name)) {
56+
name = name.replace(bindRE, '')
57+
if (name === 'class') {
58+
continue
59+
} else if (name === 'style') {
60+
data += `style: ${ attr.value },`
61+
} else if (mustUsePropsRE.test(name)) {
62+
hasProps = true
63+
props += `"${ name }": (${ attr.value }),`
64+
} else {
65+
hasAttrs = true
66+
attrs += `"${ name }": (${ attr.value }),`
67+
}
68+
} else if (onRE.test(name)) {
69+
name = name.replace(onRE, '')
70+
// TODO
71+
} else if (name !== 'class') {
72+
hasAttrs = true
73+
attrs += `"${ name }": (${ JSON.stringify(attr.value) }),`
74+
}
75+
}
76+
if (hasAttrs) {
77+
data += attrs.slice(0, -1) + '},'
78+
}
79+
if (hasProps) {
80+
data += props.slice(0, -1) + '},'
81+
}
82+
return data.replace(/,$/, '') + '}'
83+
}
84+
85+
function genChildren (el) {
86+
if (!el.children.length) {
87+
return 'undefined'
88+
}
89+
return '__flatten__([' + el.children.map(genNode).join(',') + '])'
90+
}
91+
92+
function genNode (node) {
93+
if (node.tag) {
94+
return genElement(node)
95+
} else {
96+
return genText(node)
97+
}
98+
}
99+
100+
function genText (text) {
101+
if (text === ' ') {
102+
return '" "'
103+
} else {
104+
const exp = parseText(text)
105+
if (exp) {
106+
return 'String(' + escapeNewlines(exp) + ')'
107+
} else {
108+
return escapeNewlines(JSON.stringify(text))
109+
}
110+
}
111+
}
112+
113+
function escapeNewlines (str) {
114+
return str.replace(/\n/g, '\\n')
115+
}
116+
117+
function getAttr (el, attr) {
118+
let val
119+
if (val = el.attrsMap[attr]) {
120+
el.attrsMap[attr] = null
121+
for (let i = 0, l = el.attrs.length; i < l; i++) {
122+
if (el.attrs[i].name === attr) {
123+
el.attrs.splice(i, 1)
124+
break
125+
}
126+
}
127+
}
128+
return val
129+
}

0 commit comments

Comments
 (0)