1/** 2 * Parse a condition like bf_myfield == value1, value2 3 * 4 * @param pValue <string> : the condition string to parse 5 * 6 * @return <object> : an object in the form { name : <string>, operator : <string>, values : [ string, ... ] } 7 */ 8 9export function parseCondition(pValue) { 10 // Extraire nom, opérateur et valeurs 11 const regex = /\s*([^=!<>]*)\s*(==|!=|<=|>=|=|<|>)(.*)/ 12 const matches = pValue.match(regex) 13 14 if (!matches) return null 15 16 const vName = matches[1].trim() 17 let vOperator = matches[2].trim() 18 const rawValues = matches[3].trim() 19 20 // Convertir l'opérateur "=" en "==" 21 if (vOperator === '=') vOperator = '==' 22 23 // Transformer la liste en tableau avec valeurs uniques 24 const vUniqueValues = Array.from( 25 new Set( 26 rawValues 27 .split(',') 28 .map((v) => v.trim()) 29 .filter((v) => v !== ''), 30 ), 31 ) 32 33 // Retourner la structure 34 35 const vResult = { 36 name: vName, 37 operator: vOperator, 38 values: vUniqueValues, 39 } 40 41 return vResult 42} 43 44/** 45 * Parse a keywords search string 46 * Keywords search string are composed of tokens 47 * Tokens can be single words (without space) or expression composed of several words seperated by spaces enclosed in quote or double quote. 48 * Tokens may be separated by | 49 * | stands for logical AND 50 * A token may be prefixed with - to exclude the results containing the token 51 * The position of excluded tokens is not relevant 52 * Ex : cat "my dog" -parrot | bulldog "small bird" -"cocker spaniel" 53 * will match result that contain ("cat" or "my dog") and ("bulldog" or "small bird) 54 * excluding results containing "parrot" or "cocker spaniel" 55 * 56 * @param pKeywords <string> : the keywords search string 57 * 58 * @return <array> : the parsed string as an associative array containing the keys : 59 * - CNF = the Conjonctive Normal Form (= [a OR b] AND [d or e]) of the keywords search string 60 * (ie : an AND-array of OR-arrays) 61 * - excludeds = <array> an array of excluded tokens 62 */ 63 64export function parseKeywords(pKeywords) { 65 const _t = (_key) => 'BAZ_MOT_CLE' // Remplace ça par ton système de traduction si besoin 66 67 // Résultat par défaut 68 const results = { CNF: [], excludeds: [] } 69 70 // Vérification de validité 71 if ( 72 typeof pKeywords !== 'string' || 73 pKeywords.trim() === '' || 74 pKeywords === _t('BAZ_MOT_CLE') 75 ) { 76 return results 77 } 78 79 // Séparation des clauses AND par "|" 80 const andClauses = pKeywords.split('|').map((clause) => clause.trim()) 81 82 for (const andClause of andClauses) { 83 // Extraction des tokens via RegEx 84 const regex = /(-)?("(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\S+)/gu 85 let match 86 const ors = [] 87 88 while ((match = regex.exec(andClause)) !== null) { 89 const isExcluded = match[1] === '-' 90 const rawToken = match[2] 91 const cleanedToken = rawToken.replace(/^["']|["']$/g, '') // Supprime les guillemets 92 93 if (isExcluded) { 94 results.excludeds.push(cleanedToken) 95 } else { 96 ors.push(cleanedToken) 97 } 98 } 99 100 results.CNF.push(ors) 101 } 102 103 return results 104} 105 106/** 107 * Test if a string represents a regexp 108 * A string is considered as a regexp if it contains at least one ".*" 109 * or if it begins and ends with "/" 110 * @pString <string> : the string to test 111 * @return <boolean> : true if the string represent a regexp, false otherwise 112 */ 113 114export function isRegExp(str) { 115 return ( 116 typeof str === 'string' && 117 (str.includes('.*') || (str.startsWith('/') && str.endsWith('/'))) 118 ) 119} 120 121export function removeDiacritics(str) { 122 return str 123 .normalize('NFD') 124 .replace(/[\u0300-\u036f]/g, '') 125 .toLowerCase() 126} 127 128/** 129 * Normalise une chaîne : 130 * - met en minuscules (Unicode-safe) 131 * - transforme les caractères accentués en leur équivalent non accentué 132 * - gère les ligatures courantes (Å, æ, Ã, etc.) 133 * 134 * @param <string>
134 : chaîne d'entrée (n'importe quel encodage détectable) 135 * @return <string> : chaîne lowercase, sans accents 136 */ 137 138export function toLowerCaseWithoutAccent(str) { 139 if (typeof str !== 'string') return '' 140 141 // 1. Lowercase unicode 142 str = str.toLowerCase() 143 144 // 2. Remplacer les ligatures 145 const replacements = { 146 Å: 'oe', 147 æ: 'ae', 148 Ã: 'ss', 149 ø: 'o', 150 ð: 'd', 151 þ: 'th', 152 } 153 154 str = str.replace(/Å|æ|Ã|ø|ð|þ/g, (match) => replacements[match]) 155 156 // 3. Décomposition unicode (NFD) + suppression des diacritiques 157 str = str.normalize('NFD').replace(/[\u0300-\u036f]/g, '') 158 159 // 4. Translitération ASCII (approximative via normalisation) 160 // Pas d'équivalent direct à `iconv`, mais `normalize` fait une bonne partie du travail 161 162 return str 163} 164 165/** 166 * Extract and transform a regexp string from a string recognized by isRegExp as a regexp 167 * + It removes beginning and ending "/" if it exists 168 * + Optionnaly, it add alternatives for each character that has an accented version 169 * @param pString : <string> a regexp string recognized by isRegExp as a regexp 170 * @param pAccentInsensitive : <boolean> true to make the regexp accent insensitive 171 * 172 * @return <string> : the transformed regexp string 173 */ 174 175export function extractRegExp(pString, accentInsensitive = true) { 176 let vString 177 178 if (pString.startsWith('/') && pString.endsWith('/')) { 179 vString = pString.slice(1, -1) 180 } else { 181 vString = pString 182 } 183 184 if (accentInsensitive) { 185 vString = toLowerCaseWithoutAccent(vString) 186 187 vString = vString.replace(/a/g, '(a|à |á|â|ã|ä|A|Ã|Ã|Ã|Ã|Ã)') 188 vString = vString.replace(/c/g, '(c|ç|C|Ã)') 189 vString = vString.replace(/e/g, '(e|è|é|ê|ë|E|Ã|Ã|Ã|Ã)') 190 vString = vString.replace(/i/g, '(i|ì|Ã|î|ï|I|Ã|Ã|Ã|Ã)') 191 vString = vString.replace(/n/g, '(n|ñ|N|Ã)') 192 vString = vString.replace(/o/g, '(o|ò|ó|ô|õ|ö|O|Ã|Ã|Ã|Ã|Ã)') 193 vString = vString.replace(/u/g, '(u|ù|ú|û|ü|U|Ã|Ã|Ã|Ã)') 194 vString = vString.replace(/y/g, '(y|ý|ÿ|Y|Ã)') 195 } 196 197 return vString 198}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.