Process source files with external program via custom extension

I’m a bit of a newbie to Ruby although I’ve been using Middleman for my blog for a while so I know Middleman relatively well from a non-code perspective.

I’m currently trying to write a Middleman extension that will let me process files in the source folder with a “.dart” (Dart language) extension and run them through the dart2js compiler.

It’d be really great if someone can point me in the right direction. I’ve read a bunch of blog posts and the Middleman documentation on Custom Extensions but some example code would really help me figure the rest out.

Thanks.

I’ve made some progress on this and would love feedback from anyone.

class Dart2Js < Middleman::Extension
  def initialize(app, options_hash={}, &block)
    super

    app.before_configuration do
      template_extensions :dart => :js
    end
  end

  def manipulate_resource_list(resources)
    sources = resources.dup

    # filter resources to only those with the right extension
    sources = resources.select { |i| i.ext == ".dart" }
    # filter out the files in the "packages" directory
    sources = sources.select { |i| !i.source_file.include? "packages" }

    sources.each do |source|
      src = "#{source.source_file}"
      out = "#{source.source_file.gsub!('source', 'build').gsub!('.dart', '.js')}"
      pkgDir = "#{Dir.pwd}/source/javascripts/packages"

      output = system("dart2js #{src} --out=#{out} --package-root=#{pkgDir}")
      source.destination_path=source.destination_path.gsub!('.dart', '.js')
    end
  end
end

Dart2Js.register(:dart2js)

There’s a couple of strange things going on with this code. I think that the code to filter the resources down to only the Dart source files destroys the sitemap. :disappointed:

Am I moving in the right direction with this or am I integrating with Middleman in the wrong way?

Ok, so for anyone following along I’ve made some more progress and the current code for the custom extension looks like this:

class Dart2Js < Middleman::Extension
  def initialize(app, options_hash={}, &block)
    super
  end

  def manipulate_resource_list(resources)
    resources.each do |resource|
      # check if extension isn't a ".dart" file
      next if resource.ext != ".dart"

      # check if file is a library dependency
      next if resource.source_file.include? "packages"

      # change the destination file extension to JS
      resource.destination_path = resource.destination_path.chomp(".dart") + ".js"

      # create build file path
      FileUtils.mkdir_p("build/javascripts") unless File.exists?("build/javascripts")

      # run the dart2js compiler
      system("dart2js #{resource.source_file} --out=build/#{resource.destination_path} --package-root=source/javascripts/packages")
    end
  end
end

Dart2Js.register(:dart2js)

The only problem I have left is that when I run the build process with the extension active I get these errors:

       error  build/javascripts/dashboard.js
Not found
Option :lang is not supported by Slim::Engine
Option :lang is not supported by Slim::Engine
Option :locals is not supported by Slim::Engine
      remove  build/javascripts/dashboard.js.deps
      remove  build/javascripts/dashboard.js.gz
      remove  build/javascripts/dashboard.js.map
      remove  build/javascripts/dashboard.precompiled.js
        gzip  build/javascripts/dashboard.js.gz (1.5 MB smaller)
        gzip  Total gzip savings: 1.5 MB
There were errors during this build

I’m not entirely sure what’s causing Middleman to think that the file doesn’t exist even though the file is present in the build folder with this path build/javascripts/dashboard.js