@rhinostone/swig-django 2.9.11 → 2.9.13
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/lib/filters.js +71 -34
- package/lib/index.js +1 -1
- package/package.json +2 -2
package/lib/filters.js
CHANGED
|
@@ -2,6 +2,15 @@ var utils = require('@rhinostone/swig-core/lib/utils'),
|
|
|
2
2
|
dateFormatter = require('@rhinostone/swig-core/lib/dateformatter'),
|
|
3
3
|
iterateFilter = require('@rhinostone/swig-core/lib/filters').iterateFilter;
|
|
4
4
|
|
|
5
|
+
/*!
|
|
6
|
+
* Text of a filter input, as Django's stringfilter gives it: None for null, and for a
|
|
7
|
+
* variable that fails to resolve where Django reads it as None (if, for, firstof).
|
|
8
|
+
* @private
|
|
9
|
+
*/
|
|
10
|
+
function asText(input) {
|
|
11
|
+
return (input === undefined || input === null) ? 'None' : String(input);
|
|
12
|
+
}
|
|
13
|
+
|
|
5
14
|
/**
|
|
6
15
|
* Django filter catalog.
|
|
7
16
|
*
|
|
@@ -18,6 +27,10 @@ var utils = require('@rhinostone/swig-core/lib/utils'),
|
|
|
18
27
|
*
|
|
19
28
|
* Fidelity notes (cross-checked against Django 5.2 `defaultfilters.py`):
|
|
20
29
|
*
|
|
30
|
+
* - **None.** The string filters read None, and a variable that fails to
|
|
31
|
+
* resolve where Django reads it as None (`if`, `for`, `firstof`), as the
|
|
32
|
+
* text None, as Django's `stringfilter` does. `escape`, `escapejs` and
|
|
33
|
+
* `safe` keep the empty string of `{{ x }}`.
|
|
21
34
|
* - **`.safe` vs Django `is_safe`.** Django's `is_safe=True` does NOT bypass
|
|
22
35
|
* autoescape — it only means the filter preserves an already-safe input.
|
|
23
36
|
* Only filters that Django wraps in `mark_safe()` (always returning trusted
|
|
@@ -121,7 +134,10 @@ function urlQuote(value, safe) {
|
|
|
121
134
|
/**
|
|
122
135
|
* Add the argument to the value. Numeric addition is tried first (Django's
|
|
123
136
|
* `int(value) + int(arg)`); on failure it falls back to concatenation
|
|
124
|
-
* (strings and arrays), then to the empty string
|
|
137
|
+
* (strings and arrays), then to the empty string: a string and a number, a
|
|
138
|
+
* list or a mapping with anything but a list, and two mappings give the empty
|
|
139
|
+
* string, since Python cannot add them. A None or missing input or argument
|
|
140
|
+
* gives the empty string too.
|
|
125
141
|
*
|
|
126
142
|
* @example
|
|
127
143
|
* {{ 4|add:2 }}
|
|
@@ -136,19 +152,30 @@ function urlQuote(value, safe) {
|
|
|
136
152
|
* @return {*}
|
|
137
153
|
*/
|
|
138
154
|
exports.add = function (input, arg) {
|
|
155
|
+
if (input === undefined || input === null || arg === undefined || arg === null) {
|
|
156
|
+
return '';
|
|
157
|
+
}
|
|
158
|
+
if (utils.isArray(input) && utils.isArray(arg)) {
|
|
159
|
+
return input.concat(arg);
|
|
160
|
+
}
|
|
161
|
+
// Python raises on a list or a mapping with anything else and on two mappings,
|
|
162
|
+
// and Django then gives an empty string.
|
|
163
|
+
if (typeof input === 'object' || typeof arg === 'object') {
|
|
164
|
+
return '';
|
|
165
|
+
}
|
|
166
|
+
// Python's int() reads a boolean as a number.
|
|
167
|
+
if (typeof input === 'boolean') { input = Number(input); }
|
|
168
|
+
if (typeof arg === 'boolean') { arg = Number(arg); }
|
|
139
169
|
var a = parseInt(input, 10),
|
|
140
170
|
b = parseInt(arg, 10);
|
|
141
171
|
if (!isNaN(a) && !isNaN(b) && String(input).trim() === String(a) && String(arg).trim() === String(b)) {
|
|
142
172
|
return a + b;
|
|
143
173
|
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
}
|
|
147
|
-
try {
|
|
148
|
-
return input + arg;
|
|
149
|
-
} catch (e) {
|
|
174
|
+
// Python's + raises on two different types.
|
|
175
|
+
if (typeof input !== typeof arg || (typeof input !== 'string' && typeof input !== 'number')) {
|
|
150
176
|
return '';
|
|
151
177
|
}
|
|
178
|
+
return input + arg;
|
|
152
179
|
};
|
|
153
180
|
|
|
154
181
|
/**
|
|
@@ -163,7 +190,7 @@ exports.add = function (input, arg) {
|
|
|
163
190
|
* @return {string}
|
|
164
191
|
*/
|
|
165
192
|
exports.addslashes = function (input) {
|
|
166
|
-
return
|
|
193
|
+
return asText(input).replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/'/g, "\\'");
|
|
167
194
|
};
|
|
168
195
|
|
|
169
196
|
/**
|
|
@@ -179,7 +206,7 @@ exports.addslashes = function (input) {
|
|
|
179
206
|
* @return {string}
|
|
180
207
|
*/
|
|
181
208
|
exports.capfirst = function (input) {
|
|
182
|
-
var s =
|
|
209
|
+
var s = asText(input);
|
|
183
210
|
if (!s.length) {
|
|
184
211
|
return s;
|
|
185
212
|
}
|
|
@@ -200,7 +227,7 @@ exports.capfirst = function (input) {
|
|
|
200
227
|
* @return {string}
|
|
201
228
|
*/
|
|
202
229
|
exports.center = function (input, width) {
|
|
203
|
-
var s =
|
|
230
|
+
var s = asText(input),
|
|
204
231
|
w = parseInt(width, 10),
|
|
205
232
|
marg,
|
|
206
233
|
left,
|
|
@@ -226,7 +253,7 @@ exports.center = function (input, width) {
|
|
|
226
253
|
* @return {string}
|
|
227
254
|
*/
|
|
228
255
|
exports.cut = function (input, arg) {
|
|
229
|
-
return
|
|
256
|
+
return asText(input).split(String(arg)).join('');
|
|
230
257
|
};
|
|
231
258
|
|
|
232
259
|
/**
|
|
@@ -246,7 +273,7 @@ exports.cut = function (input, arg) {
|
|
|
246
273
|
* @param {string} [format='F j, Y']
|
|
247
274
|
* @param {number} [offset] Timezone offset in minutes west of GMT.
|
|
248
275
|
* @param {string} [abbr] Output timezone abbreviation.
|
|
249
|
-
* @return {string}
|
|
276
|
+
* @return {string} Formatted date string, or an empty string when the input is undefined, null or no date.
|
|
250
277
|
*/
|
|
251
278
|
exports.date = function (input, format, offset, abbr) {
|
|
252
279
|
var l,
|
|
@@ -263,6 +290,10 @@ exports.date = function (input, format, offset, abbr) {
|
|
|
263
290
|
l = format.length;
|
|
264
291
|
date = new dateFormatter.DateZ(input);
|
|
265
292
|
|
|
293
|
+
if (isNaN(date.dateZ.getTime())) {
|
|
294
|
+
return '';
|
|
295
|
+
}
|
|
296
|
+
|
|
266
297
|
if (offset) {
|
|
267
298
|
date.setTimezoneOffset(offset, abbr);
|
|
268
299
|
}
|
|
@@ -565,7 +596,7 @@ exports.floatformat = function (input, arg) {
|
|
|
565
596
|
a = utils.trimEnd(String(arg), 'gu');
|
|
566
597
|
p = parseInt(a, 10);
|
|
567
598
|
if (isNaN(p)) {
|
|
568
|
-
return String(input);
|
|
599
|
+
return (input === undefined || input === null) ? '' : String(input);
|
|
569
600
|
}
|
|
570
601
|
}
|
|
571
602
|
|
|
@@ -595,7 +626,7 @@ exports.floatformat = function (input, arg) {
|
|
|
595
626
|
* @return {string}
|
|
596
627
|
*/
|
|
597
628
|
exports.force_escape = function (input) {
|
|
598
|
-
return exports.escape(
|
|
629
|
+
return exports.escape(asText(input));
|
|
599
630
|
};
|
|
600
631
|
exports.force_escape.safe = true;
|
|
601
632
|
|
|
@@ -644,7 +675,7 @@ exports.get_digit = function (input, arg) {
|
|
|
644
675
|
* @return {string}
|
|
645
676
|
*/
|
|
646
677
|
exports.iriencode = function (input) {
|
|
647
|
-
var s =
|
|
678
|
+
var s = asText(input),
|
|
648
679
|
out = '',
|
|
649
680
|
i,
|
|
650
681
|
c,
|
|
@@ -756,7 +787,7 @@ exports.length = function (input) {
|
|
|
756
787
|
* @return {string}
|
|
757
788
|
*/
|
|
758
789
|
exports.linebreaks = function (input) {
|
|
759
|
-
var paras = normalizeNewlines(input).split(/\n{2,}/);
|
|
790
|
+
var paras = normalizeNewlines(asText(input)).split(/\n{2,}/);
|
|
760
791
|
return utils.map(paras, function (p) {
|
|
761
792
|
return '<p>' + exports.escape(p).replace(/\n/g, '<br>') + '</p>';
|
|
762
793
|
}).join('\n\n');
|
|
@@ -775,7 +806,7 @@ exports.linebreaks.safe = true;
|
|
|
775
806
|
* @return {string}
|
|
776
807
|
*/
|
|
777
808
|
exports.linebreaksbr = function (input) {
|
|
778
|
-
return exports.escape(normalizeNewlines(input)).replace(/\n/g, '<br>');
|
|
809
|
+
return exports.escape(normalizeNewlines(asText(input))).replace(/\n/g, '<br>');
|
|
779
810
|
};
|
|
780
811
|
exports.linebreaksbr.safe = true;
|
|
781
812
|
|
|
@@ -792,7 +823,7 @@ exports.linebreaksbr.safe = true;
|
|
|
792
823
|
* @return {string}
|
|
793
824
|
*/
|
|
794
825
|
exports.linenumbers = function (input) {
|
|
795
|
-
var lines =
|
|
826
|
+
var lines = asText(input).split('\n'),
|
|
796
827
|
width = String(lines.length).length;
|
|
797
828
|
return utils.map(lines, function (line, i) {
|
|
798
829
|
var n = String(i + 1);
|
|
@@ -817,7 +848,7 @@ exports.linenumbers.safe = true;
|
|
|
817
848
|
* @return {string}
|
|
818
849
|
*/
|
|
819
850
|
exports.ljust = function (input, width) {
|
|
820
|
-
var s =
|
|
851
|
+
var s = asText(input),
|
|
821
852
|
w = parseInt(width, 10);
|
|
822
853
|
if (isNaN(w) || s.length >= w) {
|
|
823
854
|
return s;
|
|
@@ -833,10 +864,13 @@ exports.ljust = function (input, width) {
|
|
|
833
864
|
* {{ "SWIG"|lower }}
|
|
834
865
|
* // => swig
|
|
835
866
|
*
|
|
836
|
-
* @param {*} input
|
|
867
|
+
* @param {*} input None reads as the text None.
|
|
837
868
|
* @return {*}
|
|
838
869
|
*/
|
|
839
870
|
exports.lower = function (input) {
|
|
871
|
+
if (input === undefined || input === null) {
|
|
872
|
+
input = 'None';
|
|
873
|
+
}
|
|
840
874
|
var out = iterateFilter.apply(exports.lower, arguments);
|
|
841
875
|
if (out !== undefined) {
|
|
842
876
|
return out;
|
|
@@ -856,7 +890,7 @@ exports.lower = function (input) {
|
|
|
856
890
|
* @return {Array}
|
|
857
891
|
*/
|
|
858
892
|
exports.make_list = function (input) {
|
|
859
|
-
return
|
|
893
|
+
return asText(input).split('');
|
|
860
894
|
};
|
|
861
895
|
|
|
862
896
|
/**
|
|
@@ -876,7 +910,7 @@ exports.phone2numeric = function (input) {
|
|
|
876
910
|
j: '5', k: '5', l: '5', m: '6', n: '6', o: '6', p: '7', q: '7', r: '7',
|
|
877
911
|
s: '7', t: '8', u: '8', v: '8', w: '9', x: '9', y: '9', z: '9'
|
|
878
912
|
};
|
|
879
|
-
return
|
|
913
|
+
return asText(input).toLowerCase().replace(/[a-z]/g, function (c) {
|
|
880
914
|
return map[c];
|
|
881
915
|
});
|
|
882
916
|
};
|
|
@@ -971,7 +1005,7 @@ exports.pluralize = function (input, arg) {
|
|
|
971
1005
|
* @return {string}
|
|
972
1006
|
*/
|
|
973
1007
|
exports.rjust = function (input, width) {
|
|
974
|
-
var s =
|
|
1008
|
+
var s = asText(input),
|
|
975
1009
|
w = parseInt(width, 10);
|
|
976
1010
|
if (isNaN(w) || s.length >= w) {
|
|
977
1011
|
return s;
|
|
@@ -1051,7 +1085,7 @@ exports.slice = function (input, arg) {
|
|
|
1051
1085
|
* @return {string}
|
|
1052
1086
|
*/
|
|
1053
1087
|
exports.slugify = function (input) {
|
|
1054
|
-
var value =
|
|
1088
|
+
var value = asText(input);
|
|
1055
1089
|
if (value.normalize) {
|
|
1056
1090
|
value = value.normalize('NFKD').replace(/[\u0300-\u036f]/g, '');
|
|
1057
1091
|
}
|
|
@@ -1077,7 +1111,7 @@ exports.striptags = function (input) {
|
|
|
1077
1111
|
// after them (about 5 s for 100 000 characters); stripTags gives the same
|
|
1078
1112
|
// output in linear time.
|
|
1079
1113
|
// return String(input).replace(/(<([^>]+)>)/ig, '');
|
|
1080
|
-
return utils.stripTags(
|
|
1114
|
+
return utils.stripTags(asText(input));
|
|
1081
1115
|
};
|
|
1082
1116
|
|
|
1083
1117
|
/**
|
|
@@ -1111,7 +1145,7 @@ exports.time = function (input, format, offset, abbr) {
|
|
|
1111
1145
|
* @return {string}
|
|
1112
1146
|
*/
|
|
1113
1147
|
exports.title = function (input) {
|
|
1114
|
-
return
|
|
1148
|
+
return asText(input).replace(/\w\S*/g, function (str) {
|
|
1115
1149
|
return str.charAt(0).toUpperCase() + str.substr(1).toLowerCase();
|
|
1116
1150
|
});
|
|
1117
1151
|
};
|
|
@@ -1151,7 +1185,7 @@ function pyInt(arg) {
|
|
|
1151
1185
|
* @return {string}
|
|
1152
1186
|
*/
|
|
1153
1187
|
exports.truncatechars = function (input, arg) {
|
|
1154
|
-
var s =
|
|
1188
|
+
var s = asText(input),
|
|
1155
1189
|
n = pyInt(arg);
|
|
1156
1190
|
if (isNaN(n)) {
|
|
1157
1191
|
return s;
|
|
@@ -1183,7 +1217,7 @@ exports.truncatewords = function (input, arg) {
|
|
|
1183
1217
|
var n = pyInt(arg),
|
|
1184
1218
|
words;
|
|
1185
1219
|
if (isNaN(n)) {
|
|
1186
|
-
return
|
|
1220
|
+
return asText(input);
|
|
1187
1221
|
}
|
|
1188
1222
|
if (n <= 0) {
|
|
1189
1223
|
return '';
|
|
@@ -1191,7 +1225,7 @@ exports.truncatewords = function (input, arg) {
|
|
|
1191
1225
|
// A trailing \s+$ takes quadratic time on a long run of whitespace inside
|
|
1192
1226
|
// the value; utils.strip gives the same output in linear time.
|
|
1193
1227
|
// words = String(input).replace(/^\s+|\s+$/g, '').split(/\s+/);
|
|
1194
|
-
words = utils.strip(
|
|
1228
|
+
words = utils.strip(asText(input)).split(/\s+/);
|
|
1195
1229
|
if (words.length === 1 && words[0] === '') {
|
|
1196
1230
|
return '';
|
|
1197
1231
|
}
|
|
@@ -1209,10 +1243,13 @@ exports.truncatewords = function (input, arg) {
|
|
|
1209
1243
|
* {{ "swig"|upper }}
|
|
1210
1244
|
* // => SWIG
|
|
1211
1245
|
*
|
|
1212
|
-
* @param {*} input
|
|
1246
|
+
* @param {*} input None reads as the text None.
|
|
1213
1247
|
* @return {*}
|
|
1214
1248
|
*/
|
|
1215
1249
|
exports.upper = function (input) {
|
|
1250
|
+
if (input === undefined || input === null) {
|
|
1251
|
+
input = 'None';
|
|
1252
|
+
}
|
|
1216
1253
|
var out = iterateFilter.apply(exports.upper, arguments);
|
|
1217
1254
|
if (out !== undefined) {
|
|
1218
1255
|
return out;
|
|
@@ -1235,7 +1272,7 @@ exports.upper = function (input) {
|
|
|
1235
1272
|
*/
|
|
1236
1273
|
exports.urlencode = function (input, safe) {
|
|
1237
1274
|
var safeChars = (safe === undefined || safe === null) ? '/' : String(safe);
|
|
1238
|
-
return urlQuote(input, safeChars);
|
|
1275
|
+
return urlQuote(asText(input), safeChars);
|
|
1239
1276
|
};
|
|
1240
1277
|
|
|
1241
1278
|
/**
|
|
@@ -1250,7 +1287,7 @@ exports.urlencode = function (input, safe) {
|
|
|
1250
1287
|
* @return {number}
|
|
1251
1288
|
*/
|
|
1252
1289
|
exports.wordcount = function (input) {
|
|
1253
|
-
var m =
|
|
1290
|
+
var m = asText(input).match(/\S+/g);
|
|
1254
1291
|
return m ? m.length : 0;
|
|
1255
1292
|
};
|
|
1256
1293
|
|
|
@@ -1274,9 +1311,9 @@ exports.wordwrap = function (input, width) {
|
|
|
1274
1311
|
i,
|
|
1275
1312
|
word;
|
|
1276
1313
|
if (isNaN(w) || w <= 0) {
|
|
1277
|
-
return
|
|
1314
|
+
return asText(input);
|
|
1278
1315
|
}
|
|
1279
|
-
words =
|
|
1316
|
+
words = asText(input).split(/(\s+)/);
|
|
1280
1317
|
lines = [];
|
|
1281
1318
|
cur = '';
|
|
1282
1319
|
for (i = 0; i < words.length; i += 1) {
|
package/lib/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rhinostone/swig-django",
|
|
3
|
-
"version": "2.9.
|
|
3
|
+
"version": "2.9.13",
|
|
4
4
|
"description": "Django-syntax frontend for the @rhinostone/swig-core template engine. Part of the @rhinostone/swig multi-flavor family.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"template",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"node": ">=12"
|
|
23
23
|
},
|
|
24
24
|
"peerDependencies": {
|
|
25
|
-
"@rhinostone/swig-core": "2.9.
|
|
25
|
+
"@rhinostone/swig-core": "2.9.13"
|
|
26
26
|
},
|
|
27
27
|
"publishConfig": {
|
|
28
28
|
"access": "public"
|