npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

grunt-local2cdn

v0.1.2

Published

Converts local URLs to CDN ones.

Downloads

4

Readme

grunt-local2cdn

A Grunt plugin to convert local URLs to CDN ones in html files(or the like, e.g. .ejs,.jsp,.jade).

It gets some inspiration from grunt-cdnify(by @callumlocke)

What it does

The task looks through your specified files for URLs to modify, in the following places:

  • <img src="____">
  • <script src="____"></script>
  • <link rel="stylesheet" href="____">
  • background-image: url(____); in your CSS (including inside <style> tags in your HTML)

It will ignore web urls and images with data URI format, e.g. http://www.example.com/foo.png, data:image/png;base64,iVBORw0KGgoAAAANS...

Getting Started

This plugin requires Grunt ~0.4.0

If you haven't used Grunt before, be sure to check out the Getting Started guide, as it explains how to create a Gruntfile as well as install and use Grunt plugins. Once you're familiar with that process, you may install this plugin with this command:

npm install grunt-local2cdn --save-dev

Once the plugin has been installed, it may be enabled inside your Gruntfile with this line of JavaScript:

grunt.loadNpmTasks('grunt-local2cdn');

The "local2cdn" task

Overview

In your project's Gruntfile, add a section named local2cdn to the data object passed into grunt.initConfig().

grunt.initConfig({
  local2cdn: {
    options: {
      // Task-specific options go here.
    },
    your_target: {
      // Target-specific file lists and/or options go here.
    },
  },
});

Options

options.prefix

Type: [Optional]String Default value: ''

The base url of CDN, e.g. http://cdn.bootcss.com. It will prepend to all the CDN urls in options.maps. For some special urls, you can overwrite it, see options.maps bellow.

options.maps

Type: [Required] Object|Array of Objects Default value: null

It defines the maps of local urls and cdn urls. You must specify it youself.

It supports two formats:

Simple format:

An object constituted by key/value maps, the key is the local url, and the value is the CDN url.

{
    'jquery.js': 'jquery/2.0.3/jquery.min.js',
    'bootstrap.js': 'bootstrap/3.1.1/js/bootstrap.min.js',
    'bootstrap.css': '/bootstrap/3.1.1/css/bootstrap.min.css',
    'foo.png': '/xxx/foo.png',
    'foo.jpg': '/xxx/foo.jpg',
    'foo.gif': '/xxx/foo.gif',
    'foo.tif': '/xxx/foo.tif:image'
}

Advanced format:

An array constituted by objects. You can overwrite some options(prefix, regex, separator) in each object. local and cdn properties are required, prefix, regex, separator, srcType properties are optional.

[
   {local: 'jquery.js', cdn: 'jquery/2.0.3/jquery.min.js', prefix:'//cdn.a.com', regex:true, srcType:'image'},
   {local: 'bootstrap.js', cdn: 'bootstrap/3.1.1/js/bootstrap.min.js', prefix:'http://cdn.2.org', regex:true},
   {local: 'bootstrap.css', cdn: '/bootstrap/3.1.1/css/bootstrap.min.css'},
   {local: 'foo.png', cdn: '/xxx/foo.png', prefix:'http://cdn.3.org'},
   {local: 'foo.jpg', cdn: '/xxx/foo.jpg'},
   {local: 'foo.gif', cdn: '/xxx/foo.gif'},
   {local: 'foo.tif', cdn: '/xxx/foo.tif', srcType:'image'},
   {local: '^aabbcc', cdn: '/xxx/foo.pic?123#$#image', separator:'#$#',  regex:true}
]

options.regex

Type: [Optional]Boolean Default value: false

Whether local url in options.maps supports RegExp or not. If true, the final RegExp used to match will be new RegExp(localUrl, 'ig'); If false, the final RegExp used to match will be new RegExp(escapeRegExChars(localUrl)+'\\s*$', 'ig');

The plugin will stop searching in options.maps as long as it find a match. When options.regex==false, if the localUrl in a map is the tail of the original url, it will matchs. So, you must take care of the situation:

maps:{
  ...
  'bootstrap.css': 'http://cdn.example.com/bootstrap.min.css',
  ...  
  'typeahead.bootstrap.css': 'http://cdn.example.com/typeahead.bootstrap.min.css',
  ...
}
  ...
  <link href="/libs/typeahead/typeahead.bootstrap.css" rel="stylesheet">
  ...

The original url will match bootstrap.css incorrectly, not the correct one typeahead.bootstrap.css. To avoid this, there are some solutions:

  • put the typeahead.bootstrap.css map before the bootstrap.css map;
  • change the maps to /bootstrap.css and /typeahead.bootstrap.css;
  • set options.regex to true, and change the localUrls to customed regex formats;

It can be overwrote in options.maps.

options.separator

Type: [Optional]String Default value: ':'

The plugin needs to know the source type(image,css,js) of each url. It will detect the source type from local url or CDN url by the source file extension. e.g.:

'jquery.js': 'jquery/2.0.3/jquery.min.js' --> srcType will be 'js';

'bootstrap.css': '/bootstrap/3.1.1/css/bootstrap.min.css' --> srcType will be 'css';

'foo.png': '/xxx/foo.png' --> srcType will be 'image', the plugin can detect source type from these image types:'png','gif','jpeg','jpg','ico','bmp','svg'

If there is a map: 'foo.tif': '/xxx/foo.tif', the plugin cannot detect the source type, and then you need to explicitly specify the source type of this resource, juest append separator and the type to the end of CDN url, that is 'foo.tif': '/xxx/foo.tif:image', it will works as an image url.

