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

Re-enable using commands as api #243

Merged
merged 4 commits into from
Feb 1, 2022
Merged
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
125 changes: 125 additions & 0 deletions src/build.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import chalk from 'chalk';
zwaldowski marked this conversation as resolved.
Show resolved Hide resolved
import terminalLink from 'terminal-link';
import path from 'upath';
import { getExecutableBrowserPath } from './browser';
import { checkOverwriteViolation, compile, copyAssets } from './builder';
import {
CliFlags,
collectVivliostyleConfig,
mergeConfig,
MergedConfig,
} from './config';
import { checkContainerEnvironment } from './container';
import { buildPDF, buildPDFWithContainer } from './pdf';
import { teardownServer } from './server';
import { cwd, debug, log, startLogging, stopLogging } from './util';
import { exportWebPublication } from './webbook';

export interface BuildCliFlags extends CliFlags {
output?: {
output?: string;
format?: string;
}[];
bypassedPdfBuilderOption?: string;
}

export async function build(cliFlags: BuildCliFlags) {
if (cliFlags.bypassedPdfBuilderOption) {
const option = JSON.parse(cliFlags.bypassedPdfBuilderOption);
// Host doesn't know inside path of chromium path
option.executableChromium = getExecutableBrowserPath();
debug('bypassedPdfBuilderOption', option);

await buildPDF(option);
log();
return;
}

const isInContainer = checkContainerEnvironment();
if (!isInContainer) {
startLogging('Collecting build config');
}

const loadedConf = collectVivliostyleConfig(cliFlags);
const { vivliostyleConfig, vivliostyleConfigPath } = loadedConf;
cliFlags = loadedConf.cliFlags;

const context = vivliostyleConfig ? path.dirname(vivliostyleConfigPath) : cwd;

const config = await mergeConfig(cliFlags, vivliostyleConfig, context);
checkUnsupportedOutputs(config);

// check output path not to overwrite source files
for (const target of config.outputs) {
checkOverwriteViolation(config, target.path, target.format);
}

// build artifacts
if (config.manifestPath) {
await compile(config);
await copyAssets(config);
}

// generate files
for (const target of config.outputs) {
let output: string | null = null;
if (target.format === 'pdf') {
if (!isInContainer && target.renderMode === 'docker') {
output = await buildPDFWithContainer({
...config,
input: (config.manifestPath ??
config.webbookEntryPath ??
config.epubOpfPath) as string,
target,
});
} else {
output = await buildPDF({
...config,
input: (config.manifestPath ??
config.webbookEntryPath ??
config.epubOpfPath) as string,
target,
});
}
} else if (target.format === 'webpub') {
if (!config.manifestPath) {
continue;
}
output = await exportWebPublication({
...config,
input: config.workspaceDir,
output: target.path,
});
}
if (output) {
const formattedOutput = chalk.bold.green(path.relative(cwd, output));
log(
`\n${terminalLink(formattedOutput, 'file://' + output, {
fallback: () => formattedOutput,
})} has been created.`,
);
}
}

if (!isInContainer) {
stopLogging('Built successfully.', '🎉');
}

teardownServer();
}

function checkUnsupportedOutputs({
webbookEntryPath,
epubOpfPath,
outputs,
}: MergedConfig) {
if (webbookEntryPath && outputs.some((t) => t.format === 'webpub')) {
throw new Error(
'Exporting webpub format from single HTML input is not supported.',
);
} else if (epubOpfPath && outputs.some((t) => t.format === 'webpub')) {
throw new Error(
'Exporting webpub format from EPUB or OPF file is not supported.',
);
}
}
11 changes: 2 additions & 9 deletions src/commands/build.parser.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,8 @@
import commander from 'commander';
import { CliFlags, validateTimeoutFlag } from '../config';
import { BuildCliFlags } from '../build';
import { validateTimeoutFlag } from '../config';
import { checkOutputFormat, detectOutputFormat, OutputFormat } from '../output';

export interface BuildCliFlags extends CliFlags {
output?: {
output?: string;
format?: string;
}[];
bypassedPdfBuilderOption?: string;
}

