dbashford / mimosa-bower

Bower integration module for mimosa
3 stars 2 forks source link

Installing zurb foundation #3

Closed aharonp closed 11 years ago

aharonp commented 11 years ago

I'm trying to install foundation. It's listed in the bower component directory but just links to the github page. I don't see any bower.json file however. Based on instructions on their website for a "standalone installation" (relevant when not using a Ruby stack), my bower.json file looks like this:

{
  "name": "test",
  "version": "0.1.0",
  "dependencies": {
    "foundation": "https://github.com/zurb/foundation.git#scss-standalone"
  }
}

It downloads/installs the scss-standalone branch into the .mimosa/bower_components folder. This part works. There is no bower.json file in the Git repo so it seems that Bower automatically creates a .bower.json file, but without any "main files" specified. I assume I need to use the mainOverrides config to specify the files to use. This is where I'm confused:

dbashford commented 11 years ago

Working one thing at a time, could you give me the single .js file you used?

Going to play with that example for a bit and see what I might be able to do to accommodate it as best I can. I'll come back with some answers after I've played around with what is possible for a bit.

dbashford commented 11 years ago

So I through up a test project to start playing with foundation and I first tested the single js file thing. This mimosa-config yanks the expected file and tosses it where you'd expect it to go: in vendor/foundation. Is this not working?

exports.config =
  modules: ["server","require","minify","lint","live-reload","bower"]
  bower:
    copy:
      mainOverrides:
        foundation: ['js/foundation/foundation.abide.js']
dbashford commented 11 years ago

I've also updated the version and pushed to include a single log statement if the overrides config points to a file that does not exist, so you should at least get a message if that is the case.

Working on some of the other things.

dbashford commented 11 years ago

I've just pushed 0.3.0 which allows you to put a directory path to include all files in that directory. The code will detect that a provided existing path is a directory and suck up all the files inside.

If there are individual files that you want to leave out, for instance the very Rails-y foundation/js/foundation/index.js, you can add those to the exclude.

So, back to your 5 bullets above...

  1. You can now use directories
  2. Yes, you can do the same with JS fies
  3. In this case I'm fine getting off that path. It's all about UX and allowing for folders is good UX. I'm sad I didn't think of it.
  4. The decision making goes like this: Does it end in .js, then it goes in the vendor.javascripts folder. Otherwise it goes in the vendor.stylesheets folder. This means fonts, images, etc, end up in stylesheets, which might not always be perfect, but it is certainly common. Usually images go hand in hand with some sort of styling framework or library, so stylesheets makes sense. Short of someone providing a one to one mapping of file and destination (which is bad UX!) I'm not sure what else to do here.
  5. Hopefully this was just a config goof up, but let me know if you keep having trouble.
aharonp commented 11 years ago

[edited]

Thanks for those updates. It's very useful to be able to specify directories and not just files.

Regarding "foundation" specifically, these are the issues I'm now having:

Mimosa config file:

  ...
  bower:
    copy:
      mainOverrides:
        foundation: [ "scss", "js/foundation" ]

bower.json:

{
  "name": "test",
  "version": "0.1.0",
  "dependencies": {
    "foundation": "https://github.com/zurb/foundation.git#scss-standalone"
  }
}
  1. Once it has installed foundation into .mimosa (from an initial run), when I rerun mimosa build it does not copy any of the files into the project. It does copy everything into the project after I delete the .mimosa folder but then if I delete the folders inside the project (e.g. assets/javascripts/vendor) but without deleting the .mimosa folder, and rerun mimosa build it does not copy any of the files into the project. It simply reports that there's nothing to install.
  2. The javascript files all get copied directly into the vendor/foundation folder, which in this case works well. However if you look at the scss folder, you'll see a folder structure on which the scss files themselves depend, i.e. the main foundation.scss file specified dependencies based on the folder path. When all of the scss files get copied into the project, they lose that folder structure and so the scss files fail to compile with errors about missing dependencies:
18:58:01 - File [[ /project/assets/css/vendor/foundation/foundation.scss ]] failed compile. Reason: Syntax error: File to import not found or unreadable: foundation/variables.

It would seem that the solution is to simply specify bower:copy:strategy: 'none' and this indeed solves the problem of the scss files not compiling as it's now able to find the dependencies because the folder structure stays intact. However, it introduces a new problem: The file structure in the assets folder now looks like this:

assets
  javascripts
    vendor
      foundation
        foundation   <-- an extra unwanted folder
          *.js
  stylesheets
    vendor
      foundation
        scss            <-- an extra unwanted folder
          foundation.scss
          (other scss files/folders..)

If I can propose the following solution:

  1. Allow path mappings. Here's an example:
