var Utils = require("../Utils.js"); /** * HTML operations. * * @author n1474335 [n1474335@gmail.com] * @copyright Crown Copyright 2016 * @license Apache-2.0 * * @namespace */ var HTML = module.exports = { /** * @constant * @default */ CONVERT_ALL: false, /** * @constant * @default */ CONVERT_OPTIONS: ["Named entities where possible", "Numeric entities", "Hex entities"], /** * To HTML Entity operation. * * @param {string} input * @param {Object[]} args * @returns {string} */ runToEntity: function(input, args) { var convertAll = args[0], numeric = args[1] === "Numeric entities", hexa = args[1] === "Hex entities"; var charcodes = Utils.strToCharcode(input); var output = ""; for (var i = 0; i < charcodes.length; i++) { if (convertAll && numeric) { output += "&#" + charcodes[i] + ";"; } else if (convertAll && hexa) { output += "&#x" + Utils.hex(charcodes[i]) + ";"; } else if (convertAll) { output += HTML._byteToEntity[charcodes[i]] || "&#" + charcodes[i] + ";"; } else if (numeric) { if (charcodes[i] > 255 || HTML._byteToEntity.hasOwnProperty(charcodes[i])) { output += "&#" + charcodes[i] + ";"; } else { output += Utils.chr(charcodes[i]); } } else if (hexa) { if (charcodes[i] > 255 || HTML._byteToEntity.hasOwnProperty(charcodes[i])) { output += "&#x" + Utils.hex(charcodes[i]) + ";"; } else { output += Utils.chr(charcodes[i]); } } else { output += HTML._byteToEntity[charcodes[i]] || ( charcodes[i] > 255 ? "&#" + charcodes[i] + ";" : Utils.chr(charcodes[i]) ); } } return output; }, /** * From HTML Entity operation. * * @param {string} input * @param {Object[]} args * @returns {string} */ runFromEntity: function(input, args) { var regex = /&(#?x?[a-zA-Z0-9]{1,8});/g, output = "", m, i = 0; while ((m = regex.exec(input))) { // Add up to match for (; i < m.index;) output += input[i++]; // Add match var bite = HTML._entityToByte[m[1]]; if (bite) { output += Utils.chr(bite); } else if (!bite && m[1][0] === "#" && m[1].length > 1 && /^#\d{1,5}$/.test(m[1])) { // Numeric entity (e.g. ) var num = m[1].slice(1, m[1].length); output += Utils.chr(parseInt(num, 10)); } else if (!bite && m[1][0] === "#" && m[1].length > 3 && /^#x[\dA-F]{2,8}$/i.test(m[1])) { // Hex entity (e.g. :) var hex = m[1].slice(2, m[1].length); output += Utils.chr(parseInt(hex, 16)); } else { // Not a valid entity, print as normal for (; i < regex.lastIndex;) output += input[i++]; } i = regex.lastIndex; } // Add all after final match for (; i < input.length;) output += input[i++]; return output; }, /** * @constant * @default */ REMOVE_INDENTATION: true, /** * @constant * @default */ REMOVE_LINE_BREAKS: true, /** * Strip HTML tags operation. * * @param {string} input * @param {Object[]} args * @returns {string} */ runStripTags: function(input, args) { var removeIndentation = args[0], removeLineBreaks = args[1]; input = Utils.stripHtmlTags(input); if (removeIndentation) { input = input.replace(/\n[ \f\t]+/g, "\n"); } if (removeLineBreaks) { input = input.replace(/^\s*\n/, "") // first line .replace(/(\n\s*){2,}/g, "\n"); // all others } return input; }, /** * Parse colour code operation. * * @param {string} input * @param {Object[]} args * @returns {html} */ runParseColourCode: function(input, args) { var m = null, r = 0, g = 0, b = 0, a = 1; // Read in the input if ((m = input.match(/#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/i))) { // Hex - #d9edf7 r = parseInt(m[1], 16); g = parseInt(m[2], 16); b = parseInt(m[3], 16); } else if ((m = input.match(/rgba?\((\d{1,3}(?:\.\d+)?),\s?(\d{1,3}(?:\.\d+)?),\s?(\d{1,3}(?:\.\d+)?)(?:,\s?(\d(?:\.\d+)?))?\)/i))) { // RGB or RGBA - rgb(217,237,247) or rgba(217,237,247,1) r = parseFloat(m[1]); g = parseFloat(m[2]); b = parseFloat(m[3]); a = m[4] ? parseFloat(m[4]) : 1; } else if ((m = input.match(/hsla?\((\d{1,3}(?:\.\d+)?),\s?(\d{1,3}(?:\.\d+)?)%,\s?(\d{1,3}(?:\.\d+)?)%(?:,\s?(\d(?:\.\d+)?))?\)/i))) { // HSL or HSLA - hsl(200, 65%, 91%) or hsla(200, 65%, 91%, 1) var h_ = parseFloat(m[1]) / 360, s_ = parseFloat(m[2]) / 100, l_ = parseFloat(m[3]) / 100, rgb_ = HTML._hslToRgb(h_, s_, l_); r = rgb_[0]; g = rgb_[1]; b = rgb_[2]; a = m[4] ? parseFloat(m[4]) : 1; } else if ((m = input.match(/cmyk\((\d(?:\.\d+)?),\s?(\d(?:\.\d+)?),\s?(\d(?:\.\d+)?),\s?(\d(?:\.\d+)?)\)/i))) { // CMYK - cmyk(0.12, 0.04, 0.00, 0.03) var c_ = parseFloat(m[1]), m_ = parseFloat(m[2]), y_ = parseFloat(m[3]), k_ = parseFloat(m[4]); r = Math.round(255 * (1 - c_) * (1 - k_)); g = Math.round(255 * (1 - m_) * (1 - k_)); b = Math.round(255 * (1 - y_) * (1 - k_)); } var hsl_ = HTML._rgbToHsl(r, g, b), h = Math.round(hsl_[0] * 360), s = Math.round(hsl_[1] * 100), l = Math.round(hsl_[2] * 100), k = 1 - Math.max(r/255, g/255, b/255), c = (1 - r/255 - k) / (1 - k), m = (1 - g/255 - k) / (1 - k), // eslint-disable-line no-redeclare y = (1 - b/255 - k) / (1 - k); c = isNaN(c) ? "0" : c.toFixed(2); m = isNaN(m) ? "0" : m.toFixed(2); y = isNaN(y) ? "0" : y.toFixed(2); k = k.toFixed(2); var hex = "#" + Utils.padLeft(Math.round(r).toString(16), 2) + Utils.padLeft(Math.round(g).toString(16), 2) + Utils.padLeft(Math.round(b).toString(16), 2), rgb = "rgb(" + r + ", " + g + ", " + b + ")", rgba = "rgba(" + r + ", " + g + ", " + b + ", " + a + ")", hsl = "hsl(" + h + ", " + s + "%, " + l + "%)", hsla = "hsla(" + h + ", " + s + "%, " + l + "%, " + a + ")", cmyk = "cmyk(" + c + ", " + m + ", " + y + ", " + k + ")"; // Generate output return "
" + "Hex: " + hex + "\n" + "RGB: " + rgb + "\n" + "RGBA: " + rgba + "\n" + "HSL: " + hsl + "\n" + "HSLA: " + hsla + "\n" + "CMYK: " + cmyk + ""; }, /** * Converts an HSL color value to RGB. Conversion formula * adapted from http://en.wikipedia.org/wiki/HSL_colorSpace. * Assumes h, s, and l are contained in the set [0, 1] and * returns r, g, and b in the set [0, 255]. * * @private * @author Mohsen (http://stackoverflow.com/a/9493060) * * @param {number} h - The hue * @param {number} s - The saturation * @param {number} l - The lightness * @return {Array} The RGB representation */ _hslToRgb: function(h, s, l){ var r, g, b; if (s === 0){ r = g = b = l; // achromatic } else { var hue2rgb = function hue2rgb(p, q, t) { if (t < 0) t += 1; if (t > 1) t -= 1; if (t < 1/6) return p + (q - p) * 6 * t; if (t < 1/2) return q; if (t < 2/3) return p + (q - p) * (2/3 - t) * 6; return p; }; var q = l < 0.5 ? l * (1 + s) : l + s - l * s; var p = 2 * l - q; r = hue2rgb(p, q, h + 1/3); g = hue2rgb(p, q, h); b = hue2rgb(p, q, h - 1/3); } return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)]; }, /** * Converts an RGB color value to HSL. Conversion formula * adapted from http://en.wikipedia.org/wiki/HSL_colorSpace. * Assumes r, g, and b are contained in the set [0, 255] and * returns h, s, and l in the set [0, 1]. * * @private * @author Mohsen (http://stackoverflow.com/a/9493060) * * @param {number} r - The red color value * @param {number} g - The green color value * @param {number} b - The blue color value * @return {Array} The HSL representation */ _rgbToHsl: function(r, g, b) { r /= 255; g /= 255; b /= 255; var max = Math.max(r, g, b), min = Math.min(r, g, b), h, s, l = (max + min) / 2; if (max === min) { h = s = 0; // achromatic } else { var d = max - min; s = l > 0.5 ? d / (2 - max - min) : d / (max + min); switch (max) { case r: h = (g - b) / d + (g < b ? 6 : 0); break; case g: h = (b - r) / d + 2; break; case b: h = (r - g) / d + 4; break; } h /= 6; } return [h, s, l]; }, /** * Lookup table to translate byte values to their HTML entity codes. * * @private * @constant */ _byteToEntity: { 34 : """, 38 : "&", 39 : "'", 60 : "<", 62 : ">", 160 : " ", 161 : "¡", 162 : "¢", 163 : "£", 164 : "¤", 165 : "¥", 166 : "¦", 167 : "§", 168 : "¨", 169 : "©", 170 : "ª", 171 : "«", 172 : "¬", 173 : "­", 174 : "®", 175 : "¯", 176 : "°", 177 : "±", 178 : "²", 179 : "³", 180 : "´", 181 : "µ", 182 : "¶", 183 : "·", 184 : "¸", 185 : "¹", 186 : "º", 187 : "»", 188 : "¼", 189 : "½", 190 : "¾", 191 : "¿", 192 : "À", 193 : "Á", 194 : "Â", 195 : "Ã", 196 : "Ä", 197 : "Å", 198 : "Æ", 199 : "Ç", 200 : "È", 201 : "É", 202 : "Ê", 203 : "Ë", 204 : "Ì", 205 : "Í", 206 : "Î", 207 : "Ï", 208 : "Ð", 209 : "Ñ", 210 : "Ò", 211 : "Ó", 212 : "Ô", 213 : "Õ", 214 : "Ö", 215 : "×", 216 : "Ø", 217 : "Ù", 218 : "Ú", 219 : "Û", 220 : "Ü", 221 : "Ý", 222 : "Þ", 223 : "ß", 224 : "à", 225 : "á", 226 : "â", 227 : "ã", 228 : "ä", 229 : "å", 230 : "æ", 231 : "ç", 232 : "è", 233 : "é", 234 : "ê", 235 : "ë", 236 : "ì", 237 : "í", 238 : "î", 239 : "ï", 240 : "ð", 241 : "ñ", 242 : "ò", 243 : "ó", 244 : "ô", 245 : "õ", 246 : "ö", 247 : "÷", 248 : "ø", 249 : "ù", 250 : "ú", 251 : "û", 252 : "ü", 253 : "ý", 254 : "þ", 255 : "ÿ", 338 : "Œ", 339 : "œ", 352 : "Š", 353 : "š", 376 : "Ÿ", 402 : "ƒ", 710 : "ˆ", 732 : "˜", 913 : "Α", 914 : "Β", 915 : "Γ", 916 : "Δ", 917 : "Ε", 918 : "Ζ", 919 : "Η", 920 : "Θ", 921 : "Ι", 922 : "Κ", 923 : "Λ", 924 : "Μ", 925 : "Ν", 926 : "Ξ", 927 : "Ο", 928 : "Π", 929 : "Ρ", 931 : "Σ", 932 : "Τ", 933 : "Υ", 934 : "Φ", 935 : "Χ", 936 : "Ψ", 937 : "Ω", 945 : "α", 946 : "β", 947 : "γ", 948 : "δ", 949 : "ε", 950 : "ζ", 951 : "η", 952 : "θ", 953 : "ι", 954 : "κ", 955 : "λ", 956 : "μ", 957 : "ν", 958 : "ξ", 959 : "ο", 960 : "π", 961 : "ρ", 962 : "ς", 963 : "σ", 964 : "τ", 965 : "υ", 966 : "φ", 967 : "χ", 968 : "ψ", 969 : "ω", 977 : "ϑ", 978 : "ϒ", 982 : "ϖ", 8194 : " ", 8195 : " ", 8201 : " ", 8204 : "‌", 8205 : "‍", 8206 : "‎", 8207 : "‏", 8211 : "–", 8212 : "—", 8216 : "‘", 8217 : "’", 8218 : "‚", 8220 : "“", 8221 : "”", 8222 : "„", 8224 : "†", 8225 : "‡", 8226 : "•", 8230 : "…", 8240 : "‰", 8242 : "′", 8243 : "″", 8249 : "‹", 8250 : "›", 8254 : "‾", 8260 : "⁄", 8364 : "€", 8465 : "ℑ", 8472 : "℘", 8476 : "ℜ", 8482 : "™", 8501 : "ℵ", 8592 : "←", 8593 : "↑", 8594 : "→", 8595 : "↓", 8596 : "↔", 8629 : "↵", 8656 : "⇐", 8657 : "⇑", 8658 : "⇒", 8659 : "⇓", 8660 : "⇔", 8704 : "∀", 8706 : "∂", 8707 : "∃", 8709 : "∅", 8711 : "∇", 8712 : "∈", 8713 : "∉", 8715 : "∋", 8719 : "∏", 8721 : "∑", 8722 : "−", 8727 : "∗", 8730 : "√", 8733 : "∝", 8734 : "∞", 8736 : "∠", 8743 : "∧", 8744 : "∨", 8745 : "∩", 8746 : "∪", 8747 : "∫", 8756 : "∴", 8764 : "∼", 8773 : "≅", 8776 : "≈", 8800 : "≠", 8801 : "≡", 8804 : "≤", 8805 : "≥", 8834 : "⊂", 8835 : "⊃", 8836 : "⊄", 8838 : "⊆", 8839 : "⊇", 8853 : "⊕", 8855 : "⊗", 8869 : "⊥", 8901 : "⋅", 8942 : "⋮", 8968 : "⌈", 8969 : "⌉", 8970 : "⌊", 8971 : "⌋", 9001 : "⟨", 9002 : "⟩", 9674 : "◊", 9824 : "♠", 9827 : "♣", 9829 : "♥", 9830 : "♦", }, /** * Lookup table to translate HTML entity codes to their byte values. * * @private * @constant */ _entityToByte : { "quot" : 34, "amp" : 38, "apos" : 39, "lt" : 60, "gt" : 62, "nbsp" : 160, "iexcl" : 161, "cent" : 162, "pound" : 163, "curren" : 164, "yen" : 165, "brvbar" : 166, "sect" : 167, "uml" : 168, "copy" : 169, "ordf" : 170, "laquo" : 171, "not" : 172, "shy" : 173, "reg" : 174, "macr" : 175, "deg" : 176, "plusmn" : 177, "sup2" : 178, "sup3" : 179, "acute" : 180, "micro" : 181, "para" : 182, "middot" : 183, "cedil" : 184, "sup1" : 185, "ordm" : 186, "raquo" : 187, "frac14" : 188, "frac12" : 189, "frac34" : 190, "iquest" : 191, "Agrave" : 192, "Aacute" : 193, "Acirc" : 194, "Atilde" : 195, "Auml" : 196, "Aring" : 197, "AElig" : 198, "Ccedil" : 199, "Egrave" : 200, "Eacute" : 201, "Ecirc" : 202, "Euml" : 203, "Igrave" : 204, "Iacute" : 205, "Icirc" : 206, "Iuml" : 207, "ETH" : 208, "Ntilde" : 209, "Ograve" : 210, "Oacute" : 211, "Ocirc" : 212, "Otilde" : 213, "Ouml" : 214, "times" : 215, "Oslash" : 216, "Ugrave" : 217, "Uacute" : 218, "Ucirc" : 219, "Uuml" : 220, "Yacute" : 221, "THORN" : 222, "szlig" : 223, "agrave" : 224, "aacute" : 225, "acirc" : 226, "atilde" : 227, "auml" : 228, "aring" : 229, "aelig" : 230, "ccedil" : 231, "egrave" : 232, "eacute" : 233, "ecirc" : 234, "euml" : 235, "igrave" : 236, "iacute" : 237, "icirc" : 238, "iuml" : 239, "eth" : 240, "ntilde" : 241, "ograve" : 242, "oacute" : 243, "ocirc" : 244, "otilde" : 245, "ouml" : 246, "divide" : 247, "oslash" : 248, "ugrave" : 249, "uacute" : 250, "ucirc" : 251, "uuml" : 252, "yacute" : 253, "thorn" : 254, "yuml" : 255, "OElig" : 338, "oelig" : 339, "Scaron" : 352, "scaron" : 353, "Yuml" : 376, "fnof" : 402, "circ" : 710, "tilde" : 732, "Alpha" : 913, "Beta" : 914, "Gamma" : 915, "Delta" : 916, "Epsilon" : 917, "Zeta" : 918, "Eta" : 919, "Theta" : 920, "Iota" : 921, "Kappa" : 922, "Lambda" : 923, "Mu" : 924, "Nu" : 925, "Xi" : 926, "Omicron" : 927, "Pi" : 928, "Rho" : 929, "Sigma" : 931, "Tau" : 932, "Upsilon" : 933, "Phi" : 934, "Chi" : 935, "Psi" : 936, "Omega" : 937, "alpha" : 945, "beta" : 946, "gamma" : 947, "delta" : 948, "epsilon" : 949, "zeta" : 950, "eta" : 951, "theta" : 952, "iota" : 953, "kappa" : 954, "lambda" : 955, "mu" : 956, "nu" : 957, "xi" : 958, "omicron" : 959, "pi" : 960, "rho" : 961, "sigmaf" : 962, "sigma" : 963, "tau" : 964, "upsilon" : 965, "phi" : 966, "chi" : 967, "psi" : 968, "omega" : 969, "thetasym" : 977, "upsih" : 978, "piv" : 982, "ensp" : 8194, "emsp" : 8195, "thinsp" : 8201, "zwnj" : 8204, "zwj" : 8205, "lrm" : 8206, "rlm" : 8207, "ndash" : 8211, "mdash" : 8212, "lsquo" : 8216, "rsquo" : 8217, "sbquo" : 8218, "ldquo" : 8220, "rdquo" : 8221, "bdquo" : 8222, "dagger" : 8224, "Dagger" : 8225, "bull" : 8226, "hellip" : 8230, "permil" : 8240, "prime" : 8242, "Prime" : 8243, "lsaquo" : 8249, "rsaquo" : 8250, "oline" : 8254, "frasl" : 8260, "euro" : 8364, "image" : 8465, "weierp" : 8472, "real" : 8476, "trade" : 8482, "alefsym" : 8501, "larr" : 8592, "uarr" : 8593, "rarr" : 8594, "darr" : 8595, "harr" : 8596, "crarr" : 8629, "lArr" : 8656, "uArr" : 8657, "rArr" : 8658, "dArr" : 8659, "hArr" : 8660, "forall" : 8704, "part" : 8706, "exist" : 8707, "empty" : 8709, "nabla" : 8711, "isin" : 8712, "notin" : 8713, "ni" : 8715, "prod" : 8719, "sum" : 8721, "minus" : 8722, "lowast" : 8727, "radic" : 8730, "prop" : 8733, "infin" : 8734, "ang" : 8736, "and" : 8743, "or" : 8744, "cap" : 8745, "cup" : 8746, "int" : 8747, "there4" : 8756, "sim" : 8764, "cong" : 8773, "asymp" : 8776, "ne" : 8800, "equiv" : 8801, "le" : 8804, "ge" : 8805, "sub" : 8834, "sup" : 8835, "nsub" : 8836, "sube" : 8838, "supe" : 8839, "oplus" : 8853, "otimes" : 8855, "perp" : 8869, "sdot" : 8901, "vellip" : 8942, "lceil" : 8968, "rceil" : 8969, "lfloor" : 8970, "rfloor" : 8971, "lang" : 9001, "rang" : 9002, "loz" : 9674, "spades" : 9824, "clubs" : 9827, "hearts" : 9829, "diams" : 9830, }, };