-
-
Notifications
You must be signed in to change notification settings - Fork 23
/
Copy pathhtml.js
181 lines (148 loc) · 5.76 KB
/
html.js
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
/*jslint laxbreak: true, eqeqeq: true, undef: true, regexp: false */
/*global require, process, exports */
var sys = require('sys');
/* Function: escape(value);
Escapes the characters &, <, >, ' and " in string with html entities.
Arguments:
value - string to escape
*/
var escape = exports.escape = function (value) {
return value
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/'/g, ''')
.replace(/"/g, '&qout;');
};
/* Function: linebreaks(value, options);
Converts newlines into <p> and <br />s.
Arguments:
value - string, the string to convert.
options - optional, see options
Options:
escape - boolean, if true pass the string through escape()
onlybr - boolean, if true only br tags will be created.
*/
var linebreaks = exports.linebreaks = function (value, options) {
options = options || {};
value = value.replace(/\r\n|\r|\n/g, '\n');
if (options.onlybr) {
return (options.escape ? escape(value) : value).replace(/\n/g, '<br />');
}
var lines = value.split(/\n{2,}/);
if (options.escape) {
lines = lines.map( function (x) { return '<p>' + escape(x).replace('\n', '<br />') + '</p>'; } );
} else {
lines = lines.map( function (x) { return '<p>' + x.replace('\n', '<br />') + '</p>'; } );
}
return lines.join('\n\n');
};
var re_words = /&.*?;|<.*?>|(\w[\w\-]*)/g;
var re_tag = /<(\/)?([^ ]+?)(?: (\/)| .*?)?>/;
var html4_singlets = ['br', 'col', 'link', 'base', 'img', 'param', 'area', 'hr', 'input'];
var truncate_html_words = exports.truncate_html_words = function (input, cnt) {
var words = 0, pos = 0, elipsis_pos = 0, length = cnt - 0;
var open_tags = [];
if (!length) { return ''; }
re_words.lastIndex = 0;
while (words <= length) {
var m = re_words( input );
if (!m) {
// parsed through string
break;
}
pos = re_words.lastIndex;
if (m[1]) {
// this is not a tag
words += 1;
if (words === length) {
elipsis_pos = pos;
}
continue;
}
var tag = re_tag( m[0] );
if (!tag || elipsis_pos) {
// don't worry about non-tags or tags after truncate point
continue;
}
var closing_tag = tag[1], tagname = tag[2].toLowerCase(), self_closing = tag[3];
if (self_closing || html4_singlets.indexOf(tagname) > -1) {
continue;
} else if (closing_tag) {
var idx = open_tags.indexOf(tagname);
if (idx > -1) {
// SGML: An end tag closes, back to the matching start tag, all unclosed intervening start tags with omitted end tags
open_tags = open_tags.slice(idx + 1);
}
} else {
open_tags.unshift( tagname );
}
}
if (words <= length) {
return input;
}
return open_tags.reduce( function (p,c) { return p + '</' + c + '>'; }, input.slice(0, elipsis_pos) + ' ...');
};
var punctuation_re = /^((?:\(|<|<)*)(.*?)((?:\.|,|\)|>|\n|>)*)$/;
var simple_email_re = /^\S+@[a-zA-Z0-9._\-]+\.[a-zA-Z0-9._\-]+$/;
function trim_url(url, limit) {
if (limit === undefined || limit > url.length) { return url; }
return url.substr(0, limit - 3 > 0 ? limit - 3 : 0) + '...';
}
/* Function: urlize(text, options)
Converts all urls found in text into links (<a href="URL">URL</a>).
Arguments:
text - string, the text to convert.
options - optional, see options
Options:
escape - boolean, if true pass the string through escape()
limit - number, if defined the shown urls will be truncated with '...' at this length
nofollow - boolean, if true add rel="nofollow" to <a> tags
*/
function urlize(text, options) {
options = options || {};
var words = text.split(/(\s+)/g);
var nofollow = options.nofollow ? ' rel="nofollow"' : '';
words.forEach( function (word, i, words) {
var match;
if (word.indexOf('.') > -1 || word.indexOf('@') > -1 || word.indexOf(':') > -1) {
match = punctuation_re(word);
}
if (match) {
var url, lead = match[1], middle = match[2], trail = match[3];
if (middle.substr(0,7) === 'http://' || middle.substr(0,8) === 'https://') {
url = encodeURI(middle);
} else if (middle.substr(0,4) === 'www.' || (
middle.indexOf('@') === -1 && middle && middle[0].match(/[a-z0-9]/i) &&
(middle.substr(-4) === '.org' || middle.substr(-4) === '.net' || middle.substr(-4) === '.com'))) {
url = encodeURI('http://' + middle);
} else if (middle.indexOf('@') > -1 && middle.indexOf(':') === -1 && simple_email_re(middle)) {
url = 'mailto:' + middle;
nofollow = '';
}
if (url) {
var trimmed = trim_url(middle, options.limit);
if (options.escape) {
lead = escape(lead);
trail = escape(trail);
url = escape(url);
trimmed = escape(trimmed);
}
middle = '<a href="' + url + '"' + nofollow + '>' + trimmed + '</a>';
words[i] = lead + middle + trail;
}
} else if (options.escape) {
words[i] = escape(word);
}
});
return words.join('');
}
exports.urlize = urlize;
/* Function: strip_spaces_between_tags
Returns the given HTML with spaces between tags removed.
Arguments:
input: string, the html to process
*/
exports.strip_spaces_between_tags = function (input) {
return input.replace(/>\s+</g, '><');
}