diff --git a/.travis.yml b/.travis.yml
index e08909b..6ef04eb 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,6 +1,5 @@
language: node_js
node_js:
- "0.10"
- - "0.8"
before_script:
- npm install -g grunt-cli
diff --git a/Gruntfile.js b/Gruntfile.js
index 59e6e32..d000274 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -4,13 +4,13 @@ module.exports = function(grunt) {
grunt.initConfig({
inline: {
dist: {
- src: ['test/dist/*.html'],
- dest: ['tmp/']
+ src: 'test/dist/*.html',
+ dest: 'tmp/'
}
},
clean: {
- tests: ['tmp/']
+ tests: 'tmp/'
},
htmlmin: {
@@ -24,6 +24,7 @@ module.exports = function(grunt) {
'tmp/img.min.html': 'tmp/img.html',
'tmp/html.min.html': 'tmp/html.html',
'tmp/script.min.html': 'tmp/script.html',
+ 'tmp/icon.min.html': 'tmp/icon.html',
'tmp/css_greedy.min.html': 'tmp/css_greedy.html',
'tmp/img_greedy.min.html': 'tmp/img_greedy.html',
'tmp/html_greedy.min.html': 'tmp/html_greedy.html',
diff --git a/README.md b/README.md
index 5d387b7..8e0246c 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# grunt-inline[](http://travis-ci.org/miniflycn/grunt-inline)
+# grunt-inline[](http://travis-ci.org/marcusklaas/grunt-inline)
Brings externally referenced resources, such as js, css and images, into
a single file.
@@ -233,6 +233,8 @@ Then, after the `inline` task is run, the original content in `index.html` will
In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code using [Grunt](http://gruntjs.com/).
## Release History
+* 2015-03-03 v0.3.5 add feature: support for inlining favicons
+* 2015-03-09 v0.3.4 fork: fork project, fix tests and merge a number of pull requests
* 2015-01-09 v0.3.3 bug fix: when processing files of a folder and then copy the processed content to another destination, the original files are changed unexpectedly, as mentioned in this issue [Support file globbing for input and output](https://github.com/chyingp/grunt-inline/issues/35)
* 2014-06-16 v0.3.1 bug fix: protocol-relative urls in css are messed up
* 2014-06-15 v0.3.1 bug fix: when options.tag is '', then all img tags, whose src attribute has already been inlined will be matched.
diff --git a/npm-debug.log b/npm-debug.log
deleted file mode 100644
index eeac3e8..0000000
--- a/npm-debug.log
+++ /dev/null
@@ -1,110 +0,0 @@
-0 info it worked if it ends with ok
-1 verbose cli [ 'node', '/usr/local/bin/npm', 'publish' ]
-2 info using npm@1.4.14
-3 info using node@v0.10.29
-4 verbose publish [ '.' ]
-5 verbose cache add [ '.', null ]
-6 verbose cache add name=undefined spec="." args=[".",null]
-7 verbose parsed url { protocol: null,
-7 verbose parsed url slashes: null,
-7 verbose parsed url auth: null,
-7 verbose parsed url host: null,
-7 verbose parsed url port: null,
-7 verbose parsed url hostname: null,
-7 verbose parsed url hash: null,
-7 verbose parsed url search: null,
-7 verbose parsed url query: null,
-7 verbose parsed url pathname: '.',
-7 verbose parsed url path: '.',
-7 verbose parsed url href: '.' }
-8 silly lockFile 3a52ce78- .
-9 verbose lock . /Users/a/.npm/3a52ce78-.lock
-10 verbose tar pack [ '/Users/a/.npm/grunt-inline/0.3.3/package.tgz', '.' ]
-11 verbose tarball /Users/a/.npm/grunt-inline/0.3.3/package.tgz
-12 verbose folder .
-13 info prepublish grunt-inline@0.3.3
-14 silly lockFile 1f1177db-tar tar://.
-15 verbose lock tar://. /Users/a/.npm/1f1177db-tar.lock
-16 silly lockFile 9f87bd96-m-grunt-inline-0-3-3-package-tgz tar:///Users/a/.npm/grunt-inline/0.3.3/package.tgz
-17 verbose lock tar:///Users/a/.npm/grunt-inline/0.3.3/package.tgz /Users/a/.npm/9f87bd96-m-grunt-inline-0-3-3-package-tgz.lock
-18 silly lockFile 1f1177db-tar tar://.
-19 silly lockFile 1f1177db-tar tar://.
-20 silly lockFile 9f87bd96-m-grunt-inline-0-3-3-package-tgz tar:///Users/a/.npm/grunt-inline/0.3.3/package.tgz
-21 silly lockFile 9f87bd96-m-grunt-inline-0-3-3-package-tgz tar:///Users/a/.npm/grunt-inline/0.3.3/package.tgz
-22 silly lockFile f04d4788-a-npm-grunt-inline-0-3-3-package /Users/a/.npm/grunt-inline/0.3.3/package
-23 verbose lock /Users/a/.npm/grunt-inline/0.3.3/package /Users/a/.npm/f04d4788-a-npm-grunt-inline-0-3-3-package.lock
-24 silly lockFile f04d4788-a-npm-grunt-inline-0-3-3-package /Users/a/.npm/grunt-inline/0.3.3/package
-25 silly lockFile f04d4788-a-npm-grunt-inline-0-3-3-package /Users/a/.npm/grunt-inline/0.3.3/package
-26 silly lockFile 3a52ce78- .
-27 silly lockFile 3a52ce78- .
-28 silly publish { author:
-28 silly publish { name: '程序猿小卡',
-28 silly publish email: 'chyingp@gmail.com',
-28 silly publish url: 'https://github.com/chyingp' },
-28 silly publish name: 'grunt-inline',
-28 silly publish description: 'Inlines img, script and link tags into the same file.',
-28 silly publish version: '0.3.3',
-28 silly publish keywords: [ 'gruntplugin', 'inline', 'js', 'css' ],
-28 silly publish main: 'inline',
-28 silly publish repository:
-28 silly publish { type: 'git',
-28 silly publish url: 'https://github.com/chyingp/grunt-inline.git' },
-28 silly publish engines: { node: '>=0.8.0' },
-28 silly publish devDependencies:
-28 silly publish { 'grunt-contrib-nodeunit': '~0.1.2',
-28 silly publish 'grunt-contrib-clean': '~0.4.0',
-28 silly publish 'grunt-contrib-htmlmin': '~0.1.3',
-28 silly publish grunt: '~0.4.0' },
-28 silly publish dependencies: { 'uglify-js': '2.4.1', datauri: '~0.2.0', 'clean-css': '1.1.7' },
-28 silly publish scripts: { test: 'grunt test' },
-28 silly publish _id: 'grunt-inline@0.3.3',
-28 silly publish _from: '.',
-28 silly publish readme: '# grunt-inline[](http://travis-ci.org/miniflycn/grunt-inline)\r\n\r\nBrings externally referenced resources, such as js, css and images, into\r\na single file.\r\n\r\nFor exmample:\r\n\r\n````\r\n\r\n````\r\nis replaced with\r\n````\r\n\r\n```\r\n\r\nJavascript references are brought inline, and images in the html\r\nand css blocks are converted to base-64 data: urls.\r\n\r\nBy default, only urls marked with `__inline` are converted, however this\r\nbehavior can be overrided via the `tag:` option.\r\n\r\n\r\n## Getting Started\r\nThis plugin requires Grunt `~0.4.1`\r\n\r\nIf you haven\'t used [Grunt](http://gruntjs.com/) before, be sure to check out the [Getting Started](http://gruntjs.com/getting-started) guide, as it explains how to create a [Gruntfile](http://gruntjs.com/sample-gruntfile) as well as install and use Grunt plugins. Once you\'re familiar with that process, you may install this plugin with this command:\r\n\r\n\tnpm install grunt-inline --save-dev\r\n\r\nOnce the plugin has been installed, it may be enabled inside your Gruntfile with this line of JavaScript:\r\n\r\n\tgrunt.loadNpmTasks(\'grunt-inline\');\r\n\r\n## The "grunt-inline" task\r\n\r\n### Overview\r\nIn your project\'s Gruntfile, add a section named `inline` to the data object passed into `grunt.initConfig()`.\r\n\r\n\tgrunt.initConfig({\r\n\t inline: {\r\n\t dist: {\r\n\t src: \'src/index.html\',\r\n\t dest: \'dist/index.html\'\r\n\t }\r\n\t }\r\n\t})\r\n### Options\r\n\r\n#### dest\r\nIf dest is assigned, the the source file will be copied to the destination path. eg:\r\n`src/index.html` will be processed and then copied to `dist/index.html`\r\n\r\n```\r\ngrunt.initConfig({\r\n\tinline: {\r\n\t\tdist: {\r\n\t\t\tsrc: \'src/index.html\',\r\n\t\t\tdest: \'dist/index.html\'\r\n\t\t}\r\n\t}\r\n});\r\n```\r\n\r\n### cssmin\r\nIf cssmin is assigned true, `.css` will be minified before inlined.\r\n\r\n```\r\ngrunt.initConfig({\r\n\tinline: {\r\n\t\tdist: {\r\n\t\t\toptions:{\r\n\t\t\t\tcssmin: true\r\n\t\t\t},\r\n\t\t\tsrc: \'src/index.html\',\r\n\t\t\tdest: \'dist/index.html\'\r\n\t\t}\r\n\t}\r\n});\r\n```\r\n\r\n### tag (defaults to ```__inline```)\r\nOnly URLs that contain the value for ```tag``` will be inlined.\r\nSpecify ```tag: \'\'``` to include all urls.\r\n\r\n```\r\ngrunt.initConfig({\r\n\tinline: {\r\n\t\tdist: {\r\n\t\t\toptions:{\r\n\t\t\t\ttag: \'\'\r\n\t\t\t},\r\n\t\t\tsrc: \'src/index.html\',\r\n\t\t\tdest: \'dist/index.html\']\r\n\t\t}\r\n\t}\r\n});\r\n```\r\n\r\n\r\n### inlineTagAttributes\r\nAbility to add attributes string to inline tag.\r\n\r\n```\r\ngrunt.initConfig({\r\n\tinline: {\r\n\t\tdist: {\r\n\t\t\toptions:{\r\n\t\t\t\tinlineTagAttributes: {\r\n\t\t\t\t\tjs: \'data-inlined="true"\',\t// Adds ``````\r\n\t\t\t\t\tcss: \'data-inlined="true"\'\t// Adds ``````\r\n\t\t\t},\r\n\t\t\tsrc: \'src/index.html\',\r\n\t\t\tdest: \'dist/index.html\'\r\n\t\t}\r\n\t}\r\n});\r\n```\r\n\r\n\r\n### uglify\r\nIf uglify is assigned true, `.js` file will be minified before inlined.\r\n\r\n```\r\ngrunt.initConfig({\r\n\tinline: {\r\n\t\tdist: {\r\n\t\t\toptions:{\r\n\t\t\t\tuglify: true\r\n\t\t\t},\r\n\t\t\tsrc: \'src/index.html\',\r\n\t\t\tdest: \'dist/index.html\'\r\n\t\t}\r\n\t}\r\n});\r\n```\r\n\r\n### exts\r\nSetting an exts array allows multiple file extensions to be processed as\r\nhtml.\r\n\r\n```\r\ngrunt.initConfig({\r\n\tinline: {\r\n\t\tdist: {\r\n\t\t\toptions:{\r\n\t\t\t exts: [\'jade\'],\r\n\t\t\t\tuglify: true\r\n\t\t\t},\r\n\t\t\tsrc: \'src/index.jade\',\r\n\t\t\tdest: \'dist/index.jade\'\r\n\t\t}\r\n\t}\r\n});\r\n```\r\n\r\n### Usage Examples\r\n\r\n> config\r\n\r\n\tgrunt.initConfig({\r\n\t inline: {\r\n\t dist: {\r\n\t src: \'src/index.html\'\r\n\t }\r\n\t }\r\n\t})\r\n\r\n> src/index.html\r\n\r\n\t\r\n\t\t
\r\n\t\t\tdemo\r\n\t\t\t\r\n\t\t\r\n\t\t\r\n\t\t\t\r\n\r\n\t\t\t\r\n\t\t\r\n\t\r\n\r\n> after `grunt inline` was run, it will be something like\r\n\r\n\t\r\n\t\t\r\n\t\t\tdemo\r\n\t\t\t\r\n\t\t\r\n\t\t\r\n\t\t\t\r\n\t\t\t\r\n\r\n\t\t\t\r\n\t\t\r\n\t\r\n\r\n#### inline tag\r\nSuppose there is an `` tag in `index.html` like bellow\r\n\r\n```\r\n\r\n\r\n```\r\n\r\nThe content of `test.html` is\r\n\r\n```\r\n
I\'m inline html
\r\nhello world!\r\n```\r\n\r\nThen, after the `inline` task is run, the original content in `index.html` will be replaced with\r\n\r\n```\r\n
I\'m inline html
\r\nhello world!\r\n```\r\n\r\n## Contributing\r\nIn lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code using [Grunt](http://gruntjs.com/).\r\n\r\n## Release History\r\n* 2015-01-09 v0.3.3 bug fix: when processing files of a folder and then copy the processed content to another destination, the original files are changed unexpectedly, as mentioned in this issue [Support file globbing for input and output](https://github.com/chyingp/grunt-inline/issues/35)\r\n* 2014-06-16 v0.3.1 bug fix: protocol-relative urls in css are messed up\r\n* 2014-06-15 v0.3.1 bug fix: when options.tag is \'\', then all img tags, whose src attribute has already been inlined will be matched.\r\n* 2014-05-19 v0.3.0 support for new options.exts\r\n* 2014-05-19 v0.2.9 bug fix: options.tag is assigned \'\', bug image url in css are not converted to base64 formate\r\n* 2014-03-06 v0.2.6 bug fix: script tags like were not inlined\r\n* 2014-01-31 v0.2.3 radded tag option, encode url(..) images.\r\n* 2013-10-31 v0.2.2 bug fix: img urls like \'background: url(http://www.example.com/img/bg.png)\' will be transformed to \'background: url(url(http://www.example.com/img/bg.png))\'\r\n* 2013-10-30 v0.2.1 bug fix: when processing relative file path of img url in css stylesheet, forgot to transform "\\" to "/" for windows users\r\n* 2013-10-30 v0.2.0 new feature: Support for minifing js、css when they ar inlined into html.\r\n* 2013-08-30 v0.1.9 bug fix: stylesheets ended with ">" cannot be inlined\r\n* 2013-09-02 v0.1.9 add feature: add options.dest to assign a destination path where the source file will be copied\r\n* 2013-09-02 v0.1.8 add feature: support for `` tag\r\n',
-28 silly publish readmeFilename: 'README.md',
-28 silly publish gitHead: '497e222702d0c6564d3a9d8d1f7979cad803b08f',
-28 silly publish bugs: { url: 'https://github.com/chyingp/grunt-inline/issues' },
-28 silly publish homepage: 'https://github.com/chyingp/grunt-inline',
-28 silly publish _shasum: '0ae2fb5c1b1569bbea0003db01c015f4371f662d' }
-29 verbose url raw grunt-inline
-30 verbose url resolving [ 'https://registry.npmjs.org/', './grunt-inline' ]
-31 verbose url resolved https://registry.npmjs.org/grunt-inline
-32 info trying registry request attempt 1 at 02:27:12
-33 http PUT https://registry.npmjs.org/grunt-inline
-34 http 403 https://registry.npmjs.org/grunt-inline
-35 verbose headers { date: 'Thu, 08 Jan 2015 18:27:14 GMT',
-35 verbose headers server: 'CouchDB/1.5.0 (Erlang OTP/R16B03)',
-35 verbose headers 'content-type': 'application/json',
-35 verbose headers 'cache-control': 'max-age=60',
-35 verbose headers 'content-length': '230',
-35 verbose headers 'accept-ranges': 'bytes',
-35 verbose headers via: '1.1 varnish',
-35 verbose headers 'x-served-by': 'cache-ty66-TYO',
-35 verbose headers 'x-cache': 'MISS',
-35 verbose headers 'x-cache-hits': '0',
-35 verbose headers 'x-timer': 'S1420741634.005146,VS0,VE239',
-35 verbose headers 'keep-alive': 'timeout=10, max=50',
-35 verbose headers connection: 'Keep-Alive' }
-36 error publish Failed PUT 403
-37 error Error: forbidden Attempting to modify version 0.3.3,
-37 error which was previously published on 2015-01-08T17:00:33.229Z.
-37 error This is forbidden, to maintain package integrity.
-37 error Please update the version number and try again.: grunt-inline
-37 error at RegClient. (/usr/local/lib/node_modules/npm/node_modules/npm-registry-client/lib/request.js:274:14)
-37 error at Request._callback (/usr/local/lib/node_modules/npm/node_modules/npm-registry-client/lib/request.js:212:65)
-37 error at Request.self.callback (/usr/local/lib/node_modules/npm/node_modules/request/request.js:123:22)
-37 error at Request.emit (events.js:98:17)
-37 error at Request. (/usr/local/lib/node_modules/npm/node_modules/request/request.js:893:14)
-37 error at Request.emit (events.js:117:20)
-37 error at IncomingMessage. (/usr/local/lib/node_modules/npm/node_modules/request/request.js:844:12)
-37 error at IncomingMessage.emit (events.js:117:20)
-37 error at _stream_readable.js:929:16
-37 error at process._tickCallback (node.js:419:13)
-38 error If you need help, you may report this *entire* log,
-38 error including the npm and node versions, at:
-38 error
-39 error System Darwin 13.4.0
-40 error command "node" "/usr/local/bin/npm" "publish"
-41 error cwd /Users/a/Documents/git-code/grunt-inline
-42 error node -v v0.10.29
-43 error npm -v 1.4.14
-44 verbose exit [ 1, true ]
diff --git a/package.json b/package.json
index aba3f9d..5eda47d 100644
--- a/package.json
+++ b/package.json
@@ -1,40 +1,40 @@
-{
- "author": {
- "name": "程序猿小卡",
- "email": "chyingp@gmail.com",
- "url": "https://github.com/chyingp"
- },
- "name": "grunt-inline",
- "description": "Inlines img, script and link tags into the same file.",
- "version": "0.3.4",
- "keywords": [
- "gruntplugin",
- "inline",
- "js",
- "css"
- ],
- "main": "inline",
- "repository": {
- "type": "git",
- "url": "https://github.com/chyingp/grunt-inline.git"
- },
- "engines": {
- "node": ">=0.8.0"
- },
- "devDependencies": {
- "grunt-contrib-nodeunit": "~0.1.2",
- "grunt-contrib-clean": "~0.4.0",
- "grunt-contrib-htmlmin": "~0.1.3",
- "grunt": "~0.4.0"
- },
- "dependencies": {
- "uglify-js": "2.4.1",
- "datauri": "~0.2.0",
- "clean-css": "1.1.7"
- },
- "scripts": {
- "test": "grunt test"
- },
- "_id": "grunt-inline@0.1.0",
- "_from": "grunt-inline@~0.1.0"
-}
+{
+ "author": {
+ "name": "程序猿小卡",
+ "email": "chyingp@gmail.com",
+ "url": "https://github.com/chyingp"
+ },
+ "name": "grunt-inline",
+ "description": "Inlines img, script and link tags into the same file.",
+ "version": "0.3.5",
+ "keywords": [
+ "gruntplugin",
+ "inline",
+ "js",
+ "css"
+ ],
+ "main": "inline",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/chyingp/grunt-inline.git"
+ },
+ "engines": {
+ "node": ">=0.8.0"
+ },
+ "devDependencies": {
+ "grunt": "~0.4.0",
+ "grunt-contrib-clean": "~0.4.0",
+ "grunt-contrib-htmlmin": "~0.1.3",
+ "grunt-contrib-nodeunit": "~0.1.2"
+ },
+ "dependencies": {
+ "uglify-js": "2.4.1",
+ "datauri": "~0.2.0",
+ "clean-css": "1.1.7"
+ },
+ "scripts": {
+ "test": "grunt test"
+ },
+ "_id": "grunt-inline@0.1.0",
+ "_from": "grunt-inline@~0.1.0"
+}
diff --git a/tasks/inline.js b/tasks/inline.js
index 556077d..7c017a0 100644
--- a/tasks/inline.js
+++ b/tasks/inline.js
@@ -16,44 +16,50 @@ module.exports = function(grunt) {
grunt.registerMultiTask('inline', "Replaces , ';
- }else{
- grunt.log.error("Couldn't find " + inlineFilePath + '!');
- }
- }
- grunt.log.debug('ret = : ' + ret +'\n');
-
- return ret;
-
- }).replace(//g, function(matchedWord, src){
- var ret = matchedWord;
-
- if(!isRemotePath(src) && src.indexOf(options.tag)!=-1){
-
- var inlineFilePath = path.resolve( path.dirname(filepath), src ).replace(/\?.*$/, ''); // 将参数去掉
-
- if( grunt.file.exists(inlineFilePath) ){
- var styleSheetContent = grunt.file.read( inlineFilePath );
- ret = '';
- }else{
- grunt.log.error("Couldn't find " + inlineFilePath + '!');
- }
- }
- grunt.log.debug('ret = : ' + ret +'\n');
-
- return ret;
- }).replace(//g, function(matchedWord, src){
- var ret = matchedWord;
-
- if(!grunt.file.isPathAbsolute(src) && src.indexOf(options.tag)!=-1){
-
- var inlineFilePath = path.resolve( path.dirname(filepath), src ).replace(/\?.*$/, ''); // 将参数去掉
-
- if( grunt.file.exists(inlineFilePath) ){
- ret = matchedWord.replace(src, (new datauri(inlineFilePath)).content);
- }else{
- grunt.log.error("Couldn't find " + inlineFilePath + '!');
- }
- }
- grunt.log.debug('ret = : ' + ret +'\n');
-
- return ret;
- });
-
- return fileContent;
+ function cssReplacement(matchedWord, src) {
+ if(!isRemotePath(src) && src.indexOf(options.tag)!=-1) {
+ var inlineFilePath = path.resolve(path.dirname(filepath), src).replace(/\?.*$/, '');
+
+ if (grunt.file.exists(inlineFilePath)) {
+ var styleSheetContent = grunt.file.read(inlineFilePath);
+
+ return '';
+ } else {
+ grunt.log.error("Couldn't find " + inlineFilePath + '!');
+ }
+ }
+
+ return matchedWord;
+ }
+
+ function imageReplacement(matchedWord, src) {
+ if(!grunt.file.isPathAbsolute(src) && src.indexOf(options.tag)!=-1) {
+ var inlineFilePath = path.resolve( path.dirname(filepath), src ).replace(/\?.*$/, ''); // 将参数去掉
+
+ if( grunt.file.exists(inlineFilePath) ){
+ return matchedWord.replace(src, (new datauri(inlineFilePath)).content);
+ } else {
+ grunt.log.error("Couldn't find " + inlineFilePath + '!');
+ }
+ }
+
+ return matchedWord;
+ }
+
+ function scriptReplacement(matchedWord, src, attrs) {
+ if(!isRemotePath(src) && src.indexOf(options.tag)!=-1){
+ var dataAttribs = getDataAttribs(attrs);
+ var inlineFilePath = path.resolve( path.dirname(filepath), src ).replace(/\?.*$/, '');
+ var c = options.uglify ? UglifyJS.minify(inlineFilePath).code : grunt.file.read( inlineFilePath );
+
+ if( grunt.file.exists(inlineFilePath) ){
+ var inlineTagAttributes = options.inlineTagAttributes.js;
+ return '';
+ }else{
+ grunt.log.error("Couldn't find " + inlineFilePath + '!');
+ }
+ }
+
+ return matchedWord;
+ }
+
+ function htmlInclusion(matchedWord, src){
+ if(isRemotePath(src) || !grunt.file.isPathAbsolute(src)) {
+ var inlineFilePath = path.resolve( path.dirname(filepath), src );
+
+ if( grunt.file.exists(inlineFilePath) ){
+ var ret = grunt.file.read( inlineFilePath );
+
+ // @otod need to be checked, add bye herbert
+ var _more = src.match(/^(..\/)+/ig);
+ if(_more = _more && _more[0]) {
+ var _addMore = function(){
+ var _ret = arguments[0],_src = arguments[2];
+ if(!_src.match(/^http\:\/\//)){
+ _ret = arguments[1] + _more + arguments[2] + arguments[3];
+ }
+
+ return _ret;
+ };
+
+ ret = ret.replace(/(<\/script>)/g,_addMore);
+ }
+
+ return ret;
+ } else {
+ grunt.log.error("Couldn't find " + inlineFilePath + '!');
+ }
+ }
+
+ return matchedWord;
+ }
+
+ return fileContent.replace(//gi, htmlInclusion)
+ .replace(/\s*<\/script>/gi, scriptReplacement)
+ .replace(//gi, imageReplacement)
+ .replace(//gi, cssReplacement)
+ .replace(//gi, imageReplacement);
}
function css(filepath, fileContent, relativeTo, options) {
- if(relativeTo){
+ if(relativeTo) {
filepath = filepath.replace(/[^\/]+\//g, relativeTo);
}
- fileContent = fileContent.replace(/url\(["']*([^)'"]+)["']*\)/g, function(matchedWord, imgUrl){
- var newUrl = imgUrl;
+ fileContent = fileContent.replace(/url\(["']*([^)'"]+)["']*\)/g, function(matchedWord, imgUrl) {
var flag = imgUrl.indexOf(options.tag)!=-1; // urls like "img/bg.png?__inline" will be transformed to base64
+
if(isBase64Path(imgUrl) || isRemotePath(imgUrl)){
return matchedWord;
}
- grunt.log.debug( 'imgUrl: '+imgUrl);
- grunt.log.debug( 'filepath: '+filepath);
+
var absoluteImgurl = path.resolve( path.dirname(filepath),imgUrl );
- grunt.log.debug( 'absoluteImgurl: '+absoluteImgurl);
- newUrl = path.relative( path.dirname(filepath), absoluteImgurl );
- grunt.log.debug( 'newUrl: '+newUrl);
+ var newUrl = path.relative( path.dirname(filepath), absoluteImgurl );
absoluteImgurl = absoluteImgurl.replace(/\?.*$/, '');
- if(flag && grunt.file.exists(absoluteImgurl)){
+
+ if(flag && grunt.file.exists(absoluteImgurl)) {
newUrl = datauri(absoluteImgurl);
- }else{
+ } else {
newUrl = newUrl.replace(/\\/g, '/');
}
return matchedWord.replace(imgUrl, newUrl);
});
- fileContent = options.cssmin ? CleanCSS.process(fileContent) : fileContent;
- return fileContent;
+ return options.cssmin ? CleanCSS.process(fileContent) : fileContent;
}
function cssInlineToHtml(htmlFilepath, filepath, fileContent, relativeTo, options) {
@@ -217,31 +215,26 @@ module.exports = function(grunt) {
}
fileContent = fileContent.replace(/url\(["']*([^)'"]+)["']*\)/g, function(matchedWord, imgUrl){
- var newUrl = imgUrl;
var flag = !!imgUrl.match(/\?__inline/); // urls like "img/bg.png?__inline" will be transformed to base64
- grunt.log.debug('flag:'+flag);
+
if(isBase64Path(imgUrl) || isRemotePath(imgUrl)){
return matchedWord;
}
- grunt.log.debug( 'imgUrl: '+imgUrl);
- grunt.log.debug( 'filepath: '+filepath);
- var absoluteImgurl = path.resolve( path.dirname(filepath),imgUrl ); // img url relative to project root
- grunt.log.debug( 'absoluteImgurl: '+absoluteImgurl);
- newUrl = path.relative( path.dirname(htmlFilepath), absoluteImgurl ); // img url relative to the html file
- grunt.log.debug([htmlFilepath, filepath, absoluteImgurl, imgUrl]);
- grunt.log.debug( 'newUrl: '+newUrl);
+
+ var absoluteImgurl = path.resolve( path.dirname(filepath), imgUrl ); // img url relative to project root
+ var newUrl = path.relative( path.dirname(htmlFilepath), absoluteImgurl ); // img url relative to the html file
absoluteImgurl = absoluteImgurl.replace(/\?.*$/, '');
+
if(flag && grunt.file.exists(absoluteImgurl)){
newUrl = datauri(absoluteImgurl);
- }else{
+ } else {
newUrl = newUrl.replace(/\\/g, '/');
}
return matchedWord.replace(imgUrl, newUrl);
});
- fileContent = options.cssmin ? CleanCSS.process(fileContent) : fileContent;
- return fileContent;
+ return options.cssmin ? CleanCSS.process(fileContent) : fileContent;
}
};
diff --git a/test/dist/css.html b/test/dist/css.html
index 6a100a3..0f2de95 100644
--- a/test/dist/css.html
+++ b/test/dist/css.html
@@ -6,7 +6,8 @@
-
+
+
diff --git a/test/dist/icon.html b/test/dist/icon.html
new file mode 100644
index 0000000..54b518e
--- /dev/null
+++ b/test/dist/icon.html
@@ -0,0 +1,13 @@
+
+
+
+ test
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/test/dist/script.html b/test/dist/script.html
index 6f58362..1b52658 100644
--- a/test/dist/script.html
+++ b/test/dist/script.html
@@ -3,6 +3,7 @@
test
+
diff --git a/test/expected/css.min.html b/test/expected/css.min.html
index 8d3b73c..9f6d27b 100644
--- a/test/expected/css.min.html
+++ b/test/expected/css.min.html
@@ -8,4 +8,9 @@
body{background: url('http://www.example.com/img/bg.png');}
body{background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABsAAAAwCAYAAADgvwGgAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAABUlJREFUeNq8WFtsVEUY/ufsWbbtsl1aWtqCBKlJtVakTSEGa4IvJqiJPmg0PmjwRZONBGJDAzHYmD54i40PatCoMeEBL28N6oORROSlloqWW420hRbtZVvYXpa17Z4zfjNndnt2zzl7iJad5Ns5Z87MfPNf5p9/ljHGAkRkkFthjIhz1NkGq5Jt6putmKZJhYpOnmScVrtomDRoTWwDX30iSzIOFKlAMgoUk0wrJhmXTsbYbSeDvVgKNKVwiRq8rwfKlGpTwDgwumps2Gc9TGNDqJOouQTL1nNAL573ARGmaSQBLWRrGzi8uBCYmFiqsZC3Wxo+D7yCl1MYuREja+QMRBNKA76bmihvk2Ulc4eQvh91Qklvor4hpWdsn69k2++u56HQGhqfmqGxiXhGtXSL0lp9rOdB0zAbCzpI37Fu0vUAJZI36WTfAHV+eIwuDI1iPMudmOeROCPbSV/XDzCTzPQyVZSV0FOPPUynvniX9rS1KnN4hEnuIiWjHl9n5MO9wk3IXEiQmZwjPVxG8ekb1PrcAanWrEodJDl6HgB2YIHLBSWbnFyiifFFStdtJ72+hdKpRareuIGeeaTNW4VSEm7nfdtGtBZ4Hngf+BjYD2yVNjvTdUT2Dt+xmXZ0vkXhzbDx9BDtbGrwPml4ju2wFehr9bwL+AbYBJxTgUEQvwO0a5quk8DsH5dodvhPYuVVYsNQdUV5Lhd3kGRs1QWp0qplr4o49wD3Aw8AG4DPgEN6eEu97FW/cxfVtLSQMfobBZiWu0GZi3OsENfbvr6s6meBj4AoIBynHYjpbUdek6MCOidjpJd4cpYoEqG5ZGqFx83tWZZQrP4T2xehyi+Bb5WUh5QdO3S6+qvskTagCcQ7sMoTYDoxXzhTWJHwzrxevwBNwEX1fhhYkg7CM8sNBHMOnpnEXOHowbN1LbaHbrOboYiagUr7Zvc8OOduptzDk5O4GkQP4qlVoRR4AzgL/AicsJ1n7q69tJz2dneZE/GMKquBn2w9hfe9ZHt/XO2zEc9kJ6Bpzk3NXSRk2EucvsrYRdUjQK16vw7EXSTjWYJwacjdTorQFqgnYIwYN7ld7y8A7ykv7AQWVCrHbTZhWc710UiuNN5RX6z6n7y2y8CTjtiohUpIC5Vak5npbHpdtS7qfdTmRpAxSGVv3aTioqjXAAeBPVKypapGOb40Ukbm1DCZM39JsnXlYadzcJcoQvR73nIEwdMqAGds+KIkO93RjjGcKu9rpm2x/aSLTT0/QSXBoKdP5DnOgq21WdVNyguFzX4AZoV02nJyntLJJI1930Pxs/2k1W6Vs6QWFx2mdFUno4NMJD9WQUJEZ4DXVajqV6SDwKc6Q9AV42of2k2V25rJnLwiT4HBK9f8LzSWdHX4PaDCUky5uiB91dZTxMkYS1wakFNF6rC4BOwVB1lJCe3e20Gn+s9bJ7Xr4Zwj8QzaG7HR47av96poci4bG8vNKRl4zcsjJPIRipZT99HjkojysyzvbEtk0k+ocytTLjpcnzED86UpsLaMEqllOvzmUWrv/jx34ewWMk6iR/3yRr0LqVsQNvo7fp2++7mPhsbGV3JHL2ncc8oG3+zKkTPlZ1POiY8DIRVcxZergMiITxiGccHvYuGeajvTcJFmx9DuuFAIaAjcfmoUHac883vrVnMNzx8ADdbt5b+TYZuxu0AZxdsWCFoh3RVjoaAFTDOEbiIBTfjYSxJCjX5aZFEVThyWFMcIz5/5f5CJEzJY3Dt1EcnMYpEhEDPDGRhu0z88ftec1VZjuvB1e3XJjOJQEf0rwABVXGHq9lRcdAAAAABJRU5ErkJggg==');}
body{background: url(data:image/jpeg;base64,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)
+body{background: url('data:image/jpeg;base64,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')