rtf-stream-parser
Version:
Stream Transform class to tokenize RTF, and another to de-encapsulate text or HTML
189 lines (188 loc) • 6.24 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.handleFonts = void 0;
const utils_1 = require("../utils");
const charsetToCpg = {
0: 1252,
2: 42,
77: 10000,
78: 10001,
79: 10003,
80: 10008,
81: 10002,
83: 10005,
84: 10004,
85: 10006,
86: 10081,
87: 10021,
88: 10029,
89: 10007,
128: 932,
129: 949,
130: 1361,
134: 936,
136: 950,
161: 1253,
162: 1254,
163: 1258,
177: 1255,
178: 1256,
186: 1257,
204: 1251,
222: 874,
238: 1250,
254: 437,
255: 850,
};
const codepages = {
20127: true,
28591: true,
};
for (const charset in charsetToCpg) {
const cpg = charsetToCpg[charset];
codepages[cpg] = true;
}
const handleThemeFont = (global, cw) => {
if (global._constructingFontTableEntry) {
global._constructingFontTableEntry.themeFont = cw.word.slice(1);
}
};
const handleFontFamily = (global, cw) => {
if (global._constructingFontTableEntry) {
global._constructingFontTableEntry.fontFamily = cw.word.slice(1);
}
};
const fontTokenHandlers = {
[0]: global => {
if (global._constructingFontTable && global._state.destination === 'fonttbl' && global._state.groupDepth === global._state.destGroupDepth + 1) {
global._constructingFontTableEntry = {};
}
},
[1]: global => {
if (global._constructingFontTable && global._state.destination === 'fonttbl' && global._state.groupDepth === global._state.destGroupDepth) {
if (!global._constructingFontTableEntry || !global._constructingFontTableKey) {
throw new Error('Finished a font table group but no key?');
}
global._fonttbl[global._constructingFontTableKey] = global._constructingFontTableEntry;
global._constructingFontTableEntry = undefined;
global._constructingFontTableKey = undefined;
}
if (global._constructingFontTable && global._state.destGroupDepth === 1) {
global._constructingFontTable = false;
}
}
};
const fontControlHandlers = {
deff: (global, cw) => {
if (global._state.destination === 'rtf' && global._state.destDepth > 1 && typeof global._deff !== 'undefined') {
return;
}
if (global._state.destination !== 'rtf' || global._state.destDepth !== 1)
throw new Error('\\deff not at root group');
if (typeof global._deff !== 'undefined')
throw new Error('\\deff already defined');
global._deff = cw.param + '';
},
fonttbl: global => {
if (global._fonttbl && global._state.destGroupDepth > 2) {
global._options.warn('Got additional \\fonttbl');
return;
}
if (global._fonttbl) {
throw new Error('fonttbl already created');
}
else if (global._state.destDepth !== 2 || global._state.destGroupDepth !== 2) {
throw new Error('fonttbl not in header');
}
global._constructingFontTable = true;
global._fonttbl = {};
},
f: (global, cw) => {
if (typeof cw.param === 'undefined') {
throw new Error('No param for \\f');
}
const f = cw.param + '';
if (global._constructingFontTableEntry && global._constructingFontTableKey) {
throw new Error('\\f control word in font group which already has \\f');
}
else if (global._constructingFontTableEntry) {
global._constructingFontTableKey = f;
}
else {
global._state.font = f;
}
},
fcharset: (global, cw) => {
if (!global._constructingFontTableEntry) {
return;
}
if (!utils_1.isNum(cw.param)) {
throw new Error('fcharset with no param');
}
if (cw.param !== 1) {
let cpg = charsetToCpg[cw.param];
if (!utils_1.isNum(cpg) && codepages[cw.param]) {
cpg = cw.param;
}
if (!utils_1.isNum(cpg)) {
global._options.warn('No codepage for charset ' + cw.param);
}
else {
global._constructingFontTableEntry.fcharsetCpg = cpg;
}
}
},
cpg: (global, cw) => {
if (!global._constructingFontTableEntry) {
return;
}
const cpg = cw.param;
if (!utils_1.isNum(cpg)) {
global._options.warn('No codepage given');
}
else {
global._constructingFontTableEntry.cpg = cpg;
}
},
flomajor: handleThemeFont,
fhimajor: handleThemeFont,
fdbmajor: handleThemeFont,
fbimajor: handleThemeFont,
flominor: handleThemeFont,
fhiminor: handleThemeFont,
fdbminor: handleThemeFont,
fbiminor: handleThemeFont,
fnil: handleFontFamily,
froman: handleFontFamily,
fswiss: handleFontFamily,
fmodern: handleFontFamily,
fscript: handleFontFamily,
fdecor: handleFontFamily,
ftech: handleFontFamily,
fbidi: handleFontFamily,
};
const fontTextHandler = (global, data) => {
if (global._constructingFontTableEntry) {
if (!utils_1.isStr(data)) {
data = data.toString('latin1');
}
data = data.replace(/[^\x00-\x7F]/g, c => {
const hex = c.charCodeAt(0).toString(16).toUpperCase();
return '\\u' + '0000'.slice(0, 4 - hex.length) + hex;
});
let str = (global._constructingFontTableEntry.fontName || '') + data;
if (str.endsWith(';')) {
str = str.substr(0, str.length - 1);
if (str.length > 2 && str.startsWith('"') && str.endsWith('"')) {
str = str.substr(1, str.length - 2);
}
}
global._constructingFontTableEntry.fontName = str;
return true;
}
};
exports.handleFonts = {
tokenHandlers: fontTokenHandlers,
controlHandlers: fontControlHandlers,
outputDataFilter: fontTextHandler
};