I'm trying to highlight a certain body string. So if there is an # #username highlight part of the string, and leave the rest of the content unhighlighted. Very similar to how discord mentions a user.
So im trying to implement that logic
The issue is that it's highlighting the wrong parts of the string. For example
const regex = /^#/i;
const words = comment.comment_body.split(" ");
let highLight;
let username;
for (let i = 0; i < words.length; i++) {
const word = words[i];
console.log("checking for word", word);
if (regex.test(word)) {
username = word
console.log("test passed");
highLight = <ReactMarkdown className="highlightMention" source={word} />;
} else {
highLight = <ReactMarkdown className="markdownStyle" source={comment.comment_body} />;
}
}
.....
{comment.gifUrl === "" && highLight}
Map the splitted workds and if that words starts with # return it inside the highlighter else return the normal word :
const Component = () => {
...
return <div>{ comment.comment_body.split(' ').map(word=>{
if(word.startsWith('#')){
return <ReactMarkdown className="highlightMention" source={body} />;
}else{
return " "+word ;
}
})}
</div>;
};
const regex = /^#/i;
const words = comment.comment_body.split(" ");
let highLight = [];
let username;
for (let i = 0; i < words.length; i++) {
const word = words[i];
console.log("checking for word", word);
if (regex.test(word)) {
username = word
console.log("test passed");
// `highLight = <ReactMarkdown className="highlightMention" source={word} />;` this line will only do `highlight` for the last `word`
highLight.push(<ReactMarkdown className="highlightMention" source={word} />);
} else {
highLight.push(<ReactMarkdown className="markdownStyle" source={comment.comment_body} />);
}
}
.....
{comment.gifUrl === "" && highLight}
Related
How can I use regex to get an array of all the individual characters not contained within anchor tags?
So for example, with this text:
DOWNLOAD THIS OR THAT
I want an array of the indices for the characters D,O,W,N,L,O,A,D, ,T,H,I,S, , ... etc.
I managed to figure out how to get everything I don't want selected, using this: /(?:<.*?>)
But I don't know how to use that to get all the characters outside of that group.
As already pointed out by #Cid, don't do this with regular expressions. Instead, use something like below and read the input character by character:
function reader(el) {
let i = 0;
let src = el.innerHTML;
const r = {
done() {
return i >= src.length;
},
advance() {
i += 1;
},
char() {
let c = !r.done() ? src[i] : '';
r.advance();
return c;
},
peek() {
return !r.done() ? src[i] : '';
}
};
return r;
}
function collector(el) {
const r = reader(el);
const skipUntil = char => {
while (r.peek() !== char) {
r.advance();
}
r.advance();
};
return {
collect() {
const v = [];
while (!r.done()) {
if (r.peek() === '<') {
skipUntil('>');
} else if (r.peek() === '\n') {
r.advance();
} else {
v.push(r.char());
}
}
return v;
}
};
}
/* --- */
const el = document.querySelector('#source');
const cl = collector(el);
console.log(cl.collect());
<div id="source">
DOWNLOAD THIS OR THAT
</div>
My input is
const text = 'Hello #kevin12 How are you?'
How I render it
<span>{text}</span>
How I want to render it
<span>Hello <em>#kevin12</em> How are you?</span>
My parsing function (incomplete)
const parseText = value => {
const mention = value.substring(value.lastIndexOf('#')+1)
const words = value.split(mention)
return words.map(word => word === mention ? React.createElement('em', {}, word) : word)
}
...
<span>{parseText(text)}</span>
Please help me complete this rendering function.
const parseText = value => {
const words = value.split(' ')
return words.map((word, index) => {
if (index !== words.length - 1) {
word += " "
}
return word[0] === '#' ? <em>{word}</em> : word;
})
}
Split by words, iterate over the array and find the item that start with #
export default function App() {
const text = "Hello #kevin12 How are you?";
const parseText = value => {
const mention = value.split(" ");
return mention.map(w => (w[0] === "#" ? <em> {w} </em> : <> {w}</>));
};
return (
<span>
<span>{parseText(text)}</span>
</span>
);
}
I will suggest going through the regex, here is the sample code
const text = 'Hello #kevin12 How are you?';
let finalResult = test;
let re =/(?:^|\W)#(\w+)(?!\w)/g;
let match,matches =[];
while(match =re.exec(test)){
let found ='#'+match[1];
let replace ='<em>'+found+'</em>';
finalresult =finalResult.replace(found,replace);
}
console.log(finalResult) ;
im here to ask, if someone can help me with quotation and syntax checking.
im aware of the question solution 1, but i don't fully understand that solution.
here is an example, fully integrated into a website and humbly ask, if anyone can find an error?
function rewriteQuotes(){
var all_p = document.querySelectorAll(`.content_container`);
var regex_s = /[\s\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,\-.\/:;<=>?#\[\]^_`{|}~]/;
for (var i = 0; i < all_p.length; i++) {
if (all_p[i] != null) {
var all_nodes = all_p[i].querySelectorAll("*");
for (var k = 0; k < all_nodes.length; k++) {
if (all_nodes[k].childNodes.length > 0) {
var all_children = all_nodes[k].childNodes;
for (var t = 0; t < all_children.length; t++) {
if (all_children[t].nodeName == "#text") {
all_children[t].textContent = all_children[t].textContent.replace(/"/g,"\“");
all_children[t].textContent = all_children[t].textContent.replace(/\s\“/g,"\ „");
if (all_children[t].textContent.charAt(0)== "\“") {
if (all_children[t].textContent.charAt(1) === "") {
} else {
var char_1 = all_children[t].textContent.charAt(1);
if (regex_s.test(char_1)) {
} else {
all_children[t].textContent = "\„" + all_children[t].textContent.substring(1);
}
}
}
}
}
}
}
}
}
};
document.addEventListener('DOMContentLoaded',function(){
setTimeout(function(){
rewriteQuotes();
},1);
});
<div class="content_container">
<h2>"Hello"</h2>
<p>my "aunti" was driving over the "cat" with her "<em>skateboard</em>".</p>
</div>
You can simplify your regex and capture groups of "..." and then replace the quotes of those groups with your desired ones:
const regex = /"(.*?)"/g;
const str = `my "aunti" was driving over the "cat" with her "car"`;
const subst = `„$1“`;
const result = str.replace(regex, subst);
console.log('Original: ', str);
console.log('Result: ', result);
I was trying to build a hanging man game and in order to make this game, the word has been replaced by underscores like for instance (hello) ==> _ _ _ _ _. So every time when the player clicks on the keyButton it should replace the underscore by the matched letter.
But one important thing to keep in mind is that it should not replace the underscore for instance like when a user clicks on e --> _ e _ _ _ and then clicks on l --> _ _ l l _. You see the letter e that matched was being replaced by underscore which is the case in my code. The magic happens in the showMatchedLetter function
import React, { useState, useEffect } from 'react';
import { fetchButton } from '../actions';
import axios from 'axios';
import 'babel-polyfill';
const App = () => {
const [word, setWord] = useState([]);
const [underscore, setUnderscore] = useState([]);
const [data, setData] = useState([]);
useEffect(() => {
const runEffect = async () => {
const result = await axios('src/api/api.js');
setData(result.data)
}
runEffect();
}, []);
const randomWord = () => {
const chosenWord = data[Math.floor(Math.random() * data.length)];
replaceLetter(chosenWord.word);
}
const replaceLetter = (string) => {
let getString = string;
setWord(getString);
let stringToUnderScore = getString.replace(/[a-z]/gi, '_');
setUnderscore(stringToUnderScore);
}
useEffect(() => {
const checkLetter = (event) => {
if(event.keyCode >= 65 && event.keyCode <= 90) {
checkMatchLetter(word, String.fromCharCode(event.keyCode).toLowerCase());
}
};
document.addEventListener('keydown', checkLetter);
return () => {
document.removeEventListener('keydown', checkLetter);
}
}, [word]);
const checkMatchLetter = (word, keyButton) => {
if(word == undefined) {
return;
} else {
for(let i = 0; i < word.length; i++) {
if(word[i] == keyButton) {
let index = i;
showMatchedLetter(word[i], index);
}
}
}
}
const showMatchedLetter = (letter, index) => {
console.log(letter, index);
let string = word;
string = setCharAt(string, index, letter);
console.log(string)
}
const setCharAt = (string, index, letter) => {
if(index > string.length - 1) return string;
console.log(string)
return underscore.substr(0, index) + letter + underscore.substr(index + 1);
}
return (
<div>
<p>{word}</p>
<p>{underscore}</p>
<button onClick={randomWord}></button>
</div>
)
}
export default App;
A way to approach this would be to just keep a running list of the letters that have already been guessed.
Then simply replace any letter that wasn't guessed with an underscore to get your "hidden" word each time a new letter is guessed.
The revealOnly function below can be implemented in any way you want, but what's important is that it takes the full word string and a list of letters to replace and then returns a new string that omits any non-guessed letters.
const phrase = 'Hello World'
function revealOnly(str, guessed=[]){
const regExpr = new RegExp(`[^${guessed.join("")}\\s]`, 'ig')
return str.replace(regExpr, '_')
}
console.log(revealOnly(phrase, [])) // no letters guessed
console.log(revealOnly(phrase, ['e', 'l'])) // some letters guessed
The following is a working demo in react to demonstrate how you might use this:
const { useState } = React
const App = () => {
const [phrase, setPhrase] = useState('Hello World')
const [guessed, setGuessed] = useState([])
function onGuessLetter(letter){
if(guessed.includes(letter)) return
// add letter to guessed array
setGuessed(prev => [...prev, letter])
}
function revealOnly(str, guessed=[]){
const regExpr = new RegExp(`[^${guessed.join("")}\\s]`, 'ig')
return str.replace(regExpr, '_')
}
return (
<div>
<div> {revealOnly(phrase, guessed)} </div>
<LetterPicker onPick={onGuessLetter} />
</div>
)
}
const LetterPicker = (props)=>{
const letters = []
for(let i = 0; i < 26; i++){
letters.push(String.fromCharCode(97+i))
}
return (
<div className={'letter-picker'}>
{letters.map(l => <div onClick={()=>props.onPick(l)}>{l}</div>)}
</div>
)
}
ReactDOM.render(<App/>, document.querySelector("#root"))
.letter-picker > div {
display : inline-block;
cursor : pointer;
padding : 3px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Keeping a running list of letters guessed could also be useful for checking if a word has been fully revealed (although you could just check for the existence of any _ as well). Similarly in traditional hangman fashion you can show the previously letters somewhere as well.
EDIT:
How do I check if the entire word is guessed.
Just check if the revealed word is equal to the original phrase.
const curr = revealOnly(phrase, ['h','e','l','w','o','r', 'd']
const isGuessed = curr === phrase
const { useState } = React
const App = () => {
const [phrase, setPhrase] = useState('Hello World')
const [guessed, setGuessed] = useState([])
function onGuessLetter(letter){
if(guessed.includes(letter)) return
// add letter to guessed array
setGuessed(prev => [...prev, letter])
}
function revealOnly(str, guessed=[]){
const regExpr = new RegExp(`[^${guessed.join("")}\\s]`, 'ig')
return str.replace(regExpr, '_')
}
const curr = revealOnly(phrase, guessed)
const isGuessed = curr === phrase
return (
<div>
<div> {curr} </div>
<div>Gussed: {isGuessed.toString()} </div>
<LetterPicker onPick={onGuessLetter} />
</div>
)
}
const LetterPicker = (props)=>{
const letters = []
for(let i = 0; i < 26; i++){
letters.push(String.fromCharCode(97+i))
}
return (
<div className={'letter-picker'}>
{letters.map(l => <div onClick={()=>props.onPick(l)}>{l}</div>)}
</div>
)
}
ReactDOM.render(<App/>, document.querySelector("#root"))
.letter-picker > div {
display : inline-block;
cursor : pointer;
padding : 3px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>
I want to remove some words which start with # in the sentence which are duplicated in javascript how can I achieve it.
For example:
"This is #banker does banking in a #bank, this #banker is good."
Here in this sentence, I want to remove the extra word "#banker" from it.
How can I do it in javascript?
Consider every word that should be removed will start with "#"
Here is a possible solution:
const text = 'This is #banker does banking in a #bank, this #banker is good.';
const splittedWords = text.split(' ');
let newSentence = [];
splittedWords.forEach(word => {
if (word.startsWith('#')) {
if (newSentence.indexOf(word) === -1) {
newSentence.push(word);
}
} else {
newSentence.push(word);
}
});
console.log(newSentence.join(' '));
UPDATE
const text = 'This is #2, this is #3, this is #2';
const splittedWords = text.split(' ');
let newSentence = [];
splittedWords.forEach(word => {
if (word.startsWith('#')) {
cleanedSentence = newSentence.map(word => word.replace(/,/g, ''));
cleanedWord = word.replace(/,/g, '');
if (cleanedSentence.indexOf(cleanedWord) === -1) {
newSentence.push(word);
}
} else {
newSentence.push(word);
}
});
console.log(newSentence.join(' '));