Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: use esm module #20

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
{
"extends": ["eslint:recommended", "plugin:node/recommended"],
"env": {
"es2021": true,
"node": true
},
"parserOptions": {
"ecmaVersion": 2020
"sourceType": "module"
},
"rules": {
"semi": ["error", "never"]
}
"extends": [
"eslint:recommended",
"plugin:node/recommended",
"plugin:import/recommended",
"plugin:prettier/recommended",
"prettier"
],
"rules": {}
}
7 changes: 7 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"semi": false,
"trailingComma": "all",
"singleQuote": true,
"printWidth": 120,
"endOfLine": "auto"
}
119 changes: 54 additions & 65 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,70 +1,59 @@
#!/usr/bin/env node
import clear from 'clear'

const clear = require("clear")

const build = require("./lib/build")
const getFormats = require("./lib/get-formats")
const { installKindlegen } = require("./lib/kindlegen")
const mergeConfig = require("./lib/merge-config")
const { printTitle, info, success, error } = require("./lib/message")
const { getOptions, printVersion, printHelp } = require("./lib/options")
const readConfig = require("./lib/read-config")

const { log, trace } = console
const { exit } = process
import build from './lib/build.js'
import getFormats from './lib/get-formats.js'
import { installKindlegen } from './lib/kindlegen.js'
import mergeConfig from './lib/merge-config.js'
import { printTitle, info, success, error } from './lib/message.js'
import { getOptions, printVersion, printHelp } from './lib/options.js'
import readConfig from './lib/read-config.js'

const settings = { kindlegen: false }

;(async () => {
let options = getOptions()

if (options.help) {
printHelp()
return
}

if (options.version) {
printVersion()
return
}

clear()
printTitle()

try {
settings.kindlegen = await installKindlegen(options.mobi)
} catch (e) {
settings.kindlegen = false
}

let config = await readConfig()
info(`Book detected: "${config.filename}"`)

let { formats } = await getFormats(settings, options)

let builds = []
for (let format of formats) {
let currentConfig = mergeConfig(config, format)
builds.push(
new Promise(function(resolve, reject) {
return build(currentConfig)
.then(() => {
success(`Bounded "${format}" file`)
resolve()
})
.catch(e => {
error(`Error with the format "${format}"`)
reject(e)
})
})
)
}

await Promise.all(builds)
log("✨ Done.")
})
.call(this)
.catch(e => {
trace(e)
exit(1)
})
let options = getOptions()

if (options.help) {
printHelp()
process.exit()
}

if (options.version) {
printVersion()
process.exit()
}

clear()
printTitle()

try {
settings.kindlegen = await installKindlegen(options.mobi)
} catch (e) {
settings.kindlegen = false
}

let config = await readConfig()
info(`Book detected: "${config.filename}"`)

let { formats } = await getFormats(settings, options)

let builds = []
for (let format of formats) {
let currentConfig = mergeConfig(config, format)
builds.push(
new Promise(function (resolve, reject) {
return build(currentConfig)
.then(() => {
success(`Bounded "${format}" file`)
resolve()
})
.catch((e) => {
error(`Error with the format "${format}"`)
reject(e)
})
}),
)
}

await Promise.all(builds)
console.log('✨ Done.')
144 changes: 55 additions & 89 deletions lib/build.js
Original file line number Diff line number Diff line change
@@ -1,77 +1,59 @@
const fs = require("fs")
const os = require("os")
const path = require("path")
const CleanCSS = require("clean-css")
const nodePandoc = require("node-pandoc-promise")

