Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Invalid markup generated when combined with html-loader #126

Closed
edmorley opened this issue Sep 26, 2017 · 6 comments
Closed

Invalid markup generated when combined with html-loader #126

edmorley opened this issue Sep 26, 2017 · 6 comments

Comments

@edmorley
Copy link

edmorley commented Sep 26, 2017

Summary:

For SVG URLs used in HTML (eg via a template loaded via html-loader by HtmlWebpackPlugin), superfluous quotes are added to the HTML markup, that break rendering in the browser. Whilst svg-url-loader has a noquotes option, I wouldn't have expected to have to use it for this use-case given that it's supported natively by url-loader.

STR:

Run yarn install && yarn webpack using node 8.5.0 and this test project:

package.json

{
  "scripts": {
    "start": "webpack"
  },
  "dependencies": {
    "clean-webpack-plugin": "^0.1.17",
    "file-loader": "^0.11.2",
    "html-loader": "^0.5.1",
    "html-webpack-plugin": "^2.30.1",
    "svg-url-loader": "^2.2.0",
    "url-loader": "^0.5.9",
    "webpack": "^3.6.0"
  }
}

webpack.config.js

const path = require('path');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: '[name].bundle.js',
    path: path.resolve(__dirname, 'dist')
  },
  plugins: [
    new CleanWebpackPlugin(['dist']),
    new HtmlWebpackPlugin({
      template: './src/index.html'
    })
  ],
  module: {
    rules: [
      {
        test: /\.html$/,
        use: ['html-loader']
      },
      {
        test: /\.svg$/,
        use: ['svg-url-loader']
      }
    ]
  }
};

src/index.html

<!DOCTYPE html>
<html>
  <head>
    <title>Testcase</title>
  </head>
  <body>
    <img src="./test.svg" alt="Test SVG image">
  </body>
</html>

src/test.svg

<?xml version="1.0"?>
<svg  xmlns="http://www.w3.org/2000/svg"
      xmlns:xlink="http://www.w3.org/1999/xlink">
    <rect x="10" y="10" height="100" width="100"
          style="stroke:#ff0000; fill: #0000ff"/>
</svg>

src/index.js

// Empty file

Expected:

That svg-url-loader acts as a drop in replacement for url-loader (or if that's not intended, then this ideally would be made clearer in the README).

ie: The resultant dist/index.html should still:

Actual:

The resultant dist/index.html:

  • doesn't display in Firefox Nightly correctly (no image shown, just the alt text)
  • doesn't pass HTML validation on https://html5.validator.nu/ due to the extra set of quotes (plus also a whitespace issue, though that's less of a problem since even with that, the image would still work in the browser)

The generated file contents:

<!DOCTYPE html>
<html>
  <head>
    <title>Testcase</title>
  </head>
  <body>
    <img src=""data:image/svg+xml,%3C?xml version='1.0'?%3E %3Csvg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3E %3Crect x='10' y='10' height='100' width='100' style='stroke:%23ff0000; fill: %230000ff'/%3E %3C/svg%3E"" alt="Test SVG image">
  <script type="text/javascript" src="main.bundle.js"></script></body>
</html>

Compared to the output when svg-url-loader is replaced by url-loader in webpack.config.js:

<!DOCTYPE html>
<html>
  <head>
    <title>Testcase</title>
  </head>
  <body>
    <img src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIj8+CjxzdmcgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgICAgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPgogICAgPHJlY3QgeD0iMTAiIHk9IjEwIiBoZWlnaHQ9IjEwMCIgd2lkdGg9IjEwMCIKICAgICAgICAgIHN0eWxlPSJzdHJva2U6I2ZmMDAwMDsgZmlsbDogIzAwMDBmZiIvPgo8L3N2Zz4=" alt="Test SVG image">
  <script type="text/javascript" src="main.bundle.js"></script></body>
</html>

Modifying both svg-url-loader and url-loader locally, adding console.log() calls to show the raw string being returned by each loader, gives...

svg-url-loader:

module.exports = "\"data:image/svg+xml,%3C?xml version='1.0'?%3E %3Csvg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3E %3Crect x='10' y='10' height='100' width='100' style='stroke:%23ff0000; fill: %230000ff'/%3E %3C/svg%3E\""

url-loader:

module.exports = "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIj8+CjxzdmcgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgICAgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPgogICAgPHJlY3QgeD0iMTAiIHk9IjEwIiBoZWlnaHQ9IjEwMCIgd2lkdGg9IjEwMCIKICAgICAgICAgIHN0eWxlPSJzdHJva2U6I2ZmMDAwMDsgZmlsbDogIzAwMDBmZiIvPgo8L3N2Zz4="
@bhovhannes
Copy link
Owner

I see your point.
Have you tried to use noquotes option? Will it fix your issue?

@edmorley
Copy link
Author

Hi :-)

Yeah noquotes fixes the issue, however it feels like it shouldn't be something that consumers have to know/use to result in valid markup.

I've dug into this some more, and I think the real issue here is that svg-url-loader should never wrap in quotes, and the only reason it has to for the CSS url() use-case is that css-loader is incorrectly stripping quotes for these style of data URIs.

As such I've filed webpack-contrib/css-loader#615, and hopefully once that's fixed, svg-url-loader can stop adding quotes entirely and the noquotes option/complexity can just be removed :-)

@ubnt-marc-khouri
Copy link

Hi @bhovhannes, I believe the issue is fixed in css-loader (webpack-contrib/css-loader#627), so modules such as this one don't need to be wrapping their data urls in quotes. Would you consider dropping the noquotes option, or defaulting it to true instead?

Thank you for your work on the plugin!

@bhovhannes
Copy link
Owner

@ubnt-marc-khouri I have to check if everything works fine with the new recent version of css-loader and noquotes=true option.
If everything will be fine, I'd like to drop noquotes option, however I also don't want to break someone's code with the new version.
My very preliminary thoughts (after Friday 🍺) are to publish a new version which will log a warning if noquotes option is used. After some time publish a major version where noquotes will be removed.

Not sure if I'll have a time for open-source this days, but I'll work on that at some point during next week.

bhovhannes added a commit that referenced this issue Jun 29, 2019
BREAKING CHANGE: `noquotes` loader option has been removed. See #126 for more details and rationale behind that change.
@temple
Copy link

temple commented Apr 27, 2020

Apparently, this seems not to work, cause somehow something swallows surrounding quotes of single valued attributes, such for example src attribute for <img> tags.

See this project sample at commit 2b81598, what has html-loader and svg-url-loader.

If you inspect the template index.html, you'll see an <img> tag like:

        <img id="logo" src="../assets/img/spinner.svg" alt="Loading">

After building, the output index.html has this <img> tag with an unquoted inline svg value at its src attribute, like this:

<img id=logo src=data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='

Some may say this is a bug from svg-url-loader, but the ugly truth is that you may disable svg-url-loader and the quotes still disappear.

@temple
Copy link

temple commented Apr 27, 2020

Apparently, this seems not to work, cause somehow something swallows surrounding quotes of single valued attributes, such for example src attribute for <img> tags.

See this project sample at commit 2b81598, what has html-loader and svg-url-loader.

If you inspect the template index.html, you'll see an <img> tag like:

        <img id="logo" src="../assets/img/spinner.svg" alt="Loading">

After building, the output index.html has this <img> tag with an unquoted inline svg value at its src attribute, like this:

<img id=logo src=data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='

Some may say this is a bug from svg-url-loader, but the ugly truth is that you may disable svg-url-loader and the quotes still disappear.

As a possible workaround, setting removeAttributeQuotes to false in the minimize options object, may work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants