const Controller = require('libflitter/controller/Controller') const os = require('os'); const fs = require('fs').promises; const uuid = require('uuid/v4'); const path = require('path'); /* * Export Controller * ------------------------------------------------------------- * Put some description here! */ class Export extends Controller { static get services() { return [...super.services, 'models', 'app'] } /* * Serve the main page. */ async json_export(req, res) { const Page = this.models.get('api:Page') const Node = this.models.get('api:Node') const user = req.user const pages = await Page.find({ OrgUserId: user._id }) const ExportData = {} for (const page of pages) { //for all pages of the user, generate a copy of the data const nodes = await Node.find({ PageId: page.UUID }) const PageData = { ...page } PageData.Nodes = nodes.map(node => { return { ...node } }) ExportData[page.Name] = PageData } return res.api(ExportData) } async markdown_export(req, res) { const Page = this.models.get('api:Page') const Node = this.models.get('api:Node') const user = req.user const page0 = await user.get_root_page() //topmost page const temp_dir = path.resolve(os.tmpdir(), uuid()) await fs.mkdir(temp_dir) await this._markdown_recurse(page0, temp_dir) /* Archive directory */ const exec = require('child_process').exec; exec('cd ' + path.resolve(temp_dir) + '; zip -r archive.zip *', (error) => { if (error) { console.error(`exec error: ${error}`); return res.error(500); return; } return res.sendFile(`${path.resolve(temp_dir, 'archive.zip')}`) }) } async _markdown_recurse(root, temp_dir) { //recursive function for creating directory and generating markdown pages const fs = require('fs').promises const Page = this.models.get('api:Page') const child = await Page.find({ UUID: { $in: root.ChildPageIds } }) for (const page of child) { const markdown = await this._generate_markdown(page) await fs.writeFile(path.resolve(temp_dir, page.Name.replace(/\s/g, '_')) + '.md', markdown) if (page.ChildPageIds && page.ChildPageIds.length) { const sub_temp_dir = path.resolve(temp_dir, page.Name.replace(/\s/g, '_')) // console.log(sub_temp_dir) await fs.mkdir(sub_temp_dir) await this._markdown_recurse(page, sub_temp_dir) } } } async _generate_markdown(page) { //generate mark down const Node = this.models.get('api:Node') const nodes = await Node.find({ PageId: page.UUID }) return nodes.map(x => { if (x.Type === 'click_link') { return '[' + x.Value.Value + ']' + '(' + x.Value.Value + ')' } return x.Value.Value }).join('\n') } async html_export(req, res) { const Page = this.models.get('api:Page') const Node = this.models.get('api:Node') const user = req.user const pages = await Page.find({ OrgUserId: user._id, ParentId: { $ne: '0' } }) const mapping = {} //keeps track of html file UUID and file name const page0 = await user.get_root_page() //topmost page for (const page of pages) { const html_name = page.Name.replace(/\s/g, '_') + '.html' mapping[page.UUID] = html_name } const sidebar_html = await this._generate_sidebar(mapping, user) //generates the sidebar contents const temp_dir = path.resolve(os.tmpdir(), uuid()) //make temporary directory await fs.mkdir(temp_dir) /* Generates html files from template */ for (const page of pages) { const fs = require('fs').promises const contents = (await fs.readFile(path.resolve(this.app.directories.assets, 'export-template.html'))).toString('utf8') const content_html = await this._generate_html(page) const page_html = contents.replace('%%CONTENTS%%', content_html).replace('%%SIDEBAR%%', sidebar_html) await fs.writeFile(path.resolve(temp_dir, mapping[page.UUID]), page_html) } /* Archive directory */ const exec = require('child_process').exec; exec('cd ' + path.resolve(temp_dir) + '; zip -r archive.zip *', (error) => { if (error) { console.error(`exec error: ${error}`); return res.error(500); return; } return res.sendFile(`${path.resolve(temp_dir, 'archive.zip')}`) }) } async _generate_sidebar(mapping, user) {// the absolutely dreadful method to create, sidebar const Page = this.models.get('api:Page') const Node = this.models.get('api:Node') const virt_root = await user.get_root_page() return await this._sidebar_recurse(mapping, virt_root) } async _sidebar_recurse(mapping, parent) { const Page = this.models.get('api:Page') const Node = this.models.get('api:Node') const children = await Page.find({ ParentId: parent.UUID }) let base = '' for (const child of children) { if (child.ChildPageIds.length === 0) { base += '' + child.Name + '' //mapping[child.UUID] gives filename } else { base += '' + child.Name + '' base += '' } } return base } async _generate_html(page) { //generate html page from page and node data const Page = this.models.get('api:Page') const Node = this.models.get('api:Node') const nodes = await Node.find({ PageId: page.UUID }) return nodes.map(x => { return x.to_html() }).join('\n') } } module.exports = exports = Export