activator-oce-exporter
Version:
Extract Activator binder and convert it to valid OCE mono pacakge
280 lines (261 loc) • 9.53 kB
JavaScript
;
const decompress = require('decompress');
const fs = require('fs');
const gulp = require('gulp');
const clean = require('gulp-clean');
const zip = require('gulp-zip');
const path = require('path');
const exporter = require('anthill-exporter');
const slidesMap = {};
const filesExceptions = ['presentation.json', 'shared'];
const getSlideName = (id, nodes) => {
const node = nodes.find(obj => obj.version_id === id);
return node.name__v || id;
};
const addPrefix = (index) => {
const newIndex = index + 1;
return newIndex < 10 ? '0' + newIndex : newIndex;
};
const moveFile = (file, rename, index, dir) => {
return new Promise((resolve, reject) => {
const prefixIndex = addPrefix(index);
const fileName = path.basename(file);
const newIndexName = `${prefixIndex}_${rename || fileName}`;
const dest = path.resolve(dir, newIndexName);
fs.rename(file, dest, (err, data) => {
if (err) return reject(err);
resolve(data);
});
});
};
//Update relative paths in index
const updatePaths = (file, currentDirectory, filesUsedInIndex) => {
return new Promise((resolve, reject) => {
fs.readFile(file, async (err, data) => {
if (err) return reject(err);
// Update shared path
let replaceText = data.toString().replace(/\.\.\//g, './');
// Add OCE script
replaceText = replaceText.replace(
'</head>',
'<script>if (window.CLMPlayer) { window.oce = { config: {{{.}}} } }</script></head>'
);
filesUsedInIndex.forEach((fileName) => {
if (fileName === 'assets') {
const newReg = new RegExp(fileName, 'g');
replaceText = replaceText.replace(newReg, `./${fileName}`);
const newReg2 = new RegExp(`src="./shared/./${currentDirectory}/${fileName}`, 'g');
replaceText = replaceText.replace(newReg2, `src="./shared/${fileName}`);
// const newReg2 = new RegExp('url(assets', 'g');
// replaceText = replaceText.replace(newReg2, `url("./${currentDirectory}/${fileName}`);
} else {
const newReg = new RegExp(fileName, 'g');
replaceText = replaceText.replace(newReg, `./${fileName}`);
}
});
await fs.writeFile(file, replaceText, (err) => {
if (err) return reject(err);
resolve(data);
});
});
});
};
//Return files from a directory
const readCurrentDirectory = (dir) => {
return new Promise((resolve, reject) => {
fs.readdir(dir, (err, files) => {
if (err) return reject(err);
resolve(files);
});
});
};
// ./shared/src/getbundle.js refers to ./shared/dist/main.js
const updateGetBundle = (outPutPath) => {
return new Promise((resolve, reject) => {
const getBundleFile = `${outPutPath}/shared/src/getbundle.js`;
fs.readFile(getBundleFile, async (err, data) => {
if (err) return reject(err);
let replaceText = data.toString().replace(/\..\//g, './');
await fs.writeFile(getBundleFile, replaceText, (err) => {
if (err) return reject(err);
resolve(data);
});
});
});
};
// param binderDocs - The nodes object from presentation.json
const createNavigationConfig = (binderDocs, outPutPath) => {
return new Promise((resolve, reject) => {
const oceFolder = `${outPutPath}/shared/src/fusion/oce/navigation`;
const mapContent = binderDocs.reduce((map, doc) => {
const id = doc['version_id'].split('_');
map[id[0]] = doc.name__v;
return map;
}, {});
const navigationMap = {"navigationMap": mapContent};
fs.writeFile(`${oceFolder}/oce.navigation-config.json`, JSON.stringify(navigationMap), (err) => {
if (err) return reject(err);
resolve(navigationMap);
});
});
};
const convertFiles = (files, output, input) => {
return new Promise(async (resolve, reject) => {
try {
// Read presentation.json. Check first if presentation.json exists
const presentationJson = files.find((file) => file.path.includes('presentation.json'));
if (!presentationJson) throw Error('ERROR: Presentation.json not found');
const temp = JSON.parse(presentationJson.data.toString());
const nodes = temp.nodes;
const presentationJsonPath = path.basename(presentationJson.path);
fs.unlink(`${output}/${presentationJsonPath}`, () => {});
if (!nodes.length) throw Error('ERROR: Presentation.json does not have node key');
await renameFiles(output, nodes);
await updateGetBundle(output);
await createNavigationConfig(nodes, output);
for (let index = 0; index < nodes.length; index++) {
// const slide = getSlideName(nodes[index].id);
const slide = nodes[index].name__v;
const currentDirectory = `${output}/${slide}`;
const indexFile = `${currentDirectory}/index.html`;
//Extract the files which are linked in the index
const filesUsedInIndex = await readCurrentDirectory(currentDirectory);
await updatePaths(indexFile, `${slide}`, filesUsedInIndex);
//Move index.html
const indexFile2 = `./${output}/${slide}/index.html`;
await moveFile(indexFile2, `${slide}.html`, 0, `${output}/${slide}`);
//Move thumb.png and convert to jpg
const thumbFile = `./${output}/${slide}/thumb.png`;
await moveFile(thumbFile, 'thumbnail.jpg', 0, `${output}/${slide}`);
//Move shared to each sequence
const sharedFolder = `./${output}/shared/**/*`;
await new Promise((resolve, reject) => {
gulp.src([sharedFolder, `!${output}/shared/exports/**/*`, `!${output}/shared/node_modules`])
.pipe(gulp.dest(`${output}/${slide}/shared`))
.on('end', resolve);
});
//Zip data
await new Promise((resolve, reject) => {
// const zipName = slide.split('_')[0];
gulp.src(`${output}/${slide}/**/*`)
.pipe(zip(`${addPrefix(index)}_${slide}.zip`))
.on('error', reject)
.pipe(gulp.dest(`${output}`))
.on('end', async () => {
await deleteFolder(`${output}/${slide}`);
console.log(`created zip for ${slide}`);
resolve();
});
});
}
// Delete shared folder
await deleteFolder(`${output}/shared`);
const config = {
path: output,
output: output,
dot: true,
dest: `../`,
ignore: ['node_modules', '*/__MACOSX', 'exports', '.DS_Store'] // excludes the folders
};
//Compress dist folder
const exporterPath = await exporter('.', config);
// Only leave the final zip package
deleteFolder(`${output}`);
resolve('./oce-exports');
} catch (error) {
return reject(error);
}
});
};
const deleteFolder = (path) => {
return new Promise(async (resolve, reject) => {
gulp.src(path, { read: false }).pipe(clean())
.on('error', reject)
.on('finish', () => {
console.log('Folder deleted', path);
resolve();
});
});
};
const renameFiles = async (input, presentationJsonNodes) => {
const filePath = path.resolve(process.cwd(), input);
const files = await fs.promises.readdir(filePath);
const filesPromises = files.map((file) => {
return (
!filesExceptions.includes(file) &&
fs.promises.rename(path.join(filePath, file), path.join(filePath, getSlideName(file, presentationJsonNodes)))
);
});
return Promise.all(filesPromises);
};
const oceExporter = (input, output) => {
return new Promise(async (resolve, reject) => {
const inputPath = path.parse(input);
//If the input is a zip file
if (inputPath.ext && inputPath.ext.includes('.zip')) {
// Unzip binder
try {
await decompress(input, output).then(async (files) => {
const exporterPath = await convertFiles(files, output, input);
resolve(exporterPath);
});
} catch (error) {
deleteFolder(output);
reject(error);
}
} else {
//If the input is a directory, extract the files
try {
const startPath = path.resolve(process.cwd(), input);
const srcActivatorPkg = path.join(startPath, '/**/*');
const finalPath = path.resolve(process.cwd(), output);
console.log('Paths', startPath, finalPath);
gulp.src([
srcActivatorPkg,
`!${startPath}/shared/node_modules/**/*`,
`!${startPath}/shared/oce-exports/**/*`,
])
.pipe(gulp.dest(finalPath))
.on('end', () => {
fs.readdir(finalPath, async (err, files) => {
if (err) {
deleteFolder(output);
return reject(err);
}
// find presentation.json file inside the directory
const presentationJson = files.find((file) => {
return file.includes('presentation.json');
});
if (!presentationJson) {
deleteFolder(output);
return reject('ERROR: Presentation.json not found');
}
fs.readFile(`${finalPath}/${presentationJson}`, async (err, data) => {
if (err) {
deleteFolder(output);
return reject(err);
}
const presentationJsonInfo = [
{
path: `${finalPath}/${presentationJson}`,
data,
},
];
try {
const exporterPath = await convertFiles(presentationJsonInfo, output, input);
resolve(exporterPath);
} catch (error) {
// deleteFolder(output);
return reject(error);
}
});
});
});
} catch (error) {
deleteFolder(output);
return reject(error);
}
}
});
};
module.exports = oceExporter;