madskristensen / WebEssentials2013

Visual Studio extension
http://vswebessentials.com
Other
944 stars 252 forks source link

css `content:` is manipulated when minified. #616

Closed blowsie closed 10 years ago

blowsie commented 10 years ago

The minifier now changes

This:

.fa-cog:before {
  content: "\f013";
}

To this:

.fa-cog:before{content:""}

This effects libraries such as font-awesome, bootsrap and of course any other code using the same technique.

am11 commented 10 years ago

Cc: @ronklogan

Its supposed to be fixed by https://ajaxmin.codeplex.com/workitem/20541.

Btw if this was reported by you, then you know where to file this bug report. We will update the assembly, once AjaxMin's vNext is released.

blowsie commented 10 years ago

Yep my bad, I struggle to remember these small things.

Just trying to do my part by reporting bugs :+1:

@ronklogan , do you need me to report a bug in ajaxmin?

am11 commented 10 years ago

Great! :+1:

Looks like the issue is caused by line 103 of CssScanner.cs.

ronklogan commented 10 years ago

Yes, please file an AjaxMin bug, with examples. Thanks!

Sent from my mobile device

On Feb 4, 2014, at 9:26 AM, "Adeel Mujahid" notifications@github.com wrote:

Great!

Looks like the issue is caused by line 103 of CssScanner.cs.

— Reply to this email directly or view it on GitHub.

blowsie commented 10 years ago

https://ajaxmin.codeplex.com/workitem/20706

ronklogan commented 10 years ago

Thanks!

Sent from my mobile device

On Feb 4, 2014, at 10:00 AM, "Sam Blowes" notifications@github.com wrote:

https://ajaxmin.codeplex.com/workitem/20706

— Reply to this email directly or view it on GitHub.

ronklogan commented 10 years ago

No, you are mistaken. There is no bug here; the output correctly contains a Unicode U+F013 character, which is what "\f013" represents.

blowsie commented 10 years ago

have you tested this with font-awesome or bootstrap? it breaks horribly.

SLaks commented 10 years ago

That may be because you're serving the CSS files with the wrong character encoding.

blowsie commented 10 years ago

I follow google's best practices for file encoding and end up with these results.

.fa-glass:before{content:""}.fa-music:before{content:""}.fa-search:before{content:""}.fa-envelope-o:before{content:""}.fa-heart:before{content:""}.fa-star:before{content:""}.fa-star-o:before{content:""}.fa-user:before{content:""}.fa-film:before{content:""}.fa-th-large:before{content:""}.fa-th:before{content:""}.fa-th-list:before{content:""}.fa-check:before{content:""}.fa-times:before{content:""}.fa-search-plus:before{content:""}.fa-search-minus:before{content:""}.fa-power-off:before{content:""}.fa-signal:before{content:""}.fa-gear:before,.fa-cog:before{content:""}.fa-trash-o:before{content:""}.fa-home:before{content:""}.fa-file-o:before{content:""}.fa-clock-o:before{content:""}.fa-road:before{content:""}.fa-download:before{content:""}.fa-arrow-circle-o-down:before{content:""}.fa-arrow-circle-o-up:before{content:""}.fa-inbox:before{content:""}.fa-play-circle-o:before{content:""}.fa-rotate-right:before,.fa-repeat:before{content:""}.fa-refresh:before{content:""}.fa-list-alt:before{content:""}.fa-lock:before{content:""}.fa-flag:before{content:""}.fa-headphones:before{content:""}.fa-volume-off:before{content:""}.fa-volume-down:before{content:""}.fa-volume-up:before{content:""}.fa-qrcode:before{content:""}.fa-barcode:before{content:""}.fa-tag:before{content:""}.fa-tags:before{content:""}.fa-book:before{content:""}.fa-bookmark:before{content:""}.fa-print:before{content:""}.fa-camera:before{content:""}.fa-font:before{content:""}.fa-bold:before{content:""}.fa-italic:before{content:""}.fa-text-height:before{content:""}.fa-text-width:before{content:""}.fa-align-left:before{content:""}.fa-align-center:before{content:""}.fa-align-right:before{content:""}.fa-align-justify:before{content:""}.fa-list:before{content:""}.fa-dedent:before,.fa-outdent:before{content:""}.fa-indent:before{content:""}.fa-video-camera:before{content:""}.fa-picture-o:before{content:""}.fa-pencil:before{content:""}.fa-map-marker:before{content:""}.fa-adjust:before{content:""}.fa-tint:before{content:""}.fa-edit:before,.fa-pencil-square-o:before{content:""}.fa-share-square-o:before{content:""}.fa-check-square-o:before{content:""}
ronklogan commented 10 years ago

