I have babel-plugin-prismjs installed,
made .babelrc with this code:
{
"plugins": [
["prismjs", {
"languages": ["javascript", "css", "html"],
"plugins": ["line-numbers", "show-language", "copy-to-clipboard", "toolbar", "inline-color"],
"theme": "prism-tomorrow",
"css": true
}
]
]
}
and imported Prism to App.js.
This is the code in App.js:
import React, { useEffect } from "react";
import Prism from "prismjs";
const code = `
const foo = 'foo';
const bar = 'bar';
console.log(foo + bar);
`.trim()
function App() {
useEffect(() =>{
Prism.highlightAll();
}, [])
return (
<pre className="line-numbers">
<code className="language-js">
{code}
</code>
</pre>
);
}
export default App;
But the webpage is not highlighting the syntax. What am I missing here?
If you are using this in a react project built from create-react-app (CRA), your code will not work. Your .babelrc file is not being used. CRA does not expose babel configuration. Check this answer to understand more on this.
For your use-case the easiest way would be to go to prismjs page to download the CSS file. Select the right theme and click 'DOWNLOAD CSS' at the bottom of the page.
Import this CSS file in your App.js code.
import '../prism.css';
This will work for Javascript and some other built-in language packs. If proper markup for your language doesn't show up you will need to import those languages manually as well.
Note: This is just a work around to not ejecting your CRA project. The recommended way is still to use babel-plugin-prismjs if you can.
Related
I'm struggling to import SVG's when I'm using craco in my react app.
It's suggested to use #svgr/webpack but I'm not sure how to put it into my craco.config.js
My current setup as per this (I prob shouldn't follow someone's config that doesn't work and expect it to work tho) that does not work:
// craco.config.js
const CracoAlias = require("craco-alias");
module.exports = {
plugins: [
{
plugin: CracoAlias,
options: {
source: "tsconfig",
baseUrl: "./src",
tsConfigPath: "./tsconfig.paths.json"
}
},
],
webpack: {
configure: (config, { env, paths }) => {
config.module.rules.push({
test: /\.svg$/,
use: ["#svgr/webpack"]
});
return config;
}
}
};
The craco.config.js webpack documentation is here but it's so confusing to me without concrete examples.
Also to note:
Writing import {ReactComponent as mySvg} from "./mySvg.svg" doesn't work because it doesn't recognize it as a ReactComponent.
If I try importing directly via import mySvg from "./mySvg.svg" Typescript doesn't recognize the file.
What I'm currently doing is putting the svg into a React component and using that but it's a nightmare doing that every time. I also put this in #types/custom.d.ts, but it still doesn't work when put into <img src={mySvg} />
// #types/custom.d.ts
declare module "*.svg" {
const content: any;
export default content;
}
import {reactComponent as GoogleLogo} from "../assets/image/googlelogo.svg;
GoogleLogo is component and reactComponent is a required magic string
i find the fix your problem in Adding svgr to create-react-app via craco
Please see example repo
https://github.com/inspiraller/webpack-and-microbundle
Microbundle code
mymicrobundle/src/index.js
import React from 'react'
const MyMicroBundle = ({session}) => {
return (
<div>Session = {session}</div>
)
}
export default MyMicroBundle
microbundle/package.json - for output
{
...
"source": "src/index.js",
"main": "dist/index.umd.js",
"module": "dist/index.module.js",
"exports": "dist/index.modern.js",
"unpkg": "dist/index.umd.js"
}
Importing Microbundle code
webpack-loads-microbundle/package.json
{
"dependencies": {
"#mymicrobundle/example": "file:../mymicrobundle",
}
}
webpack-load-microbundle/src/index.tsx
import React, { useState } from 'react'
import ReactDOM from 'react-dom'
import MyMicroBundle from '#mymicrobundle/example'
import './index.scss'
const App = () => {
const [session, setSession] = useState('')
return (
<div>
<h1>Hello</h1>
</div>
)
}
ReactDOM.render(<App />, document.getElementById('root'))
Note: The microbundle package is bundled as javascript, but I'm using typescript to import it.
Though shouldn't make any difference. I'm also using pnpm instead of npm but also this should be fine as all other imports work.
Something about my path is wrong maybe.
Error
Module not found: Error: Can't resolve '#mymicrobundle/example' in 'C:\baps\react_all\webpack-and-microbundle\webpack-loads-microbundle\src'
webpack resolves modules from its process.cwd()/node_modules by default.
So in your case it is looking for #mymicrobundle/example in webpack-and-microbundle(the current working directory) which is your app directory.
You need to let webpack know, where it needs to search in addition to your project's node_modules.
This can be done using the resolve.modules key. See docs: https://webpack.js.org/configuration/resolve/#resolvemodules
So your webpack config should have something like:
resolve: {
modules: ['node_modules', 'path/to/#mymicrobundle/example'],
},
I am using Preview addon in Storybook for React to show the component usage in Docs.
<Preview withToolbar>
<Story name="primary">
<PrimaryButton disabled={boolean("Disabled",false)} modifiers={["small"]} onClick={action('button-click')} > {text("Label", "Hello Storybook")}</PrimaryButton>
</Story>
</Preview>
This generate doc as below :
There is a show code/ hide code switch which shows the React Code for the component , is it possible to show the plain HTML markup as well.
I need to use a single storybook component explorer for React and non React Projects so wanted to check if plain markup source code be generated as well.
Thanks
I am in a similar situation where I just want to use react for the development of the stories and only display the HTML in the docs so it can be used with other frameworks.
This is what I came up with so far.
In .storybook/preview.js I am using a custom function to render the source code so the file look something like this:
import renderToHTML from './renderToHTML'
export const parameters = {
actions: { argTypesRegex: '^on[A-Z].*' },
docs: {
transformSource: (src, storyContext) => renderToHTML(storyContext.storyFn),
},
}
this is documented here.
My renderToHTML function is defined like this:
import { renderToStaticMarkup } from 'react-dom/server'
import { AllHtmlEntities } from 'html-entities'
import prettier from 'prettier'
import HTMLParser from 'prettier/parser-html'
const entities = new AllHtmlEntities()
export default (story) =>
prettier.format(entities.decode(renderToStaticMarkup(story())), {
parser: 'html',
plugins: [HTMLParser],
})
I'm using renderToStaticMarkup to compile the story, then html-entities to
unescape it and then using prettier to format it.
I am still experimenting with this so I might update the answer if I found issues or a better way to do things
I recently decided to use PrismJS with React and to avoid import repetitions I managed to use this babel-plugin-prismjs package in order to load plugins, languages and so on.
As indicated in the plugin documentation, I've created a .babelrc file located in my root folder :
{
"plugins": [
["prismjs", {
"languages": [
"applescript",
"css",
"javascript",
"markup",
"scss"
],
"plugins": ["line-numbers"],
"theme": "twilight",
"css": true
}]
]
But I found that this file seemed to be ignored, as nothing is loaded and when console-logging my imported Prism object I'm only seeing syntax highlighting for the default languages.
The file where I want to get syntax highlighting have an import Prism from 'prismjs' statement and Prism.highlightAll()
So yes I can keep importing manually plugins, theme and languages in each of my files but I would want to find the reason of such an issue.
Thank you !
You're halfway there. You still need to import prismjs somewhere, usually in your app.js file, and then call Prism.highlightAll() in the appropriate file of the page you want syntax highlighting on.
My process was as follows:
Setup my .babelrc.js file:
const env = require('./env-config')
module.exports = {
presets: ['next/babel'],
plugins: [
[
'transform-define',
env,
],
[
'prismjs', {
'languages': ['javascript', 'css', 'html', 'jsx'],
'plugins': ['line-numbers', 'show-language', 'copy-to-clipboard'],
'theme': 'tomorrow',
'css': true
},
]
],
}
Import prismjs into my _app.js file (since I'm using Next.js, but with React, you would import this into our app.js file:
// ...
import 'prismjs'
// ...
Use the prismjs API to call the .highlightAll() method on your desired page(s):
function usePrismHighlightAll() {
useEffect(() => {
Prism.highlightAll()
}, [])
}
export default function Page () {
usePrismHighlightAll()
// ...
}
As a sidenote,
could also move the usePrismHighlightAll() hook somewhere into your app.js file so that you could enable syntax highlighting in all your pages if that would save you from recalling the hook in several locations.
However, I tried doing this, and unfortunately, it did not work in Next.js:
/* DO NOT USE THIS CODE NEXT.JS AS IT DOES NOT WORK */
import 'prismjs'
// ...
function usePrismHighlightAll() {
useEffect(() => {
Prism.highlightAll()
}, [])
}
export default function App ({ Component, pageProps }) {
usePrismHighlightAll()
return (
<>
<Layout>
<Header />
<Component {...pageProps} />
</Layout>
</>
)
}
/* DO NOT USE THIS CODE NEXT.JS AS IT DOES NOT WORK */
So, stick with the process I outlined in steps 1-3.
Tthat worked for me to enable syntax highlighting on the first load of the page, let me know if this works for you.
I want to share my logic between react js and react native
here is my logic file. it is a HOC that wrap the design component.
I use recompose to create HOCs.
import {compose, withState} from 'recompose';
import FilterOptionsPostsPaginateRelay from './FilterOptionsPostsPaginateRelay';
import handlers from './handlers';
import {withRouter} from "next/router";
export default compose(
withRouter
FilterOptionsPostsPaginateRelay,
withState('loading', 'setLoading', false),
handlers,
)
All of the HOCs are sharable between the react js and react native but the withRouter that comes from next.js router
I want to conditional import {withRouter} from "next/router"; or import {withNavigation} from 'react-navigation'; in my logic file.
I know recompose has branch HOC that I can use but I want the condition checks at build time and prevent extra codes to my bundle and increase performance.
You can create next.config.js to custom webpack config to add alias for router.
module.exports = {
webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
// Note: we provide webpack above so you should not `require` it
// Perform customizations to webpack config
// Important: return the modified config
// Example using webpack option
config.plugins.push(new webpack.IgnorePlugin(/\/__tests__\//));
config.resolve.alias.router = process.env.IS_REACT_NATIVE ? 'react-navigation' : 'next/dist/client/router.js';
return config
},
};
then in your app, you need to use require to import router
const router = require('router');
const withRouter = router.withRouter || router.withNavigation;
I find a solution using babel-plugin-module-resolver
In web project I added following code to .babelrc
{
"plugins": [
[
"module-resolver",
{
"alias": {
"hybridRouter": "next/router"
}
}
]
]
}
In mobile project I added following code to .babelrc
{
"plugins": [
[
"module-resolver",
{
"alias": {
"hybridRouter": "react-navigation"
}
}
]
]
}
And in my logic files I used this like
import HybridRouter from 'hybridRouter';
Now HybridRouter point to next/router in web project and HybridRouter points to react-navigation in mobile project
You can have conditional imports using the require syntax. There is no need to mess with webpack, if you don't want to. Just do something like this in your case:
let withRouter;
try {
//This is expected to fail if next/router is not available
const router = require("next/router");
withRouter = router.withRouter;
} catch(ex){
const reactNav = require("react-navigation");
withRouter = reactNav.withNavigation;
}
// Use withRouter like you would normally use withRouter from next/router or withNavigation from react-navigation