From 7c6535b41a39d91dc610e77e11b7b44bdf555f12 Mon Sep 17 00:00:00 2001 From: Roel van Uden Date: Fri, 23 Jan 2015 19:32:51 +0100 Subject: [PATCH] Add ASS support. --- src/subtitle/formats/ass.js | 92 +++++++++++++++++++++++++++++++++++ src/subtitle/formats/index.js | 1 + 2 files changed, 93 insertions(+) create mode 100644 src/subtitle/formats/ass.js diff --git a/src/subtitle/formats/ass.js b/src/subtitle/formats/ass.js new file mode 100644 index 0000000..0a1eab0 --- /dev/null +++ b/src/subtitle/formats/ass.js @@ -0,0 +1,92 @@ +'use strict'; +var xml2js = require('xml2js'); + +/** + * Converts an input buffer to a SubStation Alpha subtitle. + * @param {Buffer|string} input + * @param {function(Error, string=)} done + */ +module.exports = function(input, done) { + if (typeof buffer !== 'string') input = input.toString(); + xml2js.parseString(input, { + explicitArray: false, + explicitRoot: false + }, function(err, xml) { + if (err) return done(err); + try { + done(undefined, _script(xml) + '\n' + + _style(xml.styles) + '\n' + + _event(xml.events)); + } catch(err) { + done(err); + } + }); +}; + +/** + * Converts the event block. + * @param {Object} events + * @returns {string} + */ +function _event(events) { + var format = 'Layer,Start,End,Style,Name,MarginL,MarginR,MarginV,Effect,Text'; + var items = [].concat(events.event).map(function(style) { + return _values(style.$, 'Dialogue: 0,{start},{end},{style},{name},' + + '{margin_l},{margin_r},{margin_v},{effect},{text}'); + }); + return '[Events]\n' + + 'Format: ' + format + '\n' + + items.join('\n') + '\n'; +} + +/** + * Converts the script block. + * @param {Object} script + * @returns {string} + */ +function _script(script) { + return _values(script.$, + '[Script Info]\n' + + 'Title: {title}\n' + + 'ScriptType: v4.00+\n' + + 'WrapStyle: {wrap_style}\n' + + 'PlayResX: {play_res_x}}\n' + + 'PlayResY: {play_res_y}\n' + + 'Subtitle ID: {id}\n' + + 'Language: {lang_string}\n' + + 'Created: {created}\n'); +} + +/** + * Converts the style block. + * @param {Object} styles + * @returns {string} + */ +function _style(styles) { + var format = 'Name,Fontname,Fontsize,PrimaryColour,SecondaryColour,' + + 'OutlineColour,BackColour,Bold,Italic,Underline,StrikeOut,ScaleX,' + + 'ScaleY,Spacing,Angle,BorderStyle,Outline,Shadow,Alignment,' + + 'MarginL,MarginR,MarginV,Encoding'; + var items = [].concat(styles.style).map(function(style) { + return _values(style.$, 'Style: {name},{font_name},{font_size}, ' + + '{primary_colour},{secondary_colour},{outline_colour}, ' + + '{back_colour},{bold},{italic},{underline},{strikeout},{scale_x}, ' + + '{scale_y},{spacing},{angle},{border_style},{outline},{shadow},' + + '{alignment},{margin_l},{margin_r},{margin_v},{encoding}'); + }); + return '[V4+ Styles]\n' + + 'Format: ' + format + '\n' + + items.join('\n') + '\n'; +} + +/** + * Fills a predetermined format with the values from the attributes. + * @param {Object.} attributes + * @param {string} value + * @returns {string} + */ +function _values(attributes, format) { + return format.replace(/{([^}]+)}/g, function(match, key) { + return attributes[key] || ''; + }); +} diff --git a/src/subtitle/formats/index.js b/src/subtitle/formats/index.js index c944dd5..57a7798 100644 --- a/src/subtitle/formats/index.js +++ b/src/subtitle/formats/index.js @@ -1,3 +1,4 @@ module.exports = { + ass: require('./ass'), srt: require('./srt') };