1670869680
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:
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.
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.
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.
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/
1667341080
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!
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.
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.
>2.0
with Bundler >1.10
>4.2
and Yo >1.7.0
gulp-cli
: npm install gulp-cli -g
npm install generator-jekyllized -g
yo jekyllized
in the directory you want scaffold your site ingulp
and watch the magic unfoldTo 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.
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.
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.
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.
See the contribution docs.
Author: sondr3
Source Code: https://github.com/sondr3/generator-jekyllized
License: MIT license
1667321700
These are the files for my series Introduction to Gulp.js published on my website stefanimhoff.de.
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
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
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
.
Three tasks are available (npm
works, too):
$ yarn start
$ yarn run publish
$ yarn run deploy
yarn start
will start a development server, build assets and the Jekyll site and start a watch
task.yarn run publish
will copy and optimize assets and run a production build of Jekyll.yarn run deploy
will copy the generated files with Rsync to your server.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.
This tutorial includes some files for demonstation purposes:
Author: Kogakure
Source Code: https://github.com/kogakure/gulp-tutorial
1666683480
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.
bundle install
npm install
bundle exec gulp
The main settings can be found inside the _config.yml
file:
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.
Author: brianmaierjr
Source Code: https://github.com/brianmaierjr/long-haul
License: MIT license
1662060360
Rewrite occurrences of filenames which have been renamed by gulp-rev
$ npm install --save-dev gulp-rev-replace
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));
});
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.
Type: Array
Default: ['.js', '.css', '.html', '.hbs']
Only substitute in new filenames in files of these types.
Type: string
Default: ``
Add the prefix string to each replacement.
Type: Stream
(e.g., gulp.src()
)
Read JSON manifests written out by rev
. Allows replacing filenames that were rev
ed prior to the current task.
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));
Author: jamesknelson
Source Code: https://github.com/jamesknelson/gulp-rev-replace
License: MIT license
1662056520
gulp-rev
Static asset revisioning by appending content hash to filenames
unicorn.css
→unicorn-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.
$ npm install --save-dev gulp-rev
const gulp = require('gulp');
const rev = require('gulp-rev');
exports.default = () => (
gulp.src('src/*.css')
.pipe(rev())
.pipe(gulp.dest('dist'))
);
Type: string
Default: 'rev-manifest.json'
Manifest file path.
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 file paths are stored at file.revOrigPath
. This could come in handy for things like rewriting references to the assets.
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.
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.
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'))
);
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:
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'))
);
For more info on how to integrate gulp-rev
into your app, have a look at the integration guide.
It may be useful - and necessary - to use gulp-rev
with other packages to complete the task.
Author: Sindresorhus
Source Code: https://github.com/sindresorhus/gulp-rev
License: MIT license
1661939460
Clean unnecessary CSS with PurifyCSS
Package | gulp-purifycss |
Description | Clean unnecessary CSS |
Node Version | >= 0.10 |
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/'));
});
Author: Purifycss
Source Code: https://github.com/purifycss/gulp-purifycss
License: MIT license
1660674600
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.
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.
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).
git clone https://github.com/EmailThis/extension-boilerplate.git
npm install
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
extension-boilerplate/build/chrome
or (extension-boilerplate/build/opera
)Load the extension in Firefox
extension-boilerplate/build/firefox
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
Run npm run dist
to create a zipped, production-ready extension for each browser. You can then upload that to the appstore.
If you have any questions or comments, please create a new issue. I'd be happy to hear your thoughts.
Bharani, Email This
Author: EmailThis
Source Code: https://github.com/EmailThis/c
License: MIT license
1654607820
gulp-svgmin
With npm do:
npm install gulp-svgmin
import { src, dest } from 'gulp';
import svgmin from 'gulp-svgmin';
const defaultTask = () =>
src('logo.svg')
.pipe(svgmin())
.pipe(dest('./out'));
export default defaultTask;
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;
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'));
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'));
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
1654431720
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:
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' }));
});
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"
}
}
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
1652896200
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.
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:
1652708052
SPCAF Yeoman generator
This generator makes it easier to run SPCAF analysis on SharePoint Framework projects.
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 folderyo spcaf
and complete the wizardCongratulations! You can now easily run SPCAF analysis of your SharePoint Framework project from Gulp (click the image to view the video)!
Additionally, you can run SPCAF analysis directly from Visual Studio Code (click the image to view the video).
Author: Rencore
Source Code: https://github.com/rencore/generator-spcaf
License: ISC license
1652707320
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.
Run the following command to install the gulp-spsync-creds plugin:
$ npm install gulp-spsync-creds
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>",
}));
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.
The plugin has the following options that can be configured:
Type: String
Default: null
Sets the username to be used for the sync action.
Type: String
Default: null
Sets the password to be used for the sync action.
Type: String
Default: ""
Sets the site URL to where the files should be uploaded.
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.
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
.
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.
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"
]
}
}
}
]
Type: Boolean
Default: false
With this option you can specify if you want to publish files after they are uploaded.
Type: Boolean
Default: false
If set to true the plugin caches library locations that already have been processed. Makes the watch tasks quicker.
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.
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
1652699880
gulp-spsync
Gulp plugin for synchronizing local files with a SharePoint library
Features
How to use
FullControl
is required to update assets in the Master Page gallery)<AppPermissionRequests AllowAppOnlyPolicy="true">
<AppPermissionRequest
Scope="http://sharepoint/content/sitecollection/web"
Right="FullControl"/>
</AppPermissionRequests>
npm install gulp
to install the Gulp task runnernpm install gulp-spsync
to install to install the gulp-spsync{
"version": "0.1.0",
"command": "gulp",
"isShellCommand": true,
"tasks": [
{
"taskName": "default",
"isBuildCommand": true,
"showOutput": "silent"
}
]
}
gulpfile.js
, and modify it as follows. This task will monitor all files in the Src
foldervar 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'))
})
Src
(you can call it whatever you want, but the tasks above/below uses Src
)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.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
1652692320
gulp-spsave
Gulp plugin for spsave - save files in SharePoint using node.js easily.
npm install gulp-spsave --save-dev
var spsave = require('gulp-spsave');
var gulp = require('gulp');
gulp.task("default", function(){
return gulp.src("./build/*.js")
.pipe(spsave(coreOptions, creds));
});
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.
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.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.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).
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.
/test/integration/config.sample.js
to config.js
.config.js
with appropriate values (urls, credentials, environment).npm run test-int
.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!
Author: s-KaiNet
Source Code: https://github.com/s-KaiNet/gulp-spsave
License: MIT license