├── .gitignore ├── .npmignore ├── bin ├── index.js └── lib │ └── utils.js ├── index.js ├── package.json ├── readme.md ├── root ├── config │ ├── webpack.base.js │ ├── webpack.dev.js │ └── webpack.prod.js ├── index.html ├── luna.bootstrap.js ├── package.json ├── src │ ├── bootstrap.js │ ├── components │ │ └── .gitkeep │ ├── particles │ │ └── .gitkeep │ └── px2rem.scss ├── static │ ├── css │ │ └── .gitkeep │ └── js │ │ ├── .gitkeep │ │ ├── hotcss.js │ │ └── zepto.js └── template │ ├── component │ ├── index.js │ ├── snippet │ │ ├── script.js │ │ ├── style.css │ │ └── tpl.html │ └── tpl.vue │ └── particle │ ├── index.js │ └── tpl.vue └── src ├── index.js └── lib └── utils.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .DS_Store -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | src/ 2 | node_modules/ 3 | .gitignore 4 | .DS_Store -------------------------------------------------------------------------------- /bin/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; 4 | 5 | var path = _interopRequire(require("path")); 6 | 7 | var fs = _interopRequire(require("fs")); 8 | 9 | var program = _interopRequire(require("commander")); 10 | 11 | var colors = _interopRequire(require("colors")); 12 | 13 | var utils = _interopRequire(require("./lib/utils")); 14 | 15 | var lunaRoot = path.dirname(__dirname); 16 | var runRoot = process.cwd(); 17 | 18 | var lunaPath = function (dir) { 19 | return path.join(lunaRoot, dir); 20 | }; 21 | 22 | var runPath = function (dir) { 23 | return path.join(runRoot, dir); 24 | }; 25 | 26 | var updates = ["package.json", "src/bootstrap.js", "src/px2rem.scss", "static/js/hotcss.js", "static/js/zepto.js", "config/webpack.base.js", "config/webpack.dev.js", "config/webpack.prod.js", "luna.bootstrap.js"]; 27 | 28 | var getVersion = function () { 29 | var _filePath = lunaPath("package.json"); 30 | return JSON.parse(utils.readFile(_filePath)).version; 31 | }; 32 | 33 | var checkEnv = function () { 34 | var isluna = true; 35 | ["package.json", "src/bootstrap.js", "config/webpack.base.js", "config/webpack.dev.js", "config/webpack.prod.js", "luna.bootstrap.js"].map(function (item) { 36 | var _tar = runPath(item); 37 | if (!utils.isExists(_tar) && isluna) { 38 | isluna = false; 39 | } 40 | }); 41 | return isluna; 42 | }; 43 | 44 | var _createProject = function (projectRootPath) { 45 | 46 | var tarPath = function (dir) { 47 | return path.join(runRoot, projectRootPath, dir); 48 | }; 49 | 50 | utils.copyFile({ 51 | source: lunaPath("root/package.json"), 52 | target: tarPath("package.json") 53 | }); 54 | 55 | utils.copyFile({ 56 | source: lunaPath("root/index.html"), 57 | target: tarPath("index.html") 58 | }); 59 | 60 | utils.copyFile({ 61 | source: lunaPath("root/luna.bootstrap.js"), 62 | target: tarPath("luna.bootstrap.js") 63 | }); 64 | 65 | utils.copyDir(lunaPath("root/config/"), tarPath("config/")); 66 | utils.copyDir(lunaPath("root/src/"), tarPath("src/")); 67 | utils.copyDir(lunaPath("root/static/"), tarPath("static/")); 68 | }; 69 | 70 | var createProject = function (projectRootPath) { 71 | if (utils.isExists(projectRootPath)) { 72 | if (!utils.isEmptyDir(projectRootPath)) { 73 | utils.log.warn("`" + projectRootPath + "` is not an empty directory."); 74 | return false; 75 | } 76 | } else { 77 | utils.mkdir(projectRootPath); 78 | } 79 | 80 | _createProject(projectRootPath); 81 | 82 | utils.log.normal("\n enter path:"); 83 | utils.log.main(" $ cd " + projectRootPath + "\n"); 84 | 85 | utils.log.normal(" install dependencies:"); 86 | utils.log.main(" $ npm install\n"); 87 | 88 | utils.log.normal(" run the app:"); 89 | utils.log.main(" $ npm run dev\n"); 90 | }; 91 | 92 | var updateProject = function () { 93 | if (!checkEnv()) { 94 | utils.log.warn("`" + runRoot + "` is not a luna project!"); 95 | return false; 96 | } 97 | var updateNum = 0; 98 | updates.map(function (item) { 99 | var _src_path = lunaPath(path.join("root", item)); 100 | var _tar_path = runPath(item); 101 | utils.copyFile({ 102 | source: _src_path, 103 | target: _tar_path, 104 | overwrite: true, 105 | updateLog: function updateLog() { 106 | updateNum++; 107 | utils.log.debug(" file `" + item + "` is already update!"); 108 | } 109 | }); 110 | }); 111 | if (updateNum === 0) { 112 | utils.log.warn(" no file need to update!"); 113 | } 114 | }; 115 | 116 | var createWidthSnippet = function (type, name) { 117 | if (name.indexOf("-") < 0) { 118 | utils.log.error("`" + name + "` is not available . Example: title-normal "); 119 | return false; 120 | } 121 | if (!checkEnv()) { 122 | utils.log.warn("`" + runRoot + "` is not a luna project!"); 123 | return false; 124 | } 125 | var _src_path = lunaPath("root/template/component/"); 126 | var _tar_path = runPath("src/" + type + "/" + name); 127 | var nameCamel = utils.toCamel(name); 128 | 129 | if (utils.isExists(runPath("src/components/" + name))) { 130 | utils.log.error("components `" + name + "` is already exist!"); 131 | return false; 132 | } 133 | if (utils.isExists(runPath("src/particles/" + name))) { 134 | utils.log.error("particles `" + name + "` is already exist!"); 135 | return false; 136 | } 137 | 138 | utils.mkdir(_tar_path); 139 | utils.mkdir(path.join(_tar_path, "snippet")); 140 | 141 | utils.copyFile({ 142 | source: path.join(_src_path, "index.js"), 143 | target: path.join(_tar_path, "index.js"), 144 | replace: ["{{name}}->" + name, "{{nameCamel}}->" + nameCamel] 145 | }); 146 | 147 | utils.copyFile({ 148 | source: path.join(_src_path, "tpl.vue"), 149 | target: path.join(_tar_path, name + ".vue") 150 | }); 151 | 152 | utils.copyFile({ 153 | source: path.join(_src_path, "snippet/tpl.html"), 154 | target: path.join(_tar_path, "snippet/tpl.html"), 155 | replace: ["{{name}}->" + name, "{{nameCamel}}->" + nameCamel] 156 | }); 157 | 158 | utils.copyFile({ 159 | source: path.join(_src_path, "snippet/style.css"), 160 | target: path.join(_tar_path, "snippet/style.css"), 161 | replace: ["{{name}}->" + name, "{{nameCamel}}->" + nameCamel] 162 | }); 163 | 164 | utils.copyFile({ 165 | source: path.join(_src_path, "snippet/script.js"), 166 | target: path.join(_tar_path, "snippet/script.js") 167 | }); 168 | 169 | utils.log.debug(type + " `" + name + "` has been created!"); 170 | }; 171 | 172 | var createSimple = function (type, name) { 173 | if (name.indexOf("-") < 0) { 174 | utils.log.error("`" + name + "` is not available . Example: title-normal "); 175 | return false; 176 | } 177 | if (!checkEnv()) { 178 | utils.log.warn("`" + runRoot + "` is not a luna project!"); 179 | return false; 180 | } 181 | var _src_path = lunaPath("root/template/particle/"); 182 | var _tar_path = runPath("src/" + type + "/" + name); 183 | var nameCamel = utils.toCamel(name); 184 | 185 | if (utils.isExists(runPath("src/components/" + name))) { 186 | utils.log.error("components `" + name + "` is already exist!"); 187 | return false; 188 | } 189 | if (utils.isExists(runPath("src/particles/" + name))) { 190 | utils.log.error("particles `" + name + "` is already exist!"); 191 | return false; 192 | } 193 | 194 | utils.mkdir(_tar_path); 195 | 196 | utils.copyFile({ 197 | source: path.join(_src_path, "index.js"), 198 | target: path.join(_tar_path, "index.js"), 199 | replace: ["{{name}}->" + name, "{{nameCamel}}->" + nameCamel] 200 | }); 201 | 202 | utils.copyFile({ 203 | source: path.join(_src_path, "tpl.vue"), 204 | target: path.join(_tar_path, name + ".vue"), 205 | replace: ["{{name}}->" + name, "{{nameCamel}}->" + nameCamel] 206 | }); 207 | 208 | utils.log.debug(type + " `" + name + "` has been created!"); 209 | }; 210 | 211 | var createTpl = function (name, type) { 212 | 213 | if (program.mini || program.normal) { 214 | if (program.mini) { 215 | createSimple(type, name); 216 | } 217 | if (program.normal) { 218 | createWidthSnippet(type, name); 219 | } 220 | } else { 221 | if (type === "components") { 222 | createWidthSnippet(type, name); 223 | } 224 | if (type === "particles") { 225 | createSimple(type, name); 226 | } 227 | } 228 | }; 229 | 230 | var displayVersion = function () { 231 | var version = getVersion(); 232 | var chars = ["####################################", "# __ #", "# / / __ __ ____ __ _ #", "# / / / / / / / __ \\ / __`/ #", "# / / / /_/ / / / / / / /_/ / #", "# /_/ \\__,_/ /_/ /_/ \\__,_/\\ #", "# #", "# v " + version + " #", "####################################"].join("\n"); 233 | utils.log.main("\n" + chars + "\n"); 234 | }; 235 | 236 | program.usage("[command] "); 237 | program.option("-v, --version", "output the version number", function () { 238 | displayVersion(); 239 | }); 240 | 241 | program.option("-m, --mini", "when create component/particle use mini template"); 242 | program.option("-n, --normal", "when create component/particle use normal template"); 243 | 244 | program.command("init ").description("init a new project").action(function (projectPath) { 245 | createProject(path.normalize(projectPath + "/")); 246 | }); 247 | 248 | program.command("update").description("update your project , please use at the root of your project").action(function () { 249 | updateProject(); 250 | }); 251 | 252 | program.command("component ").description("create a new component").action(function (componentName) { 253 | createTpl(componentName, "components"); 254 | }); 255 | 256 | program.command("particle ").description("create a new particle").action(function (particleName) { 257 | createTpl(particleName, "particles"); 258 | }); 259 | 260 | program.on("--help", function () { 261 | utils.log.normal(" Examples:\n"); 262 | utils.log.normal(" luna component title-normal\n"); 263 | }); 264 | program.parse(process.argv); 265 | if (!process.argv.slice(2).length) { 266 | program.outputHelp(); 267 | } -------------------------------------------------------------------------------- /bin/lib/utils.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; 4 | 5 | var fs = _interopRequire(require("fs")); 6 | 7 | var colors = _interopRequire(require("colors")); 8 | 9 | var path = _interopRequire(require("path")); 10 | 11 | module.exports = { 12 | log: { 13 | normal: function normal(str) { 14 | console.log(str); 15 | }, 16 | debug: function debug(str) { 17 | console.log(colors.green(str)); 18 | }, 19 | info: function info(str) { 20 | console.log(colors.cyan(str)); 21 | }, 22 | warn: function warn(str) { 23 | console.log(colors.yellow(str)); 24 | }, 25 | error: function error(str) { 26 | console.log(colors.red(str)); 27 | }, 28 | main: function main(str) { 29 | console.log(colors.magenta(str)); 30 | } 31 | }, 32 | isExists: function isExists(src) { 33 | return fs.existsSync(src); 34 | }, 35 | isDir: function isDir(src) { 36 | var stat = fs.lstatSync(src); 37 | return stat.isDirectory(); 38 | }, 39 | isEmptyDir: function isEmptyDir(src) { 40 | var _con = this.readDir(src); 41 | if (_con.length > 0) { 42 | return false; 43 | } 44 | return true; 45 | }, 46 | isFile: function isFile(src) { 47 | var stat = fs.lstatSync(src); 48 | return stat.isFile(); 49 | }, 50 | readFile: function readFile(src) { 51 | return fs.readFileSync(src).toString(); 52 | }, 53 | readDir: function readDir(src) { 54 | return fs.readdirSync(src); 55 | }, 56 | mkdir: function mkdir(tar) { 57 | fs.mkdirSync(tar); 58 | }, 59 | delFile: function delFile(src) { 60 | if (this.isExists(src)) { 61 | fs.unlinkSync(src); 62 | } 63 | }, 64 | writeFile: function writeFile(tar, data) { 65 | fs.writeFileSync(tar, data); 66 | }, 67 | copyFile: function copyFile(config) { 68 | var conf = config || {}; 69 | 70 | var src = conf.source; 71 | var tar = conf.target; 72 | var overwrite = conf.overwrite; 73 | var replace = conf.replace; 74 | var updateLog = conf.updateLog; 75 | 76 | if (!src || !this.isFile(src)) { 77 | return false; 78 | } 79 | 80 | var _src_file_data = this.readFile(src); 81 | 82 | if (replace && replace.length > 0) { 83 | replace.map(function (item) { 84 | var _con = item.split("->"); 85 | var _regexp = new RegExp(_con[0], "g"); 86 | _src_file_data = _src_file_data.replace(_regexp, _con[1]); 87 | }); 88 | } 89 | 90 | if (overwrite && this.isExists(tar)) { 91 | var _tar_file_data = this.readFile(tar); 92 | if (_tar_file_data !== _src_file_data) { 93 | this.delFile(tar); 94 | this.writeFile(tar, _src_file_data); 95 | updateLog && updateLog(); 96 | } 97 | } 98 | 99 | if (!this.isExists(tar)) { 100 | this.writeFile(tar, _src_file_data); 101 | } 102 | }, 103 | copyDir: function copyDir(src, tar) { 104 | var _this = this; 105 | 106 | if (this.isDir(src)) { 107 | if (!this.isExists(tar)) { 108 | this.mkdir(tar); 109 | } 110 | var _con = this.readDir(src); 111 | 112 | if (_con.length < 1) { 113 | return false; 114 | } 115 | 116 | _con.map(function (item) { 117 | if (item[0] === ".") { 118 | return false; 119 | } 120 | var _src_path = path.join(src, item); 121 | var _tar_path = path.join(tar, item); 122 | if (_this.isDir(_src_path)) { 123 | _this.copyDir(_src_path, _tar_path); 124 | } 125 | if (_this.isFile(_src_path)) { 126 | _this.copyFile({ 127 | source: _src_path, 128 | target: _tar_path 129 | }); 130 | } 131 | }); 132 | } 133 | }, 134 | toCamel: function toCamel(str) { 135 | var re = /-(\w)/g; 136 | return str.replace(re, function ($0, $1) { 137 | return $1.toUpperCase(); 138 | }); 139 | } 140 | }; -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env node 2 | module.exports = require('./bin/index.js'); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "luna-command", 3 | "version": "0.1.6", 4 | "description": "For luna development , use Vuejs component", 5 | "main": "index.js", 6 | "scripts": { 7 | "compile": "babel -d bin/ src/", 8 | "prepublish": "npm run compile", 9 | "start": "npm run compile -- --watch" 10 | }, 11 | "author": "mochen ", 12 | "license": "MIT", 13 | "bin": { 14 | "luna": "./index.js" 15 | }, 16 | "dependencies": { 17 | "colors": "^1.1.2", 18 | "commander": "^2.9.0" 19 | }, 20 | "devDependencies": { 21 | "babel": "^4.6.0" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ## luna 2 | 3 | 该工具产生于vue初期,目前已年久失修,慎用 4 | 5 | > Vuejs的组件化开发工具 6 | 7 | ### luna是个啥? 8 | 别着急,慢慢看。luna不止是vue-loader的封装,同时也干了很多别的事。下面是使用luna开发的组件的目录。 9 | ```bash 10 | ├── bootstrap #启动器相关 11 | │ ├── basic.js #包含vuejs及组件标识 12 | │ └── index.js #启动器 13 | └── components #组件文件夹 14 | ├── test-title 15 | │ ├── index.css 16 | │ └── index.js 17 | └── test-banner 18 | ├── index.css 19 | └── index.js 20 | ``` 21 | 一共包含两类文件,一类启动器相关,一类是组件。那我们怎么使用嘞?接着看 22 | ```html 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 43 | ``` 44 | 按照国际惯例,基础文件先加载。启动器最后加载,为了使用便捷,可以手动发射。 45 | 中间呢加载的是组件。如果你开发了N多组件,这里可以只写你需要的即可。 46 | 推荐使用合并加载,或者使用其他工具打包需要的组件。这样可以减少请求数。 47 | 48 | ### 怎么使用? 49 | 好像有那么点意思,那luna怎么使用呢?由于`luna`模块已经被注册了,坑爹的`luna-cli`也被注册了。最后,我们只能退而求其次`luna-command`了。记得要全局安装哦 50 | ```bash 51 | npm install -g luna-command 52 | ``` 53 | 安装完之后,会多一个`luna`命令,虽然模块被注册了,还好。命令名字我们可以自己定义。 54 | ```bash 55 | luna init testProject #初始化一个项目 56 | 57 | luna update #更新项目资源。需在项目根目录执行。 58 | 59 | luna component test-component #新建一个组件,需在项目根目录执行。 60 | 61 | luna particle test-particle #新建一个颗粒组件,需在项目根目录执行。 62 | 63 | luna -h #查看所有帮助 64 | luna -v #查看版本号 65 | ``` 66 | 默认新建`component`的时候使用的是常规模式,新建`particle`使用的是mini模式。常规模式css/js/html是分开的,mini模式是把他们一起放到.vue里面了。你也可以通过命令后面加参数`-m/-n`来强制使用哪种模式。 67 | 68 | ### 如何进行开发? 69 | 70 | 介绍完命令,我们新建一个项目,进入根目录,安装依赖`npm install`。执行`npm run dev`即可开始开发。默认会打开本地`8016`端口来调试组件。 71 | 72 | 开发过程中,使用`luna component/luna particle`新建组件或者颗粒,是不用重启命令的。 73 | 74 | 开发完成后,执行`npm run build`即可将组件打包。 75 | -------------------------------------------------------------------------------- /root/config/webpack.base.js: -------------------------------------------------------------------------------- 1 | var ExtractTextPlugin = require("extract-text-webpack-plugin"); 2 | var webpack = require('webpack'); 3 | 4 | module.exports = { 5 | output: { 6 | path: './build', 7 | publicPath: 'build/', 8 | filename: '[name]/index.js' 9 | }, 10 | module: { 11 | loaders: [ 12 | { test: /\.vue$/, loader : 'vue'}, 13 | { test: /\.js$/, loader: 'babel', exclude: /node_modules/ } 14 | ] 15 | }, 16 | plugins : [ 17 | new webpack.optimize.CommonsChunkPlugin('bootstrap/basic.js'), 18 | new ExtractTextPlugin('[name]/index.css') 19 | ], 20 | babel : { 21 | "presets": ["es2015", "stage-0"], 22 | "plugins": ["transform-runtime"] 23 | }, 24 | vue : { 25 | loaders : { 26 | js: 'babel', 27 | css: ExtractTextPlugin.extract("css"), 28 | sass: ExtractTextPlugin.extract("css!sass") 29 | }, 30 | autoprefixer: { 31 | browsers: ['last 5 versions'] 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /root/config/webpack.dev.js: -------------------------------------------------------------------------------- 1 | var config = require('./webpack.base'); 2 | 3 | //开发模式。目录自动扫描。这里包含了颗粒组件 4 | var fs = require('fs'); 5 | var path = require('path'); 6 | 7 | var projectRoot = path.dirname(__dirname); 8 | 9 | var isDir = function( src ){ 10 | var stat = fs.lstatSync( src ); 11 | return stat.isDirectory(); 12 | } 13 | 14 | var isCpmDir = function( src ){ 15 | if( !isDir(src) ){ 16 | return false; 17 | } 18 | return /\/\w*-\w*[\/]?$/.test( src ); 19 | } 20 | 21 | var source = [ 22 | path.join( projectRoot , 'src/components/' ), 23 | path.join( projectRoot , 'src/particles/' ) 24 | ]; 25 | var alldirs = function(){ 26 | var _dir_tmp = []; 27 | var _entries_tmp = {}; 28 | source.forEach(function( src ){ 29 | var __dirs = fs.readdirSync( src ); 30 | __dirs.forEach(function( item ){ 31 | var __p = path.join( src , item ); 32 | if( isCpmDir(__p) ){ 33 | _dir_tmp.push( __p ); 34 | var key = src.match(/\w*\/$/)[0] + item; 35 | _entries_tmp[key] = path.join( src , item , 'index.js'); 36 | } 37 | }) 38 | }) 39 | 40 | return { 41 | dirs : _dir_tmp, 42 | entries : _entries_tmp 43 | }; 44 | } 45 | 46 | 47 | var dirObj = alldirs(); 48 | 49 | /*** 开发模式,组件自动加入index.html ***/ 50 | var signStart = ''; 51 | var signEnd = ''; 52 | var scripts = function(){ 53 | var str = (signStart + '\n'); 54 | dirObj.dirs.forEach(function( item ){ 55 | if( isCpmDir(item) ){ 56 | str += '\n'; 57 | } 58 | }); 59 | str += (signEnd+ '\n'); 60 | return str; 61 | } 62 | var scriptsStr = scripts(); 63 | var devHtmlPath = path.join( projectRoot , 'index.html'); 64 | var devHtmlCon = fs.readFileSync( devHtmlPath ).toString(); 65 | var regExp = new RegExp(signStart + '[\\w\\W\\s\\n]*' + signEnd , 'gm'); 66 | var newHtmlCon = devHtmlCon.replace(regExp, scriptsStr); 67 | fs.unlinkSync( devHtmlPath ); 68 | fs.writeFileSync( devHtmlPath , newHtmlCon ); 69 | //开发模式,组件自动加入index.html 70 | 71 | dirObj.entries.bootstrap = path.join( path.dirname(__dirname) , 'src/bootstrap.js' ); 72 | config.entry = dirObj.entries; 73 | /*** 将结果配置为entry ***/ 74 | 75 | 76 | 77 | config.devtool = '#source-map'; 78 | config.devServer = { 79 | noInfo: true, 80 | stats: { 81 | colors: true 82 | } 83 | } 84 | config.vue = { 85 | loaders: { 86 | js: 'babel' 87 | } 88 | } 89 | module.exports = config; -------------------------------------------------------------------------------- /root/config/webpack.prod.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack') 2 | var config = require('./webpack.base') 3 | var ExtractTextPlugin = require("extract-text-webpack-plugin"); 4 | var fs = require('fs'); 5 | var path = require('path'); 6 | 7 | var projectRoot = path.dirname(__dirname); 8 | 9 | var isDir = function( src ){ 10 | var stat = fs.lstatSync( src ); 11 | return stat.isDirectory(); 12 | } 13 | 14 | var isCpmDir = function( src ){ 15 | if( !isDir(src) ){ 16 | return false; 17 | } 18 | return /\/\w*-\w*[\/]?$/.test( src ); 19 | } 20 | 21 | /*** 扫描组件目录,这里会忽略颗粒组件 ***/ 22 | var source = [ 23 | path.join( projectRoot , 'src/components/' ) 24 | ]; 25 | 26 | var alldirs = function(){ 27 | var _dir_tmp = []; 28 | var _entries_tmp = {}; 29 | source.forEach(function( src ){ 30 | var __dirs = fs.readdirSync( src ); 31 | __dirs.forEach(function( item ){ 32 | var __p = path.join( src , item ); 33 | if( isCpmDir(__p) ){ 34 | _dir_tmp.push( __p ); 35 | var key = src.match(/\w*\/$/)[0] + item; 36 | _entries_tmp[key] = path.join( src , item , 'index.js'); 37 | } 38 | }) 39 | }) 40 | 41 | return { 42 | dirs : _dir_tmp, 43 | entries : _entries_tmp 44 | }; 45 | } 46 | 47 | var dirObj = alldirs(); 48 | dirObj.entries.bootstrap = path.join( path.dirname(__dirname) , 'src/bootstrap.js' ); 49 | config.entry = dirObj.entries; 50 | /*** 将结果配置为entry ***/ 51 | 52 | config.plugins = ( config.plugins || [] ).concat([ 53 | new webpack.DefinePlugin({ 54 | 'process.env' : { 55 | NODE_ENV : '"production"' 56 | } 57 | }), 58 | new webpack.optimize.UglifyJsPlugin({ 59 | compress : { 60 | warnings : false 61 | } 62 | }), 63 | new webpack.optimize.OccurenceOrderPlugin() 64 | ]); 65 | 66 | module.exports = config; -------------------------------------------------------------------------------- /root/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Document 6 | 7 | 8 | 11 | 21 | 22 | 23 | 24 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 43 | 44 | -------------------------------------------------------------------------------- /root/luna.bootstrap.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var path = require('path'); 3 | var spawn = require('child_process').spawn; 4 | 5 | var source = [ 6 | path.join( __dirname , 'src/components/' ), 7 | path.join( __dirname , 'src/particles/' ) 8 | ] 9 | 10 | var oldDirs = []; 11 | var cmd = null; 12 | var timer = 500; 13 | 14 | var alldirs = function(){ 15 | var _dir_tmp = []; 16 | 17 | source.forEach(function( src ){ 18 | var __dirs = fs.readdirSync( src ); 19 | __dirs.forEach(function( item ){ 20 | _dir_tmp.push( path.join( src , item ) ); 21 | }) 22 | }) 23 | 24 | return _dir_tmp; 25 | } 26 | 27 | var comparedir = function( oldDirs , newDirs ){ 28 | if( oldDirs.length !== newDirs.length ){ 29 | return false; 30 | } 31 | var _oldDirs = oldDirs.sort().join('###'); 32 | var _newDirs = newDirs.sort().join('###'); 33 | if( _oldDirs !== _newDirs ){ 34 | return false; 35 | } 36 | return true; 37 | } 38 | 39 | var autoReload = function(){ 40 | var newDirs = alldirs(); 41 | if( !comparedir( oldDirs , newDirs) ){ 42 | if( cmd === null ){ 43 | cmd = spawn('npm',['start']); 44 | }else{ 45 | cmd.kill(); 46 | cmd = null; 47 | cmd = spawn('npm',['restart']); 48 | } 49 | cmd.stdout.on('data', function (data) { 50 | console.log( data.toString() ); 51 | }); 52 | cmd.stderr.on('data', function (data) { 53 | console.log( data.toString() ); 54 | }); 55 | cmd.on('close',function( code ){ 56 | console.log('child process exited with code ' + code) 57 | }) 58 | oldDirs = newDirs; 59 | } 60 | setTimeout(function(){ 61 | autoReload(); 62 | },timer); 63 | } 64 | 65 | autoReload(); 66 | 67 | process.title = 'lunabootstrap'; 68 | 69 | process.on('exit',function(){ 70 | cmd.kill(); 71 | }) 72 | 73 | -------------------------------------------------------------------------------- /root/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "vue": "^1.0.13" 4 | }, 5 | "devDependencies": { 6 | "autoprefixer-loader": "^3.1.0", 7 | "babel-core": "^6.1.2", 8 | "babel-loader": "^6.1.0", 9 | "babel-plugin-transform-runtime": "^6.1.2", 10 | "babel-preset-es2015": "^6.1.2", 11 | "babel-preset-stage-0": "^6.1.2", 12 | "babel-runtime": "^5.8.0", 13 | "css-loader": "^0.23.0", 14 | "extract-text-webpack-plugin": "^0.9.1", 15 | "node-sass": "^3.4.2", 16 | "sass-loader": "^3.1.2", 17 | "vue-hot-reload-api": "^1.2.0", 18 | "vue-loader": "^7.4.1", 19 | "webpack": "^1.12.2", 20 | "webpack-dev-server": "^1.12.0" 21 | }, 22 | "scripts": { 23 | "build": "webpack --progress --hide-modules --config config/webpack.prod.js", 24 | "dev" : "node luna.bootstrap.js", 25 | "start": "webpack-dev-server --inline --hot --config config/webpack.dev.js --port 8016", 26 | "stop": "pkill -9 node" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /root/src/bootstrap.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | 3 | var lu = { 4 | init : false 5 | } 6 | 7 | var luna = { 8 | csshandle( obj , handles ){ 9 | if( typeof obj === 'undefined' ){ 10 | return; 11 | } 12 | for( var name in obj ){ 13 | if( typeof handles[name] !== 'undefined'){ 14 | handles[name](obj[name]); 15 | } 16 | } 17 | }, 18 | px2rem(px){ 19 | return hotcss.px2rem(parseInt(px)) + 'rem'; 20 | } 21 | }; 22 | 23 | luna.start = (el) => { 24 | if( lu.init === true ){ 25 | console.log('luna已经启动,不能重复start'); 26 | }else{ 27 | lu.init = true; 28 | luna.vm = new Vue({ 29 | el : el || 'body' 30 | }) 31 | } 32 | } 33 | 34 | window.luna = luna; 35 | 36 | /*window.luna = new Vue({ 37 | el : '#app' 38 | });*/ -------------------------------------------------------------------------------- /root/src/components/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imochen/luna/0d387641eea49aca989433dc8d5f13b4338d773b/root/src/components/.gitkeep -------------------------------------------------------------------------------- /root/src/particles/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imochen/luna/0d387641eea49aca989433dc8d5f13b4338d773b/root/src/particles/.gitkeep -------------------------------------------------------------------------------- /root/src/px2rem.scss: -------------------------------------------------------------------------------- 1 | @function px2rem( $px ){ 2 | @return $px*320/$designWidth/20 + rem; 3 | } 4 | 5 | $designWidth : 750; -------------------------------------------------------------------------------- /root/static/css/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imochen/luna/0d387641eea49aca989433dc8d5f13b4338d773b/root/static/css/.gitkeep -------------------------------------------------------------------------------- /root/static/js/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imochen/luna/0d387641eea49aca989433dc8d5f13b4338d773b/root/static/js/.gitkeep -------------------------------------------------------------------------------- /root/static/js/hotcss.js: -------------------------------------------------------------------------------- 1 | (function(window, document) { 2 | 3 | 'use strict'; 4 | 5 | (function() { 6 | //根据devicePixelRatio自定计算scale 7 | //可以有效解决移动端1px这个世纪难题。 8 | var viewportEl = document.querySelector('meta[name="viewport"]'), 9 | hotcssEl = document.querySelector('meta[name="hotcss"]'), 10 | dpr = window.devicePixelRatio || 1; 11 | 12 | //允许通过自定义name为hotcss的meta头,通过initial-dpr来强制定义页面缩放 13 | if (hotcssEl) { 14 | var hotcssCon = hotcssEl.getAttribute('content'); 15 | if (hotcssCon) { 16 | var initialDpr = hotcssCon.match(/initial\-dpr=([\d\.]+)/); 17 | if (initialDpr) { 18 | dpr = parseFloat(initialDpr[1]); 19 | } 20 | } 21 | } 22 | 23 | document.documentElement.setAttribute('data-dpr', dpr); 24 | 25 | var scale = 1 / dpr, 26 | content = 'width=device-width, initial-scale=' + scale + ', minimum-scale=' + scale + ', maximum-scale=' + scale + ', user-scalable=no'; 27 | 28 | if (viewportEl) { 29 | viewportEl.setAttribute('content', content); 30 | } else { 31 | viewportEl = document.createElement('meta'); 32 | viewportEl.setAttribute('name', 'viewport'); 33 | viewportEl.setAttribute('content', content); 34 | document.head.appendChild(viewportEl); 35 | } 36 | 37 | })(); 38 | 39 | //给hotcss开辟个命名空间,别问我为什么,我要给你准备你会用到的方法,免得用到的时候还要自己写。 40 | var hotcss = {}; 41 | 42 | hotcss.px2rem = function(px, designWidth) { 43 | //预判你将会在JS中用到尺寸,特提供一个方法助你在JS中将px转为rem。就是这么贴心。 44 | if (!designWidth) { 45 | //如果你在JS中大量用到此方法,建议直接定义 hotcss.designWidth 来定义设计图尺寸; 46 | //否则可以在第二个参数告诉我你的设计图是多大。 47 | designWidth = parseInt(hotcss.designWidth, 10); 48 | } 49 | 50 | return parseInt(px, 10) * 320 / designWidth / 20; 51 | } 52 | 53 | hotcss.rem2px = function(rem, designWidth) { 54 | //新增一个rem2px的方法。用法和px2rem一致。 55 | if (!designWidth) { 56 | designWidth = parseInt(hotcss.designWidth, 10); 57 | } 58 | //rem可能为小数,这里不再做处理了 59 | return rem * 20 * designWidth / 320; 60 | } 61 | 62 | hotcss.mresize = function() { 63 | //对,这个就是核心方法了,给HTML设置font-size,三行足矣。 64 | var innerWidth = window.innerWidth; 65 | 66 | if (!innerWidth) { 67 | return false; 68 | } 69 | 70 | document.documentElement.style.fontSize = (innerWidth * 20 / 320) + 'px'; 71 | 72 | }; 73 | 74 | hotcss.mresize(); 75 | //直接调用一次 76 | 77 | window.addEventListener('resize', function() { 78 | clearTimeout(hotcss.tid); 79 | hotcss.tid = setTimeout(hotcss.mresize, 33); 80 | }, false); 81 | //绑定resize的时候调用 82 | 83 | window.addEventListener('load', hotcss.mresize, false); 84 | //防止不明原因的bug。load之后再调用一次。 85 | 86 | 87 | setTimeout(function() { 88 | hotcss.mresize(); 89 | //防止某些机型怪异现象,异步再调用一次 90 | }, 333) 91 | 92 | window.hotcss = hotcss; 93 | //命名空间暴露给你,控制权交给你,想怎么调怎么调。 94 | 95 | 96 | })(window, document); -------------------------------------------------------------------------------- /root/static/js/zepto.js: -------------------------------------------------------------------------------- 1 | /* Zepto v1.1.6 - zepto event ajax form ie - zeptojs.com/license */ 2 | var Zepto = (function() { 3 | var undefined, key, $, classList, emptyArray = [], slice = emptyArray.slice, filter = emptyArray.filter, 4 | document = window.document, 5 | elementDisplay = {}, classCache = {}, 6 | cssNumber = { 'column-count': 1, 'columns': 1, 'font-weight': 1, 'line-height': 1,'opacity': 1, 'z-index': 1, 'zoom': 1 }, 7 | fragmentRE = /^\s*<(\w+|!)[^>]*>/, 8 | singleTagRE = /^<(\w+)\s*\/?>(?:<\/\1>|)$/, 9 | tagExpanderRE = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig, 10 | rootNodeRE = /^(?:body|html)$/i, 11 | capitalRE = /([A-Z])/g, 12 | 13 | // special attributes that should be get/set via method calls 14 | methodAttributes = ['val', 'css', 'html', 'text', 'data', 'width', 'height', 'offset'], 15 | 16 | adjacencyOperators = [ 'after', 'prepend', 'before', 'append' ], 17 | table = document.createElement('table'), 18 | tableRow = document.createElement('tr'), 19 | containers = { 20 | 'tr': document.createElement('tbody'), 21 | 'tbody': table, 'thead': table, 'tfoot': table, 22 | 'td': tableRow, 'th': tableRow, 23 | '*': document.createElement('div') 24 | }, 25 | readyRE = /complete|loaded|interactive/, 26 | simpleSelectorRE = /^[\w-]*$/, 27 | class2type = {}, 28 | toString = class2type.toString, 29 | zepto = {}, 30 | camelize, uniq, 31 | tempParent = document.createElement('div'), 32 | propMap = { 33 | 'tabindex': 'tabIndex', 34 | 'readonly': 'readOnly', 35 | 'for': 'htmlFor', 36 | 'class': 'className', 37 | 'maxlength': 'maxLength', 38 | 'cellspacing': 'cellSpacing', 39 | 'cellpadding': 'cellPadding', 40 | 'rowspan': 'rowSpan', 41 | 'colspan': 'colSpan', 42 | 'usemap': 'useMap', 43 | 'frameborder': 'frameBorder', 44 | 'contenteditable': 'contentEditable' 45 | }, 46 | isArray = Array.isArray || 47 | function(object){ return object instanceof Array } 48 | 49 | zepto.matches = function(element, selector) { 50 | if (!selector || !element || element.nodeType !== 1) return false 51 | var matchesSelector = element.webkitMatchesSelector || element.mozMatchesSelector || 52 | element.oMatchesSelector || element.matchesSelector 53 | if (matchesSelector) return matchesSelector.call(element, selector) 54 | // fall back to performing a selector: 55 | var match, parent = element.parentNode, temp = !parent 56 | if (temp) (parent = tempParent).appendChild(element) 57 | match = ~zepto.qsa(parent, selector).indexOf(element) 58 | temp && tempParent.removeChild(element) 59 | return match 60 | } 61 | 62 | function type(obj) { 63 | return obj == null ? String(obj) : 64 | class2type[toString.call(obj)] || "object" 65 | } 66 | 67 | function isFunction(value) { return type(value) == "function" } 68 | function isWindow(obj) { return obj != null && obj == obj.window } 69 | function isDocument(obj) { return obj != null && obj.nodeType == obj.DOCUMENT_NODE } 70 | function isObject(obj) { return type(obj) == "object" } 71 | function isPlainObject(obj) { 72 | return isObject(obj) && !isWindow(obj) && Object.getPrototypeOf(obj) == Object.prototype 73 | } 74 | function likeArray(obj) { return typeof obj.length == 'number' } 75 | 76 | function compact(array) { return filter.call(array, function(item){ return item != null }) } 77 | function flatten(array) { return array.length > 0 ? $.fn.concat.apply([], array) : array } 78 | camelize = function(str){ return str.replace(/-+(.)?/g, function(match, chr){ return chr ? chr.toUpperCase() : '' }) } 79 | function dasherize(str) { 80 | return str.replace(/::/g, '/') 81 | .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2') 82 | .replace(/([a-z\d])([A-Z])/g, '$1_$2') 83 | .replace(/_/g, '-') 84 | .toLowerCase() 85 | } 86 | uniq = function(array){ return filter.call(array, function(item, idx){ return array.indexOf(item) == idx }) } 87 | 88 | function classRE(name) { 89 | return name in classCache ? 90 | classCache[name] : (classCache[name] = new RegExp('(^|\\s)' + name + '(\\s|$)')) 91 | } 92 | 93 | function maybeAddPx(name, value) { 94 | return (typeof value == "number" && !cssNumber[dasherize(name)]) ? value + "px" : value 95 | } 96 | 97 | function defaultDisplay(nodeName) { 98 | var element, display 99 | if (!elementDisplay[nodeName]) { 100 | element = document.createElement(nodeName) 101 | document.body.appendChild(element) 102 | display = getComputedStyle(element, '').getPropertyValue("display") 103 | element.parentNode.removeChild(element) 104 | display == "none" && (display = "block") 105 | elementDisplay[nodeName] = display 106 | } 107 | return elementDisplay[nodeName] 108 | } 109 | 110 | function children(element) { 111 | return 'children' in element ? 112 | slice.call(element.children) : 113 | $.map(element.childNodes, function(node){ if (node.nodeType == 1) return node }) 114 | } 115 | 116 | // `$.zepto.fragment` takes a html string and an optional tag name 117 | // to generate DOM nodes nodes from the given html string. 118 | // The generated DOM nodes are returned as an array. 119 | // This function can be overriden in plugins for example to make 120 | // it compatible with browsers that don't support the DOM fully. 121 | zepto.fragment = function(html, name, properties) { 122 | var dom, nodes, container 123 | 124 | // A special case optimization for a single tag 125 | if (singleTagRE.test(html)) dom = $(document.createElement(RegExp.$1)) 126 | 127 | if (!dom) { 128 | if (html.replace) html = html.replace(tagExpanderRE, "<$1>") 129 | if (name === undefined) name = fragmentRE.test(html) && RegExp.$1 130 | if (!(name in containers)) name = '*' 131 | 132 | container = containers[name] 133 | container.innerHTML = '' + html 134 | dom = $.each(slice.call(container.childNodes), function(){ 135 | container.removeChild(this) 136 | }) 137 | } 138 | 139 | if (isPlainObject(properties)) { 140 | nodes = $(dom) 141 | $.each(properties, function(key, value) { 142 | if (methodAttributes.indexOf(key) > -1) nodes[key](value) 143 | else nodes.attr(key, value) 144 | }) 145 | } 146 | 147 | return dom 148 | } 149 | 150 | // `$.zepto.Z` swaps out the prototype of the given `dom` array 151 | // of nodes with `$.fn` and thus supplying all the Zepto functions 152 | // to the array. Note that `__proto__` is not supported on Internet 153 | // Explorer. This method can be overriden in plugins. 154 | zepto.Z = function(dom, selector) { 155 | dom = dom || [] 156 | dom.__proto__ = $.fn 157 | dom.selector = selector || '' 158 | return dom 159 | } 160 | 161 | // `$.zepto.isZ` should return `true` if the given object is a Zepto 162 | // collection. This method can be overriden in plugins. 163 | zepto.isZ = function(object) { 164 | return object instanceof zepto.Z 165 | } 166 | 167 | // `$.zepto.init` is Zepto's counterpart to jQuery's `$.fn.init` and 168 | // takes a CSS selector and an optional context (and handles various 169 | // special cases). 170 | // This method can be overriden in plugins. 171 | zepto.init = function(selector, context) { 172 | var dom 173 | // If nothing given, return an empty Zepto collection 174 | if (!selector) return zepto.Z() 175 | // Optimize for string selectors 176 | else if (typeof selector == 'string') { 177 | selector = selector.trim() 178 | // If it's a html fragment, create nodes from it 179 | // Note: In both Chrome 21 and Firefox 15, DOM error 12 180 | // is thrown if the fragment doesn't begin with < 181 | if (selector[0] == '<' && fragmentRE.test(selector)) 182 | dom = zepto.fragment(selector, RegExp.$1, context), selector = null 183 | // If there's a context, create a collection on that context first, and select 184 | // nodes from there 185 | else if (context !== undefined) return $(context).find(selector) 186 | // If it's a CSS selector, use it to select nodes. 187 | else dom = zepto.qsa(document, selector) 188 | } 189 | // If a function is given, call it when the DOM is ready 190 | else if (isFunction(selector)) return $(document).ready(selector) 191 | // If a Zepto collection is given, just return it 192 | else if (zepto.isZ(selector)) return selector 193 | else { 194 | // normalize array if an array of nodes is given 195 | if (isArray(selector)) dom = compact(selector) 196 | // Wrap DOM nodes. 197 | else if (isObject(selector)) 198 | dom = [selector], selector = null 199 | // If it's a html fragment, create nodes from it 200 | else if (fragmentRE.test(selector)) 201 | dom = zepto.fragment(selector.trim(), RegExp.$1, context), selector = null 202 | // If there's a context, create a collection on that context first, and select 203 | // nodes from there 204 | else if (context !== undefined) return $(context).find(selector) 205 | // And last but no least, if it's a CSS selector, use it to select nodes. 206 | else dom = zepto.qsa(document, selector) 207 | } 208 | // create a new Zepto collection from the nodes found 209 | return zepto.Z(dom, selector) 210 | } 211 | 212 | // `$` will be the base `Zepto` object. When calling this 213 | // function just call `$.zepto.init, which makes the implementation 214 | // details of selecting nodes and creating Zepto collections 215 | // patchable in plugins. 216 | $ = function(selector, context){ 217 | return zepto.init(selector, context) 218 | } 219 | 220 | function extend(target, source, deep) { 221 | for (key in source) 222 | if (deep && (isPlainObject(source[key]) || isArray(source[key]))) { 223 | if (isPlainObject(source[key]) && !isPlainObject(target[key])) 224 | target[key] = {} 225 | if (isArray(source[key]) && !isArray(target[key])) 226 | target[key] = [] 227 | extend(target[key], source[key], deep) 228 | } 229 | else if (source[key] !== undefined) target[key] = source[key] 230 | } 231 | 232 | // Copy all but undefined properties from one or more 233 | // objects to the `target` object. 234 | $.extend = function(target){ 235 | var deep, args = slice.call(arguments, 1) 236 | if (typeof target == 'boolean') { 237 | deep = target 238 | target = args.shift() 239 | } 240 | args.forEach(function(arg){ extend(target, arg, deep) }) 241 | return target 242 | } 243 | 244 | // `$.zepto.qsa` is Zepto's CSS selector implementation which 245 | // uses `document.querySelectorAll` and optimizes for some special cases, like `#id`. 246 | // This method can be overriden in plugins. 247 | zepto.qsa = function(element, selector){ 248 | var found, 249 | maybeID = selector[0] == '#', 250 | maybeClass = !maybeID && selector[0] == '.', 251 | nameOnly = maybeID || maybeClass ? selector.slice(1) : selector, // Ensure that a 1 char tag name still gets checked 252 | isSimple = simpleSelectorRE.test(nameOnly) 253 | return (isDocument(element) && isSimple && maybeID) ? 254 | ( (found = element.getElementById(nameOnly)) ? [found] : [] ) : 255 | (element.nodeType !== 1 && element.nodeType !== 9) ? [] : 256 | slice.call( 257 | isSimple && !maybeID ? 258 | maybeClass ? element.getElementsByClassName(nameOnly) : // If it's simple, it could be a class 259 | element.getElementsByTagName(selector) : // Or a tag 260 | element.querySelectorAll(selector) // Or it's not simple, and we need to query all 261 | ) 262 | } 263 | 264 | function filtered(nodes, selector) { 265 | return selector == null ? $(nodes) : $(nodes).filter(selector) 266 | } 267 | 268 | $.contains = document.documentElement.contains ? 269 | function(parent, node) { 270 | return parent !== node && parent.contains(node) 271 | } : 272 | function(parent, node) { 273 | while (node && (node = node.parentNode)) 274 | if (node === parent) return true 275 | return false 276 | } 277 | 278 | function funcArg(context, arg, idx, payload) { 279 | return isFunction(arg) ? arg.call(context, idx, payload) : arg 280 | } 281 | 282 | function setAttribute(node, name, value) { 283 | value == null ? node.removeAttribute(name) : node.setAttribute(name, value) 284 | } 285 | 286 | // access className property while respecting SVGAnimatedString 287 | function className(node, value){ 288 | var klass = node.className || '', 289 | svg = klass && klass.baseVal !== undefined 290 | 291 | if (value === undefined) return svg ? klass.baseVal : klass 292 | svg ? (klass.baseVal = value) : (node.className = value) 293 | } 294 | 295 | // "true" => true 296 | // "false" => false 297 | // "null" => null 298 | // "42" => 42 299 | // "42.5" => 42.5 300 | // "08" => "08" 301 | // JSON => parse if valid 302 | // String => self 303 | function deserializeValue(value) { 304 | try { 305 | return value ? 306 | value == "true" || 307 | ( value == "false" ? false : 308 | value == "null" ? null : 309 | +value + "" == value ? +value : 310 | /^[\[\{]/.test(value) ? $.parseJSON(value) : 311 | value ) 312 | : value 313 | } catch(e) { 314 | return value 315 | } 316 | } 317 | 318 | $.type = type 319 | $.isFunction = isFunction 320 | $.isWindow = isWindow 321 | $.isArray = isArray 322 | $.isPlainObject = isPlainObject 323 | 324 | $.isEmptyObject = function(obj) { 325 | var name 326 | for (name in obj) return false 327 | return true 328 | } 329 | 330 | $.inArray = function(elem, array, i){ 331 | return emptyArray.indexOf.call(array, elem, i) 332 | } 333 | 334 | $.camelCase = camelize 335 | $.trim = function(str) { 336 | return str == null ? "" : String.prototype.trim.call(str) 337 | } 338 | 339 | // plugin compatibility 340 | $.uuid = 0 341 | $.support = { } 342 | $.expr = { } 343 | 344 | $.map = function(elements, callback){ 345 | var value, values = [], i, key 346 | if (likeArray(elements)) 347 | for (i = 0; i < elements.length; i++) { 348 | value = callback(elements[i], i) 349 | if (value != null) values.push(value) 350 | } 351 | else 352 | for (key in elements) { 353 | value = callback(elements[key], key) 354 | if (value != null) values.push(value) 355 | } 356 | return flatten(values) 357 | } 358 | 359 | $.each = function(elements, callback){ 360 | var i, key 361 | if (likeArray(elements)) { 362 | for (i = 0; i < elements.length; i++) 363 | if (callback.call(elements[i], i, elements[i]) === false) return elements 364 | } else { 365 | for (key in elements) 366 | if (callback.call(elements[key], key, elements[key]) === false) return elements 367 | } 368 | 369 | return elements 370 | } 371 | 372 | $.grep = function(elements, callback){ 373 | return filter.call(elements, callback) 374 | } 375 | 376 | if (window.JSON) $.parseJSON = JSON.parse 377 | 378 | // Populate the class2type map 379 | $.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) { 380 | class2type[ "[object " + name + "]" ] = name.toLowerCase() 381 | }) 382 | 383 | // Define methods that will be available on all 384 | // Zepto collections 385 | $.fn = { 386 | // Because a collection acts like an array 387 | // copy over these useful array functions. 388 | forEach: emptyArray.forEach, 389 | reduce: emptyArray.reduce, 390 | push: emptyArray.push, 391 | sort: emptyArray.sort, 392 | indexOf: emptyArray.indexOf, 393 | concat: emptyArray.concat, 394 | 395 | // `map` and `slice` in the jQuery API work differently 396 | // from their array counterparts 397 | map: function(fn){ 398 | return $($.map(this, function(el, i){ return fn.call(el, i, el) })) 399 | }, 400 | slice: function(){ 401 | return $(slice.apply(this, arguments)) 402 | }, 403 | 404 | ready: function(callback){ 405 | // need to check if document.body exists for IE as that browser reports 406 | // document ready when it hasn't yet created the body element 407 | if (readyRE.test(document.readyState) && document.body) callback($) 408 | else document.addEventListener('DOMContentLoaded', function(){ callback($) }, false) 409 | return this 410 | }, 411 | get: function(idx){ 412 | return idx === undefined ? slice.call(this) : this[idx >= 0 ? idx : idx + this.length] 413 | }, 414 | toArray: function(){ return this.get() }, 415 | size: function(){ 416 | return this.length 417 | }, 418 | remove: function(){ 419 | return this.each(function(){ 420 | if (this.parentNode != null) 421 | this.parentNode.removeChild(this) 422 | }) 423 | }, 424 | each: function(callback){ 425 | emptyArray.every.call(this, function(el, idx){ 426 | return callback.call(el, idx, el) !== false 427 | }) 428 | return this 429 | }, 430 | filter: function(selector){ 431 | if (isFunction(selector)) return this.not(this.not(selector)) 432 | return $(filter.call(this, function(element){ 433 | return zepto.matches(element, selector) 434 | })) 435 | }, 436 | add: function(selector,context){ 437 | return $(uniq(this.concat($(selector,context)))) 438 | }, 439 | is: function(selector){ 440 | return this.length > 0 && zepto.matches(this[0], selector) 441 | }, 442 | not: function(selector){ 443 | var nodes=[] 444 | if (isFunction(selector) && selector.call !== undefined) 445 | this.each(function(idx){ 446 | if (!selector.call(this,idx)) nodes.push(this) 447 | }) 448 | else { 449 | var excludes = typeof selector == 'string' ? this.filter(selector) : 450 | (likeArray(selector) && isFunction(selector.item)) ? slice.call(selector) : $(selector) 451 | this.forEach(function(el){ 452 | if (excludes.indexOf(el) < 0) nodes.push(el) 453 | }) 454 | } 455 | return $(nodes) 456 | }, 457 | has: function(selector){ 458 | return this.filter(function(){ 459 | return isObject(selector) ? 460 | $.contains(this, selector) : 461 | $(this).find(selector).size() 462 | }) 463 | }, 464 | eq: function(idx){ 465 | return idx === -1 ? this.slice(idx) : this.slice(idx, + idx + 1) 466 | }, 467 | first: function(){ 468 | var el = this[0] 469 | return el && !isObject(el) ? el : $(el) 470 | }, 471 | last: function(){ 472 | var el = this[this.length - 1] 473 | return el && !isObject(el) ? el : $(el) 474 | }, 475 | find: function(selector){ 476 | var result, $this = this 477 | if (!selector) result = $() 478 | else if (typeof selector == 'object') 479 | result = $(selector).filter(function(){ 480 | var node = this 481 | return emptyArray.some.call($this, function(parent){ 482 | return $.contains(parent, node) 483 | }) 484 | }) 485 | else if (this.length == 1) result = $(zepto.qsa(this[0], selector)) 486 | else result = this.map(function(){ return zepto.qsa(this, selector) }) 487 | return result 488 | }, 489 | closest: function(selector, context){ 490 | var node = this[0], collection = false 491 | if (typeof selector == 'object') collection = $(selector) 492 | while (node && !(collection ? collection.indexOf(node) >= 0 : zepto.matches(node, selector))) 493 | node = node !== context && !isDocument(node) && node.parentNode 494 | return $(node) 495 | }, 496 | parents: function(selector){ 497 | var ancestors = [], nodes = this 498 | while (nodes.length > 0) 499 | nodes = $.map(nodes, function(node){ 500 | if ((node = node.parentNode) && !isDocument(node) && ancestors.indexOf(node) < 0) { 501 | ancestors.push(node) 502 | return node 503 | } 504 | }) 505 | return filtered(ancestors, selector) 506 | }, 507 | parent: function(selector){ 508 | return filtered(uniq(this.pluck('parentNode')), selector) 509 | }, 510 | children: function(selector){ 511 | return filtered(this.map(function(){ return children(this) }), selector) 512 | }, 513 | contents: function() { 514 | return this.map(function() { return slice.call(this.childNodes) }) 515 | }, 516 | siblings: function(selector){ 517 | return filtered(this.map(function(i, el){ 518 | return filter.call(children(el.parentNode), function(child){ return child!==el }) 519 | }), selector) 520 | }, 521 | empty: function(){ 522 | return this.each(function(){ this.innerHTML = '' }) 523 | }, 524 | // `pluck` is borrowed from Prototype.js 525 | pluck: function(property){ 526 | return $.map(this, function(el){ return el[property] }) 527 | }, 528 | show: function(){ 529 | return this.each(function(){ 530 | this.style.display == "none" && (this.style.display = '') 531 | if (getComputedStyle(this, '').getPropertyValue("display") == "none") 532 | this.style.display = defaultDisplay(this.nodeName) 533 | }) 534 | }, 535 | replaceWith: function(newContent){ 536 | return this.before(newContent).remove() 537 | }, 538 | wrap: function(structure){ 539 | var func = isFunction(structure) 540 | if (this[0] && !func) 541 | var dom = $(structure).get(0), 542 | clone = dom.parentNode || this.length > 1 543 | 544 | return this.each(function(index){ 545 | $(this).wrapAll( 546 | func ? structure.call(this, index) : 547 | clone ? dom.cloneNode(true) : dom 548 | ) 549 | }) 550 | }, 551 | wrapAll: function(structure){ 552 | if (this[0]) { 553 | $(this[0]).before(structure = $(structure)) 554 | var children 555 | // drill down to the inmost element 556 | while ((children = structure.children()).length) structure = children.first() 557 | $(structure).append(this) 558 | } 559 | return this 560 | }, 561 | wrapInner: function(structure){ 562 | var func = isFunction(structure) 563 | return this.each(function(index){ 564 | var self = $(this), contents = self.contents(), 565 | dom = func ? structure.call(this, index) : structure 566 | contents.length ? contents.wrapAll(dom) : self.append(dom) 567 | }) 568 | }, 569 | unwrap: function(){ 570 | this.parent().each(function(){ 571 | $(this).replaceWith($(this).children()) 572 | }) 573 | return this 574 | }, 575 | clone: function(){ 576 | return this.map(function(){ return this.cloneNode(true) }) 577 | }, 578 | hide: function(){ 579 | return this.css("display", "none") 580 | }, 581 | toggle: function(setting){ 582 | return this.each(function(){ 583 | var el = $(this) 584 | ;(setting === undefined ? el.css("display") == "none" : setting) ? el.show() : el.hide() 585 | }) 586 | }, 587 | prev: function(selector){ return $(this.pluck('previousElementSibling')).filter(selector || '*') }, 588 | next: function(selector){ return $(this.pluck('nextElementSibling')).filter(selector || '*') }, 589 | html: function(html){ 590 | return 0 in arguments ? 591 | this.each(function(idx){ 592 | var originHtml = this.innerHTML 593 | $(this).empty().append( funcArg(this, html, idx, originHtml) ) 594 | }) : 595 | (0 in this ? this[0].innerHTML : null) 596 | }, 597 | text: function(text){ 598 | return 0 in arguments ? 599 | this.each(function(idx){ 600 | var newText = funcArg(this, text, idx, this.textContent) 601 | this.textContent = newText == null ? '' : ''+newText 602 | }) : 603 | (0 in this ? this[0].textContent : null) 604 | }, 605 | attr: function(name, value){ 606 | var result 607 | return (typeof name == 'string' && !(1 in arguments)) ? 608 | (!this.length || this[0].nodeType !== 1 ? undefined : 609 | (!(result = this[0].getAttribute(name)) && name in this[0]) ? this[0][name] : result 610 | ) : 611 | this.each(function(idx){ 612 | if (this.nodeType !== 1) return 613 | if (isObject(name)) for (key in name) setAttribute(this, key, name[key]) 614 | else setAttribute(this, name, funcArg(this, value, idx, this.getAttribute(name))) 615 | }) 616 | }, 617 | removeAttr: function(name){ 618 | return this.each(function(){ this.nodeType === 1 && name.split(' ').forEach(function(attribute){ 619 | setAttribute(this, attribute) 620 | }, this)}) 621 | }, 622 | prop: function(name, value){ 623 | name = propMap[name] || name 624 | return (1 in arguments) ? 625 | this.each(function(idx){ 626 | this[name] = funcArg(this, value, idx, this[name]) 627 | }) : 628 | (this[0] && this[0][name]) 629 | }, 630 | data: function(name, value){ 631 | var attrName = 'data-' + name.replace(capitalRE, '-$1').toLowerCase() 632 | 633 | var data = (1 in arguments) ? 634 | this.attr(attrName, value) : 635 | this.attr(attrName) 636 | 637 | return data !== null ? deserializeValue(data) : undefined 638 | }, 639 | val: function(value){ 640 | return 0 in arguments ? 641 | this.each(function(idx){ 642 | this.value = funcArg(this, value, idx, this.value) 643 | }) : 644 | (this[0] && (this[0].multiple ? 645 | $(this[0]).find('option').filter(function(){ return this.selected }).pluck('value') : 646 | this[0].value) 647 | ) 648 | }, 649 | offset: function(coordinates){ 650 | if (coordinates) return this.each(function(index){ 651 | var $this = $(this), 652 | coords = funcArg(this, coordinates, index, $this.offset()), 653 | parentOffset = $this.offsetParent().offset(), 654 | props = { 655 | top: coords.top - parentOffset.top, 656 | left: coords.left - parentOffset.left 657 | } 658 | 659 | if ($this.css('position') == 'static') props['position'] = 'relative' 660 | $this.css(props) 661 | }) 662 | if (!this.length) return null 663 | var obj = this[0].getBoundingClientRect() 664 | return { 665 | left: obj.left + window.pageXOffset, 666 | top: obj.top + window.pageYOffset, 667 | width: Math.round(obj.width), 668 | height: Math.round(obj.height) 669 | } 670 | }, 671 | css: function(property, value){ 672 | if (arguments.length < 2) { 673 | var computedStyle, element = this[0] 674 | if(!element) return 675 | computedStyle = getComputedStyle(element, '') 676 | if (typeof property == 'string') 677 | return element.style[camelize(property)] || computedStyle.getPropertyValue(property) 678 | else if (isArray(property)) { 679 | var props = {} 680 | $.each(property, function(_, prop){ 681 | props[prop] = (element.style[camelize(prop)] || computedStyle.getPropertyValue(prop)) 682 | }) 683 | return props 684 | } 685 | } 686 | 687 | var css = '' 688 | if (type(property) == 'string') { 689 | if (!value && value !== 0) 690 | this.each(function(){ this.style.removeProperty(dasherize(property)) }) 691 | else 692 | css = dasherize(property) + ":" + maybeAddPx(property, value) 693 | } else { 694 | for (key in property) 695 | if (!property[key] && property[key] !== 0) 696 | this.each(function(){ this.style.removeProperty(dasherize(key)) }) 697 | else 698 | css += dasherize(key) + ':' + maybeAddPx(key, property[key]) + ';' 699 | } 700 | 701 | return this.each(function(){ this.style.cssText += ';' + css }) 702 | }, 703 | index: function(element){ 704 | return element ? this.indexOf($(element)[0]) : this.parent().children().indexOf(this[0]) 705 | }, 706 | hasClass: function(name){ 707 | if (!name) return false 708 | return emptyArray.some.call(this, function(el){ 709 | return this.test(className(el)) 710 | }, classRE(name)) 711 | }, 712 | addClass: function(name){ 713 | if (!name) return this 714 | return this.each(function(idx){ 715 | if (!('className' in this)) return 716 | classList = [] 717 | var cls = className(this), newName = funcArg(this, name, idx, cls) 718 | newName.split(/\s+/g).forEach(function(klass){ 719 | if (!$(this).hasClass(klass)) classList.push(klass) 720 | }, this) 721 | classList.length && className(this, cls + (cls ? " " : "") + classList.join(" ")) 722 | }) 723 | }, 724 | removeClass: function(name){ 725 | return this.each(function(idx){ 726 | if (!('className' in this)) return 727 | if (name === undefined) return className(this, '') 728 | classList = className(this) 729 | funcArg(this, name, idx, classList).split(/\s+/g).forEach(function(klass){ 730 | classList = classList.replace(classRE(klass), " ") 731 | }) 732 | className(this, classList.trim()) 733 | }) 734 | }, 735 | toggleClass: function(name, when){ 736 | if (!name) return this 737 | return this.each(function(idx){ 738 | var $this = $(this), names = funcArg(this, name, idx, className(this)) 739 | names.split(/\s+/g).forEach(function(klass){ 740 | (when === undefined ? !$this.hasClass(klass) : when) ? 741 | $this.addClass(klass) : $this.removeClass(klass) 742 | }) 743 | }) 744 | }, 745 | scrollTop: function(value){ 746 | if (!this.length) return 747 | var hasScrollTop = 'scrollTop' in this[0] 748 | if (value === undefined) return hasScrollTop ? this[0].scrollTop : this[0].pageYOffset 749 | return this.each(hasScrollTop ? 750 | function(){ this.scrollTop = value } : 751 | function(){ this.scrollTo(this.scrollX, value) }) 752 | }, 753 | scrollLeft: function(value){ 754 | if (!this.length) return 755 | var hasScrollLeft = 'scrollLeft' in this[0] 756 | if (value === undefined) return hasScrollLeft ? this[0].scrollLeft : this[0].pageXOffset 757 | return this.each(hasScrollLeft ? 758 | function(){ this.scrollLeft = value } : 759 | function(){ this.scrollTo(value, this.scrollY) }) 760 | }, 761 | position: function() { 762 | if (!this.length) return 763 | 764 | var elem = this[0], 765 | // Get *real* offsetParent 766 | offsetParent = this.offsetParent(), 767 | // Get correct offsets 768 | offset = this.offset(), 769 | parentOffset = rootNodeRE.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset() 770 | 771 | // Subtract element margins 772 | // note: when an element has margin: auto the offsetLeft and marginLeft 773 | // are the same in Safari causing offset.left to incorrectly be 0 774 | offset.top -= parseFloat( $(elem).css('margin-top') ) || 0 775 | offset.left -= parseFloat( $(elem).css('margin-left') ) || 0 776 | 777 | // Add offsetParent borders 778 | parentOffset.top += parseFloat( $(offsetParent[0]).css('border-top-width') ) || 0 779 | parentOffset.left += parseFloat( $(offsetParent[0]).css('border-left-width') ) || 0 780 | 781 | // Subtract the two offsets 782 | return { 783 | top: offset.top - parentOffset.top, 784 | left: offset.left - parentOffset.left 785 | } 786 | }, 787 | offsetParent: function() { 788 | return this.map(function(){ 789 | var parent = this.offsetParent || document.body 790 | while (parent && !rootNodeRE.test(parent.nodeName) && $(parent).css("position") == "static") 791 | parent = parent.offsetParent 792 | return parent 793 | }) 794 | } 795 | } 796 | 797 | // for now 798 | $.fn.detach = $.fn.remove 799 | 800 | // Generate the `width` and `height` functions 801 | ;['width', 'height'].forEach(function(dimension){ 802 | var dimensionProperty = 803 | dimension.replace(/./, function(m){ return m[0].toUpperCase() }) 804 | 805 | $.fn[dimension] = function(value){ 806 | var offset, el = this[0] 807 | if (value === undefined) return isWindow(el) ? el['inner' + dimensionProperty] : 808 | isDocument(el) ? el.documentElement['scroll' + dimensionProperty] : 809 | (offset = this.offset()) && offset[dimension] 810 | else return this.each(function(idx){ 811 | el = $(this) 812 | el.css(dimension, funcArg(this, value, idx, el[dimension]())) 813 | }) 814 | } 815 | }) 816 | 817 | function traverseNode(node, fun) { 818 | fun(node) 819 | for (var i = 0, len = node.childNodes.length; i < len; i++) 820 | traverseNode(node.childNodes[i], fun) 821 | } 822 | 823 | // Generate the `after`, `prepend`, `before`, `append`, 824 | // `insertAfter`, `insertBefore`, `appendTo`, and `prependTo` methods. 825 | adjacencyOperators.forEach(function(operator, operatorIndex) { 826 | var inside = operatorIndex % 2 //=> prepend, append 827 | 828 | $.fn[operator] = function(){ 829 | // arguments can be nodes, arrays of nodes, Zepto objects and HTML strings 830 | var argType, nodes = $.map(arguments, function(arg) { 831 | argType = type(arg) 832 | return argType == "object" || argType == "array" || arg == null ? 833 | arg : zepto.fragment(arg) 834 | }), 835 | parent, copyByClone = this.length > 1 836 | if (nodes.length < 1) return this 837 | 838 | return this.each(function(_, target){ 839 | parent = inside ? target : target.parentNode 840 | 841 | // convert all methods to a "before" operation 842 | target = operatorIndex == 0 ? target.nextSibling : 843 | operatorIndex == 1 ? target.firstChild : 844 | operatorIndex == 2 ? target : 845 | null 846 | 847 | var parentInDocument = $.contains(document.documentElement, parent) 848 | 849 | nodes.forEach(function(node){ 850 | if (copyByClone) node = node.cloneNode(true) 851 | else if (!parent) return $(node).remove() 852 | 853 | parent.insertBefore(node, target) 854 | if (parentInDocument) traverseNode(node, function(el){ 855 | if (el.nodeName != null && el.nodeName.toUpperCase() === 'SCRIPT' && 856 | (!el.type || el.type === 'text/javascript') && !el.src) 857 | window['eval'].call(window, el.innerHTML) 858 | }) 859 | }) 860 | }) 861 | } 862 | 863 | // after => insertAfter 864 | // prepend => prependTo 865 | // before => insertBefore 866 | // append => appendTo 867 | $.fn[inside ? operator+'To' : 'insert'+(operatorIndex ? 'Before' : 'After')] = function(html){ 868 | $(html)[operator](this) 869 | return this 870 | } 871 | }) 872 | 873 | zepto.Z.prototype = $.fn 874 | 875 | // Export internal API functions in the `$.zepto` namespace 876 | zepto.uniq = uniq 877 | zepto.deserializeValue = deserializeValue 878 | $.zepto = zepto 879 | 880 | return $ 881 | })() 882 | 883 | window.Zepto = Zepto 884 | window.$ === undefined && (window.$ = Zepto) 885 | 886 | ;(function($){ 887 | var _zid = 1, undefined, 888 | slice = Array.prototype.slice, 889 | isFunction = $.isFunction, 890 | isString = function(obj){ return typeof obj == 'string' }, 891 | handlers = {}, 892 | specialEvents={}, 893 | focusinSupported = 'onfocusin' in window, 894 | focus = { focus: 'focusin', blur: 'focusout' }, 895 | hover = { mouseenter: 'mouseover', mouseleave: 'mouseout' } 896 | 897 | specialEvents.click = specialEvents.mousedown = specialEvents.mouseup = specialEvents.mousemove = 'MouseEvents' 898 | 899 | function zid(element) { 900 | return element._zid || (element._zid = _zid++) 901 | } 902 | function findHandlers(element, event, fn, selector) { 903 | event = parse(event) 904 | if (event.ns) var matcher = matcherFor(event.ns) 905 | return (handlers[zid(element)] || []).filter(function(handler) { 906 | return handler 907 | && (!event.e || handler.e == event.e) 908 | && (!event.ns || matcher.test(handler.ns)) 909 | && (!fn || zid(handler.fn) === zid(fn)) 910 | && (!selector || handler.sel == selector) 911 | }) 912 | } 913 | function parse(event) { 914 | var parts = ('' + event).split('.') 915 | return {e: parts[0], ns: parts.slice(1).sort().join(' ')} 916 | } 917 | function matcherFor(ns) { 918 | return new RegExp('(?:^| )' + ns.replace(' ', ' .* ?') + '(?: |$)') 919 | } 920 | 921 | function eventCapture(handler, captureSetting) { 922 | return handler.del && 923 | (!focusinSupported && (handler.e in focus)) || 924 | !!captureSetting 925 | } 926 | 927 | function realEvent(type) { 928 | return hover[type] || (focusinSupported && focus[type]) || type 929 | } 930 | 931 | function add(element, events, fn, data, selector, delegator, capture){ 932 | var id = zid(element), set = (handlers[id] || (handlers[id] = [])) 933 | events.split(/\s/).forEach(function(event){ 934 | if (event == 'ready') return $(document).ready(fn) 935 | var handler = parse(event) 936 | handler.fn = fn 937 | handler.sel = selector 938 | // emulate mouseenter, mouseleave 939 | if (handler.e in hover) fn = function(e){ 940 | var related = e.relatedTarget 941 | if (!related || (related !== this && !$.contains(this, related))) 942 | return handler.fn.apply(this, arguments) 943 | } 944 | handler.del = delegator 945 | var callback = delegator || fn 946 | handler.proxy = function(e){ 947 | e = compatible(e) 948 | if (e.isImmediatePropagationStopped()) return 949 | e.data = data 950 | var result = callback.apply(element, e._args == undefined ? [e] : [e].concat(e._args)) 951 | if (result === false) e.preventDefault(), e.stopPropagation() 952 | return result 953 | } 954 | handler.i = set.length 955 | set.push(handler) 956 | if ('addEventListener' in element) 957 | element.addEventListener(realEvent(handler.e), handler.proxy, eventCapture(handler, capture)) 958 | }) 959 | } 960 | function remove(element, events, fn, selector, capture){ 961 | var id = zid(element) 962 | ;(events || '').split(/\s/).forEach(function(event){ 963 | findHandlers(element, event, fn, selector).forEach(function(handler){ 964 | delete handlers[id][handler.i] 965 | if ('removeEventListener' in element) 966 | element.removeEventListener(realEvent(handler.e), handler.proxy, eventCapture(handler, capture)) 967 | }) 968 | }) 969 | } 970 | 971 | $.event = { add: add, remove: remove } 972 | 973 | $.proxy = function(fn, context) { 974 | var args = (2 in arguments) && slice.call(arguments, 2) 975 | if (isFunction(fn)) { 976 | var proxyFn = function(){ return fn.apply(context, args ? args.concat(slice.call(arguments)) : arguments) } 977 | proxyFn._zid = zid(fn) 978 | return proxyFn 979 | } else if (isString(context)) { 980 | if (args) { 981 | args.unshift(fn[context], fn) 982 | return $.proxy.apply(null, args) 983 | } else { 984 | return $.proxy(fn[context], fn) 985 | } 986 | } else { 987 | throw new TypeError("expected function") 988 | } 989 | } 990 | 991 | $.fn.bind = function(event, data, callback){ 992 | return this.on(event, data, callback) 993 | } 994 | $.fn.unbind = function(event, callback){ 995 | return this.off(event, callback) 996 | } 997 | $.fn.one = function(event, selector, data, callback){ 998 | return this.on(event, selector, data, callback, 1) 999 | } 1000 | 1001 | var returnTrue = function(){return true}, 1002 | returnFalse = function(){return false}, 1003 | ignoreProperties = /^([A-Z]|returnValue$|layer[XY]$)/, 1004 | eventMethods = { 1005 | preventDefault: 'isDefaultPrevented', 1006 | stopImmediatePropagation: 'isImmediatePropagationStopped', 1007 | stopPropagation: 'isPropagationStopped' 1008 | } 1009 | 1010 | function compatible(event, source) { 1011 | if (source || !event.isDefaultPrevented) { 1012 | source || (source = event) 1013 | 1014 | $.each(eventMethods, function(name, predicate) { 1015 | var sourceMethod = source[name] 1016 | event[name] = function(){ 1017 | this[predicate] = returnTrue 1018 | return sourceMethod && sourceMethod.apply(source, arguments) 1019 | } 1020 | event[predicate] = returnFalse 1021 | }) 1022 | 1023 | if (source.defaultPrevented !== undefined ? source.defaultPrevented : 1024 | 'returnValue' in source ? source.returnValue === false : 1025 | source.getPreventDefault && source.getPreventDefault()) 1026 | event.isDefaultPrevented = returnTrue 1027 | } 1028 | return event 1029 | } 1030 | 1031 | function createProxy(event) { 1032 | var key, proxy = { originalEvent: event } 1033 | for (key in event) 1034 | if (!ignoreProperties.test(key) && event[key] !== undefined) proxy[key] = event[key] 1035 | 1036 | return compatible(proxy, event) 1037 | } 1038 | 1039 | $.fn.delegate = function(selector, event, callback){ 1040 | return this.on(event, selector, callback) 1041 | } 1042 | $.fn.undelegate = function(selector, event, callback){ 1043 | return this.off(event, selector, callback) 1044 | } 1045 | 1046 | $.fn.live = function(event, callback){ 1047 | $(document.body).delegate(this.selector, event, callback) 1048 | return this 1049 | } 1050 | $.fn.die = function(event, callback){ 1051 | $(document.body).undelegate(this.selector, event, callback) 1052 | return this 1053 | } 1054 | 1055 | $.fn.on = function(event, selector, data, callback, one){ 1056 | var autoRemove, delegator, $this = this 1057 | if (event && !isString(event)) { 1058 | $.each(event, function(type, fn){ 1059 | $this.on(type, selector, data, fn, one) 1060 | }) 1061 | return $this 1062 | } 1063 | 1064 | if (!isString(selector) && !isFunction(callback) && callback !== false) 1065 | callback = data, data = selector, selector = undefined 1066 | if (isFunction(data) || data === false) 1067 | callback = data, data = undefined 1068 | 1069 | if (callback === false) callback = returnFalse 1070 | 1071 | return $this.each(function(_, element){ 1072 | if (one) autoRemove = function(e){ 1073 | remove(element, e.type, callback) 1074 | return callback.apply(this, arguments) 1075 | } 1076 | 1077 | if (selector) delegator = function(e){ 1078 | var evt, match = $(e.target).closest(selector, element).get(0) 1079 | if (match && match !== element) { 1080 | evt = $.extend(createProxy(e), {currentTarget: match, liveFired: element}) 1081 | return (autoRemove || callback).apply(match, [evt].concat(slice.call(arguments, 1))) 1082 | } 1083 | } 1084 | 1085 | add(element, event, callback, data, selector, delegator || autoRemove) 1086 | }) 1087 | } 1088 | $.fn.off = function(event, selector, callback){ 1089 | var $this = this 1090 | if (event && !isString(event)) { 1091 | $.each(event, function(type, fn){ 1092 | $this.off(type, selector, fn) 1093 | }) 1094 | return $this 1095 | } 1096 | 1097 | if (!isString(selector) && !isFunction(callback) && callback !== false) 1098 | callback = selector, selector = undefined 1099 | 1100 | if (callback === false) callback = returnFalse 1101 | 1102 | return $this.each(function(){ 1103 | remove(this, event, callback, selector) 1104 | }) 1105 | } 1106 | 1107 | $.fn.trigger = function(event, args){ 1108 | event = (isString(event) || $.isPlainObject(event)) ? $.Event(event) : compatible(event) 1109 | event._args = args 1110 | return this.each(function(){ 1111 | // handle focus(), blur() by calling them directly 1112 | if (event.type in focus && typeof this[event.type] == "function") this[event.type]() 1113 | // items in the collection might not be DOM elements 1114 | else if ('dispatchEvent' in this) this.dispatchEvent(event) 1115 | else $(this).triggerHandler(event, args) 1116 | }) 1117 | } 1118 | 1119 | // triggers event handlers on current element just as if an event occurred, 1120 | // doesn't trigger an actual event, doesn't bubble 1121 | $.fn.triggerHandler = function(event, args){ 1122 | var e, result 1123 | this.each(function(i, element){ 1124 | e = createProxy(isString(event) ? $.Event(event) : event) 1125 | e._args = args 1126 | e.target = element 1127 | $.each(findHandlers(element, event.type || event), function(i, handler){ 1128 | result = handler.proxy(e) 1129 | if (e.isImmediatePropagationStopped()) return false 1130 | }) 1131 | }) 1132 | return result 1133 | } 1134 | 1135 | // shortcut methods for `.bind(event, fn)` for each event type 1136 | ;('focusin focusout focus blur load resize scroll unload click dblclick '+ 1137 | 'mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave '+ 1138 | 'change select keydown keypress keyup error').split(' ').forEach(function(event) { 1139 | $.fn[event] = function(callback) { 1140 | return (0 in arguments) ? 1141 | this.bind(event, callback) : 1142 | this.trigger(event) 1143 | } 1144 | }) 1145 | 1146 | $.Event = function(type, props) { 1147 | if (!isString(type)) props = type, type = props.type 1148 | var event = document.createEvent(specialEvents[type] || 'Events'), bubbles = true 1149 | if (props) for (var name in props) (name == 'bubbles') ? (bubbles = !!props[name]) : (event[name] = props[name]) 1150 | event.initEvent(type, bubbles, true) 1151 | return compatible(event) 1152 | } 1153 | 1154 | })(Zepto) 1155 | 1156 | ;(function($){ 1157 | var jsonpID = 0, 1158 | document = window.document, 1159 | key, 1160 | name, 1161 | rscript = /)<[^<]*)*<\/script>/gi, 1162 | scriptTypeRE = /^(?:text|application)\/javascript/i, 1163 | xmlTypeRE = /^(?:text|application)\/xml/i, 1164 | jsonType = 'application/json', 1165 | htmlType = 'text/html', 1166 | blankRE = /^\s*$/, 1167 | originAnchor = document.createElement('a') 1168 | 1169 | originAnchor.href = window.location.href 1170 | 1171 | // trigger a custom event and return false if it was cancelled 1172 | function triggerAndReturn(context, eventName, data) { 1173 | var event = $.Event(eventName) 1174 | $(context).trigger(event, data) 1175 | return !event.isDefaultPrevented() 1176 | } 1177 | 1178 | // trigger an Ajax "global" event 1179 | function triggerGlobal(settings, context, eventName, data) { 1180 | if (settings.global) return triggerAndReturn(context || document, eventName, data) 1181 | } 1182 | 1183 | // Number of active Ajax requests 1184 | $.active = 0 1185 | 1186 | function ajaxStart(settings) { 1187 | if (settings.global && $.active++ === 0) triggerGlobal(settings, null, 'ajaxStart') 1188 | } 1189 | function ajaxStop(settings) { 1190 | if (settings.global && !(--$.active)) triggerGlobal(settings, null, 'ajaxStop') 1191 | } 1192 | 1193 | // triggers an extra global event "ajaxBeforeSend" that's like "ajaxSend" but cancelable 1194 | function ajaxBeforeSend(xhr, settings) { 1195 | var context = settings.context 1196 | if (settings.beforeSend.call(context, xhr, settings) === false || 1197 | triggerGlobal(settings, context, 'ajaxBeforeSend', [xhr, settings]) === false) 1198 | return false 1199 | 1200 | triggerGlobal(settings, context, 'ajaxSend', [xhr, settings]) 1201 | } 1202 | function ajaxSuccess(data, xhr, settings, deferred) { 1203 | var context = settings.context, status = 'success' 1204 | settings.success.call(context, data, status, xhr) 1205 | if (deferred) deferred.resolveWith(context, [data, status, xhr]) 1206 | triggerGlobal(settings, context, 'ajaxSuccess', [xhr, settings, data]) 1207 | ajaxComplete(status, xhr, settings) 1208 | } 1209 | // type: "timeout", "error", "abort", "parsererror" 1210 | function ajaxError(error, type, xhr, settings, deferred) { 1211 | var context = settings.context 1212 | settings.error.call(context, xhr, type, error) 1213 | if (deferred) deferred.rejectWith(context, [xhr, type, error]) 1214 | triggerGlobal(settings, context, 'ajaxError', [xhr, settings, error || type]) 1215 | ajaxComplete(type, xhr, settings) 1216 | } 1217 | // status: "success", "notmodified", "error", "timeout", "abort", "parsererror" 1218 | function ajaxComplete(status, xhr, settings) { 1219 | var context = settings.context 1220 | settings.complete.call(context, xhr, status) 1221 | triggerGlobal(settings, context, 'ajaxComplete', [xhr, settings]) 1222 | ajaxStop(settings) 1223 | } 1224 | 1225 | // Empty function, used as default callback 1226 | function empty() {} 1227 | 1228 | $.ajaxJSONP = function(options, deferred){ 1229 | if (!('type' in options)) return $.ajax(options) 1230 | 1231 | var _callbackName = options.jsonpCallback, 1232 | callbackName = ($.isFunction(_callbackName) ? 1233 | _callbackName() : _callbackName) || ('jsonp' + (++jsonpID)), 1234 | script = document.createElement('script'), 1235 | originalCallback = window[callbackName], 1236 | responseData, 1237 | abort = function(errorType) { 1238 | $(script).triggerHandler('error', errorType || 'abort') 1239 | }, 1240 | xhr = { abort: abort }, abortTimeout 1241 | 1242 | if (deferred) deferred.promise(xhr) 1243 | 1244 | $(script).on('load error', function(e, errorType){ 1245 | clearTimeout(abortTimeout) 1246 | $(script).off().remove() 1247 | 1248 | if (e.type == 'error' || !responseData) { 1249 | ajaxError(null, errorType || 'error', xhr, options, deferred) 1250 | } else { 1251 | ajaxSuccess(responseData[0], xhr, options, deferred) 1252 | } 1253 | 1254 | window[callbackName] = originalCallback 1255 | if (responseData && $.isFunction(originalCallback)) 1256 | originalCallback(responseData[0]) 1257 | 1258 | originalCallback = responseData = undefined 1259 | }) 1260 | 1261 | if (ajaxBeforeSend(xhr, options) === false) { 1262 | abort('abort') 1263 | return xhr 1264 | } 1265 | 1266 | window[callbackName] = function(){ 1267 | responseData = arguments 1268 | } 1269 | 1270 | script.src = options.url.replace(/\?(.+)=\?/, '?$1=' + callbackName) 1271 | document.head.appendChild(script) 1272 | 1273 | if (options.timeout > 0) abortTimeout = setTimeout(function(){ 1274 | abort('timeout') 1275 | }, options.timeout) 1276 | 1277 | return xhr 1278 | } 1279 | 1280 | $.ajaxSettings = { 1281 | // Default type of request 1282 | type: 'GET', 1283 | // Callback that is executed before request 1284 | beforeSend: empty, 1285 | // Callback that is executed if the request succeeds 1286 | success: empty, 1287 | // Callback that is executed the the server drops error 1288 | error: empty, 1289 | // Callback that is executed on request complete (both: error and success) 1290 | complete: empty, 1291 | // The context for the callbacks 1292 | context: null, 1293 | // Whether to trigger "global" Ajax events 1294 | global: true, 1295 | // Transport 1296 | xhr: function () { 1297 | return new window.XMLHttpRequest() 1298 | }, 1299 | // MIME types mapping 1300 | // IIS returns Javascript as "application/x-javascript" 1301 | accepts: { 1302 | script: 'text/javascript, application/javascript, application/x-javascript', 1303 | json: jsonType, 1304 | xml: 'application/xml, text/xml', 1305 | html: htmlType, 1306 | text: 'text/plain' 1307 | }, 1308 | // Whether the request is to another domain 1309 | crossDomain: false, 1310 | // Default timeout 1311 | timeout: 0, 1312 | // Whether data should be serialized to string 1313 | processData: true, 1314 | // Whether the browser should be allowed to cache GET responses 1315 | cache: true 1316 | } 1317 | 1318 | function mimeToDataType(mime) { 1319 | if (mime) mime = mime.split(';', 2)[0] 1320 | return mime && ( mime == htmlType ? 'html' : 1321 | mime == jsonType ? 'json' : 1322 | scriptTypeRE.test(mime) ? 'script' : 1323 | xmlTypeRE.test(mime) && 'xml' ) || 'text' 1324 | } 1325 | 1326 | function appendQuery(url, query) { 1327 | if (query == '') return url 1328 | return (url + '&' + query).replace(/[&?]{1,2}/, '?') 1329 | } 1330 | 1331 | // serialize payload and append it to the URL for GET requests 1332 | function serializeData(options) { 1333 | if (options.processData && options.data && $.type(options.data) != "string") 1334 | options.data = $.param(options.data, options.traditional) 1335 | if (options.data && (!options.type || options.type.toUpperCase() == 'GET')) 1336 | options.url = appendQuery(options.url, options.data), options.data = undefined 1337 | } 1338 | 1339 | $.ajax = function(options){ 1340 | var settings = $.extend({}, options || {}), 1341 | deferred = $.Deferred && $.Deferred(), 1342 | urlAnchor 1343 | for (key in $.ajaxSettings) if (settings[key] === undefined) settings[key] = $.ajaxSettings[key] 1344 | 1345 | ajaxStart(settings) 1346 | 1347 | if (!settings.crossDomain) { 1348 | urlAnchor = document.createElement('a') 1349 | urlAnchor.href = settings.url 1350 | urlAnchor.href = urlAnchor.href 1351 | settings.crossDomain = (originAnchor.protocol + '//' + originAnchor.host) !== (urlAnchor.protocol + '//' + urlAnchor.host) 1352 | } 1353 | 1354 | if (!settings.url) settings.url = window.location.toString() 1355 | serializeData(settings) 1356 | 1357 | var dataType = settings.dataType, hasPlaceholder = /\?.+=\?/.test(settings.url) 1358 | if (hasPlaceholder) dataType = 'jsonp' 1359 | 1360 | if (settings.cache === false || ( 1361 | (!options || options.cache !== true) && 1362 | ('script' == dataType || 'jsonp' == dataType) 1363 | )) 1364 | settings.url = appendQuery(settings.url, '_=' + Date.now()) 1365 | 1366 | if ('jsonp' == dataType) { 1367 | if (!hasPlaceholder) 1368 | settings.url = appendQuery(settings.url, 1369 | settings.jsonp ? (settings.jsonp + '=?') : settings.jsonp === false ? '' : 'callback=?') 1370 | return $.ajaxJSONP(settings, deferred) 1371 | } 1372 | 1373 | var mime = settings.accepts[dataType], 1374 | headers = { }, 1375 | setHeader = function(name, value) { headers[name.toLowerCase()] = [name, value] }, 1376 | protocol = /^([\w-]+:)\/\//.test(settings.url) ? RegExp.$1 : window.location.protocol, 1377 | xhr = settings.xhr(), 1378 | nativeSetHeader = xhr.setRequestHeader, 1379 | abortTimeout 1380 | 1381 | if (deferred) deferred.promise(xhr) 1382 | 1383 | if (!settings.crossDomain) setHeader('X-Requested-With', 'XMLHttpRequest') 1384 | setHeader('Accept', mime || '*/*') 1385 | if (mime = settings.mimeType || mime) { 1386 | if (mime.indexOf(',') > -1) mime = mime.split(',', 2)[0] 1387 | xhr.overrideMimeType && xhr.overrideMimeType(mime) 1388 | } 1389 | if (settings.contentType || (settings.contentType !== false && settings.data && settings.type.toUpperCase() != 'GET')) 1390 | setHeader('Content-Type', settings.contentType || 'application/x-www-form-urlencoded') 1391 | 1392 | if (settings.headers) for (name in settings.headers) setHeader(name, settings.headers[name]) 1393 | xhr.setRequestHeader = setHeader 1394 | 1395 | xhr.onreadystatechange = function(){ 1396 | if (xhr.readyState == 4) { 1397 | xhr.onreadystatechange = empty 1398 | clearTimeout(abortTimeout) 1399 | var result, error = false 1400 | if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304 || (xhr.status == 0 && protocol == 'file:')) { 1401 | dataType = dataType || mimeToDataType(settings.mimeType || xhr.getResponseHeader('content-type')) 1402 | result = xhr.responseText 1403 | 1404 | try { 1405 | // http://perfectionkills.com/global-eval-what-are-the-options/ 1406 | if (dataType == 'script') (1,eval)(result) 1407 | else if (dataType == 'xml') result = xhr.responseXML 1408 | else if (dataType == 'json') result = blankRE.test(result) ? null : $.parseJSON(result) 1409 | } catch (e) { error = e } 1410 | 1411 | if (error) ajaxError(error, 'parsererror', xhr, settings, deferred) 1412 | else ajaxSuccess(result, xhr, settings, deferred) 1413 | } else { 1414 | ajaxError(xhr.statusText || null, xhr.status ? 'error' : 'abort', xhr, settings, deferred) 1415 | } 1416 | } 1417 | } 1418 | 1419 | if (ajaxBeforeSend(xhr, settings) === false) { 1420 | xhr.abort() 1421 | ajaxError(null, 'abort', xhr, settings, deferred) 1422 | return xhr 1423 | } 1424 | 1425 | if (settings.xhrFields) for (name in settings.xhrFields) xhr[name] = settings.xhrFields[name] 1426 | 1427 | var async = 'async' in settings ? settings.async : true 1428 | xhr.open(settings.type, settings.url, async, settings.username, settings.password) 1429 | 1430 | for (name in headers) nativeSetHeader.apply(xhr, headers[name]) 1431 | 1432 | if (settings.timeout > 0) abortTimeout = setTimeout(function(){ 1433 | xhr.onreadystatechange = empty 1434 | xhr.abort() 1435 | ajaxError(null, 'timeout', xhr, settings, deferred) 1436 | }, settings.timeout) 1437 | 1438 | // avoid sending empty string (#319) 1439 | xhr.send(settings.data ? settings.data : null) 1440 | return xhr 1441 | } 1442 | 1443 | // handle optional data/success arguments 1444 | function parseArguments(url, data, success, dataType) { 1445 | if ($.isFunction(data)) dataType = success, success = data, data = undefined 1446 | if (!$.isFunction(success)) dataType = success, success = undefined 1447 | return { 1448 | url: url 1449 | , data: data 1450 | , success: success 1451 | , dataType: dataType 1452 | } 1453 | } 1454 | 1455 | $.get = function(/* url, data, success, dataType */){ 1456 | return $.ajax(parseArguments.apply(null, arguments)) 1457 | } 1458 | 1459 | $.post = function(/* url, data, success, dataType */){ 1460 | var options = parseArguments.apply(null, arguments) 1461 | options.type = 'POST' 1462 | return $.ajax(options) 1463 | } 1464 | 1465 | $.getJSON = function(/* url, data, success */){ 1466 | var options = parseArguments.apply(null, arguments) 1467 | options.dataType = 'json' 1468 | return $.ajax(options) 1469 | } 1470 | 1471 | $.fn.load = function(url, data, success){ 1472 | if (!this.length) return this 1473 | var self = this, parts = url.split(/\s/), selector, 1474 | options = parseArguments(url, data, success), 1475 | callback = options.success 1476 | if (parts.length > 1) options.url = parts[0], selector = parts[1] 1477 | options.success = function(response){ 1478 | self.html(selector ? 1479 | $('
').html(response.replace(rscript, "")).find(selector) 1480 | : response) 1481 | callback && callback.apply(self, arguments) 1482 | } 1483 | $.ajax(options) 1484 | return this 1485 | } 1486 | 1487 | var escape = encodeURIComponent 1488 | 1489 | function serialize(params, obj, traditional, scope){ 1490 | var type, array = $.isArray(obj), hash = $.isPlainObject(obj) 1491 | $.each(obj, function(key, value) { 1492 | type = $.type(value) 1493 | if (scope) key = traditional ? scope : 1494 | scope + '[' + (hash || type == 'object' || type == 'array' ? key : '') + ']' 1495 | // handle data in serializeArray() format 1496 | if (!scope && array) params.add(value.name, value.value) 1497 | // recurse into nested objects 1498 | else if (type == "array" || (!traditional && type == "object")) 1499 | serialize(params, value, traditional, key) 1500 | else params.add(key, value) 1501 | }) 1502 | } 1503 | 1504 | $.param = function(obj, traditional){ 1505 | var params = [] 1506 | params.add = function(key, value) { 1507 | if ($.isFunction(value)) value = value() 1508 | if (value == null) value = "" 1509 | this.push(escape(key) + '=' + escape(value)) 1510 | } 1511 | serialize(params, obj, traditional) 1512 | return params.join('&').replace(/%20/g, '+') 1513 | } 1514 | })(Zepto) 1515 | 1516 | ;(function($){ 1517 | $.fn.serializeArray = function() { 1518 | var name, type, result = [], 1519 | add = function(value) { 1520 | if (value.forEach) return value.forEach(add) 1521 | result.push({ name: name, value: value }) 1522 | } 1523 | if (this[0]) $.each(this[0].elements, function(_, field){ 1524 | type = field.type, name = field.name 1525 | if (name && field.nodeName.toLowerCase() != 'fieldset' && 1526 | !field.disabled && type != 'submit' && type != 'reset' && type != 'button' && type != 'file' && 1527 | ((type != 'radio' && type != 'checkbox') || field.checked)) 1528 | add($(field).val()) 1529 | }) 1530 | return result 1531 | } 1532 | 1533 | $.fn.serialize = function(){ 1534 | var result = [] 1535 | this.serializeArray().forEach(function(elm){ 1536 | result.push(encodeURIComponent(elm.name) + '=' + encodeURIComponent(elm.value)) 1537 | }) 1538 | return result.join('&') 1539 | } 1540 | 1541 | $.fn.submit = function(callback) { 1542 | if (0 in arguments) this.bind('submit', callback) 1543 | else if (this.length) { 1544 | var event = $.Event('submit') 1545 | this.eq(0).trigger(event) 1546 | if (!event.isDefaultPrevented()) this.get(0).submit() 1547 | } 1548 | return this 1549 | } 1550 | 1551 | })(Zepto) 1552 | 1553 | ;(function($){ 1554 | // __proto__ doesn't exist on IE<11, so redefine 1555 | // the Z function to use object extension instead 1556 | if (!('__proto__' in {})) { 1557 | $.extend($.zepto, { 1558 | Z: function(dom, selector){ 1559 | dom = dom || [] 1560 | $.extend(dom, $.fn) 1561 | dom.selector = selector || '' 1562 | dom.__Z = true 1563 | return dom 1564 | }, 1565 | // this is a kludge but works 1566 | isZ: function(object){ 1567 | return $.type(object) === 'array' && '__Z' in object 1568 | } 1569 | }) 1570 | } 1571 | 1572 | // getComputedStyle shouldn't freak out when called 1573 | // without a valid element as argument 1574 | try { 1575 | getComputedStyle(undefined) 1576 | } catch(e) { 1577 | var nativeGetComputedStyle = getComputedStyle; 1578 | window.getComputedStyle = function(element){ 1579 | try { 1580 | return nativeGetComputedStyle(element) 1581 | } catch(e) { 1582 | return null 1583 | } 1584 | } 1585 | } 1586 | })(Zepto) 1587 | -------------------------------------------------------------------------------- /root/template/component/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import {{nameCamel}} from './{{name}}.vue'; 3 | Vue.component('{{name}}' , {{nameCamel}} ); -------------------------------------------------------------------------------- /root/template/component/snippet/script.js: -------------------------------------------------------------------------------- 1 | export default{ 2 | props : { //接收的属性值 3 | 4 | }, 5 | compiled(){ //解析完成,此时未必已经插入到DOM中,但可以操作DOM对象。 6 | 7 | }, 8 | ready(){ //插入到DOM完成 9 | 10 | } 11 | 12 | } -------------------------------------------------------------------------------- /root/template/component/snippet/style.css: -------------------------------------------------------------------------------- 1 | @import '../../../px2rem'; 2 | div[{{name}}]{ 3 | 4 | } -------------------------------------------------------------------------------- /root/template/component/snippet/tpl.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
-------------------------------------------------------------------------------- /root/template/component/tpl.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /root/template/particle/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import {{nameCamel}} from './{{name}}.vue'; 3 | Vue.component('{{name}}' , {{nameCamel}} ); -------------------------------------------------------------------------------- /root/template/particle/tpl.vue: -------------------------------------------------------------------------------- 1 | 7 | 12 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | import fs from 'fs'; 3 | import program from 'commander'; 4 | import colors from 'colors'; 5 | 6 | 7 | import utils from './lib/utils'; 8 | 9 | 10 | let lunaRoot = path.dirname( __dirname ); 11 | let runRoot = process.cwd(); 12 | 13 | let lunaPath = ( dir )=>{ 14 | return path.join( lunaRoot , dir ); 15 | } 16 | 17 | let runPath = ( dir )=>{ 18 | return path.join( runRoot , dir ); 19 | } 20 | 21 | 22 | let updates = [ 23 | 'package.json', 24 | 'src/bootstrap.js', 25 | 'src/px2rem.scss', 26 | 'static/js/hotcss.js', 27 | 'static/js/zepto.js', 28 | 'config/webpack.base.js', 29 | 'config/webpack.dev.js', 30 | 'config/webpack.prod.js', 31 | 'luna.bootstrap.js' 32 | ]; 33 | 34 | 35 | 36 | let getVersion = ()=>{ 37 | let _filePath = lunaPath('package.json'); 38 | return JSON.parse(utils.readFile(_filePath)).version 39 | } 40 | 41 | let checkEnv = ()=>{ 42 | let isluna = true; 43 | [ 44 | 'package.json', 45 | 'src/bootstrap.js', 46 | 'config/webpack.base.js', 47 | 'config/webpack.dev.js', 48 | 'config/webpack.prod.js', 49 | 'luna.bootstrap.js' 50 | ].map(( item )=>{ 51 | let _tar = runPath(item); 52 | if( !utils.isExists(_tar) && isluna ){ 53 | isluna = false; 54 | } 55 | }); 56 | return isluna; 57 | } 58 | 59 | let _createProject = ( projectRootPath )=>{ 60 | 61 | let tarPath = ( dir ) => { 62 | return path.join( runRoot , projectRootPath , dir ); 63 | }; 64 | 65 | utils.copyFile({ 66 | source : lunaPath('root/package.json'), 67 | target : tarPath('package.json') 68 | }); 69 | 70 | utils.copyFile({ 71 | source : lunaPath('root/index.html'), 72 | target : tarPath('index.html') 73 | }); 74 | 75 | utils.copyFile({ 76 | source : lunaPath('root/luna.bootstrap.js'), 77 | target : tarPath('luna.bootstrap.js') 78 | }); 79 | 80 | utils.copyDir( lunaPath('root/config/') , tarPath('config/') ); 81 | utils.copyDir( lunaPath('root/src/') , tarPath('src/') ); 82 | utils.copyDir( lunaPath('root/static/') , tarPath('static/') ); 83 | } 84 | 85 | let createProject = ( projectRootPath )=>{ 86 | if( utils.isExists(projectRootPath) ){ 87 | if( !utils.isEmptyDir(projectRootPath) ){ 88 | utils.log.warn('`'+ projectRootPath +'` is not an empty directory.'); 89 | return false; 90 | } 91 | }else{ 92 | utils.mkdir( projectRootPath ); 93 | } 94 | 95 | _createProject( projectRootPath ); 96 | 97 | utils.log.normal('\n enter path:'); 98 | utils.log.main(' $ cd ' + projectRootPath + '\n'); 99 | 100 | utils.log.normal(' install dependencies:'); 101 | utils.log.main(' $ npm install\n'); 102 | 103 | utils.log.normal(' run the app:'); 104 | utils.log.main(' $ npm run dev\n'); 105 | } 106 | 107 | let updateProject = ()=>{ 108 | if( !checkEnv() ){ 109 | utils.log.warn('`'+ runRoot +'` is not a luna project!'); 110 | return false; 111 | } 112 | let updateNum = 0; 113 | updates.map(( item )=>{ 114 | let _src_path = lunaPath( path.join('root', item) ); 115 | let _tar_path = runPath( item ); 116 | utils.copyFile({ 117 | source : _src_path, 118 | target : _tar_path, 119 | overwrite : true, 120 | updateLog(){ 121 | updateNum++; 122 | utils.log.debug(' file `' + item + '` is already update!'); 123 | } 124 | }); 125 | }); 126 | if( updateNum === 0 ){ 127 | utils.log.warn(' no file need to update!'); 128 | } 129 | } 130 | 131 | let createWidthSnippet = ( type , name )=>{ 132 | if( name.indexOf('-') < 0 ){ 133 | utils.log.error( '`' + name + '` is not available . Example: title-normal '); 134 | return false; 135 | } 136 | if( !checkEnv() ){ 137 | utils.log.warn('`'+ runRoot +'` is not a luna project!'); 138 | return false; 139 | } 140 | let _src_path = lunaPath('root/template/component/'); 141 | let _tar_path = runPath('src/'+ type + '/' + name ); 142 | let nameCamel = utils.toCamel( name ); 143 | 144 | if( utils.isExists( runPath('src/components/' + name ) )){ 145 | utils.log.error( 'components `' + name + '` is already exist!'); 146 | return false; 147 | } 148 | if( utils.isExists( runPath('src/particles/' + name ) )){ 149 | utils.log.error( 'particles `' + name + '` is already exist!'); 150 | return false; 151 | } 152 | 153 | utils.mkdir( _tar_path ); 154 | utils.mkdir( path.join( _tar_path , 'snippet' ) ); 155 | 156 | utils.copyFile({ 157 | source : path.join( _src_path , 'index.js'), 158 | target : path.join( _tar_path , 'index.js'), 159 | replace : ['{{name}}->'+name,'{{nameCamel}}->'+nameCamel] 160 | }); 161 | 162 | utils.copyFile({ 163 | source : path.join( _src_path , 'tpl.vue'), 164 | target : path.join( _tar_path , name + '.vue') 165 | }); 166 | 167 | utils.copyFile({ 168 | source : path.join( _src_path , 'snippet/tpl.html'), 169 | target : path.join( _tar_path , 'snippet/tpl.html'), 170 | replace : ['{{name}}->'+name,'{{nameCamel}}->'+nameCamel] 171 | }); 172 | 173 | utils.copyFile({ 174 | source : path.join( _src_path , 'snippet/style.css'), 175 | target : path.join( _tar_path , 'snippet/style.css'), 176 | replace : ['{{name}}->'+name,'{{nameCamel}}->'+nameCamel] 177 | }); 178 | 179 | utils.copyFile({ 180 | source : path.join( _src_path , 'snippet/script.js'), 181 | target : path.join( _tar_path , 'snippet/script.js') 182 | }); 183 | 184 | utils.log.debug( type + ' `' + name + '` has been created!' ); 185 | 186 | } 187 | 188 | let createSimple = ( type , name )=>{ 189 | if( name.indexOf('-') < 0 ){ 190 | utils.log.error( '`' + name + '` is not available . Example: title-normal '); 191 | return false; 192 | } 193 | if( !checkEnv() ){ 194 | utils.log.warn('`'+ runRoot +'` is not a luna project!'); 195 | return false; 196 | } 197 | let _src_path = lunaPath('root/template/particle/'); 198 | let _tar_path = runPath('src/'+ type + '/' + name ); 199 | let nameCamel = utils.toCamel( name ); 200 | 201 | if( utils.isExists( runPath('src/components/' + name ) )){ 202 | utils.log.error( 'components `' + name + '` is already exist!'); 203 | return false; 204 | } 205 | if( utils.isExists( runPath('src/particles/' + name ) )){ 206 | utils.log.error( 'particles `' + name + '` is already exist!'); 207 | return false; 208 | } 209 | 210 | utils.mkdir( _tar_path ); 211 | 212 | utils.copyFile({ 213 | source : path.join( _src_path , 'index.js'), 214 | target : path.join( _tar_path , 'index.js'), 215 | replace : ['{{name}}->'+name,'{{nameCamel}}->'+nameCamel] 216 | }); 217 | 218 | utils.copyFile({ 219 | source : path.join( _src_path , 'tpl.vue'), 220 | target : path.join( _tar_path , name + '.vue'), 221 | replace : ['{{name}}->'+name,'{{nameCamel}}->'+nameCamel] 222 | }); 223 | 224 | utils.log.debug( type + ' `' + name + '` has been created!' ); 225 | } 226 | 227 | let createTpl = ( name , type ) => { 228 | 229 | if( program.mini || program.normal ){ 230 | if( program.mini ){ 231 | createSimple( type , name ); 232 | } 233 | if( program.normal ){ 234 | createWidthSnippet( type , name ); 235 | } 236 | }else{ 237 | if( type === 'components' ){ 238 | createWidthSnippet( type , name ); 239 | } 240 | if( type === 'particles' ){ 241 | createSimple( type , name ); 242 | } 243 | } 244 | } 245 | 246 | 247 | let displayVersion = () => { 248 | let version = getVersion(); 249 | let chars = [ 250 | "####################################", 251 | "# __ #", 252 | "# / / __ __ ____ __ _ #", 253 | "# / / / / / / / __ \\ / __`/ #", 254 | "# / / / /_/ / / / / / / /_/ / #", 255 | "# /_/ \\__,_/ /_/ /_/ \\__,_/\\ #", 256 | "# #", 257 | "# v "+ version +" #", 258 | "####################################" 259 | ].join("\n"); 260 | utils.log.main("\n" + chars + "\n"); 261 | } 262 | 263 | 264 | program.usage('[command] '); 265 | program.option('-v, --version', 'output the version number', function(){ 266 | displayVersion(); 267 | }); 268 | 269 | program.option('-m, --mini', 'when create component/particle use mini template'); 270 | program.option('-n, --normal', 'when create component/particle use normal template'); 271 | 272 | program.command('init ').description('init a new project').action(function(projectPath){ 273 | createProject( path.normalize(projectPath + '/') ); 274 | }); 275 | 276 | program.command('update').description('update your project , please use at the root of your project').action(function(){ 277 | updateProject(); 278 | }); 279 | 280 | program.command('component ').description('create a new component').action(function(componentName){ 281 | createTpl( componentName , 'components'); 282 | }); 283 | 284 | program.command('particle ').description('create a new particle').action(function(particleName){ 285 | createTpl( particleName , 'particles'); 286 | }); 287 | 288 | 289 | 290 | 291 | 292 | 293 | program.on('--help', function(){ 294 | utils.log.normal(' Examples:\n'); 295 | utils.log.normal(' luna component title-normal\n'); 296 | }); 297 | program.parse(process.argv); 298 | if (!process.argv.slice(2).length) { 299 | program.outputHelp(); 300 | } 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | -------------------------------------------------------------------------------- /src/lib/utils.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import colors from 'colors'; 3 | import path from 'path'; 4 | 5 | export default { 6 | log : { 7 | normal( str ){ 8 | console.log( str ); 9 | }, 10 | debug( str ){ 11 | console.log( colors.green(str) ); 12 | }, 13 | info( str ){ 14 | console.log( colors.cyan(str) ); 15 | }, 16 | warn( str ){ 17 | console.log( colors.yellow(str) ); 18 | }, 19 | error( str ){ 20 | console.log( colors.red(str) ); 21 | }, 22 | main( str ){ 23 | console.log( colors.magenta(str) ); 24 | } 25 | }, 26 | isExists( src ){ 27 | return fs.existsSync( src ); 28 | }, 29 | isDir( src ){ 30 | let stat = fs.lstatSync( src ); 31 | return stat.isDirectory(); 32 | }, 33 | isEmptyDir( src ){ 34 | let _con = this.readDir( src ); 35 | if( _con.length > 0 ){ 36 | return false; 37 | } 38 | return true; 39 | }, 40 | isFile( src ){ 41 | let stat = fs.lstatSync( src ); 42 | return stat.isFile(); 43 | }, 44 | readFile( src ){ 45 | return fs.readFileSync( src ).toString(); 46 | }, 47 | readDir( src ){ 48 | return fs.readdirSync( src ) 49 | }, 50 | mkdir( tar ){ 51 | fs.mkdirSync( tar ); 52 | }, 53 | delFile( src ){ 54 | if( this.isExists(src) ){ 55 | fs.unlinkSync( src ); 56 | } 57 | }, 58 | writeFile( tar , data ){ 59 | fs.writeFileSync( tar , data ); 60 | }, 61 | copyFile( config ){ 62 | let conf = config || {}; 63 | 64 | let src = conf.source; 65 | let tar = conf.target; 66 | let overwrite = conf.overwrite; 67 | let replace = conf.replace; 68 | let updateLog = conf.updateLog; 69 | 70 | if( !src || !this.isFile(src) ){ 71 | return false; 72 | } 73 | 74 | let _src_file_data = this.readFile( src ); 75 | 76 | 77 | if( replace && replace.length > 0){ 78 | replace.map(( item )=>{ 79 | let _con = item.split('->'); 80 | let _regexp = new RegExp( _con[0] ,'g'); 81 | _src_file_data = _src_file_data.replace( _regexp , _con[1] ); 82 | }) 83 | } 84 | 85 | if( overwrite && this.isExists(tar) ){ 86 | let _tar_file_data = this.readFile( tar ); 87 | if( _tar_file_data !== _src_file_data ){ 88 | this.delFile( tar ); 89 | this.writeFile( tar , _src_file_data ); 90 | updateLog&&updateLog(); 91 | } 92 | } 93 | 94 | if( !this.isExists(tar) ){ 95 | this.writeFile( tar , _src_file_data ); 96 | } 97 | }, 98 | copyDir( src , tar ){ 99 | 100 | if( this.isDir( src ) ){ 101 | if( !this.isExists(tar) ){ 102 | this.mkdir(tar); 103 | } 104 | let _con = this.readDir( src ); 105 | 106 | if( _con.length < 1 ){ return false;} 107 | 108 | _con.map((item)=>{ 109 | if( item[0] === '.'){ 110 | return false; 111 | } 112 | let _src_path = path.join( src , item); 113 | let _tar_path = path.join( tar , item); 114 | if( this.isDir(_src_path) ){ 115 | this.copyDir( _src_path , _tar_path ); 116 | } 117 | if( this.isFile(_src_path) ){ 118 | this.copyFile({ 119 | source : _src_path, 120 | target : _tar_path 121 | }) 122 | } 123 | }) 124 | } 125 | }, 126 | toCamel( str ){ 127 | var re = /-(\w)/g; 128 | return str.replace(re, function($0,$1){ 129 | return $1.toUpperCase(); 130 | }); 131 | } 132 | } 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | --------------------------------------------------------------------------------