middleman/middleman-sprockets — pull request #67 by stevenosloan (2014-09-19 18:17:46+00:00)
Title: Prevent duplicate imported assets

This started with tracking down a couple bugs, and ended up here. There are a couple changes in behavior (not covered by any existing tests) that I think make things much more predictable.

This is a pretty big set of changes, so I'm sure there are some edge cases I didn't consider and slipped through. I'm open to any feedback y'all have on it.

---

#### tl;dr;

- assets won't be imported twice if they match multiple sprockets lookup paths
- if an assets logical_path matches as an "asset directory", it is rewritten to match the app config
- the output_dir argument for imported is a little more flexible in accepting procs/lambdas with/without arguments and not blowing up on you

#### doubled imports

This is where I jumped in, I noticed on one of our projects that we were getting an imported file built twice. A replicable project would have a file at `vendor/assets/css/test.css`, then in config.rb:

```ruby
sprockets.append_path 'vendor/assets'
sprockets.import_asset 'css/test.css'
```

The issue coming from the cat that 'vendor/assets' is added to the lookup_paths so that the css file can be imported as `css/test.css` instead of `test.css`. (there are a couple other reasons I find it useful to have vendor/assets in sprockets' paths, but namespacing imports is one of them) Since middleman is automatically adding 'vendor/assets/css' to sprockets' lookup paths it is matched twice in the nested loop in the [resource_manipulator](https://github.com/middleman/middleman-sprockets/blob/v3-stable/lib/middleman-sprockets/extension.rb#L86-L87).

#### destination path not matching app config

In the case an asset gem is putting assets in a non-standard location, but still naming them that they can be recognized as an "asset type" directory the current behavior builds them to the wrong directory.

For example a gem that has a file at `resources/css/file.css`, and appends `resources` to sprockets' paths. When you import the file `sprockets.import_asset 'css/file.css'` and have your css_dir set to 'stylesheets', it will be built to `build/stylesheets/css/file.css`. The new behavior will build it to `build/stylesheets/file.css`

#### more flexible output_dir procs

Just noticed while writing specs that ImportedAsset *always* calls with the logical_path, so this just checks that the proc accepts that arity before trying with the logical_path.