Hoe kan ik bestanden hernoemen met Grunt, gebaseerd op de naam van de bovenliggende map van het betreffende bestand?

Ik heb de volgende structuur:

src/
    modules/
        module1/
            js/
                main.js
            scss/
                main.scss
            index.html
        module2/
            js/
                main.js
            scss/
                main.scss
            index.html

Ik wil graag een grunttaak uitvoeren om deze naar de volgende structuur te kopiëren:

dev/
    js/
        module1.js
        module2.js
    css/
        module1.css
        module2.css
    module1.html
    module2.html

Is er een manier om dit te doen met een bestaande grunt-plug-in? Zo niet, hoe kan ik dit bereiken?


Antwoord 1, autoriteit 100%

Dit kan gedaan worden met de grunt-contrib-copyplug-in.

Het belangrijkste om op te merken is dat je de bestemming programmatisch kunt wijzigen door een hernoemingsfunctie te gebruiken (die de bestemming en de bron van elk bestand inneemt).

Hier is een (enigszins broos) voorbeeld Gruntfile.jsdat naar de gewenste structuur moet worden gekopieerd:

module.exports = function(grunt) {
  // Project configuration.
  grunt.initConfig({
    copy: {
      main: {
        files: [
          {
            expand: true, 
            cwd: 'src/modules/', 
            src: ['**/*.js'], 
            dest: 'dev/js/', 
            rename: function(dest, src) {
              // use the source directory to create the file
              // example with your directory structure
              //   dest = 'dev/js/'
              //   src = 'module1/js/main.js'
              return dest + src.substring(0, src.indexOf('/')) + '.js';
            }
          },
          {
            expand: true, 
            cwd: 'src/modules/', 
            src: ['**/*.scss'], 
            dest: 'dev/css/', 
            rename: function(dest, src) {
              return dest + src.substring(0, src.indexOf('/')) + '.css';
            }
          },
          {
            expand: true, 
            cwd: 'src/modules/', 
            src: ['**/*.html'], 
            dest: 'dev/', 
            rename: function(dest, src) {
              return dest + src.substring(0, src.indexOf('/')) + '.html';
            }
          }
        ]
      }
    }
  });
  grunt.loadNpmTasks('grunt-contrib-copy');
  // Default task(s).
  grunt.registerTask('default', ['copy']);
};

Antwoord 2, autoriteit 7%

Het is niet meer nodig om grunt-contrib-copyalleen hiervoor meer te gebruiken, je kunt nu profiteren van grunt.file.expandMappingmet opties om gewoon te veranderen de bestandsextensie, of om een ​​functie te definiëren die de uitvoerbestandsnaam retourneert.

Hier is een voorbeeld van een files-object in een jade-taak voor het compileren van .jade-sjablonen in .html-bestanden:

files: [{
    expand: true, 
    src: "**/*.jade", 
    dest: "<%= distDir %>", 
    cwd: "<%= assetsDir %>/jade", 
    rename: function(dest, matchedSrcPath, options) {
        // return the destination path and filename:
        return (dest + matchedSrcPath).replace('.jade', '.html');
    }
}]

In dit geval zou het gemakkelijker zijn geweest om de optie ext: '.html'te gebruiken in plaats van de optie rename, maar ik gebruik renamehier zodat je kunt zien hoe het werkt.

Meer info over de exten rename(en andere) opties in de grunt.file docs. Nog enkele voorbeelden hieren hier.


Antwoord 3, autoriteit 2%

U kunt gewoon de opties gebruiken:
uitbreiden: waar,
afvlakken: waar

Geen aangepaste callbacks voor hernoemen nodig.


Antwoord 4

Niet bepaald een antwoord op uw vraag maar ik heb het hier gehad op zoek naar relatieve dest mappen met grom dus … hier is hoe ik het loste

...
base: {
  files:
  [
    {
      expand: true,
      cwd: 'app/design/frontend/',
      src: ['**/Magento_Sales/email-src/*.html'],
      dest: '../../Magento_Sales/email/',
      rename: function(dest, src, expand) {
        src = path.parse(src)
        return path.join(expand.cwd, src.dir, dest, src.base);
      }
    },
  ],
}
...

Deze kleine bit path.join(expand.cwd, src.dir, dest, src.base);gewoon het maken van het pad dat ik nodig heb.

expand.cwd = app/design/frontend/

src.dir = <DYNAMIC_FOLDERS>/Magento_Sales/email-src/

dest = ../../Magento_Sales/email/

src.base = <FILE>.html

en alles samen het = app/design/frontend/<COMPANY>/<MAIN-THEME>/Magento_Sales/email/<FILE>.html

En in mijn situatie zal het nu mijn HTML-e-mails compileren in relatieve bestemmingsmappen


Antwoord 5

Als u.coffee-bestanden wilt hernoemen naar .js of iets dergelijks, kunt u deze gewoon aanpassen;)

sudo npm installeer grom-convect-kopie

copy: {
  rename: {
    files: [{
     expand: true,
     dot: true,
     cwd: './app/scripts',
     dest: './app/scripts/',
     src: [
       '**/*.coffee'
     ],
     rename: function(dest, src) {
       console.log(dest + src);
       return dest + src.replace('.coffee','.js');
     }
   }]
  }
},

Antwoord 6

Ik wilde het bestand opslaan in een MIN-map die is gemaakt op de root waar we het bestand hebben gevonden, dus het is meer eenvoudig om de plug-in-map in een ander project te moozen:

-- Plugins/    
     -- bootstrap/                
            -- bootstrap.js
            -- bootstrap.css
            -- min/
                 -- bootstrap.min.js
                 -- bootstrap.min.css

Ik post de oplossing die ik heb gevonden dankzij deze pagina Misschien kan het anderen helpen:

uglify: {
    options: {
        mangle: true
    },
    dynamic_mappings: {
        // Grunt will search for "**/*.js" under "Plugins/" when the "uglify" task
        // runs and build the appropriate src-dest file mappings then, so you
        // don't need to update the Gruntfile when files are added or removed.
        files: [
            {
                expand: true,     // Enable dynamic expansion.
                cwd: 'Plugins/',  // Src matches are relative to this path.
                src: ['**/*.js', '!**/*.min.js'], // Pattern to match (ignore .min files)
                dest: '/min/',     // Destination path prefix.
                ext: '.min.js',   // Dest filepaths will have this extension.
                extDot: 'last',   // Extensions in filenames begin after the first dot
                rename: function( dest, matchedPath, options ) {
                    Pathname = matchedPath.substring( 0, matchedPath.indexOf('/') );
                    Filename = matchedPath.replace( Pathname, '' );
                    //Return "Plugins / plugin_folder / min / file_name.min.js"
                    return options.cwd + Pathname + dest + Filename;
                }
            },
        ],
    },
}

Other episodes