const {
latexHeader,
latexNumber,
latexImage,
latexTOC,
latexTitle,
latexNewPage,
} = require("./helpers/latex")
const stylesheet = require("./helpers/stylesheet")
const { yamlToBool } = require("./utils")
const { epubToMobi } = require("./kindlegen")
const {
import fs from 'fs'
import os from 'os'
import path from 'path'
import CleanCSS from 'clean-css'
import nodePandoc from 'node-pandoc-promise'

import { latexHeader, latexNumber, latexImage, latexTOC, latexTitle, latexNewPage } from './helpers/latex.js'
import stylesheet from './helpers/stylesheet.js'
import { yamlToBool } from './utils.js'
import { epubToMobi } from './kindlegen.js'
import {
extract,
archive,
replaceGeneratorMetadata,
textSubstitutions,
navSubstitutions,
opfSubstitutions,
appendExtraMetadata,
} = require("./edition")
} from './edition.js'

const FORMAT_LATEX = "latex"
const FORMAT_MARKDOWN = "markdown"
const FORMAT_LATEX = 'latex'
const FORMAT_MARKDOWN = 'markdown'

module.exports = async (config) => {
export default async function (config) {
if (!config.filename) {
throw new Error("[Reliure] Filename attribute is missing.")
throw new Error('[Reliure] Filename attribute is missing.')
}

if (!config.files || config.files.length === 0) {
throw new Error(
"[Reliure] Files attribute MUST be an array and contains at least one file."
)
throw new Error('[Reliure] Files attribute MUST be an array and contains at least one file.')
}

let detectedInputFormat = undefined
if (
config.files.filter((file) => file.endsWith(".tex")).length !==
config.files.length
) {
if (config.files.filter((file) => file.endsWith('.tex')).length !== config.files.length) {
detectedInputFormat = FORMAT_LATEX
}
if (
config.files.filter((file) => file.endsWith(".md")).length !==
config.files.length
) {
if (config.files.filter((file) => file.endsWith('.md')).length !== config.files.length) {
detectedInputFormat = FORMAT_MARKDOWN
}
if (detectedInputFormat === undefined) {
throw new Error("[Reliure] Files MUST be in LaTeX or Markdown.")
throw new Error('[Reliure] Files MUST be in LaTeX or Markdown.')
}

let tempPath = fs.mkdtempSync(path.join(os.tmpdir(), "reliure-"))
let tempPath = fs.mkdtempSync(path.join(os.tmpdir(), 'reliure-'))

let args = []

if (config.format === "epub" || config.format === "mobi") {
if (config.format === 'epub' || config.format === 'mobi') {
// add stylesheet
let cssContent = ""
if (
config.ignoreDefaultStyleSheet === undefined ||
!yamlToBool(config.ignoreDefaultStyleSheet)
) {
let cssContent = ''
if (config.ignoreDefaultStyleSheet === undefined || !yamlToBool(config.ignoreDefaultStyleSheet)) {
cssContent = stylesheet
}
if (config.styleSheets && config.styleSheets.length > 0) {
config.styleSheets.forEach((filename) => {
cssContent = `${cssContent}${fs.readFileSync(filename, "utf8")}`
cssContent = `${cssContent}${fs.readFileSync(filename, 'utf8')}`
})
}
cssContent = new CleanCSS({
Expand All @@ -81,9 +63,9 @@ module.exports = async (config) => {
},
},
}).minify(cssContent).styles
let cssFile = path.join(tempPath, "style.css")
fs.writeFileSync(cssFile, cssContent, "utf8")
args.push("--css", cssFile)
let cssFile = path.join(tempPath, 'style.css')
fs.writeFileSync(cssFile, cssContent, 'utf8')
args.push('--css', cssFile)

if (config.coverImage) {
// add cover
Expand All @@ -92,78 +74,65 @@ module.exports = async (config) => {
}
}

if (config.format === "pdf") {
if (config.format === 'pdf') {
// use pdflatex
args.push("--pdf-engine=pdflatex")
args.push('--pdf-engine=pdflatex')

// add nice chapter split for pdf
let headerFile = path.join(tempPath, "header.tex")
fs.writeFileSync(headerFile, latexHeader(config.latexPackages), "utf8")
args.push("--include-in-header", headerFile)
let headerFile = path.join(tempPath, 'header.tex')
fs.writeFileSync(headerFile, latexHeader(config.latexPackages), 'utf8')
args.push('--include-in-header', headerFile)

// add before body: Title + Cover
let latexBeforeBody = latexTitle()
if (config.coverImage) {
latexBeforeBody +=
latexNewPage() +
latexImage(path.join(process.cwd(), config.coverImage)) +
latexNumber(false)
latexBeforeBody += latexNewPage() + latexImage(path.join(process.cwd(), config.coverImage)) + latexNumber(false)
}
let beforeBodyFile = path.join(tempPath, "beforeBody.tex")
fs.writeFileSync(beforeBodyFile, latexBeforeBody, "utf8")
args.push("--include-before-body", beforeBodyFile)
let beforeBodyFile = path.join(tempPath, 'beforeBody.tex')
fs.writeFileSync(beforeBodyFile, latexBeforeBody, 'utf8')
args.push('--include-before-body', beforeBodyFile)

// add after body: TOC + Fourth Cover
let latexAfterBody = latexTOC()
if (config.fourthCoverImage) {
latexAfterBody +=
latexNewPage() +
latexImage(path.join(process.cwd(), config.fourthCoverImage)) +
latexNumber(false)
latexNewPage() + latexImage(path.join(process.cwd(), config.fourthCoverImage)) + latexNumber(false)
}
let afterBodyFile = path.join(tempPath, "afterBody.tex")
fs.writeFileSync(afterBodyFile, latexAfterBody, "utf8")
args.push("--include-after-body", afterBodyFile)
let afterBodyFile = path.join(tempPath, 'afterBody.tex')
fs.writeFileSync(afterBodyFile, latexAfterBody, 'utf8')
args.push('--include-after-body', afterBodyFile)
}

// from latex/markdown to epub/pdf
let outputFormat = "epub"
if (config.format === "pdf") {
outputFormat = "pdf"
let outputFormat = 'epub'
if (config.format === 'pdf') {
outputFormat = 'pdf'
}
args.push("-t", outputFormat)
args.push('-t', outputFormat)

// output file
let outputFile
if (config.format === "mobi") {
outputFile = path.join(tempPath, "temp.epub")
if (config.format === 'mobi') {
outputFile = path.join(tempPath, 'temp.epub')
} else {
outputFile = path.join(
process.cwd(),
`${config.filename}.${config.format}`
)
outputFile = path.join(process.cwd(), `${config.filename}.${config.format}`)
}
args.push("-o", outputFile)
args.push('-o', outputFile)

// add metadata
if (config.metadata) {
for (const key in config.metadata) {
args.push("--metadata", `${key}:${config.metadata[key]}`)
args.push('--metadata', `${key}:${config.metadata[key]}`)
}
}

// compile with pandoc
await nodePandoc(path.join(process.cwd(), config.files[0]), args)

if (config.format === "epub" || config.format === "mobi") {
if (config.format === 'epub' || config.format === 'mobi') {
// Automatically edit epub: apply substitutions, append extra metadata
if (
config.textSubstitutions ||
config.navSubstitutions ||
config.opfSubstitutions ||
config.extraMetadata
) {
let editionTempPath = path.join(tempPath, "edition")
if (config.textSubstitutions || config.navSubstitutions || config.opfSubstitutions || config.extraMetadata) {
let editionTempPath = path.join(tempPath, 'edition')
await extract(editionTempPath, outputFile)
replaceGeneratorMetadata(editionTempPath)
if (config.textSubstitutions) {
Expand All @@ -183,11 +152,8 @@ module.exports = async (config) => {
}
}

if (config.format === "mobi") {
if (config.format === 'mobi') {
// convert epub to mobi
await epubToMobi(
outputFile,
path.join(process.cwd(), `${config.filename}.mobi`)
)
await epubToMobi(outputFile, path.join(process.cwd(), `${config.filename}.mobi`))
}
}
Loading