Skip to content

Commit

Permalink
fix: relative paths
Browse files Browse the repository at this point in the history
  • Loading branch information
simonhaenisch committed Jan 26, 2020
1 parent 7de6435 commit bb46626
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 28 deletions.
2 changes: 2 additions & 0 deletions readme.md
Expand Up @@ -78,6 +78,8 @@ The pdf is generated into the same directory as the source file and uses the sam
md-to-pdf ./**/*.md
```

_(You might need to enable the `globstar` option in bash for recursive globbing)_

Alternatively, you can pass the markdown in from `stdin`:

```sh
Expand Down
10 changes: 4 additions & 6 deletions src/lib/get-output-file-path.ts
@@ -1,12 +1,10 @@
import { parse, join } from 'path';
import { Config } from './config';
import { parse, resolve } from 'path';

/**
* Derive the output file path from the source markdown file.
* Derive the output file path from a source file.
*/
export const getOutputFilePath = (mdFilePath: string, config: Partial<Config>) => {
export const getOutputFilePath = (mdFilePath: string, extension: 'html' | 'pdf') => {
const { dir, name } = parse(mdFilePath);
const extension = config.as_html ? 'html' : 'pdf';

return join(dir, `${name}.${extension}`);
return resolve(dir, `${name}.${extension}`);
};
12 changes: 7 additions & 5 deletions src/lib/md-to-pdf.ts
Expand Up @@ -12,12 +12,12 @@ import { writeOutput } from './write-output';
* Convert markdown to pdf.
*/
export const convertMdToPdf = async (input: { path: string } | { content: string }, config: Config, args: any = {}) => {
const mdContent =
const mdFileContent =
'content' in input
? input.content
: await readFile(resolve(input.path), args['--md-file-encoding'] || config.md_file_encoding);
: await readFile(input.path, args['--md-file-encoding'] || config.md_file_encoding);

const { content: md, data: frontMatterConfig } = grayMatter(mdContent);
const { content: md, data: frontMatterConfig } = grayMatter(mdFileContent);

// merge front-matter config
config = {
Expand Down Expand Up @@ -57,7 +57,7 @@ export const convertMdToPdf = async (input: { path: string } | { content: string
if (!config.dest) {
config.dest =
'path' in input
? getOutputFilePath(input.path, config)
? getOutputFilePath(input.path, config.as_html ? 'html' : 'pdf')
: resolve(process.cwd(), `output.${config.as_html ? 'html' : 'pdf'}`);
}

Expand All @@ -72,7 +72,9 @@ export const convertMdToPdf = async (input: { path: string } | { content: string

const html = getHtml(md, config);

const output = await writeOutput(mdContent, html, config);
const relativePath = 'path' in input ? resolve(input.path).replace(config.basedir, '') : '/';

const output = await writeOutput(html, relativePath, config);

if (!('filename' in output)) {
throw new Error(`Failed to create ${config.as_html ? 'HTML' : 'PDF'}.`);
Expand Down
29 changes: 14 additions & 15 deletions src/lib/write-output.ts
@@ -1,7 +1,6 @@
import { writeFile as fsWriteFile } from 'fs';
import { promisify } from 'util';
import puppeteer from 'puppeteer';
import { getOutputFilePath } from './get-output-file-path';
import { isHttpUrl } from './is-http-url';
import { Config } from './config';

Expand All @@ -13,15 +12,19 @@ const writeFile = promisify(fsWriteFile);
* The reason that relative paths are resolved properly is that the base dir is served locally
*/
export const writeOutput = async (
mdContent: string,
html: string,
relativePath: string,
config: Config,
): Promise<{} | { filename: string; content: string | Buffer }> => {
if (!config.dest) {
throw new Error('No output file destination has been specified.');
}

const browser = await puppeteer.launch({ devtools: config.devtools, ...config.launch_options });

const page = await browser.newPage();

await page.goto(`http://localhost:${config.port}`);
await page.goto(`http://localhost:${config.port}${relativePath}`); // make sure relative paths work as expected
await page.setContent(html); // overwrite the page content with what was generated from the markdown

await Promise.all([
Expand All @@ -42,26 +45,22 @@ export const writeOutput = async (
page.evaluate(() => history.pushState(undefined, '', '#')),
]);

/**
* @todo should it be `getOutputFilePath(config.dest || mdFilePath, config)`?
*/
const outputFilePath = config.dest || getOutputFilePath(mdContent, config);

let outputFileContent: string | Buffer = '';

if (config.devtools) {
await new Promise(resolve => page.on('close', resolve));
} else if (config.as_html) {
outputFileContent = await page.content();
await writeFile(outputFilePath, outputFileContent);
} else {
await page.emulateMediaType('screen');
outputFileContent = await page.pdf(config.pdf_options);
if (config.as_html) {
outputFileContent = await page.content();
} else {
await page.emulateMediaType('screen');
outputFileContent = await page.pdf(config.pdf_options);
}

await writeFile(outputFilePath, outputFileContent);
await writeFile(config.dest, outputFileContent);
}

await browser.close();

return config.devtools ? {} : { filename: outputFilePath, content: outputFileContent };
return config.devtools ? {} : { filename: config.dest, content: outputFileContent };
};
4 changes: 2 additions & 2 deletions src/test/lib.spec.ts
Expand Up @@ -105,8 +105,8 @@ test('getMarked should accept a custom renderer with custom code highlighter', t
test('getOutputFilePath should return the same path but with different extension', t => {
const mdFilePath = posix.join('/', 'var', 'foo', 'bar.md');

t.is(getOutputFilePath(mdFilePath, {}), `${sep}var${sep}foo${sep}bar.pdf`);
t.is(getOutputFilePath(mdFilePath, { as_html: true }), `${sep}var${sep}foo${sep}bar.html`);
t.is(getOutputFilePath(mdFilePath, 'pdf'), `${sep}var${sep}foo${sep}bar.pdf`);
t.is(getOutputFilePath(mdFilePath, 'html'), `${sep}var${sep}foo${sep}bar.html`);
});

// --
Expand Down

0 comments on commit bb46626

Please sign in to comment.