UNPKG

propresenter-parser

Version:

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

282 lines (281 loc) 12.7 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.v6Builder = void 0; const fast_xml_parser_1 = require("fast-xml-parser"); const js_base64_1 = require("js-base64"); const shared_model_1 = require("../shared.model"); const Utils = __importStar(require("../utils")); class v6Builder { constructor(options) { this.winFontData = `<?xml version="1.0" encoding="utf-16"?><RVFont xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/ProPresenter.Common"><Kerning>0</Kerning><LineSpacing>0</LineSpacing><OutlineColor xmlns:d2p1="http://schemas.datacontract.org/2004/07/System.Windows.Media"><d2p1:A>255</d2p1:A><d2p1:B>0</d2p1:B><d2p1:G>0</d2p1:G><d2p1:R>0</d2p1:R><d2p1:ScA>1</d2p1:ScA><d2p1:ScB>0</d2p1:ScB><d2p1:ScG>0</d2p1:ScG><d2p1:ScR>0</d2p1:ScR></OutlineColor><OutlineWidth>0</OutlineWidth><Variants>Normal</Variants></RVFont>`; this.defaultTransitionObj = { '@rvXMLIvarName': 'transitionObject', '@transitionType': shared_model_1.IProTransitionType.None, '@transitionDirection': 0, '@transitionDuration': 1, '@motionEnabled': false, '@motionDuration': 0, '@motionSpeed': 0, '@groupIndex': 0, '@orderIndex': 0, '@slideBuildAction': 0, '@slideBuildDelay': 0, }; this.xmlBuilder = new fast_xml_parser_1.XMLBuilder({ attributeNamePrefix: '@', format: true, ignoreAttributes: false, processEntities: false, suppressUnpairedNode: false, suppressBooleanAttributes: false, unpairedTags: ['array', 'RVTransition'], }); this.options = options; const defaultProperties = { CCLIArtistCredits: '', CCLIAuthor: '', CCLIDisplay: false, CCLIPublisher: '', category: 'Song', notes: '', height: 720, width: 1280, }; this.options.properties = Object.assign(Object.assign({}, defaultProperties), this.options.properties); const defaultSlideTextFormatting = { textColor: { r: 255, g: 255, b: 255 }, textPadding: 20, fontName: 'Arial', textSize: 60, textShadow: { angle: 135, color: { r: 0, g: 0, b: 0 }, enabled: false, length: 7, radius: 10, }, }; this.options.slideTextFormatting = Object.assign(Object.assign({}, defaultSlideTextFormatting), this.options.slideTextFormatting); } build() { var _a, _b; const documentObj = { '?xml': { '@version': '1.0', '@encoding': 'utf-8', }, RVPresentationDocument: { '@CCLIArtistCredits': this.options.properties.CCLIArtistCredits, '@CCLIAuthor': this.options.properties.CCLIAuthor, '@CCLICopyrightYear': (_a = this.options.properties.CCLICopyrightYear) !== null && _a !== void 0 ? _a : '', '@CCLIDisplay': this.options.properties.CCLIDisplay, '@CCLIPublisher': this.options.properties.CCLIPublisher, '@CCLISongNumber': (_b = this.options.properties.CCLISongNumber) !== null && _b !== void 0 ? _b : '', '@CCLISongTitle': this.options.properties.CCLISongTitle, '@category': this.options.properties.category, '@notes': this.options.properties.notes, '@lastDateUsed': Utils.getIsoDateString(), '@height': this.options.properties.height, '@width': this.options.properties.width, '@backgroundColor': '0 0 0 1', '@buildNumber': 6016, '@chordChartPath': '', '@docType': 0, '@drawingBackgroundColor': false, '@resourcesDirectory': '', '@selectedArrangementID': '', '@os': 1, '@usedCount': 0, '@versionNumber': 600, RVTransition: this.getTransitions(), RVTimeline: { '@rvXMLIvarName': 'timeline', '@timeOffset': 0, '@duration': 0, '@selectedMediaTrackIndex': 0, '@loop': false, array: [{ '@rvXMLIvarName': 'timeCues' }, { '@rvXMLIvarName': 'mediaTracks' }], }, array: [ { '@rvXMLIvarName': 'groups', RVSlideGrouping: this.buildSlideGroups(), }, { '@rvXMLIvarName': 'arrangements', RVSongArrangement: [], }, ], }, }; return this.xmlBuilder.build(documentObj).trim(); } getTransitions() { if (this.options.transitions) { const transitionsCopy = Object.assign({}, this.defaultTransitionObj); transitionsCopy['@transitionDuration'] = this.options.transitions.duration; transitionsCopy['@transitionType'] = this.options.transitions.type; return transitionsCopy; } return this.defaultTransitionObj; } buildSlideGroups() { var _a; const xmlSlideGroups = []; for (const group of this.options.slideGroups) { xmlSlideGroups.push({ '@name': group.label, '@uuid': Utils.getUniqueID(), '@color': Utils.normalizeColorToRgbaString((_a = group.groupColor) !== null && _a !== void 0 ? _a : '0 0 0 0'), array: { '@rvXMLIvarName': 'slides', RVDisplaySlide: this.buildSlidesForGroup(group), }, }); } return xmlSlideGroups; } buildSlidesForGroup(thisGroup) { var _a, _b; const xmlSlides = []; for (const slide of thisGroup.slides) { let highlightColor = '0 0 0 0'; let label = ''; let text; if (typeof slide === 'string') { text = slide; } else { highlightColor = Utils.normalizeColorToRgbaString((_a = slide.slideColor) !== null && _a !== void 0 ? _a : highlightColor); label = (_b = slide.label) !== null && _b !== void 0 ? _b : ''; text = slide.text; } xmlSlides.push({ '@backgroundColor': '0 0 0 0', '@highlightColor': highlightColor, '@drawingBackgroundColor': false, '@enabled': true, '@hotKey': '', '@label': label, '@notes': '', '@UUID': Utils.getUniqueID(), '@chordChartPath': '', array: [ { '@rvXMLIvarName': 'cues' }, { '@rvXMLIvarName': 'displayElements', RVTextElement: [this.buildTextElement(text)], }, ], }); } return xmlSlides; } buildTextElement(text) { const rtfText = Utils.formatRtf(text, this.options.slideTextFormatting.fontName, this.options.slideTextFormatting.textSize, Utils.normalizeColorToRgbObj(this.options.slideTextFormatting.textColor)); return { '@displayName': 'Default', '@UUID': Utils.getUniqueID(), '@typeID': 0, '@displayDelay': 0, '@locked': false, '@persistent': 0, '@fromTemplate': false, '@opacity': 1, '@source': '', '@bezelRadius': 0, '@rotation': 0, '@drawingFill': false, '@drawingShadow': this.options.slideTextFormatting.textShadow.enabled, '@drawingStroke': false, '@fillColor': '1 1 1 0', '@adjustsHeightToFit': false, '@verticalAlignment': 0, '@revealType': 0, RVRect3D: { '@rvXMLIvarName': 'position', '#text': this.getTextElementPosition(), }, shadow: { '@rvXMLIvarName': 'shadow', '#text': this.getElementShadow() }, dictionary: { '@rvXMLIvarName': 'stroke', NSColor: { '@rvXMLDictionaryKey': 'RVShapeElementStrokeColorKey', '#text': '0 0 0 1', }, NSNumber: { '@rvXMLDictionaryKey': 'RVShapeElementStrokeWidthKey', '@hint': 'double', '#text': 0, }, }, NSString: [ { '@rvXMLIvarName': 'PlainText', '#text': js_base64_1.Base64.encode(text) }, { '@rvXMLIvarName': 'RTFData', '#text': js_base64_1.Base64.encode(rtfText) }, { '@rvXMLIvarName': 'WinFlowData', '#text': js_base64_1.Base64.encode(this.getWinFlowDocument(text)) }, { '@rvXMLIvarName': 'WinFontData', '#text': js_base64_1.Base64.encode(this.winFontData) }, ], }; } getTextElementPosition() { const posX = this.options.slideTextFormatting.textPadding; const posY = this.options.slideTextFormatting.textPadding; const width = this.options.properties.width - this.options.slideTextFormatting.textPadding * 2; const height = this.options.properties.height - this.options.slideTextFormatting.textPadding * 2; return `{${posX} ${posY} 0 ${width} ${height}}`; } getElementShadow() { const radius = this.options.slideTextFormatting.textShadow.radius; const color = Utils.normalizeColorToRgbaString(this.options.slideTextFormatting.textShadow.color); const angle = this.options.slideTextFormatting.textShadow.angle; const length = this.options.slideTextFormatting.textShadow.length; const posX = Math.sin(angle * (Math.PI / 180)) * length; const posY = Math.cos(angle * (Math.PI / 180)) * length; return `${radius}|${color}|{${posX}, ${posY}}`; } getWinFlowDocument(text) { const fontName = this.options.slideTextFormatting.fontName; const size = this.options.slideTextFormatting.textSize; const hexColor = Utils.normalizeColorToHex(this.options.slideTextFormatting.textColor); const paragraphs = text .split(/[\n\r]/g) .filter((line) => line !== '') .map((line) => `<Paragraph Margin="0,0,0,0" TextAlignment="Center" FontFamily="${fontName}" FontSize="${size}"><Run FontFamily="${fontName}" FontSize="${size}" Foreground="#${hexColor}FF" Block.TextAlignment="Center">${line}</Run></Paragraph>`) .join(''); return `<FlowDocument TextAlignment="Center" PagePadding="5,0,5,0" AllowDrop="True" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">${paragraphs}</FlowDocument>`; } } exports.v6Builder = v6Builder;