How to Generate Images From HTML with Gulp and Puppeteer

Have you ever needed to generate an image from your HTML? Whether it be for design purposes or for marketing purposes with social media, knowing how to get a screenshot of your HTML design without manually taking the screenshot can be a great thing.

A use-case I was interested in was around feature graphics for each of my blog posts. Sure I could open a graphic design tool like Affinity Photo, or use the same feature graphic for every tutorial, but what if I wanted to automatically generate them based on certain criteria?

In this tutorial we’re going to see how to use Puppeteer to take screenshots of our HTML through a headless Gulp task.

To get an idea of what we want to accomplish, take the following as an example:

Example Feature Screenshot

The above image was created entirely with HTML and could satisfy my use case of being a feature image for a tutorial on the blog. In fact, I got the idea after seeing similar feature graphics on DEV.to articles. While I don’t know what their strategy is, I thought I’d invent my own.

Designing an HTML Component or Page for Capture

Before we dive into the process of taking screenshots, we should come up with some HTML to capture. To be clear, any HTML elements would work, but let’s focus on being creative, matching the example I presented earlier.

Create a project with an index.html file, a style.css file, and a few image files. For this particular example, we’ll being using a lot of Flexbox.

Open the project’s style.css file and include the following code:

html, body {
    height: 100vh;
    margin: 0;
    display: flex;
    width: 100vw;
}
#container {
    flex: 1;
    display: flex; 
    flex-direction: column; 
    border: 10px solid black; 
    background-color: #931c22;
    padding: 25px;
    color: #FFFFFF;
}
#body {
    flex-grow: 1; 
    font-size: 4rem; 
    display: flex;
    align-items: center;
    text-transform: uppercase;
    font-weight: bold;
    line-height: 6rem;
}
#footer {
    display: flex; 
    flex-grow: 0; 
    flex-direction: row; 
    align-items: center; 
}
#author {
    flex-grow: 1;
    display: flex;
    flex-direction: row;
    align-items: center;
}
#author-img {
    width: 75px; 
    height: 75px; 
    margin-right: 25px;
    border: 2px solid #FFFFFF;
}
#author-name {
    font-size: 2.5rem;
    margin-right: 10px;
    text-transform: uppercase;
}
#brand-icon {
    width: 75px;
    height: 75px;
    border: 2px solid #FFFFFF;
}

I am by no means a CSS or design expert, so the CSS above may be able to be optimized. However, everything worked as expected when combined with my HTML.

With the CSS in place, open the project’s index.html file and include the following markup:

<!DOCTYPE html>
<html>
    <head>
        <link rel="stylesheet" href="style.css" />
    </head>
    <body>
        <div id="container">
            <div id="body">
                Execute HTTP Requests in JavaScript Applications
            </div>
            <div id="footer">
                <div id="author">
                    <img id="author-img" src="nraboy.jpg">
                    <div id="author-name">
                        Nic Raboy
                    </div>
                </div>
                <img id="brand-icon" src="icon.png">
            </div>
        </div>
    </body>
</html>

In my example, I’ve already downloaded an nraboy.jpg image and an icon.png image. However, feel free to change the CSS, HTML, and images to meet your needs.

Generating Screenshots with Puppeteer and Gulp

Now that we have some HTML in place, we can focus on generating a screenshot of it. To do this we’ll be using Puppeteer, which is a headless Chrome Node.js API.

Within the project, we’ll need to install a few dependencies, which will require Node.js. From the command line, execute the following:

npm install puppeteer gulp gulp-tap --save-dev

While Puppeteer will be doing most of the work, we’ll be using Gulp to manage the task. Since we’ll be using a Gulp file pipeline, we need to be able to tap into the pipeline and gather various information about the files being processed, hence the extra package.

Now that the dependencies are in place, create a gulpfile.js file with the following JavaScript code:

const gulp = require("gulp");
const puppeteer = require("puppeteer");
const tap = require("gulp-tap");
const path = require("path");

gulp.task("build", function () {
    return gulp.src(["**/*.html", "!node_modules/**/*"])
        .pipe(tap(async (file) => {
            const browser = await puppeteer.launch({ headless: true });
            const page = await browser.newPage();
            await page.setViewport({
                width: 1200,
                height: 600,
                deviceScaleFactor: 1,
            });
            await page.goto("file://" + file.path);
            await page.screenshot({ path: path.basename(file.basename, ".html") + ".png" });
            await browser.close();
        }));
});

This particular Gulp configuration has a single task for building the images. The task looks for all HTML files in the directory and excludes anything in the node_modules directory.

For every file in the pipeline, a headless browser is created with the specified viewport configuration. The filename and path is extracted and used for rendering the HTML, then saving the render to an image.

Conclusion

You just saw how to use Puppeteer to capture a screenshot of an HTML render without using browser based JavaScript, meaning completely headless.

There are plenty of use-cases for this, but for me, using HTML as a template for marketing images is great. These images can be generated automatically without having to open a common multimedia editing application.

Original article source at: https://www.thepolyglotdeveloper.com/

#puppeteer #html #gulp 

How to Generate Images From HTML with Gulp and Puppeteer
Gordon  Matlala

Gordon Matlala

1667341080

A Yeoman Generator for Jekyll to Rapidly Build Sites using Gulp

generator-jekyllized

Looking for a (co)-maintainer

I've since stopped using Jekyll and consequently have neither the time nor need to maintain this package, I would however love it if someone who either found this generator useful or wants to help to take over the responsibility in maintaining it. Hit me up on Twitter (@sondr3), Keybase (@sondre) or the mail in my GitHub profile, I'll be more than happy to help you get up and running! :)

NOTE: Currently using gulp 4.0 which is in beta!

Introduction

generator-jekyllized is a very opinionated Yeoman generator built with Jekyll and gulp. You will be able to quickly scaffold your site and start developing. As you are working on your site your assets will automatically be updated and injected into your browser as well as your posts. When you are done developing and want to publish it you are two commands away from having everything optimized and published.

Features

Rapidly prototype

While developing locally everything you change will automatically be updated and injected into your browser. Changing your SCSS or JavaScript files will automatically updated them, create sourcemaps and inject them. Writing or editing posts and pages for your website will do the same. Simple and effective.

Jekyll

Built on top of Jekyll 3, you get a mature and stable base with the full power that Jekyll brings you. You'll have sitemaps, Atom feeds generated and SEO meta data tags added to your posts and pages.

Optimize your assets

When you are done developing you can have your assets optimized and injected correctly into your HTML. Your assets will be minified, compressed with gzip, cache busted and otherwise optimized. Your images will be run through compressors to save space and even your HTML will be minified.

Deploying

Finally, once everything is done and you are ready to publish your site, you can do it via either Amazon S3, Github Pages or Rsync. With a single command your new/updated site is uploaded to your platform of choice.

Getting started

Installation

Dependencies

  • Ruby: >2.0 with Bundler >1.10
  • Node: >4.2 and Yo >1.7.0
  • Gulp: Since the release candidate is running Gulp 4.0 you need to install gulp-cli: npm install gulp-cli -g
  • Jekyllized: Then install Jekyllized: npm install generator-jekyllized -g

