regex_field 0.1.0

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4afbdd2c2de56a734faad1e4a8f61fd2542ce79d
4
+ data.tar.gz: '00857d6d06aead0ed3d67b3f6a3d40fadb76ef0f'
5
+ SHA512:
6
+ metadata.gz: 1be03c30b1f6a7d9f3b8d0b91e384a6fbb4c80d37ea8ef08b11a1d63d0590392cabed2f740c4c134df4784223f961cfe0c00b5d59c0e364783e64db106f35670
7
+ data.tar.gz: 3b9b591677faebf122f21cb7a3870e895f292f5b03ff3a890a87bd9ff16b86f1afbd3a14363a67d3b993c4e82c115b8d7e1dd33cb3bcecee7c31b150f2772b89
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ * Copyright (c) 2017, Applidium (https://applidium.com)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,528 @@
1
+ /*! Regex Colorizer v0.3.1
2
+ * (c) 2010-2012 Steven Levithan <http://stevenlevithan.com/regex/colorizer/>
3
+ * MIT license
4
+ */
5
+
6
+ /* v0.1 of this script was extracted from RegexPal v0.1.4 and named 'JavaScript Regex Syntax
7
+ * Highlighter'. The name changed to Regex Colorizer in v0.2. Currently supports JavaScript (with
8
+ * web reality) regex syntax only.
9
+ */
10
+
11
+ var RegexColorizer = (function () {
12
+ "use strict";
13
+
14
+ /*--------------------------------------
15
+ * Private variables
16
+ *------------------------------------*/
17
+
18
+ var self = {},
19
+ regexToken = /\[\^?]?(?:[^\\\]]+|\\[\S\s]?)*]?|\\(?:0(?:[0-3][0-7]{0,2}|[4-7][0-7]?)?|[1-9][0-9]*|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}|c[A-Za-z]|[\S\s]?)|\((?:\?[:=!]?)?|(?:[?*+]|\{[0-9]+(?:,[0-9]*)?\})\??|[^.?*+^${[()|\\]+|./g,
20
+ charClassToken = /[^\\-]+|-|\\(?:[0-3][0-7]{0,2}|[4-7][0-7]?|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}|c[A-Za-z]|[\S\s]?)/g,
21
+ charClassParts = /^(\[\^?)(]?(?:[^\\\]]+|\\[\S\s]?)*)(]?)$/,
22
+ quantifier = /^(?:[?*+]|\{[0-9]+(?:,[0-9]*)?\})\??$/,
23
+ type = {
24
+ NONE: 0,
25
+ RANGE_HYPHEN: 1,
26
+ SHORT_CLASS: 2,
27
+ ALTERNATOR: 3
28
+ },
29
+ error = {
30
+ UNCLOSED_CLASS: "Unclosed character class",
31
+ INCOMPLETE_TOKEN: "Incomplete regex token",
32
+ INVALID_RANGE: "Reversed or invalid range",
33
+ INVALID_GROUP_TYPE: "Invalid or unsupported group type",
34
+ UNBALANCED_LEFT_PAREN: "Unclosed grouping",
35
+ UNBALANCED_RIGHT_PAREN: "No matching opening parenthesis",
36
+ INTERVAL_OVERFLOW: "Interval quantifier cannot use value over 65,535",
37
+ INTERVAL_REVERSED: "Interval quantifier range is reversed",
38
+ UNQUANTIFIABLE: "Quantifiers must be preceded by a token that can be repeated",
39
+ IMPROPER_EMPTY_ALTERNATIVE: "Empty alternative effectively truncates the regex here"
40
+ };
41
+
42
+ /*--------------------------------------
43
+ * Private helper functions
44
+ *------------------------------------*/
45
+
46
+ /**
47
+ * Returns HTML for error highlighting.
48
+ * @private
49
+ * @param {String} str Pattern to apply error highlighting to.
50
+ * @param {String} [desc] Error description.
51
+ * @returns {String} HTML for error highlighting.
52
+ */
53
+ function errorize(str, desc) {
54
+ return '<b class="err"' + (desc ? ' title="' + desc + '"' : '') + '>' + str + '</b>';
55
+ }
56
+
57
+ /**
58
+ * Returns HTML for group highlighting.
59
+ * @private
60
+ * @param {String} str Pattern to apply group highlighting to.
61
+ * @param {Number} depth Group nesting depth.
62
+ * @returns {String} HTML for group highlighting.
63
+ */
64
+ function groupize(str, depth) {
65
+ return '<b class="g' + depth + '">' + str + '</b>';
66
+ }
67
+
68
+ /**
69
+ * Expands &, <, and > characters in the provided string to HTML entities &amp;, &lt;, and &gt;.
70
+ * @private
71
+ * @param {String} str String with characters to expand.
72
+ * @returns {String} String with characters expanded.
73
+ */
74
+ function expandHtmlEntities(str) {
75
+ return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
76
+ }
77
+
78
+ /**
79
+ * Returns a set of elements within the page body that have the given class name.
80
+ * @private
81
+ * @param {String} cls Class name.
82
+ * @returns {NodeList|HTMLCollection|Array} Set of elements.
83
+ */
84
+ function elsByClass(cls) {
85
+ if (document.getElementsByClassName) {
86
+ return document.body.getElementsByClassName(cls);
87
+ }
88
+ var els = document.body.getElementsByTagName("*"),
89
+ regex = new RegExp("(?:^|\\s)" + cls + "(?:\\s|$)"),
90
+ result = [],
91
+ len = els.length,
92
+ i;
93
+ for (i = 0; i < len; i++) {
94
+ if (regex.test(els[i].className)) {
95
+ result.push(els[i]);
96
+ }
97
+ }
98
+ return result;
99
+ }
100
+
101
+ /**
102
+ * Returns the character code for the provided regex token. Supports tokens used within character
103
+ * classes only, since that's all it's currently needed for.
104
+ * @private
105
+ * @param {String} token Regex token.
106
+ * @returns {Number} Character code of the provided token, or NaN.
107
+ */
108
+ function getTokenCharCode(token) {
109
+ // Escape sequence
110
+ if (token.length > 1 && token.charAt(0) === "\\") {
111
+ var t = token.slice(1);
112
+ // Control character
113
+ if (/^c[A-Za-z]$/.test(t)) {
114
+ return "ABCDEFGHIJKLMNOPQRSTUVWXYZ".indexOf(t.charAt(1).toUpperCase()) + 1;
115
+ }
116
+ // Two or four digit hexadecimal character code
117
+ if (/^(?:x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4})$/.test(t)) {
118
+ return parseInt(t.slice(1), 16);
119
+ }
120
+ // One to three digit octal character code up to 377 (0xFF)
121
+ if (/^(?:[0-3][0-7]{0,2}|[4-7][0-7]?)$/.test(t)) {
122
+ return parseInt(t, 8);
123
+ }
124
+ // Shorthand class or incomplete token
125
+ if (t.length === 1 && "cuxDdSsWw".indexOf(t) > -1) {
126
+ return NaN;
127
+ }
128
+ // Metacharacter representing a single character index, or escaped literal character
129
+ if (t.length === 1) {
130
+ switch (t) {
131
+ case "b": return 8; // Backspace
132
+ case "f": return 12; // Form feed
133
+ case "n": return 10; // Line feed
134
+ case "r": return 13; // Carriage return
135
+ case "t": return 9; // Horizontal tab
136
+ case "v": return 11; // Vertical tab
137
+ default : return t.charCodeAt(0); // Escaped literal character
138
+ }
139
+ }
140
+ }
141
+ // Unescaped literal token(s)
142
+ if (token !== "\\") {
143
+ return token.charCodeAt(0);
144
+ }
145
+ return NaN;
146
+ }
147
+
148
+ /**
149
+ * Applies regex syntax highlighting to the provided character class. Character classes have their
150
+ * own syntax rules which are different (sometimes quite subtly) from surrounding regex syntax.
151
+ * Hence, they're treated as a single token and parsed separately.
152
+ * @private
153
+ * @param {String} value Character class pattern to be colorized.
154
+ * @returns {String} HTML for displaying the character class with syntax highlighting.
155
+ */
156
+ function parseCharClass(value) {
157
+ var output = "",
158
+ parts = charClassParts.exec(value),
159
+ lastToken = {
160
+ rangeable: false,
161
+ type: type.NONE
162
+ },
163
+ match, m;
164
+ parts = {
165
+ opening: parts[1],
166
+ content: parts[2],
167
+ closing: parts[3]
168
+ };
169
+
170
+ output += parts.closing ? parts.opening : errorize(parts.opening, error.UNCLOSED_CLASS);
171
+
172
+ // The charClassToken regex does most of the tokenization grunt work
173
+ while (match = charClassToken.exec(parts.content)) {
174
+ m = match[0];
175
+ // Escape
176
+ if (m.charAt(0) === "\\") {
177
+ /* Inside character classes, browsers differ on how they handle the following:
178
+ * - Any representation of character index zero (\0, \00, \000, \x00, \u0000).
179
+ * - "\c", when not followed by A-Z or a-z.
180
+ * - "\x", when not followed by two hex characters.
181
+ * - "\u", when not followed by four hex characters.
182
+ * However, although representations of character index zero within character
183
+ * classes don't work on their own in Firefox, they don't throw an error, they work
184
+ * when used with ranges, and it's highly unlikely that the user will actually have
185
+ * such a character in their test data, so such tokens are highlighted normally.
186
+ * The remaining metasequences are flagged as errors.
187
+ */
188
+ if (/^\\[cux]$/.test(m)) {
189
+ output += errorize(m, error.INCOMPLETE_TOKEN);
190
+ lastToken = {rangeable: lastToken.type !== type.RANGE_HYPHEN};
191
+ // Shorthand class (matches more than one character index)
192
+ } else if (/^\\[dsw]$/i.test(m)) {
193
+ output += "<b>" + m + "</b>";
194
+ /* Traditional regex behavior is that a shorthand class should be unrangeable.
195
+ * Hence, [-\dz], [\d-z], and [z-\d] should all be equivalent. However, at
196
+ * least some browsers handle this inconsistently. E.g., Firefox 2 throws an
197
+ * invalid range error for [z-\d] and [\d--].
198
+ */
199
+ lastToken = {
200
+ rangeable: lastToken.type !== type.RANGE_HYPHEN,
201
+ type: type.SHORT_CLASS
202
+ };
203
+ // Unescaped "\" at the end of the regex
204
+ } else if (m === "\\") {
205
+ output += errorize(m, error.INCOMPLETE_TOKEN);
206
+ // Don't need to set lastToken since this is the end of the line
207
+ // Metasequence representing a single character index, or escaped literal character
208
+ } else {
209
+ output += "<b>" + expandHtmlEntities(m) + "</b>";
210
+ lastToken = {
211
+ rangeable: lastToken.type !== type.RANGE_HYPHEN,
212
+ charCode: getTokenCharCode(m)
213
+ };
214
+ }
215
+ // Hyphen (might indicate a range)
216
+ } else if (m === "-") {
217
+ if (lastToken.rangeable) {
218
+ // Save the regex's lastIndex so we can reset it after checking the next token
219
+ var lastIndex = charClassToken.lastIndex,
220
+ nextToken = charClassToken.exec(parts.content);
221
+
222
+ if (nextToken) {
223
+ var nextTokenCharCode = getTokenCharCode(nextToken[0]);
224
+ // Hypen for a reverse range (e.g., z-a) or shorthand class (e.g., \d-x or x-\S)
225
+ if (
226
+ (!isNaN(nextTokenCharCode) && lastToken.charCode > nextTokenCharCode) ||
227
+ lastToken.type === type.SHORT_CLASS ||
228
+ /^\\[dsw]$/i.test(nextToken[0])
229
+ ) {
230
+ output += errorize("-", error.INVALID_RANGE);
231
+ // Hyphen creating a valid range
232
+ } else {
233
+ output += "<u>-</u>";
234
+ }
235
+ lastToken = {
236
+ rangeable: false,
237
+ type: type.RANGE_HYPHEN
238
+ };
239
+ } else {
240
+ // Hyphen at the end of a properly closed character class (literal character)
241
+ if (parts.closing) {
242
+ output += "-"; // Since this is a literal, it's technically "rangeable", but that doesn't matter
243
+ // Hyphen at the end of an unclosed character class (i.e., the end of the regex)
244
+ } else {
245
+ output += "<u>-</u>";
246
+ }
247
+ }
248
+
249
+ // Reset the regex's lastIndex so the next while loop iteration will continue appropriately
250
+ charClassToken.lastIndex = lastIndex;
251
+ // Hyphen at the beginning of a character class or after a non-rangeable token
252
+ } else {
253
+ output += "-";
254
+ lastToken = {rangeable: lastToken.type !== type.RANGE_HYPHEN};
255
+ }
256
+ // Literal character sequence
257
+ } else {
258
+ output += expandHtmlEntities(m);
259
+ lastToken = {
260
+ rangeable: (m.length > 1 || lastToken.type !== type.RANGE_HYPHEN),
261
+ charCode: m.charCodeAt(m.length - 1)
262
+ };
263
+ }
264
+ } // End charClassToken loop
265
+
266
+ return output + parts.closing;
267
+ }
268
+
269
+ /*--------------------------------------
270
+ * Public methods
271
+ *------------------------------------*/
272
+
273
+ /**
274
+ * Applies regex syntax highlighting to the provided regex pattern string.
275
+ * @memberOf RegexColorizer
276
+ * @param {String} pattern Regex pattern to be colorized.
277
+ * @returns {String} HTML for displaying the regex with syntax highlighting.
278
+ * @example
279
+ *
280
+ * RegexColorizer.colorizeText('^regexp? pattern$');
281
+ */
282
+ self.colorizeText = function (pattern) {
283
+ var output = "",
284
+ capturingGroupCount = 0,
285
+ groupStyleDepth = 0,
286
+ openGroups = [],
287
+ lastToken = {
288
+ quantifiable: false,
289
+ type: type.NONE
290
+ },
291
+ match, m, char0, char1;
292
+
293
+ while (match = regexToken.exec(pattern)) {
294
+ m = match[0];
295
+ char0 = m.charAt(0);
296
+ char1 = m.charAt(1);
297
+ // Character class
298
+ if (char0 === "[") {
299
+ output += "<i>" + parseCharClass(m) + "</i>";
300
+ lastToken = {quantifiable: true};
301
+ // Group opening
302
+ } else if (char0 === "(") {
303
+ // If this is an invalid group type, mark the error and don't count it towards
304
+ // group depth or total count
305
+ if (m.length === 2) { // m is "(?"
306
+ output += errorize(m, error.INVALID_GROUP_TYPE);
307
+ } else {
308
+ if (m.length === 1) {
309
+ capturingGroupCount++;
310
+ }
311
+ groupStyleDepth = groupStyleDepth === 5 ? 1 : groupStyleDepth + 1;
312
+ /* Record the group opening's position and character sequence so we can later
313
+ * mark it as invalid if it turns out to be unclosed in the remainder of the
314
+ * regex. The value of index is the position plus the length of the opening <b>
315
+ * element with group-depth class.
316
+ */
317
+ openGroups.push({
318
+ index: output.length + '<b class="gN">'.length,
319
+ opening: m
320
+ });
321
+ // Add markup to the group-opening character sequence
322
+ output += groupize(m, groupStyleDepth);
323
+ }
324
+ lastToken = {quantifiable: false};
325
+ // Group closing
326
+ } else if (char0 === ")") {
327
+ // If this is an invalid group closing
328
+ if (!openGroups.length) {
329
+ output += errorize(")", error.UNBALANCED_RIGHT_PAREN);
330
+ lastToken = {quantifiable: false};
331
+ } else {
332
+ output += groupize(")", groupStyleDepth);
333
+ /* Although at least in some browsers it is possible to quantify lookaheads,
334
+ * this adds no value, doesn't work as you'd expect in JavaScript, and is an
335
+ * error with some regex flavors such as PCRE (also ES5?), so flag them as
336
+ * unquantifiable.
337
+ */
338
+ lastToken = {
339
+ quantifiable: !/^[=!]/.test(openGroups[openGroups.length - 1].opening.charAt(2)),
340
+ style: "g" + groupStyleDepth
341
+ };
342
+ groupStyleDepth = groupStyleDepth === 1 ? 5 : groupStyleDepth - 1;
343
+ // Drop the last opening paren from depth tracking
344
+ openGroups.pop();
345
+ }
346
+ // Escape or backreference
347
+ } else if (char0 === "\\") {
348
+ // Backreference or octal character code without a leading zero
349
+ if (/^[1-9]/.test(char1)) {
350
+ /* What does "\10" mean?
351
+ * - Backref 10, if 10 or more capturing groups opened before this point.
352
+ * - Backref 1 followed by "0", if 1-9 capturing groups opened before this point.
353
+ * - Otherwise, it's octal character index 10 (since 10 is in octal range 0-377).
354
+ * In the case of \8 or \9 when as many capturing groups weren't opened before
355
+ * this point, they're highlighted as special tokens. However, they should
356
+ * probably be marked as errors since the handling is browser-specific. E.g.,
357
+ * in Firefox 2 they seem to be equivalent to "(?!)", while in IE 7 they match
358
+ * the literal characters "8" and "9", which is correct handling. I don't mark
359
+ * them as errors because it would seem inconsistent to users who don't
360
+ * understand the highlighting rules for octals, etc. In fact, octals are not
361
+ * included in ECMA-262v3, but all the big browsers support them.
362
+ */
363
+ var nonBackrefDigits = "",
364
+ num = +m.slice(1);
365
+ while (num > capturingGroupCount) {
366
+ nonBackrefDigits = /[0-9]$/.exec(num)[0] + nonBackrefDigits;
367
+ num = Math.floor(num / 10); // Drop the last digit
368
+ }
369
+ if (num > 0) {
370
+ output += "<b>\\" + num + "</b>" + nonBackrefDigits;
371
+ } else {
372
+ var parts = /^\\([0-3][0-7]{0,2}|[4-7][0-7]?|[89])([0-9]*)/.exec(m);
373
+ output += "<b>\\" + parts[1] + "</b>" + parts[2];
374
+ }
375
+ lastToken = {quantifiable: true};
376
+ // Metasequence
377
+ } else if (/^[0bBcdDfnrsStuvwWx]/.test(char1)) {
378
+ /* Browsers differ on how they handle:
379
+ * - "\c", when not followed by A-Z or a-z.
380
+ * - "\x", when not followed by two hex characters.
381
+ * - "\u", when not followed by four hex characters.
382
+ * Hence, such metasequences are flagged as errors.
383
+ */
384
+ if (/^\\[cux]$/.test(m)) {
385
+ output += errorize(m, error.INCOMPLETE_TOKEN);
386
+ lastToken = {quantifiable: false};
387
+ // Unquantifiable metasequence
388
+ } else if ("bB".indexOf(char1) > -1) {
389
+ output += "<b>" + m + "</b>";
390
+ lastToken = {quantifiable: false};
391
+ // Quantifiable metasequence
392
+ } else {
393
+ output += "<b>" + m + "</b>";
394
+ lastToken = {quantifiable: true};
395
+ }
396
+ // Unescaped "\" at the end of the regex
397
+ } else if (m === "\\") {
398
+ output += errorize(m, error.INCOMPLETE_TOKEN);
399
+ // Don't need to set lastToken since this is the end of the line
400
+ // Escaped literal character
401
+ } else {
402
+ output += expandHtmlEntities(m);
403
+ lastToken = {quantifiable: true};
404
+ }
405
+ // Quantifier
406
+ } else if (quantifier.test(m)) {
407
+ if (lastToken.quantifiable) {
408
+ var interval = /^\{([0-9]+)(?:,([0-9]*))?/.exec(m);
409
+ // Interval quantifier out of range for Firefox
410
+ if (interval && (+interval[1] > 65535 || (interval[2] && +interval[2] > 65535))) {
411
+ output += errorize(m, error.INTERVAL_OVERFLOW);
412
+ // Interval quantifier in reverse numeric order
413
+ } else if (interval && interval[2] && (+interval[1] > +interval[2])) {
414
+ output += errorize(m, error.INTERVAL_REVERSED);
415
+ } else {
416
+ // Quantifiers for groups are shown in the style of the (preceeding) group's depth
417
+ output += (lastToken.style ? '<b class="' + lastToken.style + '">' : '<b>') + m + '</b>';
418
+ }
419
+ } else {
420
+ output += errorize(m, error.UNQUANTIFIABLE);
421
+ }
422
+ lastToken = {quantifiable: false};
423
+ // Vertical bar (alternator)
424
+ } else if (m === "|") {
425
+ /* If there is a vertical bar at the very start of the regex, flag it as an error
426
+ * since it effectively truncates the regex at that point. If two top-level
427
+ * vertical bars are next to each other, flag it as an error for similar reasons.
428
+ */
429
+ if (lastToken.type === type.NONE || (lastToken.type === type.ALTERNATOR && !openGroups.length)) {
430
+ output += errorize(m, error.IMPROPER_EMPTY_ALTERNATIVE);
431
+ } else {
432
+ // Alternators within groups are shown in the style of the containing group's depth
433
+ output += openGroups.length ? groupize("|", groupStyleDepth) : "<b>|</b>";
434
+ }
435
+ lastToken = {
436
+ quantifiable: false,
437
+ type: type.ALTERNATOR
438
+ };
439
+ // ^ or $ anchor
440
+ } else if (m === "^" || m === "$") {
441
+ output += "<b>" + m + "</b>";
442
+ lastToken = {quantifiable: false};
443
+ // Dot (.)
444
+ } else if (m === ".") {
445
+ output += "<b>.</b>";
446
+ lastToken = {quantifiable: true};
447
+ // Literal character sequence
448
+ } else {
449
+ output += expandHtmlEntities(m);
450
+ lastToken = {quantifiable: true};
451
+ }
452
+ } // End regexToken loop
453
+
454
+ // Mark the opening character sequence for each unclosed grouping as invalid
455
+ var numCharsAdded = 0, errorIndex, i;
456
+ for (i = 0; i < openGroups.length; i++) {
457
+ errorIndex = openGroups[i].index + numCharsAdded;
458
+ output = (
459
+ output.slice(0, errorIndex) +
460
+ errorize(openGroups[i].opening, error.UNBALANCED_LEFT_PAREN) +
461
+ output.slice(errorIndex + openGroups[i].opening.length)
462
+ );
463
+ numCharsAdded += errorize("", error.UNBALANCED_LEFT_PAREN).length;
464
+ }
465
+
466
+ return output;
467
+ };
468
+
469
+ /**
470
+ * Applies regex syntax highlighting to all elements on the page with the specified class.
471
+ * @memberOf RegexColorizer
472
+ * @param {String} [cls='regex'] Class name used by elements to be colorized.
473
+ * @example
474
+ *
475
+ * // Basic use
476
+ * RegexColorizer.colorizeAll();
477
+ *
478
+ * // With class name
479
+ * RegexColorizer.colorizeAll('my-class');
480
+ */
481
+ self.colorizeAll = function (cls) {
482
+ cls = cls || "regex";
483
+ var els = elsByClass(cls),
484
+ len = els.length,
485
+ el, i;
486
+ for (i = 0; i < len; i++) {
487
+ el = els[i];
488
+ el.innerHTML = self.colorizeText(el.textContent || el.innerText);
489
+ }
490
+ };
491
+
492
+ /**
493
+ * Adds a stylesheet with the default regex highlighting styles to the page. If you provide your
494
+ * own stylesheet, you don't need to run this.
495
+ * @memberOf RegexColorizer
496
+ * @example
497
+ *
498
+ * RegexColorizer.addStyleSheet();
499
+ */
500
+ self.addStyleSheet = function () {
501
+ var ss = document.createElement("style"),
502
+ rules =
503
+ ".regex {font-family: Monospace;} " +
504
+ ".regex b {background: #aad1f7;} " + // metasequence
505
+ ".regex i {background: #e3e3e3;} " + // char class
506
+ ".regex i b {background: #9fb6dc;} " + // char class: metasequence
507
+ ".regex i u {background: #c3c3c3;} " + // char class: range-hyphen
508
+ ".regex b.g1 {background: #b4fa50; color: #000;} " + // group: depth 1
509
+ ".regex b.g2 {background: #8cd400; color: #000;} " + // group: depth 2
510
+ ".regex b.g3 {background: #26b809; color: #fff;} " + // group: depth 3
511
+ ".regex b.g4 {background: #30ea60; color: #000;} " + // group: depth 4
512
+ ".regex b.g5 {background: #0c8d15; color: #fff;} " + // group: depth 5
513
+ ".regex b.err {background: #e30000; color: #fff;} " + // error
514
+ ".regex b, .regex i, .regex u {font-weight: normal; font-style: normal; text-decoration: none;}";
515
+ ss.id = "regex-colorizer-ss";
516
+ // Need to add to the DOM before setting cssText for IE < 9
517
+ document.getElementsByTagName("head")[0].appendChild(ss);
518
+ // Can't use innerHTML or innerText for stylesheets in IE < 9
519
+ if (ss.styleSheet) {
520
+ ss.styleSheet.cssText = rules;
521
+ } else {
522
+ ss.innerHTML = rules;
523
+ }
524
+ };
525
+
526
+ return self;
527
+
528
+ }());
@@ -0,0 +1,17 @@
1
+ //= require regex_field/regex_colorizer
2
+
3
+ $(document).ready(function () {
4
+ RegexColorizer.addStyleSheet();
5
+ RegexColorizer.colorizeAll();
6
+
7
+ $('.regex').on('focus', function() {
8
+ this.innerHTML = this.textContent || this.innerText;
9
+ });
10
+
11
+ $('.regex').on('blur', function() {
12
+ RegexColorizer.colorizeAll();
13
+
14
+ target = $(this).data('target');
15
+ $(this).parent().find("input[id$='" + target + "']").val(this.textContent || this.innerText);
16
+ });
17
+ });
@@ -0,0 +1,5 @@
1
+ module RegexField
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace RegexField
4
+ end
5
+ end
@@ -0,0 +1,10 @@
1
+ module RegexField
2
+ module FormBuilder
3
+ extend ActiveSupport::Concern
4
+
5
+ def regex_field(name, options = {})
6
+ content_tag(:pre, object.send(name), class: 'regex', contenteditable: true, data: {target: name}) +
7
+ hidden_field(name, options)
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,3 @@
1
+ module RegexField
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,4 @@
1
+ require 'regex_field/engine'
2
+ require 'regex_field/form_builder'
3
+
4
+ ActionView::Helpers::FormBuilder.send(:include, RegexField::FormBuilder)
metadata ADDED
@@ -0,0 +1,70 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: regex_field
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Hugo Hache
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-11-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 4.2.0
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '5.2'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: 4.2.0
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '5.2'
33
+ description: Add a regex field on Rails form helper
34
+ email: hugo.hache@fabernovel.com
35
+ executables: []
36
+ extensions: []
37
+ extra_rdoc_files: []
38
+ files:
39
+ - LICENSE
40
+ - app/assets/javascripts/regex_field.js
41
+ - app/assets/javascripts/regex_field/regex_colorizer.js
42
+ - lib/regex_field.rb
43
+ - lib/regex_field/engine.rb
44
+ - lib/regex_field/form_builder.rb
45
+ - lib/regex_field/version.rb
46
+ homepage: https://github.com/applidium/regex_field
47
+ licenses:
48
+ - MIT
49
+ metadata: {}
50
+ post_install_message:
51
+ rdoc_options: []
52
+ require_paths:
53
+ - lib
54
+ required_ruby_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: '0'
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ requirements: []
65
+ rubyforge_project:
66
+ rubygems_version: 2.6.13
67
+ signing_key:
68
+ specification_version: 4
69
+ summary: Regex field
70
+ test_files: []