Skip to content

Instantly share code, notes, and snippets.

@erikvullings
Created December 14, 2024 10:18
Show Gist options
  • Save erikvullings/fb1f7a2324f9b40bec3adc6b7f0179fd to your computer and use it in GitHub Desktop.
Save erikvullings/fb1f7a2324f9b40bec3adc6b7f0179fd to your computer and use it in GitHub Desktop.
Highlight text in a data object

Highlighter

TypeScript highlighter that takes a data object, and applies a highlighting function to selected property values.

I needed to render a data object representing an article. Before rendering it to HTML, I wanted to mark certain parts of the text with a background color.

  1. Create string or regex-based highlighters descriptions
  2. Create a factory function that takes these highlighters and converts them to functions that will wrap matching text with an HTML mark element and background color. It returns a highlighter.
  3. Use the highlighter to convert the original data object to a data object with the same shape, but where matching text is highlighted.
// Extract all nested property keys
const extractPropertyKeys = (obj: any, parentKey: string = ''): string[] => {
let keys: string[] = [];
for (const key in obj) {
const fullKey = parentKey ? `${parentKey}.${key}` : key;
keys.push(fullKey);
if (typeof obj[key] === 'object' && obj[key] !== null && !Array.isArray(obj[key])) {
keys = keys.concat(extractPropertyKeys(obj[key], fullKey));
}
}
return keys;
};
// Example usage of extractPropertyKeys
const exampleObj = {
"_index": "cocaine",
"_id": "e98c380c38a3652682642ad1a1a280e3",
"_score": null,
"_source": {
"url": "http://example.com",
"seendate": "2017-02-10T21:30:00",
"title_en": "Cocaine on a beach worth 59 million euros in England",
"text_en": "They found a bag of cocaine...",
"gpt_money_total": 500000,
"gpt_coke_total": 360
},
"sort": [4],
"id": 1
};
console.log(extractPropertyKeys(exampleObj));
// Highlighter transformation
type Highlighter = {
type: 'regex' | 'string';
value: string;
color: string;
properties: string[];
};
const createHighlighter = (highlighters: Highlighter[]) => {
const highlightValue = (value: string, highlighter: Highlighter): string => {
if (highlighter.type === 'regex') {
const regex = new RegExp(highlighter.value, 'gi');
return value.replace(regex, (match) => `<mark style="background-color: ${highlighter.color}88;">${match}</mark>`);
} else if (highlighter.type === 'string') {
return value.split(highlighter.value).join(
`<mark style="background-color: ${highlighter.color}88;">${highlighter.value}</mark>`
);
}
return value;
};
const highlightData = (data: any): any => {
const recursiveHighlight = (obj: any, parentKey: string = ''): any => {
if (typeof obj === 'string') {
// Check and apply highlighters if necessary
let highlighted = obj;
highlighters.forEach((highlighter) => {
if (highlighter.properties.some(prop => prop === parentKey)) {
highlighted = highlightValue(highlighted, highlighter);
}
});
return highlighted;
} else if (typeof obj === 'object' && obj !== null) {
// Recursively process objects and arrays
const result: any = Array.isArray(obj) ? [] : {};
for (const key in obj) {
const currentKey = parentKey ? `${parentKey}.${key}` : key;
result[key] = recursiveHighlight(obj[key], currentKey);
}
return result;
} else {
return obj; // Return non-string values as-is
}
};
return recursiveHighlight(data);
};
return highlightData;
};
// Example usage of createHighlighter
const highlighters: Highlighter[] = [
{
type: 'string',
value: 'cocaine',
color: 'yellow',
properties: ['_source.text_en', '_source.title_en']
},
{
type: 'regex',
value: '\\b59 million\\b',
color: 'lightblue',
properties: ['_source.text_en']
}
];
const exampleObj = {
"_index": "cocaine",
"_id": "e98c380c38a3652682642ad1a1a280e3",
"_score": null,
"_source": {
"url": "http://example.com",
"seendate": "2017-02-10T21:30:00",
"title_en": "Cocaine on a beach worth 59 million euros in England",
"text_en": "They found a bag of cocaine...",
"gpt_money_total": 500000,
"gpt_coke_total": 360
},
"sort": [4],
"id": 1
};
const applyHighlighter = createHighlighter(highlighters);
console.log(applyHighlighter(exampleObj));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment