Closed trajche closed 3 years ago
Hi @trajche, we had same issue during Marketo implementation.
We did few adjustments on one specific project, maybe this will be useful for you:
const gulp = require( 'gulp' ),
through = require( 'through2' ),
sass = require( 'gulp-sass' ),
gcmq = require( 'gulp-group-css-media-queries' ),
gutil = require( 'gulp-util' ),
juice = require( '@akzhan/gulp-juice' ),
del = require( 'del' ),
stripComments = require( 'gulp-strip-comments' ),
connect = require( 'gulp-connect' ),
path = require( 'path' ),
filesToSass = [
'source/sass/inlined.scss',
'source/sass/embedded.scss',
],
filesToWatch = [
'source/sass/**/*.scss',
'source/**/*.html',
];
// Ignore Marketo variables
if ( ! juice.codeBlocks ) {
juice.codeBlocks = {};
}
juice.codeBlocks.mkto = {
start: '${',
end: '}',
};
// Build SASS
gulp.task( 'build:sass', function( done ) {
'use strict';
return gulp.src( filesToSass )
.pipe(
sass( {
outputStyle: 'compressed',
} )
.on( 'error', gutil.log )
)
.pipe( gcmq() )
.pipe( gulp.dest( 'public/css/' ) )
.on( 'end', done );
} );
const replaceSpecials = function( file, enc, callback ) {
'use strict';
if ( file.isNull() ) {
return callback( null, file );
}
if ( file.isStream() ) {
return callback( null, file );
}
if ( file.isBuffer() ) {
let content = file.contents.toString();
content = content.replace( /\#curlyBracketOpen\#/g, '{' );
content = content.replace( /\#curlyBracketClose\#/g, '}' );
file.contents = new Buffer( content );
this.push( file );
}
callback();
};
// Inline CSS
gulp.task( 'inline:css', function( done ) {
'use strict';
return gulp.src( 'source/**/*.html' )
.pipe(
juice( {
applyHeightAttributes: false,
applyWidthAttributes: false,
webResources: {
relativeTo: path.resolve( __dirname, 'public/' ),
images: false,
svgs: false,
scripts: false,
links: false,
},
} )
.on( 'error', gutil.log )
)
.pipe( through.obj( replaceSpecials ) )
.pipe( gulp.dest( 'public/' ) )
.on( 'end', done );
} );
// Clean CSS
gulp.task( 'clean:css', function( done ) {
'use strict';
return del( [
'public/css/',
] )
.then( function() {
done();
} );
} );
// Clean HTML
gulp.task( 'clean:html', function( done ) {
'use strict';
return gulp.src( 'public/**/*.html' )
.pipe(
stripComments( {
safe: true,
trim: true,
} )
.on( 'error', gutil.log )
)
.pipe( gulp.dest( 'public/' ) )
.pipe( connect.reload() )
.on( 'end', done );
} );
// Default (Build)
gulp.task(
'default',
gulp.series( [
'build:sass',
'inline:css',
'clean:css',
'clean:html',
] )
);
// Start server w/ live reload
gulp.task( 'start', function( done ) {
'use strict';
connect.server( {
port: 8000,
root: 'public',
livereload: true,
} );
done();
} );
// Watch
gulp.task( 'watch', function( done ) {
'use strict';
gulp.watch(
filesToWatch,
gulp.series( [
'default',
] )
);
done();
} );
// Development mode
gulp.task(
'dev',
gulp.series( [
'default',
gulp.parallel( [
'start',
'watch',
] )
] )
);
// Clean project folder
gulp.task( 'clean', function( done ) {
'use strict';
return del( [
'public/*',
'!public/assets',
] )
.then( function() {
done();
} );
} );
Let me know if you need help with it :)
Many thanks Alen. Will test this and come back to you later today!
@alenvuletic I managed to get it working by using the replaceSpecials and using #curlyBracketOpen# and #curlyBracketClose# but I am unable to define codeBlocks on juice.
I tried to add it as an option in html.js:
function inline() {
return gulp.src( config.paths.html.inline.src )
.pipe(
juice( {
applyHeightAttributes: false,
applyWidthAttributesa: false,
xmlMode: true,
webResources: {
relativeTo: './dist',
images: false,
svgs: false,
scripts: false,
links: false,
},
codeBlocks: {
start: '${',
end: '}'
},
})
)
.pipe( through.obj( replaceSpecials ) )
.pipe( gulp.dest( config.paths.html.inline.dest ) );
}
But did not succeed. Any tips on how to use it with the current gulpfile (the one you shared seems like from an earlier Bojler version)?
Since I am not sure how to set Juice global settings, current hack for anyone reading this:
Add two functions, replaceSpecials which is ran before the inline-ing by Juice and then replaceSpecialsAgain which is ran after the inline-ing and removal of Marketo tags.
const replaceSpecials = function( file, enc, callback ) {
'use strict';
if ( file.isNull() ) {
return callback( null, file );
}
if ( file.isStream() ) {
return callback( null, file );
}
if ( file.isBuffer() ) {
let content = file.contents.toString();
content = content.replace( /\${/g, '#curlyBracketOpen#' );
content = content.replace( /}/g, '#curlyBracketClose#' );
file.contents = new Buffer.from( content );
this.push( file );
}
callback();
};
const replaceSpecialsAgain = function( file, enc, callback ) {
'use strict';
if ( file.isNull() ) {
return callback( null, file );
}
if ( file.isStream() ) {
return callback( null, file );
}
if ( file.isBuffer() ) {
let content = file.contents.toString();
content = content.replace( /\#curlyBracketOpen\#/g, '${' );
content = content.replace( /\#curlyBracketClose\#/g, '}' );
file.contents = new Buffer.from( content );
this.push( file );
}
callback();
};
Then in html.js replace the inline() function to:
function inline() {
return gulp.src( config.paths.html.inline.src )
.pipe( through.obj( replaceSpecials ) )
.pipe(
juice( {
applyHeightAttributes: false,
applyWidthAttributesa: false,
xmlMode: true,
webResources: {
relativeTo: './dist',
images: false,
svgs: false,
scripts: false,
links: false,
},
})
)
.pipe( through.obj( replaceSpecialsAgain ) )
.pipe( gulp.dest( config.paths.html.inline.dest ) );
}
If anyone figures out how to use codeBlocks please let me know :)
Thanks @trajche for your comments!
We decided that we don't want to implement the solution to the project because we're trying to keep it simple and clean.
This is something that can be added per project by developers if they need it. It's very specific.
Once again, thanks for your time and comments!
We are using Bojler as a framework for some Marketo email templates. In Marketo you define various variables, such as background color with a placeholder such as:
${heroBackgroundColor}
After compile, this is stripped away to:
$heroBackgroundColor
What we do currently is have a list of elements that we do a search & replace for, as the following example:
Is there any other, easier way of accomplishing this?
Hvala vam!