Let's say I have a string Hey @eli check out this link: https://stackoverflow.com
Ideally I want to turn this into an array like [{type: 'text', content: 'Hey '}, {type: 'mention', content: '@eli'}, {type: 'text', content: ' check out this link: '}, {type: 'href', content: 'https://stackoverflow.com'}]
so I can add styles to or wrap certain strings of the text.
I am currently doing this with a series of .split()s, but it feels somewhat complex. Is there an easier way to isolate/break-up a string, based on trailing characters/strings?
Current solution for #s and @s:
const valueAsArray = []
value.split(/\r?\n/).forEach((line) => {
if (line) {
const line_: Line[] = [];
line.split(' ').forEach((space, i) => {
space.split('@').forEach((mention, i) => {
if (i === 0) {
mention.split('#').forEach((hashtag, i) => {
if (i === 0) {
line_.push({ type: 'text', content: hashtag });
} else {
line_.push({ type: 'hashtag', content: `#${hashtag}` });
}
});
} else {
line_.push({ type: 'mention', content: `@${mention}` });
}
});
line_.push({ type: 'text', content: ' ' });
});
valueAsArray.push({ type: 'line', content: line_ });
} else {
valueAsArray.push({ type: 'spacer' });
}
});
I would just use regex for the entire keyword search, using the or pipe | separating the different keywords
const keys = /([@#]\S+|https\S+)/gi
@ or # + string of characters
^ key
https + string of characters
^ another key
And then you would end up with an array like this:
const valueAsArray = [];
value.split(keys).forEach(item => {
if (item[0] == '@' || item[0] == '#'){
valueAsArray.push({
type: 'mention',
content: item
});
} else if (item.includes('https')){
valueAsArray.push({
type: 'href',
content: item
});
} else {
valueAsArray.push({
type: 'text',
content: item
});
}
});
Maybe there’s a more efficient way, but I thought this would probably be most flexible in your case. Hope this helps