diff --git a/fiduswriter/pandoc/static/js/modules/pandoc/app.js b/fiduswriter/pandoc/static/js/modules/pandoc/app.js new file mode 100644 index 0000000..ec56aa2 --- /dev/null +++ b/fiduswriter/pandoc/static/js/modules/pandoc/app.js @@ -0,0 +1,35 @@ +import {getJson} from "../common" + +import {formats} from "./constants" +import {PandocConversionImporter} from "./importer" + +import {registerImporter} from "../importer/register" + +export class AppPandoc { + constructor(app) { + this.app = app + + this.pandocAvailable = null + } + + init() { + this.checkPandoc().then(() => { + if (this.pandocAvailable) { + registerImporter( + formats.map(format => [format[0], format[1]]), + PandocConversionImporter + ) + } + }) + } + + checkPandoc() { + if (this.pandocAvailable !== null) { + return Promise.resolve(this.pandocAvailable) + } + + return getJson("/api/pandoc/available/").then(({available}) => { + this.pandocAvailable = available + }) + } +} diff --git a/fiduswriter/pandoc/static/js/modules/pandoc/constants.js b/fiduswriter/pandoc/static/js/modules/pandoc/constants.js index a10fa1f..ac632d7 100644 --- a/fiduswriter/pandoc/static/js/modules/pandoc/constants.js +++ b/fiduswriter/pandoc/static/js/modules/pandoc/constants.js @@ -1,14 +1,18 @@ export const formats = [ - "docx", - "odt", - "doc", - "latex", - "markdown", - "mediawiki", - "org", - "rst", - "textile", - "html", - "json", - "zip" + // file formats that can be converted by pandoc + // see https://pandoc.org/MANUAL.html#general-options + // for a list of supported formats. + // The first element is the format as presented to the user, + // the second element is the file extensions. + // the third element is the format as used by pandoc, + // the fourth element is whether it is a binary format. + ["DOCX", ["docx"], "docx", true], + ["LaTeX", ["tex"], "latex", false], + ["Markdown", ["md"], "markdown", false], + ["JATS XML", ["xml"], "jats", false], + ["Emacs Org Mode", ["org"], "org", false], + ["reStructuredText", ["rst"], "rst", false], + ["Textile", ["textile"], "textile", false], + ["HTML", ["html", "htm"], "html", false], + ["EPUB", ["epub"], "epub", true] ] diff --git a/fiduswriter/pandoc/static/js/modules/pandoc/document_overview.js b/fiduswriter/pandoc/static/js/modules/pandoc/document_overview.js deleted file mode 100644 index f281991..0000000 --- a/fiduswriter/pandoc/static/js/modules/pandoc/document_overview.js +++ /dev/null @@ -1,55 +0,0 @@ -import {getJson} from "../common" - -import {formats} from "./constants" -import {PandocConversionImporter} from "./importer" - -export class DocumentOverviewPandoc { - constructor(documentOverview) { - this.documentOverview = documentOverview - - this.pandocAvailable = null - } - - init() { - this.checkPandoc().then(() => { - if (this.pandocAvailable) { - this.modifyMenu() - this.modifyExternalImporter() - } - }) - } - - checkPandoc() { - if (this.pandocAvailable !== null) { - return Promise.resolve(this.pandocAvailable) - } - - return getJson("/api/pandoc/available/").then(({available}) => { - this.pandocAvailable = available - }) - } - - modifyMenu() { - const menu = this.documentOverview.menu - let menuItem = menu.model.content.find( - menuItem => menuItem.id === "import_external" - ) - if (!menuItem) { - menuItem = { - id: "import_external" - } - menu.model.contents.push(menuItem) - } - menuItem.title = gettext("Import document") - menuItem.description = gettext("Import a document in another format") - menuItem.icon = "file" - menu.update() - } - - modifyExternalImporter() { - const actions = this.documentOverview.mod.actions - actions.externalFormats = actions.externalFormats.concat(formats) - actions.externalFormatsTitle = gettext("Import Pandoc JSON/ZIP file") - actions.externalFileImporter = PandocConversionImporter - } -} diff --git a/fiduswriter/pandoc/static/js/modules/pandoc/helpers.js b/fiduswriter/pandoc/static/js/modules/pandoc/helpers.js index 62bec87..bf5d81b 100644 --- a/fiduswriter/pandoc/static/js/modules/pandoc/helpers.js +++ b/fiduswriter/pandoc/static/js/modules/pandoc/helpers.js @@ -5,3 +5,18 @@ export const fileToBase64 = file => reader.onload = () => resolve(reader.result.split("base64,")[1]) reader.readAsDataURL(file) }) + + +export const fileToString = (file, binary = false) => { + + if (binary) { + return fileToBase64(file) + } else { + return new Promise((resolve, reject) => { + const reader = new window.FileReader() + reader.onerror = reject + reader.onload = () => resolve(reader.result) + reader.readAsText(file) + }) + } +} diff --git a/fiduswriter/pandoc/static/js/modules/pandoc/importer.js b/fiduswriter/pandoc/static/js/modules/pandoc/importer.js index 48c602c..a175fe7 100644 --- a/fiduswriter/pandoc/static/js/modules/pandoc/importer.js +++ b/fiduswriter/pandoc/static/js/modules/pandoc/importer.js @@ -2,16 +2,17 @@ import {jsonPost} from "../common" import {PandocImporter} from "../importer/pandoc" import {formats} from "./constants" -import {fileToBase64} from "./helpers" +import {fileToString} from "./helpers" export class PandocConversionImporter extends PandocImporter { init() { return this.getTemplate().then(() => { - if (this.file.type === "application/json") { - return this.importJSON() - } else if (this.file.type === "application/zip") { - return this.importZip() - } else if (formats.includes(this.file.name.split(".").pop())) { + if ( + formats + .map(format => format[1]) + .flat() + .includes(this.file.name.split(".").pop()) + ) { return this.convertAndImport() } else { this.output.statusText = gettext("Unknown file type") @@ -21,14 +22,17 @@ export class PandocConversionImporter extends PandocImporter { } convertAndImport() { - const from = this.file.name.split(".").pop() - return fileToBase64(this.file) - .then(base64String => { + const fromExtension = this.file.name.split(".").pop() + const format = formats.find(format => format[1].includes(fromExtension)) + const from = format[2] + const binary = format[3] + return fileToString(this.file, binary) + .then(text => { return jsonPost("/api/pandoc/export/", { from, to: "json", standalone: true, - text: base64String + text }) }) .then(response => response.json()) @@ -37,7 +41,11 @@ export class PandocConversionImporter extends PandocImporter { this.output.statusText = json.error return this.output } - return this.handlePandocJson(json.output) + return this.handlePandocJson( + json.output, + this.additionalFiles?.images, + this.additionalFiles?.bibliography + ) }) } } diff --git a/fiduswriter/pandoc/static/js/plugins/app/pandoc.js b/fiduswriter/pandoc/static/js/plugins/app/pandoc.js new file mode 100644 index 0000000..63793fb --- /dev/null +++ b/fiduswriter/pandoc/static/js/plugins/app/pandoc.js @@ -0,0 +1 @@ +export {AppPandoc} from "../../modules/pandoc/app" diff --git a/fiduswriter/pandoc/static/js/plugins/documents_overview/pandoc.js b/fiduswriter/pandoc/static/js/plugins/documents_overview/pandoc.js deleted file mode 100644 index 294ffde..0000000 --- a/fiduswriter/pandoc/static/js/plugins/documents_overview/pandoc.js +++ /dev/null @@ -1 +0,0 @@ -export {DocumentOverviewPandoc} from "../../modules/pandoc/document_overview"