forked from hexojs/hexo-util
/
html_tag.js
49 lines (40 loc) · 1.53 KB
/
html_tag.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
'use strict';
const encodeURL = require('./encode_url');
const escapeHTML = require('./escape_html');
const regexUrl = /(cite|download|href|src|url)$/i;
const regexMeta = /^(og:|twitter:)(audio|image|url|video)(:secure_url)?$/i;
function encSrcset(str) {
str.split(' ')
.forEach(subStr => {
if (subStr.match(/\S/)) {
subStr = subStr.trim();
str = str.replace(subStr, encodeURI(subStr));
}
});
return str;
}
function htmlTag(tag, attrs, text, escape = true) {
if (!tag) throw new TypeError('tag is required!');
let result = `<${escapeHTML(tag)}`;
for (const i in attrs) {
if (attrs[i] === null || typeof attrs[i] === 'undefined') result += '';
else {
if (i.match(regexUrl)
|| (tag === 'meta' && !attrs[i].match(regexMeta) && Object.values(attrs)[0].match(regexMeta))) {
result += ` ${escapeHTML(i)}="${encodeURL(attrs[i])}"`;
} else if (attrs[i] === true || i === attrs[i]) result += ` ${escapeHTML(i)}`;
else if (i.match(/srcset$/i)) result += ` ${escapeHTML(i)}="${encSrcset(attrs[i])}"`;
else result += ` ${escapeHTML(i)}="${escapeHTML(String(attrs[i]))}"`;
}
}
if (escape && text && tag !== 'style') text = escapeHTML(String(text));
if (text && tag === 'style') {
text = text.replace(/url\(['"](.*?)['"]\)/gi, (urlAttr, url) => {
return `url("${encodeURL(url)}")`;
});
}
if (text === null || typeof text === 'undefined') result += '>';
else result += `>${text}</${escapeHTML(tag)}>`;
return result;
}
module.exports = htmlTag;