Here is something that I'd like to achieve:
const symbolRegex = /[a-zA-Z_$][a-zA-Z_$0-9]*/g;
export function CodeSymbol(props: {code: string; symbols: SymbolMap}) {
return (
<code>
{props.code.replace(symbolRegex, (symbol): any => {
const packageName = props.symbols.get(symbol);
if (packageName) {
return <a href={`/api/${packageName}/${symbol}`}>{symbol}</a>;
}
return <>{symbol}</>;
})}
</code>
);
}
Where SymbolMap
is basically a Map<string, string>
.
Of course this doesn't work because, the preact fragment is converted to string and I get something like: Observable<[object Object]<any>>
from the Observable<HttpEvent<any>>
input (HttpEvent
is defined in the map, but Observable
isn't) .
What would you suggest?
Here's one way to achieve this by using .split
+ .map
with a regex that has one single capturing group that captures the whole matching part. With a regex like that, every even index in the array will be a non matching substring and every odd one will be a matching substring.
import { render } from 'preact';
const symbolRegex = /([a-zA-Z_$][a-zA-Z_$0-9]*)/;
function CodeSymbol(props: {code: string; symbols: SymbolMap}) {
return (
<code>
{props.code.split(symbolRegex).map((symbol, index) => {
// Every even index is a non-match when the regex has 1 capturing group
if (index % 2 === 0) return symbol;
const packageName = props.symbols.get(symbol);
if (packageName) {
return <a href={`/api/${packageName}/${symbol}`}>{symbol}</a>;
}
return symbol;
})}
</code>
);
}
render(<CodeSymbol code="foo bar" symbols={new Map([["foo", "foopackage"]])} />, document.getElementById('app'));