src/subtitle/formats/srt.ts
'use strict';
import xml2js = require('xml2js');
/**
* Converts an input buffer to a SubRip subtitle.
*/
export default function(config: IConfig, input: Buffer|string, done: (err: Error, subtitle?: string) => void)
{
const options = {explicitArray: false, explicitRoot: false};
xml2js.parseString(input.toString(), options, (err: Error, xml: ISubtitle) =>
{
try
{
if (err)
{
return done(err);
}
done(null, xml.events.event.map((event, index) =>
{
const attributes = event.$;
return (index + 1) + '\n' +
time(attributes.start) + ' --> ' + time(attributes.end) + '\n' +
text(attributes.text) + '\n';
}).join('\n'));
} catch (err)
{
done(err);
}
});
}
/**
* Prefixes a value.
*/
function prefix(value: string, length: number): string
{
while (value.length < length)
{
value = '0' + value;
}
return value;
}
/**
* Suffixes a value.
*/
function suffix(value: string, length: number): string
{
while (value.length < length)
{
value = value + '0';
}
return value;
}
/**
* Formats a text value.
*/
function text(value: string): string
{
return value
.replace(/{\\i1}/g, '<i>').replace(/{\\i0}/g, '</i>')
.replace(/{\\b1}/g, '<b>').replace(/{\\b0}/g, '</b>')
.replace(/{\\u1}/g, '<u>').replace(/{\\u0}/g, '</u>')
.replace(/{[^}]+}/g, '')
.replace(/(\s+)?\\n(\s+)?/ig, '\n')
.trim();
}
/**
* Formats a time stamp.
*/
function time(value: string): string
{
const all = value.match(/^([0-9]+):([0-9]+):([0-9]+)\.([0-9]+)$/);
if (!all)
{
throw new Error('Invalid time.');
}
const hours = prefix(all[1], 2);
const minutes = prefix(all[2], 2);
const seconds = prefix(all[3], 2);
const milliseconds = suffix(all[4], 3);
return hours + ':' + minutes + ':' + seconds + ',' + milliseconds;
}