class Sass::Render

The {Observer} for {Embedded#render}.

def canonicalize_response(canonicalize_request)

def canonicalize_response(canonicalize_request)
  url = Util.file_uri(File.absolute_path(canonicalize_request.url, (@file.nil? ? 'stdin' : @file)))
  begin
    result = @importer[canonicalize_request.importer_id].call canonicalize_request.url, @file
    raise result if result.is_a? StandardError
  rescue StandardError => e
    return EmbeddedProtocol::InboundMessage::CanonicalizeResponse.new(
      id: canonicalize_request.id,
      error: e.message
    )
  end
  if result&.key? :contents
    @import_responses[url] = EmbeddedProtocol::InboundMessage::ImportResponse.new(
      id: canonicalize_request.id,
      success: EmbeddedProtocol::InboundMessage::ImportResponse::ImportSuccess.new(
        contents: result[:contents],
        syntax: EmbeddedProtocol::Syntax::SCSS,
        source_map_url: nil
      )
    )
    EmbeddedProtocol::InboundMessage::CanonicalizeResponse.new(
      id: canonicalize_request.id,
      url: url
    )
  elsif result&.key? :file
    canonicalized_url = Util.file_uri(result[:file])
    # TODO: FileImportRequest is not supported yet.
    # Workaround by reading contents and return it when server asks
    @import_responses[canonicalized_url] = EmbeddedProtocol::InboundMessage::ImportResponse.new(
      id: canonicalize_request.id,
      success: EmbeddedProtocol::InboundMessage::ImportResponse::ImportSuccess.new(
        contents: File.read(result[:file]),
        syntax: EmbeddedProtocol::Syntax::SCSS,
        source_map_url: nil
      )
    )
    EmbeddedProtocol::InboundMessage::CanonicalizeResponse.new(
      id: canonicalize_request.id,
      url: canonicalized_url
    )
  else
    EmbeddedProtocol::InboundMessage::CanonicalizeResponse.new(
      id: canonicalize_request.id
    )
  end
end

def compile_request

def compile_request
  EmbeddedProtocol::InboundMessage::CompileRequest.new(
    id: @id,
    string: string,
    path: path,
    style: style,
    source_map: source_map,
    importers: importers,
    global_functions: global_functions,
    alert_color: $stderr.tty?,
    alert_ascii: Platform::OS == 'windows'
  )
end

def function_call_response(function_call_request)

def function_call_response(function_call_request)
  EmbeddedProtocol::InboundMessage::FunctionCallResponse.new(
    id: function_call_request.id,
    success: @functions[function_call_request.name].call(*function_call_request.arguments)
  )
rescue StandardError => e
  EmbeddedProtocol::InboundMessage::FunctionCallResponse.new(
    id: function_call_request.id,
    error: e.message
  )
end

def import_response(import_request)

def import_response(import_request)
  url = import_request.url
  if @import_responses.key? url
    @import_responses[url].id = import_request.id
  else
    @import_responses[url] = EmbeddedProtocol::InboundMessage::ImportResponse.new(
      id: import_request.id,
      error: "Failed to import: #{url}"
    )
  end
  @import_responses[url]
end

def importers

be semicolon-separated on Windows and colon-separated elsewhere.
5. Each load path specified in the SASS_PATH environment variable, which should
4. Each load path in includePaths
3. Loading a file relative to the current working directory.
2. Each custom importer.
1. Loading a file relative to the file in which the @use or @import appeared.
Order
def importers
  custom_importers = @importer.map.with_index do |_, id|
    EmbeddedProtocol::InboundMessage::CompileRequest::Importer.new(
      importer_id: id
    )
  end
  include_path_importers = @include_paths
                           .concat(Sass.include_paths)
                           .map do |include_path|
    EmbeddedProtocol::InboundMessage::CompileRequest::Importer.new(
      path: File.absolute_path(include_path)
    )
  end
  custom_importers.concat include_path_importers
end

def initialize(transport, id,

def initialize(transport, id,
               data:,
               file:,
               indented_syntax:,
               include_paths:,
               output_style:,
               source_map:,
               out_file:,
               functions:,
               importer:)
  raise ArgumentError, 'either data or file must be set' if file.nil? && data.nil?
  @id = id
  @data = data
  @file = file
  @indented_syntax = indented_syntax
  @include_paths = include_paths
  @output_style = output_style
  @source_map = source_map
  @out_file = out_file
  @global_functions = functions.keys
  @functions = functions.transform_keys do |key|
    key.to_s.split('(')[0].chomp
  end
  @importer = importer
  @import_responses = {}
  super(transport)
  send_message compile_request
end

def path

def path
  @file if @data.nil?
end

def source_map

def source_map
  @source_map.is_a?(String) || (@source_map == true && !@out_file.nil?)
end

def string

def string
  return if @data.nil?
  EmbeddedProtocol::InboundMessage::CompileRequest::StringInput.new(
    source: @data,
    url: url,
    syntax: syntax
  )
end

def style

def style
  case @output_style&.to_sym
  when :expanded
    EmbeddedProtocol::OutputStyle::EXPANDED
  when :compressed
    EmbeddedProtocol::OutputStyle::COMPRESSED
  else
    raise ArgumentError, 'output_style must be one of :expanded, :compressed'
  end
end

def syntax

def syntax
  if @indented_syntax == true
    EmbeddedProtocol::Syntax::INDENTED
  else
    EmbeddedProtocol::Syntax::SCSS
  end
end

def update(error, message)

def update(error, message)
  raise error unless error.nil?
  case message
  when EmbeddedProtocol::ProtocolError
    raise ProtocolError, message.message
  when EmbeddedProtocol::OutboundMessage::CompileResponse
    return unless message.id == @id
    Thread.new do
      super(nil, message)
    end
  when EmbeddedProtocol::OutboundMessage::LogEvent
    return unless message.compilation_id == @id && $stderr.tty?
    warn message.formatted
  when EmbeddedProtocol::OutboundMessage::CanonicalizeRequest
    return unless message.compilation_id == @id
    Thread.new do
      send_message canonicalize_response message
    end
  when EmbeddedProtocol::OutboundMessage::ImportRequest
    return unless message.compilation_id == @id
    Thread.new do
      send_message import_response message
    end
  when EmbeddedProtocol::OutboundMessage::FileImportRequest
    raise NotImplementedError, 'FileImportRequest is not implemented'
  when EmbeddedProtocol::OutboundMessage::FunctionCallRequest
    return unless message.compilation_id == @id
    Thread.new do
      send_message function_call_response message
    end
  end
rescue StandardError => e
  Thread.new do
    super(e, nil)
  end
end

def url

def url
  return if @file.nil?
  Util.file_uri @file
end