@angular-wave/angular.ts 0.0.46 → 0.0.48
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/angular-ts.esm.js +2 -2
- package/dist/angular-ts.umd.js +2 -2
- package/package.json +1 -1
- package/src/angular.spec.js +1 -2
- package/src/animations/animate-css-driver.js +1 -1
- package/src/animations/animate-queue.js +3 -4
- package/src/animations/animation.js +1 -1
- package/src/animations/raf-scheduler.js +0 -1
- package/src/animations/shared.js +1 -1
- package/src/core/animate/animate.js +0 -1
- package/src/core/compile/compile.spec.js +1 -1
- package/src/core/filter/filter.js +2 -2
- package/src/core/location/location.js +1 -1
- package/src/core/location/location.spec.js +1 -1
- package/src/core/parser/ast-type.js +22 -0
- package/src/core/parser/ast.js +422 -0
- package/src/core/parser/compiler.js +561 -0
- package/src/core/parser/interpreter.js +422 -0
- package/src/core/parser/lexer.js +257 -0
- package/src/core/parser/parse.js +9 -1930
- package/src/core/parser/parse.spec.js +2 -2
- package/src/core/parser/parser.js +39 -0
- package/src/core/parser/shared.js +228 -0
- package/src/core/q/q.spec.js +0 -1
- package/src/core/sce/sce.js +3 -6
- package/src/core/scope/scope.js +19 -11
- package/src/core/task-tracker-factory.js +0 -1
- package/src/directive/attrs/attrs.js +4 -185
- package/src/directive/attrs/attrs.md +224 -0
- package/src/directive/class/class.js +0 -2
- package/src/directive/form/form.js +0 -3
- package/src/directive/include/include.js +1 -1
- package/src/directive/include/include.spec.js +0 -1
- package/src/directive/input/input.js +1 -2
- package/src/directive/model/model.js +1 -3
- package/src/directive/model/model.spec.js +0 -1
- package/src/directive/repeat/repeat.spec.js +0 -2
- package/src/exts/aria/aria.js +0 -1
- package/src/filters/filter.spec.js +0 -1
- package/src/injector.js +1 -1
- package/src/injector.spec.js +0 -5
- package/src/loader.js +0 -5
- package/src/services/cookie-reader.js +0 -1
- package/src/services/http/http.spec.js +0 -2
- package/src/shared/jqlite/jqlite.js +219 -140
- package/src/shared/utils.js +18 -7
- package/src/types.js +10 -0
- package/types/core/parser/ast-type.d.ts +20 -0
- package/types/core/parser/ast.d.ts +78 -0
- package/types/core/parser/compiler.d.ts +49 -0
- package/types/core/parser/interpreter.d.ts +57 -0
- package/types/core/parser/parse.d.ts +79 -0
- package/types/core/parser/parser.d.ts +22 -0
- package/types/core/parser/shared.d.ts +29 -0
- package/types/core/scope/scope.d.ts +9 -2
- package/types/directive/attrs/attrs.d.ts +0 -174
- package/types/shared/jqlite/jqlite.d.ts +33 -4
- package/types/shared/utils.d.ts +18 -5
- package/types/types.d.ts +1 -0
- package/types-back/index.d.ts +0 -12
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { AST
|
|
1
|
+
import { AST } from "./ast";
|
|
2
|
+
import { Lexer } from "./lexer";
|
|
2
3
|
import {
|
|
3
4
|
forEach,
|
|
4
5
|
isFunction,
|
|
@@ -2366,7 +2367,6 @@ describe("parser", () => {
|
|
|
2366
2367
|
|
|
2367
2368
|
it("should evaluate negation", () => {
|
|
2368
2369
|
expect(scope.$eval("!false || true")).toEqual(!false || true);
|
|
2369
|
-
// eslint-disable-next-line eqeqeq
|
|
2370
2370
|
expect(scope.$eval("!11 == 10")).toEqual(!11 == 10);
|
|
2371
2371
|
expect(scope.$eval("12/6/2")).toEqual(12 / 6 / 2);
|
|
2372
2372
|
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { AST } from "./ast";
|
|
2
|
+
import { isLiteral, isConstant } from "./shared";
|
|
3
|
+
import { ASTInterpreter } from "./interpreter";
|
|
4
|
+
import { ASTCompiler } from "./compiler";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @constructor
|
|
8
|
+
*/
|
|
9
|
+
export class Parser {
|
|
10
|
+
constructor(lexer, $filter, options) {
|
|
11
|
+
this.ast = new AST(lexer, options);
|
|
12
|
+
this.astCompiler = options.csp
|
|
13
|
+
? new ASTInterpreter($filter)
|
|
14
|
+
: new ASTCompiler($filter);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
parse(text) {
|
|
18
|
+
const { ast, oneTime } = this.getAst(text);
|
|
19
|
+
const fn = this.astCompiler.compile(ast);
|
|
20
|
+
fn.literal = isLiteral(ast);
|
|
21
|
+
fn.constant = isConstant(ast);
|
|
22
|
+
fn.oneTime = oneTime;
|
|
23
|
+
return fn;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
getAst(exp) {
|
|
27
|
+
let oneTime = false;
|
|
28
|
+
exp = exp.trim();
|
|
29
|
+
|
|
30
|
+
if (exp.startsWith("::")) {
|
|
31
|
+
oneTime = true;
|
|
32
|
+
exp = exp.substring(2);
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
ast: this.ast.ast(exp),
|
|
36
|
+
oneTime,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { ASTType } from "./ast-type";
|
|
2
|
+
import { forEach, isFunction } from "../../shared/utils";
|
|
3
|
+
|
|
4
|
+
const objectValueOf = {}.constructor.prototype.valueOf;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Converts parameter to strings property name for use as keys in an object.
|
|
8
|
+
* Any non-string object, including a number, is typecasted into a string via the toString method.
|
|
9
|
+
* {@link https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Property_accessors#Property_names}
|
|
10
|
+
*
|
|
11
|
+
* @param {!any} name
|
|
12
|
+
* @returns {string}
|
|
13
|
+
*/
|
|
14
|
+
export function getStringValue(name) {
|
|
15
|
+
return `${name}`;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/// //////////////////////////////////////
|
|
19
|
+
|
|
20
|
+
export function ifDefined(v, d) {
|
|
21
|
+
return typeof v !== "undefined" ? v : d;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function plusFn(l, r) {
|
|
25
|
+
if (typeof l === "undefined") return r;
|
|
26
|
+
if (typeof r === "undefined") return l;
|
|
27
|
+
return l + r;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function isStateless($filter, filterName) {
|
|
31
|
+
const fn = $filter(filterName);
|
|
32
|
+
return !fn.$stateful;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export const PURITY_ABSOLUTE = 1;
|
|
36
|
+
export const PURITY_RELATIVE = 2;
|
|
37
|
+
|
|
38
|
+
// Detect nodes which could depend on non-shallow state of objects
|
|
39
|
+
export function isPure(node, parentIsPure) {
|
|
40
|
+
switch (node.type) {
|
|
41
|
+
// Computed members might invoke a stateful toString()
|
|
42
|
+
case ASTType.MemberExpression:
|
|
43
|
+
if (node.computed) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
break;
|
|
47
|
+
|
|
48
|
+
// Unary always convert to primative
|
|
49
|
+
case ASTType.UnaryExpression:
|
|
50
|
+
return PURITY_ABSOLUTE;
|
|
51
|
+
|
|
52
|
+
// The binary + operator can invoke a stateful toString().
|
|
53
|
+
case ASTType.BinaryExpression:
|
|
54
|
+
return node.operator !== "+" ? PURITY_ABSOLUTE : false;
|
|
55
|
+
|
|
56
|
+
// Functions / filters probably read state from within objects
|
|
57
|
+
case ASTType.CallExpression:
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return undefined === parentIsPure ? PURITY_RELATIVE : parentIsPure;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function findConstantAndWatchExpressions(ast, $filter, parentIsPure) {
|
|
65
|
+
let allConstants;
|
|
66
|
+
let argsToWatch;
|
|
67
|
+
let isStatelessFilter;
|
|
68
|
+
|
|
69
|
+
const astIsPure = (ast.isPure = isPure(ast, parentIsPure));
|
|
70
|
+
|
|
71
|
+
switch (ast.type) {
|
|
72
|
+
case ASTType.Program:
|
|
73
|
+
allConstants = true;
|
|
74
|
+
/** @type {[any]} */ (ast.body).forEach((expr) => {
|
|
75
|
+
findConstantAndWatchExpressions(expr.expression, $filter, astIsPure);
|
|
76
|
+
allConstants = allConstants && expr.expression.constant;
|
|
77
|
+
});
|
|
78
|
+
ast.constant = allConstants;
|
|
79
|
+
break;
|
|
80
|
+
case ASTType.Literal:
|
|
81
|
+
ast.constant = true;
|
|
82
|
+
ast.toWatch = [];
|
|
83
|
+
break;
|
|
84
|
+
case ASTType.UnaryExpression:
|
|
85
|
+
findConstantAndWatchExpressions(ast.argument, $filter, astIsPure);
|
|
86
|
+
ast.constant = ast.argument.constant;
|
|
87
|
+
ast.toWatch = ast.argument.toWatch;
|
|
88
|
+
break;
|
|
89
|
+
case ASTType.BinaryExpression:
|
|
90
|
+
findConstantAndWatchExpressions(ast.left, $filter, astIsPure);
|
|
91
|
+
findConstantAndWatchExpressions(ast.right, $filter, astIsPure);
|
|
92
|
+
ast.constant = ast.left.constant && ast.right.constant;
|
|
93
|
+
ast.toWatch = ast.left.toWatch.concat(ast.right.toWatch);
|
|
94
|
+
break;
|
|
95
|
+
case ASTType.LogicalExpression:
|
|
96
|
+
findConstantAndWatchExpressions(ast.left, $filter, astIsPure);
|
|
97
|
+
findConstantAndWatchExpressions(ast.right, $filter, astIsPure);
|
|
98
|
+
ast.constant = ast.left.constant && ast.right.constant;
|
|
99
|
+
ast.toWatch = ast.constant ? [] : [ast];
|
|
100
|
+
break;
|
|
101
|
+
case ASTType.ConditionalExpression:
|
|
102
|
+
findConstantAndWatchExpressions(ast.test, $filter, astIsPure);
|
|
103
|
+
findConstantAndWatchExpressions(ast.alternate, $filter, astIsPure);
|
|
104
|
+
findConstantAndWatchExpressions(ast.consequent, $filter, astIsPure);
|
|
105
|
+
ast.constant =
|
|
106
|
+
ast.test.constant && ast.alternate.constant && ast.consequent.constant;
|
|
107
|
+
ast.toWatch = ast.constant ? [] : [ast];
|
|
108
|
+
break;
|
|
109
|
+
case ASTType.Identifier:
|
|
110
|
+
ast.constant = false;
|
|
111
|
+
ast.toWatch = [ast];
|
|
112
|
+
break;
|
|
113
|
+
case ASTType.MemberExpression:
|
|
114
|
+
findConstantAndWatchExpressions(ast.object, $filter, astIsPure);
|
|
115
|
+
if (ast.computed) {
|
|
116
|
+
findConstantAndWatchExpressions(ast.property, $filter, astIsPure);
|
|
117
|
+
}
|
|
118
|
+
ast.constant =
|
|
119
|
+
ast.object.constant && (!ast.computed || ast.property.constant);
|
|
120
|
+
ast.toWatch = ast.constant ? [] : [ast];
|
|
121
|
+
break;
|
|
122
|
+
case ASTType.CallExpression:
|
|
123
|
+
isStatelessFilter = ast.filter
|
|
124
|
+
? isStateless($filter, ast.callee.name)
|
|
125
|
+
: false;
|
|
126
|
+
allConstants = isStatelessFilter;
|
|
127
|
+
argsToWatch = [];
|
|
128
|
+
forEach(ast.arguments, (expr) => {
|
|
129
|
+
findConstantAndWatchExpressions(expr, $filter, astIsPure);
|
|
130
|
+
allConstants = allConstants && expr.constant;
|
|
131
|
+
argsToWatch.push.apply(argsToWatch, expr.toWatch);
|
|
132
|
+
});
|
|
133
|
+
ast.constant = allConstants;
|
|
134
|
+
ast.toWatch = isStatelessFilter ? argsToWatch : [ast];
|
|
135
|
+
break;
|
|
136
|
+
case ASTType.AssignmentExpression:
|
|
137
|
+
findConstantAndWatchExpressions(ast.left, $filter, astIsPure);
|
|
138
|
+
findConstantAndWatchExpressions(ast.right, $filter, astIsPure);
|
|
139
|
+
ast.constant = ast.left.constant && ast.right.constant;
|
|
140
|
+
ast.toWatch = [ast];
|
|
141
|
+
break;
|
|
142
|
+
case ASTType.ArrayExpression:
|
|
143
|
+
allConstants = true;
|
|
144
|
+
argsToWatch = [];
|
|
145
|
+
forEach(ast.elements, (expr) => {
|
|
146
|
+
findConstantAndWatchExpressions(expr, $filter, astIsPure);
|
|
147
|
+
allConstants = allConstants && expr.constant;
|
|
148
|
+
argsToWatch.push.apply(argsToWatch, expr.toWatch);
|
|
149
|
+
});
|
|
150
|
+
ast.constant = allConstants;
|
|
151
|
+
ast.toWatch = argsToWatch;
|
|
152
|
+
break;
|
|
153
|
+
case ASTType.ObjectExpression:
|
|
154
|
+
allConstants = true;
|
|
155
|
+
argsToWatch = [];
|
|
156
|
+
forEach(ast.properties, (property) => {
|
|
157
|
+
findConstantAndWatchExpressions(property.value, $filter, astIsPure);
|
|
158
|
+
allConstants = allConstants && property.value.constant;
|
|
159
|
+
argsToWatch.push.apply(argsToWatch, property.value.toWatch);
|
|
160
|
+
if (property.computed) {
|
|
161
|
+
// `{[key]: value}` implicitly does `key.toString()` which may be non-pure
|
|
162
|
+
findConstantAndWatchExpressions(
|
|
163
|
+
property.key,
|
|
164
|
+
$filter,
|
|
165
|
+
/* parentIsPure= */ false,
|
|
166
|
+
);
|
|
167
|
+
allConstants = allConstants && property.key.constant;
|
|
168
|
+
argsToWatch.push.apply(argsToWatch, property.key.toWatch);
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
ast.constant = allConstants;
|
|
172
|
+
ast.toWatch = argsToWatch;
|
|
173
|
+
break;
|
|
174
|
+
case ASTType.ThisExpression:
|
|
175
|
+
ast.constant = false;
|
|
176
|
+
ast.toWatch = [];
|
|
177
|
+
break;
|
|
178
|
+
case ASTType.LocalsExpression:
|
|
179
|
+
ast.constant = false;
|
|
180
|
+
ast.toWatch = [];
|
|
181
|
+
break;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export function getInputs(body) {
|
|
186
|
+
if (body.length !== 1) return;
|
|
187
|
+
const lastExpression = body[0].expression;
|
|
188
|
+
const candidate = lastExpression.toWatch;
|
|
189
|
+
if (candidate.length !== 1) return candidate;
|
|
190
|
+
return candidate[0] !== lastExpression ? candidate : undefined;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export function isAssignable(ast) {
|
|
194
|
+
return (
|
|
195
|
+
ast.type === ASTType.Identifier || ast.type === ASTType.MemberExpression
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export function assignableAST(ast) {
|
|
200
|
+
if (ast.body.length === 1 && isAssignable(ast.body[0].expression)) {
|
|
201
|
+
return {
|
|
202
|
+
type: ASTType.AssignmentExpression,
|
|
203
|
+
left: ast.body[0].expression,
|
|
204
|
+
right: { type: ASTType.NGValueParameter },
|
|
205
|
+
operator: "=",
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export function isLiteral(ast) {
|
|
211
|
+
return (
|
|
212
|
+
ast.body.length === 0 ||
|
|
213
|
+
(ast.body.length === 1 &&
|
|
214
|
+
(ast.body[0].expression.type === ASTType.Literal ||
|
|
215
|
+
ast.body[0].expression.type === ASTType.ArrayExpression ||
|
|
216
|
+
ast.body[0].expression.type === ASTType.ObjectExpression))
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
export function isConstant(ast) {
|
|
221
|
+
return ast.constant;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
export function getValueOf(value) {
|
|
225
|
+
return isFunction(value.valueOf)
|
|
226
|
+
? value.valueOf()
|
|
227
|
+
: objectValueOf.call(value);
|
|
228
|
+
}
|
package/src/core/q/q.spec.js
CHANGED
package/src/core/sce/sce.js
CHANGED
|
@@ -46,12 +46,9 @@ export const SCE_CONTEXTS = {
|
|
|
46
46
|
// http://docs.closure-library.googlecode.com/git/local_closure_goog_string_string.js.source.html#line1021
|
|
47
47
|
// Prereq: s is a string.
|
|
48
48
|
export function escapeForRegexp(s) {
|
|
49
|
-
return
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
// eslint-disable-next-line no-control-regex
|
|
53
|
-
.replace(/\x08/g, "\\x08")
|
|
54
|
-
);
|
|
49
|
+
return s
|
|
50
|
+
.replace(/([-()[\]{}+?*.$^|,:#<!\\])/g, "\\$1")
|
|
51
|
+
.replace(/\x08/g, "\\x08");
|
|
55
52
|
}
|
|
56
53
|
|
|
57
54
|
export function adjustMatcher(matcher) {
|
package/src/core/scope/scope.js
CHANGED
|
@@ -45,6 +45,10 @@ const $rootScopeMinErr = minErr("$rootScope");
|
|
|
45
45
|
/** @type {AsyncQueueTask[]} */
|
|
46
46
|
export const $$asyncQueue = [];
|
|
47
47
|
export const $$postDigestQueue = [];
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* @type {Function[]}
|
|
51
|
+
*/
|
|
48
52
|
export const $$applyAsyncQueue = [];
|
|
49
53
|
let postDigestQueuePosition = 0;
|
|
50
54
|
let lastDirtyWatch = null;
|
|
@@ -84,9 +88,9 @@ export class $RootScopeProvider {
|
|
|
84
88
|
"$parse",
|
|
85
89
|
"$browser",
|
|
86
90
|
/**
|
|
91
|
+
* @param {import('../exception-handler').ErrorHandler} exceptionHandler
|
|
87
92
|
* @param {angular.IParseService} parse
|
|
88
|
-
* @param {import('
|
|
89
|
-
* @param {angular.IExceptionHandlerService} exceptionHandler
|
|
93
|
+
* @param {import('../../services/browser').Browser} browser
|
|
90
94
|
* @returns {Scope} root scope
|
|
91
95
|
*/
|
|
92
96
|
function (exceptionHandler, parse, browser) {
|
|
@@ -606,7 +610,6 @@ export class Scope {
|
|
|
606
610
|
oldItem = oldValue[i];
|
|
607
611
|
newItem = newValue[i];
|
|
608
612
|
|
|
609
|
-
// eslint-disable-next-line no-self-compare
|
|
610
613
|
bothNaN = oldItem !== oldItem && newItem !== newItem;
|
|
611
614
|
if (!bothNaN && oldItem !== newItem) {
|
|
612
615
|
changeDetected++;
|
|
@@ -629,7 +632,6 @@ export class Scope {
|
|
|
629
632
|
oldItem = oldValue[key];
|
|
630
633
|
|
|
631
634
|
if (key in oldValue) {
|
|
632
|
-
// eslint-disable-next-line no-self-compare
|
|
633
635
|
bothNaN = oldItem !== oldItem && newItem !== newItem;
|
|
634
636
|
if (!bothNaN && oldItem !== newItem) {
|
|
635
637
|
changeDetected++;
|
|
@@ -1238,13 +1240,19 @@ export class Scope {
|
|
|
1238
1240
|
} catch (e) {
|
|
1239
1241
|
$exceptionHandler(e);
|
|
1240
1242
|
} finally {
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1243
|
+
this.retry();
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1247
|
+
/**
|
|
1248
|
+
* @private
|
|
1249
|
+
*/
|
|
1250
|
+
retry() {
|
|
1251
|
+
try {
|
|
1252
|
+
this.$root.$digest();
|
|
1253
|
+
} catch (e) {
|
|
1254
|
+
$exceptionHandler(e);
|
|
1255
|
+
throw e;
|
|
1248
1256
|
}
|
|
1249
1257
|
}
|
|
1250
1258
|
|
|
@@ -1,194 +1,13 @@
|
|
|
1
1
|
import { BOOLEAN_ATTR } from "../../shared/jqlite/jqlite";
|
|
2
|
-
import {
|
|
2
|
+
import { directiveNormalize } from "../../shared/utils";
|
|
3
3
|
import { ALIASED_ATTR } from "../../shared/constants";
|
|
4
4
|
|
|
5
|
-
/**
|
|
6
|
-
* @ngdoc directive
|
|
7
|
-
* @name ngHref
|
|
8
|
-
* @restrict A
|
|
9
|
-
* @priority 99
|
|
10
|
-
*
|
|
11
|
-
* @description
|
|
12
|
-
* Using AngularJS markup like `{{hash}}` in an href attribute will
|
|
13
|
-
* make the link go to the wrong URL if the user clicks it before
|
|
14
|
-
* AngularJS has a chance to replace the `{{hash}}` markup with its
|
|
15
|
-
* value. Until AngularJS replaces the markup the link will be broken
|
|
16
|
-
* and will most likely return a 404 error. The `ngHref` directive
|
|
17
|
-
* solves this problem.
|
|
18
|
-
*
|
|
19
|
-
* The wrong way to write it:
|
|
20
|
-
* ```html
|
|
21
|
-
* <a href="http://www.gravatar.com/avatar/{{hash}}">link1</a>
|
|
22
|
-
* ```
|
|
23
|
-
*
|
|
24
|
-
* The correct way to write it:
|
|
25
|
-
* ```html
|
|
26
|
-
* <a ng-href="http://www.gravatar.com/avatar/{{hash}}">link1</a>
|
|
27
|
-
* ```
|
|
28
|
-
*
|
|
29
|
-
* @element A
|
|
30
|
-
* @param {template} ngHref any string which can contain `{{}}` markup.
|
|
31
|
-
*
|
|
32
|
-
*/
|
|
33
|
-
|
|
34
5
|
export const REGEX_STRING_REGEXP = /^\/(.+)\/([a-z]*)$/;
|
|
35
|
-
/**
|
|
36
|
-
* @ngdoc directive
|
|
37
|
-
* @name ngSrc
|
|
38
|
-
* @restrict A
|
|
39
|
-
* @priority 99
|
|
40
|
-
*
|
|
41
|
-
* @description
|
|
42
|
-
* Using AngularJS markup like `{{hash}}` in a `src` attribute doesn't
|
|
43
|
-
* work right: The browser will fetch from the URL with the literal
|
|
44
|
-
* text `{{hash}}` until AngularJS replaces the expression inside
|
|
45
|
-
* `{{hash}}`. The `ngSrc` directive solves this problem.
|
|
46
|
-
*
|
|
47
|
-
* The buggy way to write it:
|
|
48
|
-
* ```html
|
|
49
|
-
* <img src="http://www.gravatar.com/avatar/{{hash}}" alt="Description"/>
|
|
50
|
-
* ```
|
|
51
|
-
*
|
|
52
|
-
* The correct way to write it:
|
|
53
|
-
* ```html
|
|
54
|
-
* <img ng-src="http://www.gravatar.com/avatar/{{hash}}" alt="Description" />
|
|
55
|
-
* ```
|
|
56
|
-
*
|
|
57
|
-
* @element IMG
|
|
58
|
-
* @param {template} ngSrc any string which can contain `{{}}` markup.
|
|
59
|
-
*/
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* @ngdoc directive
|
|
63
|
-
* @name ngSrcset
|
|
64
|
-
* @restrict A
|
|
65
|
-
* @priority 99
|
|
66
|
-
*
|
|
67
|
-
* @description
|
|
68
|
-
* Using AngularJS markup like `{{hash}}` in a `srcset` attribute doesn't
|
|
69
|
-
* work right: The browser will fetch from the URL with the literal
|
|
70
|
-
* text `{{hash}}` until AngularJS replaces the expression inside
|
|
71
|
-
* `{{hash}}`. The `ngSrcset` directive solves this problem.
|
|
72
|
-
*
|
|
73
|
-
* The buggy way to write it:
|
|
74
|
-
* ```html
|
|
75
|
-
* <img srcset="http://www.gravatar.com/avatar/{{hash}} 2x" alt="Description"/>
|
|
76
|
-
* ```
|
|
77
|
-
*
|
|
78
|
-
* The correct way to write it:
|
|
79
|
-
* ```html
|
|
80
|
-
* <img ng-srcset="http://www.gravatar.com/avatar/{{hash}} 2x" alt="Description" />
|
|
81
|
-
* ```
|
|
82
|
-
*
|
|
83
|
-
* @element IMG
|
|
84
|
-
* @param {template} ngSrcset any string which can contain `{{}}` markup.
|
|
85
|
-
*/
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* @ngdoc directive
|
|
89
|
-
* @name ngDisabled
|
|
90
|
-
* @restrict A
|
|
91
|
-
* @priority 100
|
|
92
|
-
*
|
|
93
|
-
* @description
|
|
94
|
-
*
|
|
95
|
-
* This directive sets the `disabled` attribute on the element (typically a form control,
|
|
96
|
-
* e.g. `input`, `button`, `select` etc.) if the
|
|
97
|
-
* {@link guide/expression expression} inside `ngDisabled` evaluates to truthy.
|
|
98
|
-
*
|
|
99
|
-
* A special directive is necessary because we cannot use interpolation inside the `disabled`
|
|
100
|
-
* attribute. See the {@link guide/interpolation interpolation guide} for more info.
|
|
101
|
-
*
|
|
102
|
-
* @param {string} ngDisabled If the {@link guide/expression expression} is truthy,
|
|
103
|
-
* then the `disabled` attribute will be set on the element
|
|
104
|
-
*/
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* @ngdoc directive
|
|
108
|
-
* @name ngChecked
|
|
109
|
-
* @restrict A
|
|
110
|
-
* @priority 100
|
|
111
|
-
*
|
|
112
|
-
* @description
|
|
113
|
-
* Sets the `checked` attribute on the element, if the expression inside `ngChecked` is truthy.
|
|
114
|
-
*
|
|
115
|
-
* Note that this directive should not be used together with {@link ngModel `ngModel`},
|
|
116
|
-
* as this can lead to unexpected behavior.
|
|
117
|
-
*
|
|
118
|
-
* A special directive is necessary because we cannot use interpolation inside the `checked`
|
|
119
|
-
* attribute. See the {@link guide/interpolation interpolation guide} for more info.
|
|
120
|
-
*
|
|
121
|
-
* @element INPUT
|
|
122
|
-
* @param {string} ngChecked If the {@link guide/expression expression} is truthy,
|
|
123
|
-
* then the `checked` attribute will be set on the element
|
|
124
|
-
*/
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
*
|
|
128
|
-
* @description
|
|
129
|
-
*
|
|
130
|
-
* Sets the `readonly` attribute on the element, if the expression inside `ngReadonly` is truthy.
|
|
131
|
-
* Note that `readonly` applies only to `input` elements with specific types. [See the input docs on
|
|
132
|
-
* MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-readonly) for more information.
|
|
133
|
-
*
|
|
134
|
-
* A special directive is necessary because we cannot use interpolation inside the `readonly`
|
|
135
|
-
* attribute. See the {@link guide/interpolation interpolation guide} for more info.
|
|
136
|
-
* @element INPUT
|
|
137
|
-
* @param {string} ngReadonly If the {@link guide/expression expression} is truthy,
|
|
138
|
-
* then special attribute "readonly" will be set on the element
|
|
139
|
-
*/
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* @ngdoc directive
|
|
143
|
-
* @name ngSelected
|
|
144
|
-
* @restrict A
|
|
145
|
-
* @priority 100
|
|
146
|
-
*
|
|
147
|
-
* @description
|
|
148
|
-
*
|
|
149
|
-
* Sets the `selected` attribute on the element, if the expression inside `ngSelected` is truthy.
|
|
150
|
-
*
|
|
151
|
-
* A special directive is necessary because we cannot use interpolation inside the `selected`
|
|
152
|
-
* attribute. See the {@link guide/interpolation interpolation guide} for more info.
|
|
153
|
-
*
|
|
154
|
-
* <div class="alert alert-warning">
|
|
155
|
-
* **Note:** `ngSelected` does not interact with the `select` and `ngModel` directives, it only
|
|
156
|
-
* sets the `selected` attribute on the element. If you are using `ngModel` on the select, you
|
|
157
|
-
* should not use `ngSelected` on the options, as `ngModel` will set the select value and
|
|
158
|
-
* selected options.
|
|
159
|
-
* </div>
|
|
160
|
-
* @element OPTION
|
|
161
|
-
* @param {string} ngSelected If the {@link guide/expression expression} is truthy,
|
|
162
|
-
* then special attribute "selected" will be set on the element
|
|
163
|
-
*/
|
|
164
|
-
|
|
165
|
-
/**
|
|
166
|
-
* @ngdoc directive
|
|
167
|
-
* @name ngOpen
|
|
168
|
-
* @restrict A
|
|
169
|
-
* @priority 100
|
|
170
|
-
*
|
|
171
|
-
* @description
|
|
172
|
-
*
|
|
173
|
-
* Sets the `open` attribute on the element, if the expression inside `ngOpen` is truthy.
|
|
174
|
-
*
|
|
175
|
-
* A special directive is necessary because we cannot use interpolation inside the `open`
|
|
176
|
-
* attribute. See the {@link guide/interpolation interpolation guide} for more info.
|
|
177
|
-
*
|
|
178
|
-
* ## A note about browser compatibility
|
|
179
|
-
*
|
|
180
|
-
* Internet Explorer and Edge do not support the `details` element, it is
|
|
181
|
-
* recommended to use {@link ng.ngShow} and {@link ng.ngHide} instead.
|
|
182
|
-
*
|
|
183
|
-
* @element DETAILS
|
|
184
|
-
* @param {string} ngOpen If the {@link guide/expression expression} is truthy,
|
|
185
|
-
* then special attribute "open" will be set on the element
|
|
186
|
-
*/
|
|
187
6
|
|
|
188
7
|
export const ngAttributeAliasDirectives = {};
|
|
189
8
|
|
|
190
9
|
// boolean attrs are evaluated
|
|
191
|
-
forEach(
|
|
10
|
+
Object.entries(BOOLEAN_ATTR).forEach(([attrName, propName]) => {
|
|
192
11
|
// binding to multiple is not supported
|
|
193
12
|
if (propName === "multiple") return;
|
|
194
13
|
|
|
@@ -220,7 +39,7 @@ forEach(BOOLEAN_ATTR, (propName, attrName) => {
|
|
|
220
39
|
});
|
|
221
40
|
|
|
222
41
|
// aliased input attrs are evaluated
|
|
223
|
-
|
|
42
|
+
Object.entries(ALIASED_ATTR).forEach(([ngAttr]) => {
|
|
224
43
|
ngAttributeAliasDirectives[ngAttr] = function () {
|
|
225
44
|
return {
|
|
226
45
|
priority: 100,
|
|
@@ -244,7 +63,7 @@ forEach(ALIASED_ATTR, (htmlAttr, ngAttr) => {
|
|
|
244
63
|
});
|
|
245
64
|
|
|
246
65
|
// ng-src, ng-srcset, ng-href are interpolated
|
|
247
|
-
|
|
66
|
+
["src", "srcset", "href"].forEach((attrName) => {
|
|
248
67
|
const normalized = directiveNormalize(`ng-${attrName}`);
|
|
249
68
|
ngAttributeAliasDirectives[normalized] = [
|
|
250
69
|
"$sce",
|