Sass经Sprockets编译后format双引号引发Rails模板读取异常求助
问题拆解
我明白你碰到的麻烦了:原本用font-url定义的@font-face规则,经过Sprockets编译后,format('woff')里的单引号被换成了双引号format("woff"),结果在Rails模板里用=File.read "#{Rails.root}/public#..."读取编译后的CSS时,双引号和模板字符串的双引号撞车,直接抛出了异常。
先把你的代码对比列出来更清楚:
- 原始CSS代码:
@font-face { font-family: 'proxima-nova'; src: font-url(/assets/proxima_nova_reg-webfont.woff) format('woff'); font-weight: 400; font-style: normal; }
- Sprockets编译后输出:
@font-face { font-family: 'proxima-nova'; src: url(/assets/proxima_nova_reg-webfont.woff) format("woff"); font-weight: 400; font-style: normal }
可行的解决办法
这里给你几个实用的方案,按需选就行:
1. 转义读取内容里的双引号
最简单的办法就是读取文件后,把里面的双引号转义一下,避免和模板的外层双引号冲突。把模板里的代码改成这样:
= File.read("#{Rails.root}/public/path/to/your/compiled.css").gsub('"', '\\"')
这个gsub方法会把所有双引号替换成转义后的\",这样模板解析的时候就不会报错了。
2. 改Sprockets配置,强制用单引号
要是想从根源上解决,不让Sprockets把单引号换成双引号,可以在项目的config/initializers/assets.rb里加一段配置,自定义一个CSS后处理器:
Rails.application.config.assets.configure do |env| env.register_postprocessor 'text/css', :force_single_quotes do |context, css_content| css_content.gsub(/format\("([^"]+)"\)/, "format('\\1')") end end
这个处理器会把编译后CSS里的format("xxx")替换回format('xxx'),以后编译出来的代码就都是单引号了,自然不会有冲突问题。
3. 用单引号包裹File.read的路径(注意限制)
如果你的路径不需要动态插值,直接把File.read的路径用单引号包起来也行:
= File.read '/public/path/to/your/css.css'
不过要注意,Ruby的单引号字符串不会解析#{}插值,要是你的路径里需要用#{Rails.root}这种动态变量,这个方法就用不了,还是得选第一种转义的方式。
总结
个人最推荐第一种转义的方法,不用改配置,直接处理读取后的内容,快速见效;要是你希望一劳永逸,第二种配置Sprockets处理器的方式更彻底。根据你的实际场景挑就行。
内容的提问来源于stack exchange,提问作者Roberto Pezzali

