Parcel: 馃悰 SVG <defs>, <symbol> and <use> are unsupported in parcel build

Created on 30 Jan 2018  路  10Comments  路  Source: parcel-bundler/parcel

馃悰 bug report
support SVG <defs>, <symbol> and <use> in HTML

馃 Expected Behavior

SVG <defs>, <symbol> and <use> tags to be present in the output minified html file.

馃槸 Current Behavior

Ive been able to consistently reproduce the problem in one index.html file:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <svg xmlns="http://www.w3.org/2000/svg">
      <defs>
        <g id="circle">
          <circle cx="100" cy="100" r="100"/>
        </g>
      </defs>
    </svg>
    <div id="app">
      <svg style="display:block;margin:0 auto;" height="250px">
        <use xlink:href='#circle' href='#circle'/>
      </svg>
    </div>
  </body>
</html>

run: parcel build index.html

output:

<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> </head> <body> <svg xmlns="http://www.w3.org/2000/svg"/> <div id="app"> undefined </div> </body> </html> 

The <defs> tag disappears and <use> tag is replaced with undefined.
Note that I use xlink:href as href is not supported in Safari 11

馃拋 Possible Solution

Using <svg> works and is transpiled correctly. I could omit the use of <defs> and move the entire <svg> content to all the places I have the <use> tag. Sadly, as you'll notice, that'll mean having repeated svgs which <defs> were created to solve.

馃敠 Context

I define my re-usable svgs in <defs> or <symbol> in index.html and use them throughout my application.

馃實 Your Environment

| Software | Version(s) |
| ---------------- | ---------- |
| Parcel | 1.5.1
| Node | 9.4.0
| npm | 5.6.0
| Operating System | macOS High Sierra
| Browsers|Safari 11.0.1, Chrome 63.0.3239.132

Bug

Most helpful comment

@alyssaq after a quick research at the specs it looks like both attributes are required xmlns and xmlns:xlink at the svg element.

<svg xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink"
>
    <use xlink:href="assets/sprite.svg#icon"></use>
</svg>

Now my IDE (IntelliJ) shows no more warnings.

All 10 comments

This is probably related to #578 and #544 , probably an issue related to https://github.com/posthtml

I dug a little deeper and found the point where the AST went wrong: https://github.com/parcel-bundler/parcel/blob/master/src/transforms/posthtml.js#L12

posthtml parsed it correctly but the minifier htmlnano built an incorrect AST of index.html. Heres a little script that verifies this:

const posthtml = require('posthtml')
const htmlnano = require('htmlnano')

const html = `
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <svg xmlns="http://www.w3.org/2000/svg">
      <defs>
        <g id="circle">
          <circle cx="100" cy="100" r="100"/>
        </g>
      </defs>
    </svg>
    <div id="app">
      <svg style="display:block;margin:0 auto;" height="250px">
        <use xlink:href='#circle' href='#circle'/>
      </svg>
    </div>
  </body>
</html>
`

const result = posthtml()
  .process(html, { sync: true })
  .html
console.log(result)

const options = {
  collapseWhitespace: 'conservative'
}
htmlnano.process(html, options).then((result) => {
  console.log(JSON.stringify(result.tree[3]))
})

posthtml output:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <svg xmlns="http://www.w3.org/2000/svg">
      <defs>
        <g id="circle">
          <circle cx="100" cy="100" r="100"></circle>
        </g>
      </defs>
    </svg>
    <div id="app">
      <svg style="display:block;margin:0 auto;" height="250px">
        <use xlink:href="#circle" href="#circle"></use>
      </svg>
    </div>
  </body>
</html>

htmlnano output (defs and use tags are gone):

{"tag":"html","attrs":{"lang":"en"},"content":[" ",{"tag":"head","content":[" ",{"tag":"meta","attrs":{"charset":"utf-8"}}," "]}," ",{"tag":"body","content":[" ",{"tag":false,"attrs":{},"content":"<svg xmlns=\"http://www.w3.org/2000/svg\"/>"}," ",{"tag":"div","attrs":{"id":"app"},"content":[" ",{"tag":false,"attrs":{}}," "]}," "]}," "]}

I looked in htmlnano and the problem seems to be SVGO. If I disable svg minification, it works.

const options = {
  collapseWhitespace: 'conservative',
  minifySvg: false
}

@alyssaq could u report this to either htmlnano or svgo? as this appears to be an issue that should get resolved with either of these projects.
Minifysvg should minify not remove the svg so this is a bug with one of these projects not with parcel

Ha, its my fault. I ran each snippet of the svg in svgo and got this error:
{ error: 'Error in parsing SVG: Unbound namespace prefix: "xlink"\nLine: 0\nColumn: 98\nChar: >' }

I added the xlink prefix to the svg tag:

<svg xmlns:xlink="http://www.w3.org/1999/xlink" style="display:block;margin:0 auto;" >
     <use xlink:href='#circle' href='#circle'/>
</svg>

parcel build index.html correctly outputted the svg!

Learnt something new about svg.
Thanks for responding so quickly. 馃槃

@alyssaq after a quick research at the specs it looks like both attributes are required xmlns and xmlns:xlink at the svg element.

<svg xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink"
>
    <use xlink:href="assets/sprite.svg#icon"></use>
</svg>

Now my IDE (IntelliJ) shows no more warnings.

This is still broken. Parceljs is modifying my html-embedded SVG...

Please re-open

@speigg A quick work around: pass --no-minify to parcel build, or move your inline svg standalone.

This is designed behavior of posthtml, which calls htmlnano as minifier, which calls svgo to minify your inline svg.

Also still seeing this with SVG symbols which are then being used later in a HTML file. Disabling minification fixed this, but it'd be great to see a proper fix.

Please file an issue with htmlnano.

Was this page helpful?
0 / 5 - 0 ratings