From aa85fb44c79ab1b740c1ea6e66a3992a9c1ca826 Mon Sep 17 00:00:00 2001 From: Zachary Shilton <4624598+zchsh@users.noreply.github.com> Date: Tue, 5 Jan 2021 15:12:17 -0500 Subject: [PATCH] Add map option to typography plugin (#15) * Add custom className map option to typography plugin * Visit listItem nodes directly, rather than through listNode.children * Update typography plugin readme * Add release:pre cmd, bump to expected release * 3.1.0-canary.0 * Expose typography options in allPlugins * 3.1.0-canary.1 --- index.js | 3 +- package-lock.json | 2 +- package.json | 5 ++- plugins/typography/README.md | 40 ++++++++++++++++++- plugins/typography/index.js | 67 +++++++++++++++----------------- plugins/typography/index.test.js | 63 ++++++++++++++++++++++++++++-- 6 files changed, 136 insertions(+), 44 deletions(-) diff --git a/index.js b/index.js index 778aed8..fc60eaa 100644 --- a/index.js +++ b/index.js @@ -14,10 +14,11 @@ module.exports = { // for easy use of everything at the same time module.exports.allPlugins = ({ anchorLinks: anchorLinksOptions, + typography: typographyOptions, includeMarkdown: includeMarkdownOptions, } = {}) => [ [includeMarkdown, includeMarkdownOptions], [anchorLinks, anchorLinksOptions], paragraphCustomAlerts, - typography, + [typography, typographyOptions], ] diff --git a/package-lock.json b/package-lock.json index 91a1a08..cfec63c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@hashicorp/remark-plugins", - "version": "3.0.0", + "version": "3.1.0-canary.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index f6ce85e..ba391a1 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@hashicorp/remark-plugins", "description": "A potpourri of remark plugins used to process .mdx files", - "version": "3.0.0", + "version": "3.1.0-canary.1", "author": "Jeff Escalante", "bugs": "https://github.com/hashicorp/remark-plugins/issues", "contributors": [ @@ -40,6 +40,7 @@ "test": "jest --verbose", "release:patch": "release patch && npm publish", "release:minor": "release minor && npm publish", - "release:major": "release major && npm publish" + "release:major": "release major && npm publish", + "release:pre": "release pre canary && npm publish --tag=canary" } } diff --git a/plugins/typography/README.md b/plugins/typography/README.md index 1fb0769..866aebd 100644 --- a/plugins/typography/README.md +++ b/plugins/typography/README.md @@ -1,7 +1,6 @@ # Heading Type Styles -We use a set of global classes for type styling at HashiCorp. This plugin adds type styles to the appropriate elements so that content looks as intended within rendered markdown blocks without duplicating or extending css. -More details to come via our design system 😀 +We use a set of global classes for type styling at HashiCorp. This plugin adds type styles to the appropriate elements so that content looks as intended within rendered markdown blocks without duplicating or extending CSS. ### Input @@ -26,3 +25,40 @@ Here is some more stuff...
Here is some more stuff...
``` + +### Custom Class Mapping + +In rare cases, we may want to map custom `class` attributes onto specific elements. Currently, this plugin supports an `options` object, and `options.map` provides this functionality. + +Here is an imagined use case where all possible elements have custom `class` attributes. Any one of these elements can be omitted from the map, and it will fall back to our default `class` for that element. + +```js +const options = { + map: { + h1: 'custom-1', + h2: 'custom-2', + h3: 'custom-3', + h4: 'custom-4', + h5: 'custom-5', + h6: 'custom-6', + p: 'custom-paragraph', + li: 'custom-list-item', + }, +} +// example use with `mdx` +const output = mdx.sync(fileContents, { + remarkPlugins: [[typographyPlugin, options]], +}) +``` + +With this configuration, and the same input as the previous example, we would expect the following output: + +```jsx +Here are some uses...
+ +Here is some more stuff...
+``` diff --git a/plugins/typography/index.js b/plugins/typography/index.js index 9593d08..7326aa8 100644 --- a/plugins/typography/index.js +++ b/plugins/typography/index.js @@ -1,46 +1,43 @@ const visit = require('unist-util-visit') -module.exports = function typographyPlugin() { +module.exports = function typographyPlugin(options = {}) { + function getClassName(elemKey) { + const defaultMap = { + h1: 'g-type-display-2', + h2: 'g-type-display-3', + h3: 'g-type-display-4', + h4: 'g-type-display-5', + h5: 'g-type-display-6', + h6: 'g-type-label', + p: 'g-type-long-body', + li: 'g-type-long-body', + } + const customMap = options.map || {} + return customMap[elemKey] || defaultMap[elemKey] + } + + function addClassName(node, className) { + if (!className) return true + const data = node.data || (node.data = {}) + const props = data.hProperties || (data.hProperties = {}) + data.id = className + props.className = className + } + return function transformer(tree) { // Add typography classes to headings - visit(tree, 'heading', node => { - const data = node.data || (node.data = {}) - const props = data.hProperties || (data.hProperties = {}) + visit(tree, 'heading', (node) => { + addClassName(node, getClassName(`h${node.depth}`)) + }) - if (node.depth === 1) { - data.id = 'g-type-display-2' - props.className = 'g-type-display-2' - } - if (node.depth === 2) { - data.id = 'g-type-display-3' - props.className = 'g-type-display-3' - } - if (node.depth === 3) { - data.id = 'g-type-display-4' - props.className = 'g-type-display-4' - } - if (node.depth === 4) { - data.id = 'g-type-display-5' - props.className = 'g-type-display-5' - } - if (node.depth === 5) { - data.id = 'g-type-display-6' - props.className = 'g-type-display-6' - } - if (node.depth === 6) { - data.id = 'g-type-label' - props.className = 'g-type-label' - } + // Add typography classes to paragraph text + visit(tree, 'paragraph', (node) => { + addClassName(node, getClassName('p')) }) // Add typography classes to list items - visit(tree, 'list', node => { - node.children.map(li => { - const data = li.data || (li.data = {}) - const props = data.hProperties || (data.hProperties = {}) - data.id = 'g-type-long-body' - props.className = 'g-type-long-body' - }) + visit(tree, 'listItem', (node) => { + addClassName(node, getClassName('li')) }) } } diff --git a/plugins/typography/index.test.js b/plugins/typography/index.test.js index 2b4f2a3..14e7748 100644 --- a/plugins/typography/index.test.js +++ b/plugins/typography/index.test.js @@ -1,4 +1,4 @@ -const typeStyles = require('./index.js') +const typographyPlugin = require('./index.js') const mdx = require('@mdx-js/mdx') const fileContents = `hi there @@ -19,16 +19,73 @@ Foo bar baz wow *amaze* ` describe('type-styles', () => { - it('should construct add appropriate class names to headings', () => { - const output = mdx.sync(fileContents, { remarkPlugins: [typeStyles] }) + it('adds classNames to headings, paragraphs, and list items', () => { + const output = mdx.sync(fileContents, { remarkPlugins: [typographyPlugin] }) expect(output).toMatch( /{`sadklfjhlskdjf`}<\/p>/ + ) expect(output).toMatch( /
{`sadklfjhlskdjf`}<\/p>/ + ) + expect(output).toMatch( + /