Install

  • Scaffold: Run yo jekyllized in the directory you want scaffold your site in
  • Start: Run gulp and watch the magic unfold

Update

To update the generator, run npm update -g generator-jekyllized and then run yo jekyllized:update and it will update your packages and gulp tasks. You can skip installing dependencies by running it with --skip-install. NOTE: Updating will overwrite any changes you've done to your gulp tasks and package.json, so back them up before running it! It will ask before overwriting though, so you can see the diff before applying it.

Usage

gulp [--prod]

This is the default command, and probably the one you'll use the most. This command will build your assets and site with development settings. You'll get sourcemaps, your drafts will be generated and you'll only generate the last 10 posts (for speed). As you are changing your posts, pages and assets they will automatically update and inject into your browser via BrowserSync.

--prod

Once you are done and want to verify that everything works with production settings you add the flag --prod and your assets will be optimized. Your CSS, JS and HTML will be minified and gzipped, plus the CSS and JS will be cache busted. The images will be compressed and Jekyll will generate a site with all your posts and no drafts.

gulp build [--prod]

This command is identical to the normal gulp [--prod] however it will not create a BrowserSync session in your browser.

gulp (build) [--prod] main subtasks

gulp jekyll [--prod]

Without production settings Jekyll will only create the 10 latest posts and will create both future posts and drafts. With --prod none of that is true and it will generate all your posts.

gulp styles|scripts [--prod]

Both your CSS and JS will have sourcemaps generated for them under development settings. Once you generate them with production settings sourcemap generation is disabled. Both will be minified, gzipped and cache busted with production settings.

gulp images

Optimizes and caches your images. This is a set it and forget it command for the most part.

gulp html --prod

Does nothing without --prod. Minifies and gzips your HTML files.

gulp serve

If you just want to watch your site you can run this command. If wanted you can also edit the serve task to allow it to tunnel via localtunnel so people outside your local network can view it as well:

    // tunnel: true,

You can also change the behaviour for how it opens the URL when you run gulp [--prod], you can see the options here:

    // open: false,

gulp deploy

When you're done developing and have built your site with either gulp --prod or gulp build --prod you can deploy your site to either Amazon S3, Github Pages or with Rsync.

Amazon S3 and Rsync

If you chose either of these two, you'll have a [rsync/aws]-credentials.json file in your root folder that you have to fill out. It should be pretty self explanatory, however, if you need any help with configuring it, you should check out either the gulp-awspublish repo or gulp-rsync repo for help.

Github Pages

If you chose to upload to Github Pages there's no configuration besides starting a git repo in your folder, setting an origin remote repo and run gulp deploy. Your site will be automatically pushed to Github. See the FAQ for configuring personal repos vs project repos.

gulp check

Lints your JavaScript files using ESLint with XO Space settings and run jekyll doctor to look for potential errors.

gulp clean

Deletes your assets from their .tmp directory as well as in dist and deletes any gzipped files. NOTE: Does not delete your images from .tmp to reduce the time to build your site due to image optimizations.

gulp rebuild

Only use this if you want to regenerate everything, this will delete everything generated. Images, assets, your Jekyll site. You really shouldn't need to do this.

Subtasks

All of the subtasks lives in their own files in the gulp directory and are named after what they do. You can edit or look at any of them to see how they actually work. They're all commented.

Frequently Asked Questions

Inject more than one JavaScript file

If you want to split up your JavaScript files into say a index.js and a vendor.js file with files from [Bower][bower] you can do this quite easily. Create a copy of the scripts gulp task and rename it to scripts:vendor and change the gulp.src files you need:

  gulp.src([
    'bower_components/somelibrary.js/dist/somelibrary.js',
    'bower_components/otherthing.js/dist/otherthing.js'
  ])

and then change .pipe(concat('index.js')) into .pipe(concat('vendor.js')). Then you go to the bottom of the gulpfile and change the assets task:

gulp.task('assets', gulp.series(
  gulp.series('clean:assets'),
  gulp.parallel('styles', 'scripts:vendor', 'scripts', 'fonts', 'images')
));

Notice the scripts:vendor task that has been added. Also be ware that things are injected in alphabetical order, so if you need your vendor scripts before the index.js file you have to either rename the index.js file or rename the vendor.js file. When you now run gulp or gulp build it will create a vendor.js file and automatically inject it at the bottom of your HTML. When running with --prod it'll automatically optimize and such as well.

For more advanced uses, refer to the gulp-inject documentation on how to create individual inject tags and inject specific files into them.

Github Pages configuration

By default if you select Github Pages as your deployment option your site will be pushed to a gh-pages branch, this works fine for any project pages but won't work for your personal repo. If you want to use a username.github.io site all you have to do is to uncomment the branch line.

gulp.task('upload', (done) => {
  ghPages.publish(path.join(__dirname + '/../../', 'dist'), {
    dotfiles: true,
    // branch: "master"
    },
    done);
});

You might also have to configure the URL for your site if you want to use Github Pages. Luckily the Jekyll documentation has you covered.

Why don't you support Stylus/LESS/Angular/etc

Because I've never used them nor do I have any plans of using them. Furthermore, they're a bit outside what I want with this generator anyways. I want a lean, simple and opinionated generator, not a big complicated one.

Contributing

See the contribution docs.

Changelog

Download Details:

Author: sondr3
Source Code: https://github.com/sondr3/generator-jekyllized 
License: MIT license

#jekyll #gulp #generator 

A Yeoman Generator for Jekyll to Rapidly Build Sites using Gulp
Gordon  Matlala

Gordon Matlala

1667321700

Gulp-tutorial: Code Examples for My Gulp.js Tutorial Series

Introduction to Gulp.js

Tutorial

These are the files for my series Introduction to Gulp.js published on my website stefanimhoff.de.

Preparation

Install nvm and node:

