@@ -18,113 +18,149 @@ const postcssVar = require('postcss-custom-properties')
1818const { Transform } = require ( 'stream' )
1919const map = ( transform ) => new Transform ( { objectMode : true , transform } )
2020const through = ( ) => map ( ( file , enc , next ) => next ( null , file ) )
21+ const terser = require ( 'gulp-terser' )
2122const uglify = require ( 'gulp-uglify' )
2223const vfs = require ( 'vinyl-fs' )
2324
24- module . exports = ( src , dest , preview ) => ( ) => {
25- const opts = { base : src , cwd : src }
26- const sourcemaps = preview || process . env . SOURCEMAPS === 'true'
27- const postcssPlugins = [
28- postcssImport ,
29- ( css , { messages, opts : { file } } ) =>
30- Promise . all (
31- messages
32- . reduce ( ( accum , { file : depPath , type } ) => ( type === 'dependency' ? accum . concat ( depPath ) : accum ) , [ ] )
33- . map ( ( importedPath ) => fs . stat ( importedPath ) . then ( ( { mtime } ) => mtime ) )
34- ) . then ( ( mtimes ) => {
35- const newestMtime = mtimes . reduce ( ( max , curr ) => ( ! max || curr > max ? curr : max ) , file . stat . mtime )
36- if ( newestMtime > file . stat . mtime ) file . stat . mtimeMs = + ( file . stat . mtime = newestMtime )
37- } ) ,
38- postcssUrl ( [
39- {
40- filter : new RegExp ( '^src/css/[~][^/]*(?:font|face)[^/]*/.*/files/.+[.](?:ttf|woff2?)$' ) ,
41- url : ( asset ) => {
42- const relpath = asset . pathname . substr ( 1 )
43- const abspath = require . resolve ( relpath )
44- const basename = ospath . basename ( abspath )
45- const destpath = ospath . join ( dest , 'font' , basename )
46- if ( ! fs . pathExistsSync ( destpath ) ) fs . copySync ( abspath , destpath )
47- return path . join ( '..' , 'font' , basename )
48- } ,
49- } ,
50- ] ) ,
51- postcssVar ( { preserve : preview } ) ,
52- preview ? postcssCalc : ( ) => { } ,
53- autoprefixer ,
54- preview
55- ? ( ) => { }
56- : ( css , result ) => cssnano ( { preset : 'default' } ) ( css , result ) . then ( ( ) => postcssPseudoElementFixer ( css , result ) ) ,
57- ]
25+ module . exports = ( srcbase , destbase , config , preview ) => ( ) => {
26+ const sourcemaps = preview || config . preview || process . env . SOURCEMAPS === 'true'
27+
28+ const startPaths = config . sources . reduce ( ( accum , path ) => {
29+ const destPath = path . destPath
30+ destPath && ( accum . includes ( destPath ) || accum . push ( destPath ) )
31+ return accum
32+ } , [ ] )
33+
34+ startPaths . length > 0 || startPaths . push ( '' )
35+
36+ const css = ( config . css || [ 'site.css' ] ) . map ( ( p ) => `css/${ p } ` )
37+ const js = ( config . js || [ { target : 'site' , contents : [ '+([0-9])-*.js' ] } ] )
38+ . map ( ( data ) => {
39+ if ( data . require ) {
40+ data . contents = require . resolve ( data . require , { /*paths*/ } )
41+ } else if ( data . contents ) {
42+ Array . isArray ( data . contents ) || ( data . contents = [ data . contents ] )
43+ data . contents = data . contents . map ( ( glob ) => `js/${ glob } ` )
44+ } else {
45+ data . contents = [ `js/${ data . target } /+([0-9])-*.js` ]
46+ }
47+ data . target = `js/${ data . target } .js`
48+ data . processor = data . processor === 'none' ? through : data . processor === 'terser' ? terser : uglify
49+ return data
50+ } )
5851
5952 return merge (
60- vfs
61- . src ( 'js/+([0-9])-*.js' , { ...opts , sourcemaps } )
62- . pipe ( uglify ( ) )
63- // NOTE concat already uses stat from newest combined file
64- . pipe ( concat ( 'js/site.js' ) ) ,
65- vfs
66- . src ( 'js/vendor/*([^.])?(.bundle).js' , { ...opts , read : false } )
67- . pipe (
68- // see https://gulpjs.org/recipes/browserify-multiple-destination.html
69- map ( ( file , enc , next ) => {
70- if ( file . relative . endsWith ( '.bundle.js' ) ) {
71- const mtimePromises = [ ]
72- const bundlePath = file . path
73- browserify ( file . relative , { basedir : src , detectGlobals : false } )
74- . plugin ( 'browser-pack-flat/plugin' )
75- . on ( 'file' , ( bundledPath ) => {
76- if ( bundledPath !== bundlePath ) mtimePromises . push ( fs . stat ( bundledPath ) . then ( ( { mtime } ) => mtime ) )
77- } )
78- . bundle ( ( bundleError , bundleBuffer ) =>
79- Promise . all ( mtimePromises ) . then ( ( mtimes ) => {
80- const newestMtime = mtimes . reduce ( ( max , curr ) => ( curr > max ? curr : max ) , file . stat . mtime )
81- if ( newestMtime > file . stat . mtime ) file . stat . mtimeMs = + ( file . stat . mtime = newestMtime )
82- if ( bundleBuffer !== undefined ) file . contents = bundleBuffer
83- file . path = file . path . slice ( 0 , file . path . length - 10 ) + '.js'
84- next ( bundleError , file )
53+ startPaths . map ( ( startPath ) => {
54+ const src = startPath === '' ? srcbase : ospath . join ( srcbase , startPath )
55+ const dest = startPath === '' ? destbase : ospath . join ( destbase , startPath )
56+ const opts = { base : src , cwd : src }
57+
58+ const postcssPlugins = [
59+ postcssImport ,
60+ ( css , { messages, opts : { file } } ) =>
61+ Promise . all (
62+ messages
63+ . reduce ( ( accum , { file : depPath , type } ) => ( type === 'dependency' ? accum . concat ( depPath ) : accum ) , [ ] )
64+ . map ( ( importedPath ) => fs . stat ( importedPath ) . then ( ( { mtime } ) => mtime ) )
65+ ) . then ( ( mtimes ) => {
66+ const newestMtime = mtimes . reduce ( ( max , curr ) => ( ! max || curr > max ? curr : max ) , file . stat . mtime )
67+ if ( newestMtime > file . stat . mtime ) file . stat . mtimeMs = + ( file . stat . mtime = newestMtime )
68+ } ) ,
69+ postcssUrl ( [
70+ {
71+ filter : '**/~typeface-*/files/*' ,
72+ url : ( asset ) => {
73+ const relpath = asset . pathname . substr ( 1 )
74+ const abspath = require . resolve ( relpath )
75+ const basename = ospath . basename ( abspath )
76+ const destpath = ospath . join ( dest , 'font' , basename )
77+ if ( ! fs . pathExistsSync ( destpath ) ) fs . copySync ( abspath , destpath )
78+ return path . join ( '..' , 'font' , basename )
79+ } ,
80+ } ,
81+ ] ) ,
82+ // postcssVar({ preserve: preview }),
83+ // NOTE importFrom is for supplemental CSS files
84+ // asciidoctor docs ui has preview: true
85+ // TODO this does not take account of added aux. vars files.
86+ postcssVar ( { importFrom : path . join ( src , 'css' , 'vars.css' ) , preserve : preview } ) ,
87+ preview ? postcssCalc : ( ) => { } ,
88+ autoprefixer ,
89+ preview
90+ ? ( ) => { }
91+ : ( css , result ) =>
92+ cssnano ( { preset : 'default' } ) ( css , result ) . then ( ( ) => postcssPseudoElementFixer ( css , result ) ) ,
93+ ]
94+
95+ return merge (
96+ ...js . map ( ( { target, contents, processor } ) => vfs
97+ . src ( contents , { ...opts , sourcemaps } )
98+ . pipe ( processor ( ) )
99+ . pipe ( concat ( target ) ) ) ,
100+ vfs
101+ . src ( 'js/vendor/*.js' , { ...opts , read : false } )
102+ . pipe (
103+ // see https://gulpjs.org/recipes/browserify-multiple-destination.html
104+ map ( ( file , enc , next ) => {
105+ if ( file . relative . endsWith ( '.bundle.js' ) ) {
106+ const mtimePromises = [ ]
107+ const bundlePath = file . path
108+ browserify ( file . relative , { basedir : src , detectGlobals : false } )
109+ . plugin ( preview ? through : 'browser-pack-flat/plugin' )
110+ . on ( 'file' , ( bundledPath ) => {
111+ if ( bundledPath !== bundlePath ) mtimePromises . push ( fs . stat ( bundledPath ) . then ( ( { mtime } ) => mtime ) )
112+ } )
113+ . bundle ( ( bundleError , bundleBuffer ) =>
114+ Promise . all ( mtimePromises ) . then ( ( mtimes ) => {
115+ const newestMtime = mtimes . reduce ( ( max , curr ) => ( curr > max ? curr : max ) , file . stat . mtime )
116+ if ( newestMtime > file . stat . mtime ) file . stat . mtimeMs = + ( file . stat . mtime = newestMtime )
117+ if ( bundleBuffer !== undefined ) file . contents = bundleBuffer
118+ file . path = file . path . slice ( 0 , file . path . length - 10 ) + '.js'
119+ next ( bundleError , file )
120+ } )
121+ )
122+ } else {
123+ fs . readFile ( file . path , 'UTF-8' ) . then ( ( contents ) => {
124+ file . contents = Buffer . from ( contents )
125+ next ( null , file )
85126 } )
86- )
87- } else {
88- fs . readFile ( file . path , 'UTF-8' ) . then ( ( contents ) => {
89- file . contents = Buffer . from ( contents )
90- next ( null , file )
127+ }
91128 } )
92- }
93- } )
94- )
95- . pipe ( buffer ( ) )
96- . pipe ( uglify ( ) ) ,
97- vfs
98- . src ( 'js/vendor/*.min.js' , opts )
99- . pipe ( map ( ( file , enc , next ) => next ( null , Object . assign ( file , { extname : '' } , { extname : '.js' } ) ) ) ) ,
100- // NOTE use this statement to bundle a JavaScript library that cannot be browserified, like jQuery
101- //vfs.src(require.resolve('<package-name-or-require-path>'), opts).pipe(concat('js/vendor/<library-name>.js')),
102- vfs
103- . src ( [ 'css/site.css' , 'css/vendor/*.css' ] , { ...opts , sourcemaps } )
104- . pipe ( postcss ( ( file ) => ( { plugins : postcssPlugins , options : { file } } ) ) ) ,
105- vfs . src ( 'font/*.{ttf,woff*(2)}' , opts ) ,
106- vfs . src ( 'img/**/*.{gif,ico,jpg,png,svg}' , opts ) . pipe (
107- preview
108- ? through ( )
109- : imagemin (
110- [
111- imagemin . gifsicle ( ) ,
112- imagemin . jpegtran ( ) ,
113- imagemin . optipng ( ) ,
114- imagemin . svgo ( {
115- plugins : [
116- { cleanupIDs : { preservePrefixes : [ 'icon-' , 'view-' ] } } ,
117- { removeViewBox : false } ,
118- { removeDesc : false } ,
119- ] ,
120- } ) ,
121- ] . reduce ( ( accum , it ) => ( it ? accum . concat ( it ) : accum ) , [ ] )
122- )
123- ) ,
124- vfs . src ( 'helpers/*.js' , opts ) ,
125- vfs . src ( 'layouts/*.hbs' , opts ) ,
126- vfs . src ( 'partials/*.hbs' , opts )
127- ) . pipe ( vfs . dest ( dest , { sourcemaps : sourcemaps && '.' } ) )
129+ )
130+ . pipe ( buffer ( ) )
131+ . pipe ( uglify ( ) ) ,
132+ vfs . src ( css , { ...opts , sourcemaps } )
133+ . pipe ( postcss ( ( file ) => ( { plugins : postcssPlugins , options : { file } } ) ) ) ,
134+ vfs . src ( 'font/*.{ttf,woff*(2)}' , opts ) ,
135+ vfs . src ( 'img/**/*.{gif,ico,jpg,png,svg}' , opts ) . pipe (
136+ preview
137+ ? through ( )
138+ : imagemin (
139+ [
140+ imagemin . gifsicle ( ) ,
141+ imagemin . jpegtran ( ) ,
142+ imagemin . optipng ( ) ,
143+ imagemin . svgo ( {
144+ plugins : [
145+ { cleanupIDs : { preservePrefixes : [ 'symbol-' , 'view-' ] } } ,
146+ { removeViewBox : false } ,
147+ { removeDesc : false } ,
148+ ] ,
149+ } ) ,
150+ ] . reduce ( ( accum , it ) => ( it ? accum . concat ( it ) : accum ) , [ ] )
151+ )
152+ ) ,
153+ vfs . src ( 'helpers/*.js' , opts ) ,
154+ vfs . src ( 'layouts/*.hbs' , opts ) ,
155+ vfs . src ( 'partials/*.hbs' , opts ) ,
156+ vfs . src ( 'static/**/*' , opts ) . pipe ( map ( ( file , enc , next ) => {
157+ file . path = file . path . slice ( 0 , file . path . length - file . relative . length ) +
158+ file . relative . slice ( '/static' . length )
159+ next ( null , file )
160+ } ) )
161+ ) . pipe ( vfs . dest ( dest , { sourcemaps : sourcemaps && '.' } ) )
162+ } )
163+ )
128164}
129165
130166function postcssPseudoElementFixer ( css , result ) {
0 commit comments