Tengo una cadena de una entrada llamada 'texto' y, a partir de esta, me gustaría generar hashtags para un campo diferente en mi modelo de mangosta:
req.body.tags = req.body.text .split('#') .map((tag) => tag.trim().replace(/ +/g, ' ').split(' ').join('-').toLowerCase() ) .filter((tag) => tag.length !== 0)El código de arriba es casi perfecto, pero cada vez que presiono una coma, se inserta como un hashtag (o parte de él), que es algo que también intento evitar. Echa un vistazo a lo que estoy hablando:
{ "text": "Hola, mi nombre es Kevin y tu como te llamas? #random, #userundefined" }El texto de arriba son los datos que inserto a través de Postman y este es el resultado:
"tags": [ "hola,-mi-nombre-es-kevin-y-tu-como-te-llamas?", "random,", "userundefined" ],Lo que me gustaría conseguir es esto:
"tags": [ "random", "userundefined" ], Solo quiero recuperar las palabras seguidas de un # y solo eso, no quiero las comas después, como se muestra en la etiqueta random .
matchAll debería ser útil aquí...
La demostración a continuación se basa en el ejemplo de la documentación. Devuelve una matriz de matrices coincidentes. En su caso, desea el partido [1] de cada partido, por lo tanto, el map encadenado.
let text = "Hola, mi nombre es Kevin y tu como te llamas? #random, #userundefined, #user-defined, #Grand_Father, #test123Four, #99startWithNumberIsWrong, #911, #Special!characters?" let validHashtags = [...text .toLowerCase() .matchAll(/#(([a-z_]+)([\w_]+)?)/g)] .map(match => match[1]) console.log(validHashtags)Entonces eso sería:
req.body.tags = [...req.body.text .toLowerCase() .matchAll(/#(([a-z_]+)([\w_]+)?)/g)] .map(match => match[1])Usé una expresión regular que cumple con hashtag.org :
Para la longitud y las jergas, simplemente debe informar a sus usuarios al ingresar el texto.
Es posible que desee recortar las comas de los extremos de sus etiquetas después de dividir:
.map((tag) => { let newTag = tag.trim().replace(/ +/g, ' ').split(' ').join('-').toLowerCase(); if (newTag.endsWith(',')) { newTag = newTag.substring(0, newTag.length - 1); } return newTag; }) EDITAR: si está tratando de deshacerse de cualquier cosa que no esté precedida por un hashtag, debe hacer su división de manera un poco diferente. Recomendaría tal vez buscar .indexOf('#') y usar .substring() para eliminar cualquier cosa hasta ese índice, luego haga su división.
Bueno, podrías jugar con req.body.text de una manera ligeramente diferente, ahora que veo que quieres filter out the tags de los textos completos.
ejemplo de trabajo
//you can declare this function outside of whatever web-server callback you have function tagsFrom(text){ //function var toReturn=[], i=0, hashtag=false let isNumber=(n)=>Number(n).toString()==n //!isNaN(n) doesn't work properly let isValidChar=(c)=>c=="_"?true:isNumber(c)||(c.toUpperCase()!=c.toLowerCase()) for(let c of text){ if(typeof toReturn[i]!="string"){toReturn[i]=""} //because I can't add a character to undefined if(c=="#"){hashtag=true;continue} //hashtag found if(isValidChar(c)&&hashtag){toReturn[i]+=c} //character of a hashtag word else if(hashtag){hashtag=false;i++} //no longer the hashtag } return toReturn.filter(tag=>tag.length&&!isNumber(tag)) //no empty values and a tag can't be ONLY a number } var req={body:{text:"Hola, mi nombre es Kevin y tu como te llamas? #random, #userundefined #1 #spanish101 #, #1name ##underscore_test"}} //test variable req.body.tags = tagsFrom(req.body.text) //usage console.log(req.body.tags)MI EDICIÓN : analizo los hashtags según este artículo sobre hashtags