$ git clone https://github.com/creationix/nvm.git ~/.nvm
$ cd ~/.nvm
$ git checkout `git describe --abbrev=0 --tags`
$ export NVM_DIR="$HOME/.nvm/"
$ [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"  # This loads nvm

nvm install 6.3.1

If you like install yarn, I provide a yarn.lock file:

brew install yarn

Install bundler:

$ gem install bundler

Install bower:

$ npm install -g bower

Installation

Clone the repository on your computer and change into the projects folder. Run:

$ bundle
$ bower install
$ npm install

To install Fontcustom you should have Homebrew installed or use another package management tool to install the dependencies:

$ brew install fontforge --with-python
$ brew install eot-utils

Setup

Open gulp/config.js and change settings if needed. Only the rsync settings need to be adjusted. Change the destination to a path on your webserver and change hostname and username.

Running Gulp.js

Three tasks are available (npm works, too):

$ yarn start
$ yarn run publish
$ yarn run deploy
  • Running yarn start will start a development server, build assets and the Jekyll site and start a watch task.
  • Running yarn run publish will copy and optimize assets and run a production build of Jekyll.
  • Running yarn run deploy will copy the generated files with Rsync to your server.

Sass, Compass or PostCSS

The current version of this tutorial uses PostCSS. If you would like to use Sass (or Compass), you can still easily access the old code in the branch ruby-sass. The new code at the time I wrote the article is available in the branch postcss. Additionally I merge it into master and will process with PostCSS in my tutorial.

Credits

This tutorial includes some files for demonstation purposes:

Tutorial Overview

  1. Intro and Setup
  2. Server with BrowserSync and Configuration
  3. Build, Clean and Jekyll
  4. Creating CSS with Sass (and Compass)
  5. Bundling JavaScript with Browserify
  6. Images and Vector Fonts
  7. Base64 Encoded Images
  8. Watch for Changes
  9. Checking the Syntax of SCSS and JavaScript
  10. Generating CSS Image Sprites
  11. Production Build, Server and Jekyll
  12. Optimize CSS, JavaScript, Images and HTML
  13. Revisioning
  14. Deploying the Website with Rsync
  15. Performance Improvements with WebP and Gzip
  16. PostCSS

Download Details:

Author: Kogakure
Source Code: https://github.com/kogakure/gulp-tutorial 

#jekyll #gulp #tutorial 

Gulp-tutorial: Code Examples for My Gulp.js Tutorial Series
Gordon  Matlala

Gordon Matlala

1666683480

Long-haul: A Minimal, Type-focused Jekyll Theme

long-haul

Long Haul is a minimal jekyll theme built with SASS / GULP / BROWSERSYNC / AUTOPREFIXER and focuses on long form blog posts. It is meant to be used as a starting point for a jekyll blog/website.

If you really enjoy Long Haul and want to give me credit somewhere on the internet send or tweet out your experience with Long Haul and tag me @brianmaierjr.

View Demo

Features

  • Minimal, Type Focused Design
  • Built with GULP + SASS + BROWSERSYNC + AUTOPREFIXER
  • SVG Social Icons
  • Responsive Nav Menu
  • XML Feed for RSS Readers
  • Contact Form via Formspree
  • 5 Post Loop with excerpt on Home Page
  • Previous / Next Post Navigation
  • Estimated Reading Time for posts
  • Stylish Drop Cap on posts
  • A Better Type Scale for all devices
  • Comments powered by Disqus
  • Dark Mode support via prefers-color-scheme

Setup

  1. Install Jekyll
  2. Fork the Long Haul repo
  3. Clone it
  4. Install Bundler
  5. Run bundle install
  6. Install gulp dependencies by running npm install
  7. Run Jekyll and watch files by running bundle exec gulp
  8. Customize and watch the magic happen!

Site Settings

The main settings can be found inside the _config.yml file:

  • title: title of your site
  • description: description of your site
  • url: your url
  • paginate: the amount of posts displayed on homepage
  • navigation: these are the links in the main site navigation
  • social diverse social media usernames (optional)
  • google_analytics Google Analytics key (optional)

Header Option

If you'd like your header to be larger then you can use the option below in you config.yml to make it take up half of the vertical space on screens 800px wide and up. Preview image below.

  • header: large

preview Long Haul

Download Details:

Author: brianmaierjr
Source Code: https://github.com/brianmaierjr/long-haul 
License: MIT license

#jekyll #css #gulp #blog 

Long-haul: A Minimal, Type-focused Jekyll Theme
Gordon  Taylor

Gordon Taylor

1662060360

Rewrite Occurences Of Filenames Which Have Been Renamed By Gulp-rev

gulp-rev-replace 

Rewrite occurrences of filenames which have been renamed by gulp-rev

Note: this package is no longer maintained. Development continues in TheDancingCode/gulp-rev-rewrite.

Install

$ npm install --save-dev gulp-rev-replace

Usage

Pipe through a stream which has both the files you want to be updated, as well as the files which have been renamed.

For example, we can use gulp-useref to concatenate assets in an index.html, and then use gulp-rev and gulp-rev-replace to cache-bust them.

var gulp = require('gulp');
var rev = require('gulp-rev');
var revReplace = require('gulp-rev-replace');
var useref = require('gulp-useref');
var filter = require('gulp-filter');
var uglify = require('gulp-uglify');
var csso = require('gulp-csso');

gulp.task("index", function() {
  var jsFilter = filter("**/*.js", { restore: true });
  var cssFilter = filter("**/*.css", { restore: true });
  var indexHtmlFilter = filter(['**/*', '!**/index.html'], { restore: true });

  return gulp.src("src/index.html")
    .pipe(useref())      // Concatenate with gulp-useref
    .pipe(jsFilter)
    .pipe(uglify())             // Minify any javascript sources
    .pipe(jsFilter.restore)
    .pipe(cssFilter)
    .pipe(csso())               // Minify any CSS sources
    .pipe(cssFilter.restore)
    .pipe(indexHtmlFilter)
    .pipe(rev())                // Rename the concatenated files (but not index.html)
    .pipe(indexHtmlFilter.restore)
    .pipe(revReplace())         // Substitute in new filenames
    .pipe(gulp.dest('public'));
});

It is also possible to use gulp-rev-replace without gulp-useref:

var rev = require("gulp-rev");
var revReplace = require("gulp-rev-replace");
gulp.task("revision", ["dist:css", "dist:js"], function(){
  return gulp.src(["dist/**/*.css", "dist/**/*.js"])
    .pipe(rev())
    .pipe(gulp.dest(opt.distFolder))
    .pipe(rev.manifest())
    .pipe(gulp.dest(opt.distFolder))
})

gulp.task("revreplace", ["revision"], function(){
  var manifest = gulp.src("./" + opt.distFolder + "/rev-manifest.json");

  return gulp.src(opt.srcFolder + "/index.html")
    .pipe(revReplace({manifest: manifest}))
    .pipe(gulp.dest(opt.distFolder));
});

API

revReplace(options)

options.canonicalUris

Type: boolean

Default: true

Use canonical Uris when replacing filePaths, i.e. when working with filepaths with non forward slash (/) path separators we replace them with forward slash.

options.replaceInExtensions

Type: Array

Default: ['.js', '.css', '.html', '.hbs']

Only substitute in new filenames in files of these types.

options.prefix

Type: string

Default: ``

Add the prefix string to each replacement.

options.manifest

Type: Stream (e.g., gulp.src())

Read JSON manifests written out by rev. Allows replacing filenames that were reved prior to the current task.

options.modifyUnreved, options.modifyReved

Type: Function

Modify the name of the unreved/reved files before using them. The filename is passed to the function as the first argument.

For example, if in your manifest you have:

{"js/app.js.map": "js/app-98adc164.js.map"}

If you wanted to get rid of the js/ path just for .map files (because they are sourcemaps and the references to them are relative, not absolute) you could do the following:

function replaceJsIfMap(filename) {
    if (filename.indexOf('.map') > -1) {
        return filename.replace('js/', '');
    }
    return filename;
}

return gulp.src(opt.distFolder + '**/*.js')
    .pipe(revReplace({
        manifest: manifest,
        modifyUnreved: replaceJsIfMap,
        modifyReved: replaceJsIfMap
    }))
    .pipe(gulp.dest(opt.distFolder));

Contributors

  • Chad Jablonski
  • Denis Parchenko
  • Evgeniy Vasilev
  • George Song
  • Håkon K. Eide
  • Juan Lasheras
  • Majid Burney
  • Simon Ihmig
  • Vincent Voyer
  • Bradley Abrahams

Download Details:

Author: jamesknelson
Source Code: https://github.com/jamesknelson/gulp-rev-replace 
License: MIT license

#javascript #gulp 

Rewrite Occurences Of Filenames Which Have Been Renamed By Gulp-rev
Gordon  Taylor

Gordon Taylor

1662056520

Static Asset Revisioning By Appending Content Hash to Filenames

gulp-rev

Static asset revisioning by appending content hash to filenames unicorn.cssunicorn-d41d8cd98f.css

This project is feature complete. PRs adding new features will not be accepted.

Make sure to set the files to never expire for this to have an effect.

Install

$ npm install --save-dev gulp-rev

Usage

const gulp = require('gulp');
const rev = require('gulp-rev');

exports.default = () => (
	gulp.src('src/*.css')
		.pipe(rev())
		.pipe(gulp.dest('dist'))
);

API

rev()

rev.manifest(path?, options?)

path

Type: string
Default: 'rev-manifest.json'

Manifest file path.

options

Type: object

base

Type: string
Default: process.cwd()

Override the base of the manifest file.

cwd

Type: string
Default: process.cwd()

Override the current working directory of the manifest file.

merge

Type: boolean
Default: false

Merge existing manifest file.

transformer

Type: object
Default: JSON

An object with parse and stringify methods. This can be used to provide a custom transformer instead of the default JSON for the manifest file.

Original path

Original file paths are stored at file.revOrigPath. This could come in handy for things like rewriting references to the assets.

Asset hash

The hash of each rev'd file is stored at file.revHash. You can use this for customizing the file renaming, or for building different manifest formats.

Asset manifest

const gulp = require('gulp');
const rev = require('gulp-rev');

exports.default = () => (
	// By default, Gulp would pick `assets/css` as the base,
	// so we need to set it explicitly:
	gulp.src(['assets/css/*.css', 'assets/js/*.js'], {base: 'assets'})
		.pipe(gulp.dest('build/assets'))  // Copy original assets to build dir
		.pipe(rev())
		.pipe(gulp.dest('build/assets'))  // Write rev'd assets to build dir
		.pipe(rev.manifest())
		.pipe(gulp.dest('build/assets'))  // Write manifest to build dir
);

An asset manifest, mapping the original paths to the revisioned paths, will be written to build/assets/rev-manifest.json:

{
	"css/unicorn.css": "css/unicorn-d41d8cd98f.css",
	"js/unicorn.js": "js/unicorn-273c2c123f.js"
}

By default, rev-manifest.json will be replaced as a whole. To merge with an existing manifest, pass merge: true and the output destination (as base) to rev.manifest():

const gulp = require('gulp');
const rev = require('gulp-rev');

exports.default = () => (
	// By default, Gulp would pick `assets/css` as the base,
	// so we need to set it explicitly:
	gulp.src(['assets/css/*.css', 'assets/js/*.js'], {base: 'assets'})
		.pipe(gulp.dest('build/assets'))
		.pipe(rev())
		.pipe(gulp.dest('build/assets'))
		.pipe(rev.manifest({
			base: 'build/assets',
			merge: true // Merge with the existing manifest if one exists
		}))
		.pipe(gulp.dest('build/assets'))
);

You can optionally call rev.manifest('manifest.json') to give it a different path or filename.

Sourcemaps and gulp-concat

Because of the way gulp-concat handles file paths, you may need to set cwd and path manually on your gulp-concat instance to get everything to work correctly:

const gulp = require('gulp');
const rev = require('gulp-rev');
const sourcemaps = require('gulp-sourcemaps');
const concat = require('gulp-concat');

exports.default = () => (
	gulp.src('src/*.js')
		.pipe(sourcemaps.init())
		.pipe(concat({path: 'bundle.js', cwd: ''}))
		.pipe(rev())
		.pipe(sourcemaps.write('.'))
		.pipe(gulp.dest('dist'))
);

Different hash for unchanged files

Since the order of streams are not guaranteed, some plugins such as gulp-concat can cause the final file's content and hash to change. To avoid generating a new hash for unchanged source files, you can:

Streaming

This plugin does not support streaming. If you have files from a streaming source, such as Browserify, you should use gulp-buffer before gulp-rev in your pipeline:

const gulp = require('gulp');
const browserify = require('browserify');
const source = require('vinyl-source-stream');
const buffer = require('gulp-buffer');
const rev = require('gulp-rev');

exports.default = () => (
	browserify('src/index.js')
		.bundle({debug: true})
		.pipe(source('index.min.js'))
		.pipe(buffer())
		.pipe(rev())
		.pipe(gulp.dest('dist'))
);

Integration

For more info on how to integrate gulp-rev into your app, have a look at the integration guide.

Use gulp-rev in combination with one or more of

It may be useful - and necessary - to use gulp-rev with other packages to complete the task.

Download Details:

Author: Sindresorhus
Source Code: https://github.com/sindresorhus/gulp-rev 
License: MIT license

#javascript #gulp 

Static Asset Revisioning By Appending Content Hash to Filenames
Gordon  Taylor

Gordon Taylor

1661939460

Gulp-purifycss: Removed Unused CSS with The Gulp Build tool

gulp-purifycss

Clean unnecessary CSS with PurifyCSS

Information

Packagegulp-purifycss
DescriptionClean unnecessary CSS
Node Version>= 0.10

Usage

var purify = require('gulp-purifycss');

gulp.task('css', function() {
  return gulp.src('./public/app/example.css')
    .pipe(purify(['./public/app/**/*.js', './public/**/*.html']))
    .pipe(gulp.dest('./dist/'));
});

Download Details:

Author: Purifycss
Source Code: https://github.com/purifycss/gulp-purifycss 
License: MIT license

#javascript #css #gulp 

Gulp-purifycss: Removed Unused CSS with The Gulp Build tool
Gordon  Taylor

Gordon Taylor

1660674600

A Template for Building Cross Browser Extensions For Chrome, Opera

Extension Boilerplate

A foundation for creating browser extensions for Chrome, Opera & Firefox.

Now that Firefox supports WebExtensions, it has become a lot easier to build browser extensions/addons for multiple browsers without duplicating the codebase. This project serves as a sensible starting point to help you get started.

Extension Boilerplate

I have extracted this from the browser extensions that I built for my side-project, Email This.

Side note: Do check out Email This. It is a simpler alternative to bookmarking tools like Pocket, Readability & Instapaper. Email This will remove ads & distractions from an article and send you a nice email with just the text/images. No need to install any additional applications or login to another app just to access your bookmarks. The Chrome Extensions is available on the Chrome Web Store.

Features

Write once and deploy to Chrome, Opera & Firefox

Based on WebExtensions. It also includes a tiny polyfill to bring uniformity to the APIs exposed by different browsers.

Live-reload

Your changes to CSS, HTML & JS files will be relayed instantly without having to manually reload the extension. This ends up saving a lot of time and improving the developer experience.

Sensible starting point

This comes with a gulp based workflow that converts modern ES6 JavaScript and SCSS to JS/CSS. Scripts are transpiled using Babel and bundled using Browserify. Sourcemaps are available for both JS and SCSS.

Sketch (.sketch) assets for icons and promo images

A .sketch file is included in the resources directory. This has all the icons and promo images that will be needed while uploading the extensions to the app stores.

Easily configurable and extendable

The gulpfile is easily understandable and configurable. If you want to add additional tasks or remove un-used ones, you can easily tweak that file to suit your needs.

Platform specific & Environment specific variables.

You might need to specify different data variables based on your environment. For example, you might want to use a localhost API endpoint during development and a production API endpoint once the extension is submitted to the appstore. You can specify such data in the json files inside `config` directory.

You can also set custom data variables based on the platform (different variable for Chrome, FF, Opera).

Installation

  1. Clone the repository git clone https://github.com/EmailThis/extension-boilerplate.git
  2. Run npm install
  3. Run npm run build

Alternately, if you want to try out the sample extension, here are the download links. After you download it, unzip the file and load it in your browser using the steps mentioned below.

Load the extension in Chrome & Opera

  1. Open Chrome/Opera browser and navigate to chrome://extensions
  2. Select "Developer Mode" and then click "Load unpacked extension..."
  3. From the file browser, choose to extension-boilerplate/build/chrome or (extension-boilerplate/build/opera)

Load the extension in Firefox

  1. Open Firefox browser and navigate to about:debugging
  2. Click "Load Temporary Add-on" and from the file browser, choose extension-boilerplate/build/firefox

Developing

The following tasks can be used when you want to start developing the extension and want to enable live reload -

  • npm run chrome-watch
  • npm run opera-watch
  • npm run firefox-watch

Packaging

Run npm run dist to create a zipped, production-ready extension for each browser. You can then upload that to the appstore.

TODO

  •  Add support for Safari
  •  Add Firefox & Opera Promo images
  •  Add sample screenshot templates
  •  Write a guide for using config variables & JS preprocessor

If you have any questions or comments, please create a new issue. I'd be happy to hear your thoughts.

Bharani, Email This

Download Details:

Author: EmailThis
Source Code: https://github.com/EmailThis/c 
License: MIT license

#javascript #gulp #chrome #es6 

A Template for Building Cross Browser Extensions For Chrome, Opera

Gulp-svgmin: Minify SVG Files with Gulp

gulp-svgmin 

A Gulp plugin to minify SVG files with svgo-url.

Install

With npm do:

npm install gulp-svgmin

Example

import { src, dest } from 'gulp';
import svgmin from 'gulp-svgmin';

const defaultTask = () =>
  src('logo.svg')
    .pipe(svgmin())
    .pipe(dest('./out'));

export default defaultTask;

Configuration file

By default, gulp-svgmin loads options from a svgo.config.js file in your project. See the svgo’s configuration docs for more info on how to write one.

You can control which directory svgo searches for svgo.config.js with the cwd option. Or you can use a different file name with the configFile option.

import { src, dest } from 'gulp';
import svgmin from 'gulp-svgmin';

const defaultTask = () =>
  src('logo.svg')
    .pipe(svgmin({
      // Specify an absolute directory path to
      // search for the config file.
      cwd: '/users/admin/project/assets',
      // This path is relative to process.cwd()
      // or the 'cwd' option.
      configFile: 'images/svg/config.js',
    }))
    .pipe(dest('./out'));

export default defaultTask;

Options

Instead of using a config file, you can pass an object of svgo’s options to the gulp-svgmin plugin. You will need to provide the config in comma separated objects, like the example below.

const defaultTask = () =>
  src('logo.svg')
    .pipe(svgmin({
      // Ensures the best optimization.
      multipass: true,
      js2svg: {
        // Beutifies the SVG output instead of
        // stripping all white space.
        pretty: true,
        indent: 2,
      },
      // Alter the default list of plugins.
      plugins: [
        // You can enable a plugin with just its name.
        'sortAttrs',
        {
          name: 'removeViewBox',
          // Disable a plugin by setting active to false.
          active: false,
        },
        {
          name: 'cleanupIDs',
          // Add plugin options.
          params: {
            minify: true,
          }
        },
      ],
    }))
    .pipe(dest('./out'));

You can view the full list of plugins here.

By default, the plugins list given to the gulp plugin will alter the default list of svgo plugins. Optionally, you can specify your plugins and set the full flag to true to indicate that your plugins list should not be merged with the default list of plugins.

const defaultTask = () =>
  src('logo.svg')
    .pipe(svgmin({
      multipass: true,
      // The plugins list is the full list of plugins
      // to use. The default list is ignored.
      full: true,
      plugins: [
        'removeDoctype',
        'removeComments',
        'sortAttrs',
        // ...
      ],
    }))
    .pipe(dest('./out'));

Per-file options

To have per-file options, pass a function, that receives file object and returns svgo options. For example, if you need to prefix ids with filenames to make them unique before combining svgs with gulp-svgstore:

const defaultTask = () =>
  src('src/*.svg')
    .pipe(svgmin(function getOptions(file) {
      const prefix = path.basename(
        file.relative,
        path.extname(file.relative)
      );
      return {
        plugins: [
          {
            name: 'cleanupIDs',
            parmas: {
              prefix: prefix + '-',
              minify: true,
            },
          },
        ],
      };
    }))
    .pipe(svgstore())
    .pipe(dest('./dest'));

Contributing

Pull requests are welcome. If you add functionality, then please add unit tests to cover it.

If you have any difficulties with the output of this plugin, please use the SVGO tracker.

Author: Ben-eb
Source Code: https://github.com/ben-eb/gulp-svgmin 
License: MIT license

#typescript #javascript #svg #gulp 

Gulp-svgmin: Minify SVG Files with Gulp
Hermann  Frami

Hermann Frami

1654431720

Serverless-gulp: A Thin Task Wrapper Around @goserverless

serverless-gulp

A simple wrapper around serverless 1.x that simplifies the creation of gulp tasks. If you like having all your automation tasks for local and CI in one place eg running unit, acceptance and smoke tests, environment or config specific stuff, and deployment of lambdas, etc and love the simplicity that gulp brings, then this module may help you. Some examples of using gulp with serverless spawn a process with options as arguments to serverless. The approach used by this module uses serverless framework as a node module and provides options to it via your gulpfile.

To get started, npm install this module as a dev dependency:

npm install --save-dev serverless-gulp

This module has a dependency on the following modules:

  • serverless 1.x
  • gulp
  • gulp-util for logging

Once installed, unless you need other gulp task modules, you should not really need any other dev dependencies. Copy the gulpfile below to get started and keep developing your services as you would. To get started, use the code below as your initial gulpfile.js. The idea of this module is to keep things simple, so regardless of how the serverless framework evolves, this module will allow you to specify any command and and options within a gulp task as you would on the command line.

const gulp = require('gulp');
const serverlessGulp = require('serverless-gulp');
const util = require('gulp-util');

const paths = {
  serverless: ['./**/serverless.yml', '!node_modules/**/serverless.yml']
};

gulp.task('deploy', () => {
  gulp.src(paths.serverless, { read: false })
      .pipe(serverlessGulp.exec('deploy', { stage: 'dev' }));
});

gulp.task('remove', () => {
  gulp.src(paths.serverless, { read: false })
    .pipe(serverlessGulp.exec('remove', { stage: 'dev' }));
});

The first argument to serverless-gulp is the command you would pass to serverless framework, eg deploy, invoke, etc; the second takes options for the command. So, for the following command line:

serverless invoke --function someFunction --stage en --region eu-west-2

your gulp task would look something like:

gulp.task('invoke', () => {
  gulp.src(paths.serverless, { read: false })
    .pipe(serverlessGulp.exec('invoke', { function: 'someFunction', stage: 'en', region: 'eu-west-1' }));
});

Installing serverless modules

If you are writing your serverless services in nodejs, then you have to install node modules for each service. You can provide a post install hook in your main npm package to install packages for every service as follows:

Include the following gulp task in your gulpfile.js:

gulp.task('setup', () => {
  gulp.src(paths.serverless)
      .pipe(serverlessGulp.install());
})

Include the following post install step in the package.json

{
  "scripts": {
    "postinstall": "gulp setup"
  }
}

Example project

For a working example, or as a quick start project, fork/copy the repo at https://github.com/rhythminme/serverless-gulp-example

Author: rhythminme
Source Code: https://github.com/rhythminme/serverless-gulp 
License: MIT license

#serverless #gulp 

Serverless-gulp: A Thin Task Wrapper Around @goserverless

Compile Jade Templates into React De-sugared JSX with Gulp

Compile Jade templates to React.DOM

Uses jade-react to compile templates to React.DOM directives as part of your Gulp build process.

The files are kind of useless on their own, so you'll want to prefix+suffix them to handle exporting the generated expressions.

Usage

var gulp = require('gulp');
var jadeReact = require('gulp-jade-react');

// Build React templates
gulp.task('templates', function () {
  gulp.src(['templates/*.jade'])
    .pipe(jadeReact())
    .pipe(gulp.dest('build'))
});

Author: Duncanbeevers
Source Code: https://github.com/duncanbeevers/gulp-jade-react 
License: 

#react #javascript #gulp #jsx 

Compile Jade Templates into React De-sugared JSX with Gulp
Sheldon  Grant

Sheldon Grant

1652708052

Yeoman Generator to Add Support for Running SPCAF analysis

SPCAF Yeoman generator

This generator makes it easier to run SPCAF analysis on SharePoint Framework projects.

Using the generator

The SPCAF Yeoman generator extends SharePoint Framework project with additional Gulp task to make it easier for you to run SPCAF analysis on your SharePoint Framework project.

To extend your existing SharePoint Framework project with SPCAF analysis, in the command line:

  • cd to your SharePoint Framework project folder
  • run yo spcaf and complete the wizard

Congratulations! You can now easily run SPCAF analysis of your SharePoint Framework project from Gulp (click the image to view the video)!

Run SPCAF analysis of SharePoint Framework project from Gulp

Additionally, you can run SPCAF analysis directly from Visual Studio Code (click the image to view the video).

Run SPCAF analysis of SharePoint Framework project from Visual Studio Code

More information about using SPCAF and SharePoint Framework

Author: Rencore
Source Code: https://github.com/rencore/generator-spcaf 
License: ISC license

#node #gulp #javascript 

Yeoman Generator to Add Support for Running SPCAF analysis
Oral  Brekke

Oral Brekke

1652707320

Gulp-spsync-creds: Gulp Plugin for Synchronizing Local Files

gulp-spsync-creds

Gulp plugin for synchronizing local files with a SharePoint library

This Gulp plugin is based on gulp-spsync which has been created by Wictor Wilen. The difference with gulp-spsync is that this plugin makes use for client credentials (username and password) in order to upload and/or download files. This makes the plugin usable for both SharePoint Online and on-premises environments.

Installation

Run the following command to install the gulp-spsync-creds plugin:

$ npm install gulp-spsync-creds

Usage

Uploading files

For uploading files, you can add the following code to your gulpfile.js:

var gulp = require('gulp');
var spsync = require('gulp-spsync-creds').sync;

gulp.src('./src/**/*')
.pipe(spsync({
    "username": "<username>",
    "password": "<password>",
    "site": "<site-url>",
}));

Downloading files

For downloading files, you can add the following code to your gulpfile.js:

var gulp = require('gulp');
var spdwn = require('gulp-spsync-creds').download;

spdwn({
    "site": "<site-url>",
    "username": "<username>",
    "password": "<password>",
    "startFolder": "<relative-folder-location>"
}).pipe(gulp.dest("src"));

Information: it currently retrieves all files of the given path and the ones of three folders deep.

Options

The plugin has the following options that can be configured:

username

Type: String Default: null

Sets the username to be used for the sync action.

password

Type: String Default: null

Sets the password to be used for the sync action.

site

Type: String Default: ""

Sets the site URL to where the files should be uploaded.

startFolder

Type: String Default: ""

Choose the name of the folder location it has to starts from. This is useful when you have a nested folder structure. Example: if your folder structure is like this src/template1/_sp/_catalogs, and you set the startFolder option to _sp, it will strip out all the folder names before including _sp. You end up with _catalogs.

Important: this property can also be used to specify the location from where you want to download files.

libraryPath New property - v2.3.0

Type: string Default: ""

The libraryPath property can be used if you want to define a default library path to where you want to upload your files.

By default the plugin uploads the files based on their file location (under your source folder).

src
|_ _catalogs
   |_ masterpage
      |_ your-folder
         |_ file1.html

So in the above case, file1.html will be uploaded to the master page gallery (_catalogs/masterpage) in a your-folder folder.

When you define the libaryPath to for example: documents. The plugin will upload the files to that specific document library with the folder structure. So in this case it will be documents/_catalogs/masterpage/your-folder/file1.html.

update_metadata

Type: Boolean Default: false

Specify if you want to update the metadata of files you are uploading. If this is set to true, you will have to pass the file metadata via the files_metadata option.

files_metadata

Type: Object Default: []

With the files_metadata option you can specify the metadata of all the files you wish to upload. Example:

"fileMetadata": [
    {
        "name": "Item_Minimal.js",
        "metadata": {
            "__metadata": {
                "type": "SP.Data.OData__x005f_catalogs_x002f_masterpageItem"
            },
            "Title": "Item Minimal Template (via GULP)",
            "MasterPageDescription": "This is a display template added via gulp.",
            "ManagedPropertyMapping": "'Path','Title':'Title'",
            "ContentTypeId": "0x0101002039C03B61C64EC4A04F5361F38510660500A0383064C59087438E649B7323C95AF6",
            "DisplayTemplateLevel": "Item",
            "TemplateHidden": false,
            "TargetControlType": {
                "__metadata": {
                "type": "Collection(Edm.String)"
                },
                "results": [
                "SearchResults",
                "Content Web Parts"
                ]
            }
        }
    },
    {
        "name": "Control_Minimal.js",
            "metadata": {
            "__metadata": {
                "type": "SP.Data.OData__x005f_catalogs_x002f_masterpageItem"
            },
            "Title": "Control Minimal Template (via GULP)",
            "MasterPageDescription": "This is a display template added via gulp.",
            "ContentTypeId": "0x0101002039C03B61C64EC4A04F5361F38510660500A0383064C59087438E649B7323C95AF6",
            "DisplayTemplateLevel": "Control",
            "TemplateHidden": false,
            "TargetControlType": {
                "__metadata": {
                "type": "Collection(Edm.String)"
                },
                "results": [
                "SearchResults",
                "Content Web Parts"
                ]
            }
        }
    }
]

publish

Type: Boolean Default: false

With this option you can specify if you want to publish files after they are uploaded.

cache

Type: Boolean Default: false

If set to true the plugin caches library locations that already have been processed. Makes the watch tasks quicker.

associatedHtml (only for download actions)

Type: Boolean Default: true

With this property you can specify if you want to download all files (by default set to true) from a folder. This will also download the files that are associated to an HTML template like a page layout, master page and display template. If you set this property to false, the plugin only downloads the HTML files and leaves the ".aspx", ".master" and ".js" files in the folder.

verbose

Type: Boolean Default: false

If you wish to see all the plugin logging you can set this to true.

Author: Estruyf
Source Code: https://github.com/estruyf/gulp-spsync-creds 
License: MIT license

#node #gulp #sharepoint 

Gulp-spsync-creds: Gulp Plugin for Synchronizing Local Files
Oral  Brekke

Oral Brekke

1652699880

Gulp Plugin for Synchronizing Local Files with A SharePoint Library

gulp-spsync

Gulp plugin for synchronizing local files with a SharePoint library

Features

  • Gulp plugin
  • Copies local files to a SharePoint Document libraries and galleries

How to use

  1. Prepare SharePoint by registering a SharePoint app using appregnew.aspx. Eg go to https://contoso.sharepoint.com/sites/site/_layouts/15/appregnew.aspx
  2. Click on Generate for both Client Id and Client Secret. For Title, App Domain and Redirect URI, write something you don't care about. Then click on Create
  3. Note down the Client Id and Client Secret, you will need it later
  4. Navigate to appinv.aspx, https://contoso.sharepoint.com/sites/site/_layouts/15/appinv.aspx, enter the client ID in the App Id box and press Lookup
  5. In the Permission Request XML text box enter the following XML and click Create (Note: FullControl is required to update assets in the Master Page gallery)
<AppPermissionRequests AllowAppOnlyPolicy="true">
    <AppPermissionRequest
        Scope="http://sharepoint/content/sitecollection/web"
        Right="FullControl"/>
</AppPermissionRequests>
  1. In the following consent screen choose to trust the App by clicking on Trust It!
  2. Open a folder using Visual studio code
  3. Run npm install gulp to install the Gulp task runner
  4. Run npm install gulp-spsync to install to install the gulp-spsync
  5. Press Ctrl-Shift-P, type Task and choose to Configure Task Runner
  6. In the tasks.json file that is being created replace the contents with the following:
{
    "version": "0.1.0",
    "command": "gulp",
    "isShellCommand": true,
    "tasks": [
        {
            "taskName": "default",
            "isBuildCommand": true,
            "showOutput": "silent"
        }
    ]
}	
  1. Create a new file in the root of your folder called gulpfile.js, and modify it as follows. This task will monitor all files in the Src folder
var gulp = require('gulp')
var sp = require('gulp-spsync')
gulp.task('default', function() {
return gulp.src('src/**/*.*').
    pipe(sp({
        "client_id":"3d271647-2e12-4ae5-9271-04b3aa67dcd3",
        "client_secret":"Zk9ORywN0gaGljrtlxfp+s5vh7ZyWV4dRpOXCLjtl8U=",
        "realm" : "",
        "site" : "https://contoso.sharepoint.com/sites/site",
        "verbose": "true"
    })).		
    pipe(gulp.dest('build'))
})
  1. Replace the client_id and client_secret parameters with the value for the App you just created
  2. Replace the site URL with your site URL
  3. Create a folder called Src (you can call it whatever you want, but the tasks above/below uses Src)
  4. Create sub folders to the Src folder where each Subfolder represents a Library in a site. You can alos create a subfolder called _catalogs and add a subfolder to that one called masterpage if you want to sync files to the Master Page Gallery.
  5. Add files as you want to these folders
  6. Press Ctrl-Shift-B to Build and let Gulp and gulp-spsync upload the files to SharePoint

Using Gulp watchers

You can use Gulp watchers (gulp-watch) to upload files as they are changed. The following gulpfile.js shows how to upload all files on build and then upload files incrementally when changed and saved.

You need to run npm install gulp-watch to install the Gulp watcher

var gulp = require('gulp')
var sp = require('gulp-spsync')
var watch = require('gulp-watch')

var settings = {
			"client_id":"...",
			"client_secret":"...",
			"realm" : "",
			"site" : "https://contoso.sharepoint.com/sites/site",
			"verbose": "true",
			"watch": true
		};
gulp.task('default', function() {
	return gulp.src('src/**/*.*')
		.pipe(watch('src/**/*.*'))
		.pipe(sp(settings))		
		.pipe(gulp.dest('build'))
})

Setting metadata for files

If you're files require metadata to be set when they are uploaded, you can pass in a metadata options (update_metadata, files_metadata).

Example:

var fileMetadata = [
    {
        name: 'Item_Minimal.js',
        metadata: {
            "__metadata": { type: "SP.Data.OData__x005f_catalogs_x002f_masterpageItem" },
            Title: 'Item Minimal Template (via GULP)',
            MasterPageDescription: 'This is a display template added via gulp.',
            ManagedPropertyMapping: "'Path','Title':'Title'",
            ContentTypeId: '0x0101002039C03B61C64EC4A04F5361F38510660500A0383064C59087438E649B7323C95AF6',
            DisplayTemplateLevel: 'Item',
            TargetControlType: {
                "__metadata": {
                    "type": "Collection(Edm.String)"
                },
                "results": [
                    "SearchResults",
                    "Content Web Parts"
                ]
            }
        }
    },
    {
        name: 'Control_Minimal.js',
        metadata: {
            "__metadata": { type: "SP.Data.OData__x005f_catalogs_x002f_masterpageItem" },
            Title: 'Control Minimal Template (via GULP)',
            MasterPageDescription: 'This is a display template added via gulp.',
            ContentTypeId: '0x0101002039C03B61C64EC4A04F5361F38510660500A0383064C59087438E649B7323C95AF6',
            DisplayTemplateLevel: 'Control',
            TargetControlType: {
                "__metadata": {
                    "type": "Collection(Edm.String)"
                },
                "results": [
                    "SearchResults",
                    "Content Web Parts"
                ]
            }
        }
    }
];

var settings = {
    "client_id":"...",
    "client_secret":"...",
    "realm" : "",
    "site" : "https://contoso.sharepoint.com/sites/site",
    "verbose": true,
    "update_metadata": true,
    "files_metadata": fileMetadata
};

Publishing files

By setting the publish setting, you can specify to publish your files when they are uploaded to the site.

var settings = {
    "client_id":"...",
    "client_secret":"...",
    "realm" : "",
    "site" : "https://contoso.sharepoint.com/sites/site",
    "verbose": true,
    "publish": true
};

Using nested folders (new in 1.4.0)

If you're using nested folders or deep structures, you can choose the name of the "start folder", using the startFolder option. Assume you have your SharePoint files under src/template1/_sp/_catalogs and src/template2/_sp/_catalogs/ then you can use "startFolder"="_sp" to make sure that the first folder names are stripped.

var gulp = require('gulp')
var sp = require('gulp-spsync')

var settings = {
			"client_id":"...",
			"client_secret":"...",
			"realm" : "",
			"site" : "https://contoso.sharepoint.com/sites/site",
			"verbose": "true",
            "startFolder":"_sp"
		};
gulp.task('default', function() {
	return gulp.src('src/**/_sp/**/*.*')
		.pipe(sp(settings))		
})

Author: Wictorwilen
Source Code: https://github.com/wictorwilen/gulp-spsync 
License: MIT license

#node #gulp #sharepoint #javascript 

Gulp Plugin for Synchronizing Local Files with A SharePoint Library
Oral  Brekke

Oral Brekke

1652692320

Gulp-spsave: Gulp Plugin for Saving Files inside SharePoint

gulp-spsave

Gulp plugin for spsave - save files in SharePoint using node.js easily.


How to use:

Install:

npm install gulp-spsave --save-dev

Usage:

var spsave = require('gulp-spsave');
var gulp = require('gulp');

gulp.task("default", function(){
  return gulp.src("./build/*.js")
             .pipe(spsave(coreOptions, creds));
});

Options:

Exactly the same as for spsave, except file content options (because the file is piped through the gulp stream).
That means no need to provide such options as fileName, fileContent, glob, file, base (base can be provided for the gulp.src, see samples below).
I recommend you look at the spsave page to get a better understanding.

Core options (passed to spsave):

The same as for spsave core options plus two additional options exclusive to gulp-spsave:

  • folder - required string, SharePoint folder to upload file to (can be the url to document library)
  • flatten - boolean, default true, when true all files will be uploaded to folder provided, regardles of the file physical location. For example, if folder equal to MyAppAssets and you pipe two files app/controllers/HomeCtrl.js and app/templates/home.html, then MyAppAssets will contain both HomeCtrl.js and home.html in the root.
    If flatten is false, gulp-spsave will look for base for the file and will use this base for upload file in a particular folder (or create this folder automatically if required). See gulp API docs, gulp.src(globs[, options]) and glob2base.

Credentials:

gulp-spsave implicitly depends on another module used for SharePoint authentication from node js - node-sp-auth. For credentials param you need to pass exactly the same object, as for node-sp-auth credentialsOptions object. That also means that gulp-spsave supports all authentication options supported by node-sp-auth. See examples below for more info.
You can also pass a null as credentials, in that case gulp-spsave will ask you for credentials and will store your credentials in a user folder in an encrypted manner (everything is handled by node-sp-auth actually).

Examples:

Imagine we have settings.js which stores all sensitive information for us (credential information, client id\client secret etc.):

module.exports = {
    username: "[user]",
    password: "[pass]"
}

1.Watch for file changes in scripts, then bundle, minify, whatever, and upload to SharePoint automatically:


//sensitive data stored in external file:
var creds = require("./settings.js");
gulp.task("buildJS", function(){
    return gulp.src("./Scripts/**/*.js")
    .pipe(concat())
    .pipe(uglify())
    .pipe(gulp.dest("./build"));
});

gulp.task("copyToSharePoint", ["buildJS"], function(){
    return gulp.src("./build/*.js")
        .pipe(spsave({
            siteUrl: settings.siteUrl,
            folder: "YourAppAssets/js"
        }, creds));
});

gulp.task("watch", function(){
    gulp.watch(["./Scripts/**/*.js"], ["copyToSharePoint"]);
});

2.Save all files from App/build to SharePoint:


//sensitive data stored in external file:
var creds = require("./settings.js");
gulp.task("spsave", function () {
    return gulp.src(["App/build/*.*"])
        .pipe($.spsave({
            siteUrl: settings.siteUrl,
            folder: "App/build",
            flatten: true
        }, creds));
});

3.Watch all javascript file changes in ng (stands for angular) folder and upload that file automatically in SharePoint with preserved folder structure:


//sensitive data stored in external file:
var creds = require("./settings.js");
gulp.watch("App/ng/**/*.js", function (event) {
        gulp.src(event.path)
            .pipe($.spsave({
                siteUrl: settings.siteUrl,
                folder: "AppAssets",
                flatten: false
            }, creds));
    });

In this sample base will be equal to App/ng. If file path is App/ng/controllers/HomeCtrl.js, then it will saved under AppAssets/controllers/HomeCtrl.js (if some folders are missing, they will be created by spsave automatically). Next sample demonstrate how can you save it under AppAssets/ng/controllers/HomeCtrl.js

4.You can also explicitly provide base for gulp.src:


//sensitive data stored in external file:
var creds = require("./settings.js");
gulp.watch("App/ng/**/*.js", function (event) {
        gulp.src(event.path, { base: "App" })
            .pipe($.spsave({
                siteUrl: settings.siteUrl,
                folder: "AppAssets",
                flatten: false
            }, creds));
    });

In this case file be saved under AppAssets/ng/controllers/HomeCtrl.js path.

5.Upload search display template with metadata:


//sensitive data stored in external file:
var creds = require("./settings.js");
gulp.watch("App/search/Item_Display.js", function (event) {
        gulp.src(event.path)
            .pipe($.spsave({
                siteUrl: settings.siteUrl,
                folder: "_catalogs/masterpage/Display Templates/Search",
                flatten: true,
                filesMetaData: [{
                    fileName: "Item_Display.js",
                    metadata: {
                        "__metadata": { type: "SP.Data.OData__x005f_catalogs_x002f_masterpageItem" },
                        Title: "SPSave Display Template",
                        DisplayTemplateLevel: "Item",
                        TargetControlType: {
                            "__metadata": {
                                "type": "Collection(Edm.String)"
                            },
                            "results": [
                                "SearchResults"
                            ]
                        },
                        ManagedPropertyMapping: `'Title':'Title','Path':'Path','Description':'Description'`,
                        ContentTypeId: "0x0101002039C03B61C64EC4A04F5361F38510660500A0383064C59087438E649B7323C95AF6",
                        TemplateHidden: false
                    }
                }]
            }, creds));
    });

...and any other scenarios you need.

For list of all options for the spsave refer to the git hub repository.

Integration testing:

  1. Rename file /test/integration/config.sample.js to config.js.
  2. Update information in config.js with appropriate values (urls, credentials, environment).
  3. Run npm run test-int.

Known Issues

When heavily utilizing watchers along with gulp-spsave you may see errors "Save conflict" or "Cobalt error". spsave tries to recover from these errors by trying to re-upload the file once or twice again. But usually it's a good idea to use gulp-plumber or similar tool in order to make sure that your watchers will not be broken when errors occur.
Normally you can do the following in your gulpfile.js:

var plumber = require("gulp-plumber");
var onError = function (err) {
    console.log(err);
    this.emit("end");
};
gulp.watch(["App/index.html"], function (event) {
        return gulp.src(event.path, { base: "App" })
            .pipe(plumber({
                errorHandler: onError
            }))
            .pipe(spsave(settings));
    });

In case of error, your watch will remain up and running regardless of the error.

Need help on SharePoint with Node.JS? Join our gitter chat and ask question! Gitter chat

Author: s-KaiNet
Source Code: https://github.com/s-KaiNet/gulp-spsave 
License: MIT license

#node #javascript #gulp 

Gulp-spsave: Gulp Plugin for Saving Files inside SharePoint