bower:
  copy:
    packages:
      foundation:                        # name of package
        strategy: "packageRoot|vendorRoot|none"     # optional, overrides the global 'strategy'
        mappings: [
          { from: "js/foundation", to: "foo", strategy: ".." }     # map the 'js/foundation' path based on the 'strategy':
                                                  # 'vendorRoot' = map to 'javascripts/vendor/foo' (keep folder structure intact)
                                                  # 'packageRoot' = map to 'javascripts/vendor/foundation/foo'  (keep folder structure intact)
                                                  # 'none' = map to 'javascripts/vendor/foo' (put all files into this folder so don't keep folder structure intact)
                                                  # 'strategy' is optional and overrides the global and package specific strategy
                                                  # in reality, I would probably map to an empty string (using the 'packageRoot' strategy), meaning to 'javascripts/vendor/foundation', or else to 'foundation' (using the 'none' strategy) if there's a nested folder structure that I don't want.
          { from: "scss/foundation", to: "" }    # using the 'packageRoot' strategy, this would copy the files inside that folder (keeping the nested folder structure intact) to 'stylesheets/vendor/foundation' (which is exactly what I want)
        ]

So for the foundation package, I would have the following config:

bower:
  copy:
    packages:
      foundation:
        mappings: [
          { from: "scss/foundation", to: "", strategy: "packageRoot" }
          { from: "js/foundation", to: "", strategy: "packageRoot" }
        ]

The above config will produce the following result:

assets
  javascripts
    vendor
      foundation
        *.js
  stylesheets
    vendor
      foundation
        foundation.scss
        normalize.scss
        foundation
          _variables.scss
          ...

You may feel this approach is too complex, but I've tried to propose a solution that won't conflict with what's already implemented and provides significant flexibility, all of which is optional if needed. It probably needs more thought though for different scenarios and edge cases.

What do you think?

aharonp commented 11 years ago

A further option is to reuse mainOverrides instead of introducing mappings, which are both essentially referring to the same thing. So it could work like this:

bower:
  copy:
    packages:
      package1:
        strategy: ".."   # optional override of global strategy
        mainOverrides: [
          { from: "source/path", to: "destination/path", strategy: ".." }   # 'strategy' is an optional path specific override
          { from: "source/path2", to: "destination/path2" }
        ]
      package2:
        ...

Alternatively (and this even more closely matches the existing configuration structure):

bower:
  copy:
    mainOverrides:
      package1: ["path/to/file1", "path/to/file2"]   # the current implementation
      package2: [
        { from: "path/to/file1", to: "dest/path/to/file1", strategy: ".." }
        { from: "path/to/file2", to: "dest/path/to/file2" }
        "path/to/file3"                                     # you can maybe even combine the 2 types as shown here
                                                  # equivalent to: { from: "path/to/file3", "" } ?? (would be nice but not essential..)
      ]
aharonp commented 11 years ago

One problem with my last suggestion is that you can't specify/override the strategy at the package level. To do this, you'd probably need the package name key to have an object/hashmap value instead of an array. This would mean the following example structure:

bower:
  copy:
    mainOverrides:
      package1: ["path/to/file1", "path/to/file2"]   # the current implementation
      package2: {
        strategy: "..."
        mappings: [                   # or "paths"
          { from: "path/to/file1", to: "dest/path/to/file1", strategy: ".." }
          { from: "path/to/file2", to: "dest/path/to/file2" }
        ]
      }

In response to your earlier answer to my original "point 4":

Short of someone providing a one to one mapping of file and destination (which is bad UX!) I'm not sure what else to do here.

I don't think my approach would be considered bad UX as this last approach should fit nicely into the existing config structure and offer the ability to customize and fine tune where necessary while otherwise staying out of the way in most normal cases.

aharonp commented 11 years ago

It seems I mentioned two distinct and separate issues above, the first one being a bug, the second one being a feature request. Feel free to split them into separate issues.

dbashford commented 11 years ago

You've managed to talk yourself right to the config I think I like the best. =)

First though, yeah, I definitely see the feature request we're talking about with the config updates. Which thing is the bug? The single js file not copying? That still a problem? I wasn't able to repro.

It's key for me that the simple config, the one that will work in most cases, remain simple, and the complex config be an option, just a rarely used one. The only thing that feels wrong is the repeated strategy. Presumably there'd be one at the top too. Each more deeply nested strategy overriding the one above it.

But I'm not sure the strategy works at the from/to level. I'd think the from/to would short circuit the strategy, it sort of is the strategy. Moving this file/folder to that file/folder is itself a "custom" strategy. I can definitely see the package level strategy though.

