diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a5fba75..d020b642 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ ## [Unreleased] +### Added + +- Allow parsing hyphen and underscore in theme meta ([#150](https://github.com/marp-team/marpit/pull/150)) +- Support getting nested prop by `ThemeSet#getThemeProp` ([#150](https://github.com/marp-team/marpit/pull/150)) + ## v0.9.0 - 2019-04-03 ### Added diff --git a/index.d.ts b/index.d.ts index 4c57f432..f5f32a73 100644 --- a/index.d.ts +++ b/index.d.ts @@ -124,7 +124,7 @@ declare module '@marp-team/marpit' { clear(): void delete(name: string): boolean get(name: string, fallback?: boolean): Theme | undefined - getThemeProp(theme: string | Theme, prop: keyof Theme): any + getThemeProp(theme: string | Theme, propPath: string): any has(name: string): boolean pack(name: string, opts: ThemeSetPackOptions): string themes(): IterableIterator diff --git a/package.json b/package.json index 796a4bac..c8dddb31 100644 --- a/package.json +++ b/package.json @@ -95,6 +95,7 @@ "dependencies": { "color-string": "^1.5.3", "js-yaml": "^3.13.0", + "lodash.get": "^4.4.2", "lodash.kebabcase": "^4.1.1", "markdown-it": "^8.4.2", "markdown-it-front-matter": "^0.1.2", diff --git a/src/postcss/meta.js b/src/postcss/meta.js index 1ea34469..cca34975 100644 --- a/src/postcss/meta.js +++ b/src/postcss/meta.js @@ -14,12 +14,9 @@ const plugin = postcss.plugin('marpit-postcss-meta', () => (css, ret) => { css.walkComments(comment => { comment.text .slice(0) - .replace( - /^[*!\s]*@([a-z][a-z0-9]*)\s+(.+)$/gim, - (matched, metaName, value) => { - ret.marpitMeta[metaName] = value - } - ) + .replace(/^[*!\s]*@([\w-]+)\s+(.+)$/gim, (_, metaName, value) => { + ret.marpitMeta[metaName] = value + }) }) }) diff --git a/src/theme_set.js b/src/theme_set.js index ec826633..801f09bc 100644 --- a/src/theme_set.js +++ b/src/theme_set.js @@ -1,3 +1,4 @@ +import get from 'lodash.get' import postcss from 'postcss' import postcssAdvancedBackground from './postcss/advanced_background' import postcssImportReplace from './postcss/import/replace' @@ -114,9 +115,9 @@ class ThemeSet { * scaffold theme when the specified theme is undefined. * * @param {string|Theme} theme The theme name or instance. - * @param {string} prop The property name to get. + * @param {string} propPath The property name or path to get. */ - getThemeProp(theme, prop, importedThemes = []) { + getThemeProp(theme, propPath, importedThemes = []) { let importedProps = [] const themeInstance = theme instanceof Theme ? theme : this.get(theme) @@ -132,7 +133,7 @@ class ThemeSet { return importTheme ? this.getThemeProp( importTheme, - prop, + propPath, [...importedThemes, name].filter(n => n) ) : undefined @@ -142,10 +143,10 @@ class ThemeSet { } return [ - themeInstance && themeInstance[prop], + get(themeInstance, propPath), ...importedProps, - this.default && this.default[prop], - scaffold[prop], + get(this.default, propPath), + get(scaffold, propPath), ].find(t => t) } diff --git a/test/postcss/meta.js b/test/postcss/meta.js index a8d8e710..3d92158a 100644 --- a/test/postcss/meta.js +++ b/test/postcss/meta.js @@ -4,27 +4,29 @@ import meta from '../../src/postcss/meta' describe('Marpit PostCSS meta plugin', () => { const run = input => postcss([meta()]).process(input, { from: undefined }) - it('adds marpitMeta object to result', () => { - run('').then(result => { - expect(result.marpitMeta).toBeInstanceOf(Object) - expect(result.marpitMeta).toStrictEqual({}) - }) + it('adds marpitMeta object to result', async () => { + const result = await run('') + expect(result.marpitMeta).toBeInstanceOf(Object) + expect(result.marpitMeta).toStrictEqual({}) }) - it('parses meta comment and store to marpitMeta', () => - run('/* @meta value */').then(result => - expect(result.marpitMeta.meta).toBe('value') - )) + it('parses meta comment and store to marpitMeta', async () => { + expect((await run('/* @meta value */')).marpitMeta.meta).toBe('value') - it('parses meta comment with starting by double star', () => - run('/** @meta double-star */').then(result => - expect(result.marpitMeta.meta).toBe('double-star') - )) + // Number, hyphen and underscore + expect((await run('/* @123 456 */')).marpitMeta['123']).toBe('456') + expect((await run('/* @-_- _-_ */')).marpitMeta['-_-']).toBe('_-_') + }) + + it('parses meta comment with starting by double star', async () => { + const result = await run('/** @meta double-star */') + expect(result.marpitMeta.meta).toBe('double-star') + }) - it('parses meta comment with important comment', () => - run('/*! @meta important-comment */').then(result => - expect(result.marpitMeta.meta).toBe('important-comment') - )) + it('parses meta comment with important comment', async () => { + const result = await run('/*! @meta important-comment */') + expect(result.marpitMeta.meta).toBe('important-comment') + }) context('with multiline metas', () => { const css = ` @@ -35,12 +37,10 @@ describe('Marpit PostCSS meta plugin', () => { */ ` - it('parses multiline metas correctly', () => - run(css).then(result => - expect(result.marpitMeta).toStrictEqual({ - meta: 'value', - multiline: 'is supported.', - }) - )) + it('parses multiline metas correctly', async () => + expect((await run(css)).marpitMeta).toStrictEqual({ + meta: 'value', + multiline: 'is supported.', + })) }) }) diff --git a/test/theme_set.js b/test/theme_set.js index 0d958d22..0172c63d 100644 --- a/test/theme_set.js +++ b/test/theme_set.js @@ -154,6 +154,13 @@ describe('ThemeSet', () => { // Import undefined theme instance.add('/* @theme undefined-theme */\n@import "ignore"') + + // Meta value + instance.add('/* @theme meta */\n/* @meta-value A */') + instance.add('/* @theme meta-imported */\n@import "meta";') + instance.add( + '/* @theme meta-overrode */\n/* @meta-value B */\n@import "meta";' + ) }) const { width, height } = scaffoldTheme @@ -229,6 +236,19 @@ describe('ThemeSet', () => { it('ignores importing undefined theme and fallbacks to scaffold value', () => expect(instance.getThemeProp('undefined-theme', 'width')).toBe(width)) }) + + context('with path to nested meta property', () => { + it('returns the value of property', () => { + expect(instance.getThemeProp('meta', 'meta.meta-value')).toBe('A') + expect(instance.getThemeProp('meta', 'meta.unknown')).toBeUndefined() + expect(instance.getThemeProp('meta-imported', 'meta.meta-value')).toBe( + 'A' + ) + expect(instance.getThemeProp('meta-overrode', 'meta.meta-value')).toBe( + 'B' + ) + }) + }) }) describe('#has', () => { diff --git a/yarn.lock b/yarn.lock index 72bcc66c..c0333998 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4719,6 +4719,11 @@ lodash.clonedeep@^4.3.2: resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= +lodash.get@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" + integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= + lodash.kebabcase@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz#8489b1cb0d29ff88195cceca448ff6d6cc295c36"