ass-compiler
Version:
Parses and compiles ASS subtitle format to easy-to-use data structure.
90 lines (84 loc) • 2.7 kB
JavaScript
import { compileDrawing } from './drawing.js';
import { compileTag } from './tag.js';
const a2an = [
null, 1, 2, 3,
null, 7, 8, 9,
null, 4, 5, 6,
];
const globalTags = ['r', 'a', 'an', 'pos', 'org', 'move', 'fade', 'fad', 'clip'];
function inheritTag(pTag) {
return JSON.parse(JSON.stringify(Object.assign({}, pTag, {
k: undefined,
kf: undefined,
ko: undefined,
kt: undefined,
})));
}
export function compileText({ styles, style, parsed, start, end }) {
let alignment;
let q = { q: styles[style].tag.q };
let pos;
let org;
let move;
let fade;
let clip;
const slices = [];
let slice = { style, fragments: [] };
let prevTag = {};
for (let i = 0; i < parsed.length; i++) {
const { tags, text, drawing } = parsed[i];
let reset;
for (let j = 0; j < tags.length; j++) {
const tag = tags[j];
reset = tag.r === undefined ? reset : tag.r;
}
const fragment = {
tag: reset === undefined ? inheritTag(prevTag) : {},
text,
drawing: drawing.length ? compileDrawing(drawing) : null,
};
for (let j = 0; j < tags.length; j++) {
const tag = tags[j];
alignment = alignment || a2an[tag.a || 0] || tag.an;
q = compileTag(tag, 'q') || q;
if (!move) {
pos = pos || compileTag(tag, 'pos');
}
org = org || compileTag(tag, 'org');
if (!pos) {
move = move || compileTag(tag, 'move');
}
fade = fade || compileTag(tag, 'fade') || compileTag(tag, 'fad');
clip = compileTag(tag, 'clip') || clip;
const key = Object.keys(tag)[0];
if (key && !~globalTags.indexOf(key)) {
const sliceTag = styles[style].tag;
const { c1, c2, c3, c4 } = sliceTag;
const fs = prevTag.fs || sliceTag.fs;
const compiledTag = compileTag(tag, key, { start, end, c1, c2, c3, c4, fs });
if (key === 't') {
fragment.tag.t = fragment.tag.t || [];
fragment.tag.t.push(compiledTag.t);
} else {
Object.assign(fragment.tag, compiledTag);
}
}
}
prevTag = fragment.tag;
if (reset !== undefined) {
slices.push(slice);
slice = { style: styles[reset] ? reset : style, fragments: [] };
}
if (fragment.text || fragment.drawing) {
const prev = slice.fragments[slice.fragments.length - 1] || {};
if (prev.text && fragment.text && !Object.keys(fragment.tag).length) {
// merge fragment to previous if its tag is empty
prev.text += fragment.text;
} else {
slice.fragments.push(fragment);
}
}
}
slices.push(slice);
return Object.assign({ alignment, slices }, q, pos, org, move, fade, clip);
}