├── .gitignore
├── LICENSE
├── README.md
├── README_zh-CN.md
├── assets
├── .babelrc
├── build.png
├── build.svg
├── coverage.png
├── coverage.svg
└── logo.png
├── index.js
├── karma
└── karma.conf.js
├── lib
├── assetsPathParser.js
├── base64.js
├── cdnProxy.js
├── gmutil.js
├── gulp-usemin
│ ├── .npmignore
│ ├── .travis.yml
│ ├── LICENSE
│ ├── README.md
│ ├── gulpfile.js
│ ├── index.js
│ ├── lib
│ │ ├── blocksBuilder.js
│ │ ├── htmlBuilder.js
│ │ └── pipeline.js
│ ├── package.json
│ └── test
│ │ ├── expected
│ │ ├── app.js
│ │ ├── array-js-attributes.html
│ │ ├── build-remove-no-trailing-whitespace.html
│ │ ├── complex-path.html
│ │ ├── complex.html
│ │ ├── conditional-complex.html
│ │ ├── conditional-css.html
│ │ ├── conditional-inline-css.html
│ │ ├── conditional-inline-js.html
│ │ ├── conditional-js.html
│ │ ├── data
│ │ │ ├── css
│ │ │ │ ├── min-style.css
│ │ │ │ └── style.css
│ │ │ └── js
│ │ │ │ ├── app.js
│ │ │ │ ├── app_min_concat.js
│ │ │ │ └── min-app.js
│ │ ├── glob-inline-css.html
│ │ ├── glob-inline-js.html
│ │ ├── many-blocks-removal.html
│ │ ├── min-app.js
│ │ ├── min-complex-path.html
│ │ ├── min-complex.html
│ │ ├── min-css-with-media-query.html
│ │ ├── min-html-simple-css.html
│ │ ├── min-html-simple-js.html
│ │ ├── min-html-simple-removal.html
│ │ ├── min-paths-with-querystring.html
│ │ ├── min-simple-css-path.html
│ │ ├── min-simple-css.html
│ │ ├── min-simple-js-path.html
│ │ ├── min-simple-js.html
│ │ ├── min-style.css
│ │ ├── multiple-alternative-paths.html
│ │ ├── multiple-files.html
│ │ ├── paths-with-querystring.html
│ │ ├── simple-css-path.html
│ │ ├── simple-css.html
│ │ ├── simple-inline-css.html
│ │ ├── simple-inline-js.html
│ │ ├── simple-js-path.html
│ │ ├── simple-js-removal.html
│ │ ├── simple-js.html
│ │ ├── single-quotes-css.html
│ │ ├── single-quotes-inline-css.html
│ │ ├── single-quotes-inline-js.html
│ │ ├── single-quotes-js.html
│ │ ├── style.css
│ │ └── subfolder
│ │ │ ├── app.js
│ │ │ └── index.html
│ │ ├── fixtures
│ │ ├── alternative
│ │ │ └── js
│ │ │ │ └── util.js
│ │ ├── array-js-attributes.html
│ │ ├── async-less.html
│ │ ├── build-remove-no-trailing-whitespace.html
│ │ ├── comment-js.html
│ │ ├── complex-path.html
│ │ ├── complex.html
│ │ ├── conditional-complex.html
│ │ ├── conditional-css.html
│ │ ├── conditional-inline-css.html
│ │ ├── conditional-inline-js.html
│ │ ├── conditional-js.html
│ │ ├── css-with-media-query-error.html
│ │ ├── css-with-media-query.html
│ │ ├── css
│ │ │ ├── clear.css
│ │ │ └── main.css
│ │ ├── glob-css.html
│ │ ├── glob-inline-css.html
│ │ ├── glob-inline-js.html
│ │ ├── glob-js.html
│ │ ├── js
│ │ │ ├── lib.js
│ │ │ └── main.js
│ │ ├── js2
│ │ │ ├── lib2.js
│ │ │ └── main2.js
│ │ ├── less
│ │ │ ├── clear.less
│ │ │ └── main.less
│ │ ├── many-blocks-removal.html
│ │ ├── many-blocks.html
│ │ ├── min-html-simple-css.html
│ │ ├── min-html-simple-js.html
│ │ ├── min-html-simple-removal.html
│ │ ├── multiple-alternative-paths-inline.html
│ │ ├── multiple-alternative-paths.html
│ │ ├── multiple-files.html
│ │ ├── paths-with-querystring.html
│ │ ├── simple-css-alternate-path.html
│ │ ├── simple-css-path.html
│ │ ├── simple-css.html
│ │ ├── simple-inline-css.html
│ │ ├── simple-inline-js.html
│ │ ├── simple-js-alternate-path.html
│ │ ├── simple-js-path.html
│ │ ├── simple-js-removal.html
│ │ ├── simple-js.html
│ │ ├── single-quotes-css.html
│ │ ├── single-quotes-inline-css.html
│ │ ├── single-quotes-inline-js.html
│ │ ├── single-quotes-js.html
│ │ └── subfolder
│ │ │ ├── index.html
│ │ │ └── script.js
│ │ └── main.js
├── htmlPathParser.js
├── iconFonter.js
├── inline.js
├── revReplace.js
├── spriter
│ ├── README.md
│ ├── index.js
│ ├── lib
│ │ ├── get-background-image-declarations.js
│ │ ├── get-meta-info-for-declaration.js
│ │ ├── map-over-styles-and-transform-background-image-declarations.js
│ │ ├── spriter-util.js
│ │ ├── transform-file-with-sprite-sheet-data.js
│ │ └── transform-map.js
│ └── package.json
└── store.js
├── meta
├── favicon.ico
└── home
│ ├── img
│ └── logo.png
│ ├── index.html
│ ├── main.es6
│ └── main.scss
├── package-lock.json
├── package.json
├── presetlib
├── jquery.js
├── react-0.14.6
│ └── build
│ │ ├── react-dom-server.js
│ │ ├── react-dom-server.min.js
│ │ ├── react-dom.js
│ │ ├── react-dom.min.js
│ │ ├── react-with-addons.js
│ │ ├── react-with-addons.min.js
│ │ ├── react.js
│ │ └── react.min.js
└── react.js
├── scripts
├── gulp
│ └── gulpfile.js
├── install.sh
├── package.json
└── preinstall.sh
└── test.js
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | node_modules
3 | .npm
4 | .bin
5 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright Lucas, Inc. and other contributors.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | [](http://karat.cc/article/56a351c3e48d2d05682aa0ac/)
3 |
4 | -----
5 |
6 | [](http://badge.fury.io/js/gulpman)
7 |
8 |
9 |
10 | # gulpman
11 |
12 | [浏览简体中文文档](https://github.com/xunuoi/gulpman/blob/master/README_zh-CN.md)
13 |
14 | - Create Modular Front-End Build System, organize the source by module, using relative path, `html/js/css/img/fonts/tpl` are in one same folder, like Baidu `FIS`. Good concept for FE source management / development.
15 | - Concept Introduction: [前端工程之模块化](http://fex.baidu.com/blog/2014/03/fis-module/)
16 | - Component Oriented Solution, based on `gulp`. More simple, flexible, expandable and stable. Everyone know gulp can do secondary development.
17 | - Support `base64` image in `html/CSS`
18 | - Support `JS/CSS` inlnied in html
19 | - Support `require('main.css')`, require css file in js
20 | - Intergrated with `spritesmith`, support auto sprite img
21 | - Intergrated with `icon-font`, support SVG 2 Iconfont.
22 | - Intergrated with `usemin`,support complex combo/package.
23 | - Supoort FE Tpl embed function, the `.tpl` file will packaged into js file,support async js loading.
24 | - Intergrated with `SCSS|ES6|ReactJS|Vuejs|Babel|Browserify|cssnano|uglify|imagmein` and other plugins,One-Stop Solution Service, very Simple and Strong
25 | - High scalability, compatiable with almost `gulp` plugins, you can use them in `gulpman`. For example, you can put `browser-sync` in your gulpman build system
26 | - Intergrated with `karma` framework,support `babel/es6` unit test and coverage result.
27 |
28 |
29 | ## Introduction
30 | - Support Mac、Linux
31 | - No full test under Windows. You can install `gulp`、`gulp-sass` manually
32 | - Required Node >= 4.0.0
33 |
34 |
35 | ## Install
36 |
37 | - `npm install gulpman --save-dev`
38 | - Run `gulp gm:install` to finish the setup
39 | - *If in China, please use `cnpm` to install it: `cnpm install gulpman --save-dev`
40 |
41 |
42 | #### Note
43 | * If `gulp-sass` install failed, please run `cnpm install gulp-sass gulp-imagemin` by manual to fix that.
44 |
45 | * If error happened in npm install,such as `/usr/local/lib/node_modules` permission error, fix this by `sudo chown -R "$(whoami)"`+`Path`
46 | * `sudo npm install` is not recommended
47 | * The imagemin-pngquant module need`libpng-devel`,if in Linux, please run `yum install libpng-devel` at first
48 | * If install failed, check the `npm-debug.log` to see if there are some `ENOMEM`errors
49 |
50 |
51 |
52 | ## Config
53 |
54 | ### 0. Support Auto Mode, no Config
55 |
56 | * You can skip `Config`, and directly jump to `Usage`
57 |
58 |
59 | ### 1. Config gulpfile.js:
60 |
61 | - require the `gulpman` in your gulpfile.js,then it will load `gm:publish`, `gm:develop` into gulp tasks.
62 | - `gulp gm:publish` or `gulp gm:develop` in terminal then it will work
63 |
64 |
65 | ```Javascript
66 | /**
67 | * Gulpfile.js
68 | */
69 |
70 |
71 | var gulp = require('gulp'),
72 | gman = require('gulpman')
73 |
74 | // your other tasks ...
75 | // xxx ...
76 |
77 |
78 | /**
79 | * config gulpman ======================
80 | * Use config API
81 | * assets path, CDN, URL prefix
82 | */
83 |
84 | gman.config({
85 |
86 | // whether use absolute path, default `true`
87 | 'is_absolute': true,
88 |
89 | // cdn prefix support[string|array|function]arguments
90 | 'cdn_prefix': '',
91 |
92 | // url prefix, defautl `/static`. This involves the server config ,such as the static path of nginx
93 | 'url_prefix': '/static',
94 |
95 |
96 | /** use spritesmith for css-img sprite
97 | * Based on Spritesmith: https://github.com/Ensighten/spritesmith
98 | * Automatecially generate Sprite Image & CSS
99 | **/
100 | //'spritesmith': { },
101 |
102 | /** usemin config **/
103 | // 'usemin': {}
104 |
105 |
106 | // The COMPONENTS directory
107 | 'components': 'components',
108 |
109 | // For development assets and templates folder, related to Server Config
110 | 'runtime_views': 'views',
111 | 'dist_views': 'views_dist',
112 |
113 | // For production assets and templates folder, related to Server Config
114 | 'runtime_assets': 'assets',
115 | 'dist_assets': 'assets_dist',
116 |
117 | // The js library dir, set as a global module. Also you can set as `bower_components`
118 | 'lib': 'lib',
119 |
120 | // You can add one customer global directory, so you can require module name directly, like: `require ('xxx')`. The xxx is in this directory
121 | 'global': 'common'
122 | })
123 |
124 |
125 | ```
126 |
127 | ### 2. How to config CDN better
128 |
129 | * `cdn_prefix` support String, Array, Function
130 | * if argument is array, the CDN will be an random value
131 | * if argument is function,it would input one argument, `mediaFile`
132 |
133 | ```Javascript
134 |
135 | 'cdn_prefix': function (fileName) {
136 |
137 | console.log(fileName)
138 |
139 | var c_list = [
140 | 'http://s0.com',
141 | 'http://s1.com',
142 | 'http://s2.com',
143 | 'http://s3.com',
144 | 'http://s4.com'
145 | ]
146 | // You can customized your strategy
147 | if(hostFile.match(/\.html$/gm)){
148 | return c_list[0]
149 | }else {
150 | return c_list[1]
151 | }
152 | },
153 | ```
154 |
155 | ### 3. About `is_absolute`
156 |
157 | * `is_absolute` is the dist path of source in html. default true. the dist path is like `/static/home/main.js`
158 |
159 | * [*]Need consistent config with Server, like nginx, apache
160 |
161 | * If no local server, you can set is_absolute as false, use relative path. Like `../../assets/static/home/main.js`
162 |
163 |
164 | ### 4. gulpman directory
165 |
166 | * Use gulpman to arrange your directory as component,The root component dir can be`./components`(default). If you have one component named foo, then `./components/foo`,all related assets such as `html|js|css|fonts|image` should be put in `foo` folder.
167 |
168 | * This solution for assets can be high efficiency and easy to maintain.
169 |
170 | * `gm:develop` to start `develop` mode, the `views` dir and `assets` dir can be generated automatically
171 |
172 | * `gm:publish` to publish assets in production env. The `views_dist` and `assets_dist` can generated.
173 |
174 |
175 | ### 5. What is global directory
176 |
177 | - For `Browserify` packing, the js module in `global dir` can be directly `require` or `import` in es6/js code
178 |
179 | - In `gulpman.config`, the `lib`和`global` are global directory. Take an example:
180 | * In `components/lib` directory, you have one module `foo.js`,then it is `components/lib/foo.js`. So when you use foo in your es6 file, you can use it like: `import foo from 'foo'`, no need write as `import foo from '../lib/foo'`
181 |
182 | - similarly, `global` option can set your dir as global module dir. You can set `bower` dir as your `lib` dir.
183 |
184 | - Please make no conficts in your global dir
185 |
186 |
187 | ### 6. Support for complex and multi level directory in config
188 |
189 | * Such as:
190 |
191 | ```Javascript
192 | gulpman.config({
193 | 'is_absolute': false,
194 | 'components': 'components/cc',
195 | 'runtime_views': 'runtime_views/rv',
196 | 'dist_views': 'dist_views/dv/dv',
197 |
198 | 'dist_assets': 'dist_assets/da',
199 | 'runtime_assets': 'runtime_assets/ra/ra',
200 | })
201 | ```
202 |
203 |
204 | ## Usage
205 |
206 | ### 1. CLI run Task:
207 |
208 | ```Shell
209 |
210 | # Create components directory and add one demo
211 | # init components dir and a html demo
212 | gulp gm:init
213 |
214 |
215 | # develop and watch mode,watchings files changes and update files
216 | gulp gm:develop
217 |
218 | # Build and Watch one special component, other files are not compiled
219 | gulp gm:develop -c component_name1,component_name2,component_name3...
220 |
221 |
222 | # publish assets in production env
223 | gulp gm:publish
224 |
225 | # publish command support `-a`和`-v` parameters to set output assets/views path.
226 | gulp gm:publish -v your_views_dist -a your_assets_dist
227 |
228 | # clean dist files
229 | gulp gm:clean
230 |
231 | # clean dist files, including subfolders
232 | gulp gm:clean-deep
233 |
234 | # Generate one developing assets/views files, but not in watching mode
235 | # compile for develop, not watch
236 | gulp gm:compile
237 |
238 | ```
239 |
240 |
241 | ### 2. Watch one special component in development
242 |
243 | * When the project become huge, if we watch all components assets, it will be slow and low efficiency, so we can only watch special component to get better performance
244 |
245 | * Fox example, if we want watch the `home` component:
246 |
247 | ```Shell
248 |
249 | # this will only build and watch `components/home` components
250 | gulp gm:develop -c home
251 |
252 | ```
253 |
254 |
255 | ### 3. Use `React` in gulpman
256 | * Install React: `npm install react react-dom`
257 | * Use React in ES6:
258 |
259 | ```Javascript
260 | import React from 'react';
261 | import ReactDOM from 'react-dom';
262 |
263 | // xxx
264 | ```
265 |
266 |
267 | ### 4. Use `tpl` file in js|es6|jsx
268 |
269 | * Support `.tpl` file, it will be packaged in dist js files.
270 |
271 | * Usage: `import dialogTpl from './dialog.tpl'` or `var dialogTpl = require('./dialog.tpl')`
272 |
273 |
274 |
275 | ### 5. Usge base64 img in HTML/CSS
276 |
277 | * Just add `?_gm_inline` in assets src path in html/css
278 | * The `base64` code will be inlined in html/css
279 |
280 |
281 | ##### html
282 |
283 | ```html
284 |
285 |
286 |
287 | ```
288 |
289 | ##### CSS/SCSS
290 |
291 | ```css
292 |
293 | .test {
294 | background: url(./img/testb64.png?_gm_inline) no-repeat;
295 | }
296 | ```
297 |
298 |
299 | ### 6. Use inlined CSS/JS in html by querystring
300 |
301 | * Like base64, just add `?_gm_inline` in url path
302 |
303 | ```html
304 |
305 |
306 |
307 | ```
308 |
309 | * The inlined sources will be auto updated when source files changed.
310 |
311 |
312 | ### 7. Use Sprite img in css
313 |
314 | * Enable Sprite by `gulpman.config({ enableCSSSprite: true })`, the default is false.
315 | * Based on spritesmith, you can transport usemin opts in gulpman.config.
316 | * More detail about Spritesmith: [https://github.com/Ensighten/spritesmith](https://github.com/Ensighten/spritesmith)
317 | * Usage: In scss file, just add `?_gm_sprite` to img url
318 |
319 | ```css
320 | .demo {
321 | background: url(./img/abc.png?_gm_sprite) no-repeat;
322 |
323 | /* other style you can set ...*/
324 | width: 50px;
325 | height: 50px;
326 | }
327 | ```
328 |
329 | ### 8. Use Usemin
330 |
331 | * You can tranport usemin opts in gulpman.config
332 | * More detail about usemin: [https://github.com/zont/gulp-usemin](https://github.com/zont/gulp-usemin)
333 | * Uage: just add usemin build comments in html. Support `js`|`css`|`inlinejs`|`inlinecss` syntax
334 | * Note: Just write relative path in usemin build comment. Then gulpman can calculate absolute path for assets.
335 | * If you don't write output path, the gulpman will combo one new ouput file name automatically.
336 |
337 |
338 | ```html
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 | ```
351 |
352 |
353 | ### 9. Use js tpl template
354 | * Put the `.tpl` files in your component, and use `require` or `import` in ES6, then the tpl files will be packaged in js files.
355 | * All tpl will be convertd to text string into js files.
356 | * Base64 img and CSS/JS Embed are supported in Tpl
357 |
358 | - import tpl in es6
359 | ```js
360 | import dialogTpl from './dialog.tpl'
361 | ```
362 |
363 | - require
364 | ```js
365 | var dialogTpl = require('./dialog.tpl')
366 | ```
367 |
368 | ### 10. import css files into js/html
369 | - Just import the css, then the gulpman will attach it on page automatically.
370 | ```js
371 | import from './style.css';
372 | ```
373 |
374 | ```js
375 | require('./style.css');
376 | ```
377 |
378 | ### 11. Use iconfont convert svg to fontface
379 | * Convert SVG to icon-font, use `@font-face` in css
380 | * Run `gulp gm:iconfont:install` before first running
381 | * Put the svg files in `components/iconfonts/source` directory, then run `gulp gm:iconfont` to begin start convert
382 | * The icon-font and css will generated in `iconfonts/gmicon` folder
383 |
384 |
385 | ### 12. Support LAB.js to load async js
386 | * Add LAB.js in your project
387 | * Use LAB API to load js, use `relative path`
388 | * Example: `$LAB.script("../testload/test.js").wait(()=>{console.log('test loaded')})`
389 |
390 |
391 | ### 13. Require CSS in JS
392 | * Require css files in your es6/js files
393 | * The CSS contents will be packaged into js files, and automatically injected to html when page opend. Using style tag
394 | * Should keep the .css extname
395 | * Example: `require('./style.css')` or `import style from './style.css'`
396 |
397 |
398 | ### 14. Use karma for Unit Test
399 | * Run `gulp gm:karma:install` before first running, it will install dependencies and generate `karma.conf.js`.
400 | * In your one component folder, create one folder named `spec`, then put your spec es6 files in the `spec` folder, the file extname must be `.es6`
401 | * Run `gulp gm:karma:start` in CLI to start Karma Unit Test, you can view the coverage result in `coverage` foloder
402 | * Set one special spec folder、browsers and other karma options, you can set them in `karma.conf.js`
403 |
404 |
405 |
406 | ### Tutorial
407 | [Tutorial Link](http://karat.cc/article/56a351c3e48d2d05682aa0ac "karat.cc")
408 |
409 | ### License
410 | MIT
411 |
--------------------------------------------------------------------------------
/README_zh-CN.md:
--------------------------------------------------------------------------------
1 |
2 | [](http://karat.cc/article/56a351c3e48d2d05682aa0ac/)
3 |
4 | -----
5 |
6 | [](http://badge.fury.io/js/gulpman)
7 |
8 |
9 |
10 | # gulpman
11 |
12 | [English Document](https://github.com/xunuoi/gulpman/blob/master/README.md)
13 |
14 | - 支持资源模块化组织方式,通过相对路径运算,像百度的FIS一样,可以将`js/css/img/fonts/tpl`按照功能单位组织到同一个目录中,不再分散维护。Gulpman运行时会自动分发各种资源到正确目录。
15 | - 概念介绍: [前端工程之模块化](http://fex.baidu.com/blog/2014/03/fis-module/)
16 | - 基于`gulp`的前端组件化、模块化解决方案,更简单、灵活、可控性高,会gulp就会定制自己的方案
17 | - 支持图片`base64`方式嵌入到`html/CSS`
18 | - 支持`JS/CSS`内联方式嵌入html文件
19 | - 整合`spritesmith`,简单生成sprite雪碧图
20 | - 整合`icon-font`转换,支持svg转换
21 | - 整合`usemin`,构建合并更加灵活强大
22 | - 支持前端js模板嵌入,`tpl`格式的直接构建打包到最终js文件,支持异步加载js
23 | - 集成`SCSS|ES6|ReactJS|Babel|Browserify|cssnano|uglify|imagmein`等常用组件,做到一站式自动化解决方案,同时清晰、可控,定制、修改简单
24 | - 扩展性高,`gulp`现有的插件都可以拼装、加入到`gulpman`中使用,你可以自己根据实际情况组合、修改,比如可以轻松整合`browser-sync`到构建系统中。
25 | - 整合`karma`单元测试框架,适配`babel和es6`的代码单元测试和`coverage`
26 |
27 |
28 |
29 | ## 说明
30 | - 支持Mac、Linux环境下安装、使用
31 | - Windows环境未做完整安装测试,由于安装脚本使用到shell,windows不支持shell,执行完`npm install gulpman --save-dev`后,可能需要手动安装`gulp`、`gulp-sass`模块
32 | - 如果手动安装`gulp-sass`,建议使用淘宝的`cnpm`来完成,避免国内网络导致`npm`安装失败
33 | - Node版本需要不低于4.0.0
34 |
35 |
36 | ## 安装
37 | - `npm install gulpman --save-dev`
38 | - 如果在中国,请使用cnpm安装:`cnpm install gulpman --save-dev`
39 | - 完成后请运行 `gulp gm:install` 来完成安装
40 |
41 | #### 注:
42 | * 如果安装过程中提示 `gulp-sass` 安装失败, 运行 `cnpm install gulp-sass gulp-imagemin` 来修复。
43 |
44 | * 安装中若npm报出目录权限导致的error,比如涉及到`/usr/local/lib/node_modules`权限的报错,请请检查其权限是否正常并用chown来修复,将拥有者修改为当前登录用户即可。
45 | * 可以使用 `sudo chown -R "$(whoami)"`+`路径`来修复
46 | * 不要使用`sudo npm install`来手工安装因为权限问题而失败的模块。请修改权限后,再用`npm install`来安装即可
47 | * 如果你本地node和npm的安装和权限正常,那gulpman的安装过程应该都是顺利和成功的。
48 | * 图片压缩模块imagemin-pngquant需要依赖`libpng-devel`,如果是Linux环境,建议先运行`yum install libpng-devel`来确保安装
49 | * 安装过程中无故退出,请查看`npm-debug.log`,检查是否是内存不足`ENOMEM`导致。
50 |
51 |
52 |
53 | ## 配置
54 |
55 | ### 0. 支持自动默认模式,无需配置即使用
56 |
57 | * 可直接跳过`Config 配置`处的说明,直接去看后面的`Usage 使用`内容
58 |
59 |
60 | ### 1. 配置 gulpfile.js:
61 |
62 | - 只需要require gulpman模块,就会自动加载`gm:publish`, `gm:develop`(开发监视模式)等task到环境中
63 | - 使用时在命令行中直接输入`gulp gm:publish`即可执行gulpman预置的任务
64 |
65 |
66 | ```Javascript
67 | /**
68 | * Gulpfile.js
69 | */
70 |
71 |
72 | var gulp = require('gulp'),
73 | gman = require('gulpman')
74 |
75 | // your other tasks ...你的其他task
76 | // xxx ...
77 |
78 |
79 | /**
80 | * 配置gulpman ======================
81 | * Use config API
82 | * 设置路径、CDN、资源URL前缀等,API简单
83 | */
84 |
85 | gman.config({
86 |
87 | // 是否使用绝对路径,默认值true, 推荐使用,方便服务器配置。比如`/static/home/main.js`这种风格。
88 | // 如果无服务端情况下,本地调试,可以设置is_absolute为false, 那么会是类似`../../assets/static/home/main.js`这种风格
89 | 'is_absolute': true,
90 |
91 | // cdn prefix 配置CDN, 支持[字符串|数组|函数] 3中传参方式
92 | 'cdn_prefix': '',
93 |
94 | // 配置资源URL前缀,建议类似 /static这种
95 | // usually set as /static, this involves the server config ,such as the static path of nginx
96 | 'url_prefix': '/static',
97 |
98 |
99 | /** use spritesmith for css-img sprite
100 | * 基于spritesmith实现, 详细参见https://github.com/Ensighten/spritesmith
101 | * 传递自动生成雪碧图的spritesmit的options
102 | **/
103 | //'spritesmith': { },保持默认即可
104 |
105 | /** usemin config 配置usemin,保持默认即可 **/
106 | // 'usemin': {}
107 |
108 |
109 | // 模块COMPONENTS目录,同一个模块的html和资源文件在一起。默认 'components'即可
110 | 'components': 'components',
111 |
112 | // develop和publish下的views目录,跟服务端框架的views目录配置一致,比如express
113 | 'runtime_views': 'views',
114 | 'dist_views': 'views_dist',
115 |
116 | // develop和publish下的assets静态目录,跟服务器配置有关,比如nginx的static目录指向,请保持与服务器设定一致。支持多级路径设定,比如assets/public
117 | 'runtime_assets': 'assets',
118 | 'dist_assets': 'assets_dist',
119 |
120 | // 第三方JS类库、模块的目录,推荐设置为`lib`或`bower_components`(这样bower可以直接安装到这个目录)
121 | // 这个目录默认打包时为全局模块目录,可以直接`import xxx from 'xxx'`,而不用加相对路径
122 | // the js library dir, set as a global module. Also you can set as bower_components
123 | 'lib': 'lib',
124 |
125 | // 可以添加一个自定的全局模块目录,该目录下的js模块,也作为全局模块来require,不需要相对路径。
126 | // the global module dir
127 | 'global': 'common'
128 | })
129 |
130 |
131 | ```
132 |
133 | ### 2. 如何更好的配置CDN
134 |
135 | * `cdn_prefix`支持 字符串、数组、函数
136 | * 如果传入数组,那么按照随机来分配
137 | * 如果传入函数,函数会获1个参数,`mediaFile`, 就是当前被css或html中引用到的资源文件名,可以根据文件名做cdn分配
138 |
139 | ```Javascript
140 |
141 | 'cdn_prefix': function (fileName) {
142 |
143 | console.log(fileName)
144 |
145 | var c_list = [
146 | 'http://s0.com',
147 | 'http://s1.com',
148 | 'http://s2.com',
149 | 'http://s3.com',
150 | 'http://s4.com'
151 | ]
152 | // 你自可以自实现分配策略
153 | if(hostFile.match(/\.html$/gm)){
154 | return c_list[0]
155 | }else {
156 | return c_list[1]
157 | }
158 | },
159 | ```
160 |
161 | ### 3. 对于`is_absolute`的说明
162 |
163 | * `is_absolute`是指输出的html文件中的资源src/url,否使用绝对路径,默认值true,即启用绝对目录。
164 |
165 | * [常用]当使用服务器配置静态目录的情况下,推荐使用绝对目录。比如配合nginx,指定某个目录为静态资源目录。类似`/static/home/main.js`这种风格。
166 |
167 | * 如果无服务端情况下,有需要本地调试,推荐设置is_absolute为false, 即启用相对路径。类似`../../assets/static/home/main.js`这种风格。
168 |
169 | * 当is_absolute为false(启用相对路径)的情况下,直接打开输出的views目录下的html文件,就可以正常浏览、运行、调试
170 |
171 |
172 |
173 | ### 4. gulpman目录说明
174 |
175 | * 使用gulpman按照模块划分后,模块根目录可以是`./components`(默认,可配置),如果你有个模块是foo,那么应该有如下目录:`./components/foo`,然后跟foo模块相关的`html|js|css|fonts|image`等资源文件都放到`foo`下,这个结构下,做开发时非常清晰、高效,便于模块组织、资源定位等。
176 |
177 | * 通过`gm:develop`命令进入`develop`开发模式后,会自动生成模板`views`目录,和静态资源`assets`目录。
178 |
179 | * 通过`gm:publish`命令来构建发布资源,会自动生成生产环境下的模板目录`views_dist`,和静态资源目录`assets_dist`。
180 |
181 |
182 | ### 5. 什么是全局模块目录:
183 |
184 | - 对应`Browserify`的打包功能,`全局目录`是指可以直接`require`或者`import`其下的js模块的目录
185 |
186 | - `gulpman.config`的配置中,`lib`和`global`都是JS的全局模块目录。举个例子说明:
187 | * 你的`components/lib`目录下有一个模块 `foo.js`,就是: `components/lib/foo.js`,那么你在你的es6文件中,就可以这样使用:`import foo from 'foo'`,不需要写成 `import foo from '../lib/foo'`
188 |
189 | - 同理`global`那个配置也是这样的,推荐将lib目录设置成跟`bower`一致的,全部来存放第三方类库,而`global`设置的目录,比如叫`common`,可以存放自己的`公用模块`。这样开发会更加灵活、方便。
190 |
191 | - 注意全局模块不要有同名冲突。
192 |
193 |
194 | ### 6. 支持复杂目录和多级目录设定
195 |
196 | * 比如下面这种复杂路径:
197 |
198 | ```Javascript
199 | gulpman.config({
200 | 'is_absolute': false,
201 | 'components': 'components/cc',
202 | 'runtime_views': 'runtime_views/rv',
203 | 'dist_views': 'dist_views/dv/dv',
204 |
205 | 'dist_assets': 'dist_assets/da',
206 | 'runtime_assets': 'runtime_assets/ra/ra',
207 | })
208 | ```
209 |
210 |
211 | ## Usage 使用
212 |
213 | ### 1. CLI 执行Task:
214 |
215 | ```Shell
216 |
217 | # 初始化目录,建立components目录并添加一份html的demo文件
218 | # init components dir and a html demo
219 | gulp gm:init
220 |
221 |
222 | # develop and watch 开发模式,监视相关文件变动,增量更新
223 | gulp gm:develop
224 |
225 | # 指定编译和监视某个component, 提高性能和效率(其他文件不编译输出)
226 | gulp gm:develop -c component_name1,component_name2,component_name3...
227 |
228 |
229 | # publish 发布资源,包括合并、压缩资源、rev产生MD5等
230 | gulp gm:publish
231 |
232 | # publish命令支持`-a`和`-v`参数指定输出资源/模板目录(可选)
233 | gulp gm:publish -v your_views_dist -a your_assets_dist
234 |
235 | # clean 清理构建输出的目录和文件
236 | gulp gm:clean
237 |
238 | # clean 清理构建输出的目录和文件,包括自文件夹/目录
239 | gulp gm:clean-deep
240 |
241 | # 编译输出一份运行时资源文件,但是不进入监视状态
242 | # compile for develop, not watch
243 | gulp gm:compile
244 |
245 | ```
246 |
247 |
248 | ### 2. 开发中只监视某个component目录
249 |
250 | * 随着项目变大,开发中如果全局监视所有component资源,效率将会降低,因此可使用gulpman提供的监视子component的方式来开发,提高性能
251 |
252 | * 比如说,只监视components目录下的home模块:
253 |
254 | ```Shell
255 | # this will only watch `components/home` components
256 | gulp gm:develop -c home
257 |
258 | ```
259 |
260 |
261 | ### 3. 如何在gulpman下使用React
262 | * 安装React: `npm install react react-dom`
263 | * 在ES6文件中使用
264 |
265 | ```Javascript
266 | import React from 'react';
267 | import ReactDOM from 'react-dom';
268 |
269 | // xxx
270 | ```
271 |
272 |
273 | ### 4. 如何在js|es6|jsx中使用tpl模板
274 |
275 | * 目前支持.tpl扩展名的模板文件,直接打包到最终的js文件中
276 |
277 | * 用法:`import dialogTpl from './dialog.tpl'` 或者 `var dialogTpl = require('./dialog.tpl')`
278 |
279 |
280 |
281 | ### 5. 如何在HTML/CSS中嵌入base64编码的图片
282 |
283 | * 只需要图片资源后面添加`?_gm_inline`即可
284 | * 打包时候会将图片生成`base64`编码替换到到html中
285 |
286 |
287 | ##### html
288 |
289 | ```html
290 |
291 |
292 |
293 | ```
294 |
295 | ##### CSS/SCSS
296 |
297 | ```css
298 |
299 | .test {
300 | background: url(./img/testb64.png?_gm_inline) no-repeat;
301 | }
302 | ```
303 |
304 | ### 6. 如何在HTML中嵌入内联CSS/JS
305 |
306 | * 类似图片base64,只需要资源后面添加`?_gm_inline`即可
307 |
308 | ```html
309 |
310 |
311 |
312 | ```
313 |
314 | * 注:所有内嵌嵌入的资源,包括图片/JS/CSS,在develop(监视)模式下,都已自动关联更新。即如果a.html文件中,内联嵌入了一个b.css,如果b.css发生了修改,那么a.html会自动编译更新。
315 |
316 |
317 | ### 7. 如何使用Sprite雪碧图
318 |
319 | * 通过配置启用CSS Sprite `gulpman.config({ enableCSSSprite: true })` 默认false不启用
320 | * 基于spritesmith实现,在gulpman.config 中可传入spritesmith配置opts
321 | * 关于spritesmith详细参见:[https://github.com/Ensighten/spritesmith](https://github.com/Ensighten/spritesmith)
322 | * 只需要在scss文件中的图片url资源后面添加`?_gm_sprite`即可
323 |
324 | ```css
325 | .demo {
326 | background: url(./img/abc.png?_gm_sprite) no-repeat;
327 |
328 | /* other style you can set ...*/
329 | width: 50px;
330 | height: 50px;
331 | }
332 | ```
333 |
334 | ### 8. 如何使用Usemin
335 |
336 | * 整合usemin,在gulpman.config 中可传入usemin的配置opts
337 | * 关于usemin详细参见:[https://github.com/zont/gulp-usemin](https://github.com/zont/gulp-usemin)
338 | * 只需要在html文件中添加usemin的build注释即可。支持`js`|`css`|`inlinejs`|`inlinecss`等语法
339 | * 注意build注释中配置的输出路径写相对路径即可,跟script、link等标签类似,gulpman会自动转换成最终输出路径
340 |
341 | ```html
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 | ```
354 |
355 |
356 | ### 9. 如何使用前端js模板
357 | * 支持tpl扩展名,放到components相关目录下即可,js 可以直接require或者import
358 | * 最终会作为字符串格式打包进js
359 | * tpl中仍然支持资源嵌入和图片base64等,如参照前面_gm_inline等语法即可
360 |
361 | - import到es6中
362 | ```js
363 | import dialogTpl from './dialog.tpl'
364 | ```
365 |
366 | - 或者使用require语法
367 | ```js
368 | var dialogTpl = require('./dialog.tpl')
369 | ```
370 |
371 | ### 10. 引入css文件到js/html
372 | - 直接import即可,gulpman会自动加载到html页面中.
373 | ```js
374 | import from './style.css';
375 | ```
376 |
377 | ```js
378 | require('./style.css');
379 | ```
380 |
381 |
382 | ### 11. 使用iconfont转换
383 | * 可以将svg转换成icon-font,用`@font-face`方式引用
384 | * 初次使用先安装,运行`gulp gm:iconfont:install`
385 | * 将svg文件放到`components/iconfonts/source`目录下,运行`gulp gm:iconfont`即可
386 | * 自动生成的icon-font和css文件将会在`iconfonts/gmicon`目录下
387 |
388 |
389 | ### 12. 支持LAB.js来完成异步加载js
390 | * 引入LAB.js到项目中
391 | * 使用LAB的api来加载即可,使用相对路径
392 | * 代码用例: `$LAB.script("../testload/test.js").wait(()=>{console.log('test loaded')})`
393 |
394 |
395 |
396 | ### 13. Require CSS in js
397 | * 直接在js中require你的css文件(源文件时scss文件)
398 | * The CSS contents will be packaged into js files, and automatically injected to html when page opend. Using style tag
399 | * 使用时要确保添加 .css 扩展名
400 | * 举例: `require('./style.css')` or `import style from './style.css'`
401 |
402 |
403 | ### 14. 如何启用karma单元测试
404 | * 初次使用先安装,运行`gulp gm:karma:install`,会安装依赖和生成`karma.conf.js`文件
405 | * 在您的components中的对应模块目录下,建立一个spec文件夹,将对应的spec文件放在里面,文件拓展名是.es6
406 | * 运行 `gulp gm:karma:start` 来启动单元测试(watch模式),将会运行各spec文件,完成后可在生成的coverage文件夹中查看覆盖率结果
407 | * 指定spec目录、browsers等karma的选项,可以在`karma.conf.js`中设置、定制等
408 |
409 |
410 |
411 | ### 教程
412 | [浏览教程链接](http://karat.cc/article/56a351c3e48d2d05682aa0ac "karat.cc")
413 |
414 | ### License
415 | MIT
416 |
--------------------------------------------------------------------------------
/assets/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["es2015", "react", "stage-3"]
3 | }
--------------------------------------------------------------------------------
/assets/build.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xunuoi/gulpman/d12eb0fa1c71a955f98d2c4bb7090540a518dd7a/assets/build.png
--------------------------------------------------------------------------------
/assets/build.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/assets/coverage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xunuoi/gulpman/d12eb0fa1c71a955f98d2c4bb7090540a518dd7a/assets/coverage.png
--------------------------------------------------------------------------------
/assets/coverage.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xunuoi/gulpman/d12eb0fa1c71a955f98d2c4bb7090540a518dd7a/assets/logo.png
--------------------------------------------------------------------------------
/karma/karma.conf.js:
--------------------------------------------------------------------------------
1 | var stringify = require('stringify');
2 |
3 | var ignore_files = '**/lib/**',
4 | spec_files = '**/spec/**',
5 | tpl_files = '**/*.tpl',
6 | node_modules_files = '**/node_modules/**';
7 |
8 |
9 | var babelOpts = {
10 | presets: ['es2015', 'react'],
11 | // sourceMap: 'inline',
12 | ignore: [node_modules_files, ignore_files, tpl_files]
13 | }
14 |
15 | module.exports = function(config) {
16 | config.set({
17 | basePath: '',
18 | frameworks: [ 'browserify', 'jasmine' ],
19 | files: [
20 | "./components/**/*.es6",
21 | ],
22 | browsers: ['Chrome'],
23 | preprocessors: {
24 | "./components/**/*.es6": ['browserify']
25 | },
26 |
27 | browserify: {
28 | debug: true,
29 | paths: ['./components/lib'],
30 |
31 | transform: [
32 | stringify(['.tpl', '.txt']),
33 |
34 | ["babelify", babelOpts],
35 |
36 | ['browserify-istanbul', {
37 | instrumenter: require('babel-istanbul'),
38 | instrumenterConfig: {
39 | // embedSource: true,
40 | babel: babelOpts,
41 | },
42 | ignore: [
43 | spec_files,
44 | tpl_files,
45 | node_modules_files,
46 | ignore_files
47 | ],
48 | }]
49 | ],
50 | extensions: ['.es6', '.jsx', '.js']
51 | },
52 | // logLevel: config.LOG_DEBUG,
53 | reporters: ['progress', 'coverage'],
54 | coverageReporter: {
55 | type : 'html',
56 | dir : './coverage'
57 | },
58 | // if true, Karma captures browsers, runs the tests and exits
59 | singleRun: false
60 |
61 | });
62 | };
--------------------------------------------------------------------------------
/lib/assetsPathParser.js:
--------------------------------------------------------------------------------
1 | /**
2 | * For path replace into abs path
3 | */
4 |
5 | 'use strict'
6 |
7 |
8 | var through = require('through2'),
9 | path = require('path'),
10 | j = path.join,
11 |
12 | gmutil = require('./gmutil')
13 |
14 | /*
15 | var ct = ';saasdfasf url()\n\r background: url ( "./img/1.png?_gm_inline&sd=32" ) no-repeat; \n\t; .d{ background-image: url(sss.png?_gm_sprite ) }'*/
16 |
17 | var cssUrlReg = /url\s*\(\s*['"]?(.+?)['"]?\s*\)/gm
18 |
19 |
20 | var opts = {}
21 |
22 |
23 | function parseCSS(content, file){
24 | var tList = content.match(cssUrlReg)
25 |
26 | if(tList){
27 | tList.forEach(t=>{
28 |
29 | var url = t.replace(/[\n\r\b\t\s'"]+/gm, '').replace(/^url\(/gm, '').replace(/\)$/gm, '')
30 |
31 | // 如果是相对路径,那么替换
32 | if(gmutil.isUrl('relative', url) ){
33 |
34 | var baseDir = j(opts['cwd'], opts['static_dir'])
35 |
36 | // gmutil.alert('Base: '+baseDir)
37 | var fileRelativeDirOfComponents = path.relative(baseDir, file.path)
38 |
39 |
40 | // var hostFileAbsPath = j()
41 | var relativeDir = path.dirname(fileRelativeDirOfComponents)
42 |
43 | // gmutil.alert('relativeDir: '+relativeDir)
44 |
45 | var mediaRelPath = j(relativeDir, url)
46 |
47 | // gmutil.alert('mediaRelPath: '+mediaRelPath)
48 |
49 | var absUrl = j(opts['url_prefix'], mediaRelPath)
50 |
51 | // gmutil.alert('absUrl: '+absUrl)
52 |
53 | var tarStr = 'url('+absUrl+')'
54 |
55 | content = content.replace(t, tarStr)
56 | }
57 |
58 | })
59 | }
60 |
61 | return content
62 | }
63 |
64 |
65 | function parseTpl(conf, contents, file){
66 |
67 | let _opts = conf['_opts'],
68 | basepath = conf['basepath'],
69 | _isRuntimeDir = conf['_isRuntimeDir'],
70 | all_raw_source_reg = conf['all_raw_source_reg'],
71 |
72 | fdirname = path.dirname(file.relative),
73 | _urlPrefix // set assets url prefix
74 |
75 |
76 | if(_opts['is_absolute']) {
77 | _urlPrefix = _opts['url_prefix']
78 | }else {
79 | // 判断打包资源中的url路径前缀
80 | let _fPath = j(_isRuntimeDir ? _opts['runtime_views'] : _opts['dist_views'], fdirname)
81 |
82 | let _staticPath = _isRuntimeDir ? _opts['runtime_static'] : _opts['dist_static']
83 |
84 | _urlPrefix = path.relative(_fPath, _staticPath)
85 | }
86 |
87 |
88 | // 所有格式都要处理
89 | let srcQuoteReg = new RegExp('(?=[\'"]?)([\\w\\.\\-\\?\\-\\/\\:]+?(\\.('+all_raw_source_reg+')))(?=\\?_gm_inline)?(?=[\'"]?)', 'gm')
90 | // httpReg = /^http(s)?\:/
91 |
92 |
93 | let tmp_rs_list = [],
94 | rs_list = []
95 |
96 | // 提取单标签和双标签
97 | tmp_rs_list = tmp_rs_list
98 | .concat(contents.match(gmutil.reg['tagMedia']))
99 | .concat(contents.match(gmutil.reg['closeTagMedia']))
100 |
101 | // 首先提取标签,然后从标签中提取href或者src
102 | tmp_rs_list.length && (
103 | rs_list = tmp_rs_list
104 | .filter(r=>(r && r.match(srcQuoteReg)))
105 | .map(v=>v.match(srcQuoteReg)[0])
106 | .filter(r=>{
107 | // remove the http:xxx.com/xx and base64 data url
108 | // 只处理相对路径
109 | // 不处理绝对路径、http、dataURL
110 | return gmutil.isUrl('relative', r)
111 | })
112 | .filter(r=>!r.match(/^(['"]\/)/gm))
113 | )
114 |
115 | // 这里利用set做去重
116 | let rs_set = new Set(rs_list),
117 | srcPrefix = j(_urlPrefix, fdirname)
118 |
119 | // 替换url的的path和前缀
120 | rs_set.size && rs_set.forEach(epath=>{
121 | // 对于base64的参数标识要保留,不能清理掉,因为后续要嵌入base64
122 | let innerReg = new RegExp('(?=[\'"]?)('+epath+')(\\?_gm_inline)*(?=[\'"]?)', 'gm')
123 |
124 | contents = contents.replace(innerReg, j(srcPrefix, epath)+'$2')
125 | })
126 |
127 | // dealing with usemin build mark syntax
128 | // when in publish, not runtime-dir
129 | if(!_isRuntimeDir) {
130 | // 这里处理usemin 的build的注释内容
131 | contents = gmutil.replaceBuildBlock(contents, srcPrefix)
132 | }
133 |
134 | return contents
135 | }
136 |
137 |
138 | function parseJS(conf, contents, file){
139 |
140 | let _opts = conf['_opts'],
141 | basepath = conf['basepath'],
142 | _isRuntimeDir = conf['_isRuntimeDir'],
143 | all_raw_source_reg = conf['all_raw_source_reg'],
144 |
145 | fdirname = path.dirname(file.relative),
146 | _urlPrefix // set assets url prefix
147 |
148 | if(_opts['is_absolute']) {
149 | _urlPrefix = _opts['url_prefix']
150 | }else {
151 | // 判断打包资源中的url路径前缀
152 | let _fPath = j(_isRuntimeDir ? _opts['runtime_views'] : _opts['dist_views'], fdirname)
153 |
154 | let _staticPath = _isRuntimeDir ? _opts['runtime_static'] : _opts['dist_static']
155 |
156 | _urlPrefix = path.relative(_fPath, _staticPath)
157 | }
158 |
159 | // for all src "xxx.yy" format path
160 | let srcQuoteReg = new RegExp('(?=[\'"]?)([\\w\\.\\-\\?\\-\\/\\:]+?(\\.('+all_raw_source_reg+')))(?=\\?_gm_inline)?(?=[\'"]?)', 'gm')
161 | // httpReg = /^http(s)?\:/
162 |
163 | let tmp_rs_list = [],
164 | rs_list = []
165 |
166 | // 提取单标签和双标签
167 | tmp_rs_list = tmp_rs_list
168 | .concat(contents.match(gmutil.reg['requireAsync']))
169 | .concat(contents.match(gmutil.reg['jsAsyncLoad']))
170 |
171 | // 首先提取标签,然后从标签中提取href或者src
172 | tmp_rs_list.length && (
173 | rs_list = tmp_rs_list
174 | .filter(r=>(r && r.match(srcQuoteReg)))
175 | .map(v=>v.match(srcQuoteReg)[0])
176 | .filter(r=>{
177 | // remove the http:xxx.com/xx and base64 data url
178 | // 只处理相对路径
179 | // 不处理绝对路径、http、dataURL
180 | return gmutil.isUrl('relative', r)
181 | })
182 | .filter(r=>!r.match(/^(['"]\/)/gm))
183 | )
184 |
185 | // 这里利用set做去重
186 | let rs_set = new Set(rs_list),
187 | srcPrefix = j(_urlPrefix, fdirname)
188 |
189 | // 替换url的的path和前缀
190 | rs_set.size && rs_set.forEach(epath=>{
191 | // 对于base64的参数标识要保留,不能清理掉,因为后续要嵌入base64
192 | let innerReg = new RegExp('(?=[\'"]?)('+epath+')(\\?_gm_inline)*(?=[\'"]?)', 'gm')
193 |
194 | contents = contents.replace(innerReg, j(srcPrefix, epath)+'$2')
195 | })
196 |
197 | // dealing with usemin build mark syntax
198 | // when in publish, not runtime-dir
199 | if(!_isRuntimeDir) {
200 | // 这里处理usemin 的build的注释内容
201 | contents = gmutil.replaceBuildBlock(contents, srcPrefix)
202 | }
203 |
204 | return contents
205 | }
206 |
207 |
208 | function _absolutizePath(_opts){
209 |
210 | opts = Object.assign(opts, _opts)
211 |
212 | return through.obj(function(file, enc, cb){
213 |
214 | if (file.isNull()) {
215 | this.push(file);
216 | return cb()
217 | }
218 | if (file.isStream()) {
219 | gmutil.error('*PathParser Error: Streaming not supported')
220 | return cb()
221 | }
222 |
223 | var fileType = path.extname(file.path).slice(1)
224 |
225 | if(opts['is_absolute']){
226 | var content = file.contents.toString()
227 |
228 | if(fileType == 'css'){
229 | var rc = parseCSS(content, file)
230 | }else if(fileType == 'tpl'){
231 | var rc = parseTpl(opts, content, file)
232 | }else if(fileType == 'js' || fileType == 'es6'){
233 | var rc = parseJS(opts, content, file)
234 | }else{
235 | throw Error("Unknown Type: "+fileType)
236 | }
237 |
238 | file.contents = new Buffer(rc)
239 |
240 | }
241 |
242 | // gmutil.error(file.base)
243 | // gmutil.error(file.relative)
244 | // this will dest in right path
245 | if(fileType != 'js' && fileType != 'es6') {
246 | file.base = opts['cwd']
247 | }
248 |
249 | this.push(file)
250 | return cb()
251 | })
252 | }
253 |
254 |
255 |
256 | exports.absolutizePath = _absolutizePath
257 |
--------------------------------------------------------------------------------
/lib/base64.js:
--------------------------------------------------------------------------------
1 | /**
2 | * FOR BASE 64 UTILS
3 | */
4 |
5 | var path = require('path'),
6 | j = path.join,
7 | fs = require('fs'),
8 | gutil = require('gulp-util'),
9 | through = require('through2')
10 |
11 |
12 | var store = require('./store'),
13 | gmutil = require('./gmutil')
14 |
15 |
16 | var bError = null
17 |
18 | var opts
19 |
20 | const PLUGIN_NAME = 'Base64'
21 |
22 |
23 | function purifyUrlPrefix(str){
24 | return str.replace(opts['url_prefix'], '');
25 | }
26 |
27 | function purify(str){
28 | return str.split('?')[0]
29 | // return str.replace(/\?_gm_inline/gm, '')
30 | }
31 |
32 |
33 | function parseSource(images, file, refType, content, baseDir){
34 |
35 | var fileDir = path.dirname(file.relative)
36 |
37 | var status = true
38 |
39 |
40 | // gmutil.alert('debug: '+fileDir)
41 |
42 | images.forEach(function(item) {
43 |
44 | // remove url() in css
45 | var imageURL = item
46 | .replace(/\(|\)|\'/g, '')
47 | .replace(/^url/g, '')
48 |
49 | // 这里路经计算,需要后续优化
50 | // 现在相对路径计算繁琐了
51 | var pureFilePath;
52 |
53 | // console.log('item:', item)
54 | // // 如果url是相对路径,那么解析
55 | // if(!gmutil.isUrl('relative', imageURL)){
56 | // // imageURL = imageURL.replace(opts['url_prefix'], '')
57 | // }
58 |
59 | if(refType == 'css'){
60 | if(opts['isDevelop']){
61 | file.base = opts['components']
62 | fileDir = path.dirname(file.relative)
63 | }
64 |
65 | pureFilePath = j(
66 | file.cwd,
67 | baseDir,
68 | fileDir,
69 | imageURL
70 | )
71 |
72 | // html or other source
73 | }else {
74 |
75 | var srcPath = purify(j(file.cwd, opts['views'], fileDir, imageURL))
76 |
77 | // 输出资源在HMTL是相对路径情况下
78 | if(opts['is_absolute'] === false){
79 |
80 | // develop模式下
81 | if(opts['isDevelop']){
82 |
83 | pureFilePath = srcPath
84 |
85 | }else {
86 | // publish 模式下
87 |
88 | var dist_assets_path = j(file.cwd, opts['dist_assets']),
89 | runtime_assets_path = j(file.cwd, baseDir)
90 |
91 | pureFilePath = srcPath.replace(dist_assets_path, runtime_assets_path)
92 |
93 | }
94 |
95 | // 绝对路径情况下,比如/static/home/main.css
96 | }else {
97 |
98 | pureFilePath = j(baseDir, imageURL)
99 | }
100 |
101 | // remove url_prefix
102 | pureFilePath = purifyUrlPrefix(pureFilePath)
103 |
104 | }
105 |
106 | // 如果url是绝对路径,那么解析
107 | // }else {
108 |
109 | // }
110 |
111 |
112 | // remove base64 params
113 | pureFilePath = purify(pureFilePath)
114 | // gmutil.warn('pureFilePath: \n\n\n'+pureFilePath+'\n\n')
115 |
116 | // check if exist
117 | try {
118 | var filepath = fs.realpathSync(pureFilePath);
119 | }catch(err){
120 |
121 | bError = err
122 |
123 | gmutil.error(err['message'])
124 | gmutil.error('\n*Check Your Component: '+fileDir)
125 |
126 | status = false
127 |
128 | return false
129 | }
130 |
131 | var extname = purify(path.extname(imageURL).slice(1))
132 |
133 | var imageContent = new Buffer(fs.readFileSync(filepath)).toString('base64')
134 |
135 | content = content.replace(
136 | item,
137 | 'data:image/' +
138 | extname.toLowerCase() +
139 | ';base64,' +
140 | imageContent
141 | )
142 |
143 | // generate json file of relevance
144 | store.save(filepath, gmutil.convertSource(file.path, refType))
145 | gmutil.log('*Convert to Base64: ' + filepath, 'green')
146 | })
147 |
148 |
149 | if(status) {
150 | return content
151 | }else {
152 | return false
153 | }
154 | }
155 |
156 |
157 |
158 | function toBase64(_opts) {
159 | opts = _opts || {}
160 |
161 | var rule = opts.rule || /url\([^\)]+\)/g
162 |
163 | var refType = opts.type || 'css',
164 | baseDir = opts.baseDir || './'
165 |
166 | opts['dist_assets'] || (opts['dist_assets'] = '')
167 |
168 | return through.obj(function (file, enc, cb) {
169 | if (file.isNull()) {
170 | this.push(file)
171 | return cb()
172 | }
173 |
174 | if (file.isStream()) {
175 | this.emit('error', new gutil.PluginError(PLUGIN_NAME, 'Streaming not supported'))
176 | return cb()
177 | }
178 |
179 | var content = file.contents.toString()
180 | var images = content.match(rule)
181 |
182 | if(images){
183 | content = parseSource(images, file, refType, content, baseDir, this)
184 |
185 | // 如果出现错误返回了false
186 | if(content === false){
187 | var errMes = 'File Not Exist'
188 |
189 | if(bError){
190 | errMes = bError['message']
191 | }
192 |
193 | this.emit('error', new gutil.PluginError(PLUGIN_NAME, errMes))
194 | }else {
195 | file.contents = new Buffer(content)
196 | }
197 |
198 |
199 | }
200 |
201 | this.push(file)
202 | cb()
203 | })
204 | }
205 |
206 | module.exports = toBase64;
--------------------------------------------------------------------------------
/lib/cdnProxy.js:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * FOR CDN PREFIX CONFIG
4 | *
5 | * FIX gulp-rev-all and revReplace about `prefix`
6 | */
7 |
8 | /**
9 | * Another Proxy code in revReplace.js,
10 | * include random url of list and function
11 | */
12 |
13 |
14 | var gmutil = require('./gmutil')
15 |
16 |
17 | function proxyPrefix(obj){
18 | // fix prefix options for gulp-rev-all
19 | // 注意: 这了可能会干预到rev-replace里的变量
20 |
21 | obj['cdn_prefix'] = obj['cdn_prefix'] || ''
22 | obj['_prefix'] = obj['cdn_prefix']
23 |
24 |
25 | // fix array
26 | if(obj['cdn_prefix'] instanceof Array){
27 |
28 | // console.log('Array: \n', obj['cdn_prefix'])
29 |
30 | function _getRandPrefixFromList(){
31 | return obj['_prefix'][gmutil.randomNum(0, obj['_prefix'].length-1)]
32 | }
33 |
34 | // rewrite replace of array
35 | obj['cdn_prefix'].replace = function(a, b){
36 |
37 | var p = _getRandPrefixFromList().replace(a, b)
38 |
39 | return p
40 | }
41 |
42 | // rewrite toString of array
43 | obj['cdn_prefix'].toString = function(){
44 |
45 | return _getRandPrefixFromList()
46 | }
47 |
48 |
49 | }else if(obj['cdn_prefix'] instanceof Function){
50 |
51 | // !! only for gulp-rev-all
52 | obj['transformPath'] = function (rev, source, file) {
53 |
54 | return obj['_prefix'](source, rev, file)+rev
55 |
56 | // on the remote server, image files are served from `/images`
57 | // return rev.replace('/img', '/images')
58 | }
59 |
60 |
61 | }else if(typeof obj['cdn_prefix'] == 'string'){
62 |
63 | // no handle
64 | // obj['_all_prefix'].add(obj['cdn_prefix'])
65 |
66 | }else {
67 | throw Error('Unknown Type: '+ (typeof obj['cdn_prefix']))
68 | }
69 |
70 |
71 | return obj
72 |
73 | }
74 |
75 |
76 | exports.proxyPrefix = proxyPrefix
--------------------------------------------------------------------------------
/lib/gmutil.js:
--------------------------------------------------------------------------------
1 | /**
2 | * FOR UTILS
3 | */
4 |
5 | 'use strict'
6 |
7 |
8 | var colors = require('colors'),
9 | path = require('path'),
10 | j = path.join
11 |
12 |
13 | function _log (str, color) {
14 |
15 | str += ''
16 |
17 | var color = color || 'blue'
18 |
19 | console.log(str[color])
20 | }
21 |
22 | function _error (str){
23 |
24 | return _log(str, 'red')
25 | }
26 |
27 | function _alert(str) {
28 | return _log(str, 'red')
29 | }
30 |
31 | function _tip (str){
32 |
33 | return _log(str, 'green')
34 | }
35 |
36 | function _warn (str){
37 |
38 | return _log(str, 'yellow')
39 | }
40 |
41 |
42 | /**
43 | * Returns a random number between min (inclusive) and max (exclusive)
44 | */
45 | function getRandomArbitrary(min, max) {
46 | return Math.random() * (max - min) + min;
47 | }
48 |
49 | /**
50 | * Returns a random integer between min (inclusive) and max (inclusive)
51 | * Using Math.round() will give you a non-uniform distribution!
52 | */
53 | function randomNum(min, max) {
54 | return Math.floor(Math.random() * (max - min + 1)) + min;
55 | }
56 |
57 |
58 | function byLongestUnreved(a, b) {
59 | return b.unreved.length - a.unreved.length;
60 | }
61 |
62 |
63 | function pathInAssets(_cwd, fpath, componentsDir, runStaticDir){
64 | var componentsAbsPath = j(_cwd, componentsDir),
65 | imgRelPath = fpath.replace(componentsAbsPath, ''),
66 | imgAbsPath = j(_cwd, runStaticDir, imgRelPath)
67 |
68 | return imgAbsPath
69 | }
70 |
71 |
72 | function validateObj(obj){
73 | var a
74 | for(a in obj){
75 | if(obj.hasOwnProperty(a) && obj[a] === undefined) {
76 | delete obj[a]
77 | }
78 | }
79 |
80 | return obj
81 | }
82 |
83 | function isArray(o) {
84 | return Object.prototype.toString.call(o) === '[object Array]';
85 | }
86 |
87 |
88 | function convertSource(rawSource, refType){
89 | let tarType
90 |
91 | if(refType == 'css'){
92 | tarType = 'scss'
93 | }
94 |
95 | var repReg = new RegExp('\\.'+refType+'$', 'g'),
96 | rsList = []
97 |
98 | if(!rawSource.match(repReg)) {
99 |
100 | return rawSource
101 |
102 | }
103 |
104 | if(typeof tarType == 'string'){
105 | return rawSource.replace(repReg, '.'+tarType)
106 |
107 | }else {
108 | return rawSource
109 | }
110 |
111 | }
112 |
113 |
114 | function isUrl(urlType, str){
115 | var _d = {
116 | 'absolute': /^\//g,
117 | 'http': /^http(s)?\:/g,
118 | 'dataURL': /^data\:/g,
119 | }
120 |
121 | var t = _d[urlType]
122 |
123 | if(urlType == 'relative'){
124 | return !isUrl('absolute', str) &&
125 | !isUrl('http', str) &&
126 | !isUrl('dataURL', str)
127 | }
128 |
129 | if(!t){
130 | throw Error('Unknow Type: '+t)
131 | }
132 |
133 | return str.match(_d[urlType])
134 | }
135 |
136 | function joinUrl (a, b){
137 | if(!b.match(/\/$/g)) {
138 | b = b + '/'
139 | }
140 |
141 | if(!a.match(/\/$/g) && !b.match(/^\//g)) {
142 | return a + '/' + b;
143 | }else if(a.match(/\/$/g) && b.match(/^\//g)){
144 |
145 | return a.replace(/\/$/g, '') + b;
146 | }else{
147 | return a + b;
148 | }
149 |
150 | }
151 |
152 |
153 | function replaceBuildBlock(content, srcPrefix) {
154 |
155 | var startReg = //gim;
156 | var endReg = //gim;
157 |
158 |
159 | var sections = content.split(endReg)
160 |
161 | sections.forEach((e, i)=>{
162 | var block
163 |
164 | if( (block = e.match(startReg)) && (block = block[0])){
165 | var section = e.split(startReg)
166 | // var block = e.match(startReg)[0]
167 | var outputPathParam = section[4];
168 | if(!outputPathParam) {
169 | // not set output path in usemin, build:js/css
170 | var srcStr = section[5]
171 | var doExec = true
172 | var comboNameList = []
173 | var comboExtFileName
174 |
175 | while(doExec) {
176 | let oneFile = _reg['sourceUrl'].exec(srcStr)
177 | let ofname
178 | if(oneFile && (ofname = oneFile[2])){
179 | let oneFileName = path.basename(ofname);
180 | let extFileName = path.extname(ofname)
181 | if(!comboExtFileName) {
182 | comboExtFileName = extFileName
183 | }
184 |
185 | comboNameList.push(oneFileName.replace(extFileName, ''))
186 | }else {
187 | doExec = false
188 | }
189 | }
190 | if(!comboExtFileName) {
191 | comboExtFileName = '.unknown'
192 | _warn('*Found Unknown Extname, check your assets files!')
193 | }
194 | // add 80 as max combo name length
195 | var comboNameStr = comboNameList.join('_').slice(0, 80) + comboExtFileName
196 | var outputPathParam = comboNameStr.split('?')[0]
197 | _warn('*Not set build file name, use combo name: ' + outputPathParam)
198 | // _error(outputPathParam)
199 | }
200 | var newOutPath = j(srcPrefix, outputPathParam)
201 |
202 | // _alert('Usemin Build: '+newOutPath)
203 |
204 | // section[2]: alternative search path
205 | // section[3]: nameInHTML: section[3]
206 | // section[4]: relative out path
207 |
208 | content = content.replace(block, '')
209 |
210 | }
211 | })
212 |
213 |
214 | return content
215 |
216 | }
217 |
218 |
219 | // source reg
220 | var _reg = {
221 | link: new RegExp('[\\s\\S]*?<*\\/*>*', 'gi'),
222 | img: new RegExp('
[\\s\\S]*?<*\\/*>*', 'gi'),
223 |
224 | href: new RegExp('\\s*(href)=["\']+([\\s\\S]*?)["\']'),
225 | style:new RegExp('';
102 | resolve();
103 | }.bind(this));
104 | }
105 | else if (block.type == 'htmlimport') {
106 | pipeline(block.name, block.files, block.tasks, function(name, file) {
107 | _fixFilePath(name, file);
108 | push(file);
109 | html[i] += '';
110 | resolve();
111 | }.bind(this, block.nameInHTML));
112 | }
113 | });
114 | });
115 |
116 | Promise.all(promises).then(function() {
117 | var createdFile = createFile(name, html.join(''));
118 | pipeline(createdFile.path, [createdFile], options && options['html'], function(file) {
119 | callback(null, file);
120 | });
121 | });
122 | };
123 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/lib/pipeline.js:
--------------------------------------------------------------------------------
1 | module.exports = function(name, files, tasks, push) {
2 | var through = require('through2');
3 | var concat = require('gulp-concat')(name || 'filename.temp', {newLine: '\n'});
4 |
5 | /* PREPARE TASKS */
6 | tasks = (tasks || []).slice();
7 |
8 | var concatIndex = tasks.indexOf('concat');
9 | if (concatIndex == -1)
10 | tasks.unshift(concat);
11 | else
12 | tasks[concatIndex] = concat;
13 |
14 | tasks.push(through.obj(function(file, enc, streamCallback) {
15 | streamCallback(null, file);
16 | push(file);
17 | }));
18 |
19 | /* PREPARE TASKS END */
20 |
21 | var stream = through.obj(function(file, enc, streamCallback) {
22 | streamCallback(null, file);
23 | });
24 | var newStream = stream;
25 | tasks.forEach(function(task) {
26 | newStream = newStream.pipe(typeof(task) == 'function' ? task(): task);
27 | });
28 |
29 | files.forEach(stream.write.bind(stream));
30 | stream.end();
31 | };
32 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "gulp-usemin",
3 | "version": "0.3.23",
4 | "description": "Replaces references to non-optimized scripts or stylesheets into a set of HTML files (or any templates/views).",
5 | "main": "index.js",
6 | "dependencies": {
7 | "gulp-util": "~2.2.14",
8 | "through2": "~0.5.1",
9 | "glob": "~4.0.4",
10 | "gulp-concat": "~2.4.1"
11 | },
12 | "devDependencies": {
13 | "event-stream": "~3.1.0",
14 | "vinyl-fs": "~2.3.1",
15 | "gulp": "~3.8.6",
16 | "gulp-jshint": "~1.7.0",
17 | "gulp-mocha": "~0.5.1",
18 | "gulp-uglify": "~0.3.1",
19 | "gulp-minify-html": "~0.1.1",
20 | "gulp-minify-css": "~0.3.0",
21 | "gulp-rev": "~0.4.2",
22 | "gulp-less": "2.0.1"
23 | },
24 | "scripts": {
25 | "test": "gulp"
26 | },
27 | "repository": {
28 | "type": "git",
29 | "url": "git://github.com/zont/gulp-usemin.git"
30 | },
31 | "keywords": [
32 | "gulpplugin",
33 | "usemin",
34 | "gulp-usemin"
35 | ],
36 | "author": {
37 | "name": "Alexander Zonov",
38 | "email": "zont@pochta.ru"
39 | },
40 | "license": "MIT",
41 | "bugs": {
42 | "url": "https://github.com/zont/gulp-usemin/issues"
43 | },
44 | "engines": {
45 | "node": ">=0.12"
46 | },
47 | "gitHead": "81bff9fd6d46f9fbedea53e349001d0fa7bcb49c",
48 | "homepage": "https://github.com/zont/gulp-usemin#readme",
49 | "_id": "gulp-usemin@0.3.23",
50 | "_shasum": "9f451546e4ac53a00119c7343d36c42d6a5ce6f0",
51 | "_from": "gulp-usemin@>=0.3.21 <0.4.0",
52 | "_resolved": "https://registry.npm.taobao.org/gulp-usemin/download/gulp-usemin-0.3.23.tgz",
53 | "_npmVersion": "3.3.10",
54 | "_nodeVersion": "5.0.0",
55 | "_npmUser": {
56 | "name": "alexander.zonov",
57 | "email": "zont@pochta.ru"
58 | },
59 | "dist": {
60 | "shasum": "9f451546e4ac53a00119c7343d36c42d6a5ce6f0",
61 | "size": 12939,
62 | "noattachment": false,
63 | "tarball": "http://registry.npm.taobao.org/gulp-usemin/download/gulp-usemin-0.3.23.tgz"
64 | },
65 | "maintainers": [
66 | {
67 | "name": "alexander.zonov",
68 | "email": "zont@pochta.ru"
69 | }
70 | ],
71 | "_npmOperationalInternal": {
72 | "host": "packages-16-east.internal.npmjs.com",
73 | "tmp": "tmp/gulp-usemin-0.3.23.tgz_1462364006265_0.13037881650961936"
74 | },
75 | "directories": {},
76 | "publish_time": 1462364007542,
77 | "_cnpm_publish_time": 1462364007542
78 | }
79 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/app.js:
--------------------------------------------------------------------------------
1 | var sample = 111;
2 | console.log(sample);
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/array-js-attributes.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/build-remove-no-trailing-whitespace.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/complex-path.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/complex.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/conditional-complex.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/conditional-css.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/conditional-inline-css.html:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/conditional-inline-js.html:
--------------------------------------------------------------------------------
1 |
3 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/conditional-js.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/data/css/min-style.css:
--------------------------------------------------------------------------------
1 | *{margin:0;padding:0}body{margin:10px}
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/data/css/style.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | }
5 | body {
6 | margin: 10px;
7 | }
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/data/js/app.js:
--------------------------------------------------------------------------------
1 | var sample = 111;
2 | console.log(sample);
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/data/js/app_min_concat.js:
--------------------------------------------------------------------------------
1 | var sample=111;
2 | console.log(sample);
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/data/js/min-app.js:
--------------------------------------------------------------------------------
1 | var sample=111;console.log(sample);
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/glob-inline-css.html:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/glob-inline-js.html:
--------------------------------------------------------------------------------
1 |
3 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/many-blocks-removal.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/min-app.js:
--------------------------------------------------------------------------------
1 | var sample=111;console.log(sample);
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/min-complex-path.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/min-complex.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/min-css-with-media-query.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/min-html-simple-css.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/min-html-simple-js.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/min-html-simple-removal.html:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xunuoi/gulpman/d12eb0fa1c71a955f98d2c4bb7090540a518dd7a/lib/gulp-usemin/test/expected/min-html-simple-removal.html
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/min-paths-with-querystring.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/min-simple-css-path.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/min-simple-css.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/min-simple-js-path.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/min-simple-js.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/min-style.css:
--------------------------------------------------------------------------------
1 | *{margin:0;padding:0}body{margin:10px}
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/multiple-alternative-paths.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/multiple-files.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/paths-with-querystring.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/simple-css-path.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/simple-css.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/simple-inline-css.html:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/simple-inline-js.html:
--------------------------------------------------------------------------------
1 |
3 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/simple-js-path.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/simple-js-removal.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/simple-js.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/single-quotes-css.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/single-quotes-inline-css.html:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/single-quotes-inline-js.html:
--------------------------------------------------------------------------------
1 |
3 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/single-quotes-js.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/style.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | }
5 | body {
6 | margin: 10px;
7 | }
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/subfolder/app.js:
--------------------------------------------------------------------------------
1 | console.log(sample);
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/expected/subfolder/index.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/alternative/js/util.js:
--------------------------------------------------------------------------------
1 | alert(1);
2 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/array-js-attributes.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/async-less.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/build-remove-no-trailing-whitespace.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
lorem ipsum
4 |
lorem ipsum
5 |
6 |
7 |
lorem ipsum
8 |
lorem ipsum
9 |
10 |
11 |
lorem ipsum
12 |
lorem ipsum
13 |
14 |
15 |
lorem ipsum
16 |
lorem ipsum
17 |
18 |
19 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/comment-js.html:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/complex-path.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/complex.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/conditional-complex.html:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
13 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/conditional-css.html:
--------------------------------------------------------------------------------
1 |
2 |
6 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/conditional-inline-css.html:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/conditional-inline-js.html:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/conditional-js.html:
--------------------------------------------------------------------------------
1 |
2 |
6 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/css-with-media-query-error.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/css-with-media-query.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/css/clear.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | }
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/css/main.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 10px;
3 | }
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/glob-css.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/glob-inline-css.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/glob-inline-js.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/glob-js.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/js/lib.js:
--------------------------------------------------------------------------------
1 | var sample = 111;
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/js/main.js:
--------------------------------------------------------------------------------
1 | console.log(sample);
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/js2/lib2.js:
--------------------------------------------------------------------------------
1 | var sample = 111;
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/js2/main2.js:
--------------------------------------------------------------------------------
1 | console.log(sample);
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/less/clear.less:
--------------------------------------------------------------------------------
1 | @zero: 0;
2 |
3 | * {
4 | margin: @zero;
5 | padding: @zero;
6 | }
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/less/main.less:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 10px;
3 | }
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/many-blocks-removal.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/many-blocks.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/min-html-simple-css.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/min-html-simple-js.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/min-html-simple-removal.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/multiple-alternative-paths-inline.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/multiple-alternative-paths.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/multiple-files.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/paths-with-querystring.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/simple-css-alternate-path.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/simple-css-path.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/simple-css.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/simple-inline-css.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/simple-inline-js.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/simple-js-alternate-path.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/simple-js-path.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/simple-js-removal.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/simple-js.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/single-quotes-css.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/single-quotes-inline-css.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/single-quotes-inline-js.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/single-quotes-js.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/subfolder/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/fixtures/subfolder/script.js:
--------------------------------------------------------------------------------
1 | console.log(sample);
--------------------------------------------------------------------------------
/lib/gulp-usemin/test/main.js:
--------------------------------------------------------------------------------
1 | /* jshint node: true */
2 | /* global describe, it */
3 |
4 | 'use strict';
5 |
6 | var assert = require('assert');
7 | var fs = require('fs');
8 | var gutil = require('gulp-util');
9 | var PassThrough = require('stream').PassThrough;
10 | var path = require('path');
11 | var usemin = require('../index');
12 | var vfs = require('vinyl-fs');
13 |
14 | function getFile(filePath) {
15 | return new gutil.File({
16 | path: filePath,
17 | base: path.dirname(filePath),
18 | contents: fs.readFileSync(filePath)
19 | });
20 | }
21 |
22 | function getFixture(filePath) {
23 | return getFile(path.join('test', 'fixtures', filePath));
24 | }
25 |
26 | function getExpected(filePath) {
27 | return getFile(path.join('test', 'expected', filePath));
28 | }
29 |
30 | describe('gulp-usemin', function() {
31 | describe('allow removal sections', function() {
32 | function compare(name, expectedName, done) {
33 | var htmlmin = require('gulp-minify-html');
34 | var stream = usemin({html: [htmlmin({empty: true, quotes: true})]});
35 |
36 | stream.on('data', function(newFile) {
37 | if (path.basename(newFile.path) === name) {
38 | assert.equal(String(getExpected(expectedName).contents), String(newFile.contents));
39 | done();
40 | }
41 | });
42 |
43 | stream.write(getFixture(name));
44 | }
45 |
46 | it('simple js block', function(done) {
47 | compare('simple-js-removal.html', 'simple-js-removal.html', done);
48 | });
49 |
50 | it('minified js block', function(done) {
51 | compare('min-html-simple-removal.html', 'min-html-simple-removal.html', done);
52 | });
53 |
54 | it('many blocks', function(done) {
55 | compare('many-blocks-removal.html', 'many-blocks-removal.html', done);
56 | });
57 |
58 | it('robust pattern recognition (no whitespace after build:remove)', function(done) {
59 | compare('build-remove-no-trailing-whitespace.html', 'build-remove-no-trailing-whitespace.html', done);
60 | });
61 |
62 | });
63 |
64 | describe('negative test:', function() {
65 | it('shouldn\'t work in stream mode', function(done) {
66 | var stream = usemin();
67 | var t;
68 | var fakeStream = new PassThrough();
69 | var fakeFile = new gutil.File({
70 | contents: fakeStream
71 | });
72 | fakeStream.end();
73 |
74 | stream.on('error', function() {
75 | clearTimeout(t);
76 | done();
77 | });
78 |
79 | t = setTimeout(function() {
80 | assert.fail('', '', 'Should throw error', '');
81 | done();
82 | }, 1000);
83 |
84 | stream.write(fakeFile);
85 | });
86 |
87 | it('html without blocks', function(done) {
88 | var stream = usemin();
89 | var content = 'content
';
90 | var fakeFile = new gutil.File({
91 | path: 'test.file',
92 | contents: new Buffer(content)
93 | });
94 |
95 | stream.on('data', function(newFile) {
96 | assert.equal(content, String(newFile.contents));
97 | done();
98 | });
99 |
100 | stream.write(fakeFile);
101 | });
102 | });
103 |
104 | describe('should work in buffer mode with', function() {
105 | describe('minified HTML:', function() {
106 | function compare(name, expectedName, done, fail) {
107 | var htmlmin = require('gulp-minify-html');
108 | var stream = usemin({
109 | html: [function() {
110 | return htmlmin({empty: true});
111 | }]
112 | });
113 |
114 | stream.on('data', function(newFile) {
115 | if (path.basename(newFile.path) === name) {
116 | assert.equal(String(getExpected(expectedName).contents), String(newFile.contents));
117 | done();
118 | }
119 | });
120 | stream.on('error', function() {
121 | if (fail)
122 | fail();
123 | });
124 |
125 | stream.write(getFixture(name));
126 | }
127 |
128 | it('simple js block', function(done) {
129 | compare('simple-js.html', 'min-simple-js.html', done);
130 | });
131 |
132 | it('simple js block with path', function(done) {
133 | compare('simple-js-path.html', 'min-simple-js-path.html', done);
134 | });
135 |
136 | it('simple css block', function(done) {
137 | compare('simple-css.html', 'min-simple-css.html', done);
138 | });
139 |
140 | it('css block with media query', function(done) {
141 | compare('css-with-media-query.html', 'min-css-with-media-query.html', done);
142 | });
143 |
144 | it('css block with mixed incompatible media queries should error', function(done) {
145 | compare('css-with-media-query-error.html', 'min-css-with-media-query.html', function() {
146 | assert.fail('', '', 'should error', '');
147 | done();
148 | }, done);
149 | });
150 |
151 | it('simple css block with path', function(done) {
152 | compare('simple-css-path.html', 'min-simple-css-path.html', done);
153 | });
154 |
155 | it('complex (css + js)', function(done) {
156 | compare('complex.html', 'min-complex.html', done);
157 | });
158 |
159 | it('complex with path (css + js)', function(done) {
160 | compare('complex-path.html', 'min-complex-path.html', done);
161 | });
162 |
163 | it('paths with querystring', function(done) {
164 | compare('paths-with-querystring.html', 'min-paths-with-querystring.html', done);
165 | });
166 | });
167 |
168 | describe('not minified HTML:', function() {
169 | function compare(name, expectedName, done) {
170 | var stream = usemin();
171 |
172 | stream.on('data', function(newFile) {
173 | if (path.basename(newFile.path) === name) {
174 | assert.equal(String(getExpected(expectedName).contents), String(newFile.contents));
175 | done();
176 | }
177 | });
178 |
179 | stream.write(getFixture(name));
180 | }
181 |
182 | it('simple js block with single quotes', function (done) {
183 | compare('single-quotes-js.html', 'single-quotes-js.html', done);
184 | });
185 |
186 | it('simple css block with single quotes', function (done) {
187 | compare('single-quotes-css.html', 'single-quotes-css.html', done);
188 | });
189 |
190 | it('simple (js block)', function(done) {
191 | compare('simple-js.html', 'simple-js.html', done);
192 | });
193 |
194 | it('simple (js block) (html minified)', function(done) {
195 | compare('min-html-simple-js.html', 'min-html-simple-js.html', done);
196 | });
197 |
198 | it('simple with path (js block)', function(done) {
199 | compare('simple-js-path.html', 'simple-js-path.html', done);
200 | });
201 |
202 | it('simple (css block)', function(done) {
203 | compare('simple-css.html', 'simple-css.html', done);
204 | });
205 |
206 | it('simple (css block) (html minified)', function(done) {
207 | compare('min-html-simple-css.html', 'min-html-simple-css.html', done);
208 | });
209 |
210 | it('simple with path (css block)', function(done) {
211 | compare('simple-css-path.html', 'simple-css-path.html', done);
212 | });
213 |
214 | it('complex (css + js)', function(done) {
215 | compare('complex.html', 'complex.html', done);
216 | });
217 |
218 | it('complex with path (css + js)', function(done) {
219 | compare('complex-path.html', 'complex-path.html', done);
220 | });
221 |
222 | it('multiple alternative paths', function(done) {
223 | compare('multiple-alternative-paths.html', 'multiple-alternative-paths.html', done);
224 | });
225 |
226 | it('paths with querystring', function(done) {
227 | compare('paths-with-querystring.html', 'paths-with-querystring.html', done);
228 | });
229 | });
230 |
231 | describe('minified CSS:', function() {
232 | function compare(fixtureName, name, expectedName, end) {
233 | var cssmin = require('gulp-minify-css');
234 | var stream = usemin({css: ['concat', cssmin()]});
235 |
236 | stream.on('data', function(newFile) {
237 | if (path.basename(newFile.path) === name) {
238 | assert.equal(String(getExpected(expectedName).contents), String(newFile.contents));
239 | end();
240 | }
241 | });
242 |
243 | stream.write(getFixture(fixtureName));
244 | }
245 |
246 | it('simple (css block)', function(done) {
247 | var name = 'style.css';
248 | var expectedName = 'min-style.css';
249 |
250 | compare('simple-css.html', name, expectedName, done);
251 | });
252 |
253 | it('simple with path (css block)', function(done) {
254 | var name = 'style.css';
255 | var expectedName = path.join('data', 'css', 'min-style.css');
256 |
257 | compare('simple-css-path.html', name, expectedName, done);
258 | });
259 |
260 | it('simple with alternate path (css block)', function(done) {
261 | var name = 'style.css';
262 | var expectedName = path.join('data', 'css', 'min-style.css');
263 |
264 | compare('simple-css-alternate-path.html', name, expectedName, done);
265 | });
266 | });
267 |
268 | describe('not minified CSS:', function() {
269 | function compare(fixtureName, expectedName, end) {
270 | var stream = usemin();
271 |
272 | stream.on('data', function(newFile) {
273 | if (path.basename(newFile.path) === path.basename(expectedName)) {
274 | assert.equal(String(getExpected(expectedName).contents), String(newFile.contents));
275 | end();
276 | }
277 | });
278 |
279 | stream.write(getFixture(fixtureName));
280 | }
281 |
282 | it('simple (css block)', function(done) {
283 | compare('simple-css.html', 'style.css', done);
284 | });
285 |
286 | it('simple (css block) (minified html)', function(done) {
287 | compare('min-html-simple-css.html', 'style.css', done);
288 | });
289 |
290 | it('simple with path (css block)', function(done) {
291 | compare('simple-css-path.html', path.join('data', 'css', 'style.css'), done);
292 | });
293 |
294 | it('simple with alternate path (css block)', function(done) {
295 | compare('simple-css-alternate-path.html', path.join('data', 'css', 'style.css'), done);
296 | });
297 | });
298 |
299 | describe('minified JS:', function() {
300 | function compare(fixtureName, name, expectedName, end) {
301 | var jsmin = require('gulp-uglify');
302 | var stream = usemin({js: [jsmin()]});
303 |
304 | stream.on('data', function(newFile) {
305 | if (path.basename(newFile.path) === path.basename(name)) {
306 | assert.equal(String(getExpected(expectedName).contents), String(newFile.contents));
307 | end();
308 | }
309 | });
310 |
311 | stream.write(getFixture(fixtureName));
312 | }
313 |
314 | it('simple (js block)', function(done) {
315 | compare('simple-js.html', 'app.js', 'min-app.js', done);
316 | });
317 |
318 | it('simple with path (js block)', function(done) {
319 | var name = path.join('data', 'js', 'app.js');
320 | var expectedName = path.join('data', 'js', 'min-app.js');
321 |
322 | compare('simple-js-path.html', name, expectedName, done);
323 | });
324 |
325 | it('simple with alternate path (js block)', function(done) {
326 | var name = path.join('data', 'js', 'app.js');
327 | var expectedName = path.join('data', 'js', 'min-app.js');
328 |
329 | compare('simple-js-alternate-path.html', name, expectedName, done);
330 | });
331 | });
332 |
333 | describe('not minified JS:', function() {
334 | function compare(fixtureName, expectedName, end) {
335 | var stream = usemin();
336 |
337 | stream.on('data', function(newFile) {
338 | if (path.basename(newFile.path) === path.basename(expectedName)) {
339 | assert.equal(String(getExpected(expectedName).contents), String(newFile.contents));
340 | end();
341 | }
342 | });
343 |
344 | stream.write(getFixture(fixtureName));
345 | }
346 |
347 | it('simple (js block)', function(done) {
348 | compare('simple-js.html', 'app.js', done);
349 | });
350 |
351 | it('simple (js block) (minified html)', function(done) {
352 | compare('min-html-simple-js.html', 'app.js', done);
353 | });
354 |
355 | it('simple with path (js block)', function(done) {
356 | compare('simple-js-path.html', path.join('data', 'js', 'app.js'), done);
357 | });
358 |
359 | it('simple with alternate path (js block)', function(done) {
360 | compare('simple-js-alternate-path.html', path.join('data', 'js', 'app.js'), done);
361 | });
362 | });
363 |
364 | it('many html files', function(done) {
365 | var cssmin = require('gulp-minify-css');
366 | var jsmin = require('gulp-uglify');
367 | var rev = require('gulp-rev');
368 | var stream = usemin({
369 | css: ['concat', cssmin],
370 | js: ['concat', jsmin]
371 | });
372 |
373 | var nameCss = 'style.css';
374 | var expectedNameCss = 'min-style.css';
375 | var nameJs = 'app.js';
376 | var expectedNameJs = 'min-app.js';
377 | var cssExist = false;
378 | var jsExist = false;
379 | var htmlCount = 0;
380 |
381 | stream.on('data', function(newFile) {
382 | if (path.basename(newFile.path) === path.basename(nameCss)) {
383 | cssExist = true;
384 | assert.equal(String(getExpected(expectedNameCss).contents), String(newFile.contents));
385 | }
386 | else if (path.basename(newFile.path) === path.basename(nameJs)) {
387 | jsExist = true;
388 | assert.equal(String(getExpected(expectedNameJs).contents), String(newFile.contents));
389 | }
390 | else {
391 | htmlCount += 1;
392 | }
393 | });
394 |
395 | stream.on('end', function() {
396 | assert.equal(htmlCount, 2);
397 | assert.ok(cssExist);
398 | assert.ok(jsExist);
399 | done();
400 | });
401 |
402 | stream.write(getFixture('simple-css.html'));
403 | stream.write(getFixture('simple-js.html'));
404 | stream.end();
405 | });
406 |
407 | it('many blocks', function(done) {
408 | var cssmin = require('gulp-minify-css');
409 | var jsmin = require('gulp-uglify');
410 | var rev = require('gulp-rev');
411 | var stream = usemin({
412 | css1: ['concat', cssmin],
413 | js1: [jsmin, 'concat', rev]
414 | });
415 |
416 | var nameCss = path.join('data', 'css', 'style.css');
417 | var expectedNameCss = path.join('data', 'css', 'min-style.css');
418 | var nameJs = path.join('data', 'js', 'app.js');
419 | var expectedNameJs = path.join('data', 'js', 'app.js');
420 | var nameJs1 = 'app1';
421 | var expectedNameJs1 = path.join('data', 'js', 'app_min_concat.js');
422 | var nameJs2 = 'app2';
423 | var expectedNameJs2 = path.join('data', 'js', 'app_min_concat.js');
424 | var cssExist = false;
425 | var jsExist = false;
426 | var js1Exist = false;
427 | var js2Exist = false;
428 |
429 | stream.on('data', function(newFile) {
430 | if (path.basename(newFile.path) === path.basename(nameCss)) {
431 | cssExist = true;
432 | assert.equal(String(getExpected(expectedNameCss).contents), String(newFile.contents));
433 | }
434 | else if (path.basename(newFile.path) === path.basename(nameJs)) {
435 | jsExist = true;
436 | assert.equal(String(getExpected(expectedNameJs).contents), String(newFile.contents));
437 | }
438 | else if (newFile.path.indexOf(nameJs1) != -1) {
439 | js1Exist = true;
440 | assert.equal(String(getExpected(expectedNameJs1).contents), String(newFile.contents));
441 | }
442 | else if (newFile.path.indexOf(nameJs2) != -1) {
443 | js2Exist = true;
444 | assert.equal(String(getExpected(expectedNameJs2).contents), String(newFile.contents));
445 | }
446 | else {
447 | assert.ok(cssExist);
448 | assert.ok(jsExist);
449 | assert.ok(js1Exist);
450 | assert.ok(js2Exist);
451 | done();
452 | }
453 | });
454 |
455 | stream.write(getFixture('many-blocks.html'));
456 | });
457 |
458 | describe('assetsDir option:', function() {
459 | function compare(assetsDir, done) {
460 | var stream = usemin({assetsDir: assetsDir});
461 | var expectedName = 'style.css';
462 |
463 | stream.on('data', function(newFile) {
464 | if (path.basename(newFile.path) === expectedName) {
465 | assert.equal(String(getExpected(expectedName).contents), String(newFile.contents));
466 | done();
467 | }
468 | });
469 |
470 | stream.write(getFixture('simple-css.html'));
471 | }
472 |
473 | it('absolute path', function(done) {
474 | compare(path.join(process.cwd(), 'test', 'fixtures'), done);
475 | });
476 |
477 | it('relative path', function(done) {
478 | compare(path.join('test', 'fixtures'), done);
479 | });
480 | });
481 |
482 | describe('conditional comments:', function() {
483 | function compare(name, expectedName, done) {
484 | var stream = usemin();
485 |
486 | stream.on('data', function(newFile) {
487 | if (path.basename(newFile.path) === name) {
488 | assert.equal(String(getExpected(expectedName).contents), String(newFile.contents));
489 | done();
490 | }
491 | });
492 |
493 | stream.write(getFixture(name));
494 | }
495 |
496 | it('conditional (js block)', function(done) {
497 | compare('conditional-js.html', 'conditional-js.html', done);
498 | });
499 |
500 | it('conditional (css block)', function(done) {
501 | compare('conditional-css.html', 'conditional-css.html', done);
502 | });
503 |
504 | it('conditional (css + js)', function(done) {
505 | compare('conditional-complex.html', 'conditional-complex.html', done);
506 | });
507 |
508 | it('conditional (inline js block)', function(done) {
509 | compare('conditional-inline-js.html', 'conditional-inline-js.html', done);
510 | });
511 |
512 | it('conditional (inline css block)', function(done) {
513 | compare('conditional-inline-css.html', 'conditional-inline-css.html', done);
514 | });
515 |
516 | });
517 |
518 | describe('globbed files:', function() {
519 | function compare(fixtureName, name, end) {
520 | var stream = usemin();
521 |
522 | stream.on('data', function(newFile) {
523 | if (path.basename(newFile.path) === name) {
524 | assert.equal(String(newFile.contents), String(getExpected(name).contents));
525 | end();
526 | }
527 | });
528 |
529 | stream.write(getFixture(fixtureName));
530 | }
531 |
532 | it('glob (js block)', function(done) {
533 | compare('glob-js.html', 'app.js', done);
534 | });
535 |
536 | it('glob (css block)', function(done) {
537 | compare('glob-css.html', 'style.css', done);
538 | });
539 |
540 | it('glob inline (js block)', function(done) {
541 | compare('glob-inline-js.html', 'glob-inline-js.html', done);
542 | });
543 |
544 | it('glob inline (css block)', function(done) {
545 | compare('glob-inline-css.html', 'glob-inline-css.html', done);
546 | });
547 | });
548 |
549 | describe('comment files:', function() {
550 | function compare(name, callback) {
551 | var stream = usemin({enableHtmlComment: true});
552 |
553 | stream.on('data', callback);
554 |
555 | stream.write(getFixture(name));
556 | }
557 |
558 | it('comment (js block)', function(done) {
559 | var expectedName = 'app.js';
560 |
561 | compare(
562 | 'comment-js.html',
563 | function(newFile) {
564 | if (path.basename(newFile.path) === expectedName) {
565 | assert.equal(String(newFile.contents), String(getExpected(expectedName).contents));
566 | done();
567 | }
568 | }
569 | );
570 | });
571 | });
572 |
573 | describe('inline Sources:', function() {
574 | function compare(fixtureName, name, end) {
575 | var stream = usemin();
576 |
577 | stream.on('data', function(newFile) {
578 | if (path.basename(newFile.path) === name) {
579 | assert.equal(String(newFile.contents), String(getExpected(name).contents));
580 | end();
581 | }
582 | });
583 |
584 | stream.write(getFixture(fixtureName));
585 | }
586 |
587 | it('simple inline js block', function (done) {
588 | compare('simple-inline-js.html', 'simple-inline-js.html', done);
589 | });
590 |
591 | it('simple inline css block', function (done) {
592 | compare('simple-inline-css.html', 'simple-inline-css.html', done);
593 | });
594 |
595 | it('simple inline js block width single quotes', function (done) {
596 | compare('single-quotes-inline-js.html', 'single-quotes-inline-js.html', done);
597 | });
598 |
599 | it('simple inline css block with single quotes', function (done) {
600 | compare('single-quotes-inline-css.html', 'single-quotes-inline-css.html', done);
601 | });
602 |
603 | });
604 |
605 | describe('array jsAttributes:', function() {
606 |
607 | function compare(fixtureName, name, end) {
608 | var stream = usemin({
609 | jsAttributes: {
610 | seq: [1, 2, 1, 3],
611 | color: ['blue', 'red', 'yellow', 'pink']
612 | },
613 | js: [],
614 | js1: [],
615 | js2: [],
616 | js3: []
617 |
618 | });
619 |
620 | stream.on('data', function(newFile) {
621 | if (path.basename(newFile.path) === name) {
622 | assert.equal(String(newFile.contents), String(getExpected(name).contents));
623 | end();
624 | }
625 | });
626 |
627 | stream.write(getFixture(fixtureName));
628 | }
629 |
630 | it('js attributes with array define', function (done) {
631 | compare('array-js-attributes.html', 'array-js-attributes.html', done);
632 | });
633 |
634 | });
635 |
636 | it('async task', function(done) {
637 | var less = require('gulp-less');
638 | var cssmin = require('gulp-minify-css');
639 | var stream = usemin({
640 | less: [less(), 'concat', cssmin()]
641 | });
642 |
643 | var name = 'style.css';
644 | var expectedName = 'min-style.css';
645 |
646 | stream.on('data', function(newFile) {
647 | if (path.basename(newFile.path) === path.basename(name)) {
648 | assert.equal(String(getExpected(expectedName).contents), String(newFile.contents));
649 | done();
650 | }
651 | });
652 |
653 | stream.write(getFixture('async-less.html'));
654 | });
655 |
656 | it('subfolders', function(done) {
657 | var stream = usemin();
658 | var jsExist = false;
659 | var nameJs = path.join('subfolder', 'app.js');
660 |
661 | stream.on('data', function(newFile) {
662 | if (path.basename(newFile.path) === path.basename(nameJs)) {
663 | jsExist = true;
664 | assert.equal(path.relative(newFile.base, newFile.path), nameJs);
665 | assert.equal(String(getExpected(nameJs).contents), String(newFile.contents));
666 | }
667 | else {
668 | assert.ok(jsExist);
669 | done();
670 | }
671 | });
672 |
673 | vfs.src('test/fixtures/**/index.html')
674 | .pipe(stream);
675 | });
676 | });
677 |
678 | it('multiple files in stream', function(done) {
679 | var multipleFiles = function() {
680 | var through = require('through2');
681 | var File = gutil.File;
682 |
683 | return through.obj(function(file) {
684 | var stream = this;
685 |
686 | stream.push(new File({
687 | cwd: file.cwd,
688 | base: file.base,
689 | path: file.path,
690 | contents: new Buffer('test1')
691 | }));
692 |
693 | stream.push(new File({
694 | cwd: file.cwd,
695 | base: file.base,
696 | path: file.path,
697 | contents: new Buffer('test2')
698 | }));
699 | });
700 | };
701 | var stream = usemin({
702 | css: [multipleFiles],
703 | js: [multipleFiles]
704 | });
705 |
706 | stream.on('data', function(newFile) {
707 | if (path.basename(newFile.path) === path.basename('multiple-files.html')) {
708 | assert.equal(String(getExpected('multiple-files.html').contents), String(newFile.contents));
709 | done();
710 | }
711 | });
712 |
713 | stream.write(getFixture('multiple-files.html'));
714 | });
715 | });
716 |
--------------------------------------------------------------------------------
/lib/htmlPathParser.js:
--------------------------------------------------------------------------------
1 | /**
2 | * FOR PARSE HTML REF PATH
3 | */
4 |
5 | 'use strict'
6 |
7 |
8 | var through = require('through2'),
9 | path = require('path'),
10 | j = path.join,
11 | // gulpman utils
12 | gmutil = require('./gmutil')
13 |
14 |
15 |
16 | function _dealHTML(conf){
17 |
18 | let _opts = conf['_opts'],
19 | basepath = conf['basepath'],
20 | _isRuntimeDir = conf['_isRuntimeDir'],
21 | all_raw_source_reg = conf['all_raw_source_reg']
22 |
23 |
24 | return through.obj(function (file, enc, cb){
25 |
26 | if (file.isNull()) {
27 | this.push(file);
28 | return cb()
29 | }
30 | if (file.isStream()) {
31 | gmutil.error('*ParseHtml Error: Streaming not supported')
32 | return cb()
33 | }
34 |
35 | let contents = file.contents.toString()
36 |
37 | // file.relative 是根据path.base自动生成的
38 | if(basepath) file.base = basepath
39 |
40 | let fdirname = path.dirname(file.relative)
41 | // set assets url prefix
42 | let _urlPrefix
43 |
44 |
45 | if(_opts['is_absolute']) {
46 | _urlPrefix = _opts['url_prefix']
47 | }else {
48 | // 判断打包资源中的url路径前缀
49 | let _fPath = j(_isRuntimeDir ? _opts['runtime_views'] : _opts['dist_views'], fdirname)
50 |
51 | let _staticPath = _isRuntimeDir ? _opts['runtime_static'] : _opts['dist_static']
52 |
53 | _urlPrefix = path.relative(_fPath, _staticPath)
54 | }
55 |
56 |
57 | // 所有格式都要处理
58 | let srcQuoteReg = new RegExp('(?=[\'"]?)([\\w\\.\\-\\?\\-\\/\\:]+?(\\.('+all_raw_source_reg+')))(?=\\?_gm_inline)?(?=[\'"]?)', 'gm')
59 | // httpReg = /^http(s)?\:/
60 |
61 |
62 | let tmp_rs_list = [],
63 | rs_list = []
64 |
65 | // 提取单标签和双标签
66 | tmp_rs_list = tmp_rs_list
67 | .concat(contents.match(gmutil.reg['tagMedia']))
68 | .concat(contents.match(gmutil.reg['closeTagMedia']))
69 |
70 | // 首先提取标签,然后从标签中提取href或者src
71 | tmp_rs_list.length && (
72 | rs_list = tmp_rs_list
73 | .filter(r=>(r && r.match(srcQuoteReg)))
74 | .map(v=>v.match(srcQuoteReg)[0])
75 | .filter(r=>{
76 | // remove the http:xxx.com/xx and base64 data url
77 | // 只处理相对路径
78 | // 不处理绝对路径、http、dataURL
79 | return gmutil.isUrl('relative', r)
80 | })
81 | .filter(r=>!r.match(/^(['"]\/)/gm))
82 | )
83 |
84 | // 这里利用set做去重
85 | let rs_set = new Set(rs_list),
86 | srcPrefix = j(_urlPrefix, fdirname)
87 |
88 | // 替换url的的path和前缀
89 | rs_set.size && rs_set.forEach(epath=>{
90 | // 对于base64的参数标识要保留,不能清理掉,因为后续要嵌入base64
91 | let innerReg = new RegExp('(?=[\'"]?)('+epath+')(\\?_gm_inline)*(?=[\'"]?)', 'gm')
92 |
93 | contents = contents.replace(innerReg, j(srcPrefix, epath)+'$2')
94 | })
95 |
96 | // dealing with usemin build mark syntax
97 | // when in publish, not runtime-dir
98 | if(!_isRuntimeDir) {
99 | // 这里处理usemin 的build的注释内容
100 | contents = gmutil.replaceBuildBlock(contents, srcPrefix)
101 | }
102 |
103 | file.contents = new Buffer(contents)
104 |
105 | gmutil.tip('*Raw HTML File Parsed: '+file.relative)
106 |
107 | this.push(file)
108 | cb()
109 | })
110 | }
111 |
112 |
113 | module.exports = _dealHTML
114 |
--------------------------------------------------------------------------------
/lib/iconFonter.js:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015 App Annie Inc. All rights reserved.
2 | 'use strict';
3 |
4 | var path = require('path'),
5 | j = path.join;
6 |
7 | var sh = require("shelljs")
8 |
9 | var fontName = 'gmicon';
10 |
11 | function registerTask(gulp, opts) {
12 | var runTimestamp = Math.round(Date.now() / 1000);
13 |
14 | if(!opts['iconfont']) {
15 | opts['iconfont'] = {
16 |
17 | }
18 | }
19 | var _iconConf = opts['iconfont'];
20 |
21 | var svgSource = _iconConf['source'] || j(opts['components'], 'iconfonts/source')
22 | var iconPath = _iconConf['icon'] || j(opts['components'], 'iconfonts', fontName)
23 | // var iconCSSPath = _iconConf['css'] || j(opts['components'], 'iconfonts')
24 | var svgSource = j(svgSource, '/*.svg');
25 |
26 | gulp.task('gm:iconfont', function() {
27 |
28 | var iconfont = require('gulp-iconfont');
29 | var iconfontCss = require('gulp-iconfont-css');
30 |
31 | return gulp.src(svgSource)
32 | .pipe(iconfontCss({
33 | fontName: fontName,
34 | // path: 'app/assets/css/templates/_icons.scss',
35 | targetPath: 'gmicon.css',
36 | fontPath: './',
37 | cssClass: 'gmicon'
38 | }))
39 | .pipe(iconfont({
40 | fontName: fontName, // required
41 | formats: ['svg', 'ttf', 'eot', 'woff', 'woff2'],
42 | normalize: true,
43 | fontHeight: 500,
44 | timestamp: runTimestamp // recommended to get consistent builds when watching files
45 | }))
46 | .pipe(gulp.dest(iconPath))
47 | });
48 | }
49 |
50 | exports.registerTask = registerTask;
51 |
--------------------------------------------------------------------------------
/lib/inline.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Rodey on 2015/11/5.
3 | */
4 |
5 | var fs = require('fs'),
6 | path = require('path'),
7 | through2 = require('through2'),
8 | uglifycss = require('uglifycss'),
9 | jsmin = require('jsmin2'),
10 | PluginError = require('gulp-util').PluginError,
11 |
12 | gmutil = require('./gmutil'),
13 | store = require('./store')
14 |
15 |
16 | var PLUGIN_NAME = 'gulp-html-inline';
17 |
18 | var linkRegx = new RegExp('[\\s\\S]*?<*\\/*>*', 'gi'),
19 | hrefRegx = new RegExp('\\s*(href)="+([\\s\\S]*?)"'),
20 | styleRegx = new RegExp('
200 | //console.log($1);
201 | return miniInline($1, 'css', options);
202 |
203 | }).replace(scriptRegx, function($1){
204 | //like:
205 | //
212 |
213 | /**
214 | * @debug for replace bug
215 | * this trigger the src with type joined together
216 | * lead into miniInline
217 | */
218 | return miniInline($1, 'js', options);
219 | });
220 |
221 | return content;
222 | };
223 |
224 | //get the content of files
225 | var getFileContent = function(file){
226 | if(!fs.existsSync(file)) throw new Error('File not find: ' + file);
227 | var fileContent = fs.readFileSync(file, { encoding: 'utf8' });
228 | return fileContent;
229 | //file.contents = new Buffer(uglifycss.processString(fileContent, options));
230 | };
231 |
232 | //get the mined files content
233 | var getContent = function(file, options){
234 |
235 | var content = execture(file, options);
236 | return content;
237 | };
238 |
239 | //将压缩后的内容替换到html中
240 | var inline = function(options){
241 | var options = options || {},
242 | basePath = options.basePath;
243 | //是否压缩css, 默认压缩
244 | options.minifyCss = 'undefined' === typeof(options.minifyCss) ? true : options.minifyCss;
245 | //是否压缩js, 默认压缩
246 | options.minifyJs = 'undefined' === typeof(options.minifyJs) ? true : options.minifyJs;
247 |
248 | return through2.obj(function(file, enc, next){
249 |
250 | if (file.isStream()) {
251 | this.emit('error', new PluginError(PLUGIN_NAME, 'Stream content is not supported'));
252 | return next(null, file);
253 | }
254 |
255 | _file = file
256 |
257 | if (file.isBuffer()) {
258 | try {
259 | var content = getContent(file, options);
260 |
261 | file.contents = new Buffer(content);
262 | }
263 | catch (err) {
264 | this.emit('error', new PluginError(PLUGIN_NAME, err['message']));
265 | }
266 | }
267 | this.push(file);
268 | return next();
269 |
270 |
271 | });
272 |
273 | };
274 |
275 | module.exports = inline;
--------------------------------------------------------------------------------
/lib/revReplace.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var path = require('path');
4 | var gutil = require('gulp-util');
5 | var through = require('through2');
6 |
7 | var gmutil = require('./gmutil');
8 |
9 |
10 | function plugin(options) {
11 | var renames = [];
12 | var cache = [];
13 |
14 | options = options || {};
15 |
16 | if (!options.canonicalUris) {
17 | options.canonicalUris = true;
18 | }
19 |
20 | options.replaceInExtensions = options.replaceInExtensions || ['.js', '.css', '.html', '.hbs'];
21 |
22 | // @debug add for gulpman
23 | options.prefix = options.prefix || '';
24 | options['_prefix'] = options['prefix']
25 | options['_all_prefix'] = new Set()
26 | var _url_prefix = options['url_prefix']
27 |
28 | // @add prefix array and fn support
29 | // @Lucas
30 | if(typeof options.prefix == 'string'){
31 | options['_all_prefix'].add(options.prefix)
32 | }else if(options.prefix instanceof Array){
33 | // 虽然在gulpman/index中已经做了proxy,但是目前注释掉这块,会导致/http://xx的问题,需要处理下
34 | Object.defineProperty(options, 'prefix',{
35 | get: function () {
36 | var p = this['_prefix'][gmutil.randomNum(0, options['_prefix'].length-1)]
37 |
38 | options['_all_prefix'].add(p)
39 |
40 | return p
41 | },
42 | set : function (val) {
43 | this['_prefix'] = val
44 | },
45 | configurable : true
46 | })
47 | // if the param is a function
48 | }else if(options.prefix instanceof Function){
49 | Object.defineProperty(options, 'prefix',{
50 | get: function () {
51 | var p = this['_prefix'](options['_tmpMediaFilePath'], options['_tmpMediaFilePath'])
52 |
53 | options['_all_prefix'].add(p)
54 |
55 | return p;
56 |
57 | },
58 | set : function (val) {
59 | this['_prefix'] = val
60 | },
61 | configurable : true
62 | })
63 | }else {
64 | // default
65 | }
66 |
67 |
68 | return through.obj(function collectRevs(file, enc, cb) {
69 | if (file.isNull()) {
70 | this.push(file);
71 | return cb();
72 | }
73 |
74 | if (file.isStream()) {
75 | this.emit('error', new gutil.PluginError('gulp-rev-replace', 'Streaming not supported'));
76 | return cb();
77 | }
78 |
79 |
80 | // 此处file是宿主文件
81 | options['_file'] = file
82 |
83 | // Collect renames from reved files.
84 | if (file.revOrigPath) {
85 |
86 | // @add for gulpman hooks
87 | options['_tmpHostFilePath'] = file.path
88 |
89 | var mediaFilePath = fmtPath(file.revOrigBase, file.revOrigPath)
90 |
91 | // media file ,js css,egg.
92 | options['_tmpMediaFilePath'] = mediaFilePath
93 |
94 | // 此处触发一次运行函数
95 | var availablePrefix = options.prefix
96 |
97 | renames.push({
98 | unreved: mediaFilePath,
99 | reved: availablePrefix + fmtPath(file.base, file.path)
100 | });
101 | }
102 |
103 | if (options.replaceInExtensions.indexOf(path.extname(file.path)) > -1) {
104 | // file should be searched for replaces
105 | cache.push(file);
106 | } else {
107 | // nothing to do with this file
108 | this.push(file);
109 | }
110 |
111 | cb();
112 | }, function replaceInFiles(cb) {
113 | var stream = this;
114 |
115 | if (options.manifest) {
116 | // Read manifest file for the list of renames.
117 | options.manifest.on('data', function (file) {
118 |
119 | var manifest = JSON.parse(file.contents.toString());
120 |
121 |
122 | Object.keys(manifest).forEach(function (srcFile) {
123 |
124 | // @add for gulpman hooks
125 | var unrevedFilePath = canonicalizeUri(srcFile)
126 | //if want delete source file, can do delete here
127 | options['_tmpMediaFilePath'] = unrevedFilePath
128 |
129 | if(options['_file']){
130 | options['_tmpHostFilePath'] = options['_file'].path
131 | }
132 |
133 | // 此处每次get prefix,都会运行一次产生函数,每次结果可能不同
134 | var availablePrefix = options.prefix
135 |
136 | renames.push({
137 | unreved: unrevedFilePath,
138 | reved: availablePrefix + canonicalizeUri(manifest[srcFile])
139 | });
140 |
141 | });
142 | });
143 |
144 | options.manifest.on('end', replaceContents);
145 | }
146 | else {
147 | replaceContents();
148 | }
149 |
150 | function replaceContents() {
151 | renames = renames.sort(gmutil.byLongestUnreved);
152 |
153 | // Once we have a full list of renames, search/replace in the cached
154 | // files and push them through.
155 | cache.forEach(function replaceInFile(file) {
156 | var contents = file.contents.toString();
157 |
158 | renames.forEach(function replaceOnce(rename) {
159 | var unreved = options.modifyUnreved ? options.modifyUnreved(rename.unreved) : rename.unreved;
160 | var reved = options.modifyReved ? options.modifyReved(rename.reved) : rename.reved;
161 |
162 | contents = contents.split(unreved).join(reved);
163 |
164 | options['_all_prefix'].size && options['_all_prefix'].forEach((availablePrefix)=>{
165 | // add for gulpman hooks
166 | // 这块需要遍历所有prefix,每次prefix可能会变,导致替换失败
167 | if (availablePrefix) {
168 | var _tmp_full_url_prefix = _url_prefix + '/'+ availablePrefix;
169 | var _full_url_prefix = gmutil.joinUrl(availablePrefix, _url_prefix);
170 |
171 | contents = contents.split(_tmp_full_url_prefix).join(_full_url_prefix)
172 | }
173 | })
174 |
175 | });
176 |
177 | file.contents = new Buffer(contents);
178 | stream.push(file);
179 | });
180 |
181 | cb();
182 | }
183 | });
184 |
185 |
186 | function fmtPath(base, filePath) {
187 | var newPath = path.relative(base, filePath);
188 |
189 | return canonicalizeUri(newPath);
190 | }
191 |
192 |
193 | // 标准化url
194 | function canonicalizeUri(filePath) {
195 | if (path.sep !== '/' && options.canonicalUris) {
196 | filePath = filePath.split(path.sep).join('/');
197 | }
198 |
199 | return filePath;
200 | }
201 |
202 | }
203 |
204 |
205 | /**
206 | * Export API
207 | * @type {[type]}
208 | */
209 |
210 | module.exports = plugin;
211 |
--------------------------------------------------------------------------------
/lib/spriter/README.md:
--------------------------------------------------------------------------------
1 | [](http://badge.fury.io/js/gulp-css-spriter)
2 |
3 | # gulp-css-spriter
4 |
5 | `gulp-css-spriter`, a [gulp](http://gulpjs.com/) plugin, looks through the CSS you pipe in and gathers all of the background images. It then creates a sprite sheet and updates the references in the CSS.
6 |
7 | You can easily exclude/include certain background image declarations using meta info in your styles([*see meta section below*](#meta-options)) and `includeMode` option([*see options section below*](#options)) depending on your use case.
8 |
9 | # Install
10 |
11 | ### Latest Version: 0.3.3
12 |
13 | `npm install gulp-css-spriter`
14 |
15 | # About
16 |
17 | `gulp-css-spriter` uses [spritesmith](https://www.npmjs.com/package/spritesmith) behind the scenes for creating the sprite sheet.
18 |
19 | # Usage
20 |
21 | ## Basic usage
22 |
23 | This is most likely the setup you will probably end up using.
24 |
25 | ```
26 | var gulp = require('gulp');
27 | var spriter = require('gulp-css-spriter');
28 |
29 | gulp.task('css', function() {
30 | return gulp.src('./src/css/styles.css')
31 | .pipe(spriter({
32 | // The path and file name of where we will save the sprite sheet
33 | 'spriteSheet': './dist/images/spritesheet.png',
34 | // Because we don't know where you will end up saving the CSS file at this point in the pipe,
35 | // we need a litle help identifying where it will be.
36 | 'pathToSpriteSheetFromCSS': '../images/spritesheet.png'
37 | }))
38 | .pipe(gulp.dest('./dist/css'));
39 | });
40 | ```
41 |
42 | ## Barebones usage
43 |
44 | The slimmest usage possible.
45 |
46 | ```
47 | var gulp = require('gulp');
48 | var spriter = require('gulp-css-spriter');
49 |
50 | gulp.task('css', function() {
51 | return gulp.src('./styles.css')
52 | .pipe(spriter())
53 | .pipe(gulp.dest('./'));
54 | });
55 | ```
56 |
57 | ## Minify CSS output usage
58 |
59 | If you want to use [@meta data](#meta-options) but are using a preprocessor such as Sass or Less, you will need to use a output style that doesn't strip comments. After piping the CSS through `gulp-css-spriter`, you can then run it through a CSS minifier(separate plugin), such as [`gulp-minify-css`](https://www.npmjs.com/package/gulp-minify-css).
60 |
61 | ```
62 | var gulp = require('gulp');
63 | var spriter = require('gulp-css-spriter');
64 | var minifyCSS = require('gulp-minify-css'); // https://www.npmjs.com/package/gulp-minify-css
65 |
66 | gulp.task('css', function() {
67 | return gulp.src('./styles.css')
68 | .pipe(spriter())
69 | .pipe(minifyCSS())
70 | .pipe(gulp.dest('./'));
71 | });
72 | ```
73 |
74 | # Options
75 |
76 | - `options`: object - hash of options
77 | - `includeMode`: string - Determines whether meta data is necessary or not
78 | - Values: 'implicit', 'explicit'
79 | - Default: 'implicit'
80 | - For example, if `explicit`, you must have meta `include` as `true` in order for the image declarations to be included in the spritesheet: `/* @meta {"spritesheet": {"include": true}} */`
81 | - If left default at `implicit`, all images will be included in the spritesheet; except for image declarations with meta `include` as `false`: `/* @meta {"spritesheet": {"include": false}} */`
82 | - `spriteSheet`: string - The path and file name of where we will save the sprite sheet
83 | - Default: 'spritesheet.png'
84 | - `pathToSpriteSheetFromCSS`: string - Because we don't know where you will end up saving the CSS file at this point in the pipe, we need a litle help identifying where it will be. We will use this as the reference to the sprite sheet image in the CSS piped in.
85 | - Default: 'spritesheet.png'
86 | - `spriteSheetBuildCallback`: function - Same as the [spritesmith callback](https://www.npmjs.com/package/spritesmith#-spritesmith-params-callback-)
87 | - Default: null
88 | - Callback has a parameters as so: `function(err, result)`
89 | - `result.image`: Binary string representation of image
90 | - `result.coordinates`: Object mapping filename to {x, y, width, height} of image
91 | - `result.properties`: Object with metadata about spritesheet {width, height}
92 | - `silent`: bool - We ignore any images that are not found but are supposed to be sprited by default
93 | - Default: true
94 | - `shouldVerifyImagesExist`: bool - Check to make sure each image declared in the CSS exists before passing it to the spriter. Although silenced by default(`options.silent`), if an image is not found, an error is thrown.
95 | - Default: true
96 | - `spritesmithOptions`: object - Any option you pass in here, will be passed through to spritesmith. [See spritesmith options documenation](https://www.npmjs.com/package/spritesmith#-spritesmith-params-callback-)
97 | - Default: {}
98 | - `outputIndent`: bool - Used to format output CSS. You should be using a separate beautifier plugin. The reason the output code is reformatted is because it is easier to "parse->stringify" than "replace in place".
99 | - Default: '\t'
100 |
101 |
102 | # What we emit
103 |
104 | `gulp-css-spriter` emits the transformed CSS with updated image references to the sprite sheet as a normal Gulp [vinyl file](https://www.npmjs.com/package/vinyl).
105 |
106 | We also attach the binary sprite sheet image in `chunk.spriteSheet` in case you want to consume it later down the pipe.
107 |
108 |
109 | # Meta info
110 |
111 | `gulp-css-spriter` uses a JSON format to add info onto CSS declarations.
112 |
113 | The example below will exclude this declaration from the spritesheet.
114 | ```
115 | /* @meta {"spritesheet": {"include": false}} */
116 | background: url('../images/dummy-blue.png');
117 | ```
118 |
119 | Please note that if you are compiling from Sass/Less and are not getting correct results, to check the outputted CSS and make sure the comments are still in tact and on the line you expect. For Sass, use multiline `/* */` comment syntax and put them above declarations. This is because gulp-sass/node-sass/libsass removes single line comments and puts mult-line comments that are on the same line as a declaration, below the declaraton.
120 |
121 | The `@meta` comment data can be above or on the same line as the declaration for it to apply.
122 | ```
123 | /* @meta {"spritesheet": {"include": false}} */
124 | background: url('../images/dummy-blue.png'); /* @meta {"spritesheet": {"include": false}} */
125 | ```
126 |
127 | ## Meta options
128 |
129 | - `spritesheet`: object - hash of options that `gulp-css-spriter` will factor in
130 | - `include`: bool - determines whether or not the declaration should be included in the spritesheet. This can be left undefined if the `includeMode` is 'implicit'
131 |
132 |
133 |
134 | # What we emit
135 |
136 | `gulp-css-spriter` transforms your CSS image paths to the spritesheet appropriately then emits the CSS as a normal Gulp [vinyl file](https://www.npmjs.com/package/vinyl).
137 |
138 | - Gulp [vinyl file](https://www.npmjs.com/package/vinyl). We emit the CSS you passed in with transformed image paths
139 |
140 | ## Events
141 |
142 | ### `.on('log', function(message) { })`
143 |
144 | We emit log messages such as when a image defined in the CSS can't be found on disk.
145 |
146 | ### `.on('error', function(err) { })`
147 |
148 | A normal gulp error. There are a variety of errors. See source code for more details.
149 |
150 |
151 |
152 | # Testing
153 |
154 | We have a series of unit tests. We use [Mocha](http://mochajs.org/).
155 |
156 | Install Mocha globally:
157 | ```
158 | npm install -g mocha
159 | ```
160 |
161 | Run tests with: `mocha` or `npm test`
162 |
--------------------------------------------------------------------------------
/lib/spriter/index.js:
--------------------------------------------------------------------------------
1 | // gulp-css-spriter: https://www.npmjs.com/package/gulp-css-spriter
2 | // Sprite Sheet Generation from CSS source files.
3 | //
4 | // By: Eric Eastwood: EricEastwood.com
5 | //
6 | // Meta info looks like: `/* @meta {"spritesheet": {"include": false}} */`
7 |
8 | var fs = require('fs-extra');
9 | var path = require('path');
10 |
11 | var Promise = require('bluebird');
12 | var outputFile = Promise.promisify(fs.outputFile);
13 | var stat = Promise.promisify(fs.stat);
14 |
15 | var through = require('through2');
16 | var extend = require('extend')
17 | var gutil = require('gulp-util');
18 |
19 | var css = require('css');
20 | var spritesmith = require('spritesmith');
21 | var spritesmithBuild = Promise.promisify(spritesmith);
22 |
23 |
24 | var spriterUtil = require('./lib/spriter-util');
25 | var getBackgroundImageDeclarations = require('./lib/get-background-image-declarations');
26 | var transformFileWithSpriteSheetData = require('./lib/transform-file-with-sprite-sheet-data');
27 |
28 |
29 | var gmutil = require('../gmutil'),
30 | store = require('../store')
31 |
32 |
33 | // consts
34 | const PLUGIN_NAME = 'gulp-css-spriter';
35 | const gm_sprite_img_dir = 'gm_sprite_img'
36 | const gm_sprite_subfix = '_sprite_sheet.png'
37 |
38 |
39 | var spriter = function(options) {
40 |
41 | var defaults = {
42 | // ('implicit'|'explicit')
43 | 'includeMode': 'implicit',
44 | // The path and file name of where we will save the sprite sheet
45 | 'spriteSheet': 'spritesheet.png',
46 | // Because we don't know where you will end up saving the CSS file at this point in the pipe,
47 | // we need a litle help identifying where it will be.
48 | 'pathToSpriteSheetFromCSS': 'spritesheet.png',
49 | // Same as the spritesmith callback `function(err, result)`
50 | // result.image: Binary string representation of image
51 | // result.coordinates: Object mapping filename to {x, y, width, height} of image
52 | // result.properties: Object with metadata about spritesheet {width, height}
53 | 'spriteSheetBuildCallback': null,
54 | // If true, we ignore any images that are not found on disk
55 | // Note: this plugin will still emit an error if you do not verify that the images exist
56 | 'silent': true,
57 | // Check to make sure each image declared in the CSS exists before passing it to the spriter.
58 | // Although silenced by default(`options.silent`), if an image is not found, an error is thrown.
59 | 'shouldVerifyImagesExist': true,
60 | // Any option you pass in here, will be passed through to spritesmith
61 | // https://www.npmjs.com/package/spritesmith#-spritesmith-params-callback-
62 | 'spritesmithOptions': {},
63 | // Used to format output CSS
64 | // You should be using a separate beautifier plugin
65 | 'outputIndent': '\t'
66 | };
67 |
68 | var settings = extend({}, defaults, options);
69 |
70 | // Keep track of all the chunks that come in so that we can re-emit in the flush
71 | var chunkList = [];
72 | // We use an object for imageMap so we don't get any duplicates
73 | var imageMap = {};
74 | // Check to make sure all of the images exist(`options.shouldVerifyImagesExist`) before trying to sprite them
75 | var imagePromiseArray = [];
76 |
77 | // var currentChunkFile;
78 |
79 | var stream = through.obj(function(chunk, enc, cb) {
80 | // http://nodejs.org/docs/latest/api/stream.html#stream_transform_transform_chunk_encoding_callback
81 | //console.log('transform');
82 |
83 | // Each `chunk` is a vinyl file: https://www.npmjs.com/package/vinyl
84 | // chunk.cwd
85 | // chunk.base
86 | // chunk.path
87 | // chunk.contents
88 | var self = this;
89 |
90 | if (chunk.isStream()) {
91 | self.emit('error', new gutil.PluginError(PLUGIN_NAME, 'Cannot operate on stream'));
92 | }
93 | else if (chunk.isBuffer()) {
94 | var contents = String(chunk.contents);
95 |
96 | var styles;
97 | try {
98 | styles = css.parse(contents, {
99 | 'silent': settings.silent,
100 | 'source': chunk.path
101 | });
102 | }
103 | catch(err) {
104 | err.message = 'Something went wrong when parsing the CSS: ' + err.message;
105 | self.emit('log', err.message);
106 |
107 | // Emit an error if necessary
108 | if(!settings.silent) {
109 | self.emit('error', err);
110 | }
111 | }
112 |
113 |
114 | var fileDir = path.relative(settings['dist_root'], chunk.base)
115 |
116 |
117 | var fileName = path.basename(chunk.relative)
118 |
119 | // add for gulpman
120 | chunk.base = settings['cwd']
121 | // currentChunkFile = chunk
122 |
123 | var relDistPath = path.join(
124 | gm_sprite_img_dir,
125 | fileName+gm_sprite_subfix
126 | )
127 |
128 | var distSpritePath = path.join(settings['dist_root'], fileDir, relDistPath)
129 |
130 | settings['spriteSheet'] = distSpritePath
131 |
132 | settings['pathToSpriteSheetFromCSS'] = relDistPath
133 |
134 | // Gather a list of all of the image declarations
135 | var chunkBackgroundImageDeclarations = getBackgroundImageDeclarations(styles, settings.includeMode);
136 |
137 |
138 | // Go through each declaration and gather the image paths
139 | // We find the new images that we found in this chunk verify they exist below
140 | // We use an object so we don't get any duplicates
141 | var newImagesfFromChunkMap = {};
142 | var backgroundURLMatchAllRegex = new RegExp(spriterUtil.backgroundURLRegex.source, "gi");
143 | chunkBackgroundImageDeclarations.forEach(function(declaration) {
144 |
145 | // Match each background image in the declaration (there could be multiple background images per value)
146 | spriterUtil.matchBackgroundImages(declaration.value, function(imagePath) {
147 | imagePath = path.join(path.dirname(chunk.path), imagePath);
148 |
149 | // If not already in the overall list of images collected
150 | // Add to the queue/list of images to be verified
151 | if(!imageMap[imagePath]) {
152 | newImagesfFromChunkMap[imagePath] = true;
153 | }
154 |
155 | // Add it to the main overall list to keep track
156 | imageMap[imagePath] = true;
157 | });
158 | });
159 |
160 | // Filter out any images that do not exist depending on `settings.shouldVerifyImagesExist`
161 | Object.keys(newImagesfFromChunkMap).forEach(function(imagePath) {
162 | var filePromise;
163 | if(settings.shouldVerifyImagesExist) {
164 | filePromise = stat(imagePath).then(function() {
165 | return {
166 | doesExist: true,
167 | path: imagePath
168 | };
169 | }, function() {
170 | return {
171 | doesExist: false,
172 | path: imagePath
173 | };
174 | });
175 | }
176 | else {
177 | // If they don't want us to verify it exists, just pass it on with a undefined `doesExist` property
178 | filePromise = Promise.resolve({
179 | doesExist: undefined,
180 | path: imagePath
181 | });
182 | }
183 |
184 | imagePromiseArray.push(filePromise);
185 | });
186 |
187 | // Keep track of each chunk and what declarations go with it
188 | // Because the positions/line numbers pertain to that chunk only
189 | chunkList.push(chunk);
190 |
191 | }
192 |
193 |
194 | // "call callback when the transform operation is complete."
195 | cb();
196 |
197 | }, function(cb) {
198 | // http://nodejs.org/docs/latest/api/stream.html#stream_transform_flush_callback
199 | //console.log('flush');
200 | var self = this;
201 |
202 | // @debug
203 |
204 | // Create an verified image list when all of the async checks have finished
205 | var imagesVerifiedPromise = Promise.settle(imagePromiseArray).then(function(results) {
206 | var imageList = [];
207 | Array.prototype.forEach.call(results, function(result) {
208 | imageInfo = result.value();
209 |
210 | if(imageInfo.doesExist === true || imageInfo.doesExist === undefined) {
211 | imageList.push(imageInfo.path);
212 | }
213 | else {
214 |
215 | // Tell them that we could not find the image
216 | var logMessage = 'Image could not be found: ' + imageInfo.path;
217 | self.emit('log', logMessage);
218 |
219 | // Emit an error if necessary
220 | if(!settings.silent) {
221 | self.emit('error', {
222 | 'name': 'NotFound',
223 | 'message': logMessage,
224 | 'plugin': PLUGIN_NAME
225 | });
226 | }
227 | }
228 | });
229 |
230 | return imageList;
231 | });
232 |
233 |
234 | // Start spriting once we know the true list of images that exist
235 | imagesVerifiedPromise.then(function(imageList) {
236 |
237 | // fix the invalid png files when no-sprite-img
238 | // @debug ..可能有问题。。
239 | if(!imageList.length) {
240 | chunkList.forEach(chunk=>{
241 | self.push(chunk)
242 | })
243 |
244 | return cb();
245 | }
246 |
247 |
248 |
249 | // Generate the spritesheet
250 | var spritesmithOptions = extend({}, settings.spritesmithOptions, { src: imageList });
251 |
252 | var spriteSmithBuildPromise = spritesmithBuild(spritesmithOptions);
253 |
254 | spriteSmithBuildPromise.then(function(result) {
255 |
256 | var whenImageDealtWithPromise = new Promise(function(resolve, reject) {
257 | // Save out the spritesheet image
258 | if(settings.spriteSheet) {
259 | var spriteSheetSavedPromise = outputFile(settings.spriteSheet, result.image, 'binary').then(function() {
260 |
261 | //console.log("The file was saved!");
262 |
263 | // Push all of the chunks back on the pipe
264 | chunkList.forEach(function(chunk) {
265 |
266 | var transformedChunk = chunk.clone();
267 |
268 | // gmutil.alert('IMG: '+imageList)
269 | // save into relevancy store
270 | store.save(imageList, chunk.path, 'sprite')
271 |
272 |
273 | try {
274 | transformedChunk = transformFileWithSpriteSheetData(transformedChunk, result.coordinates, settings.pathToSpriteSheetFromCSS, settings.includeMode, settings.silent, settings.outputIndent);
275 | }
276 | catch(err) {
277 | err.message = 'Something went wrong when transforming chunks: ' + err.message;
278 | self.emit('log', err.message);
279 |
280 | // Emit an error if necessary
281 | if(!settings.silent) {
282 | self.emit('error', err);
283 | }
284 |
285 | reject(err);
286 | }
287 |
288 |
289 | // Attach the spritesheet in case someone wants to use it down the pipe
290 | transformedChunk.spritesheet = result.image;
291 |
292 | // Push it back on the main pipe
293 | self.push(transformedChunk);
294 | });
295 |
296 |
297 | }, function() {
298 | settings.spriteSheetBuildCallback(err, null);
299 | reject(err);
300 | });
301 |
302 |
303 | spriteSheetSavedPromise.finally(function() {
304 |
305 | // Call a callback from the settings the user can hook onto
306 | if(settings.spriteSheetBuildCallback) {
307 | settings.spriteSheetBuildCallback(null, result);
308 | }
309 |
310 | resolve();
311 | });
312 | }
313 | else {
314 | resolve();
315 | }
316 | });
317 |
318 | whenImageDealtWithPromise.finally(function() {
319 | // "call callback when the flush operation is complete."
320 | cb();
321 | });
322 |
323 |
324 | }, function(err) {
325 | if(err) {
326 | err.message = 'Error creating sprite sheet image:\n' + err.message;
327 | self.emit('error', new gutil.PluginError(PLUGIN_NAME, err));
328 | }
329 | });
330 |
331 |
332 | });
333 |
334 |
335 |
336 |
337 |
338 | });
339 |
340 | // returning the file stream
341 | return stream;
342 | };
343 |
344 |
345 | module.exports = spriter;
--------------------------------------------------------------------------------
/lib/spriter/lib/get-background-image-declarations.js:
--------------------------------------------------------------------------------
1 |
2 | var mapOverStylesAndTransformBackgroundImageDeclarations = require('./map-over-styles-and-transform-background-image-declarations');
3 |
4 |
5 | // Pass in a styles object from `css.parse`
6 | // See main module for `includeMode` values
7 | function getBackgroundImageDeclarations(styles, includeMode) {
8 | includeMode = includeMode || 'implicit';
9 |
10 | // First get all of the background image declarations
11 | var backgroundImageDeclarations = [];
12 | mapOverStylesAndTransformBackgroundImageDeclarations(styles, includeMode, function(declaration) {
13 | backgroundImageDeclarations.push(declaration);
14 | });
15 |
16 | return backgroundImageDeclarations;
17 | }
18 |
19 |
20 |
21 |
22 |
23 | module.exports = getBackgroundImageDeclarations;
--------------------------------------------------------------------------------
/lib/spriter/lib/get-meta-info-for-declaration.js:
--------------------------------------------------------------------------------
1 | var extend = require('extend');
2 |
3 |
4 | function getMetaInfoForDeclaration(declarations, declarationIndex) {
5 | var resultantMetaData = {};
6 |
7 | if(declarationIndex > 0 && declarationIndex < declarations.length) {
8 | var mainDeclaration = declarations[declarationIndex];
9 | if(mainDeclaration) {
10 |
11 | // Meta data can exist before or on the same line as the declaration.
12 | // Both Meta blocks are valid for the background property
13 | // ex.
14 | // /* @meta {"spritesheet": {"include": false}} */
15 | // background: url('../images/aenean-purple.png'); /* @meta {"sprite": {"skip": true}} */
16 | var beforeDeclaration = declarations[declarationIndex-1];
17 | var afterDeclaration = declarations[declarationIndex+1];
18 |
19 |
20 | if(beforeDeclaration) {
21 | // The before declaration should be valid no matter what (even if multiple lines above)
22 | // The parse function does all the nice checking for us
23 | extend(resultantMetaData, parseCommentDecarationForMeta(beforeDeclaration));
24 | }
25 |
26 | if(afterDeclaration) {
27 | //console.log(mainDeclaration);
28 | //console.log(afterDeclaration);
29 | //console.log(afterDeclaration.position.start.line, mainDeclaration.position.start.line);
30 | // Make sure that the comment starts on the same line as the main declaration
31 | if((((afterDeclaration || {}).position || {}).start || {}).line === (((mainDeclaration || {}).position || {}).start || {}).line) {
32 | extend(resultantMetaData, parseCommentDecarationForMeta(afterDeclaration));
33 | }
34 | }
35 | }
36 | }
37 |
38 |
39 | return resultantMetaData;
40 | }
41 |
42 | function parseCommentDecarationForMeta(declaration) {
43 | if(declaration.type === "comment") {
44 | //console.log(declaration);
45 |
46 | var metaMatches = declaration.comment.match(/@meta\s*({.*?}(?!}))/);
47 |
48 | if(metaMatches) {
49 | var parsedMeta = {};
50 | try {
51 | parsedMeta = JSON.parse(metaMatches[1]);
52 | }
53 | catch(e) {
54 | //console.warn('Meta info was found but failed was not valid JSON');
55 | }
56 |
57 | return parsedMeta;
58 | }
59 | }
60 | }
61 |
62 |
63 |
64 | module.exports = getMetaInfoForDeclaration;
--------------------------------------------------------------------------------
/lib/spriter/lib/map-over-styles-and-transform-background-image-declarations.js:
--------------------------------------------------------------------------------
1 | var extend = require('extend');
2 |
3 | var spriterUtil = require('./spriter-util');
4 | var getMetaInfoForDeclaration = require('./get-meta-info-for-declaration');
5 | var transformMap = require('./transform-map');
6 |
7 |
8 |
9 | function mapOverStylesAndTransformBackgroundImageDeclarations(styles, includeMode, cb) {
10 | // Map over all
11 | return mapOverStylesAndTransformAllBackgroundImageDeclarations(styles, function(declaration) {
12 | // Then filter down to only the proper ones (according to their meta data)
13 | if(shouldIncludeFactoringInMetaData(declaration.meta, includeMode)) {
14 | return cb.apply(null, arguments);
15 | }
16 | });
17 | }
18 |
19 | // Boolean function to determine if the meta data permits using this declaration
20 | function shouldIncludeFactoringInMetaData(meta, includeMode) {
21 | var metaIncludeValue = (meta && meta.spritesheet && meta.spritesheet.include);
22 | var shouldIncludeBecauseImplicit = includeMode === 'implicit' && (metaIncludeValue === undefined || metaIncludeValue);
23 | var shouldIncludeBecauseExplicit = includeMode === 'explicit' && metaIncludeValue;
24 | var shouldInclude = shouldIncludeBecauseImplicit || shouldIncludeBecauseExplicit;
25 |
26 | // Only return declartions that shouldn't be skipped
27 | return shouldInclude;
28 | }
29 |
30 |
31 |
32 | // Pass in a styles object from `css.parse`
33 | // Loop over all of the styles and transform/modify the background image declarations
34 | // Returns a new styles object that has the transformed declarations
35 | function mapOverStylesAndTransformAllBackgroundImageDeclarations(styles, cb) {
36 | // Clone the declartion to keep it immutable
37 | var transformedStyles = extend(true, {}, styles);
38 |
39 | // Go over each background `url()` declarations
40 | transformedStyles.stylesheet.rules.map(function(rule, ruleIndex) {
41 | if(rule.type === 'rule') {
42 |
43 | rule.declarations = transformMap(rule.declarations, function(declaration, declarationIndex, declarations) {
44 | // Clone the declartion to keep it immutable
45 | var transformedDeclaration = extend(true, {}, declaration);
46 | transformedDeclaration = attachInfoToDeclaration(declarations, declarationIndex);
47 |
48 | /*// background-image always has a url
49 | if(transformedDeclaration.property === 'background-image') {
50 | return cb(transformedDeclaration, declarationIndex, declarations);
51 | }
52 | // Background is a shorthand property so make sure `url()` is in there
53 | else if(transformedDeclaration.property === 'background') {
54 | var hasImageValue = spriterUtil.backgroundURLRegex.test(transformedDeclaration.value);
55 |
56 | if(hasImageValue) {
57 | return cb(transformedDeclaration, declarationIndex, declarations);
58 | }
59 | }*/
60 |
61 |
62 | // background-image always has a url且
63 | // 判断url是否有?__spriter后缀
64 | var gm_sprite_reg = /\?_gm_sprite/i,
65 | gm_sprite_str = '?_gm_sprite';
66 |
67 | if (transformedDeclaration.property === 'background-image' && gm_sprite_reg.test(transformedDeclaration.value)) {
68 |
69 | transformedDeclaration.value = transformedDeclaration.value.replace(gm_sprite_str, '');
70 |
71 | return cb(transformedDeclaration, declarationIndex, declarations);
72 | }
73 | //Background is a short hand property so make sure `url()` is in there
74 | // 且判断url是否有?__spriter后缀
75 | else if(transformedDeclaration.property === 'background' && gm_sprite_reg.test(transformedDeclaration.value)) {
76 |
77 | transformedDeclaration.value = transformedDeclaration.value.replace(gm_sprite_str, '');
78 |
79 | var hasImageValue = spriterUtil.backgroundURLRegex.test(transformedDeclaration.value);
80 |
81 | if (hasImageValue) {
82 | return cb(transformedDeclaration, declarationIndex, declarations);
83 | }
84 | }
85 |
86 | // Wrap in an object so that the declaration doesn't get interpreted
87 | return {
88 | 'value': transformedDeclaration
89 | };
90 | });
91 |
92 | }
93 |
94 | return rule;
95 | });
96 |
97 | return transformedStyles;
98 | }
99 |
100 | // We do NOT directly modify the declaration in the rule
101 | // We pass the whole rule and current index so we can properly look at the metaData around each declaration
102 | // and add it to the declaration
103 | function attachInfoToDeclaration(declarations, declarationIndex)
104 | {
105 | if(declarations.length > declarationIndex) {
106 | // Clone the declartion to keep it immutable
107 | var declaration = extend(true, {}, declarations[declarationIndex]);
108 |
109 | var declarationMetaInfo = getMetaInfoForDeclaration(declarations, declarationIndex);
110 |
111 | // Add the meta into to the declaration
112 | declaration.meta = extend(true, {}, declaration.meta, declarationMetaInfo);
113 |
114 | return declaration;
115 | }
116 |
117 | return null;
118 | }
119 |
120 |
121 |
122 | module.exports = mapOverStylesAndTransformBackgroundImageDeclarations;
123 |
--------------------------------------------------------------------------------
/lib/spriter/lib/spriter-util.js:
--------------------------------------------------------------------------------
1 |
2 | var backgroundURLRegex = (/(.*?url\(["\']?)(.*?\.(?:png|jpg|gif))(["\']?\).*?;?)/i);
3 |
4 |
5 | function matchBackgroundImages(declarationValue, cb) {
6 | var backgroundURLMatchAllRegex = new RegExp(backgroundURLRegex.source, "gi");
7 |
8 | return declarationValue.replace(backgroundURLMatchAllRegex, function(match, p1, p2, p3, offset, string) {
9 | var imagePath = p2;
10 |
11 | return p1 + cb(imagePath) + p3;
12 | });
13 | }
14 |
15 |
16 |
17 | module.exports = {
18 | 'backgroundURLRegex': backgroundURLRegex,
19 | 'matchBackgroundImages':matchBackgroundImages
20 | };
21 |
--------------------------------------------------------------------------------
/lib/spriter/lib/transform-file-with-sprite-sheet-data.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var extend = require('extend');
3 |
4 | var css = require('css');
5 |
6 | var spriterUtil = require('./spriter-util');
7 | var mapOverStylesAndTransformBackgroundImageDeclarations = require('./map-over-styles-and-transform-background-image-declarations');
8 |
9 | var backgroundURLMatchAllRegex = new RegExp(spriterUtil.backgroundURLRegex.source, "gi");
10 |
11 |
12 | // Replace all the paths that need replacing
13 | function transformFileWithSpriteSheetData(vinylFile, coordinateMap, pathToSpriteSheetFromCSS, /*optional*/includeMode, /*optional*/isSilent, /*optional*/outputIndent) {
14 | includeMode = includeMode ? includeMode : 'implicit';
15 | isSilent = (isSilent !== undefined) ? isSilent : false;
16 | outputIndent = outputIndent ? outputIndent : '\t';
17 |
18 | // Clone the declartion to keep it immutable
19 | var resultantFile = vinylFile.clone();
20 |
21 | if(resultantFile) {
22 |
23 | var styles = css.parse(String(resultantFile.contents), {
24 | 'silent': isSilent,
25 | 'source': vinylFile.path
26 | });
27 |
28 | styles = mapOverStylesAndTransformBackgroundImageDeclarations(styles, includeMode, function(declaration) {
29 |
30 | var coordList = [];
31 | declaration.value = spriterUtil.matchBackgroundImages(declaration.value, function(imagePath) {
32 |
33 | var coords = coordinateMap[path.join(path.dirname(resultantFile.path), imagePath)];
34 | //console.log('coords', coords);
35 |
36 | // Make sure there are coords for this image in the sprite sheet, otherwise we won't include it
37 | if(coords) {
38 | coordList.push("-" + coords.x + "px -" + coords.y + "px");
39 |
40 | // If there are coords in the spritemap for this image, lets use the spritemap
41 | return pathToSpriteSheetFromCSS;
42 | }
43 |
44 | return imagePath;
45 | });
46 |
47 | return {
48 | 'value': declaration,
49 | /* */
50 | // Add the appropriate background position according to the spritemap
51 | 'insertElements': (function() {
52 | if(coordList.length > 0) {
53 | return {
54 | type: 'declaration',
55 | property: 'background-position',
56 | value: coordList.join(', ')
57 | };
58 | }
59 | })()
60 | /* */
61 | };
62 | });
63 |
64 | //console.log(styles.stylesheet.rules[0].declarations);
65 |
66 | // Put it back into string form
67 | var resultantContents = css.stringify(styles, {
68 | indent: outputIndent
69 | });
70 | //console.log(resultantContents);
71 | resultantFile.contents = new Buffer(resultantContents);
72 | }
73 |
74 | return resultantFile;
75 | }
76 |
77 | module.exports = transformFileWithSpriteSheetData;
--------------------------------------------------------------------------------
/lib/spriter/lib/transform-map.js:
--------------------------------------------------------------------------------
1 | var extend = require('extend');
2 |
3 | function transformMap(arr, cb) {
4 | var resultantArray = extend(true, [], arr);
5 |
6 | for(var i = 0; i < resultantArray.length; i++) {
7 | var el = resultantArray[i];
8 |
9 | var result = cb(el, i, resultantArray);
10 |
11 | var defaults = {
12 | value: el,
13 | insertElements: [],
14 | appendElements: []
15 | };
16 |
17 | // You can pass in a bare value or as the `value` property of an object
18 | result = typeof result === 'object' ? result : { value: result };
19 | // Massage the result into shape
20 | result = extend({}, defaults, result);
21 |
22 |
23 | // Transform the current value
24 | resultantArray[i] = result.value ? result.value : result;
25 |
26 | // Insert after the current element
27 | var insertElements = [].concat(result.insertElements);
28 | if(insertElements.length > 0) {
29 | Array.prototype.splice.apply(resultantArray, [i+1, 0].concat(insertElements));
30 | }
31 |
32 | // Add the elements onto the end
33 | var appendElements = [].concat(result.appendElements);
34 | if(appendElements.length > 0) {
35 | resultantArray = resultantArray.concat(appendElements);
36 | }
37 | }
38 |
39 | return resultantArray;
40 | }
41 |
42 |
43 | module.exports = transformMap;
--------------------------------------------------------------------------------
/lib/spriter/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "gulp-css-spriter",
3 | "version": "0.3.3",
4 | "description": "Sprite Sheet Generation from CSS source files. The best and different approach to sprite sheets.",
5 | "main": "index.js",
6 | "repository": {
7 | "type": "git",
8 | "url": "https://github.com/MadLittleMods/gulp-css-spriter.git"
9 | },
10 | "keywords": [
11 | "css",
12 | "gulp",
13 | "gulpplugin",
14 | "gulpfriendly",
15 | "sprite",
16 | "spritesheet",
17 | "sass",
18 | "less"
19 | ],
20 | "author": {
21 | "name": "Eric Eastwood",
22 | "email": "contact@ericeastwood.com",
23 | "url": "http://ericeastwood.com/"
24 | },
25 | "license": "MIT",
26 | "bugs": {
27 | "url": "https://github.com/MadLittleMods/gulp-css-spriter/issues"
28 | },
29 | "scripts": {
30 | "test": "mocha"
31 | },
32 | "dependencies": {
33 | "bluebird": "^2.9.3",
34 | "css": "^2.1.0",
35 | "extend": "^2.0.0",
36 | "fs-extra": "^0.14.0",
37 | "gulp-util": "^3.0.1",
38 | "spritesmith": "^1.0.3",
39 | "through2": "^0.6.2"
40 | },
41 | "devDependencies": {
42 | "chai": "^1.10.0",
43 | "chai-as-promised": "^4.1.1",
44 | "gulp": "^3.8.10",
45 | "mocha": "^2.1.0"
46 | },
47 | "gitHead": "2a4f030a00e0135ff8270acf1f34bb0c2537d102",
48 | "homepage": "https://github.com/MadLittleMods/gulp-css-spriter",
49 | "_id": "gulp-css-spriter@0.3.3",
50 | "_shasum": "4f69315ac01d92a0dc9996c02054cbd4826aeac1",
51 | "_from": "gulp-css-spriter@latest",
52 | "_npmVersion": "1.4.23",
53 | "_npmUser": {
54 | "name": "mlm",
55 | "email": "contact@ericeastwood.com"
56 | },
57 | "maintainers": [
58 | {
59 | "name": "mlm",
60 | "email": "contact@ericeastwood.com"
61 | }
62 | ],
63 | "dist": {
64 | "shasum": "4f69315ac01d92a0dc9996c02054cbd4826aeac1",
65 | "tarball": "http://registry.npmjs.org/gulp-css-spriter/-/gulp-css-spriter-0.3.3.tgz"
66 | },
67 | "directories": {},
68 | "_resolved": "https://registry.npmjs.org/gulp-css-spriter/-/gulp-css-spriter-0.3.3.tgz"
69 | }
70 |
--------------------------------------------------------------------------------
/lib/store.js:
--------------------------------------------------------------------------------
1 | /**
2 | * For create JSON file
3 | */
4 |
5 | var fs = require('fs'),
6 | path = require('path'),
7 | j = path.join
8 |
9 |
10 | var gmutil = require('./gmutil')
11 |
12 | var _cwd = process.cwd()
13 |
14 | // var jsonFileName = 'gm-relevancy.json',
15 | // jsonFilePath
16 |
17 | var dataBase = {
18 | 'name':'gm-relevancy',
19 | 'time': (new Date()).getTime(),
20 | 'source': {},
21 | 'sprite': {}
22 | // 'requiredCSS': {},
23 | }
24 |
25 |
26 | function initStore(db) {
27 |
28 | // check global namespace
29 | if(!global['gm_ns']) {
30 | global['gm_ns'] = {}
31 | }
32 |
33 | // update dataBase from global is existed
34 | if(global['gm_ns']['data_base']){
35 | dataBase = db || global['gm_ns']['data_base']
36 |
37 | }else{
38 |
39 | global['gm_ns']['data_base'] = db || dataBase
40 |
41 | }
42 |
43 | }
44 |
45 |
46 | function _write(fpath){
47 | fs.writeFileSync(fpath, JSON.stringify(dataBase, null, 4))
48 | }
49 |
50 | function _push (sourceFile, refFile, dbType) {
51 | // 如果已经存储,那么不再重复push
52 | if(_isInList(sourceFile, refFile, dbType)) return true
53 |
54 | !dataBase[dbType] && (dataBase[dbType] = {})
55 | if(dataBase[dbType][sourceFile]){
56 | dataBase[dbType][sourceFile].push(refFile)
57 | }else {
58 | dataBase[dbType][sourceFile] = [refFile]
59 | }
60 | }
61 |
62 | function _check(sourceAbsPath, handler, dbType, handlerType, evtObj){
63 |
64 | // gmutil.alert('Store: \n')
65 | // console.log(global['gm_ns']['data_base'])
66 |
67 | var dbType = dbType || 'source'
68 |
69 | if(sourceAbsPath in dataBase[dbType]){
70 | // gmutil.alert('HIT Store: \n')
71 | // console.log(dataBase)
72 |
73 | if(handler){
74 | dataBase[dbType][sourceAbsPath].forEach(item=>{
75 |
76 | gmutil.warn('*Relevancy Process: '+item)
77 | // the handler default as file type
78 | var hfn = handlerType || path.extname(item).slice(1)
79 |
80 | handler[hfn] && handler[hfn](item, evtObj)
81 |
82 | })
83 | }
84 |
85 | return true
86 |
87 | }else {
88 |
89 | return false
90 | }
91 |
92 |
93 | }
94 |
95 |
96 | function _isInList(sourceFile, refFile, dbType){
97 | var r
98 | return (dataBase[dbType]) && (r = dataBase[dbType][sourceFile]) && r.indexOf(refFile) !== -1
99 | }
100 |
101 |
102 |
103 | function _save (sourceFile, refFile, dbType) {
104 | var dbType = dbType || 'source'
105 |
106 | // gmutil.alert(sourceFile+' :\n'+refFile)
107 | if(typeof sourceFile == 'string'){
108 | // just save in memory now, not write in file
109 | return _push(sourceFile, refFile, dbType)
110 | }else if(gmutil.isArray(sourceFile)){
111 | sourceFile.forEach((e,i)=>{
112 | _push(e, refFile, dbType)
113 | })
114 |
115 | return true;
116 | }else {
117 | gmutil.error("*Relevancy Store Error:\n")
118 | throw Error('Unknown Type: '+sourceFile)
119 | }
120 |
121 | }
122 |
123 |
124 | function getStore(){
125 | return dataBase
126 | }
127 |
128 |
129 | // init store
130 | initStore()
131 |
132 |
133 | // api
134 | exports.save = _save
135 | exports.check = _check
136 |
137 | exports.get = getStore
138 |
139 |
140 |
--------------------------------------------------------------------------------
/meta/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xunuoi/gulpman/d12eb0fa1c71a955f98d2c4bb7090540a518dd7a/meta/favicon.ico
--------------------------------------------------------------------------------
/meta/home/img/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xunuoi/gulpman/d12eb0fa1c71a955f98d2c4bb7090540a518dd7a/meta/home/img/logo.png
--------------------------------------------------------------------------------
/meta/home/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | HOME PAGE
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
21 |
22 |
23 |
More Information
24 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
How to use ReactJS in Gulpman ?
40 |
41 |
42 | - Put ReactJS file in html by script tag.
43 | - such as:
44 |
45 | <script src="react.min.js" type="text/javascript"></script>
46 |
47 | <script src="react-dom.min.js" type="text/javascript"></script>
48 |
49 |
50 | - Or Import React in Your ES6/JSX:
51 |
52 | import 'react'
53 |
54 |
55 | - Then you can directly use the React and ReactDOM Object in your ES6/JSX files.
56 |
57 |
58 |
Example:
59 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/meta/home/main.es6:
--------------------------------------------------------------------------------
1 | /**
2 | * FOR HOME
3 | */
4 |
5 | import 'react'
6 |
7 | let HelloMessage = React.createClass({
8 | render () {
9 | return The Content Are Created By {this.props.name}
10 | }
11 | })
12 |
13 |
14 |
15 | function renderHello (argument) {
16 | ReactDOM.render(
17 | ,
18 | document.getElementById('demo1')
19 | )
20 | }
21 |
22 |
23 |
24 | setTimeout(()=>{
25 |
26 | renderHello()
27 |
28 | }, 1200)
29 |
30 |
31 | export {
32 | renderHello
33 | }
--------------------------------------------------------------------------------
/meta/home/main.scss:
--------------------------------------------------------------------------------
1 | /**
2 | * FOR HOME
3 | */
4 |
5 |
6 | .logo {
7 | background: url(./img/logo.png) no-repeat;
8 | }
9 |
10 | // for sprite demo
11 | .demo-sprite {
12 | background: url(./img/logo.png?_gm_sprite) no-repeat;
13 | width: 50px;
14 | height: 50px;
15 | }
16 |
17 |
18 | .demo-inline {
19 | // if you want use inline-base64,
20 | // add `?_gm_inline` after img url
21 | }
22 |
23 | .header {
24 | width: 600px;
25 | margin: 0 auto;
26 | text-align: center;
27 |
28 | p {
29 | text-align: center;
30 | }
31 | }
32 |
33 | .more-info {
34 | margin-top: 20px;
35 | border: 1px dashed #8EB139;
36 | padding: 20px;
37 | background-color: #FFAA89;
38 | border-radius: 8px;
39 |
40 | h3 {
41 | color: white;
42 | }
43 | a {
44 | text-decoration: none;
45 | }
46 | ul li {
47 | line-height: 30px;
48 | }
49 | }
50 |
51 | .demo-container {
52 | margin-top: 30px;
53 | border: 1px dashed #8EB139;
54 | padding: 20px;
55 | background-color: #5B9EB2;
56 | border-radius: 8px;
57 |
58 | ol li p {
59 | color: #14581F;
60 | text-shadow: 2px 2px 2px #9A9A9A;
61 | }
62 |
63 | h3 {
64 | color: white;
65 | }
66 |
67 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "gulpman",
3 | "version": "2.0.0",
4 | "description": "Create Modular Front-End Build System. Based on gulp, very easy and light",
5 | "engines": {
6 | "node": ">=4.0.0"
7 | },
8 | "main": "index.js",
9 | "scripts": {
10 | "test": "make test"
11 | },
12 | "repository": {
13 | "type": "git",
14 | "url": "git+https://github.com/xunuoi/gulpman.git"
15 | },
16 | "keywords": [
17 | "gulp",
18 | "modular",
19 | "gulpman",
20 | "scss",
21 | "es6",
22 | "react",
23 | "jsx",
24 | "build",
25 | "easy",
26 | "fis",
27 | "component"
28 | ],
29 | "author": "Lucas X",
30 | "license": "MIT",
31 | "bugs": {
32 | "url": "https://github.com/xunuoi/gulpman/issues"
33 | },
34 | "homepage": "https://github.com/xunuoi/gulpman#readme",
35 | "devDependencies": {
36 | "gulp": "^3.9.0"
37 | },
38 | "dependencies": {
39 | "gulp-babel": "^6.1.2",
40 | "browserify": "^13.1.0",
41 | "stringify": "^5.1.0",
42 | "colors": "^1.1.2",
43 | "event-stream": "^3.3.2",
44 | "globby": "^6.0.0",
45 | "gulp-cssnano": "^2.1.2",
46 | "gulp-imagemin": "^3.0.2",
47 | "gulp-load-plugins": "^1.2.4",
48 | "gulp-concat": "^2.6.0",
49 | "gulp-rename": "^1.2.2",
50 | "gulp-rev-all": "^0.9.7",
51 | "gulp-sequence": "^0.4.4",
52 | "gulp-uglify": "^2.0.0",
53 | "gulp-sourcemaps": "^1.6.0",
54 | "imagemin-pngquant": "^5.0.0",
55 | "readable-stream": "^2.0.5",
56 | "object-assign": "^4.0.1",
57 | "shelljs": "^0.5.3",
58 | "through2": "^2.0.1",
59 | "vinyl-buffer": "^1.0.0",
60 | "vinyl-source-stream": "^1.1.0",
61 | "gulp-util": "^3.0.7",
62 | "jsmin2": "^1.2.1",
63 | "uglifycss": "0.0.20",
64 | "bluebird": "^3.4.1",
65 | "css": "^2.2.1",
66 | "extend": "^3.0.0",
67 | "fs-extra": "^0.30.0",
68 | "spritesmith": "^2.0.1"
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/presetlib/react-0.14.6/build/react-dom-server.js:
--------------------------------------------------------------------------------
1 | /**
2 | * ReactDOMServer v0.14.6
3 | *
4 | * Copyright 2013-2015, Facebook, Inc.
5 | * All rights reserved.
6 | *
7 | * This source code is licensed under the BSD-style license found in the
8 | * LICENSE file in the root directory of this source tree. An additional grant
9 | * of patent rights can be found in the PATENTS file in the same directory.
10 | *
11 | */
12 | // Based off https://github.com/ForbesLindesay/umd/blob/master/template.js
13 | ;(function(f) {
14 | // CommonJS
15 | if (typeof exports === "object" && typeof module !== "undefined") {
16 | module.exports = f(require('react'));
17 |
18 | // RequireJS
19 | } else if (typeof define === "function" && define.amd) {
20 | define(['react'], f);
21 |
22 | //