Skip to content

Commit 30bbe33

Browse files
authored
Merge pull request #1 from arobrien/arobiren/filters
Filters and Tests
2 parents 2116353 + 5f00a14 commit 30bbe33

File tree

12 files changed

+9873
-0
lines changed

12 files changed

+9873
-0
lines changed

.travis.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
language: node_js
2+
node_js:
3+
- "13"
4+
5+
script: "jasmine"
6+
7+
before_script:
8+
- npm install jasmine

filters/ansi.js

Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
_ANSI_COLORS = [
2+
'ansi-black',
3+
'ansi-red',
4+
'ansi-green',
5+
'ansi-yellow',
6+
'ansi-blue',
7+
'ansi-magenta',
8+
'ansi-cyan',
9+
'ansi-white',
10+
'ansi-black-intense',
11+
'ansi-red-intense',
12+
'ansi-green-intense',
13+
'ansi-yellow-intense',
14+
'ansi-blue-intense',
15+
'ansi-magenta-intense',
16+
'ansi-cyan-intense',
17+
'ansi-white-intense',
18+
];
19+
20+
function ansi2html(value) {
21+
// Convert ANSI colors to HTML colors.
22+
// Parameters
23+
// ----------
24+
// text : unicode
25+
// Text containing ANSI colors to convert to HTML
26+
var value;
27+
var cleaned = jinjaToJS.runtime.escape(value);
28+
29+
// state
30+
var fg, bg;
31+
var bold = false;
32+
var underline = false;
33+
var inverse = false;
34+
35+
// number collected in each match
36+
var numbers;
37+
38+
// accumulate output
39+
var out = "";
40+
41+
var last_index = 0;
42+
var ansi_re = /\x1b\[(.*?)([@-~])/g;
43+
var m;
44+
while (m = ansi_re.exec(cleaned)) {
45+
// [match, group1, group2, index: n]
46+
47+
// process state for next chunk
48+
if (m[2] == 'm') {
49+
numbers = m[1].split(';').map(n => Number(n));
50+
} else {
51+
numbers = [];
52+
}
53+
54+
if (m.index > last_index) {
55+
// process previous chunk based on current state
56+
var [starttag, endtag] = _make_ansi_tags(bold && fg < 8 ? fg + 8 : fg,
57+
bg, bold, underline, inverse);
58+
out += starttag;
59+
out += cleaned.slice(last_index, m.index);
60+
out += endtag;
61+
}
62+
63+
// increment to start of next chunk
64+
last_index = m.index + m[0].length;
65+
66+
67+
for (var i=0; i < numbers.length; i++) {
68+
var n = numbers[i]
69+
switch(n) {
70+
case 0:
71+
// same as empty: reset everything
72+
fg = bg = undefined;
73+
bold = underline = inverse = false;
74+
break;
75+
case 1:
76+
bold = true;
77+
break;
78+
case 4:
79+
underline = true;
80+
break;
81+
case 5:
82+
bold = true;
83+
break;
84+
case 7:
85+
inverse = true;
86+
break;
87+
case 21:
88+
case 22:
89+
bold = false;
90+
break;
91+
case 24:
92+
underline = false;
93+
break;
94+
case 27:
95+
inverse = false;
96+
break;
97+
case 30:
98+
case 31:
99+
case 32:
100+
case 33:
101+
case 34:
102+
case 35:
103+
case 36:
104+
case 37:
105+
fg = n - 30;
106+
break;
107+
case 38:
108+
[fg, i] = _get_extended_color(numbers, i);
109+
break;
110+
case 40:
111+
case 41:
112+
case 42:
113+
case 43:
114+
case 44:
115+
case 45:
116+
case 46:
117+
case 47:
118+
bg = n - 40;
119+
break;
120+
case 48:
121+
[bg, i] = _get_extended_color(numbers, i);
122+
break;
123+
case 49:
124+
bg = undefined;
125+
break;
126+
case 90:
127+
case 91:
128+
case 92:
129+
case 93:
130+
case 94:
131+
case 95:
132+
case 96:
133+
case 97:
134+
fg = n - 90 + 8;
135+
break;
136+
case 100:
137+
case 101:
138+
case 102:
139+
case 103:
140+
case 104:
141+
case 105:
142+
case 106:
143+
case 107:
144+
fg = n - 100 + 8;
145+
break;
146+
}
147+
}
148+
}
149+
150+
if (cleaned.length > last_index) {
151+
// process last chunk
152+
var [starttag, endtag] = _make_ansi_tags(bold && fg < 8 ? fg + 8 : fg,
153+
bg, bold, underline, inverse);
154+
out += starttag;
155+
out += cleaned.slice(last_index);
156+
out += endtag;
157+
}
158+
159+
return out;
160+
};
161+
162+
function _get_extended_color(numbers, i) {
163+
var numbers, i;
164+
var n;
165+
var c;
166+
if (numbers.length < i + 1) return [undefined, numbers.length];
167+
n = numbers[i+1];
168+
if (n == 2 && numbers.length >= i+4) {
169+
// 24-bit RGB
170+
c = numbers.slice(i+2,i+5);
171+
if (c.some((e) => c < 0 || c > 255)) return [undefined, numbers.length];
172+
return [c, i + 3];
173+
}
174+
else if (n == 5 && numbers.length >= i+2) {
175+
// 256 colors
176+
c = numbers[i+2];
177+
if (c < 0) return [undefined, numbers.length];
178+
// 16 default terminal colors
179+
if (c < 16) return [c, i+2];
180+
// 6x6x6 color cube, see http://stackoverflow.com/a/27165165/500098
181+
if (c < 232) {
182+
return [[c < 52 ? 0 : 55 + Math.floor( (c - 16) / 36 ) * 40,
183+
(c - 16) % 36 < 6 ? 0 : 55 + Math.floor(((c - 16) % 36) / 6) * 40,
184+
(c - 16) % 6 < 1 ? 0 : 55 + Math.floor(((c - 16) % 6) ) * 40
185+
], i+2];
186+
}
187+
// grayscale, see http://stackoverflow.com/a/27165165/500098
188+
if (c < 256) return [[(c - 232) * 10 + 8,
189+
(c - 232) * 10 + 8,
190+
(c - 232) * 10 + 8
191+
], i+2];
192+
}
193+
return [undefined, numbers.length];
194+
}
195+
196+
197+
function _make_ansi_tags(fg, bg, bold, underline, inverse) {
198+
var fg, bg, bold, underline, inverse;
199+
if (fg == undefined && bg == undefined && !bold && !underline && !inverse) return ['', ''];
200+
201+
var classes = [];
202+
var styles = [];
203+
204+
if (inverse)[fg, bg] = [bg, fg];
205+
206+
if (Number.isInteger(fg)) classes.push(_ANSI_COLORS[fg] + '-fg');
207+
else if (fg instanceof Array) styles.push('color: rgb('+fg[0]+','+fg[1]+','+fg[2]+')');
208+
else if (inverse) classes.push('ansi-default-inverse-fg');
209+
210+
if (Number.isInteger(bg)) classes.push(_ANSI_COLORS[bg] + '-bg');
211+
else if (bg instanceof Array) styles.push('background-color: rgb('+bg[0]+','+bg[1]+','+bg[2]+')');
212+
else if (inverse) classes.push('ansi-default-inverse-bg');
213+
214+
if (bold) classes.push('ansi-bold');
215+
if (underline) classes.push('ansi-underline');
216+
217+
var starttag = '<span';
218+
if (classes.length) starttag += ' class="' + classes.join(' ') + '"';
219+
if (styles.length) starttag += ' style="' + styles.join('; ') + '"';
220+
starttag += '>';
221+
222+
return [starttag, '</span>']
223+
}
224+
225+
226+
if (
227+
typeof module !== 'undefined' &&
228+
module.exports &&
229+
typeof exports !== 'undefined'
230+
) {
231+
module.exports = {
232+
ansi2html: ansi2html,
233+
_get_extended_color: _get_extended_color,
234+
_make_ansi_tags: _make_ansi_tags
235+
};
236+
}
237+
else {
238+
ansi = {
239+
ansi2html: ansi2html,
240+
_get_extended_color: _get_extended_color,
241+
_make_ansi_tags: _make_ansi_tags
242+
};
243+
}

filters/simple_filters.js

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
DISPLAY_DATA_PRIORITY = [
2+
'text/html',
3+
'application/pdf',
4+
'text/latex',
5+
'image/svg+xml',
6+
'image/png',
7+
'image/jpeg',
8+
'text/markdown',
9+
'text/plain'
10+
];
11+
12+
function filter_data_type(output) {
13+
for (fmt of DISPLAY_DATA_PRIORITY) {
14+
if (output.hasOwnProperty(fmt)) return [fmt];
15+
}
16+
// TODO: handle warning
17+
return [undefined];
18+
}
19+
20+
function get_metadata(output, key, mimetype=undefined) {
21+
// from nbconvert/filters/metadata.py
22+
// Resolve an output metadata key
23+
// If mimetype given, resolve at mimetype level first,
24+
// then fallback to top-level.
25+
// Otherwise, just resolve at top-level.
26+
// Returns None if no data found.
27+
const md = output.metadata;
28+
if (mimetype &&
29+
md.hasOwnProperty(mimetype) &&
30+
md[mimetype] != undefined &&
31+
md[mimetype].hasOwnProperty(key) &&
32+
md[mimetype][key] != undefined) {
33+
return md[mimetype][key];
34+
}
35+
return md[key];
36+
}
37+
38+
function highlight_code(source, language, metadata=undefined) {
39+
return hljs.highlight(language, source, false, false);
40+
}
41+
42+
function json_dumps(obj) {
43+
return JSON.stringify(obj);
44+
}
45+
46+
function markdown2html(source) {
47+
const converter = new showdown.Converter();
48+
return converter.makeHtml(source);
49+
}
50+
51+
function posix_path(path) {
52+
return path.replace(/\\/g,'/');
53+
}
54+
55+
function strip_files_prefix(dirty_text) {
56+
// Fix all fake URLs that start with `files/`, stripping out the `files/` prefix.
57+
// Applies to both urls (for html) and relative paths (for markdown paths).
58+
return dirty_text.replace(/(src|href)\=([\'"]?)\/?files\//g, (m,p1,p2) => p1 + '=' + p2).replace(
59+
/(!?)\[(.*?)\]\(\/?files\/(.*?)\)/g, (m,p1,p2,p3) => p1 + '[' + p2 + '](' + p3 + ')');
60+
}
61+
62+
if (
63+
typeof module !== 'undefined' &&
64+
module.exports &&
65+
typeof exports !== 'undefined'
66+
) {
67+
module.exports = {
68+
filter_data_type: filter_data_type,
69+
get_metadata: get_metadata,
70+
highlight_code: highlight_code,
71+
json_dumps: json_dumps,
72+
markdown2html: markdown2html,
73+
posix_path: posix_path,
74+
strip_files_prefix: strip_files_prefix
75+
};
76+
}
77+
else {
78+
simple_filters = {
79+
filter_data_type: filter_data_type,
80+
get_metadata: get_metadata,
81+
highlight_code: highlight_code,
82+
json_dumps: json_dumps,
83+
markdown2html: markdown2html,
84+
posix_path: posix_path,
85+
strip_files_prefix: strip_files_prefix
86+
};
87+
}

spec/SpecRunner.html

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8">
5+
<title>Jasmine Spec Runner v3.5.0</title>
6+
7+
<link rel="shortcut icon" type="image/png" href="lib/jasmine-3.5.0/jasmine_favicon.png">
8+
<link rel="stylesheet" href="lib/jasmine-3.5.0/jasmine.css">
9+
10+
<script src="lib/jasmine-3.5.0/jasmine.js"></script>
11+
<script src="lib/jasmine-3.5.0/jasmine-html.js"></script>
12+
<script src="lib/jasmine-3.5.0/boot.js"></script>
13+
14+
<!-- include source files here... -->
15+
<script src="../filters/ansi.js"></script>
16+
<script src="../filters/simple_filters.js"></script>
17+
18+
<!-- include spec files here... -->
19+
<script src="filters_spec.js"></script>
20+
21+
</head>
22+
23+
<body>
24+
</body>
25+
</html>

0 commit comments

Comments
 (0)