The plugin detect source type in this order: CDN url affix(separator+type) --> CDN url --> local url

It will stop detecting as long as it got a valid type.

When detecting, query and id locator will be ignored. e.g.:
/xxx/foo.png?v=12345 will be treat as /xxx/foo.png

It can be overwrote in options.maps.

options.converter

Type: [Optional]Function Default value: A built-in function

A function convert the oldUrl(local url) to finalUrl(usually is a cdn url). It must return a string. And it has three parameters:oldUrl, srcType, converter. The first parameter oldUrl is the origin url of the current resource; The second parameter srcType is the source type of the current resource, it is a string value of image|js|css; The third parameter converter is the built-in convert function.

If ignore, the built-in convert function will be used.

e.g.:

...
options: {
  ...
  converter: function(oldUrl, srcType, converterURL){
    if(oldUrl.indexOf('data:') === 0)
      return url; // leave data URIs untouched
    else if(oldUrl.indexOf('http') === 0)
      return url + '?12345'; // add query string to all other URLs
    else 
      return converterURL(oldUrl, srcType);
  }
  ...
}
...

Usage Examples

Example 1

local2cdn: {
  main: {
    options: {
      maps: {
        "/jquery.js": "http://libs.baidu.com/jquery/1.10.2/jquery.min.js",
        "/bootbox.js": "http://cdn.staticfile.org/bootbox.js/4.1.0/bootbox.min.js",
        "/bootstrap.js": "http://libs.baidu.com/bootstrap/3.0.3/js/bootstrap.min.js",
        "/bootstrap.css": "http://libs.baidu.com/bootstrap/3.0.3/css/bootstrap.min.css",           
        "/underscore.js": "http://cdn.staticfile.org/underscore.js/1.5.2/underscore-min.js"
      }
    },
    files: [
      {
        expand: true,
        cwd: 'test/src/',
        src: '**/*.{css,html,ejs}',
        dest: 'test/dist/'
      }
    ]
  }
}

Example 2

grunt.initConfig({
  local2cdn: {
    main: {
      options: {
        prefix: 'http://cdn.bootcss.com/',
        maps: {
            'jquery.js': 'jquery/2.0.3/jquery.min.js',
            'bootstrap.js': 'bootstrap/3.1.1/js/bootstrap.min.js',
            'bootstrap.css': '/bootstrap/3.1.1/css/bootstrap.min.css',
            'foo.png': '/xxx/foo.png',
            'foo.jpg': '/xxx/foo.jpg',
            'foo.gif': '/xxx/foo.gif',
            'foo.tif': '/xxx/foo.tif:image'
        }
      },
      files: [
        {
          expand: true,
          cwd: 'test/src',
          src: '**/*.{css,html,ejs}',
          dest: 'test/dist'
        }
      ]
    }//eof:local2cdn:main target
  }//eof:local2cdn task
});

The src file test/src/sample.html maybe like:

<html>
  <head>
    <style>
      body {
        background-image: url('foo.jpg');
        background-image: url("foo.jpg");
        background-image: url(foo.jpg);
        background-image: url('/foo.png');
        background-image: url('bar/foo.png');        
        background-image: url('http://demo.com/bar/foo.png');
        background-image: url('../foo.gif');
        background-image: url('foo/bar.jpg');
        background-image: url('data:gif; base64XQTRTWEQW');
      }
    </style>
    <!-- Bootstrap Core-->
    <link href="/libs/bootstrap/css/bootstrap.css" rel="stylesheet">
  </head>  
  <body>
    <img something src="foo.jpg" data-cc data-dd="1111">
    <img src=foo/bar.png so="what" />
    <img src="/foo.gif" something=xxx  >
    <img src="http://demo.com/bar/foo.png" something=aaa  >
    <img src="bar/foo.png" something=yyy  >    
    <img src="bar/foo.tif" />
    <!-- jquery.js -->
    <script src="/libs/jquery.js"></script>
    <script src="/libs/bootstrap/js/bootstrap.js"></script>
  </body>
</html>
 ...

and the dest file 'test/dist/sample.html' will like:

<html>
  <head>
    <style>
      body {
        background-image: url('http://cdn.bootcss.com/xxx/foo.jpg');
        background-image: url("http://cdn.bootcss.com/xxx/foo.jpg");
        background-image: url(http://cdn.bootcss.com/xxx/foo.jpg);
        background-image: url('http://cdn.bootcss.com/xxx/foo.png');
        background-image: url('http://cdn.bootcss.com/xxx/foo.png');        
        background-image: url('http://demo.com/bar/foo.png');
        background-image: url('http://cdn.bootcss.com/xxx/foo.gif');
        background-image: url('foo/bar.jpg');
        background-image: url('data:gif; base64XQTRTWEQW');
      }
    </style>
    <!-- Bootstrap Core-->
    <link href="http://cdn.bootcss.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
  </head>  
  <body>
    <img something src="http://cdn.bootcss.com/xxx/foo.jpg" data-cc data-dd="1111">
    <img src=foo/bar.png so="what" />
    <img src="http://cdn.bootcss.com/xxx/foo.gif" something=xxx  >
    <img src="http://demo.com/bar/foo.png" something=aaa  >
    <img src="http://cdn.bootcss.com/xxx/foo.png" something=yyy  >    
    <img src="http://cdn.bootcss.com/xxx/foo.tif" />
    <!-- jquery.js -->
    <script src="http://cdn.bootcss.com/jquery/2.0.3/jquery.min.js"></script>
    <script src="http://cdn.bootcss.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
  </body>
</html>

Hot CDNs:

China

International

Release History

  • 2014-04-05 v0.1.2