React-PDF errors when rendering <Svg> via Ternary conditional - reactjs

I have an svg header that works perfectly when rendered directly in the tree
<Document>
<Page size="A4">
<MyHeaderSvg />
</Page>
</Document>
However when I render it via a Ternary within the render callback of a element, it errors...
<Document>
<Page size="A4">
<View render={({pageNumber}) => (pageNumber === 1)
? <MyHeaderSvg />
: <NonSvgHeader />
</Page>
</Document>
MyHeaderSvg
<Svg width="555" height="80" viewBox="0 0 555 80">
<Rect width="100%" height="80" rx="8" ry="8" fill="url(#header-rectangle)"/>
<Defs>
<RadialGradient id="header-rectangle" cx="0" cy="0" fr="1">
<Stop stopColor="blue"/>
<Stop offset="1" stopColor="lightblue"/>
</RadialGradient>
</Defs>
<Text style={styles.title} x={`${535-20}px`} y="50%" textAnchor="end" dominantBaseline="middle">Some title</Text>
<G transform="translate(20,21) scale(0.749 0.749)">
<Path d="M0 47.6941V37.8042C0 35.4188 1.53483 32.1486 6.07125 32.1486C9.60438 32.1486 11.6936 35.4536 11.6936 38.6453C11.6936 41.7456 9.59732 44.8226 6.29155 44.8226C5.26468 44.8226 4.14881 44.4355 3.28243 43.6822V47.6941C3.28243 48.7881 2.59891 49.5178 1.64134 49.5178C0.683769 49.5178 0 48.7881 0 47.6941ZM5.85848 41.8135C7.56766 41.8135 8.4107 40.0355 8.4107 38.5075C8.4107 36.958 7.56766 35.1579 5.85848 35.1579C4.1031 35.1579 3.28243 36.7993 3.28243 38.3951C3.28243 39.9903 4.05763 41.8135 5.85848 41.8135Z" fill="white"/>
</G>
</Svg>
Experimentation
I tried commenting out different sections to see the results
Section commented out
Resulting error
Rect and Defs section only
Text line only
Original error
G section only
Original error
Text and G
Original error
G, Rect and Defs
Rect, Defs and Text
Updates:
I have been playing with the Repl on React-PDFs website to see where things can break more realtime.
Looks like changing any definitions of numbers from strings into actual numbers ie x="10" to x={10} helps.
<Text> breaks it entirely! There doesn't seem to be any way to get a <Text> element included in any way, shape or form.
<Path> does seem to work fine as it is defined above, however the <G> transform is breaking things as it is defined via a string.

Related

Expo append to SVG onClick at x/y coords

I have an SVG in a React-Native Expo app that I am rendering fine. The alert_coords method works to and I can get the locationX and locationY as well. What I want now is using the svgRef to append a <Rect> for example at the x/y coords but not sure how to do it and all attempts with like svgRef.current.appendChild("<Rect //.. />") and similar tests don't work.
<ReactNativeZoomableView
maxZoom={30}
contentWidth={1000}
contentHeight={800}
>
<Svg
ref={svgRef}
height="100%"
width="100%"
rotation={90}
viewBox="0 0 1300 800"
onTouchEnd={(e) => alert_coords(e)}
>
<Image href="urlhere" />
</Svg>
</ReactNativeZoomableView>
</View>

How can I use this SVG in React without getting any error?

I want to use JavaScript SVG as an icon. However, I keep getting this error. I fixed one error by changing xmls:xlink into xmlsXlink. However, it did not work same for xml:space.
SVG code
<svg
className="icon"
xmlns="http://www.w3.org/2000/svg"
xmlnsXlink="http://www.w3.org/1999/xlink"
version="1.1"
id="Layer_1"
x="0px"
y="0px"
viewBox="0 0 85 85"
style="enable-background:new 0 0 85 85;"
xml:space="preserve"
>
<polygon
class="st0"
points="6.3,1.2 13,75.4 42.4,83.8 72.1,75.4 78.9,1.2"
fill="#FFF"
/>
<g>
<g transform="translate(4.988 -113.385)">
<path
d="M7.1,189.8l-6.9-76.4H75l-7,76.4l-30.6,8.6L7.1,189.8z M62.4,185.6l5.8-65.5H37.6l0.2,72.2 L62.4,185.6z M34.7,129.8h-7.4L27.2,169l-14.5-4v9l21.9,5.9L34.7,129.8L34.7,129.8z"
fill="#D4B830"
/>
<path
d="M32.3,179.2c-1-0.3-5.7-1.6-10.6-2.9l-8.8-2.4v-4.4c0-4.3,0-4.4,0.4-4.3 c0.2,0.1,3.4,1,7.1,2l6.7,1.8l0.1-19.5l0.1-19.5h7.3v24.9c0,19.7-0.1,24.9-0.3,24.9C34.2,179.7,33.2,179.4,32.3,179.2L32.3,179.2z"
fill="#EBEBEB"
opacity="0.986"
fill-opacity="0"
enable-background="new"
/>
<path
d="M12.8,174v-9c0,0,9.2,2.6,14.4,3.9l0.1-39.1h7.4v50.1L12.8,174L12.8,174z"
fill="#EBEBEB"
opacity="0.986"
fill-opacity="0.9216"
enable-background="new"
/>
<path
d="M37.6,120.2h30.6l-5.8,65.5l-24.8,6.7V120.2z M60.8,174.6l2-24.5L48,151.8v-13.1l15.9-0.1 l0.6-8.9l-23.9,0.1l0.3,32.5l14.5-2.5l-0.2,7.2l-14.7,4l0.1,8.9L60.8,174.6L60.8,174.6z"
fill="#FDD83C"
/>
</g>
</g>
</svg>
You've no text in the file so just remove the xml:space attribute altogether.

Why does React render these SVGs differently?

If I render SVG elements to a defined SVG object, then all is well.
If I render an entire SVG object, the resulting image doesn't scale.
If you look at the following demo, the 1st svg renders correctly. The svg fills the width of the browser and everything scales.
The second svg is a 300x150 image that doesn't scale at all.
https://codepen.io/brunnock/pen/ydMdgv
// The following renders as expected.
function SVG1() {
return (
<g>
<rect height="100%" width="100%" fill="#ccc" />
<circle cx={150} cy={75} r={50} fill="red" />
<text x="100" y="275" font-size="50">
This is the right size.
</text>
</g>
);
}
// svg1 is a predefined svg element in the HTML file.
ReactDOM.render(<SVG1 />, svg1);
// The following renders a 300x150 image that doesn't scale.
function SVG2() {
return (
<svg viewbox={"0 0 600 600"}>
<rect height="100%" width="100%" fill="#ccc" />
<circle cx={150} cy={75} r={50} fill="red" />
<text x="100" y="275" font-size="50">
This is not the right size.
</text>
</svg>
);
}
// svg2 is a div.
ReactDOM.render(<SVG2 />, svg2);
I couldn't find any difference in the rendered html via Chrome's inspector.
Remove the parentheses from the viewBox
function SVG2() {
return (
<svg viewbox="0 0 600 600">
<rect height="100%" width="100%" fill="#ccc" />
<circle cx={150} cy={75} r={50} fill="red" />
<text x="100" y="275" font-size="50">
This is not the right size.
</text>
</svg>
);
}
I'm an idiot. Change "viewbox" to "viewBox" and "font-size" to "fontSize".

How to use regularExpression function in Live Templates?

I trying to insert value from clipboard with regular expression. How to do it?
Is it possible to delete svg tag with properties using regex?
I tried to write regularExpression(SVG, width="(\d+)px", $1) and variation of this.
For example
I've got this in my clipboard
<svg width="32px" height="32px" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g transform="translate(-932.000000, -4274.000000)">
<g transform="translate(0.000000, 4184.000000)">
<g transform="translate(932.000000, 90.000000)">
<rect fill="#3C5494" x="0" y="0" width="32" height="32" rx="16"></rect>
<path d="M17.1973392,16.7117794 L19.5654279,16.7117794 L19.9199468,13.8590668 L17.1973392,13.8590668 L17.1973392,12.0421097 C17.1973392,11.2181543 17.4178625,10.6566668 18.5566829,10.6566668 L20,10.6559859 L20,8.11206559 C19.7488603,8.07744655 18.887255,8 17.8848071,8 C15.7919823,8 14.3592018,9.32549911 14.3592018,11.759728 L14.3592018,13.8590668 L12,13.8590668 L12,16.7117794 L14.3592018,16.7117794 L14.3592018,24 L17.1973392,24 L17.1973392,16.7117794 Z" fill="#FFFFFE"></path>
</g>
</g>
</g>
</g>
</svg>
I use this template
/* eslint-disable max-len */
import React from 'react'
import Icon from './Icon'
const $NAME$ = ({ width, height }) => (
<Icon
width={width}
height={height}
viewBox='0 0 $width$ $height$'
>
$SVG$$END$
</Icon>
)
export default $NAME$
And I'm trying to insert $width$ and $height$ from svg properties
I except viewBox to be '0 0 32 32', but I get '0 0 '
regularExpression(String, Pattern, Replacement) Live Template function is run in the following way: all occurrences in String matching Pattern are replaced by the third argument, and the resultant string is returned (see the function implementation in https://github.com/JetBrains/intellij-community/blob/master/platform/lang-impl/src/com/intellij/codeInsight/template/macro/RegExMacro.java). So, the result of regularExpression(SVG, width="(\d+)px", $1) is your clipboard content with width="32px" replaced with 32

Svg Lineargradient not working with ReactJs

Please help me to find the issue why svg linear gradient is not working with react
<svg width='258' height='229' viewBox='0 0 258 229' >
<defs>
<lineargradient x1='.258%' y1='49.75%' x2='101.258%' y2='49.75%' id='bgGradient'>
<stop stopColor='#3023AE' offset='0%' />
<stop stopColor='#53A0FD' offset='47.525%' />
<stop stopColor='#B4EC51' offset='100%' />
</lineargradient>
</defs>
<g id='Page6' fill='none' fillRule='evenodd' strokeLinecap='round'>
<path d='M10.1757812,18.984375 C183.016927,-13.7135417 261.63151,52.9101563 246.019531,218.855469'
id='Path7' stroke='url(#bgGradient)' strokeWidth='20' />
</g>
</svg>
This is a syntax error:
linearGradient NOT lineargradient
If this is generated SVG (and not a React Template - it's not clear what you're showing here) - you should be using SVG syntax, not React syntax. AKA:
stop-color NOT stopColor
stroke-width NOT strokeWidth
fill-rule NOT fillRule
stroke-linecap NOT strokeLinecap
In SVG, attribute names are generally lowercase and dashed, element names are Camel cased and concatenated. The one exception is with filter primitive attributes - which confusingly - are also Camel case (e.g tableValues)
I'll add to the list of syntax errors Michael Mullany's
stop offset NOT offset
Seemingly minor mistake, but no corrections code not working
In the end, after all errors have been corrected, - working code
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width='258' height='229' viewBox='0 0 258 229' >
<defs>
<linearGradient x1='.258%' y1='49.75%' x2='101.258%' y2='49.75%' id='bgGradient' >
<stop offset='47.525%' stop-color='#3023AE' />
<stop offset='47.525%' stop-color='#53A0FD' />
<stop offset='100%' stop-color='#B4EC51' />
</linearGradient>
</defs>
<g id='Page6' fill='none' fill-rule='evenodd' stroke-linecap='round'>
<path d='M10.1757812,18.984375 C183.016927,-13.7135417 261.63151,52.9101563 246.019531,218.855469'
id='Path7' stroke-width='20' stroke="url(#bgGradient)" />
</g>
</svg>

Resources