export function setupBuildParserProgram(): commander.Command {
// Provide an order-sensitive command parser
// ex: "-o foo -o bar -f baz"
Expand Down
124 changes: 3 additions & 121 deletions src/commands/build.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,7 @@
import chalk from 'chalk';
import process from 'process';
import terminalLink from 'terminal-link';
import path from 'upath';
import { getExecutableBrowserPath } from '../browser';
import { checkOverwriteViolation, compile, copyAssets } from '../builder';
import { collectVivliostyleConfig, mergeConfig, MergedConfig } from '../config';
import { checkContainerEnvironment } from '../container';
import { buildPDF, buildPDFWithContainer } from '../pdf';
import { teardownServer } from '../server';
import {
cwd,
debug,
gracefulError,
log,
startLogging,
stopLogging,
} from '../util';
import { exportWebPublication } from '../webbook';
import { BuildCliFlags, setupBuildParserProgram } from './build.parser';
import { build } from '../build';
import { gracefulError } from '../util';
import { setupBuildParserProgram } from './build.parser';

try {
const program = setupBuildParserProgram();
Expand Down Expand Up @@ -51,105 +35,3 @@ try {
} catch (err) {
gracefulError(err);
}

export default async function build(cliFlags: BuildCliFlags) {
if (cliFlags.bypassedPdfBuilderOption) {
const option = JSON.parse(cliFlags.bypassedPdfBuilderOption);
// Host doesn't know inside path of chromium path
option.executableChromium = getExecutableBrowserPath();
debug('bypassedPdfBuilderOption', option);

await buildPDF(option);
log();
process.exit(0);
}

const isInContainer = checkContainerEnvironment();
if (!isInContainer) {
startLogging('Collecting build config');
}

const loadedConf = collectVivliostyleConfig(cliFlags);
const { vivliostyleConfig, vivliostyleConfigPath } = loadedConf;
cliFlags = loadedConf.cliFlags;

const context = vivliostyleConfig ? path.dirname(vivliostyleConfigPath) : cwd;

const config = await mergeConfig(cliFlags, vivliostyleConfig, context);
checkUnsupportedOutputs(config);

// check output path not to overwrite source files
for (const target of config.outputs) {
checkOverwriteViolation(config, target.path, target.format);
}

// build artifacts
if (config.manifestPath) {
await compile(config);
await copyAssets(config);
}

// generate files
for (const target of config.outputs) {
let output: string | null = null;
if (target.format === 'pdf') {
if (!isInContainer && target.renderMode === 'docker') {
output = await buildPDFWithContainer({
...config,
input: (config.manifestPath ??
config.webbookEntryPath ??
config.epubOpfPath) as string,
target,
});
} else {
output = await buildPDF({
...config,
input: (config.manifestPath ??
config.webbookEntryPath ??
config.epubOpfPath) as string,
target,
});
}
} else if (target.format === 'webpub') {
if (!config.manifestPath) {
continue;
}
output = await exportWebPublication({
...config,
input: config.workspaceDir,
output: target.path,
});
}
if (output) {
const formattedOutput = chalk.bold.green(path.relative(cwd, output));
log(
`\n${terminalLink(formattedOutput, 'file://' + output, {
fallback: () => formattedOutput,
})} has been created.`,
);
}
}

if (!isInContainer) {
stopLogging('Built successfully.', '🎉');
}

teardownServer();
process.exit(0);
}

export function checkUnsupportedOutputs({
webbookEntryPath,
epubOpfPath,
outputs,
}: MergedConfig) {
if (webbookEntryPath && outputs.some((t) => t.format === 'webpub')) {
throw new Error(
'Exporting webpub format from single HTML input is not supported.',
);
} else if (epubOpfPath && outputs.some((t) => t.format === 'webpub')) {
throw new Error(
'Exporting webpub format from EPUB or OPF file is not supported.',
);
}
}
8 changes: 0 additions & 8 deletions src/commands/init.parser.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,5 @@
import commander from 'commander';

export interface InitCliFlags {
title?: string;
author?: string;
language?: string;
theme?: string;
size?: string;
}

export function setupInitParserProgram(): commander.Command {
const program = new commander.Command();
program
Expand Down
57 changes: 3 additions & 54 deletions src/commands/init.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import chalk from 'chalk';
import fs from 'fs';
import path from 'upath';
import { CONTAINER_IMAGE } from '../container';
import { cwd, gracefulError, log } from '../util';
import { InitCliFlags, setupInitParserProgram } from './init.parser';
import { init } from '../init';
import { gracefulError } from '../util';
import { setupInitParserProgram } from './init.parser';

try {
const program = setupInitParserProgram();
Expand All @@ -19,51 +16,3 @@ try {
} catch (err) {
gracefulError(err);
}

export default async function init(cliFlags: InitCliFlags) {
const vivliostyleConfigPath = path.join(cwd, 'vivliostyle.config.js');

if (fs.existsSync(vivliostyleConfigPath)) {
return log(
`${chalk.yellow('vivliostyle.config.js already exists. aborting.')}`,
);
}

// prettier-ignore
const vivliostyleConfig = `module.exports = {
title: '${ cliFlags.title || 'Principia'}', // populated into 'publication.json', default to 'title' of the first entry or 'name' in 'package.json'.
author: '${cliFlags.author || 'Isaac Newton'}', // default to 'author' in 'package.json' or undefined
${cliFlags.language ? '' : '// '}language: '${cliFlags.language || 'la'}',
${cliFlags.size ? '' : '// '}size: '${cliFlags.size || 'A4'}',
${cliFlags.theme ? '' : '// '}theme: '${cliFlags.theme || ''}', // .css or local dir or npm package. default to undefined
image: '${CONTAINER_IMAGE}',
entry: [ // **required field**
// 'introduction.md', // 'title' is automatically guessed from the file (frontmatter > first heading)
// {
// path: 'epigraph.md',
// title: 'おわりに', // title can be overwritten (entry > file),
// theme: '@vivliostyle/theme-whatever' // theme can be set indivisually. default to root 'theme'
// },
// 'glossary.html' // html is also acceptable
], // 'entry' can be 'string' or 'object' if there's only single markdown file
// entryContext: './manuscripts', // default to '.' (relative to 'vivliostyle.config.js')
// output: [ // path to generate draft file(s). default to '{title}.pdf'
// './output.pdf', // the output format will be inferred from the name.
// {
// path: './book',
// format: 'webpub',
// },
// ],
// workspaceDir: '.vivliostyle', // directory which is saved intermediate files.
// toc: true, // whether generate and include ToC HTML or not, default to 'false'.
// cover: './cover.png', // cover image. default to undefined.
// vfm: { // options of VFM processor
// hardLineBreaks: true, // converts line breaks of VFM to <br> tags. default to 'false'.
// disableFormatHtml: true, // disables HTML formatting. default to 'false'.
// },
};
`;

fs.writeFileSync(vivliostyleConfigPath, vivliostyleConfig);
log(`Successfully created ${chalk.cyan('vivliostyle.config.js')}`);
}
3 changes: 0 additions & 3 deletions src/commands/preview.parser.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
import commander from 'commander';
import { CliFlags } from '../config';

export interface PreviewCliFlags extends CliFlags {}

export function setupPreviewParserProgram(): commander.Command {
const program = new commander.Command();
Expand Down
Loading