function chart(inputData, plotOptions) {
const hover = vl.selectSingle()
.encodings('x')
.on('mouseover')
.nearest(true)
.empty('none');
const line = vl.markLine({point: true})
.encode(
vl.x()
.fieldT(plotOptions.xField)
.axis({ title: plotOptions.xLabel, format: plotOptions.xFormat })
.scale({type: plotOptions.xScale}),
vl.y()
.fieldQ(plotOptions.yField)
.axis({ title: plotOptions.yLabel, format: plotOptions.yFormat })
.scale({type: plotOptions.yScale}),
)
.title(plotOptions.title)
.width(400);
const base = line.transform(vl.filter(hover));
const ylabel = {align: 'left', dx: -25, dy: -15};
const xLabel = {align: 'left', dx: -25, dy: -30};
const white = {stroke: 'white', strokeWidth: 10};
return vl.data(inputData)
.transform([
vl.calculate(plotOptions.xLabelTransform).as('xLabel'),
vl.calculate(plotOptions.yLabelTransform).as('yLabel'),
])
.layer(
line,
vl.markRule({color: '#aaa'})
.transform(vl.filter(hover))
.encode(vl.x().fieldT(plotOptions.xField)),
line.markCircle()
.select(hover)
.encode(vl.opacity().if(hover, vl.value(1)).value(0)),
base.markText(ylabel, white).encode(vl.text().field('yLabel')),
base.markText(ylabel).encode(vl.text().field('yLabel')),
base.markText(xLabel, white).encode(vl.text().field('xLabel')),
base.markText(xLabel).encode(vl.text().field('xLabel'))
);
};