1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 | (function () {
|
28 | 'use strict';
|
29 |
|
30 | var Name, Syntax, common;
|
31 |
|
32 | Name = 'annotate-directive';
|
33 | common = require('./common');
|
34 | Syntax = common.Syntax;
|
35 |
|
36 | function isDirective(stmt) {
|
37 | var expr;
|
38 | if (stmt.type === Syntax.ExpressionStatement) {
|
39 | expr = stmt.expression;
|
40 | if (expr.type === Syntax.Literal && typeof expr.value === 'string') {
|
41 | return true;
|
42 | }
|
43 | }
|
44 | return false;
|
45 | }
|
46 |
|
47 | function escapeAllowedCharacter(ch, next) {
|
48 | var code = ch.charCodeAt(0), hex = code.toString(16), result = '\\';
|
49 |
|
50 | switch (ch) {
|
51 | case '\b':
|
52 | result += 'b';
|
53 | break;
|
54 | case '\f':
|
55 | result += 'f';
|
56 | break;
|
57 | case '\t':
|
58 | result += 't';
|
59 | break;
|
60 | default:
|
61 | if (code > 0xff) {
|
62 | result += 'u' + '0000'.slice(hex.length) + hex;
|
63 | } else if (ch === '\u0000' && '0123456789'.indexOf(next) < 0) {
|
64 | result += '0';
|
65 | } else if (ch === '\v') {
|
66 | result += 'v';
|
67 | } else {
|
68 | result += 'x' + '00'.slice(hex.length) + hex;
|
69 | }
|
70 | break;
|
71 | }
|
72 |
|
73 | return result;
|
74 | }
|
75 |
|
76 | function escapeDisallowedCharacter(ch) {
|
77 | var result = '\\';
|
78 | switch (ch) {
|
79 | case '\\':
|
80 | result += '\\';
|
81 | break;
|
82 | case '\n':
|
83 | result += 'n';
|
84 | break;
|
85 | case '\r':
|
86 | result += 'r';
|
87 | break;
|
88 | case '\u2028':
|
89 | result += 'u2028';
|
90 | break;
|
91 | case '\u2029':
|
92 | result += 'u2029';
|
93 | break;
|
94 | default:
|
95 | throw new Error('Incorrectly classified character');
|
96 | }
|
97 |
|
98 | return result;
|
99 | }
|
100 |
|
101 | function escapeString(str) {
|
102 | var result = '', i, len, ch;
|
103 |
|
104 | if (typeof str[0] === 'undefined') {
|
105 | str = common.stringToArray(str);
|
106 | }
|
107 |
|
108 | for (i = 0, len = str.length; i < len; i += 1) {
|
109 | ch = str[i];
|
110 | if (ch === '\'') {
|
111 | result += '\\\'';
|
112 | continue;
|
113 | } else if ('\\\n\r\u2028\u2029'.indexOf(ch) >= 0) {
|
114 | result += escapeDisallowedCharacter(ch);
|
115 | continue;
|
116 | } else if (!(ch >= ' ' && ch <= '~')) {
|
117 | result += escapeAllowedCharacter(ch, str[i + 1]);
|
118 | continue;
|
119 | }
|
120 | result += ch;
|
121 | }
|
122 |
|
123 | return result;
|
124 | }
|
125 |
|
126 | function annotateDirective(tree, options) {
|
127 | var result;
|
128 |
|
129 | result = options.get('destructive', { pathName: Name }) ? tree : common.deepCopy(tree);
|
130 |
|
131 | common.traverse(result, {
|
132 | enter: function enter(node, parent) {
|
133 | var stmt, i, iz;
|
134 |
|
135 | if (!(node.type === Syntax.Program ||
|
136 | (node.type === Syntax.BlockStatement && (parent.type === Syntax.FunctionExpression || parent.type === Syntax.FunctionDeclaration)))) {
|
137 | return;
|
138 | }
|
139 |
|
140 | for (i = 0, iz = node.body.length; i < iz; ++i) {
|
141 | stmt = node.body[i];
|
142 | if (isDirective(stmt)) {
|
143 | stmt.type = Syntax.DirectiveStatement;
|
144 | if (stmt.expression.raw) {
|
145 | stmt.directive = stmt.expression.raw.substring(1, stmt.expression.raw.length - 1);
|
146 | stmt.value = stmt.expression.value;
|
147 | stmt.raw = stmt.expression.raw;
|
148 | } else {
|
149 | stmt.directive = escapeString(stmt.expression.value);
|
150 | stmt.value = stmt.expression.value;
|
151 | stmt.raw = '\'' + stmt.directive + '\'';
|
152 | }
|
153 | delete stmt.expression;
|
154 | } else {
|
155 | return;
|
156 | }
|
157 | }
|
158 | }
|
159 | });
|
160 |
|
161 | return result;
|
162 | }
|
163 |
|
164 | annotateDirective.passName = Name;
|
165 | module.exports = annotateDirective;
|
166 | }());
|
167 |
|