├── examples ├── coffeescript │ ├── vue-controller.coffee │ ├── greeter-service.coffee │ ├── service.coffee │ ├── vue-instance.coffee │ └── greeter.vue.coffee └── typescript │ ├── vue-controller.ts │ ├── service.ts │ ├── greeter-service.ts │ ├── vue-instance.ts │ └── greeter.vue.ts ├── .gitignore ├── .npmignore ├── .travis.yml ├── cli.ts ├── appveyor.yml ├── typings.json ├── vuecc.test.js ├── LICENSE ├── package.json ├── Gulpfile.js ├── README.md └── vuecc.ts /examples/coffeescript/vue-controller.coffee: -------------------------------------------------------------------------------- 1 | # Vue controller base class. 2 | 3 | class VueController extends VueInstance 4 | services = {} 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.tgz 2 | vuecc.js 3 | cli.js 4 | dt-init-config.json 5 | vuecc 6 | greeter.js 7 | greeter.ts 8 | typings/ 9 | node_modules/ 10 | tsconfig.json 11 | -------------------------------------------------------------------------------- /examples/coffeescript/greeter-service.coffee: -------------------------------------------------------------------------------- 1 | class GreeterService extends Service 2 | 3 | constructor: -> 4 | super 'GreeterService' 5 | 6 | greet: -> 7 | alert 'Hello, there!' 8 | 9 | -------------------------------------------------------------------------------- /examples/coffeescript/service.coffee: -------------------------------------------------------------------------------- 1 | class Service 2 | 3 | debug = true 4 | 5 | constructor: (name) -> 6 | if debug 7 | console.log "Initialized #{name}..." 8 | 9 | 10 | -------------------------------------------------------------------------------- /examples/typescript/vue-controller.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | // Vue controller base class. 4 | 5 | abstract class VueController extends VueInstance { 6 | protected services: any; 7 | } 8 | -------------------------------------------------------------------------------- /examples/typescript/service.ts: -------------------------------------------------------------------------------- 1 | abstract class Service { 2 | 3 | private debug: boolean = true; 4 | 5 | constructor(name: string) { 6 | if(this.debug) 7 | console.log(`Initialized ${name}...`); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/coffeescript/vue-instance.coffee: -------------------------------------------------------------------------------- 1 | # Vue instance base class. 2 | 3 | class VueInstance 4 | el = '' 5 | name = '' 6 | data = {} 7 | 8 | ready: -> 9 | null 10 | 11 | $set: (path, value) -> 12 | null 13 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | *.ts 2 | *.yml 3 | *.tgz 4 | *.test.js 5 | greeter.js 6 | greeter.ts 7 | tsd.json 8 | typings.json 9 | tsconfig.json 10 | dt-init-config.json 11 | Gulpfile.js 12 | .npmignore 13 | .gitignore 14 | typings/ 15 | examples/ 16 | -------------------------------------------------------------------------------- /examples/typescript/greeter-service.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | class GreeterService extends Service { 4 | 5 | constructor() { 6 | super('GreeterService'); 7 | } 8 | 9 | public greet(): void { 10 | alert('Hello, there!'); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /examples/typescript/vue-instance.ts: -------------------------------------------------------------------------------- 1 | // Vue instance base class. 2 | 3 | abstract class VueInstance { 4 | protected el: string; 5 | protected name: string; 6 | protected data: any; 7 | 8 | abstract ready(): void; 9 | public $set(path: string, value: any): void {}; 10 | } 11 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | notifications: 2 | email: false 3 | 4 | language: node_js 5 | node_js: 6 | - '6.2' 7 | - '5.1' 8 | 9 | # Install typings to manage TypeScript definitions. 10 | before_install: 11 | - npm install -g typings 12 | 13 | # Build vue-component-compiler (vuecc) from TypeScript source. 14 | before_script: 15 | - npm run build 16 | -------------------------------------------------------------------------------- /cli.ts: -------------------------------------------------------------------------------- 1 | /* 2 | Vue component compiler. 3 | Unoffical "compiler" for Vue.js components written in a class-based style. 4 | 5 | Copyright 2015-2016 Sam Saint-Pettersen. 6 | 7 | Released under the MIT License. 8 | */ 9 | 10 | import vuecc = require('./vuecc'); 11 | vuecc.cli(process.argv[1], process.argv[2], process.argv[3], process.argv); 12 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | environment: 2 | matrix: 3 | - nodejs_version: "6" 4 | - nodejs_version: "5" 5 | 6 | install: 7 | - ps: Install-Product node $env:nodejs_version 8 | - node --version 9 | - npm --version 10 | - npm install -g typings 11 | - npm install 12 | 13 | test_script: 14 | - npm run build 15 | - npm test 16 | 17 | build: off 18 | -------------------------------------------------------------------------------- /typings.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "chalk": "registry:npm/chalk#1.0.0+20160211003958" 4 | }, 5 | "globalDependencies": { 6 | "generic-functions": "registry:dt/generic-functions#0.0.0+20160514170344", 7 | "line-reader": "registry:dt/line-reader#0.0.0+20160316155526", 8 | "node": "registry:dt/node#6.0.0+20160621231320" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /examples/coffeescript/greeter.vue.coffee: -------------------------------------------------------------------------------- 1 | class GreeterController extends VueController 2 | 3 | constructor: -> 4 | @el = '#greeter' 5 | @name = 'greeter' 6 | @services = { 7 | greeter: new GreeterService 8 | } 9 | #! ## Please use #! to end a method block and ## for comments. 10 | 11 | ready: -> 12 | ## Please use () for method calls. 13 | @services.greeter.greet() 14 | #! 15 | 16 | sayHi: -> 17 | @ready() 18 | #! 19 | -------------------------------------------------------------------------------- /examples/typescript/greeter.vue.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | class GreeterController extends VueController { 5 | 6 | constructor() { 7 | super(); 8 | this.el = '#greeter'; 9 | this.name = 'greeter'; 10 | this.services = { 11 | greeter: new GreeterService() 12 | }; 13 | } 14 | 15 | public ready(): void { 16 | this.services.greeter.greet(); 17 | }; 18 | 19 | private sayHi(): void { 20 | this.ready(); 21 | }; 22 | } 23 | -------------------------------------------------------------------------------- /vuecc.test.js: -------------------------------------------------------------------------------- 1 | /* 2 | Run tests for vuecc. 3 | */ 4 | 5 | /* global describe it */ 6 | 'use strict' 7 | 8 | const assert = require('chai').assert 9 | const glob = require('glob') 10 | const fs = require('fs') 11 | 12 | describe('Test vue component compiler:', function () { 13 | it('Generated component -> greeter.ts via command line', function (done) { 14 | const files = glob.sync('greeter.ts') 15 | assert.equal(files[0], 'greeter.ts') 16 | assert.equal(fs.existsSync('greeter.ts'), true) 17 | done() 18 | }) 19 | it('Generated component -> greeter.js via command line', function (done) { 20 | const files = glob.sync('greeter.js') 21 | assert.equal(files[0], 'greeter.js') 22 | assert.equal(fs.existsSync('greeter.js'), true) 23 | done() 24 | }) 25 | }) 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Vue component compiler. 2 | Copyright 2015, 2016 Sam Saint-Pettersen. 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vuecc-compiler", 3 | "version": "0.1.0", 4 | "description": "Unofficial compiler for Vue.js components written in a class-based style", 5 | "main": "vuecc.js", 6 | "bin": { 7 | "vuecc": "./cli.js" 8 | }, 9 | "scripts": { 10 | "build": "gulp", 11 | "test": "gulp test" 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "https://github.com/stpettersens/vue-component-compiler.git" 16 | }, 17 | "keywords": [ 18 | "vue.js", 19 | "component", 20 | "compiler", 21 | "code", 22 | "generation", 23 | "tool", 24 | "utility" 25 | ], 26 | "author": "Sam Saint-Pettersen ", 27 | "license": "MIT", 28 | "bugs": { 29 | "url": "https://github.com/stpettersens/vue-component-compiler/issues" 30 | }, 31 | "homepage": "https://github.com/stpettersens/vue-component-compiler", 32 | "devDependencies": { 33 | "chai": "^3.5.0", 34 | "glob": "^7.0.3", 35 | "gulp": "^3.9.0", 36 | "gulp-insert": "^0.5.0", 37 | "gulp-mocha": "^3.0.1", 38 | "gulp-replace": "^0.5.4", 39 | "gulp-rimraf": "^0.2.0", 40 | "gulp-sequence": "^0.4.5", 41 | "gulp-typescript": "^3.0.1", 42 | "gulp-wait": "0.0.2", 43 | "typescript": "^2.0.3" 44 | }, 45 | "dependencies": { 46 | "chalk": "^1.1.1", 47 | "generic-functions": "^0.1.9", 48 | "line-reader": "^0.4.0" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Gulpfile.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Gulpfile for Vue component compiler. 3 | */ 4 | 5 | 'use strict' 6 | 7 | const gulp = require('gulp') 8 | const tsc = require('gulp-typescript') 9 | const replace = require('gulp-replace') 10 | const insert = require('gulp-insert') 11 | const mocha = require('gulp-mocha') 12 | const wait = require('gulp-wait') 13 | const clean = require('gulp-rimraf') 14 | const sequence = require('gulp-sequence') 15 | const _exec = require('child_process').exec 16 | const fs = require('fs') 17 | 18 | const header = [ '/*', 'Vue component compiler.', 19 | 'Unoffical "compiler" for Vue.js components written in a class-based style.', '', 20 | 'Copyright 2015-2016 Sam Saint-Pettersen.', '', 21 | 'Released under the MIT License.', '*/', '' ] 22 | 23 | gulp.task('typings', function () { 24 | if (!fs.existsSync('typings/index.d.ts')) { 25 | _exec('typings install', function (stderr, stdout) { 26 | console.info(stdout) 27 | }) 28 | return gulp.src('*', {read: false}) 29 | .pipe(wait(12000)) 30 | } 31 | }) 32 | 33 | gulp.task('core', function () { 34 | return gulp.src('vuecc.ts') 35 | .pipe(tsc({ 36 | module: 'commonjs', 37 | target: 'ES5', 38 | removeComments: true 39 | })) 40 | .pipe(insert.prepend(header.join('\n'))) 41 | .pipe(gulp.dest('.')) 42 | }) 43 | 44 | gulp.task('bin', function () { 45 | return gulp.src('cli.ts') 46 | .pipe(tsc({ 47 | module: 'commonjs', 48 | target: 'ES5', 49 | removeComments: true 50 | })) 51 | .pipe(insert.prepend(header.join('\n'))) 52 | .pipe(insert.prepend('#!/usr/bin/env node\n')) 53 | .pipe(replace(/(.\/vuecc)/g, '$1.js')) 54 | .pipe(gulp.dest('.')) 55 | }) 56 | 57 | gulp.task('test1', function () { 58 | _exec('node cli.js examples/typescript/greeter.vue.ts greeter.ts', function (stderr, stdout) { 59 | console.log(stdout) 60 | }) 61 | return gulp.src('*', {read: false}) 62 | .pipe(wait(2000)) 63 | }) 64 | 65 | gulp.task('test2', function () { 66 | _exec('node cli.js examples/typescript/greeter.vue.ts greeter.js', function (stderr, stdout) { 67 | console.log(stdout) 68 | }) 69 | return gulp.src('*', {read: false}) 70 | .pipe(wait(2000)) 71 | }) 72 | 73 | gulp.task('test3', function () { 74 | return gulp.src('vuecc.test.js', {read: false}) 75 | .pipe(mocha({reporter: 'min'})) 76 | }) 77 | 78 | gulp.task('clean', function () { 79 | return gulp.src(['cli.js', 'vuecc.js', 'greeter.ts', 'greeter.js', 'typings']) 80 | .pipe(clean()) 81 | }) 82 | 83 | gulp.task('default', sequence('typings', ['core', 'bin'])) 84 | gulp.task('test', sequence('test1', 'test2', 'test3')) 85 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### Vue component compiler by [@stpettersens](https://github.com/stpettersens) 2 | 3 | > :mount_fuji: Unofficial "compiler" for Vue.js components written in a class-based style. 4 | 5 | [![Build Status](https://travis-ci.org/stpettersens/vue-component-compiler.png?branch=master)](https://travis-ci.org/stpettersens/vue-component-compiler) 6 | [![Build status](https://ci.appveyor.com/api/projects/status/8069glp56dcrma9t?svg=true)](https://ci.appveyor.com/project/stpettersens/vue-component-compiler) 7 | [![npm version](https://badge.fury.io/js/vuecc-compiler.svg)](http://npmjs.org/package/vuecc-compiler) 8 | [![Dependency Status](https://david-dm.org/stpettersens/vue-component-compiler.png?theme=shields.io)](https://david-dm.org/stpettersens/vue-component-compiler) [![Development Dependency Status](https://david-dm.org/stpettersens/vue-component-compiler/dev-status.png?theme=shields.io)](https://david-dm.org/stpettersens/vue-component-compiler#info=devDependencies) 9 | 10 | This compiler allows you to write components like so: 11 | 12 | ```ts 13 | // Greeter Vue instance in TypeScript 14 | 15 | /// 16 | 17 | class Greeter extends VueInstance { 18 | constructor() { 19 | super(); 20 | this.el = '#greeter'; 21 | this.name = 'greeter'; // For outside access (e.g. javascript:greeter.sayHi()). 22 | this.data = { 23 | name: 'Sam' 24 | }; 25 | } 26 | 27 | public ready(): void { 28 | this.sayHi(); 29 | }; 30 | 31 | public sayHi(): void { 32 | console.log(`Hi, ${name}.`); 33 | }; 34 | } 35 | ``` 36 | 37 | ##### Install: 38 | 39 | `npm install -g vuecc-compiler` for the `vuecc` command. 40 | 41 | ##### Usage: 42 | 43 | ``` 44 | Usage: vuecc input output [['reference']][-t type][-q|--quiet][-c|--no-colors] 45 | [-n|--no-header][-h|--help|-v|--version] 46 | 47 | input : Class-based component as input (e.g. component.vue.ts) 48 | output : new Vue() formatted component as output (e.g. component.ts) 49 | ['reference'] : Reference path include(s) (TypeScript). 50 | -t | --type : Specify language input (coffee, ts, js). 51 | -q | --quiet : Be less verbose (only error output). 52 | -c | --no-colors : Don't use colorful output. 53 | -n | --no-header : Don't generate commented header for output. 54 | -h | --help : Display this usage information and exit. 55 | -v | --version : Display application version and exit. 56 | ``` 57 | 58 | ##### Using Gulp or Grunt? 59 | 60 | :tropical_drink: [gulp-vuecc](http://github.com/stpettersens/gulp-vuecc) 61 | :boar: [grunt-vuecc](http://github.com/stpettersens/grunt-vuecc) 62 | 63 | This utility should not be confused with https://github.com/vuejs/vue-component-compiler 64 | -------------------------------------------------------------------------------- /vuecc.ts: -------------------------------------------------------------------------------- 1 | /* 2 | Vue component compiler. 3 | Unoffical "compiler" for Vue.js components written in a class-based style. 4 | 5 | Copyright 2015-2016 Sam Saint-Pettersen. 6 | 7 | Released under the MIT License. 8 | */ 9 | 10 | /// 11 | 12 | import fs = require('fs'); 13 | import lr = require('line-reader'); 14 | import chalk = require('chalk'); 15 | import g = require('generic-functions'); 16 | 17 | interface CompilerOpts { 18 | verbose: boolean; 19 | colors: boolean; 20 | header: boolean; 21 | type: string; 22 | } 23 | 24 | class VueComponentCompiler { 25 | private static program: string; 26 | private static version: string; 27 | private static colors: boolean; 28 | private static verbose: boolean; 29 | private static header: boolean; 30 | private static references: string[]; 31 | private static input: string; 32 | private static output: string; 33 | private static type: string; 34 | 35 | /** 36 | * Check if line is empty. 37 | * @param line Line to check. 38 | * @returns Is line empty? 39 | */ 40 | private static isNotEmptyLine(line: string) { 41 | if (/^\s*\t*$/.test(line) == false) { 42 | return true; 43 | } 44 | return false; 45 | } 46 | 47 | /** 48 | * Print an error message. 49 | * @param message Error message to print. 50 | */ 51 | private static printError(message: string): void { 52 | if (VueComponentCompiler.colors) { 53 | console.log(chalk.bold.red(message)); 54 | } 55 | else console.log(message); 56 | } 57 | 58 | /** 59 | * Print an information message. 60 | * @param message Informatiom message to print. 61 | */ 62 | private static printInfo(message: string): void { 63 | if (VueComponentCompiler.colors) { 64 | console.log(chalk.gray(message)); 65 | } 66 | else console.log(message); 67 | } 68 | 69 | /** 70 | * Highlight some text. 71 | * @param text Text to highlight. 72 | * @returns Hilighted text. 73 | */ 74 | private static hilight(text: string): any { 75 | if (VueComponentCompiler.colors) { 76 | return chalk.yellow(text); 77 | } 78 | return text; 79 | } 80 | 81 | /** 82 | * Some text to embolden. 83 | * @param text Text to embolden. 84 | * @returns Bold text. 85 | */ 86 | private static embolden(text: string): any {text 87 | if (VueComponentCompiler.colors) { 88 | return chalk.bold.white(text); 89 | } 90 | return text; 91 | } 92 | 93 | /** 94 | * Display help information and exit. 95 | */ 96 | private static displayHelp(): void { 97 | const MIT: string = `${VueComponentCompiler.hilight('[MIT License].')}`; 98 | VueComponentCompiler.printInfo('Utility to compile class-based Vue components.'); 99 | VueComponentCompiler.printInfo(`Copyright 2015-2016 Sam Saint-Pettersen ${MIT}`); 100 | console.log(`\nUsage: ${this.embolden('vuecc')} input output [[\'reference\']][-t|--type]`); 101 | console.log('[-q|--quiet][-n|--no-colors][-c|--no-header][-h|--help|-v|--version]'); 102 | console.log('\n input : Class-based component as input (e.g. component.vue.ts)'); 103 | console.log(' output : new Vue() formatted component as output (e.g. component.ts)'); 104 | console.log(' [\'reference\'] : Reference path include(s) (TypeScript).'); 105 | console.log(' -t | --type : Specify language input (coffee, ts, js).'); 106 | console.log(' -q | --quiet : Be less verbose (only error output).'); 107 | console.log(' -c | --no-colors : Don\'t use colorful output.'); 108 | console.log(' -n | --no-header : Don\'t generate commented header for output.'); 109 | console.log(' -h | --help : Display this usage information and exit.'); 110 | console.log(' -v | --version : Display application version and exit.'); 111 | } 112 | 113 | /** 114 | * Display version and exit. 115 | */ 116 | private static displayVersion(): void { 117 | VueComponentCompiler.printInfo('vuecc v. ' + VueComponentCompiler.version); 118 | process.exit(0); 119 | } 120 | 121 | /** 122 | * Compile the output. 123 | */ 124 | private static compile(): void { 125 | var in_method: boolean = false; 126 | var in_data: boolean = false; 127 | var in_services: boolean = false; 128 | var c_method: string = null; 129 | var className: string = null 130 | var el: string = null; 131 | var name: string = null; 132 | var data = new Array(); 133 | var services = new Array(); 134 | var methods = new Array(); 135 | var signatures = new Array(); 136 | var methodsImpl = new Array(); 137 | var lines = new Array(); 138 | 139 | var iext: string = g.endswithdot(VueComponentCompiler.input); 140 | var oext: string = g.endswithdot(VueComponentCompiler.output); 141 | var header: boolean = VueComponentCompiler.header; 142 | var references: string[] = VueComponentCompiler.references; 143 | var output: string = VueComponentCompiler.output; 144 | 145 | if(VueComponentCompiler.type !== null) iext = '.' + VueComponentCompiler.type; 146 | 147 | lr.eachLine(VueComponentCompiler.input, function(line: string, last: boolean) { 148 | 149 | //console.log(line); 150 | if (!in_method && !in_data && !in_services) { 151 | 152 | var m: RegExpMatchArray = line.match(/class\s(.*)\sextends\sVue.*/); 153 | if (m != null) className = m[1]; 154 | 155 | line = line.replace(/(\s*)@(.*)/, '$1this.$2'); 156 | 157 | if (iext === '.coffee') 158 | m = line.match(/this\.el\s\=(.*)/); 159 | else 160 | m = line.match(/this\.el\s\=(.*);/); 161 | if (m !== null) el = m[1]; 162 | 163 | if (iext ==='.coffee') 164 | m = line.match(/this\.name\s\=(.*)/); 165 | else 166 | m = line.match(/this\.name\s\=(.*);/); 167 | if (m !== null) name = m[1].replace(/'|"|\s/g, ''); 168 | 169 | if (iext === '.ts' || iext === '.js') 170 | m = line.match(/(?:public|private|protected)\s*(.*)\((.*)\)/); 171 | else 172 | m = line.match(/(.*)\:\s*\(*(.*)\)*\s\-\>/); 173 | 174 | if (m !== null && m[1].indexOf('constructor') === -1) { 175 | methods.push(m[1]); 176 | if (m[2] !== null) signatures.push(m[2].replace(')', '')); 177 | else this.signatures.push(''); 178 | c_method = m[1]; 179 | in_method = true; 180 | } 181 | 182 | m = line.match(/(this.data\s=\s{)/); 183 | if (m !== null) in_data = true; 184 | 185 | m = line.match(/(this.services\s=\s{)/); 186 | if (m !== null) in_services = true; 187 | } 188 | else if(in_method) { 189 | if (iext === '.ts' || iext === '.js'){ 190 | m = line.match(/(\};)/); 191 | } 192 | else if(iext === '.coffee') { 193 | m = line.match(/(#!)/); 194 | 195 | line = line.replace('#!', ''); 196 | line = line.replace(/(\s*)@(.*)/, '$1$2'); 197 | 198 | var element = line.match(/this.el\s\=(.*)/); 199 | if (element !== null) el = element[1]; 200 | 201 | var scope = line.match(/this.name\s\=(.*)/); 202 | if (scope !== null) name = scope[1].replace(/'|"|\s/g, ''); 203 | } 204 | 205 | if (m != null) in_method = false; 206 | m = line.match(/(.*)/); 207 | if (m != null) { 208 | methodsImpl.push(c_method + '-->' + m[1]); 209 | } 210 | } 211 | else if(in_data) { 212 | if (iext === '.coffee') 213 | m = line.match(/(\})/); 214 | else 215 | m = line.match(/(\});/); 216 | 217 | if (m != null) in_data = false; 218 | m = line.match(/(.*)/); 219 | if (m != null) { 220 | data.push(m[1]); 221 | } 222 | } 223 | else if(in_services) { 224 | if (iext === '.coffee') 225 | m = line.match(/(\})/); 226 | else 227 | m = line.match(/(\});/); 228 | 229 | if (m != null) in_services = false; 230 | m = line.match(/(.*)/); 231 | if (m != null) { 232 | services.push(m[1]); 233 | } 234 | } 235 | 236 | if(last) { 237 | 238 | if(header) { 239 | lines.push('// ********************************************************************'); 240 | lines.push(`// ${className}`); 241 | lines.push(`// Generated at ${new Date().toISOString()} by Vue component compiler.`); 242 | lines.push(lines[0]); 243 | } 244 | if(oext === '.ts') { 245 | if(references.length == 0) 246 | lines.push('/// \n'); 247 | 248 | references.map(function(reference: string) { 249 | lines.push(`/// `); 250 | }); 251 | } 252 | if(name !== null) { 253 | lines.push(`var ${name} = null;`); 254 | } 255 | if(services.length > 0) { 256 | lines.push('var services = {'); 257 | services.map(function(service: string) { 258 | service = '\t' + service.replace(/^\s*/g, ''); 259 | service = service.replace(/\};/, ''); 260 | service = service.replace(/\}/, ''); 261 | lines.push(service); 262 | }); 263 | lines.push('};'); 264 | } 265 | lines.push('window.onload = function() {') 266 | if(name !== null) { 267 | lines.push(`\t${name} = new Vue({`); 268 | } 269 | else 270 | lines.push('\tnew Vue({'); 271 | 272 | lines.push(`\t\tel: ${el},`); 273 | lines.push('\t\tdata: {'); 274 | data.map(function(datum: string) { 275 | datum = datum.replace(/\};/, ''); 276 | datum = datum.replace('}', ''); 277 | lines.push(datum); 278 | }); 279 | lines.push('\t\t},'); 280 | lines.push('\t\tready: function() {'); 281 | methodsImpl.map(function(impl: string) { 282 | if (impl.indexOf(methods[0] + '-->') != -1) { 283 | impl = impl.replace('};', ''); 284 | impl = impl.replace('this.services', 'services'); 285 | var fl = impl.split('-->'); 286 | if (fl[1].length > 0) lines.push('\t' + fl[1]); 287 | } 288 | }); 289 | lines.push('\t\t},'); 290 | lines.push('\t\tmethods: {'); 291 | methods.splice(0, 1); 292 | signatures.splice(0, 1); 293 | for (var i = 0; i < methods.length; i++) { 294 | if (iext === '.coffee') methods[i] = methods[i].replace('\t', ''); 295 | if (signatures[i] === undefined) signatures[i] = ''; 296 | lines.push(`\t\t\t${methods[i]}: function(${signatures[i]}) {`); 297 | methodsImpl.map(function(impl) { 298 | if (impl.indexOf(methods[i] + '-->') != -1) { 299 | impl = impl.replace('};', ''); 300 | impl = impl.replace('this.services', 'services'); 301 | var fl = impl.split('-->'); 302 | if (fl[1].length > 0) lines.push('\t\t' + fl[1]); 303 | } 304 | }); 305 | if (i < methods.length - 1) lines.push('\t\t\t},') 306 | else lines.push('\t\t\t}'); 307 | } 308 | lines.push('\t\t}'); 309 | lines.push('\t});\n};\n') 310 | 311 | lines = lines.filter(VueComponentCompiler.isNotEmptyLine); 312 | if(iext === '.coffee') 313 | lines = lines.map(function(line) { return line.replace('##', '//') }); 314 | fs.writeFileSync(output, lines.join('\n')); 315 | return false; 316 | } 317 | }); 318 | } 319 | 320 | /** 321 | * Invoke VueComponentCompiler via command line. 322 | * @param program Program name from process.argv. 323 | * @param input Class-based component to compile. 324 | * @param output new Vue() formatted component. 325 | * @param options Additional options. 326 | */ 327 | public static cli(program: string, input: string, output: string, options: string[]): void { 328 | VueComponentCompiler.program = program; 329 | VueComponentCompiler.version = '0.1.0'; 330 | VueComponentCompiler.colors = true; 331 | VueComponentCompiler.verbose = true; 332 | VueComponentCompiler.header = true; 333 | VueComponentCompiler.references = new Array(); 334 | VueComponentCompiler.input = input; 335 | VueComponentCompiler.output = output; 336 | VueComponentCompiler.type = null; 337 | 338 | if (options) { 339 | for (let i = 0; i < options.length; i++) { 340 | if (options[i] == '-q' || options[i] == '--quiet') { 341 | VueComponentCompiler.verbose = false; 342 | } 343 | 344 | if (options[i] =='-c' || options[i] == '--no-colors') { 345 | VueComponentCompiler.colors = false; 346 | } 347 | 348 | if (options[i] == '-n' || options[i] == '--no-header') { 349 | VueComponentCompiler.header = false; 350 | } 351 | 352 | if (options[i] == '-t' || options[i] == '--type') { 353 | VueComponentCompiler.type = options[i+1]; 354 | } 355 | 356 | if (options[i] != null && options[i].charAt(0) == '[') { 357 | VueComponentCompiler.references = JSON.parse(options[i].replace(/'/g, '"')); 358 | } 359 | } 360 | } 361 | 362 | if(input == '-h' || input == '--help') { 363 | VueComponentCompiler.displayHelp(); 364 | process.exit(0); 365 | } 366 | else if(input == '-v' || input == '--version') { 367 | VueComponentCompiler.displayVersion(); 368 | } 369 | if(input == null || input.charAt(0) == '-') { 370 | VueComponentCompiler.printError('Please specify a valid input file.\n'); 371 | VueComponentCompiler.displayHelp(); 372 | process.exit(1); 373 | } 374 | else if(output == null || output.charAt(0) == '-') { 375 | VueComponentCompiler.printError('Please specify a valid output file.\n'); 376 | VueComponentCompiler.displayHelp(); 377 | process.exit(1); 378 | } 379 | if(VueComponentCompiler.verbose) 380 | VueComponentCompiler.printInfo(`Compiling Vue component: ${this.embolden(input)}`); 381 | 382 | VueComponentCompiler.compile(); 383 | } 384 | } 385 | export = VueComponentCompiler; 386 | --------------------------------------------------------------------------------