Search code examples
gulpstylusgulp-rename

Using gulp and gulp-rename to output multiple stylus theme files


I'm trying to set up a theme system for my project, what I have currently takes a theme file in stylus like theme\default.theme.styl that only includes variables storing colors and applies it to whatever other component style files we have included (e.g. button.styl). The idea is that I can have more than one theme file, say blue.theme.styl and red.theme.styl and gulp will output two separate css files based on the component styling. So I'd get button.blue.styl and button.red.styl as two separate files.

We want to be able to tell gulp which themes to compile through the CLI, so I set up the gulp task to take a build option of 'theme', and I'm using gulp-rename to add the theme name to the output files. But, I can't get gulp to output multiple theme files if I give it more than one theme option.

TaskManager.createTask
  name: 'css'
  description: 'Build the component CSS files'
  options: buildOptions.concat
    name: 'theme'
    type: 'Array'
    description: 'themes to compile'
    default: 'default'
    supported: ['default', 'blue', 'red']
  hide: true
  fn: ->
    themeName = TaskManager.getArg('theme')
    DEST = 'dest'
    nib = require 'nib'
    stream = gulp.src ["src/**/*.styl", "!src/theme/*", "!src/global/*"]
      .pipe(plugins.plumber(errorHandler: TaskManager.error))
      .pipe(plugins.stylus
        use: [
          nib()
        ]
        include: [
          'src/util'
          'src/global'
          'src/theme'
        ]
        import: themeName.map (val) -> "#{val}.theme"
      )
      .pipe(rename (path) ->
        path.extname = ".#{themeName}.css"
        undefined
      )
      .pipe(plugins.filelog 'css')
      .pipe(gulp.dest 'dest')

This works as expected if I give it only one option at build so that gulp --theme='blue' will output button.blue.css with the appropriate theme styling. But if I give it more than one option like gulp --theme='blue,red' I get files named button.blue,red.css that have whichever theme's file variables were included last as the colors that were applied.

Makes sense from what I understand of gulp and gulp-rename, but I want to be able to split the pipe at this point to get two different files. I don't want to actually copy the files into a new directory, and solutions that manually create multiple streams to concatenate are not a satisfactory since I might only have one theme or there might be twelve, and I don't want to have to edit the build file to add new themes. So how can I get multiple files compiled separately out of one stream?


Solution

  • Turns out it works to just return an array of streams:

    TaskManager.createTask
      name: 'css'
      description: 'Build the component CSS files'
      options: buildOptions.concat
        name: 'theme'
        type: 'Array'
        description: 'themes to compile'
        default: 'default'
        supported: ['default', 'blue', 'red']
      hide: true
      fn: ->
        themes = TaskManager.getArg('theme')
        DEST = 'dest/components'
        nib = require 'nib'
    
        stream = []
    
        createTask = (themeName) ->
          return gulp.src ["src/**/*.styl", "!src/theme/*", "!src/global/*"]
            .pipe(plugins.plumber(errorHandler: TaskManager.error))
            .pipe(plugins.stylus
              use: [
                nib()
              ]
              include: [
                'src/util'
                'src/global'
                'src/theme'
              ]
              import: "#{themeName}.theme"
            )
            .pipe(rename (path) ->
              path.extname = ".#{themeName}.css"
              undefined
            )
            .pipe(plugins.filelog 'css')
            .pipe(gulp.dest 'dest')
    
        themes.map (name) ->
          task = createTask name
          stream.push task
    
        return stream