You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

473 lines
9.7 KiB

5 years ago
  1. (function (global, factory) {
  2. typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
  3. typeof define === 'function' && define.amd ? define(['exports'], factory) :
  4. (global = global || self, factory(global.domNodes = {}));
  5. }(this, function (exports) { 'use strict';
  6. // similar to _.uniq
  7. const uniq = l => l.filter((x, i, a) => a.indexOf(x) === i);
  8. /**
  9. * SVG void elements that cannot be auto-closed and shouldn't contain child nodes.
  10. * @const {Array}
  11. */
  12. const VOID_SVG_TAGS_LIST = [
  13. 'circle',
  14. 'ellipse',
  15. 'line',
  16. 'path',
  17. 'polygon',
  18. 'polyline',
  19. 'rect',
  20. 'stop',
  21. 'use'
  22. ];
  23. /**
  24. * List of html elements where the value attribute is allowed
  25. * @type {Array}
  26. */
  27. const HTML_ELEMENTS_HAVING_VALUE_ATTRIBUTE_LIST = [
  28. 'button',
  29. 'data',
  30. 'input',
  31. 'select',
  32. 'li',
  33. 'meter',
  34. 'option',
  35. 'output',
  36. 'progress',
  37. 'textarea',
  38. 'param'
  39. ];
  40. /**
  41. * List of all the available svg tags
  42. * @const {Array}
  43. * @see {@link https://github.com/wooorm/svg-tag-names}
  44. */
  45. const SVG_TAGS_LIST = uniq([
  46. 'a',
  47. 'altGlyph',
  48. 'altGlyphDef',
  49. 'altGlyphItem',
  50. 'animate',
  51. 'animateColor',
  52. 'animateMotion',
  53. 'animateTransform',
  54. 'animation',
  55. 'audio',
  56. 'canvas',
  57. 'clipPath',
  58. 'color-profile',
  59. 'cursor',
  60. 'defs',
  61. 'desc',
  62. 'discard',
  63. 'feBlend',
  64. 'feColorMatrix',
  65. 'feComponentTransfer',
  66. 'feComposite',
  67. 'feConvolveMatrix',
  68. 'feDiffuseLighting',
  69. 'feDisplacementMap',
  70. 'feDistantLight',
  71. 'feDropShadow',
  72. 'feFlood',
  73. 'feFuncA',
  74. 'feFuncB',
  75. 'feFuncG',
  76. 'feFuncR',
  77. 'feGaussianBlur',
  78. 'feImage',
  79. 'feMerge',
  80. 'feMergeNode',
  81. 'feMorphology',
  82. 'feOffset',
  83. 'fePointLight',
  84. 'feSpecularLighting',
  85. 'feSpotLight',
  86. 'feTile',
  87. 'feTurbulence',
  88. 'filter',
  89. 'font',
  90. 'font-face',
  91. 'font-face-format',
  92. 'font-face-name',
  93. 'font-face-src',
  94. 'font-face-uri',
  95. 'foreignObject',
  96. 'g',
  97. 'glyph',
  98. 'glyphRef',
  99. 'handler',
  100. 'hatch',
  101. 'hatchpath',
  102. 'hkern',
  103. 'iframe',
  104. 'image',
  105. 'linearGradient',
  106. 'listener',
  107. 'marker',
  108. 'mask',
  109. 'mesh',
  110. 'meshgradient',
  111. 'meshpatch',
  112. 'meshrow',
  113. 'metadata',
  114. 'missing-glyph',
  115. 'mpath',
  116. 'pattern',
  117. 'prefetch',
  118. 'radialGradient',
  119. 'script',
  120. 'set',
  121. 'solidColor',
  122. 'solidcolor',
  123. 'style',
  124. 'svg',
  125. 'switch',
  126. 'symbol',
  127. 'tbreak',
  128. 'text',
  129. 'textArea',
  130. 'textPath',
  131. 'title',
  132. 'tref',
  133. 'tspan',
  134. 'unknown',
  135. 'video',
  136. 'view',
  137. 'vkern'
  138. ].concat(VOID_SVG_TAGS_LIST)).sort();
  139. /**
  140. * HTML void elements that cannot be auto-closed and shouldn't contain child nodes.
  141. * @type {Array}
  142. * @see {@link http://www.w3.org/TR/html-markup/syntax.html#syntax-elements}
  143. * @see {@link http://www.w3.org/TR/html5/syntax.html#void-elements}
  144. */
  145. const VOID_HTML_TAGS_LIST = [
  146. 'area',
  147. 'base',
  148. 'br',
  149. 'col',
  150. 'embed',
  151. 'hr',
  152. 'img',
  153. 'input',
  154. 'keygen',
  155. 'link',
  156. 'menuitem',
  157. 'meta',
  158. 'param',
  159. 'source',
  160. 'track',
  161. 'wbr'
  162. ];
  163. /**
  164. * List of all the html tags
  165. * @const {Array}
  166. * @see {@link https://github.com/sindresorhus/html-tags}
  167. */
  168. const HTML_TAGS_LIST = uniq([
  169. 'a',
  170. 'abbr',
  171. 'address',
  172. 'article',
  173. 'aside',
  174. 'audio',
  175. 'b',
  176. 'bdi',
  177. 'bdo',
  178. 'blockquote',
  179. 'body',
  180. 'canvas',
  181. 'caption',
  182. 'cite',
  183. 'code',
  184. 'colgroup',
  185. 'datalist',
  186. 'dd',
  187. 'del',
  188. 'details',
  189. 'dfn',
  190. 'dialog',
  191. 'div',
  192. 'dl',
  193. 'dt',
  194. 'em',
  195. 'fieldset',
  196. 'figcaption',
  197. 'figure',
  198. 'footer',
  199. 'form',
  200. 'h1',
  201. 'h2',
  202. 'h3',
  203. 'h4',
  204. 'h5',
  205. 'h6',
  206. 'head',
  207. 'header',
  208. 'hgroup',
  209. 'html',
  210. 'i',
  211. 'iframe',
  212. 'ins',
  213. 'kbd',
  214. 'label',
  215. 'legend',
  216. 'main',
  217. 'map',
  218. 'mark',
  219. 'math',
  220. 'menu',
  221. 'nav',
  222. 'noscript',
  223. 'object',
  224. 'ol',
  225. 'optgroup',
  226. 'p',
  227. 'picture',
  228. 'pre',
  229. 'q',
  230. 'rb',
  231. 'rp',
  232. 'rt',
  233. 'rtc',
  234. 'ruby',
  235. 's',
  236. 'samp',
  237. 'script',
  238. 'section',
  239. 'select',
  240. 'slot',
  241. 'small',
  242. 'span',
  243. 'strong',
  244. 'style',
  245. 'sub',
  246. 'summary',
  247. 'sup',
  248. 'svg',
  249. 'table',
  250. 'tbody',
  251. 'td',
  252. 'template',
  253. 'tfoot',
  254. 'th',
  255. 'thead',
  256. 'time',
  257. 'title',
  258. 'tr',
  259. 'u',
  260. 'ul',
  261. 'var',
  262. 'video'
  263. ]
  264. .concat(VOID_HTML_TAGS_LIST)
  265. .concat(HTML_ELEMENTS_HAVING_VALUE_ATTRIBUTE_LIST)
  266. ).sort();
  267. /**
  268. * List of all boolean HTML attributes
  269. * @const {RegExp}
  270. * @see {@link https://www.w3.org/TR/html5/infrastructure.html#sec-boolean-attributes}
  271. */
  272. const BOOLEAN_ATTRIBUTES_LIST = [
  273. 'disabled',
  274. 'visible',
  275. 'checked',
  276. 'readonly',
  277. 'required',
  278. 'allowfullscreen',
  279. 'autofocus',
  280. 'autoplay',
  281. 'compact',
  282. 'controls',
  283. 'default',
  284. 'formnovalidate',
  285. 'hidden',
  286. 'ismap',
  287. 'itemscope',
  288. 'loop',
  289. 'multiple',
  290. 'muted',
  291. 'noresize',
  292. 'noshade',
  293. 'novalidate',
  294. 'nowrap',
  295. 'open',
  296. 'reversed',
  297. 'seamless',
  298. 'selected',
  299. 'sortable',
  300. 'truespeed',
  301. 'typemustmatch'
  302. ];
  303. /**
  304. * Join a list of items with the pipe symbol (usefull for regex list concatenation)
  305. * @private
  306. * @param {Array} list - list of strings
  307. * @returns {string} the list received joined with pipes
  308. */
  309. function joinWithPipe(list) {
  310. return list.join('|')
  311. }
  312. /**
  313. * Convert list of strings to regex in order to test against it ignoring the cases
  314. * @private
  315. * @param {...Array} lists - array of strings
  316. * @returns {RegExp} regex that will match all the strings in the array received ignoring the cases
  317. */
  318. function listsToRegex(...lists) {
  319. return new RegExp(`^/?(?:${joinWithPipe(lists.map(joinWithPipe))})$`, 'i')
  320. }
  321. /**
  322. * Regex matching all the html tags ignoring the cases
  323. * @const {RegExp}
  324. */
  325. const HTML_TAGS_RE = listsToRegex(HTML_TAGS_LIST);
  326. /**
  327. * Regex matching all the svg tags ignoring the cases
  328. * @const {RegExp}
  329. */
  330. const SVG_TAGS_RE = listsToRegex(SVG_TAGS_LIST);
  331. /**
  332. * Regex matching all the void html tags ignoring the cases
  333. * @const {RegExp}
  334. */
  335. const VOID_HTML_TAGS_RE = listsToRegex(VOID_HTML_TAGS_LIST);
  336. /**
  337. * Regex matching all the void svg tags ignoring the cases
  338. * @const {RegExp}
  339. */
  340. const VOID_SVG_TAGS_RE = listsToRegex(VOID_SVG_TAGS_LIST);
  341. /**
  342. * Regex matching all the html tags where the value tag is allowed
  343. * @const {RegExp}
  344. */
  345. const HTML_ELEMENTS_HAVING_VALUE_ATTRIBUTE_RE = listsToRegex(HTML_ELEMENTS_HAVING_VALUE_ATTRIBUTE_LIST);
  346. /**
  347. * Regex matching all the boolean attributes
  348. * @const {RegExp}
  349. */
  350. const BOOLEAN_ATTRIBUTES_RE = listsToRegex(BOOLEAN_ATTRIBUTES_LIST);
  351. /**
  352. * True if it's a self closing tag
  353. * @param {string} tag - test tag
  354. * @returns {boolean} true if void
  355. * @example
  356. * isVoid('meta') // true
  357. * isVoid('circle') // true
  358. * isVoid('IMG') // true
  359. * isVoid('div') // false
  360. * isVoid('mask') // false
  361. */
  362. function isVoid(tag) {
  363. return [
  364. VOID_HTML_TAGS_RE,
  365. VOID_SVG_TAGS_RE
  366. ].some(r => r.test(tag))
  367. }
  368. /**
  369. * True if it's a known HTML tag
  370. * @param {string} tag - test tag
  371. * @returns {boolean} true if html tag
  372. * @example
  373. * isHtml('img') // true
  374. * isHtml('IMG') // true
  375. * isHtml('Img') // true
  376. * isHtml('path') // false
  377. */
  378. function isHtml(tag) {
  379. return HTML_TAGS_RE.test(tag)
  380. }
  381. /**
  382. * True if it's a known SVG tag
  383. * @param {string} tag - test tag
  384. * @returns {boolean} true if svg tag
  385. * @example
  386. * isSvg('g') // true
  387. * isSvg('radialGradient') // true
  388. * isSvg('radialgradient') // true
  389. * isSvg('div') // false
  390. */
  391. function isSvg(tag) {
  392. return SVG_TAGS_RE.test(tag)
  393. }
  394. /**
  395. * True if it's not SVG nor a HTML known tag
  396. * @param {string} tag - test tag
  397. * @returns {boolean} true if custom element
  398. * @example
  399. * isCustom('my-component') // true
  400. * isCustom('div') // false
  401. */
  402. function isCustom(tag) {
  403. return [
  404. HTML_TAGS_RE,
  405. SVG_TAGS_RE
  406. ].every(l => !l.test(tag))
  407. }
  408. /**
  409. * True if the value attribute is allowed on this tag
  410. * @param {string} tag - test tag
  411. * @returns {boolean} true if the value attribute is allowed
  412. * @example
  413. * hasValueAttribute('input') // true
  414. * hasValueAttribute('div') // false
  415. */
  416. function hasValueAttribute(tag) {
  417. return HTML_ELEMENTS_HAVING_VALUE_ATTRIBUTE_RE.test(tag)
  418. }
  419. /**
  420. * True if it's a boolean attribute
  421. * @param {string} attribute - test attribute
  422. * @returns {boolean} true if the attribute is a boolean type
  423. * @example
  424. * isBoolAttribute('selected') // true
  425. * isBoolAttribute('class') // false
  426. */
  427. function isBoolAttribute(attribute) {
  428. return BOOLEAN_ATTRIBUTES_RE.test(attribute)
  429. }
  430. exports.BOOLEAN_ATTRIBUTES_LIST = BOOLEAN_ATTRIBUTES_LIST;
  431. exports.BOOLEAN_ATTRIBUTES_RE = BOOLEAN_ATTRIBUTES_RE;
  432. exports.HTML_ELEMENTS_HAVING_VALUE_ATTRIBUTE_LIST = HTML_ELEMENTS_HAVING_VALUE_ATTRIBUTE_LIST;
  433. exports.HTML_ELEMENTS_HAVING_VALUE_ATTRIBUTE_RE = HTML_ELEMENTS_HAVING_VALUE_ATTRIBUTE_RE;
  434. exports.HTML_TAGS_LIST = HTML_TAGS_LIST;
  435. exports.HTML_TAGS_RE = HTML_TAGS_RE;
  436. exports.SVG_TAGS_LIST = SVG_TAGS_LIST;
  437. exports.SVG_TAGS_RE = SVG_TAGS_RE;
  438. exports.VOID_HTML_TAGS_LIST = VOID_HTML_TAGS_LIST;
  439. exports.VOID_HTML_TAGS_RE = VOID_HTML_TAGS_RE;
  440. exports.VOID_SVG_TAGS_LIST = VOID_SVG_TAGS_LIST;
  441. exports.VOID_SVG_TAGS_RE = VOID_SVG_TAGS_RE;
  442. exports.hasValueAttribute = hasValueAttribute;
  443. exports.isBoolAttribute = isBoolAttribute;
  444. exports.isCustom = isCustom;
  445. exports.isHtml = isHtml;
  446. exports.isSvg = isSvg;
  447. exports.isVoid = isVoid;
  448. Object.defineProperty(exports, '__esModule', { value: true });
  449. }));