diff --git a/CHANGELOG.md b/CHANGELOG.md index ad85a2af..4330acc8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ - Add server mode provided by `--server` (`-s`) option ([#27](https://github.com/marp-team/marp-cli/pull/27)) - Add fonts for internationalization to Docker image ([#26](https://github.com/marp-team/marp-cli/pull/26)) +### Changed + +- Recognize theme CSS in input directory specified by `--input-dir` (`-I`) option ([#28](https://github.com/marp-team/marp-cli/pull/28)) + ## v0.0.10 - 2018-09-20 ### Added diff --git a/src/config.ts b/src/config.ts index 9da9ab5a..0cb1236e 100644 --- a/src/config.ts +++ b/src/config.ts @@ -64,6 +64,7 @@ export class MarpCLIConfig { return resolveEngine(['@marp-team/marp-core', Marp]) })() + const inputDir = await this.inputDir() const output = this.args.output || (this.conf.output @@ -87,7 +88,10 @@ export class MarpCLIConfig { ).map(f => path.resolve(path.dirname(this.confPath!), f)) : []) - const themeSet = await ThemeSet.initialize(themeSetPathes, initialThemes) + const themeSet = await ThemeSet.initialize( + (inputDir ? [inputDir] : []).concat(themeSetPathes), + initialThemes + ) if ( themeSet.themes.size <= initialThemes.length && @@ -96,6 +100,7 @@ export class MarpCLIConfig { warn('Not found additional theme CSS files.') return { + inputDir, output, server, themeSet, @@ -106,7 +111,6 @@ export class MarpCLIConfig { ) || false, engine: engine.klass, html: this.pickDefined(this.args.html, this.conf.html), - inputDir: await this.inputDir(), lang: this.conf.lang || (await osLocale()).replace(/[_@]/g, '-'), options: this.conf.options || {}, readyScript: engine.browserScript diff --git a/src/marp-cli.ts b/src/marp-cli.ts index 7a87a109..22f81c02 100644 --- a/src/marp-cli.ts +++ b/src/marp-cli.ts @@ -52,7 +52,7 @@ export default async function(argv: string[] = []): Promise { }, 'input-dir': { alias: 'I', - describe: 'The base input directory to find markdown', + describe: 'The base directory to find markdown and theme CSS', group: OptionGroup.Basic, type: 'string', }, diff --git a/src/theme.ts b/src/theme.ts index 1ef4ab31..95261b30 100644 --- a/src/theme.ts +++ b/src/theme.ts @@ -2,6 +2,7 @@ import { Marpit } from '@marp-team/marpit' import fs from 'fs' import globby from 'globby' import path from 'path' +import { warn } from './cli' const themeExtensions = ['*.css'] @@ -95,8 +96,13 @@ export class ThemeSet { registerTo(engine: Marpit) { for (const theme of this.themes.values()) { - const engineTheme = engine.themeSet.add(theme.css) - theme.name = engineTheme.name + try { + const engineTheme = engine.themeSet.add(theme.css) + theme.name = engineTheme.name + } catch (e) { + const fn = path.relative(process.cwd(), theme.filename) + warn(`Cannot register theme CSS: ${fn} (${e.message})`) + } } } diff --git a/test/_files/themes/empty b/test/_files/themes/empty new file mode 100644 index 00000000..e69de29b diff --git a/test/marp-cli.ts b/test/marp-cli.ts index 1fe5e366..0b1741ac 100644 --- a/test/marp-cli.ts +++ b/test/marp-cli.ts @@ -107,6 +107,14 @@ describe('Marp CLI', () => { writeFile.mock.calls.forEach(([fn]) => expect(fn).toMatch(/\.html$/)) }) + it('allows using theme css in specified dir', async () => { + jest.spyOn(cli, 'info').mockImplementation() + expect(await marpCli(['--input-dir', files, '--theme', 'a'])).toBe(0) + + for (const [, buffer] of writeFile.mock.calls) + expect(buffer.toString()).toContain('/* @theme a */') + }) + it('prints error and return error code with invalid option(s)', async () => { const err = jest.spyOn(console, 'error').mockImplementation() jest.spyOn(console, 'warn').mockImplementation() @@ -163,7 +171,7 @@ describe('Marp CLI', () => { ) expect(serverStart).toBeCalledTimes(1) expect(Watcher.watch).toHaveBeenCalledWith( - [files], + expect.arrayContaining([files]), expect.objectContaining({ mode: Watcher.WatchMode.Notify, }) diff --git a/test/theme.ts b/test/theme.ts index 24492f8a..f814d486 100644 --- a/test/theme.ts +++ b/test/theme.ts @@ -101,5 +101,22 @@ describe('ThemeSet', () => { expect(names).toContain('b') expect(names).toContain('c') }) + + context('when registered theme is not compatible to Marpit engine', () => { + const emptyCSS = path.resolve(__dirname, '_files/themes/empty') + + it('outputs warning and ignores registration', async () => { + const warn = jest.spyOn(console, 'warn').mockImplementation() + const themeSet = await ThemeSet.initialize([emptyCSS]) + const marpit = new Marpit() + + themeSet.registerTo(marpit) + + expect(marpit.themeSet.size).toBe(0) + expect(warn).toBeCalledWith( + expect.stringContaining('Cannot register theme CSS') + ) + }) + }) }) })