Start new HTML export logic
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
158
app/controllers/api/v1/Export.controller.js
Normal file
158
app/controllers/api/v1/Export.controller.js
Normal file
@@ -0,0 +1,158 @@
|
||||
const { Controller } = require('libflitter')
|
||||
const ncp = require('ncp').ncp
|
||||
const fs = require('fs').promises
|
||||
const path = require('path')
|
||||
|
||||
class ExportController extends Controller {
|
||||
static get services() {
|
||||
return [...super.services, 'models', 'utility']
|
||||
}
|
||||
|
||||
async get_export_list(req, res, next) {
|
||||
const Export = this.models.get('api:Export')
|
||||
const exports = await Export.find({
|
||||
user_id: req.user.id,
|
||||
})
|
||||
|
||||
return res.api(exports)
|
||||
}
|
||||
|
||||
async export_subtree(req, res, next) {
|
||||
const format = req.form.format
|
||||
const page = req.form.page
|
||||
|
||||
if ( format === 'html' ) {
|
||||
const generated_export = await this.export_subtree_as_html(page, req.user)
|
||||
}
|
||||
}
|
||||
|
||||
async export_subtree_as_html(page, user) {
|
||||
const flat_tree = []
|
||||
|
||||
const add_to_tree = async (page, level = 0) => {
|
||||
if ( await page.is_accessible_by(user, 'view') ) {
|
||||
flat_tree.push({
|
||||
level,
|
||||
page,
|
||||
file_name: `${page.Name.replace(/\s/g, '-')}-${page.UUID}.html`,
|
||||
})
|
||||
|
||||
const children = await page.childPages
|
||||
for ( const child of children ) {
|
||||
await add_to_tree(child, level + 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await add_to_tree(page)
|
||||
|
||||
const manifest = {
|
||||
sidebar: [],
|
||||
}
|
||||
|
||||
for ( const item of flat_tree ) {
|
||||
manifest.sidebar.push({
|
||||
title: item.page.Name,
|
||||
level: item.level,
|
||||
link: item.file_name,
|
||||
})
|
||||
}
|
||||
|
||||
// Copy the template over
|
||||
const work_dir = await this.scratch_dir()
|
||||
await this.copy_template(this.utility.path('app', 'assets', 'export', 'html'), work_dir)
|
||||
|
||||
const html_template = await fs.readFile(path.resolve(work_dir, 'index.html'), 'utf-8')
|
||||
|
||||
for ( const item of flat_tree ) {
|
||||
let item_template = html_template
|
||||
|
||||
item_template = item_template.replace(/{{\s?MANIFEST\s?}}/g, JSON.stringify(manifest))
|
||||
item_template = item_template.replace(/{{\s?GROUP_TITLE\s?}}/g, page.Name)
|
||||
item_template = item_template.replace(/{{\s?PAGE_TITLE\s?}}/g, item.page.Name)
|
||||
item_template = item_template.replace(/{{\s?PAGE_CONTENT\s?}}/g, await this.page_as_html(item.page, work_dir))
|
||||
|
||||
await fs.writeFile(path.resolve(work_dir, item.file_name), item_template)
|
||||
}
|
||||
|
||||
return work_dir
|
||||
}
|
||||
|
||||
async copy_template(from, to) {
|
||||
return new Promise((res, rej) => {
|
||||
ncp(from, to, err => {
|
||||
if ( err ) rej(err)
|
||||
else res()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
async scratch_dir() {
|
||||
const tmp = require('tmp')
|
||||
|
||||
return new Promise((res, rej) => {
|
||||
tmp.dir((err, path) => {
|
||||
if ( err ) rej(err)
|
||||
else res(path)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
async page_as_html(page, work_dir) {
|
||||
const Codium = this.models.get('api:Codium')
|
||||
const FileGroup = this.models.get('api:FileGroup')
|
||||
const File = this.models.get('upload::File')
|
||||
|
||||
let html = ''
|
||||
|
||||
const nodes = await page.nodes
|
||||
for ( const node of nodes ) {
|
||||
// ATM, there are 4 node types: norm, database_ref, files_ref, and code_ref
|
||||
|
||||
if ( node.Value.Mode === 'norm' ) {
|
||||
html += node.Value.Value
|
||||
} else if ( node.Type === 'code_ref' ) {
|
||||
const code = await Codium.findOne({ UUID: node.Value.Value })
|
||||
if ( code ) {
|
||||
const snip_file = `code-snippet-${code.UUID}.txt`
|
||||
await fs.writeFile(path.resolve(work_dir, snip_file), code.code)
|
||||
|
||||
html += `
|
||||
<div class="code-ref">
|
||||
<wc-monaco-editor id="${code.UUID}" language="${code.Language}" src="${snip_file}"></wc-monaco-editor>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
} else if ( node.Type === 'file_ref' ) {
|
||||
const file_group = await FileGroup.findOne({ UUID: node.Value.Value })
|
||||
if ( file_group ) {
|
||||
const file_htmls = []
|
||||
|
||||
for ( const file_id of file_group.FileIds ) {
|
||||
const file = await File.findById(file_id)
|
||||
if ( file ) {
|
||||
const store_path = file.provider().filepath(file.store_id)
|
||||
await this.copy_template(store_path, path.resolve(work_dir, `file-${file.upload_name}`))
|
||||
|
||||
file_htmls.push(`
|
||||
<div class="file">
|
||||
<div class="file-name">${file.original_name}</div>
|
||||
<a href="file-${file.upload_name}" class="dl-link" target="_blank">▼</a>
|
||||
</div>
|
||||
`)
|
||||
}
|
||||
}
|
||||
|
||||
html += `
|
||||
<div class="file-ref">
|
||||
${file_htmls.join('\n')}
|
||||
</div>`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return html
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = exports = ExportController
|
||||
Reference in New Issue
Block a user