Yes -- I have explicitly tested with font-awesome the last time someone reported this issue, and it works just fine.

Text encodings is something that trips people up a lot. As SLaks points out, you must make sure that your server is serving up the right encoding. If you are generating UTF-8 files, you have to make sure that the server is sending them to the client as UTF-8. If you can't change the server's encoding for whatever reason (if you can, you SHOULD be serving up UTF-8), you can always tell AjaxMin to generate whatever output encoding you need to match the server. For instance, if your server is serving up your CSS as ASCII, use the -enc:out ASCII switch and AjaxMin will output your files as ASCII, in which case, your Unicode character will be escaped.

blowsie commented 10 years ago

My webconfig.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.web>
        <compilation debug="true" targetFramework="4.5" />
        <httpRuntime targetFramework="4.5" />
        <globalization fileEncoding="utf-8" requestEncoding="utf-8" responseEncoding="utf-8" />
    </system.web>
    <system.webServer>
        <!--Set default Document-->
        <defaultDocument>
            <files>
                <clear />
                <add value="index.min.html" />
                <add value="index.html" />
            </files>
        </defaultDocument>
        <!--Allow Static-->
        <staticContent>
            <clientCache cacheControlMaxAge="7.00:00:00" cacheControlMode="UseMaxAge"></clientCache>
            <remove fileExtension=".woff" />
            <mimeMap fileExtension=".woff" mimeType="application/x-font-woff" />
            <mimeMap fileExtension=".json" mimeType="application/json" />
            <mimeMap fileExtension=".appcache" mimeType="text/cache-manifest" />
        </staticContent>
        <!--GZIP-->
        <httpCompression directory="%SystemDrive%\inetpub\temp\IIS Temporary Compressed Files">
            <scheme name="gzip" dll="%Windir%\system32\inetsrv\gzip.dll"/>
            <dynamicTypes>
                <add mimeType="text/*" enabled="true"/>
                <add mimeType="message/*" enabled="true"/>
                <add mimeType="application/javascript" enabled="true"/>
                <add mimeType="*/*" enabled="false"/>
            </dynamicTypes>
            <staticTypes>
                <add mimeType="text/*" enabled="true"/>
                <add mimeType="message/*" enabled="true"/>
                <add mimeType="application/javascript" enabled="true"/>
                <add mimeType="*/*" enabled="false"/>
            </staticTypes>
        </httpCompression>
        <urlCompression doStaticCompression="true" doDynamicCompression="true"/>
        <httpProtocol>
            <customHeaders>
                <add name="Content-Type" value="charset='UTF-8'" />
                <remove name="Vary"></remove>
                <add name="Vary" value="Accept-Encoding"></add>
            </customHeaders>
        </httpProtocol>
        <!--<handlers>
            <add name="Browser Link for HTML" path="*.html" verb="*"
                  type="System.Web.StaticFileHandler, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
                  resourceType="File" preCondition="integratedMode" />
        </handlers>-->
    </system.webServer>
</configuration>
blowsie commented 10 years ago

Ive tried removing the following lines and still get the same results

<globalization fileEncoding="utf-8" requestEncoding="utf-8" responseEncoding="utf-8" />

   <httpProtocol>
            <customHeaders>
                <add name="Content-Type" value="charset='UTF-8'" />
                <remove name="Vary"></remove>
                <add name="Vary" value="Accept-Encoding"></add>
            </customHeaders>
        </httpProtocol>
ronklogan commented 10 years ago

If you want to create and serve ASCII files, just set AjaxMin to output ASCII files and you're done.

ronklogan commented 10 years ago

To tell AjaxMin to output ascii files, use the -enc:out ascii switch.

blowsie commented 10 years ago

Strange, Im pretty sure something must have changed in the minifier or WE to cause this issue. I have been using the minifed versions of the css files in my project for quite some time without any issues.

Using the -enc:out switch certainly isn't an option for me as I don't have control over this when using WE.

SLaks commented 10 years ago

