Rails - 如何在手动 sass 编译中传递 Sprockets::Context
Rails - How to pass Sprockets::Context in manual sass compiling
我正在使用以下代码片段手动编译 sass 清单,其中附加了一些变量覆盖。
template = File.read("#{Rails.root}/app/assets/schemes/#{scheme}/css/styles.css.scss")
scheme_variables.each do |key, value|
template << "$#{key}:#{value};\n"
end
engine = Sass::Engine.new(template, {
:syntax => :scss,
:cache => false,
:read_cache => false,
:style => :compressed,
:filesystem_importer => Sass::Rails::SassImporter,
:load_paths => MyApp::Application.assets.paths,
:sprockets => {
:context => ?,
:environment => MyApp::Application.assets
}
})
output = engine.render
Sass::Engine 构造函数需要选项散列中的链轮上下文和环境。我在上下文中输入了什么?我尝试的第一件事是...
:context => MyApp::Application.assets.context_class,
...但这给了我以下错误 "undefined method `font_path' for #" 当它击中我的一个 sass 资产助手时。
我尝试的第二件事是...
:context => ActionController::Base.helpers,
...这解决了资产助手问题,但在它尝试通过我的 glob 导入(例如 @import "mixins/*")时抛出以下错误 "undefined method `depend_on' for #"。
我正在使用 Rails 4.2 和 sass-rails 5.0.3.
如有任何建议,我们将不胜感激。谢谢!
我最终以稍微不同的方式解决了这个问题——使用 Sass::Rails::ScssTemplate 的渲染方法。基本上,我将修改后的 css 字符串写入文件并将其传递给 Sass::Rails::ScssTemplate 构造函数。然后我编译并在完成后删除临时文件。这感觉不太好,但对我来说效果很好。
scheme_css_dir = "#{Rails.root}/app/assets/schemes/#{scheme}/css"
css = File.read("#{scheme_css_dir}/styles.css.scss")
variables_str = ''
scheme_variables.each do |key, value|
variables_str << "$#{key}:#{value};\n"
end
css.gsub!('@import "./variables";', variables_str)
file = Tempfile.new(['styles', '.css.scss'], scheme_css_dir)
file.write(css)
file.close
abs_path = file.path
relative_path = abs_path[Rails.root.to_s.size + 1..-1]
template = Sass::Rails::ScssTemplate.new(abs_path)
environment = Evrconnect::Application.assets
context = environment.context_class.new(
:environment => environment,
:name => relative_path,
:filename => abs_path,
:metadata => {}
)
output = template.render(context)
file.unlink
要回答您的原始问题,您需要提供当前的 view_context
,或使用 ActionView::Base.new
创建一个。
http://apidock.com/rails/AbstractController/Rendering/view_context
通过使用 Sass::Rails::ScssTemplate,您可以使用以下代码段呈现 sass 代码:
template = '...' # Your sass code
logical_path = pathname = ''
environment = Rails.application.assets
context = environment.context_class.new(environment, logical_path, pathname)
template = Sass::Rails::ScssTemplate.new(pathname) { template }
output = template.render(context, {})
如果你想从文件中渲染,那么只需将其路径添加到路径名并将其资源路径添加到 logical_path。
对我来说,它适用于 Rails 4.2.5.1 和 sass-rails 5.0.4.
在 Rails 5.x 中,Sprockets v3.7.x
NOTE: Following method requires: Rails.application.config.assets.compile == true
, i.e., set config.assets.compile = true
. Check Sprockets README
我使用以下代码手动返回 sass/js 的编译源。
# For Scss Assets
def pdf_stylesheet_link_tag(name)
if Rails.env.development?
asset = Rails.application.assets.find_asset(name + '.scss')
raw ('<style type="text/css">' + asset.source + '</style>')
else
raw ('<style type="text/css">' + pdf_asset_contents(name, '.css') + '</style>')
end
end
# For Javascript Assets
def pdf_javascript_include_tag(name, *type)
if Rails.env.development?
if debug? # Can be used to check `debug == true` in params for current route
javascript_include_tag(name)
else
asset = Rails.application.assets.find_asset(name + '.js')
raw ('<script>' + asset.source + '</script>')
end
else
javascript_tag pdf_asset_contents(name, '.js')
end
end
以上代码实际上有助于动态传递 sass/js 的编译版本
到 Wicked_PDF,这实际上有助于在开发环境中为生成的 PDF 加载样式和 js。
pdf_stylesheet_link_tag
可以用作模板的助手,在 development/stage(其中,config.assets.precompile == false
)中,而不是使用 wicked_pdf_stylesheet_link_tag
(实际上需要一个路径到预编译的源文件)。
经过一夜的摸索,找到了今天的做法,分享给大家("today"意思是:rails 5.2.1 和 sprockets 3.7.2)。
按预期工作:不需要临时文件,接受@import,允许资产路径助手。
# Compile SASS and return the resulting string
# Pass the file path and name without 'sass' extension, relative to assets/stylesheets
def compile_sass(stylesheet)
# Load file content
path = Rails.root.join 'app', 'assets', 'stylesheets', "#{stylesheet}.sass"
sass = File.read path
# Configure engine
environment = Sprockets::Railtie.build_environment Rails.application
scope = environment.context_class.new environment: environment, \
filename: "/", metadata: {}
scope.sass_config.merge! cache: false, style: :compressed
# Compile
engine = Sass::Rails::SassTemplate.new {sass}
engine.render scope
end
其他 sass_config
选项可以在这里找到:https://github.com/sass/ruby-sass/blob/stable/doc-src/SASS_REFERENCE.md#options
以下适用于 rails
5.2.0、sprockets
3.7.2、sassc-rails
1.3.0 和 sassc
1.12.1:
template = '...' # Your sass code
environment = Sprockets::Railtie.build_environment(Rails.application)
engine = SassC::Rails::SassTemplate.new
engine.call(environment: environment,
filename: '/',
data: template,
metadata: {})[:data]
我正在使用以下代码片段手动编译 sass 清单,其中附加了一些变量覆盖。
template = File.read("#{Rails.root}/app/assets/schemes/#{scheme}/css/styles.css.scss")
scheme_variables.each do |key, value|
template << "$#{key}:#{value};\n"
end
engine = Sass::Engine.new(template, {
:syntax => :scss,
:cache => false,
:read_cache => false,
:style => :compressed,
:filesystem_importer => Sass::Rails::SassImporter,
:load_paths => MyApp::Application.assets.paths,
:sprockets => {
:context => ?,
:environment => MyApp::Application.assets
}
})
output = engine.render
Sass::Engine 构造函数需要选项散列中的链轮上下文和环境。我在上下文中输入了什么?我尝试的第一件事是...
:context => MyApp::Application.assets.context_class,
...但这给了我以下错误 "undefined method `font_path' for #" 当它击中我的一个 sass 资产助手时。
我尝试的第二件事是...
:context => ActionController::Base.helpers,
...这解决了资产助手问题,但在它尝试通过我的 glob 导入(例如 @import "mixins/*")时抛出以下错误 "undefined method `depend_on' for #"。
我正在使用 Rails 4.2 和 sass-rails 5.0.3.
如有任何建议,我们将不胜感激。谢谢!
我最终以稍微不同的方式解决了这个问题——使用 Sass::Rails::ScssTemplate 的渲染方法。基本上,我将修改后的 css 字符串写入文件并将其传递给 Sass::Rails::ScssTemplate 构造函数。然后我编译并在完成后删除临时文件。这感觉不太好,但对我来说效果很好。
scheme_css_dir = "#{Rails.root}/app/assets/schemes/#{scheme}/css"
css = File.read("#{scheme_css_dir}/styles.css.scss")
variables_str = ''
scheme_variables.each do |key, value|
variables_str << "$#{key}:#{value};\n"
end
css.gsub!('@import "./variables";', variables_str)
file = Tempfile.new(['styles', '.css.scss'], scheme_css_dir)
file.write(css)
file.close
abs_path = file.path
relative_path = abs_path[Rails.root.to_s.size + 1..-1]
template = Sass::Rails::ScssTemplate.new(abs_path)
environment = Evrconnect::Application.assets
context = environment.context_class.new(
:environment => environment,
:name => relative_path,
:filename => abs_path,
:metadata => {}
)
output = template.render(context)
file.unlink
要回答您的原始问题,您需要提供当前的 view_context
,或使用 ActionView::Base.new
创建一个。
http://apidock.com/rails/AbstractController/Rendering/view_context
通过使用 Sass::Rails::ScssTemplate,您可以使用以下代码段呈现 sass 代码:
template = '...' # Your sass code
logical_path = pathname = ''
environment = Rails.application.assets
context = environment.context_class.new(environment, logical_path, pathname)
template = Sass::Rails::ScssTemplate.new(pathname) { template }
output = template.render(context, {})
如果你想从文件中渲染,那么只需将其路径添加到路径名并将其资源路径添加到 logical_path。
对我来说,它适用于 Rails 4.2.5.1 和 sass-rails 5.0.4.
在 Rails 5.x 中,Sprockets v3.7.x
NOTE: Following method requires:
Rails.application.config.assets.compile == true
, i.e., setconfig.assets.compile = true
. Check Sprockets README
我使用以下代码手动返回 sass/js 的编译源。
# For Scss Assets
def pdf_stylesheet_link_tag(name)
if Rails.env.development?
asset = Rails.application.assets.find_asset(name + '.scss')
raw ('<style type="text/css">' + asset.source + '</style>')
else
raw ('<style type="text/css">' + pdf_asset_contents(name, '.css') + '</style>')
end
end
# For Javascript Assets
def pdf_javascript_include_tag(name, *type)
if Rails.env.development?
if debug? # Can be used to check `debug == true` in params for current route
javascript_include_tag(name)
else
asset = Rails.application.assets.find_asset(name + '.js')
raw ('<script>' + asset.source + '</script>')
end
else
javascript_tag pdf_asset_contents(name, '.js')
end
end
以上代码实际上有助于动态传递 sass/js 的编译版本 到 Wicked_PDF,这实际上有助于在开发环境中为生成的 PDF 加载样式和 js。
pdf_stylesheet_link_tag
可以用作模板的助手,在 development/stage(其中,config.assets.precompile == false
)中,而不是使用 wicked_pdf_stylesheet_link_tag
(实际上需要一个路径到预编译的源文件)。
经过一夜的摸索,找到了今天的做法,分享给大家("today"意思是:rails 5.2.1 和 sprockets 3.7.2)。
按预期工作:不需要临时文件,接受@import,允许资产路径助手。
# Compile SASS and return the resulting string
# Pass the file path and name without 'sass' extension, relative to assets/stylesheets
def compile_sass(stylesheet)
# Load file content
path = Rails.root.join 'app', 'assets', 'stylesheets', "#{stylesheet}.sass"
sass = File.read path
# Configure engine
environment = Sprockets::Railtie.build_environment Rails.application
scope = environment.context_class.new environment: environment, \
filename: "/", metadata: {}
scope.sass_config.merge! cache: false, style: :compressed
# Compile
engine = Sass::Rails::SassTemplate.new {sass}
engine.render scope
end
其他 sass_config
选项可以在这里找到:https://github.com/sass/ruby-sass/blob/stable/doc-src/SASS_REFERENCE.md#options
以下适用于 rails
5.2.0、sprockets
3.7.2、sassc-rails
1.3.0 和 sassc
1.12.1:
template = '...' # Your sass code
environment = Sprockets::Railtie.build_environment(Rails.application)
engine = SassC::Rails::SassTemplate.new
engine.call(environment: environment,
filename: '/',
data: template,
metadata: {})[:data]