pugjs / babel-plugin-transform-react-pug Goto Github PK
View Code? Open in Web Editor NEWA plugin for transpiling pug templates to jsx
License: MIT License
A plugin for transpiling pug templates to jsx
License: MIT License
I followed the installation guide and then did the following:
import './App.css';
class App extends Component {
render() {
return pug`
div
h1 My Component
p This is my component using pug.
`;
}
}
export default App;
But I am receiving the following error
Failed to compile.
./src/App.js
Line 7: 'pug' is not defined no-undef
Search for the keywords to learn more about each error.
each value, key in hash
throws Expected "hash" to be an array because it is passed to each
if hash is an object.
It's usually possible to iterate over objects with each right? Says so in the docs
I know this issue has been opened but seems most people got a way around it here is exactly what i'm returning in my render
return pug`
div
h1 My Component
p This is my component using pug.
`;
Like this:
MyComponent/
MyComponent.pug
MyComponent.styl
MyComponent.js
MyComponent.pug:
div(class=`${styles.container}`)
p
= this.state.text
MyComponent.js:
import React from 'react';
import styles from './MyComponent.styl';
import template from './MyComponent.pug'; // raw text loader
class MyComponent extends React.Component {
render() {
return pug`${template}`;
}
}
Babel 7 uses require('@babel/core');
now, substituting that in the source appears to work.
A temporary fix now is to install babel-core^7.0.0-bridge.0
.
Hi,
I am wondering if it would be possible to require a pug template. Using a tagged string literal is great but I would love to keep the templates separate. Unfortunately I don't know if I am able to convert a string into a string literal or if there is a global pug function which I can use on a string that I require in using raw-loader in webpack.
Thank you for any assistance on this.
Hey guys,
I completely love pugjs and this plugin for connecting it to react. But it looks like this plugin does not have enough attention from your side. I understand that you probably don't have time or this project is not a priority for you. That is why I'm starting this thread.
What are your thoughts on this? Do you need help?
//CC @ForbesLindesay
It's not a bug or issue, probably, just a question.
My task is to make a text inside a template better by inserting
and other symbols.
pug`
p Hello, World!
`
It outputs Hello, World!
in browser but expected behavior is to have a real space. Could you help me to leverage this?
I am trying to use pug in my Typescript React components like your basic example:
render() {
return pug`
div
h1 My Component
p This is my component using pug.
`;
}
The problem is that I can't get it to work because the typescript loader fails on the pug command.
However, to use babel, the Typescript files first have to be compiled to javascript. Can anyone help me get out of this Catch-22?
It would be good to let people know about changed parts between versions.
I would keep everything in releases section and in separate markdown file.
If you can suggest any good tool for this.
I'm not positive that we can revise all things there. But if you think it's important, I will do it.
First of all thanks to the authors greate work, productivity has peaked with this valuable tool.
Now I am having a hard time trying to implement this is in a ES6 classed based components. like
class UserList extends React.Component {
render() {
return pug`
React.Component
ul
each u in this.props.user_list
UserItem(key=u.id user=u)
`
}
}
Tons of error messages are returning from this code. Is this not supported or am I doing it wrong?
Below errors:
react-dom.development.js:506 Warning: Component(...): No `render` method found on the returned
react-dom.development.js:14301 Uncaught TypeError: instance.render is not a function
I have been using Pug with React-native and it has worked well thus far. However whenever I try using interpolation I get the following error screen:
The only thing I need interpolation for is fat arrow functions (for onClick or onChangeText props). I have been able to work around this by creating external fat arrow methods and passing those, but doing that for every single time I need to update a text field can be a pain.
Here are my .babelrc and package.json:
.babelrc
{ "presets": ["babel-preset-expo"], "env": { "development": { "plugins": [ "transform-react-jsx-source", "transform-react-pug", "transform-react-jsx" ] } } }
package.json
{ "name": "test", "version": "0.1.0", "private": true, "devDependencies": { "babel-plugin-transform-react-jsx": "^6.24.1", "babel-plugin-transform-react-pug": "^3.1.8", "eslint-config-rallycoding": "^3.2.0", "eslint-plugin-pug": "^1.1.0", "jest-expo": "~18.0.0", "react-native-scripts": "0.0.50", "react-test-renderer": "16.0.0-alpha.12" }, "main": "./node_modules/react-native-scripts/build/bin/crna-entry.js", "scripts": { "start": "react-native-scripts start", "eject": "react-native-scripts eject", "android": "react-native-scripts android", "ios": "react-native-scripts ios", "test": "node node_modules/jest/bin/jest.js --watch" }, "jest": { "preset": "jest-expo" }, "dependencies": { "expo": "^18.0.3", "firebase": "^4.1.3", "native-base": "2.1.3", "react": "16.0.0-alpha.12", "react-native": "^0.45.1" } }
Is there a plan to allow a generic props spread, a la
<SomeComponent {...props} />
?
Is there a way to set the doctype globally?
Is babel-plugin-transform-react-jsx plugin really required? I have not read the sources, but I have thought that:
p This is my component using pug
will be compiled directly to:
React.createElement('p', null, 'This is my component using pug');
without jsx
People follow the javascript coding style.
The pug needs to be combined with LiveScript or CoffeeScript. But not a babel
I have already created a project lsxc 1 year ago (https://github.com/askucher/lsxc)
Please check it out.
For now we try to resolve all arrays, and make combinations into arrays to combine shorthands and className
attribute.
The idea is to remove own judgement of how people want to use class
attribute. Now we make it more consistent: if we pass array or object — we get array or object. More examples:
.one.two
div(className="one two")
//- <div className="one two" />
div(className=100)
//- <div className={100} />
div(className=variable)
//- <div className={variable} />
div(className=['one', 'two'])
//- <div className={['one', 'two']} />
div(className=['one', 'two'].join(' '))
//- <div className={['one', 'two'].join(' ')} />
div(className={first: true})
//- <div className={{first: true}} />
It becomes more interesting when it mixes with shorthands:
.mix(className="one two")
//- <div className="mix one two" />
.mix(className=100)
//- <div className={'mix ' + 100} />
.mix(className=variable)
//- <div className={'mix ' + variable} />
.mix(className=['one', 'two'])
//- <div className={['mix', 'one', 'two']} />
.mix(className=['one', 'two'].join(' '))
//- <div className={'mix ' + ['one', 'two'].join(' ')} />
.mix(className={first: true})
//- <div className={'mix ' + {first: true}} />
Hey,
Now when I'm passing basic each it transpiles into a monster:
each item in [1, 2, 3]
div(key=item)= item
((_pug_nodes, _pug_arr) => {
if (!(_pug_arr == null || Array.isArray(_pug_arr)))
throw new Error(
'Expected "[1, 2, 3]" to be an array because it is passed to each.'
);
if (_pug_arr == null || _pug_arr.length === 0) return undefined;
for (let _pug_index = 0; _pug_index < _pug_arr.length; _pug_index++) {
const item = _pug_arr[_pug_index];
_pug_nodes[_pug_nodes.length] = <div key={"pug" + item + ":0"}>{item}</div>;
}
return _pug_nodes;
})([], [1, 2, 3]);
What do you think if we eliminate all these validations and return simple .map
:
[1, 2, 3].map((item) => (
<div key={"pug" + item + ":0"}>{item}</div>
))
And then even into something with initial keys:
[1, 2, 3].map((item) => (
<div key={item}>{item}</div>
))
//CC @ForbesLindesay
Hi, thank you for the plugin. I tried with CRA and it is working. But, now I am doing a project with NextJS and I do not know what should I do to make it work.
Any suggestions?
Thank you.
example:
props => pug`
for row, y in props.grid
for cell, x in row
span(key=y*row.length + x) #{cell}
`
workaround - use a flat array or insert a grouping element
props => pug`
for row, y in props.grid
div(key=y)
for cell, x in row
span(key=x) #{cell}
`
I tried to do that but I get 'pug' is not defined no-undef
I copied these lines to package.json
like that
"babel": {
"plugins": [
"transform-react-pug",
"transform-react-jsx"
]
}
I'm using babel-plugin-transform-react-pug in a React project where I'm passing dynamic class names. I use nested template literals like so:
return pug`
div(className=${`${blockClass}__element`})
| Whatever content
`;
This works fine. But JSLint throws an error that seems to come from pug-lexer:
Syntax Error: Unexpected token
Error: Pug:1:16
> 1| div(className=${`${blockClass}__element`})
----------------------^
2| | Whatever content
Syntax Error: Unexpected token
at makeError (/home/deploy/homestars-www/node_modules/pug-error/index.js:32:13)
at Lexer.error (/home/deploy/homestars-www/node_modules/pug-lexer/index.js:58:15)
at Lexer.assertExpression (/home/deploy/homestars-www/node_modules/pug-lexer/index.js:86:12)
at Lexer.attrs (/home/deploy/homestars-www/node_modules/pug-lexer/index.js:1089:18)
at Lexer.callLexerFunction (/home/deploy/homestars-www/node_modules/pug-lexer/index.js:1319:23)
at Lexer.advance (/home/deploy/homestars-www/node_modules/pug-lexer/index.js:1356:15)
at Lexer.callLexerFunction (/home/deploy/homestars-www/node_modules/pug-lexer/index.js:1319:23)
at Lexer.getTokens (/home/deploy/homestars-www/node_modules/pug-lexer/index.js:1375:12)
at lex (/home/deploy/homestars-www/node_modules/pug-lexer/index.js:12:42)
at findVariablesInTemplate (/home/deploy/homestars-www/node_modules/pug-uses-variables/lib/findVariablesInTemplate.js:31:20)
If I remove the nested literal, this error doesn't occur.
Is this just because of the difference in formatting between babel-plugin-transform-react-pug and pugjs?
viz,
babel-plugin-transform-react-pug: `${}`
pugjs: `#{}`
Incidentally, I've cross-posted this with pug-lexer:
pugjs/pug-lexer#81
Hello!
Thank you for this wonderful plugin.
Do you know how to get Sublime Text to syntax highlight pug'...
template literals?
Lots of libraries return structures which rely on toString
being used to interpolate them. For example...
import truncate from 'lodash'
const result = truncate('long string', {length:7})
...
render() {
return pug`p= result`
}
You'd expect the above to render as <p>long...</p>
, however lodash returns a chainable wrapper which is interpolated by this module as an empty string so you get <p></p>
. you need to explicitly call toString()
as in return pug'p= result.toString()'
The expected behaviour would be to call toString
when rendering objects.
Hello, I'm trying to use this plugin while using poi
as my web bundler : https://poi.js.org/
I set up my .babelrc
file like this:
{
"presets": ["poi"],
"plugins": [
"react-hot-loader/babel",
"transform-react-pug"
]
}
Since poi
also uses the .babelrc
file, but it keeps throwing me a syntax error when I try to use pug like this:
import React from 'react';
const Home = () => pug`
.wrapper
p.greeting Hello World!
export default Home;
but I get this error on the console:
odule build failed: SyntaxError: /Users/irvingarmenta/Documents/irving/poi-bundler-test/components/Home.js: Unterminated template (3:23)
1 | import React from 'react';
2 |
> 3 | const Home = () => pug`
| ^
4 | .wrapper
5 | p.greeting Hello World!
6 |
at _class.raise (/Users/irvingarmenta/Documents/irving/poi-bundler-test/node_modules/@babel/parser/lib/index.js:3861:15)
at _class.readTmplToken (/Users/irvingarmenta/Documents/irving/poi-bundler-test/node_modules/@babel/parser/lib/index.js:4839:14)
at TokContext.types$1.template [as override] (/Users/irvingarmenta/Documents/irving/poi-bundler-test/node_modules/@babel/parser/lib/index.js:3058:14)
at _class.nextToken (/Users/irvingarmenta/Documents/irving/poi-bundler-test/node_modules/@babel/parser/lib/index.js:4069:18)
at _class.next (/Users/irvingarmenta/Documents/irving/poi-bundler-test/node_modules/@babel/parser/lib/index.js:4007:10)
at _class.parseTemplate (/Users/irvingarmenta/Documents/irving/poi-bundler-test/node_modules/@babel/parser/lib/index.js:6547:10)
at _class.parseSubscript (/Users/irvingarmenta/Documents/irving/poi-bundler-test/node_modules/@babel/parser/lib/index.js:5998:28)
at _class.parseSubscripts (/Users/irvingarmenta/Documents/irving/poi-bundler-test/node_modules/@babel/parser/lib/index.js:5888:19)
at _class.parseExprSubscripts (/Users/irvingarmenta/Documents/irving/poi-bundler-test/node_modules/@babel/parser/lib/index.js:5878:17)
at _class.parseMaybeUnary (/Users/irvingarmenta/Documents/irving/poi-bundler-test/node_modules/@babel/parser/lib/index.js:5847:21)
at _class.parseExprOps (/Users/irvingarmenta/Documents/irving/poi-bundler-test/node_modules/@babel/parser/lib/index.js:5754:21)
at _class.parseMaybeConditional (/Users/irvingarmenta/Documents/irving/poi-bundler-test/node_modules/@babel/parser/lib/index.js:5726:21)
at _class.parseMaybeAssign (/Users/irvingarmenta/Documents/irving/poi-bundler-test/node_modules/@babel/parser/lib/index.js:5673:21)
at _class.parseFunctionBody (/Users/irvingarmenta/Documents/irving/poi-bundler-test/node_modules/@babel/parser/lib/index.js:6857:24)
at _class.parseArrowExpression (/Users/irvingarmenta/Documents/irving/poi-bundler-test/node_modules/@babel/parser/lib/index.js:6817:10)
at _class.parseParenAndDistinguishExpression (/Users/irvingarmenta/Documents/irving/poi-bundler-test/node_modules/@babel/parser/lib/index.js:6433:12)
Thought it was going to be a smooth implementation, however there seems to be an issue. Thank you.
Know from the documentation:
React.Fragment becomes <React className="Fragment" />
but in RN Use braces instead of quotes:
<React className={Fragment} /> or <React className={[Fragment1, Fragment2]}/>
Settings .eslintrc
"globals": {
"pug": true/false
},
is not helping
class App extends React.Component {
render() {
return pugdiv h1 My Component p This is my component using pug.
;
}
}
export default App;
With regular React JSX syntax, I write like this:
{Object.values(children).map(child => (
<Tab
key={child.id}
>
<ChildDetails child={child} />
</Tab>
))}
With pug syntax, I write like this:
each child, i in Object.values(children)
Tab(
key=i
)
ChildDetails(child=child)
For me, pug syntax looks better in terms of legibility, but I get eslint error no-undef
for iterator variable (child
).
For now, I should disable eslint temporarily using /* eslint-disable no-undef */
right before return
statement in render
function.
Can we make it pass eslint without this extra line of disabling eslint rule?
UPDATE: This is intermittent - it happens sometimes and doesn't happen other times.
What do you think if we allow using components nested in objects. Like for React.Fragment
?
React.Fragment
Icons.Open
Icons.Close
I'm not sure but there is a chance that we can understand if React
or Icons
in example above are not components and then go deeper and provide real components by resolving the whole chain: React.Fragment
and Icons.Open
. I can investigate this.
The other option is to prohibit class names start with up-case. It's a serious restriction, so I would like to investigate the first option and discuss both with you before creating a PR.
For now we have very few aliases for attributes:
babel-plugin-transform-react-pug/src/visitors/Tag.js
Lines 50 to 60 in 429ca31
I think we should get rid of it to get the same experience as with jsx and react. Unless you know good reason to do that, this way we will make more aliases to be compatible more with plain html.
Please could you provide an example of implementation?
For example the following code will throw an error:
pug`
- const i = 0
h2= i
`
See live example:
https://codesandbox.io/s/j34wv68wyy
I have a function that looks like this:
createPanel(obj) {
return pug`
Card
CardBody
CardTitle '{obj.title}'
`
}
And that works, but it produces quotation marks around my title, so it shows up as 'My title here', when I just want it to say My title here without the quotes.
I've tried all sorts of various combinations like CardTitle= {obj.title}
CardTitle #{obj.title}
CardTitle= ${obj.title}
and all of those throw errors by either the pug-as-jsx-loader or the pug-lexer
Error in ../../Component
Module build failed: TypeError: Property children[0] of JSXElement expected node to be of a type ["JSXText","JSXExpressionContainer","JSXSpreadChild","JSXElement","JSXFragment"] but instead got "CallExpression"
at validate (/Users/jitszu/Apps/MyApp/node_modules/@babel/types/lib/definitions/utils.js:136:13)
at validator (/Users/jitszu/Apps/MyApp/node_modules/@babel/types/lib/definitions/utils.js:95:7)
at Object.validate (/Users/jitszu/Apps/MyApp/node_modules/@babel/types/lib/definitions/utils.js:191:10)
at validate (/Users/jitszu/Apps/MyApp/node_modules/@babel/types/lib/validators/validate.js:15:9)
at builder (/Users/jitszu/Apps/MyApp/node_modules/@babel/types/lib/builders/builder.js:40:27)
at Object.JSXElement (/Users/jitszu/Apps/MyApp/node_modules/@babel/types/lib/builders/generated/index.js:1233:27)
at Object.jSXElement (/Users/jitszu/Apps/MyApp/node_modules/babel-plugin-transform-react-pug/lib/babel-types.js:689:52)
at buildJSXElement (/Users/jitszu/Apps/MyApp/node_modules/babel-plugin-transform-react-pug/lib/utils/jsx.js:22:31)
at buildJSXFragment (/Users/jitszu/Apps/MyApp/node_modules/babel-plugin-transform-react-pug/lib/utils/jsx.js:31:10)
at PluginPass.TaggedTemplateExpression (/Users/jitszu/Apps/MyApp/node_modules/babel-plugin-transform-react-pug/lib/index.js:58:98)
at newFn (/Users/jitszu/Apps/MyApp/node_modules/@babel/traverse/lib/visitors.js:223:21)
at NodePath._call (/Users/jitszu/Apps/MyApp/node_modules/@babel/traverse/lib/path/context.js:64:19)
at NodePath.call (/Users/jitszu/Apps/MyApp/node_modules/@babel/traverse/lib/path/context.js:38:17)
at NodePath.visit (/Users/jitszu/Apps/MyApp/node_modules/@babel/traverse/lib/path/context.js:99:12)
at TraversalContext.visitQueue (/Users/jitszu/Apps/MyApp/node_modules/@babel/traverse/lib/context.js:135:18)
at TraversalContext.visitSingle (/Users/jitszu/Apps/MyApp/node_modules/@babel/traverse/lib/context.js:94:19)
/MyComponent.js
render = () => pug`
each item in this.props.data
h1(key=item)= item.data
Button Btn
`
Using React.Fragment
makes it work when used as a Parent or as Sibling. I dont know why
i.e.
render = () => pug`
React.Fragment
each item in this.props.data
h1(key=item)= item.data
Button Btn
`
AND
render = () => pug`
React.Fragment
each item in this.props.data
h1(key=item)= item.data
Button Btn
`
Error:
./src/App.js
Line 7: 'pug' is not defined no-undef
Search for the keywords to learn more about each error.
Create-react-app : 1.5.2
Babel-plugin-transform-react-pug: ^6.0.0
Hey guys,
I started the project which kills my pain in using eslint-plugin-react
and babel-plugin-transform-react-pug
together: eslint-plugin-react-pug.
I see many duplicates of issue like #7 ('pug' is not defined no-undef), so I think it will be reasonable to mention eslint-plugin-react-pug
in README. What do you think?
Pros: everyone will easy know how to integrate this babel plugin with commonly used eslint-plugin-react
.
Cons: eslint-plugin-react-pug
is not tested enough on production.
Can we have if else in attribute. like this :
a( className=if(foo===bar) foo else bar )
Transpile into :
<a href={foo===bar? 'foo' : 'bar'}
/>
I'm setting up react-router root component using inline pug and receiving a generic "pug is not defined" error using the React.cloneElement function as seen below:
import React from 'react';
import SiteHeader from './SiteHeader';
export function GetQuotes(props) {
return pug`
.get-quotes
SiteHeader()
${ React.cloneElement(props.children, props) }
`;
}
export default GetQuotes;
Whereas it works just fine using plain old jsx like so:
import React from 'react';
import SiteHeader from './SiteHeader';
export function GetQuotes(props) {
return (
<div className='get-quotes'>
<SiteHeader/>
{ React.cloneElement(props.children, props) }
</div>
)
}
export default GetQuotes;
How should we use pug markup for React components that have a period in the name? For example, React-Bootstrap (https://react-bootstrap.github.io/components.html#navigation) has many components named like "Tab.Content" or "Tab.Pane".
When writing a the pug markup to use these components like this:
pug`Tab.Content foo`
it is transpiled to:
<Tab className="Content">foo</Tab>
when it should actually become:
<Tab.Content>foo</Tab.Content>
Is there a good workaround? Thanks!
...
div.imui-contact_info--user
div.imui-contact_info--wrap
h3.imui-contact_info--name(style={maxWidth: tags.length===0? '130px': ''}) #{name}
each item, index in tags
= item // i want add key to the item like this '=item(key=index)
span.imui-contact_info--time #{timeStr}
p.imui-contact_tip #{tipInfo}
...
For example...
const contact = {
name: 'Levi',
someEmptyField: '',
}
return pug`
div
each value, key in contact
if value
p(key=key)= value
`
Throws You must specify a key for the first item in any loops.
As a workaround you can trim the empty values before you render the pug, so you don't need the conditional.
e.g.
input(required)
Does babel not translate statements inside interpolated code? Spread operator works inside plain JSX in {} but not in pug inside ${}. Module build fails with unexpected token error when trying to use pug.
<ExpenseListItem {...expense} key={expense.id}/> // this works
pug'ExpenseListItem(${...expense}, key=${expense.id})'; - doesn't work
pug'ExpenseListItem(${(...expense)}, key=${expense.id})'; - tried wrapping in parens - doesn't work
It seems like Pug transpile its tags directly into React.createElement(Foo, ...)
-ish function instead of <Foo>...</Foo>
, that eventually compiles to React.createElement(_foo, ...)
(but not the full name Foo
, instead interoped and resolved), and it breaks references to imported files (ReferenceError). I don't know why would this happen. Is anyone having the same issue?
So when using inline HTML it's getting output as literal text, when I'd like it to be processed as JSX.
For example, p This is plain old <em>text</em> content.
(which is an example from the Pug documentation) outputs a paragraph containing "<em>text</em>", rather than an em
element.
This can be worked around, I think - I found using interpolated tags, like p This is plain old #[em text] content.
works for me for now. Still, I think it'd be nice if it worked; even just documenting that it doesn't work would have helped me.
(All assuming this isn't just an issue with my setup; if it works for other people, I'll look into the issue more.)
I big fan of Pug and want to use it in React, but have no docs for this project :(
Some popular tools for integrating CSS modules with react relies on different attribute for class names. For example 'react-css-modules' expects styleName
.
This
<div styleName="class"></div>
Will be converted into this
<div className="[context]__class__[hash]"></div>
So it would be good to add an option for this plugin to allow using different attribute names instead of 'className' always.
source:
import React from "react";
class MyComponent extends React.Component {
render() {
return pug`
div foo
| bar
div baz
`;
}
}
compile to:
import React from "react";
class MyComponent extends React.Component {
render() {
return React.createElement(
React.Fragment,
null,
React.createElement(
"div",
null,
"foo"
),
"bar",
React.createElement(
"div",
null,
"baz"
)
);
}
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.