From a2709d2dff6b6d49fce9c394a6541474e92fc75f Mon Sep 17 00:00:00 2001 From: billypon Date: Wed, 30 Mar 2022 23:15:30 +0800 Subject: [PATCH] feat: transform block to attribute --- README.md | 11 ++++++++++ .../block-attribute.test.js.snap | 20 +++++++++++++++++++ src/__tests__/block-attribute.input.js | 6 ++++++ src/__tests__/block-attribute.test.js | 3 +++ src/visitors/NamedBlock.js | 15 ++++++++++++++ src/visitors/Tag.js | 13 +++++++++++- 6 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 src/__tests__/__snapshots__/block-attribute.test.js.snap create mode 100644 src/__tests__/block-attribute.input.js create mode 100644 src/__tests__/block-attribute.test.js create mode 100644 src/visitors/NamedBlock.js diff --git a/README.md b/README.md index 5d6e989..4f1b08a 100644 --- a/README.md +++ b/README.md @@ -114,6 +114,17 @@ const Component = props => pug` //- const Component = props => ( `; ``` +#### Transform block to attribute + +```jsx +const Component = props => pug` //- const Component = props => ( + Menu //- }> + button //- + img //- ) +`; +``` + #### Interpolation If you'd prefer to use interpolation, you can. This is possible by using `${}` within your template. diff --git a/src/__tests__/__snapshots__/block-attribute.test.js.snap b/src/__tests__/__snapshots__/block-attribute.test.js.snap new file mode 100644 index 0000000..13ae810 --- /dev/null +++ b/src/__tests__/__snapshots__/block-attribute.test.js.snap @@ -0,0 +1,20 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`JavaScript output: transformed source code 1`] = ` +"module.exports = ( + > + +); +" +`; + +exports[`html output: generated html 1`] = ` +} +> + +`; + +exports[`static html output: static html 1`] = `""`; diff --git a/src/__tests__/block-attribute.input.js b/src/__tests__/block-attribute.input.js new file mode 100644 index 0000000..13d1f5e --- /dev/null +++ b/src/__tests__/block-attribute.input.js @@ -0,0 +1,6 @@ +module.exports = pug` + menu + button + block icon + img +`; diff --git a/src/__tests__/block-attribute.test.js b/src/__tests__/block-attribute.test.js new file mode 100644 index 0000000..bd8eace --- /dev/null +++ b/src/__tests__/block-attribute.test.js @@ -0,0 +1,3 @@ +import testHelper from './test-helper'; + +testHelper(__dirname + '/block-attribute.input.js'); diff --git a/src/visitors/NamedBlock.js b/src/visitors/NamedBlock.js new file mode 100644 index 0000000..367f4a9 --- /dev/null +++ b/src/visitors/NamedBlock.js @@ -0,0 +1,15 @@ +// @flow + +import type Context from '../context'; +import {visitJsxExpressions} from '../visitors'; +import {buildJSXFragment} from '../utils/jsx'; + +const NamedBlockVisitor = { + jsx(node: Object, context: Context): JSXValue { + const nodes = visitJsxExpressions(node.nodes, context); + node.nodes = nodes.length === 1 ? nodes : [buildJSXFragment(nodes)]; + return node; + }, +}; + +export default NamedBlockVisitor; diff --git a/src/visitors/Tag.js b/src/visitors/Tag.js index e2ccb11..8271819 100644 --- a/src/visitors/Tag.js +++ b/src/visitors/Tag.js @@ -135,13 +135,24 @@ function getAttributesAndChildren( attrs: Array, children: Array, } { - const children = getChildren(node, context); + let children = getChildren(node, context); if (node.attributeBlocks.length) { throw new Error('Attribute blocks are not yet supported in react-pug'); } const attrs = getAttributes(node, context); + + const blocks = children.filter(({type}) => type === 'NamedBlock'); + if (blocks.length) { + children = children.filter(({type}) => type !== 'NamedBlock'); + attrs.push( + ...blocks.map(block => + t.jSXAttribute(t.jSXIdentifier(block.name), block.nodes[0]), + ), + ); + } + context.key.handleAttributes(attrs); return {attrs, children};