bower:
  copy:
    strategy: "..."
    mainOverrides:
      package1: ["path/to/file1", "path/to/file2"]   # the current implementation
      package2: {
        strategy: "..."
        mappings: [                   # or "paths"
          { from: "path/to/file1", to: "dest/path/to/file1", strategy: ".." }
          { from: "path/to/file2", to: "dest/path/to/file2" }
        ]
      }
aharonp commented 11 years ago

Regarding the bug, here's the problem reproduced from above:

Regarding "foundation" specifically, these are the issues I'm now having:

Mimosa config file:

  ...
  bower:
    copy:
      mainOverrides:
        foundation: [ "scss", "js/foundation" ]

bower.json:

{
  "name": "test",
  "version": "0.1.0",
  "dependencies": {
    "foundation": "https://github.com/zurb/foundation.git#scss-standalone"
  }
}

Once it has installed foundation into .mimosa (from an initial run), when I rerun mimosa build it does not copy any of the files into the project. It does copy everything into the project after I delete the .mimosa folder but then if I delete the folders inside the project (e.g. assets/javascripts/vendor) but without deleting the .mimosa folder, and rerun mimosa build it does not copy any of the files into the project. It simply reports that there's nothing to install.

If you're unable to reproduce this bug, then I can attempt to do so in a clean project and push to a new repo on github for you to try out. Let me know if you'd like me to do that.

Comments about the new config proposal coming up next...

dbashford commented 11 years ago

O, I see, so if you run the install, and it does its thing, and then you go and update, for instance, your mimosa-config to try a new setup and re-run the install, it doesn't do anything?

See dbashford/mimosa#239 for me putting down some thoughts to help that among other things. The problem is I'm leaving Bower in control of when installs happen, and what Bower cares about is what is in .mimosa/bower_components. If it sees that nothing needs to be installed, based entirely on the contents of that folder, it doesn't do anything. And if it doesn't do anything, mimosa-bower assumes there is nothing to do.

I could let mimosa-bower perform asset copying regardless of whether or not Bower installed anything, but that would require leaving the assets hanging around.

If, before you perform any sort of config changes, you do a mimosa bower:clean, it should clean up all that was installed and the temp directories and let you start from scratch. Then make the config changes before running mimosa bower.

aharonp commented 11 years ago

Continued thread about these config enhancements in #4

aharonp commented 11 years ago

Ok I see. So the assumption is that once bower.json has been configured and you run a clean bower install, you need to run another clean bower install if you make any config changes. Otherwise Mimosa will only do something if Bower sees and makes changes.

Knowing that and understanding what's going on really does helps.

So it's not a bug.. it's a feature :)

dbashford commented 11 years ago

The monitoring of both the bower.json and bower config proposed in dbashford/mimosa#238 would solve this problem I think.

aharonp commented 11 years ago

Right, makes sense.

But at least I understand that, as it stands, if I make a change to the mimosa config, I should do a clean bower install in order to trigger a copy.

aharonp commented 11 years ago

Hopefully knowing that will solve the issues I've been having (apart from the config limitations which file mappings would solve). I'll let you know if there is still an issue/bug.

dbashford commented 11 years ago

Before you change the mimosa-config do a mimosa bower:clean. If you wait until after you make the change, then mimosa-bower can't help clean up all of the watch.sourceDir. It uses all the same logic, using the bower config, to figure out where the copied assets ended up so it can clean them up. If you change the config, mimosa-bower won't be able to locate the copied assets for the changed config.

I have a busy day ahead of me tomorrow, so not sure if I'll be able to work through all the updates we worked out as quickly as I'd normally like. Bit at a time. =)

dbashford commented 11 years ago

Going to close this out as all the items in it are represented elsewhere.

mbana commented 10 years ago

I am wanting to achieve the same thing. I would like to know if it's possible to keep the file structure intact. If you look at https://github.com/zurb/bower-foundation/tree/master/js/ then the config below.. All the JS files are put into assets/javascripts/vendor/foundation without keeping the directory structure above - i.e., foundation and vendor and missing.

  bower:
    copy:
      mainOverrides:
        foundation: [ "js/", "css/" ]

Thanks,

dbashford commented 10 years ago

What you are looking for is an object override. See this gist for details, specifically the highlighted line. Let me know if you have any questions.

mbana commented 10 years ago

Thanks. This did the trick for anyone having the same problem:

exports.config =
  minMimosaVersion:"0.14.14"
  modules: ["server","minify","lint","live-reload","bower"]
  template:
    amdWrap: false
  server:
    defaultServer:
      enabled:true
    views:
      compileWith: 'html'
      extension: 'html'
  bower:
    copy:
      mainOverrides:
        "foundation": [
          {
            js: "foundation"
            css: "foundation"
          }
        ]
  growl:
    onStartup: false
    onSuccess:
      javascript: false
      css: false
      template: false
      copy: false