Merge pull request #338 from hdeshev/angular-template-syntax

Angular template syntax support, xml parser fix
This commit is contained in:
Hristo Deshev
2015-06-17 16:48:44 +03:00
12 changed files with 1243 additions and 609 deletions

5
.gitignore vendored
View File

@@ -4,7 +4,6 @@
.sublime-grunt.cache
tscommand*.tmp.txt
.tscache
*.js
node_modules/
dist/
@@ -20,3 +19,7 @@ CrossPlatformModules.csproj.user
bin/
obj/
.vs/
.baseDir.ts
.ctags-exclude
tags

View File

@@ -142,6 +142,12 @@ module.exports = function(grunt) {
]
};
var nodeTestEnv = JSON.parse(JSON.stringify(process.env));
nodeTestEnv['NODE_PATH'] = localCfg.outModulesDir;
localCfg.nodeTestsDir = pathModule.join(localCfg.outModulesDir, 'node-tests');
localCfg.mainPackageContent = grunt.file.readJSON(localCfg.packageJsonFilePath);
localCfg.packageVersion = getPackageVersion(localCfg.packageJsonFilePath);
localCfg.commitSHA = getCommitSha();
@@ -180,6 +186,9 @@ module.exports = function(grunt) {
],
cwd: localCfg.outModulesDir
},
nodeTests: {
src: localCfg.nodeTestsDir,
},
readyAppFiles: {
src: [localCfg.outModulesDir + "/apps/**"]
}
@@ -293,6 +302,25 @@ module.exports = function(grunt) {
src: localCfg.typeScriptSrc,
outDir: localCfg.outModulesDir,
options: {
fast: 'never',
module: "commonjs",
target: "es5",
sourceMap: false,
declaration: false,
removeComments: "<%= !grunt.option('leavecomments') || '' %>",
compiler: "node_modules/typescript/bin/tsc",
noEmitOnError: true
}
},
buildNodeTests: {
src: [
'js-libs/easysax/**/*.ts',
'xml/**/*.ts',
'node-tests/**/*.ts',
],
outDir: localCfg.outModulesDir,
options: {
fast: 'never',
module: "commonjs",
target: "es5",
sourceMap: false,
@@ -325,6 +353,9 @@ module.exports = function(grunt) {
packApp: {
cmd: "npm pack",
cwd: "__dummy__"
},
mochaNode: {
cmd: "grunt simplemocha:node"
}
},
multidest: {
@@ -347,6 +378,16 @@ module.exports = function(grunt) {
options: {
callback: assignGitSHA
}
},
},
simplemocha: {
node: {
src: localCfg.nodeTestsDir + '/**/*.js'
}
},
env: {
nodeTests: {
NODE_PATH: localCfg.outModulesDir,
}
}
});
@@ -358,6 +399,8 @@ module.exports = function(grunt) {
grunt.loadNpmTasks("grunt-tslint");
grunt.loadNpmTasks("grunt-multi-dest");
grunt.loadNpmTasks("grunt-shell");
grunt.loadNpmTasks("grunt-env");
grunt.loadNpmTasks("grunt-simple-mocha");
var cloneTasks = function(originalTasks, taskNameSuffix)
{
@@ -486,4 +529,19 @@ module.exports = function(grunt) {
"pack-definitions",
"get-ready-packages"
]));
grunt.registerTask("testEnv", function() {
console.log('fafla', process.env.NODE_PATH);
//var x = require('xml')
//console.log(x);
});
grunt.registerTask("node-tests", [
"clean:nodeTests",
"ts:buildNodeTests",
"copy:childPackageFiles",
"copy:jsLibs",
"env:nodeTests",
"exec:mochaNode", //spawn a new process to use the new NODE_PATH
]);
};

View File

@@ -5,6 +5,7 @@ declare module "js-libs/easysax" {
parse(xml: string): void;
on(name: string, cb: Function): void;
ns(root: string, ns: any): void;
public angularSyntax: boolean;
}
}

View File

File diff suppressed because it is too large Load Diff

285
node-tests/definitions/chai.d.ts vendored Normal file
View File

