HTMLify
index.js
Views: 6 | Author: cody
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 | 'use strict'; const { unassigned_code_points, commonly_mapped_to_nothing, non_ASCII_space_characters, prohibited_characters, bidirectional_r_al, bidirectional_l, } = require('./lib/memory-code-points'); module.exports = saslprep; // 2.1. Mapping /** * non-ASCII space characters [StringPrep, C.1.2] that can be * mapped to SPACE (U+0020) */ const mapping2space = non_ASCII_space_characters; /** * the "commonly mapped to nothing" characters [StringPrep, B.1] * that can be mapped to nothing. */ const mapping2nothing = commonly_mapped_to_nothing; // utils const getCodePoint = character => character.codePointAt(0); const first = x => x[0]; const last = x => x[x.length - 1]; /** * Convert provided string into an array of Unicode Code Points. * Based on https://stackoverflow.com/a/21409165/1556249 * and https://www.npmjs.com/package/code-point-at. * @param {string} input * @returns {number[]} */ function toCodePoints(input) { const codepoints = []; const size = input.length; for (let i = 0; i < size; i += 1) { const before = input.charCodeAt(i); if (before >= 0xd800 && before <= 0xdbff && size > i + 1) { const next = input.charCodeAt(i + 1); if (next >= 0xdc00 && next <= 0xdfff) { codepoints.push((before - 0xd800) * 0x400 + next - 0xdc00 + 0x10000); i += 1; continue; } } codepoints.push(before); } return codepoints; } /** * SASLprep. * @param {string} input * @param {Object} opts * @param {boolean} opts.allowUnassigned * @returns {string} */ function saslprep(input, opts = {}) { if (typeof input !== 'string') { throw new TypeError('Expected string.'); } if (input.length === 0) { return ''; } // 1. Map const mapped_input = toCodePoints(input) // 1.1 mapping to space .map(character => (mapping2space.get(character) ? 0x20 : character)) // 1.2 mapping to nothing .filter(character => !mapping2nothing.get(character)); // 2. Normalize const normalized_input = String.fromCodePoint .apply(null, mapped_input) .normalize('NFKC'); const normalized_map = toCodePoints(normalized_input); // 3. Prohibit const hasProhibited = normalized_map.some(character => prohibited_characters.get(character) ); if (hasProhibited) { throw new Error( 'Prohibited character, see https://tools.ietf.org/html/rfc4013#section-2.3' ); } // Unassigned Code Points if (opts.allowUnassigned !== true) { const hasUnassigned = normalized_map.some(character => unassigned_code_points.get(character) ); if (hasUnassigned) { throw new Error( 'Unassigned code point, see https://tools.ietf.org/html/rfc4013#section-2.5' ); } } // 4. check bidi const hasBidiRAL = normalized_map.some(character => bidirectional_r_al.get(character) ); const hasBidiL = normalized_map.some(character => bidirectional_l.get(character) ); // 4.1 If a string contains any RandALCat character, the string MUST NOT // contain any LCat character. if (hasBidiRAL && hasBidiL) { throw new Error( 'String must not contain RandALCat and LCat at the same time,' + ' see https://tools.ietf.org/html/rfc3454#section-6' ); } /** * 4.2 If a string contains any RandALCat character, a RandALCat * character MUST be the first character of the string, and a * RandALCat character MUST be the last character of the string. */ const isFirstBidiRAL = bidirectional_r_al.get( getCodePoint(first(normalized_input)) ); const isLastBidiRAL = bidirectional_r_al.get( getCodePoint(last(normalized_input)) ); if (hasBidiRAL && !(isFirstBidiRAL && isLastBidiRAL)) { throw new Error( 'Bidirectional RandALCat character must be the first and the last' + ' character of the string, see https://tools.ietf.org/html/rfc3454#section-6' ); } return normalized_input; } |