@antv/narrative-text-schema
Version:
Json schema of narrative text visualization
69 lines (65 loc) • 2.15 kB
text/typescript
import { PhraseSpec, EntityType } from '../schema';
/**
* parse string template to phrases
* @example
* str = `<%= time %>, <%= columnAlias$$metric_name$$ %> is <%= price$$metric_value$$ %>`
* data = { time: "2020", columnAlias: "price total", price: "123" }
* =>
* [
* { type: "text", value: "2020" },
* { type: "text", value: ", " },
* { type: "entity", value: "price total", metadata: { entityType: metric_name } },
* { type: "text", value: " is " },
* { type: "entity", value: "123", metadata: { entityType: metric_value } },
* ]
*/
export function generateSentence(
template: string,
formattedData?: Record<string, string>,
originalData?: Record<string, unknown>,
): PhraseSpec[] {
const splitReg = /(<%= [\s\S]*?(::\w*?)? %>)/;
const variableReg = /<%= ([\s\S]*?)(\$\$(\w*)\$\$)? %>/;
return template.split(splitReg).reduce<PhraseSpec[]>((prev, curr) => {
if (curr) {
const variable = variableReg.exec(curr);
if (variable && variable[1] && formattedData && typeof formattedData[variable[1]] === 'string') {
const formattedVal = formattedData[variable[1]];
if (variable[3]) {
const eType = variable[3] as EntityType;
const result: PhraseSpec = {
type: 'entity',
value: formattedVal,
metadata: {
entityType: eType,
},
};
const origin = originalData ? originalData[variable[1]] : undefined;
if (
(result.metadata.entityType === 'delta_value' || result.metadata.entityType === 'ratio_value') &&
typeof origin === 'number'
) {
if (origin > 0) {
result.metadata.assessment = 'positive';
}
if (origin < 0) {
result.metadata.assessment = 'negative';
}
}
prev.push(result);
} else {
prev.push({
type: 'text',
value: formattedVal,
});
}
} else {
prev.push({
type: 'text',
value: curr,
});
}
}
return prev;
}, []);
}