@@ -0,0 +1,285 @@
/* tslint:disable */
// Type definitions for chai 1.7.2
// Project: http://chaijs.com/
// Definitions by: Jed Hunsaker <https://github.com/jedhunsaker/>, Bart van der Schoor <https://github.com/Bartvds>
// Definitions: https://github.com/borisyankov/DefinitelyTyped
declare module chai {
export class AssertionError {
constructor(message: string, _props?: any, ssf?: Function);
name: string;
message: string;
showDiff: boolean;
stack: string;
}
function expect(target: any, message?: string): Expect;
export var assert: Assert;
export var config: Config;
export interface Config {
includeStack: boolean;
}
// Provides a way to extend the internals of Chai
function use(fn: (chai: any, utils: any) => void): any;
interface ExpectStatic {
(target: any): Expect;
}
interface Assertions {
attr(name: string, value?: string): any;
css(name: string, value?: string): any;
data(name: string, value?: string): any;
class(className: string): any;
id(id: string): any;
html(html: string): any;
text(text: string): any;
value(value: string): any;
visible: any;
hidden: any;
selected: any;
checked: any;
disabled: any;
empty: any;
exist: any;
}
interface Expect extends LanguageChains, NumericComparison, TypeComparison, Assertions {
not: Expect;
deep: Deep;
a: TypeComparison;
an: TypeComparison;
include: Include;
contain: Include;
ok: Expect;
true: Expect;
false: Expect;
null: Expect;
undefined: Expect;
exist: Expect;
empty: Expect;
arguments: Expect;
Arguments: Expect;
equal: Equal;
equals: Equal;
eq: Equal;
eql: Equal;
eqls: Equal;
property: Property;
ownProperty: OwnProperty;
haveOwnProperty: OwnProperty;
length: Length;
lengthOf: Length;
match(RegularExpression: RegExp, message?: string): Expect;
string(string: string, message?: string): Expect;
keys: Keys;
key(string: string): Expect;
throw: Throw;
throws: Throw;
Throw: Throw;
respondTo(method: string, message?: string): Expect;
itself: Expect;
satisfy(matcher: Function, message?: string): Expect;
closeTo(expected: number, delta: number, message?: string): Expect;
members: Members;
}
interface LanguageChains {
to: Expect;
be: Expect;
been: Expect;
is: Expect;
that: Expect;
and: Expect;
have: Expect;
with: Expect;
at: Expect;
of: Expect;
same: Expect;
}
interface NumericComparison {
above: NumberComparer;
gt: NumberComparer;
greaterThan: NumberComparer;
least: NumberComparer;
gte: NumberComparer;
below: NumberComparer;
lt: NumberComparer;
lessThan: NumberComparer;
most: NumberComparer;
lte: NumberComparer;
within(start: number, finish: number, message?: string): Expect;
}
interface NumberComparer {
(value: number, message?: string): Expect;
}
interface TypeComparison {
(type: string, message?: string): Expect;
instanceof: InstanceOf;
instanceOf: InstanceOf;
}
interface InstanceOf {
(constructor: Object, message?: string): Expect;
}
interface Deep {
equal: Equal;
property: Property;
}
interface Equal {
(value: any, message?: string): Expect;
}
interface Property {
(name: string, value?: any, message?: string): Expect;
}
interface OwnProperty {
(name: string, message?: string): Expect;
}
interface Length extends LanguageChains, NumericComparison {
(length: number, message?: string): Expect;
}
interface Include {
(value: Object, message?: string): Expect;
(value: string, message?: string): Expect;
(value: number, message?: string): Expect;
keys: Keys;
members: Members;
}
interface Keys {
(...keys: string[]): Expect;
(keys: any[]): Expect;
}
interface Members {
(set: any[], message?: string): Expect;
}
interface Throw {
(): Expect;
(expected: string, message?: string): Expect;
(expected: RegExp, message?: string): Expect;
(constructor: Error, expected?: string, message?: string): Expect;
(constructor: Error, expected?: RegExp, message?: string): Expect;
(constructor: Function, expected?: string, message?: string): Expect;
(constructor: Function, expected?: RegExp, message?: string): Expect;
}
export interface Assert {
(express: any, msg?: string):void;
fail(actual?: any, expected?: any, msg?: string, operator?: string):void;
ok(val: any, msg?: string):void;
notOk(val: any, msg?: string):void;
equal(act: any, exp: any, msg?: string):void;
notEqual(act: any, exp: any, msg?: string):void;
strictEqual(act: any, exp: any, msg?: string):void;
notStrictEqual(act: any, exp: any, msg?: string):void;
deepEqual(act: any, exp: any, msg?: string):void;
notDeepEqual(act: any, exp: any, msg?: string):void;
isTrue(val: any, msg?: string):void;
isFalse(val: any, msg?: string):void;
isNull(val: any, msg?: string):void;
isNotNull(val: any, msg?: string):void;
isUndefined(val: any, msg?: string):void;
isDefined(val: any, msg?: string):void;
isFunction(val: any, msg?: string):void;
isNotFunction(val: any, msg?: string):void;
isObject(val: any, msg?: string):void;
isNotObject(val: any, msg?: string):void;
isArray(val: any, msg?: string):void;
isNotArray(val: any, msg?: string):void;
isString(val: any, msg?: string):void;
isNotString(val: any, msg?: string):void;
isNumber(val: any, msg?: string):void;
isNotNumber(val: any, msg?: string):void;
isBoolean(val: any, msg?: string):void;
isNotBoolean(val: any, msg?: string):void;
typeOf(val: any, type: string, msg?: string):void;
notTypeOf(val: any, type: string, msg?: string):void;
instanceOf(val: any, type: Function, msg?: string):void;
notInstanceOf(val: any, type: Function, msg?: string):void;
include(exp: string, inc: any, msg?: string):void;
include(exp: any[], inc: any, msg?: string):void;
notInclude(exp: string, inc: any, msg?: string):void;
notInclude(exp: any[], inc: any, msg?: string):void;
match(exp: any, re: RegExp, msg?: string):void;
notMatch(exp: any, re: RegExp, msg?: string):void;
property(obj: Object, prop: string, msg?: string):void;
notProperty(obj: Object, prop: string, msg?: string):void;
deepProperty(obj: Object, prop: string, msg?: string):void;
notDeepProperty(obj: Object, prop: string, msg?: string):void;
propertyVal(obj: Object, prop: string, val: any, msg?: string):void;
propertyNotVal(obj: Object, prop: string, val: any, msg?: string):void;
deepPropertyVal(obj: Object, prop: string, val: any, msg?: string):void;
deepPropertyNotVal(obj: Object, prop: string, val: any, msg?: string):void;
lengthOf(exp: any, len: number, msg?: string):void;
//alias frenzy
throw(fn: Function, msg?: string):void;
throw(fn: Function, regExp: RegExp):void;
throw(fn: Function, errType: Function, msg?: string):void;
throw(fn: Function, errType: Function, regExp: RegExp):void;
throws(fn: Function, msg?: string):void;
throws(fn: Function, regExp: RegExp):void;
throws(fn: Function, errType: Function, msg?: string):void;
throws(fn: Function, errType: Function, regExp: RegExp):void;
Throw(fn: Function, msg?: string):void;
Throw(fn: Function, regExp: RegExp):void;
Throw(fn: Function, errType: Function, msg?: string):void;
Throw(fn: Function, errType: Function, regExp: RegExp):void;
doesNotThrow(fn: Function, msg?: string):void;
doesNotThrow(fn: Function, regExp: RegExp):void;
doesNotThrow(fn: Function, errType: Function, msg?: string):void;
doesNotThrow(fn: Function, errType: Function, regExp: RegExp):void;
operator(val: any, operator: string, val2: any, msg?: string):void;
closeTo(act: number, exp: number, delta: number, msg?: string):void;
sameMembers(set1: any[], set2: any[], msg?: string):void;
includeMembers(set1: any[], set2: any[], msg?: string):void;
ifError(val: any, msg?: string):void;
}
}
declare module "chai" {
export = chai;
}

112
node-tests/definitions/mocha.d.ts vendored Normal file
View File

@@ -0,0 +1,112 @@
/* tslint:disable */
// Type definitions for mocha 1.17.1
// Project: http://visionmedia.github.io/mocha/
// Definitions by: Kazi Manzur Rashid <https://github.com/kazimanzurrashid/>, otiai10 <https://github.com/otiai10>
// Definitions: https://github.com/borisyankov/DefinitelyTyped
interface Mocha {
// Setup mocha with the given setting options.
setup(options: MochaSetupOptions): Mocha;
//Run tests and invoke `fn()` when complete.
run(callback?: () => void): void;
// Set reporter as function
reporter(reporter: () => void): Mocha;
// Set reporter, defaults to "dot"
reporter(reporter: string): Mocha;
// Enable growl support.
growl(): Mocha
}
interface MochaSetupOptions {
//milliseconds to wait before considering a test slow
slow?: number;
// timeout in milliseconds
timeout?: number;
// ui name "bdd", "tdd", "exports" etc
ui?: string;
//array of accepted globals
globals?: any[];
// reporter instance (function or string), defaults to `mocha.reporters.Dot`
reporter?: any;
// bail on the first test failure
bail?: Boolean;
// ignore global leaks
ignoreLeaks?: Boolean;
// grep string or regexp to filter tests with
grep?: any;
}
interface MochaDone {
(error?: Error): void;
}
declare var mocha: Mocha;
declare var describe : {
(description: string, spec: () => void): void;
only(description: string, spec: () => void): void;
skip(description: string, spec: () => void): void;
timeout(ms: number): void;
}
// alias for `describe`
declare var context : {
(contextTitle: string, spec: () => void): void;
only(contextTitle: string, spec: () => void): void;
skip(contextTitle: string, spec: () => void): void;
timeout(ms: number): void;
}
declare var it: {
(expectation: string, assertion?: () => void): void;
(expectation: string, assertion?: (done: MochaDone) => void): void;
only(expectation: string, assertion?: () => void): void;
only(expectation: string, assertion?: (done: MochaDone) => void): void;
skip(expectation: string, assertion?: () => void): void;
skip(expectation: string, assertion?: (done: MochaDone) => void): void;
timeout(ms: number): void;
};
declare function before(action: () => void): void;
declare function before(action: (done: MochaDone) => void): void;
declare function setup(action: () => void): void;
declare function setup(action: (done: MochaDone) => void): void;
declare function after(action: () => void): void;
declare function after(action: (done: MochaDone) => void): void;
declare function teardown(action: () => void): void;
declare function teardown(action: (done: MochaDone) => void): void;
declare function beforeEach(action: () => void): void;
declare function beforeEach(action: (done: MochaDone) => void): void;
declare function suiteSetup(action: () => void): void;
declare function suiteSetup(action: (done: MochaDone) => void): void;
declare function afterEach(action: () => void): void;
declare function afterEach(action: (done: MochaDone) => void): void;
declare function suiteTeardown(action: () => void): void;
declare function suiteTeardown(action: (done: MochaDone) => void): void;

