diff --git a/packages/core/patternlab-config.json b/packages/core/patternlab-config.json index 3169e05af..2571bb52f 100644 --- a/packages/core/patternlab-config.json +++ b/packages/core/patternlab-config.json @@ -97,5 +97,7 @@ "excludedPatternStates": [], "excludedTags": [] } - ] + ], + "patternWrapClassesEnable": false, + "patternWrapClassesKey": [] } diff --git a/packages/core/src/lib/compose.js b/packages/core/src/lib/compose.js index 3b8909b0a..c3494e123 100644 --- a/packages/core/src/lib/compose.js +++ b/packages/core/src/lib/compose.js @@ -10,6 +10,7 @@ const render = require('./render'); const uikitExcludePattern = require('./uikitExcludePattern'); const pm = require('./plugin_manager'); const dataMerger = require('./dataMerger'); +const patternWrapClassesChangePatternTemplate = require('./patternWrapClasses'); const pluginManager = new pm(); const Pattern = require('./object_factory').Pattern; @@ -159,6 +160,7 @@ module.exports = async function (pattern, patternlab) { const headHTML = intermediateResults[0]; //headPromise pattern.patternPartialCode = intermediateResults[1]; //patternPartialPromise const footerPartial = intermediateResults[2]; //footerPartialPromise + patternWrapClassesChangePatternTemplate(patternlab, pattern); //finish up our footer data let allFooterData; diff --git a/packages/core/src/lib/patternWrapClasses.js b/packages/core/src/lib/patternWrapClasses.js new file mode 100644 index 000000000..2810eef6b --- /dev/null +++ b/packages/core/src/lib/patternWrapClasses.js @@ -0,0 +1,45 @@ +/** + * get the classes from pattern markdown and/or json + * @param {PatternLab} patternlab + * @param {Pattern} pattern + * @return {string} + */ +function getPatternWrapClasses(patternlab, pattern) { + const { patternWrapClassesEnable, patternWrapClassesKey } = patternlab.config; + if ( + !patternWrapClassesEnable || + !patternWrapClassesKey || + patternWrapClassesKey.length === 0 + ) { + return ''; + } + + const classes = []; + patternWrapClassesKey.forEach((key) => { + const { allMarkdown, jsonFileData } = pattern; + + if (allMarkdown && allMarkdown[key]) { + classes.push(allMarkdown[key]); + } + + if (jsonFileData && jsonFileData[key]) { + classes.push(jsonFileData[key]); + } + }); + + return classes.join(' '); +} + +/** + * change pattern template and wrap with classes pattern wrapper + * @param {PatternLab} patternlab + * @param {Pattern} pattern + */ +function patternWrapClassesChangePatternTemplate(patternlab, pattern) { + const classes = getPatternWrapClasses(patternlab, pattern); + if (classes.length !== 0) { + pattern.patternPartialCode = `
${pattern.patternPartialCode}
`; + } +} + +module.exports = patternWrapClassesChangePatternTemplate; diff --git a/packages/core/test/files/_patterns/test/pattern-wrap-class-json.json b/packages/core/test/files/_patterns/test/pattern-wrap-class-json.json new file mode 100644 index 000000000..1cb2a1d93 --- /dev/null +++ b/packages/core/test/files/_patterns/test/pattern-wrap-class-json.json @@ -0,0 +1,3 @@ +{ + "theme-class": "json-theme-class" +} diff --git a/packages/core/test/files/_patterns/test/pattern-wrap-class-json.mustache b/packages/core/test/files/_patterns/test/pattern-wrap-class-json.mustache new file mode 100644 index 000000000..5716ca598 --- /dev/null +++ b/packages/core/test/files/_patterns/test/pattern-wrap-class-json.mustache @@ -0,0 +1 @@ +bar diff --git a/packages/core/test/files/_patterns/test/pattern-wrap-class-markdown.md b/packages/core/test/files/_patterns/test/pattern-wrap-class-markdown.md new file mode 100644 index 000000000..358c8a525 --- /dev/null +++ b/packages/core/test/files/_patterns/test/pattern-wrap-class-markdown.md @@ -0,0 +1,3 @@ +--- +theme-class: markdown-theme-class +--- diff --git a/packages/core/test/files/_patterns/test/pattern-wrap-class-markdown.mustache b/packages/core/test/files/_patterns/test/pattern-wrap-class-markdown.mustache new file mode 100644 index 000000000..5716ca598 --- /dev/null +++ b/packages/core/test/files/_patterns/test/pattern-wrap-class-markdown.mustache @@ -0,0 +1 @@ +bar diff --git a/packages/core/test/patternWrapClasses_tests.js b/packages/core/test/patternWrapClasses_tests.js new file mode 100644 index 000000000..a00d06dd1 --- /dev/null +++ b/packages/core/test/patternWrapClasses_tests.js @@ -0,0 +1,53 @@ +'use strict'; + +const path = require('path'); +const tap = require('tap'); + +const loadPattern = require('../src/lib/loadPattern'); +const patternWrapClassesChangePatternTemplate = require('../src/lib/patternWrapClasses'); +const util = require('./util/test_utils.js'); +const patternEngines = require('../src/lib/pattern_engines'); +const config = require('./util/patternlab-config.json'); + +patternEngines.loadAllEngines(config); + +const patterns_dir = `${__dirname}/files/_patterns`; + +tap.test('reading pattern wrap class from markdown', function (test) { + const patternlab = util.fakePatternLab(patterns_dir); + patternlab.config = { + ...patternlab.config, + patternWrapClassesEnable: true, + patternWrapClassesKey: ['theme-class'], + }; + + const patternPathMarkdown = path.join( + 'test', + 'pattern-wrap-class-markdown.mustache' + ); + const patternMarkdown = loadPattern(patternPathMarkdown, patternlab); + patternWrapClassesChangePatternTemplate(patternlab, patternMarkdown); + const patternPartialMarkdown = + '
'; + + test.equal(patternMarkdown.patternPartialCode, patternPartialMarkdown); + test.end(); +}); + +tap.test('reading pattern wrap class from json', function (test) { + const patternlab = util.fakePatternLab(patterns_dir); + patternlab.config = { + ...patternlab.config, + patternWrapClassesEnable: true, + patternWrapClassesKey: ['theme-class'], + }; + + const patternPathJson = path.join('test', 'pattern-wrap-class-json.mustache'); + const patternJson = loadPattern(patternPathJson, patternlab); + patternWrapClassesChangePatternTemplate(patternlab, patternJson); + const patternPartialJson = + '
'; + + test.equal(patternJson.patternPartialCode, patternPartialJson); + test.end(); +}); diff --git a/packages/docs/src/docs/advanced-config-options.md b/packages/docs/src/docs/advanced-config-options.md index 3804c5b30..7f2b5384c 100644 --- a/packages/docs/src/docs/advanced-config-options.md +++ b/packages/docs/src/docs/advanced-config-options.md @@ -210,7 +210,7 @@ For example, to export the navigation, header, and footer, one might do: ## patternMergeVariantArrays -Used to override the merge behavior of pattern variants. For more information see [The Pseudo-Pattern File Data](docs/using-pseudo-patterns/#heading-the-pseudo-pattern-file-data). +Used to override the merge behavior of pattern variants. For more information see [The Pseudo-Pattern File Data](/docs/using-pseudo-patterns/#heading-the-pseudo-pattern-file-data). - `true` will merge arrays of the pattern and pseudo-pattern with [lodash merge](https://lodash.com/docs/4.17.15#merge) - `false` will override arrays from the pattern with pseudo-patterns arrays @@ -221,6 +221,29 @@ Used to override the merge behavior of pattern variants. For more information se **default**: `true` | `undefined` +## patternWrapClassesEnable + +Set to `true` to enable adding a wrapper div with css class(es) around a pattern. +For more information see [Pattern Wrap Classes](/docs/pattern-wrap-classes/). + +```javascript +"patternWrapClassesEnable": false, +``` + +**default**: `false` + +## patternWrapClassesKey + +Configure your class keys for `"patternWrapClassesEnable": true`. +For more information see [Pattern Wrap Classes](/docs/pattern-wrap-classes/). + + +```javascript +"patternWrapClassesKey": ['theme-class'], +``` + +**default**: `[]` + ## renderFlatPatternsOnViewAllPages Used to activate rendering flat patterns on view all pages and generate view all pages if only flat patterns are available diff --git a/packages/docs/src/docs/advanced-pattern-wrap-classes.md b/packages/docs/src/docs/advanced-pattern-wrap-classes.md new file mode 100644 index 000000000..4c89bd010 --- /dev/null +++ b/packages/docs/src/docs/advanced-pattern-wrap-classes.md @@ -0,0 +1,105 @@ +--- +title: Pattern Wrap Classes +tags: + - docs +category: advanced +eleventyNavigation: + title: Pattern Wrap Classes + key: advanced + order: 300 +sitemapPriority: '0.8' +--- + +This feature allows you to add a wrapper div with css class(es) around a pattern when shown in the single preview. +If it gets included in another pattern, the wrapper is not added. + +This comes in handy if you, for example, use theming classes to visualize different backgrounds, colors etc. + +## Configuration + +Enable this feature with the configuration options +[patternWrapClassesEnable](/docs/editing-the-configuration-options/#heading-patternwrapclassesenable) and +[patternWrapClassesKey](/docs/editing-the-configuration-options/#heading-patternwrapclasseskey). + +## How does it work? + +Patternlab will look for any "data key" added to the `patternWrapClassesKey` array and adds that +date to the wrapper element classes. + +Data key can be set inside the Markdown or JSON file of any pattern. + +### Example Config + +```json +"patternWrapClassesKey": ["theme-class"] +``` + +## Use in Markdown + +Usage [Documenting Patterns](/docs/documenting-patterns/) + +### my-pattern.md +```markdown +--- +theme-class: my-theme-class +--- +``` + +### Result +```html +
...markup of pattern...
+``` + +## Use in JSON + +Usage [Creating Pattern-specific Values](/docs/creating-pattern-specific-values/) + +### my-pattern.json +```json +{ + "theme-class": "my-other-theme-class" +} +``` + +### Result +```html +
...markup of pattern...
+``` + +## Pseudo-Patterns + +This will work with pseudo-patterns too ([Using Pseudo-Patterns](/docs/using-pseudo-patterns/)) + +### my-pattern~variant.json +```json +{ + "theme-class": "my-variant-theme-class" +} +``` + +### Result +```html +
...markup of pattern...
+``` + +## Multiple entries in "patternWrapClassesKey" + +Will result in multiple classes in the wrapper div. + +### Example Config +```json +"patternWrapClassesKey": ["theme-class", "other-class"] +``` + +### my-pattern.json +```json +{ + "theme-class": "theme-class", + "other-class": "some-other-class" +} +``` + +### Result +```html +
...markup of pattern...
+```