UNPKG

propresenter-parser

Version:

Parses ProPresenter 4, 5, and 6 files to extract the data, and can build ProPresenter 5 and 6 files

172 lines (171 loc) 8.18 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.v5Parser = void 0; const fast_xml_parser_1 = require("fast-xml-parser"); const js_base64_1 = require("js-base64"); const Utils = __importStar(require("../utils")); class v5Parser { parse(fileContent) { const alwaysArray = [ 'RVPresentationDocument.timeline.timeCues', 'RVPresentationDocument.timeline.mediaTracks', 'RVPresentationDocument.arrangements.RVSongArrangement', 'RVPresentationDocument.arrangements.RVSongArrangement.groupIDs.NSMutableString', 'RVPresentationDocument.groups.RVSlideGrouping', 'RVPresentationDocument.groups.RVSlideGrouping.slides.RVDisplaySlide', 'RVPresentationDocument.groups.RVSlideGrouping.slides.RVDisplaySlide.cues.RVMediaCue', 'RVPresentationDocument.groups.RVSlideGrouping.slides.RVDisplaySlide.displayElements.RVTextElement', ]; const xmlParser = new fast_xml_parser_1.XMLParser({ ignoreAttributes: false, attributeNamePrefix: '@', parseAttributeValue: true, isArray: (_name, jPath) => alwaysArray.includes(jPath), }); const parsedDoc = xmlParser.parse(fileContent); if (parsedDoc.RVPresentationDocument['@versionNumber'] !== 500) { throw new Error(`Expected a ProPresenter 5 file with versionNumber="500" but got versionNumber="${parsedDoc.RVPresentationDocument['@versionNumber']}"`); } const properties = this.getProperties(parsedDoc.RVPresentationDocument); const slideGroups = this.getSlideGroups(parsedDoc.RVPresentationDocument.groups.RVSlideGrouping); const arrangements = this.getArrangements(parsedDoc.RVPresentationDocument, slideGroups); return { properties, slideGroups, arrangements }; } getProperties(xmlDoc) { var _a, _b, _c, _d, _e; return { CCLIArtistCredits: (_a = xmlDoc['@CCLIArtistCredits']) !== null && _a !== void 0 ? _a : '', CCLICopyrightInfo: (_b = xmlDoc['@CCLICopyrightInfo']) !== null && _b !== void 0 ? _b : '', CCLIDisplay: Boolean(xmlDoc['@CCLIDisplay']), CCLILicenseNumber: (_c = xmlDoc['@CCLILicenseNumber']) !== null && _c !== void 0 ? _c : '', CCLIPublisher: (_d = xmlDoc['@CCLIPublisher']) !== null && _d !== void 0 ? _d : '', CCLISongTitle: (_e = xmlDoc['@CCLISongTitle']) !== null && _e !== void 0 ? _e : '', album: xmlDoc['@album'], artist: xmlDoc['@artist'], author: xmlDoc['@author'], backgroundColor: Utils.normalizeColorToRgbObj(xmlDoc['@backgroundColor']), category: xmlDoc['@category'], creatorCode: xmlDoc['@creatorCode'], chordChartPath: xmlDoc['@chordChartPath'], docType: xmlDoc['@docType'], drawingBackgroundColor: Boolean(xmlDoc['@drawingBackgroundColor']), height: xmlDoc['@height'], lastDateUsed: new Date(xmlDoc['@lastDateUsed']), notes: xmlDoc['@notes'], resourcesDirectory: xmlDoc['@resourcesDirectory'], usedCount: xmlDoc['@usedCount'], versionNumber: xmlDoc['@versionNumber'], width: xmlDoc['@width'], }; } getSlideGroups(xmlGroups) { return xmlGroups.map((sg) => { var _a; const groupColor = sg['@color'] === '' ? null : Utils.normalizeColorToRgbObj(sg['@color']); return { groupColor, groupLabel: (_a = sg['@name']) !== null && _a !== void 0 ? _a : '', groupId: sg['@uuid'], slides: this.getSlidesForGroup(sg.slides.RVDisplaySlide), }; }); } getSlidesForGroup(xmlSlides) { return xmlSlides.map((slide) => { let textElements = []; if (slide.displayElements.RVTextElement) { textElements = slide.displayElements.RVTextElement.map((txt) => { const decodedContent = js_base64_1.Base64.decode(txt['@RTFData']); const textProps = Utils.getTextPropsFromRtf(decodedContent); return { position: { x: txt['_-RVRect3D-_position']['@x'], y: txt['_-RVRect3D-_position']['@y'], z: txt['_-RVRect3D-_position']['@z'], height: txt['_-RVRect3D-_position']['@height'], width: txt['_-RVRect3D-_position']['@width'], }, rawRtfContent: decodedContent, textContent: Utils.stripRtf(decodedContent), color: textProps.color, font: textProps.font, size: textProps.size, }; }); } let mediaCues = []; if (slide.cues.RVMediaCue) { mediaCues = slide.cues.RVMediaCue.map((cue) => ({ displayName: cue.element['@displayName'], source: cue.element['@source'], })); } const highlightColor = slide['@highlightColor'] === '' ? null : Utils.normalizeColorToRgbObj(slide['@highlightColor']); return { backgroundColor: Utils.normalizeColorToRgbObj(slide['@backgroundColor']), chordChartPath: slide['@chordChartPath'], enabled: Boolean(slide['@enabled']), highlightColor, id: slide['@UUID'], label: slide['@label'], notes: slide['@notes'], mediaCues, textElements, }; }); } getArrangements(xmlDoc, slideGroups) { var _a; const arrangementsArr = []; if ((_a = xmlDoc.arrangements) === null || _a === void 0 ? void 0 : _a.RVSongArrangement) { for (const a of xmlDoc.arrangements.RVSongArrangement) { arrangementsArr.push({ color: Utils.normalizeColorToRgbObj(a['@color']), label: a['@name'], groupOrder: a.groupIDs.NSMutableString.map((group) => { const slideGroupMatch = slideGroups.find((sg) => sg.groupId === group['@serialization-native-value']); return { groupId: group['@serialization-native-value'], groupLabel: slideGroupMatch.groupLabel, }; }), }); } } return arrangementsArr; } } exports.v5Parser = v5Parser;