View File

@@ -0,0 +1,81 @@
import {assert} from "chai";
import xml = require('xml');
describe("angular xml parser", () => {
let last_element = null;
let last_attrs = null;
let parser = null;
beforeEach(() => {
parser = new xml.XmlParser(function (event: xml.ParserEvent) {
switch (event.eventType) {
case xml.ParserEventType.StartElement:
last_element = event.elementName;
last_attrs = event.attributes;
break;
}
});
parser.angularSyntax = true;
});
it("parses [property] binding", () => {
parser.parse("<TextField [text]='somevar' />");
assert.equal('TextField', last_element);
assert.equal(last_attrs['[text]'], 'somevar');
});
it("parses (event) binding", () => {
parser.parse("<TextField (tap)='onTap(blah)' />");
assert.equal('TextField', last_element);
assert.equal(last_attrs['(tap)'], 'onTap(blah)');
});
it("parses (^event) binding", () => {
parser.parse("<TextField (^tap)='onTap(blah)' />");
assert.equal('TextField', last_element);
assert.equal(last_attrs['(^tap)'], 'onTap(blah)');
});
it("parses #id attribute", () => {
parser.parse("<TextField #firstName />");
assert.equal('TextField', last_element);
assert.equal(last_attrs['#firstName'], '');
});
it("parses #id attribute followed by another", () => {
parser.parse("<TextField #firstName text='Name' />");
assert.equal('TextField', last_element);
assert.equal(last_attrs['#firstName'], '');
assert.equal(last_attrs['text'], 'Name');
});
it("detects equals without value", () => {
parser.parse("<TextField brokenTag= />");
assert.isFalse(last_attrs);
});
it("detects no equals with quoted value", () => {
parser.parse("<TextField noEquals 'value' />");
assert.isFalse(last_attrs);
});
it("detects unclosed tag after no value attribute", () => {
parser.parse("<TextField #myId");
assert.isFalse(last_attrs);
});
it("rejects angular properties if syntax disabled", () => {
parser.angularSyntax = false;
parser.parse("<TextField [text]='somevalue' />");
assert.isFalse(last_attrs);
});
});

