react-native-svg icon indicating copy to clipboard operation
react-native-svg copied to clipboard

LinearGradient crash with xlink:href

Open gosuperninja opened this issue 7 years ago • 6 comments

xlink:href are not supported, the use of it causes a crash. linearGradient that use xlink:href have no children elements which causes a call on undefined.

Example

<svg id="b809eb86-ec6b-4213-aa3e-83f4128e49a5" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink" width="1082" height="725" viewBox="0 0 1082 725">
    <defs>
        <linearGradient id="b7709055-0dd4-48d6-ac10-5a758f15d1a1" x1="443.56" y1="792.13" x2="443.56" y2="251.5"
                        gradientUnits="userSpaceOnUse">
            <stop offset="0" stop-color="gray" stop-opacity="0.25"/>
            <stop offset="0.54" stop-color="gray" stop-opacity="0.12"/>
            <stop offset="1" stop-color="gray" stop-opacity="0.1"/>
        </linearGradient>
        <linearGradient id="f59ba046-7ebe-407e-be3d-c62856fc1078" x1="712" y1="788.54" x2="712" y2="248.5"
                        xlink:href="#b7709055-0dd4-48d6-ac10-5a758f15d1a1">
        </linearGradient>
    </defs>
</svg>

gosuperninja avatar Jan 31 '19 21:01 gosuperninja

That doesn't render anything in any browser or other svg viewer either. You need to refer to the gradient in a fill or stroke attribute using e.g. fill="url(#idOfGradient)" in some other element which causes some geometry to render. Check e.g. https://github.com/react-native-community/react-native-svg#lineargradient

<Svg
    height="150"
    width="300"
>
    <Defs>
        <LinearGradient id="grad" x1="0" y1="0" x2="170" y2="0">
            <Stop offset="0" stopColor="rgb(255,255,0)" stopOpacity="0" />
            <Stop offset="1" stopColor="red" stopOpacity="1" />
        </LinearGradient>
    </Defs>
    <Ellipse cx="150" cy="75" rx="85" ry="55" fill="url(#grad)" />
</Svg>

msand avatar Feb 01 '19 02:02 msand

Hmm, apparently the spec allow inheritance here: https://www.w3.org/TR/SVG11/pservers.html#LinearGradientElementHrefAttribute https://svgwg.org/svg2-draft/pservers.html#LinearGradientElementHrefAttribute

msand avatar Feb 01 '19 02:02 msand

https://www.w3.org/TR/SVG/pservers.html#PaintServerTemplates https://svgwg.org/svg2-draft/pservers.html#PaintServerTemplates

msand avatar Feb 01 '19 02:02 msand

in case anyone else runs into this..

IF you have access to the source AND you're using Illustrator

save as settings: SVG 1.1 type: SVG subsetting: none Image location: (whatever) css properties: Presentation Attributes

I then process via gulp

gulpfile.js:

var gulp = require('gulp');
var svgmin = require('gulp-svgmin');
var replace = require('gulp-replace');

gulp.task('svg', function() {
  return gulp
    .src('./svg/in/*.svg')
    .pipe(
      svgmin({
        plugins: [
          { removeXMLNS: true },
          {
            inlineStyles: { onlyMatchedOnce: false, removeMatchedSelectors: false }
          },
          { convertStyleToAttrs: true }
        ]
      })
    )
    .pipe(
      svgmin({
        plugins: [{ removeStyleElement: true }, { removeEmptyContainers: true }]
      })
    )
    .pipe(
      svgmin({
        plugins: [
          { removeEmptyContainers: true },
          {
            removeAttrs: {
              attrs: '(class|data-name)'
            }
          },
          {
            convertShapeToPath: {
              convertArcs: true
            }
          }
        ]
      })
    )
    .pipe(
      svgmin({
        plugins: [
          {
            mergePaths: {
              collapseRepeated: true,
              leadingZero: true,
              negativeExtraSpace: true
            }
          }
        ]
      })
    )
    .pipe(
      replace(/xlink:href=/g, (match, p1, offset, string) => {
        return `href=`;
      })
    )
    .pipe(
      replace(/stop-color=/g, (match, p1, offset, string) => {
        return `stopColor=`;
      })
    )
    .pipe(
      replace(/clip-path=/g, (match, p1, offset, string) => {
        return `clipPath=`;
      })
    )
    .pipe(
      replace(/stroke-linecap=/g, (match, p1, offset, string) => {
        return `strokeLinecap=`;
      })
    )
    .pipe(
      replace(/stroke-linejoin=/g, (match, p1, offset, string) => {
        return `strokeLinejoin=`;
      })
    )
    .pipe(
      replace(/stroke-width=/g, (match, p1, offset, string) => {
        return `strokeWidth=`;
      })
    )
    .pipe(
      replace(/stroke-miterlimit=/g, (match, p1, offset, string) => {
        return `strokeMiterlimit=`;
      })
    )
    .pipe(
      replace(/="(-?[0-9]*\.[0-9]*)"/g, (match, p1, offset, string) => {
        return `={${p1}}`;
      })
    )
    .pipe(
      replace(/<(\w)/g, (match, p1, offset, string) => {
        return '<Svg.' + p1.toUpperCase();
      })
    )
    .pipe(
      replace(/<\/(\w)/g, (match, p1, offset, string) => {
        return '</Svg.' + p1.toUpperCase();
      })
    )
    .pipe(gulp.dest('./svg/out'));
});

MillerGregor avatar Aug 02 '19 15:08 MillerGregor

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. You may also mark this issue as a "discussion" and I will leave this open.

stale[bot] avatar Feb 08 '20 00:02 stale[bot]

Closing this issue after a prolonged period of inactivity. Fell free to reopen this issue, if this still affecting you.

stale[bot] avatar Feb 15 '20 01:02 stale[bot]