"use strict";
import t_xml from "./t_xml";
import { Color } from "../colz";
import JSZip from "jszip";
function base64ArrayBuffer(arrayBuff) {
const buff = new Uint8Array(arrayBuff);
let text = "";
for (let i = 0; i < buff.byteLength; i++) {
text += String.fromCharCode(buff[i]);
}
return btoa(text);
}
function extractFileExtension(filename) {
const dot = filename.lastIndexOf(".");
if (dot === 0 || dot === -1) return "";
return filename.substr(filename.lastIndexOf(".") + 1);
}
/*
function escapeHtml (text) {
const map = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
'\'': '''
}
return text.replace(/[&<>"']/g, m => map[m])
}
*/
export default function processPptx(setOnMessage = () => {}, postMessage) {
const charts = [];
let chartID = 0;
let themeContent = null;
let slideLayoutClrOvride = "";
const styleTable = {};
let tableStyles;
// 设置postMessage方法
setOnMessage(async (e) => {
switch (e.type) {
case "processPPTX": {
try {
await processPPTX(e.data);
} catch (e) {
console.error("AN ERROR HAPPENED DURING processPPTX", e);
postMessage({
type: "ERROR",
data: e.toString(),
});
}
break;
}
default:
}
});
async function processPPTX(data) {
const zip = await JSZip.loadAsync(data);
const dateBefore = new Date();
if (zip.file("docProps/thumbnail.jpeg") !== null) {
const pptxThumbImg = await zip
.file("docProps/thumbnail.jpeg")
.async("base64");
postMessage({
type: "pptx-thumb",
data: pptxThumbImg,
});
}
const filesInfo = await getContentTypes(zip);
const slideSize = await getSlideSize(zip);
themeContent = await loadTheme(zip);
tableStyles = await readXmlFile(zip, "ppt/tableStyles.xml");
postMessage({
type: "slideSize",
data: slideSize,
});
const numOfSlides = filesInfo["slides"].length;
for (let i = 0; i < numOfSlides; i++) {
const filename = filesInfo["slides"][i];
const slideHtml = await processSingleSlide(zip, filename, i, slideSize);
postMessage({
type: "slide",
data: slideHtml,
});
postMessage({
type: "progress-update",
data: ((i + 1) * 100) / numOfSlides,
});
}
postMessage({
type: "globalCSS",
data: genGlobalCSS(),
});
const dateAfter = new Date();
postMessage({
type: "Done",
data: {
time: dateAfter - dateBefore,
charts,
},
});
}
async function readXmlFile(zip, filename) {
return t_xml(await zip.file(filename).async("text"));
}
async function getContentTypes(zip) {
const ContentTypesJson = await readXmlFile(zip, "[Content_Types].xml");
// console.log('CONTENT TYPES JSON', ContentTypesJson)
const subObj = ContentTypesJson["Types"]["Override"];
const slidesLocArray = [];
const slideLayoutsLocArray = [];
for (let i = 0; i < subObj.length; i++) {
switch (subObj[i]["attrs"]["ContentType"]) {
case "application/vnd.openxmlformats-officedocument.presentationml.slide+xml":
slidesLocArray.push(subObj[i]["attrs"]["PartName"].substr(1));
break;
case "application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml":
slideLayoutsLocArray.push(subObj[i]["attrs"]["PartName"].substr(1));
break;
default:
}
}
return {
slides: slidesLocArray,
slideLayouts: slideLayoutsLocArray,
};
}
async function getSlideSize(zip) {
// Pixel = EMUs * Resolution / 914400; (Resolution = 96)
const content = await readXmlFile(zip, "ppt/presentation.xml");
const sldSzAttrs = content["p:presentation"]["p:sldSz"]["attrs"];
return {
width: (parseInt(sldSzAttrs["cx"]) * 96) / 914400,
height: (parseInt(sldSzAttrs["cy"]) * 96) / 914400,
};
}
async function loadTheme(zip) {
const preResContent = await readXmlFile(
zip,
"ppt/_rels/presentation.xml.rels"
);
const relationshipArray = preResContent["Relationships"]["Relationship"];
let themeURI;
if (relationshipArray.constructor === Array) {
for (let i = 0; i < relationshipArray.length; i++) {
if (
relationshipArray[i]["attrs"]["Type"] ===
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme"
) {
themeURI = relationshipArray[i]["attrs"]["Target"];
break;
}
}
} else if (
relationshipArray["attrs"]["Type"] ===
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme"
) {
themeURI = relationshipArray["attrs"]["Target"];
}
if (themeURI === undefined) {
throw Error("Can't open theme file.");
}
return readXmlFile(zip, "ppt/" + themeURI);
}
async function processSingleSlide(zip, sldFileName, index, slideSize) {
postMessage({
type: "INFO",
data: "Processing slide" + (index + 1),
});
// =====< Step 1 >=====
// Read relationship filename of the slide (Get slideLayoutXX.xml)
// @sldFileName: ppt/slides/slide1.xml
// @resName: ppt/slides/_rels/slide1.xml.rels
const resName =
sldFileName.replace("slides/slide", "slides/_rels/slide") + ".rels";
const resContent = await readXmlFile(zip, resName);
let RelationshipArray = resContent["Relationships"]["Relationship"];
let layoutFilename = "";
const slideResObj = {};
if (RelationshipArray.constructor === Array) {
for (let i = 0; i < RelationshipArray.length; i++) {
switch (RelationshipArray[i]["attrs"]["Type"]) {
case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout":
layoutFilename = RelationshipArray[i]["attrs"]["Target"].replace(
"../",
"ppt/"
);
break;
case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/notesSlide":
case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image":
case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart":
case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink":
default: {
slideResObj[RelationshipArray[i]["attrs"]["Id"]] = {
type: RelationshipArray[i]["attrs"]["Type"].replace(
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/",
""
),
target: RelationshipArray[i]["attrs"]["Target"].replace(
"../",
"ppt/"
),
};
}
}
}
} else {
layoutFilename = RelationshipArray["attrs"]["Target"].replace(
"../",
"ppt/"
);
}
// console.log(slideResObj);
// Open slideLayoutXX.xml
const slideLayoutContent = await readXmlFile(zip, layoutFilename);
const slideLayoutTables = indexNodes(slideLayoutContent);
const sldLayoutClrOvr =
slideLayoutContent["p:sldLayout"]["p:clrMapOvr"]["a:overrideClrMapping"];
// console.log(slideLayoutClrOvride);
if (sldLayoutClrOvr !== undefined) {
slideLayoutClrOvride = sldLayoutClrOvr["attrs"];
}
// =====< Step 2 >=====
// Read slide master filename of the slidelayout (Get slideMasterXX.xml)
// @resName: ppt/slideLayouts/slideLayout1.xml
// @masterName: ppt/slideLayouts/_rels/slideLayout1.xml.rels
const slideLayoutResFilename =
layoutFilename.replace(
"slideLayouts/slideLayout",
"slideLayouts/_rels/slideLayout"
) + ".rels";
const slideLayoutResContent = await readXmlFile(
zip,
slideLayoutResFilename
);
RelationshipArray = slideLayoutResContent["Relationships"]["Relationship"];
评论2