38
node-tests/test-xml.ts Normal file
View File

@@ -0,0 +1,38 @@
import {assert} from "chai";
import xml = require('xml');
describe("xml parser", () => {
let last_element = null;
let last_attrs = null;
let last_data = null;
let parser = null;
beforeEach(() => {
parser = new xml.XmlParser(function (event: xml.ParserEvent) {
switch (event.eventType) {
case xml.ParserEventType.StartElement:
last_element = event.elementName;
last_attrs = event.attributes;
break;
case xml.ParserEventType.Text:
last_data = event.data;
break;
}
});
});
it("handles whitespace around attribute =", () => {
let attributes = null;
let element = null;
parser.parse("<TextField text = \n 'hello' />");
assert.equal('TextField', last_element);
assert.equal('hello', last_attrs['text']);
});
it("resolves entities", () => {
parser.parse("<element>&lt;&gt;&quot;&amp;&apos;</element>");
assert.equal("<>\"&'", last_data);
});
});

View File

@@ -8,7 +8,8 @@
},
"files": [
"**/*.*",
"**/*"
"**/*",
"!node-tests/"
],
"license": "Apache-2.0",
"devDependencies": {
@@ -20,6 +21,10 @@
"grunt-shell": "1.1.2",
"grunt-ts": "4.0.1",
"grunt-tslint": "0.4.2",
"mocha": "2.2.5",
"grunt-simple-mocha": "0.4.0",
"grunt-env": "0.4.4",
"chai": "2.3.0",
"typescript": "1.5.0-beta"
}
}

View File

@@ -1,2 +1,2 @@
{ "name" : "xml",
"main" : "xml.js" }
{ "name" : "xml",
"main" : "xml.js" }

4
xml/xml.d.ts vendored
View File

@@ -86,7 +86,7 @@ declare module "xml" {
* @param onError The callback to execute when a parser error occurs. The 'error' parameter contains the error.
* @param processNamespaces Specifies whether namespaces should be processed.
*/
constructor(onEvent: (event: ParserEvent) => void, onError?: (error: Error) => void, processNamespaces?: boolean);
constructor(onEvent: (event: ParserEvent) => void, onError?: (error: Error) => void, processNamespaces?: boolean, angularSyntax?: boolean);
/**
* Parses the supplied xml string.
@@ -94,4 +94,4 @@ declare module "xml" {
*/
parse(xmlString: string): void;
}
}
}

View File

@@ -148,6 +148,14 @@ export class XmlParser implements definition.XmlParser {
}
}
public get angularSyntax() : boolean {
return this._parser.angularSyntax;
}
public set angularSyntax(value: boolean) {
this._parser.angularSyntax = value;
}
public parse(xmlString: string): void {
if (this._processNamespaces) {
this._namespaceStack = [];
@@ -242,4 +250,4 @@ export class XmlParser implements definition.XmlParser {
return s;
}
}
}