What's the actual Content-Type header that gets sent to the browser?

blowsie commented 10 years ago

Here are the headers for the request. You can see the response specifies UTF-8

Request URL:http://localhost:1337/assets/css/libs.min.css
Request Method:GET
Status Code:200 OK

Request Headers

Accept:text/css,*/*;q=0.1
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-GB,en;q=0.8
Cache-Control:no-cache
Connection:keep-alive
Host:localhost:1337
Pragma:no-cache
Referer:http://localhost:1337/
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36

Response Headers

Accept-Ranges:bytes
Cache-Control:max-age=604800
Content-Encoding:gzip
Content-Length:34557
Content-Type:text/css,charset='UTF-8'
Date:Wed, 05 Feb 2014 16:46:18 GMT
ETag:"43c685318722cf1:0"
Last-Modified:Wed, 05 Feb 2014 15:30:26 GMT
Server:Microsoft-IIS/8.0
Vary:Accept-Encoding
X-Powered-By:ASP.NET
X-SourceFiles:=?UTF-8?B?RDpcU3RhcnRlYW1cRGV2ZWxvcG1lbnRcVUtcV2ViXFdlYlBPU19FQ29ubmVjdFxXZWJQT1NfRUNvbm5lY3RcYXNzZXRzXGNzc1xsaWJzLm1pbi5jc3M=?=
SLaks commented 10 years ago

I believe the quotes around the charset are incorrect. Does removing them help? Also, it should be separated by a ;, not a ,.

blowsie commented 10 years ago

Nope same issue.

Request URL:http://localhost:1337/assets/css/libs.min.css
Request Method:GET
Status Code:200 OK

Request Headers

Accept:text/css,*/*;q=0.1
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-GB,en;q=0.8
Cache-Control:no-cache
Connection:keep-alive
Host:localhost:1337
Pragma:no-cache
Referer:http://localhost:1337/
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36

Response Headers

Accept-Ranges:bytes
Cache-Control:max-age=604800
Content-Encoding:gzip
Content-Length:34557
Content-Type:text/css,charset=UTF-8
Date:Wed, 05 Feb 2014 16:52:31 GMT
ETag:"43c685318722cf1:0"
Last-Modified:Wed, 05 Feb 2014 15:30:26 GMT
Server:Microsoft-IIS/8.0
Vary:Accept-Encoding
X-Powered-By:ASP.NET
X-SourceFiles:=?UTF-8?B?RDpcU3RhcnRlYW1cRGV2ZWxvcG1lbnRcVUtcV2ViXFdlYlBPU19FQ29ubmVjdFxXZWJQT1NfRUNvbm5lY3RcYXNzZXRzXGNzc1xsaWJzLm1pbi5jc3M=?=
blowsie commented 10 years ago

Also, it should be separated by a ;, not a ,.

Any ideas how to change this? IIS is implementing the ,

blowsie commented 10 years ago

I managed to get this working by removing the filetype and adding it in again manually.

        <staticContent>
            <remove fileExtension=".css" />
            <mimeMap fileExtension=".css" mimeType="text/css;charset=UTF-8" />
        </staticContent>

Im hoping IIS provides a better way of doing this. I will report back here if I find anything better.

blowsie commented 10 years ago

This issue is worse than its seems, the text/css;charset=UTF-8 fix I applied to my web.config fixes chrome, but breaks IE. After a lot of research it appears that there is no way round this in IIS.

https://github.com/h5bp/server-configs/issues/15

This means you cant use the minified files that WE / AjaxMin produces without one of the following results.

madskristensen commented 10 years ago

I'm using Bootstrap and FontAwesome with no issues at all. I don't set the charset specifically like you do though

blowsie commented 10 years ago

And your using the minified files, in Chrome?

cvrebert commented 10 years ago

Have you tried including an encoding declaration in the CSS itself? (e.g. @charset "UTF-8";)

j2jensen commented 3 years ago

We recently had this issue crop up in an environment using the Sophos XG WAF: the little tofu box in the font CSS file was getting translated into ASCII characters somewhere between the static file on the server and the browser. The fix mentioned above worked to fix it. It's weird, because there's actually no difference in the response headers or anything (they always showed text/css;charset=utf-8 as the encoding type), but somehow re-mapping the mime type made it respect the encoding when the file got sent across the wire.