pptx-automizer
Version:
A template based pptx generator
201 lines • 8.75 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
const modify_hyperlink_element_1 = __importDefault(require("./modify-hyperlink-element"));
const xml_helper_1 = require("./xml-helper");
const general_helper_1 = require("./general-helper");
/**
* Helper class for modifying hyperlinks in PowerPoint elements
*/
class ModifyHyperlinkHelper {
static createRelationshipData(target, isInternal) {
if (isInternal) {
return {
Type: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide',
Target: `../slides/${target}`,
Id: '', // Will be set later
};
}
return {
Type: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink',
Target: target.toString(),
TargetMode: 'External',
Id: '', // Will be set later
};
}
static addRelationship(relation, relData) {
const relNodes = relation.getElementsByTagName('Relationship');
const maxId = xml_helper_1.XmlHelper.getMaxId(relNodes, 'Id', true);
const newRelId = `rId${maxId}`;
const newRel = relation.ownerDocument.createElement('Relationship');
newRel.setAttribute('Id', newRelId);
Object.entries(relData).forEach(([key, value]) => {
if (value)
newRel.setAttribute(key, value);
});
relNodes.item(0).parentNode.appendChild(newRel);
return newRelId;
}
static addHyperlinkToTextRuns(element, hyperlinkElement) {
const textRuns = element.getElementsByTagName('a:r');
Array.from(textRuns).forEach((run) => {
let rPr = run.getElementsByTagName('a:rPr')[0];
if (!rPr) {
rPr = element.ownerDocument.createElement('a:rPr');
const textElement = run.getElementsByTagName('a:t')[0];
if (textElement) {
run.insertBefore(rPr, textElement);
}
else {
run.appendChild(rPr);
}
}
rPr.appendChild(hyperlinkElement.createHlinkClick());
});
}
static addHyperlinkToParagraph(paragraph, hyperlinkElement) {
const existingText = paragraph.getElementsByTagName('a:t')[0];
const text = (existingText === null || existingText === void 0 ? void 0 : existingText.textContent) || 'Hyperlink';
if (existingText === null || existingText === void 0 ? void 0 : existingText.parentNode) {
paragraph.removeChild(existingText.parentNode);
}
const run = hyperlinkElement.createTextRun(text);
paragraph.appendChild(run);
}
static createNewTextStructure(txBody, hyperlinkElement) {
const p = txBody.ownerDocument.createElement('a:p');
const run = hyperlinkElement.createTextRun('Hyperlink');
p.appendChild(run);
txBody.appendChild(p);
}
}
exports.default = ModifyHyperlinkHelper;
_a = ModifyHyperlinkHelper;
/**
* Set the target URL of a hyperlink
*
* @param target The new target URL for the hyperlink
* @param isExternal Whether the hyperlink is external (true) or internal (false)
* @returns A callback function that modifies the hyperlink
*/
ModifyHyperlinkHelper.setHyperlinkTarget = (target, isExternal = true) => (element, relation) => __awaiter(void 0, void 0, void 0, function* () {
if (!element || !relation) {
general_helper_1.Logger.log('SetHyperlinkTarget: Missing element or relation', 2);
return;
}
// Find existing hyperlinks
const hlinkClicks = element.getElementsByTagName('a:hlinkClick');
if (hlinkClicks.length === 0) {
general_helper_1.Logger.log('No hyperlinks found to modify', 1);
return;
}
// Get all existing rIds from hyperlinks
const existingRIds = Array.from(hlinkClicks)
.map((hlink) => hlink.getAttribute('r:id'))
.filter(Boolean);
if (existingRIds.length === 0) {
general_helper_1.Logger.log('No valid relationship IDs found in hyperlinks', 1);
return;
}
// Create new relationship data
const relData = _a.createRelationshipData(target, !isExternal);
const newRelId = _a.addRelationship(relation, relData);
// Update all hyperlink elements with new relationship ID
Array.from(hlinkClicks).forEach((hlink) => {
// Update relationship ID
hlink.setAttribute('r:id', newRelId);
// Update internal/external specific attributes
if (!isExternal) {
hlink.setAttribute('action', 'ppaction://hlinksldjump');
hlink.setAttribute('xmlns:a', 'http://schemas.openxmlformats.org/drawingml/2006/main');
hlink.setAttribute('xmlns:p14', 'http://schemas.microsoft.com/office/powerpoint/2010/main');
}
else {
hlink.removeAttribute('action');
// Keep xmlns attributes as they're still needed for the relationship
}
});
// Remove old relationships
const relationships = relation.getElementsByTagName('Relationship');
Array.from(relationships).forEach((rel) => {
const relId = rel.getAttribute('Id');
if (relId && existingRIds.includes(relId)) {
relation.removeChild(rel);
}
});
general_helper_1.Logger.log('SetHyperlinkTarget: Successfully updated hyperlink target', 2);
});
/**
* Add a hyperlink to an element
*
* @param target The target URL for external links, or slide number for internal links
* @param isInternalLink
* @returns A callback function that adds a hyperlink
*/
ModifyHyperlinkHelper.addHyperlink = (target, isInternalLink) => (element, relation) => {
if (!element || !relation)
return;
if (typeof target === 'number') {
target = `slide${target}.xml`;
isInternalLink = true;
}
const relData = _a.createRelationshipData(target, isInternalLink);
const newRelId = _a.addRelationship(relation, relData);
const hasHlink = element.getElementsByTagName('a:hlinkClick');
if (hasHlink.item(0)) {
// Link has already been set by e.g. pptxGenJs, don't add another link to element
return;
}
const hyperlinkElement = new modify_hyperlink_element_1.default(element.ownerDocument, newRelId, isInternalLink);
const textRuns = element.getElementsByTagName('a:r');
if (textRuns.length > 0) {
_a.addHyperlinkToTextRuns(element, hyperlinkElement);
}
else {
const paragraphs = element.getElementsByTagName('a:p');
if (paragraphs.length > 0) {
_a.addHyperlinkToParagraph(paragraphs[0], hyperlinkElement);
}
else {
const txBody = element.getElementsByTagName('p:txBody')[0] ||
element.getElementsByTagName('a:txBody')[0];
if (txBody) {
_a.createNewTextStructure(txBody, hyperlinkElement);
}
else {
console.error('No suitable text element found to add hyperlink to');
}
}
}
general_helper_1.Logger.log('AddHyperlink: Successfully completed', 2);
};
/**
* Remove hyperlinks from an element
*
* @returns A callback function that removes hyperlinks
*/
ModifyHyperlinkHelper.removeHyperlink = () => (element, relation) => __awaiter(void 0, void 0, void 0, function* () {
if (!element)
return;
try {
const hlinkClicks = element.getElementsByTagName('a:hlinkClick');
Array.from(hlinkClicks).forEach((hlink) => { var _b; return (_b = hlink.parentNode) === null || _b === void 0 ? void 0 : _b.removeChild(hlink); });
general_helper_1.Logger.log('RemoveHyperlink: Successfully completed', 2);
}
catch (error) {
console.error('Error in RemoveHyperlink:', error);
}
});
//# sourceMappingURL=modify-hyperlink-helper.js.map